Index: ChangeLog
===================================================================
--- ChangeLog	(revision 4588)
+++ ChangeLog	(revision 4590)
@@ -4,4 +4,5 @@
 	* Added support for CRC24 (RFC 4880)
 	* Added Base64 support.
+	* Added codecfilter for FLAC (read-only, native FLAC).
 
 v. 0.4beta1 - Mon Nov 01 2010 16:14 CET
Index: roard/Makefile
===================================================================
--- roard/Makefile	(revision 4589)
+++ roard/Makefile	(revision 4590)
@@ -4,5 +4,5 @@
 SUBSYS=midi.o light.o raw.o rdtcs.o waveform.o beep.o
 DRV=driver_esd.o driver_ao.o driver_roar.o driver_raw.o driver_oss.o driver_shout.o driver_sndio.o driver_dmx.o driver_pwmled.o driver_sysclock.o driver_wmm.o driver_dstr.o driver_alsa.o driver_rsound.o driver_portaudio.o driver_pulsesimple.o driver_jack.o
-CF_CODEC=codecfilter_cmd.o codecfilter_vorbis.o codecfilter_celt.o codecfilter_speex.o codecfilter_alaw.o codecfilter_mulaw.o codecfilter_sndfile.o codecfilter_fishsound.o
+CF_CODEC=codecfilter_cmd.o codecfilter_vorbis.o codecfilter_celt.o codecfilter_speex.o codecfilter_alaw.o codecfilter_mulaw.o codecfilter_sndfile.o codecfilter_fishsound.o codecfilter_flac.o
 CF_CONTAINER=codecfilter_wave.o codecfilter_raum.o codecfilter_au.o
 EMUL=emul_esd.o emul_simple.o emul_rsound.o emul_rplay.o
Index: roard/codecfilter.c
===================================================================
--- roard/codecfilter.c	(revision 4004)
+++ roard/codecfilter.c	(revision 4590)
@@ -189,5 +189,5 @@
 
 #ifndef ROAR_WITHOUT_CF_CMD
-#ifdef ROAR_HAVE_BIN_FLAC
+#if defined(ROAR_HAVE_BIN_FLAC) && !defined(ROAR_HAVE_LIBFLAC)
  {ROAR_CODEC_FLAC, "cmd",  "flac",
 #if BYTE_ORDER == BIG_ENDIAN
@@ -201,4 +201,9 @@
   cf_cmd_open, NULL, NULL, NULL, NULL, NULL, codecfilter_delay_fulldyn, NULL},
 #endif
+#endif
+
+#ifdef ROAR_HAVE_LIBFLAC
+ {ROAR_CODEC_FLAC, "FLAC", "flac codec", NULL, NULL, ROAR_CODECFILTER_READ, ROAR_SUBSYS_WAVEFORM,
+  cf_flac_open, cf_flac_close, NULL, NULL, cf_flac_read, NULL, codecfilter_delay_fulldyn, NULL},
 #endif
 
