1 /*
2 Audio File Library
3 Copyright (C) 1998, Michael Pruett <michael@68k.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301 USA
19 */
20
21 /*
22 Miscellaneous.cpp
23
24 This file contains routines for dealing with the Audio File
25 Library's internal miscellaneous data types.
26 */
27
28 #include "config.h"
29
30 #include <algorithm>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "FileHandle.h"
36 #include "Setup.h"
37 #include "afinternal.h"
38 #include "audiofile.h"
39 #include "util.h"
40
afInitMiscIDs(AFfilesetup setup,const int * ids,int nids)41 void afInitMiscIDs (AFfilesetup setup, const int *ids, int nids)
42 {
43 if (!_af_filesetup_ok(setup))
44 return;
45
46 if (setup->miscellaneous != NULL)
47 {
48 free(setup->miscellaneous);
49 }
50
51 setup->miscellaneousCount = nids;
52
53 if (nids == 0)
54 setup->miscellaneous = NULL;
55 else
56 {
57 setup->miscellaneous = (MiscellaneousSetup *) _af_calloc(nids,
58 sizeof (MiscellaneousSetup));
59
60 if (setup->miscellaneous == NULL)
61 return;
62
63 for (int i=0; i<nids; i++)
64 {
65 setup->miscellaneous[i].id = ids[i];
66 setup->miscellaneous[i].type = 0;
67 setup->miscellaneous[i].size = 0;
68 }
69 }
70
71 setup->miscellaneousSet = true;
72 }
73
afGetMiscIDs(AFfilehandle file,int * ids)74 int afGetMiscIDs (AFfilehandle file, int *ids)
75 {
76 if (!_af_filehandle_ok(file))
77 return -1;
78
79 if (ids != NULL)
80 {
81 for (int i=0; i<file->m_miscellaneousCount; i++)
82 {
83 ids[i] = file->m_miscellaneous[i].id;
84 }
85 }
86
87 return file->m_miscellaneousCount;
88 }
89
afInitMiscType(AFfilesetup setup,int miscellaneousid,int type)90 void afInitMiscType (AFfilesetup setup, int miscellaneousid, int type)
91 {
92 if (!_af_filesetup_ok(setup))
93 return;
94
95 MiscellaneousSetup *miscellaneous = setup->getMiscellaneous(miscellaneousid);
96 if (miscellaneous)
97 miscellaneous->type = type;
98 }
99
afGetMiscType(AFfilehandle file,int miscellaneousid)100 int afGetMiscType (AFfilehandle file, int miscellaneousid)
101 {
102 if (!_af_filehandle_ok(file))
103 return -1;
104
105 Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
106 if (miscellaneous)
107 return miscellaneous->type;
108 return -1;
109 }
110
afInitMiscSize(AFfilesetup setup,int miscellaneousid,int size)111 void afInitMiscSize (AFfilesetup setup, int miscellaneousid, int size)
112 {
113 if (!_af_filesetup_ok(setup))
114 return;
115
116 MiscellaneousSetup *miscellaneous = setup->getMiscellaneous(miscellaneousid);
117 if (miscellaneous)
118 miscellaneous->size = size;
119 }
120
afGetMiscSize(AFfilehandle file,int miscellaneousid)121 int afGetMiscSize (AFfilehandle file, int miscellaneousid)
122 {
123 if (!_af_filehandle_ok(file))
124 return -1;
125
126 Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
127 if (miscellaneous)
128 return miscellaneous->size;
129 return -1;
130 }
131
afWriteMisc(AFfilehandle file,int miscellaneousid,const void * buf,int bytes)132 int afWriteMisc (AFfilehandle file, int miscellaneousid, const void *buf, int bytes)
133 {
134 if (!_af_filehandle_ok(file))
135 return -1;
136
137 if (!file->checkCanWrite())
138 return -1;
139
140 Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
141 if (!miscellaneous)
142 return -1;
143
144 if (bytes <= 0)
145 {
146 _af_error(AF_BAD_MISCSIZE, "invalid size (%d) for miscellaneous chunk", bytes);
147 return -1;
148 }
149
150 if (miscellaneous->buffer == NULL && miscellaneous->size != 0)
151 {
152 miscellaneous->buffer = _af_malloc(miscellaneous->size);
153 if (miscellaneous->buffer == NULL)
154 return -1;
155 memset(miscellaneous->buffer, 0, miscellaneous->size);
156 }
157
158 int localsize = std::min(bytes,
159 miscellaneous->size - miscellaneous->position);
160 memcpy((char *) miscellaneous->buffer + miscellaneous->position,
161 buf, localsize);
162 miscellaneous->position += localsize;
163 return localsize;
164 }
165
afReadMisc(AFfilehandle file,int miscellaneousid,void * buf,int bytes)166 int afReadMisc (AFfilehandle file, int miscellaneousid, void *buf, int bytes)
167 {
168 if (!_af_filehandle_ok(file))
169 return -1;
170
171 if (!file->checkCanRead())
172 return -1;
173
174 Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
175 if (!miscellaneous)
176 return -1;
177
178 if (bytes <= 0)
179 {
180 _af_error(AF_BAD_MISCSIZE, "invalid size (%d) for miscellaneous chunk", bytes);
181 return -1;
182 }
183
184 int localsize = std::min(bytes,
185 miscellaneous->size - miscellaneous->position);
186 memcpy(buf, (char *) miscellaneous->buffer + miscellaneous->position,
187 localsize);
188 miscellaneous->position += localsize;
189 return localsize;
190 }
191
afSeekMisc(AFfilehandle file,int miscellaneousid,int offset)192 int afSeekMisc (AFfilehandle file, int miscellaneousid, int offset)
193 {
194 if (!_af_filehandle_ok(file))
195 return -1;
196
197 Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
198 if (!miscellaneous)
199 return -1;
200
201 if (offset >= miscellaneous->size)
202 {
203 _af_error(AF_BAD_MISCSEEK,
204 "offset %d too big for miscellaneous chunk %d "
205 "(%d data bytes)",
206 offset, miscellaneousid, miscellaneous->size);
207 return -1;
208 }
209
210 miscellaneous->position = offset;
211
212 return offset;
213 }
214