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