1 #include "snd.h"
2
3
make_chan_info(chan_info * cip,int chan,snd_info * sound)4 chan_info *make_chan_info(chan_info *cip, int chan, snd_info *sound)
5 {
6 chan_info *cp; /* may be re-used */
7 if (!cip)
8 {
9 cp = (chan_info *)calloc(1, sizeof(chan_info));
10 cp->ax = (graphics_context *)calloc(1, sizeof(graphics_context));
11
12 switch (chan % 4)
13 {
14 case 0: cp->combined_data_color = ss->black; break;
15 case 1: cp->combined_data_color = ss->red; break;
16 case 2: cp->combined_data_color = ss->green; break;
17 case 3: cp->combined_data_color = ss->blue; break;
18 }
19 cp->last_sonogram = NULL;
20 cp->last_wavogram = NULL;
21 cp->temp_sonogram = NULL;
22 cp->inset_graph = NULL;
23 cp->fft = NULL;
24 #if HAVE_GL
25 cp->gl_fft_list = NO_LIST;
26 cp->gl_wavo_list = NO_LIST;
27 #endif
28 cp->edit_hook = Xen_false;
29 cp->edit_hook_loc = NOT_A_GC_LOC;
30 cp->after_edit_hook = Xen_false;
31 cp->after_edit_hook_loc = NOT_A_GC_LOC;
32 cp->undo_hook = Xen_false;
33 cp->undo_hook_loc = NOT_A_GC_LOC;
34 cp->properties = Xen_false; /* will be a vector of 1 element if it's ever used */
35 cp->properties_loc = NOT_A_GC_LOC;
36 cp->active = CHANNEL_INACTIVE;
37 }
38 else cp = cip;
39 cp->chan = chan;
40 cp->sound = sound;
41 cp->sound_ctr = NOT_A_SOUND;
42 cp->edit_ctr = -1;
43 cp->sound_size = 0;
44 cp->edit_size = 0;
45 cp->cursor_on = false;
46 cp->cursor_visible = false;
47 cp->fft_cursor_visible = false;
48 cp->show_sonogram_cursor = show_sonogram_cursor(ss);
49 cp->selection_visible = false;
50 cp->editable = true; /* must be unset (region display, variable display, etc) */
51 cp->cursor_style = cursor_style(ss);
52 cp->tracking_cursor_style = tracking_cursor_style(ss);
53 cp->cursor_size = cursor_size(ss);
54 cp->cursor_proc = Xen_undefined;
55 cp->cursor_proc_loc = NOT_A_GC_LOC;
56 cp->squelch_update = false;
57 cp->show_y_zero = show_y_zero(ss);
58 cp->show_grid = show_grid(ss);
59 cp->show_marks = show_marks(ss);
60 cp->time_graph_type = time_graph_type(ss);
61 cp->wavo_hop = wavo_hop(ss);
62 cp->wavo_trace = wavo_trace(ss);
63 cp->max_transform_peaks = max_transform_peaks(ss);
64 cp->show_transform_peaks = show_transform_peaks(ss);
65 cp->zero_pad = zero_pad(ss);
66 cp->with_verbose_cursor = with_verbose_cursor(ss);
67 cp->fft_log_frequency = fft_log_frequency(ss);
68 cp->fft_log_magnitude = fft_log_magnitude(ss);
69 cp->fft_with_phases = fft_with_phases(ss);
70 cp->min_dB = min_dB(ss);
71 cp->lin_dB = ss->lin_dB;
72 cp->in_as_one_edit = 0;
73 cp->wavelet_type = wavelet_type(ss);
74 cp->spectro_x_angle = spectro_x_angle(ss);
75 cp->spectro_y_angle = spectro_y_angle(ss);
76 cp->spectro_z_angle = spectro_z_angle(ss);
77 cp->spectro_x_scale = spectro_x_scale(ss);
78 cp->spectro_y_scale = spectro_y_scale(ss);
79 cp->spectro_z_scale = spectro_z_scale(ss);
80 cp->spectrum_end = spectrum_end(ss);
81 cp->spectrum_start = spectrum_start(ss);
82 cp->spectro_hop = spectro_hop(ss);
83 cp->fft_window_alpha = fft_window_alpha(ss);
84 cp->fft_window_beta = fft_window_beta(ss);
85 cp->transform_size = transform_size(ss);
86 cp->transform_graph_type = transform_graph_type(ss);
87 cp->fft_window = fft_window(ss);
88 cp->transform_type = transform_type(ss);
89 cp->transform_normalization = transform_normalization(ss);
90 cp->show_mix_waveforms = show_mix_waveforms(ss);
91 cp->time_graph_style = graph_style(ss);
92 cp->lisp_graph_style = graph_style(ss);
93 cp->transform_graph_style = graph_style(ss);
94 cp->graphs_horizontal = graphs_horizontal(ss);
95 cp->dot_size = dot_size(ss);
96 cp->grid_density = grid_density(ss);
97 cp->x_axis_style = x_axis_style(ss);
98 cp->beats_per_minute = beats_per_minute(ss);
99 cp->beats_per_measure = beats_per_measure(ss);
100 cp->show_axes = show_axes(ss);
101 cp->graph_time_on = true; /* the default state (button is set when we start) */
102 cp->graph_transform_on = false;
103 cp->printing = NOT_PRINTING;
104 cp->waiting_to_make_graph = false;
105 cp->new_peaks = false;
106 cp->sonogram_data = NULL;
107 cp->lisp_info = NULL;
108 cp->amp_control = NULL;
109 cp->hookable = WITH_HOOK;
110 cp->cx = 0;
111 cp->cy = 0;
112 cp->fft_cx = 0;
113 cp->selection_transform_size = 0;
114 if (cp->last_sonogram)
115 {
116 free(cp->last_sonogram);
117 cp->last_sonogram = NULL;
118 }
119 if (cp->last_wavogram)
120 {
121 free(cp->last_wavogram);
122 cp->last_wavogram = NULL;
123 }
124 if (cp->inset_graph)
125 clear_inset_graph(cp);
126 cp->active = CHANNEL_INITIALIZED;
127 return(cp);
128 }
129
130
free_chan_info(chan_info * cp)131 static chan_info *free_chan_info(chan_info *cp)
132 {
133 /* this does not free the associated widgets -- they are merely unmanaged */
134
135 cp->active = CHANNEL_INACTIVE;
136 /* need an indication right away that this channel is being deleted -- during free_snd_info (close-sound),
137 * an error may occur (an edit list temp file might have vanished for example), and normally Snd
138 * attempts to post an error message in the sound's status area. To force this out, we have to
139 * call XmUpdate or equivalent, which can cause all the sound's channels to attempt to redisplay;
140 * since the one causing the error is half-deallocated, trouble can ensue. So both the channel
141 * and the sound have "active" flags that are true only when everything is ship-shape.
142 */
143 chan_info_cleanup(cp);
144 cp->squelch_update = true;
145 cp->axis = free_axis_info(cp->axis);
146 if (cp->fft) cp->fft = free_fft_info(cp->fft);
147 cp_free_fft_state(cp);
148 cp->graph_transform_on = false;
149 cp->printing = NOT_PRINTING;
150 cp->graph_time_on = true;
151 if (cp->edits) free_edit_list(cp);
152 if (cp->sounds) free_sound_list(cp);
153 free_channel_mixes(cp);
154 cp->sound = NULL; /* a backpointer */
155 cp->cursor_on = false;
156 cp->cursor_visible = false;
157 cp->fft_cursor_visible = false;
158 cp->show_sonogram_cursor = false;
159 cp->selection_visible = false;
160 if (cp->amp_control)
161 {
162 /* not sure this is the right thing */
163 free(cp->amp_control);
164 cp->amp_control = NULL;
165 }
166 if (Xen_is_procedure(cp->cursor_proc))
167 {
168 snd_unprotect_at(cp->cursor_proc_loc);
169 cp->cursor_proc = Xen_undefined;
170 cp->cursor_proc_loc = NOT_A_GC_LOC;
171 }
172 if (Xen_is_vector(cp->properties)) /* using vector as node for GC */
173 Xen_vector_set(cp->properties, 0, Xen_empty_list);
174 cp->waiting_to_make_graph = false;
175 if (cp->sonogram_data) free_sono_info(cp);
176 if (cp->temp_sonogram)
177 {
178 /* special case -- background fft process never got a chance to run */
179 if (cp->temp_sonogram == cp->last_sonogram) cp->last_sonogram = NULL;
180 free_sonogram_fft_state(cp->temp_sonogram);
181 free(cp->temp_sonogram);
182 cp->temp_sonogram = NULL;
183 }
184 if (cp->last_sonogram)
185 {
186 free_sonogram_fft_state(cp->last_sonogram);
187 free(cp->last_sonogram);
188 cp->last_sonogram = NULL;
189 }
190 if (cp->last_wavogram)
191 {
192 free(cp->last_wavogram);
193 cp->last_wavogram = NULL;
194 }
195 if (cp->lisp_info)
196 {
197 free_lisp_info(cp);
198 cp->lisp_info = NULL;
199 }
200 cp->graph_lisp_on = false;
201 cp->selection_transform_size = 0;
202
203 if (cp->as_one_edit_positions)
204 {
205 free(cp->as_one_edit_positions);
206 cp->as_one_edit_positions = NULL;
207 cp->as_one_edit_positions_size = 0;
208 }
209
210 if (Xen_is_hook(cp->edit_hook))
211 {
212 Xen_clear_hook_list(cp->edit_hook);
213 snd_unprotect_at(cp->edit_hook_loc);
214 cp->edit_hook = Xen_false;
215 cp->edit_hook_loc = NOT_A_GC_LOC;
216 }
217 if (Xen_is_hook(cp->after_edit_hook))
218 {
219 Xen_clear_hook_list(cp->after_edit_hook);
220 snd_unprotect_at(cp->after_edit_hook_loc);
221 cp->after_edit_hook = Xen_false;
222 cp->after_edit_hook_loc = NOT_A_GC_LOC;
223 }
224 if (Xen_is_hook(cp->undo_hook))
225 {
226 Xen_clear_hook_list(cp->undo_hook);
227 snd_unprotect_at(cp->undo_hook_loc);
228 cp->undo_hook = Xen_false;
229 cp->undo_hook_loc = NOT_A_GC_LOC;
230 }
231 if (cp->inset_graph)
232 clear_inset_graph(cp);
233
234 return(cp); /* pointer is left for possible future re-use */
235 }
236
237
make_basic_snd_info(int chans)238 snd_info *make_basic_snd_info(int chans)
239 {
240 snd_info *sp;
241 sp = (snd_info *)calloc(1, sizeof(snd_info));
242 sp->chans = (chan_info **)calloc(chans, sizeof(chan_info *));
243 sp->allocated_chans = chans;
244 sp->properties = Xen_false; /* will be a vector of 1 element if it's ever used */
245 sp->properties_loc = NOT_A_GC_LOC;
246 #if USE_NO_GUI
247 sp->widgets = false; /* it's a bool if no gui */
248 #endif
249 return(sp);
250 }
251
252
initialize_control_panel(snd_info * sp)253 void initialize_control_panel(snd_info *sp)
254 {
255 sp->expand_control = DEFAULT_EXPAND_CONTROL;
256 sp->expand_control_min = expand_control_min(ss);
257 sp->expand_control_max = expand_control_max(ss);
258 sp->last_expand_control = 0.0;
259 sp->saved_expand_control = 0.0;
260 sp->expand_control_on = DEFAULT_EXPAND_CONTROL_ON;
261 sp->amp_control = DEFAULT_AMP_CONTROL;
262 sp->amp_control_min = amp_control_min(ss);
263 sp->amp_control_max = amp_control_max(ss);
264 sp->last_amp_control = 1.0;
265 sp->saved_amp_control = 1.0;
266 sp->speed_control = fabs(DEFAULT_SPEED_CONTROL);
267 sp->speed_control_min = speed_control_min(ss);
268 sp->speed_control_max = speed_control_max(ss);
269 sp->last_speed_control = 1.0;
270 sp->saved_speed_control = 1.0;
271 if (DEFAULT_SPEED_CONTROL > 0.0) sp->speed_control_direction = 1; else sp->speed_control_direction = -1;
272 sp->contrast_control_on = DEFAULT_CONTRAST_CONTROL_ON;
273 sp->contrast_control = DEFAULT_CONTRAST_CONTROL;
274 sp->contrast_control_min = contrast_control_min(ss);
275 sp->contrast_control_max = contrast_control_max(ss);
276 sp->contrast_control_amp = contrast_control_amp(ss);
277 sp->last_contrast_control = contrast_control_min(ss);
278 sp->saved_contrast_control = contrast_control_min(ss);
279 sp->reverb_control_on = DEFAULT_REVERB_CONTROL_ON;
280 sp->filter_control_on = DEFAULT_FILTER_CONTROL_ON;
281 sp->expand_control_length = expand_control_length(ss);
282 sp->expand_control_ramp = expand_control_ramp(ss);
283 sp->expand_control_hop = expand_control_hop(ss);
284 sp->expand_control_jitter = expand_control_jitter(ss);
285 sp->reverb_control_feedback = reverb_control_feedback(ss);
286 sp->reverb_control_lowpass = reverb_control_lowpass(ss);
287 sp->reverb_control_scale = DEFAULT_REVERB_CONTROL_SCALE;
288 sp->reverb_control_scale_min = reverb_control_scale_min(ss);
289 sp->reverb_control_scale_max = reverb_control_scale_max(ss);
290 sp->reverb_control_decay = reverb_control_decay(ss);
291 sp->speed_control_tones = speed_control_tones(ss);
292 sp->speed_control_style = speed_control_style(ss);
293 sp->speed_control_numerator = 1;
294 sp->speed_control_denominator = 1;
295 sp->last_reverb_control_scale = 0.0;
296 sp->saved_reverb_control_scale = 0.0;
297 sp->reverb_control_length = DEFAULT_REVERB_CONTROL_LENGTH;
298 sp->reverb_control_length_min = reverb_control_length_min(ss);
299 sp->reverb_control_length_max = reverb_control_length_max(ss);
300 sp->last_reverb_control_length = 0.0;
301 sp->saved_reverb_control_length = 0.0;
302 sp->filter_control_order = filter_control_order(ss);
303 sp->filter_control_in_dB = filter_control_in_dB(ss);
304 sp->filter_control_in_hz = filter_control_in_hz(ss);
305 if (sp->filter_control_in_hz)
306 sp->filter_control_xmax = (mus_float_t)(snd_srate(sp) / 2);
307 else sp->filter_control_xmax = 1.0;
308 sp->filter_control_changed = false;
309 sp->saved_controls = NULL;
310 }
311
312
make_snd_info(snd_info * sip,const char * filename,file_info * hdr,int snd_slot,read_only_t read_only)313 snd_info *make_snd_info(snd_info *sip, const char *filename, file_info *hdr, int snd_slot, read_only_t read_only)
314 {
315 snd_info *sp = NULL;
316 int chans, i;
317 /* assume file has been found and header read before reaching us */
318 /* if a reused pointer, may need to extend current chans array */
319 chans = hdr->chans;
320 if (!sip)
321 {
322 sp = make_basic_snd_info(chans);
323 }
324 else
325 {
326 sp = sip;
327 if (sp->allocated_chans < chans)
328 {
329 sp->chans = (chan_info **)realloc(sp->chans, chans * sizeof(chan_info *));
330 for (i = sp->allocated_chans; i < chans; i++) sp->chans[i] = NULL;
331 sp->allocated_chans = chans;
332 }
333 }
334 sp->user_read_only = read_only; /* need to be sure this is set before any hooks run */
335 sp->bomb_in_progress = false;
336 sp->index = snd_slot;
337 sp->nchans = chans;
338 sp->hdr = hdr;
339 sp->inuse = SOUND_NORMAL;
340 sp->filename = mus_strdup(filename);
341 sp->short_filename = filename_without_directory(sp->filename); /* a pointer into filename, not a new string */
342 sp->sync = DEFAULT_SYNC;
343 sp->previous_sync = sp->sync;
344 initialize_control_panel(sp);
345 sp->selectpos = -1;
346
347 if (chans > 1)
348 {
349 if (ss->update_sound_channel_style != NOT_A_CHANNEL_STYLE)
350 {
351 sp->channel_style = ss->update_sound_channel_style;
352 ss->update_sound_channel_style = NOT_A_CHANNEL_STYLE;
353 }
354 else sp->channel_style = channel_style(ss);
355 }
356 else sp->channel_style = CHANNELS_SEPARATE;
357
358 sp->selected_channel = NO_SELECTION;
359 sp->playing = 0;
360 sp->applying = false;
361 sp->lacp = NULL;
362 sp->delete_me = NULL;
363 sp->name_string = NULL;
364 sp->active = true;
365 return(sp);
366 }
367
368
free_snd_info(snd_info * sp)369 void free_snd_info(snd_info *sp)
370 {
371 uint32_t i;
372
373 #if (!USE_NO_GUI)
374 env_editor *edp;
375
376 /* make sure trough colors are ok upon reuse */
377 if (sp->reverb_control_on != DEFAULT_REVERB_CONTROL_ON)
378 toggle_reverb_button(sp, DEFAULT_REVERB_CONTROL_ON);
379 if (sp->expand_control_on != DEFAULT_EXPAND_CONTROL_ON)
380 toggle_expand_button(sp, DEFAULT_EXPAND_CONTROL_ON);
381 if (sp->contrast_control_on != DEFAULT_CONTRAST_CONTROL_ON)
382 toggle_contrast_button(sp, DEFAULT_CONTRAST_CONTROL_ON);
383
384 edp = sp->flt;
385 if (edp)
386 {
387 edp->edited = false;
388 edp->env_dragged = false;
389 edp->env_pos = 0;
390 edp->click_to_delete = false;
391 }
392 set_filter_text(sp, "");
393 #endif
394
395 /* leave most for reuse as in free_chan_info */
396 sp->active = false;
397 sp->selectpos = -1;
398 sp->sync = 0;
399 snd_info_cleanup(sp);
400 sp->previous_sync = sp->sync;
401 for (i = 0; i < sp->nchans; i++)
402 if (sp->chans[i])
403 sp->chans[i] = free_chan_info(sp->chans[i]);
404 sp->inuse = SOUND_IDLE;
405 sp->playing = 0;
406 sp->bomb_in_progress = false;
407 sp->applying = false;
408 sp->channel_style = CHANNELS_SEPARATE;
409 sp->user_read_only = FILE_READ_WRITE;
410 sp->file_read_only = FILE_READ_WRITE;
411 sp->need_update = false;
412 sp->file_unreadable = false;
413 if (Xen_is_vector(sp->properties)) /* using vector as node for GC */
414 Xen_vector_set(sp->properties, 0, Xen_empty_list);
415 sp->selected_channel = NO_SELECTION;
416 sp->short_filename = NULL; /* was a pointer into filename */
417 if (sp->filename) free(sp->filename);
418 sp->filename = NULL;
419 if (sp->filter_control_envelope) sp->filter_control_envelope = free_env(sp->filter_control_envelope);
420 if (sp->saved_controls) free_controls(sp);
421 sp->delete_me = NULL;
422 if (sp->name_string) free(sp->name_string);
423 sp->name_string = NULL;
424 sp->lacp = NULL;
425 sp->hdr = free_file_info(sp->hdr);
426 if (sp->edited_region) clear_region_backpointer(sp);
427 clear_players();
428 reflect_mix_change(ANY_MIX_ID);
429
430 if (Xen_hook_has_list(ss->effects_hook))
431 run_hook(ss->effects_hook, Xen_empty_list, S_effects_hook);
432 }
433
434
completely_free_snd_info(snd_info * sp)435 snd_info *completely_free_snd_info(snd_info *sp)
436 {
437 int i;
438
439 free_snd_info(sp);
440 for (i = 0; i < sp->allocated_chans; i++)
441 {
442 chan_info *cp;
443 cp = sp->chans[i];
444 if (cp)
445 {
446 if (Xen_is_vector(cp->properties))
447 {
448 snd_unprotect_at(cp->properties_loc);
449 cp->properties_loc = NOT_A_GC_LOC;
450 }
451 if (cp->inset_graph)
452 free_inset_graph(cp);
453
454 cp->active = CHANNEL_FREED;
455 free(cp);
456 /* it's possible to have dangling readers (snd_fd) with pointers to this channel (see note in snd-edits.c under unlist_reader) */
457 }
458 }
459 free(sp->chans);
460 if (Xen_is_vector(sp->properties))
461 {
462 snd_unprotect_at(sp->properties_loc);
463 sp->properties_loc = NOT_A_GC_LOC;
464 }
465 free(sp);
466 return(NULL);
467 }
468
469
for_each_chan_with_int(void (* func)(chan_info * ncp,int val),int value)470 void for_each_chan_with_int(void (*func)(chan_info *ncp, int val), int value)
471 {
472 int i;
473 for (i = 0; i < ss->max_sounds; i++)
474 {
475 uint32_t j;
476 snd_info *sp;
477 chan_info *cp;
478 sp = ss->sounds[i];
479 if ((sp) && ((sp->inuse == SOUND_NORMAL) || (sp->inuse == SOUND_WRAPPER)))
480 for (j = 0; j < sp->nchans; j++)
481 if ((cp = ((chan_info *)(sp->chans[j]))))
482 (*func)(cp, value);
483 }
484 }
485
486
for_each_chan_with_mus_long_t(void (* func)(chan_info * ncp,mus_long_t val),mus_long_t value)487 void for_each_chan_with_mus_long_t(void (*func)(chan_info *ncp, mus_long_t val), mus_long_t value)
488 {
489 int i;
490 for (i = 0; i < ss->max_sounds; i++)
491 {
492 uint32_t j;
493 snd_info *sp;
494 chan_info *cp;
495 sp = ss->sounds[i];
496 if ((sp) && ((sp->inuse == SOUND_NORMAL) || (sp->inuse == SOUND_WRAPPER)))
497 for (j = 0; j < sp->nchans; j++)
498 if ((cp = ((chan_info *)(sp->chans[j]))))
499 (*func)(cp, value);
500 }
501 }
502
503
for_each_chan_with_bool(void (* func)(chan_info * ncp,bool val),bool value)504 void for_each_chan_with_bool(void (*func)(chan_info *ncp, bool val), bool value)
505 {
506 int i;
507 for (i = 0; i < ss->max_sounds; i++)
508 {
509 uint32_t j;
510 snd_info *sp;
511 chan_info *cp;
512 sp = ss->sounds[i];
513 if ((sp) && ((sp->inuse == SOUND_NORMAL) || (sp->inuse == SOUND_WRAPPER)))
514 for (j = 0; j < sp->nchans; j++)
515 if ((cp = ((chan_info *)(sp->chans[j]))))
516 (*func)(cp, value);
517 }
518 }
519
520
for_each_chan_with_float(void (* func)(chan_info * ncp,mus_float_t val),mus_float_t value)521 void for_each_chan_with_float(void (*func)(chan_info *ncp, mus_float_t val), mus_float_t value)
522 {
523 int i;
524 for (i = 0; i < ss->max_sounds; i++)
525 {
526 uint32_t j;
527 snd_info *sp;
528 chan_info *cp;
529 sp = ss->sounds[i];
530 if ((sp) && ((sp->inuse == SOUND_NORMAL) || (sp->inuse == SOUND_WRAPPER)))
531 for (j = 0; j < sp->nchans; j++)
532 if ((cp = ((chan_info *)(sp->chans[j]))))
533 (*func)(cp, value);
534 }
535 }
536
537
for_each_chan(void (* func)(chan_info * ncp))538 void for_each_chan(void (*func)(chan_info *ncp))
539 {
540 int i;
541 for (i = 0; i < ss->max_sounds; i++)
542 {
543 uint32_t j;
544 snd_info *sp;
545 chan_info *cp;
546 sp = ss->sounds[i];
547 if ((sp) && ((sp->inuse == SOUND_NORMAL) || (sp->inuse == SOUND_WRAPPER)))
548 for (j = 0; j < sp->nchans; j++)
549 if ((cp = ((chan_info *)(sp->chans[j]))))
550 (*func)(cp);
551 }
552 }
553
554
for_each_normal_chan_with_void(void (* func)(chan_info * ncp,void * ptr),void * userptr)555 void for_each_normal_chan_with_void(void (*func)(chan_info *ncp, void *ptr), void *userptr)
556 {
557 int i;
558 for (i = 0; i < ss->max_sounds; i++)
559 {
560 uint32_t j;
561 snd_info *sp;
562 chan_info *cp;
563 sp = ss->sounds[i];
564 if ((sp) && (sp->inuse == SOUND_NORMAL))
565 for (j = 0; j < sp->nchans; j++)
566 if ((cp = ((chan_info *)(sp->chans[j]))))
567 (*func)(cp, userptr);
568 }
569 }
570
571
for_each_normal_chan_with_int(void (* func)(chan_info * ncp,int val),int value)572 void for_each_normal_chan_with_int(void (*func)(chan_info *ncp, int val), int value)
573 {
574 int i;
575 for (i = 0; i < ss->max_sounds; i++)
576 {
577 uint32_t j;
578 snd_info *sp;
579 chan_info *cp;
580 sp = ss->sounds[i];
581 if ((sp) && (sp->inuse == SOUND_NORMAL))
582 for (j = 0; j < sp->nchans; j++)
583 if ((cp = ((chan_info *)(sp->chans[j]))))
584 (*func)(cp, value);
585 }
586 }
587
588
for_each_normal_chan_with_refint(void (* func)(chan_info * ncp,int * val),int * value)589 void for_each_normal_chan_with_refint(void (*func)(chan_info *ncp, int *val), int *value)
590 {
591 int i;
592 for (i = 0; i < ss->max_sounds; i++)
593 {
594 uint32_t j;
595 snd_info *sp;
596 chan_info *cp;
597 sp = ss->sounds[i];
598 if ((sp) && (sp->inuse == SOUND_NORMAL))
599 for (j = 0; j < sp->nchans; j++)
600 if ((cp = ((chan_info *)(sp->chans[j]))))
601 (*func)(cp, value);
602 }
603 }
604
605
for_each_normal_chan(void (* func)(chan_info * ncp))606 void for_each_normal_chan(void (*func)(chan_info *ncp))
607 {
608 int i;
609 for (i = 0; i < ss->max_sounds; i++)
610 {
611 uint32_t j;
612 snd_info *sp;
613 chan_info *cp;
614 sp = ss->sounds[i];
615 if ((sp) && (sp->inuse == SOUND_NORMAL))
616 for (j = 0; j < sp->nchans; j++)
617 if ((cp = ((chan_info *)(sp->chans[j]))))
618 (*func)(cp);
619 }
620 }
621
622
for_each_sound_chan_with_int(snd_info * sp,void (* func)(chan_info * ncp,int val1),int value)623 void for_each_sound_chan_with_int(snd_info *sp, void (*func)(chan_info *ncp, int val1), int value)
624 {
625 uint32_t j;
626 chan_info *cp;
627 for (j = 0; j < sp->nchans; j++)
628 if ((cp = sp->chans[j]))
629 (*func)(cp, value);
630 }
631
632
map_over_sound_chans(snd_info * sp,bool (* func)(chan_info * ncp))633 bool map_over_sound_chans(snd_info *sp, bool (*func)(chan_info *ncp))
634 {
635 uint32_t j;
636 bool val = false;
637 chan_info *cp;
638 for (j = 0; j < sp->nchans; j++)
639 if ((cp = sp->chans[j]))
640 {
641 val = (*func)(cp);
642 if (val) return(val);
643 }
644 return(val);
645 }
646
647
for_each_sound_chan(snd_info * sp,void (* func)(chan_info * ncp))648 void for_each_sound_chan(snd_info *sp, void (*func)(chan_info *ncp))
649 {
650 uint32_t j;
651 chan_info *cp;
652 for (j = 0; j < sp->nchans; j++)
653 if ((cp = sp->chans[j]))
654 (*func)(cp);
655 }
656
657
for_each_sound(void (* func)(snd_info * usp))658 void for_each_sound(void (*func)(snd_info *usp))
659 {
660 int i;
661 for (i = 0; i < ss->max_sounds; i++)
662 {
663 snd_info *sp;
664 sp = ss->sounds[i];
665 if ((sp) && (sp->inuse == SOUND_NORMAL))
666 (*func)(sp);
667 }
668 }
669
670
for_each_sound_with_void(void (* func)(snd_info * usp,void * ptr),void * userptr)671 void for_each_sound_with_void(void (*func)(snd_info *usp, void *ptr), void *userptr)
672 {
673 int i;
674 for (i = 0; i < ss->max_sounds; i++)
675 {
676 snd_info *sp;
677 sp = ss->sounds[i];
678 if ((sp) && (sp->inuse == SOUND_NORMAL))
679 (*func)(sp, userptr);
680 }
681 }
682
683
for_each_separate_chan(void (* func)(chan_info * ncp))684 void for_each_separate_chan(void (*func)(chan_info *ncp))
685 {
686 /* used only to lock/unlock panes */
687 int i;
688 for (i = 0; i < ss->max_sounds; i++)
689 {
690 snd_info *sp;
691 sp = ss->sounds[i];
692 if ((sp) && (sp->inuse == SOUND_NORMAL))
693 {
694 if (sp->channel_style != CHANNELS_SEPARATE)
695 (*func)(sp->chans[0]);
696 else for_each_sound_chan(sp, func);
697 }
698 }
699 }
700
701
snd_ok(snd_info * sp)702 bool snd_ok(snd_info *sp)
703 {
704 return((sp) &&
705 (sp->inuse != SOUND_IDLE) &&
706 (sp->active));
707 }
708
709
active_channels(virtual_channels_t count_virtual_channels)710 int active_channels(virtual_channels_t count_virtual_channels)
711 {
712 int chans = 0, i;
713 for (i = 0; i < ss->max_sounds; i++)
714 {
715 snd_info *sp;
716 sp = ss->sounds[i];
717 if (snd_ok(sp) &&
718 (sp->inuse != SOUND_WRAPPER))
719 {
720 if ((count_virtual_channels == WITH_VIRTUAL_CHANNELS) ||
721 (sp->channel_style == CHANNELS_SEPARATE))
722 chans += sp->nchans;
723 else chans++;
724 }
725 }
726 return(chans);
727 }
728
729
730 #define SOUNDS_ALLOC_SIZE 4
731
find_free_sound_slot(int desired_chans)732 int find_free_sound_slot(int desired_chans)
733 {
734 int i, j;
735 snd_info *sp;
736 /* first try to find an unused slot that can accommodate desired_chans (to reduce Widget creation) */
737 if (ss->reloading_updated_file > 0)
738 {
739 /* snd_update should change the underlying slot only when it has to (user increased chans) */
740 sp = ss->sounds[ss->reloading_updated_file - 1];
741 if ((!sp) ||
742 ((sp->inuse == SOUND_IDLE) && (sp->allocated_chans >= desired_chans)))
743 return(ss->reloading_updated_file - 1);
744 }
745 for (i = 0; i < ss->max_sounds; i++)
746 {
747 sp = ss->sounds[i];
748 if ((sp) && (sp->inuse == SOUND_IDLE) && (sp->allocated_chans == desired_chans)) return(i);
749 }
750 for (i = 0; i < ss->max_sounds; i++)
751 {
752 sp = ss->sounds[i];
753 if ((sp) && (sp->inuse == SOUND_IDLE) && (sp->allocated_chans > desired_chans)) return(i);
754 }
755 for (i = 0; i < ss->max_sounds; i++)
756 {
757 sp = ss->sounds[i];
758 if (!sp) return(i);
759 if (sp->inuse == SOUND_IDLE) return(i);
760 }
761 j = ss->max_sounds;
762 ss->max_sounds += SOUNDS_ALLOC_SIZE;
763 ss->sounds = (snd_info **)realloc(ss->sounds, ss->max_sounds * sizeof(snd_info *));
764 for (i = j; i < ss->max_sounds; i++) ss->sounds[i] = NULL;
765 return(j);
766 }
767
768
find_free_sound_slot_for_channel_display(void)769 int find_free_sound_slot_for_channel_display(void)
770 {
771 int i, j;
772 for (i = 0; i < ss->max_sounds; i++)
773 if (!ss->sounds[i]) return(i);
774 j = ss->max_sounds;
775 ss->max_sounds += SOUNDS_ALLOC_SIZE;
776 ss->sounds = (snd_info **)realloc(ss->sounds, ss->max_sounds * sizeof(snd_info *));
777 for (i = j; i < ss->max_sounds; i++) ss->sounds[i] = NULL;
778 return(j);
779 }
780
781
any_active_sound(void)782 static snd_info *any_active_sound(void)
783 {
784 int i;
785 for (i = 0; i < ss->max_sounds; i++)
786 {
787 snd_info *sp;
788 sp = ss->sounds[i];
789 if ((sp) && (sp->inuse == SOUND_NORMAL))
790 return(sp);
791 }
792 return(NULL);
793 }
794
795
selected_sound(void)796 snd_info *selected_sound(void)
797 {
798 if ((ss->selected_sound != NO_SELECTION) &&
799 (snd_ok(ss->sounds[ss->selected_sound])))
800 return(ss->sounds[ss->selected_sound]);
801 ss->selected_sound = NO_SELECTION;
802 return(NULL);
803 }
804
805
any_selected_sound(void)806 snd_info *any_selected_sound(void)
807 {
808 snd_info *sp;
809 sp = selected_sound();
810 if (!sp) sp = any_active_sound();
811 return(sp);
812 }
813
814
any_selected_channel(snd_info * sp)815 chan_info *any_selected_channel(snd_info *sp)
816 {
817 int chan = 0;
818 if (sp->selected_channel != NO_SELECTION)
819 chan = sp->selected_channel;
820 if ((sp->chans[chan]) &&
821 (sp->chans[chan]->active > CHANNEL_INITIALIZED))
822 return(sp->chans[chan]);
823 return(NULL);
824 }
825
826
selected_channel(void)827 chan_info *selected_channel(void)
828 {
829 if (ss->selected_sound != NO_SELECTION)
830 {
831 snd_info *sp;
832 sp = ss->sounds[ss->selected_sound];
833 if ((sp->inuse == SOUND_NORMAL) && (sp->selected_channel != NO_SELECTION))
834 return(sp->chans[sp->selected_channel]);
835 }
836 return(NULL);
837 }
838
839
840 static Xen select_sound_hook;
841 static Xen select_channel_hook;
842 static int current_selectpos = 0;
843
select_sound(snd_info * sp)844 static void select_sound(snd_info *sp)
845 {
846 if ((!sp) || (sp->inuse != SOUND_NORMAL)) return;
847
848 if (Xen_hook_has_list(select_sound_hook))
849 run_hook(select_sound_hook,
850 Xen_list_1(C_int_to_Xen_sound(sp->index)),
851 S_select_sound_hook);
852
853 if (ss->selected_sound != sp->index)
854 {
855 reflect_sound_selection(sp);
856 ss->selected_sound = sp->index;
857 new_active_channel_alert();
858 reflect_save_as_sound_selection(sp->short_filename);
859 }
860 sp->selectpos = current_selectpos++;
861
862 if (Xen_hook_has_list(ss->effects_hook))
863 run_hook(ss->effects_hook, Xen_empty_list, S_effects_hook);
864 }
865
866
color_selected_channel(snd_info * sp)867 chan_info *color_selected_channel(snd_info *sp)
868 {
869 chan_info *ncp;
870 ncp = sp->chans[sp->selected_channel];
871 recolor_graph(ncp, true);
872 ncp->selected = true;
873 update_graph(ncp); /* update any indication of change in selected channel (channel id for example) */
874 return(ncp);
875 }
876
877
select_channel(snd_info * sp,int chan)878 void select_channel(snd_info *sp, int chan)
879 {
880 chan_info *cp;
881
882 if ((!sp) || (sp->inuse != SOUND_NORMAL)) return;
883 cp = selected_channel();
884 if (cp != sp->chans[chan])
885 {
886 chan_info *ncp;
887 sp->selected_channel = chan;
888 select_sound(sp);
889 if (cp)
890 {
891 recolor_graph(cp, false);
892 cp->selected = false;
893 if (sp != cp->sound) cp->sound->selected_channel = NO_SELECTION;
894 update_graph(cp);
895 }
896 if (Xen_hook_has_list(select_channel_hook))
897 run_hook(select_channel_hook,
898 Xen_list_2(C_int_to_Xen_sound(sp->index),
899 C_int_to_Xen_integer(chan)),
900 S_select_channel_hook);
901 ncp = color_selected_channel(sp);
902 goto_graph(ncp);
903 }
904 }
905
906
current_channel(void)907 chan_info *current_channel(void)
908 {
909 snd_info *sp = NULL;
910 if (ss->selected_sound != NO_SELECTION)
911 sp = ss->sounds[ss->selected_sound];
912 else sp = any_active_sound();
913 if (sp) return(any_selected_channel(sp));
914 return(NULL);
915 }
916
917
free_sync_info(sync_info * si)918 sync_info *free_sync_info(sync_info *si)
919 {
920 if (si)
921 {
922 if (si->begs) free(si->begs);
923 si->begs = NULL;
924 if (si->cps) free(si->cps);
925 si->cps = NULL;
926 free(si);
927 }
928 return(NULL);
929 }
930
931
syncd_channels(int sync)932 int syncd_channels(int sync)
933 {
934 if (sync != 0)
935 {
936 int i, chans = 0;
937 snd_info *sp;
938 for (i = 0; i < ss->max_sounds; i++)
939 {
940 sp = ss->sounds[i];
941 if ((sp) &&
942 (sp->inuse == SOUND_NORMAL) &&
943 (sp->sync == sync))
944 chans += sp->nchans;
945 }
946 return(chans);
947 }
948 return(0);
949 }
950
951
snd_sync(int sync)952 sync_info *snd_sync(int sync)
953 {
954 int chans;
955 snd_info *sp;
956 chans = syncd_channels(sync);
957 if (chans > 0)
958 {
959 int i, j;
960 sync_info *si;
961 si = (sync_info *)calloc(1, sizeof(sync_info));
962 si->begs = (mus_long_t *)calloc(chans, sizeof(mus_long_t));
963 si->cps = (chan_info **)calloc(chans, sizeof(chan_info *));
964 si->chans = chans;
965 for (i = 0, j = 0; i < ss->max_sounds; i++)
966 {
967 sp = ss->sounds[i];
968 if ((sp) &&
969 (sp->inuse == SOUND_NORMAL) &&
970 (sp->sync == sync))
971 {
972 uint32_t k;
973 for (k = 0; k < sp->nchans; k++, j++)
974 si->cps[j] = sp->chans[k];
975 }
976 }
977 return(si);
978 }
979 return(NULL);
980 }
981
982
make_simple_sync(chan_info * cp,mus_long_t beg)983 sync_info *make_simple_sync(chan_info *cp, mus_long_t beg)
984 {
985 sync_info *si;
986 si = (sync_info *)calloc(1, sizeof(sync_info));
987 si->chans = 1;
988 si->cps = (chan_info **)calloc(1, sizeof(chan_info *));
989 si->cps[0] = cp;
990 si->begs = (mus_long_t *)calloc(1, sizeof(mus_long_t));
991 si->begs[0] = beg;
992 return(si);
993 }
994
995
sync_to_chan(chan_info * cp)996 sync_info *sync_to_chan(chan_info *cp)
997 {
998 snd_info *sp;
999 sp = cp->sound;
1000 if (sp->sync != 0)
1001 return(snd_sync(sp->sync));
1002 return(make_simple_sync(cp, 0));
1003 }
1004
1005
find_sound(const char * name,int nth)1006 snd_info *find_sound(const char *name, int nth)
1007 {
1008 char *sname;
1009 int i, which = 0;
1010 if (!name) return(NULL);
1011 sname = filename_without_directory(name);
1012 for (i = 0; i < ss->max_sounds; i++)
1013 {
1014 snd_info *sp;
1015 sp = ss->sounds[i];
1016 if ((sp) && (sp->inuse == SOUND_NORMAL))
1017 if ((mus_strcmp(name, sp->short_filename)) ||
1018 (mus_strcmp(name, sp->filename)) ||
1019 (mus_strcmp(sname, sp->short_filename)))
1020 {
1021 if (which == nth) return(sp);
1022 which++;
1023 }
1024 }
1025 return(NULL);
1026 }
1027
1028
g_init_data(void)1029 void g_init_data(void)
1030 {
1031 #define H_select_sound_hook S_select_sound_hook " (snd): called whenever a sound is selected."
1032
1033 #define H_select_channel_hook S_select_channel_hook " (snd chn): called whenever a channel is selected. \
1034 Its arguments are the sound index and the channel number."
1035
1036 select_sound_hook = Xen_define_hook(S_select_sound_hook, "(make-hook 'snd)", 1, H_select_sound_hook);
1037 select_channel_hook = Xen_define_hook(S_select_channel_hook, "(make-hook 'snd 'chn)", 2, H_select_channel_hook);
1038 }
1039
1040