enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / gtk2_ardour / session_metadata_dialog.cc
1 /*
2     Copyright (C) 2008 Paul Davis
3     Author: Sakari Bergen
4
5     This program is free software; you can redistribute it and/or modify it
6     under the terms of the GNU General Public License as published by the Free
7     Software Foundation; either version 2 of the License, or (at your option)
8     any later version.
9
10     This program is distributed in the hope that it will be useful, but WITHOUT
11     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13     for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "session_metadata_dialog.h"
21
22 #include <sstream>
23
24 #include <gtkmm2ext/utils.h>
25
26 #include "pbd/xml++.h"
27 #include "pbd/error.h"
28
29 #include "ardour/filename_extensions.h"
30 #include "ardour/session.h"
31 #include "ardour/session_utils.h"
32
33 #include "pbd/i18n.h"
34
35 using namespace std;
36 using namespace Glib;
37 using namespace PBD;
38
39 #define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember))
40
41 /*** MetadataField ***/
42
43 MetadataField::MetadataField (string const & field_name) :
44   _name (field_name)
45 {
46 }
47
48 MetadataField::~MetadataField() { }
49
50 /* TextMetadataField */
51
52 TextMetadataField::TextMetadataField (Getter getter, Setter setter, string const & field_name, guint width ) :
53   MetadataField (field_name),
54   getter (getter),
55   setter (setter),
56   width (width)
57 {
58         entry = 0;
59         label = 0;
60         value_label = 0;
61 }
62
63 MetadataPtr
64 TextMetadataField::copy ()
65 {
66         return MetadataPtr (new TextMetadataField (getter, setter, _name, width));
67 }
68
69 void
70 TextMetadataField::save_data (ARDOUR::SessionMetadata & data) const
71 {
72         CALL_MEMBER_FN (data, setter) (_value);
73 }
74
75 void
76 TextMetadataField::load_data (ARDOUR::SessionMetadata const & data)
77 {
78         _value = CALL_MEMBER_FN (data, getter) ();
79         if (entry) {
80                 entry->set_text (_value);
81         }
82 }
83
84 Gtk::Widget &
85 TextMetadataField::name_widget ()
86 {
87         label = Gtk::manage (new Gtk::Label(_name + ':'));
88         label->set_alignment (1, 0.5);
89         return *label;
90 }
91
92 Gtk::Widget &
93 TextMetadataField::value_widget ()
94 {
95         value_label = Gtk::manage (new Gtk::Label(_value));
96         return *value_label;
97 }
98
99 Gtk::Widget &
100 TextMetadataField::edit_widget ()
101 {
102         entry = Gtk::manage (new Gtk::Entry());
103
104         entry->set_text (_value);
105         entry->set_width_chars (width);
106         entry->signal_changed().connect (sigc::mem_fun(*this, &TextMetadataField::update_value));
107
108         return *entry;
109 }
110
111 void
112 TextMetadataField::update_value ()
113 {
114         _value = entry->get_text ();
115 }
116
117 /* NumberMetadataField */
118
119 NumberMetadataField::NumberMetadataField (Getter getter, Setter setter, string const & field_name, guint numbers, guint width) :
120   MetadataField (field_name),
121   getter (getter),
122   setter (setter),
123   numbers (numbers),
124   width (width)
125 {
126         entry = 0;
127         label = 0;
128         value_label = 0;
129 }
130
131 MetadataPtr
132 NumberMetadataField::copy ()
133 {
134         return MetadataPtr (new NumberMetadataField (getter, setter, _name, numbers, width));
135 }
136
137 void
138 NumberMetadataField::save_data (ARDOUR::SessionMetadata & data) const
139 {
140         uint32_t number = str_to_uint (_value);
141         CALL_MEMBER_FN (data, setter) (number);
142 }
143
144 void
145 NumberMetadataField::load_data (ARDOUR::SessionMetadata const & data)
146 {
147         uint32_t number = CALL_MEMBER_FN (data, getter) ();
148         _value = uint_to_str (number);
149         if (entry) {
150                 entry->set_text (_value);
151         }
152 }
153
154 void
155 NumberMetadataField::update_value ()
156 {
157         // Accept only numbers that will fit into a uint32_t
158         uint32_t number = str_to_uint (entry->get_text());
159         _value = uint_to_str (number);
160         entry->set_text (_value);
161 }
162
163 Gtk::Widget &
164 NumberMetadataField::name_widget ()
165 {
166         label = Gtk::manage (new Gtk::Label(_name + ':'));
167         label->set_alignment (1, 0.5);
168         return *label;
169 }
170
171 Gtk::Widget &
172 NumberMetadataField::value_widget ()
173 {
174         value_label = Gtk::manage (new Gtk::Label(_value));
175         return *value_label;
176 }
177
178 Gtk::Widget &
179 NumberMetadataField::edit_widget ()
180 {
181         entry = Gtk::manage (new Gtk::Entry());
182
183         entry->set_text (_value);
184         entry->set_width_chars (width);
185         entry->set_max_length (numbers);
186         entry->signal_changed().connect (sigc::mem_fun(*this, &NumberMetadataField::update_value));
187
188         return *entry;
189 }
190
191 string
192 NumberMetadataField::uint_to_str (uint32_t i) const
193 {
194         std::ostringstream oss ("");
195         oss << i;
196         if (oss.str().compare("0")) {
197                 return oss.str();
198         } else {
199                 return "";
200         }
201 }
202
203 uint32_t
204 NumberMetadataField::str_to_uint (string const & str) const
205 {
206         string tmp (str);
207         string::size_type i;
208         while ((i = tmp.find_first_not_of("1234567890")) != string::npos) {
209                 tmp.erase (i, 1);
210         }
211
212         std::istringstream iss(tmp);
213         uint32_t result = 0;
214         iss >> result;
215         return result;
216 }
217
218
219
220 /* EAN13MetadataField */
221
222 EAN13MetadataField::EAN13MetadataField (Getter getter, Setter setter, string const & field_name, guint width) :
223   MetadataField (field_name),
224   getter (getter),
225   setter (setter),
226   width (width)
227 {
228         entry = 0;
229         label = 0;
230         value_label = 0;
231         status_label = Gtk::manage (new Gtk::Label (""));
232 }
233
234 MetadataPtr
235 EAN13MetadataField::copy ()
236 {
237         return MetadataPtr (new EAN13MetadataField (getter, setter, _name, width));
238 }
239
240 void
241 EAN13MetadataField::save_data (ARDOUR::SessionMetadata & data) const
242 {
243         CALL_MEMBER_FN (data, setter) (_value);
244 }
245
246 void
247 EAN13MetadataField::load_data (ARDOUR::SessionMetadata const & data)
248 {
249         _value = CALL_MEMBER_FN (data, getter) ();
250         if (entry) {
251                 entry->set_text (_value);
252         }
253         update_status ();
254 }
255
256 void
257 EAN13MetadataField::update_value ()
258 {
259         // Accept only numeric characters
260         _value = numeric_string (entry->get_text());
261         entry->set_text (_value);
262         update_status ();
263 }
264
265 void
266 EAN13MetadataField::update_status ()
267 {
268         int len = _value.length ();
269         if (len == 13) {
270                 // calculate EAN-13 modulo 10 check digit
271                 int sum = 0;
272                 const char *p = _value.c_str();
273                 for (int i = 0; i < 12; i++) {
274                         char c = p[i] - '0';
275                         if (i % 2) {
276                                 sum += c * 3;
277                         } else {
278                                 sum += c;
279                         }
280                 }
281                 sum %= 10;
282                 if (sum)
283                         sum = 10 - sum;
284
285                 if (sum == p[12] - '0') {
286                         status_label->set_markup (string_compose(
287                                                 "<span color=\"green\">%1: %2</span>",
288                                                 _("EAN Check digit OK"), sum));
289                 } else {
290                         status_label->set_markup (string_compose(
291                                                 "<span color=\"#ffa755\">%1: %2 (%3 %4)</span>",
292                                                 _("EAN Check digit error"), p[12] - '0', _("expected"), sum));
293                 }
294         } else if (len > 0) {
295                 status_label->set_markup (string_compose(
296                                         "<span color=\"#ffa755\">%1: %2 (&lt;13)</span>",
297                                         _("EAN Length error"), len));
298         } else {
299                 status_label->set_text("");
300         }
301 }
302
303 Gtk::Widget &
304 EAN13MetadataField::name_widget ()
305 {
306         label = Gtk::manage (new Gtk::Label(_name + ':'));
307         label->set_alignment (1, 0.5);
308         return *label;
309 }
310
311 Gtk::Widget &
312 EAN13MetadataField::value_widget ()
313 {
314         value_label = Gtk::manage (new Gtk::Label(_value));
315         return *value_label;
316 }
317
318 Gtk::Widget &
319 EAN13MetadataField::edit_widget ()
320 {
321         entry = Gtk::manage (new Gtk::Entry());
322
323         entry->set_text (_value);
324         entry->set_width_chars (width);
325         entry->set_max_length (13);
326         entry->signal_changed().connect (sigc::mem_fun(*this, &EAN13MetadataField::update_value));
327
328         return *entry;
329 }
330
331 string
332 EAN13MetadataField::numeric_string (string const & str) const
333 {
334         string tmp (str);
335         string::size_type i;
336         while ((i = tmp.find_first_not_of("1234567890")) != string::npos) {
337                 tmp.erase (i, 1);
338         }
339         return tmp;
340 }
341
342 /* SessionMetadataSet */
343
344 SessionMetadataSet::SessionMetadataSet (string const & name)
345   : name (name)
346 {
347 }
348
349 void
350 SessionMetadataSet::add_data_field (MetadataPtr field)
351 {
352         list.push_back (field);
353 }
354
355 /* SessionMetadataSetEditable */
356
357 SessionMetadataSetEditable::SessionMetadataSetEditable (string const & name)
358   : SessionMetadataSet (name)
359 {
360         table.set_row_spacings (6);
361         table.set_col_spacings (12);
362         table.set_homogeneous (false);
363         vbox.pack_start (table, false, false);
364         vbox.set_spacing (6);
365         vbox.set_border_width (6);
366 }
367
368 Gtk::Widget &
369 SessionMetadataSetEditable::get_tab_widget ()
370 {
371         tab_widget.set_text (name);
372         return tab_widget;
373 }
374
375 void
376 SessionMetadataSetEditable::set_session (ARDOUR::Session * s)
377 {
378         SessionHandlePtr::set_session (s);
379
380         if (!_session) {
381                 return;
382         }
383
384         ARDOUR::SessionMetadata const & data = *(ARDOUR::SessionMetadata::Metadata());
385
386         table.resize (list.size(), 2);
387         uint32_t row = 0;
388         MetadataPtr field;
389         for (DataList::const_iterator it = list.begin(); it != list.end(); ++it) {
390                 field = *it;
391                 field->load_data (data);
392                 table.attach (field->name_widget(), 0, 1, row, row + 1, Gtk::FILL);
393                 table.attach (field->edit_widget(), 1, 2, row, row + 1);
394                 ++row;
395         }
396 }
397
398 void
399 SessionMetadataSetEditable::save_data ()
400 {
401         ARDOUR::SessionMetadata & data = *(ARDOUR::SessionMetadata::Metadata());
402         for (DataList::const_iterator it = list.begin(); it != list.end(); ++it) {
403                 (*it)->save_data(data);
404         }
405 }
406
407 /* SessionMetadataSetImportable */
408
409 SessionMetadataSetImportable::SessionMetadataSetImportable (string const & name)
410   : SessionMetadataSet (name)
411   , session_list (list)
412 {
413         tree = Gtk::ListStore::create (tree_cols);
414         tree_view.set_model (tree);
415
416         Gtk::TreeView::Column * viewcol;
417
418         // Add import column
419         Gtk::CellRendererToggle * import_render = Gtk::manage(new Gtk::CellRendererToggle());
420         import_render->signal_toggled().connect (sigc::mem_fun(*this, &SessionMetadataSetImportable::selection_changed));
421         viewcol = Gtk::manage(new Gtk::TreeView::Column (_("Import"), *import_render));
422         viewcol->add_attribute (import_render->property_active(), tree_cols.import);
423         tree_view.append_column (*viewcol);
424
425         // Add field name column
426         tree_view.append_column(_("Field"), tree_cols.field);
427
428         // Add values column with pango markup
429         Gtk::CellRendererText * values_render = Gtk::manage(new Gtk::CellRendererText());
430         viewcol = Gtk::manage(new Gtk::TreeView::Column (_("Values (current value on top)"), *values_render));
431         viewcol->add_attribute (values_render->property_markup(), tree_cols.values);
432         tree_view.append_column (*viewcol);
433
434         select_all_check.signal_toggled().connect (sigc::mem_fun(*this, &SessionMetadataSetImportable::select_all));
435 }
436
437 Gtk::Widget &
438 SessionMetadataSetImportable::get_tab_widget ()
439 {
440         tab_widget.set_text (name);
441         return tab_widget;
442 }
443
444 Gtk::Widget &
445 SessionMetadataSetImportable::get_select_all_widget ()
446 {
447         select_all_check.set_label (name);
448         return select_all_check;
449 }
450
451 void
452 SessionMetadataSetImportable::load_extra_data (ARDOUR::SessionMetadata const & data)
453 {
454         if (!_session) {
455                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataSetImportable (in load_data)!") << endmsg;
456                 return;
457         }
458
459         ARDOUR::SessionMetadata const & session_data = *(ARDOUR::SessionMetadata::Metadata());
460
461         MetadataPtr session_field;
462         MetadataPtr import_field;
463         DataList::iterator session_it;
464         DataList::iterator import_it;
465
466         // Copy list and load data to import
467         for (session_it = session_list.begin(); session_it != session_list.end(); ++session_it) {
468                 session_field = *session_it;
469                 session_field->load_data(session_data);
470                 import_list.push_back (session_field->copy());
471         }
472
473         // Fill widget
474         session_it = session_list.begin();
475         import_it = import_list.begin();
476         while (session_it != session_list.end() && import_it != import_list.end()) { // _should_ be the same...
477                 session_field = *session_it;
478                 import_field = *import_it;
479
480                 import_field->load_data(data); // hasn't been done yet
481
482                 // Make string for values TODO get color from somewhere?
483                 string values = "<span weight=\"ultralight\" color=\"#777\">" + session_field->value() + "</span>\n"
484                         + "<span weight=\"bold\">" + import_field->value() + "</span>";
485
486                 Gtk::TreeModel::iterator row_iter = tree->append();
487                 Gtk::TreeModel::Row row = *row_iter;
488
489                 row[tree_cols.field] = import_field->name();
490                 row[tree_cols.values] = values;
491                 row[tree_cols.import] = false;
492                 row[tree_cols.data] = import_field;
493
494                 ++session_it;
495                 ++import_it;
496         }
497 }
498
499 void
500 SessionMetadataSetImportable::save_data ()
501 {
502         if (!_session) {
503                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataSetImportable (in import_data)!") << endmsg;
504                 return;
505         }
506
507         ARDOUR::SessionMetadata & session_data = *(ARDOUR::SessionMetadata::Metadata());
508
509         Gtk::TreeModel::Children fields = tree->children();
510         Gtk::TreeModel::Children::iterator it;
511         for (it = fields.begin(); it != fields.end(); ++it) {
512                 if ((*it)[tree_cols.import]) {
513                         MetadataPtr field = (*it)[tree_cols.data];
514                         field->save_data (session_data);
515                 }
516         }
517 }
518
519 void
520 SessionMetadataSetImportable::select_all ()
521 {
522         select_all_check.set_inconsistent (false);
523         bool state = select_all_check.get_active();
524
525         Gtk::TreeModel::Children fields = tree->children();
526         Gtk::TreeModel::Children::iterator it;
527         for (it = fields.begin(); it != fields.end(); ++it) {
528                 (*it)[tree_cols.import] = state;
529         }
530 }
531
532 void
533 SessionMetadataSetImportable::selection_changed (string const & path)
534 {
535         select_all_check.set_inconsistent (true);
536
537         Gtk::TreeModel::iterator iter = tree->get_iter (path);
538         bool value((*iter)[tree_cols.import]);
539         (*iter)[tree_cols.import] = !value;
540 }
541
542 /* SessionMetadataDialog */
543
544 template <typename DataSet>
545 SessionMetadataDialog<DataSet>::SessionMetadataDialog (string const & name) :
546   ArdourDialog (name, true)
547 {
548         cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
549         cancel_button->signal_clicked().connect (sigc::mem_fun(*this, &SessionMetadataDialog::end_dialog));
550         save_button = add_button (Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
551         save_button->signal_clicked().connect (sigc::mem_fun(*this, &SessionMetadataDialog::save_and_close));
552 }
553
554 template <typename DataSet>
555 void
556 SessionMetadataDialog<DataSet>::init_data ( bool skip_user )
557 {
558         if (!_session) {
559                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataDialog (in init_data)!") << endmsg;
560                 return;
561         }
562
563         if (!skip_user)
564                 init_user_data ();
565         init_track_data ();
566         init_album_data ();
567         init_people_data ();
568         init_school_data ();
569
570         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
571                 (*it)->set_session (_session);
572
573                 notebook.append_page ((*it)->get_widget(), (*it)->get_tab_widget());
574         }
575 }
576
577 template <typename DataSet>
578 void
579 SessionMetadataDialog<DataSet>::load_extra_data (ARDOUR::SessionMetadata const & data)
580 {
581         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
582                 (*it)->load_extra_data (data);
583         }
584 }
585
586 template <typename DataSet>
587 void
588 SessionMetadataDialog<DataSet>::save_data ()
589 {
590         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
591                 (*it)->save_data ();
592         }
593 }
594
595 template <typename DataSet>
596 void
597 SessionMetadataDialog<DataSet>::save_and_close ()
598 {
599         save_data ();
600         _session->set_dirty();
601         end_dialog ();
602 }
603
604 template <typename DataSet>
605 void
606 SessionMetadataDialog<DataSet>::end_dialog ()
607 {
608         hide_all();
609 }
610
611 template <typename DataSet>
612 void
613 SessionMetadataDialog<DataSet>::warn_user (string const & string)
614 {
615         Gtk::MessageDialog msg (string, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
616         msg.run();
617 }
618
619 template <typename DataSet>
620 boost::shared_ptr<std::list<Gtk::Widget *> >
621 SessionMetadataDialog<DataSet>::get_custom_widgets (WidgetFunc f)
622 {
623         WidgetListPtr list (new WidgetList);
624         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it)
625         {
626                 DataSet * set = dynamic_cast<DataSet *> (it->get());
627                 list->push_back (& CALL_MEMBER_FN (*set, f) ());
628         }
629
630         return list;
631 }
632
633 template <typename DataSet>
634 void
635 SessionMetadataDialog<DataSet>::add_widget (Gtk::Widget & widget)
636 {
637         get_vbox()->pack_start (widget, true, true, 0);
638 }
639
640 template <typename DataSet>
641 void
642 SessionMetadataDialog<DataSet>::init_user_data ()
643 {
644         DataSetPtr data_set (new DataSet (_("User")));
645         data_list.push_back (data_set);
646
647         MetadataPtr ptr;
648
649         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::user_name, &ARDOUR::SessionMetadata::set_user_name, _("Name")));
650         data_set->add_data_field (ptr);
651
652         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::user_email, &ARDOUR::SessionMetadata::set_user_email, _("Email")));
653         data_set->add_data_field (ptr);
654
655         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::user_web, &ARDOUR::SessionMetadata::set_user_web, _("Web")));
656         data_set->add_data_field (ptr);
657
658         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::organization, &ARDOUR::SessionMetadata::set_organization, _("Organization")));
659         data_set->add_data_field (ptr);
660
661         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::country, &ARDOUR::SessionMetadata::set_country, _("Country")));
662         data_set->add_data_field (ptr);
663
664 }
665
666 template <typename DataSet>
667 void
668 SessionMetadataDialog<DataSet>::init_track_data ()
669 {
670         DataSetPtr data_set (new DataSet (_("Track")));
671         data_list.push_back (data_set);
672
673         MetadataPtr ptr;
674
675         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::title, &ARDOUR::SessionMetadata::set_title, _("Title")));
676         data_set->add_data_field (ptr);
677
678         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::track_number, &ARDOUR::SessionMetadata::set_track_number, _("Track Number"), 3));
679         data_set->add_data_field (ptr);
680
681         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::subtitle, &ARDOUR::SessionMetadata::set_subtitle, _("Subtitle")));
682         data_set->add_data_field (ptr);
683
684         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::grouping, &ARDOUR::SessionMetadata::set_grouping, _("Grouping")));
685         data_set->add_data_field (ptr);
686
687         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::artist, &ARDOUR::SessionMetadata::set_artist, _("Artist")));
688         data_set->add_data_field (ptr);
689
690         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::genre, &ARDOUR::SessionMetadata::set_genre, _("Genre")));
691         data_set->add_data_field (ptr);
692
693         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::comment, &ARDOUR::SessionMetadata::set_comment, _("Comment")));
694         data_set->add_data_field (ptr);
695
696         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::copyright, &ARDOUR::SessionMetadata::set_copyright, _("Copyright")));
697         data_set->add_data_field (ptr);
698 }
699
700 template <typename DataSet>
701 void
702 SessionMetadataDialog<DataSet>::init_album_data ()
703 {
704         DataSetPtr data_set (new DataSet (_("Album")));
705         data_list.push_back (data_set);
706
707         MetadataPtr ptr;
708
709         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::album, &ARDOUR::SessionMetadata::set_album, _("Album")));
710         data_set->add_data_field (ptr);
711
712         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::year, &ARDOUR::SessionMetadata::set_year, _("Year"), 4));
713         data_set->add_data_field (ptr);
714
715         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::album_artist, &ARDOUR::SessionMetadata::set_album_artist, _("Album Artist")));
716         data_set->add_data_field (ptr);
717
718         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::total_tracks, &ARDOUR::SessionMetadata::set_total_tracks, _("Total Tracks"), 3));
719         data_set->add_data_field (ptr);
720
721         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::disc_subtitle, &ARDOUR::SessionMetadata::set_disc_subtitle, _("Disc Subtitle")));
722         data_set->add_data_field (ptr);
723
724         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::disc_number, &ARDOUR::SessionMetadata::set_disc_number, _("Disc Number"), 2));
725         data_set->add_data_field (ptr);
726
727         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::total_discs, &ARDOUR::SessionMetadata::set_total_discs, _("Total Discs"), 2));
728         data_set->add_data_field (ptr);
729
730         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::compilation, &ARDOUR::SessionMetadata::set_compilation, _("Compilation")));
731         data_set->add_data_field (ptr);
732
733         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::isrc, &ARDOUR::SessionMetadata::set_isrc, _("ISRC")));
734         data_set->add_data_field (ptr);
735
736         ptr = MetadataPtr (new EAN13MetadataField (&ARDOUR::SessionMetadata::barcode, &ARDOUR::SessionMetadata::set_barcode, _("EAN barcode")));
737         data_set->add_data_field (ptr);
738
739         // EAN13MetadataField is the only kind of MetadataField which has a status label.
740         EAN13MetadataField &emf = (EAN13MetadataField &) *ptr;
741         ((Gtk::VBox &) data_set->get_widget()).pack_end (*emf.status_label);
742         emf.update_status ();
743 }
744
745 template <typename DataSet>
746 void
747 SessionMetadataDialog<DataSet>::init_people_data ()
748 {
749         DataSetPtr data_set (new DataSet (_("People")));
750         data_list.push_back (data_set);
751
752         MetadataPtr ptr;
753
754         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::lyricist, &ARDOUR::SessionMetadata::set_lyricist, _("Lyricist")));
755         data_set->add_data_field (ptr);
756
757         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::composer, &ARDOUR::SessionMetadata::set_composer, _("Composer")));
758         data_set->add_data_field (ptr);
759
760         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::conductor, &ARDOUR::SessionMetadata::set_conductor, _("Conductor")));
761         data_set->add_data_field (ptr);
762
763         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::remixer, &ARDOUR::SessionMetadata::set_remixer, _("Remixer")));
764         data_set->add_data_field (ptr);
765
766         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::arranger, &ARDOUR::SessionMetadata::set_arranger, _("Arranger")));
767         data_set->add_data_field (ptr);
768
769         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::engineer, &ARDOUR::SessionMetadata::set_engineer, _("Engineer")));
770         data_set->add_data_field (ptr);
771
772         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::producer, &ARDOUR::SessionMetadata::set_producer, _("Producer")));
773         data_set->add_data_field (ptr);
774
775         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::dj_mixer, &ARDOUR::SessionMetadata::set_dj_mixer, _("DJ Mixer")));
776         data_set->add_data_field (ptr);
777
778         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::mixer, &ARDOUR::SessionMetadata::set_mixer, S_("Metadata|Mixer")));
779         data_set->add_data_field (ptr);
780 }
781
782 template <typename DataSet>
783 void
784 SessionMetadataDialog<DataSet>::init_school_data ()
785 {
786         DataSetPtr data_set (new DataSet (_("School")));
787         data_list.push_back (data_set);
788
789         MetadataPtr ptr;
790
791         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::instructor, &ARDOUR::SessionMetadata::set_instructor, _("Instructor")));
792         data_set->add_data_field (ptr);
793
794         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::course, &ARDOUR::SessionMetadata::set_course, _("Course")));
795         data_set->add_data_field (ptr);
796
797 }
798
799 /* SessionMetadataEditor */
800
801 SessionMetadataEditor::SessionMetadataEditor () :
802   SessionMetadataDialog<SessionMetadataSetEditable> (_("Edit Session Metadata"))
803 {
804
805 }
806
807 SessionMetadataEditor::~SessionMetadataEditor ()
808 {
809         // Remove pages from notebook to get rid of gsignal runtime warnings
810         notebook.pages().clear();
811 }
812
813 void
814 SessionMetadataEditor::run ()
815 {
816         init_data ();
817         init_gui();
818
819         ArdourDialog::run();
820 }
821
822 void
823 SessionMetadataEditor::init_gui ()
824 {
825         add_widget (notebook);
826
827         show_all();
828 }
829
830 /* SessionMetadataImporter */
831
832 SessionMetadataImporter::SessionMetadataImporter () :
833   SessionMetadataDialog<SessionMetadataSetImportable> (_("Import session metadata"))
834 {
835
836 }
837
838 SessionMetadataImporter::~SessionMetadataImporter ()
839 {
840         // Remove pages from notebook to get rid of gsignal runtime warnings
841         notebook.pages().clear();
842 }
843
844 void
845 SessionMetadataImporter::run ()
846 {
847         if (!_session) {
848                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataImporter (in run)!") << endmsg;
849                 return;
850         }
851
852         /* Open session file selector */
853
854         Gtk::FileChooserDialog session_selector(_("Choose session to import metadata from"), Gtk::FILE_CHOOSER_ACTION_OPEN);
855         session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
856         session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
857         session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
858
859         Gtk::FileFilter session_filter;
860         session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
861         session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
862         session_selector.add_filter (session_filter);
863         session_selector.set_filter (session_filter);
864
865         int response = session_selector.run();
866         session_selector.hide ();
867
868         switch (response) {
869         case Gtk::RESPONSE_ACCEPT:
870                 break;
871         default:
872                 return;
873         }
874
875         string session_path = session_selector.get_filename();
876         string path, name;
877         bool isnew;
878
879         if (session_path.length() > 0) {
880                 if (ARDOUR::find_session (session_path, path, name, isnew) != 0) {
881                         return;
882                 }
883         } else {
884                 return;
885         }
886
887         /* We have a session: load the data and run dialog */
888
889         string filename = Glib::build_filename (path, name + ARDOUR::statefile_suffix);
890         XMLTree session_tree;
891         if (!session_tree.read (filename)) {
892                 warn_user (_("This session file could not be read!"));
893                 return;
894         }
895
896         /* XXX GET VERSION FROM TREE */
897         int version = 3000;
898
899         XMLNode * node = session_tree.root()->child ("Metadata");
900
901         if (!node) {
902                 warn_user (_("The session file didn't contain metadata!\nMaybe this is an old session format?"));
903                 return;
904         }
905
906         //create a temporary
907         ARDOUR::SessionMetadata data;
908         data.set_state (*node, version);
909         init_data ( true );  //skip user data here
910         load_extra_data (data);
911         init_gui();
912
913         ArdourDialog::run();
914 }
915
916 void
917 SessionMetadataImporter::init_gui ()
918 {
919         // Select all from -widget
920         add_widget (selection_hbox);
921         selection_label.set_text (_("Import all from:"));
922         selection_hbox.pack_start (selection_label, false, false);
923
924         WidgetListPtr list = get_custom_widgets (&SessionMetadataSetImportable::get_select_all_widget);
925         for (WidgetList::iterator it = list->begin(); it != list->end(); ++it) {
926                 selection_hbox.pack_start (**it, false, false, 6);
927         }
928
929         add_widget (notebook);
930
931         show_all();
932 }