4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "edlsession.h"
29 #include "mwindowgui.h"
31 #include "recordlabel.h"
32 #include "mainsession.h"
39 Labels::Labels(EDL *edl, const char *xml_tag)
43 this->xml_tag = xml_tag;
51 void Labels::dump(FILE *fp)
53 for(Label *current = first; current; current = NEXT)
55 fprintf(fp, " label: %f '%s'\n", current->position, current->textstr);
59 void Labels::insert_labels(Labels *labels, double start, double length, int paste_silence)
65 //printf("Labels::insert_labels 1 %f\n", start);
67 // Insert silence in old labels
70 for(old_label = first; old_label; old_label = old_label->next)
72 if(old_label->position > start ||
73 edl->equivalent(old_label->position, start))
74 old_label->position += length;
79 // Insert one new label at a time
80 for(new_label = labels->first; new_label; new_label = new_label->next)
83 //printf("Labels::insert_labels 2 %f\n", new_label->position + start);
85 // Check every old label for existence
86 for(old_label = first; old_label; old_label = old_label->next)
88 if(edl->equivalent(old_label->position, new_label->position + start))
94 if(old_label->position > new_label->position + start)
101 insert_before(old_label, new Label(edl, this, new_label->position + start, new_label->textstr));
103 append(new Label(edl, this, new_label->position + start, new_label->textstr));
109 void Labels::insert_label(double position)
112 Label *old_label = 0;
114 // Check every old label for existence
115 for(old_label = first; old_label; old_label = old_label->next)
117 if(edl->equivalent(old_label->position, position))
123 if(old_label->position > position)
130 insert_before(old_label, new Label(edl, this, position));
132 append(new Label(edl, this, position));
137 int Labels::toggle_label(double start, double end)
140 //printf("Labels::toggle_label 1 %f %f\n", start, end);
142 // handle selection start
143 // find label the selectionstart is after
145 current && current->position < start && !edl->equivalent(current->position, start);
148 //printf("Labels::toggle_label 2 %f %f %f\n", start, end, current->position);
154 //printf("Labels::toggle_label 3 %f %f %f\n", start, end, current->position);
155 if(edl->equivalent(current->position, start))
157 //printf("Labels::toggle_label 1\n");
161 { // insert before it
162 current = insert_before(current, new Label(edl, this, start, ""));
166 { // insert after last
167 //printf("Labels::toggle_label 1\n");
168 current = append(new Label(edl, this, start, ""));
171 // handle selection end
172 if(!EQUIV(start, end))
174 //printf("Labels::toggle_label 2 %.16e %.16e\n", start, end);
175 // find label the selectionend is after
177 current && current->position < end && !edl->equivalent(current->position, end);
185 if(edl->equivalent(current->position, end))
191 current = insert_before(current, new Label(edl, this, end, ""));
196 current = append(new Label(edl, this, end, ""));
202 Label *Labels::add_label(double position)
206 current && current->position < position;
209 if( edl->equivalent(current->position, position) ) return 0;
214 current = insert_before(current, new Label(edl, this, position));
218 current = append(new Label(edl, this, position));
223 int Labels::delete_all()
230 int Labels::copy(double start, double end, FileXML *xml)
232 xml->tag.set_title("LABELS");
234 xml->append_newline();
237 for(current = label_of(start);
238 current && current->position <= end;
241 xml->tag.set_title("LABEL");
242 xml->tag.set_property("TIME", (double)current->position - start);
243 xml->tag.set_property("TEXTSTR", current->textstr);
244 //printf("Labels::copy %f\n", current->position - start);
246 xml->tag.set_title("/LABEL");
248 xml->append_newline();
251 xml->tag.set_title("/LABELS");
253 xml->append_newline();
254 xml->append_newline();
258 int Labels::copy_length(long start, long end) // return number of Labels in selection
263 for(current = label_of(start); current && current->position <= end; current = NEXT)
270 void Labels::copy_from(Labels *labels)
272 while(last) delete last;
274 for(Label *current = labels->first; current; current = NEXT)
276 Label *new_label = new Label(edl, this, current->position, current->textstr);
277 new_label->orig_id = current->orig_id;
283 Labels& Labels::operator=(Labels &that)
286 printf("Labels::operator= 1\n");
291 int Labels::save(FileXML *xml)
292 // Note: Normally the saving of Labels is done by Labels::copy()
294 xml->tag.set_title("LABELS");
296 xml->append_newline();
300 for(current = first; current; current = NEXT)
302 xml->tag.set_title("LABEL");
303 xml->tag.set_property("TIME", (double)current->position);
304 xml->tag.set_property("TEXTSTR", current->textstr);
306 xml->tag.set_title("/LABEL");
308 xml->append_newline();
311 xml->append_newline();
312 xml->tag.set_title("/LABELS");
314 xml->append_newline();
315 xml->append_newline();
319 int Labels::load(FileXML *xml, uint32_t load_flags)
322 char string1[BCTEXTLEN], string2[BCTEXTLEN];
324 sprintf(string1, "/%s", xml_tag);
325 strcpy(string2, xml_tag);
326 string2[strlen(string2) - 1] = 0;
329 result = xml->read_tag();
332 if(xml->tag.title_is(string1))
337 if(xml->tag.title_is(string2))
339 double position = xml->tag.get_property("TIME", (double)-1);
341 position = xml->tag.get_property("SAMPLE", (double)-1);
342 //printf("Labels::load %f\n", position);
345 Label *current = label_of(position);
346 current = insert_before(current, new Label(edl, this, position, ""));
347 xml->tag.get_property("TEXTSTR", current->textstr);
351 if(xml->tag.title_is("INPOINT"))
353 double position = xml->tag.get_property("TIME", (double)-1);
355 position = xml->tag.get_property("SAMPLE", (double)-1);
362 if(xml->tag.title_is("OUTPOINT"))
364 double position = xml->tag.get_property("TIME", (double)-1);
366 position = xml->tag.get_property("SAMPLE", (double)-1);
379 int Labels::clear(double start, double end, int follow)
384 //printf("Labels::clear 1\n");
385 current = label_of(start);
386 //printf("Labels::clear 2\n");
387 // remove selected labels
388 while(current && current->position < end)
394 // Shift later labels
395 //printf("Labels::clear 3\n");
400 current->position -= end - start; // shift labels forward
403 //printf("Labels::clear 4\n");
405 //printf("Labels::clear 5\n");
412 Label* Labels::prev_label(double position)
416 // Test for label under cursor position
418 current && !edl->equivalent(current->position, position);
422 // Test for label after cursor position
425 current && current->position < position;
429 // Test for label before cursor position
433 // Get previous label
439 Label* Labels::next_label(double position)
443 // Test for label under cursor position
445 current && !edl->equivalent(current->position, position);
449 // Test for label before cursor position
452 current && current->position > position;
456 // Test for label after cursor position
466 Label* Labels::get_label(int id)
468 Label *current = first;
469 while( current && current->orig_id != id ) current = NEXT;
473 int Labels::insert(double start, double length)
474 { // shift every label including the first one back
477 for(current = label_of(start); current; current = NEXT)
479 current->position += length;
484 int Labels::paste_silence(double start, double end)
486 insert(start, end - start);
491 int Labels::modify_handles(double oldposition, double newposition, int currentend)
493 if( !currentend ) { // left handle
494 if( newposition < oldposition )
495 insert(oldposition, oldposition - newposition); // shift all labels right
497 clear(oldposition, newposition); // clear selection
499 else { // right handle
500 if( newposition < oldposition )
501 clear(newposition, oldposition);
503 insert(oldposition, newposition - oldposition);
508 int Labels::optimize()
517 for(current = first; current && NEXT && !result;)
520 if(current->position == next->position)
531 Label* Labels::label_of(double position)
535 for(current = first; current; current = NEXT)
537 if(current->position >= position) return current;
558 Label::Label(EDL *edl, Labels *labels, double position, const char *textstr)
562 this->labels = labels;
563 this->position = position;
564 strcpy(this->textstr, textstr ? textstr : "");
572 // if(toggle) delete toggle;
575 LabelToggle::LabelToggle(MWindow *mwindow,
582 this->mwindow = mwindow;
586 LabelToggle::~LabelToggle() { }
588 int LabelToggle::handle_event()