Clean up and hopefully fix handling of logarithmic plugin parameters (fixes #3769).
[ardour.git] / libs / ardour / export_multiplication.cc
1 /* This file is not used at the moment. It includes code related to export a
2  * multiplication graph system that can be used together with the ExportMultiplicator
3  * class in the gtk2_ardour folder.
4  * - Sakari Bergen 6.8.2008 -
5  */
6
7 void
8 ExportProfileManager::register_all_configs ()
9 {
10         list<TimespanNodePtr>::iterator tsl_it; // timespan list node iterator
11         for (tsl_it = graph.timespans.begin(); tsl_it != graph.timespans.end(); ++tsl_it) {
12                 list<GraphNode *>::const_iterator cc_it; // channel config node iterator
13                 for (cc_it = (*tsl_it)->get_children().begin(); cc_it != (*tsl_it)->get_children().end(); ++cc_it) {
14                         list<GraphNode *>::const_iterator f_it; // format node iterator
15                         for (f_it = (*cc_it)->get_children().begin(); f_it != (*cc_it)->get_children().end(); ++f_it) {
16                                 list<GraphNode *>::const_iterator fn_it; // filename node iterator
17                                 for (fn_it = (*f_it)->get_children().begin(); fn_it != (*f_it)->get_children().end(); ++fn_it) {
18                                         /* Finally loop through each timespan in the timespan list */
19
20                                         TimespanNodePtr ts_node;
21                                         if (!(ts_node = boost::dynamic_pointer_cast<TimespanNode> (*tsl_it))) {
22                                                 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
23                                         }
24
25                                         TimespanListPtr ts_list = ts_node->data()->timespans;
26                                         TimespanList::iterator ts_it;
27                                         for (ts_it = ts_list->begin(); ts_it != ts_list->end(); ++ts_it) {
28
29                                                 TimespanPtr timespan = *ts_it;
30
31                                                 ChannelConfigNode * cc_node;
32                                                 if (!(cc_node = dynamic_cast<ChannelConfigNode *> (*cc_it))) {
33                                                         throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
34                                                 }
35                                                 ChannelConfigPtr channel_config = cc_node->data()->config;
36
37                                                 FormatNode * f_node;
38                                                 if (!(f_node = dynamic_cast<FormatNode *> (*f_it))) {
39                                                         throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
40                                                 }
41                                                 FormatPtr format = f_node->data()->format;
42
43                                                 FilenameNode * fn_node;
44                                                 if (!(fn_node = dynamic_cast<FilenameNode *> (*fn_it))) {
45                                                         throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
46                                                 }
47                                                 FilenamePtr filename = fn_node->data()->filename;
48
49                                                 handler->add_export_config (timespan, channel_config, format, filename);
50                                         }
51                                 }
52                         }
53                 }
54         }
55 }
56
57 void
58 ExportProfileManager::create_empty_config ()
59 {
60         TimespanNodePtr timespan = TimespanNode::create (new TimespanState ());
61         timespan->data()->timespans->push_back (handler->add_timespan());
62
63         ChannelConfigNodePtr channel_config = ChannelConfigNode::create (new ChannelConfigState(handler->add_channel_config()));
64
65         FormatNodePtr format;
66         load_formats ();
67         if (!format_list.empty()) {
68                 format = FormatNode::create (new FormatState (*format_list.begin ()));
69         } else {
70                 format = FormatNode::create (new FormatState (handler->add_format ()));
71         }
72
73         FilenameNodePtr filename = FilenameNode::create (new FilenameState (handler->add_filename()));
74
75         /* Bring everything together */
76
77         timespan->add_child (channel_config.get(), 0);
78         channel_config->add_child (format.get(), 0);
79         format->add_child (filename.get(), 0);
80
81         graph.timespans.push_back (timespan);
82         graph.channel_configs.push_back (channel_config);
83         graph.formats.push_back (format);
84         graph.filenames.push_back (filename);
85 }
86
87 /*** GraphNode ***/
88
89 uint32_t ExportProfileManager::GraphNode::id_counter = 0;
90
91 ExportProfileManager::GraphNode::GraphNode ()
92 {
93         _id = ++id_counter;
94 }
95
96 ExportProfileManager::GraphNode::~GraphNode ()
97 {
98         while (!children.empty()) {
99                 remove_child (children.front());
100         }
101
102         while (!parents.empty()) {
103                 parents.front()->remove_child (this);
104         }
105 }
106
107 void
108 ExportProfileManager::GraphNode::add_parent (GraphNode * parent)
109 {
110         for (list<GraphNode *>::iterator it = parents.begin(); it != parents.end(); ++it) {
111                 if (*it == parent) {
112                         return;
113                 }
114         }
115
116         parents.push_back (parent);
117 }
118
119 void
120 ExportProfileManager::GraphNode::add_child (GraphNode * child, GraphNode * left_sibling)
121 {
122         for (list<GraphNode *>::iterator it = children.begin(); it != children.end(); ++it) {
123                 if (*it == child) {
124                         return;
125                 }
126         }
127
128         if (left_sibling) {
129                 insert_after (children, left_sibling, child);
130         } else {
131                 children.push_back (child);
132         }
133
134         child->add_parent (this);
135 }
136
137 bool
138 ExportProfileManager::GraphNode::is_ancestor_of (GraphNode const * node) const
139 {
140         for (list<GraphNode *>::const_iterator it = children.begin(); it != children.end(); ++it) {
141                 if (*it == node || (*it)->is_ancestor_of (node)) {
142                         return true;
143                 }
144         }
145
146         return false;
147 }
148
149 bool
150 ExportProfileManager::GraphNode::is_descendant_of (GraphNode const * node) const
151 {
152         for (list<GraphNode *>::const_iterator it = parents.begin(); it != parents.end(); ++it) {
153                 if (*it == node || (*it)->is_descendant_of (node)) {
154                         return true;
155                 }
156         }
157
158         return false;
159 }
160
161 void
162 ExportProfileManager::GraphNode::select (bool value)
163 {
164         if (_selected == value) { return; }
165
166         _selected = value;
167         SelectChanged (value);
168 }
169
170 void
171 ExportProfileManager::GraphNode::remove_parent (GraphNode * parent)
172 {
173         for (list<GraphNode *>::iterator it = parents.begin(); it != parents.end(); ++it) {
174                 if (*it == parent) {
175                         parents.erase (it);
176                         break;
177                 }
178         }
179 }
180
181 void
182 ExportProfileManager::GraphNode::remove_child (GraphNode * child)
183 {
184         for (list<GraphNode *>::iterator it = children.begin(); it != children.end(); ++it) {
185                 if (*it == child) {
186                         children.erase (it);
187                         break;
188                 }
189         }
190
191         child->remove_parent (this);
192 }
193
194 void
195 ExportProfileManager::split_node (GraphNode * node, float position)
196 {
197         TimespanNode * ts_node;
198         if ((ts_node = dynamic_cast<TimespanNode *> (node))) {
199                 split_timespan (ts_node->self_ptr(), position);
200                 return;
201         }
202
203         ChannelConfigNode * cc_node;
204         if ((cc_node = dynamic_cast<ChannelConfigNode *> (node))) {
205                 split_channel_config (cc_node->self_ptr(), position);
206                 return;
207         }
208
209         FormatNode * f_node;
210         if ((f_node = dynamic_cast<FormatNode *> (node))) {
211                 split_format (f_node->self_ptr(), position);
212                 return;
213         }
214
215         FilenameNode * fn_node;
216         if ((fn_node = dynamic_cast<FilenameNode *> (node))) {
217                 split_filename (fn_node->self_ptr(), position);
218                 return;
219         }
220 }
221
222 void
223 ExportProfileManager::remove_node (GraphNode * node)
224 {
225         TimespanNode * ts_node;
226         if ((ts_node = dynamic_cast<TimespanNode *> (node))) {
227                 remove_timespan (ts_node->self_ptr());
228                 return;
229         }
230
231         ChannelConfigNode * cc_node;
232         if ((cc_node = dynamic_cast<ChannelConfigNode *> (node))) {
233                 remove_channel_config (cc_node->self_ptr());
234                 return;
235         }
236
237         FormatNode * f_node;
238         if ((f_node = dynamic_cast<FormatNode *> (node))) {
239                 remove_format (f_node->self_ptr());
240                 return;
241         }
242
243         FilenameNode * fn_node;
244         if ((fn_node = dynamic_cast<FilenameNode *> (node))) {
245                 remove_filename (fn_node->self_ptr());
246                 return;
247         }
248 }
249
250 void
251 ExportProfileManager::purge_graph ()
252 {
253         for (list<TimespanNodePtr>::iterator it = graph.timespans.begin(); it != graph.timespans.end(); ) {
254                 list<TimespanNodePtr>::iterator tmp = it;
255                 ++it;
256
257                 if ((*tmp)->get_children().empty()) {
258                         graph.timespans.erase (tmp);
259                 }
260         }
261
262         for (list<ChannelConfigNodePtr>::iterator it = graph.channel_configs.begin(); it != graph.channel_configs.end(); ) {
263                 list<ChannelConfigNodePtr>::iterator tmp = it;
264                 ++it;
265
266                 if ((*tmp)->get_parents().empty()) {
267                         graph.channel_configs.erase (tmp);
268                 }
269         }
270
271         for (list<FormatNodePtr>::iterator it = graph.formats.begin(); it != graph.formats.end(); ) {
272                 list<FormatNodePtr>::iterator tmp = it;
273                 ++it;
274
275                 if ((*tmp)->get_parents().empty()) {
276                         graph.formats.erase (tmp);
277                 }
278         }
279
280         for (list<FilenameNodePtr>::iterator it = graph.filenames.begin(); it != graph.filenames.end(); ) {
281                 list<FilenameNodePtr>::iterator tmp = it;
282                 ++it;
283
284                 if ((*tmp)->get_parents().empty()) {
285                         graph.filenames.erase (tmp);
286                 }
287         }
288
289         GraphChanged();
290 }
291
292 template<typename T>
293 void
294 ExportProfileManager::insert_after (list<T> & the_list, T const & position, T const & element)
295 {
296         typename list<T>::iterator it;
297         for (it = the_list.begin(); it != the_list.end(); ++it) {
298                 if (*it == position) {
299                         the_list.insert (++it, element);
300                         return;
301                 }
302         }
303
304         std::cerr << "invalid position given to ExportProfileManager::insert_after (aborting)" << std::endl;
305
306         abort();
307 }
308
309 template<typename T>
310 void
311 ExportProfileManager::remove_by_element (list<T> & the_list, T const & element)
312 {
313         typename list<T>::iterator it;
314         for (it = the_list.begin(); it != the_list.end(); ++it) {
315                 if (*it == element) {
316                         the_list.erase (it);
317                         return;
318                 }
319         }
320 }
321
322 bool
323 ExportProfileManager::nodes_have_one_common_child (list<GraphNode *> const & the_list)
324 {
325         return end_of_common_child_range (the_list, the_list.begin()) == --the_list.end();
326 }
327
328 list<ExportProfileManager::GraphNode *>::const_iterator
329 ExportProfileManager::end_of_common_child_range (list<GraphNode *> const & the_list, list<GraphNode *>::const_iterator beginning)
330 {
331         if ((*beginning)->get_children().size() != 1) { return beginning; }
332         GraphNode * child = (*beginning)->get_children().front();
333
334         list<GraphNode *>::const_iterator it = beginning;
335         while (it != the_list.end() && (*it)->get_children().size() == 1 && (*it)->get_children().front() == child) {
336                 ++it;
337         }
338
339         return --it;
340 }
341
342 void
343 ExportProfileManager::split_node_at_position (GraphNode * old_node, GraphNode * new_node, float position)
344 {
345         list<GraphNode *> const & node_parents = old_node->get_parents();
346         uint32_t split_index = (int) (node_parents.size() * position + 0.5);
347         split_index = std::max ((uint32_t) 1, std::min (split_index, node_parents.size() - 1));
348
349         list<GraphNode *>::const_iterator it = node_parents.begin();
350         for (uint32_t index = 1; it != node_parents.end(); ++index) {
351                 if (index > split_index) {
352                         list<GraphNode *>::const_iterator tmp = it++;
353                         (*tmp)->add_child (new_node, old_node);
354                         (*tmp)->remove_child (old_node);
355                 } else {
356                         ++it;
357                 }
358         }
359 }
360
361 void
362 ExportProfileManager::split_timespan (TimespanNodePtr node, float)
363 {
364         TimespanNodePtr new_timespan = duplicate_timespan_node (node);
365         insert_after (graph.timespans, node, new_timespan);
366
367         /* Note: Since a timespan selector allows all combinations of ranges
368          * there is no reason for a channel configuration to have two parents
369          */
370
371         duplicate_timespan_children (node->self_ptr(), new_timespan);
372
373         GraphChanged();
374 }
375
376 void
377 ExportProfileManager::split_channel_config (ChannelConfigNodePtr node, float)
378 {
379         ChannelConfigNodePtr new_config = duplicate_channel_config_node (node);
380         insert_after (graph.channel_configs, node, new_config);
381
382         /* Channel configs have only one parent, see above! */
383         node->get_parents().front()->add_child (new_config.get(), node.get());
384
385         if (node->get_children().size() == 1) {
386                 new_config->add_child (node->first_child(), 0);
387         } else {
388                 duplicate_channel_config_children (node, new_config);
389         }
390
391         GraphChanged();
392 }
393
394 void
395 ExportProfileManager::split_format (FormatNodePtr node, float position)
396 {
397         FormatNodePtr new_format = duplicate_format_node (node);
398         insert_after (graph.formats, node, new_format);
399
400         list<GraphNode *> const & node_parents = node->get_parents();
401         if (node_parents.size() == 1) {
402                 node_parents.front()->add_child (new_format.get(), 0);
403         } else {
404                 node->sort_parents (graph.channel_configs);
405                 split_node_at_position (node.get(), new_format.get(), position);
406         }
407
408         if (node->get_children().size() == 1) {
409                 new_format->add_child (node->first_child(), 0);
410         } else {
411                 duplicate_format_children (node, new_format);
412         }
413
414         GraphChanged();
415 }
416
417 void
418 ExportProfileManager::split_filename (FilenameNodePtr node, float position)
419 {
420         FilenameNodePtr new_filename = duplicate_filename_node (node);
421         insert_after (graph.filenames, node, new_filename);
422
423         list<GraphNode *> const & node_parents = node->get_parents();
424
425         if (node_parents.size() == 1) {
426                 node_parents.front()->add_child (new_filename.get(), 0);
427         } else {
428                 node->sort_parents (graph.formats);
429                 split_node_at_position (node.get(), new_filename.get(), position);
430         }
431
432         GraphChanged();
433 }
434
435 void
436 ExportProfileManager::duplicate_timespan_children (TimespanNodePtr source, TimespanNodePtr target, GraphNode * insertion_point)
437 {
438         list<GraphNode *> const & source_children = source->get_children();
439         bool one_grandchild = nodes_have_one_common_child (source_children);
440         GraphNode * child_insertion_point = 0;
441
442         ChannelConfigNodePtr node_insertion_point;
443         ChannelConfigNode * node_insertion_ptr;
444         if (!insertion_point) { insertion_point = source->last_child(); }
445         if (!(node_insertion_ptr = dynamic_cast<ChannelConfigNode *> (insertion_point))) {
446                 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
447         }
448         node_insertion_point = node_insertion_ptr->self_ptr();
449
450         /* Keep track of common children */
451
452         list<GraphNode *>::const_iterator common_children_begin = source_children.begin();
453         list<GraphNode *>::const_iterator common_children_end = end_of_common_child_range (source_children, source_children.begin());
454         GraphNode * common_child = 0;
455
456         for (list<GraphNode *>::const_iterator it = source_children.begin(); it != source_children.end(); ++it) {
457                 /* Duplicate node */
458
459                 ChannelConfigNode *  node;
460                 ChannelConfigNodePtr new_node;
461
462                 if (!(node = dynamic_cast<ChannelConfigNode *> (*it))) {
463                         throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
464                 }
465
466                 new_node = duplicate_channel_config_node (node->self_ptr());
467
468                 /* Insert in gaph's list and update insertion position */
469
470                 insert_after (graph.channel_configs, node_insertion_point, new_node);
471                 node_insertion_point = new_node;
472
473                 /* Handle children */
474
475                 target->add_child (new_node.get(), child_insertion_point);
476                 child_insertion_point = new_node.get();
477
478                 if (one_grandchild) {
479                         new_node->add_child (node->first_child(), 0);
480                 } else {
481                         list<GraphNode *>::const_iterator past_end = common_children_end;
482                         if (it == ++past_end) { // At end => start new range
483                                 common_children_begin = it;
484                                 common_children_end = end_of_common_child_range (source_children, it);
485                         }
486
487                         if (it == common_children_begin) { // At beginning => do duplication
488                                 GraphNode * grand_child_ins_pt = common_child;
489                                 if (!grand_child_ins_pt) {
490                                         grand_child_ins_pt = source->last_child()->last_child();
491                                 }
492                                 duplicate_channel_config_children (node->self_ptr(), new_node, grand_child_ins_pt);
493                                 common_child = new_node->first_child();
494                         } else { // Somewhere in between end and beginning => share child
495                                 new_node->add_child (common_child, 0);
496                         }
497                 }
498         }
499 }
500
501 void
502 ExportProfileManager::duplicate_channel_config_children (ChannelConfigNodePtr source, ChannelConfigNodePtr target, GraphNode * insertion_point)
503 {
504         list<GraphNode *> const & source_children = source->get_children();
505         bool one_grandchild = nodes_have_one_common_child (source_children);
506         GraphNode * child_insertion_point = 0;
507
508         FormatNodePtr node_insertion_point;
509         FormatNode * node_insertion_ptr;
510         if (!insertion_point) { insertion_point = source->last_child(); }
511         if (!(node_insertion_ptr = dynamic_cast<FormatNode *> (insertion_point))) {
512                 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
513         }
514         node_insertion_point = node_insertion_ptr->self_ptr();
515
516         /* Keep track of common children */
517
518         list<GraphNode *>::const_iterator common_children_begin = source_children.begin();
519         list<GraphNode *>::const_iterator common_children_end = end_of_common_child_range (source_children, source_children.begin());
520         GraphNode * common_child = 0;
521
522         for (list<GraphNode *>::const_iterator it = source_children.begin(); it != source_children.end(); ++it) {
523                 /* Duplicate node */
524
525                 FormatNode *  node;
526                 FormatNodePtr new_node;
527
528                 if (!(node = dynamic_cast<FormatNode *> (*it))) {
529                         throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
530                 }
531
532                 new_node = duplicate_format_node (node->self_ptr());
533
534                 /* Insert in gaph's list and update insertion position */
535
536                 insert_after (graph.formats, node_insertion_point, new_node);
537                 node_insertion_point = new_node;
538
539                 /* Handle children */
540
541                 target->add_child (new_node.get(), child_insertion_point);
542                 child_insertion_point = new_node.get();
543
544                 if (one_grandchild) {
545                         new_node->add_child (node->first_child(), 0);
546                 } else {
547                         list<GraphNode *>::const_iterator past_end = common_children_end;
548                         if (it == ++past_end) { // At end => start new range
549                                 common_children_begin = it;
550                                 common_children_end = end_of_common_child_range (source_children, it);
551                         }
552
553                         if (it == common_children_begin) { // At beginning => do duplication
554                                 GraphNode * grand_child_ins_pt = common_child;
555                                 if (!grand_child_ins_pt) {
556                                         grand_child_ins_pt = source->get_parents().back()->last_child()->last_child()->last_child();
557                                 }
558                                 duplicate_format_children (node->self_ptr(), new_node, grand_child_ins_pt);
559                                 common_child = new_node->first_child();
560                         } else { // Somewhere in between end and beginning => share child
561                                 new_node->add_child (common_child, 0);
562                         }
563                 }
564         }
565 }
566
567 void
568 ExportProfileManager::duplicate_format_children (FormatNodePtr source, FormatNodePtr target, GraphNode * insertion_point)
569 {
570         GraphNode * child_insertion_point = 0;
571
572         FilenameNodePtr node_insertion_point;
573         FilenameNode * node_insertion_ptr;
574         if (!insertion_point) { insertion_point = source->last_child(); }
575         if (!(node_insertion_ptr = dynamic_cast<FilenameNode *> (insertion_point))) {
576                 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
577         }
578         node_insertion_point = node_insertion_ptr->self_ptr();
579
580         for (list<GraphNode *>::const_iterator it = source->get_children().begin(); it != source->get_children().end(); ++it) {
581                 /* Duplicate node */
582
583                 FilenameNode *  node;
584                 FilenameNodePtr new_node;
585
586                 if (!(node = dynamic_cast<FilenameNode *> (*it))) {
587                         throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
588                 }
589
590                 new_node = duplicate_filename_node (node->self_ptr());
591
592                 /* Insert in gaph's list and update insertion position */
593
594                 insert_after (graph.filenames, node_insertion_point, new_node);
595                 node_insertion_point = new_node;
596
597                 /* Handle children */
598
599                 target->add_child (new_node.get(), child_insertion_point);
600                 child_insertion_point = new_node.get();
601         }
602 }
603
604 ExportProfileManager::TimespanNodePtr
605 ExportProfileManager::duplicate_timespan_node (TimespanNodePtr node)
606 {
607         TimespanStatePtr state = node->data();
608         TimespanStatePtr new_state (new TimespanState ());
609         TimespanNodePtr  new_node = TimespanNode::create (new_state);
610
611         for (TimespanList::iterator it = state->timespans->begin(); it != state->timespans->end(); ++it) {
612                 new_state->timespans->push_back (handler->add_timespan_copy (*it));
613         }
614
615         new_state->time_format = state->time_format;
616         new_state->marker_format = state->marker_format;
617
618         return new_node;
619 }
620
621 ExportProfileManager::ChannelConfigNodePtr
622 ExportProfileManager::duplicate_channel_config_node (ChannelConfigNodePtr node)
623 {
624         ChannelConfigStatePtr state = node->data();
625         ChannelConfigStatePtr new_state (new ChannelConfigState (handler->add_channel_config_copy (state->config)));
626         ChannelConfigNodePtr  new_node = ChannelConfigNode::create (new_state);
627
628         return new_node;
629 }
630
631 ExportProfileManager::FormatNodePtr
632 ExportProfileManager::duplicate_format_node (FormatNodePtr node)
633 {
634         FormatStatePtr state = node->data();
635         FormatStatePtr new_state (new FormatState (handler->add_format_copy (state->format)));
636         FormatNodePtr  new_node = FormatNode::create (new_state);
637
638         return new_node;
639 }
640
641 ExportProfileManager::FilenameNodePtr
642 ExportProfileManager::duplicate_filename_node (FilenameNodePtr node)
643 {
644         FilenameStatePtr state = node->data();
645         FilenameStatePtr new_state (new FilenameState (handler->add_filename_copy (state->filename)));
646         FilenameNodePtr  new_node = FilenameNode::create (new_state);
647
648         return new_node;
649 }
650
651 void
652 ExportProfileManager::remove_timespan (TimespanNodePtr node)
653 {
654         remove_by_element (graph.timespans, node);
655         purge_graph ();
656 }
657
658 void
659 ExportProfileManager::remove_channel_config (ChannelConfigNodePtr node)
660 {
661         remove_by_element (graph.channel_configs, node);
662         purge_graph ();
663 }
664
665 void
666 ExportProfileManager::remove_format (FormatNodePtr node)
667 {
668         remove_by_element (graph.formats, node);
669         purge_graph ();
670 }
671
672 void
673 ExportProfileManager::remove_filename (FilenameNodePtr node)
674 {
675         remove_by_element (graph.filenames, node);
676         purge_graph ();
677 }