mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
add FLAC__metadata_get_tags(), FLAC::Metadata::get_tags()
This commit is contained in:
@@ -168,6 +168,7 @@
|
|||||||
<LI>
|
<LI>
|
||||||
libFLAC:
|
libFLAC:
|
||||||
<UL>
|
<UL>
|
||||||
|
<LI><B>Added</B> FLAC__metadata_get_tags()</LI>
|
||||||
<LI><B>Added</B> callback-based versions of metadata editing functions:
|
<LI><B>Added</B> callback-based versions of metadata editing functions:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>FLAC__metadata_chain_read_with_callbacks()</LI>
|
<LI>FLAC__metadata_chain_read_with_callbacks()</LI>
|
||||||
@@ -198,6 +199,7 @@
|
|||||||
<LI>
|
<LI>
|
||||||
libFLAC++:
|
libFLAC++:
|
||||||
<UL>
|
<UL>
|
||||||
|
<LI><B>Added</B> FLAC::Metadata::get_tags()</LI>
|
||||||
<LI><B>Added</B> decoder functions for skipping single frames, also useful for quickly finding frame boundaries:
|
<LI><B>Added</B> decoder functions for skipping single frames, also useful for quickly finding frame boundaries:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>FLAC::Decoder::Stream::skip_single_frame()</LI>
|
<LI>FLAC::Decoder::Stream::skip_single_frame()</LI>
|
||||||
|
|||||||
@@ -787,7 +787,7 @@ namespace FLAC {
|
|||||||
* \ingroup flacpp_metadata
|
* \ingroup flacpp_metadata
|
||||||
*
|
*
|
||||||
* \brief
|
* \brief
|
||||||
* Level 0 metadata iterator.
|
* Level 0 metadata iterators.
|
||||||
*
|
*
|
||||||
* See the \link flac_metadata_level0 C layer equivalent \endlink
|
* See the \link flac_metadata_level0 C layer equivalent \endlink
|
||||||
* for more.
|
* for more.
|
||||||
@@ -797,6 +797,9 @@ namespace FLAC {
|
|||||||
|
|
||||||
//! See FLAC__metadata_get_streaminfo().
|
//! See FLAC__metadata_get_streaminfo().
|
||||||
FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
|
FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
|
||||||
|
//
|
||||||
|
//! See FLAC__metadata_get_tags().
|
||||||
|
FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags);
|
||||||
|
|
||||||
/* \} */
|
/* \} */
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
* There are three metadata interfaces of increasing complexity:
|
* There are three metadata interfaces of increasing complexity:
|
||||||
*
|
*
|
||||||
* Level 0:
|
* Level 0:
|
||||||
* Read-only access to the STREAMINFO block.
|
* Read-only access to the STREAMINFO and VORBIS_COMMENT blocks.
|
||||||
*
|
*
|
||||||
* Level 1:
|
* Level 1:
|
||||||
* Read-write access to all metadata blocks. This level is write-
|
* Read-write access to all metadata blocks. This level is write-
|
||||||
@@ -123,8 +123,8 @@ extern "C" {
|
|||||||
* \ingroup flac_metadata
|
* \ingroup flac_metadata
|
||||||
*
|
*
|
||||||
* \brief
|
* \brief
|
||||||
* The level 0 interface consists of a single routine to read the
|
* The level 0 interface consists of individual routines to read the
|
||||||
* STREAMINFO block.
|
* STREAMINFO and VORBIS_COMMENT blocks, requiring only a filename.
|
||||||
*
|
*
|
||||||
* It skips any ID3v2 tag at the head of the file.
|
* It skips any ID3v2 tag at the head of the file.
|
||||||
*
|
*
|
||||||
@@ -135,17 +135,40 @@ extern "C" {
|
|||||||
* will skip any ID3v2 tag at the head of the file.
|
* will skip any ID3v2 tag at the head of the file.
|
||||||
*
|
*
|
||||||
* \param filename The path to the FLAC file to read.
|
* \param filename The path to the FLAC file to read.
|
||||||
* \param streaminfo A pointer to space for the STREAMINFO block.
|
* \param streaminfo A pointer to space for the STREAMINFO block. Since
|
||||||
|
* FLAC__StreamMetadata is a simple structure with no
|
||||||
|
* memory allocation involved, you pass the address of
|
||||||
|
* an existing structure. It need not be initialized.
|
||||||
* \assert
|
* \assert
|
||||||
* \code filename != NULL \endcode
|
* \code filename != NULL \endcode
|
||||||
* \code streaminfo != NULL \endcode
|
* \code streaminfo != NULL \endcode
|
||||||
* \retval FLAC__bool
|
* \retval FLAC__bool
|
||||||
* \c true if a valid STREAMINFO block was read from \a filename. Returns
|
* \c true if a valid STREAMINFO block was read from \a filename. Returns
|
||||||
* \c false if there was a memory allocation error, a file decoder error,
|
* \c false if there was a memory allocation error, a file decoder error,
|
||||||
* or the file contained no STREAMINFO block.
|
* or the file contained no STREAMINFO block. (A memory allocation error
|
||||||
|
* is possible because this function must set up a file decoder.)
|
||||||
*/
|
*/
|
||||||
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo);
|
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo);
|
||||||
|
|
||||||
|
/** Read the VORBIS_COMMENT metadata block of the given FLAC file. This
|
||||||
|
* function will skip any ID3v2 tag at the head of the file.
|
||||||
|
*
|
||||||
|
* \param filename The path to the FLAC file to read.
|
||||||
|
* \param tags The address where the returned pointer will be
|
||||||
|
* stored. The \a tags object must be deleted by
|
||||||
|
* the caller using FLAC__metadata_object_delete().
|
||||||
|
* \assert
|
||||||
|
* \code filename != NULL \endcode
|
||||||
|
* \code streaminfo != NULL \endcode
|
||||||
|
* \retval FLAC__bool
|
||||||
|
* \c true if a valid VORBIS_COMMENT block was read from \a filename,
|
||||||
|
* and \a *tags will be set to the address of the tag structure.
|
||||||
|
* Returns \c false if there was a memory allocation error, a file
|
||||||
|
* decoder error, or the file contained no VORBIS_COMMENT block, and
|
||||||
|
* \a *tags will be set to \c NULL.
|
||||||
|
*/
|
||||||
|
FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags);
|
||||||
|
|
||||||
/* \} */
|
/* \} */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -985,10 +985,26 @@ namespace FLAC {
|
|||||||
{
|
{
|
||||||
FLAC__ASSERT(0 != filename);
|
FLAC__ASSERT(0 != filename);
|
||||||
|
|
||||||
::FLAC__StreamMetadata s;
|
::FLAC__StreamMetadata object;
|
||||||
|
|
||||||
if(::FLAC__metadata_get_streaminfo(filename, &s)) {
|
if(::FLAC__metadata_get_streaminfo(filename, &object)) {
|
||||||
streaminfo = s;
|
streaminfo = object;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags)
|
||||||
|
{
|
||||||
|
FLAC__ASSERT(0 != filename);
|
||||||
|
|
||||||
|
::FLAC__StreamMetadata *object;
|
||||||
|
|
||||||
|
tags = 0;
|
||||||
|
|
||||||
|
if(::FLAC__metadata_get_tags(filename, &object)) {
|
||||||
|
tags = new VorbisComment(object, /*copy=*/false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecode
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FLAC__bool got_error;
|
FLAC__bool got_error;
|
||||||
FLAC__bool got_streaminfo;
|
FLAC__bool got_object;
|
||||||
FLAC__StreamMetadata *streaminfo;
|
FLAC__StreamMetadata *object;
|
||||||
} level0_client_data;
|
} level0_client_data;
|
||||||
|
|
||||||
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
|
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
|
||||||
@@ -171,8 +171,8 @@ FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__St
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
cd.got_error = false;
|
cd.got_error = false;
|
||||||
cd.got_streaminfo = false;
|
cd.got_object = false;
|
||||||
cd.streaminfo = streaminfo;
|
cd.object = 0;
|
||||||
|
|
||||||
FLAC__file_decoder_set_md5_checking(decoder, false);
|
FLAC__file_decoder_set_md5_checking(decoder, false);
|
||||||
FLAC__file_decoder_set_filename(decoder, filename);
|
FLAC__file_decoder_set_filename(decoder, filename);
|
||||||
@@ -189,17 +189,77 @@ FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__St
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the first thing decoded must be the STREAMINFO block: */
|
|
||||||
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
|
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
|
||||||
FLAC__file_decoder_finish(decoder);
|
FLAC__file_decoder_finish(decoder);
|
||||||
FLAC__file_decoder_delete(decoder);
|
FLAC__file_decoder_delete(decoder);
|
||||||
|
if(0 != cd.object)
|
||||||
|
FLAC__metadata_object_delete(cd.object);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC__file_decoder_finish(decoder);
|
FLAC__file_decoder_finish(decoder);
|
||||||
FLAC__file_decoder_delete(decoder);
|
FLAC__file_decoder_delete(decoder);
|
||||||
|
|
||||||
return !cd.got_error && cd.got_streaminfo;
|
if(cd.got_object) {
|
||||||
|
/* can just copy the contents since STREAMINFO has no internal structure */
|
||||||
|
*streaminfo = *(cd.object);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0 != cd.object)
|
||||||
|
FLAC__metadata_object_delete(cd.object);
|
||||||
|
|
||||||
|
return cd.got_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags)
|
||||||
|
{
|
||||||
|
level0_client_data cd;
|
||||||
|
FLAC__FileDecoder *decoder;
|
||||||
|
|
||||||
|
FLAC__ASSERT(0 != filename);
|
||||||
|
FLAC__ASSERT(0 != tags);
|
||||||
|
|
||||||
|
decoder = FLAC__file_decoder_new();
|
||||||
|
|
||||||
|
if(0 == decoder)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*tags = 0;
|
||||||
|
|
||||||
|
cd.got_error = false;
|
||||||
|
cd.got_object = false;
|
||||||
|
cd.object = 0;
|
||||||
|
|
||||||
|
FLAC__file_decoder_set_md5_checking(decoder, false);
|
||||||
|
FLAC__file_decoder_set_filename(decoder, filename);
|
||||||
|
FLAC__file_decoder_set_metadata_ignore_all(decoder);
|
||||||
|
FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||||
|
FLAC__file_decoder_set_write_callback(decoder, write_callback_);
|
||||||
|
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
|
||||||
|
FLAC__file_decoder_set_error_callback(decoder, error_callback_);
|
||||||
|
FLAC__file_decoder_set_client_data(decoder, &cd);
|
||||||
|
|
||||||
|
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
|
||||||
|
FLAC__file_decoder_finish(decoder);
|
||||||
|
FLAC__file_decoder_delete(decoder);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
|
||||||
|
FLAC__file_decoder_finish(decoder);
|
||||||
|
FLAC__file_decoder_delete(decoder);
|
||||||
|
if(0 != cd.object)
|
||||||
|
FLAC__metadata_object_delete(cd.object);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLAC__file_decoder_finish(decoder);
|
||||||
|
FLAC__file_decoder_delete(decoder);
|
||||||
|
|
||||||
|
if(cd.got_object)
|
||||||
|
*tags = cd.object;
|
||||||
|
|
||||||
|
return cd.got_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
||||||
@@ -214,9 +274,15 @@ void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMeta
|
|||||||
level0_client_data *cd = (level0_client_data *)client_data;
|
level0_client_data *cd = (level0_client_data *)client_data;
|
||||||
(void)decoder;
|
(void)decoder;
|
||||||
|
|
||||||
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && 0 != cd->streaminfo) {
|
/*
|
||||||
*(cd->streaminfo) = *metadata;
|
* we assume we only get here when the one metadata block we were
|
||||||
cd->got_streaminfo = true;
|
* looking for was passed to us
|
||||||
|
*/
|
||||||
|
if(!cd->got_object) {
|
||||||
|
if(0 == (cd->object = FLAC__metadata_object_clone(metadata)))
|
||||||
|
cd->got_error = true;
|
||||||
|
else
|
||||||
|
cd->got_object = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -591,6 +591,7 @@ static bool remove_file_(const char *filename)
|
|||||||
static bool test_level_0_()
|
static bool test_level_0_()
|
||||||
{
|
{
|
||||||
FLAC::Metadata::StreamInfo streaminfo;
|
FLAC::Metadata::StreamInfo streaminfo;
|
||||||
|
FLAC::Metadata::VorbisComment *tags = 0;
|
||||||
|
|
||||||
printf("\n\n++++++ testing level 0 interface\n");
|
printf("\n\n++++++ testing level 0 interface\n");
|
||||||
|
|
||||||
@@ -600,6 +601,8 @@ static bool test_level_0_()
|
|||||||
if(!test_file_(flacfile_, /*ignore_metadata=*/true))
|
if(!test_file_(flacfile_, /*ignore_metadata=*/true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
printf("testing FLAC::Metadata::get_streaminfo()... ");
|
||||||
|
|
||||||
if(!FLAC::Metadata::get_streaminfo(flacfile_, streaminfo))
|
if(!FLAC::Metadata::get_streaminfo(flacfile_, streaminfo))
|
||||||
return die_("during FLAC::Metadata::get_streaminfo()");
|
return die_("during FLAC::Metadata::get_streaminfo()");
|
||||||
|
|
||||||
@@ -615,6 +618,21 @@ static bool test_level_0_()
|
|||||||
if(streaminfo.get_max_blocksize() != 576)
|
if(streaminfo.get_max_blocksize() != 576)
|
||||||
return die_("mismatch in streaminfo.get_max_blocksize()");
|
return die_("mismatch in streaminfo.get_max_blocksize()");
|
||||||
|
|
||||||
|
printf("OK\n");
|
||||||
|
|
||||||
|
printf("testing FLAC::Metadata::get_tags()... ");
|
||||||
|
|
||||||
|
if(!FLAC::Metadata::get_tags(flacfile_, tags))
|
||||||
|
return die_("during FLAC::Metadata::get_tags()");
|
||||||
|
|
||||||
|
/* check to see if some basic data matches (c.f. generate_file_()) */
|
||||||
|
if(tags->get_num_comments() != 0)
|
||||||
|
return die_("mismatch in tags->get_num_comments()");
|
||||||
|
|
||||||
|
printf("OK\n");
|
||||||
|
|
||||||
|
delete tags;
|
||||||
|
|
||||||
if(!remove_file_(flacfile_))
|
if(!remove_file_(flacfile_))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -604,6 +604,7 @@ static FLAC__bool remove_file_(const char *filename)
|
|||||||
static FLAC__bool test_level_0_()
|
static FLAC__bool test_level_0_()
|
||||||
{
|
{
|
||||||
FLAC__StreamMetadata streaminfo;
|
FLAC__StreamMetadata streaminfo;
|
||||||
|
FLAC__StreamMetadata *tags = 0;
|
||||||
|
|
||||||
printf("\n\n++++++ testing level 0 interface\n");
|
printf("\n\n++++++ testing level 0 interface\n");
|
||||||
|
|
||||||
@@ -613,6 +614,8 @@ static FLAC__bool test_level_0_()
|
|||||||
if(!test_file_(flacfile_, decoder_metadata_callback_null_))
|
if(!test_file_(flacfile_, decoder_metadata_callback_null_))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
printf("testing FLAC__metadata_get_streaminfo()... ");
|
||||||
|
|
||||||
if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
|
if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
|
||||||
return die_("during FLAC__metadata_get_streaminfo()");
|
return die_("during FLAC__metadata_get_streaminfo()");
|
||||||
|
|
||||||
@@ -628,6 +631,21 @@ static FLAC__bool test_level_0_()
|
|||||||
if(streaminfo.data.stream_info.max_blocksize != 576)
|
if(streaminfo.data.stream_info.max_blocksize != 576)
|
||||||
return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
|
return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
|
||||||
|
|
||||||
|
printf("OK\n");
|
||||||
|
|
||||||
|
printf("testing FLAC__metadata_get_tags()... ");
|
||||||
|
|
||||||
|
if(!FLAC__metadata_get_tags(flacfile_, &tags))
|
||||||
|
return die_("during FLAC__metadata_get_tags()");
|
||||||
|
|
||||||
|
/* check to see if some basic data matches (c.f. generate_file_()) */
|
||||||
|
if(tags->data.vorbis_comment.num_comments != 0)
|
||||||
|
return die_("mismatch in tags->data.vorbis_comment.num_comments");
|
||||||
|
|
||||||
|
printf("OK\n");
|
||||||
|
|
||||||
|
FLAC__metadata_object_delete(tags);
|
||||||
|
|
||||||
if(!remove_file_(flacfile_))
|
if(!remove_file_(flacfile_))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user