[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