root/sweep/trunk/src/edit.c

Revision 688, 40.2 kB (checked in by erikd, 2 years ago)

Clean up large number of '#if 0' and '#if 1' code blocks.

Remove code chunks surrounded by '#if 0' .. '#endif'.
Remove '#if 1' and '#endif' around code chunks that are actually being used.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Sweep, a sound wave editor.
3  *
4  * Copyright (C) 2000 Conrad Parker
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27
28 #include <unistd.h>
29 #include <sys/mman.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33
34 #include <sweep/sweep_i18n.h>
35 #include <sweep/sweep_types.h>
36 #include <sweep/sweep_typeconvert.h>
37 #include <sweep/sweep_undo.h>
38 #include <sweep/sweep_sounddata.h>
39 #include <sweep/sweep_sample.h>
40 #include <sweep/sweep_selection.h>
41
42 #include "sweep_app.h"
43 #include "edit.h"
44 #include "format.h"
45
46
47 sw_edit_buffer * ebuf = NULL;
48
49 void *
50 sweep_large_alloc_data (size_t len, void * data, int prot)
51 {
52   void * ptr;
53
54 #if HAVE_MMAP
55   FILE * f;
56   int fd;
57
58   if ((f = tmpfile ()) == NULL) {
59     perror ("tmpfile failed in sweep_large_alloc_data");
60     return NULL;
61   }
62
63   if (fwrite (data, len, 1, f) != 1) {
64     perror ("short fwrite in sweep_large_alloc_data");
65     return NULL;
66   }
67
68   if (fseek (f, 0, SEEK_SET) == -1) {
69     perror ("fseek failed in sweep_large_alloc_data");
70     return NULL;
71   }
72
73   if ((fd = fileno (f)) == -1) {
74     perror ("fileno failed in sweep_large_alloc_data");
75     return NULL;
76   }
77
78   if ((ptr = mmap (NULL, len, prot, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
79     perror ("mmap failed in sweep_large_alloc_data");
80     return NULL;
81   }
82 #else
83   ptr = g_malloc (len);
84
85   memcpy (ptr, data, len);
86 #endif
87
88   return ptr;
89 }
90
91 void *
92 sweep_large_alloc_zero (size_t len, int prot)
93 {
94   void * ptr;
95
96 #if HAVE_MMAP
97   int fd;
98
99   if ((fd = open ("/dev/zero", O_RDWR)) == -1) {
100     perror ("open failed in sweep_large_alloc_zero");
101     return NULL;
102   }
103
104   if (lseek (fd, len+1, SEEK_SET) == (off_t)-1) {
105     perror ("lseek failed in sweep_large_alloc_zero");
106     return NULL;
107   }
108
109   if (write (fd, "", 1) == -1) {
110     perror ("write failed in sweep_large_alloc_zero");
111     return NULL;
112   }
113
114   if (lseek (fd, 0, SEEK_SET) == (off_t)-1) {
115     perror ("lseek failed in sweep_large_alloc_zero");
116     return NULL;
117   }
118
119   if ((ptr = mmap (NULL, len, prot, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
120     perror ("mmap failed in sweep_large_alloc_zero");
121     return NULL;
122   }
123 #else
124   ptr = g_malloc0 (len);
125 #endif
126
127   return ptr;
128 }
129
130 void
131 sweep_large_free (void * ptr, size_t len)
132 {
133 #if HAVE_MMAP
134   if (munmap (ptr, len) == -1)
135     perror ("munmap failed in sweep_large_free()");
136 #else
137   g_free (ptr);
138 #endif
139 }
140
141 static sw_edit_region *
142 edit_region_new (sw_format * format, sw_framecount_t start,
143                  sw_framecount_t end, gpointer data)
144 {
145   sw_edit_region * er;
146   sw_framecount_t len;
147
148   er = g_malloc (sizeof(sw_edit_region));
149
150   er->start = start;
151   er->end = end;
152
153   len = frames_to_bytes (format, end-start);
154   er->data = sweep_large_alloc_data (len, data, PROT_READ);
155
156   return er;
157 }
158
159 static sw_edit_region *
160 edit_region_new0 (sw_format * format, sw_framecount_t start,
161                   sw_framecount_t end, gpointer data0)
162 {
163   sw_framecount_t offset;
164   int o2;
165
166   offset = frames_to_bytes (format, start);
167   o2 = (int)offset; /* XXX */
168
169   return edit_region_new (format, start, end, data0+o2);
170 }
171
172 static sw_edit_region *
173 edit_region_copy (sw_format * format, sw_edit_region * oer)
174 {
175   sw_edit_region * er;
176
177   er = edit_region_new (format, oer->start, oer->end, oer->data);
178
179   return er;
180 }
181
182 sw_edit_buffer *
183 edit_buffer_new (sw_format * format)
184 {
185   sw_edit_buffer * eb;
186
187   eb = g_malloc0 (sizeof(sw_edit_buffer));
188   eb->format = format_copy (format);
189   eb->regions = NULL;
190   eb->refcount = 1;
191
192   return eb;
193 }
194
195 sw_edit_buffer *
196 edit_buffer_copy (sw_edit_buffer * oeb)
197 {
198   sw_edit_buffer * eb;
199   GList * gl;
200   sw_edit_region * oer, * er;
201
202   eb = edit_buffer_new (oeb->format);
203
204   for (gl = oeb->regions; gl; gl = gl->next) {
205     oer = (sw_edit_region *)gl->data;
206
207     er = edit_region_copy (oeb->format, oer);
208  
209     eb->regions = g_list_append (eb->regions, er);
210   }
211
212   return eb;
213 }
214
215 sw_edit_buffer *
216 edit_buffer_ref (sw_edit_buffer * eb)
217 {
218   eb->refcount++;
219   return eb;
220 }
221
222 static void
223 edit_buffer_clear (sw_edit_buffer * eb)
224 {
225   GList * gl;
226   sw_edit_region * er;
227   size_t len;
228
229   if (!eb) return;
230
231   for (gl = eb->regions; gl; gl = gl->next) {
232     er = (sw_edit_region *)gl->data;
233     if (er) {
234       len = frames_to_bytes (eb->format, er->end - er->start);
235       sweep_large_free (er->data, len);
236     }
237   }
238   g_list_free (eb->regions);
239
240   g_free (eb->format);
241
242   eb->format = NULL;
243   eb->regions = NULL;
244   eb->refcount = 0;
245 }
246
247 void
248 edit_buffer_destroy (sw_edit_buffer * eb)
249 {
250   eb->refcount--;
251   if (eb->refcount > 0) return;
252
253   edit_buffer_clear (eb);
254   g_free (eb);
255 }
256
257 static void
258 ebuf_clear (void)
259 {
260   if (!ebuf) return;
261
262   edit_buffer_destroy (ebuf);
263
264   ebuf = NULL;
265 }
266
267 static sw_framecount_t
268 edit_buffer_length (sw_edit_buffer * eb)
269 {
270   GList * gl;
271   sw_edit_region * er;
272   sw_framecount_t length = 0;
273
274   for (gl = eb->regions; gl; gl = gl->next) {
275     er = (sw_edit_region *)gl->data;
276
277     length += (er->end - er->start);
278   }
279
280   return length;
281 }
282
283 static sw_framecount_t
284 edit_buffer_width (sw_edit_buffer * eb)
285 {
286   GList * gl;
287   sw_edit_region * er;
288   sw_framecount_t start, end;
289
290   if (eb == NULL) return 0;
291
292   if ((gl = eb->regions) == NULL) return 0;
293   er = (sw_edit_region *)gl->data;
294   start = er->start;
295
296   gl = g_list_last (eb->regions);
297   er = (sw_edit_region *)gl->data;
298   end = er->end;
299  
300   return (end - start);
301 }
302
303 sw_framecount_t
304 clipboard_width (void)
305 {
306   return edit_buffer_width (ebuf);
307 }
308
309 static sw_edit_buffer *
310 edit_buffer_from_sounddata_sels (sw_sounddata * sounddata, GList * sels)
311 {
312   sw_edit_buffer * eb;
313   GList * gl;
314   sw_sel * sel;
315   sw_edit_region * er;
316
317   eb = edit_buffer_new (sounddata->format);
318
319   for (gl = sels; gl; gl = gl->next) {
320     sel = (sw_sel *)gl->data;
321
322     er = edit_region_new0 (eb->format,
323                            sel->sel_start, sel->sel_end,
324                            sounddata->data);
325
326 #ifdef DEBUG
327     printf("adding eb region [%ld - %ld]\n", sel->sel_start, sel->sel_end);
328 #endif
329
330     eb->regions = g_list_append (eb->regions, er);
331   }
332
333   return eb;
334 }
335
336 static sw_edit_buffer *
337 edit_buffer_from_sounddata (sw_sounddata * sounddata)
338 {
339   return edit_buffer_from_sounddata_sels (sounddata, sounddata->sels);
340 }
341
342 sw_edit_buffer *
343 edit_buffer_from_sample (sw_sample * sample)
344 {
345   return edit_buffer_from_sounddata (sample->sounddata);
346 }
347
348 static GList *
349 sels_from_edit_buffer_offset (sw_edit_buffer * eb, sw_framecount_t offset)
350 {
351   GList * gl, * sels = NULL;
352   sw_edit_region * er;
353   sw_framecount_t start;
354
355   gl = eb->regions;
356   if (!gl) return NULL;
357
358   er = (sw_edit_region *)gl->data;
359   start = er->start;
360
361   for (gl = eb->regions; gl; gl = gl->next) {
362     er = (sw_edit_region *)gl->data;
363
364     sels = sels_add_selection_1 (sels, er->start - start + offset,
365                                  er->end - start + offset);
366   }
367
368   return sels;
369 }
370
371 static sw_sample *
372 sample_from_edit_buffer (sw_edit_buffer * eb)
373 {
374   sw_sample * s;
375   GList * gl;
376   sw_edit_region * er;
377   sw_framecount_t offset0 = 0, start, length;
378   sw_framecount_t offset, len;
379
380   /* Get length of new sample */
381   gl = eb->regions;
382
383   if (!gl) return NULL;
384
385   er = (sw_edit_region *)gl->data;
386   start = er->start;
387  
388   for (; gl->next; gl = gl->next);
389   er = (sw_edit_region *)gl->data;
390   length = er->end - start;
391
392   s = sample_new_empty (NULL,
393                         eb->format->channels,
394                         eb->format->rate,
395                         length);
396
397   offset0 = frames_to_bytes (eb->format, start);
398
399   for (gl = eb->regions; gl; gl = gl->next) {
400     er = (sw_edit_region *)gl->data;
401     offset = frames_to_bytes (eb->format, er->start) - offset0;
402     len = frames_to_bytes (eb->format, er->end - er->start);
403
404     memcpy ((gpointer)(s->sounddata->data + offset), er->data, len);
405
406     sounddata_add_selection_1 (s->sounddata, er->start - start,
407                                er->end - start);
408
409 #ifdef DEBUG
410     printf("Adding sample region [%ld - %ld]\n", er->start, er->end);
411 #endif
412   }
413
414   return s;
415 }
416
417 static void
418 head_dec_if_within (sw_head * head, sw_framecount_t lower,
419                     sw_framecount_t upper, sw_framecount_t amount)
420 {
421   if (head == NULL) return;
422
423   g_mutex_lock (head->head_mutex);
424
425   if (head->stop_offset > lower && head->stop_offset < upper)
426     head->stop_offset -= amount;
427
428   if (head->offset > lower && head->offset < upper)
429     head->offset -= amount;
430
431   g_mutex_unlock (head->head_mutex);
432 }
433
434 static void
435 head_inc_if_gt (sw_head * head, sw_framecount_t lower, sw_framecount_t amount)
436 {
437   if (head == NULL) return;
438
439   g_mutex_lock (head->head_mutex);
440
441   if (head->stop_offset > lower)
442     head->stop_offset += amount;
443
444   if (head->offset > lower)
445     head->offset += amount;
446
447   g_mutex_unlock (head->head_mutex);
448 }
449
450 static void
451 head_set_if_within (sw_head * head, sw_framecount_t lower,
452                     sw_framecount_t upper, sw_framecount_t value)
453 {
454   if (head == NULL) return;
455
456   g_mutex_lock (head->head_mutex);
457
458   if (head->stop_offset >= lower && head->stop_offset <= upper)
459     head->stop_offset = value;
460  
461   if (head->offset >= lower && head->offset <= upper)
462     head->offset = value;
463
464   g_mutex_unlock (head->head_mutex);
465 }
466
467 /* modifies sounddata */
468 sw_sample *
469 splice_out_sel (sw_sample * sample)
470 {
471   sw_sounddata * sounddata = sample->sounddata;
472   sw_format * f = sounddata->format;
473   gint length;
474   GList * gl;
475   sw_sel * osel, * sel;
476   /*sw_sounddata * out;*/
477   gpointer d;
478   sw_framecount_t offset, len, sel_length = 0;
479   sw_framecount_t move_length, run_length;
480
481   if (!sounddata->sels) {
482     printf ("Nothing to splice out.\n");
483     return sample;
484   }
485
486   length = sounddata->nr_frames - sounddata_selection_nr_frames (sounddata);
487   run_length = 0;
488
489 #ifdef DEBUG
490   printf("Splice out: remaining length %d\n", length);
491 #endif
492
493   d = sounddata->data;
494
495   /* XXX: Force splice outs to be atomic wrt. to cancellation. For
496    * multi-region selections it would be nicer to build the redo data
497    * incrementally, but wtf.
498    * Each region's memmove needs to be treated as atomic anyway so the
499    * gain isn't so much.
500    */
501   g_mutex_lock (sample->ops_mutex);
502
503   gl = sounddata->sels;
504   sel = osel = (sw_sel *)gl->data;
505   if (osel->sel_start > 0) {
506
507     if (sample->user_offset >= sel->sel_start &&
508         sample->user_offset <= sel->sel_end) {
509       sample->user_offset = sel->sel_start - sel_length;;
510     }
511
512     head_set_if_within (sample->play_head, sel->sel_start, sel->sel_end,
513                         sel->sel_start - sel_length);
514
515     head_set_if_within (sample->rec_head, sel->sel_start, sel->sel_end,
516                         sel->sel_start - sel_length);
517
518     sel_length = osel->sel_end - osel->sel_start;
519
520     move_length = osel->sel_start;
521
522     len = frames_to_bytes (f, move_length);
523     d += len;
524
525     run_length += move_length;
526     sample_set_progress_percent (sample, run_length / (length/100));
527   }
528   for (gl = gl->next; gl; gl = gl->next) {
529     sel = (sw_sel *)gl->data;
530
531     /* Move user offset */
532     if (sample->user_offset > osel->sel_end &&
533         sample->user_offset < sel->sel_start) {
534       sample->user_offset -= sel_length;
535     }
536
537     if (sample->user_offset >= sel->sel_start &&
538         sample->user_offset <= sel->sel_end) {
539       sample->user_offset = sel->sel_start - sel_length;;
540     }
541
542     head_dec_if_within (sample->play_head, osel->sel_end, sel->sel_start,
543                         sel_length);
544     head_set_if_within (sample->play_head, sel->sel_start, sel->sel_end,
545                         sel->sel_start - sel_length);
546
547     head_dec_if_within (sample->rec_head, osel->sel_end, sel->sel_start,
548                         sel_length);
549     head_set_if_within (sample->rec_head, sel->sel_start, sel->sel_end,
550                         sel->sel_start - sel_length);
551
552     sel_length += sel->sel_end - sel->sel_start;
553
554     offset = frames_to_bytes (f, osel->sel_end);
555
556     move_length = sel->sel_start - osel->sel_end;
557     len = frames_to_bytes (f, move_length);
558     g_memmove (d, (gpointer)(sounddata->data + offset), len);
559     d += len;
560
561     run_length += move_length;
562     sample_set_progress_percent (sample, run_length / (length/100));
563
564     osel = sel;
565   }
566
567   /* Move offsets occuring after last sel */
568   if (sample->user_offset > sel->sel_end) {
569     sample->user_offset -= sel_length;
570   }
571
572   head_dec_if_within (sample->play_head, sel->sel_end, FRAMECOUNT_MAX,
573                       sel_length);
574
575   head_dec_if_within (sample->rec_head, sel->sel_end, FRAMECOUNT_MAX,
576                       sel_length);
577
578   if (sel->sel_end != sounddata->nr_frames) {
579     offset = frames_to_bytes (f, sel->sel_end);
580
581     move_length = sounddata->nr_frames - sel->sel_end;
582
583     len = frames_to_bytes (f, move_length);
584     g_memmove (d, (gpointer)(sounddata->data + offset), len);
585
586     run_length += move_length;
587     sample_set_progress_percent (sample, run_length / (length/100));
588   }
589
590   d = g_realloc (sounddata->data, frames_to_bytes(f, length));
591   sounddata->data = d;
592   sounddata->nr_frames = length;
593
594   sounddata_clear_selection (sounddata);
595
596   sample_set_progress_percent (sample, 100);
597
598   g_mutex_unlock (sample->ops_mutex);
599
600   return sample;
601 }
602
603 static void
604 sounddata_set_sel_from_eb (sw_sounddata * sounddata, sw_edit_buffer * eb)
605 {
606   GList * gl;
607   sw_edit_region * er;
608
609   if (sounddata->sels)
610     sounddata_clear_selection (sounddata);
611
612   if (!eb) return;
613  
614   for (gl = eb->regions; gl; gl = gl->next) {
615     er = (sw_edit_region *)gl->data;
616
617     if (er->start > sounddata->nr_frames) break;
618
619     sounddata_add_selection_1 (sounddata, er->start, MIN(er->end, sounddata->nr_frames));
620   }
621 }
622
623 /* returns new sounddata */
624 static sw_sample *
625 splice_in_eb_data (sw_sample * sample, sw_edit_buffer * eb)
626 {
627   sw_sounddata * sounddata = sample->sounddata;
628   sw_format * f = sounddata->format;
629   gint length;
630   GList * gl;
631   sw_edit_region * er;
632   sw_framecount_t prev_start = 0;
633   sw_framecount_t er_width;
634   gpointer di, d;
635   sw_framecount_t len;
636
637   if (!eb) {
638     return sample;
639   }
640
641   g_mutex_lock (sample->ops_mutex);
642
643   /* in reverse ... decrementing d, di; just like paste at only crunchy */
644
645   length = sounddata->nr_frames + edit_buffer_length (eb);
646
647   d = g_realloc (sounddata->data, frames_to_bytes (f, length));
648   sounddata->data = d;
649
650   /* set di to point to the end of the original data */
651   di = d + frames_to_bytes (f, sounddata->nr_frames);
652
653   /* set d to point to end of newly realloc'd buffer */
654   d += frames_to_bytes (f, length);
655
656   prev_start = length;
657
658   gl = g_list_last (eb->regions);
659   er = (sw_edit_region *)gl->data;
660   if (er->start >= sounddata->nr_frames) {
661     len = frames_to_bytes (f, er->end - er->start);
662     d -= len;
663     memcpy (d, er->data, len);
664     prev_start = er->start;
665     gl = gl->prev;
666   }
667
668   for (; gl; gl = gl->prev) {
669     er = (sw_edit_region *)gl->data;
670
671     /* Move the sample data in */
672     len = frames_to_bytes (f, prev_start - er->end);
673     di -= len;
674     d -= len;
675     memmove (d, di, len);
676
677     /* Copy edit_region data in */
678     len = frames_to_bytes (f, er->end - er->start);
679     d -= len;
680     memcpy (d, er->data, len);
681     prev_start = er->start;
682   }
683
684   /* The head of the sounddata remains intact */
685
686   /* Move offset markers */
687
688   for (gl = eb->regions; gl; gl = gl->next) {
689     er = (sw_edit_region *)gl->data;
690
691     er_width = er->end - er->start;
692
693     if (sample->user_offset > er->end)
694       sample->user_offset += er_width;
695
696     head_inc_if_gt (sample->play_head, er->end, er_width);
697     head_inc_if_gt (sample->rec_head, er->end, er_width);
698   }
699
700   sounddata->nr_frames = length;
701
702   g_mutex_unlock (sample->ops_mutex);
703
704   return sample;
705 }
706
707 /* returns new sounddata */
708 sw_sample *
709 splice_in_eb (sw_sample * sample, sw_edit_buffer * eb)
710 {
711   splice_in_eb_data (sample, eb);
712   sounddata_set_sel_from_eb (sample->sounddata, eb);
713
714   return sample;
715 }
716
717 /* modifies sounddata */
718 static sw_sounddata *
719 crop_in_eb_data (sw_sounddata * sounddata, sw_edit_buffer * eb)
720 {
721   sw_format * f = sounddata->format;
722   sw_framecount_t length, byte_length, o_byte_length;
723   GList * gl;
724   sw_edit_region * er1, * er2, * er;
725   sw_framecount_t len1 = 0, len2 = 0;
726   sw_framecount_t byte_len1, byte_len2;
727   gpointer d;
728
729   if (!eb) {
730     return sounddata;
731   }
732
733   o_byte_length = frames_to_bytes (f, sounddata->nr_frames);
734
735   gl = eb->regions;
736   er1 = (sw_edit_region *)gl->data;
737   if (er1->start == 0) {
738     len1 = er1->end;
739   }
740   byte_len1 = frames_to_bytes (f, len1);
741
742   gl = g_list_last (eb->regions);
743   er2 = (sw_edit_region *)gl->data;
744   if (er2->end > sounddata->nr_frames) {
745     len2 = er2->end - er2->start;
746   }
747   byte_len2 = frames_to_bytes (f, len2);
748
749   if (len1 + len2 > 0) {
750     length = sounddata->nr_frames + len1 + len2;
751     byte_length = frames_to_bytes (f, length);
752
753     d = g_realloc (sounddata->data, byte_length);
754     sounddata->data = d;
755     sounddata->nr_frames = length;
756
757     if (len1 > 0) {
758       /* Move middle region in place */
759       memmove ((gpointer)(d + byte_len1), d, o_byte_length);
760      
761       /* Copy (prepend) first region */
762       memcpy (d, er1->data, byte_len1);
763     } else {
764       /* Overwrite first region in place */
765       gl = eb->regions;
766       er = (sw_edit_region *)gl->data;
767       memcpy ((gpointer)(d + frames_to_bytes (f, er->start)),
768               er->data, frames_to_bytes (f, er->end - er->start));
769     }
770    
771     /* Overwrite with in-between regions */
772     gl = eb->regions;
773     for (gl = gl->next; gl && gl->next; gl = gl->next) {
774       er = (sw_edit_region *)gl->data;
775       memcpy ((gpointer)(d + frames_to_bytes (f, er->start)),
776               er->data, frames_to_bytes (f, er->end - er->start));
777     }
778    
779     if (len2 > 0) {
780       /* Copy (append) last_region */
781       memcpy ((gpointer)(d + o_byte_length + byte_len1), er2->data, byte_len2);
782     } else if (gl) {
783       /* Overwrite last region in place */
784       er = (sw_edit_region *)gl->data;
785       memcpy ((gpointer)(d + frames_to_bytes (f, er->start)),
786               er->data, frames_to_bytes (f, er->end - er->start));
787     }
788
789   } else {
790     d = sounddata->data;
791     for (gl = eb->regions; gl; gl = gl->next) {
792       er = (sw_edit_region *)gl->data;
793       memcpy ((gpointer)(d + frames_to_bytes (f, er->start)),
794               er->data, frames_to_bytes (f, er->end - er->start));
795     }
796   }
797
798   return sounddata;
799 }
800
801 sw_sample *
802 crop_in (sw_sample * sample, sw_edit_buffer * eb)
803 {
804   sw_sounddata * sounddata;
805   GList * gl;
806   sw_edit_region * er;
807   sw_framecount_t delta;
808
809   crop_in_eb_data (sample->sounddata, eb);
810   sounddata = sample->sounddata;
811
812   gl = eb->regions;
813   er = (sw_edit_region *)gl->data;
814   if (er->start == 0) {
815     delta = er->end;
816
817     g_mutex_lock (sounddata->sels_mutex);
818     sounddata_selection_translate (sounddata, delta);
819     g_mutex_unlock (sounddata->sels_mutex);
820
821     g_mutex_lock (sample->play_mutex);
822     sample->user_offset += delta;
823     g_mutex_unlock (sample->play_mutex);
824
825     g_mutex_lock (sample->play_head->head_mutex);
826     sample->play_head->offset += delta;
827     sample->play_head->stop_offset += delta;
828     g_mutex_unlock (sample->play_head->head_mutex);
829
830     if (sample->rec_head) {
831       g_mutex_lock (sample->rec_head->head_mutex);
832       sample->rec_head->offset += delta;
833       sample->rec_head->stop_offset += delta;
834       g_mutex_unlock (sample->rec_head->head_mutex);
835     }
836   }
837
838   return sample;
839 }
840
841 /* Modifies sounddata */
842 static void
843 edit_clear_sel (sw_sample * sample)
844 {
845   sw_sounddata * sounddata = sample->sounddata;
846   sw_format * f = sounddata->format;
847   GList * gl;
848   sw_sel * sel;
849   sw_framecount_t offset, len;
850   sw_framecount_t sel_total, run_total;
851
852   gboolean active = TRUE;
853
854   sel_total = sounddata_selection_nr_frames (sounddata) / 100;
855   if (sel_total == 0) sel_total = 1;
856   run_total = 0;
857
858   for (gl = sounddata->sels; active && gl; gl = gl->next) {
859     g_mutex_lock (sample->ops_mutex);
860
861     if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) {
862       active = FALSE;
863     } else {
864       sel = (sw_sel *)gl->data;
865      
866       offset = frames_to_bytes (f, sel->sel_start);
867       len = frames_to_bytes (f, sel->sel_end - sel->sel_start);
868      
869       memset ((gpointer)(sounddata->data + offset), 0, (size_t)len);
870      
871       run_total += sel->sel_end - sel->sel_start;
872       sample_set_progress_percent (sample, run_total / sel_total);
873     }
874
875     g_mutex_unlock (sample->ops_mutex);
876   }
877 }
878
879 /* modifies sounddata */
880 sw_sample *
881 crop_out (sw_sample * sample)
882 {
883   sw_sounddata * sounddata = sample->sounddata;
884   sw_format * f = sounddata->format;
885   sw_framecount_t length;
886   GList * gl;
887   sw_sel * sel1, * sel2, * osel, * sel;
888   /*sw_sounddata * out;*/
889   gpointer d;
890   sw_framecount_t offset, len;
891   sw_framecount_t byte_length;
892
893   if (!sounddata->sels) {
894     return sample;
895   }
896
897
898 #ifdef DEBUG
899   printf("Splice out: remaining length %d\n", length);
900 #endif
901
902
903   /* XXX: Force crops to be atomic wrt. to cancellation. For
904    * multi-region selections it would be nicer to build the redo data
905    * incrementally, but wtf.
906    * Each region's memmove needs to be treated as atomic anyway so the
907    * gain isn't so much.
908    */
909   g_mutex_lock (sample->ops_mutex);
910
911   gl = sounddata->sels;
912   sel1 = (sw_sel *)gl->data;
913
914   gl = g_list_last (sounddata->sels);
915   sel2 = (sw_sel *)gl->data;
916
917   if (sel1->sel_start <= 0 && sel2->sel_end >= sounddata->nr_frames) {
918     d = sounddata->data;
919     goto zero_out;
920   }
921
922   sample_set_progress_percent (sample, 13);
923
924   /* ok, we have something to crop */
925
926   length = sounddata_selection_width (sounddata);
927   byte_length = frames_to_bytes (f, length);
928   d = sounddata->data;
929
930   if (sel1->sel_start > 0) {
931     /* Need to move */
932     offset = frames_to_bytes (f, sel1->sel_start);
933     g_memmove (d, (gpointer)(d + offset), byte_length);
934   }
935
936   sample_set_progress_percent (sample, 37);
937
938   /* Need to shorten */
939   d = g_realloc (sounddata->data, byte_length);
940   sounddata->data = d;
941   sounddata->nr_frames = length;
942
943   /* Fix offsets */
944   sample->user_offset -= sel1->sel_start;
945   sample->user_offset = CLAMP(sample->user_offset, 0, length);
946
947   g_mutex_lock (sample->play_head->head_mutex);
948
949   sample->play_head->offset -= sel1->sel_start;
950   sample->play_head->offset =
951     CLAMP(sample->play_head->offset, 0, length);
952
953   sample->play_head->stop_offset -= sel1->sel_start;
954   sample->play_head->stop_offset =
955     CLAMP(sample->play_head->stop_offset, 0, length);
956
957   g_mutex_unlock (sample->play_head->head_mutex);
958
959   if (sample->rec_head) {
960     g_mutex_lock (sample->rec_head->head_mutex);
961
962     sample->rec_head->offset -= sel1->sel_start;
963     sample->rec_head->offset =
964       CLAMP(sample->rec_head->offset, 0, length);
965
966     sample->rec_head->stop_offset -= sel1->sel_start;
967     sample->rec_head->stop_offset =
968       CLAMP(sample->rec_head->stop_offset, 0, length);
969
970     g_mutex_unlock (sample->rec_head->head_mutex);
971   }
972
973   /* Fix selection */
974   sounddata_selection_translate (sounddata, -(sel1->sel_start));
975
976  zero_out:
977   /* Zero out data between selections */
978   gl = sounddata->sels;
979   osel = (sw_sel *)gl->data;
980
981   for (gl = gl->next; gl; gl = gl->next) {
982     sel = (sw_sel *)gl->data;
983
984     offset = frames_to_bytes (f, osel->sel_end);
985     len = frames_to_bytes (f, sel->sel_start) - offset;
986     memset ((gpointer)(d + offset), 0, len);
987
988     osel = sel;
989   }
990
991   sample_set_progress_percent (sample, 100);
992
993   g_mutex_unlock (sample->ops_mutex);
994
995   return sample;
996 }
997
998 /* modifies sounddata */
999 static sw_sample *
1000 paste_insert (sw_sample * sample, sw_edit_buffer * eb,
1001               sw_framecount_t paste_offset)
1002 {
1003   sw_sounddata * sounddata = sample->sounddata;
1004   sw_format * f = sounddata->format;
1005   sw_framecount_t paste_delta = 0, len;
1006   sw_framecount_t length, paste_length, sel_length = 0;
1007   GList * gl;
1008   sw_edit_region * er;
1009   gpointer d;
1010
1011   paste_delta = frames_to_bytes (f, paste_offset);
1012
1013   paste_length = edit_buffer_length (eb);
1014   length = MAX(sounddata->nr_frames, paste_offset) + paste_length;
1015
1016   d = g_realloc (sounddata->data, frames_to_bytes (f, length));
1017   sounddata->data = d;
1018
1019   d = (gpointer)(sounddata->data + frames_to_bytes(f, length));
1020
1021   /* Copy in the tail end of the sounddata */
1022   if (paste_offset < sounddata->nr_frames) {
1023     len = frames_to_bytes (f, sounddata->nr_frames) - paste_delta;
1024     d -= len;
1025     memmove (d, (gpointer)(sounddata->data + paste_delta), len);
1026   }
1027
1028   /* Copy in the contents of the edit buffer */
1029   for (gl = g_list_last(eb->regions); gl; gl = gl->prev) {
1030     er = (sw_edit_region *)gl->data;
1031
1032     len = frames_to_bytes (f, er->end - er->start);
1033     sel_length += (er->end - er->start);
1034
1035     d -= len;
1036     memcpy (d, er->data, len);
1037   }
1038
1039   /* If paste point is beyond the previous sounddata length,
1040      add some silence */
1041   if (paste_offset > sounddata->nr_frames) {
1042     len = paste_delta - frames_to_bytes (f, sounddata->nr_frames);
1043     d -= len;
1044     memset (d, 0, len);
1045   }
1046
1047   /* The head of the sounddata remains intact */
1048
1049   /* Select the copied in portion of the sounddata */
1050   sounddata_set_selection_1 (sounddata, paste_offset,
1051                              paste_offset + paste_length);
1052
1053   /* Move offset markers */
1054
1055   if (sample->user_offset > paste_offset)
1056     sample->user_offset += sel_length;
1057
1058   if (sample->play_head->offset > paste_offset)
1059     sample->play_head->offset += sel_length;
1060   if (sample->play_head->stop_offset > paste_offset)
1061     sample->play_head->stop_offset += sel_length;
1062
1063   if (sample->rec_head) {
1064     if (sample->rec_head->offset > paste_offset)
1065       sample->rec_head->offset += sel_length;
1066     if (sample->rec_head->stop_offset > paste_offset)
1067       sample->rec_head->stop_offset += sel_length;
1068   }
1069
1070   sounddata->nr_frames = length;
1071
1072   return sample;
1073 }
1074
1075 /* Modifies sample */
1076 sw_sample *
1077 paste_over (sw_sample * sample, sw_edit_buffer * eb)
1078 {
1079   sw_format * f = sample->sounddata->format;
1080   sw_framecount_t offset, len;
1081   sw_framecount_t length;
1082   GList * gl;
1083   sw_edit_region * er;
1084
1085   if (!eb) return sample;
1086
1087   length = sample->sounddata->nr_frames;
1088
1089   for (gl = eb->regions; gl; gl = gl->next) {
1090     er = (sw_edit_region *)gl->data;
1091
1092     if (er->start > length) break;
1093
1094     offset = frames_to_bytes (f, er->start);
1095     len = frames_to_bytes (f, MIN(er->end, length) - er->start);
1096     memcpy ((gpointer)(sample->sounddata->data + offset), er->data, len);
1097   }
1098
1099   return sample;
1100 }
1101
1102 /* Modifies sample */
1103 static sw_sample *
1104 paste_mix (sw_sample * sample, sw_edit_buffer * eb,
1105            sw_framecount_t paste_offset, gdouble src_gain, gdouble dest_gain)
1106 {
1107   sw_format * f = sample->sounddata->format;
1108   sw_framecount_t length, eb_delta;
1109   GList * gl;
1110   sw_edit_region * er;
1111   sw_audio_t * d, * e;
1112   sw_framecount_t offset, remaining, n, i;
1113   sw_framecount_t run_total, eb_total;
1114   gint percent;
1115
1116   gboolean active = TRUE;
1117
1118 #ifdef DEBUG
1119   g_print ("paste_mix: src_gain %f, dest_gain %f\n", src_gain, dest_gain);
1120 #endif
1121
1122   if (eb == NULL || eb->regions == NULL) return sample;
1123
1124   length = sample->sounddata->nr_frames;
1125
1126   run_total = 0;
1127   eb_total = edit_buffer_length (eb);
1128
1129   eb_delta = ((sw_edit_region *)eb->regions->data)->start;
1130
1131   for (gl = eb->regions; active && gl; gl = gl->next) {
1132     er = (sw_edit_region *)gl->data;
1133
1134     if (er->start > length) break;
1135    
1136     d = sample->sounddata->data +
1137       frames_to_bytes (f, er->start - eb_delta + paste_offset);
1138     e = er->data;
1139    
1140     offset = 0;
1141     remaining = MIN(er->end, length) - er->start;
1142
1143     while (active && remaining > 0) {
1144       g_mutex_lock (sample->ops_mutex);
1145      
1146       if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) {
1147         active = FALSE;
1148       } else {
1149        
1150         n = MIN(remaining, 1024);
1151        
1152         for (i = 0; i < n * f->channels; i++) {
1153           d[i] = d[i] * dest_gain + e[i] * src_gain;
1154         }
1155        
1156         remaining -= n;
1157         offset += n;
1158        
1159         d += n * f->channels;
1160         e += n * f->channels;
1161        
1162         run_total += n;
1163         percent = run_total / (eb_total/100);
1164         sample_set_progress_percent (sample, percent);
1165        
1166 #ifdef DEBUG
1167         g_print ("completed %d / %d frames, %d%%\n", run_total, eb_total,
1168                  percent);
1169 #endif
1170       }
1171      
1172       g_mutex_unlock (sample->ops_mutex);
1173     }
1174    
1175   }
1176  
1177   return sample;
1178 }
1179
1180 /* Modifies sample */
1181 static sw_sample *
1182 paste_xfade (sw_sample * sample, sw_edit_buffer * eb,
1183              sw_framecount_t paste_offset,
1184              gdouble src_gain_start, gdouble src_gain_end,
1185              gdouble dest_gain_start, gdouble dest_gain_end)
1186 {
1187   sw_format * f = sample->sounddata->format;
1188   sw_framecount_t length, eb_delta;
1189   GList * gl;
1190   sw_edit_region * er;
1191   sw_audio_t * d, * e;
1192   sw_framecount_t offset, remaining, n, i, j, k;
1193   sw_framecount_t run_total, eb_total;
1194   gint percent;
1195
1196   gdouble src_gain, dest_gain;
1197   gdouble src_gain_delta, dest_gain_delta;
1198
1199   gboolean active = TRUE;
1200
1201 #ifdef DEBUG
1202   g_print ("paste_xfade: src: %f -> %f\tdest: %f -> %f\n",
1203            src_gain_start, src_gain_end, dest_gain_start, dest_gain_end);
1204 #endif
1205
1206   if (eb == NULL || eb->regions == NULL) return sample;
1207
1208   length = sample->sounddata->nr_frames;
1209
1210   run_total = 0;
1211   eb_total = edit_buffer_length (eb);
1212
1213   eb_delta = ((sw_edit_region *)eb->regions->data)->start;
1214
1215   src_gain = src_gain_start;
1216   dest_gain = dest_gain_start;
1217
1218   src_gain_delta = (src_gain_end - src_gain_start) / (gdouble)eb_total;
1219   dest_gain_delta = (dest_gain_end - dest_gain_start) / (gdouble)eb_total;
1220
1221   for (gl = eb->regions; active && gl; gl = gl->next) {
1222     er = (sw_edit_region *)gl->data;
1223
1224     if (er->start > length) break;
1225    
1226     d = sample->sounddata->data +
1227       frames_to_bytes (f, er->start - eb_delta + paste_offset);
1228     e = er->data;
1229    
1230     offset = 0;
1231     remaining = MIN(er->end, length) - er->start;
1232
1233     while (active && remaining > 0) {
1234       g_mutex_lock (sample->ops_mutex);
1235      
1236       if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) {
1237         active = FALSE;
1238       } else {
1239        
1240         n = MIN(remaining, 1024);
1241
1242         k = 0;
1243         for (i = 0; i < n; i++) {
1244           for (j = 0; j < f->channels; j++) {
1245             d[k] = d[k] * dest_gain + e[k] * src_gain;
1246             k++;
1247           }
1248           src_gain += src_gain_delta;
1249           dest_gain += dest_gain_delta;
1250         }
1251        
1252         remaining -= n;
1253         offset += n;
1254        
1255         d += n * f->channels;
1256         e += n * f->channels;
1257        
1258         run_total += n;
1259         percent = run_total / (eb_total/100);
1260         sample_set_progress_percent (sample, percent);
1261        
1262 #ifdef DEBUG
1263         g_print ("completed %d / %d frames, %d%%\n", run_total, eb_total,
1264                  percent);
1265 #endif
1266       }
1267      
1268       g_mutex_unlock (sample->ops_mutex);
1269     }
1270    
1271   }
1272  
1273   return sample;
1274 }
1275
1276 static void
1277 do_copy_thread (sw_op_instance * inst)
1278 {
1279   sw_sample * sample = inst->sample;
1280
1281   if (sample == NULL || sample->sounddata == NULL ||
1282       sample->sounddata->sels == NULL) goto noop;
1283
1284   ebuf_clear ();
1285
1286   ebuf = edit_buffer_from_sample (sample);
1287
1288   return;
1289
1290  noop:
1291   sample_set_tmp_message (sample, _("No selection to copy"));
1292 }
1293
1294 /* No undo for copy -- is input only */
1295 static sw_operation copy_op = {
1296   SWEEP_EDIT_MODE_FILTER,
1297   (SweepCallback)do_copy_thread,
1298   (SweepFunction)NULL,
1299   (SweepCallback)NULL,
1300   (SweepFunction)NULL,
1301   (SweepCallback)NULL,
1302   (SweepFunction)NULL,
1303 };
1304
1305 void
1306 do_copy (sw_sample * sample)
1307 {
1308   schedule_operation (sample, _("Copy"), &copy_op, NULL);
1309 }
1310
1311
1312 static void
1313 do_cut_thread (sw_op_instance * inst)
1314 {
1315   sw_sample * sample = inst->sample;
1316   sw_edit_buffer * eb;
1317
1318   if (sample == NULL || sample->sounddata == NULL ||
1319       sample->sounddata->sels == NULL) goto noop;
1320
1321   /*  inst = sw_op_instance_new ("Cut", &cut_op);*/
1322
1323   eb = edit_buffer_from_sample (sample);
1324
1325   inst->redo_data = inst->undo_data = splice_data_new (eb, NULL);
1326   set_active_op (sample, inst);
1327
1328   ebuf_clear ();
1329
1330   /*ebuf = edit_buffer_copy (eb);*/
1331   ebuf = edit_buffer_ref (eb);
1332
1333   splice_out_sel (sample);
1334
1335   if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
1336     register_operation (sample, inst);
1337   }
1338
1339   return;
1340
1341  noop:
1342   sample_set_tmp_message (sample, _("No selection to cut"));
1343 }
1344
1345 static sw_operation cut_op = {
1346   SWEEP_EDIT_MODE_ALLOC,
1347   (SweepCallback)do_cut_thread,
1348   (SweepFunction)NULL,
1349   (SweepCallback)undo_by_splice_in,
1350   (SweepFunction)splice_data_destroy,
1351   (SweepCallback)redo_by_splice_out,
1352   (SweepFunction)splice_data_destroy
1353 };
1354
1355 void
1356 do_cut (sw_sample * sample)
1357 {
1358   schedule_operation (sample, _("Cut"), &cut_op, NULL);
1359 }
1360
1361 static void
1362 do_clear_thread (sw_op_instance * inst)
1363 {
1364   sw_sample * sample = inst->sample;
1365   sw_edit_buffer * old_eb;
1366   paste_over_data * p;
1367
1368   if (sample == NULL || sample->sounddata == NULL ||
1369       sample->sounddata->sels == NULL) goto noop;
1370
1371   old_eb = edit_buffer_from_sample (sample);
1372
1373   p = paste_over_data_new (old_eb, old_eb);
1374   inst->redo_data = inst->undo_data = p;
1375   set_active_op (sample, inst);
1376
1377   edit_clear_sel (sample);
1378
1379   if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
1380     p->new_eb = edit_buffer_from_sample (sample);
1381
1382     register_operation (sample, inst);
1383   }
1384
1385   return;
1386
1387  noop:
1388   sample_set_tmp_message (sample, _("No selection to clear"));
1389 }
1390
1391 static sw_operation clear_op = {
1392   SWEEP_EDIT_MODE_FILTER,
1393   (SweepCallback)do_clear_thread,
1394   (SweepFunction)NULL,
1395   (SweepCallback)undo_by_paste_over,
1396   (SweepFunction)paste_over_data_destroy,
1397   (SweepCallback)redo_by_paste_over /* redo_by_reperform */,
1398   (SweepFunction)paste_over_data_destroy
1399 };
1400
1401 void
1402 do_clear (sw_sample * sample)
1403 {
1404   schedule_operation (sample, _("Clear"), &clear_op, NULL);
1405 }
1406
1407 static void
1408 do_delete_thread (sw_op_instance * inst)
1409 {
1410   sw_sample * sample = inst->sample;
1411   sw_edit_buffer * eb;
1412
1413   if (sample == NULL || sample->sounddata == NULL ||
1414       sample->sounddata->sels == NULL) goto noop;
1415
1416   eb = edit_buffer_from_sample (sample);
1417
1418   inst->redo_data = inst->undo_data = splice_data_new (eb, NULL);
1419   set_active_op (sample, inst);
1420
1421   splice_out_sel (sample);
1422
1423   if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
1424     register_operation (sample, inst);
1425   }
1426
1427   return;
1428
1429  noop:
1430   sample_set_tmp_message (sample, _("No selection to delete"));
1431 }
1432
1433 static sw_operation delete_op = {
1434   SWEEP_EDIT_MODE_ALLOC,
1435   (SweepCallback)do_delete_thread,
1436   (SweepFunction)NULL,
1437   (SweepCallback)undo_by_splice_in,
1438   (SweepFunction)splice_data_destroy,
1439   (SweepCallback)redo_by_splice_out,
1440   (SweepFunction)splice_data_destroy
1441 };
1442
1443
1444 void
1445 do_delete (sw_sample * sample)
1446 {
1447   schedule_operation (sample, _("Delete"), &delete_op, NULL);
1448 }
1449
1450 static void
1451 do_crop_thread (sw_op_instance * inst)
1452 {
1453   sw_sample * sample = inst->sample;
1454   GList * sels;
1455   sw_edit_buffer * eb;
1456
1457   if (sample == NULL || sample->sounddata == NULL ||
1458       sample->sounddata->sels == NULL) goto noop;
1459
1460   sels = sels_copy (sample->sounddata->sels);
1461   sels = sels_invert (sels, sample->sounddata->nr_frames);
1462
1463   if (sels == NULL) goto noop;
1464
1465   eb = edit_buffer_from_sounddata_sels (sample->sounddata, sels);
1466
1467   /* If there's nothing to crop out, do nothing and register nothing */
1468   if (eb == NULL || eb->regions == NULL) goto noop;
1469
1470   inst->redo_data = inst->undo_data = splice_data_new (eb, NULL);
1471   set_active_op (sample, inst);
1472
1473   crop_out (sample);
1474
1475   if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
1476     register_operation (sample, inst);
1477   }
1478
1479   return;
1480
1481  noop:
1482   sample_set_tmp_message (sample, _("Nothing to crop out"));
1483 }
1484
1485 static sw_operation crop_op = {
1486   SWEEP_EDIT_MODE_ALLOC,
1487   (SweepCallback)do_crop_thread,
1488   (SweepFunction)NULL,
1489   (SweepCallback)undo_by_crop_in,
1490   (SweepFunction)splice_data_destroy,
1491   (SweepCallback)redo_by_crop_out,
1492   (SweepFunction)splice_data_destroy
1493 };
1494
1495 void
1496 do_crop (sw_sample * sample)
1497 {
1498   schedule_operation (sample, _("Crop"), &crop_op, NULL);
1499 }
1500
1501 static void
1502 do_paste_insert_thread (sw_op_instance * inst)
1503 {
1504   sw_sample * sample = inst->sample;
1505   sw_sounddata * out;
1506   sw_edit_buffer * eb1, *eb2;
1507
1508   if (ebuf == NULL) goto noop;
1509
1510   if (!format_equal (ebuf->format, sample->sounddata->format))
1511     goto incompatible;
1512
1513   /*eb1 = edit_buffer_copy (ebuf);*/
1514   eb1 = edit_buffer_ref (ebuf);
1515
1516   inst->undo_data = splice_data_new (eb1, sample->sounddata->sels);
1517   inst->redo_data = NULL;
1518   set_active_op (sample, inst);
1519
1520   paste_insert (sample, ebuf, sample->user_offset);
1521
1522   if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
1523     out = sample->sounddata;
1524     eb2 = edit_buffer_from_sounddata (out);
1525     inst->redo_data = splice_data_new (eb2, NULL);
1526
1527     register_operation (sample, inst);
1528   }
1529
1530   return;
1531
1532  noop:
1533   sample_set_tmp_message (sample, _("Clipboard empty"));
1534   return;
1535
1536  incompatible:
1537   sample_set_tmp_message (sample, _("Clipboard data has incompatible format"));
1538   return;
1539 }
1540
1541 static sw_operation paste_insert_op = {
1542   SWEEP_EDIT_MODE_ALLOC,
1543   (SweepCallback)do_paste_insert_thread,
1544   (SweepFunction)NULL,
1545   (SweepCallback)undo_by_splice_out,
1546   (SweepFunction)splice_data_destroy,
1547   (SweepCallback)redo_by_splice_in,
1548   (SweepFunction)splice_data_destroy
1549 };
1550
1551
1552 void
1553 do_paste_insert (sw_sample * sample)
1554 {
1555   schedule_operation (sample, _("Paste insert"), &paste_insert_op, NULL);
1556 }
1557
1558 typedef struct {
1559   gdouble src_gain;
1560   gdouble dest_gain;
1561 } paste_mix_op_data;
1562
1563 static void
1564 do_paste_mix_thread (sw_op_instance * inst)
1565 {
1566   sw_sample * sample = inst->sample;
1567   paste_mix_op_data * pd = (paste_mix_op_data *)inst->do_data;
1568   sw_sounddata * out;
1569   GList * old_sels, * sels;
1570   sw_edit_buffer * eb1, *eb2;
1571   gdouble src_gain, dest_gain;
1572
1573   src_gain = pd->src_gain;
1574   dest_gain = pd->dest_gain;
1575   g_free (pd);
1576
1577   if (ebuf == NULL) goto noop;
1578
1579   if (!format_equal (ebuf->format, sample->sounddata->format))
1580     goto incompatible;
1581
1582   old_sels = sels_copy (sample->sounddata->sels);
1583   sels = sels_from_edit_buffer_offset (ebuf, sample->user_offset);
1584   sample_set_selection (sample, sels);
1585
1586   eb1 = edit_buffer_from_sounddata (sample->sounddata);
1587
1588   inst->undo_data = splice_data_new (eb1, old_sels);
1589   inst->redo_data = NULL;
1590   set_active_op (sample, inst);
1591
1592   paste_mix (sample, ebuf, sample->user_offset, src_gain, dest_gain);
1593
1594   if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
1595     out = sample->sounddata;
1596     eb2 = edit_buffer_from_sounddata (out);
1597     inst->redo_data = splice_data_new (eb2, sels);
1598
1599     register_operation (sample, inst);
1600   } else {
1601     sample_set_selection (sample, old_sels);
1602   }
1603
1604   return;
1605
1606  noop:
1607   sample_set_tmp_message (sample, _("Clipboard empty"));
1608   return;
1609
1610  incompatible:
1611   sample_set_tmp_message (sample, _("Clipboard data has incompatible format"));
1612   return;
1613 }
1614
1615 static sw_operation paste_mix_op = {
1616   SWEEP_EDIT_MODE_FILTER,
1617   (SweepCallback)do_paste_mix_thread,
1618   (SweepFunction)NULL,
1619   (SweepCallback)undo_by_splice_over,
1620   (SweepFunction)splice_data_destroy,
1621   (SweepCallback)redo_by_splice_over,
1622   (SweepFunction)splice_data_destroy
1623 };
1624
1625 void
1626 do_paste_mix (sw_sample * sample, gdouble src_gain, gdouble dest_gain)
1627 {
1628   paste_mix_op_data * pd;
1629
1630   pd = g_malloc (sizeof(paste_mix_op_data));
1631   pd->src_gain = src_gain;
1632   pd->dest_gain = dest_gain;
1633
1634   schedule_operation (sample, _("Paste mix"), &paste_mix_op, pd);
1635 }
1636
1637 typedef struct {
1638   gdouble src_gain_start;
1639   gdouble src_gain_end;
1640   gdouble dest_gain_start;
1641   gdouble dest_gain_end;
1642 } paste_xfade_op_data;
1643
1644 static void
1645 do_paste_xfade_thread (sw_op_instance * inst)
1646 {
1647   sw_sample * sample = inst->sample;
1648   paste_xfade_op_data * pd = (paste_xfade_op_data *)inst->do_data;
1649   sw_sounddata * out;
1650   GList * old_sels, * sels;
1651   sw_edit_buffer * eb1, *eb2;
1652   gdouble src_gain_start, src_gain_end, dest_gain_start, dest_gain_end;
1653
1654   src_gain_start = pd->src_gain_start;
1655   src_gain_end = pd->src_gain_end;
1656   dest_gain_start = pd->dest_gain_start;
1657   dest_gain_end = pd->dest_gain_end;
1658   g_free (pd);
1659
1660   if (ebuf == NULL) goto noop;
1661
1662   if (!format_equal (ebuf->format, sample->sounddata->format))
1663     goto incompatible;
1664
1665   old_sels = sels_copy (sample->sounddata->sels);
1666   sels = sels_from_edit_buffer_offset (ebuf, sample->user_offset);
1667   sample_set_selection (sample, sels);
1668
1669   eb1 = edit_buffer_from_sounddata (sample->sounddata);
1670
1671   inst->undo_data = splice_data_new (eb1, old_sels);
1672   inst->redo_data = NULL;
1673   set_active_op (sample, inst);
1674
1675   paste_xfade (sample, ebuf, sample->user_offset, src_gain_start,
1676                src_gain_end, dest_gain_start, dest_gain_end);
1677
1678   if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
1679     out = sample->sounddata;
1680     eb2 = edit_buffer_from_sounddata (out);
1681     inst->redo_data = splice_data_new (eb2, sels);
1682
1683     register_operation (sample, inst);
1684   } else {
1685     sample_set_selection (sample, old_sels);
1686   }
1687
1688   return;
1689
1690  noop:
1691   sample_set_tmp_message (sample, _("Clipboard empty"));
1692   return;
1693
1694  incompatible:
1695   sample_set_tmp_message (sample, _("Clipboard data has incompatible format"));
1696   return;
1697 }
1698
1699 static sw_operation paste_xfade_op = {
1700   SWEEP_EDIT_MODE_FILTER,
1701   (SweepCallback)do_paste_xfade_thread,
1702   (SweepFunction)NULL,
1703   (SweepCallback)undo_by_splice_over,
1704   (SweepFunction)splice_data_destroy,
1705   (SweepCallback)redo_by_splice_over,
1706   (SweepFunction)splice_data_destroy
1707 };
1708
1709 void
1710 do_paste_xfade (sw_sample * sample, gdouble src_gain_start,
1711                 gdouble src_gain_end, gdouble dest_gain_start,
1712                 gdouble dest_gain_end)
1713 {
1714   paste_xfade_op_data * pd;
1715
1716   pd = g_malloc (sizeof(paste_xfade_op_data));
1717   pd->src_gain_start = src_gain_start;
1718   pd->src_gain_end = src_gain_end;
1719   pd->dest_gain_start = dest_gain_start;
1720   pd->dest_gain_end = dest_gain_end;
1721
1722   schedule_operation (sample, _("Paste xfade"), &paste_xfade_op, pd);
1723 }
1724
1725 sw_sample *
1726 do_paste_as_new (void)
1727 {
1728   if (ebuf == NULL) return NULL;
1729
1730   return sample_from_edit_buffer (ebuf);
1731 }
1732
Note: See TracBrowser for help on using the browser.