Index: roard/codecfilter_flac.c
===================================================================
--- roard/codecfilter_flac.c	(revision 4590)
+++ roard/codecfilter_flac.c	(revision 4590)
@@ -0,0 +1,217 @@
+//codecfilter_flac.c:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
+ *
+ *  This file is part of roard a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  RoarAudio is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "roard.h"
+#include <roaraudio/units.h>
+
+#ifdef ROAR_HAVE_LIBFLAC
+
+FLAC__StreamDecoderReadStatus cf_flac_cb_read(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) {
+ struct codecfilter_flac_inst * self = client_data;
+ ssize_t ret;
+
+ ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = ?", decoder, buffer, bytes, *bytes, client_data);
+
+ ret = stream_vio_s_read(self->ss, buffer, *bytes);
+
+ self->decoder.readret = ret;
+
+ self->decoder.readc++;
+
+ if (ret == -1) {
+  *bytes = 0;
+  ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = FLAC__STREAM_DECODER_READ_STATUS_ABORT", decoder, buffer, bytes, *bytes, client_data);
+  return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+ } else {
+  *bytes = ret;
+
+  if ( ret == 0 && self->decoder.readc == 1 ) {
+   ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM", decoder, buffer, bytes, *bytes, client_data);
+   return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+  }
+  ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = FLAC__STREAM_DECODER_READ_STATUS_CONTINUE", decoder, buffer, bytes, *bytes, client_data);
+  return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+ }
+}
+
+FLAC__StreamDecoderWriteStatus cf_flac_cb_write(const FLAC__StreamDecoder * decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) {
+ struct codecfilter_flac_inst * self = client_data;
+ struct roar_buffer * buf;
+ struct roar_interleave is;
+ size_t buflen = _32BIT * frame->header.blocksize * frame->header.channels;
+ void * bufdata;
+ int32_t * c;
+ size_t i;
+ int32_t shift = 32 - frame->header.bits_per_sample;
+
+ ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = ?", decoder, frame, buffer, client_data);
+
+ if ( roar_interl_init(&is, frame->header.channels, 32) == -1 ) {
+  ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = FLAC__STREAM_DECODER_WRITE_STATUS_ABORT", decoder, frame, buffer, client_data);
+  return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+
+ if ( roar_buffer_new_data(&buf, buflen, &bufdata) == -1 ) {
+  ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = FLAC__STREAM_DECODER_WRITE_STATUS_ABORT", decoder, frame, buffer, client_data);
+  return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+
+ roar_interl_encode_ext(&is, (void**)buffer, bufdata, buflen);
+
+ roar_interl_uninit(&is);
+
+ if ( shift ) {
+  buflen /= 4;
+  for (c = bufdata, i = 0; i < buflen; i++) {
+   c[i] <<= shift;
+  }
+ }
+
+ if ( self->decoder.written == NULL ) {
+  self->decoder.written = buf;
+ } else {
+  roar_buffer_add(self->decoder.written, buf);
+ }
+
+ ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE", decoder, frame, buffer, client_data);
+
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+void cf_flac_cb_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
+ ROAR_DBG("cf_flac_cb_metadata(decoder=%p, metadata=%p, client_data=%p) = (void)", decoder, metadata, client_data);
+}
+
+void cf_flac_cb_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
+ ROAR_DBG("cf_flac_cb_error(decoder=%p, status=%i, client_data=%p) = (void)", decoder, (int)status, client_data);
+}
+
+int cf_flac_open(CODECFILTER_USERDATA_T * inst, int codec,
+                                            struct roar_stream_server * info,
+                                            struct roar_codecfilter   * filter) {
+ struct codecfilter_flac_inst * self;
+
+ if ( ROAR_STREAM(info)->dir != ROAR_DIR_PLAY )
+  return -1;
+
+ self = roar_mm_malloc(sizeof(struct codecfilter_flac_inst));
+
+ if (self == NULL)
+  return -1;
+
+ memset(self, 0, sizeof(struct codecfilter_flac_inst));
+
+ self->ss = info;
+
+ self->decoder.decoder = FLAC__stream_decoder_new();
+
+ if ( self->decoder.decoder == NULL ) {
+  roar_mm_free(self);
+  return -1;
+ }
+
+ FLAC__stream_decoder_set_read_callback(self->decoder.decoder, cf_flac_cb_read);
+ FLAC__stream_decoder_set_write_callback(self->decoder.decoder, cf_flac_cb_write);
+ FLAC__stream_decoder_set_metadata_callback(self->decoder.decoder, cf_flac_cb_metadata);
+ FLAC__stream_decoder_set_error_callback(self->decoder.decoder, cf_flac_cb_error);
+ FLAC__stream_decoder_set_client_data(self->decoder.decoder, self);
+
+ FLAC__stream_decoder_init(self->decoder.decoder);
+
+ *inst = self;
+
+ return 0;
+}
+
+int cf_flac_close(CODECFILTER_USERDATA_T   inst) {
+ struct codecfilter_flac_inst * self = inst;
+
+ if ( self->decoder.decoder != NULL ) {
+  FLAC__stream_decoder_delete(self->decoder.decoder);
+ }
+
+ roar_mm_free(self);
+
+ return 0;
+}
+
+int cf_flac_write(CODECFILTER_USERDATA_T   inst, char * buf, int len);
+
+int cf_flac_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
+ struct codecfilter_flac_inst * self = inst;
+ struct roar_audio_info * info = &(ROAR_STREAM(self->ss)->info);
+ struct roar_buffer_stats stats;
+ size_t ret;
+ FLAC__StreamDecoderState state;
+
+ if ( self->decoder.written == NULL ) {
+  stats.bytes = 0;
+ } else {
+  roar_buffer_ring_stats(self->decoder.written, &stats);
+ }
+
+ self->decoder.readret = 1;
+ self->decoder.readc   = 0;
+
+ while ( self->decoder.readret > 0 && stats.bytes < len ) {
+  if ( !FLAC__stream_decoder_process_single(self->decoder.decoder) ) {
+   break;
+  }
+
+  state = FLAC__stream_decoder_get_state(self->decoder.decoder);
+
+  if ( state == FLAC__STREAM_DECODER_END_OF_STREAM )
+   break;
+
+  if ( self->decoder.written == NULL && state == FLAC__STREAM_DECODER_READ_FRAME ) {
+   return -1;
+  }
+
+  roar_buffer_ring_stats(self->decoder.written, &stats);
+ }
+
+ if ( stats.bytes ) {
+  ret = len;
+
+  if ( roar_buffer_shift_out(&(self->decoder.written), buf, &ret) == -1 ) {
+   return -1;
+  }
+
+  info->codec    = ROAR_CODEC_DEFAULT;
+  info->bits     = 32;
+  info->channels = FLAC__stream_decoder_get_channels(self->decoder.decoder);
+  info->rate     = FLAC__stream_decoder_get_sample_rate(self->decoder.decoder);
+
+  return ret;
+ } else {
+  return self->decoder.readret == -1 ? -1 : 0;
+ }
+}
+
+int cf_flac_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data);
+
+#endif
+
+//ll
Index: roard/include/codecfilter.h
===================================================================
--- roard/include/codecfilter.h	(revision 4004)
+++ roard/include/codecfilter.h	(revision 4590)
@@ -110,4 +110,8 @@
 #endif
 
