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