[cvs-annodex] commit (libfishsound): trunk/configure.ac
trunk/include/fishsound/Makefile.am
trunk/include/fishsound/constants.h
trunk/include/fishsound/fishsound.h trunk/src/Makefile.am
trunk/src/examples/Makefile.am trunk/src/examples/encode.c
trunk/src/libfishsound/Makefile.am
trunk/src/libfishsound/Version_script.in
trunk/src/libfishsound/fishsound.c trunk/src/libfishsound/private.h
trunk/src/libfishsound/speex.c
trunk/src/libfishsound/vorbis.c trunk/src/tests/Makefile.am
trunk/win32/libfishsound/libfishsound.def
+trunk/src/tests/comment-test.c +trunk/src/tests/encdec-audio.c
+trunk/src/tests/encdec-comments.c +trunk/src/tests/fs_tests.h
conrad
nobody at lists.annodex.net
Wed May 5 20:17:08 EST 2004
Update of /annodex/libfishsound (new revision 68)
Added files:
trunk/src/tests/comment-test.c
trunk/src/tests/encdec-audio.c
trunk/src/tests/encdec-comments.c
trunk/src/tests/fs_tests.h
Modified files:
trunk/configure.ac
trunk/include/fishsound/Makefile.am
trunk/include/fishsound/constants.h
trunk/include/fishsound/fishsound.h
trunk/src/Makefile.am
trunk/src/examples/Makefile.am
trunk/src/examples/encode.c
trunk/src/libfishsound/Makefile.am
trunk/src/libfishsound/Version_script.in
trunk/src/libfishsound/fishsound.c
trunk/src/libfishsound/private.h
trunk/src/libfishsound/speex.c
trunk/src/libfishsound/vorbis.c
trunk/src/tests/Makefile.am
trunk/win32/libfishsound/libfishsound.def
Log Message:
Added support for comment packets, tests, and various bugfixes.
* Added fish_sound_comment_() API, <fishsound/comments.h>
* Fixed segv bug in decoding stereo Speex to non-interleaved
* Added test for encode/decode pipeline with a variety of
combinations of format, interleave, samplerate, channels and
buffer size.
* Added tests for comments data structure and encode/decode pipeline
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/configure.ac 2004-05-05 10:17:08 UTC (rev 68)
@@ -60,6 +60,7 @@
else
AC_DEFINE(FS_DECODE, [0], [Do not build decoding support])
fi
+AM_CONDITIONAL(FS_DECODE, [test "x${ac_enable_decode}" = "xyes"])
dnl
dnl Configuration option for building of encoding support.
@@ -75,6 +76,7 @@
else
AC_DEFINE(FS_ENCODE, [0], [Do not build encoding support])
fi
+AM_CONDITIONAL(FS_ENCODE, [test "x${ac_enable_encode}" = "xyes"])
dnl
dnl Check decode/encode option sanity
Modified: trunk/include/fishsound/Makefile.am
===================================================================
--- trunk/include/fishsound/Makefile.am 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/include/fishsound/Makefile.am 2004-05-05 10:17:08 UTC (rev 68)
@@ -2,5 +2,5 @@
# Include files to install
includedir = $(prefix)/include/fishsound
-include_HEADERS = fishsound.h constants.h
+include_HEADERS = fishsound.h comments.h constants.h
Modified: trunk/include/fishsound/constants.h
===================================================================
--- trunk/include/fishsound/constants.h 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/include/fishsound/constants.h 2004-05-05 10:17:08 UTC (rev 68)
@@ -82,11 +82,23 @@
/** No error */
FISH_SOUND_OK = 0,
+ /** generic error */
+ FISH_SOUND_ERR_GENERIC = -1,
+
+ /** Not a valid FishSound* handle */
+ FISH_SOUND_ERR_BAD = -2,
+
+ /** The requested operation is not suitable for this FishSound* handle */
+ FISH_SOUND_ERR_INVALID = -3,
+
/** Functionality disabled at build time */
FISH_SOUND_ERR_DISABLED = -10,
/** Too few bytes passed to fish_sound_identify() */
- FISH_SOUND_ERR_SHORT_IDENTIFY = -20
+ FISH_SOUND_ERR_SHORT_IDENTIFY = -20,
+
+ /** Comment violates VorbisComment restrictions */
+ FISH_SOUND_ERR_COMMENT_INVALID = -21
} FishSoundError;
#endif /* __FISH_SOUND_CONSTANTS_H__ */
Modified: trunk/include/fishsound/fishsound.h
===================================================================
--- trunk/include/fishsound/fishsound.h 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/include/fishsound/fishsound.h 2004-05-05 10:17:08 UTC (rev 68)
@@ -609,4 +609,6 @@
}
#endif
+#include <fishsound/comments.h>
+
#endif /* __FISH_SOUND_H__ */
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/Makefile.am 2004-05-05 10:17:08 UTC (rev 68)
@@ -1,3 +1,3 @@
## Process this file with automake to produce Makefile.in
-SUBDIRS = libfishsound tests examples
+SUBDIRS = libfishsound examples tests
Modified: trunk/src/examples/Makefile.am
===================================================================
--- trunk/src/examples/Makefile.am 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/examples/Makefile.am 2004-05-05 10:17:08 UTC (rev 68)
@@ -9,23 +9,27 @@
FISHSOUND_LIBS = $(FISHSOUNDDIR)/libfishsound.la $(VORBIS_LIBS) $(SPEEX_LIBS)
if HAVE_OGGZ
-oggz_examples = identify
+oggz_examples = identify fishsound-info
if HAVE_LIBSNDFILE1
-oggz_sndfile_examples = decode encode
+oggz_sndfile_examples = fishsound-decode fishsound-encode
endif
endif
# Programs to build
-noinst_PROGRAMS = $(oggz_examples) $(oggz_sndfile_examples)
+#noinst_PROGRAMS = $(oggz_examples) $(oggz_sndfile_examples)
+bin_PROGRAMS = $(oggz_examples) $(oggz_sndfile_examples)
identify_SOURCES = identify.c
identify_LDADD = $(FISHSOUND_LIBS) $(OGGZ_LIBS)
-decode_SOURCES = decode.c
-decode_LDADD = $(FISHSOUND_LIBS) $(OGGZ_LIBS) $(SNDFILE_LIBS)
+fishsound_info_SOURCES = fishsound-info.c
+fishsound_info_LDADD = $(FISHSOUND_LIBS) $(OGGZ_LIBS)
-encode_SOURCES = encode.c
-encode_LDADD = $(FISHSOUND_LIBS) $(OGGZ_LIBS) $(SNDFILE_LIBS)
+fishsound_decode_SOURCES = decode.c
+fishsound_decode_LDADD = $(FISHSOUND_LIBS) $(OGGZ_LIBS) $(SNDFILE_LIBS)
+fishsound_encode_SOURCES = encode.c
+fishsound_encode_LDADD = $(FISHSOUND_LIBS) $(OGGZ_LIBS) $(SNDFILE_LIBS)
+
Modified: trunk/src/examples/encode.c
===================================================================
--- trunk/src/examples/encode.c 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/examples/encode.c 2004-05-05 10:17:08 UTC (rev 68)
@@ -119,6 +119,9 @@
fish_sound_set_interleave (fsound, 1);
+ fish_sound_comment_add_byname (fsound, "Author", "crazy fish heads");
+ fish_sound_comment_add_byname (fsound, "FWOARR!", NULL);
+
while (sf_readf_float (sndfile, pcm, 1024) > 0) {
fish_sound_encode (fsound, (float **)pcm, 1024);
while ((n = oggz_write (oggz, 1024)) > 0);
Modified: trunk/src/libfishsound/Makefile.am
===================================================================
--- trunk/src/libfishsound/Makefile.am 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/libfishsound/Makefile.am 2004-05-05 10:17:08 UTC (rev 68)
@@ -12,8 +12,10 @@
libfishsound_la_SOURCES = \
fishsound.c \
private.h \
+ comments.c \
speex.c \
vorbis.c \
+ fs_vector.c fs_vector.h \
fs_compat.h
libfishsound_la_LDFLAGS = -version-info @SHARED_VERSION_INFO@ @SHLIB_VERSION_ARG@
Modified: trunk/src/libfishsound/Version_script.in
===================================================================
--- trunk/src/libfishsound/Version_script.in 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/libfishsound/Version_script.in 2004-05-05 10:17:08 UTC (rev 68)
@@ -22,6 +22,16 @@
fish_sound_set_interleave;
fish_sound_get_frameno;
fish_sound_set_frameno;
+
+ fish_sound_comment_get_vendor;
+ fish_sound_comment_first;
+ fish_sound_comment_first_byname;
+ fish_sound_comment_next;
+ fish_sound_comment_next_byname;
+ fish_sound_comment_add;
+ fish_sound_comment_add_byname;
+ fish_sound_comment_remove;
+ fish_sound_comment_remove_byname;
local:
*;
};
Modified: trunk/src/libfishsound/fishsound.c
===================================================================
--- trunk/src/libfishsound/fishsound.c 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/libfishsound/fishsound.c 2004-05-05 10:17:08 UTC (rev 68)
@@ -106,6 +106,8 @@
fsound->callback = NULL;
fsound->user_data = NULL;
+ fish_sound_comments_init (fsound);
+
if (mode == FISH_SOUND_DECODE) {
fsound->info.samplerate = 0;
fsound->info.channels = 0;
Modified: trunk/src/libfishsound/private.h
===================================================================
--- trunk/src/libfishsound/private.h 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/libfishsound/private.h 2004-05-05 10:17:08 UTC (rev 68)
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include "fs_compat.h"
+#include "fs_vector.h"
#include <fishsound/constants.h>
@@ -47,6 +48,7 @@
typedef struct _FishSoundInfo FishSoundInfo;
typedef struct _FishSoundCodec FishSoundCodec;
typedef struct _FishSoundFormat FishSoundFormat;
+typedef struct _FishSoundComment FishSoundComment;
typedef int (*FSCodecIdentify) (unsigned char * buf, long bytes);
typedef FishSound * (*FSCodecInit) (FishSound * fsound);
@@ -81,6 +83,11 @@
int format;
};
+struct _FishSoundComment {
+ char * name;
+ char * value;
+};
+
struct _FishSound {
/** FISH_SOUND_DECODE or FISH_SOUND_ENCODE */
FishSoundMode mode;
@@ -102,6 +109,10 @@
/** user data for encode/decode callback */
void * user_data;
+
+ /** The comments */
+ char * vendor;
+ FishSoundVector * comments;
};
struct _FishSoundFormat {
@@ -116,9 +127,32 @@
typedef int (*FishSoundEncoded) (FishSound * fsound, unsigned char * buf,
long bytes, void * user_data);
+/* data */
extern FishSoundCodec fish_sound_vorbis;
extern FishSoundCodec fish_sound_speex;
+/* comments */
+int fish_sound_comments_init (FishSound * fsound);
+int fish_sound_comments_decode (FishSound * fsound, unsigned char * buf,
+ long bytes);
+long fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
+ long length);
+
+/**
+ * Set the vendor string.
+ * \param fsound A FishSound* handle (created with FISH_SOUND_ENCODE)
+ * \param vendor The vendor string.
+ * \retval 0 Success
+ * \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
+ * \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
+ */
+int
+fish_sound_comment_set_vendor (FishSound * fsound, const char * vendor);
+
+const FishSoundComment * fish_sound_comment_first (FishSound * fsound);
+const FishSoundComment *
+fish_sound_comment_next (FishSound * fsound, const FishSoundComment * comment);
+
/* inline functions */
static inline void
@@ -126,10 +160,12 @@
long frames, int channels, float mult_factor)
{
int i, j;
+ float * d, * s = (float *)src;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
- dest[j][i] = src[i][j] * mult_factor;
+ d = dest[j];
+ d[i] = s[i*channels + j] * mult_factor;
}
}
}
Modified: trunk/src/libfishsound/speex.c
===================================================================
--- trunk/src/libfishsound/speex.c 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/libfishsound/speex.c 2004-05-05 10:17:08 UTC (rev 68)
@@ -49,6 +49,11 @@
#include <speex_stereo.h>
#include <speex_callbacks.h>
+/* Format for the vendor string: "Encoded with Speex VERSION", where VERSION
+ * is the libspeex version as read from a newly-generated Speex header.
+ */
+#define VENDOR_FORMAT "Encoded with Speex %s"
+
#define DEFAULT_ENH_ENABLED 1
#define MAX_FRAME_BYTES 2000
@@ -264,8 +269,11 @@
if (fss->nframes == 0) fss->nframes = 1;
+ } else if (fss->packetno == 1) {
+ /* Comments */
+ fish_sound_comments_decode (fsound, buf, bytes);
} else if (fss->packetno <= 1+fss->extra_headers) {
- /* XXX: metadata etc. */
+ /* Unknown extra headers */
} else {
speex_bits_read_from (&fss->bits, (char *)buf, (int)bytes);
@@ -324,7 +332,7 @@
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
SpeexMode * mode = NULL;
SpeexHeader header;
- char * buf;
+ unsigned char * buf;
int bytes;
/* XXX: set wb, nb, uwb modes */
@@ -340,15 +348,23 @@
if (fsound->callback) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback;
+ char vendor_string[128];
/* header */
- buf = speex_header_to_packet (&header, &bytes);
- encoded (fsound, (unsigned char *)buf, (long)bytes, fsound->user_data);
+ buf = (unsigned char *) speex_header_to_packet (&header, &bytes);
+ encoded (fsound, buf, (long)bytes, fsound->user_data);
fss->packetno++;
free (buf);
- /* XXX: and comments */
- encoded (fsound, NULL, 0, fsound->user_data);
+ /* comments */
+ snprintf (vendor_string, 128, VENDOR_FORMAT, header.speex_version);
+ fish_sound_comment_set_vendor (fsound, vendor_string);
+ bytes = fish_sound_comments_encode (fsound, NULL, 0);
+ buf = malloc (bytes);
+ bytes = fish_sound_comments_encode (fsound, buf, bytes);
+ encoded (fsound, buf, (long)bytes, fsound->user_data);
+ fss->packetno++;
+ free (buf);
}
speex_encoder_ctl (fss->st, SPEEX_SET_SAMPLING_RATE,
Modified: trunk/src/libfishsound/vorbis.c
===================================================================
--- trunk/src/libfishsound/vorbis.c 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/libfishsound/vorbis.c 2004-05-05 10:17:08 UTC (rev 68)
@@ -197,6 +197,7 @@
op.packetno = fsv->packetno;
if (fsv->packetno < 3) {
+
if ((ret = vorbis_synthesis_headerin (&fsv->vi, &fsv->vc, &op)) == 0) {
if (fsv->vi.rate != 0) {
#ifdef DEBUG
@@ -208,7 +209,12 @@
}
}
- if (fsv->packetno == 2) {
+ /* Decode comments from packet 1. Vorbis has 7 bytes of marker at the
+ * start of vorbiscomment packet. */
+ if (fsv->packetno == 1 && bytes > 7 && buf[0] == 0x03 &&
+ !strncmp ((char *)&buf[1], "vorbis", 6)) {
+ fish_sound_comments_decode (fsound, buf+7, bytes-7);
+ } else if (fsv->packetno == 2) {
vorbis_synthesis_init (&fsv->vd, &fsv->vi);
vorbis_block_init (&fsv->vd, &fsv->vb);
}
@@ -258,6 +264,7 @@
fs_vorbis_enc_headers (FishSound * fsound)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
+ const FishSoundComment * comment;
ogg_packet header;
ogg_packet header_comm;
ogg_packet header_code;
@@ -268,10 +275,22 @@
third header holds the bitstream codebook. We merely need to
make the headers, then pass them to libvorbis one at a time;
libvorbis handles the additional Ogg bitstream constraints */
+
+ /* Update the comments */
+ for (comment = fish_sound_comment_first (fsound); comment;
+ comment = fish_sound_comment_next (fsound, comment)) {
+#ifdef DEBUG
+ fprintf (stderr, "fs_vorbis_enc_headers: %s = %s\n",
+ comment->name, comment->value);
+#endif
+ vorbis_comment_add_tag (&fsv->vc, comment->name, comment->value);
+ }
+ /* Generate the headers */
vorbis_analysis_headerout(&fsv->vd, &fsv->vc,
&header, &header_comm, &header_code);
+ /* Pass the generated headers to the user */
if (fsound->callback) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback;
@@ -318,7 +337,6 @@
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
float ** vpcm;
long len, remaining = frames;
- int i, j;
float * d = (float *)pcm;
if (fsv->packetno == 0) {
@@ -331,12 +349,7 @@
/* expose the buffer to submit data */
vpcm = vorbis_analysis_buffer (&fsv->vd, 1024);
- /*_fs_deinterleave (p, vpcm, len, fsound->info.channels, 1.0);*/
- for (i = 0; i < fsound->info.channels; i++) {
- for (j = 0; j < len; j++) {
- vpcm[i][j] = d[j*fsound->info.channels + i];
- }
- }
+ _fs_deinterleave ((float **)d, vpcm, len, fsound->info.channels, 1.0);
d += (len * fsound->info.channels);
Modified: trunk/src/tests/Makefile.am
===================================================================
--- trunk/src/tests/Makefile.am 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/tests/Makefile.am 2004-05-05 10:17:08 UTC (rev 68)
@@ -4,9 +4,33 @@
INCLUDES = -I$(top_srcdir)/include
+FISHSOUNDDIR = ../libfishsound
+FISHSOUND_LIBS = $(FISHSOUNDDIR)/libfishsound.la $(VORBIS_LIBS) $(SPEEX_LIBS)
+
# Test programs
-#xTESTS =
+test: check
-#noinst_PROGRAMS = $(xTESTS)
+if FS_ENCODE
+encode_tests = comment-test
+endif
+if FS_DECODE
+if FS_ENCODE
+encdec_tests = encdec-comments encdec-audio
+endif
+endif
+
+TESTS = $(encode_tests) $(decode_tests) $(encdec_tests)
+
+noinst_PROGRAMS = $(TESTS)
+noinst_HEADERS = fs_tests.h
+
+comment_test_SOURCES = comment-test.c
+comment_test_LDADD = $(FISHSOUND_LIBS)
+
+encdec_comments_SOURCES = encdec-comments.c
+encdec_comments_LDADD = $(FISHSOUND_LIBS)
+
+encdec_audio_SOURCES = encdec-audio.c
+encdec_audio_LDADD = $(FISHSOUND_LIBS)
\ No newline at end of file
Added: trunk/src/tests/comment-test.c
===================================================================
--- trunk/src/tests/comment-test.c 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/tests/comment-test.c 2004-05-05 10:17:08 UTC (rev 68)
@@ -0,0 +1,221 @@
+/*
+ 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 <fishsound/fishsound.h>
+
+#include "fs_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 FishSound * fsound;
+
+int
+main (int argc, char * argv[])
+{
+ FishSoundInfo fsinfo;
+ const FishSoundComment * comment, * comment2;
+ FishSoundComment mycomment;
+ int err;
+
+ fsinfo.samplerate = 16000;
+ fsinfo.channels = 1;
+ /* The format doesn't really matter as we're not actually
+ * going to encode any audio, so just ensure we can
+ * set this to something that's configured.
+ */
+#if HAVE_VORBIS
+ fsinfo.format = FISH_SOUND_VORBIS;
+#else
+ fsinfo.format = FISH_SOUND_SPEEX;
+#endif
+
+#if FS_ENCODE
+ INFO ("Initializing FishSound for comments (encode)");
+ fsound = fish_sound_new (FISH_SOUND_ENCODE, &fsinfo);
+
+ INFO ("+ Testing add of invalid unstructured COMMENT byname");
+ err = fish_sound_comment_add_byname (fsound, COMMENT, NULL);
+ if (err != FISH_SOUND_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 = fish_sound_comment_add (fsound, &mycomment);
+ if (err != FISH_SOUND_ERR_COMMENT_INVALID)
+ FAIL ("Invalid comment not detected");
+
+ INFO ("+ Adding ARTIST1 byname");
+ err = fish_sound_comment_add_byname (fsound, "ARTIST", ARTIST1);
+ if (err < 0) FAIL ("Operation failed");
+
+ INFO ("+ Adding COPYRIGHT byname");
+ err = fish_sound_comment_add_byname (fsound, "COPYRIGHT", COPYRIGHT);
+ if (err < 0) FAIL ("Operation failed");
+
+ INFO ("+ Retrieving first (expect ARTIST1)");
+ comment = fish_sound_comment_first (fsound);
+
+ 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 = fish_sound_comment_next (fsound, comment);
+
+ if (comment == NULL)
+ FAIL ("Recently inserted COPYRIGHT not retrieved");
+
+ if (strcmp (comment->name, "COPYRIGHT"))
+ FAIL ("Incorrect COPYRIGHT name found");
+
+ if (strcmp (comment->value, COPYRIGHT))
+ FAIL ("Incorrect COPYRIGHT value found");
+
+ INFO ("+ Checking comments termination");
+ comment2 = fish_sound_comment_next (fsound, comment);
+
+ if (comment2 != NULL)
+ FAIL ("Comments unterminated");
+
+ INFO ("+ Adding LICENSE from local storage");
+ mycomment.name = "LICENSE";
+ mycomment.value = LICENSE;
+ err = fish_sound_comment_add (fsound, &mycomment);
+ if (err < 0) FAIL ("Operation failed");
+
+ INFO ("+ Retrieving next (expect LICENSE)");
+ comment = fish_sound_comment_next (fsound, comment);
+
+ if (comment == NULL)
+ FAIL ("Recently inserted LICENSE not retrieved");
+
+ if (comment == &mycomment)
+ FAIL ("Recently inserted LICENSE not restored");
+
+ if (strcmp (comment->name, "LICENSE"))
+ FAIL ("Incorrect LICENSE name found");
+
+ if (strcmp (comment->value, LICENSE))
+ FAIL ("Incorrect LICENSE value found");
+
+ INFO ("+ Adding ARTIST2 byname");
+ err = fish_sound_comment_add_byname (fsound, "ARTIST", ARTIST2);
+ if (err < 0) FAIL ("Operation failed");
+
+ INFO ("+ Retrieving first ARTIST (expect ARTIST1)");
+ comment = fish_sound_comment_first_byname (fsound, "ARTIST");
+
+ 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 ARTIST (expect ARTIST2)");
+ comment = fish_sound_comment_next_byname (fsound, comment);
+
+ if (comment == NULL)
+ FAIL ("Recently inserted ARTIST2 not retrieved");
+
+ if (strcmp (comment->name, "ARTIST"))
+ FAIL ("Incorrect ARTIST2 name found");
+
+ if (strcmp (comment->value, ARTIST2))
+ FAIL ("Incorrect ARTIST2 value found");
+
+ INFO ("+ Removing LICENSE byname");
+ err = fish_sound_comment_remove_byname (fsound, "LICENSE");
+ if (err != 1) FAIL ("Operation failed");
+
+ INFO ("+ Attempting to retrieve LICENSE");
+ comment = fish_sound_comment_first_byname (fsound, "LICENSE");
+
+ if (comment != NULL)
+ FAIL ("Removed comment incorrectly retrieved");
+
+ INFO ("+ Removing COPYRIGHT from local storage");
+ mycomment.name = "COPYRIGHT";
+ mycomment.value = COPYRIGHT;
+ err = fish_sound_comment_remove (fsound, &mycomment);
+ if (err != 1) FAIL ("Operation failed");
+
+ INFO ("+ Attempting to retrieve COPYRIGHT");
+ comment = fish_sound_comment_first_byname (fsound, "COPYRIGHT");
+
+ if (comment != NULL)
+ FAIL ("Removed comment incorrectly retrieved");
+
+ INFO ("Deleting FishSound (encode)");
+ fish_sound_delete (fsound);
+#endif /* FS_ENCODE */
+
+#if FS_DECODE
+ INFO ("Initializing FishSound for comments (decode)");
+ fsound = fish_sound_new (FISH_SOUND_DECODE, &fsinfo);
+
+ INFO ("+ Adding ARTIST1 byname (invalid for decode)");
+ err = fish_sound_comment_add_byname (fsound, "ARTIST", ARTIST1);
+
+ if (err == 0)
+ FAIL ("Operation disallowed");
+
+ INFO ("+ Removing ARTIST byname (invalid for decode)");
+ err = fish_sound_comment_remove_byname (fsound, "ARTIST");
+
+ if (err == 0)
+ FAIL ("Operation disallowed");
+
+ INFO ("Deleteing FishSound (decode)");
+ fish_sound_delete (fsound);
+#endif
+
+ exit (0);
+}
Added: trunk/src/tests/encdec-audio.c
===================================================================
--- trunk/src/tests/encdec-audio.c 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/tests/encdec-audio.c 2004-05-05 10:17:08 UTC (rev 68)
@@ -0,0 +1,195 @@
+/*
+ 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 <fishsound/fishsound.h>
+
+#include "fs_tests.h"
+
+#define DEBUG
+
+typedef struct {
+ FishSound * encoder;
+ FishSound * decoder;
+ float ** pcm;
+} FS_EncDec;
+
+static int
+decoded (FishSound * fsound, float ** pcm, long frames, void * user_data)
+{
+ /* Boo! */
+ return 0;
+}
+
+static int
+encoded (FishSound * fsound, unsigned char * buf, long bytes, void * user_data)
+{
+ FS_EncDec * ed = (FS_EncDec *) user_data;
+ fish_sound_decode (ed->decoder, buf, bytes);
+ return 0;
+}
+
+/* Fill a PCM buffer with a squarish wave */
+static void
+fs_fill_square (float * pcm, int length)
+{
+ float value = 0.5;
+ int i;
+
+ for (i = 0; i < length; i++) {
+ pcm[i] = value;
+ if ((i % 100) == 0) {
+ value = -value;
+ }
+ }
+}
+
+static FS_EncDec *
+fs_encdec_new (int samplerate, int channels, int format, int interleave,
+ int blocksize)
+{
+ FS_EncDec * ed;
+ FishSoundInfo fsinfo;
+ int i;
+
+ ed = malloc (sizeof (FS_EncDec));
+
+ fsinfo.samplerate = samplerate;
+ fsinfo.channels = channels;
+ fsinfo.format = format;
+
+ ed->encoder = fish_sound_new (FISH_SOUND_ENCODE, &fsinfo);
+ ed->decoder = fish_sound_new (FISH_SOUND_DECODE, &fsinfo);
+
+ fish_sound_set_interleave (ed->encoder, interleave);
+ fish_sound_set_interleave (ed->decoder, interleave);
+
+ fish_sound_set_encoded_callback (ed->encoder, encoded, ed);
+ fish_sound_set_decoded_callback (ed->decoder, decoded, ed);
+
+ if (interleave) {
+ ed->pcm = (float **) malloc (sizeof (float) * channels * blocksize);
+ fs_fill_square ((float *)ed->pcm, channels * blocksize);
+ } else {
+ ed->pcm = (float **) malloc (sizeof (float *) * channels);
+ for (i = 0; i < channels; i++) {
+ ed->pcm[i] = (float *) malloc (sizeof (float) * blocksize);
+ fs_fill_square (ed->pcm[i], blocksize);
+ }
+ }
+
+ return ed;
+}
+
+static int
+fs_encdec_delete (FS_EncDec * ed)
+{
+ if (!ed) return -1;
+
+ fish_sound_delete (ed->encoder);
+ fish_sound_delete (ed->decoder);
+ free (ed);
+
+ return 0;
+}
+
+static int
+fs_encdec_test (int samplerate, int channels, int format, int interleave,
+ int blocksize)
+{
+ FS_EncDec * ed;
+ int i;
+
+ ed = fs_encdec_new (samplerate, channels, format, interleave, blocksize);
+
+ for (i = 0; i < 2; i++) {
+ fish_sound_encode (ed->encoder, ed->pcm, blocksize);
+ }
+
+ fs_encdec_delete (ed);
+
+ return 0;
+}
+
+int
+main (int argc, char * argv[])
+{
+
+#ifdef NASTY
+ int blocksizes[6] = {128, 256, 512, 1024, 2048, 4096};
+ int samplerates[4] = {8000, 16000, 32000, 48000};
+ int channels[9] = {1, 2, 4, 5, 6, 8, 10, 16, 32};
+#else
+ int blocksizes[2] = {128, 1024};
+ int samplerates[2] = {8000, 48000};
+ int channels[4] = {1, 2, 6, 16};
+#endif
+ int interleave, b, s, c;
+ char buf[128];
+
+ INFO ("Testing encode/decode pipeline for audio");
+
+ for (b = 0; b < sizeof (blocksizes) / sizeof (int); b++) {
+ for (s = 0; s < sizeof (samplerates) / sizeof (int); s++) {
+ for (c = 0; c < sizeof (channels) / sizeof (int); c++) {
+ for (interleave = 0; interleave < 2; interleave++) {
+
+ /* Test VORBIS */
+ snprintf (buf, 128, "+ %2d channel %6d Hz Vorbis, %d frame buffer (%s)",
+ channels[c], samplerates[s], blocksizes[b],
+ interleave ? "interleave" : "non-interleave");
+ INFO (buf);
+ fs_encdec_test (samplerates[s], channels[c], FISH_SOUND_VORBIS,
+ interleave, blocksizes[b]);
+
+ /* Test SPEEX */
+ if (channels[c] <= 2) {
+ snprintf (buf, 128, "+ %2d channel %6d Hz Speex, %d frame buffer (%s)",
+ channels[c], samplerates[s], blocksizes[b],
+ interleave ? "interleave" : "non-interleave");
+ INFO (buf);
+ fs_encdec_test (samplerates[s], channels[c], FISH_SOUND_SPEEX,
+ interleave, blocksizes[b]);
+
+ }
+ }
+ }
+ }
+ }
+
+ exit (0);
+}
Added: trunk/src/tests/encdec-comments.c
===================================================================
--- trunk/src/tests/encdec-comments.c 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/tests/encdec-comments.c 2004-05-05 10:17:08 UTC (rev 68)
@@ -0,0 +1,230 @@
+/*
+ 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 <fishsound/fishsound.h>
+
+#include "fs_tests.h"
+
+#define DEBUG
+
+#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"
+
+typedef struct {
+ FishSound * encoder;
+ FishSound * decoder;
+ float ** pcm;
+} FS_EncDec;
+
+static int
+decoded (FishSound * fsound, float ** pcm, long frames, void * user_data)
+{
+ const FishSoundComment * comment;
+
+ INFO ("+ Retrieving first (expect ARTIST1)");
+ comment = fish_sound_comment_first (fsound);
+
+ 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 = fish_sound_comment_next (fsound, comment);
+
+ if (comment == NULL)
+ FAIL ("Recently inserted COPYRIGHT not retrieved");
+
+ if (strcmp (comment->name, "COPYRIGHT"))
+ FAIL ("Incorrect COPYRIGHT name found");
+
+ if (strcmp (comment->value, COPYRIGHT))
+ FAIL ("Incorrect COPYRIGHT value found");
+
+ INFO ("+ Retrieving next (expect LICENSE)");
+ comment = fish_sound_comment_next (fsound, comment);
+
+ if (comment == NULL)
+ FAIL ("Recently inserted LICENSE not retrieved");
+
+ if (strcmp (comment->name, "LICENSE"))
+ FAIL ("Incorrect LICENSE name found");
+
+ if (strcmp (comment->value, LICENSE))
+ FAIL ("Incorrect LICENSE value found");
+
+ INFO ("+ Retrieving first ARTIST (expect ARTIST1)");
+ comment = fish_sound_comment_first_byname (fsound, "ARTIST");
+
+ if (comment == NULL)
+ FAIL ("First artist 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 ARTIST (expect ARTIST2)");
+ comment = fish_sound_comment_next_byname (fsound, comment);
+
+ if (comment == NULL)
+ FAIL ("Next artist ARTIST2 not retrieved");
+
+ if (strcmp (comment->name, "ARTIST"))
+ FAIL ("Incorrect ARTIST2 name found");
+
+ if (strcmp (comment->value, ARTIST2))
+ FAIL ("Incorrect ARTIST2 value found");
+
+ return 0;
+}
+
+static int
+encoded (FishSound * fsound, unsigned char * buf, long bytes, void * user_data)
+{
+ FS_EncDec * ed = (FS_EncDec *) user_data;
+ fish_sound_decode (ed->decoder, buf, bytes);
+ return 0;
+}
+
+/* Fill a PCM buffer with a squarish wave */
+static void
+fs_fill_square (float * pcm, int length)
+{
+ float value = 0.5;
+ int i;
+
+ for (i = 0; i < length; i++) {
+ pcm[i] = value;
+ if ((i % 100) == 0) {
+ value = -value;
+ }
+ }
+}
+
+static FS_EncDec *
+fs_encdec_new (int format, int blocksize)
+{
+ FS_EncDec * ed;
+ FishSoundInfo fsinfo;
+
+ ed = malloc (sizeof (FS_EncDec));
+
+ fsinfo.samplerate = 8000;
+ fsinfo.channels = 1;
+ fsinfo.format = format;
+
+ ed->encoder = fish_sound_new (FISH_SOUND_ENCODE, &fsinfo);
+ ed->decoder = fish_sound_new (FISH_SOUND_DECODE, &fsinfo);
+
+ fish_sound_set_interleave (ed->encoder, 1);
+ fish_sound_set_interleave (ed->decoder, 1);
+
+ fish_sound_set_encoded_callback (ed->encoder, encoded, ed);
+ fish_sound_set_decoded_callback (ed->decoder, decoded, ed);
+
+ ed->pcm = (float **) malloc (sizeof (float) * blocksize);
+ fs_fill_square ((float *)ed->pcm, blocksize);
+
+ return ed;
+}
+
+static int
+fs_encdec_delete (FS_EncDec * ed)
+{
+ if (!ed) return -1;
+
+ fish_sound_delete (ed->encoder);
+ fish_sound_delete (ed->decoder);
+ free (ed);
+
+ return 0;
+}
+
+static int
+fs_encdec_comments_test (int format, int blocksize)
+{
+ FS_EncDec * ed;
+ FishSoundComment mycomment;
+ int err;
+
+ ed = fs_encdec_new (format, blocksize);
+
+ INFO ("+ Adding ARTIST1 byname");
+ err = fish_sound_comment_add_byname (ed->encoder, "ARTIST", ARTIST1);
+ if (err < 0) FAIL ("Operation failed");
+
+ INFO ("+ Adding COPYRIGHT byname");
+ err = fish_sound_comment_add_byname (ed->encoder, "COPYRIGHT", COPYRIGHT);
+ if (err < 0) FAIL ("Operation failed");
+
+ INFO ("+ Adding LICENSE from local storage");
+ mycomment.name = "LICENSE";
+ mycomment.value = LICENSE;
+ err = fish_sound_comment_add (ed->encoder, &mycomment);
+ if (err < 0) FAIL ("Operation failed");
+
+ INFO ("+ Adding ARTIST2 byname");
+ err = fish_sound_comment_add_byname (ed->encoder, "ARTIST", ARTIST2);
+ if (err < 0) FAIL ("Operation failed");
+
+ fish_sound_encode (ed->encoder, ed->pcm, blocksize);
+
+ fs_encdec_delete (ed);
+
+ return 0;
+}
+
+int
+main (int argc, char * argv[])
+{
+ INFO ("Testing encode/decode pipeline for comments: VORBIS");
+ fs_encdec_comments_test (FISH_SOUND_VORBIS, 2048);
+
+ INFO ("Testing encode/decode pipeline for comments: SPEEX");
+ fs_encdec_comments_test (FISH_SOUND_SPEEX, 2048);
+
+ exit (0);
+}
Added: trunk/src/tests/fs_tests.h
===================================================================
--- trunk/src/tests/fs_tests.h 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/src/tests/fs_tests.h 2004-05-05 10:17:08 UTC (rev 68)
@@ -0,0 +1,45 @@
+/*
+ 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>
+
+#define INFO(str) \
+ { printf ("---- %s ...\n", (str)); fflush (stdout); }
+
+#define WARN(str) \
+ { printf ("%s:%d: warning: %s\n", __FILE__, __LINE__, (str)); fflush (stdout); }
+
+#define FAIL(str) \
+ { printf ("%s:%d: %s\n", __FILE__, __LINE__, (str)); fflush (stdout); exit(1); }
Modified: trunk/win32/libfishsound/libfishsound.def
===================================================================
--- trunk/win32/libfishsound/libfishsound.def 2004-05-03 22:27:11 UTC (rev 67)
+++ trunk/win32/libfishsound/libfishsound.def 2004-05-05 10:17:08 UTC (rev 68)
@@ -13,4 +13,13 @@
fish_sound_get_interleave
fish_sound_set_interleave
fish_sound_get_frameno
- fish_sound_set_frameno
\ No newline at end of file
+ fish_sound_set_frameno
+ fish_sound_get_vendor
+ fish_sound_comment_first
+ fish_sound_comment_next
+ fish_sound_comment_first_byname
+ fish_sound_comment_next_byname
+ fish_sound_comment_add
+ fish_sound_comment_add_byname
+ fish_sound_comment_remove
+ fish_sound_comment_remove_byname
--
conrad
More information about the cvs-annodex
mailing list