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 <sweep/sweep_i18n.h>
29 #include <sweep/sweep_types.h>
30 #include <sweep/sweep_typeconvert.h>
31 #include <sweep/sweep_undo.h>
32 #include <sweep/sweep_filter.h>
33 #include <sweep/sweep_sounddata.h>
34 #include <sweep/sweep_sample.h>
35
36 #include "sweep_app.h"
37 #include "edit.h"
38
39
40 static void
do_filter_regions(sw_sample * sample,SweepFilterRegion func,sw_param_set pset,gpointer custom_data)41 do_filter_regions (sw_sample * sample, SweepFilterRegion func,
42 sw_param_set pset, gpointer custom_data)
43 {
44 sw_sounddata * sounddata = sample->sounddata;
45 sw_format * f = sounddata->format;
46 GList * gl;
47 sw_sel * sel;
48 sw_framecount_t sel_total, run_total;
49 sw_framecount_t offset, remaining, n;
50 gpointer d;
51 gint percent;
52
53 gboolean active = TRUE;
54
55 sel_total = sounddata_selection_nr_frames (sounddata) / 100;
56 if (sel_total == 0) sel_total = 1;
57 run_total = 0;
58
59 for (gl = sounddata->sels; active && gl; gl = gl->next) {
60 sel = (sw_sel *)gl->data;
61
62 offset = 0;
63 remaining = sel->sel_end - sel->sel_start;
64
65 while (active && remaining > 0) {
66 g_mutex_lock (sample->ops_mutex);
67
68 if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) {
69 active = FALSE;
70 } else {
71 d = sounddata->data + (int)frames_to_bytes (f, sel->sel_start + offset);
72
73 n = MIN(remaining, 1024);
74
75 func (d, sounddata->format, n, pset, custom_data);
76
77 remaining -= n;
78 offset += n;
79
80 run_total += n;
81 percent = run_total / sel_total;
82 sample_set_progress_percent (sample, percent);
83
84 #ifdef DEBUG
85 g_print ("completed %d / %d frames, %d%%\n", run_total, sel_total,
86 percent);
87 #endif
88 }
89
90 g_mutex_unlock (sample->ops_mutex);
91 }
92 }
93 }
94
95 static void
do_filter_regions_thread(sw_op_instance * inst)96 do_filter_regions_thread (sw_op_instance * inst)
97 {
98 sw_sample * sample = inst->sample;
99 sw_perform_data * pd = (sw_perform_data *)inst->do_data;
100
101 sw_edit_buffer * old_eb;
102 paste_over_data * p;
103
104 if (sample == NULL || sample->sounddata == NULL ||
105 sample->sounddata->sels == NULL) goto noop;
106
107 old_eb = edit_buffer_from_sample (sample);
108
109 p = paste_over_data_new (old_eb, old_eb);
110 inst->redo_data = inst->undo_data = p;
111 set_active_op (sample, inst);
112
113 do_filter_regions (sample, (SweepFilterRegion)pd->func, pd->pset,
114 pd->custom_data);
115
116 if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
117 p->new_eb = edit_buffer_from_sample (sample);
118
119 register_operation (sample, inst);
120 }
121
122 return;
123
124 noop:
125 sample_set_tmp_message (sample, _("No selection to process"));
126 }
127
128 static sw_operation filter_regions_op = {
129 SWEEP_EDIT_MODE_FILTER,
130 (SweepCallback)do_filter_regions_thread,
131 (SweepFunction)g_free,
132 (SweepCallback)undo_by_paste_over,
133 (SweepFunction)paste_over_data_destroy,
134 (SweepCallback)redo_by_paste_over,
135 (SweepFunction)paste_over_data_destroy
136 };
137
138 sw_op_instance *
perform_filter_region_op(sw_sample * sample,char * desc,SweepFilterRegion func,sw_param_set pset,gpointer custom_data)139 perform_filter_region_op (sw_sample * sample, char * desc,
140 SweepFilterRegion func,
141 sw_param_set pset, gpointer custom_data)
142 {
143 sw_perform_data * pd = (sw_perform_data *)g_malloc (sizeof(*pd));
144
145 pd->func = (SweepFunction)func;
146 pd->pset = pset;
147 pd->custom_data = custom_data;
148
149 schedule_operation (sample, desc, &filter_regions_op, pd);
150
151 return NULL;
152 }
153
154 static void
do_filter_thread(sw_op_instance * inst)155 do_filter_thread (sw_op_instance * inst)
156 {
157 sw_sample * sample = inst->sample;
158 sw_perform_data * pd = (sw_perform_data *)inst->do_data;
159
160 SweepFilter func = (SweepFilter)pd->func;
161 sw_param_set pset = pd->pset;
162 void * custom_data = pd->custom_data;
163
164 sw_edit_buffer * old_eb;
165 paste_over_data * p;
166 sw_sample * out;
167
168 old_eb = edit_buffer_from_sample (sample);
169
170 p = paste_over_data_new (old_eb, old_eb);
171 inst->redo_data = inst->undo_data = p;
172 set_active_op (sample, inst);
173
174 out = func (sample, pset, custom_data);
175
176 /* XXX: this is all kinda assuming out == sample if out != NULL */
177 if (out != NULL && sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
178 p->new_eb = edit_buffer_from_sample (sample);
179
180 register_operation (sample, inst);
181 }
182 }
183
184 static sw_operation filter_op = {
185 SWEEP_EDIT_MODE_FILTER,
186 (SweepCallback)do_filter_thread,
187 (SweepFunction)g_free,
188 (SweepCallback)undo_by_paste_over,
189 (SweepFunction)paste_over_data_destroy,
190 (SweepCallback)redo_by_paste_over,
191 (SweepFunction)paste_over_data_destroy
192 };
193
194
195 sw_op_instance *
perform_filter_op(sw_sample * sample,char * desc,SweepFilter func,sw_param_set pset,gpointer custom_data)196 perform_filter_op (sw_sample * sample, char * desc, SweepFilter func,
197 sw_param_set pset, gpointer custom_data)
198 {
199 sw_perform_data * pd = (sw_perform_data *)g_malloc (sizeof(*pd));
200
201 pd->func = (SweepFunction)func;
202 pd->pset = pset;
203 pd->custom_data = custom_data;
204
205 schedule_operation (sample, desc, &filter_op, pd);
206
207 return NULL;
208 }
209