root/sweep/trunk/src/head.c

Revision 691, 21.6 kB (checked in by erikd, 2 years ago)

Remove needless #defines of buffer lengths.

Code had many instances of:

#undef BUF_LEN
#define BUF_LEN 64
char buf[BUF_LEN];
snprintf (buf, BUF_LEN, ....);

which can be replaced with:

char buf[64];
snprintf (buf, sizeof (buf), ....);

which is far cleaner and more difficult to get wrong.

  • 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 #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
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
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
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
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
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
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
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
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
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
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
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
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
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
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   char buf[16];
237
238   snprint_time (buf, sizeof (buf),
239                 frames_to_time (sample->sounddata->format, offset));
240
241   gtk_label_set_text (GTK_LABEL(hctl->pos_label), buf);
242 }
243
244 void
245 hctl_refresh_gain (sw_head_controller * hctl)
246 {
247 }
248
249 static gboolean
250 h_rewind_step (gpointer data)
251 {
252   sw_head * head = (sw_head *)data;
253   sw_sample * sample = head->sample;
254   gint step;
255
256   step = sample->sounddata->format->rate; /* 1 second */
257   head_set_offset (head, head->offset - step);
258
259   return TRUE;
260 }
261
262 static gboolean
263 h_ffwd_step (gpointer data)
264 {
265   sw_head * head = (sw_head *)data;
266   sw_sample * sample = head->sample;
267   gint step;
268
269   step = sample->sounddata->format->rate; /* 1 second */
270   head_set_offset (head, head->offset + step);
271
272   return TRUE;
273 }
274
275 void
276 hctl_rewind_pressed_cb (GtkWidget * widget, gpointer data)
277 {
278   sw_head_controller * hctl = (sw_head_controller *)data;
279   sw_head * head = hctl->head;
280
281   head_init_repeater (head, (GtkFunction)h_rewind_step, head);
282 }
283
284 void
285 hctl_ffwd_pressed_cb (GtkWidget * widget, gpointer data)
286 {
287   sw_head_controller * hctl = (sw_head_controller *)data;
288   sw_head * head = hctl->head;
289
290   head_init_repeater (head, (GtkFunction)h_ffwd_step, head);
291 }
292
293 void
294 hctl_goto_start_cb (GtkWidget * widget, gpointer data)
295 {
296   sw_head_controller * hctl = (sw_head_controller *)data;
297   sw_head * head = hctl->head;
298
299   /*head_set_scrubbing (head, FALSE);*/
300   head_set_offset (head, 0);
301 }
302
303 void
304 hctl_goto_end_cb (GtkWidget * widget, gpointer data)
305 {
306   sw_head_controller * hctl = (sw_head_controller *)data;
307   sw_head * head = hctl->head;
308   sw_sample * sample = head->sample;
309
310   /*head_set_scrubbing (head, FALSE);*/
311   head_set_offset (head, sample->sounddata->nr_frames);
312 }
313
314 void
315 hctl_destroy_cb (GtkWidget * widget, gpointer data)
316 {
317   sw_head_controller * hctl = (sw_head_controller *)data;
318
319   hctl->head->controllers = g_list_remove (hctl->head->controllers, hctl);
320
321   g_free (hctl);
322 }
323
324 void
325 head_controller_set_head (sw_head_controller * hctl, sw_head * head)
326 {
327   sw_head * old_head = hctl->head;
328
329   if (old_head != NULL) {
330     old_head->controllers = g_list_remove (old_head->controllers, hctl);
331   }
332
333   hctl->head = head;
334
335   if (g_list_find (head->controllers, hctl) == 0) {
336     head->controllers = g_list_append (head->controllers, hctl);
337   }
338
339   hctl_refresh_looping (hctl);
340   hctl_refresh_reverse (hctl);
341   hctl_refresh_mute (hctl);
342   hctl_refresh_going (hctl);
343   hctl_refresh_offset (hctl);
344   hctl_refresh_gain (hctl);
345 }
346
347 GtkWidget *
348 head_controller_create (sw_head * head, GtkWidget * window,
349                         sw_head_controller ** hctl_ret)
350 {
351   sw_head_controller * hctl;
352
353   GtkWidget * handlebox;
354   GtkWidget * hbox;
355   GtkWidget * tool_hbox;
356   GtkWidget * frame;
357   GtkWidget * lcdbox;
358   GtkWidget * imagebox;
359   GtkWidget * pixmap;
360   GtkWidget * button;
361   GtkWidget * label;
362
363   GtkStyle * style;
364
365   GtkTooltips * tooltips;
366
367   g_assert (head != NULL);
368
369   hctl = g_malloc0 (sizeof (sw_head_controller));
370   hctl->head = head;
371
372
373   if (head->type == SWEEP_HEAD_RECORD) {
374       style = style_red_grey;
375   } else {
376       style = style_green_grey;
377   }
378  
379     handlebox = gtk_handle_box_new ();
380     /*    gtk_box_pack_start (GTK_BOX (main_vbox), handlebox, FALSE, TRUE, 0);
381     gtk_widget_show (handlebox);
382     */
383    
384     gtk_widget_set_style (handlebox, style);
385
386     g_signal_connect (G_OBJECT (handlebox), "destroy",
387                         G_CALLBACK (hctl_destroy_cb), hctl);
388
389     hbox = gtk_hbox_new (FALSE, 8);
390     gtk_container_add (GTK_CONTAINER (handlebox), hbox);
391     gtk_widget_show (hbox);
392    
393     gtk_widget_set_size_request(hbox, -1, 24);
394
395     frame = gtk_frame_new (NULL);
396     gtk_widget_set_style (frame, style_light_grey);
397     gtk_box_pack_start (GTK_BOX(hbox), frame, TRUE, TRUE, 0);
398     gtk_widget_show (frame);
399
400     lcdbox = gtk_event_box_new ();
401     gtk_widget_set_style (lcdbox, style_LCD);
402     gtk_container_add (GTK_CONTAINER(frame), lcdbox);
403     gtk_widget_show (lcdbox);
404
405     tooltips = gtk_tooltips_new ();
406     gtk_tooltips_set_tip (tooltips, lcdbox,
407                           _("Cursor position (indicator)"), NULL);
408    
409     tool_hbox = gtk_hbox_new (FALSE, 0);
410     gtk_container_add (GTK_CONTAINER(lcdbox), tool_hbox);
411     gtk_widget_show (tool_hbox);
412
413     imagebox = gtk_vbox_new (FALSE, 0);
414     gtk_box_pack_start (GTK_BOX(tool_hbox), imagebox, FALSE, FALSE, 0);
415     gtk_widget_show (imagebox);
416
417     pixmap = create_widget_from_xpm (window, upleft_xpm);
418     gtk_widget_show (pixmap);
419     gtk_box_pack_start (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
420
421     pixmap = create_widget_from_xpm (window, lowleft_xpm);
422     gtk_widget_show (pixmap);
423     gtk_box_pack_end (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
424  
425     label = gtk_label_new ("00:00:00.000");
426     gtk_box_pack_start (GTK_BOX(tool_hbox), label, TRUE, TRUE, 0);
427     gtk_widget_show (label);
428
429     hctl->pos_label = label;
430
431     imagebox = gtk_vbox_new (FALSE, 0);
432     gtk_box_pack_start (GTK_BOX(tool_hbox), imagebox, FALSE, FALSE, 0);
433     gtk_widget_show (imagebox);
434
435     pixmap = create_widget_from_xpm (window, upright_xpm);
436     gtk_widget_show (pixmap);
437     gtk_box_pack_start (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
438
439     pixmap = create_widget_from_xpm (window, lowright_xpm);
440     gtk_widget_show (pixmap);
441     gtk_box_pack_end (GTK_BOX(imagebox), pixmap, FALSE, FALSE, 0);
442
443     tool_hbox = gtk_hbox_new (TRUE, 0);
444     gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0);
445     gtk_widget_show (tool_hbox);
446
447     button = create_pixmap_button (window, playrev_xpm,
448                                    _("Reverse mode (toggle)"),
449                                    style, SW_TOOLBAR_TOGGLE_BUTTON,
450                                    G_CALLBACK (hctl_reverse_toggled_cb), NULL, NULL, hctl);
451
452         g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
453                                                                         0, 0, 0, hctl);
454     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
455                                   head->reverse);
456    
457         g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
458                                                                         0, 0, 0, hctl);
459    
460     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
461     gtk_widget_show (button);
462
463     hctl->reverse_toggle = button;
464
465     button = create_pixmap_button (window, loop_xpm,
466                                    _("Loop mode recording (toggle)"),
467                                    style, SW_TOOLBAR_TOGGLE_BUTTON,
468                                    G_CALLBACK (hctl_loop_toggled_cb), NULL, NULL, hctl);
469     g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
470                                                                         0, 0, 0, hctl);
471     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button),
472                                   head->looping);
473     g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
474                                                                         0, 0, 0, hctl);
475     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
476     gtk_widget_show (button);
477
478     hctl->loop_toggle = button;
479    
480     tool_hbox = gtk_hbox_new (TRUE, 0);
481     gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, TRUE, TRUE, 0);
482     gtk_widget_show (tool_hbox);
483
484     button = create_pixmap_button (window, recpausesel_xpm,
485                                    _("Record into selection"),
486                                    style, SW_TOOLBAR_TOGGLE_BUTTON,
487                                    G_CALLBACK (hctl_record_cb), NULL, NULL, hctl);
488     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
489     gtk_widget_show (button);
490     g_signal_handlers_block_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
491                                                                         0, 0, 0, hctl);
492     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), head->going);
493     g_signal_handlers_unblock_matched (GTK_OBJECT(button), G_SIGNAL_MATCH_DATA, 0,
494                                                                         0, 0, 0, hctl);
495
496     hctl->go_toggle = button;
497
498     button = create_pixmap_button (window, stop_xpm, _("Stop"),
499                                    style, SW_TOOLBAR_BUTTON,
500                                    G_CALLBACK (hctl_record_stop_cb), NULL, NULL, hctl);
501     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
502     gtk_widget_show (button);
503
504
505     tool_hbox = gtk_hbox_new (TRUE, 0);
506     gtk_box_pack_start (GTK_BOX (hbox), tool_hbox, FALSE, TRUE, 0);
507     gtk_widget_show (tool_hbox);
508
509     button
510       = create_pixmap_button (window, prevtrk_xpm,
511                               _("Go to beginning"),
512                               style, SW_TOOLBAR_BUTTON,
513                               G_CALLBACK (hctl_goto_start_cb), NULL, NULL, hctl);
514     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
515     gtk_widget_show (button);
516    
517     /*NOALLOC(button);*/
518    
519     /* Rewind */
520    
521     button
522       = create_pixmap_button (window, rew_xpm, _("Rewind"),
523                               style, SW_TOOLBAR_BUTTON,
524                               NULL,
525                               G_CALLBACK (hctl_rewind_pressed_cb),
526                               G_CALLBACK (hctl_repeater_released_cb), hctl);
527     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
528     gtk_widget_show (button);
529    
530     /*    NOALLOC(button);*/
531    
532     /* Fast forward */
533    
534     button
535       = create_pixmap_button (window, ff_xpm, _("Fast forward"),
536                               style, SW_TOOLBAR_BUTTON,
537                               NULL,
538                               G_CALLBACK (hctl_ffwd_pressed_cb),
539                               G_CALLBACK (hctl_repeater_released_cb),
540                               hctl);
541     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
542     gtk_widget_show (button);
543    
544     /*NOALLOC(button);*/
545    
546     /* End */
547    
548     button
549       = create_pixmap_button (window, nexttrk_xpm,
550                               _("Go to the end"),
551                               style, SW_TOOLBAR_BUTTON,
552                               G_CALLBACK (hctl_goto_end_cb), NULL, NULL, hctl);
553     gtk_box_pack_start (GTK_BOX (tool_hbox), button, FALSE, TRUE, 0);
554     gtk_widget_show (button);
555    
556     /*NOALLOC(button);*/
557
558     head->controllers = g_list_append (head->controllers, hctl);
559
560     *hctl_ret = hctl;
561    
562     return handlebox;
563 }
564
565 /* head functions */
566
567 #define PBOOL(p) ((p) ? "TRUE" : "FALSE" )
568
569 int
570 head_dump (sw_head * head)
571 {
572   printf ("head %p\toffset: %f", head, head->offset);
573   printf ("\tstop:\t%d\n", head->stop_offset);
574   printf ("\tgoing:\t%s\n", PBOOL(head->going));
575   printf ("\trestricted:\t%s\n", PBOOL(head->restricted));
576   printf ("\tlooping:\t%s\n", PBOOL(head->looping));
577   printf ("\tpreviewing:\t%s\n", PBOOL(head->previewing));
578   printf ("\treverse:\t%s\n", PBOOL(head->reverse));
579   printf ("\tmute:\t%s\n", PBOOL(head->mute));
580   printf ("\tgain:\t%f\n", head->gain);
581   printf ("\trate:\t%f\n", head->rate);
582   printf ("\tmix:\t%f\n", head->mix);
583   return 0;
584 }
585
586 sw_head *
587 head_new (sw_sample * sample, sw_head_t head_type)
588 {
589   sw_head * head;
590
591   head = g_malloc0 (sizeof (sw_head));
592
593   head->sample = sample;
594
595   head->head_mutex = g_mutex_new ();
596   head->type = head_type;
597   head->stop_offset = 0;
598   head->offset = 0;
599   head->going = FALSE;
600   head->restricted = FALSE;
601   head->looping = FALSE;
602   head->previewing = FALSE;
603   head->reverse = FALSE;
604   head->mute = FALSE;
605   head->gain = (head->type == SWEEP_HEAD_PLAY ? 0.7 : 1.0);
606   head->rate = 1.0;
607   head->mix = 0.0;
608
609   head->repeater_tag = -1;
610   head->controllers = NULL;
611
612   return head;
613 }
614
615 void
616 head_set_scrubbing (sw_head * h, gboolean scrubbing)
617 {
618   g_mutex_lock (h->head_mutex);
619
620   h->scrubbing = scrubbing;
621
622   g_mutex_unlock (h->head_mutex);
623 }
624
625 void
626 head_set_previewing (sw_head * h, gboolean previewing)
627 {
628   g_mutex_lock (h->head_mutex);
629
630   h->previewing = previewing;
631
632   g_mutex_unlock (h->head_mutex);
633 }
634
635 void
636 head_set_looping (sw_head * h, gboolean looping)
637 {
638   GList * gl;
639   sw_head_controller * hctl;
640
641   g_mutex_lock (h->head_mutex);
642
643   h->looping = looping;
644
645   for (gl = h->controllers; gl; gl = gl->next) {
646     hctl = (sw_head_controller *)gl->data;
647     hctl_refresh_looping (hctl);
648   }
649
650   g_mutex_unlock (h->head_mutex);
651 }
652
653 void
654 head_set_reverse (sw_head * h, gboolean reverse)
655 {
656   GList * gl;
657   sw_head_controller * hctl;
658
659   g_mutex_lock (h->head_mutex);
660
661   h->reverse = reverse;
662
663   for (gl = h->controllers; gl; gl = gl->next) {
664     hctl = (sw_head_controller *)gl->data;
665     hctl_refresh_reverse (hctl);
666   }
667
668   g_mutex_unlock (h->head_mutex);
669 }
670
671 void
672 head_set_mute (sw_head * h, gboolean mute)
673 {
674   GList * gl;
675   sw_head_controller * hctl;
676
677   g_mutex_lock (h->head_mutex);
678
679   h->mute = mute;
680
681   for (gl = h->controllers; gl; gl = gl->next) {
682     hctl = (sw_head_controller *)gl->data;
683     hctl_refresh_mute (hctl);
684   }
685
686   g_mutex_unlock (h->head_mutex); 
687 }
688
689 void
690 head_set_going (sw_head * h, gboolean going)
691 {
692   GList * gl;
693   sw_head_controller * hctl;
694
695   g_mutex_lock (h->head_mutex);
696
697   h->going = going;
698
699   for (gl = h->controllers; gl; gl = gl->next) {
700     hctl = (sw_head_controller *)gl->data;
701     hctl_refresh_going (hctl);
702   }
703
704   g_mutex_unlock (h->head_mutex); 
705 }
706
707 void
708 head_set_restricted (sw_head * h, gboolean restricted)
709 {
710   GList * gl;
711   sw_head_controller * hctl;
712
713   g_mutex_lock (h->head_mutex);
714
715   h->restricted = restricted;
716
717   for (gl = h->controllers; gl; gl = gl->next) {
718     hctl = (sw_head_controller *)gl->data;
719     hctl_refresh_going (hctl);
720   }
721
722   g_mutex_unlock (h->head_mutex); 
723 }
724
725 void
726 head_set_stop_offset (sw_head * h, sw_framecount_t offset)
727 {
728   g_mutex_lock (h->head_mutex);
729
730   h->stop_offset = offset;
731
732   g_mutex_unlock (h->head_mutex); 
733 }
734
735 void
736 head_set_offset (sw_head * h, sw_framecount_t offset)
737 {
738   GList * gl;
739   sw_head_controller * hctl;
740
741   g_mutex_lock (h->head_mutex);
742
743   offset = CLAMP (offset, 0, h->sample->sounddata->nr_frames);
744
745   h->offset = offset;
746
747   for (gl = h->controllers; gl; gl = gl->next) {
748     hctl = (sw_head_controller *)gl->data;
749     hctl_refresh_offset (hctl);
750   }
751
752   if (h == h->sample->rec_head)
753     sample_refresh_rec_marker (h->sample);
754
755   g_mutex_unlock (h->head_mutex); 
756 }
757
758 void
759 head_set_gain (sw_head * h, gfloat gain)
760 {
761   GList * gl;
762   sw_head_controller * hctl;
763
764   g_mutex_lock (h->head_mutex);
765
766   h->gain = gain;
767
768   for (gl = h->controllers; gl; gl = gl->next) {
769     hctl = (sw_head_controller *)gl->data;
770     hctl_refresh_gain (hctl);
771   }
772
773   g_mutex_unlock (h->head_mutex);
774 }
775
776 void
777 head_set_rate (sw_head * h, gfloat rate)
778 {
779   g_mutex_lock (h->head_mutex);
780
781   h->rate = rate;
782
783   g_mutex_unlock (h->head_mutex);
784 }
785
786 void
787 head_set_monitor (sw_head * h, gboolean monitor)
788 {
789   g_mutex_lock (h->head_mutex);
790
791   h->monitor = monitor;
792
793   g_mutex_unlock (h->head_mutex);
794
795   sample_update_device (h->sample);
796 }
797
798 static sw_framecount_t
799 head_write_unrestricted (sw_head * head, sw_audio_t * buf,
800                          sw_framecount_t count)
801 {
802   sw_sample * sample = head->sample;
803   sw_sounddata * sounddata = sample->sounddata;
804   sw_format * f = sounddata->format;
805   gpointer d;
806   sw_audio_t * rd;
807   sw_framecount_t i, j, t, b;
808
809   d = sounddata->data +
810     (int)frames_to_bytes (f, head->offset);
811   rd = (sw_audio_t *)d;
812
813   if (head->reverse) {
814     b = 0;
815
816     for (i = 0; i < count; i++) {
817       for (j = 0; j < f->channels; j++) {
818         t = (count-1 - i) * f->channels + j;
819         rd[t] *= head->mix;
820         rd[t] += (buf[b] * head->gain);
821         b++;
822       }
823     }
824
825     head->offset -= count;
826
827   } else {
828     for (i = 0; i < count * f->channels; i++) {
829       rd[i] *= head->mix;
830       rd[i] += (buf[i] * head->gain);
831     }
832
833     head->offset += count;
834
835   }
836
837   return count;
838 }
839
840 sw_framecount_t
841 head_write (sw_head * head, sw_audio_t * buf, sw_framecount_t count)
842 {
843   sw_sample * sample = head->sample;
844   sw_sounddata * sounddata = sample->sounddata;
845   sw_format * f = sounddata->format;
846   sw_framecount_t remaining = count, written = 0, n = 0;
847   GList * gl;
848   sw_sel * sel;
849
850   while (head->restricted && remaining > 0) {
851     g_mutex_lock (sounddata->sels_mutex);
852
853     /* Find selection region that offset is or should be in */
854     if (head->reverse) {
855       for (gl = g_list_last (sounddata->sels); gl; gl = gl->prev) {
856         sel = (sw_sel *)gl->data;
857        
858         if (head->offset > sel->sel_end)
859           head->offset = sel->sel_end;
860        
861         if (head->offset > sel->sel_start) {
862           n = MIN (remaining, head->offset - sel->sel_start);
863           break;
864         }
865       }
866     } else {
867       for (gl = sounddata->sels; gl; gl = gl->next) {
868         sel = (sw_sel *)gl->data;
869        
870         if (head->offset < sel->sel_start)
871           head->offset = sel->sel_start;
872        
873         if (head->offset < sel->sel_end) {
874           n = MIN (remaining, sel->sel_end - head->offset);
875           break;
876         }
877       }
878     }
879
880     g_mutex_unlock (sounddata->sels_mutex);
881
882     if (gl == NULL) {
883       if (head->looping) {
884         head->offset = head->reverse ? sounddata->nr_frames : 0;
885       } else {
886         head->going = FALSE;
887         return written;
888       }
889     } else {
890       written += head_write_unrestricted (head, buf, n);
891       buf += (int)frames_to_samples (f, n);
892       remaining -= n;
893     }
894   }
895
896   if (remaining > 0) {
897     written += head_write_unrestricted (head, buf, remaining);
898   }
899
900   return written;
901 }
Note: See TracBrowser for help on using the browser.