[xiph-cvs] cvs commit: vorbis-tools/ogg123 easyflac.c easyflac.h flac_format.c vorbis_comments.c vorbis_comments.h Makefile.am format.c oggvorbis_format.c
Stan Seibert
volsung at xiph.org
Sat Jan 11 14:51:45 PST 2003
volsung 03/01/11 17:51:45
Modified: . configure.in
ogg123 Makefile.am format.c oggvorbis_format.c
Added: ogg123 easyflac.c easyflac.h flac_format.c
vorbis_comments.c vorbis_comments.h
Log:
ogg123 now plays FLAC files!
- Added stuff into configure.in to detect FLAC libraries and headers
(should autodetect correctly, but you can also force it off with
--without-flac) as well as setup conditional building.
- FLAC is not required to build ogg123 (unlike curl).
- Reads both FLAC and Ogg FLAC
- Refactored vorbis comment pretty printing into separate file since it
is shared by both FLAC and Vorbis readers (and future Speex reader will
need it too)
- Fixed bug caused by assuming Vorbis comments were null terminated.
Revision Changes Path
1.46 +25 -3 vorbis-tools/configure.in
Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/configure.in,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- configure.in 7 Nov 2002 11:16:13 -0000 1.45
+++ configure.in 11 Jan 2003 22:51:44 -0000 1.46
@@ -90,7 +90,7 @@
AC_ARG_ENABLE(ogginfo,[ --disable-ogginfo Skip building ogginfo], build_ogginfo="$enableval", build_ogginfo="yes")
AC_ARG_ENABLE(vcut, [ --disable-vcut Skip building vcut], build_vcut="$enableval", build_vcut="yes")
AC_ARG_ENABLE(vorbiscomment, [ --disable-vorbiscomment Skip building vorbiscomment], build_vorbiscomment="$enableval", build_vorbiscomment="yes")
-
+AC_ARG_WITH(flac, [ --without-flac Do not compile FLAC support], build_flac="$enableval", build_flac="yes")
dnl --------------------------------------------------
dnl Check for generally needed libraries
@@ -110,7 +110,7 @@
AC_CHECK_LIB(nsl, gethostbyname, SOCKET_LIBS="-lnsl $SOCKET_LIBS")
dnl --------------------------------------------------
-dnl Check for ogg123 critical libraries
+dnl Check for ogg123 critical libraries and other optional libraries
dnl --------------------------------------------------
if test "x$build_ogg123" = xyes; then
@@ -124,7 +124,29 @@
AC_MSG_WARN([Prerequisites for ogg123 not met, ogg123 will not be built])
fi
fi
-
+
+FLAC_LIBS=
+
+AC_CHECK_LIB(m,log,FLAC_EXTRA_LIBS="-lm")
+AC_CHECK_LIB(FLAC, FLAC__stream_decoder_process_single,have_libFLAC=yes,
+ AC_MSG_WARN(libFLAC missing)
+ have_libFLAC=no, $FLAC_EXTRA_LIBS
+)
+AC_CHECK_HEADER(FLAC/stream_decoder.h,,
+ AC_MSG_WARN(libFLAC headers missing)
+ have_libFLAC=no,[ ])
+
+if test "x$have_libFLAC" = xyes; then
+ if test "x$build_flac" = xyes; then
+ AC_DEFINE(HAVE_LIBFLAC)
+ FLAC_LIBS="$FLAC_EXTRA_LIBS -lFLAC -lOggFLAC"
+ fi
+else
+ build_flac="no"
+fi
+AM_CONDITIONAL(HAVE_LIBFLAC, test "x$build_flac" = xyes)
+AC_SUBST(FLAC_LIBS)
+
dnl --------------------------------------------------
dnl Check for library functions
dnl --------------------------------------------------
<p><p>1.27 +19 -5 vorbis-tools/ogg123/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/Makefile.am,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- Makefile.am 11 Jul 2002 02:45:37 -0000 1.26
+++ Makefile.am 11 Jan 2003 22:51:44 -0000 1.27
@@ -8,11 +8,25 @@
cfgfile_options.c cmdline_options.c \
file_transport.c format.c http_transport.c \
ogg123.c oggvorbis_format.c playlist.c \
- status.c transport.c \
+ status.c transport.c vorbis_comments.c \
audio.h buffer.h callbacks.h compat.h \
cfgfile_options.h cmdline_options.h \
format.h ogg123.h playlist.h status.h \
- transport.h
+ transport.h vorbis_comments.h
+flacsources = flac_format.c easyflac.c easyflac.h
+
+
+if HAVE_LIBFLAC
+
+buildsources = $(ogg123sources) $(flacsources)
+flaclibs = @FLAC_LIBS@
+
+else
+
+buildsources = $(ogg123sources)
+flaclibs =
+
+endif
if BUILD_OGG123
@@ -31,16 +45,16 @@
ogg123_LDADD = @SHARE_LIBS@ \
@VORBISFILE_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ @AO_LIBS@ \
@SOCKET_LIBS@ @LIBICONV@ @CURL_LIBS@ @PTHREAD_CFLAGS@ \
- @PTHREAD_LIBS@ @I18N_LIBS@
+ @PTHREAD_LIBS@ @I18N_LIBS@ $(flaclibs)
ogg123_DEPENDENCIES = @SHARE_LIBS@
-ogg123_SOURCES = $(ogg123sources)
+ogg123_SOURCES = $(buildsources)
man_MANS = $(mans)
doc_DATA = $(docs)
endif
-EXTRA_DIST = $(ogg123sources) $(mans) $(docs)
+EXTRA_DIST = $(ogg123sources) $(flacsources) $(mans) $(docs)
debug:
<p><p>1.4 +14 -2 vorbis-tools/ogg123/format.c
Index: format.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/format.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- format.c 26 Jan 2002 11:06:37 -0000 1.3
+++ format.c 11 Jan 2003 22:51:44 -0000 1.4
@@ -11,7 +11,7 @@
* *
********************************************************************
- last mod: $Id: format.c,v 1.3 2002/01/26 11:06:37 segher Exp $
+ last mod: $Id: format.c,v 1.4 2003/01/11 22:51:44 volsung Exp $
********************************************************************/
@@ -24,7 +24,19 @@
extern format_t oggvorbis_format;
-format_t *formats[] = { &oggvorbis_format, NULL };
+#ifdef HAVE_LIBFLAC
+extern format_t flac_format;
+extern format_t oggflac_format;
+#endif
+
+
+format_t *formats[] = {
+#ifdef HAVE_LIBFLAC
+ &flac_format,
+ &oggflac_format,
+#endif
+ &oggvorbis_format,
+ NULL };
format_t *get_format_by_name (char *name)
<p><p>1.10 +32 -108 vorbis-tools/ogg123/oggvorbis_format.c
Index: oggvorbis_format.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/oggvorbis_format.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- oggvorbis_format.c 19 Jul 2002 10:31:53 -0000 1.9
+++ oggvorbis_format.c 11 Jan 2003 22:51:44 -0000 1.10
@@ -11,7 +11,7 @@
* *
********************************************************************
- last mod: $Id: oggvorbis_format.c,v 1.9 2002/07/19 10:31:53 msmith Exp $
+ last mod: $Id: oggvorbis_format.c,v 1.10 2003/01/11 22:51:44 volsung Exp $
********************************************************************/
@@ -23,6 +23,7 @@
#include <vorbis/vorbisfile.h>
#include "transport.h"
#include "format.h"
+#include "vorbis_comments.h"
#include "utf8.h"
#include "i18n.h"
@@ -43,26 +44,9 @@
ov_callbacks vorbisfile_callbacks;
-/* Vorbis comment keys that need special formatting. */
-struct {
- char *key; /* includes the '=' for programming convenience */
- char *formatstr; /* formatted output */
-} vorbis_comment_keys[] = {
- {"TRACKNUMBER=", N_("Track number:")},
- {"REPLAYGAIN_TRACK_GAIN=", N_("ReplayGain (Track):")},
- {"REPLAYGAIN_ALBUM_GAIN=", N_("ReplayGain (Album):")},
- {"REPLAYGAIN_TRACK_PEAK=", N_("ReplayGain (Track) Peak:")},
- {"REPLAYGAIN_ALBUM_PEAK=", N_("ReplayGain (Album) Peak:")},
- {"COPYRIGHT=", N_("Copyright")},
- {"=", N_("Comment:")},
- {NULL, N_("Comment:")}
-};
-
-
-/* Private functions declarations */
-char *lookup_comment_prettyprint (char *comment, int *offset);
-void print_stream_comments (decoder_t *decoder);
-void print_stream_info (decoder_t *decoder);
+void print_vorbis_stream_info (decoder_t *decoder);
+void print_vorbis_comments (vorbis_comment *vc, decoder_callbacks_t *cb,
+ void *callback_arg);
/* ----------------------------------------------------------- */
@@ -139,8 +123,9 @@
decoder->actual_fmt.rate = priv->vi->rate;
decoder->actual_fmt.channels = priv->vi->channels;
- print_stream_comments(decoder);
- print_stream_info(decoder);
+
+ print_vorbis_comments(priv->vc, cb, decoder->callback_arg);
+ print_vorbis_stream_info(decoder);
priv->bos = 0;
}
@@ -304,91 +289,7 @@
/* ------------------- Private functions -------------------- */
-char *lookup_comment_prettyprint (char *comment, int *offset)
-{
- int i, j;
- char *s;
-
- /* Search for special-case formatting */
- for (i = 0; vorbis_comment_keys[i].key != NULL; i++) {
-
- if ( !strncasecmp (vorbis_comment_keys[i].key, comment,
- strlen(vorbis_comment_keys[i].key)) ) {
-
- *offset = strlen(vorbis_comment_keys[i].key);
- s = malloc(strlen(vorbis_comment_keys[i].formatstr) + 1);
- if (s == NULL) {
- fprintf(stderr, _("Error: Out of memory.\n"));
- exit(1);
- };
- strcpy(s, vorbis_comment_keys[i].formatstr);
- return s;
- }
-
- }
-
- /* Use default formatting */
- j = strcspn(comment, "=");
- if (j) {
- *offset = j + 1;
- s = malloc(j + 2);
- if (s == NULL) {
- fprintf(stderr, _("Error: Out of memory.\n"));
- exit(1);
- };
- strncpy(s, comment, j);
- strcpy(s + j, ":");
-
- /* Capitalize */
- s[0] = toupper(s[0]);
- for (i = 1; i < j; i++) {
- s[i] = tolower(s[i]);
- };
- return s;
- }
-
- /* Unrecognized comment, use last format string */
- *offset = 0;
- s = malloc(strlen(vorbis_comment_keys[i].formatstr) + 1);
- if (s == NULL) {
- fprintf(stderr, _("Error: Out of memory.\n"));
- exit(1);
- };
- strcpy(s, vorbis_comment_keys[i].formatstr);
- return s;
-}
-
-
-void print_stream_comments (decoder_t *decoder)
-{
- ovf_private_t *priv = decoder->private;
- decoder_callbacks_t *cb = decoder->callbacks;
- char *comment, *comment_prettyprint;
- int offset;
- int i;
-
-
- if (cb == NULL || cb->printf_metadata == NULL)
- return;
-
- for (i = 0; i < priv->vc->comments; i++) {
- char *decoded_value;
-
- comment = priv->vc->user_comments[i];
- comment_prettyprint = lookup_comment_prettyprint(comment, &offset);
-
- if (utf8_decode(comment + offset, &decoded_value) >= 0) {
- cb->printf_metadata(decoder->callback_arg, 1,
- "%s %s", comment_prettyprint, decoded_value);
- free(decoded_value);
- } else
- cb->printf_metadata(decoder->callback_arg, 1,
- "%s %s", comment_prettyprint, comment + offset);
- free(comment_prettyprint);
- }
-}
-
-void print_stream_info (decoder_t *decoder)
+void print_vorbis_stream_info (decoder_t *decoder)
{
ovf_private_t *priv = decoder->private;
decoder_callbacks_t *cb = decoder->callbacks;
@@ -419,3 +320,26 @@
_("Encoded by: %s"), priv->vc->vendor);
}
+void print_vorbis_comments (vorbis_comment *vc, decoder_callbacks_t *cb,
+ void *callback_arg)
+{
+ int i;
+ char *temp = NULL;
+ int temp_len = 0;
+
+ for (i = 0; i < vc->comments; i++) {
+
+ /* Gotta null terminate these things */
+ if (temp_len < vc->comment_lengths[i] + 1) {
+ temp_len = vc->comment_lengths[i] + 1;
+ temp = realloc(temp, sizeof(char) * temp_len);
+ }
+
+ strncpy(temp, vc->user_comments[i], vc->comment_lengths[i]);
+ temp[vc->comment_lengths[i]] = '\0';
+
+ print_vorbis_comment(temp, cb, callback_arg);
+ }
+
+ free(temp);
+}
<p><p>1.1 vorbis-tools/ogg123/easyflac.c
Index: easyflac.c
===================================================================
/* EasyFLAC - A thin decoding wrapper around libFLAC and libOggFLAC to
* make your code less ugly. See easyflac.h for explanation.
*
* Copyright 2003 - Stan Seibert <volsung at xiph.org>
* This code is licensed under a BSD style license:
*
* 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 the Xiph.org Foundation 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 FOUNDATION
* 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 <stdlib.h>
#include "easyflac.h"
<p>FLAC__bool EasyFLAC__is_oggflac(EasyFLAC__StreamDecoder *decoder)
{
return decoder->is_oggflac;
}
<p>EasyFLAC__StreamDecoder *EasyFLAC__stream_decoder_new(FLAC__bool is_oggflac)
{
EasyFLAC__StreamDecoder *decoder = malloc(sizeof(EasyFLAC__StreamDecoder));
if (decoder != NULL)
{
decoder->is_oggflac = is_oggflac;
if (decoder->is_oggflac)
decoder->oggflac = OggFLAC__stream_decoder_new();
else
decoder->flac = FLAC__stream_decoder_new();
if ( (decoder->is_oggflac && decoder->oggflac == NULL)
||(!decoder->is_oggflac && decoder->flac == NULL) )
{
free(decoder);
decoder = NULL;
}
}
return decoder;
}
<p>void EasyFLAC__stream_decoder_delete(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
OggFLAC__stream_decoder_delete(decoder->oggflac);
else
FLAC__stream_decoder_delete(decoder->flac);
free(decoder);
}
<p>/* Wrappers around the callbacks for OggFLAC */
FLAC__StreamDecoderReadStatus oggflac_read_callback(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
return (*e_decoder->callbacks.read)(e_decoder, buffer, bytes, e_decoder->callbacks.client_data);
}
<p>FLAC__StreamDecoderWriteStatus oggflac_write_callback(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
return (*(e_decoder->callbacks.write))(e_decoder, frame, buffer, e_decoder->callbacks.client_data);
}
<p>void oggflac_metadata_callback(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
(*e_decoder->callbacks.metadata)(e_decoder, metadata, e_decoder->callbacks.client_data);
}
<p>void oggflac_error_callback(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
(*e_decoder->callbacks.error)(e_decoder, status, e_decoder->callbacks.client_data);
}
<p>/* Wrappers around the callbacks for FLAC */
FLAC__StreamDecoderReadStatus flac_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
return (*e_decoder->callbacks.read)(e_decoder, buffer, bytes, e_decoder->callbacks.client_data);
}
<p>FLAC__StreamDecoderWriteStatus flac_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
return (*e_decoder->callbacks.write)(e_decoder, frame, buffer, e_decoder->callbacks.client_data);
}
<p>void flac_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
(*e_decoder->callbacks.metadata)(e_decoder, metadata, e_decoder->callbacks.client_data);
}
<p>void flac_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data;
(*e_decoder->callbacks.error)(e_decoder, status, e_decoder->callbacks.client_data);
}
<p>FLAC__bool EasyFLAC__set_read_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderReadCallback value)
{
decoder->callbacks.read = value;
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_read_callback(decoder->oggflac, &oggflac_read_callback);
else
return FLAC__stream_decoder_set_read_callback(decoder->flac, &flac_read_callback);
}
<p>FLAC__bool EasyFLAC__set_write_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderWriteCallback value)
{
decoder->callbacks.write = value;
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_write_callback(decoder->oggflac, &oggflac_write_callback);
else
return FLAC__stream_decoder_set_write_callback(decoder->flac, &flac_write_callback);
}
<p>FLAC__bool EasyFLAC__set_metadata_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderMetadataCallback value)
{
decoder->callbacks.metadata = value;
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_metadata_callback(decoder->oggflac, &oggflac_metadata_callback);
else
return FLAC__stream_decoder_set_metadata_callback(decoder->flac, &flac_metadata_callback);
}
<p>FLAC__bool EasyFLAC__set_error_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderErrorCallback value)
{
decoder->callbacks.error = value;
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_error_callback(decoder->oggflac, &oggflac_error_callback);
else
return FLAC__stream_decoder_set_error_callback(decoder->flac, &flac_error_callback);
}
<p>FLAC__bool EasyFLAC__set_client_data(EasyFLAC__StreamDecoder *decoder, void *value)
{
decoder->callbacks.client_data = value;
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_client_data(decoder->oggflac, decoder);
else
return FLAC__stream_decoder_set_client_data(decoder->flac, decoder);
}
<p>FLAC__bool EasyFLAC__set_metadata_respond(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_metadata_respond(decoder->oggflac, type);
else
return FLAC__stream_decoder_set_metadata_respond(decoder->flac, type);
}
<p>FLAC__bool EasyFLAC__set_metadata_respond_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4])
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->oggflac, id);
else
return FLAC__stream_decoder_set_metadata_respond_application(decoder->flac, id);
}
<p>FLAC__bool EasyFLAC__set_metadata_respond_all(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->oggflac);
else
return FLAC__stream_decoder_set_metadata_respond_all(decoder->flac);
}
<p>FLAC__bool EasyFLAC__set_metadata_ignore(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_metadata_ignore(decoder->oggflac, type);
else
return FLAC__stream_decoder_set_metadata_ignore(decoder->flac, type);
}
<p>FLAC__bool EasyFLAC__set_metadata_ignore_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4])
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->oggflac, id);
else
return FLAC__stream_decoder_set_metadata_ignore_application(decoder->flac, id);
}
FLAC__bool EasyFLAC__set_metadata_ignore_all(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->oggflac);
else
return FLAC__stream_decoder_set_metadata_ignore_all(decoder->flac);
}
<p>FLAC__StreamDecoderState EasyFLAC__get_state(const EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->oggflac);
else
return FLAC__stream_decoder_get_state(decoder->flac);
}
<p>unsigned EasyFLAC__get_channels(const EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_get_channels(decoder->oggflac);
else
return FLAC__stream_decoder_get_channels(decoder->flac);
}
<p>FLAC__ChannelAssignment EasyFLAC__get_channel_assignment(const EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_get_channel_assignment(decoder->oggflac);
else
return FLAC__stream_decoder_get_channel_assignment(decoder->flac);
}
<p>unsigned EasyFLAC__get_bits_per_sample(const EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_get_bits_per_sample(decoder->oggflac);
else
return FLAC__stream_decoder_get_bits_per_sample(decoder->flac);
}
<p>unsigned EasyFLAC__get_sample_rate(const EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_get_sample_rate(decoder->oggflac);
else
return FLAC__stream_decoder_get_sample_rate(decoder->flac);
}
<p>unsigned EasyFLAC__get_blocksize(const EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_get_blocksize(decoder->oggflac);
else
return FLAC__stream_decoder_get_blocksize(decoder->flac);
}
<p>FLAC__StreamDecoderState EasyFLAC__init(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
{
OggFLAC__stream_decoder_init(decoder->oggflac);
return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->oggflac);
}
else
return FLAC__stream_decoder_init(decoder->flac);
}
<p>void EasyFLAC__finish(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
OggFLAC__stream_decoder_finish(decoder->oggflac);
else
FLAC__stream_decoder_finish(decoder->flac);
}
<p>FLAC__bool EasyFLAC__flush(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_flush(decoder->oggflac);
else
return FLAC__stream_decoder_flush(decoder->flac);
}
<p>FLAC__bool EasyFLAC__reset(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_reset(decoder->oggflac);
else
return FLAC__stream_decoder_reset(decoder->flac);
}
<p>FLAC__bool EasyFLAC__process_single(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_process_single(decoder->oggflac);
else
return FLAC__stream_decoder_process_single(decoder->flac);
}
<p>FLAC__bool EasyFLAC__process_until_end_of_metadata(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->oggflac);
else
return FLAC__stream_decoder_process_until_end_of_metadata(decoder->flac);
}
<p>FLAC__bool EasyFLAC__process_until_end_of_stream(EasyFLAC__StreamDecoder *decoder)
{
if (decoder->is_oggflac)
return OggFLAC__stream_decoder_process_until_end_of_stream(decoder->oggflac);
else
return FLAC__stream_decoder_process_until_end_of_stream(decoder->flac);
}
<p><p>1.1 vorbis-tools/ogg123/easyflac.h
Index: easyflac.h
===================================================================
/* EasyFLAC - A thin decoding wrapper around libFLAC and libOggFLAC to
* make your code less ugly.
*
* Copyright 2003 - Stan Seibert <volsung at xiph.org>
* This code is licensed under a BSD style license:
*
* 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 the Xiph.org Foundation 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 FOUNDATION
* 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.
*
************************************************************************
*
* The motivation for this wrapper is to avoid issues where you need to
* decode both FLAC and Ogg FLAC but don't want to enclose all of your code
* in enormous if blocks where the body of the two branches is essentially
* the same. For example, you don't want to do something like this:
*
* if (is_ogg_flac)
* {
* OggFLAC__blah_blah();
* OggFLAC__more_stuff();
* }
* else
* {
* FLAC__blah_blah();
* FLAC__more_stuff();
* }
*
* when you really just want this:
*
* EasyFLAC__blah_blah();
* EasyFLAC__more_stuff();
*
* This is even more cumbersome when you have to deal with constants.
*
* EasyFLAC uses essentially the same API as
* FLAC__stream_decoder with two additions:
*
* - EasyFLAC__is_oggflac() for those rare occassions when you might
* need to distiguish the difference cases.
*
* - EasyFLAC__stream_decoder_new() takes a parameter to select when
* you are reading FLAC or Ogg FLAC.
*
* The constants are all FLAC__stream_decoder_*.
*
* WARNING: Always call EasyFLAC__set_client_data() even if all you
* want to do is set the client data to NULL.
*/
#ifndef __EASYFLAC_H
#define __EASYFLAC_H
#include <FLAC/stream_decoder.h>
#include <OggFLAC/stream_decoder.h>
#ifdef __cplusplus
extern "C" {
#endif
<p>typedef struct EasyFLAC__StreamDecoder EasyFLAC__StreamDecoder;
<p>typedef FLAC__StreamDecoderReadStatus (*EasyFLAC__StreamDecoderReadCallback)(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
typedef FLAC__StreamDecoderWriteStatus (*EasyFLAC__StreamDecoderWriteCallback)(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
typedef void (*EasyFLAC__StreamDecoderMetadataCallback)(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
typedef void (*EasyFLAC__StreamDecoderErrorCallback)(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
truct EasyFLAC__StreamDecoder {
FLAC__bool is_oggflac;
FLAC__StreamDecoder *flac;
OggFLAC__StreamDecoder *oggflac;
struct {
EasyFLAC__StreamDecoderReadCallback read;
EasyFLAC__StreamDecoderWriteCallback write;
EasyFLAC__StreamDecoderMetadataCallback metadata;
EasyFLAC__StreamDecoderErrorCallback error;
void *client_data;
} callbacks;
};
<p><p>FLAC__bool EasyFLAC__is_oggflac(EasyFLAC__StreamDecoder *decoder);
EasyFLAC__StreamDecoder *EasyFLAC__stream_decoder_new(FLAC__bool is_oggflac);
void EasyFLAC__stream_decoder_delete(EasyFLAC__StreamDecoder *decoder);
FLAC__bool EasyFLAC__set_read_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderReadCallback value);
FLAC__bool EasyFLAC__set_write_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderWriteCallback value);
FLAC__bool EasyFLAC__set_metadata_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderMetadataCallback value);
FLAC__bool EasyFLAC__set_error_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderErrorCallback value);
FLAC__bool EasyFLAC__set_client_data(EasyFLAC__StreamDecoder *decoder, void *value);
FLAC__bool EasyFLAC__set_metadata_respond(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type);
FLAC__bool EasyFLAC__set_metadata_respond_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4]);
FLAC__bool EasyFLAC__set_metadata_respond_all(EasyFLAC__StreamDecoder *decoder);
FLAC__bool EasyFLAC__set_metadata_ignore(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type);
FLAC__bool EasyFLAC__set_metadata_ignore_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4]);
FLAC__bool EasyFLAC__set_metadata_ignore_all(EasyFLAC__StreamDecoder *decoder);
FLAC__StreamDecoderState EasyFLAC__get_state(const EasyFLAC__StreamDecoder *decoder);
unsigned EasyFLAC__get_channels(const EasyFLAC__StreamDecoder *decoder);
FLAC__ChannelAssignment EasyFLAC__get_channel_assignment(const EasyFLAC__StreamDecoder *decoder);
unsigned EasyFLAC__get_bits_per_sample(const EasyFLAC__StreamDecoder *decoder);
unsigned EasyFLAC__get_sample_rate(const EasyFLAC__StreamDecoder *decoder);
unsigned EasyFLAC__get_blocksize(const EasyFLAC__StreamDecoder *decoder);
FLAC__StreamDecoderState EasyFLAC__init(EasyFLAC__StreamDecoder *decoder);
void EasyFLAC__finish(EasyFLAC__StreamDecoder *decoder);
FLAC__bool EasyFLAC__flush(EasyFLAC__StreamDecoder *decoder);
FLAC__bool EasyFLAC__reset(EasyFLAC__StreamDecoder *decoder);
FLAC__bool EasyFLAC__process_single(EasyFLAC__StreamDecoder *decoder);
FLAC__bool EasyFLAC__process_until_end_of_metadata(EasyFLAC__StreamDecoder *decoder);
FLAC__bool EasyFLAC__process_until_end_of_stream(EasyFLAC__StreamDecoder *decoder);
#ifdef __cplusplus
}
#endif
#endif
<p><p>1.1 vorbis-tools/ogg123/flac_format.c
Index: flac_format.c
===================================================================
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
* THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
* PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2003 *
* by Stan Seibert <volsung at xiph.org> AND OTHER CONTRIBUTORS *
* http://www.xiph.org/ *
* *
********************************************************************
last mod: $Id: flac_format.c,v 1.1 2003/01/11 22:51:44 volsung Exp $
********************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <math.h>
#include <FLAC/metadata.h>
#include <ao/ao.h>
#include "audio.h"
#include "format.h"
#include "i18n.h"
#include "easyflac.h"
#include "vorbis_comments.h"
#define DEFAULT_FLAC_FRAME_SIZE 4608
typedef struct {
EasyFLAC__StreamDecoder *decoder;
short channels;
int rate;
int bits_per_sample;
long totalsamples; /* per channel, of course */
long currentsample; /* number of samples played, (not decoded,
as those may still be buffered in buf) */
/* For calculating bitrate stats */
long samples_decoded;
long samples_decoded_previous;
long bytes_read;
long bytes_read_previous;
FLAC__StreamMetadata *comments;
int bos; /* At beginning of stream */
int eos; /* End of stream read */
/* Buffer for decoded audio */
FLAC__int32 **buf; /* channels by buf_len array */
int buf_len;
int buf_start; /* Offset to start of audio data */
int buf_fill; /* Number of bytes of audio data in buffer */
decoder_stats_t stats;
} flac_private_t;
/* Forward declarations */
format_t flac_format;
format_t oggflac_format;
<p>/* Private functions declarations */
FLAC__StreamDecoderReadStatus easyflac_read_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
FLAC__StreamDecoderWriteStatus easyflac_write_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
void easyflac_metadata_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
void easyflac_error_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
void resize_buffer(flac_private_t *flac, int newchannels, int newsamples);
/*void copy_comments (vorbis_comment *v_comments, FLAC__StreamMetadata_VorbisComment *f_comments);*/
void print_flac_stream_info (decoder_t *decoder);
void print_flac_comments (FLAC__StreamMetadata_VorbisComment *comments,
decoder_callbacks_t *cb, void *callback_arg);
<p><p>int flac_can_decode (data_source_t *source)
{
char buf[4];
int len;
len = source->transport->peek(source, buf, sizeof(char), 4);
if (len >= 4 && memcmp(buf, "fLaC", 4) == 0)
return 1; /* Naked FLAC */
else
return 0;
}
<p>int oggflac_can_decode (data_source_t *source)
{
char buf[32];
int len;
len = source->transport->peek(source, buf, sizeof(char), 32);
if (len >= 32 && memcmp(buf, "OggS", 4) == 0
&& memcmp(buf+28, "fLaC", 4) == 0)
return 1; /* Ogg FLAC */
else
return 0;
}
<p>decoder_t* flac_init (data_source_t *source, ogg123_options_t *ogg123_opts,
audio_format_t *audio_fmt,
decoder_callbacks_t *callbacks, void *callback_arg)
{
decoder_t *decoder;
flac_private_t *private;
FLAC__bool ret;
<p> /* Allocate data source structures */
decoder = malloc(sizeof(decoder_t));
private = malloc(sizeof(flac_private_t));
if (decoder != NULL && private != NULL) {
decoder->source = source;
decoder->actual_fmt = decoder->request_fmt = *audio_fmt;
/* Set format below when we distinguish which we are doing */
decoder->callbacks = callbacks;
decoder->callback_arg = callback_arg;
decoder->private = private;
private->stats.total_time = 0.0;
private->stats.current_time = 0.0;
private->stats.instant_bitrate = 0;
private->stats.avg_bitrate = 0;
} else {
fprintf(stderr, _("Error: Out of memory.\n"));
exit(1);
}
private->bos = 1;
private->eos = 0;
private->comments = NULL;
private->samples_decoded = private->samples_decoded_previous = 0;
private->bytes_read = private->bytes_read_previous = 0;
private->currentsample = 0;
/* Setup empty audio buffer that will be resized on first frame
callback */
private->channels = 0;
private->buf = NULL;
private->buf_len = 0;
private->buf_fill = 0;
private->buf_start = 0;
/* Setup FLAC decoder */
if (oggflac_can_decode(source)) {
decoder->format = &oggflac_format;
private->decoder = EasyFLAC__stream_decoder_new(1);
} else {
decoder->format = &flac_format;
private->decoder = EasyFLAC__stream_decoder_new(0);
}
<p> EasyFLAC__set_client_data(private->decoder, decoder);
EasyFLAC__set_read_callback(private->decoder, &easyflac_read_callback);
EasyFLAC__set_write_callback(private->decoder, &easyflac_write_callback);
EasyFLAC__set_metadata_callback(private->decoder, &easyflac_metadata_callback);
EasyFLAC__set_error_callback(private->decoder, &easyflac_error_callback);
EasyFLAC__set_metadata_respond(private->decoder, FLAC__METADATA_TYPE_STREAMINFO);
EasyFLAC__set_metadata_respond(private->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
EasyFLAC__init(private->decoder);
/* Callback will set the total samples and sample rate */
EasyFLAC__process_until_end_of_metadata(private->decoder);
/* Callback will set the number of channels and resize the
audio buffer */
EasyFLAC__process_single(private->decoder);
/* FLAC API returns signed samples on all streams */
decoder->actual_fmt.signed_sample = 1;
decoder->actual_fmt.big_endian = ao_is_big_endian();
return decoder;
}
<p>int flac_read (decoder_t *decoder, void *ptr, int nbytes, int *eos,
audio_format_t *audio_fmt)
{
flac_private_t *priv = decoder->private;
decoder_callbacks_t *cb = decoder->callbacks;
FLAC__int8 *buf8 = (FLAC__int8 *) ptr;
FLAC__int16 *buf16 = (FLAC__int16 *) ptr;
long samples, realsamples = 0;
FLAC__bool ret;
int i,j;
/* Read comments and audio info at the start of a logical bitstream */
if (priv->bos) {
decoder->actual_fmt.rate = priv->rate;
decoder->actual_fmt.channels = priv->channels;
decoder->actual_fmt.word_size = ((priv->bits_per_sample + 7) / 8);
if (priv->comments != NULL)
print_flac_comments(&priv->comments->data.vorbis_comment, cb,
decoder->callback_arg);
print_flac_stream_info(decoder);
priv->bos = 0;
}
*audio_fmt = decoder->actual_fmt;
<p> /* Only return whole samples (no channel splitting) */
samples = nbytes / (audio_fmt->channels * audio_fmt->word_size);
while (realsamples < samples) {
if (priv->buf_fill > 0) {
int copy = priv->buf_fill < (samples - realsamples) ?
priv->buf_fill : (samples - realsamples);
/* Need sample mangling code here! */
if (audio_fmt->word_size == 1) {
for (i = 0; i < priv->channels; i++)
for (j = 0; j < copy; j++)
buf8[(j+realsamples)*2+i] = (FLAC__int8) (0xFF & priv->buf[i][j+priv->buf_start]);
} else if (audio_fmt->word_size == 2) {
for (i = 0; i < priv->channels; i++)
for (j = 0; j < copy; j++)
buf16[(j+realsamples)*2+i] = (FLAC__int16) (0xFFFF & priv->buf[i][j+priv->buf_start]);
}
priv->buf_start += copy;
priv->buf_fill -= copy;
realsamples += copy;
}
else if (!priv->eos) {
ret = EasyFLAC__process_single(priv->decoder);
if (!ret ||
EasyFLAC__get_state(priv->decoder)
== FLAC__STREAM_DECODER_END_OF_STREAM)
priv->eos = 1; /* Bail out! */
} else
break;
}
priv->currentsample += realsamples;
return realsamples * audio_fmt->channels * audio_fmt->word_size;
}
<p>int flac_seek (decoder_t *decoder, double offset, int whence)
{
return 0; /* No seeking at this time */
}
<p>#define AVG_FACTOR 0.5
decoder_stats_t *flac_statistics (decoder_t *decoder)
{
flac_private_t *priv = decoder->private;
long instant_bitrate;
/* ov_time_tell() doesn't work on non-seekable streams, so we use
ov_pcm_tell() */
priv->stats.total_time = (double) priv->totalsamples /
(double) decoder->actual_fmt.rate;
priv->stats.current_time = (double) priv->currentsample /
(double) decoder->actual_fmt.rate;
/* Need this test to prevent averaging in false zeros. */
if ((priv->bytes_read - priv->bytes_read_previous) != 0 &&
(priv->samples_decoded - priv->samples_decoded_previous) != 0) {
instant_bitrate = 8.0 * (priv->bytes_read - priv->bytes_read_previous)
* decoder->actual_fmt.rate
/ (double) (priv->samples_decoded - priv->samples_decoded_previous);
/* A little exponential averaging to smooth things out */
priv->stats.instant_bitrate = AVG_FACTOR * instant_bitrate
+ (1.0 - AVG_FACTOR) * priv->stats.instant_bitrate;
priv->bytes_read_previous = priv->bytes_read;
priv->samples_decoded_previous = priv->samples_decoded;
}
// priv->stats.instant_bitrate = 8.0 * priv->bytes_read * decoder->actual_fmt.rate / (double) priv->samples_decoded;
/* Don't know unless we seek the stream */
priv->stats.avg_bitrate = 0;
<p> return malloc_decoder_stats(&priv->stats);
}
<p>void flac_cleanup (decoder_t *decoder)
{
flac_private_t *priv = decoder->private;
int i;
for (i = 0; i < priv->channels; i++)
free(priv->buf[i]);
free(priv->buf);
EasyFLAC__finish(priv->decoder);
EasyFLAC__stream_decoder_delete(priv->decoder);
free(decoder->private);
free(decoder);
}
<p>format_t flac_format = {
"flac",
&flac_can_decode,
&flac_init,
&flac_read,
&flac_seek,
&flac_statistics,
&flac_cleanup,
};
<p>format_t oggflac_format = {
"oggflac",
&oggflac_can_decode,
&flac_init,
&flac_read,
&flac_seek,
&flac_statistics,
&flac_cleanup,
};
<p><p>FLAC__StreamDecoderReadStatus easyflac_read_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
{
decoder_t *e_decoder = client_data;
flac_private_t *priv = e_decoder->private;
int read = 0;
read = e_decoder->source->transport->read(e_decoder->source, buffer,
sizeof(FLAC__byte), *bytes);
*bytes = read;
priv->bytes_read += read;
/* Immediately return if errors occured */
if(read == 0)
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
<p>FLAC__StreamDecoderWriteStatus easyflac_write_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
decoder_t *e_decoder = client_data;
flac_private_t *priv = e_decoder->private;
int samples = frame->header.blocksize;
int channels = frame->header.channels;
int bits_per_sample = priv->bits_per_sample = frame->header.bits_per_sample;
int i, j;
resize_buffer(priv, channels, samples);
for (i = 0; i < channels; i++)
for (j = 0; j < samples; j++)
priv->buf[i][j] = buffer[i][j];
priv->buf_start = 0;
priv->buf_fill = samples;
<p> priv->samples_decoded += samples;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
<p>void easyflac_metadata_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
decoder_t *e_decoder = client_data;
flac_private_t *priv = e_decoder->private;
switch (metadata->type) {
case FLAC__METADATA_TYPE_STREAMINFO:
priv->totalsamples = metadata->data.stream_info.total_samples;
priv->rate = metadata->data.stream_info.sample_rate;
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
priv->comments = FLAC__metadata_object_clone(metadata);
break;
default:
break;
}
}
<p>void easyflac_error_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
<p>}
<p>void resize_buffer(flac_private_t *flac, int newchannels, int newsamples)
{
int i;
if (newchannels == flac->channels && newsamples == flac->buf_len) {
flac->buf_start = 0;
flac->buf_fill = 0;
return;
}
/* Not the most efficient approach, but it is easy to follow */
if(newchannels != flac->channels) {
/* Deallocate all of the sample vectors */
for (i = 0; i < flac->channels; i++)
free(flac->buf[i]);
flac->buf = realloc(flac->buf, sizeof(FLAC__int32*) * newchannels);
flac->channels = newchannels;
}
for (i = 0; i < newchannels; i++)
flac->buf[i] = malloc(sizeof(FLAC__int32) * newsamples);
flac->buf_len = newsamples;
flac->buf_start = 0;
flac->buf_fill = 0;
}
<p>void print_flac_stream_info (decoder_t *decoder)
{
flac_private_t *priv = decoder->private;
decoder_callbacks_t *cb = decoder->callbacks;
<p> if (cb == NULL || cb->printf_metadata == NULL)
return;
cb->printf_metadata(decoder->callback_arg, 2,
_("Audio is %d bits, %d channel, %ldHz"),
priv->bits_per_sample,
priv->channels,
priv->rate);
}
void print_flac_comments (FLAC__StreamMetadata_VorbisComment *f_comments,
decoder_callbacks_t *cb, void *callback_arg)
{
int i;
char *temp = NULL;
int temp_len = 0;
for (i = 0; i < f_comments->num_comments; i++) {
/* Gotta null terminate these things */
if (temp_len < f_comments->comments[i].length + 1) {
temp_len = f_comments->comments[i].length + 1;
temp = realloc(temp, sizeof(char) * temp_len);
}
strncpy(temp, f_comments->comments[i].entry,
f_comments->comments[i].length);
temp[f_comments->comments[i].length] = '\0';
print_vorbis_comment(temp, cb, callback_arg);
}
free(temp);
}
<p><p><p>1.1 vorbis-tools/ogg123/vorbis_comments.c
Index: vorbis_comments.c
===================================================================
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
* THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
* PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2001 *
* by Stan Seibert <volsung at xiph.org> AND OTHER CONTRIBUTORS *
* http://www.xiph.org/ *
* *
********************************************************************
last mod: $Id: vorbis_comments.c,v 1.1 2003/01/11 22:51:44 volsung Exp $
********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#include "format.h"
#include "utf8.h"
#include "i18n.h"
<p>/* Vorbis comment keys that need special formatting. */
struct {
char *key; /* includes the '=' for programming convenience */
char *formatstr; /* formatted output */
} vorbis_comment_keys[] = {
{"TRACKNUMBER=", N_("Track number:")},
{"REPLAYGAIN_TRACK_GAIN=", N_("ReplayGain (Track):")},
{"REPLAYGAIN_ALBUM_GAIN=", N_("ReplayGain (Album):")},
{"REPLAYGAIN_TRACK_PEAK=", N_("ReplayGain (Track) Peak:")},
{"REPLAYGAIN_ALBUM_PEAK=", N_("ReplayGain (Album) Peak:")},
{"COPYRIGHT=", N_("Copyright")},
{"=", N_("Comment:")},
{NULL, N_("Comment:")}
};
<p>char *lookup_comment_prettyprint (char *comment, int *offset)
{
int i, j;
char *s;
/* Search for special-case formatting */
for (i = 0; vorbis_comment_keys[i].key != NULL; i++) {
if ( !strncasecmp (vorbis_comment_keys[i].key, comment,
strlen(vorbis_comment_keys[i].key)) ) {
*offset = strlen(vorbis_comment_keys[i].key);
s = malloc(strlen(vorbis_comment_keys[i].formatstr) + 1);
if (s == NULL) {
fprintf(stderr, _("Error: Out of memory.\n"));
exit(1);
};
strcpy(s, vorbis_comment_keys[i].formatstr);
return s;
}
}
/* Use default formatting */
j = strcspn(comment, "=");
if (j) {
*offset = j + 1;
s = malloc(j + 2);
if (s == NULL) {
fprintf(stderr, _("Error: Out of memory.\n"));
exit(1);
};
strncpy(s, comment, j);
strcpy(s + j, ":");
/* Capitalize */
s[0] = toupper(s[0]);
for (i = 1; i < j; i++) {
s[i] = tolower(s[i]);
};
return s;
}
/* Unrecognized comment, use last format string */
*offset = 0;
s = malloc(strlen(vorbis_comment_keys[i].formatstr) + 1);
if (s == NULL) {
fprintf(stderr, _("Error: Out of memory.\n"));
exit(1);
};
strcpy(s, vorbis_comment_keys[i].formatstr);
return s;
}
void print_vorbis_comment (char *comment, decoder_callbacks_t *cb,
void *callback_arg)
{
char *comment_prettyprint;
char *decoded_value;
int offset;
if (cb == NULL || cb->printf_metadata == NULL)
return;
comment_prettyprint = lookup_comment_prettyprint(comment, &offset);
if (utf8_decode(comment + offset, &decoded_value) >= 0) {
cb->printf_metadata(callback_arg, 1, "%s %s", comment_prettyprint,
decoded_value);
free(decoded_value);
} else
cb->printf_metadata(callback_arg, 1, "%s %s", comment_prettyprint,
comment + offset);
free(comment_prettyprint);
}
<p><p>1.1 vorbis-tools/ogg123/vorbis_comments.h
Index: vorbis_comments.h
===================================================================
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
* THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
* PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2003 *
* by Stan Seibert <volsung at xiph.org> AND OTHER CONTRIBUTORS *
* http://www.xiph.org/ *
* *
********************************************************************
last mod: $Id: vorbis_comments.h,v 1.1 2003/01/11 22:51:44 volsung Exp $
********************************************************************/
<p>#ifndef __VORBIS_COMMENTS_H__
#define __VORBIS_COMMENTS_H__
#include "format.h"
<p>void print_vorbis_comment (char *comment, decoder_callbacks_t *cb,
void *callback_arg);
#endif /* __VORBIS_COMMENTS_H__ */
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list