+#ifdef ROAR_HAVE_LIBFLAC
+#include "codecfilter_flac.h"
+#endif
+
 #include "container_framework.h"
 
Index: roard/include/codecfilter_flac.h
===================================================================
--- roard/include/codecfilter_flac.h	(revision 4590)
+++ roard/include/codecfilter_flac.h	(revision 4590)
@@ -0,0 +1,65 @@
+//codecfilter_flac.h:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
+ *
+ *  This file is part of roard a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  RoarAudio is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _CODECFILTER_FLAC_H_
+#define _CODECFILTER_FLAC_H_
+
+#include <roaraudio.h>
+
+#if defined(ROAR_HAVE_LIBFLAC)
+
+#include <FLAC/all.h>
+
+struct codecfilter_flac_inst {
+ struct roar_stream_server * ss;
+ struct {
+  FLAC__StreamDecoder * decoder;
+  struct roar_buffer * written;
+  ssize_t readret;
+  size_t readc;
+ } decoder;
+};
+
+FLAC__StreamDecoderReadStatus cf_flac_cb_read(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+FLAC__StreamDecoderWriteStatus cf_flac_cb_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+void cf_flac_cb_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+void cf_flac_cb_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+
+int cf_flac_open(CODECFILTER_USERDATA_T * inst, int codec,
+                                            struct roar_stream_server * info,
+                                            struct roar_codecfilter   * filter);
+
+int cf_flac_close(CODECFILTER_USERDATA_T   inst);
+
+int cf_flac_write(CODECFILTER_USERDATA_T   inst, char * buf, int len);
+int cf_flac_read(CODECFILTER_USERDATA_T   inst, char * buf, int len);
+
+int cf_flac_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data);
+
+#endif
+
+#endif
+
+//ll
