diff options
Diffstat (limited to 'akode/plugins/xiph_decoder')
-rw-r--r-- | akode/plugins/xiph_decoder/Makefile.am | 8 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/Makefile.in | 689 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/flac113_decoder.cpp | 377 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/flac_decoder.cpp | 587 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/flac_decoder.h | 103 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/speex_decoder.cpp | 351 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/speex_decoder.h | 74 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/vorbis_decoder.cpp | 277 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/vorbis_decoder.h | 70 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/xiph_decoder.cpp | 84 | ||||
-rw-r--r-- | akode/plugins/xiph_decoder/xiph_decoder.h | 42 |
11 files changed, 2662 insertions, 0 deletions
diff --git a/akode/plugins/xiph_decoder/Makefile.am b/akode/plugins/xiph_decoder/Makefile.am new file mode 100644 index 0000000..367760e --- /dev/null +++ b/akode/plugins/xiph_decoder/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I$(top_srcdir)/akode/lib -I$(top_builddir)/akode/lib $(USER_INCLUDES) $(all_includes) + +lib_LTLIBRARIES = libakode_xiph_decoder.la + +libakode_xiph_decoder_la_SOURCES = flac_decoder.cpp flac113_decoder.cpp speex_decoder.cpp vorbis_decoder.cpp xiph_decoder.cpp + +libakode_xiph_decoder_la_LDFLAGS = -module -avoid-version -no-undefined $(USER_LDFLAGS) +libakode_xiph_decoder_la_LIBADD = ../../lib/libakode.la $(LIBFLAC) $(LIBOGGFLAC) $(VORBIS_LIBS) $(VORBISFILE_LIBS) $(SPEEXLIBS)
\ No newline at end of file diff --git a/akode/plugins/xiph_decoder/Makefile.in b/akode/plugins/xiph_decoder/Makefile.in new file mode 100644 index 0000000..b603541 --- /dev/null +++ b/akode/plugins/xiph_decoder/Makefile.in @@ -0,0 +1,689 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# KDE tags expanded automatically by am_edit - $Revision: 483858 $ +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = akode/plugins/xiph_decoder +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/admin/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h \ + $(top_builddir)/akode/lib/akode_export.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libakode_xiph_decoder_la_DEPENDENCIES = ../../lib/libakode.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_libakode_xiph_decoder_la_OBJECTS = flac_decoder.lo \ + flac113_decoder.lo speex_decoder.lo vorbis_decoder.lo \ + xiph_decoder.lo +#>- libakode_xiph_decoder_la_OBJECTS = \ +#>- $(am_libakode_xiph_decoder_la_OBJECTS) +#>+ 6 +libakode_xiph_decoder_la_final_OBJECTS = libakode_xiph_decoder_la.all_cpp.lo +libakode_xiph_decoder_la_nofinal_OBJECTS = flac_decoder.lo \ + flac113_decoder.lo speex_decoder.lo vorbis_decoder.lo \ + xiph_decoder.lo +@KDE_USE_FINAL_FALSE@libakode_xiph_decoder_la_OBJECTS = $(libakode_xiph_decoder_la_nofinal_OBJECTS) +@KDE_USE_FINAL_TRUE@libakode_xiph_decoder_la_OBJECTS = $(libakode_xiph_decoder_la_final_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -I$(top_builddir)/akode/lib +depcomp = $(SHELL) $(top_srcdir)/admin/depcomp +am__depfiles_maybe = depfiles +#>- CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ +#>- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +#>+ 2 +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS) +#>- LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ +#>- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ +#>- $(AM_CXXFLAGS) $(CXXFLAGS) +#>+ 3 +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS) +CXXLD = $(CXX) +#>- CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ +#>- $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +#>+ 2 +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(KDE_CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libakode_xiph_decoder_la_SOURCES) +DIST_SOURCES = $(libakode_xiph_decoder_la_SOURCES) +ETAGS = etags +CTAGS = ctags +#>- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +#>+ 1 +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST) +ACLOCAL = @ACLOCAL@ +AKODE_LIBDL = @AKODE_LIBDL@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTODIRS = @AUTODIRS@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ +AVCODEC_LDFLAGS = @AVCODEC_LDFLAGS@ +AVCODEC_LIBADD = @AVCODEC_LIBADD@ +AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ +AVFORMAT_LDFLAGS = @AVFORMAT_LDFLAGS@ +AVFORMAT_LIBADD = @AVFORMAT_LIBADD@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONF_FILES = @CONF_FILES@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_PERMISSIVE_FLAG = @ENABLE_PERMISSIVE_FLAG@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +HAVE_GCC_VISIBILITY = @HAVE_GCC_VISIBILITY@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JACK_CFLAGS = @JACK_CFLAGS@ +JACK_LDFLAGS = @JACK_LDFLAGS@ +JACK_LIBADD = @JACK_LIBADD@ +KDE_CHECK_PLUGIN = @KDE_CHECK_PLUGIN@ +KDE_NO_UNDEFINED = @KDE_NO_UNDEFINED@ +KDE_PLUGIN = @KDE_PLUGIN@ +KDE_USE_CLOSURE_FALSE = @KDE_USE_CLOSURE_FALSE@ +KDE_USE_CLOSURE_TRUE = @KDE_USE_CLOSURE_TRUE@ +KDE_USE_FINAL_FALSE = @KDE_USE_FINAL_FALSE@ +KDE_USE_FINAL_TRUE = @KDE_USE_FINAL_TRUE@ +KDE_USE_NMCHECK_FALSE = @KDE_USE_NMCHECK_FALSE@ +KDE_USE_NMCHECK_TRUE = @KDE_USE_NMCHECK_TRUE@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_AS_NEEDED = @LDFLAGS_AS_NEEDED@ +LDFLAGS_NEW_DTAGS = @LDFLAGS_NEW_DTAGS@ +LIBFLAC = @LIBFLAC@ +LIBOBJS = @LIBOBJS@ +LIBOGGFLAC = @LIBOGGFLAC@ +LIBOSSAUDIO = @LIBOSSAUDIO@ +LIBPTHREAD = @LIBPTHREAD@ +LIBS = @LIBS@ +LIBSAMPLERATE = @LIBSAMPLERATE@ +LIBSEM = @LIBSEM@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MADLIBS = @MADLIBS@ +MAKEINFO = @MAKEINFO@ +NOOPT_CFLAGS = @NOOPT_CFLAGS@ +NOOPT_CXXFLAGS = @NOOPT_CXXFLAGS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POLYP_CFLAGS = @POLYP_CFLAGS@ +POLYP_LDFLAGS = @POLYP_LDFLAGS@ +POLYP_LIBADD = @POLYP_LIBADD@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPEEXLIBS = @SPEEXLIBS@ +STRIP = @STRIP@ +TOPSUBDIRS = @TOPSUBDIRS@ +USER_INCLUDES = @USER_INCLUDES@ +USER_LDFLAGS = @USER_LDFLAGS@ +USE_EXCEPTIONS = @USE_EXCEPTIONS@ +USE_RTTI = @USE_RTTI@ +VERSION = @VERSION@ +VORBISFILE_LIBS = @VORBISFILE_LIBS@ +VORBIS_LIBS = @VORBIS_LIBS@ +WOVERLOADED_VIRTUAL = @WOVERLOADED_VIRTUAL@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +akode_SUBDIR_included_FALSE = @akode_SUBDIR_included_FALSE@ +akode_SUBDIR_included_TRUE = @akode_SUBDIR_included_TRUE@ +all_includes = @all_includes@ +all_libraries = @all_libraries@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +include_alsa_sink_FALSE = @include_alsa_sink_FALSE@ +include_alsa_sink_TRUE = @include_alsa_sink_TRUE@ +include_ffmpeg_decoder_FALSE = @include_ffmpeg_decoder_FALSE@ +include_ffmpeg_decoder_TRUE = @include_ffmpeg_decoder_TRUE@ +include_jack_sink_FALSE = @include_jack_sink_FALSE@ +include_jack_sink_TRUE = @include_jack_sink_TRUE@ +include_mpeg_decoder_FALSE = @include_mpeg_decoder_FALSE@ +include_mpeg_decoder_TRUE = @include_mpeg_decoder_TRUE@ +include_oss_sink_FALSE = @include_oss_sink_FALSE@ +include_oss_sink_TRUE = @include_oss_sink_TRUE@ +include_polyp_sink_FALSE = @include_polyp_sink_FALSE@ +include_polyp_sink_TRUE = @include_polyp_sink_TRUE@ +include_src_resampler_FALSE = @include_src_resampler_FALSE@ +include_src_resampler_TRUE = @include_src_resampler_TRUE@ +include_sun_sink_FALSE = @include_sun_sink_FALSE@ +include_sun_sink_TRUE = @include_sun_sink_TRUE@ +include_xiph_decoder_FALSE = @include_xiph_decoder_FALSE@ +include_xiph_decoder_TRUE = @include_xiph_decoder_TRUE@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +unsermake_enable_pch_FALSE = @unsermake_enable_pch_FALSE@ +unsermake_enable_pch_TRUE = @unsermake_enable_pch_TRUE@ +INCLUDES = -I$(top_srcdir)/akode/lib -I$(top_builddir)/akode/lib $(USER_INCLUDES) $(all_includes) +lib_LTLIBRARIES = libakode_xiph_decoder.la +libakode_xiph_decoder_la_SOURCES = flac_decoder.cpp flac113_decoder.cpp speex_decoder.cpp vorbis_decoder.cpp xiph_decoder.cpp +#>- libakode_xiph_decoder_la_LDFLAGS = -module -avoid-version -no-undefined $(USER_LDFLAGS) +#>+ 1 +libakode_xiph_decoder_la_LDFLAGS = -module -avoid-version -no-undefined $(KDE_NO_UNDEFINED) $(USER_LDFLAGS) +libakode_xiph_decoder_la_LIBADD = ../../lib/libakode.la $(LIBFLAC) $(LIBOGGFLAC) $(VORBIS_LIBS) $(VORBISFILE_LIBS) $(SPEEXLIBS) +#>- all: all-am +#>+ 1 +all: docs-am all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) +#>- @for dep in $?; do \ +#>- case '$(am__configure_deps)' in \ +#>- *$$dep*) \ +#>- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ +#>- && exit 0; \ +#>- exit 1;; \ +#>- esac; \ +#>- done; \ +#>- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu akode/plugins/xiph_decoder/Makefile'; \ +#>- cd $(top_srcdir) && \ +#>- $(AUTOMAKE) --gnu akode/plugins/xiph_decoder/Makefile +#>+ 12 + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu akode/plugins/xiph_decoder/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu akode/plugins/xiph_decoder/Makefile + cd $(top_srcdir) && perl admin/am_edit akode/plugins/xiph_decoder/Makefile.in +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +#>- libakode_xiph_decoder.la: $(libakode_xiph_decoder_la_OBJECTS) $(libakode_xiph_decoder_la_DEPENDENCIES) +#>+ 2 +@KDE_USE_CLOSURE_TRUE@libakode_xiph_decoder.la: libakode_xiph_decoder.la.closure $(libakode_xiph_decoder_la_OBJECTS) $(libakode_xiph_decoder_la_DEPENDENCIES) +@KDE_USE_CLOSURE_FALSE@libakode_xiph_decoder.la: $(libakode_xiph_decoder_la_OBJECTS) $(libakode_xiph_decoder_la_DEPENDENCIES) + $(CXXLINK) -rpath $(libdir) $(libakode_xiph_decoder_la_LDFLAGS) $(libakode_xiph_decoder_la_OBJECTS) $(libakode_xiph_decoder_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flac113_decoder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flac_decoder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speex_decoder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vorbis_decoder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xiph_decoder.Plo@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +#>- clean: clean-am +#>+ 1 +clean: kde-rpo-clean clean-am + +#>- clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ +#>- mostlyclean-am +#>+ 2 +clean-am: clean-closures clean-bcheck clean-final clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-libLTLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am \ + uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: + +#>+ 8 +libakode_xiph_decoder.la.closure: $(libakode_xiph_decoder_la_OBJECTS) $(libakode_xiph_decoder_la_DEPENDENCIES) + @echo "int main() {return 0;}" > libakode_xiph_decoder_la_closure.cpp + @$(LTCXXCOMPILE) -c libakode_xiph_decoder_la_closure.cpp + $(CXXLINK) libakode_xiph_decoder_la_closure.lo $(libakode_xiph_decoder_la_LDFLAGS) $(libakode_xiph_decoder_la_OBJECTS) $(libakode_xiph_decoder_la_LIBADD) $(LIBS) + @rm -f libakode_xiph_decoder_la_closure.* libakode_xiph_decoder.la.closure + @echo "timestamp" > libakode_xiph_decoder.la.closure + + +#>+ 2 +KDE_DIST=Makefile.in xiph_decoder.h vorbis_decoder.h flac_decoder.h Makefile.am speex_decoder.h + +#>+ 3 +clean-closures: + -rm -f libakode_xiph_decoder.la.closure + +#>+ 2 +docs-am: + +#>+ 15 +force-reedit: + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu akode/plugins/xiph_decoder/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu akode/plugins/xiph_decoder/Makefile + cd $(top_srcdir) && perl admin/am_edit akode/plugins/xiph_decoder/Makefile.in + + +#>+ 21 +clean-bcheck: + rm -f *.bchecktest.cc *.bchecktest.cc.class a.out + +bcheck: bcheck-am + +bcheck-am: + @for i in ; do \ + if test $(srcdir)/$$i -nt $$i.bchecktest.cc; then \ + echo "int main() {return 0;}" > $$i.bchecktest.cc ; \ + echo "#include \"$$i\"" >> $$i.bchecktest.cc ; \ + echo "$$i"; \ + if ! $(CXXCOMPILE) --dump-class-hierarchy -c $$i.bchecktest.cc; then \ + rm -f $$i.bchecktest.cc; exit 1; \ + fi ; \ + echo "" >> $$i.bchecktest.cc.class; \ + perl $(top_srcdir)/admin/bcheck.pl $$i.bchecktest.cc.class || { rm -f $$i.bchecktest.cc; exit 1; }; \ + rm -f a.out; \ + fi ; \ + done + + +#>+ 11 +libakode_xiph_decoder_la.all_cpp.cpp: $(srcdir)/Makefile.in $(srcdir)/flac_decoder.cpp $(srcdir)/flac113_decoder.cpp $(srcdir)/speex_decoder.cpp $(srcdir)/vorbis_decoder.cpp $(srcdir)/xiph_decoder.cpp + @echo 'creating libakode_xiph_decoder_la.all_cpp.cpp ...'; \ + rm -f libakode_xiph_decoder_la.all_cpp.files libakode_xiph_decoder_la.all_cpp.final; \ + echo "#define KDE_USE_FINAL 1" >> libakode_xiph_decoder_la.all_cpp.final; \ + for file in flac_decoder.cpp flac113_decoder.cpp speex_decoder.cpp vorbis_decoder.cpp xiph_decoder.cpp ; do \ + echo "#include \"$$file\"" >> libakode_xiph_decoder_la.all_cpp.files; \ + test ! -f $(srcdir)/$$file || egrep '^#pragma +implementation' $(srcdir)/$$file >> libakode_xiph_decoder_la.all_cpp.final; \ + done; \ + cat libakode_xiph_decoder_la.all_cpp.final libakode_xiph_decoder_la.all_cpp.files > libakode_xiph_decoder_la.all_cpp.cpp; \ + rm -f libakode_xiph_decoder_la.all_cpp.final libakode_xiph_decoder_la.all_cpp.files + +#>+ 3 +clean-final: + -rm -f libakode_xiph_decoder_la.all_cpp.cpp + +#>+ 3 +final: + $(MAKE) libakode_xiph_decoder_la_OBJECTS="$(libakode_xiph_decoder_la_final_OBJECTS)" all-am + +#>+ 3 +final-install: + $(MAKE) libakode_xiph_decoder_la_OBJECTS="$(libakode_xiph_decoder_la_final_OBJECTS)" install-am + +#>+ 3 +no-final: + $(MAKE) libakode_xiph_decoder_la_OBJECTS="$(libakode_xiph_decoder_la_nofinal_OBJECTS)" all-am + +#>+ 3 +no-final-install: + $(MAKE) libakode_xiph_decoder_la_OBJECTS="$(libakode_xiph_decoder_la_nofinal_OBJECTS)" install-am + +#>+ 3 +kde-rpo-clean: + -rm -f *.rpo + +#>+ 3 +nmcheck: +nmcheck-am: nmcheck diff --git a/akode/plugins/xiph_decoder/flac113_decoder.cpp b/akode/plugins/xiph_decoder/flac113_decoder.cpp new file mode 100644 index 0000000..46a46e2 --- /dev/null +++ b/akode/plugins/xiph_decoder/flac113_decoder.cpp @@ -0,0 +1,377 @@ +/* aKode: FLAC-Decoder (using libFLAC 1.1.3 API) + + Copyright (C) 2004-2005 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "akodelib.h" + +#ifdef HAVE_LIBFLAC113 + +#include <string.h> +#include <iostream> + +#include <FLAC/format.h> +#include <FLAC/stream_decoder.h> + +#include "audioframe.h" +#include "decoder.h" +#include "file.h" +#include "flac_decoder.h" + + +namespace aKode { + +class FLACDecoder; + +static bool checkFLAC(File *src) { + char header[6]; + bool res = false; + src->seek(0); + if(src->read(header, 4) == 4) { + // skip id3v2 headers + if (memcmp(header, "ID3", 3) == 0) { + if (src->read(header, 6) != 6) goto end; + int size = 0; + if (header[1] & 0x10) size += 10; + size += header[5]; + size += header[4] << 7; + size += header[3] << 14; + size += header[2] << 21; + src->seek(10+size); + if (src->read(header, 4) != 4) goto end; + } + if (memcmp(header, "fLaC",4) == 0 ) res = true; + } +end: + return res; +} + +static bool checkOggFLAC(File *src) { + char header[34]; + bool res = false; + src->seek(0); + if (src->read(header, 34) == 34) + if (memcmp(header, "OggS",4) == 0 ) + // old FLAC 1.1.0 format + if (memcmp(header+28, "fLaC",4) == 0) res = true; + else + // new FLAC 1.1.1 format + if (memcmp(header+29, "FLAC",4) == 0) res = true; + return res; +} + + +bool FLACDecoderPlugin::canDecode(File* src) { + src->openRO(); + bool res = checkFLAC(src); + if (!res) res = checkOggFLAC(src); + src->close(); + return res; +} + +extern "C" { FLACDecoderPlugin flac_decoder; } +extern "C" { FLACDecoderPlugin oggflac_decoder; } + +struct FLACDecoder::private_data { + private_data() : decoder(0), valid(false), out(0), source(0), eof(false), error(false) {}; + + FLAC__StreamDecoder *decoder; + const FLAC__StreamMetadata_StreamInfo* si; + const FLAC__StreamMetadata_VorbisComment* vc; + + bool valid; + AudioFrame *out; + File *source; + AudioConfiguration config; + + uint32_t max_block_size; + uint64_t position, length; + + bool eof, error; +}; + +static FLAC__StreamDecoderReadStatus flac_read_callback( + const FLAC__StreamDecoder *, + FLAC__byte buffer[], + unsigned *bytes, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + long res = data->source->read((char*)buffer, *bytes); + if (res<=0) { + if (data->source->eof()) { + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + } + else { + *bytes = res; + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } +} + +static FLAC__StreamDecoderSeekStatus flac_seek_callback( + const FLAC__StreamDecoder *, + FLAC__uint64 absolute_byte_offset, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + if(data->source->seek(absolute_byte_offset)) + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; + else + return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; +} + +static FLAC__StreamDecoderTellStatus flac_tell_callback( + const FLAC__StreamDecoder *, + FLAC__uint64 *absolute_byte_offset, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + long res = data->source->position(); + if (res<0) + return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; + else { + *absolute_byte_offset = res; + return FLAC__STREAM_DECODER_TELL_STATUS_OK; + } +} + +static FLAC__StreamDecoderLengthStatus flac_length_callback( + const FLAC__StreamDecoder *, + FLAC__uint64 *stream_length, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + long res = data->source->length(); + if (res<0) + return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; + else { + *stream_length = res; + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + } +} + +static FLAC__bool eof_callback( + const FLAC__StreamDecoder *, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + return data->source->eof(); +} + +static FLAC__StreamDecoderWriteStatus write_callback( + const FLAC__StreamDecoder *, + const FLAC__Frame *frame, + const FLAC__int32 * const buffer[], + void* client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + if (!data->out) // Handle spurious callbacks (happens during seeks) + data->out = new AudioFrame; + + const long frameSize = frame->header.blocksize; + const char bits = frame->header.bits_per_sample; + const char channels = frame->header.channels; + + AudioFrame* const outFrame = data->out; + + outFrame->reserveSpace(channels, frameSize, bits); + outFrame->sample_rate = frame->header.sample_rate; + + if (channels == 1 || channels == 2) + outFrame->channel_config = aKode::MonoStereo; + else if (channels > 2 && channels < 8) + outFrame->channel_config = aKode::Surround; + else + outFrame->channel_config = aKode::MultiChannel; + + for(int i = 0; i<channels; i++) { + if (outFrame->data[i] == 0) break; + if (bits<=8) { + int8_t** data = (int8_t**)outFrame->data; + for(long j=0; j<frameSize; j++) + data[i][j] = buffer[i][j]; + } else + if (bits<=16) { + int16_t** data = (int16_t**)outFrame->data; + for(long j=0; j<frameSize; j++) + data[i][j] = buffer[i][j]; + } else { + int32_t** data = (int32_t**)outFrame->data; + for(long j=0; j<frameSize; j++) + data[i][j] = buffer[i][j]; + } + } + data->position+=frameSize; + data->valid = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +static void metadata_callback( + const FLAC__StreamDecoder *, + const FLAC__StreamMetadata *metadata, + void* client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + data->length = metadata->data.stream_info.total_samples; + data->config.sample_rate = metadata->data.stream_info.sample_rate; + data->config.sample_width = metadata->data.stream_info.bits_per_sample; + data->config.channels = metadata->data.stream_info.channels; + data->max_block_size = metadata->data.stream_info.max_blocksize; + + if (data->config.channels <= 2) + data->config.channel_config = aKode::MonoStereo; + else if (data->config.channels <= 7) + data->config.channel_config = aKode::Surround; + else + data->config.channel_config = aKode::MultiChannel; + + data->si = &metadata->data.stream_info; + + data->position = 0; + + } else + if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + data->vc = &metadata->data.vorbis_comment; + } +} + +static void error_callback( + const FLAC__StreamDecoder *, + FLAC__StreamDecoderErrorStatus status, + void* /* client_data */) +{ + std::cerr << "FLAC error: " << FLAC__StreamDecoderErrorStatusString[status] << "\n"; + switch (status) { + case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC: + break; + case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER: + break; + case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH: + break; + case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM: + break; + } + //data->valid = false; +} + +const AudioConfiguration* FLACDecoder::audioConfiguration() { + return &m_data->config; +} + +FLACDecoder::FLACDecoder(File* src) { + m_data = new private_data; + m_data->out = 0; + m_data->decoder = FLAC__stream_decoder_new(); + m_data->source = src; + m_data->source->openRO(); + m_data->source->fadvise(); + // ### check return value + FLAC__stream_decoder_init_stream( + m_data->decoder, + flac_read_callback, + flac_seek_callback, + flac_tell_callback, + flac_length_callback, + eof_callback, + write_callback, + metadata_callback, + error_callback, + m_data + ); + FLAC__stream_decoder_process_until_end_of_metadata(m_data->decoder); +} + +FLACDecoder::~FLACDecoder() { + FLAC__stream_decoder_finish(m_data->decoder); + FLAC__stream_decoder_delete(m_data->decoder); + m_data->source->close(); + delete m_data; +} + +bool FLACDecoder::readFrame(AudioFrame* frame) { + if (m_data->error || m_data->eof) return false; + + if (m_data->out) { // Handle spurious callbacks + frame->freeSpace(); + *frame = *m_data->out; // copy + m_data->out->data = 0; // nullify, don't free! + delete m_data->out; + m_data->out = 0; + return true; + } + m_data->valid = false; + m_data->out = frame; + bool ret = FLAC__stream_decoder_process_single(m_data->decoder); + m_data->out = 0; + if (ret && m_data->valid) { + frame->pos = position(); + return true; + } else { + FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state(m_data->decoder); + if (state == FLAC__STREAM_DECODER_END_OF_STREAM) + m_data->eof = true; + else + if (state > FLAC__STREAM_DECODER_END_OF_STREAM) + m_data->error = true; + return false; + } +} + +long FLACDecoder::length() { + float pos = ((float)m_data->length)/m_data->config.sample_rate; + return (long)(pos*1000.0); +} + +long FLACDecoder::position() { + float pos = ((float)m_data->position)/m_data->config.sample_rate; + return (long)(pos*1000.0); +} + +bool FLACDecoder::eof() { + return m_data->eof; +} + +bool FLACDecoder::error() { + return m_data->error; +} + +bool FLACDecoder::seekable() { + return m_data->source->seekable(); +} + +bool FLACDecoder::seek(long pos) { + if (m_data->error) return false; + float samplePos = (float)pos * (float)m_data->config.sample_rate / 1000.0; + m_data->position = (uint64_t)samplePos; + return FLAC__stream_decoder_seek_absolute(m_data->decoder, m_data->position); +} + +} // namespace + +#endif // HAVE_LIBFLAC113 diff --git a/akode/plugins/xiph_decoder/flac_decoder.cpp b/akode/plugins/xiph_decoder/flac_decoder.cpp new file mode 100644 index 0000000..130e2a1 --- /dev/null +++ b/akode/plugins/xiph_decoder/flac_decoder.cpp @@ -0,0 +1,587 @@ +/* aKode: FLAC-Decoder + + Copyright (C) 2004-2005 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "akodelib.h" + +#if defined(HAVE_LIBFLAC) && !defined(HAVE_LIBFLAC113) + +#include <string.h> +#include <iostream> + +#include <FLAC/format.h> +#include <FLAC/seekable_stream_decoder.h> + +#ifdef HAVE_LIBOGGFLAC + #include <OggFLAC/seekable_stream_decoder.h> +#endif + +#include "audioframe.h" +#include "decoder.h" +#include "file.h" +#include "flac_decoder.h" + + +namespace aKode { + +class FLACDecoder; + +bool FLACDecoderPlugin::canDecode(File* src) { + char header[6]; + bool res = false; + src->openRO(); + if(src->read(header, 4) == 4) { + // skip id3v2 headers + if (memcmp(header, "ID3", 3) == 0) { + if (src->read(header, 6) != 6) goto end; + int size = 0; + if (header[1] & 0x10) size += 10; + size += header[5]; + size += header[4] << 7; + size += header[3] << 14; + size += header[2] << 21; + src->seek(10+size); + if (src->read(header, 4) != 4) goto end; + } + if (memcmp(header, "fLaC",4) == 0 ) res = true; + } +end: + src->close(); + return res; +} + +extern "C" { FLACDecoderPlugin flac_decoder; } + +#ifdef HAVE_LIBOGGFLAC +bool OggFLACDecoderPlugin::canDecode(File* src) { + char header[34]; + bool res = false; + src->openRO(); + if (src->read(header, 34) == 34) + if (memcmp(header, "OggS",4) == 0 ) + // old FLAC 1.1.0 format + if (memcmp(header+28, "fLaC",4) == 0) res = true; + else + // new FLAC 1.1.1 format + if (memcmp(header+29, "FLAC",4) == 0) res = true; + src->close(); + return res; +} +extern "C" { OggFLACDecoderPlugin oggflac_decoder; } +#endif + +struct FLACDecoder::private_data { + private_data() : decoder(0), valid(false), out(0), source(0), eof(false), error(false) {}; + + FLAC__SeekableStreamDecoder *decoder; + const FLAC__StreamMetadata_StreamInfo* si; + const FLAC__StreamMetadata_VorbisComment* vc; + + bool valid; + AudioFrame *out; + File *source; + AudioConfiguration config; + + uint32_t max_block_size; + uint64_t position, length; + + bool eof, error; +}; + +#ifdef HAVE_LIBOGGFLAC +struct OggFLACDecoder::private_data { + private_data() : decoder(0), valid(false), out(0), source(0), eof(false), error(false) {}; + + OggFLAC__SeekableStreamDecoder *decoder; + const FLAC__StreamMetadata_StreamInfo* si; + const FLAC__StreamMetadata_VorbisComment* vc; + + bool valid; + AudioFrame *out; + File *source; + AudioConfiguration config; + + uint32_t max_block_size; + uint64_t position, length; + + bool eof, error; +}; +#endif + +static FLAC__SeekableStreamDecoderReadStatus flac_read_callback( + const FLAC__SeekableStreamDecoder *, + FLAC__byte buffer[], + unsigned *bytes, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + long res = data->source->read((char*)buffer, *bytes); + if (res<=0) { + return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + } + else { + *bytes = res; + return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; + } +} + +#ifdef HAVE_LIBOGGFLAC +// God, I hate people doing OO in C! +static OggFLAC__SeekableStreamDecoderReadStatus oggflac_read_callback( + const OggFLAC__SeekableStreamDecoder *, + FLAC__byte buffer[], + unsigned *bytes, + void *client_data) +{ + OggFLACDecoder::private_data *data = (OggFLACDecoder::private_data*)client_data; + + long res = data->source->read((char*)buffer, *bytes); + if (res<=0) { + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + } + else { + *bytes = res; + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; + } +} +#endif + +static FLAC__SeekableStreamDecoderSeekStatus flac_seek_callback( + const FLAC__SeekableStreamDecoder *, + FLAC__uint64 absolute_byte_offset, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + if(data->source->seek(absolute_byte_offset)) + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; + else + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; +} + +#ifdef HAVE_LIBOGGFLAC +static OggFLAC__SeekableStreamDecoderSeekStatus oggflac_seek_callback( + const OggFLAC__SeekableStreamDecoder *, + FLAC__uint64 absolute_byte_offset, + void *client_data) +{ + OggFLACDecoder::private_data *data = (OggFLACDecoder::private_data*)client_data; + + if(data->source->seek(absolute_byte_offset)) + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; + else + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; +} +#endif + +static FLAC__SeekableStreamDecoderTellStatus flac_tell_callback( + const FLAC__SeekableStreamDecoder *, + FLAC__uint64 *absolute_byte_offset, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + long res = data->source->position(); + if (res<0) + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + else { + *absolute_byte_offset = res; + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; + } +} + +#ifdef HAVE_LIBOGGFLAC +static OggFLAC__SeekableStreamDecoderTellStatus oggflac_tell_callback( + const OggFLAC__SeekableStreamDecoder *, + FLAC__uint64 *absolute_byte_offset, + void *client_data) +{ + OggFLACDecoder::private_data *data = (OggFLACDecoder::private_data*)client_data; + + long res = data->source->position(); + if (res<0) + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + else { + *absolute_byte_offset = res; + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; + } +} +#endif + +static FLAC__SeekableStreamDecoderLengthStatus flac_length_callback( + const FLAC__SeekableStreamDecoder *, + FLAC__uint64 *stream_length, + void *client_data) +{ + FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + long res = data->source->length(); + if (res<0) + return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; + else { + *stream_length = res; + return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; + } +} + +#ifdef HAVE_LIBOGGFLAC +static OggFLAC__SeekableStreamDecoderLengthStatus oggflac_length_callback( + const OggFLAC__SeekableStreamDecoder *, + FLAC__uint64 *stream_length, + void *client_data) +{ + OggFLACDecoder::private_data *data = (OggFLACDecoder::private_data*)client_data; + + long res = data->source->length(); + if (res<0) + return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; + else { + *stream_length = res; + return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; + } +} +#endif + +template<class S, class T> +static FLAC__bool eof_callback( + const S *, + void *client_data) +{ + T *data = (T*)client_data; + + return data->source->eof(); +} + +template<class S, class T> +static FLAC__StreamDecoderWriteStatus write_callback( + const S *, + const FLAC__Frame *frame, + const FLAC__int32 * const buffer[], + void* client_data) +{ + T *data = (T*)client_data; + //FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + if (!data->out) // Handle spurious callbacks (happens during seeks) + data->out = new AudioFrame; + + const long frameSize = frame->header.blocksize; + const char bits = frame->header.bits_per_sample; + const char channels = frame->header.channels; + + AudioFrame* const outFrame = data->out; + + outFrame->reserveSpace(channels, frameSize, bits); + outFrame->sample_rate = frame->header.sample_rate; + + if (channels == 1 || channels == 2) + outFrame->channel_config = aKode::MonoStereo; + else if (channels > 2 && channels < 8) + outFrame->channel_config = aKode::Surround; + else + outFrame->channel_config = aKode::MultiChannel; + + for(int i = 0; i<channels; i++) { + if (outFrame->data[i] == 0) break; + if (bits<=8) { + int8_t** data = (int8_t**)outFrame->data; + for(long j=0; j<frameSize; j++) + data[i][j] = buffer[i][j]; + } else + if (bits<=16) { + int16_t** data = (int16_t**)outFrame->data; + for(long j=0; j<frameSize; j++) + data[i][j] = buffer[i][j]; + } else { + int32_t** data = (int32_t**)outFrame->data; + for(long j=0; j<frameSize; j++) + data[i][j] = buffer[i][j]; + } + } + data->position+=frameSize; + data->valid = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +template<class S, class T> +static void metadata_callback( + const S *, + //const FLAC__SeekableStreamDecoder *decoder, + const FLAC__StreamMetadata *metadata, + void* client_data) +{ + T *data = (T*)client_data; +// FLACDecoder::private_data *data = (FLACDecoder::private_data*)client_data; + + if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + data->length = metadata->data.stream_info.total_samples; + data->config.sample_rate = metadata->data.stream_info.sample_rate; + data->config.sample_width = metadata->data.stream_info.bits_per_sample; + data->config.channels = metadata->data.stream_info.channels; + data->max_block_size = metadata->data.stream_info.max_blocksize; + + if (data->config.channels <= 2) + data->config.channel_config = aKode::MonoStereo; + else if (data->config.channels <= 7) + data->config.channel_config = aKode::Surround; + else + data->config.channel_config = aKode::MultiChannel; + + data->si = &metadata->data.stream_info; + + data->position = 0; + + } else + if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + data->vc = &metadata->data.vorbis_comment; + } +} + +template<class S, class T> +static void error_callback( + const S *, + //const FLAC__SeekableStreamDecoder *decoder, + FLAC__StreamDecoderErrorStatus status, + void* /* client_data */) +{ + //T *data = (T*)client_data; + std::cerr << "FLAC error: " << FLAC__StreamDecoderErrorStatusString[status] << "\n"; + switch (status) { + case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC: + break; + case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER: + break; + case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH: + break; + } + //data->valid = false; +} + +const AudioConfiguration* FLACDecoder::audioConfiguration() { + return &m_data->config; +} + +#ifdef HAVE_LIBOGGFLAC +const AudioConfiguration* OggFLACDecoder::audioConfiguration() { + return &m_data->config; +} +#endif + +FLACDecoder::FLACDecoder(File* src) { + m_data = new private_data; + m_data->out = 0; + m_data->decoder = FLAC__seekable_stream_decoder_new(); + m_data->source = src; + m_data->source->openRO(); + m_data->source->fadvise(); + FLAC__seekable_stream_decoder_set_client_data(m_data->decoder, m_data); + FLAC__seekable_stream_decoder_set_read_callback (m_data->decoder, flac_read_callback); + FLAC__seekable_stream_decoder_set_seek_callback (m_data->decoder, flac_seek_callback); + FLAC__seekable_stream_decoder_set_tell_callback (m_data->decoder, flac_tell_callback); + FLAC__seekable_stream_decoder_set_length_callback (m_data->decoder, flac_length_callback); + FLAC__seekable_stream_decoder_set_eof_callback (m_data->decoder, + eof_callback<FLAC__SeekableStreamDecoder, private_data>); + FLAC__seekable_stream_decoder_set_write_callback (m_data->decoder, + write_callback<FLAC__SeekableStreamDecoder, private_data>); + FLAC__seekable_stream_decoder_set_error_callback (m_data->decoder, + error_callback<FLAC__SeekableStreamDecoder, private_data>); + FLAC__seekable_stream_decoder_set_metadata_callback(m_data->decoder, + metadata_callback<FLAC__SeekableStreamDecoder, private_data>); + FLAC__seekable_stream_decoder_set_metadata_respond (m_data->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); + + FLAC__seekable_stream_decoder_init(m_data->decoder); + FLAC__seekable_stream_decoder_process_until_end_of_metadata(m_data->decoder); +} + +FLACDecoder::~FLACDecoder() { + FLAC__seekable_stream_decoder_finish(m_data->decoder); + FLAC__seekable_stream_decoder_delete(m_data->decoder); + m_data->source->close(); + delete m_data; +} + +#ifdef HAVE_LIBOGGFLAC +OggFLACDecoder::OggFLACDecoder(File* src) { + m_data = new private_data; + m_data->out = 0; + m_data->decoder = OggFLAC__seekable_stream_decoder_new(); + m_data->source = src; + m_data->source->openRO(); + m_data->source->fadvise(); + OggFLAC__seekable_stream_decoder_set_client_data(m_data->decoder, m_data); + OggFLAC__seekable_stream_decoder_set_read_callback (m_data->decoder, oggflac_read_callback); + OggFLAC__seekable_stream_decoder_set_seek_callback (m_data->decoder, oggflac_seek_callback); + OggFLAC__seekable_stream_decoder_set_tell_callback (m_data->decoder, oggflac_tell_callback); + OggFLAC__seekable_stream_decoder_set_length_callback (m_data->decoder, oggflac_length_callback); + OggFLAC__seekable_stream_decoder_set_eof_callback (m_data->decoder, + eof_callback<OggFLAC__SeekableStreamDecoder, private_data>); + OggFLAC__seekable_stream_decoder_set_write_callback (m_data->decoder, + write_callback<OggFLAC__SeekableStreamDecoder, private_data>); + OggFLAC__seekable_stream_decoder_set_error_callback (m_data->decoder, + error_callback<OggFLAC__SeekableStreamDecoder, private_data>); + OggFLAC__seekable_stream_decoder_set_metadata_callback(m_data->decoder, + metadata_callback<OggFLAC__SeekableStreamDecoder, private_data>); + OggFLAC__seekable_stream_decoder_set_metadata_respond (m_data->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); + + OggFLAC__seekable_stream_decoder_init(m_data->decoder); + OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(m_data->decoder); +} + +OggFLACDecoder::~OggFLACDecoder() { + OggFLAC__seekable_stream_decoder_finish(m_data->decoder); + OggFLAC__seekable_stream_decoder_delete(m_data->decoder); + m_data->source->close(); + delete m_data; +} +#endif + +bool FLACDecoder::readFrame(AudioFrame* frame) { + if (m_data->error || m_data->eof) return false; + + if (m_data->out) { // Handle spurious callbacks + frame->freeSpace(); + *frame = *m_data->out; // copy + m_data->out->data = 0; // nullify, don't free! + delete m_data->out; + m_data->out = 0; + return true; + } + m_data->valid = false; + m_data->out = frame; + bool ret = FLAC__seekable_stream_decoder_process_single(m_data->decoder); + m_data->out = 0; + if (ret && m_data->valid) { + frame->pos = position(); + return true; + } else { + FLAC__SeekableStreamDecoderState state = FLAC__seekable_stream_decoder_get_state(m_data->decoder); + switch (state) { + case FLAC__SEEKABLE_STREAM_DECODER_OK: + break; + case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: + m_data->eof = true; + break; + default: + m_data->error = true; + break; + } + return false; + } +} + +#ifdef HAVE_LIBOGGFLAC +bool OggFLACDecoder::readFrame(AudioFrame* frame) { + if (m_data->error || m_data->eof) return false; + + if (m_data->out) { // Handle spurious callbacks + frame->freeSpace(); + *frame = *m_data->out; // copy + m_data->out->data = 0; // nullify, don't free! + delete m_data->out; + m_data->out = 0; + return true; + } + m_data->valid = false; + m_data->out = frame; + bool ret = OggFLAC__seekable_stream_decoder_process_single(m_data->decoder); + m_data->out = 0; + if (ret && m_data->valid) { + frame->pos = position(); + return true; + } else { + OggFLAC__SeekableStreamDecoderState state = OggFLAC__seekable_stream_decoder_get_state(m_data->decoder); + switch (state) { + case OggFLAC__SEEKABLE_STREAM_DECODER_OK: + break; + case OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: + m_data->eof = true; + break; + default: + m_data->error = true; + break; + } + return false; + } +} +#endif + +long FLACDecoder::length() { + float pos = ((float)m_data->length)/m_data->config.sample_rate; + return (long)(pos*1000.0); +} + +long FLACDecoder::position() { + float pos = ((float)m_data->position)/m_data->config.sample_rate; + return (long)(pos*1000.0); +} + +bool FLACDecoder::eof() { + return m_data->eof; +} + +bool FLACDecoder::error() { + return m_data->error; +} + +bool FLACDecoder::seekable() { + return m_data->source->seekable(); +} + +bool FLACDecoder::seek(long pos) { + if (m_data->error) return false; + float samplePos = (float)pos * (float)m_data->config.sample_rate / 1000.0; + m_data->position = (uint64_t)samplePos; + return FLAC__seekable_stream_decoder_seek_absolute(m_data->decoder, m_data->position); +} + +#ifdef HAVE_LIBOGGFLAC +long OggFLACDecoder::length() { + float pos = ((float)m_data->length)/m_data->config.sample_rate; + return (long)(pos*1000.0); +} + +long OggFLACDecoder::position() { + float pos = ((float)m_data->position)/m_data->config.sample_rate; + return (long)(pos*1000.0); +} + +bool OggFLACDecoder::eof() { + return m_data->eof; +} + +bool OggFLACDecoder::error() { + return m_data->error; +} + +bool OggFLACDecoder::seekable() { + return m_data->source->seekable(); +} + +bool OggFLACDecoder::seek(long pos) { + if (m_data->error) return false; + float samplePos = (float)pos * (float)m_data->config.sample_rate / 1000.0; + m_data->position = (uint64_t)samplePos; + return OggFLAC__seekable_stream_decoder_seek_absolute(m_data->decoder, m_data->position); +} +#endif + +} // namespace + +#endif // HAVE_LIBFLAC diff --git a/akode/plugins/xiph_decoder/flac_decoder.h b/akode/plugins/xiph_decoder/flac_decoder.h new file mode 100644 index 0000000..68a4cd9 --- /dev/null +++ b/akode/plugins/xiph_decoder/flac_decoder.h @@ -0,0 +1,103 @@ +/* aKode: FLAC-Decoder + + Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _AKODE_FLAC_DECODER_H +#define _AKODE_FLAC_DECODER_H + +#include "akodelib.h" +#if defined(HAVE_LIBFLAC) || defined(HAVE_LIBFLAC113) + +#include "decoder.h" + +namespace aKode { + +class File; +class AudioFrame; + +class FLACDecoder : public Decoder { +public: + FLACDecoder(File* src); + virtual ~FLACDecoder(); + virtual bool readFrame(AudioFrame*); + virtual long length(); + virtual long position(); + virtual bool seek(long); + virtual bool seekable(); + virtual bool eof(); + virtual bool error(); + + virtual const AudioConfiguration* audioConfiguration(); + + struct private_data; +private: + private_data *m_data; +}; + +#ifdef HAVE_LIBOGGFLAC +class OggFLACDecoder : public Decoder { +public: + OggFLACDecoder(File* src); + virtual ~OggFLACDecoder(); + virtual bool readFrame(AudioFrame*); + virtual long length(); + virtual long position(); + virtual bool seek(long); + virtual bool seekable(); + virtual bool eof(); + virtual bool error(); + + virtual const AudioConfiguration* audioConfiguration(); + + struct private_data; +private: + private_data *m_data; +}; +#endif + +class FLACDecoderPlugin : public DecoderPlugin { +public: + virtual bool canDecode(File*); + virtual Decoder* openDecoder(File* fil) { + return new FLACDecoder(fil); + }; +}; + +extern "C" FLACDecoderPlugin flac_decoder; +#ifdef HAVE_LIBFLAC113 +extern "C" FLACDecoderPlugin oggflac_decoder; +#endif + +#ifdef HAVE_LIBOGGFLAC +class OggFLACDecoderPlugin : public DecoderPlugin { +public: + virtual bool canDecode(File*); + virtual Decoder* openDecoder(File* fil) { + return new OggFLACDecoder(fil); + }; +}; + +extern "C" OggFLACDecoderPlugin oggflac_decoder; +#endif + +} // namespace + + +#endif // HAVE_LIBFLAC +#endif diff --git a/akode/plugins/xiph_decoder/speex_decoder.cpp b/akode/plugins/xiph_decoder/speex_decoder.cpp new file mode 100644 index 0000000..4c3d816 --- /dev/null +++ b/akode/plugins/xiph_decoder/speex_decoder.cpp @@ -0,0 +1,351 @@ +/* aKode: Speex-Decoder + + Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "akodelib.h" + +#ifdef HAVE_SPEEX + +extern "C" { +#include <string.h> +#include <stdlib.h> +#include <speex.h> +#include <speex_header.h> +#include <speex_callbacks.h> +#include <speex_stereo.h> +#include <ogg/ogg.h> +} + +#ifdef SPEEX_DEBUG +#include <iostream> +using std::cerr; +#endif + +#include "file.h" +#include "audioframe.h" +#include "decoder.h" +#include "speex_decoder.h" + +namespace aKode { + +bool SpeexDecoderPlugin::canDecode(File* src) { + char header[36]; + bool res = false; + src->openRO(); + if (src->read(header, 36) == 36) + if (memcmp(header, "OggS",4) == 0 ) + if (memcmp(header+28, "Speex ",8) == 0) res = true; + src->close(); + return res; +}; + +extern "C" { SpeexDecoderPlugin speex_decoder; }; + +struct SpeexDecoder::private_data +{ + SpeexBits bits; + SpeexMode *mode; + SpeexStereoState stereo; + + ogg_sync_state sync; + ogg_stream_state stream; + ogg_page page; // current page + ogg_packet packet; // current packet + + void *dec_state; + File *src; +#ifdef HAVE_SPEEX11 + int16_t *out_buffer; +#else + float *out_buffer; +#endif + + unsigned int bitrate; + int frame_size; + int frames_per_packet; + int frame_nr; + AudioConfiguration config; + int serialno; + long position; + bool seeked; + + bool initialized; + bool error, eof; +}; + +SpeexDecoder::SpeexDecoder(File *src) { + m_data = new private_data; + m_data->src = src; + m_data->out_buffer = 0; + + ogg_sync_init(&m_data->sync); + + m_data->dec_state = 0; + SpeexStereoState initstereo = SPEEX_STEREO_STATE_INIT; + m_data->stereo = initstereo; + + m_data->initialized = m_data->eof = m_data->error = false; + m_data->frame_nr = 100000; + m_data->position = 0; + m_data->seeked = false; + + src->openRO(); + src->fadvise(); +}; + +SpeexDecoder::~SpeexDecoder() { + if (m_data->initialized) { + speex_bits_reset(&m_data->bits); + ogg_sync_clear(&m_data->sync); + ogg_stream_clear(&m_data->stream); + if (m_data->dec_state) speex_decoder_destroy(m_data->dec_state); + m_data->src->close(); + delete[] m_data->out_buffer; + } + delete m_data; +} + +bool SpeexDecoder::openFile() { + m_data->error = false; + while(ogg_sync_pageout(&m_data->sync, &m_data->page) != 1) { + char *buf = ogg_sync_buffer(&m_data->sync, 1024); + int read = m_data->src->read(buf, 1024); + if (read <= 0) { + m_data->error = true; + return false; + } + ogg_sync_wrote(&m_data->sync, read); + } + m_data->serialno = ogg_page_serialno(&m_data->page); + ogg_stream_init(&m_data->stream, m_data->serialno); + speex_bits_init(&m_data->bits); + +// ogg_stream_pagein(&m_data->stream, &m_data->page); + //ogg_stream_packetout(&m_data->stream, &m_data->packet); +// ogg_stream_packetout(&m_data->stream, &m_data->packet); + + if(!decodeHeader()) + { + m_data->error = true; + return false; + } + + m_data->initialized = true; + return true; +} + +bool SpeexDecoder::readPage() { + + while (ogg_sync_pageout(&m_data->sync, &m_data->page) != 1) { + char *buf = ogg_sync_buffer(&m_data->sync, 4096); + long read = m_data->src->read(buf, 4096); + if (read <= 0) return false; + ogg_sync_wrote(&m_data->sync, read); + } + + ogg_stream_pagein(&m_data->stream, &m_data->page); +// m_data->packets = ogg_page_packets(&m_data->page); + return true; +} + +bool SpeexDecoder::readPacket() { + bool res = true; + while (ogg_stream_packetpeek(&m_data->stream, &m_data->packet) != 1 && res) { + res = readPage(); + } + ogg_stream_packetout(&m_data->stream, &m_data->packet); + speex_bits_read_from(&m_data->bits, (char*)m_data->packet.packet, m_data->packet.bytes); + m_data->frame_nr = 0; + + return res; +} + +bool SpeexDecoder::decodeHeader() { + + SpeexHeader *header; + header = speex_packet_to_header((char*)m_data->page.body, m_data->page.body_len); + if (!header) { + // invalid file + m_data->error = true; + #ifdef SPEEX_DEBUG + std::cerr << "Invalid file\n"; + #endif + return false; + } + + SpeexMode *mode = ( SpeexMode* )speex_mode_list[ header->mode ]; + m_data->mode = mode; + m_data->config.channels = header->nb_channels; + m_data->config.channel_config = MonoStereo; + m_data->frames_per_packet = header->frames_per_packet; + + if (mode->bitstream_version != header->mode_bitstream_version) { + // incompatible bitstream + m_data->error = true; + return false; + } + + m_data->dec_state = speex_decoder_init(mode); + speex_decoder_ctl(m_data->dec_state, SPEEX_GET_FRAME_SIZE, &m_data->frame_size); + //m_data->bitrate = header->bitrate; + speex_decoder_ctl(m_data->dec_state, SPEEX_GET_BITRATE, &m_data->bitrate); + m_data->config.sample_rate = header->rate; + m_data->config.sample_width = 16; + speex_decoder_ctl(m_data->dec_state, SPEEX_SET_SAMPLING_RATE, &m_data->config.sample_rate); + //speex_decoder_ctl(m_data->dec_state, SPEEX_GET_SAMPLING_RATE, &m_data->sample_rate); + + // Use the perceptial enhancement, which gives a subjectively better result + // but is technically further from the source. + int i = 1; + speex_decoder_ctl(m_data->dec_state, SPEEX_SET_ENH, &i); + + // Handle the patched-on stereo stuff + if (m_data->config.channels != 1) { + SpeexCallback callback; + callback.callback_id = SPEEX_INBAND_STEREO; + callback.func = speex_std_stereo_request_handler; + callback.data = &m_data->stereo; + speex_decoder_ctl(m_data->dec_state, SPEEX_SET_HANDLER, &callback); + } + #ifdef HAVE_SPEEX11 + m_data->out_buffer = new int16_t[m_data->frame_size*m_data->config.channels]; + #else + m_data->out_buffer = new float[m_data->frame_size*m_data->config.channels]; + #endif + + free(header); + return true; +} + +bool SpeexDecoder::readFrame(AudioFrame* frame) +{ + if (!m_data->initialized) openFile(); + + if (m_data->eof || m_data->error) return false; + + if (m_data->frame_nr >= m_data->frames_per_packet) { + if (!readPacket()) { + m_data->eof = true; + return false; + } + } + #if defined(HAVE_SPEEX11) && !defined(BROKEN_SPEEX11) + speex_decode_int(m_data->dec_state, &m_data->bits, m_data->out_buffer); + #else + speex_decode(m_data->dec_state, &m_data->bits, m_data->out_buffer); + #endif + + int channels = m_data->config.channels; + int length = m_data->frame_size; + frame->reserveSpace(&m_data->config, length); + + if (m_data->config.channels == 2) + #if defined(HAVE_SPEEX11) && !defined(BROKEN_SPEEX11) + speex_decode_stereo_int(m_data->out_buffer, length, &m_data->stereo); + #else + speex_decode_stereo(m_data->out_buffer, length, &m_data->stereo); + #endif + + + for (int i=0; i<m_data->frame_size*m_data->config.channels; i++) { + if (m_data->out_buffer[i] > 32766) m_data->out_buffer[i] = 32767; + else + if (m_data->out_buffer[i] < -32767) m_data->out_buffer[i] = -32768; + else + m_data->out_buffer[i] = m_data->out_buffer[i]; + }; + + // Decode into frame + int16_t** data = (int16_t**)frame->data; + for(int i=0; i<length; i++) + for(int j=0; j<channels; j++) + #if defined(HAVE_SPEEX11) + data[j][i] = m_data->out_buffer[i*channels+j]; + #else + data[j][i] = (int16_t)(m_data->out_buffer[i*channels+j]+0.5); + #endif + + + m_data->position += m_data->frame_size; + frame->pos = position(); + m_data->frame_nr++; + return true; +} + +long SpeexDecoder::length() { + if (!m_data->bitrate || !m_data->initialized) return -1; + float spxlen = (8.0*m_data->src->length())/(float)m_data->bitrate; + return (long)(spxlen*1000.0); +} + +long SpeexDecoder::position() { + if (!m_data->bitrate || !m_data->initialized) return -1; + float spxpos = ((float)m_data->position)/(float)m_data->config.sample_rate; + + if (m_data->seeked) { + float tellpos = (8.0*m_data->src->position())/(float)m_data->bitrate; + // tellpos should always be somewhat ahead, if spxpos is worse use tellpos + if (tellpos < spxpos) { + spxpos = tellpos; + m_data->position = (long)(tellpos*m_data->config.sample_rate); + } + } + + return (long)(spxpos*1000.0); +} + +bool SpeexDecoder::eof() { + return m_data->eof || m_data->error; + /*return m_data->error || (m_data->src->eof() && m_data->frame_nr >= m_data->frames_per_packet); */ +} + +bool SpeexDecoder::error() { + return m_data->error; +} + +bool SpeexDecoder::seekable() { + return m_data->src->seekable(); +} + +bool SpeexDecoder::seek(long pos) { + if(!m_data->initialized) return false; + + long bpos = (long)(((float)pos*(float)m_data->bitrate)/8000.0); + if (m_data->src->seek(bpos)) { + speex_bits_reset(&m_data->bits); + ogg_sync_reset(&m_data->sync); + ogg_stream_reset(&m_data->stream); + readPage(); + readPacket(); + // We should now have read in a whole new page + bpos = (m_data->src->position()-m_data->page.body_len); + m_data->position = (long)((bpos*8.0*m_data->config.sample_rate)/(float)m_data->bitrate); + m_data->seeked = true; + return true; + } + return false; +} + +const AudioConfiguration* SpeexDecoder::audioConfiguration() { + return &m_data->config; +} + +} // namespace + +#endif // HAVE_SPEEX diff --git a/akode/plugins/xiph_decoder/speex_decoder.h b/akode/plugins/xiph_decoder/speex_decoder.h new file mode 100644 index 0000000..903f828 --- /dev/null +++ b/akode/plugins/xiph_decoder/speex_decoder.h @@ -0,0 +1,74 @@ +/* aKode: Speex-Format + + Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _AKODE_SPEEX_DECODER_H +#define _AKODE_SPEEX_DECODER_H + +#include "akodelib.h" +#ifdef HAVE_SPEEX + +#include "decoder.h" + +namespace aKode { + +class File; +class AudioFrame; + +class SpeexDecoder : public Decoder { +public: + SpeexDecoder(File* src); + virtual ~SpeexDecoder(); + bool openFile(); + + virtual bool readFrame(AudioFrame*); + virtual long length(); + virtual long position(); + virtual bool seek(long); + virtual bool seekable(); + virtual bool eof(); + virtual bool error(); + + virtual const AudioConfiguration* audioConfiguration(); + + struct private_data; +private: + bool readPage(); + bool readPacket(); + bool decodeHeader(); + + private_data *m_data; +}; + + +class SpeexDecoderPlugin : public DecoderPlugin { +public: + virtual bool canDecode(File*); + virtual Decoder* openDecoder(File* src) { + return new SpeexDecoder(src); + }; +}; + +extern "C" SpeexDecoderPlugin speex_decoder; + +} // namespace + + +#endif // HAVE_SPEEX +#endif diff --git a/akode/plugins/xiph_decoder/vorbis_decoder.cpp b/akode/plugins/xiph_decoder/vorbis_decoder.cpp new file mode 100644 index 0000000..44329d0 --- /dev/null +++ b/akode/plugins/xiph_decoder/vorbis_decoder.cpp @@ -0,0 +1,277 @@ +/* aKode: Ogg Vorbis-Decoder + + Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "akodelib.h" +#ifdef HAVE_OGG_VORBIS + +#include <vorbis/vorbisfile.h> + +#include "file.h" +#include "audioframe.h" +#include "decoder.h" +#include "vorbis_decoder.h" + +//#include <iostream> + +namespace aKode { + +static size_t _read(void *ptr, size_t size, size_t nmemb, void *datasource) { + File *src = (File*)datasource; + return src->read((char*)ptr, size*nmemb); +} + +static int _seek(void *datasource, ogg_int64_t offset, int whence) { + File *src = (File*)datasource; + if (src->seek(offset, whence)) + return 0; + else + return -1; +} + +static int _close(void *datasource) { + File *src = (File*)datasource; + src->close(); + return 0; +} + +static long _tell(void *datasource) { + File *src = (File*)datasource; + return src->position(); +} + +static ov_callbacks _callbacks = {_read, _seek, _close, _tell}; + +bool VorbisDecoderPlugin::canDecode(File* src) { + OggVorbis_File vf; + src->openRO(); + int r = ov_test_callbacks(src, &vf, 0, 0, _callbacks); + ov_clear(&vf); + src->close(); + return r==0; +} + +extern "C" { VorbisDecoderPlugin vorbis_decoder; } + + +struct VorbisDecoder::private_data +{ + private_data() : bitstream(0), eof(false), error(false), initialized(false), retries(0), big_endian(0) {}; + OggVorbis_File *vf; + vorbis_comment *vc; + vorbis_info *vi; + + File *src; + AudioConfiguration config; + + int bitstream; + bool eof, error; + char buffer[8192]; + bool initialized; + int retries; + + int big_endian; +}; + +VorbisDecoder::VorbisDecoder(File *src) { + m_data = new private_data; + m_data->vf = new OggVorbis_File; + + m_data->src = src; + m_data->src->openRO(); + m_data->src->fadvise(); + + unsigned short endian_test = 1; + m_data->big_endian = 1 - (*((char *)(&endian_test))); +} + +VorbisDecoder::~VorbisDecoder() { + if (m_data->initialized) + ov_clear(m_data->vf); + delete m_data->vf; + delete m_data; +} + +static void setAudioConfiguration(AudioConfiguration *config, vorbis_info *vi) +{ + config->channels = vi->channels; + config->sample_rate = vi->rate; + config->sample_width = 16; + + if (config->channels <= 2) { + config->channel_config = MonoStereo; + config->surround_config = 0; + } else + if (config->channels <= 6) { + config->channel_config = Surround; + SurroundConfiguration surround_config; + switch (config->channels) { + case 3: + surround_config.front_channels = 3; + break; + case 4: + surround_config.front_channels = 2; + surround_config.rear_channels = 2; + break; + case 5: + surround_config.front_channels = 3; + surround_config.rear_channels = 2; + break; + case 6: + surround_config.front_channels = 3; + surround_config.rear_channels = 2; + surround_config.LFE_channel = 1; + break; + } + config->surround_config = surround_config; + } + else { + config->channel_config = MultiChannel; + config->surround_config = 0; + } +} + +bool VorbisDecoder::openFile() { + int status; + + status = ov_open_callbacks(m_data->src, m_data->vf, 0, 0, _callbacks); + if (status != 0) goto fault; + + m_data->vi = ov_info(m_data->vf, -1); + //m_data->vc = ov_comment(m_data->vf, -1); + setAudioConfiguration(&m_data->config, m_data->vi); + + m_data->initialized = true; + m_data->error = false; + m_data->retries = 0; + return true; +fault: + m_data->initialized = false; + m_data->error = true; + return false; +} + +// translation from vorbis channel-layout to akodelib channel-layout +static int vorbis_channel[7][6] = { + {-1, -1, -1, -1, -1, -1}, + {0, -1, -1, -1, -1, -1}, + {0, 1, -1, -1, -1, -1}, + {0, 2, 1, -1, -1, -1}, + {0, 1, 2, 3, -1, -1}, + {0, 2, 1, 3, 4, -1}, + {0, 2, 1, 3, 4, 5} +}; + +bool VorbisDecoder::readFrame(AudioFrame* frame) +{ + if (!m_data->initialized) { + if (!openFile()) return false; + } + + int old_bitstream = m_data->bitstream; + long v = ov_read(m_data->vf, (char*)m_data->buffer, 8192, m_data->big_endian, 2, 1, &m_data->bitstream); + + if (v == 0 || v == OV_EOF ) { + // vorbisfile sometimes return 0 even though EOF is not yet reached + if (m_data->src->eof() || m_data->src->error() || ++m_data->retries >= 16) + m_data->eof = true; +// std::cerr << "akode-vorbis: EOF\n"; + } + else + if (v == OV_HOLE) { + if (++m_data->retries >= 16) m_data->error = true; +// std::cerr << "akode-vorbis: Hole\n"; + } + else + if (v < 0) { + m_data->error = true; +// std::cerr << "akode-vorbis: Error\n"; + } + + if (v <= 0) return false; + m_data->retries = 0; + + if (old_bitstream != m_data->bitstream) { // changing streams, update info + m_data->vi = ov_info(m_data->vf, -1); + //m_data->vc = ov_comment(m_data->vf, -1); + setAudioConfiguration(&m_data->config, m_data->vi); + } + + int channels = m_data->config.channels; + long length = v/(channels*2); + frame->reserveSpace(&m_data->config, length); + + // Demux into frame + int16_t* buffer = (int16_t*)m_data->buffer; + int16_t** data = (int16_t**)frame->data; + if (channels <= 6) { + int *trans = vorbis_channel[channels]; + for(int i=0; i<length; i++) + for(int j=0; j<channels; j++) + data [trans[j]] [i] = buffer[i*channels+j]; + } + else + for(int i=0; i<length; i++) + for(int j=0; j<channels; j++) + data[j][i] = buffer[i*channels+j]; + + frame->pos = position(); + return true; +} + +long VorbisDecoder::length() { + if (!m_data->initialized) return -1; + // -1 return total length of all bitstreams. + // Should we take them one at a time instead? + double ogglen = ov_time_total(m_data->vf,-1); + return (long)(ogglen*1000.0); +} + +long VorbisDecoder::position() { + if (!m_data->initialized) return -1; + double oggpos = ov_time_tell(m_data->vf); + return (long)(oggpos*1000.0); +} + +bool VorbisDecoder::eof() { + return m_data->eof; +} + +bool VorbisDecoder::error() { + return m_data->error; +} + +bool VorbisDecoder::seekable() { + return m_data->src->seekable(); +} + +bool VorbisDecoder::seek(long pos) { + if (!m_data->initialized) return false; + int r = ov_time_seek(m_data->vf, pos/1000.0); + return r == 0; +} + +const AudioConfiguration* VorbisDecoder::audioConfiguration() { + if (!m_data->initialized) return 0; + return &m_data->config; +} + +} // namespace + +#endif //OGG_VORBIS diff --git a/akode/plugins/xiph_decoder/vorbis_decoder.h b/akode/plugins/xiph_decoder/vorbis_decoder.h new file mode 100644 index 0000000..5dd6790 --- /dev/null +++ b/akode/plugins/xiph_decoder/vorbis_decoder.h @@ -0,0 +1,70 @@ +/* aKode: Ogg Vorbis-Format + + Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _AKODE_VORBISFORMAT_H +#define _AKODE_VORBISFORMAT_H + +#include "akodelib.h" +#ifdef HAVE_OGG_VORBIS + +#include "decoder.h" + +namespace aKode { + +class File; +class AudioFrame; + +class VorbisDecoder : public Decoder { +public: + VorbisDecoder(File* src); + virtual ~VorbisDecoder(); + + virtual bool openFile(); + + virtual bool readFrame(AudioFrame*); + virtual long length(); + virtual long position(); + virtual bool seek(long); + virtual bool seekable(); + virtual bool eof(); + virtual bool error(); + + virtual const AudioConfiguration* audioConfiguration(); + + struct private_data; +private: + private_data *m_data; +}; + + +class VorbisDecoderPlugin : public DecoderPlugin { +public: + virtual bool canDecode(File*); + virtual VorbisDecoder* openDecoder(File* src) { + return new VorbisDecoder(src); + }; +}; + +extern "C" VorbisDecoderPlugin vorbis_decoder; + +} // namespace + +#endif // HAVE_VORBIS +#endif diff --git a/akode/plugins/xiph_decoder/xiph_decoder.cpp b/akode/plugins/xiph_decoder/xiph_decoder.cpp new file mode 100644 index 0000000..841656d --- /dev/null +++ b/akode/plugins/xiph_decoder/xiph_decoder.cpp @@ -0,0 +1,84 @@ +/* aKode: Xiph-Format + + Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the src COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "akodelib.h" + +#include "file.h" +#include "audioframe.h" +#include "decoder.h" + +#include "xiph_decoder.h" +#include "flac_decoder.h" +#include "vorbis_decoder.h" +#include "speex_decoder.h" + +namespace aKode { + +bool XiphDecoderPlugin::canDecode(File* src) { +#if defined(HAVE_LIBFLAC) || defined(HAVE_LIBFLAC113) + if (flac_decoder.canDecode(src)) + return true; + else +#endif +#ifdef HAVE_LIBOGGFLAC + if (oggflac_decoder.canDecode(src)) + return true; + else +#endif +#ifdef HAVE_OGG_VORBIS + if (vorbis_decoder.canDecode(src)) + return true; + else +#endif +#ifdef HAVE_SPEEX + if (speex_decoder.canDecode(src)) + return true; + else +#endif + return false; +} + +Decoder* XiphDecoderPlugin::openDecoder(File* src) { +#if defined(HAVE_LIBFLAC) || defined(HAVE_LIBFLAC113) + if (flac_decoder.canDecode(src)) + return flac_decoder.openDecoder(src); + else +#endif +#ifdef HAVE_LIBOGGFLAC + if (oggflac_decoder.canDecode(src)) + return oggflac_decoder.openDecoder(src); + else +#endif +#ifdef HAVE_OGG_VORBIS + if (vorbis_decoder.canDecode(src)) + return vorbis_decoder.openDecoder(src); + else +#endif +#ifdef HAVE_SPEEX + if (speex_decoder.canDecode(src)) + return speex_decoder.openDecoder(src); + else +#endif + return 0; +} + +extern "C" { XiphDecoderPlugin xiph_decoder; } + +} // namespace diff --git a/akode/plugins/xiph_decoder/xiph_decoder.h b/akode/plugins/xiph_decoder/xiph_decoder.h new file mode 100644 index 0000000..bef9fc8 --- /dev/null +++ b/akode/plugins/xiph_decoder/xiph_decoder.h @@ -0,0 +1,42 @@ +/* aKode: Xiph-Format (parent for various Xiph formats) + + Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _AKODE_XIPH_DECODER_H +#define _AKODE_XIPH_DECODER_H + +#include "akodelib.h" + +#include "decoder.h" + +namespace aKode { + +class File; + +class XiphDecoderPlugin : public DecoderPlugin { +public: + virtual bool canDecode(File*); + virtual Decoder* openDecoder(File* src); +}; + +extern "C" XiphDecoderPlugin xiph_decoder; + +} // namespace + +#endif |