Add EAN barcode field to session metadata dialogue
[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 "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 }
232
233 MetadataPtr
234 EAN13MetadataField::copy ()
235 {
236         return MetadataPtr (new EAN13MetadataField (getter, setter, _name, width));
237 }
238
239 void
240 EAN13MetadataField::save_data (ARDOUR::SessionMetadata & data) const
241 {
242         CALL_MEMBER_FN (data, setter) (_value);
243 }
244
245 void
246 EAN13MetadataField::load_data (ARDOUR::SessionMetadata const & data)
247 {
248         _value = CALL_MEMBER_FN (data, getter) ();
249         if (entry) {
250                 entry->set_text (_value);
251         }
252 }
253
254 void
255 EAN13MetadataField::update_value ()
256 {
257         // Accept only numeric characters
258         _value = numeric_string (entry->get_text());
259         entry->set_text (_value);
260 }
261
262 Gtk::Widget &
263 EAN13MetadataField::name_widget ()
264 {
265         label = Gtk::manage (new Gtk::Label(_name + ':'));
266         label->set_alignment (1, 0.5);
267         return *label;
268 }
269
270 Gtk::Widget &
271 EAN13MetadataField::value_widget ()
272 {
273         value_label = Gtk::manage (new Gtk::Label(_value));
274         return *value_label;
275 }
276
277 Gtk::Widget &
278 EAN13MetadataField::edit_widget ()
279 {
280         entry = Gtk::manage (new Gtk::Entry());
281
282         entry->set_text (_value);
283         entry->set_width_chars (width);
284         entry->set_max_length (13);
285         entry->signal_changed().connect (sigc::mem_fun(*this, &EAN13MetadataField::update_value));
286
287         return *entry;
288 }
289
290 string
291 EAN13MetadataField::numeric_string (string const & str) const
292 {
293         string tmp (str);
294         string::size_type i;
295         while ((i = tmp.find_first_not_of("1234567890")) != string::npos) {
296                 tmp.erase (i, 1);
297         }
298         return tmp;
299 }
300
301 /* SessionMetadataSet */
302
303 SessionMetadataSet::SessionMetadataSet (string const & name)
304   : name (name)
305 {
306 }
307
308 void
309 SessionMetadataSet::add_data_field (MetadataPtr field)
310 {
311         list.push_back (field);
312 }
313
314 /* SessionMetadataSetEditable */
315
316 SessionMetadataSetEditable::SessionMetadataSetEditable (string const & name)
317   : SessionMetadataSet (name)
318 {
319         table.set_row_spacings (6);
320         table.set_col_spacings (12);
321         table.set_homogeneous (false);
322         vbox.pack_start (table, false, false);
323         vbox.set_spacing (6);
324         vbox.set_border_width (6);
325 }
326
327 Gtk::Widget &
328 SessionMetadataSetEditable::get_tab_widget ()
329 {
330         tab_widget.set_text (name);
331         return tab_widget;
332 }
333
334 void
335 SessionMetadataSetEditable::set_session (ARDOUR::Session * s)
336 {
337         SessionHandlePtr::set_session (s);
338
339         if (!_session) {
340                 return;
341         }
342
343         ARDOUR::SessionMetadata const & data = *(ARDOUR::SessionMetadata::Metadata());
344
345         table.resize (list.size(), 2);
346         uint32_t row = 0;
347         MetadataPtr field;
348         for (DataList::const_iterator it = list.begin(); it != list.end(); ++it) {
349                 field = *it;
350                 field->load_data (data);
351                 table.attach (field->name_widget(), 0, 1, row, row + 1, Gtk::FILL);
352                 table.attach (field->edit_widget(), 1, 2, row, row + 1);
353                 ++row;
354         }
355 }
356
357 void
358 SessionMetadataSetEditable::save_data ()
359 {
360         ARDOUR::SessionMetadata & data = *(ARDOUR::SessionMetadata::Metadata());
361         for (DataList::const_iterator it = list.begin(); it != list.end(); ++it) {
362                 (*it)->save_data(data);
363         }
364 }
365
366 /* SessionMetadataSetImportable */
367
368 SessionMetadataSetImportable::SessionMetadataSetImportable (string const & name)
369   : SessionMetadataSet (name)
370   , session_list (list)
371 {
372         tree = Gtk::ListStore::create (tree_cols);
373         tree_view.set_model (tree);
374
375         Gtk::TreeView::Column * viewcol;
376
377         // Add import column
378         Gtk::CellRendererToggle * import_render = Gtk::manage(new Gtk::CellRendererToggle());
379         import_render->signal_toggled().connect (sigc::mem_fun(*this, &SessionMetadataSetImportable::selection_changed));
380         viewcol = Gtk::manage(new Gtk::TreeView::Column (_("Import"), *import_render));
381         viewcol->add_attribute (import_render->property_active(), tree_cols.import);
382         tree_view.append_column (*viewcol);
383
384         // Add field name column
385         tree_view.append_column(_("Field"), tree_cols.field);
386
387         // Add values column with pango markup
388         Gtk::CellRendererText * values_render = Gtk::manage(new Gtk::CellRendererText());
389         viewcol = Gtk::manage(new Gtk::TreeView::Column (_("Values (current value on top)"), *values_render));
390         viewcol->add_attribute (values_render->property_markup(), tree_cols.values);
391         tree_view.append_column (*viewcol);
392
393         select_all_check.signal_toggled().connect (sigc::mem_fun(*this, &SessionMetadataSetImportable::select_all));
394 }
395
396 Gtk::Widget &
397 SessionMetadataSetImportable::get_tab_widget ()
398 {
399         tab_widget.set_text (name);
400         return tab_widget;
401 }
402
403 Gtk::Widget &
404 SessionMetadataSetImportable::get_select_all_widget ()
405 {
406         select_all_check.set_label (name);
407         return select_all_check;
408 }
409
410 void
411 SessionMetadataSetImportable::load_extra_data (ARDOUR::SessionMetadata const & data)
412 {
413         if (!_session) {
414                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataSetImportable (in load_data)!") << endmsg;
415                 return;
416         }
417
418         ARDOUR::SessionMetadata const & session_data = *(ARDOUR::SessionMetadata::Metadata());
419
420         MetadataPtr session_field;
421         MetadataPtr import_field;
422         DataList::iterator session_it;
423         DataList::iterator import_it;
424
425         // Copy list and load data to import
426         for (session_it = session_list.begin(); session_it != session_list.end(); ++session_it) {
427                 session_field = *session_it;
428                 session_field->load_data(session_data);
429                 import_list.push_back (session_field->copy());
430         }
431
432         // Fill widget
433         session_it = session_list.begin();
434         import_it = import_list.begin();
435         while (session_it != session_list.end() && import_it != import_list.end()) { // _should_ be the same...
436                 session_field = *session_it;
437                 import_field = *import_it;
438
439                 import_field->load_data(data); // hasn't been done yet
440
441                 // Make string for values TODO get color from somewhere?
442                 string values = "<span weight=\"ultralight\" color=\"#777\">" + session_field->value() + "</span>\n"
443                         + "<span weight=\"bold\">" + import_field->value() + "</span>";
444
445                 Gtk::TreeModel::iterator row_iter = tree->append();
446                 Gtk::TreeModel::Row row = *row_iter;
447
448                 row[tree_cols.field] = import_field->name();
449                 row[tree_cols.values] = values;
450                 row[tree_cols.import] = false;
451                 row[tree_cols.data] = import_field;
452
453                 ++session_it;
454                 ++import_it;
455         }
456 }
457
458 void
459 SessionMetadataSetImportable::save_data ()
460 {
461         if (!_session) {
462                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataSetImportable (in import_data)!") << endmsg;
463                 return;
464         }
465
466         ARDOUR::SessionMetadata & session_data = *(ARDOUR::SessionMetadata::Metadata());
467
468         Gtk::TreeModel::Children fields = tree->children();
469         Gtk::TreeModel::Children::iterator it;
470         for (it = fields.begin(); it != fields.end(); ++it) {
471                 if ((*it)[tree_cols.import]) {
472                         MetadataPtr field = (*it)[tree_cols.data];
473                         field->save_data (session_data);
474                 }
475         }
476 }
477
478 void
479 SessionMetadataSetImportable::select_all ()
480 {
481         select_all_check.set_inconsistent (false);
482         bool state = select_all_check.get_active();
483
484         Gtk::TreeModel::Children fields = tree->children();
485         Gtk::TreeModel::Children::iterator it;
486         for (it = fields.begin(); it != fields.end(); ++it) {
487                 (*it)[tree_cols.import] = state;
488         }
489 }
490
491 void
492 SessionMetadataSetImportable::selection_changed (string const & path)
493 {
494         select_all_check.set_inconsistent (true);
495
496         Gtk::TreeModel::iterator iter = tree->get_iter (path);
497         bool value((*iter)[tree_cols.import]);
498         (*iter)[tree_cols.import] = !value;
499 }
500
501 /* SessionMetadataDialog */
502
503 template <typename DataSet>
504 SessionMetadataDialog<DataSet>::SessionMetadataDialog (string const & name) :
505   ArdourDialog (name, true)
506 {
507         cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
508         cancel_button->signal_clicked().connect (sigc::mem_fun(*this, &SessionMetadataDialog::end_dialog));
509         save_button = add_button (Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
510         save_button->signal_clicked().connect (sigc::mem_fun(*this, &SessionMetadataDialog::save_and_close));
511 }
512
513 template <typename DataSet>
514 void
515 SessionMetadataDialog<DataSet>::init_data ( bool skip_user )
516 {
517         if (!_session) {
518                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataDialog (in init_data)!") << endmsg;
519                 return;
520         }
521
522         if (!skip_user)
523                 init_user_data ();
524         init_track_data ();
525         init_album_data ();
526         init_people_data ();
527         init_school_data ();
528
529         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
530                 (*it)->set_session (_session);
531
532                 notebook.append_page ((*it)->get_widget(), (*it)->get_tab_widget());
533         }
534 }
535
536 template <typename DataSet>
537 void
538 SessionMetadataDialog<DataSet>::load_extra_data (ARDOUR::SessionMetadata const & data)
539 {
540         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
541                 (*it)->load_extra_data (data);
542         }
543 }
544
545 template <typename DataSet>
546 void
547 SessionMetadataDialog<DataSet>::save_data ()
548 {
549         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
550                 (*it)->save_data ();
551         }
552 }
553
554 template <typename DataSet>
555 void
556 SessionMetadataDialog<DataSet>::save_and_close ()
557 {
558         save_data ();
559         _session->set_dirty();
560         end_dialog ();
561 }
562
563 template <typename DataSet>
564 void
565 SessionMetadataDialog<DataSet>::end_dialog ()
566 {
567         hide_all();
568 }
569
570 template <typename DataSet>
571 void
572 SessionMetadataDialog<DataSet>::warn_user (string const & string)
573 {
574         Gtk::MessageDialog msg (string, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
575         msg.run();
576 }
577
578 template <typename DataSet>
579 boost::shared_ptr<std::list<Gtk::Widget *> >
580 SessionMetadataDialog<DataSet>::get_custom_widgets (WidgetFunc f)
581 {
582         WidgetListPtr list (new WidgetList);
583         for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it)
584         {
585                 DataSet * set = dynamic_cast<DataSet *> (it->get());
586                 list->push_back (& CALL_MEMBER_FN (*set, f) ());
587         }
588
589         return list;
590 }
591
592 template <typename DataSet>
593 void
594 SessionMetadataDialog<DataSet>::add_widget (Gtk::Widget & widget)
595 {
596         get_vbox()->pack_start (widget, true, true, 0);
597 }
598
599 template <typename DataSet>
600 void
601 SessionMetadataDialog<DataSet>::init_user_data ()
602 {
603         DataSetPtr data_set (new DataSet (_("User")));
604         data_list.push_back (data_set);
605
606         MetadataPtr ptr;
607
608         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::user_name, &ARDOUR::SessionMetadata::set_user_name, _("Name")));
609         data_set->add_data_field (ptr);
610
611         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::user_email, &ARDOUR::SessionMetadata::set_user_email, _("Email")));
612         data_set->add_data_field (ptr);
613
614         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::user_web, &ARDOUR::SessionMetadata::set_user_web, _("Web")));
615         data_set->add_data_field (ptr);
616
617         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::organization, &ARDOUR::SessionMetadata::set_organization, _("Organization")));
618         data_set->add_data_field (ptr);
619
620         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::country, &ARDOUR::SessionMetadata::set_country, _("Country")));
621         data_set->add_data_field (ptr);
622
623 }
624
625 template <typename DataSet>
626 void
627 SessionMetadataDialog<DataSet>::init_track_data ()
628 {
629         DataSetPtr data_set (new DataSet (_("Track")));
630         data_list.push_back (data_set);
631
632         MetadataPtr ptr;
633
634         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::title, &ARDOUR::SessionMetadata::set_title, _("Title")));
635         data_set->add_data_field (ptr);
636
637         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::track_number, &ARDOUR::SessionMetadata::set_track_number, _("Track Number"), 3));
638         data_set->add_data_field (ptr);
639
640         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::subtitle, &ARDOUR::SessionMetadata::set_subtitle, _("Subtitle")));
641         data_set->add_data_field (ptr);
642
643         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::grouping, &ARDOUR::SessionMetadata::set_grouping, _("Grouping")));
644         data_set->add_data_field (ptr);
645
646         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::artist, &ARDOUR::SessionMetadata::set_artist, _("Artist")));
647         data_set->add_data_field (ptr);
648
649         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::genre, &ARDOUR::SessionMetadata::set_genre, _("Genre")));
650         data_set->add_data_field (ptr);
651
652         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::comment, &ARDOUR::SessionMetadata::set_comment, _("Comment")));
653         data_set->add_data_field (ptr);
654
655         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::copyright, &ARDOUR::SessionMetadata::set_copyright, _("Copyright")));
656         data_set->add_data_field (ptr);
657 }
658
659 template <typename DataSet>
660 void
661 SessionMetadataDialog<DataSet>::init_album_data ()
662 {
663         DataSetPtr data_set (new DataSet (_("Album")));
664         data_list.push_back (data_set);
665
666         MetadataPtr ptr;
667
668         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::album, &ARDOUR::SessionMetadata::set_album, _("Album")));
669         data_set->add_data_field (ptr);
670
671         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::year, &ARDOUR::SessionMetadata::set_year, _("Year"), 4));
672         data_set->add_data_field (ptr);
673
674         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::album_artist, &ARDOUR::SessionMetadata::set_album_artist, _("Album Artist")));
675         data_set->add_data_field (ptr);
676
677         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::total_tracks, &ARDOUR::SessionMetadata::set_total_tracks, _("Total Tracks"), 3));
678         data_set->add_data_field (ptr);
679
680         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::disc_subtitle, &ARDOUR::SessionMetadata::set_disc_subtitle, _("Disc Subtitle")));
681         data_set->add_data_field (ptr);
682
683         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::disc_number, &ARDOUR::SessionMetadata::set_disc_number, _("Disc Number"), 2));
684         data_set->add_data_field (ptr);
685
686         ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::total_discs, &ARDOUR::SessionMetadata::set_total_discs, _("Total Discs"), 2));
687         data_set->add_data_field (ptr);
688
689         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::compilation, &ARDOUR::SessionMetadata::set_compilation, _("Compilation")));
690         data_set->add_data_field (ptr);
691
692         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::isrc, &ARDOUR::SessionMetadata::set_isrc, _("ISRC")));
693         data_set->add_data_field (ptr);
694
695         ptr = MetadataPtr (new EAN13MetadataField (&ARDOUR::SessionMetadata::barcode, &ARDOUR::SessionMetadata::set_barcode, _("EAN barcode")));
696         data_set->add_data_field (ptr);
697 }
698
699 template <typename DataSet>
700 void
701 SessionMetadataDialog<DataSet>::init_people_data ()
702 {
703         DataSetPtr data_set (new DataSet (_("People")));
704         data_list.push_back (data_set);
705
706         MetadataPtr ptr;
707
708         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::lyricist, &ARDOUR::SessionMetadata::set_lyricist, _("Lyricist")));
709         data_set->add_data_field (ptr);
710
711         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::composer, &ARDOUR::SessionMetadata::set_composer, _("Composer")));
712         data_set->add_data_field (ptr);
713
714         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::conductor, &ARDOUR::SessionMetadata::set_conductor, _("Conductor")));
715         data_set->add_data_field (ptr);
716
717         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::remixer, &ARDOUR::SessionMetadata::set_remixer, _("Remixer")));
718         data_set->add_data_field (ptr);
719
720         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::arranger, &ARDOUR::SessionMetadata::set_arranger, _("Arranger")));
721         data_set->add_data_field (ptr);
722
723         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::engineer, &ARDOUR::SessionMetadata::set_engineer, _("Engineer")));
724         data_set->add_data_field (ptr);
725
726         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::producer, &ARDOUR::SessionMetadata::set_producer, _("Producer")));
727         data_set->add_data_field (ptr);
728
729         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::dj_mixer, &ARDOUR::SessionMetadata::set_dj_mixer, _("DJ Mixer")));
730         data_set->add_data_field (ptr);
731
732         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::mixer, &ARDOUR::SessionMetadata::set_mixer, S_("Metadata|Mixer")));
733         data_set->add_data_field (ptr);
734 }
735
736 template <typename DataSet>
737 void
738 SessionMetadataDialog<DataSet>::init_school_data ()
739 {
740         DataSetPtr data_set (new DataSet (_("School")));
741         data_list.push_back (data_set);
742
743         MetadataPtr ptr;
744
745         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::instructor, &ARDOUR::SessionMetadata::set_instructor, _("Instructor")));
746         data_set->add_data_field (ptr);
747
748         ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::course, &ARDOUR::SessionMetadata::set_course, _("Course")));
749         data_set->add_data_field (ptr);
750
751 }
752
753 /* SessionMetadataEditor */
754
755 SessionMetadataEditor::SessionMetadataEditor () :
756   SessionMetadataDialog<SessionMetadataSetEditable> (_("Edit Session Metadata"))
757 {
758
759 }
760
761 SessionMetadataEditor::~SessionMetadataEditor ()
762 {
763         // Remove pages from notebook to get rid of gsignal runtime warnings
764         notebook.pages().clear();
765 }
766
767 void
768 SessionMetadataEditor::run ()
769 {
770         init_data ();
771         init_gui();
772
773         ArdourDialog::run();
774 }
775
776 void
777 SessionMetadataEditor::init_gui ()
778 {
779         add_widget (notebook);
780
781         show_all();
782 }
783
784 /* SessionMetadataImporter */
785
786 SessionMetadataImporter::SessionMetadataImporter () :
787   SessionMetadataDialog<SessionMetadataSetImportable> (_("Import session metadata"))
788 {
789
790 }
791
792 SessionMetadataImporter::~SessionMetadataImporter ()
793 {
794         // Remove pages from notebook to get rid of gsignal runtime warnings
795         notebook.pages().clear();
796 }
797
798 void
799 SessionMetadataImporter::run ()
800 {
801         if (!_session) {
802                 error << string_compose (_("programming error: %1"), "no session set for SessionMetaDataImporter (in run)!") << endmsg;
803                 return;
804         }
805
806         /* Open session file selector */
807
808         Gtk::FileChooserDialog session_selector(_("Choose session to import metadata from"), Gtk::FILE_CHOOSER_ACTION_OPEN);
809         session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
810         session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
811         session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
812
813         Gtk::FileFilter session_filter;
814         session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
815         session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
816         session_selector.add_filter (session_filter);
817         session_selector.set_filter (session_filter);
818
819         int response = session_selector.run();
820         session_selector.hide ();
821
822         switch (response) {
823         case Gtk::RESPONSE_ACCEPT:
824                 break;
825         default:
826                 return;
827         }
828
829         string session_path = session_selector.get_filename();
830         string path, name;
831         bool isnew;
832
833         if (session_path.length() > 0) {
834                 if (ARDOUR::find_session (session_path, path, name, isnew) != 0) {
835                         return;
836                 }
837         } else {
838                 return;
839         }
840
841         /* We have a session: load the data and run dialog */
842
843         string filename = Glib::build_filename (path, name + ARDOUR::statefile_suffix);
844         XMLTree session_tree;
845         if (!session_tree.read (filename)) {
846                 warn_user (_("This session file could not be read!"));
847                 return;
848         }
849
850         /* XXX GET VERSION FROM TREE */
851         int version = 3000;
852
853         XMLNode * node = session_tree.root()->child ("Metadata");
854
855         if (!node) {
856                 warn_user (_("The session file didn't contain metadata!\nMaybe this is an old session format?"));
857                 return;
858         }
859
860         //create a temporary 
861         ARDOUR::SessionMetadata data;
862         data.set_state (*node, version);
863         init_data ( true );  //skip user data here
864         load_extra_data (data);
865         init_gui();
866
867         ArdourDialog::run();
868 }
869
870 void
871 SessionMetadataImporter::init_gui ()
872 {
873         // Select all from -widget
874         add_widget (selection_hbox);
875         selection_label.set_text (_("Import all from:"));
876         selection_hbox.pack_start (selection_label, false, false);
877
878         WidgetListPtr list = get_custom_widgets (&SessionMetadataSetImportable::get_select_all_widget);
879         for (WidgetList::iterator it = list->begin(); it != list->end(); ++it) {
880                 selection_hbox.pack_start (**it, false, false, 6);
881         }
882
883         add_widget (notebook);
884
885         show_all();
886 }