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 <stdlib.h>
28
29 #include <gtk/gtk.h>
30
31 #include <sweep/sweep_i18n.h>
32 #include <sweep/sweep_types.h>
33 #include <sweep/sweep_typeconvert.h>
34 #include "sweep_app.h"
35
36 #include "head.h"
37 #include "callbacks.h"
38 #include "interface.h"
39 #include "print.h"
40 #include "play.h"
41 #include "record.h"
42 #include "sample.h"
43
44 #include "../pixmaps/playrev.xpm"
45 #include "../pixmaps/loop.xpm"
46 #include "../pixmaps/recpausesel.xpm"
47 #include "../pixmaps/stop.xpm"
48 #include "../pixmaps/prevtrk.xpm"
49 #include "../pixmaps/nexttrk.xpm"
50 #include "../pixmaps/ff.xpm"
51 #include "../pixmaps/rew.xpm"
52 #include "../pixmaps/upleft.xpm"
53 #include "../pixmaps/lowleft.xpm"
54 #include "../pixmaps/upright.xpm"
55 #include "../pixmaps/lowright.xpm"
56
57 #define FRAMERATE 10
58
59 extern GtkStyle * style_wb;
60 extern GtkStyle * style_LCD;
61 extern GtkStyle * style_light_grey;
62 extern GtkStyle * style_red_grey;
63 extern GtkStyle * style_green_grey;
64 extern GtkStyle * style_red;
65
66 static void
head_init_repeater(sw_head * head,GtkFunction function,gpointer data)67 head_init_repeater (sw_head * head, GtkFunction function, gpointer data)
68 {
69 function (data);
70
71 g_mutex_lock (head->head_mutex);
72
73 if (head->repeater_tag > 0) {
74 g_source_remove (head->repeater_tag);
75 }
76
77 head->repeater_tag = g_timeout_add ((guint32)1000/FRAMERATE,
78 function, data);
79
80 g_mutex_unlock (head->head_mutex);
81 }
82
83 void
hctl_repeater_released_cb(GtkWidget * widget,gpointer data)84 hctl_repeater_released_cb (GtkWidget * widget, gpointer data)
85 {
86 sw_head_controller * hctl = (sw_head_controller *)data;
87 sw_head * head = hctl->head;
88
89 g_mutex_lock (head->head_mutex);
90
91 if (head->repeater_tag > 0) {
92 g_source_remove (head->repeater_tag);
93 head->repeater_tag = 0;
94 }
95
96 g_mutex_unlock (head->head_mutex);
97 }
98
99 void
hctl_loop_toggled_cb(GtkWidget * widget,gpointer data)100 hctl_loop_toggled_cb (GtkWidget * widget, gpointer data)
101 {
102 sw_head_controller * hctl = (sw_head_controller *)data;
103 sw_head * head = hctl->head;
104 gboolean active;
105
106 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget));
107 head_set_looping (head, active);
108 }
109
110 void
hctl_reverse_toggled_cb(GtkWidget * widget,gpointer data)111 hctl_reverse_toggled_cb (GtkWidget * widget, gpointer data)
112 {
113 sw_head_controller * hctl = (sw_head_controller *)data;
114 sw_head * head = hctl->head;
115 gboolean active;
116
117 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget));
118 head_set_reverse (head, active);
119 }
120
121 void
hctl_reverse_toggle_cb(GtkWidget * widget,gpointer data)122 hctl_reverse_toggle_cb (GtkWidget * widget, gpointer data)
123 {
124 sw_head_controller * hctl = (sw_head_controller *)data;
125 sw_head * head = hctl->head;
126
127 head_set_reverse (head, !head->reverse);
128 }
129
130 void
hctl_mute_toggled_cb(GtkWidget * widget,gpointer data)131 hctl_mute_toggled_cb (GtkWidget * widget, gpointer data)
132 {
133 sw_head_controller * hctl = (sw_head_controller *)data;
134 sw_head * head = hctl->head;
135 gboolean active;
136
137 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget));
138 head_set_mute (head, active);
139 }
140
141 void
hctl_mute_toggle_cb(GtkWidget * widget,gpointer data)142 hctl_mute_toggle_cb (GtkWidget * widget, gpointer data)
143 {
144 sw_head_controller * hctl = (sw_head_controller *)data;
145 sw_head * head = hctl->head;
146
147 head_set_mute (head, !head->mute);
148 }
149
150 void
hctl_record_cb(GtkWidget * widget,gpointer data)151 hctl_record_cb (GtkWidget * widget, gpointer data)
152 {
153 sw_head_controller * hctl = (sw_head_controller *)data;
154 sw_head * head = hctl->head;
155
156 record_cb (widget, head);
157 }
158
159 void
hctl_record_stop_cb(GtkWidget * widget,gpointer data)160 hctl_record_stop_cb (GtkWidget * widget, gpointer data)
161 {
162 sw_head_controller * hctl = (sw_head_controller *)data;
163 sw_head * head = hctl->head;
164
165 stop_recording (head->sample);
166 }
167
168 void
hctl_refresh_looping(sw_head_controller * hctl)169 hctl_refresh_looping (sw_head_controller * hctl)
170 {
171 sw_head * head = hctl->head;
172
173 if (hctl->loop_toggle) {
174 g_signal_handlers_block_matched (GTK_OBJECT(hctl->loop_toggle), G_SIGNAL_MATCH_DATA, 0,
175 0, 0, 0, hctl);
176 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(hctl->loop_toggle),
177 head->looping);
178 g_signal_handlers_unblock_matched (GTK_OBJECT(hctl->loop_toggle), G_SIGNAL_MATCH_DATA, 0,
179 0, 0, 0, hctl);
180 }
181 }
182
183 void
hctl_refresh_reverse(sw_head_controller * hctl)184 hctl_refresh_reverse (sw_head_controller * hctl)
185 {
186 sw_head * head = hctl->head;
187
188 if (hctl->reverse_toggle) {
189 g_signal_handlers_block_matched (GTK_OBJECT(hctl->reverse_toggle), G_SIGNAL_MATCH_DATA, 0,
190 0, 0, 0, hctl);
191
192 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(hctl->reverse_toggle),
193 head->reverse);
194 g_signal_handlers_unblock_matched (GTK_OBJECT(hctl->reverse_toggle), G_SIGNAL_MATCH_DATA, 0,
195 0, 0, 0, hctl);
196 }
197 }
198
199 void
hctl_refresh_mute(sw_head_controller * hctl)200 hctl_refresh_mute (sw_head_controller * hctl)
201 {
202 sw_head * head = hctl->head;
203
204 if (hctl->mute_toggle) {
205 g_signal_handlers_block_matched (GTK_OBJECT(hctl->mute_toggle), G_SIGNAL_MATCH_DATA, 0,
206 0, 0, 0, hctl);
207 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(hctl->mute_toggle),
208 head->mute);
209 g_signal_handlers_unblock_matched (GTK_OBJECT(hctl->mute_toggle), G_SIGNAL_MATCH_DATA, 0,
210 0, 0, 0, hctl);
211 }
212 }
213
214 void
hctl_refresh_going(sw_head_controller * hctl)215 hctl_refresh_going (sw_head_controller * hctl)
216 {
217 sw_head * head = hctl->head;
218
219 if (hctl->go_toggle) {
220 g_signal_handlers_block_matched (GTK_OBJECT(hctl->go_toggle), G_SIGNAL_MATCH_DATA, 0,
221 0, 0, 0, hctl);
222 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(hctl->go_toggle),
223 head->going);
224 g_signal_handlers_unblock_matched (GTK_OBJECT(hctl->go_toggle), G_SIGNAL_MATCH_DATA, 0,
225 0, 0, 0, hctl);
226 }
227 }
228
229 void
hctl_refresh_offset(sw_head_controller * hctl)230 hctl_refresh_offset (sw_head_controller * hctl)
231 {
232 sw_head * head = hctl->head;
233 sw_sample * sample = head->sample;
234 sw_framecount_t offset = head->offset;
235
236 #define BUF_LEN 16
237 char buf[BUF_LEN];
238
239 snprint_time (buf, BUF_LEN,
240 frames_to_time (sample->sounddata->format, offset));
241
242 gtk_label_set_text (GTK_LABEL(hctl->pos_label), buf);
243 }
244
245 void
hctl_refresh_gain(sw_head_controller * hctl)246 hctl_refresh_gain (sw_head_controller * hctl)
247 {
248 }
249
250 static gboolean
h_rewind_step(gpointer data)251 h_rewind_step (gpointer data)
252 {
253 sw_head * head = (sw_head *)data;
254 sw_sample * sample = head->sample;
255 gint step;
256
257 step = sample->sounddata->format->rate; /* 1 second */
258 head_set_offset (head, head->offset - step);
259
260 return TRUE;
261 }
262
263 static gboolean
h_ffwd_step(gpointer data)264 h_ffwd_step (gpointer data)
265 {
266 sw_head * head = (sw_head *)data;
267 sw_sample * sample = head->sample;
268 gint step;
269
270 step = sample->sounddata->format->rate; /* 1 second */
271 head_set_offset (head, head->offset + step);
272
273 return TRUE;
274 }
275
276 void
hctl_rewind_pressed_cb(GtkWidget * widget,gpointer data)277 hctl_rewind_pressed_cb (GtkWidget * widget, gpointer data)
278 {
279 sw_head_controller * hctl = (sw_head_controller *)data;
280 sw_head * head = hctl->head;
281
282 head_init_repeater (head, (GtkFunction)h_rewind_step, head);
283 }
284
285 void
hctl_ffwd_pressed_cb(GtkWidget * widget,gpointer data)286 hctl_ffwd_pressed_cb (GtkWidget * widget, gpointer data)
287 {
288 sw_head_controller * hctl = (sw_head_controller *)data;
289 sw_head * head = hctl->head;
290
291 head_init_repeater (head, (GtkFunction)h_ffwd_step, head);
292 }
293
294 void
hctl_goto_start_cb(GtkWidget * widget,gpointer data)295 hctl_goto_start_cb (GtkWidget * widget, gpointer data)
296 {
297 sw_head_controller * hctl = (sw_head_controller *)data;
298 sw_head * head = hctl->head;
299
300 /*head_set_scrubbing (head, FALSE);*/
301 head_set_offset (head, 0);
302 }
303
304 void
hctl_goto_end_cb(GtkWidget * widget,gpointer data)305 hctl_goto_end_cb (GtkWidget * widget, gpointer data)
306 {
307 sw_head_controller * hctl = (sw_head_controller *)data;
308 sw_head * head = hctl->head;
309 sw_sample * sample = head->sample;
310
311 /*head_set_scrubbing (head, FALSE);*/
312 head_set_offset (head, sample->sounddata->nr_frames);
313 }
314
315 void
hctl_destroy_cb(GtkWidget * widget,gpointer data)316 hctl_destroy_cb (GtkWidget * widget, gpointer data)
317 {
318 sw_head_controller * hctl = (sw_head_controller *)data;
319
320 hctl->head->controllers = g_list_remove (hctl->head->controllers, hctl);
321
322 g_free (hctl);
323 }
324
325 void
head_controller_set_head(sw_head_controller * hctl,sw_head * head)326 head_controller_set_head (sw_head_controller * hctl, sw_head * head)
327 {
328 sw_head * old_head = hctl->head;
329
330 if (old_head != NULL) {
331 old_head->controllers = g_list_remove (old_head->controllers, hctl);
332 }
333
334 hctl->head = head;
335
336 if (g_list_find (head->controllers, hctl) == 0) {
337 head->controllers = g_list_append (head->controllers, hctl);
338 }
339
340 hctl_refresh_looping (hctl);
341 hctl_refresh_reverse (hctl);
342 hctl_refresh_mute (hctl);
343 hctl_refresh_going (hctl);
344 hctl_refresh_offset (hctl);
345 hctl_refresh_gain (hctl);
346 }
347
348 GtkWidget *
head_controller_create(sw_head * head,GtkWidget * window,sw_head_controller ** hctl_ret)349 head_controller_create (sw_head * head, GtkWidget * window,
350 sw_head_controller ** hctl_ret)
351 {
352 sw_head_controller * hctl;
353
354 GtkWidget * handlebox;
355 GtkWidget * hbox;
356 GtkWidget * tool_hbox;
357 GtkWidget * frame;
358 GtkWidget * lcdbox;
359 GtkWidget * imagebox;
360 GtkWidget * pixmap;
361 GtkWidget * button;
362 GtkWidget * label;
363
364 GtkStyle * style;
365
366 GtkTooltips * tooltips;
367
368 g_assert (head != NULL);
369
370 hctl = g_malloc0 (sizeof (sw_head_controller));
371 hctl->head = head;
372
373
374 if (head->type == SWEEP_HEAD_RECORD) {
375 style = style_red_grey;
376 } else {
377 style = style_green_grey;
378 }
379
380 handlebox = gtk_handle_box_new ();
381 /* gtk_box_pack_start (GTK_BOX (main_vbox), handlebox, FALSE, TRUE, 0);
382 gtk_widget_show (handlebox);
383 */
384
385 gtk_widget_set_style (handlebox, style);
386
387 g_signal_connect (G_OBJECT (handlebox), "destroy",
388 G_CALLBACK (hctl_destroy_cb), hctl);
389
390 hbox = gtk_hbox_new (FALSE, 8);
391 gtk_container_add (GTK_CONTAINER (handlebox), hbox);
392 gtk_widget_show (hbox);
393
394 gtk_widget_set_size_request(hbox, -1, 24);
395
396 frame = gtk_frame_new (NULL);
397 gtk_widget_set_style (frame, style_light_grey);
398 gtk_box_pack_start (GTK_BOX(hbox), frame, TRUE, TRUE, 0);
399 gtk_widget_show (frame);
400
401 lcdbox = gtk_event_box_new ();
402 gtk_widget_set_style (lcdbox, style_LCD);
403 gtk_container_add (GTK_CONTAINER(frame), lcdbox);
404 gtk_widget_show (lcdbox);
405
406 tooltips = gtk_tooltips_new ();
407 gtk_tooltips_set_tip (tooltips, lcdbox,
408 _("Cursor position (indicator)"), NULL);
409
410 tool_hbox = gtk_hbox_new (FALSE, 0);
411 gtk_container_add (GTK_CONTAINER(lcdbox), tool_hbox);
412 gtk_widget_show (tool_hbox);
413
414 imagebox = gtk_vbox_new (FALSE, 0);
415 gtk_box_pack_start (GTK_BOX(tool_hbox), imagebox, FALSE, FALSE, 0);
416 gtk_widget_show (imagebox);
417
418 pixmap = create_widget_from_xpm (window, upleft_xpm);
419 gtk_widget_show (pixmap);
420 gtk_box_pack_start (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
421
422 pixmap = create_widget_from_xpm (window, lowleft_xpm);
423 gtk_widget_show (pixmap);
424 gtk_box_pack_end (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
425
426 label = gtk_label_new ("00:00:00.000");
427 gtk_box_pack_start (GTK_BOX(tool_hbox), label, TRUE, TRUE, 0);
428 gtk_widget_show (label);
429
430 hctl->pos_label = label;
431
432 imagebox = gtk_vbox_new (FALSE, 0);
433 gtk_box_pack_start (GTK_BOX(tool_hbox), imagebox, FALSE, FALSE, 0);
434 gtk_widget_show (imagebox);
435
436 pixmap = create_widget_from_xpm (window, upright_xpm);
437 gtk_widget_show (pixmap);
438 gtk_box_pack_start (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
439
440 pixmap = create_widget_from_xpm (window, lowright_xpm);
441 gtk_widget_show (pixmap);
442 gtk_box_pack_end (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
443
444 tool_hbox = gtk_hbox_new (TRUE, 0);
445 gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0);
446 gtk_widget_show (tool_hbox);
447
448 button = create_pixmap_button (window, playrev_xpm,
449 _("Reverse mode (toggle)"),
450 style, SW_TOOLBAR_TOGGLE_BUTTON,
451 G_CALLBACK (hctl_reverse_toggled_cb), NULL, NULL, hctl);
452
453 g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
454 0, 0, 0, hctl);
455 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
456 head->reverse);
457
458 g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
459 0, 0, 0, hctl);
460
461 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
462 gtk_widget_show (button);
463
464 hctl->reverse_toggle = button;
465
466 button = create_pixmap_button (window, loop_xpm,
467 _("Loop mode recording (toggle)"),
468 style, SW_TOOLBAR_TOGGLE_BUTTON,
469 G_CALLBACK (hctl_loop_toggled_cb), NULL, NULL, hctl);
470 g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
471 0, 0, 0, hctl);
472 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
473 head->looping);
474 g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
475 0, 0, 0, hctl);
476 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
477 gtk_widget_show (button);
478
479 hctl->loop_toggle = button;
480
481 tool_hbox = gtk_hbox_new (TRUE, 0);
482 gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, TRUE, TRUE, 0);
483 gtk_widget_show (tool_hbox);
484
485 button = create_pixmap_button (window, recpausesel_xpm,
486 _("Record into selection"),
487 style, SW_TOOLBAR_TOGGLE_BUTTON,
488 G_CALLBACK (hctl_record_cb), NULL, NULL, hctl);
489 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
490 gtk_widget_show (button);
491 #if 0
492 gtk_widget_add_accelerator (button, "clicked", accel_group,
493 GDK_r, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
494 #endif
495 g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
496 0, 0, 0, hctl);
497 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), head->going);
498 g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
499 0, 0, 0, hctl);
500
501 hctl->go_toggle = button;
502
503 button = create_pixmap_button (window, stop_xpm, _("Stop"),
504 style, SW_TOOLBAR_BUTTON,
505 G_CALLBACK (hctl_record_stop_cb), NULL, NULL, hctl);
506 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
507 gtk_widget_show (button);
508
509
510 tool_hbox = gtk_hbox_new (TRUE, 0);
511 gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0);
512 gtk_widget_show (tool_hbox);
513
514 button
515 = create_pixmap_button (window, prevtrk_xpm,
516 _("Go to beginning"),
517 style, SW_TOOLBAR_BUTTON,
518 G_CALLBACK (hctl_goto_start_cb), NULL, NULL, hctl);
519 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
520 gtk_widget_show (button);
521
522 /*NOALLOC(button);*/
523
524 /* Rewind */
525
526 button
527 = create_pixmap_button (window, rew_xpm, _("Rewind"),
528 style, SW_TOOLBAR_BUTTON,
529 NULL,
530 G_CALLBACK (hctl_rewind_pressed_cb),
531 G_CALLBACK (hctl_repeater_released_cb), hctl);
532 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
533 gtk_widget_show (button);
534
535 /* NOALLOC(button);*/
536
537 /* Fast forward */
538
539 button
540 = create_pixmap_button (window, ff_xpm, _("Fast forward"),
541 style, SW_TOOLBAR_BUTTON,
542 NULL,
543 G_CALLBACK (hctl_ffwd_pressed_cb),
544 G_CALLBACK (hctl_repeater_released_cb),
545 hctl);
546 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
547 gtk_widget_show (button);
548
549 /*NOALLOC(button);*/
550
551 /* End */
552
553 button
554 = create_pixmap_button (window, nexttrk_xpm,
555 _("Go to the end"),
556 style, SW_TOOLBAR_BUTTON,
557 G_CALLBACK (hctl_goto_end_cb), NULL, NULL, hctl);
558 gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
559 gtk_widget_show (button);
560
561 /*NOALLOC(button);*/
562
563 head->controllers = g_list_append (head->controllers, hctl);
564
565 *hctl_ret = hctl;
566
567 return handlebox;
568 }
569
570 /* head functions */
571
572 #define PBOOL(p) ((p) ? "TRUE" : "FALSE" )
573
574 int
head_dump(sw_head * head)575 head_dump (sw_head * head)
576 {
577 printf ("head %p\toffset: %f", head, head->offset);
578 printf ("\tstop:\t%d\n", head->stop_offset);
579 printf ("\tgoing:\t%s\n", PBOOL(head->going));
580 printf ("\trestricted:\t%s\n", PBOOL(head->restricted));
581 printf ("\tlooping:\t%s\n", PBOOL(head->looping));
582 printf ("\tpreviewing:\t%s\n", PBOOL(head->previewing));
583 printf ("\treverse:\t%s\n", PBOOL(head->reverse));
584 printf ("\tmute:\t%s\n", PBOOL(head->mute));
585 printf ("\tgain:\t%f\n", head->gain);
586 printf ("\trate:\t%f\n", head->rate);
587 printf ("\tmix:\t%f\n", head->mix);
588 return 0;
589 }
590
591 sw_head *
head_new(sw_sample * sample,sw_head_t head_type)592 head_new (sw_sample * sample, sw_head_t head_type)
593 {
594 sw_head * head;
595
596 head = g_malloc0 (sizeof (sw_head));
597
598 head->sample = sample;
599
600 head->head_mutex = g_mutex_new ();
601 head->type = head_type;
602 head->stop_offset = 0;
603 head->offset = 0;
604 head->going = FALSE;
605 head->restricted = FALSE;
606 head->looping = FALSE;
607 head->previewing = FALSE;
608 head->reverse = FALSE;
609 head->mute = FALSE;
610 head->gain = (head->type == SWEEP_HEAD_PLAY ? 0.7 : 1.0);
611 head->rate = 1.0;
612 head->mix = 0.0;
613
614 head->repeater_tag = -1;
615 head->controllers = NULL;
616
617 return head;
618 }
619
620 void
head_set_scrubbing(sw_head * h,gboolean scrubbing)621 head_set_scrubbing (sw_head * h, gboolean scrubbing)
622 {
623 g_mutex_lock (h->head_mutex);
624
625 h->scrubbing = scrubbing;
626
627 g_mutex_unlock (h->head_mutex);
628 }
629
630 void
head_set_previewing(sw_head * h,gboolean previewing)631 head_set_previewing (sw_head * h, gboolean previewing)
632 {
633 g_mutex_lock (h->head_mutex);
634
635 h->previewing = previewing;
636
637 g_mutex_unlock (h->head_mutex);
638 }
639
640 void
head_set_looping(sw_head * h,gboolean looping)641 head_set_looping (sw_head * h, gboolean looping)
642 {
643 GList * gl;
644 sw_head_controller * hctl;
645
646 g_mutex_lock (h->head_mutex);
647
648 h->looping = looping;
649
650 for (gl = h->controllers; gl; gl = gl->next) {
651 hctl = (sw_head_controller *)gl->data;
652 hctl_refresh_looping (hctl);
653 }
654
655 g_mutex_unlock (h->head_mutex);
656 }
657
658 void
head_set_reverse(sw_head * h,gboolean reverse)659 head_set_reverse (sw_head * h, gboolean reverse)
660 {
661 GList * gl;
662 sw_head_controller * hctl;
663
664 g_mutex_lock (h->head_mutex);
665
666 h->reverse = reverse;
667
668 for (gl = h->controllers; gl; gl = gl->next) {
669 hctl = (sw_head_controller *)gl->data;
670 hctl_refresh_reverse (hctl);
671 }
672
673 g_mutex_unlock (h->head_mutex);
674 }
675
676 void
head_set_mute(sw_head * h,gboolean mute)677 head_set_mute (sw_head * h, gboolean mute)
678 {
679 GList * gl;
680 sw_head_controller * hctl;
681
682 g_mutex_lock (h->head_mutex);
683
684 h->mute = mute;
685
686 for (gl = h->controllers; gl; gl = gl->next) {
687 hctl = (sw_head_controller *)gl->data;
688 hctl_refresh_mute (hctl);
689 }
690
691 g_mutex_unlock (h->head_mutex);
692 }
693
694 void
head_set_going(sw_head * h,gboolean going)695 head_set_going (sw_head * h, gboolean going)
696 {
697 GList * gl;
698 sw_head_controller * hctl;
699
700 g_mutex_lock (h->head_mutex);
701
702 h->going = going;
703
704 for (gl = h->controllers; gl; gl = gl->next) {
705 hctl = (sw_head_controller *)gl->data;
706 hctl_refresh_going (hctl);
707 }
708
709 g_mutex_unlock (h->head_mutex);
710 }
711
712 void
head_set_restricted(sw_head * h,gboolean restricted)713 head_set_restricted (sw_head * h, gboolean restricted)
714 {
715 GList * gl;
716 sw_head_controller * hctl;
717
718 g_mutex_lock (h->head_mutex);
719
720 h->restricted = restricted;
721
722 for (gl = h->controllers; gl; gl = gl->next) {
723 hctl = (sw_head_controller *)gl->data;
724 hctl_refresh_going (hctl);
725 }
726
727 g_mutex_unlock (h->head_mutex);
728 }
729
730 void
head_set_stop_offset(sw_head * h,sw_framecount_t offset)731 head_set_stop_offset (sw_head * h, sw_framecount_t offset)
732 {
733 g_mutex_lock (h->head_mutex);
734
735 h->stop_offset = offset;
736
737 g_mutex_unlock (h->head_mutex);
738 }
739
740 void
head_set_offset(sw_head * h,sw_framecount_t offset)741 head_set_offset (sw_head * h, sw_framecount_t offset)
742 {
743 GList * gl;
744 sw_head_controller * hctl;
745
746 g_mutex_lock (h->head_mutex);
747
748 offset = CLAMP (offset, 0, h->sample->sounddata->nr_frames);
749
750 h->offset = offset;
751
752 for (gl = h->controllers; gl; gl = gl->next) {
753 hctl = (sw_head_controller *)gl->data;
754 hctl_refresh_offset (hctl);
755 }
756
757 if (h == h->sample->rec_head)
758 sample_refresh_rec_marker (h->sample);
759
760 g_mutex_unlock (h->head_mutex);
761 }
762
763 void
head_set_gain(sw_head * h,gfloat gain)764 head_set_gain (sw_head * h, gfloat gain)
765 {
766 GList * gl;
767 sw_head_controller * hctl;
768
769 g_mutex_lock (h->head_mutex);
770
771 h->gain = gain;
772
773 for (gl = h->controllers; gl; gl = gl->next) {
774 hctl = (sw_head_controller *)gl->data;
775 hctl_refresh_gain (hctl);
776 }
777
778 g_mutex_unlock (h->head_mutex);
779 }
780
781 void
head_set_rate(sw_head * h,gfloat rate)782 head_set_rate (sw_head * h, gfloat rate)
783 {
784 g_mutex_lock (h->head_mutex);
785
786 h->rate = rate;
787
788 g_mutex_unlock (h->head_mutex);
789 }
790
791 void
head_set_monitor(sw_head * h,gboolean monitor)792 head_set_monitor (sw_head * h, gboolean monitor)
793 {
794 g_mutex_lock (h->head_mutex);
795
796 h->monitor = monitor;
797
798 g_mutex_unlock (h->head_mutex);
799
800 sample_update_device (h->sample);
801 }
802
803 static sw_framecount_t
head_write_unrestricted(sw_head * head,sw_audio_t * buf,sw_framecount_t count)804 head_write_unrestricted (sw_head * head, sw_audio_t * buf,
805 sw_framecount_t count)
806 {
807 sw_sample * sample = head->sample;
808 sw_sounddata * sounddata = sample->sounddata;
809 sw_format * f = sounddata->format;
810 gpointer d;
811 sw_audio_t * rd;
812 sw_framecount_t i, j, t, b;
813
814 d = sounddata->data +
815 (int)frames_to_bytes (f, head->offset);
816 rd = (sw_audio_t *)d;
817
818 if (head->reverse) {
819 b = 0;
820
821 for (i = 0; i < count; i++) {
822 for (j = 0; j < f->channels; j++) {
823 t = (count-1 - i) * f->channels + j;
824 rd[t] *= head->mix;
825 rd[t] += (buf[b] * head->gain);
826 b++;
827 }
828 }
829
830 head->offset -= count;
831
832 } else {
833 for (i = 0; i < count * f->channels; i++) {
834 rd[i] *= head->mix;
835 rd[i] += (buf[i] * head->gain);
836 }
837
838 head->offset += count;
839
840 }
841
842 return count;
843 }
844
845 sw_framecount_t
head_write(sw_head * head,sw_audio_t * buf,sw_framecount_t count)846 head_write (sw_head * head, sw_audio_t * buf, sw_framecount_t count)
847 {
848 sw_sample * sample = head->sample;
849 sw_sounddata * sounddata = sample->sounddata;
850 sw_format * f = sounddata->format;
851 sw_framecount_t remaining = count, written = 0, n = 0;
852 GList * gl;
853 sw_sel * sel;
854
855 while (head->restricted && remaining > 0) {
856 g_mutex_lock (sounddata->sels_mutex);
857
858 /* Find selection region that offset is or should be in */
859 if (head->reverse) {
860 for (gl = g_list_last (sounddata->sels); gl; gl = gl->prev) {
861 sel = (sw_sel *)gl->data;
862
863 if (head->offset > sel->sel_end)
864 head->offset = sel->sel_end;
865
866 if (head->offset > sel->sel_start) {
867 n = MIN (remaining, head->offset - sel->sel_start);
868 break;
869 }
870 }
871 } else {
872 for (gl = sounddata->sels; gl; gl = gl->next) {
873 sel = (sw_sel *)gl->data;
874
875 if (head->offset < sel->sel_start)
876 head->offset = sel->sel_start;
877
878 if (head->offset < sel->sel_end) {
879 n = MIN (remaining, sel->sel_end - head->offset);
880 break;
881 }
882 }
883 }
884
885 g_mutex_unlock (sounddata->sels_mutex);
886
887 if (gl == NULL) {
888 if (head->looping) {
889 head->offset = head->reverse ? sounddata->nr_frames : 0;
890 } else {
891 head->going = FALSE;
892 return written;
893 }
894 } else {
895 written += head_write_unrestricted (head, buf, n);
896 buf += (int)frames_to_samples (f, n);
897 remaining -= n;
898 }
899 }
900
901 if (remaining > 0) {
902 written += head_write_unrestricted (head, buf, remaining);
903 }
904
905 return written;
906 }
907