2 Copyright (C) 2008-2012 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* This file is not used at the moment. It includes code related to export a
22 * multiplication graph system that can be used together with the ExportMultiplicator
23 * class in the gtk2_ardour folder.
24 * - Sakari Bergen 6.8.2008 -
28 ExportProfileManager::register_all_configs ()
30 list<TimespanNodePtr>::iterator tsl_it; // timespan list node iterator
31 for (tsl_it = graph.timespans.begin(); tsl_it != graph.timespans.end(); ++tsl_it) {
32 list<GraphNode *>::const_iterator cc_it; // channel config node iterator
33 for (cc_it = (*tsl_it)->get_children().begin(); cc_it != (*tsl_it)->get_children().end(); ++cc_it) {
34 list<GraphNode *>::const_iterator f_it; // format node iterator
35 for (f_it = (*cc_it)->get_children().begin(); f_it != (*cc_it)->get_children().end(); ++f_it) {
36 list<GraphNode *>::const_iterator fn_it; // filename node iterator
37 for (fn_it = (*f_it)->get_children().begin(); fn_it != (*f_it)->get_children().end(); ++fn_it) {
38 /* Finally loop through each timespan in the timespan list */
40 TimespanNodePtr ts_node;
41 if (!(ts_node = boost::dynamic_pointer_cast<TimespanNode> (*tsl_it))) {
42 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
45 TimespanListPtr ts_list = ts_node->data()->timespans;
46 TimespanList::iterator ts_it;
47 for (ts_it = ts_list->begin(); ts_it != ts_list->end(); ++ts_it) {
49 TimespanPtr timespan = *ts_it;
51 ChannelConfigNode * cc_node;
52 if (!(cc_node = dynamic_cast<ChannelConfigNode *> (*cc_it))) {
53 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
55 ChannelConfigPtr channel_config = cc_node->data()->config;
58 if (!(f_node = dynamic_cast<FormatNode *> (*f_it))) {
59 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
61 FormatPtr format = f_node->data()->format;
63 FilenameNode * fn_node;
64 if (!(fn_node = dynamic_cast<FilenameNode *> (*fn_it))) {
65 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
67 FilenamePtr filename = fn_node->data()->filename;
69 handler->add_export_config (timespan, channel_config, format, filename);
78 ExportProfileManager::create_empty_config ()
80 TimespanNodePtr timespan = TimespanNode::create (new TimespanState ());
81 timespan->data()->timespans->push_back (handler->add_timespan());
83 ChannelConfigNodePtr channel_config = ChannelConfigNode::create (new ChannelConfigState(handler->add_channel_config()));
87 if (!format_list.empty()) {
88 format = FormatNode::create (new FormatState (*format_list.begin ()));
90 format = FormatNode::create (new FormatState (handler->add_format ()));
93 FilenameNodePtr filename = FilenameNode::create (new FilenameState (handler->add_filename()));
95 /* Bring everything together */
97 timespan->add_child (channel_config.get(), 0);
98 channel_config->add_child (format.get(), 0);
99 format->add_child (filename.get(), 0);
101 graph.timespans.push_back (timespan);
102 graph.channel_configs.push_back (channel_config);
103 graph.formats.push_back (format);
104 graph.filenames.push_back (filename);
109 uint32_t ExportProfileManager::GraphNode::id_counter = 0;
111 ExportProfileManager::GraphNode::GraphNode ()
116 ExportProfileManager::GraphNode::~GraphNode ()
118 while (!children.empty()) {
119 remove_child (children.front());
122 while (!parents.empty()) {
123 parents.front()->remove_child (this);
128 ExportProfileManager::GraphNode::add_parent (GraphNode * parent)
130 for (list<GraphNode *>::iterator it = parents.begin(); it != parents.end(); ++it) {
136 parents.push_back (parent);
140 ExportProfileManager::GraphNode::add_child (GraphNode * child, GraphNode * left_sibling)
142 for (list<GraphNode *>::iterator it = children.begin(); it != children.end(); ++it) {
149 insert_after (children, left_sibling, child);
151 children.push_back (child);
154 child->add_parent (this);
158 ExportProfileManager::GraphNode::is_ancestor_of (GraphNode const * node) const
160 for (list<GraphNode *>::const_iterator it = children.begin(); it != children.end(); ++it) {
161 if (*it == node || (*it)->is_ancestor_of (node)) {
170 ExportProfileManager::GraphNode::is_descendant_of (GraphNode const * node) const
172 for (list<GraphNode *>::const_iterator it = parents.begin(); it != parents.end(); ++it) {
173 if (*it == node || (*it)->is_descendant_of (node)) {
182 ExportProfileManager::GraphNode::select (bool value)
184 if (_selected == value) { return; }
187 SelectChanged (value);
191 ExportProfileManager::GraphNode::remove_parent (GraphNode * parent)
193 for (list<GraphNode *>::iterator it = parents.begin(); it != parents.end(); ++it) {
202 ExportProfileManager::GraphNode::remove_child (GraphNode * child)
204 for (list<GraphNode *>::iterator it = children.begin(); it != children.end(); ++it) {
211 child->remove_parent (this);
215 ExportProfileManager::split_node (GraphNode * node, float position)
217 TimespanNode * ts_node;
218 if ((ts_node = dynamic_cast<TimespanNode *> (node))) {
219 split_timespan (ts_node->self_ptr(), position);
223 ChannelConfigNode * cc_node;
224 if ((cc_node = dynamic_cast<ChannelConfigNode *> (node))) {
225 split_channel_config (cc_node->self_ptr(), position);
230 if ((f_node = dynamic_cast<FormatNode *> (node))) {
231 split_format (f_node->self_ptr(), position);
235 FilenameNode * fn_node;
236 if ((fn_node = dynamic_cast<FilenameNode *> (node))) {
237 split_filename (fn_node->self_ptr(), position);
243 ExportProfileManager::remove_node (GraphNode * node)
245 TimespanNode * ts_node;
246 if ((ts_node = dynamic_cast<TimespanNode *> (node))) {
247 remove_timespan (ts_node->self_ptr());
251 ChannelConfigNode * cc_node;
252 if ((cc_node = dynamic_cast<ChannelConfigNode *> (node))) {
253 remove_channel_config (cc_node->self_ptr());
258 if ((f_node = dynamic_cast<FormatNode *> (node))) {
259 remove_format (f_node->self_ptr());
263 FilenameNode * fn_node;
264 if ((fn_node = dynamic_cast<FilenameNode *> (node))) {
265 remove_filename (fn_node->self_ptr());
271 ExportProfileManager::purge_graph ()
273 for (list<TimespanNodePtr>::iterator it = graph.timespans.begin(); it != graph.timespans.end(); ) {
274 list<TimespanNodePtr>::iterator tmp = it;
277 if ((*tmp)->get_children().empty()) {
278 graph.timespans.erase (tmp);
282 for (list<ChannelConfigNodePtr>::iterator it = graph.channel_configs.begin(); it != graph.channel_configs.end(); ) {
283 list<ChannelConfigNodePtr>::iterator tmp = it;
286 if ((*tmp)->get_parents().empty()) {
287 graph.channel_configs.erase (tmp);
291 for (list<FormatNodePtr>::iterator it = graph.formats.begin(); it != graph.formats.end(); ) {
292 list<FormatNodePtr>::iterator tmp = it;
295 if ((*tmp)->get_parents().empty()) {
296 graph.formats.erase (tmp);
300 for (list<FilenameNodePtr>::iterator it = graph.filenames.begin(); it != graph.filenames.end(); ) {
301 list<FilenameNodePtr>::iterator tmp = it;
304 if ((*tmp)->get_parents().empty()) {
305 graph.filenames.erase (tmp);
314 ExportProfileManager::insert_after (list<T> & the_list, T const & position, T const & element)
316 typename list<T>::iterator it;
317 for (it = the_list.begin(); it != the_list.end(); ++it) {
318 if (*it == position) {
319 the_list.insert (++it, element);
324 std::cerr << "invalid position given to ExportProfileManager::insert_after (aborting)" << std::endl;
331 ExportProfileManager::remove_by_element (list<T> & the_list, T const & element)
333 typename list<T>::iterator it;
334 for (it = the_list.begin(); it != the_list.end(); ++it) {
335 if (*it == element) {
343 ExportProfileManager::nodes_have_one_common_child (list<GraphNode *> const & the_list)
345 return end_of_common_child_range (the_list, the_list.begin()) == --the_list.end();
348 list<ExportProfileManager::GraphNode *>::const_iterator
349 ExportProfileManager::end_of_common_child_range (list<GraphNode *> const & the_list, list<GraphNode *>::const_iterator beginning)
351 if ((*beginning)->get_children().size() != 1) { return beginning; }
352 GraphNode * child = (*beginning)->get_children().front();
354 list<GraphNode *>::const_iterator it = beginning;
355 while (it != the_list.end() && (*it)->get_children().size() == 1 && (*it)->get_children().front() == child) {
363 ExportProfileManager::split_node_at_position (GraphNode * old_node, GraphNode * new_node, float position)
365 list<GraphNode *> const & node_parents = old_node->get_parents();
366 uint32_t split_index = (int) (node_parents.size() * position + 0.5);
367 split_index = std::max ((uint32_t) 1, std::min (split_index, node_parents.size() - 1));
369 list<GraphNode *>::const_iterator it = node_parents.begin();
370 for (uint32_t index = 1; it != node_parents.end(); ++index) {
371 if (index > split_index) {
372 list<GraphNode *>::const_iterator tmp = it++;
373 (*tmp)->add_child (new_node, old_node);
374 (*tmp)->remove_child (old_node);
382 ExportProfileManager::split_timespan (TimespanNodePtr node, float)
384 TimespanNodePtr new_timespan = duplicate_timespan_node (node);
385 insert_after (graph.timespans, node, new_timespan);
387 /* Note: Since a timespan selector allows all combinations of ranges
388 * there is no reason for a channel configuration to have two parents
391 duplicate_timespan_children (node->self_ptr(), new_timespan);
397 ExportProfileManager::split_channel_config (ChannelConfigNodePtr node, float)
399 ChannelConfigNodePtr new_config = duplicate_channel_config_node (node);
400 insert_after (graph.channel_configs, node, new_config);
402 /* Channel configs have only one parent, see above! */
403 node->get_parents().front()->add_child (new_config.get(), node.get());
405 if (node->get_children().size() == 1) {
406 new_config->add_child (node->first_child(), 0);
408 duplicate_channel_config_children (node, new_config);
415 ExportProfileManager::split_format (FormatNodePtr node, float position)
417 FormatNodePtr new_format = duplicate_format_node (node);
418 insert_after (graph.formats, node, new_format);
420 list<GraphNode *> const & node_parents = node->get_parents();
421 if (node_parents.size() == 1) {
422 node_parents.front()->add_child (new_format.get(), 0);
424 node->sort_parents (graph.channel_configs);
425 split_node_at_position (node.get(), new_format.get(), position);
428 if (node->get_children().size() == 1) {
429 new_format->add_child (node->first_child(), 0);
431 duplicate_format_children (node, new_format);
438 ExportProfileManager::split_filename (FilenameNodePtr node, float position)
440 FilenameNodePtr new_filename = duplicate_filename_node (node);
441 insert_after (graph.filenames, node, new_filename);
443 list<GraphNode *> const & node_parents = node->get_parents();
445 if (node_parents.size() == 1) {
446 node_parents.front()->add_child (new_filename.get(), 0);
448 node->sort_parents (graph.formats);
449 split_node_at_position (node.get(), new_filename.get(), position);
456 ExportProfileManager::duplicate_timespan_children (TimespanNodePtr source, TimespanNodePtr target, GraphNode * insertion_point)
458 list<GraphNode *> const & source_children = source->get_children();
459 bool one_grandchild = nodes_have_one_common_child (source_children);
460 GraphNode * child_insertion_point = 0;
462 ChannelConfigNodePtr node_insertion_point;
463 ChannelConfigNode * node_insertion_ptr;
464 if (!insertion_point) { insertion_point = source->last_child(); }
465 if (!(node_insertion_ptr = dynamic_cast<ChannelConfigNode *> (insertion_point))) {
466 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
468 node_insertion_point = node_insertion_ptr->self_ptr();
470 /* Keep track of common children */
472 list<GraphNode *>::const_iterator common_children_begin = source_children.begin();
473 list<GraphNode *>::const_iterator common_children_end = end_of_common_child_range (source_children, source_children.begin());
474 GraphNode * common_child = 0;
476 for (list<GraphNode *>::const_iterator it = source_children.begin(); it != source_children.end(); ++it) {
479 ChannelConfigNode * node;
480 ChannelConfigNodePtr new_node;
482 if (!(node = dynamic_cast<ChannelConfigNode *> (*it))) {
483 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
486 new_node = duplicate_channel_config_node (node->self_ptr());
488 /* Insert in gaph's list and update insertion position */
490 insert_after (graph.channel_configs, node_insertion_point, new_node);
491 node_insertion_point = new_node;
493 /* Handle children */
495 target->add_child (new_node.get(), child_insertion_point);
496 child_insertion_point = new_node.get();
498 if (one_grandchild) {
499 new_node->add_child (node->first_child(), 0);
501 list<GraphNode *>::const_iterator past_end = common_children_end;
502 if (it == ++past_end) { // At end => start new range
503 common_children_begin = it;
504 common_children_end = end_of_common_child_range (source_children, it);
507 if (it == common_children_begin) { // At beginning => do duplication
508 GraphNode * grand_child_ins_pt = common_child;
509 if (!grand_child_ins_pt) {
510 grand_child_ins_pt = source->last_child()->last_child();
512 duplicate_channel_config_children (node->self_ptr(), new_node, grand_child_ins_pt);
513 common_child = new_node->first_child();
514 } else { // Somewhere in between end and beginning => share child
515 new_node->add_child (common_child, 0);
522 ExportProfileManager::duplicate_channel_config_children (ChannelConfigNodePtr source, ChannelConfigNodePtr target, GraphNode * insertion_point)
524 list<GraphNode *> const & source_children = source->get_children();
525 bool one_grandchild = nodes_have_one_common_child (source_children);
526 GraphNode * child_insertion_point = 0;
528 FormatNodePtr node_insertion_point;
529 FormatNode * node_insertion_ptr;
530 if (!insertion_point) { insertion_point = source->last_child(); }
531 if (!(node_insertion_ptr = dynamic_cast<FormatNode *> (insertion_point))) {
532 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
534 node_insertion_point = node_insertion_ptr->self_ptr();
536 /* Keep track of common children */
538 list<GraphNode *>::const_iterator common_children_begin = source_children.begin();
539 list<GraphNode *>::const_iterator common_children_end = end_of_common_child_range (source_children, source_children.begin());
540 GraphNode * common_child = 0;
542 for (list<GraphNode *>::const_iterator it = source_children.begin(); it != source_children.end(); ++it) {
546 FormatNodePtr new_node;
548 if (!(node = dynamic_cast<FormatNode *> (*it))) {
549 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
552 new_node = duplicate_format_node (node->self_ptr());
554 /* Insert in gaph's list and update insertion position */
556 insert_after (graph.formats, node_insertion_point, new_node);
557 node_insertion_point = new_node;
559 /* Handle children */
561 target->add_child (new_node.get(), child_insertion_point);
562 child_insertion_point = new_node.get();
564 if (one_grandchild) {
565 new_node->add_child (node->first_child(), 0);
567 list<GraphNode *>::const_iterator past_end = common_children_end;
568 if (it == ++past_end) { // At end => start new range
569 common_children_begin = it;
570 common_children_end = end_of_common_child_range (source_children, it);
573 if (it == common_children_begin) { // At beginning => do duplication
574 GraphNode * grand_child_ins_pt = common_child;
575 if (!grand_child_ins_pt) {
576 grand_child_ins_pt = source->get_parents().back()->last_child()->last_child()->last_child();
578 duplicate_format_children (node->self_ptr(), new_node, grand_child_ins_pt);
579 common_child = new_node->first_child();
580 } else { // Somewhere in between end and beginning => share child
581 new_node->add_child (common_child, 0);
588 ExportProfileManager::duplicate_format_children (FormatNodePtr source, FormatNodePtr target, GraphNode * insertion_point)
590 GraphNode * child_insertion_point = 0;
592 FilenameNodePtr node_insertion_point;
593 FilenameNode * node_insertion_ptr;
594 if (!insertion_point) { insertion_point = source->last_child(); }
595 if (!(node_insertion_ptr = dynamic_cast<FilenameNode *> (insertion_point))) {
596 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
598 node_insertion_point = node_insertion_ptr->self_ptr();
600 for (list<GraphNode *>::const_iterator it = source->get_children().begin(); it != source->get_children().end(); ++it) {
604 FilenameNodePtr new_node;
606 if (!(node = dynamic_cast<FilenameNode *> (*it))) {
607 throw ExportFailed (X_("Programming error, Invalid pointer cast in ExportProfileManager"));
610 new_node = duplicate_filename_node (node->self_ptr());
612 /* Insert in gaph's list and update insertion position */
614 insert_after (graph.filenames, node_insertion_point, new_node);
615 node_insertion_point = new_node;
617 /* Handle children */
619 target->add_child (new_node.get(), child_insertion_point);
620 child_insertion_point = new_node.get();
624 ExportProfileManager::TimespanNodePtr
625 ExportProfileManager::duplicate_timespan_node (TimespanNodePtr node)
627 TimespanStatePtr state = node->data();
628 TimespanStatePtr new_state (new TimespanState ());
629 TimespanNodePtr new_node = TimespanNode::create (new_state);
631 for (TimespanList::iterator it = state->timespans->begin(); it != state->timespans->end(); ++it) {
632 new_state->timespans->push_back (handler->add_timespan_copy (*it));
635 new_state->time_format = state->time_format;
636 new_state->marker_format = state->marker_format;
641 ExportProfileManager::ChannelConfigNodePtr
642 ExportProfileManager::duplicate_channel_config_node (ChannelConfigNodePtr node)
644 ChannelConfigStatePtr state = node->data();
645 ChannelConfigStatePtr new_state (new ChannelConfigState (handler->add_channel_config_copy (state->config)));
646 ChannelConfigNodePtr new_node = ChannelConfigNode::create (new_state);
651 ExportProfileManager::FormatNodePtr
652 ExportProfileManager::duplicate_format_node (FormatNodePtr node)
654 FormatStatePtr state = node->data();
655 FormatStatePtr new_state (new FormatState (handler->add_format_copy (state->format)));
656 FormatNodePtr new_node = FormatNode::create (new_state);
661 ExportProfileManager::FilenameNodePtr
662 ExportProfileManager::duplicate_filename_node (FilenameNodePtr node)
664 FilenameStatePtr state = node->data();
665 FilenameStatePtr new_state (new FilenameState (handler->add_filename_copy (state->filename)));
666 FilenameNodePtr new_node = FilenameNode::create (new_state);
672 ExportProfileManager::remove_timespan (TimespanNodePtr node)
674 remove_by_element (graph.timespans, node);
679 ExportProfileManager::remove_channel_config (ChannelConfigNodePtr node)
681 remove_by_element (graph.channel_configs, node);
686 ExportProfileManager::remove_format (FormatNodePtr node)
688 remove_by_element (graph.formats, node);
693 ExportProfileManager::remove_filename (FilenameNodePtr node)
695 remove_by_element (graph.filenames, node);