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