[beast/devel: 11/28] FLAC: support compressed flac data handles stored in .bsewave / .bse files
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast/devel: 11/28] FLAC: support compressed flac data handles stored in .bsewave / .bse files
- Date: Sat, 4 May 2013 03:53:09 +0000 (UTC)
commit 682b286bdcd2712517663e90d494d672fadf58d0
Author: Stefan Westerfeld <stefan space twc de>
Date: Wed Mar 20 20:22:46 2013 +0100
FLAC: support compressed flac data handles stored in .bsewave / .bse files
bse/Makefile.am | 2 +-
bse/bsedatahandle-flac.cc | 274 ++++++++++++++++++++++++++++++++++++++++++---
bse/bseloader-bsewave.cc | 46 ++++++++-
bse/bseloader-flac.cc | 1 +
bse/bsestorage.cc | 52 +++++++--
bse/gsldatahandle.hh | 6 -
tools/bwtwave.cc | 9 ++
7 files changed, 356 insertions(+), 34 deletions(-)
---
diff --git a/bse/Makefile.am b/bse/Makefile.am
index b05260c..1014e31 100644
--- a/bse/Makefile.am
+++ b/bse/Makefile.am
@@ -55,7 +55,7 @@ bse_public_headers = $(strip \
bsenote.hh bsemidifile.hh bseblockutils.hh \
bsecxxvalue.hh bsecxxutils.hh bsecxxbase.hh bsecxxclosure.hh \
bsecxxarg.hh bsecxxmodule.hh bsecxxplugin.hh bseloader.hh \
- bseresampler.hh bseresamplerimpl.hh \
+ bseresampler.hh bseresamplerimpl.hh bsedatahandle-flac.hh \
testobject.hh \
)
# BSE C & C++ sources
diff --git a/bse/bsedatahandle-flac.cc b/bse/bsedatahandle-flac.cc
index 303ea83..f9c4949 100644
--- a/bse/bsedatahandle-flac.cc
+++ b/bse/bsedatahandle-flac.cc
@@ -1,5 +1,6 @@
// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "gsldatahandle.hh"
+#include "bsedatahandle-flac.hh"
#include "gsldatautils.hh"
#include "gslfilter.hh"
#include "bseblockutils.hh"
@@ -16,6 +17,10 @@ using std::vector;
using std::string;
using std::min;
+namespace {
+ enum FlacZOffset { NO_ZOFFSET, ADD_ZOFFSET };
+}
+
class DataHandleFlac;
struct CDataHandleFlac : public GslDataHandle
@@ -26,6 +31,80 @@ struct CDataHandleFlac : public GslDataHandle
class DataHandleFlac {
private:
+// ***************************** virtual file I/O ********************************
+ GslLong m_file_byte_offset;
+ GslLong m_file_byte_size;
+ GslRFile *m_rfile;
+
+ static FLAC__StreamDecoderReadStatus
+ file_read_callback (const FLAC__StreamDecoder *decoder,
+ FLAC__byte buffer[],
+ size_t *bytes,
+ void *client_data)
+ {
+ DataHandleFlac *dh = static_cast<DataHandleFlac *> (client_data);
+
+ const size_t bytes_to_eof = dh->m_file_byte_size - (gsl_rfile_position (dh->m_rfile) -
dh->m_file_byte_offset);
+ GslLong l = gsl_rfile_read (dh->m_rfile, MIN (*bytes, bytes_to_eof), buffer);
+ if (l < 0)
+ return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+
+ *bytes = l;
+ if (*bytes == 0)
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ else
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+ }
+
+ static FLAC__StreamDecoderSeekStatus
+ file_seek_callback (const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 absolute_byte_offset,
+ void *client_data)
+ {
+ DataHandleFlac *dh = static_cast<DataHandleFlac *> (client_data);
+
+ int64 l = dh->m_file_byte_offset + absolute_byte_offset;
+ l = CLAMP (l, dh->m_file_byte_offset, dh->m_file_byte_offset + dh->m_file_byte_size);
+ l = gsl_rfile_seek_set (dh->m_rfile, l);
+ if (l >= 0)
+ return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+ else
+ return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+ }
+
+ static FLAC__StreamDecoderTellStatus
+ file_tell_callback (const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 *absolute_byte_offset,
+ void *client_data)
+ {
+ DataHandleFlac *dh = static_cast<DataHandleFlac *> (client_data);
+
+ *absolute_byte_offset = gsl_rfile_position (dh->m_rfile) - dh->m_file_byte_offset;
+ return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+ }
+
+ static FLAC__StreamDecoderLengthStatus
+ file_length_callback (const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 *stream_length,
+ void *client_data)
+ {
+ DataHandleFlac *dh = static_cast<DataHandleFlac *> (client_data);
+
+ *stream_length = dh->m_file_byte_size;
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+ }
+
+ static FLAC__bool
+ file_eof_callback (const FLAC__StreamDecoder *decoder,
+ void *client_data)
+ {
+ DataHandleFlac *dh = static_cast<DataHandleFlac *> (client_data);
+
+ return dh->m_file_byte_size == (gsl_rfile_position (dh->m_rfile) - dh->m_file_byte_offset);
+ }
+
+// *******************************************************************************
+
static FLAC__StreamDecoderWriteStatus
flac_write_callback (const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame,
@@ -70,12 +149,21 @@ protected:
int64 m_buffer_start;
vector<float> m_buffer;
float m_osc_freq;
+ FlacZOffset m_init_add_zoffset;
+ GslLong m_init_byte_offset;
+ GslLong m_init_byte_size;
public:
DataHandleFlac (const string& file_name,
- float osc_freq) :
+ float osc_freq,
+ FlacZOffset add_zoffset,
+ GslLong byte_offset = -1,
+ GslLong byte_size = -1) :
m_init_ok (false),
- m_decoder (NULL)
+ m_decoder (NULL),
+ m_init_add_zoffset (add_zoffset),
+ m_init_byte_offset (byte_offset),
+ m_init_byte_size (byte_size)
{
memset (&m_dhandle, 0, sizeof (m_dhandle));
m_init_ok = gsl_data_handle_common_init (&m_dhandle, NULL);
@@ -99,9 +187,37 @@ public:
if (!m_decoder)
return BSE_ERROR_IO;
+ m_rfile = gsl_rfile_open (m_file_name.c_str());
+ if (!m_rfile)
+ return gsl_error_from_errno (errno, BSE_ERROR_FILE_OPEN_FAILED);
+
+ if (m_init_byte_offset >= 0 && m_init_byte_size >= 0)
+ {
+ m_file_byte_offset = m_init_byte_offset;
+ m_file_byte_size = m_init_byte_size;
+ }
+ else
+ {
+ m_file_byte_offset = 0;
+ m_file_byte_size = gsl_rfile_length (m_rfile);
+ }
+
+ if (m_init_add_zoffset == ADD_ZOFFSET)
+ {
+ m_file_byte_offset += gsl_hfile_zoffset (m_rfile->hfile) + 1;
+ }
+
+ /* seek to beginning of the virtual file */
+ file_seek_callback (m_decoder, 0, this);
+
m_error_occurred = false;
- int err = FLAC__stream_decoder_init_file (m_decoder, m_file_name.c_str(),
- flac_write_callback, NULL, flac_error_callback, this);
+ int err = FLAC__stream_decoder_init_stream (m_decoder,
+ file_read_callback,
+ file_seek_callback,
+ file_tell_callback,
+ file_length_callback,
+ file_eof_callback,
+ flac_write_callback, NULL, flac_error_callback, this);
if (err != 0)
return BSE_ERROR_IO;
@@ -167,19 +283,10 @@ public:
return 0;
}
+ static GslDataHandleFuncs dh_vtable;
static GslDataHandle*
dh_create (DataHandleFlac *cxx_dh)
{
- static GslDataHandleFuncs dh_vtable =
- {
- dh_open,
- dh_read,
- dh_close,
- NULL,
- NULL,
- dh_destroy,
- };
-
if (cxx_dh->m_init_ok)
{
cxx_dh->m_dhandle.vtable = &dh_vtable;
@@ -197,6 +304,17 @@ public:
{
return static_cast<CDataHandleFlac *> (dhandle)->cxx_dh;
}
+
+ GslLong
+ file_byte_offset()
+ {
+ return m_file_byte_offset;
+ }
+ GslLong
+ file_byte_size()
+ {
+ return m_file_byte_size;
+ }
private:
/* for the "C" API (vtable) */
static BseErrorType
@@ -224,14 +342,138 @@ private:
}
};
+GslDataHandleFuncs DataHandleFlac::dh_vtable
+{
+ dh_open,
+ dh_read,
+ dh_close,
+ NULL,
+ NULL,
+ dh_destroy,
+};
+
}
using namespace Bse;
-extern "C" GslDataHandle*
+GslDataHandle*
bse_data_handle_new_flac (const char *file_name,
gfloat osc_freq)
{
- DataHandleFlac *cxx_dh = new DataHandleFlac (file_name, osc_freq);
+ DataHandleFlac *cxx_dh = new DataHandleFlac (file_name, osc_freq, NO_ZOFFSET);
return DataHandleFlac::dh_create (cxx_dh);
}
+
+GslDataHandle*
+bse_data_handle_new_flac_zoffset (const char *file_name,
+ float osc_freq,
+ GslLong byte_offset,
+ GslLong byte_size,
+ uint *n_channels_p,
+ gfloat *mix_freq_p)
+{
+ g_return_val_if_fail (file_name != NULL, NULL);
+ g_return_val_if_fail (byte_offset >= 0, NULL);
+ g_return_val_if_fail (byte_size > 0, NULL);
+
+ DataHandleFlac *cxx_dh = new DataHandleFlac (file_name, osc_freq, ADD_ZOFFSET, byte_offset, byte_size);
+ GslDataHandle *dhandle = DataHandleFlac::dh_create (cxx_dh);
+ if (!dhandle)
+ return NULL;
+
+ /* figure out mix_freq, n_channels */
+ BseErrorType error = gsl_data_handle_open (dhandle);
+ if (!error)
+ {
+ if (n_channels_p)
+ *n_channels_p = dhandle->setup.n_channels;
+ if (mix_freq_p)
+ *mix_freq_p = dhandle->setup.mix_freq;
+
+ gsl_data_handle_close (dhandle);
+ return dhandle;
+ }
+ else
+ {
+ gsl_data_handle_unref (dhandle);
+ return NULL;
+ }
+}
+
+/* flac storage */
+
+Flac1Handle *
+Flac1Handle::create (GslDataHandle *dhandle)
+{
+ if (dhandle->vtable == &DataHandleFlac::dh_vtable &&
+ gsl_data_handle_open (dhandle) == BSE_ERROR_NONE)
+ {
+ return new Flac1Handle (dhandle);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void
+Flac1Handle::destroy_fn (gpointer data)
+{
+ delete (Flac1Handle *) data;
+}
+
+int
+Flac1Handle::read_data_fn (void *data, void *buffer, uint blength)
+{
+ Flac1Handle *flac_handle = (Flac1Handle*) data;
+
+ return flac_handle->read_data (buffer, blength);
+}
+
+Flac1Handle::Flac1Handle (GslDataHandle *dhandle) :
+ rfile (nullptr),
+ dhandle (dhandle)
+{
+ flac_handle = DataHandleFlac::dh_cast (dhandle);
+}
+
+Flac1Handle::~Flac1Handle()
+{
+ if (rfile)
+ {
+ gsl_rfile_close (rfile);
+ rfile = NULL;
+ }
+ gsl_data_handle_close (dhandle);
+ dhandle = NULL;
+}
+
+int
+Flac1Handle::read_data (void *buffer, uint blength)
+{
+ if (!rfile)
+ {
+ rfile = gsl_rfile_open (dhandle->name);
+ if (!rfile)
+ return gsl_error_from_errno (errno, BSE_ERROR_FILE_OPEN_FAILED);
+ byte_length = gsl_rfile_length (rfile);
+ gsl_rfile_seek_set (rfile, flac_handle->file_byte_offset());
+ }
+ const uint bytes_to_eof = flac_handle->file_byte_size() - (gsl_rfile_position (rfile) -
flac_handle->file_byte_offset());
+
+ int n_bytes_read;
+ do
+ n_bytes_read = gsl_rfile_read (rfile, std::min (blength, bytes_to_eof), buffer);
+ while (n_bytes_read < 0 && errno == EINTR);
+
+ if (n_bytes_read <= 0) /* bail on errors */
+ return errno ? -errno : -EIO;
+
+ return n_bytes_read;
+}
+
+void
+Flac1Handle::put_wstore (SfiWStore *wstore)
+{
+ sfi_wstore_put_binary (wstore, read_data_fn, this, destroy_fn);
+}
diff --git a/bse/bseloader-bsewave.cc b/bse/bseloader-bsewave.cc
index b8e3ee9..80a6397 100644
--- a/bse/bseloader-bsewave.cc
+++ b/bse/bseloader-bsewave.cc
@@ -3,6 +3,7 @@
#include "bsemain.hh"
#include "gsldatahandle.hh"
#include "gsldatahandle-vorbis.hh"
+#include "bsedatahandle-flac.hh"
#include "bsemath.hh"
#include <sfi/sfistore.hh>
#include <fcntl.h>
@@ -27,6 +28,7 @@ typedef enum
BSEWAVE_TOKEN_OSC_FREQ,
BSEWAVE_TOKEN_XINFO,
BSEWAVE_TOKEN_VORBIS_LINK,
+ BSEWAVE_TOKEN_FLAC_LINK,
BSEWAVE_TOKEN_FILE,
BSEWAVE_TOKEN_INDEX, /* file (auto detect loader) */
BSEWAVE_TOKEN_RAW_FILE,
@@ -61,7 +63,7 @@ typedef enum
static const char *bsewave_tokens[] = {
/* keyword tokens */
"wave", "chunk", "name", "n-channels",
- "midi-note", "osc-freq", "xinfo", "vorbis-link",
+ "midi-note", "osc-freq", "xinfo", "vorbis-link", "flac-link",
"file", "index", "raw-file", "boffset",
"n-values", "raw-link", "byte-order", "format",
"mix-freq",
@@ -102,6 +104,7 @@ typedef struct
#define RAW_FILE_MAGIC (('R' << 24) | ('a' << 16) | ('w' << 8) | 'F')
#define RAW_LINK_MAGIC (('R' << 24) | ('a' << 16) | ('w' << 8) | 'L')
#define VORBIS_LINK_MAGIC (('O' << 24) | ('/' << 16) | ('V' << 8) | '1')
+#define FLAC_LINK_MAGIC (('F' << 24) | ('L' << 16) | ('C' << 8) | '1')
/* --- functions --- */
static GTokenType
@@ -310,6 +313,21 @@ bsewave_parse_chunk_dsc (GScanner *scanner,
LOADER_FILE (chunk) = NULL;
LOADER_TYPE (chunk) = VORBIS_LINK_MAGIC;
break;
+ case BSEWAVE_TOKEN_FLAC_LINK:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, '(');
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER);
+ if (strcmp (scanner->value.v_identifier, "binary-appendix") != 0)
+ return G_TOKEN_IDENTIFIER;
+ parse_or_return (scanner, G_TOKEN_INT);
+ LOADER_BOFFSET (chunk) = scanner->value.v_int64; /* byte offset */
+ parse_or_return (scanner, G_TOKEN_INT);
+ LOADER_LENGTH (chunk) = scanner->value.v_int64; /* byte length */
+ parse_or_return (scanner, ')');
+ g_free (LOADER_FILE (chunk));
+ LOADER_FILE (chunk) = NULL;
+ LOADER_TYPE (chunk) = FLAC_LINK_MAGIC;
+ break;
case BSEWAVE_TOKEN_FILE:
parse_or_return (scanner, '=');
parse_or_return (scanner, G_TOKEN_STRING);
@@ -788,6 +806,32 @@ bsewave_create_chunk_handle (void *data,
else
*error_p = BSE_ERROR_WAVE_NOT_FOUND;
break;
+ case FLAC_LINK_MAGIC:
+ if (LOADER_LENGTH (chunk)) /* inlined binary data */
+ {
+ *error_p = BSE_ERROR_IO;
+ uint vnch = 0;
+ dhandle = bse_data_handle_new_flac_zoffset (fi->wfi.file_name,
+ chunk->osc_freq,
+ LOADER_BOFFSET (chunk), /* byte offset */
+ LOADER_LENGTH (chunk), /* byte length */
+ &vnch, NULL);
+ if (dhandle && vnch != dsc->wdsc.n_channels)
+ {
+ *error_p = BSE_ERROR_WRONG_N_CHANNELS;
+ gsl_data_handle_unref (dhandle);
+ dhandle = NULL;
+ }
+ if (dhandle && chunk->xinfos)
+ {
+ GslDataHandle *tmp_handle = dhandle;
+ dhandle = gsl_data_handle_new_add_xinfos (dhandle, chunk->xinfos);
+ gsl_data_handle_unref (tmp_handle);
+ }
+ }
+ else
+ *error_p = BSE_ERROR_WAVE_NOT_FOUND;
+ break;
default: /* no file_name and no loader specified */
*error_p = BSE_ERROR_FORMAT_UNKNOWN;
break;
diff --git a/bse/bseloader-flac.cc b/bse/bseloader-flac.cc
index 6d38fd6..dff0fba 100644
--- a/bse/bseloader-flac.cc
+++ b/bse/bseloader-flac.cc
@@ -1,5 +1,6 @@
// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bseloader.hh"
+#include "bsedatahandle-flac.hh"
#include <stdio.h>
#include <errno.h>
#include <string.h>
diff --git a/bse/bsestorage.cc b/bse/bsestorage.cc
index 6d8b5f2..4db8024 100644
--- a/bse/bsestorage.cc
+++ b/bse/bsestorage.cc
@@ -3,6 +3,7 @@
#include "bseitem.hh"
#include "gsldatahandle.hh"
#include "gsldatahandle-vorbis.hh"
+#include "bsedatahandle-flac.hh"
#include "gsldatautils.hh"
#include "gslcommon.hh"
#include "bseproject.hh"
@@ -13,6 +14,9 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+
+using Bse::Flac1Handle;
+
/* --- macros --- */
#define parse_or_return sfi_scanner_parse_or_return
#define peek_or_return sfi_scanner_peek_or_return
@@ -65,6 +69,7 @@ static GTokenType compat_parse_data_handle (BseStorage *self,
static gpointer parent_class = NULL;
static GQuark quark_raw_data_handle = 0;
static GQuark quark_vorbis_data_handle = 0;
+static GQuark quark_flac_data_handle = 0;
static GQuark quark_dblock_data_handle = 0;
static GQuark quark_bse_storage_binary_v0 = 0;
@@ -101,6 +106,7 @@ bse_storage_class_init (BseStorageClass *klass)
quark_raw_data_handle = g_quark_from_static_string ("raw-data-handle");
quark_vorbis_data_handle = g_quark_from_static_string ("vorbis-data-handle");
+ quark_flac_data_handle = g_quark_from_static_string ("flac-data-handle");
quark_dblock_data_handle = g_quark_from_static_string ("dblock-data-handle");
quark_bse_storage_binary_v0 = g_quark_from_static_string ("BseStorageBinaryV0");
@@ -1322,6 +1328,7 @@ bse_storage_put_data_handle (BseStorage *self,
}
while (tmp_handle); /* skip comment or cache handles */
GslVorbis1Handle *vhandle = gsl_vorbis1_handle_new (test_handle, gsl_vorbis_make_serialno());
+ Flac1Handle *flac_handle = Flac1Handle::create (dhandle);
if (vhandle) /* save already compressed Ogg/Vorbis data */
{
bse_storage_break (self);
@@ -1333,6 +1340,17 @@ bse_storage_put_data_handle (BseStorage *self,
bse_storage_pop_level (self);
bse_storage_putc (self, ')');
}
+ else if (flac_handle) /* save flac compressed handle */
+ {
+ bse_storage_break (self);
+ bse_storage_printf (self, "(%s ", g_quark_to_string (quark_flac_data_handle));
+ bse_storage_putf (self, gsl_data_handle_osc_freq (dhandle));
+ bse_storage_push_level (self);
+ bse_storage_break (self);
+ flac_handle->put_wstore (self->wstore);
+ bse_storage_pop_level (self);
+ bse_storage_putc (self, ')');
+ }
else /* save raw data handle */
{
if (significant_bits < 1)
@@ -1434,11 +1452,12 @@ parse_raw_data_handle (BseStorage *self,
return G_TOKEN_NONE;
}
static GTokenType
-parse_vorbis_data_handle (BseStorage *self,
- GslDataHandle **data_handle_p,
- guint *n_channels_p,
- gfloat *mix_freq_p,
- gfloat *osc_freq_p)
+parse_vorbis_or_flac_data_handle (BseStorage *self,
+ GQuark quark,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
{
GScanner *scanner = bse_storage_get_scanner (self);
GTokenType token;
@@ -1467,8 +1486,20 @@ parse_vorbis_data_handle (BseStorage *self,
else
{
gfloat mix_freq;
- *data_handle_p = gsl_data_handle_new_ogg_vorbis_zoffset (self->rstore->fname, osc_freq,
- offset, length, n_channels_p, &mix_freq);
+ if (quark == quark_vorbis_data_handle)
+ {
+ *data_handle_p = gsl_data_handle_new_ogg_vorbis_zoffset (self->rstore->fname, osc_freq,
+ offset, length, n_channels_p, &mix_freq);
+ }
+ else if (quark == quark_flac_data_handle)
+ {
+ *data_handle_p = bse_data_handle_new_flac_zoffset (self->rstore->fname, osc_freq,
+ offset, length, n_channels_p, &mix_freq);
+ }
+ else
+ {
+ return bse_storage_warn_skip (self, "unknown compressed data handle type in
parse_vorbis_or_flac_data_handle");
+ }
if (osc_freq <= 0 || mix_freq < 4000 || osc_freq >= mix_freq / 2)
return bse_storage_warn_skip (self, "invalid oscillating/mixing frequencies: %.7g/%.7g", osc_freq,
mix_freq);
if (mix_freq_p)
@@ -1484,7 +1515,8 @@ bse_storage_match_data_handle (BseStorage *self,
quark == quark_dblock_data_handle)
return TRUE;
if (quark == quark_raw_data_handle ||
- quark == quark_vorbis_data_handle)
+ quark == quark_vorbis_data_handle ||
+ quark == quark_flac_data_handle)
return TRUE;
return FALSE;
}
@@ -1513,8 +1545,8 @@ parse_data_handle_trampoline (BseStorage *self,
return parse_dblock_data_handle (self, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
if (quark == quark_raw_data_handle)
return parse_raw_data_handle (self, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
- else if (quark == quark_vorbis_data_handle)
- return parse_vorbis_data_handle (self, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
+ else if (quark == quark_vorbis_data_handle || quark == quark_flac_data_handle)
+ return parse_vorbis_or_flac_data_handle (self, quark, data_handle_p, n_channels_p, mix_freq_p,
osc_freq_p);
if (BSE_STORAGE_COMPAT (self, 0, 5, 1) && quark == quark_bse_storage_binary_v0)
return compat_parse_data_handle (self, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
bse_storage_error (self, "unknown data handle keyword: %s", scanner->value.v_identifier);
diff --git a/bse/gsldatahandle.hh b/bse/gsldatahandle.hh
index 6d064a2..521f8b7 100644
--- a/bse/gsldatahandle.hh
+++ b/bse/gsldatahandle.hh
@@ -115,12 +115,6 @@ GslDataHandle* bse_data_handle_new_fir_lowpass (GslDataHandle *src_handle,
gdouble bse_data_handle_fir_response_db (GslDataHandle *fir_handle, // implemented in
bsedatahandle-fir.cc
gdouble freq);
-/* --- flac datahandle --- */
-GslDataHandle* bse_data_handle_new_flac (const gchar* file_name,
- gfloat osc_freq);
-
-
-
/* --- xinfo handling --- */
GslDataHandle* gsl_data_handle_new_add_xinfos (GslDataHandle *src_handle,
gchar **xinfos);
diff --git a/tools/bwtwave.cc b/tools/bwtwave.cc
index 49570ff..c3b80be 100644
--- a/tools/bwtwave.cc
+++ b/tools/bwtwave.cc
@@ -3,6 +3,7 @@
#include <bse/bsemath.hh>
#include <bse/gsldatautils.hh>
#include <bse/gsldatahandle-vorbis.hh>
+#include <bse/bsedatahandle-flac.hh>
#include <bse/bseloader.hh>
#include <bse/bsecxxutils.hh>
#include <sys/stat.h>
@@ -14,6 +15,7 @@
#include <vector>
#include <map>
+using Bse::Flac1Handle;
namespace BseWaveTool {
@@ -340,12 +342,19 @@ Wave::store (const string file_name)
}
while (tmp_handle);
GslVorbis1Handle *vhandle = gsl_vorbis1_handle_new (dhandle, gsl_vorbis_make_serialno());
+ Flac1Handle *flac_handle = Flac1Handle::create (dhandle);
if (vhandle) /* save already compressed Ogg/Vorbis data */
{
sfi_wstore_puts (wstore, " vorbis-link = ");
gsl_vorbis1_handle_put_wstore (vhandle, wstore);
sfi_wstore_puts (wstore, "\n");
}
+ else if (flac_handle)
+ {
+ sfi_wstore_puts (wstore, " flac-link = ");
+ flac_handle->put_wstore (wstore);
+ sfi_wstore_puts (wstore, "\n");
+ }
else
{
sfi_wstore_puts (wstore, " raw-link = ");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]