Commit 736ae7d6 authored by conrad's avatar conrad

Added comment reading support, and preliminary writing structures:

  + oggz_comment_() functions for querying comments per logical bitstream, and
                    for adding/removing comments in-memory
  + added comment-test to test suite
  + tested under valgrind (no leaks)
  + added example program in src/examples/dump-comments
  + auto detection to dump speex comments
NB: No writing comments to files yet, though the internals are there for it.


git-svn-id: http://svn.annodex.net/liboggz/trunk@2563 8158c8cd-e7e1-0310-9fa4-c5954c97daef
parent bb14728b
......@@ -2,6 +2,6 @@
# Include files to install
oggzincludedir = $(includedir)/oggz
oggzinclude_HEADERS = oggz.h oggz_constants.h oggz_read.h oggz_seek.h \
oggz_write.h oggz_io.h oggz_table.h oggz_deprecated.h
oggzinclude_HEADERS = oggz.h oggz_comments.h oggz_constants.h oggz_read.h \
oggz_seek.h oggz_write.h oggz_io.h oggz_table.h oggz_deprecated.h
......@@ -551,6 +551,7 @@ int oggz_get_eos (OGGZ * oggz, long serialno);
*/
long oggz_serialno_new (OGGZ * oggz);
#include <oggz/oggz_comments.h>
#include <oggz/oggz_read.h>
#include <oggz/oggz_seek.h>
#include <oggz/oggz_write.h>
......
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __OGGZ_COMMENT_H__
#define __OGGZ_COMMENT_H__
/** \file
* Encoding and decoding of comments.
*
* Vorbis, Speex and Theora bitstreams
* use a comment format called "Vorbiscomment", defined
* <a href="http://www.xiph.org/ogg/vorbis/doc/v-comment.html">here</a>.
* Many standard comment names (such as TITLE, COPYRIGHT and GENRE) are
* defined in that document.
*
* The following general features of Vorbiscomment are relevant to this API:
* - Each stream has one comment packet, which occurs before any encoded
* audio data in the stream.
* - When encoding, OGGZ will generate the comment block and pass it
* to the encoded() callback in sequence, just like any other packet.
* Hence, all comments must be set before any call to oggz_encode_*().
* - When decoding, OGGZ will decode the comment block before calling
* the first decoded() callback. Hence, retrieving comment data is possible
* from as soon as the decoded() callback is first called.
*
* Each comment block contains one Vendor string, which can be retrieved
* with oggz_comment_get_vendor(). When encoding, this string is
* effectively fixed by the codec libraries; it cannot be set by the
* application.
*
* The rest of a comment block consists of \a name = \a value pairs, with
* the following restrictions:
* - Both the \a name and \a value must be non-empty
* - The \a name is case-insensitive and must consist of ASCII within the
* range 0x20 to 0x7D inclusive, 0x3D ('=') excluded.
* - The \a name is not unique; multiple entries may exist with equivalent
* \a name within a Vorbiscomment block.
* - The \a value may be any UTF-8 string.
*
* \section comments_get Retrieving comments
*
* OGGZ contains API methods to iterate through all comments associated
* with a OGGZ* handle (oggz_comment_first() and
* oggz_comment_next(), and to iterate through comments matching a
* particular name (oggz_comment_first_byname() and
* oggz_comment_next_byname()). Given that multiple comments may exist
* with the same \a name, you should not use
* oggz_comment_first_byname() as a simple "get" function.
*
* \section comments_set Encoding comments
*
* For encoding, OGGZ contains API methods for adding comments
* (oggz_comment_add() and oggz_comment_add_byname()
* and for removing comments
* (oggz_comment_remove() and oggz_comment_remove_byname()).
*/
#include <oggz/oggz.h>
/**
* A comment.
*/
typedef struct {
/** The name of the comment, eg. "AUTHOR" */
char * name;
/** The value of the comment, as UTF-8 */
char * value;
} OggzComment;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Retrieve the vendor string.
* \param oggz A OGGZ* handle
* \param serialno Identify a logical bitstream within \a oggz
* \returns A read-only copy of the vendor string.
* \retval NULL No vendor string is associated with \a oggz,
* or \a oggz is NULL, or \a serialno does not identify an
* existing logical bitstream in \a oggz.
*/
const char *
oggz_comment_get_vendor (OGGZ * oggz, long serialno);
/**
* Retrieve the first comment.
* \param oggz A OGGZ* handle
* \param serialno Identify a logical bitstream within \a oggz
* \returns A read-only copy of the first comment.
* \retval NULL No comments exist for this OGGZ* object, or \a serialno
* does not identify an existing logical bitstream in \a oggz.
*/
const OggzComment *
oggz_comment_first (OGGZ * oggz, long serialno);
/**
* Retrieve the next comment.
* \param oggz A OGGZ* handle
* \param serialno Identify a logical bitstream within \a oggz
* \param comment The previous comment.
* \returns A read-only copy of the comment immediately following the given
* comment.
* \retval NULL \a serialno does not identify an existing
* logical bitstream in \a oggz.
*/
const OggzComment *
oggz_comment_next (OGGZ * oggz, long serialno, const OggzComment * comment);
/**
* Retrieve the first comment with a given name.
* \param oggz A OGGZ* handle
* \param serialno Identify a logical bitstream within \a oggz
* \param name the name of the comment to retrieve.
* \returns A read-only copy of the first comment matching the given \a name.
* \retval NULL No match was found, or \a serialno does not identify an
* existing logical bitstream in \a oggz.
* \note If \a name is NULL, the behaviour is the same as for
* oggz_comment_first()
*/
const OggzComment *
oggz_comment_first_byname (OGGZ * oggz, long serialno, char * name);
/**
* Retrieve the next comment following and with the same name as a given
* comment.
* \param oggz A OGGZ* handle
* \param serialno Identify a logical bitstream within \a oggz
* \param comment A comment
* \returns A read-only copy of the next comment with the same name as
* \a comment.
* \retval NULL No further comments with the same name exist for this
* OGGZ* object, or \a serialno does not identify an existing
* logical bitstream in \a oggz.
*/
const OggzComment *
oggz_comment_next_byname (OGGZ * oggz, long serialno,
const OggzComment * comment);
/**
* Add a comment
* \param oggz A OGGZ* handle (created with mode OGGZ_ENCODE)
* \param serialno Identify a logical bitstream within \a oggz
* \param comment The comment to add
* \retval 0 Success
* \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
*/
int
oggz_comment_add (OGGZ * oggz, long serialno, OggzComment * comment);
/**
* Add a comment by name and value.
* \param oggz A OGGZ* handle (created with mode OGGZ_ENCODE)
* \param serialno Identify a logical bitstream within \a oggz
* \param name The name of the comment to add
* \param value The contents of the comment to add
* \retval 0 Success
* \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
*/
int
oggz_comment_add_byname (OGGZ * oggz, long serialno,
const char * name, const char * value);
/**
* Remove a comment
* \param oggz A OGGZ* handle (created with OGGZ_ENCODE)
* \param serialno Identify a logical bitstream within \a oggz
* \param comment The comment to remove.
* \retval 1 Success: comment removed
* \retval 0 No-op: comment not found, nothing to remove
* \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
* \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
* logical bitstream in \a oggz.
*/
int
oggz_comment_remove (OGGZ * oggz, long serialno, OggzComment * comment);
/**
* Remove all comments with a given name.
* \param oggz A OGGZ* handle (created with OGGZ_ENCODE)
* \param serialno Identify a logical bitstream within \a oggz
* \param name The name of the comments to remove
* \retval ">= 0" The number of comments removed
* \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
* \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
* logical bitstream in \a oggz.
*/
int
oggz_comment_remove_byname (OGGZ * oggz, long serialno, char * name);
#ifdef __cplusplus
}
#endif
#endif /* __OGGZ_COMMENTS_H__ */
......@@ -181,6 +181,10 @@ enum OggzError {
/** Packet disallowed due to invalid packetno */
OGGZ_ERR_BAD_PACKETNO = -25,
/** Comment violates VorbisComment restrictions */
/* 129 == 0x81 is the frame marker for Theora's comments page ;-) */
OGGZ_ERR_COMMENT_INVALID = -129,
/** Guard provided by user has non-zero value */
OGGZ_ERR_BAD_GUARD = -210,
......
......@@ -14,7 +14,7 @@ endif
endif
if OGGZ_CONFIG_READ
oggz_read_programs = read-file read-io
oggz_read_programs = read-file read-io dump-comments
endif
if OGGZ_CONFIG_WRITE
......@@ -40,6 +40,9 @@ read_file_LDADD = $(OGGZ_LIBS)
read_io_SOURCES = read-io.c
read_io_LDADD = $(OGGZ_LIBS)
dump_comments_SOURCES = dump-comments.c
dump_comments_LDADD = $(OGGZ_LIBS)
write_feed_SOURCES = write-feed.c
write_feed_LDADD = $(OGGZ_LIBS)
......
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oggz/oggz.h>
static char * infilename;
static int previous_b_o_s = 0;
static void
read_comments (OGGZ * oggz, long serialno)
{
const OggzComment * comment;
const char * vendor;
vendor = oggz_comment_get_vendor (oggz, serialno);
if (vendor) puts (vendor);
for (comment = oggz_comment_first (oggz, serialno); comment;
comment = oggz_comment_next (oggz, serialno, comment)) {
if (comment->value) {
printf ("%s: %s\r\n", comment->name, comment->value);
} else {
printf ("%s\r\n", comment->name);
}
}
}
static int
read_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
{
if (previous_b_o_s) {
read_comments (oggz, serialno);
}
previous_b_o_s = op->b_o_s;
return 0;
}
int
main (int argc, char ** argv)
{
OGGZ * oggz;
long n;
if (argc < 2) {
printf ("usage: %s infilename\n", argv[0]);
printf ("*** Oggz example program. ***\n");
printf ("Read comments from an Ogg file.\n");
exit (1);
}
infilename = argv[1];
if ((oggz = oggz_open ((char *) infilename, OGGZ_READ)) == NULL) {
printf ("unable to open file %s\n", infilename);
exit (1);
}
oggz_set_read_callback (oggz, -1, read_packet, NULL);
while ((n = oggz_read (oggz, 1024)) > 0);
oggz_close (oggz);
exit (0);
}
......@@ -12,6 +12,7 @@ lib_LTLIBRARIES = liboggz.la
liboggz_la_SOURCES = \
oggz.c \
oggz_private.h oggz_byteorder.h oggz_compat.h oggz_macros.h \
comments.c \
oggz_io.c \
oggz_read.c oggz_write.c \
oggz_seek.c \
......
......@@ -67,6 +67,17 @@
oggz_table_lookup;
oggz_table_size;
oggz_table_nth;
oggz_comment_get_vendor;
oggz_comment_first;
oggz_comment_first_byname;
oggz_comment_next;
oggz_comment_next_byname;
oggz_comment_add;
oggz_comment_add_byname;
oggz_comment_remove;
oggz_comment_remove_byname;
local:
*;
};
This diff is collapsed.
......@@ -167,6 +167,8 @@ oggz_stream_clear (void * data)
{
oggz_stream_t * stream = (oggz_stream_t *) data;
oggz_comments_free (stream);
if (stream->ogg_stream.serialno != -1)
ogg_stream_clear (&stream->ogg_stream);
......@@ -301,7 +303,7 @@ oggz_get_stream (OGGZ * oggz, long serialno)
{
if (serialno < 0) return NULL;
return oggz_vector_find (oggz->streams, oggz_find_stream, serialno);
return oggz_vector_find_with (oggz->streams, oggz_find_stream, serialno);
}
oggz_stream_t *
......@@ -314,6 +316,8 @@ oggz_add_stream (OGGZ * oggz, long serialno)
ogg_stream_init (&stream->ogg_stream, (int)serialno);
oggz_comments_init (stream);
stream->content = OGGZ_CONTENT_UNKNOWN;
stream->nr_headers = 0;
stream->preroll = 0;
......@@ -326,7 +330,7 @@ oggz_add_stream (OGGZ * oggz, long serialno)
stream->b_o_s = 1;
stream->e_o_s = 0;
stream->granulepos = 0;
stream->packetno = -1; /* will be incremented on first write */
stream->packetno = -1; /* will be incremented on first read or write */
stream->metric = NULL;
stream->metric_user_data = NULL;
......
......@@ -774,4 +774,28 @@ oggz_auto_calculate_granulepos(int content, ogg_int64_t now,
}
int
oggz_auto_read_comments (OGGZ * oggz, oggz_stream_t * stream, long serialno,
ogg_packet * op)
{
int offset = -1;
switch (stream->content) {
case OGGZ_CONTENT_VORBIS:
break;
case OGGZ_CONTENT_SPEEX:
offset = 0; break;
case OGGZ_CONTENT_THEORA:
break;
default:
break;
}
if (offset >= 0) {
oggz_comments_decode (oggz, serialno, op->packet+offset, op->bytes-offset);
}
return 0;
}
#endif /* OGGZ_CONFIG_READ */
......@@ -43,6 +43,7 @@
#include "oggz_vector.h"
typedef struct _OGGZ OGGZ;
typedef struct _OggzComment OggzComment;
typedef struct _OggzIO OggzIO;
typedef struct _OggzReader OggzReader;
typedef struct _OggzWriter OggzWriter;
......@@ -84,6 +85,10 @@ struct _oggz_stream_t {
ogg_int64_t basegranule;
int granuleshift;
/* The comments */
char * vendor;
OggzVector * comments;
/** CURRENT STATE **/
/* non b_o_s packet has been written (not just queued) */
int delivered_non_b_o_s;
......@@ -194,6 +199,14 @@ struct _OggzIO {
void * flush_user_handle;
};
struct _OggzComment {
/** The name of the comment, eg. "AUTHOR" */
char * name;
/** The value of the comment, as UTF-8 */
char * value;
};
struct _OGGZ {
int flags;
FILE * file;
......@@ -255,6 +268,18 @@ oggz_get_granulerate (OGGZ * oggz, long serialno,
ogg_int64_t * granulerate_n,
ogg_int64_t * granulerate_d);
int
oggz_auto_read_comments (OGGZ * oggz, oggz_stream_t * stream, long serialno,
ogg_packet * op);
/* comments */
int oggz_comments_init (oggz_stream_t * stream);
int oggz_comments_free (oggz_stream_t * stream);
int oggz_comments_decode (OGGZ * oggz, long serialno,
unsigned char * comments, long length);
long oggz_comments_encode (OGGZ * oggz, long serialno,
unsigned char * buf, long length);
/* oggz_io */
size_t oggz_io_read (OGGZ * oggz, void * buf, size_t n);
size_t oggz_io_write (OGGZ * oggz, void * buf, size_t n);
......
......@@ -304,6 +304,8 @@ oggz_read_sync (OGGZ * oggz)
if(result > 0){
int content;
stream->packetno++;
/* got a packet. process it */
granulepos = op->granulepos;
......@@ -342,6 +344,10 @@ oggz_read_sync (OGGZ * oggz)
oggz_get_unit (oggz, serialno, reader->current_granulepos);
}
if (stream->packetno == 1) {
oggz_auto_read_comments (oggz, stream, serialno, op);
}
if (stream->read_packet) {
cb_ret =
stream->read_packet (oggz, op, serialno, stream->read_user_data);
......
......@@ -136,15 +136,49 @@ oggz_vector_nth_l (OggzVector * vector, int n)
}
void *
oggz_vector_find (OggzVector * vector, OggzFindFunc func, long serialno)
oggz_vector_find_p (OggzVector * vector, const void * data)
{
void * data;
void * d;
int i;
if (vector->compare == NULL) -1;
for (i = 0; i < vector->nr_elements; i++) {
d = vector->data[i].p;
if (vector->compare (d, data, vector->compare_user_data))
return d;
}
return NULL;
}
int
oggz_vector_find_index_p (OggzVector * vector, const void * data)
{
void * d;
int i;
if (vector->compare == NULL) -1;
for (i = 0; i < vector->nr_elements; i++) {
d = vector->data[i].p;
if (vector->compare (d, data, vector->compare_user_data))
return i;
}
return -1;
}
void *
oggz_vector_find_with (OggzVector * vector, OggzFindFunc func, long serialno)
{
void * d;
int i;
for (i = 0; i < vector->nr_elements; i++) {
data = vector->data[i].p;
if (func (data, serialno))
return data;
d = vector->data[i].p;
if (func (d, serialno))
return d;
}
return NULL;
......
......@@ -46,7 +46,13 @@ void
oggz_vector_delete (OggzVector * vector);
void *
oggz_vector_find (OggzVector * vector, OggzFindFunc func, long serialno);
oggz_vector_find_p (OggzVector * vector, const void * data);
int
oggz_vector_find_index_p (OggzVector * vector, const void * data);
void *
oggz_vector_find_with (OggzVector * vector, OggzFindFunc func, long serialno);
void *
oggz_vector_nth_p (OggzVector * vector, int n);
......
......@@ -13,6 +13,8 @@ TESTS_ENVIRONMENT = $(VALGRIND_ENVIRONMENT)
test: check
comment_tests = comment-test
if OGGZ_CONFIG_WRITE
write_tests = write-bad-guard write-unmarked-guard write-recursive \
write-bad-bytes write-bad-bos write-dup-bos write-bad-eos \
......@@ -32,13 +34,16 @@ seek_tests = seek-stress-test.sh
endif
noinst_SCRIPTS = $(seek_tests)
noinst_PROGRAMS = $(write_tests) $(rw_tests) $(seek_progs)
noinst_PROGRAMS = $(comment_tests) $(write_tests) $(rw_tests) $(seek_progs)
noinst_HEADERS = oggz_tests.h
EXTRA_DIST = $(seek_tests)
#TESTS = $(write_tests) $(rw_tests) $(seek_tests)
TESTS = $(write_tests) $(rw_tests)
TESTS = $(comment_tests) $(write_tests) $(rw_tests)
comment_test_SOURCES = comment-test.c
comment_test_LDADD = $(OGGZ_LIBS)
write_bad_guard_SOURCES = write-bad-guard.c
write_bad_guard_LDADD = $(OGGZ_LIBS)
......
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oggz/oggz.h>
#include "oggz_tests.h"
#define ARTIST1 "Trout Junkies"
#define ARTIST2 "DJ Fugu"
#define COPYRIGHT "Copyright (C) 2004. Some Rights Reserved."
#define LICENSE "Creative Commons Attribute Share-Alike v1.0"
#define COMMENT "Unstructured comments are evil."
static OGGZ * oggz;
int
main (int argc, char * argv[])
{
const OggzComment * comment, * comment2;
OggzComment mycomment;
int err;
long serialno = 7;
#if OGGZ_CONFIG_WRITE
INFO ("Initializing OGGZ for comments (writer)");
oggz = oggz_new (OGGZ_WRITE);
INFO ("+ Adding ARTIST1 byname");
err = oggz_comment_add_byname (oggz, serialno, "ARTIST", ARTIST1);
if (err == OGGZ_ERR_BAD_SERIALNO)
FAIL ("Comment add to fresh bitstream failed");
if (err < 0) FAIL ("Operation failed");
INFO ("+ Testing add of invalid unstructured COMMENT byname");
err = oggz_comment_add_byname (oggz, serialno, COMMENT, NULL);
if (err != OGGZ_ERR_COMMENT_INVALID)
FAIL ("Invalid comment not detected");
INFO ("+ Testing add of invalid unstructured COMMENT from local storage");
mycomment.name = COMMENT;
mycomment.value = NULL;
err = oggz_comment_add (oggz, serialno, &mycomment);
if (err != OGGZ_ERR_COMMENT_INVALID)
FAIL ("Invalid comment not detected");
INFO ("+ Adding COPYRIGHT byname");
err = oggz_comment_add_byname (oggz, serialno, "COPYRIGHT", COPYRIGHT);
if (err < 0) FAIL ("Operation failed");
INFO ("+ Retrieving first (expect ARTIST1)");
comment = oggz_comment_first (oggz, serialno);
if (comment == NULL)
FAIL ("Recently inserted ARTIST1 not retrieved");
if (strcmp (comment->name, "ARTIST"))
FAIL ("Incorrect ARTIST1 name found");
if (strcmp (comment->value, ARTIST1))
FAIL ("Incorrect ARTIST1 value found");
INFO ("+ Retrieving next (expect COPYRIGHT)");
comment = oggz_comment_next (oggz, serialno, comment);