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