| 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 |
#include <glib.h> |
|---|
| 28 |
|
|---|
| 29 |
#include <sweep/sweep_sample.h> |
|---|
| 30 |
#include <sweep/sweep_typeconvert.h> |
|---|
| 31 |
#include <sweep/sweep_undo.h> |
|---|
| 32 |
|
|---|
| 33 |
#include "format.h" |
|---|
| 34 |
#include "view.h" |
|---|
| 35 |
#include "sample-display.h" |
|---|
| 36 |
#include "driver.h" |
|---|
| 37 |
|
|---|
| 38 |
sw_sel * |
|---|
| 39 |
sel_new (sw_framecount_t start, sw_framecount_t end) |
|---|
| 40 |
{ |
|---|
| 41 |
sw_framecount_t s, e; |
|---|
| 42 |
sw_sel * sel; |
|---|
| 43 |
|
|---|
| 44 |
if (end>start) { s = start; e = end; } |
|---|
| 45 |
else { s = end; e = start; } |
|---|
| 46 |
|
|---|
| 47 |
sel = g_malloc (sizeof(sw_sel)); |
|---|
| 48 |
sel->sel_start = s; |
|---|
| 49 |
sel->sel_end = e; |
|---|
| 50 |
|
|---|
| 51 |
return sel; |
|---|
| 52 |
} |
|---|
| 53 |
|
|---|
| 54 |
void |
|---|
| 55 |
sel_free (sw_sel * sel) |
|---|
| 56 |
{ |
|---|
| 57 |
if (!sel) |
|---|
| 58 |
return; |
|---|
| 59 |
|
|---|
| 60 |
g_free(sel); |
|---|
| 61 |
} |
|---|
| 62 |
|
|---|
| 63 |
sw_sel * |
|---|
| 64 |
sel_copy (sw_sel * sel) |
|---|
| 65 |
{ |
|---|
| 66 |
sw_sel * nsel; |
|---|
| 67 |
|
|---|
| 68 |
nsel = sel_new (sel->sel_start, sel->sel_end); |
|---|
| 69 |
|
|---|
| 70 |
return nsel; |
|---|
| 71 |
} |
|---|
| 72 |
|
|---|
| 73 |
/* |
|---|
| 74 |
* sel_cmp (s1, s2) |
|---|
| 75 |
* |
|---|
| 76 |
* Compares two sw_sel's for g_list_insert_sorted() -- |
|---|
| 77 |
* return > 0 if s1 comes after s2 in the sort order. |
|---|
| 78 |
*/ |
|---|
| 79 |
gint |
|---|
| 80 |
sel_cmp (sw_sel * s1, sw_sel * s2) |
|---|
| 81 |
{ |
|---|
| 82 |
if (s1->sel_start > s2->sel_start) return 1; |
|---|
| 83 |
else return 0; |
|---|
| 84 |
} |
|---|
| 85 |
|
|---|
| 86 |
static void |
|---|
| 87 |
dump_sels (GList * sels, char * desc) |
|---|
| 88 |
{ |
|---|
| 89 |
#ifdef DEBUG |
|---|
| 90 |
GList * gl; |
|---|
| 91 |
sw_sel * sel; |
|---|
| 92 |
|
|---|
| 93 |
printf ("<dump %s (%p)>\n", desc, sels); |
|---|
| 94 |
for (gl = sels; gl; gl = gl->next) { |
|---|
| 95 |
sel = (sw_sel *)gl->data; |
|---|
| 96 |
printf ("\t[%ld - %ld]\n", sel->sel_start, sel->sel_end); |
|---|
| 97 |
} |
|---|
| 98 |
printf ("</dump>\n"); |
|---|
| 99 |
#endif |
|---|
| 100 |
} |
|---|
| 101 |
|
|---|
| 102 |
|
|---|
| 103 |
/* |
|---|
| 104 |
* sels_copy (sels) |
|---|
| 105 |
* |
|---|
| 106 |
* returns a copy of sels |
|---|
| 107 |
*/ |
|---|
| 108 |
GList * |
|---|
| 109 |
sels_copy (GList * sels) |
|---|
| 110 |
{ |
|---|
| 111 |
GList * gl, * nsels = NULL; |
|---|
| 112 |
sw_sel * sel, * nsel; |
|---|
| 113 |
|
|---|
| 114 |
for (gl = sels; gl; gl = gl->next) { |
|---|
| 115 |
sel = (sw_sel *)gl->data; |
|---|
| 116 |
nsel = sel_copy (sel); |
|---|
| 117 |
nsels = g_list_insert_sorted(nsels, nsel, (GCompareFunc)sel_cmp); |
|---|
| 118 |
} |
|---|
| 119 |
|
|---|
| 120 |
return nsels; |
|---|
| 121 |
} |
|---|
| 122 |
|
|---|
| 123 |
GList * |
|---|
| 124 |
sels_add_selection (GList * sels, sw_sel * sel) |
|---|
| 125 |
{ |
|---|
| 126 |
return g_list_insert_sorted (sels, sel, (GCompareFunc)sel_cmp); |
|---|
| 127 |
} |
|---|
| 128 |
|
|---|
| 129 |
GList * |
|---|
| 130 |
sels_add_selection_1 (GList * sels, sw_framecount_t start, sw_framecount_t end) |
|---|
| 131 |
{ |
|---|
| 132 |
sw_sel * sel; |
|---|
| 133 |
|
|---|
| 134 |
sel = sel_new (start, end); |
|---|
| 135 |
|
|---|
| 136 |
return sels_add_selection (sels, sel); |
|---|
| 137 |
} |
|---|
| 138 |
|
|---|
| 139 |
/* |
|---|
| 140 |
* sels_invert (sels, nr_frames) |
|---|
| 141 |
* |
|---|
| 142 |
* inverts sels in place |
|---|
| 143 |
*/ |
|---|
| 144 |
GList * |
|---|
| 145 |
sels_invert (GList * sels, sw_framecount_t nr_frames) |
|---|
| 146 |
{ |
|---|
| 147 |
GList * gl; |
|---|
| 148 |
GList * osels; |
|---|
| 149 |
sw_sel * osel, * sel; |
|---|
| 150 |
|
|---|
| 151 |
if (!sels) { |
|---|
| 152 |
g_list_free (sels); |
|---|
| 153 |
sel = sel_new (0, nr_frames); |
|---|
| 154 |
sels = NULL; |
|---|
| 155 |
sels = g_list_append (sels, sel); |
|---|
| 156 |
return sels; |
|---|
| 157 |
} |
|---|
| 158 |
|
|---|
| 159 |
gl = osels = sels; |
|---|
| 160 |
sels = NULL; |
|---|
| 161 |
|
|---|
| 162 |
sel = osel = (sw_sel *)gl->data; |
|---|
| 163 |
if (osel->sel_start > 0) { |
|---|
| 164 |
sels = sels_add_selection_1 (sels, 0, osel->sel_start - 1); |
|---|
| 165 |
} |
|---|
| 166 |
|
|---|
| 167 |
gl = gl->next; |
|---|
| 168 |
|
|---|
| 169 |
for (; gl; gl = gl->next) { |
|---|
| 170 |
sel = (sw_sel *)gl->data; |
|---|
| 171 |
sels = sels_add_selection_1 (sels, osel->sel_end, sel->sel_start - 1); |
|---|
| 172 |
osel = sel; |
|---|
| 173 |
} |
|---|
| 174 |
|
|---|
| 175 |
if (sel->sel_end != nr_frames) { |
|---|
| 176 |
sels = sels_add_selection_1 (sels, sel->sel_end, nr_frames); |
|---|
| 177 |
} |
|---|
| 178 |
|
|---|
| 179 |
g_list_free (osels); |
|---|
| 180 |
|
|---|
| 181 |
return sels; |
|---|
| 182 |
} |
|---|
| 183 |
|
|---|
| 184 |
/* |
|---|
| 185 |
* sel_replace: undo/redo functions for changing selection |
|---|
| 186 |
*/ |
|---|
| 187 |
|
|---|
| 188 |
typedef struct _sel_replace_data sel_replace_data; |
|---|
| 189 |
|
|---|
| 190 |
struct _sel_replace_data { |
|---|
| 191 |
GList * sels; |
|---|
| 192 |
}; |
|---|
| 193 |
|
|---|
| 194 |
static sel_replace_data * |
|---|
| 195 |
sel_replace_data_new (GList * sels) |
|---|
| 196 |
{ |
|---|
| 197 |
sel_replace_data * s; |
|---|
| 198 |
|
|---|
| 199 |
s = g_malloc (sizeof(sel_replace_data)); |
|---|
| 200 |
|
|---|
| 201 |
s->sels = sels; |
|---|
| 202 |
|
|---|
| 203 |
return s; |
|---|
| 204 |
} |
|---|
| 205 |
|
|---|
| 206 |
static void |
|---|
| 207 |
sel_replace_data_destroy (sel_replace_data * s) |
|---|
| 208 |
{ |
|---|
| 209 |
g_list_free (s->sels); |
|---|
| 210 |
g_free (s); |
|---|
| 211 |
} |
|---|
| 212 |
|
|---|
| 213 |
static void |
|---|
| 214 |
do_by_sel_replace (sw_sample * s, sel_replace_data * sr) |
|---|
| 215 |
{ |
|---|
| 216 |
dump_sels (sr->sels, "at replace action"); |
|---|
| 217 |
sample_set_selection (s, sr->sels); |
|---|
| 218 |
|
|---|
| 219 |
/* sample_refresh_views (s);*/ |
|---|
| 220 |
} |
|---|
| 221 |
|
|---|
| 222 |
static void |
|---|
| 223 |
do_selection_op_thread (sw_op_instance * inst) |
|---|
| 224 |
{ |
|---|
| 225 |
sw_sample * sample = inst->sample; |
|---|
| 226 |
sw_perform_data * pd = (sw_perform_data *)inst->do_data; |
|---|
| 227 |
|
|---|
| 228 |
SweepFilter func = (SweepFilter)pd->func; |
|---|
| 229 |
sw_param_set pset = pd->pset; |
|---|
| 230 |
void * custom_data = pd->custom_data; |
|---|
| 231 |
|
|---|
| 232 |
GList * sels; |
|---|
| 233 |
|
|---|
| 234 |
sels = sels_copy (sample->sounddata->sels); |
|---|
| 235 |
dump_sels (sels, "copied for undo data"); |
|---|
| 236 |
inst->undo_data = sel_replace_data_new (sels); |
|---|
| 237 |
set_active_op (sample, inst); |
|---|
| 238 |
|
|---|
| 239 |
func (sample, pset, custom_data); |
|---|
| 240 |
|
|---|
| 241 |
if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) { |
|---|
| 242 |
sels = sels_copy (sample->sounddata->sels); |
|---|
| 243 |
dump_sels (sels, "copied for redo data"); |
|---|
| 244 |
inst->redo_data = sel_replace_data_new (sels); |
|---|
| 245 |
|
|---|
| 246 |
register_operation (sample, inst); |
|---|
| 247 |
} |
|---|
| 248 |
} |
|---|
| 249 |
|
|---|
| 250 |
static sw_operation selection_op = { |
|---|
| 251 |
SWEEP_EDIT_MODE_META, |
|---|
| 252 |
(SweepCallback)do_selection_op_thread, |
|---|
| 253 |
(SweepFunction)NULL, |
|---|
| 254 |
(SweepCallback)do_by_sel_replace, |
|---|
| 255 |
(SweepFunction)sel_replace_data_destroy, |
|---|
| 256 |
(SweepCallback)do_by_sel_replace, |
|---|
| 257 |
(SweepFunction)sel_replace_data_destroy |
|---|
| 258 |
}; |
|---|
| 259 |
|
|---|
| 260 |
sw_op_instance * |
|---|
| 261 |
perform_selection_op (sw_sample * sample, char * desc, SweepFilter func, |
|---|
| 262 |
sw_param_set pset, gpointer custom_data) |
|---|
| 263 |
{ |
|---|
| 264 |
sw_perform_data * pd = (sw_perform_data *)g_malloc (sizeof(*pd)); |
|---|
| 265 |
|
|---|
| 266 |
pd->func = (SweepFunction)func; |
|---|
| 267 |
pd->pset = pset; |
|---|
| 268 |
pd->custom_data = custom_data; |
|---|
| 269 |
|
|---|
| 270 |
schedule_operation (sample, desc, &selection_op, pd); |
|---|
| 271 |
|
|---|
| 272 |
return NULL; |
|---|
| 273 |
} |
|---|