1b815c7f3Sopenharmony_ci/*
2b815c7f3Sopenharmony_ci** Copyright (C) 2001-2020 Erik de Castro Lopo <erikd@mega-nerd.com>
3b815c7f3Sopenharmony_ci** Copyright (C) 2004 Paavo Jumppanen
4b815c7f3Sopenharmony_ci**
5b815c7f3Sopenharmony_ci** This program is free software; you can redistribute it and/or modify
6b815c7f3Sopenharmony_ci** it under the terms of the GNU Lesser General Public License as published by
7b815c7f3Sopenharmony_ci** the Free Software Foundation; either version 2.1 of the License, or
8b815c7f3Sopenharmony_ci** (at your option) any later version.
9b815c7f3Sopenharmony_ci**
10b815c7f3Sopenharmony_ci** This program is distributed in the hope that it will be useful,
11b815c7f3Sopenharmony_ci** but WITHOUT ANY WARRANTY; without even the implied warranty of
12b815c7f3Sopenharmony_ci** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13b815c7f3Sopenharmony_ci** GNU Lesser General Public License for more details.
14b815c7f3Sopenharmony_ci**
15b815c7f3Sopenharmony_ci** You should have received a copy of the GNU Lesser General Public License
16b815c7f3Sopenharmony_ci** along with this program; if not, write to the Free Software
17b815c7f3Sopenharmony_ci** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18b815c7f3Sopenharmony_ci*/
19b815c7f3Sopenharmony_ci
20b815c7f3Sopenharmony_ci/*
21b815c7f3Sopenharmony_ci** The sd2 support implemented in this file was partially sponsored
22b815c7f3Sopenharmony_ci** (financially) by Paavo Jumppanen.
23b815c7f3Sopenharmony_ci*/
24b815c7f3Sopenharmony_ci
25b815c7f3Sopenharmony_ci/*
26b815c7f3Sopenharmony_ci** Documentation on the Mac resource fork was obtained here :
27b815c7f3Sopenharmony_ci** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
28b815c7f3Sopenharmony_ci*/
29b815c7f3Sopenharmony_ci
30b815c7f3Sopenharmony_ci#include	"sfconfig.h"
31b815c7f3Sopenharmony_ci
32b815c7f3Sopenharmony_ci#include	<stdio.h>
33b815c7f3Sopenharmony_ci#include	<stdlib.h>
34b815c7f3Sopenharmony_ci#include	<string.h>
35b815c7f3Sopenharmony_ci#include	<ctype.h>
36b815c7f3Sopenharmony_ci
37b815c7f3Sopenharmony_ci#include	"sndfile.h"
38b815c7f3Sopenharmony_ci#include	"sfendian.h"
39b815c7f3Sopenharmony_ci#include	"common.h"
40b815c7f3Sopenharmony_ci
41b815c7f3Sopenharmony_ci/*------------------------------------------------------------------------------
42b815c7f3Sopenharmony_ci * Markers.
43b815c7f3Sopenharmony_ci*/
44b815c7f3Sopenharmony_ci
45b815c7f3Sopenharmony_ci#define	Sd2f_MARKER			MAKE_MARKER ('S', 'd', '2', 'f')
46b815c7f3Sopenharmony_ci#define	Sd2a_MARKER			MAKE_MARKER ('S', 'd', '2', 'a')
47b815c7f3Sopenharmony_ci#define	ALCH_MARKER			MAKE_MARKER ('A', 'L', 'C', 'H')
48b815c7f3Sopenharmony_ci#define lsf1_MARKER			MAKE_MARKER ('l', 's', 'f', '1')
49b815c7f3Sopenharmony_ci
50b815c7f3Sopenharmony_ci#define STR_MARKER			MAKE_MARKER ('S', 'T', 'R', ' ')
51b815c7f3Sopenharmony_ci#define sdML_MARKER			MAKE_MARKER ('s', 'd', 'M', 'L')
52b815c7f3Sopenharmony_ci
53b815c7f3Sopenharmony_cienum
54b815c7f3Sopenharmony_ci{	RSRC_STR = 111,
55b815c7f3Sopenharmony_ci	RSRC_BIN
56b815c7f3Sopenharmony_ci} ;
57b815c7f3Sopenharmony_ci
58b815c7f3Sopenharmony_citypedef struct
59b815c7f3Sopenharmony_ci{	unsigned char * rsrc_data ;
60b815c7f3Sopenharmony_ci	int rsrc_len ;
61b815c7f3Sopenharmony_ci	int need_to_free_rsrc_data ;
62b815c7f3Sopenharmony_ci
63b815c7f3Sopenharmony_ci	int data_offset, data_length ;
64b815c7f3Sopenharmony_ci	int map_offset, map_length ;
65b815c7f3Sopenharmony_ci
66b815c7f3Sopenharmony_ci	int type_count, type_offset ;
67b815c7f3Sopenharmony_ci	int item_offset ;
68b815c7f3Sopenharmony_ci
69b815c7f3Sopenharmony_ci	int str_index, str_count ;
70b815c7f3Sopenharmony_ci
71b815c7f3Sopenharmony_ci	int string_offset ;
72b815c7f3Sopenharmony_ci
73b815c7f3Sopenharmony_ci	/* All the above just to get these three. */
74b815c7f3Sopenharmony_ci	int sample_size, sample_rate, channels ;
75b815c7f3Sopenharmony_ci} SD2_RSRC ;
76b815c7f3Sopenharmony_ci
77b815c7f3Sopenharmony_citypedef struct
78b815c7f3Sopenharmony_ci{	int type ;
79b815c7f3Sopenharmony_ci	int id ;
80b815c7f3Sopenharmony_ci	char name [32] ;
81b815c7f3Sopenharmony_ci	char value [32] ;
82b815c7f3Sopenharmony_ci	int value_len ;
83b815c7f3Sopenharmony_ci} STR_RSRC ;
84b815c7f3Sopenharmony_ci
85b815c7f3Sopenharmony_ci/*------------------------------------------------------------------------------
86b815c7f3Sopenharmony_ci * Private static functions.
87b815c7f3Sopenharmony_ci*/
88b815c7f3Sopenharmony_ci
89b815c7f3Sopenharmony_cistatic int sd2_close	(SF_PRIVATE *psf) ;
90b815c7f3Sopenharmony_ci
91b815c7f3Sopenharmony_cistatic int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ;
92b815c7f3Sopenharmony_cistatic int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ;
93b815c7f3Sopenharmony_ci
94b815c7f3Sopenharmony_cistatic int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ;
95b815c7f3Sopenharmony_ci
96b815c7f3Sopenharmony_ci/*------------------------------------------------------------------------------
97b815c7f3Sopenharmony_ci** Public functions.
98b815c7f3Sopenharmony_ci*/
99b815c7f3Sopenharmony_ci
100b815c7f3Sopenharmony_ciint
101b815c7f3Sopenharmony_cisd2_open (SF_PRIVATE *psf)
102b815c7f3Sopenharmony_ci{	int subformat, error = 0, valid ;
103b815c7f3Sopenharmony_ci
104b815c7f3Sopenharmony_ci	/* SD2 is always big endian. */
105b815c7f3Sopenharmony_ci	psf->endian = SF_ENDIAN_BIG ;
106b815c7f3Sopenharmony_ci
107b815c7f3Sopenharmony_ci	if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->rsrclength > 0))
108b815c7f3Sopenharmony_ci	{	psf_use_rsrc (psf, SF_TRUE) ;
109b815c7f3Sopenharmony_ci		valid = psf_file_valid (psf) ;
110b815c7f3Sopenharmony_ci		psf_use_rsrc (psf, SF_FALSE) ;
111b815c7f3Sopenharmony_ci		if (! valid)
112b815c7f3Sopenharmony_ci		{	psf_log_printf (psf, "sd2_open : psf->rsrc.filedes < 0\n") ;
113b815c7f3Sopenharmony_ci			return SFE_SD2_BAD_RSRC ;
114b815c7f3Sopenharmony_ci			} ;
115b815c7f3Sopenharmony_ci
116b815c7f3Sopenharmony_ci		error = sd2_parse_rsrc_fork (psf) ;
117b815c7f3Sopenharmony_ci
118b815c7f3Sopenharmony_ci		if (error)
119b815c7f3Sopenharmony_ci			goto error_cleanup ;
120b815c7f3Sopenharmony_ci		} ;
121b815c7f3Sopenharmony_ci
122b815c7f3Sopenharmony_ci	if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_SD2)
123b815c7f3Sopenharmony_ci	{	error = SFE_BAD_OPEN_FORMAT ;
124b815c7f3Sopenharmony_ci		goto error_cleanup ;
125b815c7f3Sopenharmony_ci		} ;
126b815c7f3Sopenharmony_ci
127b815c7f3Sopenharmony_ci	subformat = SF_CODEC (psf->sf.format) ;
128b815c7f3Sopenharmony_ci	psf->dataoffset = 0 ;
129b815c7f3Sopenharmony_ci
130b815c7f3Sopenharmony_ci	/* Only open and write the resource in RDWR mode is its current length is zero. */
131b815c7f3Sopenharmony_ci	if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->rsrclength == 0))
132b815c7f3Sopenharmony_ci	{	psf->rsrc.mode = psf->file.mode ;
133b815c7f3Sopenharmony_ci		psf_open_rsrc (psf) ;
134b815c7f3Sopenharmony_ci
135b815c7f3Sopenharmony_ci		error = sd2_write_rsrc_fork (psf, SF_FALSE) ;
136b815c7f3Sopenharmony_ci
137b815c7f3Sopenharmony_ci		if (error)
138b815c7f3Sopenharmony_ci			goto error_cleanup ;
139b815c7f3Sopenharmony_ci
140b815c7f3Sopenharmony_ci		/* Not needed. */
141b815c7f3Sopenharmony_ci		psf->write_header = NULL ;
142b815c7f3Sopenharmony_ci		} ;
143b815c7f3Sopenharmony_ci
144b815c7f3Sopenharmony_ci	psf->container_close = sd2_close ;
145b815c7f3Sopenharmony_ci
146b815c7f3Sopenharmony_ci	psf->blockwidth = psf->bytewidth * psf->sf.channels ;
147b815c7f3Sopenharmony_ci
148b815c7f3Sopenharmony_ci	switch (subformat)
149b815c7f3Sopenharmony_ci	{	case SF_FORMAT_PCM_S8 :	/* 8-bit linear PCM. */
150b815c7f3Sopenharmony_ci		case SF_FORMAT_PCM_16 :	/* 16-bit linear PCM. */
151b815c7f3Sopenharmony_ci		case SF_FORMAT_PCM_24 :	/* 24-bit linear PCM */
152b815c7f3Sopenharmony_ci		case SF_FORMAT_PCM_32 :	/* 32-bit linear PCM */
153b815c7f3Sopenharmony_ci				error = pcm_init (psf) ;
154b815c7f3Sopenharmony_ci				break ;
155b815c7f3Sopenharmony_ci
156b815c7f3Sopenharmony_ci		default :
157b815c7f3Sopenharmony_ci				error = SFE_UNIMPLEMENTED ;
158b815c7f3Sopenharmony_ci				break ;
159b815c7f3Sopenharmony_ci		} ;
160b815c7f3Sopenharmony_ci
161b815c7f3Sopenharmony_ci	psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
162b815c7f3Sopenharmony_ci
163b815c7f3Sopenharmony_cierror_cleanup:
164b815c7f3Sopenharmony_ci
165b815c7f3Sopenharmony_ci	/* Close the resource fork regardless. We won't need it again. */
166b815c7f3Sopenharmony_ci	psf_close_rsrc (psf) ;
167b815c7f3Sopenharmony_ci
168b815c7f3Sopenharmony_ci	return error ;
169b815c7f3Sopenharmony_ci} /* sd2_open */
170b815c7f3Sopenharmony_ci
171b815c7f3Sopenharmony_ci/*------------------------------------------------------------------------------
172b815c7f3Sopenharmony_ci*/
173b815c7f3Sopenharmony_ci
174b815c7f3Sopenharmony_cistatic int
175b815c7f3Sopenharmony_cisd2_close	(SF_PRIVATE *psf)
176b815c7f3Sopenharmony_ci{
177b815c7f3Sopenharmony_ci	if (psf->file.mode == SFM_WRITE)
178b815c7f3Sopenharmony_ci	{	/*  Now we know for certain the audio_length of the file we can re-write
179b815c7f3Sopenharmony_ci		**	correct values for the FORM, 8SVX and BODY chunks.
180b815c7f3Sopenharmony_ci		*/
181b815c7f3Sopenharmony_ci
182b815c7f3Sopenharmony_ci		} ;
183b815c7f3Sopenharmony_ci
184b815c7f3Sopenharmony_ci	return 0 ;
185b815c7f3Sopenharmony_ci} /* sd2_close */
186b815c7f3Sopenharmony_ci
187b815c7f3Sopenharmony_ci/*------------------------------------------------------------------------------
188b815c7f3Sopenharmony_ci*/
189b815c7f3Sopenharmony_ci
190b815c7f3Sopenharmony_cistatic int
191b815c7f3Sopenharmony_cisd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
192b815c7f3Sopenharmony_ci{	SD2_RSRC rsrc ;
193b815c7f3Sopenharmony_ci	STR_RSRC str_rsrc [] =
194b815c7f3Sopenharmony_ci	{	{ RSRC_STR, 1000, "_sample-size", "", 0 },
195b815c7f3Sopenharmony_ci		{ RSRC_STR, 1001, "_sample-rate", "", 0 },
196b815c7f3Sopenharmony_ci		{ RSRC_STR, 1002, "_channels", "", 0 },
197b815c7f3Sopenharmony_ci		{ RSRC_BIN, 1000, "_Markers", "", 8 }
198b815c7f3Sopenharmony_ci		} ;
199b815c7f3Sopenharmony_ci
200b815c7f3Sopenharmony_ci	int k, str_offset, data_offset, next_str ;
201b815c7f3Sopenharmony_ci
202b815c7f3Sopenharmony_ci	psf_use_rsrc (psf, SF_TRUE) ;
203b815c7f3Sopenharmony_ci
204b815c7f3Sopenharmony_ci	memset (&rsrc, 0, sizeof (rsrc)) ;
205b815c7f3Sopenharmony_ci
206b815c7f3Sopenharmony_ci	rsrc.sample_rate = psf->sf.samplerate ;
207b815c7f3Sopenharmony_ci	rsrc.sample_size = psf->bytewidth ;
208b815c7f3Sopenharmony_ci	rsrc.channels = psf->sf.channels ;
209b815c7f3Sopenharmony_ci
210b815c7f3Sopenharmony_ci	rsrc.rsrc_data = psf->header.ptr ;
211b815c7f3Sopenharmony_ci	rsrc.rsrc_len = psf->header.len ;
212b815c7f3Sopenharmony_ci	memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ;
213b815c7f3Sopenharmony_ci
214b815c7f3Sopenharmony_ci	snprintf (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ;
215b815c7f3Sopenharmony_ci	snprintf (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ;
216b815c7f3Sopenharmony_ci	snprintf (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels) ;
217b815c7f3Sopenharmony_ci
218b815c7f3Sopenharmony_ci	for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
219b815c7f3Sopenharmony_ci	{	if (str_rsrc [k].value_len == 0)
220b815c7f3Sopenharmony_ci		{	str_rsrc [k].value_len = strlen (str_rsrc [k].value) ;
221b815c7f3Sopenharmony_ci			str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ;
222b815c7f3Sopenharmony_ci			} ;
223b815c7f3Sopenharmony_ci
224b815c7f3Sopenharmony_ci		/* Turn name string into a pascal string. */
225b815c7f3Sopenharmony_ci		str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ;
226b815c7f3Sopenharmony_ci		} ;
227b815c7f3Sopenharmony_ci
228b815c7f3Sopenharmony_ci	rsrc.data_offset = 0x100 ;
229b815c7f3Sopenharmony_ci
230b815c7f3Sopenharmony_ci	/*
231b815c7f3Sopenharmony_ci	** Calculate data length :
232b815c7f3Sopenharmony_ci	**		length of strings, plus the length of the sdML chunk.
233b815c7f3Sopenharmony_ci	*/
234b815c7f3Sopenharmony_ci	rsrc.data_length = 0 ;
235b815c7f3Sopenharmony_ci	for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
236b815c7f3Sopenharmony_ci		rsrc.data_length += str_rsrc [k].value_len + 4 ;
237b815c7f3Sopenharmony_ci
238b815c7f3Sopenharmony_ci	rsrc.map_offset = rsrc.data_offset + rsrc.data_length ;
239b815c7f3Sopenharmony_ci
240b815c7f3Sopenharmony_ci	/* Very start of resource fork. */
241b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "E444", BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ;
242b815c7f3Sopenharmony_ci
243b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Eop", BHWo (0x30), BHWp (psf->file.name)) ;
244b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Eo2mm", BHWo (0x50), BHW2 (0), BHWm (Sd2f_MARKER), BHWm (lsf1_MARKER)) ;
245b815c7f3Sopenharmony_ci
246b815c7f3Sopenharmony_ci	/* Very start of resource map. */
247b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "E4444", BHW4 (rsrc.map_offset), BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ;
248b815c7f3Sopenharmony_ci
249b815c7f3Sopenharmony_ci	/* These I don't currently understand. */
250b815c7f3Sopenharmony_ci	if (1)
251b815c7f3Sopenharmony_ci	{	psf_binheader_writef (psf, "Eo1422", BHWo (rsrc.map_offset + 16), BHW1 (1), BHW4 (0x12345678), BHW2 (0xabcd), BHW2 (0)) ;
252b815c7f3Sopenharmony_ci		} ;
253b815c7f3Sopenharmony_ci
254b815c7f3Sopenharmony_ci	/* Resource type offset. */
255b815c7f3Sopenharmony_ci	rsrc.type_offset = rsrc.map_offset + 30 ;
256b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 24), BHW2 (rsrc.type_offset - rsrc.map_offset - 2)) ;
257b815c7f3Sopenharmony_ci
258b815c7f3Sopenharmony_ci	/* Type index max. */
259b815c7f3Sopenharmony_ci	rsrc.type_count = 2 ;
260b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 28), BHW2 (rsrc.type_count - 1)) ;
261b815c7f3Sopenharmony_ci
262b815c7f3Sopenharmony_ci	rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
263b815c7f3Sopenharmony_ci
264b815c7f3Sopenharmony_ci	rsrc.str_count = ARRAY_LEN (str_rsrc) ;
265b815c7f3Sopenharmony_ci	rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ;
266b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Eo2", BHWo (rsrc.map_offset + 26), BHW2 (rsrc.string_offset)) ;
267b815c7f3Sopenharmony_ci
268b815c7f3Sopenharmony_ci	/* Write 'STR ' resource type. */
269b815c7f3Sopenharmony_ci	rsrc.str_count = 3 ;
270b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Eom22", BHWo (rsrc.type_offset), BHWm (STR_MARKER), BHW2 (rsrc.str_count - 1), BHW2 (0x12)) ;
271b815c7f3Sopenharmony_ci
272b815c7f3Sopenharmony_ci	/* Write 'sdML' resource type. */
273b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Em22", BHWm (sdML_MARKER), BHW2 (0), BHW2 (0x36)) ;
274b815c7f3Sopenharmony_ci
275b815c7f3Sopenharmony_ci	str_offset = rsrc.map_offset + rsrc.string_offset ;
276b815c7f3Sopenharmony_ci	next_str = 0 ;
277b815c7f3Sopenharmony_ci	data_offset = rsrc.data_offset ;
278b815c7f3Sopenharmony_ci	for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
279b815c7f3Sopenharmony_ci	{	psf_binheader_writef (psf, "Eop", BHWo (str_offset), BHWp (str_rsrc [k].name)) ;
280b815c7f3Sopenharmony_ci		psf_binheader_writef (psf, "Eo22", BHWo (rsrc.item_offset + k * 12), BHW2 (str_rsrc [k].id), BHW2 (next_str)) ;
281b815c7f3Sopenharmony_ci
282b815c7f3Sopenharmony_ci		str_offset += strlen (str_rsrc [k].name) ;
283b815c7f3Sopenharmony_ci		next_str += strlen (str_rsrc [k].name) ;
284b815c7f3Sopenharmony_ci
285b815c7f3Sopenharmony_ci		psf_binheader_writef (psf, "Eo4", BHWo (rsrc.item_offset + k * 12 + 4), BHW4 (data_offset - rsrc.data_offset)) ;
286b815c7f3Sopenharmony_ci		psf_binheader_writef (psf, "Eo4", BHWo (data_offset), BHW4 (str_rsrc [k].value_len)) ;
287b815c7f3Sopenharmony_ci
288b815c7f3Sopenharmony_ci		psf_binheader_writef (psf, "Eob", BHWo (data_offset + 4), BHWv (str_rsrc [k].value), BHWz (str_rsrc [k].value_len)) ;
289b815c7f3Sopenharmony_ci		data_offset += 4 + str_rsrc [k].value_len ;
290b815c7f3Sopenharmony_ci		} ;
291b815c7f3Sopenharmony_ci
292b815c7f3Sopenharmony_ci	/* Finally, calculate and set map length. */
293b815c7f3Sopenharmony_ci	rsrc.map_length = str_offset - rsrc.map_offset ;
294b815c7f3Sopenharmony_ci	psf_binheader_writef (psf, "Eo4o4", BHWo (12), BHW4 (rsrc.map_length),
295b815c7f3Sopenharmony_ci							BHWo (rsrc.map_offset + 12), BHW4 (rsrc.map_length)) ;
296b815c7f3Sopenharmony_ci
297b815c7f3Sopenharmony_ci	psf->header.indx = rsrc.map_offset + rsrc.map_length ;
298b815c7f3Sopenharmony_ci
299b815c7f3Sopenharmony_ci	psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
300b815c7f3Sopenharmony_ci
301b815c7f3Sopenharmony_ci	psf_use_rsrc (psf, SF_FALSE) ;
302b815c7f3Sopenharmony_ci
303b815c7f3Sopenharmony_ci	if (psf->error)
304b815c7f3Sopenharmony_ci		return psf->error ;
305b815c7f3Sopenharmony_ci
306b815c7f3Sopenharmony_ci	return 0 ;
307b815c7f3Sopenharmony_ci} /* sd2_write_rsrc_fork */
308b815c7f3Sopenharmony_ci
309b815c7f3Sopenharmony_ci/*------------------------------------------------------------------------------
310b815c7f3Sopenharmony_ci*/
311b815c7f3Sopenharmony_ci
312b815c7f3Sopenharmony_cistatic inline int
313b815c7f3Sopenharmony_ciread_rsrc_char (const SD2_RSRC *prsrc, int offset)
314b815c7f3Sopenharmony_ci{	const unsigned char * data = prsrc->rsrc_data ;
315b815c7f3Sopenharmony_ci	if (offset < 0 || offset >= prsrc->rsrc_len)
316b815c7f3Sopenharmony_ci		return 0 ;
317b815c7f3Sopenharmony_ci	return data [offset] ;
318b815c7f3Sopenharmony_ci} /* read_rsrc_char */
319b815c7f3Sopenharmony_ci
320b815c7f3Sopenharmony_cistatic inline int
321b815c7f3Sopenharmony_ciread_rsrc_short (const SD2_RSRC *prsrc, int offset)
322b815c7f3Sopenharmony_ci{	const unsigned char * data = prsrc->rsrc_data ;
323b815c7f3Sopenharmony_ci	if (offset < 0 || offset + 1 >= prsrc->rsrc_len)
324b815c7f3Sopenharmony_ci		return 0 ;
325b815c7f3Sopenharmony_ci	return (data [offset] << 8) + data [offset + 1] ;
326b815c7f3Sopenharmony_ci} /* read_rsrc_short */
327b815c7f3Sopenharmony_ci
328b815c7f3Sopenharmony_cistatic inline int
329b815c7f3Sopenharmony_ciread_rsrc_int (const SD2_RSRC *prsrc, int offset)
330b815c7f3Sopenharmony_ci{	const unsigned char * data = prsrc->rsrc_data ;
331b815c7f3Sopenharmony_ci	if (offset < 0 || offset + 3 >= prsrc->rsrc_len)
332b815c7f3Sopenharmony_ci		return 0 ;
333b815c7f3Sopenharmony_ci	return (((uint32_t) data [offset]) << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
334b815c7f3Sopenharmony_ci} /* read_rsrc_int */
335b815c7f3Sopenharmony_ci
336b815c7f3Sopenharmony_cistatic inline int
337b815c7f3Sopenharmony_ciread_rsrc_marker (const SD2_RSRC *prsrc, int offset)
338b815c7f3Sopenharmony_ci{	const unsigned char * data = prsrc->rsrc_data ;
339b815c7f3Sopenharmony_ci
340b815c7f3Sopenharmony_ci	if (offset < 0 || offset + 3 >= prsrc->rsrc_len)
341b815c7f3Sopenharmony_ci		return 0 ;
342b815c7f3Sopenharmony_ci
343b815c7f3Sopenharmony_ci	if (CPU_IS_BIG_ENDIAN)
344b815c7f3Sopenharmony_ci		return (((uint32_t) data [offset]) << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
345b815c7f3Sopenharmony_ci	if (CPU_IS_LITTLE_ENDIAN)
346b815c7f3Sopenharmony_ci		return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (((uint32_t) data [offset + 3]) << 24) ;
347b815c7f3Sopenharmony_ci
348b815c7f3Sopenharmony_ci	return 0 ;
349b815c7f3Sopenharmony_ci} /* read_rsrc_marker */
350b815c7f3Sopenharmony_ci
351b815c7f3Sopenharmony_cistatic void
352b815c7f3Sopenharmony_ciread_rsrc_str (const SD2_RSRC *prsrc, int offset, char * buffer, int buffer_len)
353b815c7f3Sopenharmony_ci{	const unsigned char * data = prsrc->rsrc_data ;
354b815c7f3Sopenharmony_ci	int k ;
355b815c7f3Sopenharmony_ci
356b815c7f3Sopenharmony_ci	memset (buffer, 0, buffer_len) ;
357b815c7f3Sopenharmony_ci
358b815c7f3Sopenharmony_ci	if (offset < 0 || offset + buffer_len >= prsrc->rsrc_len)
359b815c7f3Sopenharmony_ci		return ;
360b815c7f3Sopenharmony_ci
361b815c7f3Sopenharmony_ci	for (k = 0 ; k < buffer_len - 1 ; k++)
362b815c7f3Sopenharmony_ci	{	if (psf_isprint (data [offset + k]) == 0)
363b815c7f3Sopenharmony_ci			return ;
364b815c7f3Sopenharmony_ci		buffer [k] = data [offset + k] ;
365b815c7f3Sopenharmony_ci		} ;
366b815c7f3Sopenharmony_ci	return ;
367b815c7f3Sopenharmony_ci} /* read_rsrc_str */
368b815c7f3Sopenharmony_ci
369b815c7f3Sopenharmony_cistatic int
370b815c7f3Sopenharmony_cisd2_parse_rsrc_fork (SF_PRIVATE *psf)
371b815c7f3Sopenharmony_ci{	SD2_RSRC rsrc ;
372b815c7f3Sopenharmony_ci	int k, marker, error = 0 ;
373b815c7f3Sopenharmony_ci
374b815c7f3Sopenharmony_ci	psf_use_rsrc (psf, SF_TRUE) ;
375b815c7f3Sopenharmony_ci
376b815c7f3Sopenharmony_ci	memset (&rsrc, 0, sizeof (rsrc)) ;
377b815c7f3Sopenharmony_ci
378b815c7f3Sopenharmony_ci	rsrc.rsrc_len = psf_get_filelen (psf) ;
379b815c7f3Sopenharmony_ci	psf_log_printf (psf, "Resource length : %d (0x%04X)\n", rsrc.rsrc_len, rsrc.rsrc_len) ;
380b815c7f3Sopenharmony_ci
381b815c7f3Sopenharmony_ci	if (rsrc.rsrc_len > psf->header.len)
382b815c7f3Sopenharmony_ci	{	rsrc.rsrc_data = calloc (1, rsrc.rsrc_len) ;
383b815c7f3Sopenharmony_ci		rsrc.need_to_free_rsrc_data = SF_TRUE ;
384b815c7f3Sopenharmony_ci		}
385b815c7f3Sopenharmony_ci	else
386b815c7f3Sopenharmony_ci	{
387b815c7f3Sopenharmony_ci		rsrc.rsrc_data = psf->header.ptr ;
388b815c7f3Sopenharmony_ci		// rsrc.rsrc_len > psf->header.len ;
389b815c7f3Sopenharmony_ci		rsrc.need_to_free_rsrc_data = SF_FALSE ;
390b815c7f3Sopenharmony_ci		} ;
391b815c7f3Sopenharmony_ci
392b815c7f3Sopenharmony_ci	/* Read in the whole lot. */
393b815c7f3Sopenharmony_ci	psf_fread (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
394b815c7f3Sopenharmony_ci
395b815c7f3Sopenharmony_ci	/* Reset the header storage because we have changed to the rsrcdes. */
396b815c7f3Sopenharmony_ci	psf->header.indx = psf->header.end = rsrc.rsrc_len ;
397b815c7f3Sopenharmony_ci
398b815c7f3Sopenharmony_ci	rsrc.data_offset = read_rsrc_int (&rsrc, 0) ;
399b815c7f3Sopenharmony_ci	rsrc.map_offset = read_rsrc_int (&rsrc, 4) ;
400b815c7f3Sopenharmony_ci	rsrc.data_length = read_rsrc_int (&rsrc, 8) ;
401b815c7f3Sopenharmony_ci	rsrc.map_length = read_rsrc_int (&rsrc, 12) ;
402b815c7f3Sopenharmony_ci
403b815c7f3Sopenharmony_ci	if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000)
404b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ;
405b815c7f3Sopenharmony_ci		rsrc.data_offset = read_rsrc_int (&rsrc, 0x52 + 0) + 0x52 ;
406b815c7f3Sopenharmony_ci		rsrc.map_offset = read_rsrc_int (&rsrc, 0x52 + 4) + 0x52 ;
407b815c7f3Sopenharmony_ci		rsrc.data_length = read_rsrc_int (&rsrc, 0x52 + 8) ;
408b815c7f3Sopenharmony_ci		rsrc.map_length = read_rsrc_int (&rsrc, 0x52 + 12) ;
409b815c7f3Sopenharmony_ci		} ;
410b815c7f3Sopenharmony_ci
411b815c7f3Sopenharmony_ci	psf_log_printf (psf, "  data offset : 0x%04X\n  map  offset : 0x%04X\n"
412b815c7f3Sopenharmony_ci				"  data length : 0x%04X\n  map  length : 0x%04X\n",
413b815c7f3Sopenharmony_ci				rsrc.data_offset, rsrc.map_offset, rsrc.data_length, rsrc.map_length) ;
414b815c7f3Sopenharmony_ci
415b815c7f3Sopenharmony_ci	if (rsrc.data_offset > rsrc.rsrc_len)
416b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Error : rsrc.data_offset (%d, 0x%x) > len\n", rsrc.data_offset, rsrc.data_offset) ;
417b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_DATA_OFFSET ;
418b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
419b815c7f3Sopenharmony_ci		} ;
420b815c7f3Sopenharmony_ci
421b815c7f3Sopenharmony_ci	if (rsrc.map_offset > rsrc.rsrc_len)
422b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Error : rsrc.map_offset > len\n") ;
423b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_MAP_OFFSET ;
424b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
425b815c7f3Sopenharmony_ci		} ;
426b815c7f3Sopenharmony_ci
427b815c7f3Sopenharmony_ci	if (rsrc.data_length > rsrc.rsrc_len)
428b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Error : rsrc.data_length > len\n") ;
429b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_DATA_LENGTH ;
430b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
431b815c7f3Sopenharmony_ci		} ;
432b815c7f3Sopenharmony_ci
433b815c7f3Sopenharmony_ci	if (rsrc.map_length > rsrc.rsrc_len)
434b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Error : rsrc.map_length > len\n") ;
435b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_MAP_LENGTH ;
436b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
437b815c7f3Sopenharmony_ci		} ;
438b815c7f3Sopenharmony_ci
439b815c7f3Sopenharmony_ci	if (rsrc.data_offset + rsrc.data_length != rsrc.map_offset || rsrc.map_offset + rsrc.map_length != rsrc.rsrc_len)
440b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Error : This does not look like a MacOSX resource fork.\n") ;
441b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_RSRC ;
442b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
443b815c7f3Sopenharmony_ci		} ;
444b815c7f3Sopenharmony_ci
445b815c7f3Sopenharmony_ci	if (rsrc.map_offset + 28 >= rsrc.rsrc_len)
446b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Bad map offset (%d + 28 > %d).\n", rsrc.map_offset, rsrc.rsrc_len) ;
447b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_RSRC ;
448b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
449b815c7f3Sopenharmony_ci		} ;
450b815c7f3Sopenharmony_ci
451b815c7f3Sopenharmony_ci	rsrc.string_offset = rsrc.map_offset + read_rsrc_short (&rsrc, rsrc.map_offset + 26) ;
452b815c7f3Sopenharmony_ci	if (rsrc.string_offset > rsrc.rsrc_len)
453b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ;
454b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_RSRC ;
455b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
456b815c7f3Sopenharmony_ci		} ;
457b815c7f3Sopenharmony_ci
458b815c7f3Sopenharmony_ci	rsrc.type_offset = rsrc.map_offset + 30 ;
459b815c7f3Sopenharmony_ci
460b815c7f3Sopenharmony_ci	if (rsrc.map_offset + 28 > rsrc.rsrc_len)
461b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Bad map offset.\n") ;
462b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
463b815c7f3Sopenharmony_ci		} ;
464b815c7f3Sopenharmony_ci
465b815c7f3Sopenharmony_ci	rsrc.type_count = read_rsrc_short (&rsrc, rsrc.map_offset + 28) + 1 ;
466b815c7f3Sopenharmony_ci	if (rsrc.type_count < 1)
467b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Bad type count.\n") ;
468b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_RSRC ;
469b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
470b815c7f3Sopenharmony_ci		} ;
471b815c7f3Sopenharmony_ci
472b815c7f3Sopenharmony_ci	rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
473b815c7f3Sopenharmony_ci	if (rsrc.item_offset < 0 || rsrc.item_offset > rsrc.rsrc_len)
474b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Bad item offset (%d).\n", rsrc.item_offset) ;
475b815c7f3Sopenharmony_ci		error = SFE_SD2_BAD_RSRC ;
476b815c7f3Sopenharmony_ci		goto parse_rsrc_fork_cleanup ;
477b815c7f3Sopenharmony_ci		} ;
478b815c7f3Sopenharmony_ci
479b815c7f3Sopenharmony_ci	rsrc.str_index = -1 ;
480b815c7f3Sopenharmony_ci	for (k = 0 ; k < rsrc.type_count ; k ++)
481b815c7f3Sopenharmony_ci	{	if (rsrc.type_offset + k * 8 > rsrc.rsrc_len)
482b815c7f3Sopenharmony_ci		{	psf_log_printf (psf, "Bad rsrc marker.\n") ;
483b815c7f3Sopenharmony_ci			goto parse_rsrc_fork_cleanup ;
484b815c7f3Sopenharmony_ci			} ;
485b815c7f3Sopenharmony_ci
486b815c7f3Sopenharmony_ci		marker = read_rsrc_marker (&rsrc, rsrc.type_offset + k * 8) ;
487b815c7f3Sopenharmony_ci
488b815c7f3Sopenharmony_ci		if (marker == STR_MARKER)
489b815c7f3Sopenharmony_ci		{	rsrc.str_index = k ;
490b815c7f3Sopenharmony_ci			rsrc.str_count = read_rsrc_short (&rsrc, rsrc.type_offset + k * 8 + 4) + 1 ;
491b815c7f3Sopenharmony_ci			error = parse_str_rsrc (psf, &rsrc) ;
492b815c7f3Sopenharmony_ci			goto parse_rsrc_fork_cleanup ;
493b815c7f3Sopenharmony_ci			} ;
494b815c7f3Sopenharmony_ci		} ;
495b815c7f3Sopenharmony_ci
496b815c7f3Sopenharmony_ci	psf_log_printf (psf, "No 'STR ' resource.\n") ;
497b815c7f3Sopenharmony_ci	error = SFE_SD2_BAD_RSRC ;
498b815c7f3Sopenharmony_ci
499b815c7f3Sopenharmony_ciparse_rsrc_fork_cleanup :
500b815c7f3Sopenharmony_ci
501b815c7f3Sopenharmony_ci	psf_use_rsrc (psf, SF_FALSE) ;
502b815c7f3Sopenharmony_ci
503b815c7f3Sopenharmony_ci	if (rsrc.need_to_free_rsrc_data)
504b815c7f3Sopenharmony_ci		free (rsrc.rsrc_data) ;
505b815c7f3Sopenharmony_ci
506b815c7f3Sopenharmony_ci	return error ;
507b815c7f3Sopenharmony_ci} /* sd2_parse_rsrc_fork */
508b815c7f3Sopenharmony_ci
509b815c7f3Sopenharmony_cistatic int
510b815c7f3Sopenharmony_ciparse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
511b815c7f3Sopenharmony_ci{	char name [32], value [32] ;
512b815c7f3Sopenharmony_ci	int k, str_offset, rsrc_id, data_offset = 0, data_len = 0 ;
513b815c7f3Sopenharmony_ci
514b815c7f3Sopenharmony_ci	psf_log_printf (psf, "Finding parameters :\n") ;
515b815c7f3Sopenharmony_ci
516b815c7f3Sopenharmony_ci	str_offset = rsrc->string_offset ;
517b815c7f3Sopenharmony_ci	psf_log_printf (psf, "  Offset    RsrcId    dlen    slen    Value\n") ;
518b815c7f3Sopenharmony_ci
519b815c7f3Sopenharmony_ci
520b815c7f3Sopenharmony_ci	for (k = 0 ; data_offset + data_len < rsrc->rsrc_len ; k++)
521b815c7f3Sopenharmony_ci	{	int slen ;
522b815c7f3Sopenharmony_ci
523b815c7f3Sopenharmony_ci		slen = read_rsrc_char (rsrc, str_offset) ;
524b815c7f3Sopenharmony_ci		read_rsrc_str (rsrc, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
525b815c7f3Sopenharmony_ci		str_offset += slen + 1 ;
526b815c7f3Sopenharmony_ci
527b815c7f3Sopenharmony_ci		// work-around for GitHub issue #340
528b815c7f3Sopenharmony_ci		int id_offset = rsrc->item_offset + k * 12 ;
529b815c7f3Sopenharmony_ci		if (id_offset < 0 || id_offset + 1 >= rsrc->rsrc_len)
530b815c7f3Sopenharmony_ci		{	psf_log_printf (psf, "Exiting parser on id_offset of %d.\n", id_offset) ;
531b815c7f3Sopenharmony_ci			break ;
532b815c7f3Sopenharmony_ci			}
533b815c7f3Sopenharmony_ci		rsrc_id = read_rsrc_short (rsrc, id_offset) ;
534b815c7f3Sopenharmony_ci
535b815c7f3Sopenharmony_ci		data_offset = rsrc->data_offset + read_rsrc_int (rsrc, rsrc->item_offset + k * 12 + 4) ;
536b815c7f3Sopenharmony_ci		if (data_offset < 0 || data_offset > rsrc->rsrc_len)
537b815c7f3Sopenharmony_ci		{	psf_log_printf (psf, "Exiting parser on data offset of %d.\n", data_offset) ;
538b815c7f3Sopenharmony_ci			break ;
539b815c7f3Sopenharmony_ci			} ;
540b815c7f3Sopenharmony_ci
541b815c7f3Sopenharmony_ci		data_len = read_rsrc_int (rsrc, data_offset) ;
542b815c7f3Sopenharmony_ci		if (data_len < 0 || data_len > rsrc->rsrc_len)
543b815c7f3Sopenharmony_ci		{	psf_log_printf (psf, "Exiting parser on data length of %d.\n", data_len) ;
544b815c7f3Sopenharmony_ci			break ;
545b815c7f3Sopenharmony_ci			} ;
546b815c7f3Sopenharmony_ci
547b815c7f3Sopenharmony_ci		slen = read_rsrc_char (rsrc, data_offset + 4) ;
548b815c7f3Sopenharmony_ci		read_rsrc_str (rsrc, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ;
549b815c7f3Sopenharmony_ci
550b815c7f3Sopenharmony_ci		psf_log_printf (psf, "  0x%04x     %4d     %4d     %3d    '%s'\n", data_offset, rsrc_id, data_len, slen, value) ;
551b815c7f3Sopenharmony_ci
552b815c7f3Sopenharmony_ci		if (strstr (value, "Photoshop"))
553b815c7f3Sopenharmony_ci		{	psf_log_printf (psf, "Exiting parser on Photoshop data.\n", data_offset) ;
554b815c7f3Sopenharmony_ci			break ;
555b815c7f3Sopenharmony_ci			} ;
556b815c7f3Sopenharmony_ci
557b815c7f3Sopenharmony_ci		if (rsrc_id == 1000 && rsrc->sample_size == 0)
558b815c7f3Sopenharmony_ci			rsrc->sample_size = strtol (value, NULL, 10) ;
559b815c7f3Sopenharmony_ci		else if (rsrc_id == 1001 && rsrc->sample_rate == 0)
560b815c7f3Sopenharmony_ci			rsrc->sample_rate = strtol (value, NULL, 10) ;
561b815c7f3Sopenharmony_ci		else if (rsrc_id == 1002 && rsrc->channels == 0)
562b815c7f3Sopenharmony_ci			rsrc->channels = strtol (value, NULL, 10) ;
563b815c7f3Sopenharmony_ci		} ;
564b815c7f3Sopenharmony_ci
565b815c7f3Sopenharmony_ci	psf_log_printf (psf, "Found Parameters :\n") ;
566b815c7f3Sopenharmony_ci	psf_log_printf (psf, "  sample-size : %d\n", rsrc->sample_size) ;
567b815c7f3Sopenharmony_ci	psf_log_printf (psf, "  sample-rate : %d\n", rsrc->sample_rate) ;
568b815c7f3Sopenharmony_ci	psf_log_printf (psf, "  channels    : %d\n", rsrc->channels) ;
569b815c7f3Sopenharmony_ci
570b815c7f3Sopenharmony_ci	if (rsrc->sample_rate <= 4 && rsrc->sample_size > 4)
571b815c7f3Sopenharmony_ci	{	int temp ;
572b815c7f3Sopenharmony_ci
573b815c7f3Sopenharmony_ci		psf_log_printf (psf, "Geez!! Looks like sample rate and sample size got switched.\nCorrecting this screw up.\n") ;
574b815c7f3Sopenharmony_ci		temp = rsrc->sample_rate ;
575b815c7f3Sopenharmony_ci		rsrc->sample_rate = rsrc->sample_size ;
576b815c7f3Sopenharmony_ci		rsrc->sample_size = temp ;
577b815c7f3Sopenharmony_ci		} ;
578b815c7f3Sopenharmony_ci
579b815c7f3Sopenharmony_ci	if (rsrc->sample_rate < 0)
580b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Bad sample rate (%d)\n", rsrc->sample_rate) ;
581b815c7f3Sopenharmony_ci		return SFE_SD2_BAD_RSRC ;
582b815c7f3Sopenharmony_ci		} ;
583b815c7f3Sopenharmony_ci
584b815c7f3Sopenharmony_ci	if (rsrc->channels < 0)
585b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Bad channel count (%d)\n", rsrc->channels) ;
586b815c7f3Sopenharmony_ci		return SFE_SD2_BAD_RSRC ;
587b815c7f3Sopenharmony_ci		} ;
588b815c7f3Sopenharmony_ci
589b815c7f3Sopenharmony_ci	psf->sf.samplerate = rsrc->sample_rate ;
590b815c7f3Sopenharmony_ci	psf->sf.channels = rsrc->channels ;
591b815c7f3Sopenharmony_ci	psf->bytewidth = rsrc->sample_size ;
592b815c7f3Sopenharmony_ci
593b815c7f3Sopenharmony_ci	switch (rsrc->sample_size)
594b815c7f3Sopenharmony_ci	{	case 1 :
595b815c7f3Sopenharmony_ci			psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_S8 ;
596b815c7f3Sopenharmony_ci			break ;
597b815c7f3Sopenharmony_ci
598b815c7f3Sopenharmony_ci		case 2 :
599b815c7f3Sopenharmony_ci			psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ;
600b815c7f3Sopenharmony_ci			break ;
601b815c7f3Sopenharmony_ci
602b815c7f3Sopenharmony_ci		case 3 :
603b815c7f3Sopenharmony_ci			psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ;
604b815c7f3Sopenharmony_ci			break ;
605b815c7f3Sopenharmony_ci
606b815c7f3Sopenharmony_ci		case 4 :
607b815c7f3Sopenharmony_ci			psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_32 ;
608b815c7f3Sopenharmony_ci			break ;
609b815c7f3Sopenharmony_ci
610b815c7f3Sopenharmony_ci		default :
611b815c7f3Sopenharmony_ci			psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ;
612b815c7f3Sopenharmony_ci			return SFE_SD2_BAD_SAMPLE_SIZE ;
613b815c7f3Sopenharmony_ci		} ;
614b815c7f3Sopenharmony_ci
615b815c7f3Sopenharmony_ci	psf_log_printf (psf, "ok\n") ;
616b815c7f3Sopenharmony_ci
617b815c7f3Sopenharmony_ci	return 0 ;
618b815c7f3Sopenharmony_ci} /* parse_str_rsrc */
619b815c7f3Sopenharmony_ci
620