int psf_set_string (SF_PRIVATE *psf, int str_type, const char *str) { if (psf->mode == SFM_READ) return SFE_STR_NOT_WRITE ; return psf_store_string (psf, str_type, str) ; } /* psf_set_string */
static int vorbis_read_header (SF_PRIVATE *psf, int log_data) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; char *buffer ; int bytes ; int i, nn ; odata->eos = 0 ; /* Weird stuff happens if these aren't called. */ ogg_stream_reset (&odata->ostream) ; ogg_sync_reset (&odata->osync) ; /* ** Grab some data at the head of the stream. We want the first page ** (which is guaranteed to be small and only contain the Vorbis ** stream initial header) We need the first page to get the stream ** serialno. */ /* Expose the buffer */ buffer = ogg_sync_buffer (&odata->osync, 4096L) ; /* Grab the part of the header that has already been read. */ memcpy (buffer, psf->header, psf->headindex) ; bytes = psf->headindex ; /* Submit a 4k block to libvorbis' Ogg layer */ bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ; ogg_sync_wrote (&odata->osync, bytes) ; /* Get the first page. */ if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1) { /* Have we simply run out of data? If so, we're done. */ if (bytes < 4096) return 0 ; /* Error case. Must not be Vorbis data */ psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ; return SFE_MALFORMED_FILE ; } ; /* ** Get the serial number and set up the rest of decode. ** Serialno first ; use it to set up a logical stream. */ ogg_stream_clear (&odata->ostream) ; ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ; if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0) { /* Error ; stream version mismatch perhaps. */ psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ; return SFE_MALFORMED_FILE ; } ; if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1) { /* No page? must not be vorbis. */ psf_log_printf (psf, "Error reading initial header packet.\n") ; return SFE_MALFORMED_FILE ; } ; /* ** This function (vorbis_read_header) gets called multiple times, so the OGG ** and vorbis structs have to be cleared every time we pass through to ** prevent memory leaks. */ vorbis_block_clear (&vdata->vblock) ; vorbis_dsp_clear (&vdata->vdsp) ; vorbis_comment_clear (&vdata->vcomment) ; vorbis_info_clear (&vdata->vinfo) ; /* ** Extract the initial header from the first page and verify that the ** Ogg bitstream is in fact Vorbis data. ** ** I handle the initial header first instead of just having the code ** read all three Vorbis headers at once because reading the initial ** header is an easy way to identify a Vorbis bitstream and it's ** useful to see that functionality seperated out. */ vorbis_info_init (&vdata->vinfo) ; vorbis_comment_init (&vdata->vcomment) ; if (vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) < 0) { /* Error case ; not a vorbis header. */ psf_log_printf (psf, "Found Vorbis in stream header, but vorbis_synthesis_headerin failed.\n") ; return SFE_MALFORMED_FILE ; } ; /* ** Common Ogg metadata fields? ** TITLE, VERSION, ALBUM, TRACKNUMBER, ARTIST, PERFORMER, COPYRIGHT, LICENSE, ** ORGANIZATION, DESCRIPTION, GENRE, DATE, LOCATION, CONTACT, ISRC, */ if (log_data) { int k ; for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++) { char *dd ; dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ; if (dd == NULL) continue ; psf_store_string (psf, vorbis_metatypes [k].id, dd) ; } ; } ; /* ** At this point, we're sure we're Vorbis. We've set up the logical (Ogg) ** bitstream decoder. Get the comment and codebook headers and set up the ** Vorbis decoder. ** ** The next two packets in order are the comment and codebook headers. ** They're likely large and may span multiple pages. Thus we reead ** and submit data until we get our two pacakets, watching that no ** pages are missing. If a page is missing, error out ; losing a ** header page is the only place where missing data is fatal. */ i = 0 ; /* Count of number of packets read */ while (i < 2) { int result = ogg_sync_pageout (&odata->osync, &odata->opage) ; if (result == 0) { /* Need more data */ buffer = ogg_sync_buffer (&odata->osync, 4096) ; bytes = psf_fread (buffer, 1, 4096, psf) ; if (bytes == 0 && i < 2) { psf_log_printf (psf, "End of file before finding all Vorbis headers!\n") ; return SFE_MALFORMED_FILE ; } ; nn = ogg_sync_wrote (&odata->osync, bytes) ; } else if (result == 1) { /* ** Don't complain about missing or corrupt data yet. We'll ** catch it at the packet output phase. ** ** We can ignore any errors here as they'll also become apparent ** at packetout. */ nn = ogg_stream_pagein (&odata->ostream, &odata->opage) ; while (i < 2) { result = ogg_stream_packetout (&odata->ostream, &odata->opacket) ; if (result == 0) break ; if (result < 0) { /* Uh oh ; data at some point was corrupted or missing! ** We can't tolerate that in a header. Die. */ psf_log_printf (psf, "Corrupt secondary header. Exiting.\n") ; return SFE_MALFORMED_FILE ; } ; vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) ; i++ ; } ; } ; } ; if (log_data) { int printed_metadata_msg = 0 ; int k ; psf_log_printf (psf, "Bitstream is %d channel, %D Hz\n", vdata->vinfo.channels, vdata->vinfo.rate) ; psf_log_printf (psf, "Encoded by : %s\n", vdata->vcomment.vendor) ; /* Throw the comments plus a few lines about the bitstream we're decoding. */ for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++) { char *dd ; dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ; if (dd == NULL) continue ; if (printed_metadata_msg == 0) { psf_log_printf (psf, "Metadata :\n") ; printed_metadata_msg = 1 ; } ; psf_store_string (psf, vorbis_metatypes [k].id, dd) ; psf_log_printf (psf, " %-10s : %s\n", vorbis_metatypes [k].name, dd) ; } ; psf_log_printf (psf, "End\n") ; } ; psf->sf.samplerate = vdata->vinfo.rate ; psf->sf.channels = vdata->vinfo.channels ; psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ; /* OK, got and parsed all three headers. Initialize the Vorbis ** packet->PCM decoder. ** Central decode state. */ vorbis_synthesis_init (&vdata->vdsp, &vdata->vinfo) ; /* Local state for most of the decode so multiple block decodes can ** proceed in parallel. We could init multiple vorbis_block structures ** for vd here. */ vorbis_block_init (&vdata->vdsp, &vdata->vblock) ; vdata->loc = 0 ; return 0 ; } /* vorbis_read_header */
static int caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size) { //char buf [chunk_size - 4] ; char *buf = (char*)malloc(chunk_size-4); char *key, *value ; uint32_t count, hash ; psf_binheader_readf (psf, "E4b", &count, buf, make_size_t (chunk_size - 4)) ; psf_log_printf (psf, " count: %u\n", count) ; /* Force terminate `buf` to make sure. */ buf [chunk_size-4 - 1] = 0 ; for (key = buf ; key < buf + chunk_size-4 ; ) { value = key + strlen (key) + 1 ; if (value > buf + chunk_size-4) break ; psf_log_printf (psf, " %-12s : %s\n", key, value) ; hash = string_hash32 (key) ; switch (hash) { case 0xC4861943 : /* 'title' */ psf_store_string (psf, SF_STR_TITLE, value) ; break ; case 0xAD47A394 : /* 'software' */ psf_store_string (psf, SF_STR_SOFTWARE, value) ; break ; case 0x5D178E2A : /* 'copyright' */ psf_store_string (psf, SF_STR_COPYRIGHT, value) ; break ; case 0x60E4D0C8 : /* 'artist' */ psf_store_string (psf, SF_STR_ARTIST, value) ; break ; case 0x83B5D16A : /* 'genre' */ psf_store_string (psf, SF_STR_GENRE, value) ; break ; case 0x15E5FC88 : /* 'comment' */ case 0x7C297D5B : /* 'comments' */ psf_store_string (psf, SF_STR_COMMENT, value) ; break ; case 0x24A7C347 : /* 'tracknumber' */ psf_store_string (psf, SF_STR_TRACKNUMBER, value) ; break ; case 0x50A31EB7 : /* 'date' */ psf_store_string (psf, SF_STR_DATE, value) ; break ; case 0x6583545A : /* 'album' */ psf_store_string (psf, SF_STR_ALBUM, value) ; break ; case 0xE7C64B6C : /* 'license' */ psf_store_string (psf, SF_STR_LICENSE, value) ; break ; default : psf_log_printf (psf, " Unhandled hash 0x%x : /* '%s' */\n", hash, key) ; break ; } ; key = value + strlen (value) + 1 ; } ; free(buf); return 0 ; }