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