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