r689: Fixed that changes made by dragging a control would often store each
[cinelerra_cv.git] / cinelerra / labels.C
blobcb0b1207f037d610370e3e09eb49a6792e55441c
1 #include "clip.h"
2 #include "edl.h"
3 #include "edlsession.h"
4 #include "filexml.h"
5 #include "labels.h"
6 #include "mwindow.h"
7 #include "mwindowgui.h"
8 #include "patchbay.h"
9 #include "recordlabel.h"
10 #include "mainsession.h"
11 #include "stringfile.h"
12 #include "theme.h"
13 #include "timebar.h"
14 #include <string.h>
18 Labels::Labels(EDL *edl, char *xml_tag)
19  : List<Label>()
21         this->edl = edl;
22         this->xml_tag = xml_tag;
25 Labels::~Labels()
27         delete_all();
30 void Labels::dump()
32         for(Label *current = first; current; current = NEXT)
33         {
34                 printf("  label: %f\n", current->position);
35         }
38 void Labels::insert_labels(Labels *labels, double start, double length, int paste_silence)
40         Label *new_label;
41         Label *old_label;
44 //printf("Labels::insert_labels 1 %f\n", start);
46 // Insert silence in old labels
47         if(paste_silence)
48         {
49                 for(old_label = first; old_label; old_label = old_label->next)
50                 {
51                         if(old_label->position > start ||
52                                 edl->equivalent(old_label->position, start))
53                                 old_label->position += length;
54                 }
55         }
58 // Insert one new label at a time
59         for(new_label = labels->first; new_label; new_label = new_label->next)
60         {
61                 int exists = 0;
62 //printf("Labels::insert_labels 2 %f\n", new_label->position + start);
64 // Check every old label for existence
65                 for(old_label = first; old_label; old_label = old_label->next)
66                 {
67                         if(edl->equivalent(old_label->position, new_label->position + start))
68                         {
69                                 exists = 1;
70                                 break;
71                         }
72                         else
73                         if(old_label->position > new_label->position + start)
74                                 break;
75                 }
77                 if(!exists)
78                 {
79                         if(old_label)
80                                 insert_before(old_label, new Label(edl, this, new_label->position + start));
81                         else
82                                 append(new Label(edl, this, new_label->position + start));
83                 }
84         }
87 int Labels::toggle_label(double start, double end)
89         Label *current;
90 //printf("Labels::toggle_label 1 %f %f\n", start, end);
92 // handle selection start
93 // find label the selectionstart is after
94         for(current = first; 
95                 current && current->position < start && !edl->equivalent(current->position, start); 
96                 current = NEXT)
97         {
98 //printf("Labels::toggle_label 2 %f %f %f\n", start, end, current->position);
99                 ;
100         }
102         if(current)
103         {
104 //printf("Labels::toggle_label 3 %f %f %f\n", start, end, current->position);
105                 if(edl->equivalent(current->position, start))
106                 {        // remove it
107 //printf("Labels::toggle_label 1\n");
108                         remove(current);
109                 }
110                 else
111                 {        // insert before it
112                         current = insert_before(current, new Label(edl, this, start));
113                 }
114         }
115         else
116         {           // insert after last
117 //printf("Labels::toggle_label 1\n");
118                 current = append(new Label(edl, this, start));
119         }
121 // handle selection end
122         if(!EQUIV(start, end))
123         {
124 //printf("Labels::toggle_label 2 %.16e %.16e\n", start, end);
125 // find label the selectionend is after
126                 for(current = first; 
127                         current && current->position < end && !edl->equivalent(current->position, end); 
128                         current = NEXT)
129                 {
130                         ;
131                 }
133                 if(current)
134                 {
135                         if(edl->equivalent(current->position, end))
136                         {
137                                 remove(current);
138                         }
139                         else
140                         {
141                                 current = insert_before(current, new Label(edl, this, end));
142                         }
143                 }
144                 else
145                 {
146                         current = append(new Label(edl, this, end));
147                 }
148         }
149         return 0;
152 int Labels::delete_all()
154         while(last)
155                 remove(last);
156         return 0;
159 int Labels::copy(double start, double end, FileXML *xml)
161         char string[BCTEXTLEN];
162         xml->tag.set_title(xml_tag);
163         xml->append_tag();
164         xml->append_newline();
166         Label *current;
167         sprintf(string, xml_tag);
168         string[strlen(string) - 1] = 0;
169         for(current = label_of(start); 
170                 current && current->position <= end; 
171                 current = NEXT)
172         {
173                 xml->tag.set_title(string);
174                 xml->tag.set_property("SAMPLE", (double)current->position - start);
175 //printf("Labels::copy %f\n", current->position - start);
176                 xml->append_tag();
177         }
178         
179         sprintf(string, "/%s", xml_tag);
180         xml->tag.set_title(string);
181         xml->append_tag();
182         xml->append_newline();
183         xml->append_newline();
184         return 0;
187 int Labels::copy_length(long start, long end) // return number of Labels in selection
189         int result = 0;
190         Label *current;
191         
192         for(current = label_of(start); current && current->position <= end; current = NEXT)
193         {
194                 result++;
195         }
196         return result;
199 void Labels::copy_from(Labels *labels)
201         while(last) delete last;
203         for(Label *current = labels->first; current; current = NEXT)
204         {
205                 append(new Label(edl, this, current->position));
206         }
210 Labels& Labels::operator=(Labels &that)
212         copy_from(&that);
213 printf("Labels::operator= 1\n");
214         return *this;
218 int Labels::save(FileXML *xml)
220         xml->tag.set_title("LABELS");
221         xml->append_tag();
222         xml->append_newline();
224         Label *current;
226         for(current = first; current; current = NEXT)
227         {
228                 xml->tag.set_title("LABEL");
229                 xml->tag.set_property("SAMPLE", (double)current->position);
230                 xml->append_tag();
231         }
232         
233         xml->append_newline();
234         xml->tag.set_title("/LABELS");
235         xml->append_tag();
236         xml->append_newline();
237         xml->append_newline();
238         return 0;
241 int Labels::load(FileXML *xml, uint32_t load_flags)
243         int result = 0;
244         char string1[BCTEXTLEN], string2[BCTEXTLEN];
246         sprintf(string1, "/%s", xml_tag);
247         strcpy(string2, xml_tag);
248         string2[strlen(string2) - 1] = 0;
250         do{
251                 result = xml->read_tag();
252                 if(!result)
253                 {
254                         if(xml->tag.title_is(string1))
255                         {
256                                 result = 1;
257                         }
258                         else
259                         if(xml->tag.title_is(string2))
260                         {
261                                 double position = xml->tag.get_property("SAMPLE", (double)-1);
262 //printf("Labels::load %f\n", position);
263                                 if(position > -1)
264                                 {
265                                         Label *current = label_of(position);
266                                         current = insert_before(current, new Label(edl, this, position));
267                                 }
268                         }
269                         else
270                         if(xml->tag.title_is("INPOINT"))
271                         {
272                                 double position = xml->tag.get_property("SAMPLE", (double)-1);
273                                 if(position > -1)
274                                 {
275                                         ;
276                                 }
277                         }
278                         else
279                         if(xml->tag.title_is("OUTPOINT"))
280                         {
281                                 double position = xml->tag.get_property("SAMPLE", (double)-1);
282                                 if(position > -1)
283                                 {
284                                         ;
285                                 }
286                         }
287                 }
288         }while(!result);
289         return 0;
294 int Labels::clear(double start, double end, int follow)
296         Label *current;
297         Label *next;
299 //printf("Labels::clear 1\n");
300         current = label_of(start);
301 //printf("Labels::clear 2\n");
302 // remove selected labels
303         while(current && current->position < end)
304         {
305                 next = NEXT;
306                 delete current;              
307                 current = next;
308         }
309 // Shift later labels
310 //printf("Labels::clear 3\n");
311         if(follow)
312         {
313                 while(current)
314                 {
315                         current->position -= end - start;   // shift labels forward
316                         current = NEXT;
317                 }
318 //printf("Labels::clear 4\n");
319                 optimize();
320 //printf("Labels::clear 5\n");
321         }
323         return 0;
327 Label* Labels::prev_label(double position)
329         Label *current;
331 // Test for label under cursor position
332         for(current = first; 
333                 current && !edl->equivalent(current->position, position); 
334                 current = NEXT)
335                 ;
337 // Test for label after cursor position
338         if(!current)
339                 for(current = first;
340                         current && current->position < position;
341                         current = NEXT)
342                         ;
344 // Test for label before cursor position
345         if(!current) 
346                 current = last;
347         else
348 // Get previous label
349                 current = PREVIOUS;
351         return current;
354 Label* Labels::next_label(double position)
356         Label *current;
358 // Test for label under cursor position
359         for(current = first; 
360                 current && !edl->equivalent(current->position, position); 
361                 current = NEXT)
362                 ;
364 // Test for label before cursor position
365         if(!current)
366                 for(current = last;
367                         current && current->position > position;
368                         current = PREVIOUS)
369                         ;
371 // Test for label after cursor position
372         if(!current)
373                 current = first;
374         else
375 // Get next label
376                 current = NEXT;
378         return current;
381 int Labels::insert(double start, double length)
382 {      // shift every label including the first one back
383         Label *current;
385         for(current = label_of(start); current; current = NEXT)
386         {
387                 current->position += length;
388         }
389         return 0;
392 int Labels::paste_silence(double start, double end)
394         insert(start, end - start);
395         optimize();
396         return 0;
399 int Labels::modify_handles(double oldposition, 
400         double newposition, 
401         int currentend, 
402         int handle_mode,
403         int edit_labels)
405         if(edit_labels &&
406                 handle_mode == MOVE_ALL_EDITS)
407         {
408                 if(currentend == 0)          // left handle
409                 {
410                         if(newposition < oldposition)
411                         {
412                                 insert(oldposition, oldposition - newposition);    // shift all labels right
413                         }
414                         else
415                         {
416                                 clear(oldposition, newposition);   // clear selection
417                         }
418                 }
419                 else
420                 {                            // right handle
421                         if(newposition < oldposition)
422                         {
423                                 clear(newposition, oldposition);
424                         }
425                         else
426                         {
427                                 insert(oldposition, newposition - oldposition);
428                         }
429                 }
430         }
431         return 0;
434 int Labels::optimize()
436         int result = 1;
437         Label *current;
439         while(result)
440         {
441                 result = 0;
442                 
443                 for(current = first; current && NEXT && !result;)
444                 {
445                         Label *next = NEXT;
446                         if(current->position == next->position)
447                         {
448                                 delete current;
449                                 result  = 1;
450                         }
451                         current = next;
452                 }
453         }
454         return 0;
457 Label* Labels::label_of(double position)
459         Label *current;
461         for(current = first; current; current = NEXT)
462         {
463                 if(current->position >= position) return current;
464         }
465         return 0;
477 Label::Label()
478  : ListItem<Label>()
482 Label::Label(EDL *edl, Labels *labels, double position)
483  : ListItem<Label>()
485         this->edl = edl;
486         this->labels = labels;
487         this->position = position;
491 Label::~Label()
493 //      if(toggle) delete toggle;
496 LabelToggle::LabelToggle(MWindow *mwindow, 
497         Label *label, 
498         int x, 
499         int y, 
500         long position)
501  : BC_Label(x, y, 0)
503         this->mwindow = mwindow;
504         this->label = label;
507 LabelToggle::~LabelToggle() { }
509 int LabelToggle::handle_event()
511         return 0;