root/sweep/trunk/src/sweep_sample.c

Revision 702, 43.0 kB (checked in by erikd, 2 years ago)

src/sweep_sample.c : Revert more leak fixes.

GTK+ is the suck. These g_list_free() calls cause segfaults and GTK+ memory
management code problems.

  • 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 <glib.h>
30 #include <gdk/gdkkeysyms.h>
31 #include <gtk/gtk.h>
32
33 #include <sweep/sweep_i18n.h>
34 #include <sweep/sweep_sample.h>
35 #include <sweep/sweep_typeconvert.h>
36 #include <sweep/sweep_sounddata.h>
37 #include <sweep/sweep_selection.h>
38 #include <sweep/sweep_undo.h>
39
40 #include "sample.h" /* app internal functions for samples */
41
42 #include "format.h"
43 #include "print.h"
44 #include "view.h"
45 #include "sample-display.h"
46 #include "play.h"
47 #include "undo_dialog.h"
48 #include "head.h"
49 #include "interface.h"
50 #include "preferences.h"
51 #include "record.h"
52 #include "question_dialogs.h"
53 #include "sw_chooser.h"
54
55 #include "../pixmaps/new.xpm"
56
57 /* Defaults for new files */
58 #define DEFAULT_DURATION "00:01:00.000"
59 #define DEFAULT_SAMPLERATE 44100
60 #define DEFAULT_CHANNELS 2
61
62 /* Preferences keys for "new file" remembered values */
63 #define SAMPLERATE_KEY "NewFile_Samplerate"
64 #define CHANNELS_KEY "NewFile_Channels"
65
66 /*#define DEBUG*/
67
68 extern sw_view * last_tmp_view;
69
70 static GList * sample_bank = NULL;
71
72 static int untitled_count = 0;
73
74 static void
75 sample_info_update (sw_sample * sample);
76
77 /* Sample functions */
78
79 void
80 sample_add_view (sw_sample * s, sw_view * v)
81 {
82  s->views = g_list_append(s->views, v);
83 }
84
85 void
86 sample_remove_view (sw_sample * s, sw_view * v)
87 {
88  s->views = g_list_remove(s->views, v);
89
90  if(!s->views) {
91    sample_bank_remove(s);
92  }
93 }
94
95 /*
96  * filename_color_hash
97  *
98  * Choose colour for this file based on the filename, such that
99  * a file is loaded with the same colour each time it is edited.
100  *
101  * Idea due to Erik de Castro Lopo
102  */
103 static int
104 filename_color_hash (char * filename)
105 {
106   char *p;
107   int i = 0;
108
109   if (filename == NULL) return 0;
110
111   for (p = filename; *p; p++) i += (int)*p;
112
113   return (i % VIEW_COLOR_DEFAULT_MAX);
114 }
115
116 static gchar *
117 filename_generate (void)
118 {
119   return g_strdup_printf ("%s-%d.aiff", _("Untitled"), ++untitled_count);
120 }
121
122 sw_sample *
123 sample_new_empty(gchar * pathname,
124                  gint nr_channels, gint sample_rate,
125                  sw_framecount_t sample_length)
126 {
127   sw_sample *s;
128
129   s = g_malloc0 (sizeof(sw_sample));
130   if (!s)
131     return NULL;
132
133   s->sounddata = sounddata_new_empty (nr_channels, sample_rate, sample_length);
134
135   s->views = NULL;
136
137   if (pathname != NULL)
138     s->pathname = strdup (pathname);
139   else
140     s->pathname = filename_generate ();
141
142   s->ops_thread = (pthread_t) -1;
143
144   s->ops_mutex = g_mutex_new ();
145   s->registered_ops = NULL;
146   s->current_undo = NULL;
147   s->current_redo = NULL;
148   s->active_op = NULL;
149   s->op_progress_tag = -1;
150
151   s->tmp_sel = NULL;
152
153   s->playmarker_tag = 0;
154
155   s->edit_mutex = g_mutex_new ();
156   s->edit_mode = SWEEP_EDIT_MODE_READY;
157   s->edit_state = SWEEP_EDIT_STATE_IDLE;
158   s->modified = FALSE;
159
160   s->pending_cond = g_cond_new ();
161   s->pending_ops = NULL;
162
163   s->play_mutex = g_mutex_new ();
164   s->user_offset = 0;
165   s->by_user = 0;
166
167   s->play_head = head_new (s, SWEEP_HEAD_PLAY);
168
169   s->rate = 1.0;
170
171   s->color = filename_color_hash ((gchar *)g_basename (s->pathname));
172
173   s->info_clist = NULL;
174
175   /*  s->recording = FALSE;*/
176   /*  s->rec_offset = 0;*/
177   s->rec_head = NULL;
178
179   s->tmp_message_active = FALSE;
180   s->last_tmp_message = NULL;
181   s->tmp_message_tag = -1;
182   s->progress_ready_tag = -1;
183
184   return s;
185 }
186
187 sw_sample *
188 sample_new_copy(sw_sample * s)
189 {
190   sw_sample * sn;
191
192   sn = sample_new_empty(NULL,
193                         s->sounddata->format->channels,
194                         s->sounddata->format->rate,
195                         s->sounddata->nr_frames);
196
197   if(!sn) {
198     fprintf(stderr, "Unable to allocate new sample.\n");
199     return NULL;
200   }
201
202   memcpy(sn->sounddata->data, s->sounddata->data,
203          frames_to_bytes(s->sounddata->format, s->sounddata->nr_frames));
204
205   sounddata_copyin_selection (s->sounddata, sn->sounddata);
206
207   /*  sn->last_mtime = s->last_mtime;*/
208
209   return sn;
210 }
211
212 static void
213 sample_new_dialog_ok_cb (GtkWidget * widget, gpointer data)
214 {
215   GtkWidget * dialog;
216   GtkWidget * entry;
217   GtkWidget * checkbutton;
218   gchar * filename, * text;
219   gdouble seconds;
220   sw_framecount_t nr_frames;
221   gint nr_channels;
222   gint sample_rate;
223   gboolean rem_format;
224
225   sw_sample * s;
226   sw_view * v;
227
228   dialog = gtk_widget_get_toplevel (widget);
229
230   entry = g_object_get_data (G_OBJECT(dialog), "name_entry");
231   filename = (gchar *) gtk_entry_get_text (GTK_ENTRY(entry));
232
233   entry = g_object_get_data (G_OBJECT(dialog), "duration_entry");
234   text = (gchar *) gtk_entry_get_text (GTK_ENTRY(entry));
235   seconds = strtime_to_seconds (text);
236   if (seconds == -1) goto out; /* XXX: invalid time spec */
237
238   entry = g_object_get_data (G_OBJECT(dialog), "rate_chooser");
239   sample_rate = samplerate_chooser_get_rate (entry);
240
241   entry = g_object_get_data (G_OBJECT(dialog), "channelcount_chooser");
242   nr_channels = channelcount_chooser_get_count (entry);
243
244   nr_frames = (sw_framecount_t) (sample_rate * seconds);
245
246   checkbutton =
247     GTK_WIDGET(g_object_get_data (G_OBJECT(dialog), "rem_format_chb"));
248   rem_format =
249     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(checkbutton));
250
251   if (rem_format) {
252     prefs_set_int (SAMPLERATE_KEY, sample_rate);
253     prefs_set_int (CHANNELS_KEY, nr_channels);
254   }
255
256   s = sample_new_empty ((gchar *)filename, nr_channels, sample_rate, nr_frames);
257   v = view_new_all (s, 1.0);
258   sample_add_view (s, v);
259   sample_bank_add (s);
260
261  out:
262   gtk_widget_destroy (dialog);
263 }
264
265 static void
266 sample_new_dialog_cancel_cb (GtkWidget * widget, gpointer data)
267 {
268   GtkWidget * dialog;
269
270   dialog = gtk_widget_get_toplevel (widget);
271   gtk_widget_destroy (dialog);
272
273   if (sample_bank == NULL) {
274     sweep_quit ();
275   }
276 }
277
278
279 static void
280 sample_new_dialog_update (GtkWidget * widget)
281 {
282   GtkWidget * dialog;
283   GtkWidget * entry;
284   GtkWidget * memsize_label;
285   GtkWidget * ok_button;
286   gchar * text;
287   gdouble seconds;
288   gint sample_rate, nr_channels;
289   glong bytes;
290
291   char buf[16];
292
293   dialog = gtk_widget_get_toplevel (widget);
294
295   entry = g_object_get_data (G_OBJECT(dialog), "duration_entry");
296   text = (gchar *)gtk_entry_get_text (GTK_ENTRY(entry));
297   seconds = strtime_to_seconds (text);
298
299   entry = g_object_get_data (G_OBJECT(dialog), "rate_chooser");
300   sample_rate = samplerate_chooser_get_rate (entry);
301
302   entry = g_object_get_data (G_OBJECT(dialog), "channelcount_chooser");
303   nr_channels = channelcount_chooser_get_count (entry);
304
305   memsize_label = g_object_get_data (G_OBJECT(dialog), "memsize_label");
306
307   bytes = (glong) (seconds * sample_rate * nr_channels * sizeof(sw_audio_t));
308   if (bytes < 0) {
309     gtk_label_set_text (GTK_LABEL(memsize_label), _("Overflow"));
310   } else {
311     snprint_bytes (buf, sizeof (buf), bytes);
312     gtk_label_set_text (GTK_LABEL(memsize_label), buf);
313   }
314
315   ok_button = g_object_get_data (G_OBJECT(dialog), "ok_button");
316
317   if (seconds <= 0.0 || sample_rate <= 0 || nr_channels <= 0 || bytes < 0) {
318     gtk_widget_set_sensitive (ok_button, FALSE);
319   } else {
320     gtk_widget_set_sensitive (ok_button, TRUE);
321   }
322 }
323
324 static void
325 sample_new_dialog_reset_cb (GtkWidget * widget, gpointer data)
326 {
327   GtkWidget * dialog;
328   GtkWidget * entry;
329
330   int * i, sample_rate, nr_channels;
331
332   i = prefs_get_int (SAMPLERATE_KEY);
333   sample_rate = i ? *i : DEFAULT_SAMPLERATE;
334
335   i = prefs_get_int (CHANNELS_KEY);
336   nr_channels = i ? *i : DEFAULT_CHANNELS;
337
338   dialog = gtk_widget_get_toplevel (widget);
339
340   entry = g_object_get_data (G_OBJECT(dialog), "rate_chooser");
341   samplerate_chooser_set_rate (entry, sample_rate);
342
343   entry = g_object_get_data (G_OBJECT(dialog), "channelcount_chooser");
344   channelcount_chooser_set_count (entry, nr_channels);
345
346   sample_new_dialog_update (dialog);
347 }
348
349 static void
350 sample_new_dialog_defaults_cb (GtkWidget * widget, gpointer data)
351 {
352   GtkWidget * dialog;
353   GtkWidget * entry;
354
355   dialog = gtk_widget_get_toplevel (widget);
356
357   entry = g_object_get_data (G_OBJECT(dialog), "duration_entry");
358   gtk_entry_set_text (GTK_ENTRY (entry), DEFAULT_DURATION);
359
360   entry = g_object_get_data (G_OBJECT(dialog), "rate_chooser");
361   samplerate_chooser_set_rate (entry, DEFAULT_SAMPLERATE);
362
363   entry = g_object_get_data (G_OBJECT(dialog), "channelcount_chooser");
364   channelcount_chooser_set_count (entry, DEFAULT_CHANNELS);
365
366   sample_new_dialog_update (dialog);
367 }
368
369 static void
370 create_sample_new_dialog ( gchar * pathname, gint nr_channels, gint sample_rate,
371                           sw_time_t duration, gboolean do_reset)
372 {
373   GtkWidget * dialog;
374   GtkWidget * main_vbox, * vbox;
375   GtkWidget * main_hbox, * hbox, * hbox2;
376   GtkWidget * pixmap;
377   GtkWidget * frame;
378   GtkWidget * ebox;
379   GtkWidget * label;
380   GtkWidget * entry;
381   GtkWidget * button;
382   GtkWidget * checkbutton;
383   GtkWidget * ok_button;
384   GtkTooltips * tooltips;
385
386   gchar buf[16];
387
388   dialog = gtk_dialog_new ();
389   sweep_set_window_icon (GTK_WINDOW(dialog));
390   gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
391   gtk_window_set_title (GTK_WINDOW(dialog), _("Sweep: New file"));
392   /*gtk_container_border_width (GTK_CONTAINER(dialog), 8);*/
393
394   g_signal_connect (G_OBJECT(dialog), "destroy",
395                       G_CALLBACK(sample_new_dialog_cancel_cb), dialog);
396
397   attach_window_close_accel(GTK_WINDOW(dialog));
398
399   main_vbox = GTK_DIALOG(dialog)->vbox;
400
401   main_hbox = gtk_hbox_new (FALSE, 0);
402   gtk_box_pack_start (GTK_BOX(main_vbox), main_hbox, FALSE, FALSE, 0);
403   gtk_widget_show (main_hbox);
404
405   /* Left side */
406
407   vbox = gtk_vbox_new (FALSE, 0);
408   gtk_box_pack_start (GTK_BOX(main_hbox), vbox, FALSE, FALSE, 0);
409   gtk_container_set_border_width (GTK_CONTAINER(vbox), 4);
410   gtk_widget_show (vbox);
411
412   /* Name */
413
414   hbox = gtk_hbox_new (FALSE, 0);
415   gtk_container_set_border_width (GTK_CONTAINER(hbox), 8);
416   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
417   gtk_widget_show (hbox);
418
419   label = gtk_label_new (_("Name:"));
420   gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 4);
421   gtk_widget_show (label);
422
423   entry = gtk_entry_new ();
424   gtk_box_pack_start (GTK_BOX(hbox), entry, TRUE, TRUE, 4);
425   gtk_widget_show (entry);
426
427   gtk_entry_set_text (GTK_ENTRY (entry),
428                       pathname ? pathname : filename_generate ());
429
430   g_object_set_data (G_OBJECT (dialog), "name_entry", entry);
431
432   /* Duration */
433  
434   hbox = gtk_hbox_new (FALSE, 0);
435   gtk_container_set_border_width (GTK_CONTAINER(hbox), 8);
436   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
437   gtk_widget_show (hbox);
438
439   label = gtk_label_new (_("Duration:"));
440   gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 4);
441   gtk_widget_show (label);
442
443   entry = gtk_entry_new ();
444   gtk_box_pack_start (GTK_BOX(hbox), entry, TRUE, TRUE, 4);
445   gtk_widget_show (entry);
446
447   snprint_time (buf, sizeof (buf), duration);
448   gtk_entry_set_text (GTK_ENTRY (entry), buf);
449
450   g_signal_connect (G_OBJECT(entry), "changed",
451                       G_CALLBACK(sample_new_dialog_update), NULL);
452
453   g_object_set_data (G_OBJECT (dialog), "duration_entry", entry);
454
455   label = gtk_label_new (_("hh:mm:ss.xxx"));
456   gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 4);
457   gtk_widget_show (label);
458
459   /* Right side */
460
461   vbox = gtk_vbox_new (FALSE, 0);
462   gtk_box_pack_start (GTK_BOX(main_hbox), vbox, FALSE, FALSE, 0);
463   gtk_container_set_border_width (GTK_CONTAINER(vbox), 4);
464   gtk_widget_show (vbox);
465
466   /* Sampling rate */
467
468   entry = samplerate_chooser_new (NULL);
469   samplerate_chooser_set_rate (entry, sample_rate);
470   gtk_box_pack_start (GTK_BOX(vbox), entry, FALSE, FALSE, 4);
471   gtk_widget_show (entry);
472
473   g_signal_connect (G_OBJECT(entry), "number-changed",
474                       G_CALLBACK(sample_new_dialog_update), NULL);
475
476   g_object_set_data (G_OBJECT (dialog), "rate_chooser", entry);
477
478   /* Channels */
479
480   entry = channelcount_chooser_new (NULL);
481   channelcount_chooser_set_count (entry, nr_channels);
482   gtk_box_pack_start (GTK_BOX(vbox), entry, FALSE, FALSE, 4);
483   gtk_widget_show (entry);
484
485   g_signal_connect (G_OBJECT(entry), "number-changed",
486                       G_CALLBACK(sample_new_dialog_update), NULL);
487
488   g_object_set_data (G_OBJECT (dialog), "channelcount_chooser", entry);
489
490   /* Defaults */
491
492   hbox = gtk_hbox_new (FALSE, 4);
493   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 4);
494   gtk_container_set_border_width (GTK_CONTAINER(hbox), 12);
495   gtk_widget_show (hbox);
496
497   checkbutton =
498     gtk_check_button_new_with_label (_("Remember this format"));
499   gtk_box_pack_start (GTK_BOX (hbox), checkbutton, TRUE, TRUE, 0);
500   gtk_widget_show (checkbutton);
501
502   tooltips = gtk_tooltips_new ();
503   gtk_tooltips_set_tip (tooltips, checkbutton,
504                         _("Remember this sampling rate and channel "
505                           "configuration for creating new files."),
506                         NULL);
507
508   g_object_set_data (G_OBJECT (dialog), "rem_format_chb", checkbutton);
509
510   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbutton), do_reset);
511
512   hbox2 = gtk_hbox_new (TRUE, 4);
513   gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, TRUE, 0);
514   gtk_widget_show (hbox2);
515
516   button = gtk_button_new_with_label (_("Reset"));
517   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, TRUE, 4);
518   g_signal_connect (G_OBJECT(button), "clicked",
519                       G_CALLBACK(sample_new_dialog_reset_cb), NULL);
520   gtk_widget_show (button);
521
522   tooltips = gtk_tooltips_new ();
523   gtk_tooltips_set_tip (tooltips, button,
524                         _("Reset to the last remembered format for new files."),
525                         NULL);
526
527   button = gtk_button_new_with_label (_("Defaults"));
528   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, TRUE, 4);
529   g_signal_connect (G_OBJECT(button), "clicked",
530                       G_CALLBACK(sample_new_dialog_defaults_cb), NULL);
531   gtk_widget_show (button);
532
533   tooltips = gtk_tooltips_new ();
534   gtk_tooltips_set_tip (tooltips, button,
535                         _("Set to the default format for new files."),
536                         NULL);
537
538   /* Data memory */
539
540   frame = gtk_frame_new (NULL);
541   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 4);
542   gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
543   gtk_widget_show (frame);
544
545   ebox = gtk_event_box_new ();
546   gtk_container_add (GTK_CONTAINER(frame), ebox);
547   gtk_widget_show (ebox);
548
549   tooltips = gtk_tooltips_new ();
550   gtk_tooltips_set_tip (tooltips, ebox,
551                         _("Indicates the amount of data memory which "
552                           "will be allocated for the selected duration and "
553                           "format. All audio data is processed "
554                           "internally in 32 bit floating point format."),
555                         NULL);
556
557   hbox = gtk_hbox_new (FALSE, 0);
558   gtk_container_add (GTK_CONTAINER(ebox), hbox);
559   gtk_container_set_border_width (GTK_CONTAINER(hbox), 2);
560   gtk_widget_show (hbox);
561
562   pixmap = create_widget_from_xpm (dialog, new_xpm);
563   gtk_box_pack_start (GTK_BOX(hbox), pixmap, FALSE, FALSE, 4);
564   gtk_widget_show (pixmap);
565
566   label = gtk_label_new (_("Data memory:"));
567   gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 4);
568   gtk_widget_show (label);
569
570   label = gtk_label_new (NULL);
571   gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 4);
572   gtk_widget_show (label);
573
574   g_object_set_data (G_OBJECT (dialog), "memsize_label", label);
575
576   /* OK */
577
578   ok_button = gtk_button_new_with_label (_("Create"));
579   GTK_WIDGET_SET_FLAGS (GTK_WIDGET(ok_button), GTK_CAN_DEFAULT);
580   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), ok_button,
581                       TRUE, TRUE, 0);
582   gtk_widget_show (ok_button);
583   g_signal_connect (G_OBJECT(ok_button), "clicked",
584                       G_CALLBACK (sample_new_dialog_ok_cb), NULL);
585
586   g_object_set_data (G_OBJECT (dialog), "ok_button", ok_button);
587
588   /* Cancel */
589
590   button = gtk_button_new_with_label (_("Don't create"));
591   GTK_WIDGET_SET_FLAGS (GTK_WIDGET(button), GTK_CAN_DEFAULT);
592   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), button,
593                       TRUE, TRUE, 0);
594   gtk_widget_show (button);
595   g_signal_connect (G_OBJECT(button), "clicked",
596                       G_CALLBACK (sample_new_dialog_cancel_cb), NULL);
597
598   gtk_widget_grab_default (ok_button);
599
600   if (do_reset) {
601     /* Call the reset callback now to set remembered options */
602     sample_new_dialog_reset_cb (dialog, NULL);
603   } else {
604     sample_new_dialog_update (dialog);
605   }
606
607   gtk_widget_show (dialog);
608 }
609
610 void
611 create_sample_new_dialog_defaults ( gchar * pathname)
612 {
613   create_sample_new_dialog (pathname, DEFAULT_CHANNELS, DEFAULT_SAMPLERATE,
614                             60, TRUE);
615 }
616
617 void
618 create_sample_new_dialog_like (sw_sample * s)
619 {
620   sw_format * f = s->sounddata->format;
621
622   create_sample_new_dialog (NULL, f->channels, f->rate,
623                             frames_to_time (f, s->sounddata->nr_frames),
624                             FALSE);
625 }
626
627 void
628 sample_destroy (sw_sample * s)
629 {
630   sweep_timeout_remove (s->tmp_message_tag);
631   sweep_timeout_remove (s->progress_ready_tag);
632
633   stop_playback (s);
634
635   sounddata_destroy (s->sounddata);
636
637   /* XXX: Should do this: */
638   /* trim_registered_ops (s, 0); */
639
640   g_list_free (s->views);
641   g_free (s->pathname);
642
643   g_mutex_free (s->ops_mutex);
644   g_mutex_free (s->edit_mutex);
645   g_mutex_free (s->play_mutex);
646
647   /* XXX: Should do this, but GTK+ barfs. */
648   /*
649   g_list_free (s->registered_ops);
650   g_list_free (s->current_undo);
651   g_list_free (s->current_redo);
652   g_list_free (s->pending_ops);
653   */
654
655   if (s->info_clist)
656     gtk_widget_destroy (s->info_clist);
657
658   if (s->last_tmp_message) {
659     memset (s->last_tmp_message, 0, strlen (s->last_tmp_message));
660     g_free (s->last_tmp_message);
661   }
662
663   memset (s, 0, sizeof (*s));
664   g_free (s);
665 }
666
667 sw_sounddata *
668 sample_get_sounddata (sw_sample * s)
669 {
670   return s->sounddata;
671 }
672
673 void
674 sample_set_pathname (sw_sample * s, gchar * pathname)
675 {
676   sw_view * v;
677   GList * gl;
678
679   if (pathname == s->pathname) return;
680
681   if (pathname) {
682     s->pathname = strdup (pathname);
683   } else {
684     if (s->pathname) g_free (s->pathname);
685     s->pathname = NULL;
686   }
687
688   for(gl = s->views; gl; gl = gl->next) {
689     v = (sw_view *)gl->data;
690     view_refresh_title (v);
691   }
692 }
693
694 GList *
695 sample_bank_list_names (void)
696 {
697   GList * ret = NULL;
698   GList * gl = NULL;
699   sw_sample * s;
700
701   for (gl = sample_bank; gl; gl = gl->next) {
702     s = (sw_sample *)gl->data;
703
704     ret = g_list_append (ret, (gpointer *)g_basename (s->pathname));
705   }
706
707   return ret;
708 }
709
710 sw_sample *
711 sample_bank_find_byname (const gchar * name)
712 {
713   GList * gl;
714   sw_sample * sample;
715
716   if (name == NULL) return NULL;
717
718   for (gl = sample_bank; gl; gl = gl->next) {
719     sample = (sw_sample *)gl->data;
720
721     if ((sample->pathname != NULL) &&
722         (!strcmp (name, g_basename (sample->pathname))))
723       return sample;
724   }
725
726   return NULL;
727 }
728
729 gboolean
730 sample_bank_contains (sw_sample *s)
731 {
732   return (g_list_find (sample_bank, s) != 0);
733 }
734
735 void
736 sample_bank_add (sw_sample * s)
737 {
738   /* Check that sample is not already in sample_bank */
739   if (g_list_find (sample_bank, s)) return;
740
741   sample_bank = g_list_append (sample_bank, s);
742
743   undo_dialog_refresh_sample_list ();
744   rec_dialog_refresh_sample_list ();
745 }
746
747 /*
748  * sample_bank_remove (s)
749  *
750  * Takes a sample out of the sample list.
751  */
752 void
753 sample_bank_remove (sw_sample * s)
754 {
755   if (s) {
756     sample_bank = g_list_remove(sample_bank, s);
757    
758     undo_dialog_refresh_sample_list ();
759     rec_dialog_refresh_sample_list ();
760     sample_destroy(s);
761     s = NULL;
762   }
763
764   if (sample_bank == NULL) {
765     sweep_quit ();
766   }
767 }
768
769 void
770 sweep_quit_ok_cb (GtkWidget * widget, gpointer data)
771 {
772   stop_all_playback ();
773   gtk_main_quit ();
774 }
775
776 void
777 sweep_quit_cancel_cb (GtkWidget * widget, gpointer data)
778 {
779   GList * gl;
780   sw_sample * s;
781
782   for (gl = sample_bank; gl; gl = gl->next) {
783     s = (sw_sample *)gl->data;
784     sample_set_tmp_message (s, _("Excellent!!!"));
785     sample_set_progress_ready (s);
786   }
787
788 }
789
790 void
791 sweep_quit (void)
792 {
793   GList * gl;
794   sw_sample * s;
795   gboolean any_modified = FALSE;
796
797   for (gl = sample_bank; gl; gl = gl->next) {
798     s = (sw_sample *)gl->data;
799     if (s->modified) {
800       any_modified = TRUE;
801       break;
802     }
803   }
804
805   if (any_modified) {
806     question_dialog_new (NULL, _("Files unsaved"),
807                          _("Some files are unsaved. If you quit, all "
808                            "changes will be lost.\n\n"
809                            "Are you sure you want to quit?"),
810                          _("Quit"), _("Don't quit"),
811                          G_CALLBACK (sweep_quit_ok_cb), NULL, G_CALLBACK (sweep_quit_cancel_cb), NULL,
812                          SWEEP_EDIT_MODE_READY);
813   } else if (any_playing()) {
814     question_dialog_new (NULL, _("Files playing"),
815                          _("No files are unsaved, but some files are "
816                            "currently playing.\n\n"
817                            "Are you sure you want to quit?"),
818                          _("Quit"), _("Don't quit"),
819                          G_CALLBACK (sweep_quit_ok_cb), NULL, G_CALLBACK (sweep_quit_cancel_cb), NULL,
820                          SWEEP_EDIT_MODE_READY);
821   } else {
822     sweep_quit_ok_cb (NULL, NULL);
823   }
824 }
825
826 /* info dialog */
827
828
829 void
830 sample_refresh_views (sw_sample * s)
831 {
832   sw_view * v;
833   GList * gl;
834
835   g_mutex_lock (s->ops_mutex);
836
837   sample_info_update (s);
838
839   for(gl = s->views; gl; gl = gl->next) {
840     v = (sw_view *)gl->data;
841     view_refresh (v);
842   }
843
844   g_mutex_unlock (s->ops_mutex);
845 }
846
847 void
848 sample_start_marching_ants (sw_sample * s)
849 {
850   sw_view * v;
851   GList * gl;
852
853   for(gl = s->views; gl; gl = gl->next) {
854     v = (sw_view *)gl->data;
855     sample_display_start_marching_ants (SAMPLE_DISPLAY(v->display));
856   }
857 }
858
859 void
860 sample_stop_marching_ants (sw_sample * s)
861 {
862   sw_view * v;
863   GList * gl;
864
865   for(gl = s->views; gl; gl = gl->next) {
866     v = (sw_view *)gl->data;
867     sample_display_stop_marching_ants (SAMPLE_DISPLAY(v->display));
868   }
869 }
870
871 /* Edit state */
872
873
874 static void
875 _sample_set_edit_mode (sw_sample * s, sw_edit_mode edit_mode)
876 {
877   GList * gl;
878   sw_view * v;
879
880   s->edit_mode = edit_mode;
881
882   for(gl = s->views; gl; gl = gl->next) {
883     v = (sw_view *)gl->data;
884     view_refresh_edit_mode (v);
885   }
886
887   undo_dialog_refresh_edit_mode (s);
888 }
889
890 void
891 sample_set_edit_mode (sw_sample * s, sw_edit_mode edit_mode)
892 {
893   g_mutex_lock (s->edit_mutex);
894
895   _sample_set_edit_mode (s, edit_mode);
896
897 #ifdef DEBUG
898   g_print ("set_edit_mode %d\n", edit_mode);
899 #endif
900
901   g_mutex_unlock (s->edit_mutex);
902 }
903
904 void
905 sample_set_edit_state (sw_sample * s, sw_edit_state edit_state)
906 {
907   g_mutex_lock (s->edit_mutex);
908
909   s->edit_state = edit_state;
910
911 #ifdef DEBUG
912   g_print ("set_edit_state %d\n", edit_state);
913 #endif
914
915   if (edit_state == SWEEP_EDIT_STATE_IDLE) {
916     _sample_set_edit_mode (s, SWEEP_EDIT_MODE_READY);
917   }
918
919   g_mutex_unlock (s->edit_mutex);
920
921   if (edit_state == SWEEP_EDIT_STATE_PENDING) {
922     g_cond_signal (s->pending_cond);
923   }
924 }
925
926 /* Playback state */
927
928 void
929 sample_refresh_playmode (sw_sample * s)
930 {
931   GList * gl;
932   sw_view * v;
933   sw_head * head = s->play_head;
934
935   if (!head->going) {
936     if (s->playmarker_tag > 0) {
937       g_source_remove (s->playmarker_tag);
938     }
939   }
940
941   for(gl = s->views; gl; gl = gl->next) {
942     v = (sw_view *)gl->data;
943     view_refresh_playmode (v);
944   }
945 }
946
947 void
948 sample_set_stop_offset (sw_sample * s)
949 {
950   sw_framecount_t offset;
951
952   g_mutex_lock (s->play_mutex);
953
954   offset = s->user_offset;
955   if (offset == s->sounddata->nr_frames)
956     offset = 0;
957
958   head_set_stop_offset (s->play_head, offset);
959   /*  s->play_head->stop_offset = offset;*/
960
961   g_mutex_unlock (s->play_mutex);
962 }
963
964 void
965 sample_set_playmarker (sw_sample * s, sw_framecount_t offset,
966                        gboolean by_user)
967 {
968   GList * gl;
969   sw_view * v;
970   sw_head * head = s->play_head;
971
972 #ifdef DEBUG
973   g_print ("sample_set_playmarker (%p, %d, %s)\n", s, offset,
974            by_user ? "TRUE" : "FALSE");
975 #endif
976
977   g_mutex_lock (s->play_mutex);
978
979   if (offset < 0) offset = 0;
980   if (offset > s->sounddata->nr_frames) offset = s->sounddata->nr_frames;
981
982   if (by_user) {
983     s->by_user = by_user;
984     s->user_offset = offset;
985     if (!head->going || head->scrubbing == FALSE) {
986       head_set_stop_offset (head, offset);
987       head_set_offset (head, offset);
988     }
989   } else {
990     /*
991     if (head->scrubbing == FALSE)
992       head_set_offset (head, offset);
993     */
994   }
995
996   g_mutex_unlock (s->play_mutex);
997
998   for(gl = s->views; gl; gl = gl->next) {
999     v = (sw_view *)gl->data;
1000     view_refresh_offset_indicators (v);
1001   }
1002 }
1003
1004 void
1005 sample_set_offset_next_bound_left (sw_sample * s)
1006 {
1007   GList * gl;
1008   sw_sel * sel;
1009
1010   for (gl = g_list_last (s->sounddata->sels); gl; gl = gl->prev) {
1011     sel = (sw_sel *)gl->data;
1012     if (sel->sel_end < s->user_offset) {
1013       sample_set_playmarker (s, sel->sel_end, TRUE);
1014       return;
1015     }
1016     if (sel->sel_start < s->user_offset) {
1017       sample_set_playmarker (s, sel->sel_start, TRUE);
1018       return;
1019     }
1020   }
1021 }
1022
1023 void
1024 sample_set_offset_next_bound_right (sw_sample * s)
1025 {
1026   GList * gl;
1027   sw_sel * sel;
1028
1029   for (gl = s->sounddata->sels; gl; gl = gl->next) {
1030     sel = (sw_sel *)gl->data;
1031     if (sel->sel_start > s->user_offset) {
1032       sample_set_playmarker (s, sel->sel_start, TRUE);
1033       return;
1034     }
1035     if (sel->sel_end > s->user_offset) {
1036       sample_set_playmarker (s, sel->sel_end, TRUE);
1037       return;
1038     }
1039   }
1040 }
1041
1042 void
1043 sample_set_rec_marker (sw_sample * s, sw_framecount_t offset)
1044 {
1045   GList * gl;
1046   sw_view * v;
1047
1048   g_assert (s->rec_head != NULL);
1049
1050   head_set_offset (s->rec_head, (gdouble)offset);
1051
1052   for(gl = s->views; gl; gl = gl->next) {
1053     v = (sw_view *)gl->data;
1054     view_refresh_rec_offset_indicators (v);
1055   }
1056
1057 }
1058
1059 void
1060 sample_refresh_rec_marker (sw_sample * s)
1061 {
1062   GList * gl;
1063   sw_view * v;
1064
1065   g_assert (s->rec_head != NULL);
1066
1067   for(gl = s->views; gl; gl = gl->next) {
1068     v = (sw_view *)gl->data;
1069     view_refresh_rec_offset_indicators (v);
1070   }
1071 }
1072
1073 void
1074 sample_set_scrubbing (sw_sample * s, gboolean scrubbing)
1075 {
1076   sw_head * head = s->play_head;
1077
1078   head_set_scrubbing (head, scrubbing);
1079
1080   sample_set_progress_ready (s);
1081 }
1082
1083 void
1084 sample_set_looping (sw_sample * s, gboolean looping)
1085 {
1086   GList * gl;
1087   sw_view * v;
1088   sw_head * head = s->play_head;
1089
1090   head_set_looping (head, looping);
1091  
1092   for(gl = s->views; gl; gl = gl->next) {
1093     v = (sw_view *)gl->data;
1094     view_refresh_looping (v);
1095   }
1096 }
1097
1098 void
1099 sample_set_playrev (sw_sample * s, gboolean reverse)
1100 {
1101   GList * gl;
1102   sw_view * v;
1103   sw_head * head = s->play_head;
1104
1105   head_set_reverse (head, reverse);
1106
1107   for(gl = s->views; gl; gl = gl->next) {
1108     v = (sw_view *)gl->data;
1109     view_refresh_playrev (v);
1110   }
1111 }
1112
1113 void
1114 sample_set_mute (sw_sample * s, gboolean mute)
1115 {
1116   GList * gl;
1117   sw_view * v;
1118   sw_head * head = s->play_head;
1119
1120   head_set_mute (head, mute);
1121
1122   for(gl = s->views; gl; gl = gl->next) {
1123     v = (sw_view *)gl->data;
1124     view_refresh_mute (v);
1125   }
1126 }
1127
1128 void
1129 sample_set_monitor (sw_sample * s, gboolean monitor)
1130 {
1131   GList * gl;
1132   sw_view * v;
1133   sw_head * head = s->play_head;
1134
1135   head_set_monitor (head, monitor);
1136
1137   for(gl = s->views; gl; gl = gl->next) {
1138     v = (sw_view *)gl->data;
1139     view_refresh_monitor (v);
1140   }
1141 }
1142
1143 void
1144 sample_set_previewing (sw_sample * s, gboolean previewing)
1145 {
1146   head_set_previewing (s->play_head, previewing);
1147 }
1148
1149 void
1150 sample_set_color (sw_sample * s, gint color)
1151 {
1152   GList * gl;
1153   sw_view * v;
1154
1155   if (color < 0 || color > VIEW_COLOR_MAX) return;
1156
1157   s->color = color;
1158
1159   for(gl = s->views; gl; gl = gl->next) {
1160     v = (sw_view *)gl->data;
1161     view_refresh_display (v);
1162   }
1163 }
1164
1165 void
1166 sample_set_progress_text (sw_sample * s, gchar * text)
1167 {
1168   GList * gl;
1169   sw_view * v;
1170
1171   s->tmp_message_active = FALSE;
1172
1173   for(gl = s->views; gl; gl = gl->next) {
1174     v = (sw_view *)gl->data;
1175     view_set_progress_text (v, text);
1176   }
1177 }
1178
1179 void
1180 sample_set_progress_percent (sw_sample * s, gint percent)
1181 {
1182   s->progress_percent = CLAMP (percent, 0, 100);
1183 }
1184
1185 void
1186 sample_refresh_progress_percent (sw_sample * s)
1187 {
1188   GList * gl;
1189   sw_view * v;
1190
1191   if (s->edit_state == SWEEP_EDIT_STATE_IDLE) return;
1192
1193   for(gl = s->views; gl; gl = gl->next) {
1194     v = (sw_view *)gl->data;
1195     view_set_progress_percent (v, s->progress_percent);
1196   }
1197 }
1198
1199 int
1200 sample_set_progress_ready (sw_sample * s)
1201 {
1202   GList * gl;
1203   sw_view * v;
1204
1205   if (s->edit_state != SWEEP_EDIT_STATE_IDLE) return FALSE;
1206
1207   if (s->tmp_message_active) {
1208     for(gl = s->views; gl; gl = gl->next) {
1209       v = (sw_view *)gl->data;
1210       view_set_tmp_message (v, s->last_tmp_message);
1211     }
1212   } else {
1213     for(gl = s->views; gl; gl = gl->next) {
1214       v = (sw_view *)gl->data;
1215       view_set_progress_ready (v);
1216     }
1217   }
1218
1219   return FALSE; /* for use as a one-shot timeout function */
1220 }
1221
1222 gint
1223 sample_clear_tmp_message (gpointer data)
1224 {
1225   sw_sample * sample = (sw_sample *)data;
1226
1227   sample->tmp_message_active = FALSE;
1228
1229   if (sample->edit_state == SWEEP_EDIT_STATE_IDLE)
1230     sample_set_progress_ready (sample);
1231
1232   g_free (sample->last_tmp_message);
1233   sample->last_tmp_message = NULL;
1234
1235   sample->tmp_message_tag = -1;
1236
1237   return FALSE;
1238 }
1239
1240 void
1241 sample_set_tmp_message (sw_sample * s, const char * fmt, ...)
1242 {
1243   va_list ap;
1244   char buf[512];
1245
1246   va_start (ap, fmt);
1247   vsnprintf (buf, sizeof (buf), fmt, ap);
1248   va_end (ap);
1249
1250   s->tmp_message_active = TRUE;
1251   s->last_tmp_message = g_strdup (buf);
1252
1253   sweep_timeout_remove (s->tmp_message_tag);
1254   s->tmp_message_tag =
1255     sweep_timeout_add ((guint32)5000,
1256                        (GtkFunction)sample_clear_tmp_message, s);
1257
1258   sweep_timeout_remove (s->progress_ready_tag);
1259   s->progress_ready_tag =
1260     sweep_timeout_add ((guint32)0, (GtkFunction)sample_set_progress_ready, s);
1261 }
1262
1263 /*
1264  * sample_replace_throughout (os, s)
1265  *
1266  * Replaces os with s throughout the program, ie:
1267  *   - in the sample bank
1268  *   - in all os's views
1269  *
1270  * Destroys os.
1271  *
1272  * This function is not needed in general filters because sw_sample
1273  * pointers are persistent across sounddata modifications.
1274  * However, this function is still required where the entire sample
1275  * changes but the view must stay the same, eg. for File->Revert.
1276  */
1277 void
1278 sample_replace_throughout (sw_sample * os, sw_sample * s)
1279 {
1280   sw_view * v;
1281   GList * gl;
1282
1283   if (os == s) return;
1284
1285   if ((!os) || (!s)) return;
1286
1287   s->views = os->views;
1288
1289   for(gl = s->views; gl; gl = gl->next) {
1290     v = (sw_view *)gl->data;
1291     v->sample = s;
1292     /* view_refresh (v); */
1293   }
1294
1295   sample_bank_remove (os);
1296   sample_bank_add (s);
1297 }
1298
1299 gboolean
1300 sample_offset_in_sel (sw_sample * s, sw_framecount_t offset)
1301 {
1302   GList * gl;
1303   sw_sel * sel;
1304
1305   for (gl = s->sounddata->sels; gl; gl = gl->next) {
1306     sel = (sw_sel *)gl->data;
1307
1308     if (sel->sel_start <= offset && sel->sel_end >= offset)
1309       return TRUE;
1310   }
1311
1312   return FALSE;
1313 }
1314
1315 guint
1316 sample_sel_nr_regions (sw_sample * s)
1317 {
1318   return g_list_length (s->sounddata->sels);
1319 }
1320
1321 void
1322 sample_clear_selection (sw_sample * s)
1323 {
1324   sounddata_clear_selection (s->sounddata);
1325
1326   sample_stop_marching_ants (s);
1327 }
1328
1329 static void
1330 sample_normalise_selection (sw_sample * s)
1331 {
1332   sounddata_normalise_selection (s->sounddata);
1333 }
1334
1335 void
1336 sample_add_selection (sw_sample * s, sw_sel * sel)
1337 {
1338   if (!s->sounddata->sels)
1339     sample_start_marching_ants (s);
1340
1341   sounddata_add_selection (s->sounddata, sel);
1342 }
1343
1344 sw_sel *
1345 sample_add_selection_1 (sw_sample * s, sw_framecount_t start, sw_framecount_t end)
1346 {
1347   return sounddata_add_selection_1 (s->sounddata, start, end);
1348 }
1349
1350 void
1351 sample_set_selection (sw_sample * s, GList * gl)
1352 {
1353   sample_clear_selection(s);
1354
1355   s->sounddata->sels = sels_copy (gl);
1356 }
1357
1358 sw_sel *
1359 sample_set_selection_1 (sw_sample * s, sw_framecount_t start, sw_framecount_t end)
1360 {
1361   return sounddata_set_selection_1 (s->sounddata, start, end);
1362 }
1363
1364 void
1365 sample_selection_modify (sw_sample * s, sw_sel * sel,
1366                          sw_framecount_t new_start, sw_framecount_t new_end)
1367 {
1368   sel->sel_start = new_start;
1369   sel->sel_end = new_end;
1370
1371   sample_normalise_selection (s);
1372 }
1373
1374 static sw_sample *
1375 ss_invert (sw_sample * s, sw_param_set unused, gpointer unused2)
1376 {
1377   sw_sounddata * sounddata = s->sounddata;
1378   GList * gl;
1379   GList * osels;
1380   sw_sel * osel, * sel;
1381
1382   g_mutex_lock (sounddata->sels_mutex);
1383
1384   if (!sounddata->sels) {
1385     sounddata_set_selection_1 (sounddata, 0, sounddata->nr_frames);
1386     goto out;
1387   }
1388
1389   gl = osels = sounddata->sels;
1390   sounddata->sels = NULL;
1391
1392   sel = osel = (sw_sel *)gl->data;
1393   if (osel->sel_start > 0) {
1394     sounddata_add_selection_1 (sounddata, 0, osel->sel_start - 1);
1395   }
1396
1397   gl = gl->next;
1398
1399   for (; gl; gl = gl->next) {
1400     sel = (sw_sel *)gl->data;
1401     sounddata_add_selection_1 (sounddata, osel->sel_end, sel->sel_start - 1);
1402     osel = sel;
1403   }
1404
1405   if (sel->sel_end != sounddata->nr_frames) {
1406     sounddata_add_selection_1 (sounddata, sel->sel_end, sounddata->nr_frames);
1407   }
1408
1409   g_list_free (osels);
1410
1411 out:
1412
1413   g_mutex_unlock (sounddata->sels_mutex);
1414
1415   return s;
1416 }
1417
1418 void
1419 sample_selection_invert (sw_sample * s)
1420 {
1421   perform_selection_op (s, _("Invert selection"), ss_invert, NULL, NULL);
1422 }
1423
1424 static sw_sample *
1425 ss_select_all (sw_sample * s, sw_param_set unused, gpointer unused2)
1426 {
1427   sw_sounddata * sounddata = s->sounddata;
1428
1429   g_mutex_lock (sounddata->sels_mutex);
1430
1431   sounddata_set_selection_1 (sounddata, 0, sounddata->nr_frames);
1432
1433   g_mutex_unlock (sounddata->sels_mutex);
1434
1435   return s;
1436 }
1437
1438 void
1439 sample_selection_select_all (sw_sample * s)
1440 {
1441   perform_selection_op (s, _("Select all"), ss_select_all, NULL, NULL);
1442 }
1443
1444 static sw_sample *
1445 ss_select_none (sw_sample * s, sw_param_set unused, gpointer unused2)
1446 {
1447   sw_sounddata * sounddata = s->sounddata;
1448
1449   g_mutex_lock (sounddata->sels_mutex);
1450
1451   sounddata_clear_selection (sounddata);
1452
1453   g_mutex_unlock (sounddata->sels_mutex);
1454
1455   return s;
1456 }
1457
1458 void
1459 sample_selection_select_none (sw_sample * s)
1460 {
1461   perform_selection_op (s, _("Select none"), ss_select_none, NULL, NULL);
1462 }
1463
1464 static sw_sample *
1465 ss_halve (sw_sample * s, sw_param_set unused, gpointer unused2)
1466 {
1467   sw_sounddata * sounddata = s->sounddata;
1468
1469   g_mutex_lock (sounddata->sels_mutex);
1470
1471   sounddata_selection_scale (sounddata, 0.5);
1472
1473   g_mutex_unlock (sounddata->sels_mutex);
1474
1475   return s;
1476 }
1477
1478 void
1479 sample_selection_halve (sw_sample * s)
1480 {
1481   perform_selection_op (s, _("Halve selection"), ss_halve, NULL, NULL);
1482 }
1483
1484 static sw_sample *
1485 ss_double (sw_sample * s, sw_param_set unused, gpointer unused2)
1486 {
1487   sw_sounddata * sounddata = s->sounddata;
1488
1489   g_mutex_lock (sounddata->sels_mutex);
1490
1491   sounddata_selection_scale (sounddata, 2.0);
1492
1493   g_mutex_unlock (sounddata->sels_mutex);
1494
1495   return s;
1496 }
1497
1498 void
1499 sample_selection_double (sw_sample * s)
1500 {
1501   perform_selection_op (s, _("Double selection"), ss_double, NULL, NULL);
1502 }
1503
1504 static sw_sample *
1505 ss_shift_left (sw_sample * s, sw_param_set unused, gpointer unused2)
1506 {
1507   sw_sounddata * sounddata = s->sounddata;
1508
1509   sw_framecount_t delta;
1510
1511   g_mutex_lock (sounddata->sels_mutex);
1512
1513   delta = - (sounddata_selection_width (sounddata));
1514   sounddata_selection_translate (sounddata, delta);
1515
1516   g_mutex_unlock (sounddata->sels_mutex);
1517
1518   return s;
1519 }
1520
1521 void
1522 sample_selection_shift_left (sw_sample * s)
1523 {
1524   perform_selection_op (s, _("Selection left"), ss_shift_left, NULL, NULL);
1525 }
1526
1527 static sw_sample *
1528 ss_shift_right (sw_sample * s, sw_param_set unused, gpointer unused2)
1529 {
1530   sw_sounddata * sounddata = s->sounddata;
1531   sw_framecount_t delta;
1532
1533   g_mutex_lock (sounddata->sels_mutex);
1534
1535   delta = (sounddata_selection_width (sounddata));
1536   sounddata_selection_translate (sounddata, delta);
1537
1538   g_mutex_unlock (sounddata->sels_mutex);
1539
1540   return s;
1541 }
1542
1543 void
1544 sample_selection_shift_right (sw_sample * s)
1545 {
1546   perform_selection_op (s, _("Selection right"), ss_shift_right, NULL, NULL);
1547 }
1548
1549 /*
1550  * Functions to handle the temporary selection
1551  */
1552
1553 void
1554 sample_clear_tmp_sel (sw_sample * s)
1555 {
1556  if (s->tmp_sel) g_free (s->tmp_sel);
1557  s->tmp_sel = NULL;
1558  last_tmp_view = NULL;
1559 }
1560
1561
1562 /*
1563  * sample_set_tmp_sel (s, tsel)
1564  *
1565  * sets the tmp_sel of sample s to a list containing only tsel.
1566  * If tsel was part of the actual selection of s, it is first
1567  * removed from the selection.
1568  */
1569 void
1570 sample_set_tmp_sel (sw_sample * s, sw_view * tview, sw_sel * tsel)
1571 {
1572   GList * gl;
1573   sw_sel * sel;
1574
1575   /* XXX: Dump old tmp_sel */
1576   sample_clear_tmp_sel (s);
1577
1578   s->tmp_sel =
1579     sel_copy (tsel); /* XXX: try to do this without copying? */
1580   last_tmp_view = tview;
1581
1582   g_mutex_lock (s->sounddata->sels_mutex);
1583
1584   for(gl = s->sounddata->sels; gl; gl = gl->next) {
1585     sel = (sw_sel *)gl->data;
1586
1587     if(sel == tsel) {
1588       s->sounddata->sels = g_list_remove(s->sounddata->sels, sel);
1589     }
1590   }
1591
1592   g_mutex_unlock (s->sounddata->sels_mutex);
1593 }
1594
1595 void
1596 sample_set_tmp_sel_1 (sw_sample * s, sw_view * tview, sw_framecount_t start, sw_framecount_t end)
1597 {
1598   sw_sel * tsel;
1599
1600   tsel = sel_new (start, end);
1601
1602   sample_set_tmp_sel (s, tview, tsel);
1603 }
1604
1605 /* For convenience, as the tmp_sel handling is internal to the application,
1606  * we pass the actual sw_sample pointer to the tmp_sel handling ops.
1607  */
1608
1609 static sw_sample *
1610 ssits (sw_sample * s, sw_param_set unused, gpointer data)
1611 {
1612   sw_sel * sel = (sw_sel *)data;
1613
1614   g_mutex_lock (s->sounddata->sels_mutex);
1615
1616   sample_add_selection (s, sel);
1617   sample_normalise_selection (s);
1618
1619   g_mutex_unlock (s->sounddata->sels_mutex);
1620
1621   return s;
1622 }
1623
1624 void
1625 sample_selection_insert_tmp_sel (sw_sample * s)
1626 {
1627   int n;
1628   gchar buf[64];
1629   sw_format * format = s->sounddata->format;
1630   sw_sel * sel;
1631
1632   n = snprintf (buf, sizeof (buf), _("Insert selection ["));
1633   if (n < sizeof (buf)) {
1634     n += snprint_time (buf+n, sizeof (buf)-n,
1635                      frames_to_time (format, s->tmp_sel->sel_start));
1636   }
1637
1638   if (n < sizeof (buf)) {
1639     n += snprintf (buf+n, sizeof (buf)-n, " - ");
1640   }
1641
1642   if (n < sizeof (buf)) {
1643     n += snprint_time (buf+n, sizeof (buf)-n,
1644                      frames_to_time (format, s->tmp_sel->sel_end));
1645   }
1646
1647   if (n < sizeof (buf)) {
1648     n += snprintf (buf+n, sizeof (buf)-n, "]");
1649   }
1650
1651   g_mutex_lock (s->sounddata->sels_mutex);
1652
1653   sel = sel_copy (s->tmp_sel);
1654
1655   s->tmp_sel = NULL;
1656   last_tmp_view = NULL;
1657
1658   g_mutex_unlock (s->sounddata->sels_mutex);
1659  
1660   perform_selection_op (s, buf, ssits, NULL, sel);
1661 }
1662
1663 static sw_sample *
1664 sssts (sw_sample * s, sw_param_set unused, gpointer data)
1665 {
1666   GList * sels;
1667   sw_sel * sel = (sw_sel *)data;
1668
1669   g_mutex_lock (s->sounddata->sels_mutex);
1670
1671   sels = s->sounddata->sels;
1672
1673   sels = sels_invert (sels, s->sounddata->nr_frames);
1674   s->sounddata->sels = sels_add_selection (sels, sel);
1675
1676   sample_normalise_selection (s);
1677   sels = s->sounddata->sels;
1678
1679   s->sounddata->sels = sels_invert (sels, s->sounddata->nr_frames);
1680
1681   g_mutex_unlock (s->sounddata->sels_mutex);
1682
1683   return s;
1684 }
1685
1686 void
1687 sample_selection_subtract_tmp_sel (sw_sample * s)
1688 {
1689   int n;
1690   gchar buf[64];
1691   sw_format * format = s->sounddata->format;
1692   sw_sel * sel;
1693
1694   n = snprintf (buf, sizeof (buf), _("Subtract selection ["));
1695   n += snprint_time (buf+n, sizeof (buf)-n,
1696                      frames_to_time (format, s->tmp_sel->sel_start));
1697   n += snprintf (buf+n, sizeof (buf)-n, " - ");
1698   n += snprint_time (buf+n, sizeof (buf)-n,
1699                      frames_to_time (format, s->tmp_sel->sel_end));
1700   n += snprintf (buf+n, sizeof (buf)-n, "]");
1701
1702   g_mutex_lock (s->sounddata->sels_mutex);
1703
1704   sel = sel_copy (s->tmp_sel);
1705
1706   s->tmp_sel = NULL;
1707   last_tmp_view = NULL;
1708
1709   g_mutex_unlock (s->sounddata->sels_mutex);
1710  
1711   perform_selection_op (s, buf, sssts, NULL, sel);
1712 }
1713
1714 static sw_sample *
1715 ssrwts (sw_sample * s, sw_param_set unused, gpointer data)
1716 {
1717   sw_sel * sel = (sw_sel *)data;
1718
1719   g_mutex_lock (s->sounddata->sels_mutex);
1720
1721   sample_clear_selection (s);
1722
1723   sample_add_selection (s, sel);
1724
1725   g_mutex_unlock (s->sounddata->sels_mutex);
1726
1727   return s;
1728 }
1729
1730 void
1731 sample_selection_replace_with_tmp_sel (sw_sample * s)
1732 {
1733   int n;
1734   gchar buf[64];
1735   sw_format * format = s->sounddata->format;
1736   sw_sel * sel;
1737
1738   n = snprintf (buf, sizeof (buf), _("Set selection ["));
1739   n += snprint_time (buf+n, sizeof (buf)-n,
1740                      frames_to_time (format, s->tmp_sel->sel_start));
1741   n += snprintf (buf+n, sizeof (buf)-n, " - ");
1742   n += snprint_time (buf+n, sizeof (buf)-n,
1743                      frames_to_time (format, s->tmp_sel->sel_end));
1744   n += snprintf (buf+n, sizeof (buf)-n, "]");
1745
1746   g_mutex_lock (s->sounddata->sels_mutex);
1747
1748   sel = sel_copy (s->tmp_sel);
1749
1750   s->tmp_sel = NULL;
1751   last_tmp_view = NULL;
1752
1753   g_mutex_unlock (s->sounddata->sels_mutex);
1754
1755   perform_selection_op (s, buf, ssrwts, NULL, sel);
1756 }
1757
1758
1759 /* Sample info dialog */
1760
1761 static void
1762 sample_info_update (sw_sample * sample)
1763 {
1764   sw_sounddata * sounddata = sample->sounddata;
1765   GtkWidget * clist = sample->info_clist;
1766
1767   char rate_buf[16];
1768   char chan_buf[16];
1769   char byte_buf[16];
1770   char time_buf[16];
1771
1772   if (clist == NULL) return;
1773
1774   snprintf (rate_buf, sizeof (rate_buf), "%d Hz", sounddata->format->rate);
1775
1776   snprintf (chan_buf, sizeof (chan_buf), "%d", sounddata->format->channels);
1777
1778   snprint_bytes (byte_buf, sizeof (byte_buf),
1779                  frames_to_bytes (sounddata->format, sounddata->nr_frames));
1780  
1781   snprint_time (time_buf, sizeof (time_buf),
1782                 frames_to_time (sounddata->format, sounddata->nr_frames));
1783
1784
1785   gtk_clist_set_text (GTK_CLIST(clist), 0, 1, g_basename(sample->pathname));
1786   gtk_clist_set_text (GTK_CLIST(clist), 1, 1, rate_buf);
1787   gtk_clist_set_text (GTK_CLIST(clist), 2, 1, chan_buf);
1788   gtk_clist_set_text (GTK_CLIST(clist), 3, 1, byte_buf);
1789   gtk_clist_set_text (GTK_CLIST(clist), 4, 1, time_buf);
1790
1791 }
1792
1793 static void
1794 sample_info_dialog_destroy_cb (GtkWidget * widget, gpointer data)
1795 {
1796   sw_sample * sample = (sw_sample *)data;
1797
1798   sample->info_clist = NULL;
1799 }
1800
1801 static void
1802 sample_info_dialog_ok_cb (GtkWidget * widget, gpointer data)
1803 {
1804   GtkWidget * dialog;
1805
1806   dialog = gtk_widget_get_toplevel (widget);
1807   gtk_widget_hide (dialog);
1808 }
1809
1810 /*
1811 static gchar * filename_info[] = { N_("Filename:"), "" };
1812 static gchar * rate_info[] = { N_("Sampling rate:"), "" };
1813 static gchar * channels_info[] = { N_("Channels:"), "" };
1814 static gchar * size_info[] = { N_("Data memory:"), "" };
1815 static gchar * duration_info[] = { N_("Duration:"), "" };
1816 */
1817
1818 void
1819 sample_show_info_dialog (sw_sample * sample)
1820 {
1821   GtkWidget * dialog;
1822   GtkWidget * clist;
1823   GtkWidget * ok_button;
1824   gchar * list_item[] = { "" };
1825   gint i=0;
1826
1827   if (sample->info_clist == NULL) {
1828     dialog = gtk_dialog_new ();
1829     gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
1830     gtk_window_set_title (GTK_WINDOW(dialog), _("Sweep: File properties"));
1831     gtk_container_set_border_width (GTK_CONTAINER(dialog), 8);
1832
1833     g_signal_connect (G_OBJECT(dialog), "destroy",
1834                         G_CALLBACK(sample_info_dialog_destroy_cb),
1835                         sample);
1836    
1837     clist = gtk_clist_new (2);
1838     gtk_clist_set_selection_mode (GTK_CLIST(clist), GTK_SELECTION_BROWSE);
1839     gtk_clist_set_column_justification (GTK_CLIST(clist), 0,
1840                                         GTK_JUSTIFY_RIGHT);
1841     gtk_clist_set_column_justification (GTK_CLIST(clist), 1,
1842                                         GTK_JUSTIFY_LEFT);
1843     gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), clist,
1844                         FALSE, FALSE, 0);
1845     /*   
1846     gtk_clist_append (GTK_CLIST(clist), filename_info);
1847     gtk_clist_append (GTK_CLIST(clist), rate_info);
1848     gtk_clist_append (GTK_CLIST(clist), channels_info);
1849     gtk_clist_append (GTK_CLIST(clist), size_info);
1850     gtk_clist_append (GTK_CLIST(clist), duration_info);
1851     */
1852      
1853     gtk_clist_append (GTK_CLIST(clist), list_item);
1854     gtk_clist_set_text (GTK_CLIST(clist), i++, 0, _("Filename: "));
1855     gtk_clist_append (GTK_CLIST(clist), list_item);
1856     gtk_clist_set_text (GTK_CLIST(clist), i++, 0, _("Sampling rate: "));
1857     gtk_clist_append (GTK_CLIST(clist), list_item);
1858     gtk_clist_set_text (GTK_CLIST(clist), i++, 0, _("Channels: "));
1859     gtk_clist_append (GTK_CLIST(clist), list_item);
1860     gtk_clist_set_text (GTK_CLIST(clist), i++, 0, _("Data memory: "));
1861     gtk_clist_append (GTK_CLIST(clist), list_item);
1862     gtk_clist_set_text (GTK_CLIST(clist), i++, 0, _("Duration: "));
1863    
1864     gtk_clist_set_column_min_width (GTK_CLIST(clist), 0, 120);
1865     gtk_clist_set_column_min_width (GTK_CLIST(clist), 1, 160);
1866    
1867     gtk_widget_show (clist);
1868
1869     sample->info_clist = clist;
1870
1871     /* OK */
1872    
1873     ok_button = gtk_button_new_with_label (_("OK"));
1874     GTK_WIDGET_SET_FLAGS (GTK_WIDGET (ok_button), GTK_CAN_DEFAULT);
1875     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), ok_button,
1876                         TRUE, TRUE, 0);
1877     gtk_widget_show (ok_button);
1878     g_signal_connect (G_OBJECT(ok_button), "clicked",
1879                         G_CALLBACK (sample_info_dialog_ok_cb), sample);
1880    
1881     gtk_widget_grab_default (ok_button);
1882    
1883   } else {
1884     dialog = gtk_widget_get_toplevel (sample->info_clist);
1885   }
1886
1887   sample_info_update (sample);
1888
1889   if (!GTK_WIDGET_VISIBLE(dialog)) {
1890     gtk_widget_show (dialog);
1891   } else {
1892     gdk_window_raise (dialog->window);
1893   }
1894 }
Note: See TracBrowser for help on using the browser.