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