source: trunk/third/audiofile/libaudiofile/openclose.c @ 18227

Revision 18227, 12.9 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18226, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2        Audio File Library
3        Copyright (C) 2000-2001, Silicon Graphics, Inc.
4
5        This library is free software; you can redistribute it and/or
6        modify it under the terms of the GNU Library General Public
7        License as published by the Free Software Foundation; either
8        version 2 of the License, or (at your option) any later version.
9
10        This library is distributed in the hope that it will be useful,
11        but WITHOUT ANY WARRANTY; without even the implied warranty of
12        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13        Library General Public License for more details.
14
15        You should have received a copy of the GNU Library General Public
16        License along with this library; if not, write to the
17        Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18        Boston, MA  02111-1307  USA.
19*/
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include <stdlib.h>
26#include <assert.h>
27#include <string.h>
28
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
32
33#include <audiofile.h>
34
35#include "afinternal.h"
36#include "units.h"
37#include "util.h"
38#include "modules.h"
39
40#ifndef _MSC_VER
41#define SETBINARYMODE(x)
42#endif
43
44extern _Unit _af_units[];
45
46static void freeFileHandle (AFfilehandle filehandle);
47static void freeInstParams (AFPVu *values, int fileFormat);
48static status _afOpenFile (int access, AFvirtualfile *vf, const char *filename,
49        AFfilehandle *file, AFfilesetup filesetup);
50
51int _af_identify (AFvirtualfile *vf, int *implemented)
52{
53        off_t   curpos;
54        int     i;
55
56        curpos = af_ftell(vf);
57
58        for (i=0; i<_AF_NUM_UNITS; i++)
59        {
60                if (_af_units[i].read.recognize &&
61                        _af_units[i].read.recognize(vf))
62                {
63                        if (implemented != NULL)
64                                *implemented = _af_units[i].implemented;
65                        af_fseek(vf, curpos, SEEK_SET);
66                        return _af_units[i].fileFormat;
67                }
68        }
69
70        af_fseek(vf, curpos, SEEK_SET);
71
72        if (implemented != NULL)
73                *implemented = AF_FALSE;
74
75        return AF_FILE_UNKNOWN;
76}
77
78int afIdentifyFD (int fd)
79{
80        FILE            *fp;
81        AFvirtualfile   *vf;
82        int             result;
83
84        /*
85                Duplicate the file descriptor since otherwise the
86                original file descriptor would get closed when we close
87                the virtual file below.
88        */
89        fd = dup(fd);
90
91        fp = fdopen(fd, "r");
92        if (fp == NULL)
93        {
94                _af_error(AF_BAD_OPEN, "could not open file");
95                return AF_FILE_UNKNOWN;
96        }
97
98        SETBINARYMODE(fp);
99
100        vf = af_virtual_file_new_for_file(fp);
101        if (vf == NULL)
102        {
103                _af_error(AF_BAD_OPEN, "could not open file");
104                return AF_FILE_UNKNOWN;
105        }
106
107        result = _af_identify(vf, NULL);
108
109        af_fclose(vf);
110
111        return result;
112}
113
114int afIdentifyNamedFD (int fd, const char *filename, int *implemented)
115{
116        FILE            *fp;
117        AFvirtualfile   *vf;
118        int             result;
119
120        /*
121                Duplicate the file descriptor since otherwise the
122                original file descriptor would get closed when we close
123                the virtual file below.
124        */
125        fd = dup(fd);
126
127        fp = fdopen(fd, "r");
128        if (fp == NULL)
129        {
130                _af_error(AF_BAD_OPEN, "could not open file '%s'", filename);
131                return AF_FILE_UNKNOWN;
132        }
133
134        SETBINARYMODE(fp);
135
136        vf = af_virtual_file_new_for_file(fp);
137        if (vf == NULL)
138        {
139                _af_error(AF_BAD_OPEN, "could not open file '%s'", filename);
140                return AF_FILE_UNKNOWN;
141        }
142
143        result = _af_identify(vf, implemented);
144
145        af_fclose(vf);
146
147        return result;
148}
149
150AFfilehandle afOpenFD (int fd, const char *mode, AFfilesetup setup)
151{
152        FILE            *fp;
153        AFvirtualfile   *vf;
154        AFfilehandle    filehandle;
155        int             access;
156
157        if (mode == NULL)
158        {
159                _af_error(AF_BAD_ACCMODE, "null access mode");
160                return AF_NULL_FILEHANDLE;
161        }
162
163        if (mode[0] == 'r')
164                access = _AF_READ_ACCESS;
165        else if (mode[0] == 'w')
166                access = _AF_WRITE_ACCESS;
167        else
168        {
169                _af_error(AF_BAD_ACCMODE, "unrecognized access mode '%s'", mode);
170                return AF_NULL_FILEHANDLE;
171        }
172
173        if ((fp = fdopen(fd, mode)) == NULL)
174        {
175                _af_error(AF_BAD_OPEN, "could not open file");
176                return AF_NULL_FILEHANDLE;
177        }
178
179        SETBINARYMODE(fp);
180
181        vf = af_virtual_file_new_for_file(fp);
182
183        if (_afOpenFile(access, vf, NULL, &filehandle, setup) != AF_SUCCEED)
184                af_fclose(vf);
185
186        return filehandle;
187}
188
189AFfilehandle afOpenNamedFD (int fd, const char *mode, AFfilesetup setup,
190        const char *filename)
191{
192        FILE            *fp;
193        AFvirtualfile   *vf;
194        AFfilehandle    filehandle;
195        int             access;
196
197        if (mode == NULL)
198        {
199                _af_error(AF_BAD_ACCMODE, "null access mode");
200                return AF_NULL_FILEHANDLE;
201        }
202
203        if (mode[0] == 'r')
204                access = _AF_READ_ACCESS;
205        else if (mode[0] == 'w')
206                access = _AF_WRITE_ACCESS;
207        else
208        {
209                _af_error(AF_BAD_ACCMODE, "unrecognized access mode '%s'", mode);
210                return AF_NULL_FILEHANDLE;
211        }
212
213        if ((fp = fdopen(fd, mode)) == NULL)
214        {
215                _af_error(AF_BAD_OPEN, "could not open file '%s'", filename);
216                return AF_NULL_FILEHANDLE;
217        }
218
219        SETBINARYMODE(fp);
220
221        vf = af_virtual_file_new_for_file(fp);
222
223        if (_afOpenFile(access, vf, filename, &filehandle, setup) != AF_SUCCEED)
224                af_fclose(vf);
225
226        return filehandle;
227}
228
229AFfilehandle afOpenFile (const char *filename, const char *mode, AFfilesetup setup)
230{
231        FILE            *fp;
232        AFvirtualfile   *vf;
233        AFfilehandle    filehandle;
234        int             access;
235
236        if (mode == NULL)
237        {
238                _af_error(AF_BAD_ACCMODE, "null access mode");
239                return AF_NULL_FILEHANDLE;
240        }
241
242        if (mode[0] == 'r')
243                access = _AF_READ_ACCESS;
244        else if (mode[0] == 'w')
245                access = _AF_WRITE_ACCESS;
246        else
247        {
248                _af_error(AF_BAD_ACCMODE, "unrecognized access mode '%s'", mode);
249                return AF_NULL_FILEHANDLE;
250        }
251
252        if ((fp = fopen(filename, mode)) == NULL)
253        {
254                _af_error(AF_BAD_OPEN, "could not open file '%s'", filename);
255                return AF_NULL_FILEHANDLE;
256        }
257
258        SETBINARYMODE(fp);
259
260        vf = af_virtual_file_new_for_file(fp);
261
262        if (_afOpenFile(access, vf, filename, &filehandle, setup) != AF_SUCCEED)
263                af_fclose(vf);
264
265        return filehandle;
266}
267
268static status _afOpenFile (int access, AFvirtualfile *vf, const char *filename,
269        AFfilehandle *file, AFfilesetup filesetup)
270{
271        int     fileFormat = AF_FILE_UNKNOWN;
272        bool    implemented = AF_TRUE;
273        char    *formatName;
274        status  (*initfunc) (AFfilesetup, AFfilehandle);
275
276        int             userSampleFormat = 0;
277        double          userSampleRate = 0.0;
278        _PCMInfo        userPCM;
279        bool            userFormatSet = AF_FALSE;
280
281        int     t;
282
283        AFfilehandle    filehandle = AF_NULL_FILEHANDLE;
284        AFfilesetup     completesetup = AF_NULL_FILESETUP;
285
286        *file = AF_NULL_FILEHANDLE;
287
288        if (access == _AF_WRITE_ACCESS || filesetup != AF_NULL_FILESETUP)
289        {
290                if (!_af_filesetup_ok(filesetup))
291                        return AF_FAIL;
292
293                fileFormat = filesetup->fileFormat;
294                if (access == _AF_READ_ACCESS && fileFormat != AF_FILE_RAWDATA)
295                {
296                        _af_error(AF_BAD_FILESETUP,
297                                "warning: opening file for read access: "
298                                "ignoring file setup with non-raw file format");
299                        filesetup = AF_NULL_FILESETUP;
300                        fileFormat = _af_identify(vf, &implemented);
301                }
302        }
303        else if (filesetup == AF_NULL_FILESETUP)
304                fileFormat = _af_identify(vf, &implemented);
305
306        if (fileFormat == AF_FILE_UNKNOWN)
307        {
308                if (filename != NULL)
309                        _af_error(AF_BAD_NOT_IMPLEMENTED,
310                                "'%s': unrecognized audio file format",
311                                filename);
312                else
313                        _af_error(AF_BAD_NOT_IMPLEMENTED,
314                                "unrecognized audio file format");
315                return AF_FAIL;
316        }
317
318        formatName = _af_units[fileFormat].name;
319
320        if (implemented == AF_FALSE)
321        {
322                _af_error(AF_BAD_NOT_IMPLEMENTED,
323                        "%s format not currently supported", formatName);
324        }
325
326        assert(_af_units[fileFormat].completesetup != NULL);
327        assert(_af_units[fileFormat].read.init != NULL);
328
329        if (access == _AF_WRITE_ACCESS &&
330                _af_units[fileFormat].write.init == NULL)
331        {
332                _af_error(AF_BAD_NOT_IMPLEMENTED,
333                        "%s format is currently supported for reading only",
334                        formatName);
335                return AF_FAIL;
336        }
337
338        completesetup = NULL;
339        if (filesetup != AF_NULL_FILESETUP)
340        {
341                userSampleFormat = filesetup->tracks[0].f.sampleFormat;
342                userPCM = filesetup->tracks[0].f.pcm;
343                userSampleRate = filesetup->tracks[0].f.sampleRate;
344                userFormatSet = AF_TRUE;
345                if ((completesetup = _af_units[fileFormat].completesetup(filesetup)) == NULL)
346                        return AF_FAIL;
347        }
348
349        filehandle = _af_malloc(sizeof (_AFfilehandle));
350        if (filehandle == NULL)
351        {
352                if (completesetup)
353                        afFreeFileSetup(completesetup);
354                return AF_FAIL;
355        }
356        memset(filehandle, 0, sizeof (_AFfilehandle));
357
358        filehandle->valid = _AF_VALID_FILEHANDLE;
359        filehandle->fh = vf;
360        filehandle->access = access;
361        filehandle->fileFormat = fileFormat;
362        filehandle->formatSpecific = NULL;
363
364        initfunc = (access == _AF_READ_ACCESS) ?
365                _af_units[fileFormat].read.init : _af_units[fileFormat].write.init;
366
367        if (initfunc(completesetup, filehandle) != AF_SUCCEED)
368        {
369                freeFileHandle(filehandle);
370                filehandle = AF_NULL_FILEHANDLE;
371                if (completesetup)
372                        afFreeFileSetup(completesetup);
373                return AF_FAIL;
374        }
375
376        if (completesetup)
377        {
378                afFreeFileSetup(completesetup);
379                completesetup = NULL;
380        }
381
382        /*
383                Initialize virtual format.
384        */
385        for (t=0; t<filehandle->trackCount; t++)
386        {
387                _Track  *track = &filehandle->tracks[t];
388
389                track->v = track->f;
390
391                if (userFormatSet)
392                {
393                        track->v.sampleFormat = userSampleFormat;
394                        track->v.pcm = userPCM;
395                        track->v.sampleRate = userSampleRate;
396                }
397
398                track->v.compressionType = AF_COMPRESSION_NONE;
399                track->v.compressionParams = NULL;
400
401#if WORDS_BIGENDIAN
402                track->v.byteOrder = AF_BYTEORDER_BIGENDIAN;
403#else
404                track->v.byteOrder = AF_BYTEORDER_LITTLEENDIAN;
405#endif
406
407                if (track->f.sampleWidth > 16 &&
408                        (track->f.sampleFormat == AF_SAMPFMT_TWOSCOMP ||
409                        track->f.sampleFormat == AF_SAMPFMT_UNSIGNED))
410                        track->v.sampleWidth = 32;
411
412                if (_AFinitmodules(filehandle, track) == AF_FAIL)
413                {
414                        freeFileHandle(filehandle);
415                        return AF_FAIL;
416                }
417        }
418
419        *file = filehandle;
420
421        return AF_SUCCEED;
422}
423
424int afSyncFile (AFfilehandle handle)
425{
426        if (!_af_filehandle_ok(handle))
427                return -1;
428
429        if (handle->access == _AF_WRITE_ACCESS)
430        {
431                int     filefmt = handle->fileFormat;
432                int     trackno;
433
434                /* Finish writes on all tracks. */
435                for (trackno = 0; trackno < handle->trackCount; trackno++)
436                {
437                        _Track  *track = &handle->tracks[trackno];
438
439                        if (track->ms.modulesdirty)
440                        {
441                                if (_AFsetupmodules(handle, track) == AF_FAIL)
442                                        return -1;
443                        }
444
445                        if (_AFsyncmodules(handle, track) != AF_SUCCEED)
446                                return -1;
447                }
448
449                /* Update file headers. */
450                if (_af_units[filefmt].write.update != NULL &&
451                        _af_units[filefmt].write.update(handle) != AF_SUCCEED)
452                        return AF_FAIL;
453        }
454        else if (handle->access == _AF_READ_ACCESS)
455        {
456                /* Do nothing. */
457        }
458        else
459        {
460                _af_error(AF_BAD_ACCMODE, "unrecognized access mode %d",
461                        handle->access);
462                return AF_FAIL;
463        }
464
465        return AF_SUCCEED;
466}
467
468int afCloseFile (AFfilehandle file)
469{
470        int     err;
471
472        if (!_af_filehandle_ok(file))
473                return -1;
474
475        afSyncFile(file);
476
477        err = af_fclose(file->fh);
478        if (err < 0)
479                _af_error(AF_BAD_CLOSE, "close returned %d", err);
480
481        freeFileHandle(file);
482
483        return 0;
484}
485
486static void freeFileHandle (AFfilehandle filehandle)
487{
488        int     fileFormat;
489        if (filehandle == NULL || filehandle->valid != _AF_VALID_FILEHANDLE)
490        {
491                _af_error(AF_BAD_FILEHANDLE, "bad filehandle");
492                return;
493        }
494
495        filehandle->valid = 0;
496        fileFormat = filehandle->fileFormat;
497
498        if (filehandle->formatSpecific != NULL)
499        {
500                free(filehandle->formatSpecific);
501                filehandle->formatSpecific = NULL;
502        }
503
504        if (filehandle->tracks)
505        {
506                int     i;
507                for (i=0; i<filehandle->trackCount; i++)
508                {
509                        /* Free the compression parameters. */
510                        if (filehandle->tracks[i].f.compressionParams)
511                        {
512                                AUpvfree(filehandle->tracks[i].f.compressionParams);
513                                filehandle->tracks[i].f.compressionParams = AU_NULL_PVLIST;
514                        }
515
516                        if (filehandle->tracks[i].v.compressionParams)
517                        {
518                                AUpvfree(filehandle->tracks[i].v.compressionParams);
519                                filehandle->tracks[i].v.compressionParams = AU_NULL_PVLIST;
520                        }
521
522                        /* Free the track's modules. */
523
524                        _AFfreemodules(&filehandle->tracks[i]);
525
526                        if (filehandle->tracks[i].channelMatrix)
527                        {
528                                free(filehandle->tracks[i].channelMatrix);
529                                filehandle->tracks[i].channelMatrix = NULL;
530                        }
531
532                        if (filehandle->tracks[i].markers)
533                        {
534                                int     j;
535                                for (j=0; j<filehandle->tracks[i].markerCount; j++)
536                                {
537                                        if (filehandle->tracks[i].markers[j].name)
538                                        {
539                                                free(filehandle->tracks[i].markers[j].name);
540                                                filehandle->tracks[i].markers[j].name = NULL;
541                                        }
542                                        if (filehandle->tracks[i].markers[j].comment)
543                                        {
544                                                free(filehandle->tracks[i].markers[j].comment);
545                                                filehandle->tracks[i].markers[j].comment = NULL;
546                                        }
547
548                                }
549
550                                free(filehandle->tracks[i].markers);
551                                filehandle->tracks[i].markers = NULL;
552                        }
553                }
554
555                free(filehandle->tracks);
556                filehandle->tracks = NULL;
557        }
558        filehandle->trackCount = 0;
559
560        if (filehandle->instruments)
561        {
562                int     i;
563                for (i=0; i<filehandle->instrumentCount; i++)
564                {
565                        if (filehandle->instruments[i].loops)
566                        {
567                                free(filehandle->instruments[i].loops);
568                                filehandle->instruments[i].loops = NULL;
569                        }
570                        filehandle->instruments[i].loopCount = 0;
571
572                        if (filehandle->instruments[i].values)
573                        {
574                                freeInstParams(filehandle->instruments[i].values, fileFormat);
575                                filehandle->instruments[i].values = NULL;
576                        }
577                }
578                free(filehandle->instruments);
579                filehandle->instruments = NULL;
580        }
581        filehandle->instrumentCount = 0;
582
583        if (filehandle->miscellaneous)
584        {
585                free(filehandle->miscellaneous);
586                filehandle->miscellaneous = NULL;
587        }
588        filehandle->miscellaneousCount = 0;
589
590        memset(filehandle, 0, sizeof (_AFfilehandle));
591        free(filehandle);
592}
593
594static void freeInstParams (AFPVu *values, int fileFormat)
595{
596        int     i;
597        int     parameterCount = _af_units[fileFormat].instrumentParameterCount;
598
599        for (i=0; i<parameterCount; i++)
600        {
601                if (_af_units[fileFormat].instrumentParameters[i].type == AU_PVTYPE_PTR)
602                        if (values[i].v != NULL)
603                                free(values[i].v);
604        }
605
606        free(values);
607}
Note: See TracBrowser for help on using the repository browser.