1 /*
2  * Copyright (C) 2002 2003 2004 2005 2006 2009, Magnus Hjorth
3  *
4  * This file is part of mhWaveEdit.
5  *
6  * mhWaveEdit 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  * mhWaveEdit 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 mhWaveEdit; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 /* Datasource object represent a source of PCM data. */
22 
23 /* This is (and should be) mainly used by chunk.c */
24 
25 #ifndef DATASOURCE_H_INCLUDED
26 #define DATASOURCE_H_INCLUDED
27 
28 #include <gtk/gtk.h>
29 #include "gtkfiles.h"
30 #include "statusbar.h"
31 #include "dataformat.h"
32 
33 #define DATASOURCE(obj) GTK_CHECK_CAST(obj,datasource_get_type(),Datasource)
34 #define DATASOURCE_CLASS(klass) GTK_CHECK_CLASS_CAST(klass,datasource_get_type(),DatasourceClass)
35 #define IS_DATASOURCE(obj) GTK_CHECK_TYPE(obj,datasource_get_type())
36 
37 #ifndef HAVE_LIBSNDFILE
38 #define SNDFILE void
39 #else
40 #include <sndfile.h>
41 #endif
42 
43 
44 
45 /* Values for the type member of the Datasource struct. Determines how to
46  * actually get the data. */
47 
48 /* Data stored directly in memory */
49 #define DATASOURCE_REAL              0
50 /* The data is stored in a (read-only) file. */
51 #define DATASOURCE_VIRTUAL           1
52 /* Data stored in a file that will be removed when the Datasource is
53  * destroyed. */
54 #define DATASOURCE_TEMPFILE          2
55 /* Silence (duh) */
56 #define DATASOURCE_SILENCE           3
57 /* The data is read using libSndfile */
58 #define DATASOURCE_SNDFILE           4
59 /* Same as DATASOURCE_SNDFILE but will be removed when the chunk is
60  * destroyed. */
61 #define DATASOURCE_SNDFILE_TEMPORARY 5
62 /* Reference to another Datasource. Has the same format.
63  * All requests will simply be passed on to the referred datasource. */
64 #define DATASOURCE_REF               6
65 /* Clone of another PCM Datasource. The Clone can have different
66  * format than the original. This is used for mending files with
67  * broken headers..*/
68 #define DATASOURCE_CLONE             7
69 /* Byteswapped clone of PCM datsource.*/
70 #define DATASOURCE_BYTESWAP          8
71 /* Autoconverting datasource. This Datasource must have the
72  * same number of channels as referred Datasource.
73  * Floating point requests will be passed on to the referred
74  * Datasource, PCM requests will be sent as FP requests and then
75  * automatically converted from the FP data. */
76 #define DATASOURCE_CONVERT           9
77 /* Clone of other datasource with channels rearranged.
78  * Has the sample sample format and rate, but can have different number of
79  * channels */
80 #define DATASOURCE_CHANMAP          10
81 
82 struct temparea {
83      gpointer ptr;
84      int size;
85 };
86 
87 struct _Datasource;
88 
89 struct _Datasource {
90 
91      GtkObject object;
92 
93      gint type;
94 
95      Dataformat format;
96 
97      off_t length;             /*�Number of samples */
98      off_t bytes;               /* Number of bytes in file. */
99 
100      guint opencount;            /* To keep track of nested open/close calls */
101 
102      /* Temporary areas for internal use */
103      struct temparea read_temparea,readfp_temparea;
104 
105      gint tag;                   /* Extra field... */
106 
107      /* Type-specific data */
108      union {
109 
110 	  /* --- DATASOURCE_TEMPFILE and DATASOURCE_VIRTUAL --- */
111 	  struct {
112 	       char *filename;
113 	       off_t offset;  /* Offset of data in file (bytes) */
114 	       EFILE *handle;
115 	       off_t pos;     /* Current position in file (bytes) */
116 	  } virtual;
117 
118 	  /* --- DATASOURCE_REAL ---*/
119 	  char *real;  /* Pointer into the memory buffer with the sound data. */
120 
121 
122 	  /* --- DATASOURCE_SNDFILE and DATASOURCE_SNDFILE_TEMPORARY --- */
123 	  struct {
124 	       char *filename;
125 	       gboolean raw_readable;
126 	       SNDFILE *handle;
127 	       off_t pos; /* Current position in file (samples) */
128 	  } sndfile;
129 
130 	  /* DATASOURCE_CLONE, DATASOURCE_REF, DATASOURCE_CONVERT and
131 	   * DATASOURCE_BYTESWAP */
132 	  struct _Datasource *clone;
133 
134 	  /* DATASOURCE_CHANMAP */
135 	  struct {
136 	       struct _Datasource *clone;
137 	       int *map;
138 	  } chanmap;
139 
140      } data;
141 };
142 
143 typedef struct _Datasource Datasource;
144 
145 typedef struct {
146      GtkObjectClass klass;
147 } DatasourceClass;
148 
149 
150 GtkType datasource_get_type(void);
151 
152 /* ------------
153  * CONSTRUCTORS
154  * ------------ */
155 
156 
157 /* Create data source from another Datasource object. The format of the data
158  * will be that of the format argument, regardless of what the other source
159  * specifies. This makes it possible to override the format when you know it is
160  * wrong.
161  * source must be a PCM datasource
162  */
163 Datasource *datasource_clone_df(Datasource *source, Dataformat *format);
164 
165 
166 /* Returns a byte-swapped clone of another Datasource.
167  * source must be a PCM datasource */
168 Datasource *datasource_byteswap(Datasource *source);
169 
170 
171 /* Returns a Datasource containing the same data as source, but converted to
172  * new_format. If source is floating-point, the original data will still
173  * be returned when the read_array_fp function is used. source and new must
174  * have the same number of channels and samplerate.  */
175 Datasource *datasource_convert(Datasource *source, Dataformat *new_format);
176 
177 /* Returns a Datasource containing the same data as source, but with its
178  * channels remapped.
179  * n_channels is the number of channels in the new source.
180  * map should point to an array length n_channels mapping to source channels */
181 Datasource *datasource_channel_map(Datasource *source, int n_channels,
182 				   int *map);
183 
184 /* Create a data source from a memory buffer of data. The buffer will be
185  * g_free:d when the data source is destroyed and the data should not be
186  * modified by the caller any more after this call.
187  */
188 Datasource *datasource_new_from_data(void *data, Dataformat *format,
189 				     guint32 size);
190 
191 
192 /* Create a new datasource containing silence with a certain format and the
193  * specified number of samples
194  */
195 Datasource *datasource_new_silent(Dataformat *format, off_t samples);
196 
197 
198 
199 /* ---------------------
200  * DATA ACCESS FUNCTIONS
201  * --------------------- */
202 
203 
204 
205 /* Open the data source. Must be called before any of the other data access
206  * functions. May be called more than one time for the same Datasource.
207  */
208 
209 gboolean datasource_open(Datasource *source);
210 
211 
212 
213 /* Close the data source. Must be called once for each call to
214  * datasource_open.
215  */
216 
217 void datasource_close(Datasource *source);
218 
219 
220 
221 /* Read one/many PCM/float sample from the Data source into the buffer. The
222  * sample data will always be in host endian order.
223  */
224 gboolean datasource_read(Datasource *source, off_t sampleno, gpointer buffer,
225 			 int dither_mode);
226 gboolean datasource_read_fp(Datasource *source, off_t sampleno,
227 			    sample_t *buffer, int dither_mode);
228 /* Returns number of bytes read (0 on error). If clipping != NULL and clipping
229  * conversion was performed, sets *clipping to TRUE.
230  */
231 guint datasource_read_array(Datasource *source, off_t sampleno,
232 			    guint size, gpointer buffer, int dither_mode,
233 			    off_t *clipcount);
234 /* Returns number of (multi-channel) samples read (0 on error). */
235 guint datasource_read_array_fp(Datasource *source, off_t sampleno,
236 			       guint samples, sample_t *buffer,
237 			       int dither_mode, off_t *clipcount);
238 
239 
240 
241 
242 
243 
244 /* -------
245  * VARIOUS
246  * ------- */
247 
248 
249 /* Returns the number of active Datasource objects */
250 guint datasource_count(void);
251 
252 
253 
254 /* This dumps the contents of the datasource into a file. You don't need
255  * to open the datasource when using this function. The StatusBar must
256  * already be in progress mode.
257  */
258 
259 gboolean datasource_dump(Datasource *ds, off_t position, off_t length,
260 			 EFILE *file, int dither_mode, StatusBar *bar,
261 			 off_t *clipcount);
262 
263 
264 /* This reads all the data of the datasource into a memory buffer and converts
265  * it into a memory datasource.
266  */
267 
268 gboolean datasource_realize(Datasource *ds, int dither_mode);
269 
270 /* This function will unlink a file. If any of the Datasources depend on this
271  * file, the file will be moved or copied into a temporary file before the
272  * original name is unlinked.
273  */
274 
275 gboolean datasource_backup_unlink(gchar *filename);
276 
277 /* Returns zero if reading the datasource does not cause clipping conversion.
278  * and the datasource contains normalized data.
279  * Returns non-zero if reading the datasource causes clipping conversion
280  * Returns 1 if the error can be solved by normalizing the Datasource
281  * Returns 2 if the error can not be solved in that way (very special cases)
282  * Returns <0 if an error or break occurred while checking
283  * The StatusBar must already be in progress mode.
284  */
285 gint datasource_clip_check(Datasource *ds, StatusBar *bar);
286 
287 #endif
288