waveout, directx, qnx, beos, win32, macosx, and the AltiVec modules.
* ALL: removed mention of AC3 in favour of A52.
* ./configure.in, ./Makefile*: modules can now be built deeper than 1
directory. As a consequence, the build is even slower (but I'm fixing
this) and make clean doesn't work anymore.
# Objects and files
###############################################################################
-#
-# All possible plugin directories, needed for make clean
-#
-PLUGINS_DIR := a52 \
- a52_system \
- aa \
- ac3_adec \
- ac3_spdif \
- access \
- alsa \
- arts \
- avi \
- beos \
- chroma \
- cinepak \
- directx \
- downmix \
- dsp \
- dummy \
- dvd \
- dvdread \
- dvdplay \
- esd \
- familiar \
- fb \
- ffmpeg \
- mp4 \
- filter \
- fx \
- ggi \
- glide \
- gtk \
- idct \
- imdct \
- kde \
- lirc \
- lpcm_adec \
- macosx \
- mad \
- memcpy \
- mga \
- motion \
- mpeg_system \
- mpeg_adec \
- mpeg_vdec \
- mp4 \
- network \
- ogg \
- qnx \
- qt \
- satellite \
- sdl \
- spudec \
- text \
- vcd \
- win32 \
- x11 \
- xosd
-
-PLUGINS_TARGETS := a52/a52 \
- aa/aa \
- a52_system/a52_system \
- ac3_adec/ac3_adec \
- ac3_spdif/ac3_spdif \
- access/file \
- access/udp \
- access/http \
- alsa/alsa \
- arts/arts \
- avi/avi \
- beos/beos \
- chroma/chroma_i420_rgb \
- chroma/chroma_i420_rgb_mmx \
- chroma/chroma_i420_yuy2 \
- chroma/chroma_i420_yuy2_mmx \
- chroma/chroma_i422_yuy2 \
- chroma/chroma_i422_yuy2_mmx \
- chroma/chroma_i420_ymga \
- chroma/chroma_i420_ymga_mmx \
- cinepak/cinepak \
- directx/directx \
- downmix/downmix \
- downmix/downmixsse \
- downmix/downmix3dn \
- dsp/dsp \
- dummy/dummy \
- dummy/null \
- dvd/dvd \
- dvdread/dvdread \
- dvdplay/dvdplay \
- esd/esd \
- familiar/familiar \
- fb/fb \
- ffmpeg/ffmpeg \
- mp4/mp4 \
- filter/filter_clone \
- filter/filter_crop \
- filter/filter_deinterlace \
- filter/filter_distort \
- filter/filter_invert \
- filter/filter_transform \
- filter/filter_wall \
- filter/filter_clone \
- fx/fx_scope \
- ggi/ggi \
- glide/glide \
- gtk/gnome \
- gtk/gtk \
- idct/idct \
- idct/idctclassic \
- idct/idctmmx \
- idct/idctmmxext \
- idct/idctaltivec \
- imdct/imdct \
- imdct/imdct3dn \
- imdct/imdctsse \
- kde/kde \
- lirc/lirc \
- lpcm_adec/lpcm_adec \
- macosx/macosx \
- mad/mad \
- memcpy/memcpy \
- memcpy/memcpymmx \
- memcpy/memcpymmxext \
- memcpy/memcpy3dn \
- memcpy/memcpyaltivec \
- mga/mga \
- mga/xmga \
- motion/motion \
- motion/motionmmx \
- motion/motionmmxext \
- motion/motion3dnow \
- motion/motionaltivec \
- mpeg_system/mpeg_audio \
- mpeg_system/mpeg_es \
- mpeg_system/mpeg_ps \
- mpeg_system/mpeg_ts \
- mpeg_system/mpeg_ts_dvbpsi \
- mpeg_adec/mpeg_adec \
- mpeg_vdec/mpeg_vdec \
- mp4/mp4 \
- network/ipv4 \
- network/ipv6 \
- ogg/vorbis \
- qnx/qnx \
- qt/qt \
- satellite/satellite \
- sdl/sdl \
- spudec/spudec \
- text/logger \
- text/ncurses \
- text/rc \
- vcd/vcd \
- win32/waveout \
- win32/intfwin \
- x11/x11 \
- x11/xvideo \
- xosd/xosd
-
#
# C Objects
#
# Translate plugin names
#
ifneq (,$(PLUGINS))
-PLUGIN_OBJ := $(shell for i in $(PLUGINS) ; do echo " "$(PLUGINS_TARGETS)" " | sed -e 's@.*/\('$$i'\) .*@plugins/\1.so@' -e 's@^ .*@@' ; done)
+PLUGIN_OBJ := $(PLUGINS:%=modules/%.so)
endif
ifneq (,$(BUILTINS))
-BUILTIN_OBJ := $(shell for i in $(BUILTINS) ; do echo " "$(PLUGINS_TARGETS)" " | sed -e 's@.*/\('$$i'\) .*@plugins/\1.a@' -e 's@^ .*@@' ; done)
+BUILTIN_OBJ := $(BUILTINS:%=modules/%.a)
endif
#
plugins-clean:
for dir in $(PLUGINS_DIR) ; do \
- ( cd plugins/$${dir} \
+ ( cd modules/$${dir} \
&& $(MAKE) -f ../../Makefile.modules clean ) ; done
- rm -f plugins/*/*.o plugins/*/*.lo plugins/*/*.moc plugins/*/*.bak
+ rm -f modules/**/*.o modules/**/*.lo modules/**/*.moc modules/**/*.bak
vlc-clean:
rm -f $(C_OBJ) $(CPP_OBJ)
plugins-install:
mkdir -p $(DESTDIR)$(libdir)/vlc
ifneq (,$(PLUGINS))
- $(INSTALL) $(PLUGINS:%=plugins/%.so) $(DESTDIR)$(libdir)/vlc
+ $(INSTALL) $(PLUGINS:%=modules/%.so) $(DESTDIR)$(libdir)/vlc
endif
plugins-uninstall:
builtins-install:
mkdir -p $(DESTDIR)$(libdir)/vlc
ifneq (,$(BUILTINS))
- $(INSTALL) -m 644 $(BUILTINS:%=plugins/%.a) $(DESTDIR)$(libdir)/vlc
+ $(INSTALL) -m 644 $(BUILTINS:%=modules/%.a) $(DESTDIR)$(libdir)/vlc
endif
builtins-uninstall:
find debian -mindepth 1 -maxdepth 1 -type d | \
while read i ; do rm -Rf tmp/vlc/$$i ; done
# Copy .c .h .in .cpp .m and .glade files
- find include src plugins -type f -name '*.[bcdhigmrst]*' | while read i ; \
+ find include src modules -type f -name '*.[bcdhigmrst]*' | while read i ; \
do cp $$i tmp/vlc/$$i ; done
# Grmbl... special case...
for i in API BUGS DESIGN TODO ; \
- do cp plugins/mad/$$i tmp/vlc/plugins/mad ; done
+ do cp modules/mad/$$i tmp/vlc/modules/mad ; done
# Copy plugin Makefiles
- find plugins -type f -name Makefile | while read i ; \
+ find modules -type f -name Makefile | while read i ; \
do cp $$i tmp/vlc/$$i ; done
# Copy extra programs and documentation
cp -a extras/* tmp/vlc/extras
for file in AUTHORS COPYING ChangeLog README FAQ TODO ; \
do cp $$file tmp/$${file}.txt ; \
unix2dos tmp/$${file}.txt ; done
- mkdir tmp/plugins
- cp $(PLUGINS:%=plugins/%.so) tmp/plugins/
+ mkdir tmp/modules
+ cp $(PLUGINS:%=modules/%.so) tmp/modules/
# don't include these two
- #rm -f tmp/plugins/gtk.so tmp/plugins/sdl.so
+ #rm -f tmp/modules/gtk.so tmp/modules/sdl.so
ifneq (,$(PLUGINS))
- for i in $(PLUGINS) ; do if test $$i != intfwin ; then $(STRIP) tmp/plugins/$$i.so ; fi ; done
+ for i in $(PLUGINS) ; do if test $$i != intfwin ; then $(STRIP) tmp/modules/$$i.so ; fi ; done
endif
mkdir tmp/share
for file in default8x16.psf default8x9.psf ; \
cp AUTHORS COPYING ChangeLog README FAQ TODO tmp/vlc/
for file in default8x16.psf default8x9.psf ; \
do cp share/$$file tmp/vlc/share/ ; done
- mkdir tmp/vlc/plugins
- cp $(PLUGINS:%=plugins/%.so) tmp/vlc/plugins/
- strip $(PLUGINS:%=tmp/vlc/plugins/%.so)
+ mkdir tmp/vlc/modules
+ cp $(PLUGINS:%=modules/%.so) tmp/vlc/modules/
+ strip $(PLUGINS:%=tmp/vlc/modules/%.so)
# Create package
mv tmp/vlc tmp/vlc-${VERSION}
(cd tmp ; find vlc-${VERSION} | \
cd extras/MacOSX ; pbxbuild | grep -v '^ ' | grep -v '^\t' | grep -v "^$$"
cp -r extras/MacOSX/build/vlc.bundle ./vlc.app
$(INSTALL) -d vlc.app/Contents/MacOS/share
- $(INSTALL) -d vlc.app/Contents/MacOS/plugins
+ $(INSTALL) -d vlc.app/Contents/MacOS/modules
$(INSTALL) vlc vlc.app/Contents/MacOS/
ifneq (,$(PLUGINS))
- $(INSTALL) $(PLUGINS:%=plugins/%.so) vlc.app/Contents/MacOS/plugins
+ $(INSTALL) $(PLUGINS:%=modules/%.so) vlc.app/Contents/MacOS/modules
endif
$(INSTALL) -m 644 share/*.psf vlc.app/Contents/MacOS/share
endif
@rm -f $@ && cp $@.in $@
ifneq (,$(BUILTINS))
@for i in $(BUILTINS) ; do \
- echo "int vlc_entry__"$$i"( module_t* );" >>$@; \
+ echo "int vlc_entry__"`basename $$i`"( module_t* );" >>$@; \
done
@echo "" >> $@ ;
endif
@echo " { \\" >> $@ ;
ifneq (,$(BUILTINS))
@for i in $(BUILTINS) ; do \
- echo " ALLOCATE_BUILTIN("$$i"); \\" >> $@ ; \
+ echo " ALLOCATE_BUILTIN("`basename $$i`"); \\" >> $@ ; \
done
endif
@echo " } while( 0 );" >> $@ ;
#lib/libvlc.so: Makefile.opts Makefile.dep Makefile $(LIBVLC_OBJ)
# $(CC) -shared $(LIBVLC_OBJ) $(LDFLAGS) $(vlc_LDFLAGS) -o $@
-#
-# Plugins target
-#
+builtins: Makefile.modules Makefile.opts Makefile.dep Makefile $(BUILTIN_OBJ)
plugins: Makefile.modules Makefile.opts Makefile.dep Makefile $(PLUGIN_OBJ)
-$(PLUGIN_OBJ): $(H_OBJ) FORCE
- @cd $(shell echo " "$(PLUGINS_TARGETS)" " | sed -e 's@.* \([^/]*/\)'$(@:plugins/%.so=%)' .*@plugins/\1@' -e 's@^ .*@@') && $(MAKE) -f ../../Makefile.modules $(@:plugins/%=../%)
-#
-# Built-in modules target
-#
-builtins: Makefile.modules Makefile.opts Makefile.dep Makefile $(BUILTIN_OBJ)
-$(BUILTIN_OBJ): $(H_OBJ) FORCE
- @cd $(shell echo " "$(PLUGINS_TARGETS)" " | sed -e 's@.* \([^/]*/\)'$(@:plugins/%.a=%)' .*@plugins/\1@' -e 's@^ .*@@') && $(MAKE) -f ../../Makefile.modules $(@:plugins/%=../%)
+modules/%.a modules/%.so: $(H_OBJ) FORCE
+ @cd $(shell echo $@ | sed -e 's@\(.*\)/.*@\1@') && $(MAKE) -f $(shell echo $@ | sed -e 's@[^/]*/@../@g' -e 's@\(.*\)/.*@\1@')/Makefile.modules $(shell echo $@ | sed -e 's@.*/@@') PARENT=$(shell echo $@ | sed -e 's@[^/]*/@../@g' -e 's@\(.*\)/.*@\1@')
#
# Mozilla plugin target
#
# Analyze the target we are asked to build
#
-module_name := $(shell echo $(MAKECMDGOALS) | sed 's@.*/\(.*\)\..*@\1@')
+module_name := $(shell echo $(MAKECMDGOALS) | sed 's@\..*@@')
suff := $(shell echo $(MAKECMDGOALS) | sed 's@.*\.@@' | tr so/a lo/o)
#
SRC_CPP := $(filter %.cpp,$($(module_name)_SOURCES))
SRC_M := $(filter %.m,$($(module_name)_SOURCES))
+plugins_CFLAGS += -D__PLUGIN__ -I$(PARENT)/include -I$(PARENT)/extras
+builtins_CFLAGS += -D__BUILTIN__ -I$(PARENT)/include -I$(PARENT)/extras
+
ifeq (lo,$(suff))
extra_CFLAGS := $(plugins_CFLAGS) $($(module_name)_CFLAGS) \
-DMODULE_NAME=$(module_name) -DMODULE_NAME_IS_$(module_name) \
FORCE:
-$(OBJ_ALL): ../../Makefile.modules ../../Makefile.dep ../../Makefile ../../Makefile.opts Makefile
-$(OBJ_ALL): $(H_DEP:%=../../include/%)
+$(OBJ_ALL): $(PARENT)/Makefile.modules $(PARENT)/Makefile.dep $(PARENT)/Makefile $(PARENT)/Makefile.opts Makefile
+$(OBJ_ALL): $(H_DEP:%=$(PARENT)/include/%)
$(C_DEP): %.d: FORCE
- @$(MAKE) -s --no-print-directory -f ../../Makefile.dep $@ CFLAGS="$(CFLAGS) $(extra_CFLAGS)"
+ @$(MAKE) -s --no-print-directory -f $(PARENT)/Makefile.dep $@ CFLAGS="$(CFLAGS) $(extra_CFLAGS)"
$(CPP_DEP): %.dpp: FORCE
- @$(MAKE) -s --no-print-directory -f ../../Makefile.dep $@ CFLAGS="$(CFLAGS) $(extra_CFLAGS)"
+ @$(MAKE) -s --no-print-directory -f $(PARENT)/Makefile.dep $@ CFLAGS="$(CFLAGS) $(extra_CFLAGS)"
$(M_DEP): %.dm: FORCE
- @$(MAKE) -s --no-print-directory -f ../../Makefile.dep $@ CFLAGS="$(CFLAGS) $(extra_CFLAGS)"
+ @$(MAKE) -s --no-print-directory -f $(PARENT)/Makefile.dep $@ CFLAGS="$(CFLAGS) $(extra_CFLAGS)"
$(SRC_C:%.c=%.$(suff).$(module_name)): %.$(suff).$(module_name): .dep/%.d
$(SRC_C:%.c=%.$(suff).$(module_name)): %.$(suff).$(module_name): %.c
# foo_CUSTOM lets us override all target rules for foo.so and foo.a
ifeq (,$($(module_name)_CUSTOM))
-../$(module_name).so: $(EXTRA_DEP) $(OBJ_ALL)
+$(module_name).so: $(EXTRA_DEP) $(OBJ_ALL)
$(CC) $(OBJ_ALL) $(LDFLAGS) $(plugins_LDFLAGS) $($(module_name)_LDFLAGS) -o $@
-../$(module_name).a: $(EXTRA_DEP) $(OBJ_ALL)
+$(module_name).a: $(EXTRA_DEP) $(OBJ_ALL)
rm -f $@
ar rc $@ $(OBJ_ALL)
$(RANLIB) $@
a52_CFLAGS = @a52_CFLAGS@
arts_CFLAGS = @arts_CFLAGS@
-chroma_i420_yuy2_mmx_CFLAGS = @chroma_i420_yuy2_mmx_CFLAGS@
+i420_yuy2_mmx_CFLAGS = @i420_yuy2_mmx_CFLAGS@
directx_CFLAGS = @directx_CFLAGS@
dvd_CFLAGS = @dvd_CFLAGS@
dvdread_CFLAGS = @dvdread_CFLAGS@
mad_CFLAGS = @mad_CFLAGS@
memcpyaltivec_CFLAGS = @memcpyaltivec_CFLAGS@
motionaltivec_CFLAGS = @motionaltivec_CFLAGS@
-mpeg_ts_dvbpsi_CFLAGS = @mpeg_ts_dvbpsi_CFLAGS@
+ts_dvbpsi_CFLAGS = @ts_dvbpsi_CFLAGS@
qt_CFLAGS = @qt_CFLAGS@
sdl_CFLAGS = @sdl_CFLAGS@
x11_CFLAGS = @x11_CFLAGS@
alsa_LDFLAGS = @alsa_LDFLAGS@
arts_LDFLAGS = @arts_LDFLAGS@
beos_LDFLAGS = @beos_LDFLAGS@
-chroma_i420_rgb_LDFLAGS = @chroma_i420_rgb_LDFLAGS@
+i420_rgb_LDFLAGS = @i420_rgb_LDFLAGS@
directx_LDFLAGS = @directx_LDFLAGS@
dsp_LDFLAGS = @dsp_LDFLAGS@
dvd_LDFLAGS = @dvd_LDFLAGS@
dvdplay_LDFLAGS = @dvdplay_LDFLAGS@
esd_LDFLAGS = @esd_LDFLAGS@
familiar_LDFLAGS = @familiar_LDFLAGS@
-filter_distort_LDFLAGS = @filter_distort_LDFLAGS@
+distort_LDFLAGS = @distort_LDFLAGS@
ffmpeg_LDFLAGS = @ffmpeg_LDFLAGS@
mp4_LDFLAGS = @mp4_LDFLAGS@
ggi_LDFLAGS = @ggi_LDFLAGS@
mad_LDFLAGS = @mad_LDFLAGS@
memcpyaltivec_LDFLAGS = @memcpyaltivec_LDFLAGS@
motionaltivec_LDFLAGS = @motionaltivec_LDFLAGS@
-mpeg_ts_dvbpsi_LDFLAGS = @mpeg_ts_dvbpsi_LDFLAGS@
+ts_dvbpsi_LDFLAGS = @ts_dvbpsi_LDFLAGS@
ncurses_LDFLAGS = @ncurses_LDFLAGS@
qnx_LDFLAGS = @qnx_LDFLAGS@
qt_LDFLAGS = @qt_LDFLAGS@
endif
endif
-#
-# C compiler flags: plugins and builtins compilation
-#
-plugins_CFLAGS += -D__PLUGIN__ -I../../include -I../../extras
-builtins_CFLAGS += -D__BUILTIN__ -I../../include -I../../extras
-
#
# Linker flags: plugins and builtins linking
#
-builtins_LDFLAGS += $(patsubst %,$$%_LDFLAGS,$(BUILTINS))
+builtins_LDFLAGS += $(patsubst %,$$%_LDFLAGS,$(shell echo $(BUILTINS) | sed -e 's@\([^ ]*/\)*@@g'))
#
# Debugging and profiling support
if test "x${ac_cv_c_omit_frame_pointer}" != "xno"; then
CFLAGS_OPTIM_NODEBUG="${CFLAGS_OPTIM_NODEBUG} -fomit-frame-pointer"
# this plugin does not compile without -fomit-frame-pointer, damn gcc!
- chroma_i420_yuy2_mmx_CFLAGS="${chroma_i420_yuy2_mmx_CFLAGS} -fomit-frame-pointer"
+ i420_yuy2_mmx_CFLAGS="${i420_yuy2_mmx_CFLAGS} -fomit-frame-pointer"
fi
echo $ac_n "checking if \$CC accepts -bundle -undefined error -lcc_dynamic""... $ac_c" 1>&6
esac
BUILTINS="${BUILTINS}"
-PLUGINS="${PLUGINS} dummy null rc logger mpeg_es mpeg_audio mpeg_ps mpeg_ts idct idctclassic motion imdct downmix mpeg_adec ac3_adec mpeg_vdec file udp http ipv4 memcpy lpcm_adec ac3_spdif spudec filter_deinterlace filter_invert filter_wall filter_transform filter_distort filter_clone filter_crop fx_scope chroma_i420_rgb chroma_i420_yuy2 chroma_i422_yuy2 chroma_i420_ymga"
-
-MMX_MODULES="memcpymmx idctmmx motionmmx chroma_i420_rgb_mmx chroma_i420_yuy2_mmx chroma_i422_yuy2_mmx chroma_i420_ymga_mmx"
-MMXEXT_MODULES="memcpymmxext idctmmxext motionmmxext"
-THREEDNOW_MODULES="memcpy3dn imdct3dn downmix3dn"
-SSE_MODULES="imdctsse downmixsse"
-ALTIVEC_MODULES="idctaltivec motionaltivec memcpyaltivec"
+PLUGINS="${PLUGINS} misc/dummy/dummy misc/null/null"
+PLUGINS="${PLUGINS} control/rc/rc misc/logger/logger access/file access/udp access/http misc/network/ipv4 misc/memcpy/memcpy"
+PLUGINS="${PLUGINS} demux/mpeg/es demux/mpeg/audio demux/mpeg/ps demux/mpeg/ts"
+PLUGINS="${PLUGINS} codec/mpeg_video/idct/idct codec/mpeg_video/idct/idctclassic codec/mpeg_video/motion/motion codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/mpeg_audio/mpeg_audio codec/a52old/a52old codec/mpeg_video/mpeg_video codec/lpcm/lpcm codec/spdif/spdif codec/spudec/spudec"
+PLUGINS="${PLUGINS} video_filter/deinterlace/deinterlace video_filter/invert video_filter/wall video_filter/transform video_filter/distort video_filter/clone video_filter/crop"
+PLUGINS="${PLUGINS} visualization/scope/scope"
+PLUGINS="${PLUGINS} video_chroma/i420_rgb video_chroma/i420_yuy2 video_chroma/i422_yuy2 video_chroma/i420_ymga"
+
+MMX_MODULES="misc/memcpy/memcpymmx codec/mpeg_video/idct/idctmmx codec/mpeg_video/motion/motionmmx video_chroma/i420_rgb_mmx video_chroma/i420_yuy2_mmx video_chroma/i422_yuy2_mmx video_chroma/i420_ymga_mmx"
+MMXEXT_MODULES="misc/memcpy/memcpymmxext codec/mpeg_video/idct/idctmmxext codec/mpeg_video/motion/motionmmxext"
+THREEDNOW_MODULES="misc/memcpy/memcpy3dn codec/a52old/imdct/imdct3dn codec/a52old/downmix/downmix3dn"
+SSE_MODULES="codec/a52old/imdct/imdctsse codec/a52old/downmix/downmixsse"
+ALTIVEC_MODULES="codec/mpeg_video/idct/idctaltivec codec/mpeg_video/motion/motionaltivec misc/memcpy/memcpyaltivec"
echo $ac_n "checking if \$CC groks MMX inline assembly""... $ac_c" 1>&6
-echo "configure:5545: checking if \$CC groks MMX inline assembly" >&5
+echo "configure:5551: checking if \$CC groks MMX inline assembly" >&5
if eval "test \"`echo '$''{'ac_cv_mmx_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
CFLAGS="${save_CFLAGS}"
cat > conftest.$ac_ext <<EOF
-#line 5551 "configure"
+#line 5557 "configure"
#include "confdefs.h"
int main() {
void *p;asm volatile("packuswb %%mm1,%%mm2"::"r"(p));
; return 0; }
EOF
-if { (eval echo configure:5558: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5564: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_mmx_inline=yes
else
fi
echo $ac_n "checking if \$CC groks MMX EXT inline assembly""... $ac_c" 1>&6
-echo "configure:5576: checking if \$CC groks MMX EXT inline assembly" >&5
+echo "configure:5582: checking if \$CC groks MMX EXT inline assembly" >&5
if eval "test \"`echo '$''{'ac_cv_mmxext_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
CFLAGS="${save_CFLAGS}"
cat > conftest.$ac_ext <<EOF
-#line 5582 "configure"
+#line 5588 "configure"
#include "confdefs.h"
int main() {
void *p;asm volatile("maskmovq %%mm1,%%mm2"::"r"(p));
; return 0; }
EOF
-if { (eval echo configure:5589: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5595: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_mmxext_inline=yes
else
fi
echo $ac_n "checking if \$CC groks 3D Now! inline assembly""... $ac_c" 1>&6
-echo "configure:5607: checking if \$CC groks 3D Now! inline assembly" >&5
+echo "configure:5613: checking if \$CC groks 3D Now! inline assembly" >&5
if eval "test \"`echo '$''{'ac_cv_3dnow_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
CFLAGS="${save_CFLAGS}"
cat > conftest.$ac_ext <<EOF
-#line 5613 "configure"
+#line 5619 "configure"
#include "confdefs.h"
int main() {
void *p;asm volatile("pfadd %%mm1,%%mm2"::"r"(p));
; return 0; }
EOF
-if { (eval echo configure:5620: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5626: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_3dnow_inline=yes
else
fi
echo $ac_n "checking if \$CC groks SSE inline assembly""... $ac_c" 1>&6
-echo "configure:5642: checking if \$CC groks SSE inline assembly" >&5
+echo "configure:5648: checking if \$CC groks SSE inline assembly" >&5
if eval "test \"`echo '$''{'ac_cv_sse_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
CFLAGS="${save_CFLAGS}"
cat > conftest.$ac_ext <<EOF
-#line 5648 "configure"
+#line 5654 "configure"
#include "confdefs.h"
int main() {
void *p;asm volatile("xorps %%xmm1,%%xmm2"::"r"(p));
; return 0; }
EOF
-if { (eval echo configure:5655: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5661: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sse_inline=yes
else
# we should be able to remove this test with future versions of mingw32
if test "x${SYS}" != "xmingw32"; then
echo $ac_n "checking if \$CC groks AltiVec inline assembly""... $ac_c" 1>&6
-echo "configure:5680: checking if \$CC groks AltiVec inline assembly" >&5
+echo "configure:5686: checking if \$CC groks AltiVec inline assembly" >&5
if eval "test \"`echo '$''{'ac_cv_altivec_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
CFLAGS="${save_CFLAGS}"
cat > conftest.$ac_ext <<EOF
-#line 5686 "configure"
+#line 5692 "configure"
#include "confdefs.h"
int main() {
asm volatile("vperm 0,1,2,3");
; return 0; }
EOF
-if { (eval echo configure:5693: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5699: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_altivec_inline=yes
else
rm -rf conftest*
CFLAGS="${save_CFLAGS} -Wa,-m7400"
cat > conftest.$ac_ext <<EOF
-#line 5702 "configure"
+#line 5708 "configure"
#include "confdefs.h"
int main() {
asm volatile("vperm 0,1,2,3");
; return 0; }
EOF
-if { (eval echo configure:5709: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5715: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_altivec_inline="-Wa,-m7400"
else
fi
echo $ac_n "checking if \$CC groks AltiVec C extensions""... $ac_c" 1>&6
-echo "configure:5740: checking if \$CC groks AltiVec C extensions" >&5
+echo "configure:5746: checking if \$CC groks AltiVec C extensions" >&5
if eval "test \"`echo '$''{'ac_cv_c_altivec'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
CFLAGS="${save_CFLAGS} -faltivec"
# Darwin test
cat > conftest.$ac_ext <<EOF
-#line 5747 "configure"
+#line 5753 "configure"
#include "confdefs.h"
int main() {
vec_mtvscr((vector unsigned int)(0));
; return 0; }
EOF
-if { (eval echo configure:5754: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5760: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_altivec=-faltivec
else
# Linux/PPC test
CFLAGS="${save_CFLAGS} ${idctaltivec_CFLAGS} -fvec"
cat > conftest.$ac_ext <<EOF
-#line 5765 "configure"
+#line 5771 "configure"
#include "confdefs.h"
int main() {
vec_mtvscr((vector unsigned int)(0));
; return 0; }
EOF
-if { (eval echo configure:5772: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5778: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_altivec="-fvec"
else
fi
echo $ac_n "checking if linker needs -framework vecLib""... $ac_c" 1>&6
-echo "configure:5802: checking if linker needs -framework vecLib" >&5
+echo "configure:5808: checking if linker needs -framework vecLib" >&5
if eval "test \"`echo '$''{'ac_cv_ld_altivec'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
LDFLAGS="${vlc_LDFLAGS} -framework vecLib"
cat > conftest.$ac_ext <<EOF
-#line 5808 "configure"
+#line 5814 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:5815: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5821: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_ld_altivec=yes
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:5947: checking for $ac_hdr" >&5
+echo "configure:5953: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5952 "configure"
+#line 5958 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:5957: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:5963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} dvd"
+ PLUGINS="${PLUGINS} access/dvd/dvd"
dvd_LDFLAGS="${dvd_LDFLAGS} -ldvdcss"
else
echo "$ac_t""no" 1>&6
else
echo $ac_n "checking for libdvdcss.a in ${with_dvdcss_tree}""... $ac_c" 1>&6
-echo "configure:5988: checking for libdvdcss.a in ${with_dvdcss_tree}" >&5
+echo "configure:5994: checking for libdvdcss.a in ${with_dvdcss_tree}" >&5
real_dvdcss_tree="`cd ${with_dvdcss_tree} 2>/dev/null && pwd`"
if test "x${real_dvdcss_tree}" = "x"
then
if test -f "${real_dvdcss_tree}/src/.libs/libdvdcss.a"
then
echo "$ac_t""${real_dvdcss_tree}/src/.libs/libdvdcss.a" 1>&6
- BUILTINS="${BUILTINS} dvd"
+ BUILTINS="${BUILTINS} access/dvd/dvd"
dvd_LDFLAGS="${dvd_LDFLAGS} ${real_dvdcss_tree}/src/.libs/libdvdcss.a"
dvd_CFLAGS="${dvd_CFLAGS} -I${real_dvdcss_tree}/src"
else
fi
;;
xno)
- PLUGINS="${PLUGINS} dvd"
+ PLUGINS="${PLUGINS} access/dvd/dvd"
dvd_CFLAGS="${dvd_CFLAGS} -DGOD_DAMN_DMCA"
dvd_LDFLAGS="${dvd_LDFLAGS} -ldl"
;;
*)
echo $ac_n "checking for dvdcss headers in ${with_dvdcss}""... $ac_c" 1>&6
-echo "configure:6014: checking for dvdcss headers in ${with_dvdcss}" >&5
+echo "configure:6020: checking for dvdcss headers in ${with_dvdcss}" >&5
if test -f ${with_dvdcss}/include/dvdcss/dvdcss.h
then
echo "$ac_t""yes" 1>&6
- PLUGINS="${PLUGINS} dvd"
+ PLUGINS="${PLUGINS} access/dvd/dvd"
dvd_LDFLAGS="${dvd_LDFLAGS} -L${with_dvdcss}/lib -ldvdcss"
dvd_CFLAGS="${dvd_CFLAGS} -I${with_dvdcss}/include"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6056: checking for $ac_hdr" >&5
+echo "configure:6062: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6061 "configure"
+#line 6067 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6066: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6072: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
EOF
cat > conftest.$ac_ext <<EOF
-#line 6088 "configure"
+#line 6094 "configure"
#include "confdefs.h"
#include <dvdread/dvd_reader.h>
int main() {
void foo() { int i=DVD_VIDEO_LB_LEN; }
; return 0; }
EOF
-if { (eval echo configure:6095: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6101: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
- PLUGINS="${PLUGINS} dvdread"
+ PLUGINS="${PLUGINS} access/dvdread/dvdread"
dvdread_LDFLAGS="${dvdread_LDFLAGS} ${test_LDFLAGS} -ldvdread"
dvdread_CFLAGS="${dvdread_CFLAGS} ${test_CFLAGS}"
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6160: checking for $ac_hdr" >&5
+echo "configure:6166: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6165 "configure"
+#line 6171 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6170: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6176: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} dvdplay"
+ PLUGINS="${PLUGINS} access/dvdplay/dvdplay"
dvdplay_LDFLAGS="${dvdplay_LDFLAGS} ${test_LDFLAGS} -ldvdplay -ldvdread"
dvdplay_CFLAGS="${dvdplay_CFLAGS} ${test_CFLAGS}"
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6242: checking for $ac_hdr" >&5
+echo "configure:6248: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6247 "configure"
+#line 6253 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6252: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6258: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} mpeg_ts_dvbpsi"
- mpeg_ts_dvbpsi_LDFLAGS="${mpeg_ts_dvbpsi_LDFLAGS} -ldvbpsi"
+ PLUGINS="${PLUGINS} demux/mpeg/ts_dvbpsi"
+ ts_dvbpsi_LDFLAGS="${ts_dvbpsi_LDFLAGS} -ldvbpsi"
else
echo "$ac_t""no" 1>&6
fi
else
echo $ac_n "checking for libdvbpsi.a in ${with_dvbpsi_tree}""... $ac_c" 1>&6
-echo "configure:6281: checking for libdvbpsi.a in ${with_dvbpsi_tree}" >&5
+echo "configure:6287: checking for libdvbpsi.a in ${with_dvbpsi_tree}" >&5
real_dvbpsi_tree="`cd ${with_dvbpsi_tree} 2>/dev/null && pwd`"
if test "x${real_dvbpsi_tree}" = "x"
then
if test -f "${real_dvbpsi_tree}/src/.libs/libdvbpsi.a"
then
echo "$ac_t""${real_dvbpsi_tree}/src/.libs/libdvbpsi.a" 1>&6
- BUILTINS="${BUILTINS} mpeg_ts_dvbpsi"
- mpeg_ts_dvbpsi_LDFLAGS="${mpeg_ts_dvbpsi_LDFLAGS} ${real_dvbpsi_tree}/src/.libs/libdvbpsi.a"
- mpeg_ts_dvbpsi_CFLAGS="${mpeg_ts_dvbpsi_CFLAGS} -I${real_dvbpsi_tree}/src"
+ BUILTINS="${BUILTINS} demux/mpeg/ts_dvbpsi"
+ ts_dvbpsi_LDFLAGS="${ts_dvbpsi_LDFLAGS} ${real_dvbpsi_tree}/src/.libs/libdvbpsi.a"
+ ts_dvbpsi_CFLAGS="${ts_dvbpsi_CFLAGS} -I${real_dvbpsi_tree}/src"
else
echo "$ac_t""no" 1>&6
{ echo "configure: error: cannot find ${real_dvbpsi_tree}/src/.libs/libdvbpsi.a, make sure you compiled libdvbpsi in ${with_dvbpsi_tree}" 1>&2; exit 1; }
;;
*)
echo $ac_n "checking for dvbpsi headers in ${with_dvbpsi}""... $ac_c" 1>&6
-echo "configure:6304: checking for dvbpsi headers in ${with_dvbpsi}" >&5
+echo "configure:6310: checking for dvbpsi headers in ${with_dvbpsi}" >&5
if test "x${with_dvbpsi}" = "x"
then
test_LDFLAGS=""
CPPFLAGS="${save_CPPFLAGS} ${test_CFLAGS}"
ac_safe=`echo "dvbpsi/dr.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for dvbpsi/dr.h""... $ac_c" 1>&6
-echo "configure:6316: checking for dvbpsi/dr.h" >&5
+echo "configure:6322: checking for dvbpsi/dr.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6321 "configure"
+#line 6327 "configure"
#include "confdefs.h"
#include <dvbpsi/dr.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6326: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6332: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
- PLUGINS="${PLUGINS} mpeg_ts_dvbpsi"
- mpeg_ts_dvbpsi_LDFLAGS="${mpeg_ts_dvbpsi_LDFLAGS} ${test_LDFLAGS} -ldvbpsi"
- mpeg_ts_dvbpsi_CFLAGS="${mpeg_ts_dvbpsi_CFLAGS} ${test_CFLAGS}"
+ PLUGINS="${PLUGINS} demux/mpeg/ts_dvbpsi"
+ ts_dvbpsi_LDFLAGS="${ts_dvbpsi_LDFLAGS} ${test_LDFLAGS} -ldvbpsi"
+ ts_dvbpsi_CFLAGS="${ts_dvbpsi_CFLAGS} ${test_CFLAGS}"
else
echo "$ac_t""no" 1>&6
if test "x${enable_vcd}" != "xno"
then
cat > conftest.$ac_ext <<EOF
-#line 6372 "configure"
+#line 6378 "configure"
#include "confdefs.h"
#include <linux/cdrom.h>
EOF
egrep "cdrom_msf0" >/dev/null 2>&1; then
rm -rf conftest*
- PLUGINS="${PLUGINS} vcd"
+ PLUGINS="${PLUGINS} access/vcd/vcd"
fi
rm -f conftest*
cat > conftest.$ac_ext <<EOF
-#line 6387 "configure"
+#line 6393 "configure"
#include "confdefs.h"
#include <sys/cdio.h>
EOF
egrep "ioc_toc_header " >/dev/null 2>&1; then
rm -rf conftest*
- PLUGINS="${PLUGINS} vcd"
+ PLUGINS="${PLUGINS} access/vcd/vcd"
cat >> confdefs.h <<\EOF
#define HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H 1
EOF
if test "x${SYS}" = "xbsdi"
then
- PLUGINS="${PLUGINS} vcd"
+ PLUGINS="${PLUGINS} access/vcd/vcd"
fi
if test "x${SYS}" = "xdarwin"
enableval="$enable_satellite"
if test "x${enable_satellite}" = "xyes"
then
- PLUGINS="${PLUGINS} satellite"
+ PLUGINS="${PLUGINS} access/satellite/satellite"
fi
fi
then
have_ipv6=0
echo $ac_n "checking for inet_pton""... $ac_c" 1>&6
-echo "configure:6431: checking for inet_pton" >&5
+echo "configure:6437: checking for inet_pton" >&5
if eval "test \"`echo '$''{'ac_cv_func_inet_pton'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6436 "configure"
+#line 6442 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char inet_pton(); below. */
; return 0; }
EOF
-if { (eval echo configure:6459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6465: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_inet_pton=yes"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for inet_pton in -lresolv""... $ac_c" 1>&6
-echo "configure:6478: checking for inet_pton in -lresolv" >&5
+echo "configure:6484: checking for inet_pton in -lresolv" >&5
ac_lib_var=`echo resolv'_'inet_pton | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lresolv $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 6486 "configure"
+#line 6492 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
inet_pton()
; return 0; }
EOF
-if { (eval echo configure:6497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6503: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for sockaddr_in6 in netinet/in.h""... $ac_c" 1>&6
-echo "configure:6522: checking for sockaddr_in6 in netinet/in.h" >&5
+echo "configure:6528: checking for sockaddr_in6 in netinet/in.h" >&5
cat > conftest.$ac_ext <<EOF
-#line 6524 "configure"
+#line 6530 "configure"
#include "confdefs.h"
#include <netinet/in.h>
EOF
rm -f conftest*
if test x$have_ipv6 = x1; then
- PLUGINS="${PLUGINS} ipv6"
+ PLUGINS="${PLUGINS} misc/network/ipv6"
fi
fi
if test "x${SYS}" = "xmingw32"
then
echo $ac_n "checking for getaddrinfo in ws2tcpip.h""... $ac_c" 1>&6
-echo "configure:6545: checking for getaddrinfo in ws2tcpip.h" >&5
+echo "configure:6551: checking for getaddrinfo in ws2tcpip.h" >&5
cat > conftest.$ac_ext <<EOF
-#line 6547 "configure"
+#line 6553 "configure"
#include "confdefs.h"
#include <ws2tcpip.h>
EOF
egrep "addrinfo" >/dev/null 2>&1; then
rm -rf conftest*
echo "$ac_t""yes" 1>&6
- PLUGINS="${PLUGINS} ipv6"
+ PLUGINS="${PLUGINS} misc/network/ipv6"
else
rm -rf conftest*
echo "$ac_t""no" 1>&6
if test "x${enable_avi}" != "xno"
then
- PLUGINS="${PLUGINS} avi"
+ PLUGINS="${PLUGINS} demux/avi/avi"
fi
{ echo "configure: error: ${with_mad_tree} directory doesn't exist" 1>&2; exit 1; }
fi
echo $ac_n "checking for mad.h in ${real_mad_tree}/libmad""... $ac_c" 1>&6
-echo "configure:6618: checking for mad.h in ${real_mad_tree}/libmad" >&5
+echo "configure:6624: checking for mad.h in ${real_mad_tree}/libmad" >&5
if test -f ${real_mad_tree}/libmad/mad.h
then
echo "$ac_t""yes" 1>&6
mad_LDFLAGS="${mad_LDFLAGS} -L${real_mad_tree}/libmad/.libs"
LDFLAGS="${save_LDFLAGS} ${mad_LDFLAGS}"
echo $ac_n "checking for mad_bit_init in -lmad""... $ac_c" 1>&6
-echo "configure:6626: checking for mad_bit_init in -lmad" >&5
+echo "configure:6632: checking for mad_bit_init in -lmad" >&5
ac_lib_var=`echo mad'_'mad_bit_init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lmad $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 6634 "configure"
+#line 6640 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
mad_bit_init()
; return 0; }
EOF
-if { (eval echo configure:6645: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6651: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- BUILTINS="${BUILTINS} mad"
+ BUILTINS="${BUILTINS} codec/mad/mad"
mad_LDFLAGS="${mad_LDFLAGS} -lmad"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6682: checking for $ac_hdr" >&5
+echo "configure:6688: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6687 "configure"
+#line 6693 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6692: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6698: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
done
echo $ac_n "checking for mad_bit_init in -lmad""... $ac_c" 1>&6
-echo "configure:6720: checking for mad_bit_init in -lmad" >&5
+echo "configure:6726: checking for mad_bit_init in -lmad" >&5
ac_lib_var=`echo mad'_'mad_bit_init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lmad $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 6728 "configure"
+#line 6734 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
mad_bit_init()
; return 0; }
EOF
-if { (eval echo configure:6739: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6745: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- PLUGINS="${PLUGINS} mad"
+ PLUGINS="${PLUGINS} codec/mad/mad"
mad_LDFLAGS="${mad_LDFLAGS} -lmad"
else
echo "$ac_t""no" 1>&6
if test "x${with_ffmpeg_tree}" != "x"
then
echo $ac_n "checking for libavcodec.a in ${with_ffmpeg_tree}""... $ac_c" 1>&6
-echo "configure:6796: checking for libavcodec.a in ${with_ffmpeg_tree}" >&5
+echo "configure:6802: checking for libavcodec.a in ${with_ffmpeg_tree}" >&5
real_ffmpeg_tree="`cd ${with_ffmpeg_tree} 2>/dev/null && pwd`"
if test "x${real_ffmpeg_tree}" = x
then
if test -f "${real_ffmpeg_tree}/libavcodec/libavcodec.a"
then
echo "$ac_t""${real_ffmpeg_tree}/libavcodec/libavcodec.a" 1>&6
- BUILTINS="${BUILTINS} ffmpeg"
+ BUILTINS="${BUILTINS} codec/ffmpeg/ffmpeg"
ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} ${real_ffmpeg_tree}/libavcodec/libavcodec.a -lm"
ffmpeg_CFLAGS="${ffmpeg_CFLAGS} -I${real_ffmpeg_tree}/libavcodec"
else
CFLAGS="${save_CFLAGS} ${ffmpeg_CFLAGS}"
LDFLAGS="${save_LDFLAGS} ${ffmpeg_LDFLAGS} -lm"
echo $ac_n "checking for avcodec_init in -lavcodec""... $ac_c" 1>&6
-echo "configure:6817: checking for avcodec_init in -lavcodec" >&5
+echo "configure:6823: checking for avcodec_init in -lavcodec" >&5
ac_lib_var=`echo avcodec'_'avcodec_init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lavcodec $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 6825 "configure"
+#line 6831 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
avcodec_init()
; return 0; }
EOF
-if { (eval echo configure:6836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6842: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- BUILTINS="${BUILTINS} ffmpeg"
+ BUILTINS="${BUILTINS} codec/ffmpeg/ffmpeg"
ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} -lavcodec -lm"
else
echo "$ac_t""no" 1>&6
then
ac_safe=`echo "zlib.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for zlib.h""... $ac_c" 1>&6
-echo "configure:6874: checking for zlib.h" >&5
+echo "configure:6880: checking for zlib.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6879 "configure"
+#line 6885 "configure"
#include "confdefs.h"
#include <zlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6884: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6890: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
echo $ac_n "checking for inflateEnd in -lz""... $ac_c" 1>&6
-echo "configure:6901: checking for inflateEnd in -lz" >&5
+echo "configure:6907: checking for inflateEnd in -lz" >&5
ac_lib_var=`echo z'_'inflateEnd | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lz $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 6909 "configure"
+#line 6915 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
inflateEnd()
; return 0; }
EOF
-if { (eval echo configure:6920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6926: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- PLUGINS="${PLUGINS} mp4"
+ PLUGINS="${PLUGINS} demux/mp4/mp4"
mp4_LDFLAGS="${mp4_LDFLAGS} -lz"
else
echo "$ac_t""no" 1>&6
if test "x${SYS}" = "xbeos"
then
- PLUGINS="${PLUGINS} beos"
+ PLUGINS="${PLUGINS} gui/beos/beos"
fi
# Check whether --enable-a52 or --disable-a52 was given.
{ echo "configure: error: ${with_a52_tree} directory doesn't exist" 1>&2; exit 1; }
fi
echo $ac_n "checking for a52.h in ${real_a52_tree}/include""... $ac_c" 1>&6
-echo "configure:6977: checking for a52.h in ${real_a52_tree}/include" >&5
+echo "configure:6983: checking for a52.h in ${real_a52_tree}/include" >&5
if test -f ${real_a52_tree}/include/a52.h
then
echo "$ac_t""yes" 1>&6
a52_LDFLAGS="${a52_LDFLAGS} -L${real_a52_tree}/liba52/.libs"
LDFLAGS="${save_LDFLAGS} ${a52_LDFLAGS}"
echo $ac_n "checking for a52_free in -la52""... $ac_c" 1>&6
-echo "configure:6985: checking for a52_free in -la52" >&5
+echo "configure:6991: checking for a52_free in -la52" >&5
ac_lib_var=`echo a52'_'a52_free | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-la52 -lm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 6993 "configure"
+#line 6999 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
a52_free()
; return 0; }
EOF
-if { (eval echo configure:7004: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7010: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- BUILTINS="${BUILTINS} a52"
+ BUILTINS="${BUILTINS} codec/a52/a52"
a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
a52_CFLAGS="${a52_CFLAGS} -DUSE_A52DEC_TREE"
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7045: checking for $ac_hdr" >&5
+echo "configure:7051: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7050 "configure"
+#line 7056 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7055: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7061: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
EOF
echo $ac_n "checking for a52_free in -la52""... $ac_c" 1>&6
-echo "configure:7077: checking for a52_free in -la52" >&5
+echo "configure:7083: checking for a52_free in -la52" >&5
ac_lib_var=`echo a52'_'a52_free | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-la52 -lm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7085 "configure"
+#line 7091 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
a52_free()
; return 0; }
EOF
-if { (eval echo configure:7096: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7102: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- BUILTINS="${BUILTINS} a52"
+ BUILTINS="${BUILTINS} codec/a52/a52"
a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
a52_CFLAGS="${a52_CFLAGS}"
if test "x${enable_cinepak}" != "xno"
then
- PLUGINS="${PLUGINS} cinepak"
+ PLUGINS="${PLUGINS} codec/cinepak/cinepak"
fi
# Check whether --enable-vorbis or --disable-vorbis was given.
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7152: checking for $ac_hdr" >&5
+echo "configure:7158: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7157 "configure"
+#line 7163 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7162: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7168: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
#define $ac_tr_hdr 1
EOF
- #PLUGINS="${PLUGINS} vorbis"
+ #PLUGINS="${PLUGINS} demux/ogg/ogg codec/vorbis/vorbis"
vorbis_LDFLAGS="${vorbis_LDFLAGS} -lvorbis"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7214: checking for $ac_hdr" >&5
+echo "configure:7220: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7219 "configure"
+#line 7225 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7224: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7230: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} x11"
+ PLUGINS="${PLUGINS} video_output/x11/x11"
x11_LDFLAGS="${x11_LDFLAGS} -L${x_libraries} -lX11 -lXext"
x11_CFLAGS="${x11_CFLAGS} -I${x_includes}"
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7270: checking for $ac_hdr" >&5
+echo "configure:7276: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7275 "configure"
+#line 7281 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7280: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7286: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
CFLAGS="${save_CFLAGS} -L${x_libraries} -lX11 -lXext"
echo $ac_n "checking for XvPutImage in -lXv_pic""... $ac_c" 1>&6
-echo "configure:7303: checking for XvPutImage in -lXv_pic" >&5
+echo "configure:7309: checking for XvPutImage in -lXv_pic" >&5
ac_lib_var=`echo Xv_pic'_'XvPutImage | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lXv_pic $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7311 "configure"
+#line 7317 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
XvPutImage()
; return 0; }
EOF
-if { (eval echo configure:7322: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
# We have Xv_pic, that's good, we can build an xvideo.so plugin !
- PLUGINS="${PLUGINS} xvideo"
+ PLUGINS="${PLUGINS} video_output/x11/xvideo"
xvideo_LDFLAGS="${xvideo_LDFLAGS} -L${x_libraries} -lX11 -lXext -lXv_pic"
xvideo_CFLAGS="${xvideo_CFLAGS} -I${x_includes}"
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for XvPutImage in -lXv""... $ac_c" 1>&6
-echo "configure:7344: checking for XvPutImage in -lXv" >&5
+echo "configure:7350: checking for XvPutImage in -lXv" >&5
ac_lib_var=`echo Xv'_'XvPutImage | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lXv $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7352 "configure"
+#line 7358 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
XvPutImage()
; return 0; }
EOF
-if { (eval echo configure:7363: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
# We don't have Xv_pic, but we have Xv, let's make xvideo.a as builtin
- PLUGINS="${PLUGINS} xvideo"
+ PLUGINS="${PLUGINS} video_output/x11/xvideo"
xvideo_LDFLAGS="${xvideo_LDFLAGS} -L${x_libraries} -lX11 -lXext -lXv"
xvideo_CFLAGS="${xvideo_CFLAGS} -I${x_includes}"
else
echo "$ac_t""no" 1>&6
# Otherwise... well, do nothing.
+ :
fi
# Extract the first word of "sdl12-config", so it can be a program name with args.
set dummy sdl12-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:7422: checking for $ac_word" >&5
+echo "configure:7429: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SDL12_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "sdl11-config", so it can be a program name with args.
set dummy sdl11-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:7462: checking for $ac_word" >&5
+echo "configure:7469: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SDL11_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "sdl-config", so it can be a program name with args.
set dummy sdl-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:7503: checking for $ac_word" >&5
+echo "configure:7510: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
if test "x${SDL_CONFIG}" != "xno"
then
- PLUGINS="${PLUGINS} sdl"
+ PLUGINS="${PLUGINS} video_output/sdl/sdl"
sdl_CFLAGS="${sdl_CFLAGS} `${SDL_CONFIG} --cflags`"
sdl_LDFLAGS="${sdl_LDFLAGS} `${SDL_CONFIG} --libs | sed 's,-rdynamic,,'`"
CPPFLAGS="${save_CPPFLAGS} ${sdl_CFLAGS}"
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7548: checking for $ac_hdr" >&5
+echo "configure:7555: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7553 "configure"
+#line 7560 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7558: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7565: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7628: checking for $ac_hdr" >&5
+echo "configure:7635: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7633 "configure"
+#line 7640 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7638: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7645: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} directx"
+ PLUGINS="${PLUGINS} video_output/directx/directx"
directx_LDFLAGS="${directx_LDFLAGS} -lgdi32"
else
echo "$ac_t""no" 1>&6
else
echo $ac_n "checking for directX headers in ${with_directx}""... $ac_c" 1>&6
-echo "configure:7667: checking for directX headers in ${with_directx}" >&5
+echo "configure:7674: checking for directX headers in ${with_directx}" >&5
if test -f ${with_directx}/ddraw.h
then
- PLUGINS="${PLUGINS} directx"
+ PLUGINS="${PLUGINS} video_output/directx/directx"
directx_LDFLAGS="${directx_LDFLAGS} -lgdi32"
directx_CFLAGS="${directx_CFLAGS} -I${with_directx}"
echo "$ac_t""yes" 1>&6
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7694: checking for $ac_hdr" >&5
+echo "configure:7701: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7699 "configure"
+#line 7706 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7704: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7711: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} fb"
+ PLUGINS="${PLUGINS} video_output/fb/fb"
else
echo "$ac_t""no" 1>&6
enableval="$enable_mga"
if test "x${enable_mga}" = "xyes"
then
- PLUGINS="${PLUGINS} mga xmga"
+ PLUGINS="${PLUGINS} video_output/mga/mga video_output/mga/xmga"
fi
fi
if test "x${enable_ggi}" = "xyes"
then
- PLUGINS="${PLUGINS} ggi"
+ PLUGINS="${PLUGINS} video_output/ggi/ggi"
ggi_LDFLAGS="${ggi_LDFLAGS} -lggi"
# Check whether --with-ggi or --without-ggi was given.
if test "${with_ggi+set}" = set; then
if test "x${enable_glide}" = "xyes"
then
- PLUGINS="${PLUGINS} glide"
+ PLUGINS="${PLUGINS} video_output/glide/glide"
glide_LDFLAGS="${glide_LDFLAGS} -lglide2x -lm"
glide_CFLAGS="${glide_CFLAGS} -I/usr/include/glide"
# Check whether --with-glide or --without-glide was given.
then
ac_safe=`echo "aalib.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for aalib.h""... $ac_c" 1>&6
-echo "configure:7799: checking for aalib.h" >&5
+echo "configure:7806: checking for aalib.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7804 "configure"
+#line 7811 "configure"
#include "confdefs.h"
#include <aalib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7809: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7816: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test "x${have_aa}" = "xtrue"
then
- PLUGINS="${PLUGINS} aa"
+ PLUGINS="${PLUGINS} video_output/aa/aa"
aa_LDFLAGS="${aa_LDFLAGS} -laa"
fi
fi
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:7860: checking for $ac_hdr" >&5
+echo "configure:7867: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7865 "configure"
+#line 7872 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7870: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7877: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} dsp"
+ PLUGINS="${PLUGINS} audio_output/dsp/dsp"
echo $ac_n "checking for main in -lossaudio""... $ac_c" 1>&6
-echo "configure:7893: checking for main in -lossaudio" >&5
+echo "configure:7900: checking for main in -lossaudio" >&5
ac_lib_var=`echo ossaudio'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lossaudio $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7901 "configure"
+#line 7908 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:7908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7915: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
# Extract the first word of "esd-config", so it can be a program name with args.
set dummy esd-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:7944: checking for $ac_word" >&5
+echo "configure:7951: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_ESD_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "x${ESD_CONFIG}" != "xno"
then
- PLUGINS="${PLUGINS} esd"
+ PLUGINS="${PLUGINS} audio_output/esd/esd"
esd_CFLAGS="${esd_CFLAGS} `${ESD_CONFIG} --cflags`"
esd_LDFLAGS="${esd_LDFLAGS} `${ESD_CONFIG} --libs`"
fi
# Extract the first word of "artsc-config", so it can be a program name with args.
set dummy artsc-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:7995: checking for $ac_word" >&5
+echo "configure:8002: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_ARTS_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "x${ARTS_CONFIG}" != "xno"
then
- PLUGINS="${PLUGINS} arts"
+ PLUGINS="${PLUGINS} audio_output/arts/arts"
arts_CFLAGS="${arts_CFLAGS} `${ARTS_CONFIG} --cflags`"
arts_LDFLAGS="${arts_LDFLAGS} `${ARTS_CONFIG} --libs `"
fi
then
ac_safe=`echo "alsa/asoundlib.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for alsa/asoundlib.h""... $ac_c" 1>&6
-echo "configure:8045: checking for alsa/asoundlib.h" >&5
+echo "configure:8052: checking for alsa/asoundlib.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8050 "configure"
+#line 8057 "configure"
#include "confdefs.h"
#include <alsa/asoundlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8055: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8062: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
echo $ac_n "checking for main in -lasound""... $ac_c" 1>&6
-echo "configure:8072: checking for main in -lasound" >&5
+echo "configure:8079: checking for main in -lasound" >&5
ac_lib_var=`echo asound'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lasound $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8080 "configure"
+#line 8087 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:8087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8094: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test "x${have_alsa}" = "xtrue"
then
- PLUGINS="${PLUGINS} alsa"
+ PLUGINS="${PLUGINS} audio_output/alsa/alsa"
alsa_LDFLAGS="${alsa_LDFLAGS} -lasound -lm -ldl"
fi
fi
if test "x${enable_waveout}" != "xno" -a "x${SYS}" = "xmingw32"
then
- PLUGINS="${PLUGINS} waveout"
+ PLUGINS="${PLUGINS} audio_output/waveout/waveout"
waveout_LDFLAGS="-lwinmm"
fi
# Extract the first word of "gtk12-config", so it can be a program name with args.
set dummy gtk12-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8164: checking for $ac_word" >&5
+echo "configure:8171: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GTK12_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8203: checking for $ac_word" >&5
+echo "configure:8210: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8252: checking for $ac_hdr" >&5
+echo "configure:8259: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8257 "configure"
+#line 8264 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8262: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8269: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test "x${ac_cv_gtk_headers}" = "xyes"
then
- PLUGINS="${PLUGINS} gtk"
+ PLUGINS="${PLUGINS} gui/gtk/gtk"
ALIASES="${ALIASES} gvlc"
fi
CPPFLAGS="${save_CPPFLAGS}"
# Extract the first word of "gtk12-config", so it can be a program name with args.
set dummy gtk12-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8322: checking for $ac_word" >&5
+echo "configure:8329: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GTK12_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8361: checking for $ac_word" >&5
+echo "configure:8368: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8410: checking for $ac_hdr" >&5
+echo "configure:8417: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8415 "configure"
+#line 8422 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8420: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8427: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test "x${ac_cv_gtk_headers}" = "xyes"
then
- PLUGINS="${PLUGINS} familiar"
+ PLUGINS="${PLUGINS} gui/familiar/familiar"
fi
CPPFLAGS="${save_CPPFLAGS}"
fi
# Extract the first word of "gnome-config", so it can be a program name with args.
set dummy gnome-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8465: checking for $ac_word" >&5
+echo "configure:8472: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GNOME_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8509: checking for $ac_hdr" >&5
+echo "configure:8516: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8514 "configure"
+#line 8521 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8519: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8526: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} gnome"
+ PLUGINS="${PLUGINS} gui/gtk/gnome"
ALIASES="${ALIASES} gnome-vlc"
else
if test "${enable_qt+set}" = set; then
enableval="$enable_qt"
if test "x${enable_qt}" = "xyes"; then
- PLUGINS="${PLUGINS} qt"
+ PLUGINS="${PLUGINS} gui/qt/qt"
ALIASES="${ALIASES} qvlc"
qt_LDFLAGS="${qt_LDFLAGS} -lqt -L${QTDIR}/lib"
qt_CFLAGS="${qt_CFLAGS} -I/usr/include/qt -I${QTDIR}/include"
if test "${enable_kde+set}" = set; then
enableval="$enable_kde"
if test "x${enable_kde}" = "xyes"; then
- PLUGINS="${PLUGINS} kde"
+ PLUGINS="${PLUGINS} gui/kde/kde"
ALIASES="${ALIASES} kvlc"
kde_LDFLAGS="${kde_LDFLAGS} -L${KDEDIR}/lib -lkfile"
kde_CFLAGS="${kde_CFLAGS} -I/usr/include/kde -I/usr/include/qt"
enableval="$enable_macosx"
if test "x${enable_macosx}" = "xyes"
then
- BUILTINS="${BUILTINS} macosx"
+ BUILTINS="${BUILTINS} gui/macosx/macosx"
macosx_LDFLAGS="${macosx_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework IOKit -framework Cocoa -framework Carbon -framework AGL -framework QuickTime -lobjc -ObjC"
fi
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8606: checking for $ac_hdr" >&5
+echo "configure:8613: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8611 "configure"
+#line 8618 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8616: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8623: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
- BUILTINS="${BUILTINS} macosx"
+ BUILTINS="${BUILTINS} gui/macosx/macosx"
macosx_LDFLAGS="${macosx_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework IOKit -framework Cocoa -framework Carbon -framework AGL -framework QuickTime -lobjc -ObjC"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8659: checking for $ac_hdr" >&5
+echo "configure:8666: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8664 "configure"
+#line 8671 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8669: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8676: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
#define $ac_tr_hdr 1
EOF
- PLUGINS="${PLUGINS} qnx"
+ PLUGINS="${PLUGINS} gui/qnx/qnx"
qnx_LDFLAGS="${qnx_LDFLAGS} -lasound -lph"
else
then
BCBUILDER="${with_bcbuilder}"
fi
- PLUGINS="${PLUGINS} intfwin"
+ PLUGINS="${PLUGINS} gui/win32/win32"
fi
fi
if test "${enable_ncurses+set}" = set; then
enableval="$enable_ncurses"
if test "x${enable_ncurses}" = "xyes"; then
- PLUGINS="${PLUGINS} ncurses"
+ PLUGINS="${PLUGINS} gui/ncurses/ncurses"
ncurses_LDFLAGS="${ncurses_LDFLAGS} -lncurses"
fi
fi
then
ac_safe=`echo "xosd.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for xosd.h""... $ac_c" 1>&6
-echo "configure:8740: checking for xosd.h" >&5
+echo "configure:8747: checking for xosd.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8745 "configure"
+#line 8752 "configure"
#include "confdefs.h"
#include <xosd.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8750: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8757: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test "x${have_xosd}" = "xtrue"
then
- PLUGINS="${PLUGINS} xosd"
+ PLUGINS="${PLUGINS} visualization/xosd/xosd"
xosd_LDFLAGS="${xosd_LDFLAGS} -lxosd"
fi
fi
then
ac_safe=`echo "lirc/lirc_client.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for lirc/lirc_client.h""... $ac_c" 1>&6
-echo "configure:8789: checking for lirc/lirc_client.h" >&5
+echo "configure:8796: checking for lirc/lirc_client.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 8794 "configure"
+#line 8801 "configure"
#include "confdefs.h"
#include <lirc/lirc_client.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8799: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8806: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
echo $ac_n "checking for lirc_init in -llirc_client""... $ac_c" 1>&6
-echo "configure:8816: checking for lirc_init in -llirc_client" >&5
+echo "configure:8823: checking for lirc_init in -llirc_client" >&5
ac_lib_var=`echo lirc_client'_'lirc_init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-llirc_client $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8824 "configure"
+#line 8831 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
lirc_init()
; return 0; }
EOF
-if { (eval echo configure:8835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8842: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test "x${have_lirc}" = "xtrue"
then
- PLUGINS="${PLUGINS} lirc"
+ PLUGINS="${PLUGINS} control/lirc/lirc"
lirc_LDFLAGS="${lirc_LDFLAGS} -llirc_client"
fi
fi
;;
*)
echo $ac_n "checking whether the byte order is big-endian""... $ac_c" 1>&6
-echo "configure:8890: checking whether the byte order is big-endian" >&5
+echo "configure:8897: checking whether the byte order is big-endian" >&5
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
enableval="$enable_pth"
if test "x${enable_pth}" = "xyes"; then
echo $ac_n "checking for pth_init in -lpth""... $ac_c" 1>&6
-echo "configure:8972: checking for pth_init in -lpth" >&5
+echo "configure:8979: checking for pth_init in -lpth" >&5
ac_lib_var=`echo pth'_'pth_init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lpth $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8980 "configure"
+#line 8987 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
pth_init()
; return 0; }
EOF
-if { (eval echo configure:8991: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
cat > conftest.$ac_ext <<EOF
-#line 9019 "configure"
+#line 9026 "configure"
#include "confdefs.h"
#include <pth.h>
EOF
enableval="$enable_st"
if test "x${enable_st}" = "xyes"; then
echo $ac_n "checking for st_init in -lst""... $ac_c" 1>&6
-echo "configure:9045: checking for st_init in -lst" >&5
+echo "configure:9052: checking for st_init in -lst" >&5
ac_lib_var=`echo st'_'st_init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lst $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9053 "configure"
+#line 9060 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
st_init()
; return 0; }
EOF
-if { (eval echo configure:9064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9071: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
cat > conftest.$ac_ext <<EOF
-#line 9092 "configure"
+#line 9099 "configure"
#include "confdefs.h"
#include <st.h>
EOF
# Extract the first word of "mozilla-config", so it can be a program name with args.
set dummy mozilla-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:9128: checking for $ac_word" >&5
+echo "configure:9135: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_MOZILLA_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "x${SYS}" != "xmingw32"; then
LDFLAGS="${save_LDFLAGS} -L${x_libraries}"
echo $ac_n "checking for XtStrings in -lXt""... $ac_c" 1>&6
-echo "configure:9166: checking for XtStrings in -lXt" >&5
+echo "configure:9173: checking for XtStrings in -lXt" >&5
ac_lib_var=`echo Xt'_'XtStrings | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lXt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9174 "configure"
+#line 9181 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
XtStrings()
; return 0; }
EOF
-if { (eval echo configure:9185: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9192: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
s%@mozilla_CFLAGS@%$mozilla_CFLAGS%g
s%@a52_CFLAGS@%$a52_CFLAGS%g
s%@arts_CFLAGS@%$arts_CFLAGS%g
-s%@chroma_i420_yuy2_mmx_CFLAGS@%$chroma_i420_yuy2_mmx_CFLAGS%g
+s%@i420_yuy2_mmx_CFLAGS@%$i420_yuy2_mmx_CFLAGS%g
s%@dvd_CFLAGS@%$dvd_CFLAGS%g
s%@dvdread_CFLAGS@%$dvdread_CFLAGS%g
s%@dvdplay_CFLAGS@%$dvdplay_CFLAGS%g
-s%@mpeg_ts_dvbpsi_CFLAGS@%$mpeg_ts_dvbpsi_CFLAGS%g
+s%@ts_dvbpsi_CFLAGS@%$ts_dvbpsi_CFLAGS%g
s%@directx_CFLAGS@%$directx_CFLAGS%g
s%@esd_CFLAGS@%$esd_CFLAGS%g
s%@familiar_CFLAGS@%$familiar_CFLAGS%g
s%@alsa_LDFLAGS@%$alsa_LDFLAGS%g
s%@arts_LDFLAGS@%$arts_LDFLAGS%g
s%@beos_LDFLAGS@%$beos_LDFLAGS%g
-s%@chroma_i420_rgb_LDFLAGS@%$chroma_i420_rgb_LDFLAGS%g
+s%@i420_rgb_LDFLAGS@%$i420_rgb_LDFLAGS%g
s%@directx_LDFLAGS@%$directx_LDFLAGS%g
s%@dsp_LDFLAGS@%$dsp_LDFLAGS%g
s%@dvd_LDFLAGS@%$dvd_LDFLAGS%g
s%@dvdread_LDFLAGS@%$dvdread_LDFLAGS%g
s%@dvdplay_LDFLAGS@%$dvdplay_LDFLAGS%g
-s%@mpeg_ts_dvbpsi_LDFLAGS@%$mpeg_ts_dvbpsi_LDFLAGS%g
+s%@ts_dvbpsi_LDFLAGS@%$ts_dvbpsi_LDFLAGS%g
s%@esd_LDFLAGS@%$esd_LDFLAGS%g
s%@familiar_LDFLAGS@%$familiar_LDFLAGS%g
-s%@filter_distort_LDFLAGS@%$filter_distort_LDFLAGS%g
+s%@distort_LDFLAGS@%$distort_LDFLAGS%g
s%@ffmpeg_LDFLAGS@%$ffmpeg_LDFLAGS%g
s%@mp4_LDFLAGS@%$mp4_LDFLAGS%g
s%@ggi_LDFLAGS@%$ggi_LDFLAGS%g
if test "x${ac_cv_c_omit_frame_pointer}" != "xno"; then
CFLAGS_OPTIM_NODEBUG="${CFLAGS_OPTIM_NODEBUG} -fomit-frame-pointer"
# this plugin does not compile without -fomit-frame-pointer, damn gcc!
- chroma_i420_yuy2_mmx_CFLAGS="${chroma_i420_yuy2_mmx_CFLAGS} -fomit-frame-pointer"
+ i420_yuy2_mmx_CFLAGS="${i420_yuy2_mmx_CFLAGS} -fomit-frame-pointer"
fi
dnl Check for Darwin plugin linking flags
dnl default modules
dnl
BUILTINS="${BUILTINS}"
-PLUGINS="${PLUGINS} dummy null rc logger mpeg_es mpeg_audio mpeg_ps mpeg_ts idct idctclassic motion imdct downmix mpeg_adec ac3_adec mpeg_vdec file udp http ipv4 memcpy lpcm_adec ac3_spdif spudec filter_deinterlace filter_invert filter_wall filter_transform filter_distort filter_clone filter_crop fx_scope chroma_i420_rgb chroma_i420_yuy2 chroma_i422_yuy2 chroma_i420_ymga"
+PLUGINS="${PLUGINS} misc/dummy/dummy misc/null/null"
+PLUGINS="${PLUGINS} control/rc/rc misc/logger/logger access/file access/udp access/http misc/network/ipv4 misc/memcpy/memcpy"
+PLUGINS="${PLUGINS} demux/mpeg/es demux/mpeg/audio demux/mpeg/ps demux/mpeg/ts"
+PLUGINS="${PLUGINS} codec/mpeg_video/idct/idct codec/mpeg_video/idct/idctclassic codec/mpeg_video/motion/motion codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/mpeg_audio/mpeg_audio codec/a52old/a52old codec/mpeg_video/mpeg_video codec/lpcm/lpcm codec/spdif/spdif codec/spudec/spudec"
+PLUGINS="${PLUGINS} video_filter/deinterlace/deinterlace video_filter/invert video_filter/wall video_filter/transform video_filter/distort video_filter/clone video_filter/crop"
+PLUGINS="${PLUGINS} visualization/scope/scope"
+PLUGINS="${PLUGINS} video_chroma/i420_rgb video_chroma/i420_yuy2 video_chroma/i422_yuy2 video_chroma/i420_ymga"
dnl
dnl Accelerated modules
dnl
-MMX_MODULES="memcpymmx idctmmx motionmmx chroma_i420_rgb_mmx chroma_i420_yuy2_mmx chroma_i422_yuy2_mmx chroma_i420_ymga_mmx"
-MMXEXT_MODULES="memcpymmxext idctmmxext motionmmxext"
-THREEDNOW_MODULES="memcpy3dn imdct3dn downmix3dn"
-SSE_MODULES="imdctsse downmixsse"
-ALTIVEC_MODULES="idctaltivec motionaltivec memcpyaltivec"
+MMX_MODULES="misc/memcpy/memcpymmx codec/mpeg_video/idct/idctmmx codec/mpeg_video/motion/motionmmx video_chroma/i420_rgb_mmx video_chroma/i420_yuy2_mmx video_chroma/i422_yuy2_mmx video_chroma/i420_ymga_mmx"
+MMXEXT_MODULES="misc/memcpy/memcpymmxext codec/mpeg_video/idct/idctmmxext codec/mpeg_video/motion/motionmmxext"
+THREEDNOW_MODULES="misc/memcpy/memcpy3dn codec/a52old/imdct/imdct3dn codec/a52old/downmix/downmix3dn"
+SSE_MODULES="codec/a52old/imdct/imdctsse codec/a52old/downmix/downmixsse"
+ALTIVEC_MODULES="codec/mpeg_video/idct/idctaltivec codec/mpeg_video/motion/motionaltivec misc/memcpy/memcpyaltivec"
AC_CACHE_CHECK([if \$CC groks MMX inline assembly],
[ac_cv_mmx_inline],
if test "x${with_dvdcss_tree}" = x
then
AC_CHECK_HEADERS(dvdcss/dvdcss.h,
- [ PLUGINS="${PLUGINS} dvd"
+ [ PLUGINS="${PLUGINS} access/dvd/dvd"
dvd_LDFLAGS="${dvd_LDFLAGS} -ldvdcss" ],
[ AC_MSG_WARN([libdvdcss is no longer provided with vlc; please get libdvdcss from http://www.videolan.org/libdvdcss/ and build it. Then either use --with-dvdcss=<path/where/libdvdcss/was/installed> for dynamic linking (recommended under Unix) or --with-dvdcss-tree=<path/where/libdvdcss/was/built> for static linking (recommended under BeOS, Windows, MacOS X). Alternatively you can use --disable-dvd to disable the DVD plugin.])
AC_MSG_ERROR([cannot find libdvdcss headers]) ])
then
dnl Use a custom libdvdcss
AC_MSG_RESULT(${real_dvdcss_tree}/src/.libs/libdvdcss.a)
- BUILTINS="${BUILTINS} dvd"
+ BUILTINS="${BUILTINS} access/dvd/dvd"
dvd_LDFLAGS="${dvd_LDFLAGS} ${real_dvdcss_tree}/src/.libs/libdvdcss.a"
dvd_CFLAGS="${dvd_CFLAGS} -I${real_dvdcss_tree}/src"
else
;;
xno)
dnl Compile without dvdcss (dlopen version, works only under Linux)
- PLUGINS="${PLUGINS} dvd"
+ PLUGINS="${PLUGINS} access/dvd/dvd"
dvd_CFLAGS="${dvd_CFLAGS} -DGOD_DAMN_DMCA"
dvd_LDFLAGS="${dvd_LDFLAGS} -ldl"
;;
then
dnl Use ${with_dvdcss}/include/dvdcss/dvdcss.h
AC_MSG_RESULT(yes)
- PLUGINS="${PLUGINS} dvd"
+ PLUGINS="${PLUGINS} access/dvd/dvd"
dvd_LDFLAGS="${dvd_LDFLAGS} -L${with_dvdcss}/lib -ldvdcss"
dvd_CFLAGS="${dvd_CFLAGS} -I${with_dvdcss}/include"
else
AC_CHECK_HEADERS(dvdread/dvd_reader.h, [
AC_TRY_COMPILE([#include <dvdread/dvd_reader.h>],
[void foo() { int i=DVD_VIDEO_LB_LEN; }],[
- PLUGINS="${PLUGINS} dvdread"
+ PLUGINS="${PLUGINS} access/dvdread/dvdread"
dvdread_LDFLAGS="${dvdread_LDFLAGS} ${test_LDFLAGS} -ldvdread"
dvdread_CFLAGS="${dvdread_CFLAGS} ${test_CFLAGS}"
],[
fi
CPPFLAGS="$save_CPPFLAGS $test_CFLAGS"
AC_CHECK_HEADERS(dvdplay/dvdplay.h, [
- PLUGINS="${PLUGINS} dvdplay"
+ PLUGINS="${PLUGINS} access/dvdplay/dvdplay"
dvdplay_LDFLAGS="${dvdplay_LDFLAGS} ${test_LDFLAGS} -ldvdplay -ldvdread"
dvdplay_CFLAGS="${dvdplay_CFLAGS} ${test_CFLAGS}"
],[
if test "x${with_dvbpsi_tree}" = "x"
then
AC_CHECK_HEADERS(dvbpsi/dr.h,
- [ PLUGINS="${PLUGINS} mpeg_ts_dvbpsi"
- mpeg_ts_dvbpsi_LDFLAGS="${mpeg_ts_dvbpsi_LDFLAGS} -ldvbpsi" ], [],
+ [ PLUGINS="${PLUGINS} demux/mpeg/ts_dvbpsi"
+ ts_dvbpsi_LDFLAGS="${ts_dvbpsi_LDFLAGS} -ldvbpsi" ], [],
[ AC_MSG_ERROR([cannot find libdvbpsi headers]) ])
else
AC_MSG_CHECKING(for libdvbpsi.a in ${with_dvbpsi_tree})
then
dnl Use a custom libdvbpsi
AC_MSG_RESULT(${real_dvbpsi_tree}/src/.libs/libdvbpsi.a)
- BUILTINS="${BUILTINS} mpeg_ts_dvbpsi"
- mpeg_ts_dvbpsi_LDFLAGS="${mpeg_ts_dvbpsi_LDFLAGS} ${real_dvbpsi_tree}/src/.libs/libdvbpsi.a"
- mpeg_ts_dvbpsi_CFLAGS="${mpeg_ts_dvbpsi_CFLAGS} -I${real_dvbpsi_tree}/src"
+ BUILTINS="${BUILTINS} demux/mpeg/ts_dvbpsi"
+ ts_dvbpsi_LDFLAGS="${ts_dvbpsi_LDFLAGS} ${real_dvbpsi_tree}/src/.libs/libdvbpsi.a"
+ ts_dvbpsi_CFLAGS="${ts_dvbpsi_CFLAGS} -I${real_dvbpsi_tree}/src"
else
dnl The given libdvbpsi wasn't built
AC_MSG_RESULT(no)
fi
CPPFLAGS="${save_CPPFLAGS} ${test_CFLAGS}"
AC_CHECK_HEADER([dvbpsi/dr.h],[
- PLUGINS="${PLUGINS} mpeg_ts_dvbpsi"
- mpeg_ts_dvbpsi_LDFLAGS="${mpeg_ts_dvbpsi_LDFLAGS} ${test_LDFLAGS} -ldvbpsi"
- mpeg_ts_dvbpsi_CFLAGS="${mpeg_ts_dvbpsi_CFLAGS} ${test_CFLAGS}"
+ PLUGINS="${PLUGINS} demux/mpeg/ts_dvbpsi"
+ ts_dvbpsi_LDFLAGS="${ts_dvbpsi_LDFLAGS} ${test_LDFLAGS} -ldvbpsi"
+ ts_dvbpsi_CFLAGS="${ts_dvbpsi_CFLAGS} ${test_CFLAGS}"
],[
if test "x${enable_dvbpsi}" != "x"
then
if test "x${enable_vcd}" != "xno"
then
AC_EGREP_HEADER(cdrom_msf0,linux/cdrom.h,[
- PLUGINS="${PLUGINS} vcd"
+ PLUGINS="${PLUGINS} access/vcd/vcd"
])
AC_EGREP_HEADER(ioc_toc_header ,sys/cdio.h,[
- PLUGINS="${PLUGINS} vcd"
+ PLUGINS="${PLUGINS} access/vcd/vcd"
AC_DEFINE(HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H, 1, For FreeBSD VCD support)
])
if test "x${SYS}" = "xbsdi"
then
- PLUGINS="${PLUGINS} vcd"
+ PLUGINS="${PLUGINS} access/vcd/vcd"
fi
if test "x${SYS}" = "xdarwin"
[ --enable-satellite satellite card support (default disabled)],
[ if test "x${enable_satellite}" = "xyes"
then
- PLUGINS="${PLUGINS} satellite"
+ PLUGINS="${PLUGINS} access/satellite/satellite"
fi])
dnl
AC_EGREP_HEADER(sockaddr_in6,netinet/in.h,
[AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no); have_ipv6=0])
if test x$have_ipv6 = x1; then
- PLUGINS="${PLUGINS} ipv6"
+ PLUGINS="${PLUGINS} misc/network/ipv6"
fi
fi
if test "x${SYS}" = "xmingw32"
then
AC_MSG_CHECKING(for getaddrinfo in ws2tcpip.h)
AC_EGREP_HEADER(addrinfo,ws2tcpip.h,[AC_MSG_RESULT(yes)
- PLUGINS="${PLUGINS} ipv6"],[AC_MSG_RESULT(no)])
+ PLUGINS="${PLUGINS} misc/network/ipv6"],[AC_MSG_RESULT(no)])
fi
dnl
[ --enable-avi AVI demux module (default enabled)])
if test "x${enable_avi}" != "xno"
then
- PLUGINS="${PLUGINS} avi"
+ PLUGINS="${PLUGINS} demux/avi/avi"
fi
dnl
mad_LDFLAGS="${mad_LDFLAGS} -L${real_mad_tree}/libmad/.libs"
LDFLAGS="${save_LDFLAGS} ${mad_LDFLAGS}"
AC_CHECK_LIB(mad, mad_bit_init, [
- BUILTINS="${BUILTINS} mad"
+ BUILTINS="${BUILTINS} codec/mad/mad"
mad_LDFLAGS="${mad_LDFLAGS} -lmad"
],[ AC_MSG_ERROR([the specified tree hasn't been compiled ])
],[])
AC_CHECK_HEADERS(mad.h, ,
[ AC_MSG_ERROR([Cannot find development headers for libmad...]) ])
AC_CHECK_LIB(mad, mad_bit_init, [
- PLUGINS="${PLUGINS} mad"
+ PLUGINS="${PLUGINS} codec/mad/mad"
mad_LDFLAGS="${mad_LDFLAGS} -lmad" ],
[ AC_MSG_ERROR([Cannot find libmad library...]) ])
CFLAGS="${save_CFLAGS}"
then
dnl Use a custom libffmpeg
AC_MSG_RESULT(${real_ffmpeg_tree}/libavcodec/libavcodec.a)
- BUILTINS="${BUILTINS} ffmpeg"
+ BUILTINS="${BUILTINS} codec/ffmpeg/ffmpeg"
ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} ${real_ffmpeg_tree}/libavcodec/libavcodec.a -lm"
ffmpeg_CFLAGS="${ffmpeg_CFLAGS} -I${real_ffmpeg_tree}/libavcodec"
else
CFLAGS="${save_CFLAGS} ${ffmpeg_CFLAGS}"
LDFLAGS="${save_LDFLAGS} ${ffmpeg_LDFLAGS} -lm"
AC_CHECK_LIB(avcodec, avcodec_init, [
- BUILTINS="${BUILTINS} ffmpeg"
+ BUILTINS="${BUILTINS} codec/ffmpeg/ffmpeg"
ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} -lavcodec -lm" ],
[ AC_MSG_ERROR([Cannot find libavcodec library...]) ])
LDFLAGS="${save_LDFLAGS}"
then
AC_CHECK_HEADER(zlib.h,
AC_CHECK_LIB(z, inflateEnd,
- [ PLUGINS="${PLUGINS} mp4"
+ [ PLUGINS="${PLUGINS} demux/mp4/mp4"
mp4_LDFLAGS="${mp4_LDFLAGS} -lz" ],
[ AC_MSG_ERROR([cannot find zlib library...]) ]),
[ AC_MSG_ERROR([cannot find zlib header...]) ])
dnl special case for BeOS
if test "x${SYS}" = "xbeos"
then
- PLUGINS="${PLUGINS} beos"
+ PLUGINS="${PLUGINS} gui/beos/beos"
fi
dnl
a52_LDFLAGS="${a52_LDFLAGS} -L${real_a52_tree}/liba52/.libs"
LDFLAGS="${save_LDFLAGS} ${a52_LDFLAGS}"
AC_CHECK_LIB(a52, a52_free, [
- BUILTINS="${BUILTINS} a52"
+ BUILTINS="${BUILTINS} codec/a52/a52"
a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
a52_CFLAGS="${a52_CFLAGS} -DUSE_A52DEC_TREE"
],[
else dnl no with args
AC_CHECK_HEADERS(a52dec/a52.h, [
AC_CHECK_LIB(a52, a52_free, [
- BUILTINS="${BUILTINS} a52"
+ BUILTINS="${BUILTINS} codec/a52/a52"
a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
a52_CFLAGS="${a52_CFLAGS}"
],[],[-lm])
[ --enable-cinepak Cinepak decoder (default enabled)])
if test "x${enable_cinepak}" != "xno"
then
- PLUGINS="${PLUGINS} cinepak"
+ PLUGINS="${PLUGINS} codec/cinepak/cinepak"
fi
dnl
then
AC_CHECK_HEADERS(ogg/ogg.h, [
dnl disabled for the moment
- #PLUGINS="${PLUGINS} vorbis"
+ #PLUGINS="${PLUGINS} demux/ogg/ogg codec/vorbis/vorbis"
vorbis_LDFLAGS="${vorbis_LDFLAGS} -lvorbis"
],[])
fi
(test "x${SYS}" != "xmingw32" || test "x${enable_x11}" = "xyes"); then
CPPFLAGS="${save_CPPFLAGS} -I${x_includes}"
AC_CHECK_HEADERS(X11/Xlib.h, [
- PLUGINS="${PLUGINS} x11"
+ PLUGINS="${PLUGINS} video_output/x11/x11"
x11_LDFLAGS="${x11_LDFLAGS} -L${x_libraries} -lX11 -lXext"
x11_CFLAGS="${x11_CFLAGS} -I${x_includes}"
])
CFLAGS="${save_CFLAGS} -L${x_libraries} -lX11 -lXext"
AC_CHECK_LIB(Xv_pic,XvPutImage,
# We have Xv_pic, that's good, we can build an xvideo.so plugin !
- PLUGINS="${PLUGINS} xvideo"
+ PLUGINS="${PLUGINS} video_output/x11/xvideo"
xvideo_LDFLAGS="${xvideo_LDFLAGS} -L${x_libraries} -lX11 -lXext -lXv_pic"
xvideo_CFLAGS="${xvideo_CFLAGS} -I${x_includes}",
AC_CHECK_LIB(Xv,XvPutImage,
# We don't have Xv_pic, but we have Xv, let's make xvideo.a as builtin
- PLUGINS="${PLUGINS} xvideo"
+ PLUGINS="${PLUGINS} video_output/x11/xvideo"
xvideo_LDFLAGS="${xvideo_LDFLAGS} -L${x_libraries} -lX11 -lXext -lXv"
xvideo_CFLAGS="${xvideo_CFLAGS} -I${x_includes}",
# Otherwise... well, do nothing.
+ :
)
)
CFLAGS="${save_CFLAGS}"
fi
if test "x${SDL_CONFIG}" != "xno"
then
- PLUGINS="${PLUGINS} sdl"
+ PLUGINS="${PLUGINS} video_output/sdl/sdl"
sdl_CFLAGS="${sdl_CFLAGS} `${SDL_CONFIG} --cflags`"
sdl_LDFLAGS="${sdl_LDFLAGS} `${SDL_CONFIG} --libs | sed 's,-rdynamic,,'`"
CPPFLAGS="${save_CPPFLAGS} ${sdl_CFLAGS}"
if test "x${with_directx}" = "x"
then
AC_CHECK_HEADERS(ddraw.h,
- [ PLUGINS="${PLUGINS} directx"
+ [ PLUGINS="${PLUGINS} video_output/directx/directx"
directx_LDFLAGS="${directx_LDFLAGS} -lgdi32" ])
else
AC_MSG_CHECKING(for directX headers in ${with_directx})
if test -f ${with_directx}/ddraw.h
then
- PLUGINS="${PLUGINS} directx"
+ PLUGINS="${PLUGINS} video_output/directx/directx"
directx_LDFLAGS="${directx_LDFLAGS} -lgdi32"
directx_CFLAGS="${directx_CFLAGS} -I${with_directx}"
AC_MSG_RESULT(yes)
if test "x${enable_fb}" != "xno"
then
AC_CHECK_HEADERS(linux/fb.h, [
- PLUGINS="${PLUGINS} fb"
+ PLUGINS="${PLUGINS} video_output/fb/fb"
])
fi
[ --enable-mga Linux kernel Matrox support (default disabled)],
[ if test "x${enable_mga}" = "xyes"
then
- PLUGINS="${PLUGINS} mga xmga"
+ PLUGINS="${PLUGINS} video_output/mga/mga video_output/mga/xmga"
fi ])
dnl
[ --enable-ggi GGI support (default disabled)])
if test "x${enable_ggi}" = "xyes"
then
- PLUGINS="${PLUGINS} ggi"
+ PLUGINS="${PLUGINS} video_output/ggi/ggi"
ggi_LDFLAGS="${ggi_LDFLAGS} -lggi"
AC_ARG_WITH(ggi,
[ --with-ggi=PATH path to libggi],
[ --enable-glide Glide (3dfx) support (default disabled)])
if test "x${enable_glide}" = "xyes"
then
- PLUGINS="${PLUGINS} glide"
+ PLUGINS="${PLUGINS} video_output/glide/glide"
glide_LDFLAGS="${glide_LDFLAGS} -lglide2x -lm"
glide_CFLAGS="${glide_CFLAGS} -I/usr/include/glide"
AC_ARG_WITH(glide,
AC_CHECK_HEADER(aalib.h,have_aa="true",have_aa="false")
if test "x${have_aa}" = "xtrue"
then
- PLUGINS="${PLUGINS} aa"
+ PLUGINS="${PLUGINS} video_output/aa/aa"
aa_LDFLAGS="${aa_LDFLAGS} -laa"
fi
fi
(test "x${SYS}" != "xmingw32" || test "x${enable_dsp}" = "xyes")
then
AC_CHECK_HEADERS(soundcard.h sys/soundcard.h machine/soundcard.h, [
- PLUGINS="${PLUGINS} dsp"
+ PLUGINS="${PLUGINS} audio_output/dsp/dsp"
AC_CHECK_LIB(ossaudio,main,dsp_LDFLAGS="${dsp_LDFLAGS} -lossaudio")
])
fi
AC_PATH_PROG(ESD_CONFIG, esd-config, no)
if test "x${ESD_CONFIG}" != "xno"
then
- PLUGINS="${PLUGINS} esd"
+ PLUGINS="${PLUGINS} audio_output/esd/esd"
esd_CFLAGS="${esd_CFLAGS} `${ESD_CONFIG} --cflags`"
esd_LDFLAGS="${esd_LDFLAGS} `${ESD_CONFIG} --libs`"
fi
AC_PATH_PROG(ARTS_CONFIG, artsc-config, no)
if test "x${ARTS_CONFIG}" != "xno"
then
- PLUGINS="${PLUGINS} arts"
+ PLUGINS="${PLUGINS} audio_output/arts/arts"
arts_CFLAGS="${arts_CFLAGS} `${ARTS_CONFIG} --cflags`"
arts_LDFLAGS="${arts_LDFLAGS} `${ARTS_CONFIG} --libs `"
fi
AC_CHECK_HEADER(alsa/asoundlib.h, AC_CHECK_LIB(asound, main, have_alsa="true", have_alsa="false"),have_alsa="false")
if test "x${have_alsa}" = "xtrue"
then
- PLUGINS="${PLUGINS} alsa"
+ PLUGINS="${PLUGINS} audio_output/alsa/alsa"
alsa_LDFLAGS="${alsa_LDFLAGS} -lasound -lm -ldl"
fi
fi])
[ --enable-waveout Win32 waveOut module (default enabled on Win32)])
if test "x${enable_waveout}" != "xno" -a "x${SYS}" = "xmingw32"
then
- PLUGINS="${PLUGINS} waveout"
+ PLUGINS="${PLUGINS} audio_output/waveout/waveout"
waveout_LDFLAGS="-lwinmm"
fi
])
if test "x${ac_cv_gtk_headers}" = "xyes"
then
- PLUGINS="${PLUGINS} gtk"
+ PLUGINS="${PLUGINS} gui/gtk/gtk"
ALIASES="${ALIASES} gvlc"
fi
CPPFLAGS="${save_CPPFLAGS}"
])
if test "x${ac_cv_gtk_headers}" = "xyes"
then
- PLUGINS="${PLUGINS} familiar"
+ PLUGINS="${PLUGINS} gui/familiar/familiar"
fi
CPPFLAGS="${save_CPPFLAGS}"
fi
# now look for the gnome.h header
CPPFLAGS="${save_CPPFLAGS} ${gnome_CFLAGS}"
AC_CHECK_HEADERS(gnome.h, [
- PLUGINS="${PLUGINS} gnome"
+ PLUGINS="${PLUGINS} gui/gtk/gnome"
ALIASES="${ALIASES} gnome-vlc"
],[
AC_MSG_ERROR([Can't find gnome headers. Please install the gnome
AC_ARG_ENABLE(qt,
[ --enable-qt Qt interface support (default disabled)],
[if test "x${enable_qt}" = "xyes"; then
- PLUGINS="${PLUGINS} qt"
+ PLUGINS="${PLUGINS} gui/qt/qt"
ALIASES="${ALIASES} qvlc"
qt_LDFLAGS="${qt_LDFLAGS} -lqt -L${QTDIR}/lib"
qt_CFLAGS="${qt_CFLAGS} -I/usr/include/qt -I${QTDIR}/include"
AC_ARG_ENABLE(kde,
[ --enable-kde KDE interface support (default disabled)],
[if test "x${enable_kde}" = "xyes"; then
- PLUGINS="${PLUGINS} kde"
+ PLUGINS="${PLUGINS} gui/kde/kde"
ALIASES="${ALIASES} kvlc"
kde_LDFLAGS="${kde_LDFLAGS} -L${KDEDIR}/lib -lkfile"
kde_CFLAGS="${kde_CFLAGS} -I/usr/include/kde -I/usr/include/qt"
[ --enable-macosx MacOS X support (default enabled on MacOS X)],
[if test "x${enable_macosx}" = "xyes"
then
- BUILTINS="${BUILTINS} macosx"
+ BUILTINS="${BUILTINS} gui/macosx/macosx"
macosx_LDFLAGS="${macosx_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework IOKit -framework Cocoa -framework Carbon -framework AGL -framework QuickTime -lobjc -ObjC"
fi],
[AC_CHECK_HEADERS(Cocoa/Cocoa.h,
- BUILTINS="${BUILTINS} macosx"
+ BUILTINS="${BUILTINS} gui/macosx/macosx"
macosx_LDFLAGS="${macosx_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework IOKit -framework Cocoa -framework Carbon -framework AGL -framework QuickTime -lobjc -ObjC"
)])
if test "x${enable_qnx}" != "xno"
then
AC_CHECK_HEADERS(Ph.h, [
- PLUGINS="${PLUGINS} qnx"
+ PLUGINS="${PLUGINS} gui/qnx/qnx"
qnx_LDFLAGS="${qnx_LDFLAGS} -lasound -lph"
])
fi
then
BCBUILDER="${with_bcbuilder}"
fi
- PLUGINS="${PLUGINS} intfwin"
+ PLUGINS="${PLUGINS} gui/win32/win32"
fi ])
dnl
AC_ARG_ENABLE(ncurses,
[ --enable-ncurses ncurses interface support (default disabled)],
[if test "x${enable_ncurses}" = "xyes"; then
- PLUGINS="${PLUGINS} ncurses"
+ PLUGINS="${PLUGINS} gui/ncurses/ncurses"
ncurses_LDFLAGS="${ncurses_LDFLAGS} -lncurses"
fi])
AC_CHECK_HEADER(xosd.h, have_xosd="true", have_xosd="false")
if test "x${have_xosd}" = "xtrue"
then
- PLUGINS="${PLUGINS} xosd"
+ PLUGINS="${PLUGINS} visualization/xosd/xosd"
xosd_LDFLAGS="${xosd_LDFLAGS} -lxosd"
fi
fi
AC_CHECK_HEADER(lirc/lirc_client.h, AC_CHECK_LIB(lirc_client, lirc_init, have_lirc="true", have_lirc="false"),have_lirc="false")
if test "x${have_lirc}" = "xtrue"
then
- PLUGINS="${PLUGINS} lirc"
+ PLUGINS="${PLUGINS} control/lirc/lirc"
lirc_LDFLAGS="${lirc_LDFLAGS} -llirc_client"
fi
fi
AC_SUBST(a52_CFLAGS)
AC_SUBST(arts_CFLAGS)
-AC_SUBST(chroma_i420_yuy2_mmx_CFLAGS)
+AC_SUBST(i420_yuy2_mmx_CFLAGS)
AC_SUBST(dvd_CFLAGS)
AC_SUBST(dvdread_CFLAGS)
AC_SUBST(dvdplay_CFLAGS)
-AC_SUBST(mpeg_ts_dvbpsi_CFLAGS)
+AC_SUBST(ts_dvbpsi_CFLAGS)
AC_SUBST(directx_CFLAGS)
AC_SUBST(esd_CFLAGS)
AC_SUBST(familiar_CFLAGS)
AC_SUBST(alsa_LDFLAGS)
AC_SUBST(arts_LDFLAGS)
AC_SUBST(beos_LDFLAGS)
-AC_SUBST(chroma_i420_rgb_LDFLAGS)
+AC_SUBST(i420_rgb_LDFLAGS)
AC_SUBST(directx_LDFLAGS)
AC_SUBST(dsp_LDFLAGS)
AC_SUBST(dvd_LDFLAGS)
AC_SUBST(dvdread_LDFLAGS)
AC_SUBST(dvdplay_LDFLAGS)
-AC_SUBST(mpeg_ts_dvbpsi_LDFLAGS)
+AC_SUBST(ts_dvbpsi_LDFLAGS)
AC_SUBST(esd_LDFLAGS)
AC_SUBST(familiar_LDFLAGS)
-AC_SUBST(filter_distort_LDFLAGS)
+AC_SUBST(distort_LDFLAGS)
AC_SUBST(ffmpeg_LDFLAGS)
AC_SUBST(mp4_LDFLAGS)
AC_SUBST(ggi_LDFLAGS)
--- /dev/null
+MAD API documentation collected from e-mails of Joe Drew and Rob Leslie.
+The original e-mails can be found in the docs directory. They contain the
+same information as is presented below.
+
+INDEX
+======
+1. I/O Synchronous Mode
+2. Low-level API
+
+
+
+1. I/O SYNCHRONOUS MODE (extract from Joe Drew)
+===============================================
+MAD operates with callbacks for functions. Each of these functions is
+expected to return type enum mad_flow; this allows you to control the
+decoding process.
+
+MAD always outputs 32-bit (well, mad_fixed_t) little-endian data. Take
+this into account when outputting samples to the sound card.
+Related to the above, since MAD outputs type mad_fixed_t, unless you can
+output with 32-bit accuracy (most sound cards can't), you will have to
+quantize, round, dither, etc these samples to 16-bit (or whatever you
+need.) While there is a sample routine in minimad.c, if you want good
+quality you'll either want to roll your own or take a look in madplay's
+sources.
+
+Integral to understanding MAD: MAD is a decoding library only. You
+handle input and output; you're responsible for fast-forwarding and
+rewinding, if you want that type of functionality. All that MAD will do
+is take input from you, decode the MPEG frames, give you some
+information about them, and give you the decoded PCM data.
+
+Now, the nitty-gritty information.
+
+First, you need a mad_decoder struct. This holds all information about
+how you want your stream decoded, such as input/output functions, error
+handling functions, etc.
+
+mad_decoder_init() sets this structure up for you.
+
+struct mad_decoder decoder;
+struct my_playbuf playbuf;
+
+mad_decoder_init(&decoder, &playbuf, input_func, header_func, /*filter*/
+0, output_func, /*error*/ 0, /* message */ 0);
+
+In this example, the function called to get more data is set to
+input_func, the function called after MPEG headers have been decoded is
+header_func, the function called after all sound data has been decoded
+to PCM (for output) is output_func, and the filter, error, and message
+functions are unset.
+
+Now, MAD runs in a constant decoding loop. It runs something along the
+following lines:
+
+if I'm out of data
+ call input_func
+if input_func says there's no more data,
+ quit
+decode the header and call header_func
+decode the mpeg audio data
+call the filter function
+call the output function
+loop
+
+Now, this is an oversimplification obviously. The important thing to
+realise is that at every step of the process you can tell MAD what to
+do.
+
+Since all of these functions return enum mad_flow, you can tell MAD to
+do any of the following:
+
+enum mad_flow {
+ MAD_FLOW_CONTINUE = 0x0000, /* Keep decoding this stream */
+ MAD_FLOW_STOP = 0x0010, /* Stop decoding this stream, but exit
+ normally */
+ MAD_FLOW_BREAK = 0x0011, /* Stop decoding this stream, and exit
+ with an error */
+ MAD_FLOW_IGNORE = 0x0020 /* Don't decode this frame,
+ but continue afterwards */
+};
+
+Most of the time you'll probably want to return MAD_FLOW_CONTINUE. In
+every case, you'll have to return one of these values from the functions
+you define.
+
+This is the definition of each of the functions:
+
+enum mad_flow (*input_func)(void *, struct mad_stream *);
+enum mad_flow (*header_func)(void *, struct mad_header const *);
+enum mad_flow (*filter_func)(void *, struct mad_stream const *, struct
+mad_frame *);
+enum mad_flow (*output_func)(void *, struct mad_header const *, struct
+mad_pcm *);
+enum mad_flow (*error_func)(void *, struct mad_stream *, struct
+mad_frame *);
+enum mad_flow (*message_func)(void *, void *, unsigned int *);
+
+In each of these functions the void* pointer passed to the function is
+your "playbuf" structure. This can hold whatever you want - for example,
+song title, length, number of frames - just remember to re-cast it to
+the type you've defined.
+
+input_func takes a mad_stream pointer. Most of the time what you'll want
+to do is something along the lines of the following:
+
+if (more_data_available)
+ buffer = refill_buffer();
+ mad_stream_buffer(stream, buffer, length_of_buffer);
+ return MAD_FLOW_CONTINUE;
+else
+ return MAD_FLOW_STOP;
+
+(On many systems you'll want to use mmap() for this.)
+
+header_func takes a mad_header pointer. This contains most of the
+important information about a given frame; in constant bitrate files, it
+can contain most of the important information about the stream. It will
+give you the length of that frame, using mad_timer_t; the audio layer;
+extension; bitrate... the list is long. Read frame.h or mad.h in the
+frame.h area for more information.
+Again, return MAD_FLOW_{CONTINUE,STOP,BREAK} depending on outside
+conditions.
+
+The only other function I have firsthand information on is output_func;
+in this case, you are given a pointer to struct mad_pcm. This gives you
+the sampling rate, number of channels, and number of samples per
+channel; doing something like the following should work:
+
+mad_fixed_t *left_channel = pcm->samples[0], *right_channel =
+pcm->samples[1];
+int nsamples = pcm->length;
+signed int sample;
+unsigned char * buffer = some_buffer;
+unsigned char * ptr = buffer;
+
+while (nsamples--)
+{
+ sample = (signed int) do_downsample(*left_ch++)
+
+ *ptr++ = (unsigned char) (sample >> 0);
+ *ptr++ = (unsigned char) (sample >> 8);
+
+ sample = (signed int) do_downsample(*right_ch++)
+
+ *ptr++ = (unsigned char) (sample >> 0);
+ *ptr++ = (unsigned char) (sample >> 8);
+}
+
+output buffer to device.
+
+Be sure to handle the big-endian case (autoconf can test for this), and
+also the mono (1 channel) case. See mad.c in mpg321, at the end of the
+file, for an example.
+
+Information on the other (error, filter, message) functions would be
+appreciated, though I think in knowing this information anyone should be
+able to puzzle it out.
+
+Now that the decoder is set up with all these callback functions, you
+call
+
+mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
+
+and then
+
+mad_decoder_finish(&decoder);
+
+Once you've called mad_decoder_finish, you can re-use the decoder
+struct, if you're, for example, within a playlist. Incidentally, all MAD
+structures have similar mad_(whatever)_init and mad_(whatever)_finish
+functions.
+
+I hope this helps people get their feet wet with MAD. Read the source,
+and particularly mad.h - there are a lot of things there you might not
+expect. Rob has done a good job in making MAD a complete solution. :)
+
+
+2. LOW-LEVEL API (extract from Rob Leslie)
+==========================================
+
+By way of clarification, MAD also has a low-level API which does not use
+callbacks. You can control the entire decoding process yourself more or less
+as follows:
+
+ /* load buffer with your MPEG audio data */
+
+ mad_stream_buffer(&stream, buffer, buflen);
+
+ while (1) {
+ mad_frame_decode(&frame, &stream);
+ mad_synth_frame(&synth, &frame);
+
+ /* output PCM samples in synth.pcm */
+ }
+
+This is vastly simplified, but it shows the general idea. mad_frame_decode()
+decodes the next frame's header and subband samples. mad_synth_frame() takes
+those subband samples and synthesizes PCM samples.
+
+It is also possible to call mad_header_decode() before mad_frame_decode().
+This just gives you the frame's header info, in case that's all you want, or
+perhaps to help you decide whether you want to decode the rest of the frame.
+
+As Joe mentions, each of the stream, frame, and synth structs needs to be
+initialized and "finished" before and after use:
+
+ struct mad_stream stream;
+ struct mad_frame frame;
+ struct mad_synth synth;
+
+ mad_stream_init(&stream);
+ mad_frame_init(&frame);
+ mad_synth_init(&synth);
+
+ /* ... */
+
+ mad_synth_finish(&synth);
+ mad_frame_finish(&frame);
+ mad_stream_finish(&stream);
+
+You can work with just a struct mad_header instead of a struct mad_frame if
+you only want to decode frame headers.
+
+Joe writes:
+> MAD always outputs 32-bit (well, mad_fixed_t) little-endian data. Take
+> this into account when outputting samples to the sound card.
+
+This isn't quite right: the mad_fixed_t type is not necessarily little-endian.
+It's the same endianness as the native integer types. Also, it's only
+guaranteed to be *at least* 32 bits wide.
+
+The fixed-point sample format is important to understand, and I recommend
+reading the comments in libmad/fixed.h. The thing to remember when converting
+MAD's fixed-point integer samples to 16-bit PCM (or whatever) is that MAD
+encodes samples as numbers in the full-scale range [-1.0, +1.0) where the
+binary point is placed 28 (MAD_F_FRACBITS) bits to the left of the integer.
+However, you need to be prepared to handle clipping as some numbers may be
+less than -1.0 (-MAD_F_ONE) or greater than or equal to +1.0 (MAD_F_ONE, aka
+1 << MAD_F_FRACBITS).
+
+> Information on the other (error, filter, message) functions would be
+> appreciated, though I think in knowing this information anyone should be
+> able to puzzle it out.
+
+In the high-level API, the error callback function is called whenever a
+decoding error occurs. The error number is in stream->error.
+
+The filter callback function is called after decoding a frame, but before
+synthesis. Here it is possible to modify the frame's subband samples, for
+example to perform a uniform attenuation/amplification, or to do other special
+processing in the frequency domain.
+
+The message callback function is only used with MAD_DECODER_MODE_ASYNC, and is
+called whenever the parent process sends a message via mad_decoder_message().
+This callback can generate a reply by overwriting the message buffer that is
+passed to it. (The size of the reply must be the same or smaller than the
+message.)
+
+
+
+
--- /dev/null
+bug #09/11/2001-1: (FIXED 20/11/2001, by JP Saman)
+ Makefile.opts.in and Makefile.opts static libmad.a library is not filled in automatically by configure.
+ It should say in Makefile.opts LIB_MAD=lib/libmad.a
+
+bug #09/11/2001-2: (FIXED december 2001)
+ Libmad is not included in the vlc source code. It is assumed that the library is already available on the machine
+ where the plugin is compiled on. The configure option --with-libmad tells the script where libmad.a or libmad.so library
+ and mad.h include file are installed. E.g. if libmad.a is in /usr/lib and mad.h is in /usr/include then the configure
+ option should be --with-libmad=/usr
+
+bug #12/11/2001-1 (FIXED january 2002)
+ smoothen out audio in libmad_output callback function, by optimizing conversion routines. After investigation
+ and experimenting I found out that my input routine and output routine were not balanced correctly with
+ respect to buffer sizes. A lot of data got lost. I fixed that, but still need a bater scaling/smoothing routine
+ for the audio.
+ I tried a simpler audio scale function, but it did not improve the audio much. Not even on Intel machine, so I suspect the audio
+ decoding to need a bit too much time. The next thing to try is to steer the decoding process by hand (going to a lower level API).
+ Rewriting mad plugin to use a lower level API was not needed. I found the problem by reviewing libmad example code madlld and bbplay.
+ This resulted in a partial rewrite a some parts and a lot of testing. There are still some issues when trying on different CPU's
+ but this will sort itself gradually.
+
+bug #20/11/2001-1 (FIXED 25/11/2001, by JP Saman)
+ synchronization between audio and video output is lost. In libmad_output a timestamp is set on the audio data, but
+ it points to a later video frame, then when the audio data was read. How can I set the correct timestamp on the
+ audio fifo at the time it was read from the bitstream, so that it matches the video frame it belongs to?
+ Solution: Do it in two steps, in the input function save i_pts of fifo and in output function pass saved i_pts to
+ aout_fifo.
--- /dev/null
+File: Plugin mad for vlc is based upon libmad from the mad distribution.
+Author: Jean-Paul Saman <jpsaman@wxs.nl>
+
+Directories:
+============
+vlc/plugins/mad : mad audio decoder plugin for vlc
+
+Interface functions
+===================
+The following interface functions are implemented in the mad plugin.
+
+decoder_Probe : vlc probes for plugin capabilities
+decoder_Run : vlc starts a decoder plugin by calling this function
+InitThread : routine to do some initializations
+EndThread : cleanup function
+
+The following functions are callback functions for the mad decoder library:
+
+libmad_input : called when input data is needed
+libmad_output : called whenever a frame has been decoded
+libmad_header : called upon decoding of only a frame header
+libmad_messages : libmad messages
+libmad_error : called whenever an error occured during the decoding process
+
+Design: (ASCII art)
+=======
+It represents the function call flow viewed from the vlc main program. The main program is in charge of allocating decoders,
+initializing, starting and stopping them.
+
+ ---------------
+ | <library> |
+ | libmad |
+ ---------------
+ ^
+ |
+ ---------------
+ | <plugin> |
+ | mad |
+ _______________
+ ^
+ |
+ ________________________
+ | <decoder interface> |
+ | vlc plugin interface |
+ ________________________
+
+
+Interface view:
+===============
+ [mad decoder plugin]
+ ----------------------
+ vlc decoder interface -> | mad_adec mad_libmad | -> libmad
+ -----------------------
+
+Rationel:
+========
+Keeping libmad as a separate library on the system, either dynamic or statically linked in, makes maintenance so much simpeler.
+Merging with a new libmad version should be straight forward as long as the interface stays stable.
+There is another benefit: Disk (actually flash ROM) resources and memory are very limited on a iPaq.
+Other programs or utilities like madplay and BBplay can make use of the same libmad version we do. In this way
+limiting the needed storage place on disk (flash ROM). Also this is only possible when the interface stays the same.
+
+
--- /dev/null
+TODO: (Jean-Paul Saman <jpsaman@wxs.nl>)
+
+[1 - 30 October 2001, done]
+introduce libmad in vlc-dev code tree, this includes:
+ configure from top level of source tree
+ compilable from top level of source tree
+
+[2 - 25 November 2001, done]
+creating basic mad plugin in vlc-dev code tree, this include:
+ writing most simple vlc-plugin (no fancy stuf)
+ configurable from top level of source tree
+ compilable from top level of source tree
+
+[3 - 25 November 2001, done]
+test basic mad plugin
+ native Intel
+ native iPaq
+
+[4 - 26 November 2001, done]
+commit to current vlc-dev tree in CVS at VideoLan
+ fix broken things and conflicts
+ run tests again (see [3])
+
+[5 - all ready done by Christophe Massiot]
+make cross-compile possible for vlc without interface. With interface it is to damn difficult to do cross-compilation.
+
+[6 - done by fenrir ]
+extending mad plugin with more features
+ do fancy stuff (enable MP3 decoding)
+
+[7 - done ]
+test extended plugin
+ native Intel
+ native iPaq
+
+[8 - done ]
+commit to current vlc-dev tree in CVS at Videolan
+ fix broken things and conflicts
+ run tests again (see [7])
+
--- /dev/null
+Subject: [mad-dev] Some information about programming with MAD (in synchronous mode)
+
+As the author of mpg321, I too faced the problem of MAD not being
+documented. However, in looking at minimad.c, and re-writing mpg321 to
+use MAD, I came to understand it better. Here's some information which
+will help anybody start out with MAD:
+
+First, some basic information.
+MAD operates with callbacks for functions. Each of these functions is
+expected to return type enum mad_flow; this allows you to control the
+decoding process.
+MAD always outputs 32-bit (well, mad_fixed_t) little-endian data. Take
+this into account when outputting samples to the sound card.
+Related to the above, since MAD outputs type mad_fixed_t, unless you can
+output with 32-bit accuracy (most sound cards can't), you will have to
+quantize, round, dither, etc these samples to 16-bit (or whatever you
+need.) While there is a sample routine in minimad.c, if you want good
+quality you'll either want to roll your own or take a look in madplay's
+sources.
+Integral to understanding MAD: MAD is a decoding library only. You
+handle input and output; you're responsible for fast-forwarding and
+rewinding, if you want that type of functionality. All that MAD will do
+is take input from you, decode the MPEG frames, give you some
+information about them, and give you the decoded PCM data.
+
+Now, the nitty-gritty information.
+
+First, you need a mad_decoder struct. This holds all information about
+how you want your stream decoded, such as input/output functions, error
+handling functions, etc.
+
+mad_decoder_init() sets this structure up for you.
+
+struct mad_decoder decoder;
+struct my_playbuf playbuf;
+
+mad_decoder_init(&decoder, &playbuf, input_func, header_func, /*filter*/
+0, output_func, /*error*/ 0, /* message */ 0);
+
+In this example, the function called to get more data is set to
+input_func, the function called after MPEG headers have been decoded is
+header_func, the function called after all sound data has been decoded
+to PCM (for output) is output_func, and the filter, error, and message
+functions are unset.
+
+Now, MAD runs in a constant decoding loop. It runs something along the
+following lines:
+
+if I'm out of data
+ call input_func
+if input_func says there's no more data,
+ quit
+decode the header and call header_func
+decode the mpeg audio data
+call the filter function
+call the output function
+loop
+
+Now, this is an oversimplification obviously. The important thing to
+realise is that at every step of the process you can tell MAD what to
+do.
+
+Since all of these functions return enum mad_flow, you can tell MAD to
+do any of the following:
+
+enum mad_flow {
+ MAD_FLOW_CONTINUE = 0x0000, /* Keep decoding this stream */
+ MAD_FLOW_STOP = 0x0010, /* Stop decoding this stream, but exit
+ normally */
+ MAD_FLOW_BREAK = 0x0011, /* Stop decoding this stream, and exit
+ with an error */
+ MAD_FLOW_IGNORE = 0x0020 /* Don't decode this frame,
+ but continue afterwards */
+};
+
+Most of the time you'll probably want to return MAD_FLOW_CONTINUE. In
+every case, you'll have to return one of these values from the functions
+you define.
+
+This is the definition of each of the functions:
+
+enum mad_flow (*input_func)(void *, struct mad_stream *);
+enum mad_flow (*header_func)(void *, struct mad_header const *);
+enum mad_flow (*filter_func)(void *, struct mad_stream const *, struct
+mad_frame *);
+enum mad_flow (*output_func)(void *, struct mad_header const *, struct
+mad_pcm *);
+enum mad_flow (*error_func)(void *, struct mad_stream *, struct
+mad_frame *);
+enum mad_flow (*message_func)(void *, void *, unsigned int *);
+
+In each of these functions the void* pointer passed to the function is
+your "playbuf" structure. This can hold whatever you want - for example,
+song title, length, number of frames - just remember to re-cast it to
+the type you've defined.
+
+input_func takes a mad_stream pointer. Most of the time what you'll want
+to do is something along the lines of the following:
+
+if (more_data_available)
+ buffer = refill_buffer();
+ mad_stream_buffer(stream, buffer, length_of_buffer);
+ return MAD_FLOW_CONTINUE;
+else
+ return MAD_FLOW_STOP;
+
+(On many systems you'll want to use mmap() for this.)
+
+header_func takes a mad_header pointer. This contains most of the
+important information about a given frame; in constant bitrate files, it
+can contain most of the important information about the stream. It will
+give you the length of that frame, using mad_timer_t; the audio layer;
+extension; bitrate... the list is long. Read frame.h or mad.h in the
+frame.h area for more information.
+Again, return MAD_FLOW_{CONTINUE,STOP,BREAK} depending on outside
+conditions.
+
+The only other function I have firsthand information on is output_func;
+in this case, you are given a pointer to struct mad_pcm. This gives you
+the sampling rate, number of channels, and number of samples per
+channel; doing something like the following should work:
+
+mad_fixed_t *left_channel = pcm->samples[0], *right_channel =
+pcm->samples[1];
+int nsamples = pcm->length;
+signed int sample;
+unsigned char * buffer = some_buffer;
+unsigned char * ptr = buffer;
+
+while (nsamples--)
+{
+ sample = (signed int) do_downsample(*left_ch++)
+
+ *ptr++ = (unsigned char) (sample >> 0);
+ *ptr++ = (unsigned char) (sample >> 8);
+
+ sample = (signed int) do_downsample(*right_ch++)
+
+ *ptr++ = (unsigned char) (sample >> 0);
+ *ptr++ = (unsigned char) (sample >> 8);
+}
+
+output buffer to device.
+
+Be sure to handle the big-endian case (autoconf can test for this), and
+also the mono (1 channel) case. See mad.c in mpg321, at the end of the
+file, for an example.
+
+Information on the other (error, filter, message) functions would be
+appreciated, though I think in knowing this information anyone should be
+able to puzzle it out.
+
+Now that the decoder is set up with all these callback functions, you
+call
+
+mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
+
+and then
+
+mad_decoder_finish(&decoder);
+
+Once you've called mad_decoder_finish, you can re-use the decoder
+struct, if you're, for example, within a playlist. Incidentally, all MAD
+structures have similar mad_(whatever)_init and mad_(whatever)_finish
+functions.
+
+I hope this helps people get their feet wet with MAD. Read the source,
+and particularly mad.h - there are a lot of things there you might not
+expect. Rob has done a good job in making MAD a complete solution. :)
+
+--
+Joe Drew <hoserhead@woot.net> <drew@debian.org>
+
+Please encrypt email sent to me.
--- /dev/null
+From - Mon Nov 5 09:19:09 2001
+Return-Path: <mad-dev-admin@lists.mars.org>
+Received: from smtp01.wxs.nl ([195.121.5.15]) by po05.wxs.nl
+ (Netscape Messaging Server 4.15) with ESMTP id GLLMFJ00.3DF for
+ <jpsaman@wxs.nl>; Mon, 22 Oct 2001 10:33:19 +0200
+Received: from surveyor.mars.org ([216.98.134.66]) by
+ smtp01.wxs.nl (Netscape Messaging Server 4.15) with ESMTP id
+ GLLMFZ00.C2Z for <jpsaman@wxs.nl>; Mon, 22 Oct 2001 10:33:35 +0200
+Received: from surveyor.mars.org (localhost [127.0.0.1])
+ by surveyor.mars.org (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id BAA07654;
+ Mon, 22 Oct 2001 01:32:07 -0700
+Received: from mars.org (localhost [127.0.0.1])
+ by surveyor.mars.org (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id BAA07629
+ for <mad-dev@lists.mars.org>; Mon, 22 Oct 2001 01:31:30 -0700
+Message-Id: <200110220831.BAA07629@surveyor.mars.org>
+X-Authentication-Warning: surveyor.mars.org: Host localhost [127.0.0.1] claimed to be mars.org
+From: Rob Leslie <rob@mars.org>
+To: mad-dev@lists.mars.org
+Subject: Re: [mad-dev] Some information about programming with MAD (in synchronous mode)
+In-reply-to: Your message of "21 Oct 2001 16:13:19 EDT."
+ <1003695199.24019.56.camel@pisces>
+Mime-Version: 1.0 (generated by tm-edit 7.106)
+Content-Type: text/plain; charset=US-ASCII
+Sender: mad-dev-admin@lists.mars.org
+Errors-To: mad-dev-admin@lists.mars.org
+X-BeenThere: mad-dev@lists.mars.org
+X-Mailman-Version: 2.0.1
+Precedence: bulk
+List-Help: <mailto:mad-dev-request@lists.mars.org?subject=help>
+List-Post: <mailto:mad-dev@lists.mars.org>
+List-Subscribe: <http://www.mars.org/bin/mailman/listinfo/mad-dev>,
+ <mailto:mad-dev-request@lists.mars.org?subject=subscribe>
+List-Id: MAD developer's mailing list <mad-dev.lists.mars.org>
+List-Unsubscribe: <http://www.mars.org/bin/mailman/listinfo/mad-dev>,
+ <mailto:mad-dev-request@lists.mars.org?subject=unsubscribe>
+List-Archive: <http://www.mars.org/mailman/public/mad-dev/>
+Date: Mon, 22 Oct 2001 01:31:30 -0700
+X-Mozilla-Status: 8011
+X-Mozilla-Status2: 00000000
+X-UIDL: 1879-1001307689
+
+Joe Drew wrote some good info on the MAD high-level API that I hope will be
+helpful to others.
+
+By way of clarification, MAD also has a low-level API which does not use
+callbacks. You can control the entire decoding process yourself more or less
+as follows:
+
+ /* load buffer with your MPEG audio data */
+
+ mad_stream_buffer(&stream, buffer, buflen);
+
+ while (1) {
+ mad_frame_decode(&frame, &stream);
+ mad_synth_frame(&synth, &frame);
+
+ /* output PCM samples in synth.pcm */
+ }
+
+This is vastly simplified, but it shows the general idea. mad_frame_decode()
+decodes the next frame's header and subband samples. mad_synth_frame() takes
+those subband samples and synthesizes PCM samples.
+
+It is also possible to call mad_header_decode() before mad_frame_decode().
+This just gives you the frame's header info, in case that's all you want, or
+perhaps to help you decide whether you want to decode the rest of the frame.
+
+As Joe mentions, each of the stream, frame, and synth structs needs to be
+initialized and "finished" before and after use:
+
+ struct mad_stream stream;
+ struct mad_frame frame;
+ struct mad_synth synth;
+
+ mad_stream_init(&stream);
+ mad_frame_init(&frame);
+ mad_synth_init(&synth);
+
+ /* ... */
+
+ mad_synth_finish(&synth);
+ mad_frame_finish(&frame);
+ mad_stream_finish(&stream);
+
+You can work with just a struct mad_header instead of a struct mad_frame if
+you only want to decode frame headers.
+
+Joe writes:
+> MAD always outputs 32-bit (well, mad_fixed_t) little-endian data. Take
+> this into account when outputting samples to the sound card.
+
+This isn't quite right: the mad_fixed_t type is not necessarily little-endian.
+It's the same endianness as the native integer types. Also, it's only
+guaranteed to be *at least* 32 bits wide.
+
+The fixed-point sample format is important to understand, and I recommend
+reading the comments in libmad/fixed.h. The thing to remember when converting
+MAD's fixed-point integer samples to 16-bit PCM (or whatever) is that MAD
+encodes samples as numbers in the full-scale range [-1.0, +1.0) where the
+binary point is placed 28 (MAD_F_FRACBITS) bits to the left of the integer.
+However, you need to be prepared to handle clipping as some numbers may be
+less than -1.0 (-MAD_F_ONE) or greater than or equal to +1.0 (MAD_F_ONE, aka
+1 << MAD_F_FRACBITS).
+
+> Information on the other (error, filter, message) functions would be
+> appreciated, though I think in knowing this information anyone should be
+> able to puzzle it out.
+
+In the high-level API, the error callback function is called whenever a
+decoding error occurs. The error number is in stream->error.
+
+The filter callback function is called after decoding a frame, but before
+synthesis. Here it is possible to modify the frame's subband samples, for
+example to perform a uniform attenuation/amplification, or to do other special
+processing in the frequency domain.
+
+The message callback function is only used with MAD_DECODER_MODE_ASYNC, and is
+called whenever the parent process sends a message via mad_decoder_message().
+This callback can generate a reply by overwriting the message buffer that is
+passed to it. (The size of the reply must be the same or smaller than the
+message.)
+
+Cheers,
+ -rob
* audio_output.h : audio output thread interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: audio_output.h,v 1.50 2002/07/31 20:56:50 sam Exp $
+ * $Id: audio_output.h,v 1.51 2002/08/04 17:23:41 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
#define AOUT_FMT_S8 0x00000040
#define AOUT_FMT_U16_LE 0x00000080 /* Little endian U16 */
#define AOUT_FMT_U16_BE 0x00000100 /* Big endian U16 */
-#define AOUT_FMT_AC3 0x00000400 /* Dolby Digital AC3 */
+#define AOUT_FMT_A52 0x00000400 /* Dolby Digital A52 */
#ifdef WORDS_BIGENDIAN
#define AOUT_FMT_S16_NE AOUT_FMT_S16_BE
#define AOUT_FMT_S16_NE AOUT_FMT_S16_LE
#endif
-/* Number of samples in an AC3 frame */
-#define AC3_FRAME_SIZE 1536
+/* Number of samples in an A52 frame */
+#define A52_FRAME_SIZE 1536
/* Size of a frame for spdif output */
#define SPDIF_FRAME_SIZE 6144
* input_ext-dec.h: structures exported to the VideoLAN decoders
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: input_ext-dec.h,v 1.65 2002/07/31 20:56:50 sam Exp $
+ * $Id: input_ext-dec.h,v 1.66 2002/08/04 17:23:41 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Kaempf <maxx@via.ecp.fr>
#define MPEG2_VIDEO_ES 0x02
#define MPEG1_AUDIO_ES 0x03
#define MPEG2_AUDIO_ES 0x04
-#define AC3_AUDIO_ES 0x81
+#define A52_AUDIO_ES 0x81
/* These ones might violate the norm : */
#define DVD_SPU_ES 0x82
#define LPCM_AUDIO_ES 0x83
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.73 2002/07/31 20:56:50 sam Exp $
+ * $Id: input_ext-intf.h,v 1.74 2002/08/04 17:23:41 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
*/
/* FIXME ! */
#define REQUESTED_MPEG 1
-#define REQUESTED_AC3 2
+#define REQUESTED_A52 2
#define REQUESTED_LPCM 3
#define REQUESTED_NOAUDIO 255
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+file_SOURCES = file.c
+udp_SOURCES = udp.c
+http_SOURCES = http.c
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+dvd_SOURCES = dvd.c access.c demux.c seek.c es.c ifo.c udf.c summary.c
--- /dev/null
+/* access.c: DVD access plugin.
+ *****************************************************************************
+ * This plugins should handle all the known specificities of the DVD format,
+ * especially the 2048 bytes logical block size.
+ * It depends on:
+ * -libdvdcss for access and unscrambling
+ * -ifo.* for ifo parsing and analyse
+ * -udf.* to find files
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: access.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#ifdef GOD_DAMN_DMCA
+# include "dvdcss.h"
+#else
+# include <dvdcss/dvdcss.h>
+#endif
+
+#include "dvd.h"
+#include "es.h"
+#include "seek.h"
+#include "ifo.h"
+#include "summary.h"
+#include "iso_lang.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+/* called from outside */
+static int DVDSetArea ( input_thread_t *, input_area_t * );
+static int DVDSetProgram ( input_thread_t *, pgrm_descriptor_t * );
+static ssize_t DVDRead ( input_thread_t *, byte_t *, size_t );
+static void DVDSeek ( input_thread_t *, off_t );
+
+static char * DVDParse( input_thread_t * );
+
+/*
+ * Data access functions
+ */
+
+#define DVDTell LB2OFF( p_dvd->i_vts_start + p_dvd->i_vts_lb ) \
+ - p_input->stream.p_selected_area->i_start
+
+/*****************************************************************************
+ * DVDOpen: open dvd
+ *****************************************************************************/
+int E_(DVDOpen) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ char * psz_device;
+ thread_dvd_data_t * p_dvd;
+ input_area_t * p_area;
+ int i;
+ char * psz_dvdcss_env;
+
+ p_dvd = malloc( sizeof(thread_dvd_data_t) );
+ if( p_dvd == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ return -1;
+ }
+ p_input->p_access_data = (void *)p_dvd;
+
+ p_input->pf_read = DVDRead;
+ p_input->pf_seek = DVDSeek;
+ p_input->pf_set_area = DVDSetArea;
+ p_input->pf_set_program = DVDSetProgram;
+
+ /* Parse command line */
+ if( !( psz_device = DVDParse( p_input ) ) )
+ {
+ free( p_dvd );
+ return -1;
+ }
+
+ /*
+ * set up input
+ */
+ p_input->i_mtu = 0;
+
+ /* override environment variable DVDCSS_METHOD with config option
+ * (FIXME: this creates a small memory leak) */
+ psz_dvdcss_env = config_GetPsz( p_input, "dvd-css-method" );
+ if( psz_dvdcss_env && *psz_dvdcss_env )
+ {
+ char *psz_env;
+
+ psz_env = malloc( strlen("DVDCSS_METHOD=") +
+ strlen( psz_dvdcss_env ) + 1 );
+
+ if( !psz_env )
+ {
+ free( p_dvd );
+ return -1;
+ }
+
+ sprintf( psz_env, "%s%s", "DVDCSS_METHOD=", psz_dvdcss_env );
+
+ putenv( psz_env );
+ }
+ if( psz_dvdcss_env ) free( psz_dvdcss_env );
+
+ /*
+ * get plugin ready
+ */
+ p_dvd->dvdhandle = dvdcss_open( psz_device );
+
+ /* free allocated string */
+ free( psz_device );
+
+ if( p_dvd->dvdhandle == NULL )
+ {
+ msg_Err( p_input, "dvdcss cannot open device" );
+ free( p_dvd );
+ return -1;
+ }
+
+ if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 )
+ {
+ msg_Err( p_input, "%s", dvdcss_error( p_dvd->dvdhandle ) );
+ dvdcss_close( p_dvd->dvdhandle );
+ free( p_dvd );
+ return -1;
+ }
+
+ /* Ifo allocation & initialisation */
+ if( IfoCreate( p_dvd ) < 0 )
+ {
+ msg_Err( p_input, "allcation error in ifo" );
+ dvdcss_close( p_dvd->dvdhandle );
+ free( p_dvd );
+ return -1;
+ }
+
+ if( IfoInit( p_dvd->p_ifo ) < 0 )
+ {
+ msg_Err( p_input, "fatal failure in ifo" );
+ IfoDestroy( p_dvd->p_ifo );
+ dvdcss_close( p_dvd->dvdhandle );
+ free( p_dvd );
+ return -1;
+ }
+
+ /* Set stream and area data */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.i_method = INPUT_METHOD_DVD;
+ p_input->stream.b_pace_control = 1;
+ p_input->stream.b_seekable = 1;
+ p_input->stream.p_selected_area->i_size = 0;
+ p_input->stream.p_selected_area->i_tell = 0;
+
+ /* Initialize ES structures */
+ input_InitStream( p_input, sizeof( stream_ps_data_t ) );
+
+#define title_inf p_dvd->p_ifo->vmg.title_inf
+ msg_Dbg( p_input, "number of titles: %d", title_inf.i_title_nb );
+
+#define area p_input->stream.pp_areas
+ /* We start from 1 here since the default area 0
+ * is reserved for video_ts.vob */
+ for( i = 1 ; i <= title_inf.i_title_nb ; i++ )
+ {
+ input_AddArea( p_input );
+
+ /* Titles are Program Chains */
+ area[i]->i_id = i;
+
+ /* Absolute start offset and size
+ * We can only set that with vts ifo, so we do it during the
+ * first call to DVDSetArea */
+ area[i]->i_start = 0;
+ area[i]->i_size = 0;
+
+ /* Number of chapters */
+ area[i]->i_part_nb = title_inf.p_attr[i-1].i_chapter_nb;
+ area[i]->i_part = 1;
+
+ /* Offset to vts_i_0.ifo */
+ area[i]->i_plugin_data = p_dvd->p_ifo->i_start +
+ title_inf.p_attr[i-1].i_start_sector;
+ }
+#undef area
+
+ p_dvd->i_title = p_dvd->i_title <= title_inf.i_title_nb ?
+ p_dvd->i_title : 1;
+#undef title_inf
+
+ p_area = p_input->stream.pp_areas[p_dvd->i_title];
+
+ p_area->i_part = p_dvd->i_chapter <= p_area->i_part_nb ?
+ p_dvd->i_chapter : 1;
+ p_dvd->i_chapter = 1;
+
+ p_dvd->b_new_chapter = 0;
+ p_dvd->i_audio_nb = 0;
+ p_dvd->i_spu_nb = 0;
+
+ /* set title, chapter, audio and subpic */
+ if( DVDSetArea( p_input, p_area ) < 0 )
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ IfoDestroy( p_dvd->p_ifo );
+ dvdcss_close( p_dvd->dvdhandle );
+ free( p_dvd );
+ return -1;
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_input->psz_demux = "dvdold";
+
+ return 0;
+}
+
+/*****************************************************************************
+ * DVDClose: close dvd
+ *****************************************************************************/
+void E_(DVDClose) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ thread_dvd_data_t *p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
+
+ IfoDestroy( p_dvd->p_ifo );
+ dvdcss_close( p_dvd->dvdhandle );
+ free( p_dvd );
+}
+
+/*****************************************************************************
+ * DVDSetProgram: used to change angle
+ *****************************************************************************/
+static int DVDSetProgram( input_thread_t * p_input,
+ pgrm_descriptor_t * p_program )
+{
+ if( p_input->stream.p_selected_program != p_program )
+ {
+ thread_dvd_data_t * p_dvd;
+ int i_angle;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+ i_angle = p_program->i_number;
+
+ /* DVD is actually mono-program: we only need the current angle
+ * number, so copy the data between programs */
+ memcpy( p_program,
+ p_input->stream.p_selected_program,
+ sizeof(pgrm_descriptor_t) );
+ p_program->i_number = i_angle;
+ p_input->stream.p_selected_program = p_program;
+
+#define title \
+ p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
+ if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
+ {
+ if( ( p_program->i_number - p_dvd->i_angle ) < 0 )
+ {
+ /* we have to go backwards */
+ p_dvd->i_map_cell = 0;
+ }
+ p_dvd->i_prg_cell += ( p_program->i_number - p_dvd->i_angle );
+ p_dvd->i_map_cell = CellPrg2Map( p_dvd );
+ p_dvd->i_map_cell += p_dvd->i_angle_cell;
+ p_dvd->i_vts_lb = CellFirstSector( p_dvd );
+ p_dvd->i_last_lb = CellLastSector( p_dvd );
+ p_dvd->i_angle = p_program->i_number;
+ }
+ else
+ {
+ p_dvd->i_angle = p_program->i_number;
+ }
+#undef title
+ msg_Dbg( p_input, "angle %d selected", p_dvd->i_angle );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * DVDSetArea: initialize input data for title x, chapter y.
+ * It should be called for each user navigation request.
+ *****************************************************************************
+ * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
+ * Note that you have to take the lock before entering here.
+ *****************************************************************************/
+#define vmg p_dvd->p_ifo->vmg
+#define vts p_dvd->p_ifo->vts
+
+static void DVDFlushStream( input_thread_t * p_input )
+{
+ if( p_input->stream.pp_programs != NULL )
+ {
+ /* We don't use input_EndStream here since
+ * we keep area structures */
+ while( p_input->stream.i_es_number )
+ {
+ input_DelES( p_input, p_input->stream.pp_es[0] );
+ }
+
+ while( p_input->stream.i_pgrm_number )
+ {
+ input_DelProgram( p_input, p_input->stream.pp_programs[0] );
+ }
+
+ if( p_input->stream.pp_selected_es )
+ {
+ free( p_input->stream.pp_selected_es );
+ p_input->stream.pp_selected_es = NULL;
+ }
+ p_input->stream.i_selected_es_number = 0;
+ }
+
+ return;
+}
+
+static int DVDReadAngle( input_thread_t * p_input )
+{
+ thread_dvd_data_t * p_dvd;
+ int i_angle_nb;
+ int i;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+ i_angle_nb = vmg.title_inf.p_attr[p_dvd->i_title-1].i_angle_nb;
+
+ input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+
+ for( i = 1 ; i < i_angle_nb ; i++ )
+ {
+ input_AddProgram( p_input, i+1, 0 );
+ }
+
+ return i_angle_nb;
+}
+
+static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
+{
+ thread_dvd_data_t * p_dvd;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+
+ /* we can't use the interface slider until initilization is complete */
+ p_input->stream.b_seekable = 0;
+
+ if( p_area != p_input->stream.p_selected_area )
+ {
+ int i_vts_title;
+ u32 i_first;
+ u32 i_last;
+
+ /* Reset the Chapter position of the old title */
+ p_input->stream.p_selected_area->i_part = 1;
+ p_input->stream.p_selected_area = p_area;
+
+ /*
+ * We have to load all title information
+ */
+
+ /* title number as it appears in the interface list */
+ p_dvd->i_title = p_area->i_id;
+ p_dvd->i_chapter_nb = p_area->i_part_nb;
+
+ if( IfoTitleSet( p_dvd->p_ifo, p_dvd->i_title ) < 0 )
+ {
+ msg_Err( p_input, "fatal error in vts ifo" );
+ free( p_dvd );
+ return -1;
+ }
+
+ /* title position inside the selected vts */
+ i_vts_title = vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;
+ p_dvd->i_title_id =
+ vts.title_inf.p_title_start[i_vts_title-1].i_title_id;
+
+ msg_Dbg( p_input, "title %d vts_title %d pgc %d",
+ p_dvd->i_title, i_vts_title, p_dvd->i_title_id );
+
+ /* title set offset XXX: convert to block values */
+ p_dvd->i_vts_start =
+ vts.i_pos + vts.manager_inf.i_title_vob_start_sector;
+
+ /* last cell */
+ p_dvd->i_prg_cell = -1 +
+ vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb;
+ p_dvd->i_map_cell = 0;
+ p_dvd->i_map_cell = CellPrg2Map( p_dvd );
+ i_last = CellLastSector( p_dvd );
+
+ /* first cell */
+ p_dvd->i_prg_cell = 0;
+ p_dvd->i_map_cell = 0;
+ p_dvd->i_angle_cell = 0;
+ p_dvd->i_map_cell = CellPrg2Map ( p_dvd );
+ p_dvd->i_vts_lb = CellFirstSector( p_dvd );
+ p_dvd->i_last_lb = CellLastSector ( p_dvd );
+
+ /* Force libdvdcss to check its title key.
+ * It is only useful for title cracking method. Methods using the
+ * decrypted disc key are fast enough to check the key at each seek */
+ i_first = dvdcss_seek( p_dvd->dvdhandle,
+ p_dvd->i_vts_start + p_dvd->i_vts_lb,
+ DVDCSS_SEEK_KEY );
+ if( i_first < 0 )
+ {
+ msg_Err( p_input, "%s", dvdcss_error( p_dvd->dvdhandle ) );
+ return -1;
+ }
+
+ /* Area definition */
+ p_input->stream.p_selected_area->i_start = LB2OFF( i_first );
+ p_input->stream.p_selected_area->i_size =
+ LB2OFF( i_last + 1 - p_dvd->i_vts_lb );
+
+ /* Destroy obsolete ES by reinitializing programs */
+ DVDFlushStream( p_input );
+
+ /* Angle management: angles are handled through programs */
+ p_dvd->i_angle_nb = DVDReadAngle( p_input );
+ if( ( p_dvd->i_angle <= 0 ) || p_dvd->i_angle > p_dvd->i_angle_nb )
+ {
+ p_dvd->i_angle = 1;
+ }
+
+ DVDSetProgram( p_input,
+ p_input->stream.pp_programs[p_dvd->i_angle-1] );
+
+ msg_Dbg( p_input, "title first %i, last %i, size %i",
+ i_first, i_last, i_last + 1 - p_dvd->i_vts_lb );
+ IfoPrintTitle( p_dvd );
+
+ /* No PSM to read in DVD mode, we already have all information */
+ p_input->stream.p_selected_program->b_is_ok = 1;
+
+ /* Find all ES in title with ifo data */
+ DVDReadVideo( p_input );
+ DVDReadAudio( p_input );
+ DVDReadSPU ( p_input );
+
+ if( p_input->p_demux )
+ {
+ DVDLaunchDecoders( p_input );
+ }
+
+ } /* i_title >= 0 */
+ else
+ {
+ p_area = p_input->stream.p_selected_area;
+ }
+
+ /* Chapter selection */
+ p_dvd->i_chapter = DVDSetChapter( p_dvd, p_area->i_part );
+
+ p_input->stream.p_selected_area->i_tell = DVDTell;
+
+ /* warn interface that something has changed */
+ p_input->stream.b_seekable = 1;
+ p_input->stream.b_changed = 1;
+
+ return 0;
+}
+#undef vts
+#undef vmg
+
+#define title \
+ p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
+
+/*****************************************************************************
+ * DVDRead: reads data packets.
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
+ * bytes.
+ *****************************************************************************/
+static ssize_t DVDRead( input_thread_t * p_input,
+ byte_t * p_buffer, size_t i_count )
+{
+ thread_dvd_data_t * p_dvd;
+ int i_read;
+ int i_blocks;
+ int i_block_once = 0;
+
+ p_dvd = (thread_dvd_data_t *)(p_input->p_access_data);
+
+ i_read = 0;
+ i_blocks = OFF2LB(i_count);
+
+ while( i_blocks )
+ {
+ i_block_once = LbMaxOnce( p_dvd );
+ if( i_block_once > i_blocks )
+ {
+ i_block_once = i_blocks;
+ }
+ else if( i_block_once <= 0 )
+ {
+ /* EOT */
+ break;
+ }
+
+ if( i_block_once != dvdcss_read( p_dvd->dvdhandle, p_buffer,
+ i_block_once, DVDCSS_READ_DECRYPT ) )
+ {
+ return -1;
+ }
+
+ i_blocks -= i_block_once;
+ i_read += i_block_once;
+ p_buffer += LB2OFF( i_block_once );
+
+ /* Update global position */
+ p_dvd->i_vts_lb += i_block_once;
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.p_selected_area->i_tell += LB2OFF( i_read );
+ if( p_dvd->b_new_chapter )
+ {
+ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
+ p_dvd->b_new_chapter = 0;
+ }
+
+ if( ( p_input->stream.p_selected_area->i_tell
+ >= p_input->stream.p_selected_area->i_size )
+ || ( i_block_once <= 0 ) )
+ {
+ if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb )
+ {
+ /* EOF */
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ return 0;
+ }
+
+ /* EOT */
+ msg_Dbg( p_input, "new title" );
+ p_dvd->i_title++;
+ DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] );
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return LB2OFF( i_read );
+}
+
+/*****************************************************************************
+ * DVDSeek : Goes to a given position on the stream.
+ *****************************************************************************
+ * This one is used by the input and translate chronological position from
+ * input to logical position on the device.
+ * The lock should be taken before calling this function.
+ *****************************************************************************/
+static void DVDSeek( input_thread_t * p_input, off_t i_off )
+{
+ thread_dvd_data_t * p_dvd;
+
+ p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data);
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_dvd->i_vts_lb = OFF2LB(i_off + p_input->stream.p_selected_area->i_start)
+ - p_dvd->i_vts_start;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_dvd->i_prg_cell = Lb2CellPrg( p_dvd );
+ p_dvd->i_map_cell = Lb2CellMap( p_dvd );
+
+ if( CellIsInterleaved( p_dvd ) )
+ {
+ /* if we're inside a multi-angle zone, we have to choose i_sector
+ * in the current angle ; we can't do it all the time since cells
+ * can be very wide out of such zones */
+ p_dvd->i_vts_lb = CellFirstSector( p_dvd );
+ }
+
+ p_dvd->i_last_lb = CellLastSector( p_dvd );
+ p_dvd->i_chapter = CellPrg2Chapter( p_dvd );
+
+ if( dvdcss_seek( p_dvd->dvdhandle, p_dvd->i_vts_start + p_dvd->i_vts_lb,
+ DVDCSS_SEEK_MPEG ) < 0 )
+ {
+ msg_Err( p_input, "%s", dvdcss_error( p_dvd->dvdhandle ) );
+ p_input->b_error = 1;
+ return;
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
+ p_input->stream.p_selected_area->i_tell = DVDTell;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ msg_Dbg( p_input, "program cell: %d cell: %d chapter: %d tell %lld",
+ p_dvd->i_prg_cell, p_dvd->i_map_cell, p_dvd->i_chapter, DVDTell );
+
+ return;
+}
+
+/*****************************************************************************
+ * DVDParse: parse command line
+ *****************************************************************************/
+static char * DVDParse( input_thread_t * p_input )
+{
+ thread_dvd_data_t * p_dvd;
+ struct stat stat_info;
+ char * psz_parser;
+ char * psz_device;
+ char * psz_raw;
+ char * psz_next;
+ vlc_bool_t b_options = 0;
+ int i_title = 1;
+ int i_chapter = 1;
+ int i_angle = 1;
+ int i;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+
+#ifdef WIN32
+ /* On Win32 we want the DVD access plugin to be explicitly requested,
+ * we end up with lots of problems otherwise */
+ if( !p_input->psz_access || !*p_input->psz_access ) return NULL;
+#endif
+
+ psz_parser = psz_device = strdup( p_input->psz_name );
+ if( !psz_parser )
+ {
+ return NULL;
+ }
+
+ /* Parse input string :
+ * [device][@rawdevice][@[title][,[chapter][,angle]]] */
+ while( *psz_parser && *psz_parser != '@' )
+ {
+ psz_parser++;
+ }
+
+ if( *psz_parser == '@' )
+ {
+ /* Maybe found raw device or option list */
+ *psz_parser = '\0';
+ psz_raw = ++psz_parser;
+ }
+ else
+ {
+ psz_raw = "";
+ }
+
+ if( *psz_parser && !strtol( psz_parser, NULL, 10 ) )
+ {
+ /* what we've found is either a raw device or a partial option
+ * list e.g. @,29 or both a device and a list ; search end of string */
+ while( *psz_parser && *psz_parser != '@' )
+ {
+ psz_parser++;
+ }
+
+ if( *psz_parser == '@' )
+ {
+ /* found end of raw device, and beginning of options */
+ *psz_parser = '\0';
+ ++psz_parser;
+ b_options = 1;
+ }
+ else
+ {
+ psz_parser = psz_raw + 1;
+ for( i=0 ; i<3 ; i++ )
+ {
+ if( !*psz_parser )
+ {
+ /* we have only a raw device */
+ break;
+ }
+ if( strtol( psz_parser, NULL, 10 ) )
+ {
+ /* we have only a partial list of options, no device */
+ psz_parser = psz_raw;
+ psz_raw = "";
+ b_options = 1;
+ break;
+ }
+ psz_parser++;
+ }
+ }
+ }
+ else
+ {
+ /* found beginning of options ; no raw device specified */
+ psz_raw = "";
+ b_options = 1;
+ }
+
+ if( b_options )
+ {
+ /* Found options */
+ i_title = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ psz_parser = psz_next + 1;
+ i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ i_angle = (int)strtol( psz_next + 1, NULL, 10 );
+ }
+ }
+
+ p_dvd->i_title = i_title ? i_title : 1;
+ p_dvd->i_chapter = i_chapter ? i_chapter : 1;
+ p_dvd->i_angle = i_angle ? i_angle : 1;
+ }
+
+ if( *psz_raw )
+ {
+ if( *psz_raw )
+ {
+ /* check the raw device */
+ if( stat( psz_raw, &stat_info ) == -1 )
+ {
+ msg_Warn( p_input, "cannot stat() raw device `%s' (%s)",
+ psz_raw, strerror(errno));
+ /* put back '@' */
+ *(psz_raw - 1) = '@';
+ psz_raw = "";
+ }
+ else
+ {
+ char * psz_env;
+
+#ifndef WIN32
+ if( !S_ISCHR(stat_info.st_mode) )
+ {
+ msg_Warn( p_input, "raw device %s is"
+ " not a valid char device", psz_raw );
+ /* put back '@' */
+ *(psz_raw - 1) = '@';
+ psz_raw = "";
+ }
+ else
+#endif
+ {
+ psz_env = malloc( strlen("DVDCSS_RAW_DEVICE=")
+ + strlen( psz_raw ) + 1 );
+ sprintf( psz_env, "DVDCSS_RAW_DEVICE=%s", psz_raw );
+ putenv( psz_env );
+ }
+ }
+ }
+ else
+ {
+ psz_raw = "";
+ }
+ }
+
+ if( !*psz_device )
+ {
+ free( psz_device );
+
+ if( !p_input->psz_access )
+ {
+ /* no device and no access specified: we probably don't want DVD */
+ return NULL;
+ }
+ psz_device = config_GetPsz( p_input, "dvd" );
+ }
+
+#ifndef WIN32
+ /* check block device */
+ if( stat( psz_device, &stat_info ) == -1 )
+ {
+ msg_Err( p_input, "cannot stat() device `%s' (%s)",
+ psz_device, strerror(errno));
+ free( psz_device );
+ return NULL;
+ }
+
+ if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode) )
+ {
+ msg_Warn( p_input,
+ "dvd module discarded (not a valid block device)" );
+ free( psz_device );
+ return NULL;
+ }
+#endif
+
+ msg_Dbg( p_input, "dvd=%s raw=%s title=%d chapter=%d angle=%d",
+ psz_device, psz_raw, p_dvd->i_title,
+ p_dvd->i_chapter, p_dvd->i_angle );
+
+ return psz_device;
+}
--- /dev/null
+/* demux.c: DVD demux functions.
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: demux.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+/* how many packets DVDDemux will read in each loop */
+#define DVD_READ_ONCE 64
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int DVDDemux ( input_thread_t * );
+
+void DVDLaunchDecoders( input_thread_t * );
+
+/*
+ * Data demux functions
+ */
+
+/*****************************************************************************
+ * DVDInit: initializes DVD structures
+ *****************************************************************************/
+int E_(DVDInit) ( vlc_object_t *p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+
+ if( p_input->stream.i_method != INPUT_METHOD_DVD )
+ {
+ return -1;
+ }
+
+ p_input->pf_demux = DVDDemux;
+ p_input->pf_rewind = NULL;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ DVDLaunchDecoders( p_input );
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * DVDDemux
+ *****************************************************************************/
+static int DVDDemux( input_thread_t * p_input )
+{
+ data_packet_t * p_data;
+ ssize_t i_result;
+ int i;
+
+ /* Read headers to compute payload length */
+ for( i = 0 ; i < DVD_READ_ONCE ; i++ )
+ {
+ i_result = input_ReadPS( p_input, &p_data );
+
+ if( i_result < 0 )
+ {
+ return i_result;
+ }
+ else if( i_result == 0 )
+ {
+ return i;
+ }
+
+ input_DemuxPS( p_input, p_data );
+ }
+
+ return i;
+}
--- /dev/null
+/*****************************************************************************
+ * dvd.c : DVD input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: dvd.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+
+#include <vlc/vlc.h>
+
+#ifdef GOD_DAMN_DMCA
+# include <stdio.h>
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/uio.h> /* struct iovec */
+# include <sys/ioctl.h>
+# include <dlfcn.h>
+# include <netinet/in.h>
+# include <linux/cdrom.h>
+
+# include "dvdcss.h"
+#endif
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+int E_(DVDOpen) ( vlc_object_t * );
+void E_(DVDClose) ( vlc_object_t * );
+
+int E_(DVDInit) ( vlc_object_t * );
+
+#ifdef GOD_DAMN_DMCA
+static void *p_libdvdcss;
+static void ProbeLibDVDCSS ( void );
+static void UnprobeLibDVDCSS( void );
+#endif
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define CSSMETHOD_TEXT N_("Method to use by libdvdcss for key decryption")
+#define CSSMETHOD_LONGTEXT N_( \
+ "title: decrypted title key is guessed from the encrypted sectors of " \
+ "the stream. Thus it should work with a file as well as the " \
+ "DVD device. But it sometimes takes much time to decrypt a title " \
+ "key and may even fail. With this method, the key is only checked "\
+ "at the beginning of each title, so it won't work if the key " \
+ "changes in the middle of a title.\n" \
+ "disc: the disc key is first cracked, then all title keys can be " \
+ "decrypted instantly, which allows us to check them often.\n" \
+ "key: the same as \"disc\" if you don't have a file with player keys " \
+ "at compilation time. If you do, the decryption of the disc key " \
+ "will be faster with this method. It is the one that was used by " \
+ "libcss.\n" \
+ "The default method is: key.")
+
+static char *cssmethod_list[] = { "title", "disc", "key", NULL };
+
+vlc_module_begin();
+ int i;
+ add_category_hint( N_("[dvd:][device][@raw_device][@[title][,[chapter][,angle]]]"), NULL );
+ add_string_from_list( "dvd-css-method", NULL, cssmethod_list, NULL,
+ CSSMETHOD_TEXT, CSSMETHOD_LONGTEXT );
+#ifdef GOD_DAMN_DMCA
+ set_description( _("DVD input module, uses libdvdcss if installed") );
+ i = 90;
+#else
+ set_description( _("DVD input module, uses libdvdcss") );
+ i = 100;
+#endif
+ add_shortcut( "dvdold" );
+ add_submodule();
+ set_capability( "access", i );
+ set_callbacks( E_(DVDOpen), E_(DVDClose) );
+ add_submodule();
+ set_capability( "demux", 0 );
+ set_callbacks( E_(DVDInit), NULL );
+#ifdef GOD_DAMN_DMCA
+ ProbeLibDVDCSS();
+#endif
+vlc_module_end();
+
+#if 0 /* FIXME */
+ UnprobeLibDVDCSS();
+#endif
+
+/* Following functions are local */
+
+#ifdef GOD_DAMN_DMCA
+/*****************************************************************************
+ * ProbeLibDVDCSS: look for a libdvdcss object.
+ *****************************************************************************
+ * This functions looks for libdvdcss, using dlopen(), and fills function
+ * pointers with what it finds. On failure, uses the dummy libdvdcss
+ * replacement provided by vlc.
+ *****************************************************************************/
+static void ProbeLibDVDCSS( void )
+{
+ static char *pp_filelist[] = { "libdvdcss.so.2",
+ "./libdvdcss.so.2",
+ "./lib/libdvdcss.so.2",
+ "libdvdcss.so.1",
+ "./libdvdcss.so.1",
+ "./lib/libdvdcss.so.1",
+ NULL };
+ char **pp_file = pp_filelist;
+
+ /* Try to open the dynamic object */
+ do
+ {
+ p_libdvdcss = dlopen( *pp_file, RTLD_LAZY );
+ if( p_libdvdcss != NULL )
+ {
+//X intf_WarnMsg( 2, "module: builtin module `dvd' found libdvdcss "
+//X "in `%s'", *pp_file );
+ break;
+ }
+ pp_file++;
+
+ } while( *pp_file != NULL );
+
+ /* If libdvdcss.so was found, check that it's valid */
+ if( p_libdvdcss == NULL )
+ {
+//X intf_ErrMsg( "dvd warning: libdvdcss.so.2 not present" );
+ }
+ else
+ {
+ ____dvdcss_open = dlsym( p_libdvdcss, "dvdcss_open" );
+ ____dvdcss_close = dlsym( p_libdvdcss, "dvdcss_close" );
+ ____dvdcss_title = dlsym( p_libdvdcss, "dvdcss_title" );
+ ____dvdcss_seek = dlsym( p_libdvdcss, "dvdcss_seek" );
+ ____dvdcss_read = dlsym( p_libdvdcss, "dvdcss_read" );
+ ____dvdcss_readv = dlsym( p_libdvdcss, "dvdcss_readv" );
+ ____dvdcss_error = dlsym( p_libdvdcss, "dvdcss_error" );
+
+ if( ____dvdcss_open == NULL || ____dvdcss_close == NULL
+ || ____dvdcss_title == NULL || ____dvdcss_seek == NULL
+ || ____dvdcss_read == NULL || ____dvdcss_readv == NULL
+ || ____dvdcss_error == NULL )
+ {
+//X intf_ErrMsg( "dvd warning: missing symbols in libdvdcss.so.2, "
+//X "this shouldn't happen !" );
+ dlclose( p_libdvdcss );
+ p_libdvdcss = NULL;
+ }
+ }
+
+ /* If libdvdcss was not found or was not valid, use the dummy
+ * replacement functions. */
+ if( p_libdvdcss == NULL )
+ {
+//X intf_ErrMsg( "dvd warning: no valid libdvdcss found, "
+//X "I will only play unencrypted DVDs" );
+//X intf_ErrMsg( "dvd warning: get libdvdcss at "
+//X "http://www.videolan.org/libdvdcss/" );
+
+ ____dvdcss_open = dummy_dvdcss_open;
+ ____dvdcss_close = dummy_dvdcss_close;
+ ____dvdcss_title = dummy_dvdcss_title;
+ ____dvdcss_seek = dummy_dvdcss_seek;
+ ____dvdcss_read = dummy_dvdcss_read;
+ ____dvdcss_readv = dummy_dvdcss_readv;
+ ____dvdcss_error = dummy_dvdcss_error;
+ }
+}
+
+/*****************************************************************************
+ * UnprobeLibDVDCSS: free resources allocated by ProbeLibDVDCSS, if any.
+ *****************************************************************************/
+static void UnprobeLibDVDCSS( void )
+{
+ if( p_libdvdcss != NULL )
+ {
+ dlclose( p_libdvdcss );
+ p_libdvdcss = NULL;
+ }
+}
+
+/* Dummy libdvdcss with minimal DVD access. */
+
+/*****************************************************************************
+ * Local structure
+ *****************************************************************************/
+struct dvdcss_s
+{
+ /* File descriptor */
+ int i_fd;
+};
+
+/*****************************************************************************
+ * dvdcss_open: initialize library, open a DVD device, crack CSS key
+ *****************************************************************************/
+extern dvdcss_handle dummy_dvdcss_open ( char *psz_target )
+{
+ dvdcss_handle dvdcss;
+ dvd_struct dvd;
+
+ /* Allocate the library structure */
+ dvdcss = malloc( sizeof( struct dvdcss_s ) );
+ if( dvdcss == NULL )
+ {
+ fprintf( stderr, "dvd error: "
+ "dummy libdvdcss could not allocate memory\n" );
+ return NULL;
+ }
+
+ /* Open the device */
+ dvdcss->i_fd = open( psz_target, 0 );
+ if( dvdcss->i_fd < 0 )
+ {
+ fprintf( stderr, "dvd error: "
+ "dummy libdvdcss could not open device\n" );
+ free( dvdcss );
+ return NULL;
+ }
+
+ /* Check for encryption or ioctl failure */
+ dvd.type = DVD_STRUCT_COPYRIGHT;
+ dvd.copyright.layer_num = 0;
+ if( ioctl( dvdcss->i_fd, DVD_READ_STRUCT, &dvd ) != 0
+ || dvd.copyright.cpst )
+ {
+ fprintf( stderr, "dvd error: "
+ "dummy libdvdcss could not decrypt disc\n" );
+ close( dvdcss->i_fd );
+ free( dvdcss );
+ return NULL;
+ }
+
+ return dvdcss;
+}
+
+/*****************************************************************************
+ * dvdcss_error: return the last libdvdcss error message
+ *****************************************************************************/
+extern char * dummy_dvdcss_error ( dvdcss_handle dvdcss )
+{
+ return "generic error";
+}
+
+/*****************************************************************************
+ * dvdcss_seek: seek into the device
+ *****************************************************************************/
+extern int dummy_dvdcss_seek ( dvdcss_handle dvdcss, int i_blocks,
+ int i_flags )
+{
+ off_t i_read;
+
+ i_read = lseek( dvdcss->i_fd,
+ (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
+
+ return i_read / DVDCSS_BLOCK_SIZE;
+}
+
+/*****************************************************************************
+ * dvdcss_title: crack the current title key if needed
+ *****************************************************************************/
+extern int dummy_dvdcss_title ( dvdcss_handle dvdcss, int i_block )
+{
+ return 0;
+}
+
+/*****************************************************************************
+ * dvdcss_read: read data from the device, decrypt if requested
+ *****************************************************************************/
+extern int dummy_dvdcss_read ( dvdcss_handle dvdcss, void *p_buffer,
+ int i_blocks,
+ int i_flags )
+{
+ int i_bytes;
+
+ i_bytes = read( dvdcss->i_fd, p_buffer,
+ (size_t)i_blocks * DVDCSS_BLOCK_SIZE );
+
+ return i_bytes / DVDCSS_BLOCK_SIZE;
+}
+
+/*****************************************************************************
+ * dvdcss_readv: read data to an iovec structure, decrypt if reaquested
+ *****************************************************************************/
+extern int dummy_dvdcss_readv ( dvdcss_handle dvdcss, void *p_iovec,
+ int i_blocks,
+ int i_flags )
+{
+ int i_read;
+
+ i_read = readv( dvdcss->i_fd, (struct iovec*)p_iovec, i_blocks );
+
+ return i_read / DVDCSS_BLOCK_SIZE;
+}
+
+/*****************************************************************************
+ * dvdcss_close: close the DVD device and clean up the library
+ *****************************************************************************/
+extern int dummy_dvdcss_close ( dvdcss_handle dvdcss )
+{
+ int i_ret;
+
+ i_ret = close( dvdcss->i_fd );
+
+ if( i_ret < 0 )
+ {
+ return i_ret;
+ }
+
+ free( dvdcss );
+
+ return 0;
+}
+
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * dvd.h: thread structure of the DVD plugin
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: dvd.h,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+/* Logical block size for DVD-VIDEO */
+#define DVD_LB_SIZE 2048
+#define LB2OFF(x) ((off_t)(x) * (off_t)(DVD_LB_SIZE))
+#define OFF2LB(x) ((x) >> 11)
+
+/*****************************************************************************
+ * thread_dvd_data_t: extension of input_thread_t for DVD specificity.
+ *****************************************************************************/
+typedef struct thread_dvd_data_s
+{
+ dvdcss_handle dvdhandle; /* libdvdcss handle */
+
+ int i_audio_nb;
+ int i_spu_nb;
+
+ /* Navigation information */
+ int i_title;
+ int i_title_id;
+
+ int i_chapter_nb;
+ int i_chapter;
+ vlc_bool_t b_new_chapter;
+
+ int i_angle_nb;
+ int i_angle;
+
+ int i_map_cell; /* cell index in adress map */
+ int i_prg_cell; /* cell index in program map */
+ int i_angle_cell; /* cell index in the current angle */
+
+ int i_vts_start; /* offset to beginning of vts */
+ int i_vts_lb; /* sector in vts */
+ int i_last_lb; /* last sector of current cell */
+
+ /* Structure that contains all information of the DVD */
+ struct ifo_s * p_ifo;
+
+} thread_dvd_data_t;
+
--- /dev/null
+/*****************************************************************************
+ * dvdcss.h: Dummy libdvdcss header.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: dvdcss.h,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * The libdvdcss structure
+ *****************************************************************************/
+typedef struct dvdcss_s* dvdcss_handle;
+
+/*****************************************************************************
+ * Defines and flags
+ *****************************************************************************/
+#define DVDCSS_BLOCK_SIZE 2048
+
+#define DVDCSS_NOFLAGS 0
+#define DVDCSS_READ_DECRYPT (1 << 0)
+#define DVDCSS_SEEK_MPEG (1 << 0)
+#define DVDCSS_SEEK_KEY (1 << 1)
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+dvdcss_handle dummy_dvdcss_open ( char * );
+int dummy_dvdcss_close ( dvdcss_handle );
+int dummy_dvdcss_title ( dvdcss_handle, int );
+int dummy_dvdcss_seek ( dvdcss_handle, int, int );
+int dummy_dvdcss_read ( dvdcss_handle, void *, int, int );
+int dummy_dvdcss_readv ( dvdcss_handle, void *, int, int );
+char * dummy_dvdcss_error ( dvdcss_handle );
+
+/*****************************************************************************
+ * Pointers which will be filled either with dummy_dvdcss functions or
+ * with the dlopen()ed ones.
+ *****************************************************************************/
+#define ____dvdcss_open dvdcss_open
+#define ____dvdcss_close dvdcss_close
+#define ____dvdcss_title dvdcss_title
+#define ____dvdcss_seek dvdcss_seek
+#define ____dvdcss_read dvdcss_read
+#define ____dvdcss_readv dvdcss_readv
+#define ____dvdcss_error dvdcss_error
+
+dvdcss_handle (* ____dvdcss_open ) ( char * );
+int (* ____dvdcss_close ) ( dvdcss_handle );
+int (* ____dvdcss_title ) ( dvdcss_handle, int );
+int (* ____dvdcss_seek ) ( dvdcss_handle, int, int );
+int (* ____dvdcss_read ) ( dvdcss_handle, void *, int, int );
+int (* ____dvdcss_readv ) ( dvdcss_handle, void *, int, int );
+char * (* ____dvdcss_error ) ( dvdcss_handle );
+
+
--- /dev/null
+/* es.c: functions to find and select ES
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: es.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#ifdef GOD_DAMN_DMCA
+# include "dvdcss.h"
+#else
+# include <dvdcss/dvdcss.h>
+#endif
+
+#include "dvd.h"
+#include "ifo.h"
+#include "summary.h"
+#include "iso_lang.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+void DVDLaunchDecoders( input_thread_t * p_input );
+
+#define vmg p_dvd->p_ifo->vmg
+#define vts p_dvd->p_ifo->vts
+
+#define ADDES( stream_id, private_id, fourcc, cat, lang, size ) \
+ i_id = ( (private_id) << 8 ) | (stream_id); \
+ p_es = input_AddES( p_input, NULL, i_id, size ); \
+ p_es->i_stream_id = (stream_id); \
+ p_es->i_fourcc = (fourcc); \
+ p_es->i_cat = (cat); \
+ if( lang ) \
+ { \
+ strcpy( p_es->psz_desc, DecodeLanguage( lang ) ); \
+ }
+
+
+/*****************************************************************************
+ * DVDReadVideo: read video ES
+ *****************************************************************************/
+void DVDReadVideo( input_thread_t * p_input )
+{
+ thread_dvd_data_t * p_dvd;
+ es_descriptor_t * p_es;
+ int i_id;
+ int i_ratio;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+
+ /* ES 0 -> video MPEG2 */
+ IfoPrintVideo( p_dvd );
+ i_ratio = vts.manager_inf.video_attr.i_ratio;
+
+ if( i_ratio )
+ {
+ ADDES( 0xe0, 0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0, sizeof(int) );
+ *(int*)(p_es->p_demux_data) = i_ratio;
+ }
+ else
+ {
+ ADDES( 0xe0, 0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0, 0 );
+ }
+
+}
+
+/*****************************************************************************
+ * DVDReadAudio: read audio ES
+ *****************************************************************************/
+#define audio_status \
+ vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
+
+void DVDReadAudio( input_thread_t * p_input )
+{
+ thread_dvd_data_t * p_dvd;
+ es_descriptor_t * p_es;
+ int i_lang;
+ int i_id;
+ int i;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+ p_dvd->i_audio_nb = 0;
+
+ /* Audio ES, in the order they appear in .ifo */
+ for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
+ {
+ IfoPrintAudio( p_dvd, i );
+
+ /* audio channel is active if first byte is 0x80 */
+ if( audio_status.i_available )
+ {
+ p_dvd->i_audio_nb++;
+ i_lang = vts.manager_inf.p_audio_attr[i-1].i_lang_code;
+ i_id = audio_status.i_position;
+
+ switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
+ {
+ case 0x00: /* A52 */
+ ADDES( 0xbd, 0x80 + audio_status.i_position,
+ VLC_FOURCC('a','5','2',' '), AUDIO_ES, i_lang, 0 );
+ strcat( p_es->psz_desc, " (A52)" );
+
+ break;
+ case 0x02:
+ case 0x03: /* MPEG audio */
+ ADDES( 0xc0 + audio_status.i_position, 0,
+ VLC_FOURCC('m','p','g','a'), AUDIO_ES, i_lang, 0 );
+ strcat( p_es->psz_desc, " (mpeg)" );
+
+ break;
+ case 0x04: /* LPCM */
+ ADDES( 0xbd, 0xa0 + audio_status.i_position,
+ VLC_FOURCC('l','p','c','m'), AUDIO_ES, i_lang, 0 );
+ strcat( p_es->psz_desc, " (lpcm)" );
+
+ break;
+ case 0x06: /* DTS */
+ i_id = ( ( 0x88 + audio_status.i_position ) << 8 ) | 0xbd;
+ msg_Err( p_input, "DTS audio not handled yet (0x%x)", i_id );
+ break;
+ default:
+ i_id = 0;
+ msg_Err( p_input, "unknown audio type %.2x",
+ vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
+ }
+ }
+ }
+}
+#undef audio_status
+
+/*****************************************************************************
+ * DVDReadSPU: read subpictures ES
+ *****************************************************************************/
+#define spu_status \
+ vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
+#define palette \
+ vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_yuv_color
+
+void DVDReadSPU( input_thread_t * p_input )
+{
+ thread_dvd_data_t * p_dvd;
+ es_descriptor_t * p_es;
+ int i_id;
+ int i;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+ p_dvd->i_spu_nb = 0;
+
+ for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
+ {
+ IfoPrintSpu( p_dvd, i );
+
+ if( spu_status.i_available )
+ {
+ p_dvd->i_spu_nb++;
+
+ /* there are several streams for one spu */
+ if( vts.manager_inf.video_attr.i_ratio )
+ {
+ /* 16:9 */
+ switch( vts.manager_inf.video_attr.i_perm_displ )
+ {
+ case 1:
+ i_id = spu_status.i_position_pan;
+ break;
+ case 2:
+ i_id = spu_status.i_position_letter;
+ break;
+ default:
+ i_id = spu_status.i_position_wide;
+ break;
+ }
+ }
+ else
+ {
+ /* 4:3 */
+ i_id = spu_status.i_position_43;
+ }
+
+ if( vmg.title.pi_yuv_color )
+ {
+ ADDES( 0xbd, 0x20 + i_id, VLC_FOURCC('s','p','u',' '), SPU_ES,
+ vts.manager_inf.p_spu_attr[i-1].i_lang_code,
+ sizeof(int) + 16*sizeof(u32) );
+ *(int*)p_es->p_demux_data = 0xBeeF;
+ memcpy( (char*)p_es->p_demux_data + sizeof(int),
+ palette, 16*sizeof(u32) );
+ }
+ else
+ {
+ ADDES( 0xbd, 0x20 + i_id, VLC_FOURCC('s','p','u',' '), SPU_ES,
+ vts.manager_inf.p_spu_attr[i-1].i_lang_code, 0 );
+ }
+ }
+ }
+}
+#undef palette
+#undef spu_status
+
+#undef vts
+#undef vmg
+
+/*****************************************************************************
+ * DVDLaunchDecoders: select ES for video, audio and spu
+ *****************************************************************************/
+void DVDLaunchDecoders( input_thread_t * p_input )
+{
+ thread_dvd_data_t * p_dvd;
+ int i_audio;
+ int i_spu;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+
+ /* Select Video stream (always 0) */
+ if( config_GetInt( p_input, "video" ) )
+ {
+ input_SelectES( p_input, p_input->stream.pp_es[0] );
+ }
+
+ /* Select audio stream */
+ if( p_dvd->i_audio_nb > 0 && config_GetInt( p_input, "audio" ) )
+ {
+ /* For audio: first one if none or a not existing one specified */
+ i_audio = config_GetInt( p_input, "audio-channel" );
+ if( i_audio <= 0 || i_audio > p_dvd->i_audio_nb )
+ {
+ config_PutInt( p_input, "audio-channel", 1 );
+ i_audio = 1;
+ }
+
+ if( ( config_GetInt( p_input, "audio-type" )
+ == REQUESTED_A52 ) )
+ {
+ int i_a52 = i_audio;
+ while( ( p_input->stream.pp_es[i_a52]->i_fourcc !=
+ VLC_FOURCC('a','5','2',' ') ) && ( i_a52 <=
+ p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
+ {
+ i_a52++;
+ }
+ if( p_input->stream.pp_es[i_a52]->i_fourcc
+ == VLC_FOURCC('a','5','2',' ') )
+ {
+ input_SelectES( p_input,
+ p_input->stream.pp_es[i_a52] );
+ }
+ }
+ else
+ {
+ input_SelectES( p_input,
+ p_input->stream.pp_es[i_audio] );
+ }
+ }
+
+ /* Select subtitle */
+ if( p_dvd->i_spu_nb > 0 && config_GetInt( p_input, "video" ) )
+ {
+ /* for spu, default is none */
+ i_spu = config_GetInt( p_input, "spu-channel" );
+ if( i_spu < 0 || i_spu > p_dvd->i_spu_nb )
+ {
+ config_PutInt( p_input, "spu-channel", 0 );
+ i_spu = 0;
+ }
+ if( i_spu > 0 )
+ {
+ int i = 0, j = 0;
+ for( i = 0; i < p_input->stream.i_es_number; i++ )
+ {
+ if ( p_input->stream.pp_es[i]->i_fourcc
+ == VLC_FOURCC('s','p','u',' ') )
+ {
+ j++;
+ if ( i_spu == j ) break;
+ }
+ }
+ if( i_spu == j )
+ {
+ input_SelectES( p_input, p_input->stream.pp_es[i] );
+ }
+ }
+ }
+}
--- /dev/null
+/* dvd_es.h: functions to find and select ES
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: es.h,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+void DVDLaunchDecoders ( input_thread_t * );
+void DVDReadVideo ( input_thread_t * );
+void DVDReadAudio ( input_thread_t * );
+void DVDReadSPU ( input_thread_t * );
+
--- /dev/null
+/*****************************************************************************
+ * ifo.c: Functions for ifo parsing
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: ifo.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ * German Tischler <tanis@gaspode.franken.de>
+ *
+ * based on:
+ * - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at>
+ * - IFO structure documentation by Thomas Mirlacher, Björn Englund,
+ * Håkan Hjort
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#elif defined( _MSC_VER ) && defined( _WIN32 )
+# include <io.h>
+#endif
+
+#include <string.h>
+#include <fcntl.h>
+
+#ifdef GOD_DAMN_DMCA
+# include "dvdcss.h"
+#else
+# include <dvdcss/dvdcss.h>
+#endif
+
+#include "dvd.h"
+#include "ifo.h"
+#include "udf.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+void CommandRead ( command_desc_t );
+static int ReadTitle ( ifo_t * , title_t *, int, int );
+static int FreeTitle ( title_t * );
+static int ReadUnitInf ( ifo_t * , unit_inf_t *, int, int );
+static int FreeUnitInf ( unit_inf_t * );
+static int ReadTitleUnit ( ifo_t * , title_unit_t *, int );
+static int FreeTitleUnit ( title_unit_t * );
+static int ReadVobuMap ( ifo_t * , vobu_map_t *, int );
+static int FreeVobuMap ( vobu_map_t * );
+static int ReadCellInf ( ifo_t * , cell_inf_t *, int );
+static int FreeCellInf ( cell_inf_t * );
+static int FreeTitleSet ( vts_t * );
+
+static u8* FillBuffer ( ifo_t *, u8 *, int );
+static u8 ReadByte ( ifo_t *, u8 *, u8 ** );
+static void ReadBytes ( ifo_t *, u8 *, u8 **, u8 *, int );
+static void DumpBytes ( ifo_t *, u8 *, u8 **, int );
+static u16 ReadWord ( ifo_t *, u8 *, u8 ** );
+static u32 ReadDouble ( ifo_t *, u8 *, u8 ** );
+static u64 ReadQuad ( ifo_t *, u8 *, u8 ** );
+
+/*
+ * IFO Management.
+ */
+
+/*****************************************************************************
+ * IfoCreate : Creates an ifo structure and prepares for parsing directly
+ * on DVD device
+ *****************************************************************************/
+int IfoCreate( thread_dvd_data_t * p_dvd )
+{
+ p_dvd->p_ifo = malloc( sizeof(ifo_t) );
+ if( p_dvd->p_ifo == NULL )
+ {
+//X intf_Err( p_input, "unable to allocate memory. aborting" );
+ return -1;
+ }
+
+ /* if we are here the dvd device has already been opened */
+ p_dvd->p_ifo->dvdhandle = p_dvd->dvdhandle;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * IfoInit : Reads information from the management table.
+ *****************************************************************************/
+int IfoInit( ifo_t * p_ifo )
+{
+ u8 p_buf[DVD_LB_SIZE];
+ u8* p_tmp;
+ u64 i_temp;
+ int i, j, k;
+ int i_start;
+
+ /* find the start sector of video information on the dvd */
+ p_ifo->i_start = DVDUDFFindFile( p_ifo->dvdhandle, "/VIDEO_TS/VIDEO_TS.IFO" );
+ if( !p_ifo->i_start ) return -1;
+
+ p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start );
+ //i_start = p_ifo->i_pos;
+
+ /*
+ * read the video manager information table
+ */
+#define MGINF p_ifo->vmg.manager_inf
+ //fprintf( stderr, "VMGI\n" );
+
+ ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.psz_id, 12 );
+ MGINF.psz_id[12] = '\0';
+ MGINF.i_vmg_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 12 );
+ MGINF.i_vmg_inf_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ MGINF.i_spec_ver = ReadByte( p_ifo, p_buf, &p_tmp );
+ MGINF.i_cat = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_volume_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ MGINF.i_volume = ReadWord( p_ifo, p_buf, &p_tmp );
+ MGINF.i_disc_side = ReadByte( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 19 );
+ MGINF.i_title_set_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.ps_provider_id, 32 );
+ MGINF.i_pos_code = ReadQuad( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 24 );
+ MGINF.i_vmg_inf_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_first_play_title_start_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 56 );
+ MGINF.i_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_title_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_title_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_parental_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_vts_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_text_data_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 32 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ MGINF.i_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "vmgi audio nb : %d\n", MGINF.i_audio_nb );
+
+ for( i = 0 ; i < 8 ; i++ )
+ {
+ i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
+ }
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
+ MGINF.i_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "vmgi subpic nb : %d\n", MGINF.i_spu_nb );
+
+ for( i = 0 ; i < MGINF.i_spu_nb ; i++ )
+ {
+ ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
+ /* FIXME : take care of endianness */
+ }
+
+ /*
+ * read first play title.
+ */
+ //fprintf(stderr,"readtitle %i\n", MGINF.i_first_play_title_start_byte & 0x7ff );
+ if( ReadTitle( p_ifo, &p_ifo->vmg.title, p_ifo->i_start
+ + OFF2LB( MGINF.i_first_play_title_start_byte ),
+ MGINF.i_first_play_title_start_byte & 0x7ff ) < 0 )
+ {
+ return -1;
+ }
+
+ /*
+ * fills the title information structure.
+ */
+#define TITINF p_ifo->vmg.title_inf
+ if( MGINF.i_title_inf_start_sector )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf,
+ p_ifo->i_start + MGINF.i_title_inf_start_sector );
+ //fprintf( stderr, "title inf %d\n", p_ifo->i_pos );
+
+ TITINF.i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "title_inf: TTU nb %d\n", TITINF.i_title_nb );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ TITINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ /* parsing of title attributes */
+ TITINF.p_attr = malloc( TITINF.i_title_nb *sizeof(title_attr_t) );
+ if( TITINF.p_attr == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoInit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < TITINF.i_title_nb ; i++ )
+ {
+ TITINF.p_attr[i].i_play_type = ReadByte( p_ifo, p_buf, &p_tmp );
+ TITINF.p_attr[i].i_angle_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ TITINF.p_attr[i].i_chapter_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ TITINF.p_attr[i].i_parental_id = ReadWord( p_ifo, p_buf, &p_tmp );
+ TITINF.p_attr[i].i_title_set_num = ReadByte( p_ifo, p_buf, &p_tmp );
+ TITINF.p_attr[i].i_title_num = ReadByte( p_ifo, p_buf, &p_tmp );
+ TITINF.p_attr[i].i_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "title_inf: %d %d %d\n", TITINF.p_attr[i].i_chapter_nb, TITINF.p_attr[i].i_title_set_num, TITINF.p_attr[i].i_title_num );
+ }
+ }
+ else
+ {
+ TITINF.p_attr = NULL;
+ }
+#undef TITINF
+
+ /*
+ * fills the title unit structure.
+ */
+ if( MGINF.i_title_unit_start_sector )
+ {
+ if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit, p_ifo->i_start
+ + MGINF.i_title_unit_start_sector ) < 0 )
+ {
+ return -1;
+ }
+ }
+
+ /*
+ * fills the structure about parental information.
+ */
+#define PARINF p_ifo->vmg.parental_inf
+ if( MGINF.i_parental_inf_start_sector )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start +
+ MGINF.i_parental_inf_start_sector );
+ i_start = p_ifo->i_pos;
+
+ //fprintf( stderr, "PTL\n" );
+
+ PARINF.i_country_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ PARINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ PARINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ PARINF.p_parental_desc = malloc( PARINF.i_country_nb
+ * sizeof(parental_desc_t) );
+ if( PARINF.p_parental_desc == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoInit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < PARINF.i_country_nb ; i++ )
+ {
+ ReadBytes( p_ifo, p_buf, &p_tmp,
+ PARINF.p_parental_desc[i].ps_country_code, 2 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ PARINF.p_parental_desc[i].i_parental_mask_start_byte =
+ ReadWord( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ }
+
+ PARINF.p_parental_mask = malloc( PARINF.i_country_nb
+ * sizeof(parental_mask_t) );
+ if( PARINF.p_parental_mask == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoInit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < PARINF.i_country_nb ; i++ )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, i_start + OFF2LB(
+ PARINF.p_parental_desc[i].i_parental_mask_start_byte ) )
+ + (PARINF.p_parental_desc[i].i_parental_mask_start_byte & 0x7ff);
+
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ PARINF.p_parental_mask[i].ppi_mask[j] =
+ malloc( ( PARINF.i_vts_nb + 1 ) * sizeof(u16) );
+
+ if( PARINF.p_parental_mask[i].ppi_mask[j] == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoInit" );
+ return -1;
+ }
+
+ for( k = 0 ; k < PARINF.i_vts_nb + 1 ; k++ )
+ {
+ PARINF.p_parental_mask[i].ppi_mask[j][k] =
+ ReadWord( p_ifo, p_buf, &p_tmp );
+ }
+ }
+ }
+ }
+#undef PARINF
+
+ /*
+ * information and attributes about for each vts.
+ */
+#define VTSINF p_ifo->vmg.vts_inf
+ if( MGINF.i_vts_inf_start_sector )
+ {
+ u64 i_temp;
+
+ p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start +
+ MGINF.i_vts_inf_start_sector );
+ i_start = p_ifo->i_pos;
+
+ //fprintf( stderr, "VTS ATTR\n" );
+
+ VTSINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp );;
+ //fprintf( stderr, "VTS ATTR Nb: %d\n", VTSINF.i_vts_nb );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ VTSINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+ VTSINF.pi_vts_attr_start_byte =
+ malloc( VTSINF.i_vts_nb * sizeof(u32) );
+ if( VTSINF.pi_vts_attr_start_byte == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoInit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < VTSINF.i_vts_nb ; i++ )
+ {
+ VTSINF.pi_vts_attr_start_byte[i] =
+ ReadDouble( p_ifo, p_buf, &p_tmp );
+ }
+
+ VTSINF.p_vts_attr = malloc( VTSINF.i_vts_nb * sizeof(vts_attr_t) );
+ if( VTSINF.p_vts_attr == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoInit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < VTSINF.i_vts_nb ; i++ )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, i_start +
+ OFF2LB( VTSINF.pi_vts_attr_start_byte[i] ) )
+ + ( VTSINF.pi_vts_attr_start_byte[i] & 0x7ff );
+
+ VTSINF.p_vts_attr[i].i_last_byte =
+ ReadDouble( p_ifo, p_buf, &p_tmp );
+ VTSINF.p_vts_attr[i].i_cat_app_type =
+ ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ VTSINF.p_vts_attr[i].i_vts_menu_audio_nb =
+ ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "m audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_audio_nb );
+
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
+ }
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
+ VTSINF.p_vts_attr[i].i_vts_menu_spu_nb =
+ ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "m subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_spu_nb );
+
+ for( j = 0 ; j < 28 ; j++ )
+ {
+ /* FIXME : Fix endianness issue here */
+ ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
+ }
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ VTSINF.p_vts_attr[i].i_vts_title_audio_nb =
+ ReadDouble( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "tt audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_audio_nb );
+
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );;
+ }
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
+ VTSINF.p_vts_attr[i].i_vts_title_spu_nb =
+ ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "tt subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_spu_nb );
+
+ for( j = 0 ; j < 28 /*VTSINF.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ )
+ {
+ /* FIXME : Fix endianness issue here */
+ ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
+ }
+ }
+ }
+#undef VTSINF
+
+ /*
+ * global cell map.
+ */
+ if( MGINF.i_cell_inf_start_sector )
+ {
+ if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf, p_ifo->i_start +
+ MGINF.i_cell_inf_start_sector ) < 0 )
+ {
+ return -1;
+ }
+ }
+
+ /*
+ * global vob unit map.
+ */
+ if( MGINF.i_vobu_map_start_sector )
+ {
+ if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map, p_ifo->i_start +
+ MGINF.i_vobu_map_start_sector ) < 0 )
+ {
+ return -1;
+ }
+ }
+#undef MGINF
+
+ p_ifo->vts.b_initialized = 0;
+
+//X intf_Warn( p_input, 2, "vmg initialized" );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure.
+ *****************************************************************************/
+int IfoTitleSet( ifo_t * p_ifo, int i_title )
+{
+ u8 p_buf[DVD_LB_SIZE];
+ u8 * p_tmp;
+ int i_off;
+ int i_start;
+ u64 i_temp;
+ u16 i_short;
+ int i, j;
+
+ if( p_ifo->vts.b_initialized )
+ {
+ FreeTitleSet( &p_ifo->vts );
+ }
+
+ i_off = p_ifo->vmg.title_inf.p_attr[i_title-1].i_start_sector
+ + p_ifo->i_start;
+
+ //fprintf(stderr, "offset: %d\n" , i_off );
+
+ p_tmp = FillBuffer( p_ifo, p_buf, i_off );
+ //i_start = p_ifo->i_pos;
+ p_ifo->vts.i_pos = p_ifo->i_pos;
+
+#define MGINF p_ifo->vts.manager_inf
+
+ /*
+ * read manager information
+ */
+ //fprintf( stderr, "VTSI\n" );
+
+ ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.psz_id , 12 );
+ MGINF.psz_id[12] = '\0';
+ MGINF.i_last_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 12 );
+ MGINF.i_inf_last_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ MGINF.i_spec_ver = ReadByte( p_ifo, p_buf, &p_tmp );
+ MGINF.i_cat = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 90 );
+ MGINF.i_inf_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 60 );
+ MGINF.i_menu_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_title_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_title_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_title_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_menu_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_time_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_menu_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_menu_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ MGINF.i_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 24 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ MGINF.i_menu_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+
+ for( i = 0 ; i < 8 ; i++ )
+ {
+ i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
+ }
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
+ MGINF.i_menu_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+
+ for( i = 0 ; i < 28 ; i++ )
+ {
+ /* FIXME : take care of endianness */
+ ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
+ }
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+
+ i_short = ReadWord( p_ifo, p_buf, &p_tmp );
+ i_short >>= 2;
+ MGINF.video_attr.i_mode = i_short & 0x1;
+ i_short >>= 1;
+ MGINF.video_attr.i_letterboxed = i_short & 0x1;
+ i_short >>= 1;
+ MGINF.video_attr.i_source_res = i_short & 0x3;
+ i_short >>= 2;
+ MGINF.video_attr.i_line21_2 = i_short & 0x1;
+ i_short >>= 1;
+ MGINF.video_attr.i_line21_1 = i_short & 0x1;
+ i_short >>= 1;
+ MGINF.video_attr.i_perm_displ = i_short & 0x3;
+ i_short >>= 2;
+ MGINF.video_attr.i_ratio = i_short & 0x3;
+ i_short >>= 2;
+ MGINF.video_attr.i_system = i_short & 0x3;
+ i_short >>= 2;
+ MGINF.video_attr.i_compression = i_short & 0x3;
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ MGINF.i_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "vtsi audio nb : %d\n", MGINF.i_audio_nb );
+
+ for( i = 0 ; i < 8 ; i++ )
+ {
+ i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
+ i_temp >>= 8;
+ MGINF.p_audio_attr[i].i_bar = i_temp & 0xff;
+ i_temp >>= 8;
+ MGINF.p_audio_attr[i].i_caption = i_temp & 0xff;
+ i_temp >>= 8;
+ MGINF.p_audio_attr[i].i_foo = i_temp & 0xff;
+ i_temp >>= 8;
+ MGINF.p_audio_attr[i].i_lang_code = i_temp & 0xffff;
+ i_temp >>= 16;
+ MGINF.p_audio_attr[i].i_num_channels = i_temp & 0x7;
+ i_temp >>= 3;
+ MGINF.p_audio_attr[i].i_test = i_temp & 0x1;
+ i_temp >>= 1;
+ MGINF.p_audio_attr[i].i_sample_freq = i_temp & 0x3;
+ i_temp >>= 2;
+ MGINF.p_audio_attr[i].i_quantization = i_temp & 0x3;
+ i_temp >>= 2;
+ MGINF.p_audio_attr[i].i_appl_mode = i_temp & 0x3;
+ i_temp >>= 2;
+ MGINF.p_audio_attr[i].i_type = i_temp & 0x3;
+ i_temp >>= 2;
+ MGINF.p_audio_attr[i].i_multichannel_extension = i_temp & 0x1;
+ i_temp >>= 1;
+ MGINF.p_audio_attr[i].i_coding_mode = i_temp & 0x7;
+ }
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
+ MGINF.i_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "vtsi subpic nb : %d\n", MGINF.i_spu_nb );
+
+ for( i=0 ; i<MGINF.i_spu_nb ; i++ )
+ {
+ ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
+ i_temp = hton64( i_temp ) >> 16;
+ //fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
+ MGINF.p_spu_attr[i].i_caption = i_temp & 0xff;
+ i_temp >>= 8;
+ MGINF.p_spu_attr[i].i_foo = i_temp & 0xff;
+ i_temp >>= 8;
+ MGINF.p_spu_attr[i].i_lang_code = i_temp & 0xffff;
+ i_temp >>= 16;
+ MGINF.p_spu_attr[i].i_prefix = i_temp & 0xffff;
+ }
+
+ /*
+ * read title information: set of pointers to title
+ */
+#define TITINF p_ifo->vts.title_inf
+ if( MGINF.i_title_inf_start_sector )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->vts.i_pos +
+ MGINF.i_title_inf_start_sector );
+
+ i_start = p_ifo->i_pos;
+
+ //fprintf( stderr, "VTS PTR\n" );
+
+ TITINF.i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "VTS title_inf nb: %d\n", TITINF.i_title_nb );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ TITINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ TITINF.pi_start_byte = malloc( TITINF.i_title_nb * sizeof(u32) );
+ if( TITINF.pi_start_byte == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoTitleSet" );
+ return -1;
+ }
+
+ for( i = 0 ; i < TITINF.i_title_nb ; i++ )
+ {
+ TITINF.pi_start_byte[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
+ }
+
+ /* Parsing of tts */
+ TITINF.p_title_start = malloc( TITINF.i_title_nb
+ * sizeof(title_start_t) );
+ if( TITINF.p_title_start == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoTitleSet" );
+ return -1;
+ }
+
+ for( i = 0 ; i < TITINF.i_title_nb ; i++ )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, i_start +
+ OFF2LB( TITINF.pi_start_byte[i] ) )
+ + (TITINF.pi_start_byte[i] & 0x7ff);
+
+ TITINF.p_title_start[i].i_title_id =
+ ReadWord( p_ifo, p_buf, &p_tmp );
+ TITINF.p_title_start[i].i_chapter =
+ ReadWord( p_ifo, p_buf, &p_tmp );
+ }
+ }
+#undef TITINF
+
+ /*
+ * menu unit information
+ */
+ if( MGINF.i_menu_unit_start_sector )
+ {
+ if( ReadTitleUnit( p_ifo, &p_ifo->vts.menu_unit, p_ifo->vts.i_pos +
+ MGINF.i_menu_unit_start_sector ) < 0 )
+ {
+ return -1;
+ }
+ }
+
+ /*
+ * title unit information
+ */
+ if( MGINF.i_title_unit_start_sector )
+ {
+ if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit, p_ifo->vts.i_pos +
+ MGINF.i_title_unit_start_sector, 0 ) < 0 )
+ {
+ return -1;
+ }
+ }
+
+ /*
+ * time map information
+ */
+#define TIMINF p_ifo->vts.time_inf
+ if( MGINF.i_time_inf_start_sector )
+ {
+ u8 p_buf[DVD_LB_SIZE];
+
+ p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->vts.i_pos +
+ MGINF.i_time_inf_start_sector );
+
+ //fprintf( stderr, "TMAP\n" );
+
+ TIMINF.i_nb = ReadWord( p_ifo, p_buf, &p_tmp );;
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ TIMINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ TIMINF.pi_start_byte = malloc( TIMINF.i_nb * sizeof(u32) );
+ if( TIMINF.pi_start_byte == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoTitleSet" );
+ return -1;
+ }
+
+ for( i = 0 ; i < TIMINF.i_nb ; i++ )
+ {
+ TIMINF.pi_start_byte[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
+ }
+
+ TIMINF.p_time_map = malloc( TIMINF.i_nb * sizeof(time_map_t) );
+ if( TIMINF.p_time_map == NULL )
+ {
+//X intf_Err( p_input, "out of memory in IfoTitleSet" );
+ return -1;
+ }
+
+ for( i = 0 ; i < TIMINF.i_nb ; i++ )
+ {
+ TIMINF.p_time_map[i].i_time_unit = ReadByte( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ TIMINF.p_time_map[i].i_entry_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+
+ if( TIMINF.p_time_map[i].i_entry_nb )
+ {
+ TIMINF.p_time_map[i].pi_sector =
+ malloc( TIMINF.p_time_map[i].i_entry_nb * sizeof(u32) );
+ if( TIMINF.p_time_map[i].pi_sector == NULL )
+ {
+//X msg_Err( p_input, "out of memory in IfoTitleSet" );
+ return -1;
+ }
+
+ for( j = 0 ; j < TIMINF.p_time_map[i].i_entry_nb ; j++ )
+ {
+ TIMINF.p_time_map[i].pi_sector[j] =
+ ReadDouble( p_ifo, p_buf, &p_tmp );
+ }
+ }
+ }
+ }
+#undef TIMINF
+
+ if( MGINF.i_menu_cell_inf_start_sector
+ && ReadCellInf( p_ifo, &p_ifo->vts.menu_cell_inf, p_ifo->vts.i_pos +
+ MGINF.i_menu_cell_inf_start_sector ) < 0 )
+ {
+ return -1;
+ }
+
+ if( MGINF.i_menu_vobu_map_start_sector
+ && ReadVobuMap( p_ifo, &p_ifo->vts.menu_vobu_map, p_ifo->vts.i_pos +
+ MGINF.i_menu_vobu_map_start_sector ) < 0 )
+ {
+ return -1;
+ }
+
+ if( MGINF.i_cell_inf_start_sector
+ && ReadCellInf( p_ifo, &p_ifo->vts.cell_inf, p_ifo->vts.i_pos +
+ MGINF.i_cell_inf_start_sector ) )
+ {
+ return -1;
+ }
+
+ if( MGINF.i_vobu_map_start_sector
+ && ReadVobuMap( p_ifo, &p_ifo->vts.vobu_map, p_ifo->vts.i_pos +
+ MGINF.i_vobu_map_start_sector ) )
+ {
+ return -1;
+ }
+#undef MGINF
+
+//X intf_Warn( p_input, 4, "vts %d initialized",
+//X p_ifo->vmg.title_inf.p_attr[i_title-1].i_title_set_num );
+
+ p_ifo->vts.b_initialized = 1;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeTitleSet : free all structures allocated by IfoTitleSet
+ *****************************************************************************/
+static int FreeTitleSet( vts_t * p_vts )
+{
+ int i;
+
+ if( p_vts->manager_inf.i_vobu_map_start_sector )
+ {
+ FreeVobuMap( &p_vts->vobu_map );
+ }
+
+ if( p_vts->manager_inf.i_cell_inf_start_sector )
+ {
+ FreeCellInf( &p_vts->cell_inf );
+ }
+
+ if( p_vts->manager_inf.i_menu_vobu_map_start_sector )
+ {
+ FreeVobuMap( &p_vts->menu_vobu_map );
+ }
+
+ if( p_vts->manager_inf.i_menu_cell_inf_start_sector )
+ {
+ FreeCellInf( &p_vts->menu_cell_inf );
+ }
+
+ if( p_vts->manager_inf.i_time_inf_start_sector )
+ {
+ for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ )
+ {
+ if( p_vts->time_inf.p_time_map[i].i_entry_nb )
+ {
+ free( p_vts->time_inf.p_time_map[i].pi_sector );
+ }
+ }
+
+ free( p_vts->time_inf.p_time_map );
+ free( p_vts->time_inf.pi_start_byte );
+ }
+
+ if( p_vts->manager_inf.i_title_unit_start_sector )
+ {
+ FreeUnitInf( &p_vts->title_unit );
+ }
+
+ if( p_vts->manager_inf.i_menu_unit_start_sector )
+ {
+ FreeTitleUnit( &p_vts->menu_unit );
+ }
+
+ if( p_vts->manager_inf.i_title_inf_start_sector )
+ {
+ free( p_vts->title_inf.pi_start_byte );
+ free( p_vts->title_inf.p_title_start );
+ }
+
+ p_vts->b_initialized = 0;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * IfoDestroy : Frees all the memory allocated to ifo structures
+ *****************************************************************************/
+void IfoDestroy( ifo_t * p_ifo )
+{
+ int i, j;
+
+ FreeTitleSet( &p_ifo->vts );
+
+ if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector )
+ {
+ FreeVobuMap( &p_ifo->vmg.vobu_map );
+ }
+
+ if( p_ifo->vmg.manager_inf.i_cell_inf_start_sector )
+ {
+ FreeCellInf( &p_ifo->vmg.cell_inf );
+ }
+
+ if( p_ifo->vmg.manager_inf.i_vts_inf_start_sector )
+ {
+ free( p_ifo->vmg.vts_inf.p_vts_attr );
+ free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte );
+ }
+
+ /* free parental information structures */
+ if( p_ifo->vmg.manager_inf.i_parental_inf_start_sector )
+ {
+ for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ )
+ {
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ free( p_ifo->vmg.parental_inf.p_parental_mask[i].ppi_mask[j] );
+ }
+ }
+
+ free( p_ifo->vmg.parental_inf.p_parental_mask );
+ free( p_ifo->vmg.parental_inf.p_parental_desc );
+ }
+
+ if( p_ifo->vmg.manager_inf.i_title_unit_start_sector )
+ {
+ FreeTitleUnit( &p_ifo->vmg.title_unit );
+ }
+
+ if( p_ifo->vmg.manager_inf.i_title_inf_start_sector )
+ {
+ free( p_ifo->vmg.title_inf.p_attr );
+ }
+
+ FreeTitle( &p_ifo->vmg.title );
+
+ free( p_ifo );
+
+ return;
+}
+
+/*
+ * Function common to Video Manager and Video Title set Processing
+ */
+
+/*****************************************************************************
+ * ReadTitle : Fills the title structure.
+ *****************************************************************************
+ * Titles are logical stream units that correspond to a whole inside the dvd.
+ * Several title can point to the same part of the physical DVD, and give
+ * map to different anglesfor instance.
+ *****************************************************************************/
+static int ReadTitle( ifo_t * p_ifo, title_t * p_title, int i_block, int i_bytes )
+{
+ u8 p_buf[DVD_LB_SIZE];
+ u8 * p_tmp;
+ int i_start;
+ u16 i_audio;
+ u32 i_spu;
+ int i;
+
+ p_tmp = FillBuffer( p_ifo, p_buf, i_block ) + i_bytes;
+
+ i_start = p_ifo->i_pos;
+
+ //fprintf( stderr, "PGC @ %d + %d\n", p_ifo->i_pos, i_bytes );
+
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2);
+ p_title->i_chapter_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ p_title->i_cell_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "title: Prg: %d Cell: %d\n",p_title->i_chapter_nb,p_title->i_cell_nb );
+ p_title->i_play_time = ReadDouble( p_ifo, p_buf, &p_tmp );
+ p_title->i_prohibited_user_op = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ for( i = 0 ; i < 8 ; i++ )
+ {
+ i_audio = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->pi_audio_status[i].i_foo = i_audio & 0xff;
+ i_audio >>= 8;
+ p_title->pi_audio_status[i].i_position = i_audio & 0x07;
+ i_audio >>= 7;
+ p_title->pi_audio_status[i].i_available = i_audio;
+ }
+
+ for( i = 0 ; i < 32 ; i++ )
+ {
+ i_spu = ReadDouble( p_ifo, p_buf, &p_tmp );
+ p_title->pi_spu_status[i].i_position_pan = i_spu & 0x1f;
+ i_spu >>= 8;
+ p_title->pi_spu_status[i].i_position_letter = i_spu & 0x1f;
+ i_spu >>= 8;
+ p_title->pi_spu_status[i].i_position_wide = i_spu & 0x1f;
+ i_spu >>= 8;
+ p_title->pi_spu_status[i].i_position_43 = i_spu & 0x1f;
+ i_spu >>= 7;
+ p_title->pi_spu_status[i].i_available = i_spu;
+ }
+
+ p_title->i_next_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->i_prev_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->i_go_up_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->i_still_time = ReadByte( p_ifo, p_buf, &p_tmp );
+ p_title->i_play_mode = ReadByte( p_ifo, p_buf, &p_tmp );
+
+ for( i = 0 ; i < 16 ; i++ )
+ {
+ /* FIXME : We have to erase the extra bit */
+ p_title->pi_yuv_color[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
+ }
+
+ p_title->i_command_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->i_chapter_map_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->i_cell_play_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->i_cell_pos_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
+
+ /* parsing of command_t */
+ if( p_title->i_command_start_byte )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, i_start +
+ OFF2LB( p_title->i_command_start_byte + i_bytes ) )
+ + ( (p_title->i_command_start_byte + i_bytes) & 0x7ff );
+
+ /* header */
+ p_title->command.i_pre_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->command.i_post_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ p_title->command.i_cell_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+
+ /* pre-title commands */
+ if( p_title->command.i_pre_command_nb )
+ {
+ p_title->command.p_pre_command =
+ malloc( p_title->command.i_pre_command_nb
+ * sizeof(command_desc_t) );
+
+ if( p_title->command.p_pre_command == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadTitle" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_title->command.i_pre_command_nb ; i++ )
+ {
+ p_title->command.p_pre_command[i] =
+ ReadQuad( p_ifo, p_buf, &p_tmp );
+ }
+ }
+ else
+ {
+ p_title->command.p_pre_command = NULL;
+ }
+
+ /* post-title commands */
+ if( p_title->command.i_post_command_nb )
+ {
+ p_title->command.p_post_command =
+ malloc( p_title->command.i_post_command_nb
+ * sizeof(command_desc_t) );
+
+ if( p_title->command.p_post_command == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadTitle" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_title->command.i_post_command_nb ; i++ )
+ {
+ p_title->command.p_post_command[i] =
+ ReadQuad( p_ifo, p_buf, &p_tmp );
+ }
+ }
+ else
+ {
+ p_title->command.p_post_command = NULL;
+ }
+
+ /* cell commands */
+ if( p_title->command.i_cell_command_nb )
+ {
+ p_title->command.p_cell_command =
+ malloc( p_title->command.i_cell_command_nb
+ * sizeof(command_desc_t) );
+
+ if( p_title->command.p_cell_command == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadTitle" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_title->command.i_cell_command_nb ; i++ )
+ {
+ p_title->command.p_cell_command[i] =
+ ReadQuad( p_ifo, p_buf, &p_tmp );
+ }
+ }
+ else
+ {
+ p_title->command.p_cell_command = NULL;
+ }
+ }
+
+ /* parsing of chapter_map_t: it gives the entry cell for each chapter */
+ if( p_title->i_chapter_map_start_byte )
+ {
+ p_ifo->i_pos = dvdcss_seek( p_ifo->dvdhandle,
+ OFF2LB( i_start + p_title->i_chapter_map_start_byte ),
+ DVDCSS_NOFLAGS );
+
+ p_title->chapter_map.pi_start_cell =
+ malloc( p_title->i_chapter_nb * sizeof(chapter_map_t) );
+
+ if( p_title->chapter_map.pi_start_cell == NULL )
+ {
+//X intf_Err( p_input, "out of memory in Read Title" );
+ return -1;
+ }
+
+ ReadBytes( p_ifo, p_buf, &p_tmp, p_title->chapter_map.pi_start_cell,
+ p_title->i_chapter_nb );
+ }
+ else
+ {
+ p_title->chapter_map.pi_start_cell = NULL;
+ }
+
+ /* parsing of cell_play_t */
+ if( p_title->i_cell_play_start_byte )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, i_start +
+ OFF2LB( p_title->i_cell_play_start_byte+i_bytes ) )
+ + ( (p_title->i_cell_play_start_byte+i_bytes) & 0x7ff );
+
+ p_title->p_cell_play = malloc( p_title->i_cell_nb
+ * sizeof(cell_play_t) );
+
+ if( p_title->p_cell_play == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadTitle" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_title->i_cell_nb ; i++ )
+ {
+#define PLAY p_title->p_cell_play[i]
+ PLAY.i_category = ReadWord( p_ifo, p_buf, &p_tmp );
+ PLAY.i_still_time = ReadByte( p_ifo, p_buf, &p_tmp );
+ PLAY.i_command_nb = ReadByte( p_ifo, p_buf, &p_tmp );
+ PLAY.i_play_time = ReadDouble( p_ifo, p_buf, &p_tmp );
+ PLAY.i_first_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ PLAY.i_first_ilvu_vobu_esector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ PLAY.i_last_vobu_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+ PLAY.i_last_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+#undef PLAY
+ }
+ }
+
+ /* Parsing of cell_pos_t */
+ if( p_title->i_cell_pos_start_byte )
+ {
+ p_tmp = FillBuffer( p_ifo, p_buf, i_start +
+ OFF2LB( p_title->i_cell_pos_start_byte + i_bytes ) )
+ + ( (p_title->i_cell_pos_start_byte + i_bytes) & 0x7ff );
+
+ p_title->p_cell_pos = malloc( p_title->i_cell_nb
+ * sizeof(cell_pos_t) );
+
+ if( p_title->p_cell_pos == NULL )
+ {
+//X intf_Err( p_input, "out of memory" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_title->i_cell_nb ; i++ )
+ {
+ p_title->p_cell_pos[i].i_vob_id = ReadWord( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ p_title->p_cell_pos[i].i_cell_id = ReadByte( p_ifo, p_buf, &p_tmp );
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeTitle: frees alla structure allocated by a call to ReadTitle
+ *****************************************************************************/
+static int FreeTitle( title_t * p_title )
+{
+ if( p_title->i_command_start_byte )
+ {
+ if( p_title->command.i_pre_command_nb )
+ {
+ free( p_title->command.p_pre_command );
+ }
+
+ if( p_title->command.i_post_command_nb )
+ {
+ free( p_title->command.p_post_command );
+ }
+
+ if( p_title->command.i_cell_command_nb )
+ {
+ free( p_title->command.p_cell_command );
+ }
+ }
+
+ if( p_title->i_chapter_map_start_byte )
+ {
+ free( p_title->chapter_map.pi_start_cell );
+ }
+
+ if( p_title->i_cell_play_start_byte )
+ {
+ free( p_title->p_cell_play );
+ }
+
+ if( p_title->i_cell_pos_start_byte )
+ {
+ free( p_title->p_cell_pos );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * ReadUnitInf : Fills Menu Language Unit Table/ PGC Info Table
+ *****************************************************************************/
+static int ReadUnitInf( ifo_t * p_ifo, unit_inf_t * p_unit_inf,
+ int i_block, int i_bytes )
+{
+ u8 p_buf[DVD_LB_SIZE];
+ u8 * p_tmp;
+ int i_start;
+ int i;
+
+ p_tmp = FillBuffer( p_ifo, p_buf, i_block ) + i_bytes;
+
+ i_start = p_ifo->i_pos;
+ //fprintf( stderr, "Unit\n" );
+
+ p_unit_inf->i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "Unit nb: %d\n", p_unit_inf->i_title_nb );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ p_unit_inf->i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ p_unit_inf->p_title =
+ malloc( p_unit_inf->i_title_nb * sizeof(unit_title_t) );
+ if( p_unit_inf->p_title == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadUnit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
+ {
+#define TITLE p_unit_inf->p_title[i]
+ TITLE.i_category_mask = ReadByte( p_ifo, p_buf, &p_tmp );
+ TITLE.i_category = ReadByte( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "cat mask %d: %x cat %x\n", i, TITLE.i_category_mask, TITLE.i_category );
+ TITLE.i_parental_mask = ReadWord( p_ifo, p_buf, &p_tmp );
+ TITLE.i_title_start_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+#undef TITLE
+ }
+
+ for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
+ {
+ //fprintf( stderr, "Unit: PGC %d @ %d\n", i, p_ifo->i_pos );
+ ReadTitle( p_ifo, &p_unit_inf->p_title[i].title, i_start +
+ OFF2LB( p_unit_inf->p_title[i].i_title_start_byte + i_bytes ),
+ (p_unit_inf->p_title[i].i_title_start_byte+i_bytes) & 0x7ff );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeUnitInf : frees a structure allocated by ReadUnit
+ *****************************************************************************/
+static int FreeUnitInf( unit_inf_t * p_unit_inf )
+{
+ int i;
+
+ if( p_unit_inf->p_title != NULL )
+ {
+ for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
+ {
+ FreeTitle( &p_unit_inf->p_title[i].title );
+ }
+
+ free( p_unit_inf->p_title );
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * ReadTitleUnit: Fills the Title Unit structure.
+ *****************************************************************************/
+static int ReadTitleUnit( ifo_t * p_ifo, title_unit_t * p_title_unit,
+ int i_block )
+{
+ u8 p_buf[DVD_LB_SIZE];
+ u8 * p_tmp;
+ int i;
+ int i_start;
+
+ p_tmp = FillBuffer( p_ifo, p_buf, i_block );
+ i_start = p_ifo->i_pos;
+ //fprintf( stderr, "Unit Table\n" );
+
+ p_title_unit->i_unit_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ p_title_unit->i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ //fprintf(stderr, "Unit: nb %d last %d\n", p_title_unit->i_unit_nb, p_title_unit->i_last_byte );
+
+ p_title_unit->p_unit = malloc( p_title_unit->i_unit_nb * sizeof(unit_t) );
+ if( p_title_unit->p_unit == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadTitleUnit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
+ {
+ //ReadBytes( p_ifo, p_buf, &p_tmp, p_title_unit->p_unit[i].ps_lang_code, 2 );
+ p_title_unit->p_unit[i].i_lang_code = ReadWord( p_ifo, p_buf, &p_tmp );
+ //fprintf( stderr, "lang %d %x\n", i,p_title_unit->p_unit[i].i_lang_code );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ p_title_unit->p_unit[i].i_existence_mask =
+ ReadByte( p_ifo, p_buf, &p_tmp );
+ p_title_unit->p_unit[i].i_unit_inf_start_byte =
+ ReadDouble( p_ifo, p_buf, &p_tmp );
+ }
+
+ p_title_unit->p_unit_inf =
+ malloc( p_title_unit->i_unit_nb * sizeof(unit_inf_t) );
+ if( p_title_unit->p_unit_inf == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadTitleUnit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
+ {
+ ReadUnitInf( p_ifo, &p_title_unit->p_unit_inf[i], i_start +
+ OFF2LB( p_title_unit->p_unit[i].i_unit_inf_start_byte ),
+ p_title_unit->p_unit[i].i_unit_inf_start_byte & 0x7ff );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeTitleUnit: frees a structure allocateed by ReadTitleUnit
+ *****************************************************************************/
+static int FreeTitleUnit( title_unit_t * p_title_unit )
+{
+ int i;
+
+ if( p_title_unit->p_unit_inf != NULL )
+ {
+ for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
+ {
+ FreeUnitInf( &p_title_unit->p_unit_inf[i] );
+ }
+
+ free( p_title_unit->p_unit_inf );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * ReadCellInf : Fills the Cell Information structure.
+ *****************************************************************************/
+static int ReadCellInf( ifo_t * p_ifo, cell_inf_t * p_cell_inf, int i_block )
+{
+ u8 p_buf[DVD_LB_SIZE];
+ u8 * p_tmp;
+ int i_start;
+ int i;
+
+ p_tmp = FillBuffer( p_ifo, p_buf, i_block );
+ i_start = p_ifo->i_pos;
+// fprintf( stderr, "CELL ADD\n" );
+
+ p_cell_inf->i_vob_nb = ReadWord( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
+ p_cell_inf->i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+
+ p_cell_inf->i_cell_nb = (p_cell_inf->i_last_byte + 1/* - 7*/) / sizeof(cell_map_t);
+
+/* fprintf( stderr, "Cell inf: vob %d, %d cells, last byte %d\n", p_cell_inf->i_vob_nb, p_cell_inf->i_cell_nb, p_cell_inf->i_last_byte );
+*/
+ p_cell_inf->p_cell_map =
+ malloc( p_cell_inf->i_cell_nb *sizeof(cell_map_t) );
+ if( p_cell_inf->p_cell_map == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadCellInf" );
+ return -1;
+ }
+
+ for( i = 0 ; i < p_cell_inf->i_cell_nb ; i++ )
+ {
+#define MAP p_cell_inf->p_cell_map[i]
+ MAP.i_vob_id = ReadWord( p_ifo, p_buf, &p_tmp );
+ MAP.i_cell_id = ReadByte( p_ifo, p_buf, &p_tmp );
+ DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
+ MAP.i_first_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+/* fprintf(stderr, "sector[%d] %d (%d)\n", i,ntohl(*(u32*)(p_tmp)), p_ifo->i_pos);*/
+ MAP.i_last_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
+#undef MAP
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeCellInf : frees structures allocated by ReadCellInf
+ *****************************************************************************/
+static int FreeCellInf( cell_inf_t * p_cell_inf )
+{
+ free( p_cell_inf->p_cell_map );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * ReadVobuMap : Fills the VOBU Map structure.
+ *****************************************************************************/
+static int ReadVobuMap( ifo_t * p_ifo, vobu_map_t * p_vobu_map, int i_block )
+{
+ u8 p_buf[DVD_LB_SIZE];
+ u8 * p_tmp;
+ int i_start;
+ int i, i_max;
+
+ p_tmp = FillBuffer( p_ifo, p_buf, i_block );
+ i_start = p_ifo->i_pos;
+ //fprintf( stderr, "VOBU ADMAP\n" );
+
+ p_vobu_map->i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
+ i_max = ( i_start + p_vobu_map->i_last_byte + 1 - p_ifo->i_pos )
+ / sizeof(u32);
+
+ p_vobu_map->pi_vobu_start_sector = malloc( i_max * sizeof(u32) );
+ if( p_vobu_map->pi_vobu_start_sector == NULL )
+ {
+//X intf_Err( p_input, "out of memory in ReadVobuMap" );
+ return -1;
+ }
+
+ for( i = 0 ; i < i_max ; i++ )
+ {
+ p_vobu_map->pi_vobu_start_sector[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeVobuMap: frees structures allocated by ReadVobuMap
+ *****************************************************************************/
+static int FreeVobuMap( vobu_map_t * p_vobu_map )
+{
+ free( p_vobu_map->pi_vobu_start_sector );
+
+ return 0;
+}
+
+/*
+ * IFO virtual machine : a set of commands that give the
+ * interactive behaviour of the dvd
+ */
+#if 0
+
+#define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
+#define OP_VAL_8(i) ((com.data.pi_8[i]))
+
+static char ifo_reg[][80]=
+{
+ "Menu_Language_Code",
+ "Audio_Stream_#",
+ "SubPicture_Stream_#",
+ "Angle_#",
+ "VTS_#",
+ "VTS_Title_#",
+ "PGC_#",
+ "PTT_#",
+ "Highlighted_Button_#",
+ "Nav_Timer",
+ "TimedPGC",
+ "Karaoke_audio_mixing_mode",
+ "Parental_mgmt_country_code",
+ "Parental_Level",
+ "Player_Video_Cfg",
+ "Player_Audio_Cfg",
+ "Audio_language_code_setting",
+ "Audio_language_extension_code",
+ "SPU_language_code_setting",
+ "SPU_language_extension_code",
+ "?Player_Regional_Code",
+ "Reserved_21",
+ "Reserved_22",
+ "Reserved_23"
+};
+
+static char * IfoMath( char val )
+{
+ static char math_op[][10] =
+ {
+ "none",
+ "=",
+ "<->", // swap
+ "+=",
+ "-=",
+ "*=",
+ "/=",
+ "%=",
+ "rnd", // rnd
+ "&=",
+ "|=",
+ "^=",
+ "??", // invalid
+ "??", // invalid
+ "??", // invalid
+ "??" // invalid
+ };
+
+ return (char *) math_op[val & 0x0f];
+}
+
+
+char ifo_cmp[][10] =
+{
+ "none",
+ "&&",
+ "==",
+ "!=",
+ ">=",
+ ">",
+ "<",
+ "<="
+};
+
+char ifo_parental[][10] =
+{
+ "0",
+ "G",
+ "2",
+ "PG",
+ "PG-13",
+ "5",
+ "R",
+ "NC-17"
+};
+
+char ifo_menu_id[][80] =
+{
+ "-0-",
+ "-1-",
+ "Title (VTS menu)",
+ "Root",
+ "Sub-Picture",
+ "Audio",
+ "Angle",
+ "Part of Title",
+};
+
+char * IfoMenuName( char index )
+{
+ return ifo_menu_id[index&0x07];
+}
+
+static void IfoRegister( u16 i_data, u8 i_direct)
+{
+ if( i_direct )
+ {
+ if( 0/*isalpha( i_data >> 8 & 0xff )*/ )
+ {
+ printf("'%c%c'", i_data>>8&0xff, i_data&0xff);
+ }
+ else
+ {
+ printf("0x%02x", i_data);
+ }
+ }
+ else
+ {
+ if( i_data & 0x80 )
+ {
+ i_data &= 0x1f;
+
+ if( i_data > 0x17 )
+ {
+ printf("s[ILL]");
+ }
+ else
+ {
+ printf("s[%s]", ifo_reg[i_data]);
+ }
+ }
+ else
+ {
+ i_data &= 0x1f;
+
+ if( i_data > 0xf )
+ {
+ printf("r[ILL]");
+ }
+ else
+ {
+ printf("r[0x%02x]", i_data);
+ }
+ }
+ }
+}
+
+static void IfoAdvanced( u8 *pi_code )
+{
+ u8 i_cmd = pi_code[0];
+
+ printf(" { ");
+
+ if( pi_code[1]>>2 )
+ {
+ printf( " Highlight button %d; ", pi_code[1]>>2 );
+ }
+
+ if( i_cmd == 0xff )
+ {
+ printf( " Illegal " );
+ }
+
+ if( i_cmd == 0x00 )
+ {
+ printf( "ReSuME %d", pi_code[7] );
+ }
+ else if( ( i_cmd & 0x06) == 0x02 )
+ { // XX01Y
+ printf ("Link to %s cell ", ( i_cmd & 0x01 ) ? "prev" : "next");
+ }
+ else
+ {
+ printf( "advanced (0x%02x) ", i_cmd );
+ }
+ printf(" } ");
+}
+
+static void IfoJmp( ifo_command_t com )
+{
+
+ printf ("jmp ");
+
+ switch( com.i_sub_cmd )
+ {
+ case 0x01:
+ printf( "Exit" );
+ break;
+ case 0x02:
+ printf( "VTS 0x%02x", OP_VAL_8(3) );
+ break;
+ case 0x03:
+ printf( "This VTS Title 0x%02x", OP_VAL_8(3) );
+ break;
+ case 0x05:
+ printf( "This VTS Title 0x%02x Part 0x%04x",
+ OP_VAL_8(3),
+ OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ case 0x06:
+#if 0
+ printf ("in SystemSpace ");
+ switch (OP_VAL_8(3)>>4) {
+ case 0x00:
+ printf ("to play first PGC");
+ break;
+ case 0x01: {
+ printf ("to menu \"%s\"", decode_menuname (OP_VAL_8(3)));
+ }
+ break;
+ case 0x02:
+ printf ("to VTS 0x%02x and TTN 0x%02x", OP_VAL_8(1), OP_VAL_8(2));
+ break;
+ case 0x03:
+ printf ("to VMGM PGC number 0x%02x", OP_VAL_8(0)<<8 | OP_VAL_8(1));
+ break;
+ case 0x08:
+ printf ("vts 0x%02x lu 0x%02x menu \"%s\"", OP_VAL_8(2), OP_VAL_8(1), decode_menuname (OP_VAL_8(3)));
+ break;
+#else
+ switch( OP_VAL_8(3)>>6 )
+ {
+ case 0x00:
+ printf( "to play first PGC" );
+ break;
+ case 0x01:
+ printf( "to VMG title menu (?)" );
+ break;
+ case 0x02:
+ printf( "vts 0x%02x lu 0x%02x menu \"%s\"",
+ OP_VAL_8(2),
+ OP_VAL_8(1),
+ IfoMenuName( OP_VAL_8(3)&0xF ) );
+ break;
+ case 0x03:
+ printf( "vmg pgc 0x%04x (?)", ( OP_VAL_8(0)<<8) | OP_VAL_8(1) );
+ break;
+#endif
+ }
+ break;
+ case 0x08:
+#if 0
+ switch(OP_VAL_8(3)>>4) {
+ case 0x00:
+ printf ("system first pgc");
+ break;
+ case 0x01:
+ printf ("system title menu");
+ break;
+ case 0x02:
+ printf ("system menu \"%s\"", decode_menuname (OP_VAL_8(3)));
+ break;
+ case 0x03:
+ printf ("system vmg pgc %02x ????", OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ case 0x08:
+ printf ("system lu 0x%02x menu \"%s\"", OP_VAL_8(2), decode_menuname (OP_VAL_8(3)));
+ break;
+ case 0x0c:
+ printf ("system vmg pgc 0x%02x", OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ }
+#else
+ // OP_VAL_8(2) is number of cell
+ // it is processed BEFORE switch
+ // under some conditions, it is ignored
+ // I don't understand exactly what it means
+ printf( " ( spec cell 0x%02X ) ", OP_VAL_8(2) );
+
+ switch( OP_VAL_8(3)>>6 )
+ {
+ case 0:
+ printf( "to FP PGC" );
+ break;
+ case 1:
+ printf( "to VMG root menu (?)" );
+ break;
+ case 2:
+ printf( "to VTS menu \"%s\" (?)",
+ IfoMenuName(OP_VAL_8(3)&0xF) );
+ break;
+ case 3:
+ printf( "vmg pgc 0x%02x (?)", (OP_VAL_8(0)<<8)|OP_VAL_8(1) );
+ break;
+ }
+#endif
+ break;
+ }
+}
+
+static void IfoLnk( ifo_command_t com )
+{
+ u16 i_button=OP_VAL_8(4)>>2;
+
+ printf ("lnk to ");
+
+ switch( com.i_sub_cmd )
+ {
+ case 0x01:
+ IfoAdvanced( &OP_VAL_8(4) );
+ break;
+
+ case 0x04:
+ printf( "PGC 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 0x05:
+ printf( "PTT 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 0x06:
+ printf( "Program 0x%02x this PGC", OP_VAL_8(5) );
+ break;
+
+ case 0x07:
+ printf( "Cell 0x%02x this PGC", OP_VAL_8(5) );
+ break;
+ default:
+ return;
+ }
+
+ if( i_button )
+ {
+ printf( ", Highlight 0x%02x", OP_VAL_8(4)>>2 );
+ }
+
+}
+
+void IfoSetSystem( ifo_command_t com )
+{
+ switch( com.i_cmd )
+ {
+ case 1: {
+ int i;
+
+ for( i=1; i<=3; i++ )
+ {
+ if( OP_VAL_8(i)&0x80 )
+ {
+ if( com.i_direct )
+ {
+ printf ("s[%s] = 0x%02x;", ifo_reg[i], OP_VAL_8(i)&0xf);
+ }
+ else
+ {
+ printf ("s[%s] = r[0x%02x];", ifo_reg[i], OP_VAL_8(i)&0xf);
+ }
+ }
+ }
+#if 0
+ if(op->direct) {
+ if(OP_VAL_8(1]&0x80)
+ printf ("s[%s] = 0x%02x;", reg_name[1], OP_VAL_8(1]&0xf);
+ if(OP_VAL_8(2)&0x80)
+//DENT: lwhat about 0x7f here ???
+ printf ("s[%s] = 0x%02x;", reg_name[2], OP_VAL_8(2)&0x7f);
+ if(OP_VAL_8(3)&0x80)
+ printf ("s[%s] = 0x%02x;", reg_name[3], OP_VAL_8(3)&0xf);
+ } else {
+ if(OP_VAL_8(1)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[1], OP_VAL_8(1)&0xf);
+ if(OP_VAL_8(2)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[2], OP_VAL_8(2)&0xf);
+ if(OP_VAL_8(3)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[3], OP_VAL_8(3)&0xf);
+ }
+#endif
+ }
+ break;
+ case 2:
+ if( com.i_direct )
+ {
+ printf( "s[%s] = 0x%02x", ifo_reg[9], OP_VAL_16(0) );
+ }
+ else
+ {
+ printf( "s[%s] = r[0x%02x]", ifo_reg[9], OP_VAL_8(1)&0x0f );
+ }
+
+ printf( "s[%s] = (s[%s]&0x7FFF)|0x%02x",
+ ifo_reg[10], ifo_reg[10], OP_VAL_16(1)&0x8000);
+ break;
+ case 3:
+ if( com.i_direct )
+ {
+ printf( "r[0x%02x] = 0x%02x", OP_VAL_8(3)&0x0f, OP_VAL_16(0) );
+ }
+ else
+ {
+ printf ("r[r[0x%02x]] = r[0x%02x]",
+ OP_VAL_8(3)&0x0f, OP_VAL_8(1)&0x0f);
+ }
+ break;
+ case 4:
+ //actually only bits 00011100 00011100 are set
+ if( com.i_direct )
+ {
+ printf ("s[%s] = 0x%02x", ifo_reg[11], OP_VAL_16(1));
+ }
+ else
+ {
+ printf ("s[%s] = r[0x%02x]", ifo_reg[11], OP_VAL_8(3)&0x0f );
+ }
+ break;
+ case 6:
+ //actually,
+ //s[%s]=(r[%s]&0x3FF) | (0x%02x << 0xA);
+ //but it is way too ugly
+ if( com.i_direct )
+ {
+ printf( "s[%s] = 0x%02x", ifo_reg[8], OP_VAL_8(2)>>2 );
+ }
+ else
+ {
+ printf( "s[%s] = r[0x%02x]", ifo_reg[8], OP_VAL_8(3)&0x0f );
+ }
+ break;
+ default:
+ printf ("unknown");
+ }
+}
+
+static void IfoSet( ifo_command_t com )
+{
+ IfoRegister( OP_VAL_16(0), 0 );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+ IfoRegister( OP_VAL_16(1), com.i_direct );
+}
+
+/*****************************************************************************
+ * CommandRead : translates the command strings in ifo into command
+ * structures.
+ *****************************************************************************/
+void CommandRead( ifo_command_t com )
+{
+ u8* pi_code = (u8*)(&com);
+
+ switch( com.i_type )
+ {
+ /* Goto */
+ case 0:
+ /* Main command */
+ if( !pi_code[1] )
+ {
+ printf( "NOP\n" );
+ }
+ else
+ {
+ if( com.i_cmp )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
+ ifo_cmp[com.i_cmp]);
+ IfoRegister (OP_VAL_16(1), com.i_dir_cmp);
+ printf (") ");
+ }
+
+ /* Sub command */
+ switch( com.i_sub_cmd )
+ {
+ case 1:
+ printf( "goto Line 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 2:
+ printf( "stop VM" );
+ break;
+
+ case 3:
+ printf( "Set Parental Level To %s and goto Line 0x%02x",
+ ifo_parental[OP_VAL_8(4)&0x7],
+ OP_VAL_8(5) );
+ break;
+
+ default:
+ printf( "Illegal" );
+ break;
+ }
+ }
+ break;
+
+ /* Lnk */
+ case 1:
+ /* Main command */
+ if( !pi_code[1] )
+ {
+ printf( "NOP\n" );
+ }
+ else
+ {
+ if( com.i_direct )
+ {
+ if( com.i_cmp )
+ {
+ printf( "if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f,
+ ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_8(5), 0 );
+ printf( ") " );
+ }
+
+ /* Sub command */
+ IfoJmp( com );
+ }
+ else
+ {
+ if( com.i_cmp )
+ {
+ printf( "if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
+ ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_16(1), com.i_dir_cmp );
+ printf( ") " );
+ }
+
+ /* Sub command */
+ IfoLnk( com );
+ }
+ }
+ break;
+
+ /* SetSystem */
+ case 2:
+ if( !pi_code[1] )
+ {
+ IfoSetSystem( com );
+ }
+ else if( com.i_cmp && !com.i_sub_cmd )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f, ifo_cmp[com.i_cmp]);
+ IfoRegister( OP_VAL_8(5), 0 );
+ printf (") ");
+ IfoSetSystem( com );
+ }
+ else if( !com.i_cmp && com.i_sub_cmd )
+ {
+ printf( "if (" );
+ IfoSetSystem( com );
+ printf( ") " );
+ IfoLnk( com );
+ }
+ else
+ {
+ printf("nop");
+ }
+ break;
+
+ /* Set */
+ case 3:
+ if( ! pi_code[1] )
+ {
+ IfoSet( com );
+ }
+ else if( com.i_cmp && !com.i_sub_cmd )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(0)&0x0f, ifo_cmp[com.i_cmp]);
+ IfoRegister( OP_VAL_16(2), com.i_dir_cmp );
+ printf (") ");
+ IfoSet( com );
+ }
+ else if( !com.i_cmp && com.i_sub_cmd )
+ {
+ printf ("if (");
+ IfoSet( com );
+ printf (") ");
+ IfoLnk( com );
+ }
+ else
+ {
+ printf( "nop" );
+ }
+ break;
+
+ /*
+ * math command on r[opcode[1]] and
+ * direct?be2me_16(OP_VAL_8(0)):reg[OP_VAL_8(1)] is executed
+ * ( unless command is swap; then r[opcode[1]] and r[OP_VAL_8(1)]
+ * are swapped )
+ * boolean operation cmp on r[opcode[1]] and
+ * dir_cmp?be2me_16(OP_VAL_8(1)[1]):reg[OP_VAL_8(3)] is executed
+ * on true result, buttons(c[6], c[7]) is called
+ * problem is 'what is buttons()'
+ */
+ case 4:
+ printf( "r[0x%X] ", pi_code[1] );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+ if( com.i_cmd == 2 )
+ {
+ printf( "r[0x%X] ", OP_VAL_8(1) );
+ }
+ else
+ {
+ IfoRegister( OP_VAL_16(0), com.i_direct );
+ }
+ printf("; ");
+
+ printf( "if ( r[%d] %s ", pi_code[1], ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_8(1), com.i_dir_cmp );
+ printf( " ) then {" );
+ IfoAdvanced( &OP_VAL_8(4) );
+ printf( "}" );
+ break;
+
+ /*
+ * opposite to case 4: boolean, math and buttons.
+ */
+ case 5:
+ case 6:
+ printf("if (");
+
+ if( !com.i_direct && com.i_dir_cmp )
+ {
+ printf( "0x%X", OP_VAL_16(1) );
+ }
+ else
+ {
+ IfoRegister( OP_VAL_8(3), 0 );
+ if( OP_VAL_8(3)&0x80 )
+ {
+ printf( "s[%s]", ifo_reg[OP_VAL_8(3)&0x1F] );
+ }
+ else
+ {
+ printf( "r[0x%X]", OP_VAL_8(3)&0x1F);
+ // 0x1F is either not a mistake,
+ // or Microsoft programmer's mistake!!!
+ }
+ }
+
+ printf( " %s r[0x%X] ", ifo_cmp[com.i_cmp],
+ com.i_direct ? OP_VAL_8(2) : OP_VAL_8(1) );
+ printf( " ) then {" );
+ printf( "r[0x%X] ", pi_code[1] & 0xF );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+
+ if( com.i_cmd == 0x02 ) // swap
+ {
+ printf("r[0x%X] ", OP_VAL_8(0)&0x1F);
+ }
+ else
+ {
+ if( com.i_direct )
+ {
+ printf( "0x%X", OP_VAL_16(0) );
+ }
+ else
+ {
+ if( OP_VAL_8(0) & 0x80 )
+ {
+ printf("s[%s]", ifo_reg[OP_VAL_8(0) & 0x1F] );
+ }
+ else
+ {
+ printf("r[0x%X]", OP_VAL_8(0) & 0x1F );
+ }
+ }
+ }
+
+ printf("; ");
+ IfoAdvanced( &OP_VAL_8(4) );
+ printf("}");
+
+ break;
+
+ default:
+ printf( "Unknown Command\n" );
+ break;
+ }
+
+ return;
+}
+
+/*****************************************************************************
+ * CommandPrint : print in clear text (I hope so !) what a command does
+ *****************************************************************************/
+void CommandPrint( ifo_t ifo )
+{
+ return;
+}
+
+#endif
+
+/*****************************************************************************
+ * ReadByte and so
+ *****************************************************************************/
+static u8* FillBuffer( ifo_t* p_ifo, u8* p_buf, int i_pos )
+{
+ p_ifo->i_pos = dvdcss_seek( p_ifo->dvdhandle, i_pos, DVDCSS_NOFLAGS );
+ dvdcss_read( p_ifo->dvdhandle, p_buf, 1, DVDCSS_NOFLAGS );
+
+ return p_buf;
+}
+
+static void ReadBytes( ifo_t* p_ifo, u8* p_buf, u8** pp_tmp,
+ u8* pi_dest, int i_nb )
+{
+ if( i_nb > DVD_LB_SIZE )
+ {
+//X intf_Err( p_input, "excessive ReadBytes call (%i)", i_nb );
+ }
+
+ if( *pp_tmp + i_nb >= p_buf + DVD_LB_SIZE )
+ {
+ int i_spare = (int)( (p_buf + DVD_LB_SIZE) - *pp_tmp );
+
+ /* Copy the bytes remaining in the current buffer */
+ memcpy( pi_dest, *pp_tmp, i_spare );
+ pi_dest += i_spare;
+ i_nb -= i_spare;
+
+ /* Load the next buffer */
+ *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 );
+ }
+
+ memcpy( pi_dest, *pp_tmp, i_nb );
+ *pp_tmp += i_nb;
+
+ return;
+}
+
+static void DumpBytes( ifo_t* p_ifo, u8* p_buf, u8** pp_tmp, int i_nb )
+{
+ if( i_nb > DVD_LB_SIZE )
+ {
+//X intf_Err( p_input, "excessive DumpBytes call (%i)", i_nb );
+ }
+
+ *pp_tmp += i_nb;
+
+ if( *pp_tmp >= p_buf + DVD_LB_SIZE )
+ {
+ /* If we went too far, load the next buffer */
+ *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 )
+ + (int)( (*pp_tmp) - (p_buf + DVD_LB_SIZE) );
+ }
+
+ return;
+}
+
+#define ADDBYTE \
+ if( *pp_tmp >= p_buf + DVD_LB_SIZE ) \
+ { \
+ *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 ); \
+ } \
+ i_ret <<= 8; i_ret |= **pp_tmp; (*pp_tmp)++;
+
+static u8 ReadByte( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
+{
+ u8 i_ret = 0;
+ ADDBYTE;
+ return i_ret;
+}
+
+static u16 ReadWord( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
+{
+ u16 i_ret = 0;
+ ADDBYTE; ADDBYTE;
+ return i_ret;
+}
+
+static u32 ReadDouble( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
+{
+ u32 i_ret = 0;
+ ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE;
+ return i_ret;
+}
+
+static u64 ReadQuad( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
+{
+ u64 i_ret = 0;
+ ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE;
+ return i_ret;
+}
+
--- /dev/null
+/*****************************************************************************
+ * dvd_ifo.h: Structures for ifo parsing
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: ifo.h,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * based on:
+ * - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at>
+ * - IFO structure documentation by Thomas Mirlacher, Björn Englund,
+ * Håkan Hjort
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Common structures for Video Management and Video Title sets
+ *****************************************************************************/
+
+/*
+ * Program Chain structures
+ */
+typedef struct ifo_video_s
+{
+ u8 i_compression ;// 2;
+ u8 i_system ;// 2;
+ u8 i_ratio ;// 2;
+ u8 i_perm_displ ;// 2;
+
+ u8 i_line21_1 ;// 1;
+ u8 i_line21_2 ;// 1;
+ u8 i_source_res ;// 2;
+ u8 i_letterboxed ;// 1;
+ u8 i_mode ;// 1;
+} ifo_video_t;
+
+/* Audio type information */
+typedef struct ifo_audio_s
+{
+ u8 i_coding_mode ;// 3;
+ u8 i_multichannel_extension ;// 1;
+ u8 i_type ;// 2;
+ u8 i_appl_mode ;// 2;
+
+ u8 i_quantization ;// 2;
+ u8 i_sample_freq ;// 2;
+ u8 i_test ;// 1;
+ u8 i_num_channels ;// 3;
+ u16 i_lang_code ;// 16; // <char> description
+ u8 i_foo ;// 8; // 0x00000000 ?
+ u8 i_caption ;// 8;
+ u8 i_bar ;// 8; // 0x00000000 ?
+} ifo_audio_t;
+
+/* Audio Status */
+typedef struct audio_status_s
+{
+ u8 i_available; // 1
+ u8 i_position; // 7
+ u8 i_foo; // 8
+} audio_status_t;
+
+typedef struct ifo_spu_t
+{
+ u16 i_prefix ;// 16; // 0x0100 ?
+ u16 i_lang_code ;// 16; // <char> description
+ u8 i_foo ;// 8; // dont know
+ u8 i_caption ;// 8; // 0x00 ?
+} ifo_spu_t;
+
+/* Subpicture status */
+typedef struct spu_status_s
+{
+ u8 i_available; //1
+ u8 i_position_43; //7
+ u8 i_position_wide; //8
+ u8 i_position_letter; //8
+ u8 i_position_pan; //8
+} spu_status_t;
+
+
+/* Ifo vitual machine Commands */
+typedef struct command_desc_s
+{
+ u8 i_type :3;
+ u8 i_direct :1;
+ u8 i_cmd :4;
+ u8 i_dir_cmp :1;
+ u8 i_cmp :3;
+ u8 i_sub_cmd :4;
+ union
+ {
+ u8 pi_8[6];
+ u16 pi_16[3];
+ } data;
+} command_desc_t;
+
+/* Program Chain Command Table
+ - start at i_pgc_com_tab_sbyte */
+typedef struct command_s
+{
+ u16 i_pre_command_nb; // 2 bytes
+ u16 i_post_command_nb; // 2 bytes
+ u16 i_cell_command_nb; // 2 bytes
+// char[2] ???
+ u64* p_pre_command; // i_pre_com_nb * 8 bytes
+ u64* p_post_command; // i_post_com_nb * 8 bytes
+ u64* p_cell_command; // i_pre_com_nb * 8 bytes
+
+// command_desc_t* p_cell_command; // i_cell_com_nb * 8 bytes
+// command_desc_t* p_post_command; // i_post_com_nb * 8 bytes
+// command_desc_t* p_cell_command; // i_cell_com_nb * 8 bytes
+} command_t;
+
+/* Program Chain Map Table
+ * - start at "i_pgc_prg_map_sbyte" */
+typedef struct chapter_map_s
+{
+ u8* pi_start_cell; // i_prg_nb * 1 byte
+} chapter_map_t;
+
+/* Cell Playback Information Table
+ * we have a pointer to such a structure for each cell
+ * - first start at "i_cell_play_inf_sbyte" */
+typedef struct cell_play_s
+{
+ /* This information concerns the currently selected cell */
+ u16 i_category; // 2 bytes
+ u8 i_still_time; // 1 byte; in seconds; ff=inf
+ u8 i_command_nb; // 1 byte; 0 = no com
+ u32 i_play_time; // 4 bytes
+ u32 i_first_sector; // 4 bytes
+ u32 i_first_ilvu_vobu_esector; // 4 bytes; ???
+ u32 i_last_vobu_start_sector; // 4 bytes
+ u32 i_last_sector; // 4 bytes
+} cell_play_t;
+
+/* Cell Position Information Table
+ * we have a pointer to such a structure for each cell
+ * - first start at "i_cell_pos_inf_sbyte" */
+typedef struct cell_pos_s
+{
+ /* This information concerns the currently selected cell */
+ u16 i_vob_id; // 2 bytes
+// char ???
+ u8 i_cell_id; // 1 byte
+} cell_pos_t;
+
+/* Main structure for Program Chain
+ * - start at i_fp_pgc_sbyte
+ * - or at i_vmgm_pgci_sbyte in vmgm_pgci_srp_t */
+typedef struct title_s
+{
+ /* Global features of program chain */
+// char[2] ???
+ u8 i_chapter_nb; // 1 byte
+ u8 i_cell_nb; // 1 byte
+ u32 i_play_time; // 4 bytes
+ u32 i_prohibited_user_op; // 4 bytes
+ audio_status_t pi_audio_status[8]; // 8*2 bytes
+ spu_status_t pi_spu_status[32]; // 32*4 bytes
+ u16 i_next_title_num; // 2 bytes
+ u16 i_prev_title_num; // 2 bytes
+ u16 i_go_up_title_num; // 2 bytes
+ u8 i_still_time; // 1 byte ; in seconds
+ u8 i_play_mode; // 1 byte
+ /* In video_ts.ifo, the 3 significant bytes of each color are
+ * preceded by 1 unsignificant byte */
+ u32 pi_yuv_color[16]; // 16*3 bytes
+ /* Here come the start bytes of the following structures */
+ u16 i_command_start_byte; // 2 bytes
+ u16 i_chapter_map_start_byte; // 2 bytes
+ u16 i_cell_play_start_byte; // 2 bytes
+ u16 i_cell_pos_start_byte; // 2 bytes
+ /* Predefined structures */
+ command_t command;
+ chapter_map_t chapter_map;
+ cell_play_t* p_cell_play; // i_cell_nb * 24 bytes
+ cell_pos_t* p_cell_pos; // i_cell_nb * 4 bytes
+} title_t;
+
+/*
+ * Menu PGCI Unit Table
+ */
+
+/* Menu PGCI Language unit Descriptor */
+typedef struct unit_s
+{
+ u16 i_lang_code; // 2 bytes (ISO-xx)
+// char ???
+ u8 i_existence_mask; // 1 byte
+ u32 i_unit_inf_start_byte; // 4 bytes
+} unit_t;
+
+typedef struct unit_title_s
+{
+ u8 i_category_mask; // 1 byte
+ u8 i_category; // 1 byte
+ u16 i_parental_mask; // 2 bytes
+ u32 i_title_start_byte; // 4 bytes
+ title_t title;
+} unit_title_t;
+
+/* Menu PGCI Language Unit Table
+ * - start at i_lu_sbyte */
+typedef struct unit_inf_s
+{
+ u16 i_title_nb; // 2 bytes
+// char[2] ???
+ u32 i_last_byte; // 4 bytes
+ unit_title_t * p_title; // i_srp_nb * 8 bytes
+} unit_inf_t;
+
+/* Main Struct for Menu PGCI
+ * - start at i_*_pgci_ut_ssector */
+typedef struct title_unit_s
+{
+ u16 i_unit_nb; // 2 bytes; ???
+// char[2] ???
+ u32 i_last_byte; // 4 bytes
+ unit_t* p_unit; // i_lu_nb * 8 bytes
+ unit_inf_t* p_unit_inf; // i_lu_nb * 8 bytes
+} title_unit_t;
+
+/*
+ * Cell Adress Table Information
+ */
+typedef struct cell_map_s
+{
+ u16 i_vob_id; // 2 bytes
+ u8 i_cell_id; // 1 byte
+// char ???
+ u32 i_first_sector; // 4 bytes
+ u32 i_last_sector; // 4 bytes
+} cell_map_t;
+
+typedef struct cell_inf_s
+{
+ u16 i_vob_nb; // 2 bytes
+// char[2] ???
+ u32 i_last_byte; // 4 bytes
+ u16 i_cell_nb; // not in ifo; computed
+ // with e_byte
+ cell_map_t* p_cell_map;
+} cell_inf_t;
+
+
+/*
+ * VOBU Adress Map Table
+ */
+typedef struct vobu_map_s
+{
+ u32 i_last_byte; // 4 bytes
+ u32* pi_vobu_start_sector; // (nb of vobu) * 4 bytes
+} vobu_map_t;
+
+/*****************************************************************************
+ * Structures for Video Management (cf video_ts.ifo)
+ *****************************************************************************/
+
+/*
+ * Video Manager Information Management Table
+ */
+typedef struct manager_inf_s
+{
+ char psz_id[13]; // 12 bytes (DVDVIDEO-VMG)
+ u32 i_vmg_end_sector; // 4 bytes
+// char[12] ???
+ u32 i_vmg_inf_end_sector; // 4 bytes
+// char ???
+ u8 i_spec_ver; // 1 byte
+ u32 i_cat; // 4 bytes
+ u16 i_volume_nb; // 2 bytes
+ u16 i_volume; // 2 bytes
+ u8 i_disc_side; // 1 bytes
+// char[20] ???
+ u16 i_title_set_nb; // 2 bytes
+ char ps_provider_id[32]; // 32 bytes
+ u64 i_pos_code; // 8 bytes
+// char[24] ???
+ u32 i_vmg_inf_end_byte; // 4 bytes
+ u32 i_first_play_title_start_byte; // 4 bytes
+// char[56] ???
+ u32 i_vob_start_sector; // 4 bytes
+ u32 i_title_inf_start_sector; // 4 bytes
+ u32 i_title_unit_start_sector; // 4 bytes
+ u32 i_parental_inf_start_sector; // 4 bytes
+ u32 i_vts_inf_start_sector; // 4 bytes
+ u32 i_text_data_start_sector; // 4 bytes
+ u32 i_cell_inf_start_sector; // 4 bytes
+ u32 i_vobu_map_start_sector; // 4 bytes
+// char[2] ???
+ ifo_video_t video_attr; // 2 bytes
+// char ???
+ u8 i_audio_nb; // 1 byte
+ ifo_audio_t p_audio_attr[8]; // i_vmgm_audio_nb * 8 bytes
+// char[16] ???
+ u8 i_spu_nb; // 1 byte
+ ifo_spu_t p_spu_attr[32]; // i_subpic_nb * 6 bytes
+} manager_inf_t;
+
+
+/*
+ * Part Of Title Search Pointer Table Information
+ */
+
+/* Title sets structure
+ * we have a pointer to this structure for each tts */
+typedef struct title_attr_s
+{
+ u8 i_play_type; // 1 byte
+ u8 i_angle_nb; // 1 byte
+ u16 i_chapter_nb; // 2 bytes; Chapters/PGs
+ u16 i_parental_id; // 2 bytes
+ u8 i_title_set_num; // 1 byte (VTS#)
+ u8 i_title_num; // 1 byte ???
+ u32 i_start_sector; // 4 bytes
+} title_attr_t;
+
+/* Main struct for tts
+ * - start at "i_vmg_ptt_srpt_ssector" */
+typedef struct title_inf_s
+{
+ u16 i_title_nb; // 2 bytes
+// char[2] ???
+ u32 i_last_byte; // 4 bytes
+ title_attr_t * p_attr; // i_ttu_nb * 12 bytes
+} title_inf_t;
+
+/*
+ * Parental Management Information Table
+ */
+typedef struct parental_desc_s
+{
+ char ps_country_code[2]; // 2 bytes
+// char[2] ???
+ u16 i_parental_mask_start_byte; // 2 bytes
+// char[2] ???
+} parental_desc_t;
+
+typedef struct parental_mask_s
+{
+ u16* ppi_mask[8]; // (i_vts_nb +1) * 8 * 2 bytes
+} parental_mask_t;
+
+/* Main struct for parental management
+ * - start at i_vmg_ptl_mait_ssector */
+typedef struct parental_inf_s
+{
+ u16 i_country_nb; // 2 bytes
+ u16 i_vts_nb; // 2 bytes
+ u32 i_last_byte; // 4 bytes
+ parental_desc_t* p_parental_desc; // i_country_nb * 8 bytes
+ parental_mask_t* p_parental_mask; // i_country_nb * sizeof(vmg_ptl_mask_t)
+} parental_inf_t;
+
+/*
+ * Video Title Set Attribute Table
+ */
+
+/* Attribute structure : one for each vts
+ * - start at pi_atrt_sbyte */
+typedef struct vts_attr_s
+{
+ u32 i_last_byte; // 4 bytes
+ u32 i_cat_app_type; // 4 bytes
+ ifo_video_t vts_menu_video_attr; // 2 bytes
+// char ???
+ u8 i_vts_menu_audio_nb; // 1 byte
+ ifo_audio_t p_vts_menu_audio_attr[8]; // 8 * 8 bytes
+// char[17] ???
+ u8 i_vts_menu_spu_nb; // 1 byte
+ ifo_spu_t p_vts_menu_spu_attr[28]; // i_vtsm_subpic_nb * 6 bytes
+// char[2] ???
+ ifo_video_t vts_title_video_attr; // 2 bytes
+// char ???
+ u8 i_vts_title_audio_nb; // 1 byte
+ ifo_audio_t p_vts_title_audio_attr[8]; // 8 * 8 bytes
+// char[17] ???
+ u8 i_vts_title_spu_nb; // 1 byte
+ ifo_spu_t p_vts_title_spu_attr[28]; // i_vtstt_subpic_nb * 6 bytes
+} vts_attr_t;
+
+/* Main struct for vts attributes
+ * - start at i_vmg_vts_atrt_ssector */
+typedef struct vts_inf_s
+{
+ u16 i_vts_nb; // 2 bytes
+// char[2] ???
+ u32 i_last_byte; // 4 bytes
+ u32* pi_vts_attr_start_byte; // i_vts_nb * 4 bytes
+ vts_attr_t* p_vts_attr;
+} vts_inf_t;
+
+/*
+ * Global Structure for Video Manager
+ */
+typedef struct vmg_s
+{
+ manager_inf_t manager_inf;
+ title_t title;
+ title_inf_t title_inf;
+ title_unit_t title_unit;
+ parental_inf_t parental_inf;
+ vts_inf_t vts_inf;
+ cell_inf_t cell_inf;
+ vobu_map_t vobu_map;
+} vmg_t;
+
+/*****************************************************************************
+ * Structures for Video Title Sets (cf vts_*.ifo)
+ ****************************************************************************/
+
+/*
+ * Video Title Sets Information Management Table
+ */
+typedef struct vts_manager_s
+{
+ char psz_id[13]; // 12 bytes (DVDVIDEO-VTS)
+ u32 i_last_sector; // 4 bytes
+// char[12] ???
+ u32 i_inf_last_sector; // 4 bytes
+// char ???
+ u8 i_spec_ver; // 1 byte
+ u32 i_cat; // 4 bytes
+// char[90] ???
+ u32 i_inf_end_byte; // 4 bytes
+// char[60] ???
+ u32 i_menu_vob_start_sector; // 4 bytes
+ u32 i_title_vob_start_sector; // 4 bytes
+ u32 i_title_inf_start_sector; // 4 bytes
+ u32 i_title_unit_start_sector; // 4 bytes
+ u32 i_menu_unit_start_sector; // 4 bytes
+ u32 i_time_inf_start_sector; // 4 bytes
+ u32 i_menu_cell_inf_start_sector; // 4 bytes
+ u32 i_menu_vobu_map_start_sector; // 4 bytes
+ u32 i_cell_inf_start_sector; // 4 bytes
+ u32 i_vobu_map_start_sector; // 4 bytes
+// char[24] ???
+ ifo_video_t menu_video_attr; // 2 bytes
+// char ???
+ u8 i_menu_audio_nb; // 1 byte
+ ifo_audio_t p_menu_audio_attr[8]; // i_vmgm_audio_nb * 8 bytes
+// char[16] ???
+ u8 i_menu_spu_nb; // 1 byte
+ ifo_spu_t p_menu_spu_attr[32]; // i_subpic_nb * 6 bytes
+ // !!! only 28 subpics ???
+// char[2] ???
+ ifo_video_t video_attr; // 2 bytes
+// char ???
+ u8 i_audio_nb; // 1 byte
+ ifo_audio_t p_audio_attr[8]; // i_vmgm_audio_nb * 8 bytes
+// char[16] ???
+ u8 i_spu_nb; // 1 byte
+ ifo_spu_t p_spu_attr[32]; // i_subpic_nb * 6 bytes
+} vts_manager_t;
+
+/*
+ * Part Of Title Search Pointer Table Information
+ */
+
+/* Title sets structure
+ * we have a pointer to this structure for each tts */
+typedef struct title_start_s
+{
+ u16 i_title_id; // 2 bytes; Chapters/PGs
+ u16 i_chapter; // 2 bytes
+} title_start_t;
+
+/* Main struct for tts
+ * - start at "i_vts_ptt_srpt_ssector" */
+typedef struct vts_title_s
+{
+ u16 i_title_nb; // 2 bytes
+// char[2] ???
+ u32 i_last_byte; // 4 bytes
+ u32* pi_start_byte;
+ title_start_t * p_title_start; // i_ttu_nb * 4 bytes
+} vts_title_t;
+
+/*
+ * Time Map table information
+ */
+
+/* Time Map structure */
+typedef struct time_map_s
+{
+ u8 i_time_unit; // 1 byte
+// char ???
+ u16 i_entry_nb; // 2 bytes
+ u32* pi_sector; // i_entry_nb * 4 bytes
+} time_map_t;
+
+/* Main structure for tmap_ti
+ * - start at "i_tmap_ti_ssector" */
+typedef struct time_inf_s
+{
+ u16 i_nb; // 2 bytes
+// char[2] ???
+ u32 i_last_byte; // 4 bytes
+ u32* pi_start_byte; // i_tmap_nb * 4 bytes
+ time_map_t* p_time_map;
+} time_inf_t;
+
+/*
+ * Video Title Set
+ */
+typedef struct vts_s
+{
+ vlc_bool_t b_initialized;
+ int i_pos;
+ vts_manager_t manager_inf;
+ vts_title_t title_inf;
+ title_unit_t menu_unit;
+ unit_inf_t title_unit;
+ time_inf_t time_inf;
+ cell_inf_t menu_cell_inf;
+ vobu_map_t menu_vobu_map;
+ cell_inf_t cell_inf;
+ vobu_map_t vobu_map;
+} vts_t;
+
+/*
+ * Global Ifo Structure
+ */
+typedef struct ifo_s
+{
+ dvdcss_handle dvdhandle; /* File descriptor for the device */
+ int i_start; /* Offset to video_ts.ifo on the device */
+ int i_pos; /* Position of stream pointer */
+ vlc_bool_t b_error; /* Error Management */
+ vmg_t vmg; /* Structure described in video_ts */
+ vts_t vts; /* Vts ifo for current title set */
+
+ /* Remap buffer for unaligned reads */
+ u8 p_remap[ 2 * DVD_LB_SIZE ];
+
+} ifo_t;
+
+
+/*****************************************************************************
+ * Prototypes in dvd_ifo.c
+ *****************************************************************************/
+struct thread_dvd_data_s;
+
+int IfoCreate ( struct thread_dvd_data_s * );
+int IfoInit ( struct ifo_s * );
+int IfoTitleSet ( struct ifo_s *, int );
+void IfoDestroy ( struct ifo_s * );
+
--- /dev/null
+/* seek.c: functions to navigate through DVD.
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: seek.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#ifdef GOD_DAMN_DMCA
+# include "dvdcss.h"
+#else
+# include <dvdcss/dvdcss.h>
+#endif
+
+#include "dvd.h"
+#include "seek.h"
+#include "ifo.h"
+
+#define title \
+ p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
+#define cell p_dvd->p_ifo->vts.cell_inf
+
+int CellIsInterleaved( thread_dvd_data_t * p_dvd )
+{
+ return title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000;
+}
+
+int CellPrg2Map( thread_dvd_data_t * p_dvd )
+{
+ int i_cell;
+
+ i_cell = p_dvd->i_map_cell;
+
+ if( i_cell >= cell.i_cell_nb )
+ {
+ return -1;
+ }
+
+ while( ( i_cell < cell.i_cell_nb ) &&
+ ( ( title.p_cell_pos[p_dvd->i_prg_cell].i_vob_id !=
+ cell.p_cell_map[i_cell].i_vob_id ) ||
+ ( title.p_cell_pos[p_dvd->i_prg_cell].i_cell_id !=
+ cell.p_cell_map[i_cell].i_cell_id ) ) )
+ {
+ i_cell++;
+ }
+
+ if( i_cell >= cell.i_cell_nb )
+ {
+ return -1;
+ }
+
+ return i_cell;
+}
+
+int CellAngleOffset( thread_dvd_data_t * p_dvd, int i_prg_cell )
+{
+ int i_cell_off;
+
+ if( i_prg_cell >= title.i_cell_nb )
+ {
+ return 0;
+ }
+
+ /* basic handling of angles */
+ switch( ( ( title.p_cell_play[i_prg_cell].i_category & 0xf000 )
+ >> 12 ) )
+ {
+ /* we enter a muli-angle section */
+ case 0x5:
+ i_cell_off = p_dvd->i_angle - 1;
+ p_dvd->i_angle_cell = 0;
+ break;
+ /* we exit a multi-angle section */
+ case 0x9:
+ case 0xd:
+ i_cell_off = p_dvd->i_angle_nb - p_dvd->i_angle;
+ break;
+ default:
+ i_cell_off = 0;
+ }
+
+ return i_cell_off;
+}
+
+int CellFirstSector( thread_dvd_data_t * p_dvd )
+{
+ return __MAX( cell.p_cell_map[p_dvd->i_map_cell].i_first_sector,
+ title.p_cell_play[p_dvd->i_prg_cell].i_first_sector );
+}
+
+int CellLastSector( thread_dvd_data_t * p_dvd )
+{
+ return __MIN( cell.p_cell_map[p_dvd->i_map_cell].i_last_sector,
+ title.p_cell_play[p_dvd->i_prg_cell].i_last_sector );
+}
+
+int NextCellPrg( thread_dvd_data_t * p_dvd )
+{
+ int i_cell = p_dvd->i_prg_cell;
+
+ if( p_dvd->i_vts_lb > title.p_cell_play[i_cell].i_last_sector )
+ {
+ i_cell ++;
+ i_cell += CellAngleOffset( p_dvd, i_cell );
+
+ if( i_cell >= title.i_cell_nb )
+ {
+ return -1;
+ }
+ }
+
+ return i_cell;
+}
+
+int Lb2CellPrg( thread_dvd_data_t * p_dvd )
+{
+ int i_cell = 0;
+
+ while( p_dvd->i_vts_lb > title.p_cell_play[i_cell].i_last_sector )
+ {
+ i_cell ++;
+ i_cell += CellAngleOffset( p_dvd, i_cell );
+
+ if( i_cell >= title.i_cell_nb )
+ {
+ return -1;
+ }
+ }
+
+ return i_cell;
+}
+
+int Lb2CellMap( thread_dvd_data_t * p_dvd )
+{
+ int i_cell = 0;
+
+ while( p_dvd->i_vts_lb > cell.p_cell_map[i_cell].i_last_sector )
+ {
+ i_cell ++;
+
+ if( i_cell >= cell.i_cell_nb )
+ {
+ return -1;
+ }
+ }
+
+ return i_cell;
+}
+
+int LbMaxOnce( thread_dvd_data_t * p_dvd )
+{
+ int i_block_once = p_dvd->i_last_lb + 1 - p_dvd->i_vts_lb;
+
+ /* Get the position of the next cell if we're at cell end */
+ if( i_block_once <= 0 )
+ {
+ p_dvd->i_map_cell++;
+ p_dvd->i_angle_cell++;
+
+ p_dvd->i_prg_cell = NextCellPrg( p_dvd );
+ if( p_dvd->i_prg_cell < 0 )
+ {
+ /* EOF */
+ return 0;
+ }
+
+ p_dvd->i_map_cell = CellPrg2Map( p_dvd );
+ if( p_dvd->i_map_cell < 0 )
+ {
+ return 0;
+ }
+
+ p_dvd->i_vts_lb = CellFirstSector( p_dvd );
+ p_dvd->i_last_lb = CellLastSector( p_dvd );
+
+ p_dvd->i_chapter = NextChapter( p_dvd );
+ if( p_dvd->i_chapter < 0 )
+ {
+ return 0;
+ }
+
+ /* Position the fd pointer on the right address */
+ if( dvdcss_seek( p_dvd->dvdhandle,
+ p_dvd->i_vts_start + p_dvd->i_vts_lb,
+ DVDCSS_SEEK_MPEG ) < 0 )
+ {
+//X intf_ErrMsg( "dvd error: %s",
+//X dvdcss_error( p_dvd->dvdhandle ) );
+ return 0;
+ }
+
+ i_block_once = p_dvd->i_last_lb + 1 - p_dvd->i_vts_lb;
+ }
+
+ return i_block_once;
+}
+
+
+int CellPrg2Chapter( thread_dvd_data_t * p_dvd )
+{
+ int i_chapter = 1;
+ int i_cell = p_dvd->i_prg_cell;
+
+ if( CellIsInterleaved( p_dvd ) )
+ {
+ i_cell -= (p_dvd->i_angle - 1);
+ }
+
+ while( title.chapter_map.pi_start_cell[i_chapter] <= i_cell+1 )
+ {
+ i_chapter ++;
+ if( i_chapter >= p_dvd->i_chapter_nb )
+ {
+ return p_dvd->i_chapter_nb;
+ }
+ }
+
+ return i_chapter;
+}
+
+int NextChapter( thread_dvd_data_t * p_dvd )
+{
+ int i_cell = p_dvd->i_prg_cell;
+
+ if( CellIsInterleaved( p_dvd ) )
+ {
+ i_cell -= (p_dvd->i_angle - 1);
+ }
+
+ if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <= i_cell+1 )
+ {
+ p_dvd->i_chapter++;
+ if( p_dvd->i_chapter > p_dvd->i_chapter_nb )
+ {
+ return -1;
+ }
+ p_dvd->b_new_chapter = 1;
+
+ return p_dvd->i_chapter;
+ }
+
+ return p_dvd->i_chapter;
+}
+
+
+
+int DVDSetChapter( thread_dvd_data_t * p_dvd, int i_chapter )
+{
+ if( i_chapter <= 0 || i_chapter > p_dvd->i_chapter_nb )
+ {
+ i_chapter = 1;
+ }
+
+ if( p_dvd->i_chapter != i_chapter )
+ {
+ /* Find cell index in Program chain for current chapter */
+ p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1;
+ p_dvd->i_prg_cell += CellAngleOffset( p_dvd, p_dvd->i_prg_cell );
+ if( i_chapter < p_dvd->i_chapter )
+ {
+ p_dvd->i_map_cell = 0;
+ }
+ p_dvd->i_map_cell = CellPrg2Map( p_dvd );
+ p_dvd->i_vts_lb = CellFirstSector( p_dvd );
+ p_dvd->i_last_lb = CellLastSector( p_dvd );
+
+ /* Position the fd pointer on the right address */
+ if( dvdcss_seek( p_dvd->dvdhandle,
+ p_dvd->i_vts_start + p_dvd->i_vts_lb,
+ DVDCSS_SEEK_MPEG ) < 0 )
+ {
+//X intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
+ return -1;
+ }
+
+//X intf_WarnMsg( 4, "dvd info: chapter %d prg_cell %d map_cell %d",
+//X i_chapter, p_dvd->i_prg_cell, p_dvd->i_map_cell );
+ }
+
+ return i_chapter;
+}
+
+
+#undef cell
+#undef title
--- /dev/null
+/* dvd_seek.h: DVD access plugin.
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: seek.h,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+int CellIsInterleaved( thread_dvd_data_t * );
+int CellAngleOffset ( thread_dvd_data_t *, int );
+int CellPrg2Map ( thread_dvd_data_t * );
+int CellFirstSector ( thread_dvd_data_t * );
+int CellLastSector ( thread_dvd_data_t * );
+
+int NextCellPrg ( thread_dvd_data_t * );
+int Lb2CellPrg ( thread_dvd_data_t * );
+int Lb2CellMap ( thread_dvd_data_t * );
+int LbMaxOnce ( thread_dvd_data_t * );
+
+int CellPrg2Chapter ( thread_dvd_data_t * );
+int NextChapter ( thread_dvd_data_t * );
+int DVDSetChapter ( thread_dvd_data_t *, int );
+
--- /dev/null
+/*****************************************************************************
+ * summary.c: set of functions to print options of selected title
+ * found in .ifo.
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: summary.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if !defined( WIN32 )
+# include <netinet/in.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <string.h>
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+#include <errno.h>
+
+#ifdef GOD_DAMN_DMCA
+# include "dvdcss.h"
+#else
+# include <dvdcss/dvdcss.h>
+#endif
+
+#include "dvd.h"
+#include "ifo.h"
+#include "iso_lang.h"
+
+/*
+ * Local tools to decode some data in ifo
+ */
+
+/****************************************************************************
+ * IfoPrintTitle
+ ****************************************************************************/
+void IfoPrintTitle( thread_dvd_data_t * p_dvd )
+{
+//X intf_WarnMsg( 5, "dvd info: title %d, %d chapter%s, %d angle%s",
+//X p_dvd->i_title, p_dvd->i_chapter_nb,
+//X (p_dvd->i_chapter_nb == 1) ? "" : "s",
+//X p_dvd->i_angle_nb,
+//X (p_dvd->i_angle_nb == 1) ? "" : "s" );
+}
+
+/****************************************************************************
+ * IfoPrintVideo
+ ****************************************************************************/
+#define video p_dvd->p_ifo->vts.manager_inf.video_attr
+void IfoPrintVideo( thread_dvd_data_t * p_dvd )
+{
+//X char* psz_perm_displ[4] =
+//X {
+//X "pan-scan & letterboxed",
+//X "pan-scan",
+//X "letterboxed",
+//X "not specified"
+//X };
+//X char* psz_source_res[4] =
+//X {
+//X "720x480 ntsc or 720x576 pal",
+//X "704x480 ntsc or 704x576 pal",
+//X "352x480 ntsc or 352x576 pal",
+//X "352x240 ntsc or 352x288 pal"
+//X };
+
+//X intf_WarnMsg( 5, "dvd info: MPEG-%d video, %sHz, aspect ratio %s",
+//X video.i_compression + 1,
+//X video.i_system ? "pal 625 @50" : "ntsc 525 @60",
+//X video.i_ratio ? (video.i_ratio == 3) ? "16:9"
+//X : "unknown"
+//X : "4:3" );
+
+//X intf_WarnMsg( 5, "dvd info: display mode %s, %s, %s",
+//X psz_perm_displ[video.i_perm_displ],
+//X video.i_line21_1 ? "line21-1 data in GOP"
+//X : "no line21-1 data",
+//X video.i_line21_2 ? "line21-2 data in GOP"
+//X : "no line21-2 data" );
+
+//X intf_WarnMsg( 5, "dvd info: source is %s, %sletterboxed, %s mode",
+//X psz_source_res[video.i_source_res],
+//X video.i_letterboxed ? "" : "not ",
+//X video.i_mode ? "film (625/50 only)" : "camera" );
+}
+#undef video
+
+/****************************************************************************
+ * IfoPrintAudio
+ ****************************************************************************/
+#define audio p_dvd->p_ifo->vts.manager_inf.p_audio_attr[i-1]
+#define audio_status \
+ p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
+void IfoPrintAudio( thread_dvd_data_t * p_dvd, int i )
+{
+ if( audio_status.i_available )
+ {
+//X char* ppsz_mode[8] =
+//X { "A52", "unknown", "MPEG", "MPEG-2", "LPCM", "SDDS", "DTS", "" };
+//X char* ppsz_appl_mode[4] =
+//X { "no application specified", "karaoke", "surround sound", "" };
+//X char* ppsz_quant[4] =
+//X { "16 bits", "20 bits", "24 bits", "drc" };
+
+//X intf_WarnMsg( 5, "dvd info: audio %d (%s) is %s, "
+//X "%d%s channel%s, %dHz, %s", i,
+//X DecodeLanguage( audio.i_lang_code ),
+//X ppsz_mode[audio.i_coding_mode & 0x7],
+//X audio.i_num_channels + 1,
+//X audio.i_multichannel_extension ? " ext." : "",
+//X audio.i_num_channels ? "s" : "",
+//X audio.i_sample_freq ? 96000 : 48000,
+//X ppsz_appl_mode[audio.i_appl_mode & 0x3] );
+
+//X intf_WarnMsg( 5, "dvd info: %s, quantization %s, status %x",
+//X (audio.i_caption == 1) ? "normal caption"
+//X : (audio.i_caption == 3) ? "directors comments"
+//X : "unknown caption",
+//X ppsz_quant[audio.i_quantization & 0x3],
+//X audio_status.i_position );
+ }
+}
+#undef audio_status
+#undef audio
+
+/****************************************************************************
+ * IfoPrintSpu
+ ****************************************************************************/
+#define spu p_dvd->p_ifo->vts.manager_inf.p_spu_attr[i-1]
+#define spu_status \
+ p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
+
+void IfoPrintSpu( thread_dvd_data_t * p_dvd, int i )
+{
+ if( spu_status.i_available )
+ {
+//X intf_WarnMsg( 5, "dvd info: spu %d (%s), caption %d "
+//X "prefix %x, modes [%s%s%s%s ]", i,
+//X DecodeLanguage( spu.i_lang_code ),
+//X spu.i_caption, spu.i_prefix,
+//X spu_status.i_position_43 ? " 4:3" : "",
+//X spu_status.i_position_wide ? " wide" : "",
+//X spu_status.i_position_letter ? " letter" : "",
+//X spu_status.i_position_pan ? " pan" : "" );
+ }
+}
+#undef spu_status
+#undef spu
--- /dev/null
+/*****************************************************************************
+ * dvd_summary.h: prototype of functions that print out current options.
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: summary.h,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+struct thread_dvd_data_s;
+
+void IfoPrintTitle( struct thread_dvd_data_s * );
+void IfoPrintVideo( struct thread_dvd_data_s * );
+void IfoPrintAudio( struct thread_dvd_data_s *, int );
+void IfoPrintSpu ( struct thread_dvd_data_s *, int );
+
+
--- /dev/null
+/*****************************************************************************
+ * udf.c: udf filesystem tools.
+ *****************************************************************************
+ * Mainly used to find asolute logical block adress of *.ifo files. It only
+ * contains the basic udf handling functions
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: udf.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * based on:
+ * - dvdudf by Christian Wolff <scarabaeus@convergence.de>
+ * - fixes by Billy Biggs <vektor@dumbterm.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#elif defined( _MSC_VER ) && defined( _WIN32 )
+# include <io.h>
+#endif
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#ifdef GOD_DAMN_DMCA
+# include "dvdcss.h"
+#else
+# include <dvdcss/dvdcss.h>
+#endif
+
+#include "dvd.h"
+#include "ifo.h"
+
+#define UDFADshort 1
+#define UDFADlong 2
+#define UDFADext 4
+
+typedef struct partition_s
+{
+ vlc_bool_t b_valid;
+ u8 pi_volume_desc[128];
+ u16 i_flags;
+ u16 i_number;
+ u8 pi_contents[32];
+ u32 i_access_type;
+ u32 i_start;
+ u32 i_length;
+ dvdcss_handle dvdhandle;
+} partition_t;
+
+typedef struct ad_s
+{
+ u32 i_location;
+ u32 i_length;
+ u8 i_flags;
+ u16 i_partition;
+} ad_t;
+
+/* for direct data access, LSB first */
+#define GETN1(p) ((u8)pi_data[p])
+#define GETN2(p) ((u16)pi_data[p]|((u16)pi_data[(p)+1]<<8))
+#define GETN4(p) ((u32)pi_data[p]|((u32)pi_data[(p)+1]<<8)|((u32)pi_data[(p)+2]<<16)|((u32)pi_data[(p)+3]<<24))
+#define GETN(p,n,target) memcpy(target,&pi_data[p],n)
+
+
+/*****************************************************************************
+ * UDFReadLB: reads absolute Logical Block of the disc
+ *****************************************************************************
+ * Returns number of read bytes on success, 0 on error
+ *****************************************************************************/
+static int UDFReadLB( dvdcss_handle dvdhandle, off_t i_lba,
+ size_t i_block_count, u8 *pi_data )
+{
+ if( dvdcss_seek( dvdhandle, i_lba, DVDCSS_NOFLAGS ) < 0 )
+ {
+//X intf_ErrMsg( "dvd error: block %i not found", i_lba );
+ return 0;
+ }
+
+ return dvdcss_read( dvdhandle, pi_data, i_block_count, DVDCSS_NOFLAGS );
+}
+
+
+/*****************************************************************************
+ * UDFDecode: decode unicode encoded udf data
+ *****************************************************************************/
+static int UDFDecode( u8 * pi_data, int i_len, char * psz_target )
+{
+ int p = 1;
+ int i = 0;
+
+ if( !( pi_data[0] & 0x18 ) )
+ {
+ psz_target[0] = '\0';
+ return 0;
+ }
+
+ if( pi_data[0] & 0x10 )
+ {
+ /* ignore MSB of unicode16 */
+ p++;
+
+ while( p < i_len )
+ {
+ psz_target[i++] = pi_data[p+=2];
+ }
+ }
+ else
+ {
+ while( p < i_len )
+ {
+ psz_target[i++] = pi_data[p++];
+ }
+ }
+
+ psz_target[i]='\0';
+
+ return 0;
+}
+
+#if 0
+/**
+ *
+ **/
+
+int UDFEntity (u8 *data, u8 *Flags, char *Identifier)
+{
+ Flags[0] = data[0];
+ strncpy (Identifier, &data[1], 5);
+
+ return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ * UDFDescriptor: gives a tag ID from your data to find out what it refers to
+ *****************************************************************************/
+static int UDFDescriptor( u8 * pi_data, u16 * pi_tag_id )
+{
+ pi_tag_id[0] = GETN2( 0 );
+ /* TODO: check CRC 'n stuff */
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * UDFExtendAD: main volume information
+ *****************************************************************************/
+static int UDFExtentAD (u8 * pi_data, u32 * pi_length, u32 * pi_location)
+{
+ pi_length[0] = GETN4( 0 );
+ pi_location[0] = GETN4( 4 );
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * UDFAD: file set information
+ *****************************************************************************/
+static int UDFAD( u8 * pi_data, struct ad_s * p_ad, u8 i_type,
+ struct partition_s partition )
+{
+ p_ad->i_length = GETN4( 0 );
+ p_ad->i_flags = p_ad->i_length >> 30;
+ p_ad->i_length &= 0x3FFFFFFF;
+
+ switch( i_type )
+ {
+ case UDFADshort:
+ p_ad->i_location = GETN4( 4 );
+ /* use number of current partition */
+ p_ad->i_partition = partition.i_number;
+ break;
+
+ case UDFADlong:
+ p_ad->i_location = GETN4( 4 );
+ p_ad->i_partition = GETN2( 8 );
+ break;
+
+ case UDFADext:
+ p_ad->i_location = GETN4( 12 );
+ p_ad->i_partition = GETN2( 16 );
+ break;
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * UDFICB: takes Information Control Block from pi_data
+ *****************************************************************************/
+static int UDFICB( u8 * pi_data, u8 * pi_file_type, u16 * pi_flags)
+{
+ pi_file_type[0] = GETN1( 11 );
+ pi_flags[0] = GETN2( 18 );
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * UDFPartition: gets partition descriptor
+ *****************************************************************************/
+static int UDFPartition( u8 * pi_data, u16 * pi_flags, u16 * pi_nb,
+ char * ps_contents, u32 * pi_start, u32 * pi_length )
+{
+ pi_flags[0] = GETN2( 20 );
+ pi_nb[0] = GETN2( 22 );
+ GETN( 24, 32, ps_contents );
+ pi_start[0] = GETN4( 188 );
+ pi_length[0] = GETN4( 192 );
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * UDFLogVolume: reads the volume descriptor and checks the parameters
+ *****************************************************************************
+ * Returns 0 on OK, 1 on error
+ *****************************************************************************/
+static int UDFLogVolume(u8 * pi_data, char * p_volume_descriptor )
+{
+ u32 i_lb_size;
+ u32 i_MT_L;
+ u32 i_N_PM;
+
+ UDFDecode( &pi_data[84], 128, p_volume_descriptor );
+
+ i_lb_size = GETN4( 212 ); // should be 2048
+ i_MT_L = GETN4( 264 ); // should be 6
+ i_N_PM = GETN4( 268 ); // should be 1
+
+ if( i_lb_size != DVD_LB_SIZE )
+ {
+//X intf_ErrMsg( "dvd error: invalid UDF sector size (%d)", i_lb_size );
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * UDFFileEntry: fills a ad_t struct with information at pi_data
+ *****************************************************************************/
+static int UDFFileEntry( u8 * pi_data, u8 * pi_file_type, struct ad_s * p_ad,
+ struct partition_s partition )
+{
+ u8 i_file_type;
+ u16 i_flags;
+ u32 i_L_EA;
+ u32 i_L_AD;
+ int p;
+
+ UDFICB( &pi_data[16], &i_file_type, &i_flags );
+
+ pi_file_type[0] = i_file_type;
+ i_L_EA = GETN4( 168 );
+ i_L_AD = GETN4( 172 );
+ p = 176 + i_L_EA;
+
+ while( p < 176 + i_L_EA + i_L_AD )
+ {
+ switch( i_flags & 0x07 )
+ {
+ case 0:
+ UDFAD( &pi_data[p], p_ad, UDFADshort, partition );
+ p += 0x08;
+ break;
+ case 1:
+ UDFAD( &pi_data[p], p_ad, UDFADlong, partition );
+ p += 0x10;
+ break;
+ case 2:
+ UDFAD( &pi_data[p], p_ad, UDFADext, partition );
+ p += 0x14;
+ break;
+ case 3:
+ switch( i_L_AD )
+ {
+ case 0x08:
+ UDFAD( &pi_data[p], p_ad, UDFADshort, partition );
+ break;
+ case 0x10:
+ UDFAD( &pi_data[p], p_ad, UDFADlong, partition );
+ break;
+ case 0x14:
+ UDFAD( &pi_data[p], p_ad, UDFADext, partition );
+ break;
+ }
+ default:
+ p += i_L_AD;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * UDFFileIdentifier: gives filename and characteristics of pi_data
+ *****************************************************************************/
+static int UDFFileIdentifier( u8 * pi_data, u8 * pi_file_characteristics,
+ char * psz_filename, struct ad_s * p_file_icb,
+ struct partition_s partition )
+{
+ u8 i_L_FI;
+ u16 i_L_IU;
+
+ pi_file_characteristics[0] = GETN1( 18 );
+ i_L_FI = GETN1( 19 );
+ UDFAD( &pi_data[20], p_file_icb, UDFADlong, partition );
+ i_L_IU = GETN2( 36 );
+
+ if( i_L_FI )
+ {
+ UDFDecode( &pi_data[38+i_L_IU], i_L_FI, psz_filename );
+ }
+ else
+ {
+ psz_filename[0]='\0';
+ }
+
+ return 4 * ( ( 38 + i_L_FI + i_L_IU + 3 ) / 4 );
+}
+
+
+/*****************************************************************************
+ * UDFMapICB: Maps ICB to FileAD
+ *****************************************************************************
+ * ICB: Location of ICB of directory to scan
+ * FileType: Type of the file
+ * File: Location of file the ICB is pointing to
+ * return 1 on success, 0 on error;
+ *****************************************************************************/
+static int UDFMapICB( struct ad_s icb, u8 * pi_file_type, struct ad_s * p_file,
+ struct partition_s partition )
+{
+ u8 pi_lb[DVD_LB_SIZE];
+ u32 i_lba;
+ u16 i_tag_id;
+
+ i_lba = partition.i_start + icb.i_location;
+
+ do
+ {
+ if( !UDFReadLB( partition.dvdhandle, i_lba++, 1, pi_lb ) )
+ {
+ i_tag_id = 0;
+ }
+ else
+ {
+ UDFDescriptor( pi_lb , &i_tag_id );
+ }
+
+ if( i_tag_id == 261 )
+ {
+ UDFFileEntry( pi_lb, pi_file_type, p_file, partition );
+ return 1;
+ }
+
+ } while( ( i_lba <= partition.i_start + icb.i_location +
+ ( icb.i_length - 1 ) / DVD_LB_SIZE ) && ( i_tag_id != 261 ) );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * UDFScanDir: serach filename in dir
+ *****************************************************************************
+ * Dir: Location of directory to scan
+ * FileName: Name of file to look for
+ * FileICB: Location of ICB of the found file
+ * return 1 on success, 0 on error;
+ *****************************************************************************/
+static int UDFScanDir( struct ad_s dir, char * psz_filename,
+ struct ad_s * p_file_icb, struct partition_s partition )
+{
+ u8 pi_lb[2*DVD_LB_SIZE];
+ u32 i_lba;
+ u16 i_tag_id;
+ u8 i_file_char;
+ char psz_temp[DVD_LB_SIZE];
+ int p;
+
+ /* Scan dir for ICB of file */
+ i_lba = partition.i_start + dir.i_location;
+#if 0
+ do
+ {
+ if( !UDFReadLB( partition.dvdhandle, i_lba++, 1, pi_lb ) )
+ {
+ i_tag_id = 0;
+ }
+ else
+ {
+ p=0;
+ while( p < DVD_LB_SIZE )
+ {
+ UDFDescriptor( &pi_lb[p], &i_tag_id );
+
+ if( i_tag_id == 257 )
+ {
+ p += UDFFileIdentifier( &pi_lb[p], &i_file_char,
+ psz_temp, p_file_icb, partition );
+ if( !strcasecmp( psz_filename, psz_temp ) )
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ p = DVD_LB_SIZE;
+ }
+ }
+ }
+
+ } while( i_lba <=
+ partition.i_start + dir.i_location + ( dir.i_length - 1 ) / DVD_LB_SIZE );
+
+#else
+
+ if( UDFReadLB( partition.dvdhandle, i_lba, 2, pi_lb ) <= 0 ) {
+ return 0;
+ }
+
+ p = 0;
+ while( p < dir.i_length )
+ {
+ if( p > DVD_LB_SIZE )
+ {
+ ++i_lba;
+ p -= DVD_LB_SIZE;
+ dir.i_length -= DVD_LB_SIZE;
+ if( UDFReadLB( partition.dvdhandle, i_lba, 2, pi_lb ) <= 0 )
+ {
+ return 0;
+ }
+ }
+
+ UDFDescriptor( &pi_lb[p], &i_tag_id );
+
+ if( i_tag_id == 257 )
+ {
+ p += UDFFileIdentifier( &pi_lb[p], &i_file_char,
+ psz_temp, p_file_icb, partition );
+ if( !strcasecmp( psz_filename, psz_temp ) )
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+#endif
+ return 0;
+}
+
+/*****************************************************************************
+ * UDFFindPartition: looks for a partition on the disc
+ *****************************************************************************
+ * partnum: number of the partition, starting at 0
+ * part: structure to fill with the partition information
+ * return 1 if partition found, 0 on error;
+ *****************************************************************************/
+static int UDFFindPartition( int i_part_nb, struct partition_s *p_partition )
+{
+ u8 pi_lb[DVD_LB_SIZE];
+ u8 pi_anchor[DVD_LB_SIZE];
+ u16 i_tag_id;
+ u32 i_lba;
+ u32 i_MVDS_location;
+ u32 i_MVDS_length;
+ u32 i_last_sector;
+ vlc_bool_t b_term;
+ vlc_bool_t b_vol_valid;
+ int i;
+
+ /* Find Anchor */
+ i_last_sector = 0;
+
+ /* try #1, prime anchor */
+ i_lba = 256;
+ b_term = 0;
+
+ /* Search anchor loop */
+ while( 1 )
+ {
+ if( UDFReadLB( p_partition->dvdhandle, i_lba, 1, pi_anchor ) )
+ {
+ UDFDescriptor( pi_anchor, &i_tag_id );
+ }
+ else
+ {
+ i_tag_id = 0;
+ }
+
+ if( i_tag_id != 2 )
+ {
+ /* not an anchor? */
+ if( b_term )
+ {
+ /* final try failed */
+ return 0;
+ }
+
+ if( i_last_sector )
+ {
+ /* we already found the last sector
+ * try #3, alternative backup anchor */
+ i_lba = i_last_sector;
+
+ /* but that's just about enough, then! */
+ b_term = 1;
+ }
+ else
+ {
+ /* TODO: find last sector of the disc (this is optional) */
+ if( i_last_sector )
+ {
+ /* try #2, backup anchor */
+ i_lba = i_last_sector - 256;
+ }
+ else
+ {
+ /* unable to find last sector */
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ /* it is an anchor! continue... */
+ break;
+ }
+ }
+
+ /* main volume descriptor */
+ UDFExtentAD( &pi_anchor[16], &i_MVDS_length, &i_MVDS_location );
+
+ p_partition->b_valid = 0;
+ b_vol_valid = 0;
+ p_partition->pi_volume_desc[0] = '\0';
+
+ i = 1;
+ /* Find Volume Descriptor */
+ do
+ {
+ i_lba = i_MVDS_location;
+
+ do
+ {
+ if( !UDFReadLB( p_partition->dvdhandle, i_lba++, 1, pi_lb ) )
+ {
+ i_tag_id = 0;
+ }
+ else
+ {
+ UDFDescriptor( pi_lb, &i_tag_id );
+ }
+
+ if( ( i_tag_id == 5 ) && ( !p_partition->b_valid ) )
+ {
+ /* Partition Descriptor */
+ UDFPartition( pi_lb,
+ &p_partition->i_flags,
+ &p_partition->i_number,
+ p_partition->pi_contents,
+ &p_partition->i_start,
+ &p_partition->i_length );
+ p_partition->b_valid = ( i_part_nb == p_partition->i_number );
+ }
+ else if( ( i_tag_id == 6 ) && ( !b_vol_valid) )
+ {
+ /* Logical Volume Descriptor */
+ if( UDFLogVolume( pi_lb , p_partition->pi_volume_desc ) )
+ {
+ /* TODO: sector size wrong! */
+ }
+ else
+ {
+ b_vol_valid = 1;
+ }
+ }
+
+ } while( ( i_lba <= i_MVDS_location +
+ ( i_MVDS_length - 1 ) / DVD_LB_SIZE )
+ && ( i_tag_id != 8 )
+ && ( ( !p_partition->b_valid ) || ( !b_vol_valid ) ) );
+
+ if( ( !p_partition->b_valid ) || ( !b_vol_valid ) )
+ {
+ /* backup volume descriptor */
+ UDFExtentAD( &pi_anchor[24], &i_MVDS_length, &i_MVDS_location );
+ }
+ } while( i-- && ( ( !p_partition->b_valid ) || ( !b_vol_valid ) ) );
+
+ /* we only care for the partition, not the volume */
+ return( p_partition->b_valid);
+}
+
+
+/*****************************************************************************
+ * DVDUDFFindFile: looks for a file on the UDF disc/imagefile
+ *****************************************************************************
+ * Path has to be the absolute pathname on the UDF filesystem,
+ * starting with '/'.
+ * returns absolute LB number, or 0 on error
+ *****************************************************************************/
+u32 DVDUDFFindFile( dvdcss_handle dvdhandle, char * psz_path )
+{
+ struct partition_s partition;
+ struct ad_s root_icb;
+ struct ad_s file;
+ struct ad_s icb;
+ u32 i_lba;
+ u16 i_tag_id;
+ u8 pi_lb[DVD_LB_SIZE];
+ u8 i_file_type;
+ char psz_tokenline[DVD_LB_SIZE] = "";
+ char * psz_token;
+ int i_partition;
+
+ strcat( psz_tokenline, psz_path );
+
+ /* Init file descriptor of UDF filesystem (== DVD) */
+ partition.dvdhandle = dvdhandle;
+
+ /* Find partition 0, standard partition for DVD-Video */
+ i_partition = 0;
+ if( !UDFFindPartition( i_partition, &partition ) )
+ {
+//X intf_ErrMsg( "dvd error: partition 0 not found" );
+ return 0;
+ }
+
+ /* Find root dir ICB */
+ i_lba = partition.i_start;
+
+ do
+ {
+ if( !UDFReadLB( dvdhandle, i_lba++, 1, pi_lb ) )
+ {
+ i_tag_id = 0;
+ }
+ else
+ {
+ UDFDescriptor( pi_lb, &i_tag_id );
+ }
+
+ if( i_tag_id == 256 )
+ {
+ /* File Set Descriptor */
+ UDFAD( &pi_lb[400], &root_icb, UDFADlong, partition );
+ }
+
+ } while( ( i_lba < partition.i_start + partition.i_length )
+ && ( i_tag_id != 8) && ( i_tag_id != 256 ) );
+
+ if( i_tag_id != 256 )
+ {
+//X intf_ErrMsg( "dvd error: bad UDF descriptor" );
+ return 0;
+ }
+ if( root_icb.i_partition != i_partition )
+ {
+//X intf_ErrMsg( "dvd error: bad UDF partition" );
+ return 0;
+ }
+
+ /* Find root dir */
+ if( !UDFMapICB( root_icb, &i_file_type, &file, partition ) )
+ {
+//X intf_ErrMsg( "dvd error: can't find root dir" );
+ return 0;
+ }
+
+ /* root dir should be dir */
+ if( i_file_type != 4 )
+ {
+//X intf_ErrMsg( "dvd error: root dir error" );
+ return 0;
+ }
+
+ /* Tokenize filepath */
+ psz_token = strtok( psz_tokenline, "/" );
+ while( psz_token )
+ {
+ if( !UDFScanDir( file, psz_token, &icb, partition ) )
+ {
+//X intf_ErrMsg( "dvd error: scan dir error" );
+ return 0;
+ }
+
+ if( !UDFMapICB ( icb, &i_file_type, &file, partition ) )
+ {
+//X intf_ErrMsg( "dvd error: ICB error" );
+ return 0;
+ }
+
+ psz_token = strtok( NULL, "/" );
+ }
+
+ return partition.i_start + file.i_location;
+}
+
--- /dev/null
+/*****************************************************************************
+ * dvd_udf.h: structures for udf filesystem tools.
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: udf.h,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * based on:
+ * - dvdudf by Christian Wolff <scarabaeus@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*
+ * Fonctions in dvd_udf.c
+ */
+u32 DVDUDFFindFile( dvdcss_handle, char * );
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+dvdplay_SOURCES = dvd.c access.c demux.c intf.c es.c tools.c
--- /dev/null
+/*****************************************************************************
+ * access.c: access capabilities for dvdplay plugin.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: access.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#if defined( WIN32 )
+# include <io.h> /* read() */
+#else
+# include <sys/uio.h> /* struct iovec */
+#endif
+
+#if defined( WIN32 )
+# include "input_iovec.h"
+#endif
+
+#include "dvd.h"
+#include "es.h"
+#include "tools.h"
+#include "intf.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+/* called from outside */
+static int dvdplay_SetArea ( input_thread_t *, input_area_t * );
+static int dvdplay_SetProgram ( input_thread_t *, pgrm_descriptor_t * );
+static int dvdplay_Read ( input_thread_t *, byte_t *, size_t );
+static void dvdplay_Seek ( input_thread_t *, off_t );
+
+static void pf_vmg_callback ( void*, dvdplay_event_t );
+
+/* only from inside */
+static int dvdNewArea( input_thread_t *, input_area_t * );
+static int dvdNewPGC ( input_thread_t * );
+
+/*****************************************************************************
+ * OpenDVD: open libdvdplay
+ *****************************************************************************/
+int E_(OpenDVD) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ char * psz_source;
+ dvd_data_t * p_dvd;
+ input_area_t * p_area;
+ int i_title_nr;
+ int i_title;
+ int i_chapter;
+ int i_angle;
+ int i;
+
+ p_dvd = malloc( sizeof(dvd_data_t) );
+ if( p_dvd == NULL )
+ {
+ msg_Err( p_input, "dvdplay error: out of memory" );
+ return -1;
+ }
+
+ p_input->p_access_data = (void *)p_dvd;
+
+ p_input->pf_read = dvdplay_Read;
+ p_input->pf_seek = dvdplay_Seek;
+ p_input->pf_set_area = dvdplay_SetArea;
+ p_input->pf_set_program = dvdplay_SetProgram;
+
+ /* command line */
+ if( ( psz_source = dvdplay_ParseCL( p_input,
+ &i_title, &i_chapter, &i_angle ) ) == NULL )
+ {
+ free( p_dvd );
+ return -1;
+ }
+
+ /* Open libdvdplay */
+ p_dvd->vmg = dvdplay_open( psz_source, pf_vmg_callback, (void*)p_input );
+
+ /* free allocated strings */
+ free( psz_source );
+
+ if( p_dvd->vmg == NULL )
+ {
+ msg_Err( p_input, "dvdplay error: can't open source" );
+ free( p_dvd );
+ return -1;
+ }
+
+ p_dvd->p_intf = NULL;
+
+ p_dvd->i_still_time = 0;
+
+ /* set up input */
+ p_input->i_mtu = 0;
+
+ /* Set stream and area data */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ /* If we are here we can control the pace... */
+ p_input->stream.b_pace_control = 1;
+ /* seek is only allowed when we have size info */
+ p_input->stream.b_seekable = 0;
+
+ /* Initialize ES structures */
+ input_InitStream( p_input, sizeof( stream_ps_data_t ) );
+
+ /* disc input method */
+ p_input->stream.i_method = INPUT_METHOD_DVD;
+
+ i_title_nr = dvdplay_title_nr( p_dvd->vmg );
+#define area p_input->stream.pp_areas
+
+ /* Area 0 for menu */
+ area[0]->i_plugin_data = 0;
+
+ for( i = 1 ; i <= i_title_nr ; i++ )
+ {
+ input_AddArea( p_input );
+
+ /* Titles id */
+ area[i]->i_id = i;
+
+ /* Number of chapters */
+ area[i]->i_part_nb = dvdplay_chapter_nr( p_dvd->vmg, i );
+
+ area[i]->i_plugin_data = 0;
+ }
+#undef area
+ msg_Dbg( p_input, "number of titles: %d", i_title_nr );
+
+ i_title = i_title <= i_title_nr ? i_title : 0;
+
+ p_area = p_input->stream.pp_areas[i_title];
+ p_area->i_part = i_chapter;
+ p_input->stream.p_selected_area = NULL;
+
+ /* set title, chapter, audio and subpic */
+ if( dvdplay_SetArea( p_input, p_area ) )
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ return -1;
+ }
+
+ if( i_angle <= p_input->stream.i_pgrm_number )
+ {
+ dvdplay_SetProgram( p_input,
+ p_input->stream.pp_programs[i_angle - 1] );
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_input->psz_demux = "dvdplay";
+
+ return 0;
+}
+
+/*****************************************************************************
+ * CloseDVD: close libdvdplay
+ *****************************************************************************/
+void E_(CloseDVD) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ dvd_data_t * p_dvd = (dvd_data_t *)p_input->p_access_data;
+
+ /* close libdvdplay */
+ dvdplay_close( p_dvd->vmg );
+
+ free( p_dvd );
+ p_input->p_access_data = NULL;
+
+}
+
+/*****************************************************************************
+ * dvdplay_SetProgram: set dvd angle.
+ *****************************************************************************
+ * This is actually a hack to make angle change through vlc interface with
+ * no need for a specific button.
+ *****************************************************************************/
+static int dvdplay_SetProgram( input_thread_t * p_input,
+ pgrm_descriptor_t * p_program )
+{
+ if( p_input->stream.p_selected_program != p_program )
+ {
+ dvd_data_t * p_dvd;
+ int i_angle;
+
+ p_dvd = (dvd_data_t*)(p_input->p_access_data);
+ i_angle = p_program->i_number;
+
+ if( !dvdplay_angle( p_dvd->vmg, i_angle ) )
+ {
+ memcpy( p_program, p_input->stream.p_selected_program,
+ sizeof(pgrm_descriptor_t) );
+ p_program->i_number = i_angle;
+ p_input->stream.p_selected_program = p_program;
+
+ msg_Dbg( p_input, "angle %d selected", i_angle );
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * dvdplay_SetArea: initialize input data for title x, chapter y.
+ * It should be called for each user navigation request.
+ *****************************************************************************
+ * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
+ * Note that you have to take the lock before entering here.
+ *****************************************************************************/
+static int dvdplay_SetArea( input_thread_t * p_input, input_area_t * p_area )
+{
+ dvd_data_t * p_dvd;
+
+ p_dvd = (dvd_data_t*)p_input->p_access_data;
+
+ /*
+ * Title selection
+ */
+ if( p_area != p_input->stream.p_selected_area )
+ {
+ int i_chapter;
+
+ /* prevent intf to try to seek */
+ p_input->stream.b_seekable = 0;
+
+ /* Store selected chapter */
+ i_chapter = p_area->i_part;
+
+ dvdNewArea( p_input, p_area );
+
+ dvdplay_start( p_dvd->vmg, p_area->i_id );
+
+ p_area->i_part = i_chapter;
+ } /* i_title >= 0 */
+ else
+ {
+ p_area = p_input->stream.p_selected_area;
+ }
+
+ /*
+ * Chapter selection
+ */
+
+ if( p_area->i_part != dvdplay_chapter_cur( p_dvd->vmg ) )
+ {
+ if( ( p_area->i_part > 0 ) &&
+ ( p_area->i_part <= p_area->i_part_nb ))
+ {
+ dvdplay_pg( p_dvd->vmg, p_area->i_part );
+ }
+ p_area->i_part = dvdplay_chapter_cur( p_dvd->vmg );
+ }
+
+ /* warn interface that something has changed */
+ p_area->i_tell =
+ LB2OFF( dvdplay_position( p_dvd->vmg ) ) - p_area->i_start;
+ p_input->stream.b_changed = 1;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * dvdplay_Read: reads data packets.
+ *****************************************************************************
+ * Returns -1 in case of error, the number of bytes read if everything went
+ * well.
+ *****************************************************************************/
+static int dvdplay_Read( input_thread_t * p_input,
+ byte_t * p_buffer, size_t i_count )
+{
+ dvd_data_t * p_dvd;
+ off_t i_read;
+
+ p_dvd = (dvd_data_t *)p_input->p_access_data;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ i_read = LB2OFF( dvdplay_read( p_dvd->vmg, p_buffer, OFF2LB( i_count ) ) );
+
+ p_input->stream.p_selected_area->i_tell =
+ LB2OFF( dvdplay_position( p_dvd->vmg ) ) -
+ p_input->stream.p_selected_area->i_start;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return i_read;
+}
+
+/*****************************************************************************
+ * dvdplay_Seek : Goes to a given position on the stream.
+ *****************************************************************************
+ * This one is used by the input and translate chronological position from
+ * input to logical position on the device.
+ * The lock should be taken before calling this function.
+ *****************************************************************************/
+static void dvdplay_Seek( input_thread_t * p_input, off_t i_off )
+{
+ dvd_data_t * p_dvd;
+
+ p_dvd = (dvd_data_t *)p_input->p_access_data;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ dvdplay_seek( p_dvd->vmg, OFF2LB( i_off ) );
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return;
+}
+
+
+/*****************************************************************************
+ * pf_vmg_callback: called by libdvdplay when some event happens
+ *****************************************************************************
+ * The stream lock has to be taken before entering here
+ *****************************************************************************/
+static void pf_vmg_callback( void* p_args, dvdplay_event_t event )
+{
+ input_thread_t * p_input;
+ dvd_data_t * p_dvd;
+ int i;
+
+ p_input = (input_thread_t*)p_args;
+ p_dvd = (dvd_data_t*)p_input->p_access_data;
+
+ switch( event )
+ {
+ case NEW_DOMAIN:
+ break;
+ case NEW_VTS:
+ break;
+ case NEW_FILE:
+
+ break;
+ case NEW_PGC:
+ /* prevent intf to try to seek by default */
+ p_input->stream.b_seekable = 0;
+
+ if( ( i = dvdplay_title_cur( p_dvd->vmg ) ) !=
+ p_input->stream.p_selected_area->i_id )
+ {
+ /* the title number has changed: update area */
+ msg_Warn( p_input, "new title %d (%d)", i,
+ p_input->stream.p_selected_area->i_id );
+ dvdNewArea( p_input,
+ p_input->stream.pp_areas[i] );
+ }
+
+ /* new pgc in same title: reinit ES */
+ dvdNewPGC( p_input );
+
+ p_input->stream.b_changed = 1;
+
+ break;
+ case NEW_PG:
+ /* update current chapter */
+ p_input->stream.p_selected_area->i_part =
+ dvdplay_chapter_cur( p_dvd->vmg );
+ break;
+ case NEW_CELL:
+ p_dvd->b_end_of_cell = 0;
+ break;
+ case END_OF_CELL:
+ p_dvd->b_end_of_cell = 1;
+ break;
+ case JUMP:
+ dvdplay_ES( p_input );
+ break;
+ case STILL_TIME:
+ /* we must pause only from demux
+ * when the data in cache has been decoded */
+ p_dvd->i_still_time = dvdplay_still_time( p_dvd->vmg );
+ msg_Dbg( p_input, "still time %d", p_dvd->i_still_time );
+ break;
+ case COMPLETE_VIDEO:
+ break;
+ case NEW_HIGHLIGHT:
+
+ break;
+ default:
+ msg_Err( p_input, "unknown event from libdvdplay (%d)",
+ event );
+ }
+
+ return;
+}
+
+static int dvdNewArea( input_thread_t * p_input, input_area_t * p_area )
+{
+ dvd_data_t * p_dvd;
+ int i_angle_nb, i_angle;
+ int i;
+
+ p_dvd = (dvd_data_t*)p_input->p_access_data;
+
+ p_input->stream.p_selected_area = p_area;
+
+ /*
+ * One program for each angle
+ */
+ while( p_input->stream.i_pgrm_number )
+ {
+ input_DelProgram( p_input, p_input->stream.pp_programs[0] );
+ }
+
+ input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+
+ dvdplay_angle_info( p_dvd->vmg, &i_angle_nb, &i_angle );
+ for( i = 1 ; i < i_angle_nb ; i++ )
+ {
+ input_AddProgram( p_input, i+1, 0 );
+ }
+
+ dvdplay_SetProgram( p_input,
+ p_input->stream.pp_programs[i_angle-1] );
+
+// dvdNewPGC( p_input );
+
+ /* No PSM to read in DVD mode, we already have all information */
+ p_input->stream.p_selected_program->b_is_ok = 1;
+
+ return 0;
+}
+
+static int dvdNewPGC( input_thread_t * p_input )
+{
+ dvd_data_t * p_dvd;
+// int i_audio_nr = -1;
+// int i_audio = -1;
+// int i_subp_nr = -1;
+// int i_subp = -1;
+// int i_sec;
+
+ p_dvd = (dvd_data_t*)p_input->p_access_data;
+
+// dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_audio );
+// dvdplay_subp_info( p_dvd->vmg, &i_subp_nr, &i_subp );
+
+ dvdplay_ES( p_input );
+ p_input->stream.p_selected_area->i_start =
+ LB2OFF( dvdplay_title_first( p_dvd->vmg ) );
+ p_input->stream.p_selected_area->i_size =
+ LB2OFF( dvdplay_title_end ( p_dvd->vmg ) ) -
+ p_input->stream.p_selected_area->i_start;
+
+ if( p_input->stream.p_selected_area->i_size > 0 )
+ {
+ p_input->stream.b_seekable = 1;
+ }
+ else
+ {
+ p_input->stream.b_seekable = 0;
+ }
+
+#if 0
+ i_sec = dvdplay_title_time( p_dvd->vmg );
+ msg_Dbg( p_input, "title time: %d:%02d:%02d (%d)",
+ i_sec/3600, (i_sec%3600)/60, i_sec%60, i_sec );
+#endif
+
+ return 0;
+}
--- /dev/null
+/*****************************************************************************
+ * access.h: send info to access plugin.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: access.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+union dvdplay_ctrl_u;
+
+void dvdAccessSendControl( struct input_thread_t *, union dvdplay_ctrl_u * );
--- /dev/null
+/*****************************************************************************
+ * demux.c: demux functions for dvdplay.
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: demux.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#include "interface.h"
+#include "dvd.h"
+#include "intf.h"
+#include "es.h"
+
+/* how many packets dvdplay_Demux will read in each loop */
+#define dvdplay_READ_ONCE 64
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Demux ( input_thread_t * );
+
+/*****************************************************************************
+ * InitDVD: initializes dvdplay structures
+ *****************************************************************************/
+int E_(InitDVD) ( vlc_object_t *p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+ dvd_data_t * p_dvd;
+ char * psz_intf = NULL;
+
+ if( p_input->stream.i_method != INPUT_METHOD_DVD )
+ {
+ return -1;
+ }
+
+ p_input->p_demux_data = (void*)p_input->p_access_data;
+ p_dvd = (dvd_data_t *)p_input->p_demux_data;
+
+ p_input->pf_demux = Demux;
+ p_input->pf_rewind = NULL;
+
+ psz_intf = config_GetPsz( p_input, "intf" );
+ config_PutPsz( p_input, "intf", "dvdplay" );
+ p_dvd->p_intf = intf_Create( p_input );
+ p_dvd->p_intf->b_block = VLC_FALSE;
+ intf_RunThread( p_dvd->p_intf );
+
+ if( psz_intf != NULL )
+ {
+ config_PutPsz( p_input, "intf", psz_intf );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * EndDVD: frees unused data
+ *****************************************************************************/
+void E_(EndDVD) ( vlc_object_t *p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+ dvd_data_t * p_dvd;
+ intf_thread_t * p_intf = NULL;
+
+ p_intf = vlc_object_find( p_input, VLC_OBJECT_INTF, FIND_CHILD );
+ if( p_intf != NULL )
+ {
+ intf_StopThread( p_intf );
+ vlc_object_detach_all( p_intf );
+ vlc_object_release( p_intf );
+ intf_Destroy( p_intf );
+ }
+
+ p_dvd = (dvd_data_t *)p_input->p_demux_data;
+ p_dvd->p_intf = NULL;
+}
+
+/*****************************************************************************
+ * Demux
+ *****************************************************************************/
+static int Demux( input_thread_t * p_input )
+{
+ dvd_data_t * p_dvd;
+ data_packet_t * p_data;
+ ssize_t i_result;
+ ptrdiff_t i_remains;
+ int i_data_nb = 0;
+
+ p_dvd = (dvd_data_t *)p_input->p_demux_data;
+
+ /* Read headers to compute payload length */
+ do
+ {
+ if( ( i_result = input_ReadPS( p_input, &p_data ) ) <= 0)
+ {
+ return i_result;
+ }
+
+ i_remains = p_input->p_last_data - p_input->p_current_data;
+
+ input_DemuxPS( p_input, p_data );
+
+
+ ++i_data_nb;
+ }
+ while( i_remains );
+
+
+
+// if( p_dvd->b_still && p_dvd->b_end_of_cell && p_dvd->p_intf != NULL )
+ if( p_dvd->i_still_time && p_dvd->b_end_of_cell && p_dvd->p_intf != NULL )
+ {
+ pgrm_descriptor_t * p_pgrm;
+
+ /* when we receive still_time flag, we have to pause immediately */
+ input_SetStatus( p_input, INPUT_STATUS_PAUSE );
+
+ dvdIntfStillTime( p_dvd->p_intf, p_dvd->i_still_time );
+ p_dvd->i_still_time = 0;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_pgrm = p_input->stream.p_selected_program;
+ p_pgrm->i_synchro_state = SYNCHRO_REINIT;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ input_ClockManageControl( p_input, p_pgrm, 0 );
+ }
+
+ return i_data_nb;
+}
+
--- /dev/null
+/*****************************************************************************
+ * es.h: functions to handle elementary streams.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: demux.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+void dvdplay_DeleteES( struct input_thread_s * );
+void dvdplay_Video( struct input_thread_s * );
+void dvdplay_Audio( struct input_thread_s * );
+void dvdplay_Subp( struct input_thread_s * );
+void dvdplay_ES( struct input_thread_s * );
+void dvdplay_LaunchDecoders( struct input_thread_s * );
--- /dev/null
+/*****************************************************************************
+ * dvd.c : dvdplay module for vlc
+ *****************************************************************************
+ * This plugins should handle all the known specificities of the DVD format,
+ * especially the 2048 bytes logical block size.
+ * It depends on: libdvdplay for ifo files and block reading.
+ *****************************************************************************
+ *
+ * Copyright (C) 2001 VideoLAN
+ * $Id: dvd.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+int E_(OpenDVD) ( vlc_object_t * );
+void E_(CloseDVD) ( vlc_object_t * );
+int E_(InitDVD) ( vlc_object_t * );
+void E_(EndDVD) ( vlc_object_t * );
+int E_(OpenIntf) ( vlc_object_t * );
+void E_(CloseIntf) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ add_category_hint( "[dvdplay:][device][@[title][,[chapter][,angle]]]", NULL );
+ set_description( "dvdplay input module" );
+ add_submodule();
+ set_capability( "access", 120 );
+ set_callbacks( E_(OpenDVD), E_(CloseDVD) );
+ add_shortcut( "dvd" );
+ add_submodule();
+ set_capability( "demux", 0 );
+ set_callbacks( E_(InitDVD), E_(EndDVD) );
+ add_submodule();
+ set_capability( "interface", 0 );
+ set_callbacks( E_(OpenIntf), E_(CloseIntf) );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * dvd.h: structure of the dvdplay plugin
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: dvd.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+#include <dvdread/nav_read.h>
+#include <dvdread/nav_print.h>
+
+#include <dvdplay/dvdplay.h>
+#include <dvdplay/info.h>
+#include <dvdplay/nav.h>
+#include <dvdplay/state.h>
+
+#define LB2OFF(x) ((off_t)(x) * (off_t)(DVD_VIDEO_LB_LEN))
+#define OFF2LB(x) ((x) / DVD_VIDEO_LB_LEN)
+
+
+/*****************************************************************************
+ * dvd_data_t: structure for communication between dvdplay access, demux
+ * and intf.
+ *****************************************************************************/
+typedef struct
+{
+ dvdplay_ptr vmg;
+ intf_thread_t * p_intf;
+
+ int i_audio_nb;
+ int i_spu_nb;
+
+ int i_still_time;
+ vlc_bool_t b_end_of_cell;
+
+ dvdplay_event_t event;
+ dvdplay_ctrl_t control;
+
+} dvd_data_t;
+
--- /dev/null
+/*****************************************************************************
+ * es.c: functions to handle elementary streams.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: es.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#include "dvd.h"
+#include "iso_lang.h"
+
+void dvdplay_LaunchDecoders( input_thread_t * p_input );
+
+/*****************************************************************************
+ * dvdplay_DeleteES:
+ *****************************************************************************/
+void dvdplay_DeleteES( input_thread_t* p_input )
+{
+ free( p_input->stream.pp_selected_es );
+
+ p_input->stream.pp_selected_es = NULL;
+ p_input->stream.i_selected_es_number = 0;
+
+ while( p_input->stream.i_es_number )
+ {
+ input_DelES( p_input, p_input->stream.pp_es[0] );
+ }
+
+ free( p_input->stream.pp_es );
+
+ p_input->stream.pp_es = NULL;
+ p_input->stream.i_es_number = 0;
+
+}
+
+#define ADDES( id, fourcc, cat, lang, size ) \
+ msg_Dbg( p_input, "new es 0x%x", i_id ); \
+ p_es = input_AddES( p_input, NULL, id, size ); \
+ p_es->i_stream_id = i_id & 0xff; \
+ p_es->i_fourcc = (fourcc); \
+ p_es->i_cat = (cat); \
+ if( lang ) \
+ { \
+ strcpy( p_es->psz_desc, DecodeLanguage( lang ) ); \
+ }
+
+/*****************************************************************************
+ * dvdplay_Video: read video ES
+ *****************************************************************************/
+void dvdplay_Video( input_thread_t * p_input )
+{
+ dvd_data_t * p_dvd;
+ es_descriptor_t * p_es;
+ video_attr_t * p_attr;
+ int i_id;
+
+ p_dvd = (dvd_data_t*)(p_input->p_access_data);
+ p_attr = dvdplay_video_attr( p_dvd->vmg );
+
+ /* ES 0 -> video MPEG2 */
+ i_id = 0xe0;
+
+ if( p_attr->display_aspect_ratio )
+ {
+ ADDES( 0xe0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0, sizeof(int) );
+ *(int*)(p_es->p_demux_data) = p_attr->display_aspect_ratio;
+ }
+ else
+ {
+ ADDES( 0xe0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0, 0 );
+ }
+
+}
+
+/*****************************************************************************
+ * dvdplay_Audio: read audio ES
+ *****************************************************************************/
+void dvdplay_Audio( input_thread_t * p_input )
+{
+ dvd_data_t * p_dvd;
+ es_descriptor_t * p_es;
+ audio_attr_t * p_attr;
+ int i_audio_nr = -1;
+ int i_audio = -1;
+ int i_channels;
+ int i_lang;
+ int i_id;
+ int i;
+
+ p_dvd = (dvd_data_t*)(p_input->p_access_data);
+ p_dvd->i_audio_nb = 0;
+ dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_audio );
+
+ /* Audio ES, in the order they appear in .ifo */
+ for( i = 1 ; i <= i_audio_nr ; i++ )
+ {
+ if( ( i_id = dvdplay_audio_id( p_dvd->vmg, i-1 ) ) > 0 )
+ {
+ p_attr = dvdplay_audio_attr( p_dvd->vmg, i-1 );
+ i_channels = p_attr->channels;
+ i_lang = p_attr->lang_code;
+
+ ++p_dvd->i_audio_nb;
+
+ switch( p_attr->audio_format )
+ {
+ case 0x00: /* A52 */
+ ADDES( i_id, VLC_FOURCC('a','5','2',' '), AUDIO_ES, i_lang, 0 );
+ strcat( p_es->psz_desc, " (A52)" );
+
+ break;
+ case 0x02:
+ case 0x03: /* MPEG audio */
+ ADDES( i_id, VLC_FOURCC('m','p','g','a'), AUDIO_ES, i_lang, 0 );
+ strcat( p_es->psz_desc, " (mpeg)" );
+
+ break;
+ case 0x04: /* LPCM */
+ ADDES( i_id, VLC_FOURCC('l','p','c','m'), AUDIO_ES, i_lang, 0 );
+ strcat( p_es->psz_desc, " (lpcm)" );
+
+ break;
+ case 0x05: /* SDDS */
+ msg_Warn( p_input, "SDDS audio not handled" );
+ break;
+ case 0x06: /* DTS */
+ msg_Warn( p_input, "DTS audio not handled yet"
+ "(0x%x)", i_id );
+ break;
+ default:
+ i_id = 0;
+ msg_Warn( p_input, "unknown audio type %.2x",
+ p_attr->audio_format );
+ }
+ }
+ }
+}
+
+/*****************************************************************************
+ * dvdplay_Subp: read subpictures ES
+ *****************************************************************************/
+void dvdplay_Subp( input_thread_t * p_input )
+{
+ dvd_data_t * p_dvd;
+ es_descriptor_t * p_es;
+ subp_attr_t * p_attr;
+ u32 * pi_palette;
+ int i_subp_nr = -1;
+ int i_subp = -1;
+ int i_id;
+ int i;
+
+ p_dvd = (dvd_data_t*)(p_input->p_access_data);
+ p_dvd->i_spu_nb = 0;
+
+ dvdplay_subp_info( p_dvd->vmg, &i_subp_nr, &i_subp );
+ pi_palette = dvdplay_subp_palette( p_dvd->vmg );
+
+ for( i = 1 ; i <= i_subp_nr; i++ )
+ {
+ if( ( i_id = dvdplay_subp_id( p_dvd->vmg, i-1 ) ) >= 0 )
+ {
+ p_attr = dvdplay_subp_attr( p_dvd->vmg, i-1 );
+ ++p_dvd->i_spu_nb;
+
+ if( pi_palette )
+ {
+ ADDES( i_id, VLC_FOURCC('s','p','u',' '), SPU_ES,
+ p_attr->lang_code, 16*sizeof(u32) );
+ *(int*)p_es->p_demux_data = 0xBeeF;
+ memcpy( (void*)p_es->p_demux_data + sizeof(int),
+ pi_palette, 16*sizeof(u32) );
+ }
+ else
+ {
+ ADDES( i_id, VLC_FOURCC('s','p','u',' '), SPU_ES,
+ p_attr->lang_code, 0 );
+ }
+ }
+ }
+}
+
+/*****************************************************************************
+ * dvdplay_LaunchDecoders
+ *****************************************************************************/
+void dvdplay_LaunchDecoders( input_thread_t * p_input )
+{
+ dvd_data_t * p_dvd;
+ int i_audio_nr = -1;
+ int i_audio = -1;
+ int i_subp_nr = -1;
+ int i_subp = -1;
+
+ p_dvd = (dvd_data_t*)(p_input->p_access_data);
+
+ dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_audio );
+ dvdplay_subp_info( p_dvd->vmg, &i_subp_nr, &i_subp );
+
+ if( config_GetInt( p_input, "video" ) )
+ {
+ input_SelectES( p_input, p_input->stream.pp_es[0] );
+ }
+
+// if( !i_audio ) i_audio = 1;
+ if( i_audio > p_dvd->i_audio_nb ) i_audio = 1;
+ if( config_GetInt( p_input, "audio" )
+ &&( i_audio > 0 ) && ( p_dvd->i_audio_nb > 0 ) )
+ {
+ if( config_GetInt( p_input, "audio-type" ) == REQUESTED_A52 )
+ {
+ int i_a52 = i_audio;
+
+ while( ( i_a52 < p_dvd->i_audio_nb ) &&
+ ( p_input->stream.pp_es[i_a52]->i_fourcc !=
+ VLC_FOURCC('a','5','2',' ') ) )
+ {
+ i_a52++;
+ }
+ if( p_input->stream.pp_es[i_a52]->i_fourcc ==
+ VLC_FOURCC('a','5','2',' ') )
+ {
+ input_SelectES( p_input,
+ p_input->stream.pp_es[i_a52] );
+
+ /* warn libdvdplay that we have chosen another stream */
+ dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_a52 );
+ }
+ else
+ {
+// input_SelectES( p_input,
+// p_input->stream.pp_es[i_audio] );
+ }
+ }
+ else
+ {
+ input_SelectES( p_input,
+ p_input->stream.pp_es[i_audio] );
+ }
+ }
+
+ if( config_GetInt( p_input, "video" )
+ && ( i_subp > 0 ) && ( p_dvd->i_spu_nb > 0 ) )
+ {
+ i_subp += p_dvd->i_audio_nb;
+ input_SelectES( p_input, p_input->stream.pp_es[i_subp] );
+ }
+}
+
+/*****************************************************************************
+ * dvdplay_ES:
+ *****************************************************************************/
+void dvdplay_ES( input_thread_t * p_input )
+{
+ dvdplay_DeleteES ( p_input );
+ dvdplay_Video ( p_input );
+ dvdplay_Audio ( p_input );
+ dvdplay_Subp ( p_input );
+ dvdplay_LaunchDecoders( p_input );
+}
+
+
--- /dev/null
+/*****************************************************************************
+ * es.h: functions to handle elementary streams.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: es.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+void dvdplay_DeleteES( struct input_thread_t * );
+void dvdplay_Video( struct input_thread_t * );
+void dvdplay_Audio( struct input_thread_t * );
+void dvdplay_Subp( struct input_thread_t * );
+void dvdplay_ES( struct input_thread_t * );
+void dvdplay_LaunchDecoders( struct input_thread_t * );
--- /dev/null
+/*****************************************************************************
+ * intf.c: interface for DVD video manager
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: intf.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+#include <unistd.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
+#include "video.h"
+#include "video_output.h"
+
+#include "dvd.h"
+
+/*****************************************************************************
+ * intf_sys_t: description and status of interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ input_thread_t * p_input;
+ dvd_data_t * p_dvd;
+
+ vlc_bool_t b_still;
+ vlc_bool_t b_inf_still;
+ mtime_t m_still_time;
+
+};
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int InitThread ( intf_thread_t *p_intf );
+
+/* Exported functions */
+static void RunIntf ( intf_thread_t *p_intf );
+
+/*****************************************************************************
+ * OpenIntf: initialize dummy interface
+ *****************************************************************************/
+int E_(OpenIntf) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ return( 1 );
+ };
+
+ p_intf->pf_run = RunIntf;
+
+ p_intf->p_sys->m_still_time = 0;
+ p_intf->p_sys->b_inf_still = 0;
+ p_intf->p_sys->b_still = 0;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CloseIntf: destroy dummy interface
+ *****************************************************************************/
+void E_(CloseIntf) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+
+/*****************************************************************************
+ * RunIntf: main loop
+ *****************************************************************************/
+static void RunIntf( intf_thread_t *p_intf )
+{
+ vout_thread_t * p_vout;
+ dvdplay_ctrl_t control;
+ mtime_t mtime = 0;
+ mtime_t mlast = 0;
+
+ if( InitThread( p_intf ) < 0 )
+ {
+ msg_Err( p_intf, "can't initialize intf" );
+ return;
+ }
+ msg_Dbg( p_intf, "intf initialized" );
+
+ p_vout = NULL;
+ control.mouse.i_x = 0;
+ control.mouse.i_y = 0;
+
+ /* Main loop */
+ while( !p_intf->b_die )
+ {
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ /*
+ * still images
+ */
+#if 1
+ if( p_intf->p_sys->b_still && !p_intf->p_sys->b_inf_still )
+ {
+ if( p_intf->p_sys->m_still_time > 0 )
+ {
+ /* update remaining still time */
+ mtime = mdate();
+ if( mlast )
+ {
+ p_intf->p_sys->m_still_time -= mtime - mlast;
+ }
+
+ mlast = mtime;
+ }
+ else
+ {
+ /* still time elasped */
+ input_SetStatus( p_intf->p_sys->p_input,
+ INPUT_STATUS_PLAY );
+ p_intf->p_sys->m_still_time = 0;
+ p_intf->p_sys->b_still = 0;
+ mlast = 0;
+ }
+ }
+#else
+ if( p_intf->p_sys->m_still_time != (mtime_t)(-1) )
+ {
+ if( p_intf->p_sys->m_still_time )
+ {
+ mtime = mdate();
+ if( mlast )
+ {
+ p_intf->p_sys->m_still_time -= mtime - mlast;
+ }
+ if( !p_intf->p_sys->m_still_time )
+ {
+ input_SetStatus( p_intf->p_sys->p_input,
+ INPUT_STATUS_PLAY );
+ }
+ mlast = mtime;
+ }
+
+ }
+#endif
+
+ /*
+ * mouse cursor
+ */
+ p_vout = vlc_object_find( p_intf->p_sys->p_input,
+ VLC_OBJECT_VOUT, FIND_CHILD );
+ if( p_vout != NULL )
+ {
+ vlc_mutex_lock( &p_vout->change_lock );
+
+ if( control.mouse.i_x != p_vout->i_mouse_x ||
+ control.mouse.i_y != p_vout->i_mouse_y ||
+ p_vout->i_mouse_button )
+ {
+ int i_activate = 0;
+
+ control.mouse.i_x = p_vout->i_mouse_x;
+ control.mouse.i_y = p_vout->i_mouse_y;
+
+ if( p_vout->i_mouse_button )
+ {
+ control.type = DVDCtrlMouseActivate;
+
+ msg_Dbg( p_intf, "Activate coordinates: %dx%d",
+ p_vout->i_mouse_x, p_vout->i_mouse_y );
+ }
+ else
+ {
+ control.type = DVDCtrlMouseSelect;
+
+ msg_Dbg( p_intf, "Select coordinates: %dx%d",
+ p_vout->i_mouse_x, p_vout->i_mouse_y );
+ }
+ p_vout->i_mouse_button = 0;
+ vlc_mutex_unlock( &p_vout->change_lock );
+
+ msg_Dbg( p_intf, "send button" );
+
+ /* we can safely interact with libdvdplay
+ * with the stream lock */
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ i_activate =
+ dvdplay_button( p_intf->p_sys->p_dvd->vmg, &control );
+
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+
+ if( i_activate && p_intf->p_sys->b_still )
+ {
+ input_SetStatus( p_intf->p_sys->p_input,
+ INPUT_STATUS_PLAY );
+ p_intf->p_sys->b_still = 0;
+ p_intf->p_sys->b_inf_still = 0;
+ p_intf->p_sys->m_still_time = 0;
+ }
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_vout->change_lock );
+ }
+
+
+ vlc_object_release( p_vout );
+ }
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ /* Wait a bit */
+ msleep( INTF_IDLE_SLEEP );
+ }
+
+ vlc_object_release( p_intf->p_sys->p_input );
+
+}
+
+/*****************************************************************************
+ * InitThread:
+ *****************************************************************************/
+static int InitThread( intf_thread_t * p_intf )
+{
+ /* we might need some locking here */
+ if( !p_intf->b_die )
+ {
+ input_thread_t * p_input;
+ dvd_data_t * p_dvd;
+
+ p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
+ p_dvd = (dvd_data_t*)p_input->p_access_data;
+
+ p_dvd->p_intf = p_intf;
+
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ p_intf->p_sys->p_input = p_input;
+ p_intf->p_sys->p_dvd = p_dvd;
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+/*****************************************************************************
+ * dvdIntfStillTime: function provided to demux plugin to request
+ * still images
+ *****************************************************************************/
+int dvdIntfStillTime( intf_thread_t *p_intf, int i_sec )
+{
+ vlc_mutex_lock( &p_intf->change_lock );
+#if 1
+
+ if( i_sec == 0xff )
+ {
+ p_intf->p_sys->b_still = 1;
+ p_intf->p_sys->b_inf_still = 1;
+ }
+ else if( i_sec > 0 )
+ {
+ p_intf->p_sys->b_still = 1;
+ p_intf->p_sys->m_still_time = 1000000 * i_sec;
+ }
+#else
+ if( i_sec > 0 )
+ {
+ if( i_sec == 0xff )
+ {
+ p_intf->p_sys->m_still_time = (mtime_t)(-1);
+ msg_Warn( p_intf, "%lld", p_intf->p_sys->m_still_time );
+ }
+ else
+ {
+ p_intf->p_sys->m_still_time = 1000000 * i_sec;
+ }
+
+ }
+#endif
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return 0;
+}
+
+
--- /dev/null
+/*****************************************************************************
+ * intf.h: send info to intf.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: intf.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+int dvdIntfStillTime( struct intf_thread_t *, int );
--- /dev/null
+/*****************************************************************************
+ * tools.c: tools for dvd plugin.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: tools.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <vlc/vlc.h>
+
+#include "stream_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
+#include "input_ext-plugins.h"
+
+#include "dvd.h"
+
+/*****************************************************************************
+ * dvdplay_ParseCL: parse command line
+ *****************************************************************************/
+char * dvdplay_ParseCL( input_thread_t * p_input,
+ int * i_title, int * i_chapter, int * i_angle )
+{
+ dvd_data_t * p_dvd;
+ struct stat stat_info;
+ char * psz_parser;
+ char * psz_source;
+ char * psz_next;
+
+ p_dvd = (dvd_data_t*)(p_input->p_access_data);
+
+ psz_parser = psz_source = strdup( p_input->psz_name );
+ if( !psz_parser )
+ {
+ return NULL;
+ }
+
+ while( *psz_parser && *psz_parser != '@' )
+ {
+ psz_parser++;
+ }
+
+ *i_title = 0;
+ *i_chapter = 1;
+ *i_angle = 1;
+
+ if( *psz_parser == '@' )
+ {
+ /* Found options */
+ *psz_parser = '\0';
+ ++psz_parser;
+
+ *i_title = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ psz_parser = psz_next + 1;
+ *i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ *i_angle = (int)strtol( psz_next + 1, NULL, 10 );
+ }
+ }
+ }
+
+ *i_title = *i_title >= 0 ? *i_title : 0;
+ *i_chapter = *i_chapter ? *i_chapter : 1;
+ *i_angle = *i_angle ? *i_angle : 1;
+
+ if( !*psz_source )
+ {
+ free( psz_source );
+ if( !p_input->psz_access )
+ {
+ return NULL;
+ }
+ psz_source = config_GetPsz( p_input, "dvd" );
+ }
+
+ if( stat( psz_source, &stat_info ) == -1 )
+ {
+ msg_Err( p_input, "cannot stat() source `%s' (%s)",
+ psz_source, strerror(errno));
+ return NULL;
+ }
+ if( !S_ISBLK(stat_info.st_mode) &&
+ !S_ISCHR(stat_info.st_mode) &&
+ !S_ISDIR(stat_info.st_mode) )
+ {
+ msg_Dbg( p_input, "plugin discarded"
+ " (not a valid source)" );
+ return NULL;
+ }
+
+ msg_Dbg( p_input, "dvdroot=%s title=%d chapter=%d angle=%d",
+ psz_source, *i_title, *i_chapter, *i_angle );
+
+ return psz_source;
+}
--- /dev/null
+/*****************************************************************************
+ * tools.h: tools for dvdplay plugin.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: tools.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+char * dvdplay_ParseCL( struct input_thread_t *, int*, int*, int* );
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+dvdread_SOURCES = dvdread.c input.c
--- /dev/null
+/*****************************************************************************
+ * dvdread.c : DvdRead input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: dvdread.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(OpenDVD) ( vlc_object_t * );
+void E_(CloseDVD) ( vlc_object_t * );
+
+int E_(InitDVD) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ add_category_hint( "[dvdread:][device][@[title][,[chapter][,angle]]]", NULL );
+ set_description( _("DVDRead input module") );
+ add_submodule();
+ set_capability( "access", 110 );
+ set_callbacks( E_(OpenDVD), E_(CloseDVD) );
+ add_submodule();
+ set_capability( "demux", 0 );
+ set_callbacks( E_(InitDVD), NULL );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * input.c: DvdRead plugin.
+ *****************************************************************************
+ * This plugins should handle all the known specificities of the DVD format,
+ * especially the 2048 bytes logical block size.
+ * It depends on: libdvdread for ifo files and block reading.
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: input.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * Some code taken form the play_title.c by Billy Biggs <vektor@dumbterm.net>
+ * in libdvdread.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#if defined( WIN32 )
+# include <io.h> /* read() */
+#else
+# include <sys/uio.h> /* struct iovec */
+#endif
+
+#if defined( WIN32 )
+# include "input_iovec.h"
+#endif
+
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+#include <dvdread/nav_read.h>
+#include <dvdread/nav_print.h>
+
+#include "input.h"
+
+#include "iso_lang.h"
+
+/* how many blocks DVDRead will read in each loop */
+#define DVD_BLOCK_READ_ONCE 64
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+/* called from outside */
+static int DvdReadDemux ( input_thread_t * );
+static int DvdReadRewind ( input_thread_t * );
+
+static int DvdReadSetArea ( input_thread_t *, input_area_t * );
+static int DvdReadSetProgram ( input_thread_t *, pgrm_descriptor_t * );
+static int DvdReadRead ( input_thread_t *, byte_t *, size_t );
+static void DvdReadSeek ( input_thread_t *, off_t );
+
+/* called only from here */
+static void DvdReadLauchDecoders( input_thread_t * p_input );
+static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data );
+static void DvdReadFindCell ( thread_dvd_data_t * p_dvd );
+
+/*
+ * Data demux functions
+ */
+
+/*****************************************************************************
+ * InitDVD: initializes DVD structures
+ *****************************************************************************/
+int E_(InitDVD) ( vlc_object_t *p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+
+ if( p_input->stream.i_method != INPUT_METHOD_DVD )
+ {
+ return -1;
+ }
+
+ p_input->pf_demux = DvdReadDemux;
+ p_input->pf_rewind = NULL;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ DvdReadLauchDecoders( p_input );
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * DvdReadDemux
+ *****************************************************************************/
+#define PEEK( SIZE ) \
+ i_result = input_Peek( p_input, &p_peek, SIZE ); \
+ if( i_result == -1 ) \
+ { \
+ return( -1 ); \
+ } \
+ else if( i_result < SIZE ) \
+ { \
+ /* EOF */ \
+ return( 0 ); \
+ }
+
+static int DvdReadDemux( input_thread_t * p_input )
+{
+ int i;
+ byte_t * p_peek;
+ data_packet_t * p_data;
+ ssize_t i_result;
+ int i_packet_size;
+
+
+ /* Read headers to compute payload length */
+ for( i = 0 ; i < DVD_BLOCK_READ_ONCE ; i++ )
+ {
+
+ /* Read what we believe to be a packet header. */
+ PEEK( 4 );
+
+ /* Default header */
+ if( U32_AT( p_peek ) != 0x1BA )
+ {
+ /* That's the case for all packets, except pack header. */
+ i_packet_size = U16_AT( p_peek + 4 );
+ }
+ else
+ {
+ /* MPEG-2 Pack header. */
+ i_packet_size = 8;
+ }
+
+ /* Fetch a packet of the appropriate size. */
+ i_result = input_SplitBuffer( p_input, &p_data, i_packet_size + 6 );
+ if( i_result <= 0 )
+ {
+ return( i_result );
+ }
+
+ /* In MPEG-2 pack headers we still have to read stuffing bytes. */
+ if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )
+ {
+ size_t i_stuffing = (p_data->p_demux_start[13] & 0x7);
+ /* Force refill of the input buffer - though we don't care
+ * about p_peek. Please note that this is unoptimized. */
+ PEEK( i_stuffing );
+ p_input->p_current_data += i_stuffing;
+ }
+
+ input_DemuxPS( p_input, p_data );
+
+ }
+
+ return i;
+}
+
+/*****************************************************************************
+ * DVDRewind : reads a stream backward
+ *****************************************************************************/
+static int DvdReadRewind( input_thread_t * p_input )
+{
+ return( -1 );
+}
+
+/*
+ * Data access functions
+ */
+
+/*****************************************************************************
+ * OpenDVD: open libdvdread
+ *****************************************************************************/
+int E_(OpenDVD) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ char * psz_orig;
+ char * psz_parser;
+ char * psz_source;
+ char * psz_next;
+ struct stat stat_info;
+ thread_dvd_data_t * p_dvd;
+ dvd_reader_t * p_dvdread;
+ input_area_t * p_area;
+ int i_title = 1;
+ int i_chapter = 1;
+ int i_angle = 1;
+ int i;
+
+ psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
+ if( !psz_orig )
+ {
+ return( -1 );
+ }
+
+ p_input->pf_read = DvdReadRead;
+ p_input->pf_seek = DvdReadSeek;
+ p_input->pf_set_area = DvdReadSetArea;
+ p_input->pf_set_program = DvdReadSetProgram;
+
+ while( *psz_parser && *psz_parser != '@' )
+ {
+ psz_parser++;
+ }
+
+ if( *psz_parser == '@' )
+ {
+ /* Found options */
+ *psz_parser = '\0';
+ ++psz_parser;
+
+ i_title = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ psz_parser = psz_next + 1;
+ i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ i_angle = (int)strtol( psz_next + 1, NULL, 10 );
+ }
+ }
+
+ i_title = i_title ? i_title : 1;
+ i_chapter = i_chapter ? i_chapter : 1;
+ i_angle = i_angle ? i_angle : 1;
+ }
+
+ if( !*psz_source )
+ {
+ if( !p_input->psz_access )
+ {
+ free( psz_orig );
+ return -1;
+ }
+ psz_source = config_GetPsz( p_input, "dvd" );
+ }
+
+ if( stat( psz_source, &stat_info ) == -1 )
+ {
+ msg_Err( p_input, "cannot stat() source `%s' (%s)",
+ psz_source, strerror(errno));
+ return( -1 );
+ }
+ if( !S_ISBLK(stat_info.st_mode) &&
+ !S_ISCHR(stat_info.st_mode) &&
+ !S_ISDIR(stat_info.st_mode) )
+ {
+ msg_Warn( p_input, "dvdread module discarded (not a valid source)" );
+ return -1;
+ }
+
+ msg_Dbg( p_input, "dvdroot=%s title=%d chapter=%d angle=%d",
+ psz_source, i_title, i_chapter, i_angle );
+
+
+ p_dvdread = DVDOpen( psz_source );
+
+ /* free allocated strings */
+ if( psz_source != psz_orig )
+ free( psz_source );
+ free( psz_orig );
+
+ if( ! p_dvdread )
+ {
+ msg_Err( p_input, "libdvdcss cannot open source" );
+ return -1;
+ }
+
+ /* set up input */
+ p_input->i_mtu = 0;
+
+ p_dvd = malloc( sizeof(thread_dvd_data_t) );
+ if( p_dvd == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ return -1;
+ }
+
+ p_dvd->p_dvdread = p_dvdread;
+ p_dvd->p_title = NULL;
+ p_dvd->p_vts_file = NULL;
+
+
+ p_input->p_access_data = (void *)p_dvd;
+
+ /* Ifo allocation & initialisation */
+ if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) )
+ {
+ msg_Err( p_input, "cannot open VMG info" );
+ free( p_dvd );
+ return -1;
+ }
+ msg_Dbg( p_input, "VMG opened" );
+
+ /* Set stream and area data */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.i_method = INPUT_METHOD_DVD;
+
+ /* If we are here we can control the pace... */
+ p_input->stream.b_pace_control = 1;
+ p_input->stream.b_seekable = 1;
+
+ p_input->stream.p_selected_area->i_size = 0;
+ p_input->stream.p_selected_area->i_tell = 0;
+
+ /* Initialize ES structures */
+ input_InitStream( p_input, sizeof( stream_ps_data_t ) );
+
+ /* disc input method */
+ p_input->stream.i_method = INPUT_METHOD_DVD;
+
+#define tt_srpt p_dvd->p_vmg_file->tt_srpt
+ msg_Dbg( p_input, "number of titles: %d", tt_srpt->nr_of_srpts );
+
+#define area p_input->stream.pp_areas
+ /* We start from 1 here since the default area 0
+ * is reserved for video_ts.vob */
+ for( i = 1 ; i <= tt_srpt->nr_of_srpts ; i++ )
+ {
+ input_AddArea( p_input );
+
+ /* Titles are Program Chains */
+ area[i]->i_id = i;
+
+ /* Absolute start offset and size
+ * We can only set that with vts ifo, so we do it during the
+ * first call to DVDSetArea */
+ area[i]->i_start = 0;
+ area[i]->i_size = 0;
+
+ /* Number of chapters */
+ area[i]->i_part_nb = tt_srpt->title[i-1].nr_of_ptts;
+ area[i]->i_part = 1;
+
+ area[i]->i_plugin_data = tt_srpt->title[i-1].title_set_nr;
+ }
+#undef area
+
+ p_dvd->i_title = i_title <= tt_srpt->nr_of_srpts ? i_title : 1;
+#undef tt_srpt
+
+ p_area = p_input->stream.pp_areas[p_dvd->i_title];
+ p_dvd->i_chapter = i_chapter;
+
+ p_dvd->i_chapter = i_chapter < p_area->i_part_nb ? i_chapter : 1;
+ p_area->i_part = p_dvd->i_chapter;
+
+ p_dvd->i_angle = i_angle;
+
+ /* set title, chapter, audio and subpic */
+ if( DvdReadSetArea( p_input, p_area ) )
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ return -1;
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_input->psz_demux = "dvdread";
+
+ return 0;
+}
+
+/*****************************************************************************
+ * CloseDVD: close libdvdread
+ *****************************************************************************/
+void E_(CloseDVD) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ thread_dvd_data_t * p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
+
+ /* close libdvdread */
+ DVDCloseFile( p_dvd->p_title );
+ ifoClose( p_dvd->p_vts_file );
+ ifoClose( p_dvd->p_vmg_file );
+
+ DVDClose( p_dvd->p_dvdread );
+ free( p_dvd );
+ p_input->p_access_data = NULL;
+
+}
+
+/*****************************************************************************
+ * DvdReadSetProgram: Does nothing, a DVD is mono-program
+ *****************************************************************************/
+static int DvdReadSetProgram( input_thread_t * p_input,
+ pgrm_descriptor_t * p_program )
+{
+ if( p_input->stream.p_selected_program != p_program )
+ {
+ thread_dvd_data_t * p_dvd;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+ p_dvd->i_angle = p_program->i_number;
+
+ memcpy( p_program, p_input->stream.p_selected_program,
+ sizeof(pgrm_descriptor_t) );
+ p_program->i_number = p_dvd->i_angle;
+ p_input->stream.p_selected_program = p_program;
+
+ msg_Dbg( p_input, "angle %d selected", p_dvd->i_angle );
+ }
+
+ return 0;
+}
+
+#define p_pgc p_dvd->p_cur_pgc
+
+/*****************************************************************************
+ * DvdReadSetArea: initialize input data for title x, chapter y.
+ * It should be called for each user navigation request.
+ *****************************************************************************
+ * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
+ * Note that you have to take the lock before entering here.
+ *****************************************************************************/
+static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
+{
+ thread_dvd_data_t * p_dvd;
+ int pgc_id = 0;
+ int pgn = 0;
+
+ p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
+
+ /* we can't use the interface slider until initilization is complete */
+ p_input->stream.b_seekable = 0;
+
+ if( p_area != p_input->stream.p_selected_area )
+ {
+ es_descriptor_t * p_es;
+ int i_cell = 0;
+ int i_audio_nb = 0;
+ int i_spu_nb = 0;
+ int i;
+
+#define p_vmg p_dvd->p_vmg_file
+#define p_vts p_dvd->p_vts_file
+ if( p_dvd->p_title != NULL )
+ {
+ DVDCloseFile( p_dvd->p_title );
+ }
+
+ if( p_vts != NULL )
+ {
+ ifoClose( p_vts );
+ }
+
+ /* Reset the Chapter position of the old title */
+ p_input->stream.p_selected_area->i_part = 1;
+
+ /*
+ * We have to load all title information
+ */
+ /* Change the default area */
+ p_input->stream.p_selected_area = p_area;
+
+ msg_Dbg( p_input, "open VTS %d, for title %d",
+ p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr,
+ p_area->i_id );
+
+ /* ifo vts */
+ if( ! ( p_vts = ifoOpen( p_dvd->p_dvdread,
+ p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr ) ) )
+ {
+ msg_Err( p_input, "fatal error in vts ifo" );
+ ifoClose( p_vmg );
+ DVDClose( p_dvd->p_dvdread );
+ return -1;
+ }
+
+ /* title position inside the selected vts */
+ p_dvd->i_ttn = p_vmg->tt_srpt->title[ p_area->i_id - 1 ].vts_ttn;
+
+ /*
+ * Set selected title start
+ */
+ pgc_id = p_vts->vts_ptt_srpt->title[p_dvd->i_ttn-1].ptt[0].pgcn;
+ pgn = p_vts->vts_ptt_srpt->title[p_dvd->i_ttn-1].ptt[0].pgn;
+ p_pgc = p_vts->vts_pgcit->pgci_srp[ pgc_id - 1 ].pgc;
+ i_cell = p_pgc->program_map[ pgn - 1 ] - 1;
+
+ p_area->i_start =
+ LB2OFF( p_dvd->p_cur_pgc->cell_playback[ i_cell ].first_sector );
+
+ msg_Dbg( p_input, "start %d vts_title %d pgc %d pgn %d",
+ p_area->i_id, p_dvd->i_ttn, pgc_id, pgn );
+
+ /*
+ * Find title end
+ */
+ i_cell = p_dvd->p_cur_pgc->nr_of_cells - 1;
+
+ p_dvd->i_end_block = p_pgc->cell_playback[ i_cell ].last_sector;
+ p_area->i_size = LB2OFF( p_dvd->i_end_block )- p_area->i_start;
+
+ msg_Dbg( p_input, "start %lld size %lld end %d",
+ p_area->i_start , p_area->i_size, p_dvd->i_end_block );
+
+ /*
+ * Set properties for current chapter
+ */
+ /* Remeber current chapter */
+ p_dvd->i_chapter = p_area->i_part;
+ p_dvd->b_eoc = 0;
+
+ pgc_id = p_vts->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgcn;
+ pgn = p_vts->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgn;
+
+ p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id-1].pgc;
+ p_dvd->i_pack_len = 0;
+ p_dvd->i_next_cell = p_dvd->i_cur_cell = p_pgc->program_map[pgn-1] - 1;
+ DvdReadFindCell( p_dvd );
+
+ p_dvd->i_next_vobu = p_dvd->i_cur_block =
+ p_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
+
+ /*
+ * Angle management
+ */
+ p_dvd->i_angle_nb = p_vmg->tt_srpt->title[p_area->i_id-1].nr_of_angles;
+
+ if( p_dvd->i_angle > p_dvd->i_angle_nb )
+ {
+ p_dvd->i_angle = 1;
+ }
+
+ /*
+ * We've got enough info, time to open the title set data.
+ */
+ if( ! ( p_dvd->p_title = DVDOpenFile( p_dvd->p_dvdread,
+ p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr,
+ DVD_READ_TITLE_VOBS ) ) )
+ {
+ msg_Err( p_input, "cannot open title (VTS_%02d_1.VOB)",
+ p_vmg->tt_srpt->title[p_area->i_id-1].title_set_nr );
+ ifoClose( p_vts );
+ ifoClose( p_vmg );
+ DVDClose( p_dvd->p_dvdread );
+ return -1;
+ }
+
+// IfoPrintTitle( p_dvd );
+
+ /*
+ * Destroy obsolete ES by reinitializing program 0
+ * and find all ES in title with ifo data
+ */
+ if( p_input->stream.pp_programs != NULL )
+ {
+ /* We don't use input_EndStream here since
+ * we keep area structures */
+
+ while( p_input->stream.i_es_number )
+ {
+ input_DelES( p_input, p_input->stream.pp_es[0] );
+ }
+
+ while( p_input->stream.i_pgrm_number )
+ {
+ input_DelProgram( p_input, p_input->stream.pp_programs[0] );
+ }
+
+ if( p_input->stream.pp_selected_es )
+ {
+ free( p_input->stream.pp_selected_es );
+ p_input->stream.pp_selected_es = NULL;
+ }
+ p_input->stream.i_selected_es_number = 0;
+ }
+
+ input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+
+ for( i = 1 ; i < p_dvd->i_angle_nb ; i++ )
+ {
+ input_AddProgram( p_input, i+1, 0 );
+ }
+
+ DvdReadSetProgram( p_input,
+ p_input->stream.pp_programs[p_dvd->i_angle-1] );
+
+ /* No PSM to read in DVD mode, we already have all information */
+ p_input->stream.p_selected_program->b_is_ok = 1;
+
+ p_es = NULL;
+
+ /* ES 0 -> video MPEG2 */
+// IfoPrintVideo( p_dvd );
+
+ p_es = input_AddES( p_input, NULL, 0xe0, 0 );
+ p_es->i_stream_id = 0xe0;
+ p_es->i_fourcc = VLC_FOURCC('m','p','g','v');
+ p_es->i_cat = VIDEO_ES;
+
+#define audio_control \
+ p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
+ /* Audio ES, in the order they appear in .ifo */
+ for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams ; i++ )
+ {
+ int i_position = 0;
+ u16 i_id;
+
+// IfoPrintAudio( p_dvd, i );
+
+ /* audio channel is active if first byte is 0x80 */
+ if( audio_control & 0x8000 )
+ {
+ i_audio_nb++;
+ i_position = ( audio_control & 0x7F00 ) >> 8;
+
+ msg_Dbg( p_input, "audio position %d", i_position );
+ switch( p_vts->vtsi_mat->vts_audio_attr[i-1].audio_format )
+ {
+ case 0x00: /* A52 */
+ i_id = ( ( 0x80 + i_position ) << 8 ) | 0xbd;
+ p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es->i_stream_id = 0xbd;
+ p_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
+ p_es->i_cat = AUDIO_ES;
+ strcpy( p_es->psz_desc, DecodeLanguage(
+ p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) );
+ strcat( p_es->psz_desc, " (A52)" );
+
+ break;
+ case 0x02:
+ case 0x03: /* MPEG audio */
+ i_id = 0xc0 + i_position;
+ p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es->i_stream_id = i_id;
+ p_es->i_fourcc = VLC_FOURCC('m','p','g','a');
+ p_es->i_cat = AUDIO_ES;
+ strcpy( p_es->psz_desc, DecodeLanguage(
+ p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) );
+ strcat( p_es->psz_desc, " (mpeg)" );
+
+ break;
+ case 0x04: /* LPCM */
+
+ i_id = ( ( 0xa0 + i_position ) << 8 ) | 0xbd;
+ p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es->i_stream_id = i_id;
+ p_es->i_fourcc = VLC_FOURCC('l','p','c','m');
+ p_es->i_cat = AUDIO_ES;
+ strcpy( p_es->psz_desc, DecodeLanguage(
+ p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) );
+ strcat( p_es->psz_desc, " (lpcm)" );
+
+ break;
+ case 0x06: /* DTS */
+ i_id = ( ( 0x88 + i_position ) << 8 ) | 0xbd;
+ msg_Err( p_input, "DTS audio not handled yet"
+ "(0x%x)", i_id );
+ break;
+ default:
+ i_id = 0;
+ msg_Err( p_input, "unknown audio type %.2x",
+ p_vts->vtsi_mat->vts_audio_attr[i-1].audio_format );
+ }
+ }
+ }
+#undef audio_control
+#define spu_control \
+ p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i-1]
+
+ /* Sub Picture ES */
+
+ for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
+ {
+ int i_position = 0;
+ u16 i_id;
+
+// IfoPrintSpu( p_dvd, i );
+ msg_Dbg( p_input, "spu %d 0x%02x", i, spu_control );
+
+ if( spu_control & 0x80000000 )
+ {
+ i_spu_nb++;
+
+ /* there are several streams for one spu */
+ if( p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
+ {
+ /* 16:9 */
+ switch( p_vts->vtsi_mat->vts_video_attr.permitted_df )
+ {
+ case 1:
+ i_position = spu_control & 0xff;
+ break;
+ case 2:
+ i_position = ( spu_control >> 8 ) & 0xff;
+ break;
+ default:
+ i_position = ( spu_control >> 16 ) & 0xff;
+ break;
+ }
+ }
+ else
+ {
+ /* 4:3 */
+ i_position = ( spu_control >> 24 ) & 0x7F;
+ }
+
+ i_id = ( ( 0x20 + i_position ) << 8 ) | 0xbd;
+ p_es = input_AddES( p_input, NULL, i_id, 0 );
+ p_es->i_stream_id = 0xbd;
+ p_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
+ p_es->i_cat = SPU_ES;
+ strcpy( p_es->psz_desc, DecodeLanguage(
+ p_vts->vtsi_mat->vts_subp_attr[i-1].lang_code ) );
+ }
+ }
+#undef spu_control
+
+ /* FIXME: hack to check that the demuxer is ready, and set
+ * the decoders */
+ if( p_input->p_demux )
+ {
+ DvdReadLauchDecoders( p_input );
+ }
+
+ } /* i_title >= 0 */
+ else
+ {
+ p_area = p_input->stream.p_selected_area;
+ }
+
+ /*
+ * Chapter selection
+ */
+
+ if( p_area->i_part != p_dvd->i_chapter )
+ {
+ if( ( p_area->i_part > 0 ) &&
+ ( p_area->i_part <= p_area->i_part_nb ))
+ {
+ p_dvd->i_ttn = p_vmg->tt_srpt->title[p_area->i_id-1].vts_ttn;
+ pgc_id = p_vts->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgcn;
+ pgn = p_vts->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgn;
+
+ p_pgc = p_vts->vts_pgcit->pgci_srp[ pgc_id - 1 ].pgc;
+
+ p_dvd->i_cur_cell = p_pgc->program_map[ pgn - 1 ] - 1;
+ p_dvd->i_chapter = p_area->i_part;
+ DvdReadFindCell( p_dvd );
+
+ p_dvd->i_pack_len = 0;
+ p_dvd->i_next_vobu = p_dvd->i_cur_block =
+ p_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
+ }
+ else
+ {
+ p_area->i_part = p_dvd->i_chapter;
+ }
+ }
+#undef p_vts
+#undef p_vmg
+
+ /* warn interface that something has changed */
+ p_area->i_tell = LB2OFF( p_dvd->i_next_vobu ) - p_area->i_start;
+ p_input->stream.b_seekable = 1;
+ p_input->stream.b_changed = 1;
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * DvdReadRead: reads data packets into the netlist.
+ *****************************************************************************
+ * Returns -1 in case of error, 0 if everything went well, and 1 in case of
+ * EOF.
+ *****************************************************************************/
+static int DvdReadRead( input_thread_t * p_input,
+ byte_t * p_buffer, size_t i_count )
+{
+ thread_dvd_data_t * p_dvd;
+ byte_t * p_buf;
+ int i_blocks_once;
+ int i_blocks;
+ int i_read;
+ int i_read_total;
+ vlc_bool_t b_eot = 0;
+
+ p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
+ p_buf = p_buffer;
+
+ /*
+ * Playback by cell in this pgc, starting at the cell for our chapter.
+ */
+ i_blocks = OFF2LB( i_count );
+ i_read_total = 0;
+ i_read = 0;
+
+ while( i_blocks )
+ {
+ /*
+ * End of pack, we select the following one
+ */
+ if( ! p_dvd->i_pack_len )
+ {
+ /*
+ * Read NAV packet.
+ */
+ if( ( i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_next_vobu,
+ 1, p_buf ) ) != 1 )
+ {
+ msg_Err( p_input, "read failed for block %d",
+ p_dvd->i_next_vobu );
+ return -1;
+ }
+
+ /* basic check to be sure we don't have a empty title
+ * go to next title if so */
+ //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
+
+ /*
+ * Parse the contained dsi packet.
+ */
+
+ DvdReadHandleDSI( p_dvd, p_buf );
+
+ /* End of File */
+ if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 )
+ {
+ return 1;
+ }
+
+ assert( p_dvd->i_pack_len < 1024 );
+ /* FIXME: Ugly kludge: we send the pack block to the input for it
+ * sometimes has a zero scr and restart the sync */
+ p_dvd->i_cur_block ++;
+ //p_dvd->i_pack_len++;
+
+ i_read_total++;
+ p_buf += DVD_VIDEO_LB_LEN;
+ i_blocks--;
+ }
+
+ /*
+ * Compute the number of blocks to read
+ */
+ i_blocks_once = p_dvd->i_pack_len >= i_blocks
+ ? i_blocks : p_dvd->i_pack_len;
+ p_dvd->i_pack_len -= i_blocks_once;
+
+ /* Reads from DVD */
+ i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_cur_block,
+ i_blocks_once, p_buf );
+ if( i_read != i_blocks_once )
+ {
+ msg_Err( p_input, "read failed for %d/%d blocks at 0x%02x",
+ i_read, i_blocks_once, p_dvd->i_cur_block );
+ return -1;
+ }
+
+ i_blocks -= i_read;
+ i_read_total += i_read;
+ p_dvd->i_cur_block += i_read;
+ p_buf += LB2OFF( i_read );
+
+ }
+/*
+ msg_Dbg( p_input, "i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block );
+*/
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.p_selected_area->i_tell =
+ LB2OFF( p_dvd->i_cur_block ) -
+ p_input->stream.p_selected_area->i_start;
+
+ if( p_dvd->b_eoc )
+ {
+ /* We modify i_part only at end of chapter not to erase
+ * some modification from the interface */
+ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
+ p_dvd->b_eoc = 0;
+ }
+
+ if( p_input->stream.p_selected_area->i_tell
+ >= p_input->stream.p_selected_area->i_size || b_eot )
+ {
+ if( ( p_input->stream.p_selected_area->i_id + 1 ) >=
+ p_input->stream.i_area_nb )
+ {
+ /* EOF */
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ return 1;
+ }
+
+ /* EOT */
+ msg_Dbg( p_input, "new title" );
+ DvdReadSetArea( p_input, p_input->stream.pp_areas[
+ p_input->stream.p_selected_area->i_id+1] );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ return 0;
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return LB2OFF( i_read_total );
+}
+#undef p_pgc
+
+/*****************************************************************************
+ * DvdReadSeek : Goes to a given position on the stream.
+ *****************************************************************************
+ * This one is used by the input and translate chronological position from
+ * input to logical position on the device.
+ * The lock should be taken before calling this function.
+ *****************************************************************************/
+static void DvdReadSeek( input_thread_t * p_input, off_t i_off )
+{
+ thread_dvd_data_t * p_dvd;
+ int i_lb;
+ int i_tmp;
+ int i_chapter = 0;
+ int i_cell = 0;
+ int i_vobu = 0;
+ int i_sub_cell = 0;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ i_off += p_input->stream.p_selected_area->i_start;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ i_lb = OFF2LB( i_off );
+ p_dvd = ( thread_dvd_data_t * )p_input->p_access_data;
+
+ /* find cell */
+ while( p_dvd->p_cur_pgc->cell_playback[i_cell].last_sector < i_lb )
+ {
+ i_cell++;
+ }
+
+ /* find chapter */
+ do
+ {
+ pgc_t * p_pgc;
+ int pgc_id, pgn;
+
+ i_chapter++;
+ pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[i_chapter-1].pgcn;
+ pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[i_chapter-1].pgn;
+
+ p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
+ i_tmp = p_pgc->program_map[pgn-1];
+
+ } while( i_tmp <= i_cell );
+
+ /* find vobu */
+ while( p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu]
+ <= i_lb )
+ {
+ i_vobu++;
+ }
+
+ /* find sub_cell */
+ while( p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell].start_sector <
+ p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu-1] )
+ {
+ i_sub_cell++;
+ }
+
+/*
+ msg_Dbg( p_input, "cell %d i_sub_cell %d chapter %d vobu %d cell_sector %d vobu_sector %d sub_cell_sector %d",
+ i_cell, i_sub_cell,i_chapter, i_vobu,
+ p_dvd->p_cur_pgc->cell_playback[i_cell].first_sector,
+ p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu],
+ p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell-1].start_sector);
+*/
+ p_dvd->i_cur_block = i_lb;
+ p_dvd->i_next_vobu =
+ p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu];
+ p_dvd->i_pack_len = p_dvd->i_next_vobu - i_lb;
+ p_dvd->i_cur_cell = i_cell;
+ p_dvd->i_chapter = i_chapter;
+ DvdReadFindCell( p_dvd );
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.p_selected_area->i_tell =
+ LB2OFF ( p_dvd->i_cur_block )
+ - p_input->stream.p_selected_area->i_start;
+ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return;
+}
+
+/*****************************************************************************
+ * DvdReadHandleDSI
+ *****************************************************************************/
+static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data )
+{
+ navRead_DSI( &(p_dvd->dsi_pack), &(p_data[ DSI_START_BYTE ]) );
+
+ /*
+ * Determine where we go next. These values are the ones we mostly
+ * care about.
+ */
+ p_dvd->i_cur_block = p_dvd->dsi_pack.dsi_gi.nv_pck_lbn;
+
+ /*
+ * If we're not at the end of this cell, we can determine the next
+ * VOBU to display using the VOBU_SRI information section of the
+ * DSI. Using this value correctly follows the current angle,
+ * avoiding the doubled scenes in The Matrix, and makes our life
+ * really happy.
+ */
+ if( p_dvd->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL )
+ {
+#if 1
+ switch( ( p_dvd->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
+ {
+ case 0x4:
+ /* interleaved unit with no angle */
+ if( p_dvd->dsi_pack.sml_pbi.ilvu_sa != -1 )
+ {
+ p_dvd->i_next_vobu = p_dvd->i_cur_block +
+ p_dvd->dsi_pack.sml_pbi.ilvu_sa;
+ p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea;
+ }
+ else
+ {
+ p_dvd->i_next_vobu = p_dvd->i_cur_block +
+ p_dvd->dsi_pack.dsi_gi.vobu_ea + 1;
+ p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
+ }
+ break;
+ case 0x5:
+ /* vobu is end of ilvu */
+ if( p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address )
+ {
+ p_dvd->i_next_vobu = p_dvd->i_cur_block +
+ p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address;
+ p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea;
+
+ break;
+ }
+ case 0x6:
+ /* vobu is beginning of ilvu */
+ case 0x9:
+ /* next scr is 0 */
+ case 0xa:
+ /* entering interleaved section */
+ case 0x8:
+ /* non interleaved cells in interleaved section */
+ default:
+ p_dvd->i_next_vobu = p_dvd->i_cur_block +
+ ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+ p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
+ break;
+ }
+#else
+ p_dvd->i_next_vobu = p_dvd->i_cur_block +
+ ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+ p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
+#endif
+ }
+ else
+ {
+ p_dvd->i_cur_cell = p_dvd->i_next_cell;
+ DvdReadFindCell( p_dvd );
+
+ p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
+ p_dvd->i_next_vobu =
+ p_dvd->p_cur_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
+ }
+
+#if 0
+ msg_Dbg( p_input, 12, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d",
+ p_dvd->dsi_pack.dsi_gi.nv_pck_scr,
+ p_dvd->dsi_pack.dsi_gi.nv_pck_lbn,
+ p_dvd->dsi_pack.dsi_gi.vobu_ea,
+ p_dvd->dsi_pack.dsi_gi.vobu_vob_idn,
+ p_dvd->dsi_pack.dsi_gi.vobu_c_idn );
+
+ msg_Dbg( p_input, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d",
+ p_dvd->dsi_pack.sml_pbi.category,
+ p_dvd->dsi_pack.sml_pbi.ilvu_ea,
+ p_dvd->dsi_pack.sml_pbi.ilvu_sa,
+ p_dvd->dsi_pack.sml_pbi.size );
+
+ msg_Dbg( p_input, 12, "next_vobu %d next_ilvu1 %d next_ilvu2 %d",
+ p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff,
+ p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle - 1 ].address,
+ p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle ].address);
+#endif
+}
+
+/*****************************************************************************
+ * DvdReadFindCell
+ *****************************************************************************/
+static void DvdReadFindCell( thread_dvd_data_t * p_dvd )
+{
+ int pgc_id, pgn;
+ int i = 0;
+ pgc_t * p_pgc;
+#define cell p_dvd->p_cur_pgc->cell_playback
+ if( cell[p_dvd->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
+ {
+#if 0
+ p_dvd->i_next_cell = p_dvd->i_cur_cell + p_dvd->i_angle_nb;
+ p_dvd->i_cur_cell += p_dvd->i_angle - 1;
+#else
+ p_dvd->i_cur_cell += p_dvd->i_angle - 1;
+
+ while( cell[p_dvd->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL )
+ {
+ i++;
+ }
+ p_dvd->i_next_cell = p_dvd->i_cur_cell + i + 1;
+#endif
+ }
+ else
+ {
+ p_dvd->i_next_cell = p_dvd->i_cur_cell + 1;
+ }
+#undef cell
+ pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgcn;
+ pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[
+ p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgn;
+ p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
+
+ if( p_pgc->program_map[pgn-1] <= p_dvd->i_cur_cell )
+ {
+ p_dvd->i_chapter++;
+ p_dvd->b_eoc = 1;
+ }
+}
+
+/*****************************************************************************
+ * DvdReadLaunchDecoders
+ *****************************************************************************/
+static void DvdReadLauchDecoders( input_thread_t * p_input )
+{
+ thread_dvd_data_t * p_dvd;
+
+ p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
+
+ if( config_GetInt( p_input, "video" ) )
+ {
+ input_SelectES( p_input, p_input->stream.pp_es[0] );
+ }
+
+ if( config_GetInt( p_input, "audio" ) )
+ {
+ /* For audio: first one if none or a not existing one specified */
+ int i_audio = config_GetInt( p_input, "audio-channel" );
+ if( i_audio < 0 /*|| i_audio > i_audio_nb*/ )
+ {
+ config_PutInt( p_input, "audio-channel", 1 );
+ i_audio = 1;
+ }
+ if( i_audio > 0/* && i_audio_nb > 0*/ )
+ {
+ if( config_GetInt( p_input, "audio-type" )
+ == REQUESTED_A52 )
+ {
+ int i_a52 = i_audio;
+ while( ( p_input->stream.pp_es[i_a52]->i_fourcc !=
+ VLC_FOURCC('a','5','2',' ') ) && ( i_a52 <=
+ p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams ) )
+ {
+ i_a52++;
+ }
+ if( p_input->stream.pp_es[i_a52]->i_fourcc
+ == VLC_FOURCC('a','5','2',' ') )
+ {
+ input_SelectES( p_input,
+ p_input->stream.pp_es[i_a52] );
+ }
+ }
+ else
+ {
+ input_SelectES( p_input,
+ p_input->stream.pp_es[i_audio] );
+ }
+ }
+ }
+
+ if( config_GetInt( p_input, "video" ) )
+ {
+ /* for spu, default is none */
+ int i_spu = config_GetInt( p_input, "spu-channel" );
+ if( i_spu < 0 /*|| i_spu > i_spu_nb*/ )
+ {
+ config_PutInt( p_input, "spu-channel", 0 );
+ i_spu = 0;
+ }
+ if( i_spu > 0 /*&& i_spu_nb > 0*/ )
+ {
+ i_spu += p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams;
+ input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
+ }
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * input.h: thread structure of the DVD plugin
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: input.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+/* Logical block size for DVD-VIDEO */
+#define LB2OFF(x) ((off_t)(x) * (off_t)(DVD_VIDEO_LB_LEN))
+#define OFF2LB(x) ((x) >> 11)
+
+/*****************************************************************************
+ * thread_dvd_data_t: extension of input_thread_t for DVD specificity.
+ *****************************************************************************/
+typedef struct thread_dvd_data_s
+{
+ dvd_reader_t * p_dvdread;
+ dvd_file_t * p_title;
+
+ ifo_handle_t * p_vmg_file;
+ ifo_handle_t * p_vts_file;
+
+ int i_title;
+ int i_chapter;
+ int i_angle;
+ int i_angle_nb;
+
+ tt_srpt_t * p_tt_srpt;
+ pgc_t * p_cur_pgc;
+
+ dsi_t dsi_pack;
+
+ int i_ttn;
+
+ unsigned int i_pack_len;
+ unsigned int i_cur_block;
+ unsigned int i_next_vobu;
+ unsigned int i_end_block;
+
+ int i_cur_cell;
+ int i_next_cell;
+ vlc_bool_t b_eoc;
+} thread_dvd_data_t;
+
--- /dev/null
+/*****************************************************************************
+ * file.c: file input (file: access plug-in)
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: file.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#elif defined( _MSC_VER ) && defined( _WIN32 )
+# include <io.h>
+#endif
+
+/*****************************************************************************
+ * Open: open the file
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ char * psz_name = p_input->psz_name;
+ int i_stat;
+ struct stat stat_info;
+ input_socket_t * p_access_data;
+ vlc_bool_t b_stdin;
+
+ p_input->i_mtu = 0;
+
+ b_stdin = psz_name[0] == '-' && psz_name[1] == '\0';
+
+ if( !b_stdin && (i_stat = stat( psz_name, &stat_info )) == (-1) )
+ {
+ msg_Err( p_input, "cannot stat() file `%s' (%s)",
+ psz_name, strerror(errno));
+ return( -1 );
+ }
+
+ p_input->pf_read = input_FDRead;
+ p_input->pf_set_program = input_SetProgram;
+ p_input->pf_set_area = NULL;
+ p_input->pf_seek = input_FDSeek;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ if( *p_input->psz_access && !strncmp( p_input->psz_access, "stream", 7 ) )
+ {
+ /* stream:%s */
+ p_input->stream.b_pace_control = 0;
+ p_input->stream.b_seekable = 0;
+ p_input->stream.p_selected_area->i_size = 0;
+ }
+ else
+ {
+ /* file:%s or %s */
+ p_input->stream.b_pace_control = 1;
+
+ if( b_stdin )
+ {
+ p_input->stream.b_seekable = 0;
+ p_input->stream.p_selected_area->i_size = 0;
+ }
+ else if( S_ISREG(stat_info.st_mode) || S_ISCHR(stat_info.st_mode)
+ || S_ISBLK(stat_info.st_mode) )
+ {
+ p_input->stream.b_seekable = 1;
+ p_input->stream.p_selected_area->i_size = stat_info.st_size;
+ }
+ else if( S_ISFIFO(stat_info.st_mode)
+#if !defined( SYS_BEOS ) && !defined( WIN32 )
+ || S_ISSOCK(stat_info.st_mode)
+#endif
+ )
+ {
+ p_input->stream.b_seekable = 0;
+ p_input->stream.p_selected_area->i_size = 0;
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ msg_Err( p_input, "unknown file type for `%s'", psz_name );
+ return( -1 );
+ }
+ }
+
+ p_input->stream.p_selected_area->i_tell = 0;
+ p_input->stream.i_method = INPUT_METHOD_FILE;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ msg_Dbg( p_input, "opening file `%s'", psz_name );
+ p_access_data = malloc( sizeof(input_socket_t) );
+ p_input->p_access_data = (void *)p_access_data;
+ if( p_access_data == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ return( -1 );
+ }
+
+ if( b_stdin )
+ {
+ p_access_data->i_handle = 0;
+ }
+ else if( (p_access_data->i_handle = open( psz_name,
+ /*O_NONBLOCK | O_LARGEFILE*/ 0 )) == (-1) )
+ {
+ msg_Err( p_input, "cannot open file %s (%s)", psz_name,
+ strerror(errno) );
+ free( p_access_data );
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Standard filesystem file reading") );
+ set_capability( "access", 50 );
+ add_shortcut( "stream" );
+ set_callbacks( Open, __input_FDClose );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * http.c: HTTP access plug-in
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: http.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#elif defined( _MSC_VER ) && defined( _WIN32 )
+# include <io.h>
+#endif
+
+#ifdef WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# ifndef IN_MULTICAST
+# define IN_MULTICAST(a) IN_CLASSD(a)
+# endif
+#else
+# include <sys/socket.h>
+#endif
+
+#include "network.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static int SetProgram ( input_thread_t *, pgrm_descriptor_t * );
+static void Seek ( input_thread_t *, off_t );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("HTTP access module") );
+ set_capability( "access", 0 );
+ add_shortcut( "http4" );
+ add_shortcut( "http6" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * _input_socket_t: private access plug-in data, modified to add private
+ * fields
+ *****************************************************************************/
+typedef struct _input_socket_s
+{
+ input_socket_t _socket;
+
+ char * psz_network;
+ network_socket_t socket_desc;
+ char psz_buffer[256];
+ char * psz_name;
+} _input_socket_t;
+
+/*****************************************************************************
+ * HTTPConnect: connect to the server and seek to i_tell
+ *****************************************************************************/
+static int HTTPConnect( input_thread_t * p_input, off_t i_tell )
+{
+ _input_socket_t * p_access_data = p_input->p_access_data;
+ module_t * p_network;
+ char psz_buffer[256];
+ byte_t * psz_parser;
+ int i_returncode, i;
+ char * psz_return_alpha;
+
+ /* Find an appropriate network module */
+ p_input->p_private = (void*) &p_access_data->socket_desc;
+ p_network = module_Need( p_input, "network", p_access_data->psz_network );
+ if( p_network == NULL )
+ {
+ return( -1 );
+ }
+ module_Unneed( p_input, p_network );
+
+ p_access_data->_socket.i_handle = p_access_data->socket_desc.i_handle;
+
+# define HTTP_USERAGENT "User-Agent: " COPYRIGHT_MESSAGE "\r\n"
+# define HTTP_END "\r\n"
+
+ if ( p_input->stream.b_seekable )
+ {
+ snprintf( psz_buffer, sizeof(psz_buffer),
+ "%s"
+ "Range: bytes=%lld-\r\n"
+ HTTP_USERAGENT HTTP_END,
+ p_access_data->psz_buffer, i_tell );
+ }
+ else
+ {
+ snprintf( psz_buffer, sizeof(psz_buffer),
+ "%s"
+ HTTP_USERAGENT HTTP_END,
+ p_access_data->psz_buffer );
+ }
+ psz_buffer[sizeof(psz_buffer) - 1] = '\0';
+
+ /* Send GET ... */
+ if( send( p_access_data->_socket.i_handle, psz_buffer,
+ strlen( psz_buffer ), 0 ) == (-1) )
+ {
+ msg_Err( p_input, "cannot send request (%s)", strerror(errno) );
+ input_FDNetworkClose( p_input );
+ return( -1 );
+ }
+
+ /* Prepare the input thread for reading. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+
+ /* FIXME: we shouldn't have to do that ! It's UGLY but mandatory because
+ * input_FillBuffer assumes p_input->pf_read exists */
+ p_input->pf_read = input_FDNetworkRead;
+
+ while( !input_FillBuffer( p_input ) )
+ {
+ if( p_input->b_die || p_input->b_error )
+ {
+ input_FDNetworkClose( p_input );
+ return( -1 );
+ }
+ }
+
+ /* Parse HTTP header. */
+#define MAX_LINE 1024
+
+ /* get the returncode */
+ if( input_Peek( p_input, &psz_parser, MAX_LINE ) <= 0 )
+ {
+ msg_Err( p_input, "not enough data" );
+ input_FDNetworkClose( p_input );
+ return( -1 );
+ }
+
+ if( !strncmp( psz_parser, "HTTP/1.",
+ strlen("HTTP/1.") ) )
+ {
+ psz_parser += strlen("HTTP 1.") + 2;
+ i_returncode = atoi( psz_parser );
+ msg_Dbg( p_input, "HTTP server replied: %i", i_returncode );
+ psz_parser += 4;
+ for ( i = 0; psz_parser[i] != '\r' || psz_parser[i+1] != '\n'; i++ )
+ {
+ ;
+ }
+ psz_return_alpha = malloc( i + 1 );
+ memcpy( psz_return_alpha, psz_parser, i );
+ psz_return_alpha[i] = '\0';
+ }
+ else
+ {
+ msg_Err( p_input, "invalid http reply" );
+ return -1;
+ }
+
+ if ( i_returncode >= 400 ) /* something is wrong */
+ {
+ msg_Err( p_input, "%i %s", i_returncode,
+ psz_return_alpha );
+ return -1;
+ }
+
+ for( ; ; )
+ {
+ if( input_Peek( p_input, &psz_parser, MAX_LINE ) <= 0 )
+ {
+ msg_Err( p_input, "not enough data" );
+ input_FDNetworkClose( p_input );
+ return( -1 );
+ }
+
+ if( psz_parser[0] == '\r' && psz_parser[1] == '\n' )
+ {
+ /* End of header. */
+ p_input->p_current_data += 2;
+ break;
+ }
+
+ if( !strncmp( psz_parser, "Content-Length: ",
+ strlen("Content-Length: ") ) )
+ {
+ psz_parser += strlen("Content-Length: ");
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+#ifdef HAVE_ATOLL
+ p_input->stream.p_selected_area->i_size = atoll( psz_parser )
+ + i_tell;
+#else
+ /* FIXME : this won't work for 64-bit lengths */
+ p_input->stream.p_selected_area->i_size = atoi( psz_parser )
+ + i_tell;
+#endif
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+
+ while( *psz_parser != '\r' && psz_parser < p_input->p_last_data )
+ {
+ psz_parser++;
+ }
+ p_input->p_current_data = psz_parser + 2;
+ }
+
+ if( p_input->stream.p_selected_area->i_size )
+ {
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.p_selected_area->i_tell = i_tell
+ + (p_input->p_last_data - p_input->p_current_data);
+ p_input->stream.b_seekable = 1;
+ p_input->stream.b_changed = 1;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Open: parse URL and open the remote file at the beginning
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ _input_socket_t * p_access_data;
+ char * psz_name = strdup(p_input->psz_name);
+ char * psz_parser = psz_name;
+ char * psz_server_addr = "";
+ char * psz_server_port = "";
+ char * psz_path = "";
+ char * psz_proxy;
+ int i_server_port = 0;
+
+ p_access_data = p_input->p_access_data = malloc( sizeof(_input_socket_t) );
+ if( p_access_data == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ free(psz_name);
+ return( -1 );
+ }
+
+ p_access_data->psz_name = psz_name;
+ p_access_data->psz_network = "";
+ if( config_GetInt( p_input, "ipv4" ) )
+ {
+ p_access_data->psz_network = "ipv4";
+ }
+ if( config_GetInt( p_input, "ipv6" ) )
+ {
+ p_access_data->psz_network = "ipv6";
+ }
+ if( *p_input->psz_access )
+ {
+ /* Find out which shortcut was used */
+ if( !strncmp( p_input->psz_access, "http6", 6 ) )
+ {
+ p_access_data->psz_network = "ipv6";
+ }
+ else if( !strncmp( p_input->psz_access, "http4", 6 ) )
+ {
+ p_access_data->psz_network = "ipv4";
+ }
+ }
+
+ /* Parse psz_name syntax :
+ * //<hostname>[:<port>][/<path>] */
+ while( *psz_parser == '/' )
+ {
+ psz_parser++;
+ }
+ psz_server_addr = psz_parser;
+
+ while( *psz_parser && *psz_parser != ':' && *psz_parser != '/' )
+ {
+ psz_parser++;
+ }
+
+ if ( *psz_parser == ':' )
+ {
+ *psz_parser = '\0';
+ psz_parser++;
+ psz_server_port = psz_parser;
+
+ while( *psz_parser && *psz_parser != '/' )
+ {
+ psz_parser++;
+ }
+ }
+
+ if( *psz_parser == '/' )
+ {
+ *psz_parser = '\0';
+ psz_parser++;
+ psz_path = psz_parser;
+ }
+
+ /* Convert port format */
+ if( *psz_server_port )
+ {
+ i_server_port = strtol( psz_server_port, &psz_parser, 10 );
+ if( *psz_parser )
+ {
+ msg_Err( p_input, "cannot parse server port near %s", psz_parser );
+ free( p_input->p_access_data );
+ free( psz_name );
+ return( -1 );
+ }
+ }
+
+ if( i_server_port == 0 )
+ {
+ i_server_port = 80;
+ }
+
+ if( !*psz_server_addr )
+ {
+ msg_Err( p_input, "no server given" );
+ free( p_input->p_access_data );
+ free( psz_name );
+ return( -1 );
+ }
+
+ /* Check proxy */
+ if( (psz_proxy = getenv( "http_proxy" )) != NULL && *psz_proxy )
+ {
+ /* http://myproxy.mydomain:myport/ */
+ int i_proxy_port = 0;
+
+ /* Skip the protocol name */
+ while( *psz_proxy && *psz_proxy != ':' )
+ {
+ psz_proxy++;
+ }
+
+ /* Skip the "://" part */
+ while( *psz_proxy && (*psz_proxy == ':' || *psz_proxy == '/') )
+ {
+ psz_proxy++;
+ }
+
+ /* Found a proxy name */
+ if( *psz_proxy )
+ {
+ char *psz_port = psz_proxy;
+
+ /* Skip the hostname part */
+ while( *psz_port && *psz_port != ':' && *psz_port != '/' )
+ {
+ psz_port++;
+ }
+
+ /* Found a port name */
+ if( *psz_port )
+ {
+ char * psz_junk;
+
+ /* Replace ':' with '\0' */
+ *psz_port = '\0';
+ psz_port++;
+
+ psz_junk = psz_port;
+ while( *psz_junk && *psz_junk != '/' )
+ {
+ psz_junk++;
+ }
+
+ if( *psz_junk )
+ {
+ *psz_junk = '\0';
+ }
+
+ if( *psz_port != '\0' )
+ {
+ i_proxy_port = atoi( psz_port );
+ }
+ }
+ }
+ else
+ {
+ msg_Err( p_input, "http_proxy environment variable is invalid!" );
+ free( p_input->p_access_data );
+ free( psz_name );
+ return( -1 );
+ }
+
+ p_access_data->socket_desc.i_type = NETWORK_TCP;
+ p_access_data->socket_desc.psz_server_addr = psz_proxy;
+ p_access_data->socket_desc.i_server_port = i_proxy_port;
+
+ snprintf( p_access_data->psz_buffer, sizeof(p_access_data->psz_buffer),
+ "GET http://%s:%d/%s\r\n HTTP/1.0\r\n",
+ psz_server_addr, i_server_port, psz_path );
+ }
+ else
+ {
+ /* No proxy, direct connection. */
+ p_access_data->socket_desc.i_type = NETWORK_TCP;
+ p_access_data->socket_desc.psz_server_addr = psz_server_addr;
+ p_access_data->socket_desc.i_server_port = i_server_port;
+
+ snprintf( p_access_data->psz_buffer, sizeof(p_access_data->psz_buffer),
+ "GET /%s HTTP/1.1\r\nHost: %s\r\n",
+ psz_path, psz_server_addr );
+ }
+ p_access_data->psz_buffer[sizeof(p_access_data->psz_buffer) - 1] = '\0';
+
+ msg_Dbg( p_input, "opening server=%s port=%d path=%s",
+ psz_server_addr, i_server_port, psz_path );
+
+ p_input->pf_read = input_FDNetworkRead;
+ p_input->pf_set_program = SetProgram;
+ p_input->pf_set_area = NULL;
+ p_input->pf_seek = Seek;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.b_pace_control = 1;
+ p_input->stream.b_seekable = 1;
+ p_input->stream.p_selected_area->i_tell = 0;
+ p_input->stream.p_selected_area->i_size = 0;
+ p_input->stream.i_method = INPUT_METHOD_NETWORK;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ p_input->i_mtu = 0;
+
+ if( HTTPConnect( p_input, 0 ) )
+ {
+ char * psz_pos = strstr(p_access_data->psz_buffer, "HTTP/1.1");
+ p_input->stream.b_seekable = 0;
+ psz_pos[7] = '0';
+ if( HTTPConnect( p_input, 0 ) )
+ {
+ free( p_input->p_access_data );
+ free( psz_name );
+ return( -1 );
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ * Close: free unused data structures
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ _input_socket_t * p_access_data =
+ (_input_socket_t *)p_input->p_access_data;
+
+ free( p_access_data->psz_name );
+ input_FDNetworkClose( p_input );
+}
+
+/*****************************************************************************
+ * SetProgram: do nothing
+ *****************************************************************************/
+static int SetProgram( input_thread_t * p_input,
+ pgrm_descriptor_t * p_program )
+{
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Seek: close and re-open a connection at the right place
+ *****************************************************************************/
+static void Seek( input_thread_t * p_input, off_t i_pos )
+{
+ _input_socket_t * p_access_data = p_input->p_access_data;
+ close( p_access_data->_socket.i_handle );
+ msg_Dbg( p_input, "seeking to position %lld", i_pos );
+ HTTPConnect( p_input, i_pos );
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+satellite_SOURCES = satellite.c access.c dvb.c
--- /dev/null
+/*****************************************************************************
+ * access.c: Satellite card input
+ *****************************************************************************
+ * Copyright (C) 1998-2002 VideoLAN
+ *
+ * Authors: Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef STRNCASECMP_IN_STRINGS_H
+# include <strings.h>
+#endif
+
+#include "dvb.h"
+
+#define SATELLITE_READ_ONCE 3
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
+ size_t i_len );
+static int SatelliteSetArea ( input_thread_t *, input_area_t * );
+static int SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
+static void SatelliteSeek ( input_thread_t *, off_t );
+
+/*****************************************************************************
+ * Open: open the dvr device
+ *****************************************************************************/
+int E_(Open) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ input_socket_t * p_satellite;
+ char * psz_parser;
+ char * psz_next;
+ int i_fd = 0;
+ int i_freq = 0;
+ int i_srate = 0;
+ vlc_bool_t b_pol = 0;
+ int i_fec = 0;
+ float f_fec = 1./2;
+ vlc_bool_t b_diseqc;
+ int i_lnb_lof1;
+ int i_lnb_lof2;
+ int i_lnb_slof;
+
+ /* parse the options passed in command line : */
+
+ psz_parser = strdup( p_input->psz_name );
+
+ if( !psz_parser )
+ {
+ return( -1 );
+ }
+
+ p_input->pf_read = SatelliteRead;
+ p_input->pf_set_program = SatelliteSetProgram;
+ p_input->pf_set_area = SatelliteSetArea;
+ p_input->pf_seek = SatelliteSeek;
+
+ i_freq = (int)strtol( psz_parser, &psz_next, 10 );
+
+ if( *psz_next )
+ {
+ psz_parser = psz_next + 1;
+ b_pol = (vlc_bool_t)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ psz_parser = psz_next + 1;
+ i_fec = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ psz_parser = psz_next + 1;
+ i_srate = (int)strtol( psz_parser, &psz_next, 10 );
+ }
+ }
+
+ }
+
+ if( i_freq > 12999 || i_freq < 10000 )
+ {
+ msg_Warn( p_input, "invalid frequency, using default one" );
+ i_freq = config_GetInt( p_input, "frequency" );
+ if( i_freq > 12999 || i_freq < 10000 )
+ {
+ msg_Err( p_input, "invalid default frequency" );
+ return -1;
+ }
+ }
+
+ if( i_srate > 30000 || i_srate < 1000 )
+ {
+ msg_Warn( p_input, "invalid symbol rate, using default one" );
+ i_srate = config_GetInt( p_input, "symbol-rate" );
+ if( i_srate > 30000 || i_srate < 1000 )
+ {
+ msg_Err( p_input, "invalid default symbol rate" );
+ return -1;
+ }
+ }
+
+ if( b_pol && b_pol != 1 )
+ {
+ msg_Warn( p_input, "invalid polarization, using default one" );
+ b_pol = config_GetInt( p_input, "polarization" );
+ if( b_pol && b_pol != 1 )
+ {
+ msg_Err( p_input, "invalid default polarization" );
+ return -1;
+ }
+ }
+
+ if( i_fec > 7 || i_fec < 1 )
+ {
+ msg_Warn( p_input, "invalid FEC, using default one" );
+ i_fec = config_GetInt( p_input, "fec" );
+ if( i_fec > 7 || i_fec < 1 )
+ {
+ msg_Err( p_input, "invalid default FEC" );
+ return -1;
+ }
+ }
+
+ switch( i_fec )
+ {
+ case 1:
+ f_fec = 1./2;
+ break;
+ case 2:
+ f_fec = 2./3;
+ break;
+ case 3:
+ f_fec = 3./4;
+ break;
+ case 4:
+ f_fec = 4./5;
+ break;
+ case 5:
+ f_fec = 5./6;
+ break;
+ case 6:
+ f_fec = 6./7;
+ break;
+ case 7:
+ f_fec = 7./8;
+ break;
+ default:
+ /* cannot happen */
+ break;
+ }
+
+
+ /* Initialise structure */
+ p_satellite = malloc( sizeof( input_socket_t ) );
+
+ if( p_satellite == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ return -1;
+ }
+
+ p_input->p_access_data = (void *)p_satellite;
+
+ /* Open the DVR device */
+ msg_Dbg( p_input, "opening DVR device `%s'", DVR );
+
+ if( (p_satellite->i_handle = open( DVR,
+ /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
+ {
+ msg_Warn( p_input, "cannot open `%s' (%s)", DVR, strerror(errno) );
+ free( p_satellite );
+ return -1;
+ }
+
+
+ /* Get antenna configuration options */
+ b_diseqc = config_GetInt( p_input, "diseqc" );
+ i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" );
+ i_lnb_lof2 = config_GetInt( p_input, "lnb-lof2" );
+ i_lnb_slof = config_GetInt( p_input, "lnb-slof" );
+
+ /* Initialize the Satellite Card */
+
+ msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, "
+ "FEC: %03f, Srate: %d", i_freq, b_pol, f_fec, i_srate );
+
+ if ( ioctl_SECControl( i_freq * 1000, b_pol, i_lnb_slof * 1000,
+ b_diseqc ) < 0 )
+ {
+ msg_Err( p_input, "an error occured when controling SEC" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ }
+
+ msg_Dbg( p_input, "initializing frontend device" );
+ switch (ioctl_SetQPSKFrontend ( i_freq * 1000, i_srate* 1000, f_fec,
+ i_lnb_lof1 * 1000, i_lnb_lof2 * 1000, i_lnb_slof * 1000))
+ {
+ case -2:
+ msg_Err( p_input, "frontend returned an unexpected event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -3:
+ msg_Err( p_input, "frontend returned no event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -4:
+ msg_Err( p_input, "frontend: timeout when polling for event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -5:
+ msg_Err( p_input, "an error occured when polling frontend device" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -1:
+ msg_Err( p_input, "frontend returned a failure event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ default:
+ break;
+ }
+
+ msg_Dbg( p_input, "setting filter on PAT" );
+
+ if ( ioctl_SetDMXFilter( 0, &i_fd, 3 ) < 0 )
+ {
+ msg_Err( p_input, "an error occured when setting filter on PAT" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ }
+
+ if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
+ {
+ msg_Err( p_input, "could not initialize stream structure" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return( -1 );
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.b_pace_control = 1;
+ p_input->stream.b_seekable = 0;
+ p_input->stream.p_selected_area->i_tell = 0;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_input->i_mtu = SATELLITE_READ_ONCE * TS_PACKET_SIZE;
+ p_input->stream.i_method = INPUT_METHOD_SATELLITE;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Close : Close the device
+ *****************************************************************************/
+void E_(Close) ( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ input_socket_t * p_satellite;
+ int i_es_index;
+
+ if ( p_input->stream.p_selected_program )
+ {
+ for ( i_es_index = 1 ;
+ i_es_index < p_input->stream.p_selected_program->
+ i_es_number ;
+ i_es_index ++ )
+ {
+#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
+ if ( p_es->p_decoder_fifo )
+ {
+ ioctl_UnsetDMXFilter( p_es->i_demux_fd );
+ }
+#undef p_es
+ }
+ }
+
+ p_satellite = (input_socket_t *)p_input;
+ close( p_satellite->i_handle );
+}
+
+
+/*****************************************************************************
+ * SatelliteRead: reads data from the satellite card
+ *****************************************************************************/
+static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
+ size_t i_len )
+{
+ int i;
+
+ /* if not set, set filters to the PMTs */
+ for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
+ {
+ if ( p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd == 0 )
+ {
+ msg_Dbg( p_input, "setting filter on pmt pid %d",
+ p_input->stream.pp_programs[i]->pp_es[0]->i_id );
+ ioctl_SetDMXFilter( p_input->stream.pp_programs[i]->pp_es[0]->i_id,
+ &p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd,
+ 3 );
+ }
+ }
+
+ return input_FDRead( p_input, p_buffer, i_len );
+}
+
+
+
+
+/*****************************************************************************
+ * SatelliteSetArea : Does nothing
+ *****************************************************************************/
+static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
+{
+ return -1;
+}
+
+/*****************************************************************************
+ * SatelliteSetProgram : Sets the card filters according to the
+ * selected program,
+ * and makes the appropriate changes to stream structure.
+ *****************************************************************************/
+int SatelliteSetProgram( input_thread_t * p_input,
+ pgrm_descriptor_t * p_new_prg )
+{
+ int i_es_index;
+
+ if ( p_input->stream.p_selected_program )
+ {
+ for ( i_es_index = 1 ; /* 0 should be the PMT */
+ i_es_index < p_input->stream.p_selected_program->
+ i_es_number ;
+ i_es_index ++ )
+ {
+#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
+ if ( p_es->p_decoder_fifo )
+ {
+ input_UnselectES( p_input , p_es );
+ }
+ if ( p_es->i_demux_fd )
+ {
+ ioctl_UnsetDMXFilter( p_es->i_demux_fd );
+ p_es->i_demux_fd = 0;
+ }
+#undef p_es
+ }
+ }
+
+ for (i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
+ {
+#define p_es p_new_prg->pp_es[i_es_index]
+ switch( p_es->i_cat )
+ {
+ case MPEG1_VIDEO_ES:
+ case MPEG2_VIDEO_ES:
+ if ( config_GetInt( p_input, "video" ) )
+ {
+ ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 1);
+ input_SelectES( p_input , p_es );
+ }
+ break;
+ case MPEG1_AUDIO_ES:
+ case MPEG2_AUDIO_ES:
+ if ( config_GetInt( p_input, "audio" ) )
+ {
+ ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 2);
+ input_SelectES( p_input , p_es );
+ }
+ break;
+ default:
+ ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 3);
+ input_SelectES( p_input , p_es );
+ break;
+#undef p_es
+ }
+ }
+
+ p_input->stream.p_selected_program = p_new_prg;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SatelliteSeek: does nothing (not a seekable stream
+ *****************************************************************************/
+static void SatelliteSeek( input_thread_t * p_input, off_t i_off )
+{
+ return;
+}
--- /dev/null
+/*****************************************************************************
+ * dvb.c : functions to control a DVB card under Linux
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ *
+ * Authors: Damien Lucas <nitrox@via.ecp.fr>
+ * Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <vlc/vlc.h>
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h> /* int16_t .. */
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+
+/* DVB Card Drivers */
+#include <ost/sec.h>
+#include <ost/dmx.h>
+#include <ost/frontend.h>
+
+
+#include "dvb.h"
+
+/*****************************************************************************
+ * ioctl_SECControl : commands the SEC device
+ *****************************************************************************/
+
+
+int ioctl_SECControl( int freq, int pol, int lnb_slof, int diseqc)
+{
+ struct secCommand scmd;
+ struct secCmdSequence scmds;
+ int sec;
+
+ if((sec = open(SEC,O_RDWR)) < 0)
+ {
+ return -1;
+ }
+
+ /* Set the frequency of the transponder, taking into account the
+ local frequencies of the LNB */
+ scmds.continuousTone = (freq<lnb_slof) ? SEC_TONE_OFF : SEC_TONE_ON;
+
+ /* Set the polarity of the transponder by setting the correct
+ voltage on the universal LNB */
+ scmds.voltage = (pol) ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13;
+
+ /* In case we have a DiSEqC, set it to the correct address */
+ scmd.type=0;
+ scmd.u.diseqc.addr=0x10;
+ scmd.u.diseqc.cmd=0x38;
+ scmd.u.diseqc.numParams=1;
+ scmd.u.diseqc.params[0] = 0xF0 | ((diseqc * 4) & 0x0F) |
+ (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
+ (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
+
+ scmds.miniCommand=SEC_MINI_NONE;
+ scmds.numCommands=1;
+ scmds.commands=&scmd;
+
+ /* Send the data to the SEC device to prepare the LNB for tuning */
+ /*intf_Msg("Sec: Sending data\n");*/
+ if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0)
+ {
+ return -1;
+ }
+
+ close(sec);
+
+ return 0;
+}
+
+static int check_qpsk( int );
+
+/*****************************************************************************
+ * ioctl_SetQPSKFrontend : controls the FE device
+ *****************************************************************************/
+
+int ioctl_SetQPSKFrontend (int freq, int srate, int fec,\
+ int lnb_lof1, int lnb_lof2, int lnb_slof)
+{
+ FrontendParameters fep;
+ int front;
+ int rc;
+
+ /* Open the frontend device */
+ if((front = open(FRONTEND,O_RDWR)) < 0)
+ {
+ return -1;
+ }
+
+ /* Set the frequency of the transponder, taking into account the
+ local frequencies of the LNB */
+ fep.Frequency = (freq < lnb_slof) ? freq - lnb_lof1 : freq - lnb_lof2;
+
+ /* Set symbol rate and FEC */
+ fep.u.qpsk.SymbolRate = srate;
+ fep.u.qpsk.FEC_inner = FEC_AUTO;
+
+ /* Now send it all to the frontend device */
+ if (ioctl(front, FE_SET_FRONTEND, &fep) < 0)
+ {
+ return -1;
+ }
+
+ /* Check if it worked */
+ rc=check_qpsk(front);
+
+ /* Close front end device */
+ close(front);
+
+ return rc;
+}
+
+
+
+/******************************************************************
+ * Check completion of the frontend control sequence
+ ******************************************************************/
+static int check_qpsk(int front)
+{
+ struct pollfd pfd[1];
+ FrontendEvent event;
+ /* poll for QPSK event to check if tuning worked */
+ pfd[0].fd = front;
+ pfd[0].events = POLLIN;
+
+ if (poll(pfd,1,3000))
+ {
+ if (pfd[0].revents & POLLIN)
+ {
+ if ( ioctl(front, FE_GET_EVENT, &event) == -EBUFFEROVERFLOW)
+ {
+ return -5;
+ }
+
+ switch(event.type)
+ {
+ case FE_UNEXPECTED_EV:
+ return -2;
+ case FE_FAILURE_EV:
+ return -1;
+ case FE_COMPLETION_EV:
+ break;
+ }
+ }
+ else
+ {
+ /* should come here */
+ return -3;
+ }
+ }
+ else
+ {
+ return -4;
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * ioctl_SetDMXAudioFilter : controls the demux to add a filter
+ *****************************************************************************/
+
+int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type )
+{
+ struct dmxPesFilterParams s_filter_params;
+
+ /* We first open the device */
+ if ((*pi_fd = open(DMX, O_RDWR|O_NONBLOCK)) < 0)
+ {
+ return -1;
+ }
+
+ /* We fill the DEMUX structure : */
+ s_filter_params.pid = i_pid;
+ s_filter_params.input = DMX_IN_FRONTEND;
+ s_filter_params.output = DMX_OUT_TS_TAP;
+ switch ( i_type )
+ {
+ case 1:
+ s_filter_params.pesType = DMX_PES_VIDEO;
+ break;
+ case 2:
+ s_filter_params.pesType = DMX_PES_AUDIO;
+ break;
+ case 3:
+ s_filter_params.pesType = DMX_PES_OTHER;
+ break;
+ }
+ s_filter_params.flags = DMX_IMMEDIATE_START;
+
+ /* We then give the order to the device : */
+ if (ioctl(*pi_fd, DMX_SET_PES_FILTER, &s_filter_params) < 0)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * ioctl_UnsetDMXFilter : removes a filter
+ *****************************************************************************/
+int ioctl_UnsetDMXFilter(int demux)
+{
+ ioctl(demux, DMX_STOP);
+ close(demux);
+ return 0;
+}
--- /dev/null
+/*****************************************************************************
+ * linux_dvb_tools.h : functions to control a DVB card under Linux
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ *
+ * Authors: Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * Devices location
+ *****************************************************************************/
+#define SEC "/dev/ost/sec"
+#define DMX "/dev/ost/demux"
+#define FRONTEND "/dev/ost/frontend"
+#define DVR "/dev/ost/dvr"
+
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+int ioctl_SECControl( int , int , int , int );
+int ioctl_SetQPSKFrontend ( int , int , int , int , int , int );
+int ioctl_SetDMXFilter( int , int *, int );
+int ioctl_UnsetDMXFilter( int );
--- /dev/null
+/*****************************************************************************
+ * satellite.c : Satellite input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000 VideoLAN
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(Open) ( vlc_object_t * );
+void E_(Close) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+#define FREQ_TEXT N_("satellite default transponder frequency")
+#define FREQ_LONGTEXT ""
+
+#define POL_TEXT N_("satellite default transponder polarization")
+#define POL_LONGTEXT ""
+
+#define FEC_TEXT N_("satellite default transponder FEC")
+#define FEC_LONGTEXT ""
+
+#define SRATE_TEXT N_("satellite default transponder symbol rate")
+#define SRATE_LONGTEXT ""
+
+#define DISEQC_TEXT N_("use diseqc with antenna")
+#define DISEQC_LONGTEXT ""
+
+#define LNB_LOF1_TEXT N_("antenna lnb_lof1 (kHz)")
+#define LNB_LOF1_LONGTEXT ""
+
+#define LNB_LOF2_TEXT N_("antenna lnb_lof2 (kHz)")
+#define LNB_LOF2_LONGTEXT ""
+
+#define LNB_SLOF_TEXT N_("antenna lnb_slof (kHz)")
+#define LNB_SLOF_LONGTEXT ""
+
+vlc_module_begin();
+ add_category_hint( N_("Input"), NULL );
+ add_integer( "frequency", 11954, NULL, FREQ_TEXT, FREQ_LONGTEXT );
+ add_integer( "polarization", 0, NULL, POL_TEXT, POL_LONGTEXT );
+ add_integer( "fec", 3, NULL, FEC_TEXT, FEC_LONGTEXT );
+ add_integer( "symbol-rate", 27500, NULL, SRATE_TEXT, SRATE_LONGTEXT );
+ add_bool( "diseqc", 0, NULL, DISEQC_TEXT, DISEQC_LONGTEXT );
+ add_integer( "lnb-lof1", 10000, NULL,
+ LNB_LOF1_TEXT, LNB_LOF1_LONGTEXT );
+ add_integer( "lnb-lof2", 10000, NULL,
+ LNB_LOF2_TEXT, LNB_LOF2_LONGTEXT );
+ add_integer( "lnb-slof", 11700, NULL,
+ LNB_SLOF_TEXT, LNB_SLOF_LONGTEXT );
+ set_description( _("satellite input module") );
+ set_capability( "access", 0 );
+ add_shortcut( "sat" );
+ set_callbacks( E_(Open), E_(Close) );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * udp.c: raw UDP access plug-in
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: udp.c,v 1.1 2002/08/04 17:23:41 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#elif defined( _MSC_VER ) && defined( _WIN32 )
+# include <io.h>
+#endif
+
+#include "network.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("raw UDP access module") );
+ set_capability( "access", 0 );
+ add_shortcut( "udpstream" );
+ add_shortcut( "udp4" );
+ add_shortcut( "udp6" );
+ set_callbacks( Open, __input_FDNetworkClose );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: open the socket
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ input_socket_t * p_access_data;
+ module_t * p_network;
+ char * psz_network = "";
+ char * psz_name = strdup(p_input->psz_name);
+ char * psz_parser = psz_name;
+ char * psz_server_addr = "";
+ char * psz_server_port = "";
+ char * psz_bind_addr = "";
+ char * psz_bind_port = "";
+ int i_bind_port = 0, i_server_port = 0;
+ network_socket_t socket_desc;
+
+ if( config_GetInt( p_input, "ipv4" ) )
+ {
+ psz_network = "ipv4";
+ }
+ if( config_GetInt( p_input, "ipv6" ) )
+ {
+ psz_network = "ipv6";
+ }
+
+ if( *p_input->psz_access )
+ {
+ /* Find out which shortcut was used */
+ if( !strncmp( p_input->psz_access, "udp6", 5 ) )
+ {
+ psz_network = "ipv6";
+ }
+ else if( !strncmp( p_input->psz_access, "udp4", 5 ) )
+ {
+ psz_network = "ipv4";
+ }
+ }
+
+ /* Parse psz_name syntax :
+ * [serveraddr[:serverport]][@[bindaddr]:[bindport]] */
+
+ if( *psz_parser && *psz_parser != '@' )
+ {
+ /* Found server */
+ psz_server_addr = psz_parser;
+
+ while( *psz_parser && *psz_parser != ':' && *psz_parser != '@' )
+ {
+ if( *psz_parser == '[' )
+ {
+ /* IPv6 address */
+ while( *psz_parser && *psz_parser != ']' )
+ {
+ psz_parser++;
+ }
+ }
+ psz_parser++;
+ }
+
+ if( *psz_parser == ':' )
+ {
+ /* Found server port */
+ *psz_parser = '\0'; /* Terminate server name */
+ psz_parser++;
+ psz_server_port = psz_parser;
+
+ while( *psz_parser && *psz_parser != '@' )
+ {
+ psz_parser++;
+ }
+ }
+ }
+
+ if( *psz_parser == '@' )
+ {
+ /* Found bind address or bind port */
+ *psz_parser = '\0'; /* Terminate server port or name if necessary */
+ psz_parser++;
+
+ if( *psz_parser && *psz_parser != ':' )
+ {
+ /* Found bind address */
+ psz_bind_addr = psz_parser;
+
+ while( *psz_parser && *psz_parser != ':' )
+ {
+ if( *psz_parser == '[' )
+ {
+ /* IPv6 address */
+ while( *psz_parser && *psz_parser != ']' )
+ {
+ psz_parser++;
+ }
+ }
+ psz_parser++;
+ }
+ }
+
+ if( *psz_parser == ':' )
+ {
+ /* Found bind port */
+ *psz_parser = '\0'; /* Terminate bind address if necessary */
+ psz_parser++;
+
+ psz_bind_port = psz_parser;
+ }
+ }
+
+ /* Convert ports format */
+ if( *psz_server_port )
+ {
+ i_server_port = strtol( psz_server_port, &psz_parser, 10 );
+ if( *psz_parser )
+ {
+ msg_Err( p_input, "cannot parse server port near %s", psz_parser );
+ free(psz_name);
+ return( -1 );
+ }
+ }
+
+ if( *psz_bind_port )
+ {
+ i_bind_port = strtol( psz_bind_port, &psz_parser, 10 );
+ if( *psz_parser )
+ {
+ msg_Err( p_input, "cannot parse bind port near %s", psz_parser );
+ free(psz_name);
+ return( -1 );
+ }
+ }
+
+ p_input->pf_read = input_FDNetworkRead;
+ p_input->pf_set_program = input_SetProgram;
+ p_input->pf_set_area = NULL;
+ p_input->pf_seek = NULL;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.b_pace_control = 0;
+ p_input->stream.b_seekable = 0;
+ p_input->stream.p_selected_area->i_tell = 0;
+ p_input->stream.i_method = INPUT_METHOD_NETWORK;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ if( *psz_server_addr || i_server_port )
+ {
+ msg_Err( p_input, "this UDP syntax is deprecated; the server argument will be");
+ msg_Err( p_input, "ignored (%s:%d). If you wanted to enter a multicast address",
+ psz_server_addr, i_server_port);
+ msg_Err( p_input, "or local port, type : %s:@%s:%d",
+ *p_input->psz_access ? p_input->psz_access : "udp",
+ psz_server_addr, i_server_port );
+
+ i_server_port = 0;
+ psz_server_addr = "";
+ }
+
+ msg_Dbg( p_input, "opening server=%s:%d local=%s:%d",
+ psz_server_addr, i_server_port, psz_bind_addr, i_bind_port );
+
+ /* Prepare the network_socket_t structure */
+ socket_desc.i_type = NETWORK_UDP;
+ socket_desc.psz_bind_addr = psz_bind_addr;
+ socket_desc.i_bind_port = i_bind_port;
+ socket_desc.psz_server_addr = psz_server_addr;
+ socket_desc.i_server_port = i_server_port;
+
+ /* Find an appropriate network module */
+ p_input->p_private = (void*) &socket_desc;
+ p_network = module_Need( p_input, "network", psz_network );
+ free(psz_name);
+ if( p_network == NULL )
+ {
+ return( -1 );
+ }
+ module_Unneed( p_input, p_network );
+
+ p_access_data = p_input->p_access_data = malloc( sizeof(input_socket_t) );
+ if( p_access_data == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ return( -1 );
+ }
+
+ p_access_data->i_handle = socket_desc.i_handle;
+ p_input->i_mtu = socket_desc.i_mtu;
+
+ return( 0 );
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+vcd_SOURCES = vcd.c cdrom.c
--- /dev/null
+/****************************************************************************
+ * cdrom.c: cdrom tools
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: cdrom.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Johan Bilien <jobi@via.ecp.fr>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+
+#if defined( SYS_BSDI )
+# include <dvd.h>
+#elif defined ( SYS_DARWIN )
+# include <CoreFoundation/CFBase.h>
+# include <IOKit/IOKitLib.h>
+# include <IOKit/storage/IOCDTypes.h>
+# include <IOKit/storage/IOCDMedia.h>
+# include <IOKit/storage/IOCDMediaBSDClient.h>
+#elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H )
+# include <sys/cdio.h>
+# include <sys/cdrio.h>
+#else
+# include <linux/cdrom.h>
+#endif
+
+#include "cdrom.h"
+
+/*****************************************************************************
+ * Platform specific
+ *****************************************************************************/
+#if defined( SYS_DARWIN )
+CDTOC *getTOC( const char * );
+#define freeTOC( p ) free( (void*)p )
+int getNumberOfDescriptors( CDTOC * );
+int getNumberOfTracks( CDTOC *, int );
+#define CD_MIN_TRACK_NO 01
+#define CD_MAX_TRACK_NO 99
+#endif
+
+/*****************************************************************************
+ * ioctl_ReadTocHeader: Read the TOC header and return the track number.
+ *****************************************************************************/
+int ioctl_GetTrackCount( int i_fd, const char *psz_dev )
+{
+ int i_count = -1;
+
+#if defined( SYS_DARWIN )
+ CDTOC *pTOC;
+ int i_descriptors;
+
+ if( ( pTOC = getTOC( psz_dev ) ) == NULL )
+ {
+//X intf_ErrMsg( "vcd error: failed to get the TOC" );
+ return( -1 );
+ }
+
+ i_descriptors = getNumberOfDescriptors( pTOC );
+ i_count = getNumberOfTracks( pTOC, i_descriptors );
+
+ freeTOC( pTOC );
+
+#elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H )
+ struct ioc_toc_header tochdr;
+
+ if( ioctl( i_fd, CDIOREADTOCHEADER, &tochdr ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: could not read TOCHDR" );
+ return -1;
+ }
+
+ i_count = tochdr.ending_track - tochdr.starting_track + 1;
+
+#else
+ struct cdrom_tochdr tochdr;
+
+ /* First we read the TOC header */
+ if( ioctl( i_fd, CDROMREADTOCHDR, &tochdr ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: could not read TOCHDR" );
+ return -1;
+ }
+
+ i_count = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
+#endif
+
+ return( i_count );
+}
+
+/*****************************************************************************
+ * ioctl_GetSectors: Read the Table of Contents and fill p_vcd.
+ *****************************************************************************/
+int * ioctl_GetSectors( int i_fd, const char *psz_dev )
+{
+ int i, i_tracks;
+ int *p_sectors = NULL;
+
+#if defined( SYS_DARWIN )
+ CDTOC *pTOC;
+ u_char track;
+ int i_descriptors;
+ int i_leadout = -1;
+ CDTOCDescriptor *pTrackDescriptors;
+
+ if( ( pTOC = getTOC( psz_dev ) ) == NULL )
+ {
+//X intf_ErrMsg( "vcd error: failed to get the TOC" );
+ return( NULL );
+ }
+
+ i_descriptors = getNumberOfDescriptors( pTOC );
+ i_tracks = getNumberOfTracks( pTOC, i_descriptors );
+
+ p_sectors = malloc( (i_tracks + 1) * sizeof(int) );
+ if( p_sectors == NULL )
+ {
+//X intf_ErrMsg( "vcd error: could not allocate p_sectors" );
+ freeTOC( pTOC );
+ return NULL;
+ }
+
+ pTrackDescriptors = pTOC->descriptors;
+
+ for( i_tracks = 0, i = 0; i <= i_descriptors; i++ )
+ {
+ track = pTrackDescriptors[i].point;
+
+ if( track == 0xA2 )
+ i_leadout = i;
+
+ if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO )
+ continue;
+
+ p_sectors[i_tracks++] =
+ CDConvertMSFToLBA( pTrackDescriptors[i].p );
+ }
+
+ if( i_leadout == -1 )
+ {
+//X intf_ErrMsg( "vcd error: leadout not found" );
+ free( p_sectors );
+ freeTOC( pTOC );
+ return( NULL );
+ }
+
+ /* set leadout sector */
+ p_sectors[i_tracks] =
+ CDConvertMSFToLBA( pTrackDescriptors[i_leadout].p );
+
+ freeTOC( pTOC );
+
+#elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H )
+ struct ioc_read_toc_entry toc_entries;
+
+ i_tracks = ioctl_GetTrackCount( i_fd, psz_dev );
+ p_sectors = malloc( (i_tracks + 1) * sizeof(int) );
+ if( p_sectors == NULL )
+ {
+//X intf_ErrMsg( "vcd error: could not allocate p_sectors" );
+ return NULL;
+ }
+
+ toc_entries.address_format = CD_LBA_FORMAT;
+ toc_entries.starting_track = 0;
+ toc_entries.data_len = ( i_tracks + 1 ) * sizeof( struct cd_toc_entry );
+ toc_entries.data = (struct cd_toc_entry *) malloc( toc_entries.data_len );
+ if( toc_entries.data == NULL )
+ {
+//X intf_ErrMsg( "vcd error: not enoug memory" );
+ free( p_sectors );
+ return NULL;
+ }
+
+ /* Read the TOC */
+ if( ioctl( i_fd, CDIOREADTOCENTRYS, &toc_entries ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: could not read the TOC" );
+ free( p_sectors );
+ free( toc_entries.data );
+ return NULL;
+ }
+
+ /* Fill the p_sectors structure with the track/sector matches */
+ for( i = 0 ; i <= i_tracks ; i++ )
+ {
+ p_sectors[ i ] = ntohl( toc_entries.data[i].addr.lba );
+ }
+#else
+ struct cdrom_tochdr tochdr;
+ struct cdrom_tocentry tocent;
+
+ /* First we read the TOC header */
+ if( ioctl( i_fd, CDROMREADTOCHDR, &tochdr ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: could not read TOCHDR" );
+ return NULL;
+ }
+
+ i_tracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
+
+ p_sectors = malloc( (i_tracks + 1) * sizeof(int) );
+ if( p_sectors == NULL )
+ {
+//X intf_ErrMsg( "vcd error: could not allocate p_sectors" );
+ return NULL;
+ }
+
+ /* Fill the p_sectors structure with the track/sector matches */
+ for( i = 0 ; i <= i_tracks ; i++ )
+ {
+ tocent.cdte_format = CDROM_LBA;
+ tocent.cdte_track =
+ ( i == i_tracks ) ? CDROM_LEADOUT : tochdr.cdth_trk0 + i;
+
+ if( ioctl( i_fd, CDROMREADTOCENTRY, &tocent ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: could not read TOCENTRY" );
+ free( p_sectors );
+ return NULL;
+ }
+
+ p_sectors[ i ] = tocent.cdte_addr.lba;
+ }
+#endif
+
+ return p_sectors;
+}
+
+/****************************************************************************
+ * ioctl_ReadSector: Read a sector (2324 bytes)
+ ****************************************************************************/
+int ioctl_ReadSector( int i_fd, int i_sector, byte_t * p_buffer )
+{
+ byte_t p_block[ VCD_SECTOR_SIZE ];
+
+#if defined( SYS_DARWIN )
+ dk_cd_read_t cd_read;
+
+ memset( &cd_read, 0, sizeof(cd_read) );
+
+ cd_read.offset = i_sector * VCD_SECTOR_SIZE;
+ cd_read.sectorArea = kCDSectorAreaSync | kCDSectorAreaHeader |
+ kCDSectorAreaSubHeader | kCDSectorAreaUser |
+ kCDSectorAreaAuxiliary;
+ cd_read.sectorType = kCDSectorTypeUnknown;
+
+ cd_read.buffer = p_block;
+ cd_read.bufferLength = sizeof(p_block);
+
+ if( ioctl( i_fd, DKIOCCDREAD, &cd_read ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: could not read block %d", i_sector );
+ return( -1 );
+ }
+
+#elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H )
+
+ int i_size = VCD_SECTOR_SIZE;
+
+ if( ioctl( i_fd, CDRIOCSETBLOCKSIZE, &i_size ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: Could not set block size" );
+ return( -1 );
+ }
+
+ if( lseek( i_fd, i_sector * VCD_SECTOR_SIZE, SEEK_SET ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: Could not lseek to sector %d", i_sector );
+ return( -1 );
+ }
+
+ if( read( i_fd, p_block, VCD_SECTOR_SIZE ) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: Could not read sector %d", i_sector );
+ return( -1 );
+ }
+
+#else
+ int i_dummy = i_sector + 2 * CD_FRAMES;
+
+#define p_msf ((struct cdrom_msf0 *)p_block)
+ p_msf->minute = i_dummy / (CD_FRAMES * CD_SECS);
+ p_msf->second = ( i_dummy % (CD_FRAMES * CD_SECS) ) / CD_FRAMES;
+ p_msf->frame = ( i_dummy % (CD_FRAMES * CD_SECS) ) % CD_FRAMES;
+#undef p_msf
+
+ if( ioctl(i_fd, CDROMREADRAW, p_block) == -1 )
+ {
+//X intf_ErrMsg( "vcd error: could not read block %i from disc",
+//X i_sector );
+ return( -1 );
+ }
+#endif
+
+ /* We don't want to keep the header of the read sector */
+ memcpy( p_buffer, p_block + VCD_DATA_START, VCD_DATA_SIZE );
+
+ return( 0 );
+}
+
+#if defined( SYS_DARWIN )
+/****************************************************************************
+ * getTOC: get the TOC
+ ****************************************************************************/
+CDTOC *getTOC( const char *psz_dev )
+{
+ mach_port_t port;
+ char *psz_devname;
+ kern_return_t ret;
+ CDTOC *pTOC = NULL;
+ io_iterator_t iterator;
+ io_registry_entry_t service;
+ CFDictionaryRef properties;
+ CFDataRef data;
+
+ if( psz_dev == NULL )
+ {
+//X intf_ErrMsg( "vcd error: invalid device path" );
+ return( NULL );
+ }
+
+ /* get the device name */
+ if( ( psz_devname = strrchr( psz_dev, '/') ) != NULL )
+ ++psz_devname;
+ else
+ psz_devname = (char *)psz_dev;
+
+ /* unraw the device name */
+ if( *psz_devname == 'r' )
+ ++psz_devname;
+
+ /* get port for IOKit communication */
+ if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS )
+ {
+//X intf_ErrMsg( "vcd error: IOMasterPort: 0x%08x", ret );
+ return( NULL );
+ }
+
+ /* get service iterator for the device */
+ if( ( ret = IOServiceGetMatchingServices(
+ port, IOBSDNameMatching( port, 0, psz_devname ),
+ &iterator ) ) != KERN_SUCCESS )
+ {
+//X intf_ErrMsg( "vcd error: IOServiceGetMatchingServices: 0x%08x", ret );
+ return( NULL );
+ }
+
+ /* first service */
+ service = IOIteratorNext( iterator );
+ IOObjectRelease( iterator );
+
+ /* search for kIOCDMediaClass */
+ while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) )
+ {
+ if( ( ret = IORegistryEntryGetParentIterator( service,
+ kIOServicePlane, &iterator ) ) != KERN_SUCCESS )
+ {
+//X intf_ErrMsg( "vcd error: "
+//X "IORegistryEntryGetParentIterator: 0x%08x", ret );
+ IOObjectRelease( service );
+ return( NULL );
+ }
+
+ IOObjectRelease( service );
+ service = IOIteratorNext( iterator );
+ IOObjectRelease( iterator );
+ }
+
+ if( service == NULL )
+ {
+//X intf_ErrMsg( "vcd error: search for kIOCDMediaClass came up empty" );
+ return( NULL );
+ }
+
+ /* create a CF dictionary containing the TOC */
+ if( ( ret = IORegistryEntryCreateCFProperties( service, &properties,
+ kCFAllocatorDefault, kNilOptions ) ) != KERN_SUCCESS )
+ {
+//X intf_ErrMsg( "vcd error: "
+//X " IORegistryEntryCreateCFProperties: 0x%08x", ret );
+ IOObjectRelease( service );
+ return( NULL );
+ }
+
+ /* get the TOC from the dictionary */
+ if( ( data = (CFDataRef) CFDictionaryGetValue( properties,
+ CFSTR(kIOCDMediaTOCKey) ) ) != NULL )
+ {
+ CFRange range;
+ CFIndex buf_len;
+
+ buf_len = CFDataGetLength( data ) + 1;
+ range = CFRangeMake( 0, buf_len );
+
+ if( ( pTOC = (CDTOC *)malloc( buf_len ) ) != NULL )
+ {
+ CFDataGetBytes( data, range, (u_char *)pTOC );
+ }
+ }
+ else
+ {
+//X intf_ErrMsg( "vcd error: CFDictionaryGetValue failed" );
+ }
+
+ CFRelease( properties );
+ IOObjectRelease( service );
+
+ return( pTOC );
+}
+
+/****************************************************************************
+ * getNumberOfDescriptors: get number of descriptors in TOC
+ ****************************************************************************/
+int getNumberOfDescriptors( CDTOC *pTOC )
+{
+ int i_descriptors;
+
+ /* get TOC length */
+ i_descriptors = pTOC->length;
+
+ /* remove the first and last session */
+ i_descriptors -= ( sizeof(pTOC->sessionFirst) +
+ sizeof(pTOC->sessionLast) );
+
+ /* divide the length by the size of a single descriptor */
+ i_descriptors /= sizeof(CDTOCDescriptor);
+
+ return( i_descriptors );
+}
+
+/****************************************************************************
+ * getNumberOfTracks: get number of tracks in TOC
+ ****************************************************************************/
+int getNumberOfTracks( CDTOC *pTOC, int i_descriptors )
+{
+ u_char track;
+ int i, i_tracks = 0;
+ CDTOCDescriptor *pTrackDescriptors;
+
+ pTrackDescriptors = pTOC->descriptors;
+
+ for( i = i_descriptors; i >= 0; i-- )
+ {
+ track = pTrackDescriptors[i].point;
+
+ if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO )
+ continue;
+
+ i_tracks++;
+ }
+
+ return( i_tracks );
+}
+#endif
--- /dev/null
+/****************************************************************************
+ * cdrom.h: cdrom tools header
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: cdrom.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/* where the data start on a VCD sector */
+#define VCD_DATA_START 24
+/* size of the availablr data on a VCD sector */
+#define VCD_DATA_SIZE 2324
+/* size of a VCD sector, header and tail included */
+#define VCD_SECTOR_SIZE 2352
+
+/******************************************************************************
+* Prototypes *
+******************************************************************************/
+int ioctl_GetTrackCount ( int, const char *psz_dev );
+int * ioctl_GetSectors ( int, const char *psz_dev );
+int ioctl_ReadSector ( int, int, byte_t * );
+
--- /dev/null
+/*****************************************************************************
+ * vcd.c : VCD input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000 VideoLAN
+ * $Id: vcd.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#if defined( WIN32 )
+# include <io.h> /* read() */
+#else
+# include <sys/uio.h> /* struct iovec */
+#endif
+
+#if defined( WIN32 )
+# include "input_iovec.h"
+#endif
+
+#include "vcd.h"
+#include "cdrom.h"
+
+/* how many blocks VCDRead will read in each loop */
+#define VCD_BLOCKS_ONCE 20
+#define VCD_DATA_ONCE (VCD_BLOCKS_ONCE * VCD_DATA_SIZE)
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int VCDOpen ( vlc_object_t * );
+static void VCDClose ( vlc_object_t * );
+static int VCDRead ( input_thread_t *, byte_t *, size_t );
+static void VCDSeek ( input_thread_t *, off_t );
+static int VCDSetArea ( input_thread_t *, input_area_t * );
+static int VCDSetProgram ( input_thread_t *, pgrm_descriptor_t * );
+
+/*****************************************************************************
+ * Module descriptior
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("VCD input module") );
+ set_capability( "access", 80 );
+ set_callbacks( VCDOpen, VCDClose );
+ add_shortcut( "svcd" );
+vlc_module_end();
+
+/*
+ * Data reading functions
+ */
+
+/*****************************************************************************
+ * VCDOpen: open vcd
+ *****************************************************************************/
+static int VCDOpen( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ char * psz_orig;
+ char * psz_parser;
+ char * psz_source;
+ char * psz_next;
+ struct stat stat_info;
+ thread_vcd_data_t * p_vcd;
+ int i;
+ input_area_t * p_area;
+ int i_title = 1;
+ int i_chapter = 1;
+
+ p_input->pf_read = VCDRead;
+ p_input->pf_seek = VCDSeek;
+ p_input->pf_set_area = VCDSetArea;
+ p_input->pf_set_program = VCDSetProgram;
+
+ /* parse the options passed in command line : */
+ psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
+
+ if( !psz_orig )
+ {
+ return( -1 );
+ }
+
+ while( *psz_parser && *psz_parser != '@' )
+ {
+ psz_parser++;
+ }
+
+ if( *psz_parser == '@' )
+ {
+ /* Found options */
+ *psz_parser = '\0';
+ ++psz_parser;
+
+ i_title = (int)strtol( psz_parser, &psz_next, 10 );
+ if( *psz_next )
+ {
+ psz_parser = psz_next + 1;
+ i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
+ }
+
+ i_title = i_title ? i_title : 1;
+ i_chapter = i_chapter ? i_chapter : 1;
+ }
+
+ if( !*psz_source )
+ {
+ if( !p_input->psz_access )
+ {
+ free( psz_orig );
+ return -1;
+ }
+ psz_source = config_GetPsz( p_input, "vcd" );
+ }
+
+ /* test the type of file given */
+
+ if( stat( psz_source, &stat_info ) == -1 )
+ {
+ msg_Err( p_input, "cannot stat() source `%s' (%s)",
+ psz_source, strerror(errno));
+ return( -1 );
+ }
+
+ if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode))
+ {
+ msg_Warn( p_input, "vcd module discarded (not a valid drive)" );
+ return -1;
+ }
+
+
+ p_vcd = malloc( sizeof(thread_vcd_data_t) );
+
+ if( p_vcd == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ return -1;
+ }
+
+ p_input->p_access_data = (void *)p_vcd;
+
+ p_input->i_mtu = VCD_DATA_ONCE;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_input->stream.b_pace_control = 1;
+
+ p_input->stream.b_seekable = 1;
+ p_input->stream.p_selected_area->i_size = 0;
+ p_input->stream.p_selected_area->i_tell = 0;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_vcd->i_handle = open( psz_source, O_RDONLY | O_NONBLOCK );
+
+ if( p_vcd->i_handle == -1 )
+ {
+ msg_Err( p_input, "could not open %s\n", psz_source );
+ free (p_vcd);
+ return -1;
+ }
+
+ /* We read the Table Of Content information */
+ p_vcd->nb_tracks = ioctl_GetTrackCount( p_vcd->i_handle,
+ psz_source );
+ if( p_vcd->nb_tracks < 0 )
+ {
+ msg_Err( p_input, "unable to count tracks" );
+ close( p_vcd->i_handle );
+ free( p_vcd );
+ return -1;
+ }
+ else if( p_vcd->nb_tracks <= 1 )
+ {
+ msg_Err( p_input, "no movie tracks found" );
+ close( p_vcd->i_handle );
+ free( p_vcd );
+ return -1;
+ }
+
+ p_vcd->p_sectors = ioctl_GetSectors( p_vcd->i_handle,
+ psz_source );
+ if( p_vcd->p_sectors == NULL )
+ {
+ input_BuffersEnd( p_input, p_input->p_method_data );
+ close( p_vcd->i_handle );
+ free( p_vcd );
+ return -1;
+ }
+
+ /* Set stream and area data */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ /* Initialize ES structures */
+ input_InitStream( p_input, sizeof( stream_ps_data_t ) );
+
+ /* disc input method */
+ p_input->stream.i_method = INPUT_METHOD_VCD;
+
+#define area p_input->stream.pp_areas
+ for( i = 1 ; i <= p_vcd->nb_tracks - 1 ; i++ )
+ {
+ input_AddArea( p_input );
+
+ /* Titles are Program Chains */
+ area[i]->i_id = i;
+
+ /* Absolute start offset and size */
+ area[i]->i_start = (off_t)p_vcd->p_sectors[i] * (off_t)VCD_DATA_SIZE;
+ area[i]->i_size = (off_t)(p_vcd->p_sectors[i+1] - p_vcd->p_sectors[i])
+ * (off_t)VCD_DATA_SIZE;
+
+ /* Number of chapters */
+ area[i]->i_part_nb = 0; // will be the entry points
+ area[i]->i_part = 1;
+
+ area[i]->i_plugin_data = p_vcd->p_sectors[i];
+ }
+#undef area
+
+ p_area = p_input->stream.pp_areas[i_title];
+
+ VCDSetArea( p_input, p_area );
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_input->psz_demux = "ps";
+
+ return 0;
+}
+
+/*****************************************************************************
+ * VCDClose: closes vcd
+ *****************************************************************************/
+static void VCDClose( vlc_object_t *p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ thread_vcd_data_t *p_vcd = (thread_vcd_data_t *)p_input->p_access_data;
+
+ close( p_vcd->i_handle );
+ free( p_vcd );
+}
+
+/*****************************************************************************
+ * VCDRead: reads from the VCD into PES packets.
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
+ * bytes.
+ *****************************************************************************/
+static int VCDRead( input_thread_t * p_input, byte_t * p_buffer,
+ size_t i_len )
+{
+ thread_vcd_data_t * p_vcd;
+ int i_blocks;
+ int i_index;
+ int i_read;
+ byte_t p_last_sector[ VCD_DATA_SIZE ];
+
+ p_vcd = (thread_vcd_data_t *)p_input->p_access_data;
+
+ i_read = 0;
+
+ /* Compute the number of blocks we have to read */
+
+ i_blocks = i_len / VCD_DATA_SIZE;
+
+ for ( i_index = 0 ; i_index < i_blocks ; i_index++ )
+ {
+ if ( ioctl_ReadSector( p_vcd->i_handle, p_vcd->i_sector,
+ p_buffer + i_index * VCD_DATA_SIZE ) < 0 )
+ {
+ msg_Err( p_input, "could not read sector %d", p_vcd->i_sector );
+ return -1;
+ }
+
+ p_vcd->i_sector ++;
+ if ( p_vcd->i_sector == p_vcd->p_sectors[p_vcd->i_track + 1] )
+ {
+ input_area_t *p_area;
+
+ if ( p_vcd->i_track >= p_vcd->nb_tracks - 1 )
+ return 0; /* EOF */
+
+ p_area = p_input->stream.pp_areas[
+ p_input->stream.p_selected_area->i_id + 1 ];
+
+ msg_Dbg( p_input, "new title" );
+
+ p_area->i_part = 1;
+ VCDSetArea( p_input, p_area );
+
+ }
+ i_read += VCD_DATA_SIZE;
+ }
+
+ if ( i_len % VCD_DATA_SIZE ) /* this should not happen */
+ {
+ if ( ioctl_ReadSector( p_vcd->i_handle, p_vcd->i_sector,
+ p_last_sector ) < 0 )
+ {
+ msg_Err( p_input, "could not read sector %d", p_vcd->i_sector );
+ return -1;
+ }
+
+ p_input->p_vlc->pf_memcpy( p_buffer + i_blocks * VCD_DATA_SIZE,
+ p_last_sector, i_len % VCD_DATA_SIZE );
+ i_read += i_len % VCD_DATA_SIZE;
+ }
+
+ p_input->stream.p_selected_area->i_tell =
+ (off_t)p_vcd->i_sector * (off_t)VCD_DATA_SIZE
+ - p_input->stream.p_selected_area->i_start;
+
+ return i_read;
+}
+
+
+/*****************************************************************************
+ * VCDSetProgram: Does nothing since a VCD is mono_program
+ *****************************************************************************/
+static int VCDSetProgram( input_thread_t * p_input,
+ pgrm_descriptor_t * p_program)
+{
+ return 0;
+}
+
+
+/*****************************************************************************
+ * VCDSetArea: initialize input data for title x, chapter y.
+ * It should be called for each user navigation request.
+ ****************************************************************************/
+static int VCDSetArea( input_thread_t * p_input, input_area_t * p_area )
+{
+ thread_vcd_data_t * p_vcd;
+
+ p_vcd = (thread_vcd_data_t*)p_input->p_access_data;
+
+ /* we can't use the interface slider until initilization is complete */
+ p_input->stream.b_seekable = 0;
+
+ if( p_area != p_input->stream.p_selected_area )
+ {
+ /* Reset the Chapter position of the current title */
+ p_input->stream.p_selected_area->i_part = 1;
+ p_input->stream.p_selected_area->i_tell = 0;
+
+ /* Change the default area */
+ p_input->stream.p_selected_area = p_area;
+
+ /* Change the current track */
+ /* The first track is not a valid one */
+ p_vcd->i_track = p_area->i_id;
+ p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track];
+ }
+
+ /* warn interface that something has changed */
+ p_input->stream.b_seekable = 1;
+ p_input->stream.b_changed = 1;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * VCDSeek
+ ****************************************************************************/
+static void VCDSeek( input_thread_t * p_input, off_t i_off )
+{
+ thread_vcd_data_t * p_vcd;
+
+ p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
+
+ p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track]
+ + i_off / (off_t)VCD_DATA_SIZE;
+
+ p_input->stream.p_selected_area->i_tell =
+ (off_t)p_vcd->i_sector * (off_t)VCD_DATA_SIZE
+ - p_input->stream.p_selected_area->i_start;
+}
--- /dev/null
+/*****************************************************************************
+ * vcd.h: thread structure of the VCD plugin
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: vcd.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * thread_vcd_data_t: VCD information
+ *****************************************************************************/
+typedef struct thread_vcd_data_s
+{
+ int i_handle; /* File descriptor */
+ int nb_tracks; /* Nb of tracks (titles) */
+ int i_track; /* Current track */
+ int i_sector; /* Current Sector */
+ int * p_sectors; /* Track sectors */
+ vlc_bool_t b_end_of_track; /* If the end of track was reached */
+
+} thread_vcd_data_t;
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+alsa_SOURCES = alsa.c
--- /dev/null
+/*****************************************************************************
+ * alsa.c : alsa plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: alsa.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Henri Fallon <henri@videolan.org> - Original Author
+ * Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
+ * John Paul Lorenti <jpl31@columbia.edu> - Device selection
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include <alsa/asoundlib.h>
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+static void HandleXrun ( aout_thread_t *);
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ add_category_hint( N_("Device"), NULL );
+ add_string( "alsa-device", NULL, NULL, N_("Name"), NULL );
+ set_description( _("ALSA audio module") );
+ set_capability( "audio output", 50 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+typedef struct alsa_device_t
+{
+ int i_num;
+} alsa_device_t;
+
+typedef struct alsa_card_t
+{
+ int i_num;
+} alsa_card_t;
+
+/* here we store plugin dependant informations */
+
+struct aout_sys_t
+{
+ snd_pcm_t * p_alsa_handle;
+ unsigned long buffer_time;
+ unsigned long period_time;
+ unsigned long chunk_size;
+ unsigned long buffer_size;
+ unsigned long rate;
+ unsigned int bytes_per_sample;
+ unsigned int samples_per_frame;
+ unsigned int bytes_per_frame;
+};
+
+/*****************************************************************************
+ * Open: create a handle and open an alsa device
+ *****************************************************************************
+ * This function opens an alsa device, through the alsa API
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+
+ /* Allows user to choose which ALSA device to use */
+ char psz_alsadev[128];
+ char *psz_device, *psz_userdev;
+ int i_ret;
+
+ /* Allocate structures */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return -1;
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ /* Read in ALSA device preferences from configuration */
+ psz_userdev = config_GetPsz( p_aout, "alsa-device" );
+
+ if( psz_userdev )
+ {
+ psz_device = psz_userdev;
+ }
+ else
+ {
+ /* Use the internal logic to decide on the device name */
+ if( p_aout->i_format != AOUT_FMT_A52 )
+ {
+ psz_device = "default";
+ }
+ else
+ {
+ unsigned char s[4];
+ s[0] = IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO;
+ s[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER;
+ s[2] = 0;
+ s[3] = IEC958_AES3_CON_FS_48000;
+ sprintf( psz_alsadev,
+ "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
+ s[0], s[1], s[2], s[3] );
+ psz_device = psz_alsadev;
+ }
+ }
+
+ /* Open device */
+ i_ret = snd_pcm_open( &(p_aout->p_sys->p_alsa_handle),
+ psz_device, SND_PCM_STREAM_PLAYBACK, 0);
+ if( i_ret != 0 )
+ {
+ msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
+ psz_device, snd_strerror(i_ret) );
+ if( psz_userdev )
+ {
+ free( psz_userdev );
+ }
+
+ return -1;
+ }
+
+ if( psz_userdev )
+ {
+ free( psz_userdev );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * SetFormat : sets the alsa output format
+ *****************************************************************************
+ * This function prepares the device, sets the rate, format, the mode
+ * ( "play as soon as you have data" ), and buffer information.
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ int i_rv;
+ int i_format;
+
+ snd_pcm_hw_params_t *p_hw;
+ snd_pcm_sw_params_t *p_sw;
+
+ snd_pcm_hw_params_alloca(&p_hw);
+ snd_pcm_sw_params_alloca(&p_sw);
+
+ /* default value for snd_pcm_hw_params_set_buffer_time_near() */
+ p_aout->p_sys->buffer_time = AOUT_BUFFER_DURATION;
+
+ switch (p_aout->i_format)
+ {
+ case AOUT_FMT_S16_LE:
+ i_format = SND_PCM_FORMAT_S16_LE;
+ p_aout->p_sys->bytes_per_sample = 2;
+ break;
+
+ case AOUT_FMT_A52:
+ i_format = SND_PCM_FORMAT_S16_LE;
+ p_aout->p_sys->bytes_per_sample = 2;
+ /* buffer_time must be 500000 to avoid a system crash */
+ p_aout->p_sys->buffer_time = 500000;
+ break;
+
+ default:
+ i_format = SND_PCM_FORMAT_S16_BE;
+ p_aout->p_sys->bytes_per_sample = 2;
+ break;
+ }
+
+ p_aout->p_sys->samples_per_frame = p_aout->i_channels;
+ p_aout->p_sys->bytes_per_frame = p_aout->p_sys->samples_per_frame *
+ p_aout->p_sys->bytes_per_sample;
+
+ i_rv = snd_pcm_hw_params_any( p_aout->p_sys->p_alsa_handle, p_hw );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to retrieve initial parameters" );
+ return -1;
+ }
+
+ i_rv = snd_pcm_hw_params_set_access( p_aout->p_sys->p_alsa_handle, p_hw,
+ SND_PCM_ACCESS_RW_INTERLEAVED );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to set interleaved stream format" );
+ return -1;
+ }
+
+ i_rv = snd_pcm_hw_params_set_format( p_aout->p_sys->p_alsa_handle,
+ p_hw, i_format );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to set stream sample size and word order" );
+ return -1;
+ }
+
+ i_rv = snd_pcm_hw_params_set_channels( p_aout->p_sys->p_alsa_handle, p_hw,
+ p_aout->i_channels );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to set number of output channels" );
+ return -1;
+ }
+
+ i_rv = snd_pcm_hw_params_set_rate_near( p_aout->p_sys->p_alsa_handle, p_hw,
+ p_aout->i_rate, 0 );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to set sample rate" );
+ return -1;
+ }
+ p_aout->p_sys->rate = i_rv;
+
+ i_rv = snd_pcm_hw_params_set_buffer_time_near( p_aout->p_sys->p_alsa_handle,
+ p_hw,
+ p_aout->p_sys->buffer_time,
+ 0 );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to set buffer time" );
+ return -1;
+ }
+ p_aout->p_sys->buffer_time = i_rv;
+
+ i_rv = snd_pcm_hw_params_set_period_time_near( p_aout->p_sys->p_alsa_handle,
+ p_hw, p_aout->p_sys->buffer_time / p_aout->p_sys->bytes_per_frame, 0 );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to set period time" );
+ return -1;
+ }
+ p_aout->p_sys->period_time = i_rv;
+
+ i_rv = snd_pcm_hw_params(p_aout->p_sys->p_alsa_handle, p_hw);
+ if (i_rv < 0)
+ {
+ msg_Err( p_aout, "unable to set hardware configuration" );
+ return -1;
+ }
+
+ p_aout->p_sys->chunk_size = snd_pcm_hw_params_get_period_size( p_hw, 0 );
+ p_aout->p_sys->buffer_size = snd_pcm_hw_params_get_buffer_size( p_hw );
+
+ snd_pcm_sw_params_current( p_aout->p_sys->p_alsa_handle, p_sw );
+ i_rv = snd_pcm_sw_params_set_sleep_min( p_aout->p_sys->p_alsa_handle, p_sw,
+ 0 );
+
+ i_rv = snd_pcm_sw_params_set_avail_min( p_aout->p_sys->p_alsa_handle, p_sw,
+ p_aout->p_sys->chunk_size );
+
+ /* Worked with the CVS version but not with 0.9beta3
+ i_rv = snd_pcm_sw_params_set_start_threshold( p_aout->p_sys->p_alsa_handle,
+ p_sw, p_aout->p_sys->buffer_size );
+
+ i_rv = snd_pcm_sw_params_set_stop_threshold( p_aout->p_sys->p_alsa_handle,
+ p_sw, p_aout->p_sys->buffer_size);
+ */
+ i_rv = snd_pcm_sw_params( p_aout->p_sys->p_alsa_handle, p_sw );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to set software configuration" );
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * HandleXrun : reprepare the output
+ *****************************************************************************
+ * When buffer gets empty, the driver goes in "Xrun" state, where it needs
+ * to be reprepared before playing again
+ *****************************************************************************/
+static void HandleXrun(aout_thread_t *p_aout)
+{
+ int i_rv;
+
+ msg_Err( p_aout, "resetting output after buffer underrun" );
+
+// i_rv = snd_pcm_reset( p_aout->p_sys->p_alsa_handle );
+ i_rv = snd_pcm_prepare( p_aout->p_sys->p_alsa_handle );
+ if( i_rv < 0 )
+ {
+ msg_Err( p_aout, "unable to recover from buffer underrun (%s)",
+ snd_strerror( i_rv ) );
+ }
+}
+
+
+/*****************************************************************************
+ * BufInfo: buffer status query
+ *****************************************************************************
+ * This function returns the number of used byte in the queue.
+ * It also deals with errors : indeed if the device comes to run out
+ * of data to play, it switches to the "underrun" status. It has to
+ * be flushed and re-prepared
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ snd_pcm_status_t *p_status;
+ int i_alsa_get_status_returns;
+
+ snd_pcm_status_alloca( &p_status );
+
+ i_alsa_get_status_returns = snd_pcm_status( p_aout->p_sys->p_alsa_handle,
+ p_status );
+
+ if( i_alsa_get_status_returns )
+ {
+ msg_Err( p_aout, "failed getting alsa buffer info (%s)",
+ snd_strerror ( i_alsa_get_status_returns ) );
+ return ( -1 );
+ }
+
+ switch( snd_pcm_status_get_state( p_status ) )
+ {
+ case SND_PCM_STATE_XRUN :
+ HandleXrun( p_aout );
+ break;
+
+ case SND_PCM_STATE_OPEN:
+ case SND_PCM_STATE_PREPARED:
+ case SND_PCM_STATE_RUNNING:
+ break;
+
+ default:
+ msg_Err( p_aout, "unhandled condition %i",
+ snd_pcm_status_get_state( p_status ) );
+ break;
+ }
+
+ return snd_pcm_status_get_avail(p_status) * p_aout->p_sys->bytes_per_frame;
+}
+
+/*****************************************************************************
+ * Play : plays a sample
+ *****************************************************************************
+ * Plays a sample using the snd_pcm_writei function from the alsa API
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ snd_pcm_uframes_t tot_frames;
+ snd_pcm_uframes_t frames_left;
+ snd_pcm_uframes_t rv;
+
+ tot_frames = i_size / p_aout->p_sys->bytes_per_frame;
+ frames_left = tot_frames;
+
+ while( frames_left > 0 )
+ {
+ rv = snd_pcm_writei( p_aout->p_sys->p_alsa_handle, buffer +
+ (tot_frames - frames_left) *
+ p_aout->p_sys->bytes_per_frame, frames_left );
+
+ if( (signed int) rv < 0 )
+ {
+ msg_Err( p_aout, "failed writing to output (%s)",
+ snd_strerror( rv ) );
+ return;
+ }
+
+ frames_left -= rv;
+ }
+}
+
+/*****************************************************************************
+ * Close: close the Alsa device
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+ int i_close_returns;
+
+ i_close_returns = snd_pcm_close( p_aout->p_sys->p_alsa_handle );
+
+ if( i_close_returns )
+ {
+ msg_Err( p_aout, "failed closing ALSA device (%s)",
+ snd_strerror( i_close_returns ) );
+ }
+
+ free( p_aout->p_sys );
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+arts_SOURCES = arts.c
--- /dev/null
+/*****************************************************************************
+ * arts.c : aRts module
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ *
+ * Authors: Emmanuel Blindauer <manu@agat.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <fcntl.h> /* open(), O_WRONLY */
+#include <string.h> /* strerror() */
+#include <unistd.h> /* write(), close() */
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include <artsc.h>
+
+/*****************************************************************************
+ * aout_sys_t: arts audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes some arts specific variables.
+ *****************************************************************************/
+struct aout_sys_t
+{
+ arts_stream_t stream;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("aRts audio module") );
+ set_capability( "audio output", 50 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: initialize arts connection to server
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+ int i_err = 0;
+
+ /* Allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ i_err = arts_init();
+
+ if (i_err < 0)
+ {
+ msg_Err( p_aout, "arts_init failed (%s)", arts_error_text(i_err) );
+ free( p_aout->p_sys );
+ return(-1);
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ p_aout->p_sys->stream =
+ arts_play_stream( p_aout->i_rate, 16, p_aout->i_channels, "vlc" );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: set the output format
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ /*Not ready*/
+/* p_aout->i_latency = esd_get_latency(i_fd);*/
+ p_aout->i_latency = 0;
+
+ //msg_Dbg( p_aout, "aout_arts_latency: %d", p_aout->i_latency );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ /* arbitrary value that should be changed */
+ return( i_buffer_limit );
+}
+
+/*****************************************************************************
+ * Play: play a sound samples buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes in the socket
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ int i_err = arts_write( p_aout->p_sys->stream, buffer, i_size );
+
+ if( i_err < 0 )
+ {
+ msg_Err( p_aout, "arts_write failed (%s)", arts_error_text(i_err) );
+ }
+}
+
+/*****************************************************************************
+ * Close: close the Esound socket
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+
+ arts_close_stream( p_aout->p_sys->stream );
+ free( p_aout->p_sys );
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+dsp_SOURCES = dsp.c
--- /dev/null
+/*****************************************************************************
+ * dsp.c : OSS /dev/dsp module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: dsp.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <fcntl.h> /* open(), O_WRONLY */
+#include <sys/ioctl.h> /* ioctl() */
+#include <string.h> /* strerror() */
+#include <unistd.h> /* write(), close() */
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+/* SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT, SNDCTL_DSP_STEREO, SNDCTL_DSP_SPEED,
+ * SNDCTL_DSP_GETOSPACE */
+#ifdef HAVE_SOUNDCARD_H
+# include <soundcard.h>
+#elif defined( HAVE_SYS_SOUNDCARD_H )
+# include <sys/soundcard.h>
+#elif defined( HAVE_MACHINE_SOUNDCARD_H )
+# include <machine/soundcard.h>
+#endif
+
+/*****************************************************************************
+ * aout_sys_t: dsp audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes the dsp specific properties of an audio device.
+ *****************************************************************************/
+struct aout_sys_t
+{
+ audio_buf_info audio_buf;
+
+ /* Path to the audio output device */
+ char * psz_device;
+ int i_fd;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_file( "dspdev", "/dev/dsp", NULL, N_("OSS dsp device"), NULL );
+ set_description( _("Linux OSS /dev/dsp module") );
+ set_capability( "audio output", 100 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: opens the audio device (the digital sound processor)
+ *****************************************************************************
+ * This function opens the dsp as a usual non-blocking write-only file, and
+ * modifies the p_aout->p_sys->i_fd with the file's descriptor.
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Initialize some variables */
+ if( !(p_aout->p_sys->psz_device = config_GetPsz( p_aout, "dspdev" )) )
+ {
+ msg_Err( p_aout, "don't know which audio device to open" );
+ free( p_aout->p_sys );
+ return( -1 );
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ /* Open the sound device */
+ if( (p_aout->p_sys->i_fd = open( p_aout->p_sys->psz_device, O_WRONLY ))
+ < 0 )
+ {
+ msg_Err( p_aout, "cannot open audio device (%s)",
+ p_aout->p_sys->psz_device );
+ free( p_aout->p_sys->psz_device );
+ free( p_aout->p_sys );
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: resets the dsp and sets its format
+ *****************************************************************************
+ * This functions resets the DSP device, tries to initialize the output
+ * format with the value contained in the dsp structure, and if this value
+ * could not be set, the default value returned by ioctl is set. It then
+ * does the same for the stereo mode, and for the output rate.
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ int i_format;
+ int i_rate;
+ vlc_bool_t b_stereo;
+
+ /* Reset the DSP device */
+ if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
+ {
+ msg_Err( p_aout, "cannot reset audio device (%s)",
+ p_aout->p_sys->psz_device );
+ return( -1 );
+ }
+
+ /* Set the output format */
+ i_format = p_aout->i_format;
+ if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )
+ {
+ msg_Err( p_aout, "cannot set audio output format (%i)",
+ p_aout->i_format );
+ return( -1 );
+ }
+
+ if( i_format != p_aout->i_format )
+ {
+ msg_Warn( p_aout, "audio output format not supported (%i)",
+ p_aout->i_format );
+ p_aout->i_format = i_format;
+ }
+
+ /* Set the number of channels */
+ b_stereo = ( p_aout->i_channels >= 2 );
+
+ if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_STEREO, &b_stereo ) < 0 )
+ {
+ msg_Err( p_aout, "cannot set number of audio channels (%i)",
+ p_aout->i_channels );
+ return( -1 );
+ }
+
+ if( (1 + b_stereo) != p_aout->i_channels )
+ {
+ msg_Warn( p_aout, "%i audio channels not supported",
+ p_aout->i_channels );
+ p_aout->i_channels = 1 + b_stereo;
+ }
+
+ /* Set the output rate */
+ i_rate = p_aout->i_rate;
+ if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_SPEED, &i_rate ) < 0 )
+ {
+ msg_Err( p_aout, "cannot set audio output rate (%i)", p_aout->i_rate );
+ return( -1 );
+ }
+
+ if( i_rate != p_aout->i_rate )
+ {
+ msg_Warn( p_aout, "audio output rate not supported (%li)",
+ p_aout->i_rate );
+ p_aout->i_rate = i_rate;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************
+ * This function fills in the audio_buf_info structure :
+ * - returns : number of available fragments (not partially used ones)
+ * - int fragstotal : total number of fragments allocated
+ * - int fragsize : size of a fragment in bytes
+ * - int bytes : available space in bytes (includes partially used fragments)
+ * Note! 'bytes' could be more than fragments*fragsize
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_GETOSPACE,
+ &p_aout->p_sys->audio_buf );
+
+ /* returns the allocated space in bytes */
+ return ( (p_aout->p_sys->audio_buf.fragstotal
+ * p_aout->p_sys->audio_buf.fragsize)
+ - p_aout->p_sys->audio_buf.bytes );
+}
+
+/*****************************************************************************
+ * Play: plays a sound samples buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes in the dsp
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ int i_tmp;
+ i_tmp = write( p_aout->p_sys->i_fd, buffer, i_size );
+
+ if( i_tmp < 0 )
+ {
+ msg_Err( p_aout, "write failed (%s)", strerror(errno) );
+ }
+}
+
+/*****************************************************************************
+ * Close: closes the dsp audio device
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+
+ close( p_aout->p_sys->i_fd );
+ free( p_aout->p_sys->psz_device );
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+esd_SOURCES = esd.c
--- /dev/null
+/*****************************************************************************
+ * esd.c : EsounD module
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: esd.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <fcntl.h> /* open(), O_WRONLY */
+#include <string.h> /* strerror() */
+#include <unistd.h> /* write(), close() */
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include <esd.h>
+
+/*****************************************************************************
+ * aout_sys_t: esd audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes some esd specific variables.
+ *****************************************************************************/
+struct aout_sys_t
+{
+ esd_format_t esd_format;
+ int i_fd;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("EsounD audio module") );
+ set_capability( "audio output", 50 );
+ set_callbacks( Open, Close );
+ add_shortcut( "esound" );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: open an esd socket
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+
+ /* mpg123 does it this way */
+ int i_bits = ESD_BITS16;
+ int i_mode = ESD_STREAM;
+ int i_func = ESD_PLAY;
+
+ /* Allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Initialize some variables */
+ p_aout->i_rate = esd_audio_rate; /* We use actual esd rate value, not
+ * initial value */
+
+ i_bits = ESD_BITS16;
+ i_mode = ESD_STREAM;
+ i_func = ESD_PLAY;
+ p_aout->p_sys->esd_format = (i_bits | i_mode | i_func) & (~ESD_MASK_CHAN);
+
+ if( p_aout->i_channels == 1 )
+ {
+ p_aout->p_sys->esd_format |= ESD_MONO;
+ }
+ else
+ {
+ p_aout->p_sys->esd_format |= ESD_STEREO;
+ }
+
+ /* open a socket for playing a stream
+ * and try to open /dev/dsp if there's no EsounD */
+ if ( (p_aout->p_sys->i_fd
+ = esd_play_stream_fallback(p_aout->p_sys->esd_format,
+ p_aout->i_rate, NULL, "vlc")) < 0 )
+ {
+ msg_Err( p_aout, "cannot open esound socket (format 0x%08x at %ld Hz)",
+ p_aout->p_sys->esd_format, p_aout->i_rate );
+ return( -1 );
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: set the output format
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ int i_fd;
+
+ i_fd = esd_open_sound(NULL);
+ p_aout->i_latency = esd_get_latency(i_fd);
+
+ msg_Dbg( p_aout, "aout_esd_latency: %d", p_aout->i_latency );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ /* arbitrary value that should be changed */
+ return( i_buffer_limit );
+}
+
+/*****************************************************************************
+ * Play: play a sound samples buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes in the socket
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ int i_amount;
+
+ if (p_aout->p_sys->esd_format & ESD_STEREO)
+ {
+ if (p_aout->p_sys->esd_format & ESD_BITS16)
+ {
+ i_amount = (44100 * (ESD_BUF_SIZE + 64)) / p_aout->i_rate;
+ }
+ else
+ {
+ i_amount = (44100 * (ESD_BUF_SIZE + 128)) / p_aout->i_rate;
+ }
+ }
+ else
+ {
+ if (p_aout->p_sys->esd_format & ESD_BITS16)
+ {
+ i_amount = (2 * 44100 * (ESD_BUF_SIZE + 128)) / p_aout->i_rate;
+ }
+ else
+ {
+ i_amount = (2 * 44100 * (ESD_BUF_SIZE + 256)) / p_aout->i_rate;
+ }
+ }
+
+ write( p_aout->p_sys->i_fd, buffer, i_size );
+}
+
+/*****************************************************************************
+ * Close: close the Esound socket
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+
+ close( p_aout->p_sys->i_fd );
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+waveout_SOURCES = waveout.c
--- /dev/null
+/*****************************************************************************
+ * waveout.c : Windows waveOut plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: waveout.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <fcntl.h> /* open(), O_WRONLY */
+#include <string.h> /* strerror() */
+
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include <mmsystem.h>
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/* local functions */
+static int OpenWaveOutDevice( aout_thread_t *p_aout );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Win32 waveOut extension module") );
+ set_capability( "audio output", 250 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * aout_sys_t: waveOut audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes the waveOut specific properties of an audio device.
+ *****************************************************************************/
+
+#define NUMBUF 3 /* We use triple buffering to be on the safe side */
+
+struct aout_sys_t
+{
+ HWAVEOUT h_waveout; /* handle to waveout instance */
+
+ WAVEFORMATEX waveformat; /* Audio format */
+
+ WAVEHDR waveheader[NUMBUF];
+
+ int i_current_buffer;
+
+ DWORD dw_counter; /* Number of bytes played since beginning */
+};
+
+/*****************************************************************************
+ * Open: open the audio device
+ *****************************************************************************
+ * This function opens and setups Win32 waveOut
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+ int i;
+
+ /* Allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ /* Initialize some variables */
+ p_aout->p_sys->i_current_buffer = 0;
+ for( i=0; i<NUMBUF; i++)
+ p_aout->p_sys->waveheader[i].lpData = malloc( 1 );
+
+ return OpenWaveOutDevice( p_aout );
+
+}
+
+/*****************************************************************************
+ * SetFormat: reset the audio device and sets its format
+ *****************************************************************************
+ * This functions set a new audio format.
+ * For this we need to close the current device and create another
+ * one with the desired format.
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ msg_Dbg( p_aout, "SetFormat" );
+
+ /* Check if the format has changed */
+
+ if( (p_aout->p_sys->waveformat.nChannels != p_aout->i_channels) ||
+ (p_aout->p_sys->waveformat.nSamplesPerSec != p_aout->i_rate) )
+ {
+ /* Before calling waveOutClose we must reset the device */
+ waveOutReset( p_aout->p_sys->h_waveout );
+
+ if( waveOutClose( p_aout->p_sys->h_waveout ) != MMSYSERR_NOERROR )
+ {
+ msg_Err( p_aout, "waveOutClose failed" );
+ }
+
+ return OpenWaveOutDevice( p_aout );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************
+ * returns the number of bytes in the audio buffer that have not yet been
+ * sent to the sound device.
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ MMTIME mmtime;
+
+ mmtime.wType = TIME_BYTES;
+ if( (waveOutGetPosition(p_aout->p_sys->h_waveout, &mmtime, sizeof(MMTIME)))
+ != MMSYSERR_NOERROR || (mmtime.wType != TIME_BYTES) )
+ {
+ msg_Warn( p_aout, "waveOutGetPosition failed" );
+ return i_buffer_limit;
+ }
+
+
+#if 0
+ msg_Dbg( p_aout, "GetBufInfo: %i",
+ p_aout->p_sys->dw_counter - mmtime.u.cb );
+#endif
+
+ return (p_aout->p_sys->dw_counter - mmtime.u.cb);
+}
+
+/*****************************************************************************
+ * Play: play a sound buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *p_buffer, int i_size )
+{
+ MMRESULT result;
+ int current_buffer = p_aout->p_sys->i_current_buffer;
+
+ p_aout->p_sys->i_current_buffer = (current_buffer + 1) % NUMBUF;
+
+ /* Unprepare the old buffer */
+ waveOutUnprepareHeader( p_aout->p_sys->h_waveout,
+ &p_aout->p_sys->waveheader[current_buffer],
+ sizeof(WAVEHDR) );
+
+ /* Prepare the buffer */
+ p_aout->p_sys->waveheader[current_buffer].lpData =
+ realloc( p_aout->p_sys->waveheader[current_buffer].lpData, i_size );
+ if( !p_aout->p_sys->waveheader[current_buffer].lpData )
+ {
+ msg_Err( p_aout, "could not allocate buffer" );
+ return;
+ }
+ p_aout->p_sys->waveheader[current_buffer].dwBufferLength = i_size;
+ p_aout->p_sys->waveheader[current_buffer].dwFlags = 0;
+
+ result = waveOutPrepareHeader( p_aout->p_sys->h_waveout,
+ &p_aout->p_sys->waveheader[current_buffer],
+ sizeof(WAVEHDR) );
+ if( result != MMSYSERR_NOERROR )
+ {
+ msg_Err( p_aout, "waveOutPrepareHeader failed" );
+ return;
+ }
+
+ /* Send the buffer the waveOut queue */
+ p_aout->p_vlc->pf_memcpy( p_aout->p_sys->waveheader[current_buffer].lpData,
+ p_buffer, i_size );
+ result = waveOutWrite( p_aout->p_sys->h_waveout,
+ &p_aout->p_sys->waveheader[current_buffer],
+ sizeof(WAVEHDR) );
+ if( result != MMSYSERR_NOERROR )
+ {
+ msg_Err( p_aout, "waveOutWrite failed" );
+ return;
+ }
+
+ /* keep track of number of bytes played */
+ p_aout->p_sys->dw_counter += i_size;
+
+}
+
+/*****************************************************************************
+ * Close: close the audio device
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+ int i;
+
+ /* Before calling waveOutClose we must reset the device */
+ waveOutReset( p_aout->p_sys->h_waveout );
+
+ /* Close the device */
+ if( waveOutClose( p_aout->p_sys->h_waveout ) != MMSYSERR_NOERROR )
+ {
+ msg_Err( p_aout, "waveOutClose failed" );
+ }
+
+ /* Deallocate memory */
+ for( i=0; i<NUMBUF; i++ )
+ free( p_aout->p_sys->waveheader[i].lpData );
+
+ if( p_aout->p_sys != NULL )
+ {
+ free( p_aout->p_sys );
+ p_aout->p_sys = NULL;
+ }
+}
+
+/*****************************************************************************
+ * OpenWaveOutDevice: open the sound device
+ ****************************************************************************/
+static int OpenWaveOutDevice( aout_thread_t *p_aout )
+{
+ MMRESULT result;
+
+ /* initialize played bytes counter */
+ p_aout->p_sys->dw_counter = 0;
+
+ /* Set sound format */
+ p_aout->p_sys->waveformat.wFormatTag = WAVE_FORMAT_PCM;
+ p_aout->p_sys->waveformat.nChannels = p_aout->i_channels;
+ p_aout->p_sys->waveformat.nSamplesPerSec = p_aout->i_rate;
+ p_aout->p_sys->waveformat.wBitsPerSample = 16;
+ p_aout->p_sys->waveformat.nBlockAlign =
+ p_aout->p_sys->waveformat.wBitsPerSample / 8 * p_aout->i_channels;
+ p_aout->p_sys->waveformat.nAvgBytesPerSec =
+ p_aout->p_sys->waveformat.nSamplesPerSec *
+ p_aout->p_sys->waveformat.nBlockAlign;
+
+
+ /* Open the device */
+ result = waveOutOpen( &p_aout->p_sys->h_waveout, WAVE_MAPPER,
+ &p_aout->p_sys->waveformat,
+ 0 /*callback*/, 0 /*callback data*/, CALLBACK_NULL );
+ if( result != MMSYSERR_NOERROR )
+ {
+ msg_Err( p_aout, "waveOutOpen failed" );
+ return( 1 );
+ }
+
+ return( 0 );
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+a52_SOURCES = a52.c
--- /dev/null
+/*****************************************************************************
+ * a52.c: ATSC A/52 aka AC-3 decoder plugin for vlc.
+ * This plugin makes use of liba52 to decode A/52 audio
+ * (http://liba52.sf.net/).
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: a52.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#ifdef HAVE_STDINT_H
+# include <stdint.h> /* int16_t .. */
+#elif HAVE_INTTYPES_H
+# include <inttypes.h> /* int16_t .. */
+#endif
+
+#ifdef USE_A52DEC_TREE /* liba52 header file */
+# include "include/a52.h"
+#else
+# include "a52dec/a52.h"
+#endif
+
+#include "a52.h"
+
+#define A52DEC_FRAME_SIZE 1536
+
+/*
+ * Global lock for accessing liba52 functions.
+ * Currently, liba52 isn't thread-safe. So to prevent two threads from
+ * using liba52 at the same time, we have to set up a global lock.
+ * I know static variables aren't a good idea in multi-threaded programs,
+ * but believe me, this is the way to go.
+ * --Meuuh 2002-07-19
+ */
+static vlc_mutex_t a52_lock;
+static vlc_bool_t b_liba52_initialized = 0;
+
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+static int DecodeFrame ( a52_adec_thread_t * );
+static int InitThread ( a52_adec_thread_t * );
+static void EndThread ( a52_adec_thread_t * );
+
+static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
+static void float2s16_2 ( float *, int16_t * );
+static inline int16_t convert ( int32_t );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define DYNRNG_TEXT N_("A/52 dynamic range compression")
+#define DYNRNG_LONGTEXT N_( \
+ "Dynamic range compression makes the loud sounds softer, and the soft " \
+ "sounds louder, so you can more easily listen to the stream in a noisy " \
+ "environment without disturbing anyone. If you disable the dynamic range "\
+ "compression the playback will be more adapted to a movie theater or a " \
+ "listening room.")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_bool( "a52-dynrng", 1, NULL, DYNRNG_TEXT, DYNRNG_LONGTEXT );
+ set_description( _("a52 ATSC A/52 aka AC-3 audio decoder module") );
+ set_capability( "decoder", 60 );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to choose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
+ {
+ return VLC_EGENERIC;
+ }
+
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+ a52_adec_thread_t *p_a52_adec;
+
+ /* Allocate the memory needed to store the thread's structure */
+ p_a52_adec = (a52_adec_thread_t *)malloc( sizeof(a52_adec_thread_t) );
+ if (p_a52_adec == NULL)
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ /* FIXME */
+ p_a52_adec->i_channels = 2;
+
+ /*
+ * Initialize the thread properties
+ */
+ p_a52_adec->p_aout_fifo = NULL;
+ p_a52_adec->p_fifo = p_fifo;
+
+ if( InitThread( p_a52_adec ) )
+ {
+ msg_Err( p_a52_adec->p_fifo, "could not initialize thread" );
+ DecoderError( p_fifo );
+ free( p_a52_adec );
+ return( -1 );
+ }
+
+ /* liba52 decoder thread's main loop */
+ while( !p_a52_adec->p_fifo->b_die && !p_a52_adec->p_fifo->b_error )
+ {
+
+ /* look for sync word - should be 0x0b77 */
+ RealignBits(&p_a52_adec->bit_stream);
+ while( (ShowBits( &p_a52_adec->bit_stream, 16 ) ) != 0x0b77 &&
+ (!p_a52_adec->p_fifo->b_die) && (!p_a52_adec->p_fifo->b_error))
+ {
+ RemoveBits( &p_a52_adec->bit_stream, 8 );
+ }
+
+ /* get a52 frame header */
+ GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer, 7 );
+ if( p_a52_adec->p_fifo->b_die ) break;
+
+ /* check if frame is valid and get frame info */
+ vlc_mutex_lock( &a52_lock );
+ p_a52_adec->frame_size = a52_syncinfo( p_a52_adec->p_frame_buffer,
+ &p_a52_adec->flags,
+ &p_a52_adec->sample_rate,
+ &p_a52_adec->bit_rate );
+ vlc_mutex_unlock( &a52_lock );
+
+ if( !p_a52_adec->frame_size )
+ {
+ msg_Warn( p_a52_adec->p_fifo, "a52_syncinfo failed" );
+ continue;
+ }
+
+ if( DecodeFrame( p_a52_adec ) && !p_a52_adec->p_fifo->b_die )
+ {
+ DecoderError( p_fifo );
+ free( p_a52_adec );
+ return( -1 );
+ }
+
+ }
+
+ /* If b_error is set, the decoder thread enters the error loop */
+ if( p_a52_adec->p_fifo->b_error )
+ {
+ DecoderError( p_a52_adec->p_fifo );
+ }
+
+ /* End of the liba52 decoder thread */
+ EndThread( p_a52_adec );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * InitThread: initialize data before entering main loop
+ *****************************************************************************/
+static int InitThread( a52_adec_thread_t * p_a52_adec )
+{
+ /* Initialize the global lock */
+ vlc_mutex_lock( p_a52_adec->p_fifo->p_vlc->p_global_lock );
+ if ( !b_liba52_initialized )
+ {
+ vlc_mutex_init( p_a52_adec->p_fifo, &a52_lock );
+ b_liba52_initialized = 1;
+ }
+ vlc_mutex_unlock( p_a52_adec->p_fifo->p_vlc->p_global_lock );
+
+ /* Initialize liba52 */
+ vlc_mutex_lock( &a52_lock );
+ p_a52_adec->p_a52_state = a52_init( 0 );
+ vlc_mutex_unlock( &a52_lock );
+ if( p_a52_adec->p_a52_state == NULL )
+ {
+ msg_Err( p_a52_adec->p_fifo, "unable to initialize liba52" );
+ return -1;
+ }
+
+ p_a52_adec->b_dynrng = config_GetInt( p_a52_adec->p_fifo, "a52-dynrng" );
+
+ /* Init the BitStream */
+ InitBitstream( &p_a52_adec->bit_stream,
+ p_a52_adec->p_fifo,
+ BitstreamCallback, NULL );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * DecodeFrame: decodes an ATSC A/52 frame.
+ *****************************************************************************/
+static int DecodeFrame( a52_adec_thread_t * p_a52_adec )
+{
+ sample_t sample_level = 1;
+ byte_t *p_buffer;
+ int i;
+
+ if( ( p_a52_adec->p_aout_fifo != NULL ) &&
+ ( p_a52_adec->p_aout_fifo->i_rate != p_a52_adec->sample_rate ) )
+ {
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock));
+ aout_DestroyFifo (p_a52_adec->p_aout_fifo);
+ vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait));
+ vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock));
+
+ p_a52_adec->p_aout_fifo = NULL;
+ }
+
+ /* Creating the audio output fifo if not created yet */
+ if( p_a52_adec->p_aout_fifo == NULL )
+ {
+ p_a52_adec->p_aout_fifo = aout_CreateFifo( p_a52_adec->p_fifo,
+ AOUT_FIFO_PCM, p_a52_adec->i_channels,
+ p_a52_adec->sample_rate,
+ A52DEC_FRAME_SIZE * p_a52_adec->i_channels,
+ NULL );
+
+ if ( p_a52_adec->p_aout_fifo == NULL )
+ {
+ return( -1 );
+ }
+ }
+
+ /* Set the Presentation Time Stamp */
+ CurrentPTS( &p_a52_adec->bit_stream,
+ &p_a52_adec->p_aout_fifo->date[
+ p_a52_adec->p_aout_fifo->i_end_frame],
+ NULL );
+
+ if( !p_a52_adec->p_aout_fifo->date[
+ p_a52_adec->p_aout_fifo->i_end_frame] )
+ {
+ p_a52_adec->p_aout_fifo->date[
+ p_a52_adec->p_aout_fifo->i_end_frame] = LAST_MDATE;
+ }
+
+
+
+ p_buffer = ((byte_t *)p_a52_adec->p_aout_fifo->buffer) +
+ ( p_a52_adec->p_aout_fifo->i_end_frame * A52DEC_FRAME_SIZE *
+ p_a52_adec->i_channels * sizeof(s16) );
+
+ /* FIXME */
+ p_a52_adec->flags = A52_STEREO | A52_ADJUST_LEVEL;
+
+ /* Get the complete frame */
+ GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer + 7,
+ p_a52_adec->frame_size - 7 );
+ if( p_a52_adec->p_fifo->b_die ) return( -1 );
+
+ /* do the actual decoding now */
+ vlc_mutex_lock( &a52_lock );
+ a52_frame( p_a52_adec->p_a52_state, p_a52_adec->p_frame_buffer,
+ &p_a52_adec->flags, &sample_level, 384 );
+
+ if( !p_a52_adec->b_dynrng )
+ a52_dynrng( p_a52_adec->p_a52_state, NULL, NULL );
+
+ for( i = 0; i < 6; i++ )
+ {
+ if( a52_block( p_a52_adec->p_a52_state ) )
+ {
+ msg_Warn( p_a52_adec->p_fifo, "a52_block failed for block %i", i );
+ }
+
+ float2s16_2( a52_samples( p_a52_adec->p_a52_state ),
+ ((int16_t *)p_buffer) + i * 256 * p_a52_adec->i_channels );
+ }
+ vlc_mutex_unlock( &a52_lock );
+
+
+ vlc_mutex_lock( &p_a52_adec->p_aout_fifo->data_lock );
+ p_a52_adec->p_aout_fifo->i_end_frame =
+ (p_a52_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
+ vlc_cond_signal (&p_a52_adec->p_aout_fifo->data_wait);
+ vlc_mutex_unlock (&p_a52_adec->p_aout_fifo->data_lock);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * EndThread : liba52 decoder thread destruction
+ *****************************************************************************/
+static void EndThread (a52_adec_thread_t *p_a52_adec)
+{
+ /* If the audio output fifo was created, we destroy it */
+ if (p_a52_adec->p_aout_fifo != NULL)
+ {
+ aout_DestroyFifo (p_a52_adec->p_aout_fifo);
+
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock));
+ vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait));
+ vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock));
+ }
+
+ vlc_mutex_lock( &a52_lock );
+ a52_free( p_a52_adec->p_a52_state );
+ vlc_mutex_unlock( &a52_lock );
+ free( p_a52_adec );
+
+}
+
+/*****************************************************************************
+ * float2s16_2 : converts floats to ints using a trick based on the IEEE
+ * floating-point format
+ *****************************************************************************/
+static inline int16_t convert (int32_t i)
+{
+ if (i > 0x43c07fff)
+ return 32767;
+ else if (i < 0x43bf8000)
+ return -32768;
+ else
+ return i - 0x43c00000;
+}
+
+static void float2s16_2 (float * _f, int16_t * s16)
+{
+ int i;
+ int32_t * f = (int32_t *) _f;
+
+ for (i = 0; i < 256; i++) {
+ s16[2*i] = convert (f[i]);
+ s16[2*i+1] = convert (f[i+256]);
+ }
+}
+
+/*****************************************************************************
+ * BitstreamCallback: Import parameters from the new data/PES packet
+ *****************************************************************************
+ * This function is called by input's NextDataPacket.
+ *****************************************************************************/
+static void BitstreamCallback ( bit_stream_t * p_bit_stream,
+ vlc_bool_t b_new_pes )
+{
+ if( b_new_pes )
+ {
+ /* Drop special A52 header */
+/* p_bit_stream->p_byte += 3; */
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * a52.h: ATSC A/52 aka AC-3 decoder plugin for vlc.
+ * This plugin makes use of liba52 to decode A/52 audio
+ * (http://liba52.sf.net/).
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: a52.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * a52_adec_thread_t : a52 decoder thread descriptor
+ *****************************************************************************/
+typedef struct a52_adec_thread_s
+{
+ /*
+ * liba52 properties
+ */
+ a52_state_t *p_a52_state;
+ int frame_size;
+ int flags;
+ int sample_rate;
+ int bit_rate;
+ vlc_bool_t b_dynrng;
+
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+
+ /*
+ * Input properties
+ */
+ decoder_fifo_t *p_fifo; /* stores the PES stream data */
+ data_packet_t *p_data;
+
+ /*
+ * Output properties
+ */
+ aout_fifo_t *p_aout_fifo; /* stores the decompressed audio frames */
+ int i_channels;
+
+ /* temporary buffer to store the raw frame to be decoded */
+ u8 p_frame_buffer[3840];
+
+} a52_adec_thread_t;
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+a52old_SOURCES = a52old.c decoder.c parse.c exponent.c bit_allocate.c mantissa.c rematrix.c imdct.c
--- /dev/null
+/*****************************************************************************
+ * a52old.c: A52 decoder module main file
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: a52old.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Lespinasse <walken@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> /* getpid() */
+#endif
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h"
+
+#define A52DEC_FRAME_SIZE (2*1536)
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+static int InitThread ( a52dec_t * p_adec );
+static void EndThread ( a52dec_t * p_adec );
+static void BitstreamCallback ( bit_stream_t *p_bit_stream,
+ vlc_bool_t b_new_pes );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_module ( "a52-downmix", "downmix", NULL, NULL,
+ N_("A52 downmix module"), NULL );
+ add_module ( "a52-imdct", "imdct", NULL, NULL,
+ N_("A52 IMDCT module"), NULL );
+ set_description( _("software A52 decoder") );
+ set_capability( "decoder", 50 );
+ set_callbacks( OpenDecoder, NULL );
+ add_shortcut( "a52" );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to chose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
+ {
+ return VLC_EGENERIC;
+ }
+
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+ a52dec_t * p_a52dec;
+ void * p_orig; /* pointer before memalign */
+ vlc_bool_t b_sync = 0;
+
+ /* Allocate the memory needed to store the thread's structure */
+ p_a52dec = (a52dec_t *)vlc_memalign( &p_orig, 16, sizeof(a52dec_t) );
+ memset( p_a52dec, 0, sizeof( a52dec_t ) );
+
+ if( p_a52dec == NULL )
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_a52dec->p_fifo = p_fifo;
+ if( InitThread( p_a52dec ) )
+ {
+ msg_Err( p_fifo, "could not initialize thread" );
+ DecoderError( p_fifo );
+ free( p_orig );
+ return( -1 );
+ }
+
+ /* A52 decoder thread's main loop */
+ /* FIXME : do we have enough room to store the decoded frames ?? */
+ while ((!p_a52dec->p_fifo->b_die) && (!p_a52dec->p_fifo->b_error))
+ {
+ s16 * buffer;
+ sync_info_t sync_info;
+
+ if( !b_sync )
+ {
+ int i_sync_ptr;
+#define p_bit_stream (&p_a52dec->bit_stream)
+
+ /* Go to the next PES packet and jump to sync_ptr */
+ do {
+ BitstreamNextDataPacket( p_bit_stream );
+ } while( !p_bit_stream->p_decoder_fifo->b_die
+ && !p_bit_stream->p_decoder_fifo->b_error
+ && p_bit_stream->p_data !=
+ p_bit_stream->p_decoder_fifo->p_first->p_first );
+ i_sync_ptr = *(p_bit_stream->p_byte - 2) << 8
+ | *(p_bit_stream->p_byte - 1);
+ p_bit_stream->p_byte += i_sync_ptr;
+
+ /* Empty the bit FIFO and realign the bit stream */
+ p_bit_stream->fifo.buffer = 0;
+ p_bit_stream->fifo.i_available = 0;
+ AlignWord( p_bit_stream );
+ b_sync = 1;
+#undef p_bit_stream
+ }
+
+ if (sync_frame (p_a52dec, &sync_info))
+ {
+ b_sync = 0;
+ continue;
+ }
+
+ if( ( p_a52dec->p_aout_fifo != NULL ) &&
+ ( p_a52dec->p_aout_fifo->i_rate != sync_info.sample_rate ) )
+ {
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock (&(p_a52dec->p_aout_fifo->data_lock));
+ aout_DestroyFifo (p_a52dec->p_aout_fifo);
+ vlc_cond_signal (&(p_a52dec->p_aout_fifo->data_wait));
+ vlc_mutex_unlock (&(p_a52dec->p_aout_fifo->data_lock));
+
+ p_a52dec->p_aout_fifo = NULL;
+ }
+
+ /* Creating the audio output fifo if not created yet */
+ if (p_a52dec->p_aout_fifo == NULL ) {
+ p_a52dec->p_aout_fifo =
+ aout_CreateFifo( p_a52dec->p_fifo, AOUT_FIFO_PCM, 2,
+ sync_info.sample_rate, A52DEC_FRAME_SIZE, NULL );
+ if ( p_a52dec->p_aout_fifo == NULL )
+ {
+ p_a52dec->p_fifo->b_error = 1;
+ break;
+ }
+ }
+
+ CurrentPTS( &p_a52dec->bit_stream,
+ &p_a52dec->p_aout_fifo->date[p_a52dec->p_aout_fifo->i_end_frame],
+ NULL );
+ if( !p_a52dec->p_aout_fifo->date[p_a52dec->p_aout_fifo->i_end_frame] )
+ {
+ p_a52dec->p_aout_fifo->date[
+ p_a52dec->p_aout_fifo->i_end_frame] =
+ LAST_MDATE;
+ }
+
+ buffer = ((s16 *)p_a52dec->p_aout_fifo->buffer) +
+ (p_a52dec->p_aout_fifo->i_end_frame * A52DEC_FRAME_SIZE);
+
+ if (decode_frame (p_a52dec, buffer))
+ {
+ b_sync = 0;
+ continue;
+ }
+
+ vlc_mutex_lock (&p_a52dec->p_aout_fifo->data_lock);
+ p_a52dec->p_aout_fifo->i_end_frame =
+ (p_a52dec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
+ vlc_cond_signal (&p_a52dec->p_aout_fifo->data_wait);
+ vlc_mutex_unlock (&p_a52dec->p_aout_fifo->data_lock);
+
+ RealignBits(&p_a52dec->bit_stream);
+ }
+
+ /* If b_error is set, the A52 decoder thread enters the error loop */
+ if (p_a52dec->p_fifo->b_error)
+ {
+ DecoderError( p_a52dec->p_fifo );
+ }
+
+ /* End of the A52 decoder thread */
+ EndThread (p_a52dec);
+
+ free( p_orig );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * InitThread: initialize data before entering main loop
+ *****************************************************************************/
+static int InitThread( a52dec_t * p_a52dec )
+{
+ char *psz_name;
+
+ /*
+ * Choose the best downmix module
+ */
+ p_a52dec->p_downmix = vlc_object_create( p_a52dec->p_fifo,
+ sizeof( downmix_t ) );
+ p_a52dec->p_downmix->psz_object_name = "downmix";
+
+ psz_name = config_GetPsz( p_a52dec->p_downmix, "a52-downmix" );
+ p_a52dec->p_downmix->p_module =
+ module_Need( p_a52dec->p_downmix, "downmix", psz_name );
+ if( psz_name ) free( psz_name );
+
+ if( p_a52dec->p_downmix->p_module == NULL )
+ {
+ msg_Err( p_a52dec->p_fifo, "no suitable downmix module" );
+ vlc_object_destroy( p_a52dec->p_downmix );
+ return( -1 );
+ }
+
+ /*
+ * Choose the best IMDCT module
+ */
+ p_a52dec->p_imdct = vlc_object_create( p_a52dec->p_fifo,
+ sizeof( imdct_t ) );
+
+#define IMDCT p_a52dec->p_imdct
+ psz_name = config_GetPsz( p_a52dec->p_fifo, "a52-imdct" );
+ p_a52dec->p_imdct->p_module =
+ module_Need( p_a52dec->p_imdct, "imdct", psz_name );
+ if( psz_name ) free( psz_name );
+
+ if( p_a52dec->p_imdct->p_module == NULL )
+ {
+ msg_Err( p_a52dec->p_fifo, "no suitable IMDCT module" );
+ vlc_object_destroy( p_a52dec->p_imdct );
+ module_Unneed( p_a52dec->p_downmix, p_a52dec->p_downmix->p_module );
+ vlc_object_destroy( p_a52dec->p_downmix );
+ return( -1 );
+ }
+
+ /* Initialize the A52 decoder structures */
+ p_a52dec->samples = vlc_memalign( &p_a52dec->samples_orig,
+ 16, 6 * 256 * sizeof(float) );
+
+ IMDCT->buf = vlc_memalign( &IMDCT->buf_orig,
+ 16, N/4 * sizeof(complex_t) );
+ IMDCT->delay = vlc_memalign( &IMDCT->delay_orig,
+ 16, 6 * 256 * sizeof(float) );
+ IMDCT->delay1 = vlc_memalign( &IMDCT->delay1_orig,
+ 16, 6 * 256 * sizeof(float) );
+ IMDCT->xcos1 = vlc_memalign( &IMDCT->xcos1_orig,
+ 16, N/4 * sizeof(float) );
+ IMDCT->xsin1 = vlc_memalign( &IMDCT->xsin1_orig,
+ 16, N/4 * sizeof(float) );
+ IMDCT->xcos2 = vlc_memalign( &IMDCT->xcos2_orig,
+ 16, N/8 * sizeof(float) );
+ IMDCT->xsin2 = vlc_memalign( &IMDCT->xsin2_orig,
+ 16, N/8 * sizeof(float) );
+ IMDCT->xcos_sin_sse = vlc_memalign( &IMDCT->xcos_sin_sse_orig,
+ 16, 128 * 4 * sizeof(float) );
+ IMDCT->w_1 = vlc_memalign( &IMDCT->w_1_orig,
+ 16, 1 * sizeof(complex_t) );
+ IMDCT->w_2 = vlc_memalign( &IMDCT->w_2_orig,
+ 16, 2 * sizeof(complex_t) );
+ IMDCT->w_4 = vlc_memalign( &IMDCT->w_4_orig,
+ 16, 4 * sizeof(complex_t) );
+ IMDCT->w_8 = vlc_memalign( &IMDCT->w_8_orig,
+ 16, 8 * sizeof(complex_t) );
+ IMDCT->w_16 = vlc_memalign( &IMDCT->w_16_orig,
+ 16, 16 * sizeof(complex_t) );
+ IMDCT->w_32 = vlc_memalign( &IMDCT->w_32_orig,
+ 16, 32 * sizeof(complex_t) );
+ IMDCT->w_64 = vlc_memalign( &IMDCT->w_64_orig,
+ 16, 64 * sizeof(complex_t) );
+#undef IMDCT
+
+ E_( a52_init )( p_a52dec );
+
+ /*
+ * Initialize the output properties
+ */
+ p_a52dec->p_aout_fifo = NULL;
+
+ /*
+ * Bit stream
+ */
+ InitBitstream( &p_a52dec->bit_stream, p_a52dec->p_fifo,
+ BitstreamCallback, (void *) p_a52dec );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * EndThread : A52 decoder thread destruction
+ *****************************************************************************/
+static void EndThread (a52dec_t * p_a52dec)
+{
+ /* If the audio output fifo was created, we destroy it */
+ if (p_a52dec->p_aout_fifo != NULL)
+ {
+ aout_DestroyFifo (p_a52dec->p_aout_fifo);
+
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock (&(p_a52dec->p_aout_fifo->data_lock));
+ vlc_cond_signal (&(p_a52dec->p_aout_fifo->data_wait));
+ vlc_mutex_unlock (&(p_a52dec->p_aout_fifo->data_lock));
+ }
+
+ /* Free allocated structures */
+#define IMDCT p_a52dec->p_imdct
+ free( IMDCT->w_1_orig );
+ free( IMDCT->w_64_orig );
+ free( IMDCT->w_32_orig );
+ free( IMDCT->w_16_orig );
+ free( IMDCT->w_8_orig );
+ free( IMDCT->w_4_orig );
+ free( IMDCT->w_2_orig );
+ free( IMDCT->xcos_sin_sse_orig );
+ free( IMDCT->xsin2_orig );
+ free( IMDCT->xcos2_orig );
+ free( IMDCT->xsin1_orig );
+ free( IMDCT->xcos1_orig );
+ free( IMDCT->delay1_orig );
+ free( IMDCT->delay_orig );
+ free( IMDCT->buf_orig );
+#undef IMDCT
+
+ free( p_a52dec->samples_orig );
+
+ /* Unlock the modules */
+ module_Unneed( p_a52dec->p_downmix, p_a52dec->p_downmix->p_module );
+ vlc_object_destroy( p_a52dec->p_downmix );
+
+ module_Unneed( p_a52dec->p_imdct, p_a52dec->p_imdct->p_module );
+ vlc_object_destroy( p_a52dec->p_imdct );
+
+ /* Free what's left of the decoder */
+ free( p_a52dec->imdct_orig );
+}
+
+/*****************************************************************************
+ * BitstreamCallback: Import parameters from the new data/PES packet
+ *****************************************************************************
+ * This function is called by input's NextDataPacket.
+ *****************************************************************************/
+static void BitstreamCallback ( bit_stream_t * p_bit_stream,
+ vlc_bool_t b_new_pes )
+{
+ if( b_new_pes )
+ {
+ /* Drop special A52 header */
+/* p_bit_stream->p_byte += 3; */
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * adec.h : A52 decoder interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: adec.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+vlc_thread_t a52dec_CreateThread( decoder_fifo_t * p_fifo );
+
+/**** A52 decoder API - public A52 decoder structures */
+
+typedef struct a52dec_s a52dec_t;
+
+typedef struct sync_info_s {
+ int sample_rate; /* sample rate in Hz */
+ int frame_size; /* frame size in bytes */
+ int bit_rate; /* nominal bit rate in kbps */
+} sync_info_t;
+
+
+/**** A52 decoder API - functions publically provided by the A52 decoder ****/
+
+int E_( a52_init )(a52dec_t * p_a52dec);
+int sync_frame (a52dec_t * p_a52dec, sync_info_t * p_sync_info);
+int decode_frame (a52dec_t * p_a52dec, s16 * buffer);
+
+/**** EVERYTHING AFTER THIS POINT IS PRIVATE ! DO NOT USE DIRECTLY ****/
+
+/**** A52 decoder internal structures ****/
+
+/* The following structures are filled in by their corresponding parse_*
+ * functions. See http://www.atsc.org/Standards/A52/a_52.pdf for
+ * full details on each field. Indented fields are used to denote
+ * conditional fields.
+ */
+
+typedef struct syncinfo_s {
+ /* Sync word == 0x0B77 */
+ /* u16 syncword; */
+ /* crc for the first 5/8 of the sync block */
+ /* u16 crc1; */
+ /* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */
+ u16 fscod;
+ /* Frame size code */
+ u16 frmsizecod;
+
+ /* Information not in the AC-3 bitstream, but derived */
+ /* Frame size in 16 bit words */
+ u16 frame_size;
+ /* Bit rate in kilobits */
+ //u16 bit_rate;
+} syncinfo_t;
+
+typedef struct bsi_s {
+ /* Bit stream identification == 0x8 */
+ u16 bsid;
+ /* Bit stream mode */
+ u16 bsmod;
+ /* Audio coding mode */
+ u16 acmod;
+ /* If we're using the centre channel then */
+ /* centre mix level */
+ u16 cmixlev;
+ /* If we're using the surround channel then */
+ /* surround mix level */
+ u16 surmixlev;
+ /* If we're in 2/0 mode then */
+ /* Dolby surround mix level - NOT USED - */
+ u16 dsurmod;
+ /* Low frequency effects on */
+ u16 lfeon;
+ /* Dialogue Normalization level */
+ u16 dialnorm;
+ /* Compression exists */
+ u16 compre;
+ /* Compression level */
+ u16 compr;
+ /* Language code exists */
+ u16 langcode;
+ /* Language code */
+ u16 langcod;
+ /* Audio production info exists*/
+ u16 audprodie;
+ u16 mixlevel;
+ u16 roomtyp;
+ /* If we're in dual mono mode (acmod == 0) then extra stuff */
+ u16 dialnorm2;
+ u16 compr2e;
+ u16 compr2;
+ u16 langcod2e;
+ u16 langcod2;
+ u16 audprodi2e;
+ u16 mixlevel2;
+ u16 roomtyp2;
+ /* Copyright bit */
+ u16 copyrightb;
+ /* Original bit */
+ u16 origbs;
+ /* Timecode 1 exists */
+ u16 timecod1e;
+ /* Timecode 1 */
+ u16 timecod1;
+ /* Timecode 2 exists */
+ u16 timecod2e;
+ /* Timecode 2 */
+ u16 timecod2;
+ /* Additional bit stream info exists */
+ u16 addbsie;
+ /* Additional bit stream length - 1 (in bytes) */
+ u16 addbsil;
+ /* Additional bit stream information (max 64 bytes) */
+ u8 addbsi[64];
+
+ /* Information not in the AC-3 bitstream, but derived */
+ /* Number of channels (excluding LFE)
+ * Derived from acmod */
+ u16 nfchans;
+} bsi_t;
+
+/* more pain */
+typedef struct audblk_s {
+ /* block switch bit indexed by channel num */
+ u16 blksw[5];
+ /* dither enable bit indexed by channel num */
+ u16 dithflag[5];
+ /* dynamic range gain exists */
+ u16 dynrnge;
+ /* dynamic range gain */
+ u16 dynrng;
+ /* if acmod==0 then */
+ /* dynamic range 2 gain exists */
+ u16 dynrng2e;
+ /* dynamic range 2 gain */
+ u16 dynrng2;
+ /* coupling strategy exists */
+ u16 cplstre;
+ /* coupling in use */
+ u16 cplinu;
+ /* channel coupled */
+ u16 chincpl[5];
+ /* if acmod==2 then */
+ /* Phase flags in use */
+ u16 phsflginu;
+ /* coupling begin frequency code */
+ u16 cplbegf;
+ /* coupling end frequency code */
+ u16 cplendf;
+ /* coupling band structure bits */
+ u16 cplbndstrc[18];
+ /* Do coupling co-ords exist for this channel? */
+ u16 cplcoe[5];
+ /* Master coupling co-ordinate */
+ u16 mstrcplco[5];
+ /* Per coupling band coupling co-ordinates */
+ u16 cplcoexp[5][18];
+ u16 cplcomant[5][18];
+ /* Phase flags for dual mono */
+ u16 phsflg[18];
+ /* Is there a rematrixing strategy */
+ u16 rematstr;
+ /* Rematrixing bits */
+ u16 rematflg[4];
+ /* Coupling exponent strategy */
+ u16 cplexpstr;
+ /* Exponent strategy for full bandwidth channels */
+ u16 chexpstr[5];
+ /* Exponent strategy for lfe channel */
+ u16 lfeexpstr;
+ /* Channel bandwidth for independent channels */
+ u16 chbwcod[5];
+ /* The absolute coupling exponent */
+ u16 cplabsexp;
+ /* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */
+ u16 cplexps[18 * 12 / 3];
+ /* Sanity checking constant */
+ u32 magic2;
+ /* fbw channel exponents */
+ u16 exps[5][252 / 3];
+ /* channel gain range */
+ u16 gainrng[5];
+ /* low frequency exponents */
+ u16 lfeexps[3];
+
+ /* Bit allocation info */
+ u16 baie;
+ /* Slow decay code */
+ u16 sdcycod;
+ /* Fast decay code */
+ u16 fdcycod;
+ /* Slow gain code */
+ u16 sgaincod;
+ /* dB per bit code */
+ u16 dbpbcod;
+ /* masking floor code */
+ u16 floorcod;
+
+ /* SNR offset info */
+ u16 snroffste;
+ /* coarse SNR offset */
+ u16 csnroffst;
+ /* coupling fine SNR offset */
+ u16 cplfsnroffst;
+ /* coupling fast gain code */
+ u16 cplfgaincod;
+ /* fbw fine SNR offset */
+ u16 fsnroffst[5];
+ /* fbw fast gain code */
+ u16 fgaincod[5];
+ /* lfe fine SNR offset */
+ u16 lfefsnroffst;
+ /* lfe fast gain code */
+ u16 lfefgaincod;
+
+ /* Coupling leak info */
+ u16 cplleake;
+ /* coupling fast leak initialization */
+ u16 cplfleak;
+ /* coupling slow leak initialization */
+ u16 cplsleak;
+
+ /* delta bit allocation info */
+ u16 deltbaie;
+ /* coupling delta bit allocation exists */
+ u16 cpldeltbae;
+ /* fbw delta bit allocation exists */
+ u16 deltbae[5];
+ /* number of cpl delta bit segments */
+ u16 cpldeltnseg;
+ /* coupling delta bit allocation offset */
+ u16 cpldeltoffst[8];
+ /* coupling delta bit allocation length */
+ u16 cpldeltlen[8];
+ /* coupling delta bit allocation length */
+ u16 cpldeltba[8];
+ /* number of delta bit segments */
+ u16 deltnseg[5];
+ /* fbw delta bit allocation offset */
+ u16 deltoffst[5][8];
+ /* fbw delta bit allocation length */
+ u16 deltlen[5][8];
+ /* fbw delta bit allocation length */
+ u16 deltba[5][8];
+
+ /* skip length exists */
+ u16 skiple;
+ /* skip length */
+ u16 skipl;
+
+ /* channel mantissas */
+// u16 chmant[5][256];
+
+ /* coupling mantissas */
+ float cpl_flt[ 256 ];
+// u16 cplmant[256];
+
+ /* coupling mantissas */
+// u16 lfemant[7];
+
+ /* -- Information not in the bitstream, but derived thereof -- */
+
+ /* Number of coupling sub-bands */
+ u16 ncplsubnd;
+
+ /* Number of combined coupling sub-bands
+ * Derived from ncplsubnd and cplbndstrc */
+ u16 ncplbnd;
+
+ /* Number of exponent groups by channel
+ * Derived from strmant, endmant */
+ u16 nchgrps[5];
+
+ /* Number of coupling exponent groups
+ * Derived from cplbegf, cplendf, cplexpstr */
+ u16 ncplgrps;
+
+ /* End mantissa numbers of fbw channels */
+ u16 endmant[5];
+
+ /* Start and end mantissa numbers for the coupling channel */
+ u16 cplstrtmant;
+ u16 cplendmant;
+
+ /* Decoded exponent info */
+ u16 fbw_exp[5][256];
+ u16 cpl_exp[256];
+ u16 lfe_exp[7];
+
+ /* Bit allocation pointer results */
+ u16 fbw_bap[5][256];
+ /* FIXME?? figure out exactly how many entries there should be (253-37?) */
+ u16 cpl_bap[256];
+ u16 lfe_bap[7];
+} audblk_t;
+
+/* Everything you wanted to know about band structure */
+
+/*
+ * The entire frequency domain is represented by 256 real
+ * floating point fourier coefficients. Only the lower 253
+ * coefficients are actually utilized however. We use arrays
+ * of 256 to be efficient in some cases.
+ *
+ * The 5 full bandwidth channels (fbw) can have their higher
+ * frequencies coupled together. These coupled channels then
+ * share their high frequency components.
+ *
+ * This coupling band is broken up into 18 sub-bands starting
+ * at mantissa number 37. Each sub-band is 12 bins wide.
+ *
+ * There are 50 bit allocation sub-bands which cover the entire
+ * frequency range. The sub-bands are of non-uniform width, and
+ * approximate a 1/6 octave scale.
+ */
+
+typedef struct bit_allocate_s
+{
+ s16 psd[256];
+ s16 bndpsd[256];
+ s16 excite[256];
+ s16 mask[256];
+ s16 sdecay;
+ s16 fdecay;
+ s16 sgain;
+ s16 dbknee;
+ s16 floor;
+} bit_allocate_t;
+
+/* These store the persistent state of the packed mantissas */
+typedef struct mantissa_s
+{
+ float q_1[2];
+ float q_2[2];
+ float q_4[1];
+ s32 q_1_pointer;
+ s32 q_2_pointer;
+ s32 q_4_pointer;
+ u16 lfsr_state;
+} mantissa_t;
+
+/*****************************************************************************
+ * a52dec_t : A52 decoder thread descriptor
+ *****************************************************************************/
+
+struct a52dec_s
+{
+ /*
+ * Decoder properties
+ */
+ void * decoder_orig; /* pointer before memalign */
+
+ /*
+ * Thread properties
+ */
+ vlc_thread_t thread_id; /* id for thread functions */
+
+ /*
+ * Input properties
+ */
+ decoder_fifo_t * p_fifo; /* stores the PES stream data */
+
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+ int i_available;
+ unsigned int total_bits_read; /* temporary */
+
+ /*
+ * Decoder properties
+ */
+ syncinfo_t syncinfo;
+ bsi_t bsi;
+ audblk_t audblk;
+
+ dm_par_t dm_par;
+
+ bit_allocate_t bit_allocate;
+ mantissa_t mantissa;
+ downmix_t * p_downmix;
+
+ /*
+ * Output properties
+ */
+ aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
+
+ float * samples;
+ void * samples_orig; /* pointer before memalign */
+ imdct_t * p_imdct;
+ void * imdct_orig; /* pointer before memalign */
+};
+
--- /dev/null
+/*****************************************************************************
+ * bit_allocate.c: A52 allocation tables
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: bit_allocate.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ * Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h"
+
+#include "internal.h" /* DELTA_BIT_REUSE */
+
+
+static void ba_compute_psd (bit_allocate_t * p_bit, s16 start, s16 end, s16 exps[]);
+
+static void ba_compute_excitation (bit_allocate_t * p_bit, s16 start, s16 end, s16 fgain,
+ s16 fastleak, s16 slowleak, s16 is_lfe);
+static void ba_compute_mask (bit_allocate_t * p_bit, s16 start, s16 end, u16 fscod,
+ u16 deltbae, u16 deltnseg, u16 deltoffst[],
+ u16 deltba[], u16 deltlen[]);
+static void ba_compute_bap (bit_allocate_t * p_bit, s16 start, s16 end,
+ s16 snroffset, s16 bap[]);
+
+/* Misc LUTs for bit allocation process */
+
+static const s16 slowdec[] = { 0x0f, 0x11, 0x13, 0x15 };
+static const s16 fastdec[] = { 0x3f, 0x53, 0x67, 0x7b };
+static const s16 slowgain[] = { 0x540, 0x4d8, 0x478, 0x410 };
+static const s16 dbpbtab[] = { 0x000, 0x700, 0x900, 0xb00 };
+
+static const u16 floortab[] = { 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800 };
+static const s16 fastgain[] = { 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400 };
+
+static const s16 bndtab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 31,
+ 34, 37, 40, 43, 46, 49, 55, 61, 67, 73,
+ 79, 85, 97, 109, 121, 133, 157, 181, 205, 229 };
+
+static const s16 bndsz[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 3,
+ 3, 3, 3, 3, 3, 6, 6, 6, 6, 6,
+ 6, 12, 12, 12, 12, 24, 24, 24, 24, 24 };
+
+static const s16 masktab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 29,
+ 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34,
+ 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37,
+ 37, 37, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40,
+ 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0 };
+
+
+static const s16 latab[] = { 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003b, 0x003a, 0x0039,
+ 0x0038, 0x0037, 0x0036, 0x0035, 0x0034, 0x0034, 0x0033, 0x0032,
+ 0x0031, 0x0030, 0x002f, 0x002f, 0x002e, 0x002d, 0x002c, 0x002c,
+ 0x002b, 0x002a, 0x0029, 0x0029, 0x0028, 0x0027, 0x0026, 0x0026,
+ 0x0025, 0x0024, 0x0024, 0x0023, 0x0023, 0x0022, 0x0021, 0x0021,
+ 0x0020, 0x0020, 0x001f, 0x001e, 0x001e, 0x001d, 0x001d, 0x001c,
+ 0x001c, 0x001b, 0x001b, 0x001a, 0x001a, 0x0019, 0x0019, 0x0018,
+ 0x0018, 0x0017, 0x0017, 0x0016, 0x0016, 0x0015, 0x0015, 0x0015,
+ 0x0014, 0x0014, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012,
+ 0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x000f, 0x000f,
+ 0x000f, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d, 0x000d,
+ 0x000c, 0x000c, 0x000c, 0x000c, 0x000b, 0x000b, 0x000b, 0x000b,
+ 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0009, 0x0009, 0x0009,
+ 0x0009, 0x0009, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0005, 0x0005,
+ 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000};
+
+static const s16 hth[][50] = {{ 0x04d0, 0x04d0, 0x0440, 0x0400, 0x03e0, 0x03c0, 0x03b0, 0x03b0,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390,
+ 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, 0x0350, 0x0350,
+ 0x0340, 0x0340, 0x0330, 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0,
+ 0x02f0, 0x02f0, 0x0300, 0x0310, 0x0340, 0x0390, 0x03e0, 0x0420,
+ 0x0460, 0x0490, 0x04a0, 0x0460, 0x0440, 0x0440, 0x0520, 0x0800,
+ 0x0840, 0x0840 },
+
+ { 0x04f0, 0x04f0, 0x0460, 0x0410, 0x03e0, 0x03d0, 0x03c0, 0x03b0,
+ 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390,
+ 0x0390, 0x0380, 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360,
+ 0x0350, 0x0350, 0x0340, 0x0340, 0x0320, 0x0310, 0x0300, 0x02f0,
+ 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0320, 0x0350, 0x0390, 0x03e0,
+ 0x0420, 0x0450, 0x04a0, 0x0490, 0x0460, 0x0440, 0x0480, 0x0630,
+ 0x0840, 0x0840 },
+
+ { 0x0580, 0x0580, 0x04b0, 0x0450, 0x0420, 0x03f0, 0x03e0, 0x03d0,
+ 0x03c0, 0x03b0, 0x03b0, 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, 0x0390,
+ 0x0380, 0x0380, 0x0380, 0x0370, 0x0360, 0x0350, 0x0340, 0x0330,
+ 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0310,
+ 0x0330, 0x0350, 0x03c0, 0x0410, 0x0470, 0x04a0, 0x0460, 0x0440,
+ 0x0450, 0x04e0 }};
+
+
+static const s16 baptab[] = { 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
+ 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10,
+ 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14,
+ 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
+
+static inline u16 max_value (s16 a, s16 b)
+{
+ return (a > b ? a : b);
+}
+
+static inline u16 min_value (s16 a, s16 b)
+{
+ return (a < b ? a : b);
+}
+
+static inline s16 logadd (s16 a, s16 b)
+{
+ s16 c;
+
+ if ((c = a - b) >= 0) {
+ return (a + latab[min_value(((c) >> 1), 255)]);
+ } else {
+ return (b + latab[min_value(((-c) >> 1), 255)]);
+ }
+}
+
+static inline s16 calc_lowcomp (s16 a, s16 b0, s16 b1, s16 bin)
+{
+ if (bin < 7) {
+ if ((b0 + 256) == b1)
+ a = 384;
+ else if (b0 > b1)
+ a = max_value(0, a - 64);
+ } else if (bin < 20) {
+ if ((b0 + 256) == b1)
+ a = 320;
+ else if (b0 > b1)
+ a = max_value(0, a - 64) ;
+ } else
+ a = max_value(0, a - 128);
+
+ return a;
+}
+
+void bit_allocate (a52dec_t * p_a52dec)
+{
+ u16 i;
+ s16 fgain;
+ s16 snroffset;
+ s16 start;
+ s16 end;
+ s16 fastleak;
+ s16 slowleak;
+
+ /* Only perform bit_allocation if the exponents have changed or we
+ * have new sideband information */
+ if (p_a52dec->audblk.chexpstr[0] == 0 && p_a52dec->audblk.chexpstr[1] == 0 &&
+ p_a52dec->audblk.chexpstr[2] == 0 && p_a52dec->audblk.chexpstr[3] == 0 &&
+ p_a52dec->audblk.chexpstr[4] == 0 && p_a52dec->audblk.cplexpstr == 0 &&
+ p_a52dec->audblk.lfeexpstr == 0 && p_a52dec->audblk.baie == 0 &&
+ p_a52dec->audblk.snroffste == 0 && p_a52dec->audblk.deltbaie == 0)
+ return;
+
+ /* Do some setup before we do the bit alloc */
+ p_a52dec->bit_allocate.sdecay = slowdec[p_a52dec->audblk.sdcycod];
+ p_a52dec->bit_allocate.fdecay = fastdec[p_a52dec->audblk.fdcycod];
+ p_a52dec->bit_allocate.sgain = slowgain[p_a52dec->audblk.sgaincod];
+ p_a52dec->bit_allocate.dbknee = dbpbtab[p_a52dec->audblk.dbpbcod];
+ p_a52dec->bit_allocate.floor = floortab[p_a52dec->audblk.floorcod];
+
+ /* if all the SNR offset constants are zero then the whole block is zero */
+ if (!p_a52dec->audblk.csnroffst && !p_a52dec->audblk.fsnroffst[0] &&
+ !p_a52dec->audblk.fsnroffst[1] && !p_a52dec->audblk.fsnroffst[2] &&
+ !p_a52dec->audblk.fsnroffst[3] && !p_a52dec->audblk.fsnroffst[4] &&
+ !p_a52dec->audblk.cplfsnroffst && !p_a52dec->audblk.lfefsnroffst) {
+ memset(p_a52dec->audblk.fbw_bap,0,sizeof(u16) * 256 * 5);
+ memset(p_a52dec->audblk.cpl_bap,0,sizeof(u16) * 256);
+ memset(p_a52dec->audblk.lfe_bap,0,sizeof(u16) * 7);
+ return;
+ }
+
+ for (i = 0; i < p_a52dec->bsi.nfchans; i++) {
+ start = 0;
+ end = p_a52dec->audblk.endmant[i] ;
+ fgain = fastgain[p_a52dec->audblk.fgaincod[i]];
+ snroffset = (((p_a52dec->audblk.csnroffst - 15) << 4) + p_a52dec->audblk.fsnroffst[i]) << 2;
+ fastleak = 0;
+ slowleak = 0;
+
+ ba_compute_psd (&p_a52dec->bit_allocate, start, end, p_a52dec->audblk.fbw_exp[i]);
+
+ ba_compute_excitation (&p_a52dec->bit_allocate, start, end , fgain, fastleak, slowleak, 0);
+
+ ba_compute_mask (&p_a52dec->bit_allocate, start, end, p_a52dec->syncinfo.fscod,
+ p_a52dec->audblk.deltbae[i],
+ p_a52dec->audblk.deltnseg[i],
+ p_a52dec->audblk.deltoffst[i],
+ p_a52dec->audblk.deltba[i],
+ p_a52dec->audblk.deltlen[i]);
+
+ ba_compute_bap (&p_a52dec->bit_allocate, start, end, snroffset, p_a52dec->audblk.fbw_bap[i]);
+ }
+
+ if (p_a52dec->audblk.cplinu) {
+ start = p_a52dec->audblk.cplstrtmant;
+ end = p_a52dec->audblk.cplendmant;
+ fgain = fastgain[p_a52dec->audblk.cplfgaincod];
+ snroffset = (((p_a52dec->audblk.csnroffst - 15) << 4) + p_a52dec->audblk.cplfsnroffst) << 2 ;
+ fastleak = (p_a52dec->audblk.cplfleak << 8) + 768;
+ slowleak = (p_a52dec->audblk.cplsleak << 8) + 768;
+
+ ba_compute_psd (&p_a52dec->bit_allocate, start, end, p_a52dec->audblk.cpl_exp);
+
+ ba_compute_excitation (&p_a52dec->bit_allocate, start, end , fgain, fastleak, slowleak, 0);
+
+ ba_compute_mask (&p_a52dec->bit_allocate, start, end, p_a52dec->syncinfo.fscod,
+ p_a52dec->audblk.cpldeltbae,
+ p_a52dec->audblk.cpldeltnseg,
+ p_a52dec->audblk.cpldeltoffst,
+ p_a52dec->audblk.cpldeltba,
+ p_a52dec->audblk.cpldeltlen);
+
+ ba_compute_bap (&p_a52dec->bit_allocate, start, end, snroffset, p_a52dec->audblk.cpl_bap);
+ }
+
+ if (p_a52dec->bsi.lfeon) {
+ start = 0;
+ end = 7;
+ fgain = fastgain[p_a52dec->audblk.lfefgaincod];
+ snroffset = (((p_a52dec->audblk.csnroffst - 15) << 4) + p_a52dec->audblk.lfefsnroffst) << 2 ;
+ fastleak = 0;
+ slowleak = 0;
+
+ ba_compute_psd (&p_a52dec->bit_allocate, start, end, p_a52dec->audblk.lfe_exp);
+
+ ba_compute_excitation (&p_a52dec->bit_allocate, start, end , fgain, fastleak, slowleak, 1);
+
+ ba_compute_mask (&p_a52dec->bit_allocate, start, end, p_a52dec->syncinfo.fscod, 2, 0, 0, 0, 0);
+
+ ba_compute_bap (&p_a52dec->bit_allocate, start, end, snroffset, p_a52dec->audblk.lfe_bap);
+ }
+}
+
+
+static void ba_compute_psd (bit_allocate_t * p_bit, s16 start, s16 end, s16 exps[])
+{
+ int bin,j,k;
+ s16 lastbin = 0;
+
+ /* Map the exponents into dBs */
+ for (bin=start; bin<end; bin++) {
+ p_bit->psd[bin] = (3072 - (exps[bin] << 7));
+ }
+
+ /* Integrate the psd function over each bit allocation band */
+ j = start;
+ k = masktab[start];
+
+ do {
+ lastbin = min_value(bndtab[k] + bndsz[k], end);
+ p_bit->bndpsd[k] = p_bit->psd[j];
+ j++;
+
+ for (; j < lastbin; j++) {
+ p_bit->bndpsd[k] = logadd(p_bit->bndpsd[k],p_bit->psd[j]);
+ }
+
+ k++;
+ } while (end > lastbin);
+}
+
+static void ba_compute_excitation (bit_allocate_t * p_bit, s16 start, s16 end,
+ s16 fgain, s16 fastleak, s16 slowleak, s16 is_lfe)
+{
+ int bin;
+ s16 bndstrt;
+ s16 bndend;
+ s16 lowcomp = 0;
+ s16 begin = 0;
+
+ /* Compute excitation function */
+ bndstrt = masktab[start];
+ bndend = masktab[end - 1] + 1;
+
+ if (bndstrt == 0) { /* For fbw and lfe channels */
+ lowcomp = calc_lowcomp(lowcomp, p_bit->bndpsd[0], p_bit->bndpsd[1], 0);
+ p_bit->excite[0] = p_bit->bndpsd[0] - fgain - lowcomp;
+ lowcomp = calc_lowcomp(lowcomp, p_bit->bndpsd[1], p_bit->bndpsd[2], 1);
+ p_bit->excite[1] = p_bit->bndpsd[1] - fgain - lowcomp;
+ begin = 7 ;
+
+ /* Note: Do not call calc_lowcomp() for the last band of the lfe channel, (bin = 6) */
+ for (bin = 2; bin < 7; bin++) {
+ if (!(is_lfe && (bin == 6)))
+ lowcomp = calc_lowcomp (lowcomp, p_bit->bndpsd[bin], p_bit->bndpsd[bin+1], bin);
+ fastleak = p_bit->bndpsd[bin] - fgain;
+ slowleak = p_bit->bndpsd[bin] - p_bit->sgain;
+ p_bit->excite[bin] = fastleak - lowcomp;
+
+ if (!(is_lfe && (bin == 6))) {
+ if (p_bit->bndpsd[bin] <=
+ p_bit->bndpsd[bin+1])
+ {
+ begin = bin + 1 ;
+ break;
+ }
+ }
+ }
+
+ for (bin = begin; bin < min_value(bndend, 22); bin++) {
+ if (!(is_lfe && (bin == 6)))
+ lowcomp = calc_lowcomp (lowcomp, p_bit->bndpsd[bin],
+ p_bit->bndpsd[bin+1], bin);
+ fastleak -= p_bit->fdecay ;
+ fastleak = max_value(fastleak, p_bit->bndpsd[bin] - fgain);
+ slowleak -= p_bit->sdecay ;
+ slowleak = max_value(slowleak, p_bit->bndpsd[bin] - p_bit->sgain);
+ p_bit->excite[bin] = max_value(fastleak - lowcomp, slowleak);
+ }
+ begin = 22;
+ } else { /* For coupling channel */
+ begin = bndstrt;
+ }
+
+ for (bin = begin; bin < bndend; bin++) {
+ fastleak -= p_bit->fdecay;
+ fastleak = max_value(fastleak, p_bit->bndpsd[bin] - fgain);
+ slowleak -= p_bit->sdecay;
+ slowleak = max_value(slowleak, p_bit->bndpsd[bin] - p_bit->sgain);
+ p_bit->excite[bin] = max_value(fastleak, slowleak) ;
+ }
+}
+
+static void ba_compute_mask (bit_allocate_t * p_bit, s16 start, s16 end, u16 fscod,
+ u16 deltbae, u16 deltnseg, u16 deltoffst[],
+ u16 deltba[], u16 deltlen[])
+{
+ int bin,k;
+ s16 bndstrt;
+ s16 bndend;
+ s16 delta;
+
+ bndstrt = masktab[start];
+ bndend = masktab[end - 1] + 1;
+
+ /* Compute the masking curve */
+ for (bin = bndstrt; bin < bndend; bin++) {
+ if (p_bit->bndpsd[bin] < p_bit->dbknee) {
+ p_bit->excite[bin] += ((p_bit->dbknee - p_bit->bndpsd[bin]) >> 2);
+ }
+ p_bit->mask[bin] = max_value(p_bit->excite[bin], hth[fscod][bin]);
+ }
+
+ /* Perform delta bit modulation if necessary */
+ if ((deltbae == DELTA_BIT_REUSE) || (deltbae == DELTA_BIT_NEW)) {
+ s16 band = 0;
+ s16 seg = 0;
+
+ for (seg = 0; seg < deltnseg+1; seg++) {
+ band += deltoffst[seg];
+ if (deltba[seg] >= 4) {
+ delta = (deltba[seg] - 3) << 7;
+ } else {
+ delta = (deltba[seg] - 4) << 7;
+ }
+ for (k = 0; k < deltlen[seg]; k++) {
+ p_bit->mask[band] += delta;
+ band++;
+ }
+ }
+ }
+}
+
+static void ba_compute_bap (bit_allocate_t * p_bit, s16 start, s16 end, s16 snroffset,
+ s16 bap[])
+{
+ int i,j,k;
+ s16 lastbin = 0;
+ s16 address = 0;
+
+ /* Compute the bit allocation pointer for each bin */
+ i = start;
+ j = masktab[start];
+
+ do {
+ lastbin = min_value(bndtab[j] + bndsz[j], end);
+ p_bit->mask[j] -= snroffset;
+ p_bit->mask[j] -= p_bit->floor;
+
+ if (p_bit->mask[j] < 0)
+ p_bit->mask[j] = 0;
+
+ p_bit->mask[j] &= 0x1fe0;
+ p_bit->mask[j] += p_bit->floor;
+ for (k = i; k < lastbin; k++) {
+ address = (p_bit->psd[i] - p_bit->mask[j]) >> 5;
+ address = min_value(63, max_value(0, address));
+ bap[i] = baptab[address];
+ i++;
+ }
+ j++;
+ } while (end > lastbin);
+}
--- /dev/null
+/*****************************************************************************
+ * decoder.c: core A52 decoder
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: decoder.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@zoy.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h" /* a52dec_thread_t */
+
+#include "internal.h"
+
+static const float cmixlev_lut[4] = { 0.707, 0.595, 0.500, 0.707 };
+static const float smixlev_lut[4] = { 0.707, 0.500, 0.0 , 0.500 };
+
+int E_( a52_init )(a52dec_t * p_a52dec)
+{
+ p_a52dec->mantissa.lfsr_state = 1; /* dither_gen initialization */
+ E_( imdct_init )(p_a52dec->p_imdct) ;
+
+ return 0;
+}
+
+int decode_frame (a52dec_t * p_a52dec, s16 * buffer)
+{
+ int i;
+
+ if (parse_bsi (p_a52dec))
+ {
+ msg_Warn( p_a52dec->p_fifo, "parse error" );
+ parse_auxdata (p_a52dec);
+ return 1;
+ }
+
+ /* compute downmix parameters
+ * downmix to tow channels for now */
+ p_a52dec->dm_par.clev = 0.0;
+ p_a52dec->dm_par.slev = 0.0;
+ p_a52dec->dm_par.unit = 1.0;
+ if (p_a52dec->bsi.acmod & 0x1) /* have center */
+ p_a52dec->dm_par.clev = cmixlev_lut[p_a52dec->bsi.cmixlev];
+
+ if (p_a52dec->bsi.acmod & 0x4) /* have surround channels */
+ p_a52dec->dm_par.slev = smixlev_lut[p_a52dec->bsi.surmixlev];
+
+ p_a52dec->dm_par.unit /= 1.0 + p_a52dec->dm_par.clev + p_a52dec->dm_par.slev;
+ p_a52dec->dm_par.clev *= p_a52dec->dm_par.unit;
+ p_a52dec->dm_par.slev *= p_a52dec->dm_par.unit;
+
+ for (i = 0; i < 6; i++) {
+ /* Initialize freq/time sample storage */
+ memset(p_a52dec->samples, 0, sizeof(float) * 256 *
+ (p_a52dec->bsi.nfchans + p_a52dec->bsi.lfeon));
+
+
+ if( p_a52dec->p_fifo->b_die || p_a52dec->p_fifo->b_error )
+ {
+ return 1;
+ }
+
+ if( parse_audblk( p_a52dec, i ) )
+ {
+ msg_Warn( p_a52dec->p_fifo, "audioblock error" );
+ parse_auxdata( p_a52dec );
+ return 1;
+ }
+
+ if( p_a52dec->p_fifo->b_die || p_a52dec->p_fifo->b_error )
+ {
+ return 1;
+ }
+
+ if( exponent_unpack( p_a52dec ) )
+ {
+ msg_Warn( p_a52dec->p_fifo, "unpack error" );
+ parse_auxdata( p_a52dec );
+ return 1;
+ }
+
+ bit_allocate (p_a52dec);
+ mantissa_unpack (p_a52dec);
+
+ if( p_a52dec->p_fifo->b_die || p_a52dec->p_fifo->b_error )
+ {
+ return 1;
+ }
+
+ if (p_a52dec->bsi.acmod == 0x2)
+ {
+ rematrix (p_a52dec);
+ }
+
+ imdct (p_a52dec, buffer);
+
+ buffer += 2 * 256;
+ }
+
+ parse_auxdata (p_a52dec);
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * decoder.h : A52 decoder interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: decoder.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/**** A52 decoder API - public A52 decoder structures */
+
+typedef struct a52dec_s a52dec_t;
+
+typedef struct sync_info_s {
+ int sample_rate; /* sample rate in Hz */
+ int frame_size; /* frame size in bytes */
+ int bit_rate; /* nominal bit rate in kbps */
+} sync_info_t;
+
+
+/**** A52 decoder API - functions publically provided by the A52 decoder ****/
+
+int E_( a52_init )(a52dec_t * p_a52dec);
+int sync_frame (a52dec_t * p_a52dec, sync_info_t * p_sync_info);
+int decode_frame (a52dec_t * p_a52dec, s16 * buffer);
+
+/**** EVERYTHING AFTER THIS POINT IS PRIVATE ! DO NOT USE DIRECTLY ****/
+
+/**** A52 decoder internal structures ****/
+
+/* The following structures are filled in by their corresponding parse_*
+ * functions. See http://www.atsc.org/Standards/A52/a_52.pdf for
+ * full details on each field. Indented fields are used to denote
+ * conditional fields.
+ */
+
+typedef struct syncinfo_s {
+ /* Sync word == 0x0B77 */
+ /* u16 syncword; */
+ /* crc for the first 5/8 of the sync block */
+ /* u16 crc1; */
+ /* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */
+ u16 fscod;
+ /* Frame size code */
+ u16 frmsizecod;
+
+ /* Information not in the AC-3 bitstream, but derived */
+ /* Frame size in 16 bit words */
+ u16 frame_size;
+ /* Bit rate in kilobits */
+ //u16 bit_rate;
+} syncinfo_t;
+
+typedef struct bsi_s {
+ /* Bit stream identification == 0x8 */
+ u16 bsid;
+ /* Bit stream mode */
+ u16 bsmod;
+ /* Audio coding mode */
+ u16 acmod;
+ /* If we're using the centre channel then */
+ /* centre mix level */
+ u16 cmixlev;
+ /* If we're using the surround channel then */
+ /* surround mix level */
+ u16 surmixlev;
+ /* If we're in 2/0 mode then */
+ /* Dolby surround mix level - NOT USED - */
+ u16 dsurmod;
+ /* Low frequency effects on */
+ u16 lfeon;
+ /* Dialogue Normalization level */
+ u16 dialnorm;
+ /* Compression exists */
+ u16 compre;
+ /* Compression level */
+ u16 compr;
+ /* Language code exists */
+ u16 langcode;
+ /* Language code */
+ u16 langcod;
+ /* Audio production info exists*/
+ u16 audprodie;
+ u16 mixlevel;
+ u16 roomtyp;
+ /* If we're in dual mono mode (acmod == 0) then extra stuff */
+ u16 dialnorm2;
+ u16 compr2e;
+ u16 compr2;
+ u16 langcod2e;
+ u16 langcod2;
+ u16 audprodi2e;
+ u16 mixlevel2;
+ u16 roomtyp2;
+ /* Copyright bit */
+ u16 copyrightb;
+ /* Original bit */
+ u16 origbs;
+ /* Timecode 1 exists */
+ u16 timecod1e;
+ /* Timecode 1 */
+ u16 timecod1;
+ /* Timecode 2 exists */
+ u16 timecod2e;
+ /* Timecode 2 */
+ u16 timecod2;
+ /* Additional bit stream info exists */
+ u16 addbsie;
+ /* Additional bit stream length - 1 (in bytes) */
+ u16 addbsil;
+ /* Additional bit stream information (max 64 bytes) */
+ u8 addbsi[64];
+
+ /* Information not in the AC-3 bitstream, but derived */
+ /* Number of channels (excluding LFE)
+ * Derived from acmod */
+ u16 nfchans;
+} bsi_t;
+
+/* more pain */
+typedef struct audblk_s {
+ /* block switch bit indexed by channel num */
+ u16 blksw[5];
+ /* dither enable bit indexed by channel num */
+ u16 dithflag[5];
+ /* dynamic range gain exists */
+ u16 dynrnge;
+ /* dynamic range gain */
+ u16 dynrng;
+ /* if acmod==0 then */
+ /* dynamic range 2 gain exists */
+ u16 dynrng2e;
+ /* dynamic range 2 gain */
+ u16 dynrng2;
+ /* coupling strategy exists */
+ u16 cplstre;
+ /* coupling in use */
+ u16 cplinu;
+ /* channel coupled */
+ u16 chincpl[5];
+ /* if acmod==2 then */
+ /* Phase flags in use */
+ u16 phsflginu;
+ /* coupling begin frequency code */
+ u16 cplbegf;
+ /* coupling end frequency code */
+ u16 cplendf;
+ /* coupling band structure bits */
+ u16 cplbndstrc[18];
+ /* Do coupling co-ords exist for this channel? */
+ u16 cplcoe[5];
+ /* Master coupling co-ordinate */
+ u16 mstrcplco[5];
+ /* Per coupling band coupling co-ordinates */
+ u16 cplcoexp[5][18];
+ u16 cplcomant[5][18];
+ /* Phase flags for dual mono */
+ u16 phsflg[18];
+ /* Is there a rematrixing strategy */
+ u16 rematstr;
+ /* Rematrixing bits */
+ u16 rematflg[4];
+ /* Coupling exponent strategy */
+ u16 cplexpstr;
+ /* Exponent strategy for full bandwidth channels */
+ u16 chexpstr[5];
+ /* Exponent strategy for lfe channel */
+ u16 lfeexpstr;
+ /* Channel bandwidth for independent channels */
+ u16 chbwcod[5];
+ /* The absolute coupling exponent */
+ u16 cplabsexp;
+ /* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */
+ u16 cplexps[18 * 12 / 3];
+ /* Sanity checking constant */
+ u32 magic2;
+ /* fbw channel exponents */
+ u16 exps[5][252 / 3];
+ /* channel gain range */
+ u16 gainrng[5];
+ /* low frequency exponents */
+ u16 lfeexps[3];
+
+ /* Bit allocation info */
+ u16 baie;
+ /* Slow decay code */
+ u16 sdcycod;
+ /* Fast decay code */
+ u16 fdcycod;
+ /* Slow gain code */
+ u16 sgaincod;
+ /* dB per bit code */
+ u16 dbpbcod;
+ /* masking floor code */
+ u16 floorcod;
+
+ /* SNR offset info */
+ u16 snroffste;
+ /* coarse SNR offset */
+ u16 csnroffst;
+ /* coupling fine SNR offset */
+ u16 cplfsnroffst;
+ /* coupling fast gain code */
+ u16 cplfgaincod;
+ /* fbw fine SNR offset */
+ u16 fsnroffst[5];
+ /* fbw fast gain code */
+ u16 fgaincod[5];
+ /* lfe fine SNR offset */
+ u16 lfefsnroffst;
+ /* lfe fast gain code */
+ u16 lfefgaincod;
+
+ /* Coupling leak info */
+ u16 cplleake;
+ /* coupling fast leak initialization */
+ u16 cplfleak;
+ /* coupling slow leak initialization */
+ u16 cplsleak;
+
+ /* delta bit allocation info */
+ u16 deltbaie;
+ /* coupling delta bit allocation exists */
+ u16 cpldeltbae;
+ /* fbw delta bit allocation exists */
+ u16 deltbae[5];
+ /* number of cpl delta bit segments */
+ u16 cpldeltnseg;
+ /* coupling delta bit allocation offset */
+ u16 cpldeltoffst[8];
+ /* coupling delta bit allocation length */
+ u16 cpldeltlen[8];
+ /* coupling delta bit allocation length */
+ u16 cpldeltba[8];
+ /* number of delta bit segments */
+ u16 deltnseg[5];
+ /* fbw delta bit allocation offset */
+ u16 deltoffst[5][8];
+ /* fbw delta bit allocation length */
+ u16 deltlen[5][8];
+ /* fbw delta bit allocation length */
+ u16 deltba[5][8];
+
+ /* skip length exists */
+ u16 skiple;
+ /* skip length */
+ u16 skipl;
+
+ /* channel mantissas */
+// u16 chmant[5][256];
+
+ /* coupling mantissas */
+ float cpl_flt[ 256 ];
+// u16 cplmant[256];
+
+ /* coupling mantissas */
+// u16 lfemant[7];
+
+ /* -- Information not in the bitstream, but derived thereof -- */
+
+ /* Number of coupling sub-bands */
+ u16 ncplsubnd;
+
+ /* Number of combined coupling sub-bands
+ * Derived from ncplsubnd and cplbndstrc */
+ u16 ncplbnd;
+
+ /* Number of exponent groups by channel
+ * Derived from strmant, endmant */
+ u16 nchgrps[5];
+
+ /* Number of coupling exponent groups
+ * Derived from cplbegf, cplendf, cplexpstr */
+ u16 ncplgrps;
+
+ /* End mantissa numbers of fbw channels */
+ u16 endmant[5];
+
+ /* Start and end mantissa numbers for the coupling channel */
+ u16 cplstrtmant;
+ u16 cplendmant;
+
+ /* Decoded exponent info */
+ u16 fbw_exp[5][256];
+ u16 cpl_exp[256];
+ u16 lfe_exp[7];
+
+ /* Bit allocation pointer results */
+ u16 fbw_bap[5][256];
+ /* FIXME?? figure out exactly how many entries there should be (253-37?) */
+ u16 cpl_bap[256];
+ u16 lfe_bap[7];
+} audblk_t;
+
+/* Everything you wanted to know about band structure */
+
+/*
+ * The entire frequency domain is represented by 256 real
+ * floating point fourier coefficients. Only the lower 253
+ * coefficients are actually utilized however. We use arrays
+ * of 256 to be efficient in some cases.
+ *
+ * The 5 full bandwidth channels (fbw) can have their higher
+ * frequencies coupled together. These coupled channels then
+ * share their high frequency components.
+ *
+ * This coupling band is broken up into 18 sub-bands starting
+ * at mantissa number 37. Each sub-band is 12 bins wide.
+ *
+ * There are 50 bit allocation sub-bands which cover the entire
+ * frequency range. The sub-bands are of non-uniform width, and
+ * approximate a 1/6 octave scale.
+ */
+
+typedef struct bit_allocate_s
+{
+ s16 psd[256];
+ s16 bndpsd[256];
+ s16 excite[256];
+ s16 mask[256];
+ s16 sdecay;
+ s16 fdecay;
+ s16 sgain;
+ s16 dbknee;
+ s16 floor;
+} bit_allocate_t;
+
+/* These store the persistent state of the packed mantissas */
+typedef struct mantissa_s
+{
+ float q_1[2];
+ float q_2[2];
+ float q_4[1];
+ s32 q_1_pointer;
+ s32 q_2_pointer;
+ s32 q_4_pointer;
+ u16 lfsr_state;
+} mantissa_t;
+
+struct a52dec_s
+{
+ float * samples;
+ void * samples_orig; /* pointer before memalign */
+ imdct_t * imdct;
+ void * imdct_orig; /* pointer before memalign */
+
+ /*
+ * Input properties
+ */
+
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+ int i_available;
+ unsigned int total_bits_read; /* temporary */
+
+ /*
+ * Decoder properties
+ */
+ syncinfo_t syncinfo;
+ bsi_t bsi;
+ audblk_t audblk;
+
+ dm_par_t dm_par;
+
+ bit_allocate_t bit_allocate;
+ mantissa_t mantissa;
+ downmix_t downmix;
+
+};
+
/*****************************************************************************
- * ac3_downmix.h : AC3 downmix types
+ * downmix.h : A52 downmix types
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: ac3_downmix.h,v 1.6 2002/07/31 20:56:50 sam Exp $
+ * $Id: downmix.h,v 1.1 2002/08/04 17:23:42 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Renaud Dartus <reno@videolan.org>
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+downmix_SOURCES = downmix.c downmix_c.c
+downmixsse_SOURCES = downmix.c downmix_sse.c
+downmix3dn_SOURCES = downmix.c downmix_3dn.c
--- /dev/null
+/*****************************************************************************
+ * downmix.c : A52 downmix module
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: downmix.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "../downmix.h"
+#include "downmix_common.h"
+
+/*****************************************************************************
+ * Module initializer
+ *****************************************************************************/
+static int Open ( vlc_object_t *p_this )
+{
+ downmix_t *p_downmix = (downmix_t *)p_this;
+
+ p_downmix->pf_downmix_3f_2r_to_2ch = E_( downmix_3f_2r_to_2ch );
+ p_downmix->pf_downmix_3f_1r_to_2ch = E_( downmix_3f_1r_to_2ch );
+ p_downmix->pf_downmix_2f_2r_to_2ch = E_( downmix_2f_2r_to_2ch );
+ p_downmix->pf_downmix_2f_1r_to_2ch = E_( downmix_2f_1r_to_2ch );
+ p_downmix->pf_downmix_3f_0r_to_2ch = E_( downmix_3f_0r_to_2ch );
+ p_downmix->pf_stream_sample_2ch_to_s16 = E_( stream_sample_2ch_to_s16 );
+ p_downmix->pf_stream_sample_1ch_to_s16 = E_( stream_sample_1ch_to_s16 );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#ifdef MODULE_NAME_IS_downmix
+ set_description( _("A52 downmix module") );
+ set_capability( "downmix", 50 );
+ add_shortcut( "c" );
+#elif defined( MODULE_NAME_IS_downmixsse )
+ set_description( _("SSE A52 downmix module") );
+ set_capability( "downmix", 200 );
+ add_shortcut( "sse" );
+#elif defined( MODULE_NAME_IS_downmix3dn )
+ set_description( _("3D Now! A52 downmix module") );
+ set_capability( "downmix", 200 );
+ add_shortcut( "3dn" );
+ add_shortcut( "3dnow" );
+#endif
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * downmix_3dn.c: accelerated 3D Now! A52 downmix functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: downmix_3dn.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+
+#include "../downmix.h"
+
+static const float sqrt2_3dn __asm__ ("sqrt2_3dn") = 0.7071068;
+
+void E_( downmix_3f_2r_to_2ch ) (float * samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $128, %%ebx\n" /* loop counter */
+
+ "movd (%%ecx), %%mm5\n" /* unit */
+ "punpckldq %%mm5, %%mm5\n" /* unit | unit */
+
+ "movd 4(%%ecx), %%mm6\n" /* clev */
+ "punpckldq %%mm6, %%mm6\n" /* clev | clev */
+
+ "movd 8(%%ecx), %%mm7\n" /* slev */
+ "punpckldq %%mm7, %%mm7\n" /* slev | slev */
+
+ ".align 16\n"
+".loop:\n"
+ "movq (%%eax), %%mm0\n" /* left */
+ "movq 2048(%%eax), %%mm1\n" /* right */
+ "movq 1024(%%eax), %%mm2\n" /* center */
+ "movq 3072(%%eax), %%mm3\n" /* leftsur */
+ "movq 4096(%%eax), %%mm4\n" /* rightsur */
+ "pfmul %%mm5, %%mm0\n"
+ "pfmul %%mm5, %%mm1\n"
+ "pfmul %%mm6, %%mm2\n"
+ "pfadd %%mm2, %%mm0\n"
+ "pfadd %%mm2, %%mm1\n"
+ "pfmul %%mm7, %%mm3\n"
+ "pfmul %%mm7, %%mm4\n"
+ "pfadd %%mm3, %%mm0\n"
+ "pfadd %%mm4, %%mm1\n"
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 1024(%%eax)\n"
+
+ "addl $8, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop\n"
+
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_2f_2r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $128, %%ebx\n" /* loop counter */
+
+ "movd (%%ecx), %%mm5\n" /* unit */
+ "punpckldq %%mm5, %%mm5\n" /* unit | unit */
+
+ "movd 8(%%ecx), %%mm7\n" /* slev */
+ "punpckldq %%mm7, %%mm7\n" /* slev | slev */
+
+ ".align 16\n"
+".loop3:\n"
+ "movq (%%eax), %%mm0\n" /* left */
+ "movq 1024(%%eax), %%mm1\n" /* right */
+ "movq 2048(%%eax), %%mm3\n" /* leftsur */
+ "movq 3072(%%eax), %%mm4\n" /* rightsur */
+ "pfmul %%mm5, %%mm0\n"
+ "pfmul %%mm5, %%mm1\n"
+ "pfmul %%mm7, %%mm3\n"
+ "pfmul %%mm7, %%mm4\n"
+ "pfadd %%mm3, %%mm0\n"
+ "pfadd %%mm4, %%mm1\n"
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 1024(%%eax)\n"
+
+ "addl $8, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop3\n"
+
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_3f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $128, %%ebx\n" /* loop counter */
+
+ "movd (%%ecx), %%mm5\n" /* unit */
+ "punpckldq %%mm5, %%mm5\n" /* unit | unit */
+
+ "movd 4(%%ecx), %%mm6\n" /* clev */
+ "punpckldq %%mm6, %%mm6\n" /* clev | clev */
+
+ "movd 8(%%ecx), %%mm7\n" /* slev */
+ "punpckldq %%mm7, %%mm7\n" /* slev | slev */
+
+ ".align 16\n"
+".loop4:\n"
+ "movq (%%eax), %%mm0\n" /* left */
+ "movq 2048(%%eax), %%mm1\n" /* right */
+ "movq 1024(%%eax), %%mm2\n" /* center */
+ "movq 3072(%%eax), %%mm3\n" /* sur */
+ "pfmul %%mm5, %%mm0\n"
+ "pfmul %%mm5, %%mm1\n"
+ "pfmul %%mm6, %%mm2\n"
+ "pfadd %%mm2, %%mm0\n"
+ "pfmul %%mm7, %%mm3\n"
+ "pfadd %%mm2, %%mm1\n"
+ "pfsub %%mm3, %%mm0\n"
+ "pfadd %%mm3, %%mm1\n"
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 1024(%%eax)\n"
+
+ "addl $8, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop4\n"
+
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_2f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $128, %%ebx\n" /* loop counter */
+
+ "movd (%%ecx), %%mm5\n" /* unit */
+ "punpckldq %%mm5, %%mm5\n" /* unit | unit */
+
+ "movd 8(%%ecx), %%mm7\n" /* slev */
+ "punpckldq %%mm7, %%mm7\n" /* slev | slev */
+
+ ".align 16\n"
+".loop5:\n"
+ "movq (%%eax), %%mm0\n" /* left */
+ "movq 1024(%%eax), %%mm1\n" /* right */
+ "movq 2048(%%eax), %%mm3\n" /* sur */
+ "pfmul %%mm5, %%mm0\n"
+ "pfmul %%mm5, %%mm1\n"
+ "pfmul %%mm7, %%mm3\n"
+ "pfsub %%mm3, %%mm0\n"
+ "pfadd %%mm3, %%mm1\n"
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 1024(%%eax)\n"
+
+ "addl $8, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop5\n"
+
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_3f_0r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $128, %%ebx\n" /* loop counter */
+
+ "movd (%%ecx), %%mm5\n" /* unit */
+ "punpckldq %%mm5, %%mm5\n" /* unit | unit */
+
+ "movd 4(%%ecx), %%mm6\n" /* clev */
+ "punpckldq %%mm6, %%mm6\n" /* clev | clev */
+
+ ".align 16\n"
+".loop6:\n"
+ "movq (%%eax), %%mm0\n" /*left */
+ "movq 2048(%%eax), %%mm1\n" /* right */
+ "movq 1024(%%eax), %%mm2\n" /* center */
+ "pfmul %%mm5, %%mm0\n"
+ "pfmul %%mm5, %%mm1\n"
+ "pfmul %%mm6, %%mm2\n"
+ "pfadd %%mm2, %%mm0\n"
+ "pfadd %%mm2, %%mm1\n"
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 1024(%%eax)\n"
+
+ "addl $8, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop6\n"
+
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( stream_sample_1ch_to_s16 ) (s16 *s16_samples, float *left)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "pushl %%edx\n"
+
+ "movl $sqrt2_3dn, %%edx\n"
+ "movd (%%edx), %%mm7\n"
+ "punpckldq %%mm7, %%mm7\n" /* sqrt2 | sqrt2 */
+ "movl $128, %%ebx\n"
+
+ ".align 16\n"
+".loop2:\n"
+ "movq (%%ecx), %%mm0\n" /* c1 | c0 */
+ "pfmul %%mm7, %%mm0\n"
+
+ "pf2id %%mm0, %%mm0\n" /* c1 c0 --> mm0, int_32 */
+
+ "packssdw %%mm0, %%mm0\n" /* c1 c1 c0 c0 --> mm0, int_16 */
+
+ "movq %%mm0, (%%eax)\n"
+ "addl $8, %%eax\n"
+ "addl $8, %%ecx\n"
+
+ "decl %%ebx\n"
+ "jnz .loop2\n"
+
+ "popl %%edx\n"
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (s16_samples), "=c" (left)
+ : "a" (s16_samples), "c" (left));
+}
+
+void E_( stream_sample_2ch_to_s16 ) (s16 *s16_samples, float *left, float *right)
+{
+
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $128, %%ebx\n"
+
+ ".align 16\n"
+".loop1:\n"
+ "movq (%%ecx), %%mm0\n" /* l1 | l0 */
+ "movq (%%edx), %%mm1\n" /* r1 | r0 */
+ "movq %%mm0, %%mm2\n" /* l1 | l0 */
+ "punpckldq %%mm1, %%mm0\n" /* r0 | l0 */
+ "punpckhdq %%mm1, %%mm2\n" /* r1 | l1 */
+
+ "pf2id %%mm0, %%mm0\n" /* r0 l0 --> mm0, int_32 */
+ "pf2id %%mm2, %%mm2\n" /* r0 l0 --> mm0, int_32 */
+
+ "packssdw %%mm2, %%mm0\n" /* r1 l1 r0 l0 --> mm0, int_16 */
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm2, 8(%%eax)\n"
+ "addl $8, %%eax\n"
+ "addl $8, %%ecx\n"
+ "addl $8, %%edx\n"
+
+ "decl %%ebx\n"
+ "jnz .loop1\n"
+
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (s16_samples), "=c" (left), "=d" (right)
+ : "a" (s16_samples), "c" (left), "d" (right));
+
+}
+
--- /dev/null
+/*****************************************************************************
+ * downmix_c.c: A52 downmix functions in C
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: downmix_c.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy() */
+
+#include <vlc/vlc.h>
+
+#include "../downmix.h"
+
+void E_( downmix_3f_2r_to_2ch ) (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *center, *left_sur, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = samples;
+ center = samples + 256;
+ right = samples + 256*2;
+ left_sur = samples + 256*3;
+ right_sur = samples + 256*4;
+
+ for (i=0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->clev * *center + dm_par->slev * *left_sur++;
+ right_tmp = dm_par->unit * *right++ + dm_par->clev * *center + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *center++ = right_tmp;
+ }
+}
+
+void E_( downmix_2f_2r_to_2ch ) (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *left_sur, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ right = &samples[256];
+ left_sur = &samples[512];
+ right_sur = &samples[768];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->slev * *left_sur++;
+ right_tmp= dm_par->unit * *right + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *right++ = right_tmp;
+ }
+}
+
+void E_( downmix_3f_1r_to_2ch ) (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *center, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ right = &samples[512];
+ center = &samples[256];
+ right_sur = &samples[768];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->clev * *center - dm_par->slev * *right_sur;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *center++ = right_tmp;
+ }
+}
+
+
+void E_( downmix_2f_1r_to_2ch ) (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ right = &samples[256];
+ right_sur = &samples[512];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left - dm_par->slev * *right_sur;
+ right_tmp= dm_par->unit * *right + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *right++ = right_tmp;
+ }
+}
+
+
+void E_( downmix_3f_0r_to_2ch ) (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *center;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ center = &samples[256];
+ right = &samples[512];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->clev * *center;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center;
+ *left++ = left_tmp;
+ *center++ = right_tmp;
+ }
+}
+
+
+void E_( stream_sample_2ch_to_s16 ) (s16 *out_buf, float *left, float *right)
+{
+ int i;
+ for (i=0; i < 256; i++) {
+ *out_buf++ = (s16) (*left++);
+ *out_buf++ = (s16) (*right++);
+ }
+}
+
+
+void E_( stream_sample_1ch_to_s16 ) (s16 *out_buf, float *center)
+{
+ int i;
+ float tmp;
+
+ for (i=0; i < 256; i++) {
+ *out_buf++ = tmp = (s16) (0.7071f * *center++);
+ *out_buf++ = tmp;
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * downmix_common.h: A52 downmix functions headers
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: downmix_common.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+void E_( downmix_3f_2r_to_2ch ) ( float *, dm_par_t * );
+void E_( downmix_2f_2r_to_2ch ) ( float *, dm_par_t * );
+void E_( downmix_3f_1r_to_2ch ) ( float *, dm_par_t * );
+void E_( downmix_2f_1r_to_2ch ) ( float *, dm_par_t * );
+void E_( downmix_3f_0r_to_2ch ) ( float *, dm_par_t * );
+void E_( stream_sample_2ch_to_s16 ) ( s16 *, float *, float * );
+void E_( stream_sample_1ch_to_s16 ) ( s16 *, float * );
+
--- /dev/null
+/*****************************************************************************
+ * downmix_sse.c: accelerated SSE A52 downmix functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: downmix_sse.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+
+#include "../downmix.h"
+
+static const float sqrt2_sse __asm__ ("sqrt2_sse") __attribute__ ((aligned (16))) = 0.7071068;
+
+void E_( downmix_3f_2r_to_2ch ) (float * samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $64, %%ebx\n" /* loop counter */
+
+ "movss (%%ecx), %%xmm5\n" /* unit */
+ "shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
+
+ "movss 4(%%ecx), %%xmm6\n" /* clev */
+ "shufps $0, %%xmm6, %%xmm6\n" /* clev | clev | clev | clev */
+
+ "movss 8(%%ecx), %%xmm7\n" /* slev */
+ "shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
+
+ ".align 16\n"
+".loop:\n"
+ "movaps (%%eax), %%xmm0\n" /* left */
+ "movaps 2048(%%eax), %%xmm1\n" /* right */
+ "movaps 1024(%%eax), %%xmm2\n" /* center */
+ "movaps 3072(%%eax), %%xmm3\n" /* leftsur */
+ "movaps 4096(%%eax), %%xmm4\n" /* rithgsur */
+ "mulps %%xmm5, %%xmm0\n"
+ "mulps %%xmm5, %%xmm1\n"
+ "mulps %%xmm6, %%xmm2\n"
+ "addps %%xmm2, %%xmm0\n"
+ "addps %%xmm2, %%xmm1\n"
+ "mulps %%xmm7, %%xmm3\n"
+ "mulps %%xmm7, %%xmm4\n"
+ "addps %%xmm3, %%xmm0\n"
+ "addps %%xmm4, %%xmm1\n"
+
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm1, 1024(%%eax)\n"
+
+ "addl $16, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop\n"
+
+ "popl %%ebx\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_2f_2r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $64, %%ebx\n" /* loop counter */
+
+ "movss (%%ecx), %%xmm5\n" /* unit */
+ "shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
+
+ "movss 8(%%ecx), %%xmm7\n" /* slev */
+ "shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
+
+ ".align 16\n"
+".loop3:\n"
+ "movaps (%%eax), %%xmm0\n" /* left */
+ "movaps 1024(%%eax), %%xmm1\n" /* right */
+ "movaps 2048(%%eax), %%xmm3\n" /* leftsur */
+ "movaps 3072(%%eax), %%xmm4\n" /* rightsur */
+ "mulps %%xmm5, %%xmm0\n"
+ "mulps %%xmm5, %%xmm1\n"
+ "mulps %%xmm7, %%xmm3\n"
+ "mulps %%xmm7, %%xmm4\n"
+ "addps %%xmm3, %%xmm0\n"
+ "addps %%xmm4, %%xmm1\n"
+
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm1, 1024(%%eax)\n"
+
+ "addl $16, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop3\n"
+
+ "popl %%ebx\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_3f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $64, %%ebx\n" /* loop counter */
+
+ "movss (%%ecx), %%xmm5\n" /* unit */
+ "shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
+
+ "movss 4(%%ecx), %%xmm6\n" /* clev */
+ "shufps $0, %%xmm6, %%xmm6\n" /* clev | clev | clev | clev */
+
+ "movss 8(%%ecx), %%xmm7\n" /* slev */
+ "shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
+
+ ".align 16\n"
+".loop4:\n"
+ "movaps (%%eax), %%xmm0\n" /* left */
+ "movaps 2048(%%eax), %%xmm1\n" /* right */
+ "movaps 1024(%%eax), %%xmm2\n" /* center */
+ "movaps 3072(%%eax), %%xmm3\n" /* sur */
+ "mulps %%xmm5, %%xmm0\n"
+ "mulps %%xmm5, %%xmm1\n"
+ "mulps %%xmm6, %%xmm2\n"
+ "addps %%xmm2, %%xmm0\n"
+ "mulps %%xmm7, %%xmm3\n"
+ "addps %%xmm2, %%xmm1\n"
+ "subps %%xmm3, %%xmm0\n"
+ "addps %%xmm3, %%xmm1\n"
+
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm1, 1024(%%eax)\n"
+
+ "addl $16, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop4\n"
+
+ "popl %%ebx\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_2f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $64, %%ebx\n" /* loop counter */
+
+ "movss (%%ecx), %%xmm5\n" /* unit */
+ "shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
+
+ "movss 8(%%ecx), %%xmm7\n" /* slev */
+ "shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
+
+ ".align 16\n"
+".loop5:\n"
+ "movaps (%%eax), %%xmm0\n" /* left */
+ "movaps 1024(%%eax), %%xmm1\n" /* right */
+ "movaps 2048(%%eax), %%xmm3\n" /* sur */
+ "mulps %%xmm5, %%xmm0\n"
+ "mulps %%xmm5, %%xmm1\n"
+ "mulps %%xmm7, %%xmm3\n"
+ "subps %%xmm3, %%xmm0\n"
+ "addps %%xmm3, %%xmm1\n"
+
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm1, 1024(%%eax)\n"
+
+ "addl $16, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop5\n"
+
+ "popl %%ebx\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( downmix_3f_0r_to_2ch ) (float *samples, dm_par_t * dm_par)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $64, %%ebx\n" /* loop counter */
+
+ "movss (%%ecx), %%xmm5\n" /* unit */
+ "shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
+
+ "movss 4(%%ecx), %%xmm6\n" /* clev */
+ "shufps $0, %%xmm6, %%xmm6\n" /* clev | clev | clev | clev */
+
+ ".align 16\n"
+".loop6:\n"
+ "movaps (%%eax), %%xmm0\n" /*left */
+ "movaps 2048(%%eax), %%xmm1\n" /* right */
+ "movaps 1024(%%eax), %%xmm2\n" /* center */
+ "mulps %%xmm5, %%xmm0\n"
+ "mulps %%xmm5, %%xmm1\n"
+ "mulps %%xmm6, %%xmm2\n"
+ "addps %%xmm2, %%xmm0\n"
+ "addps %%xmm2, %%xmm1\n"
+
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm1, 1024(%%eax)\n"
+
+ "addl $16, %%eax\n"
+ "decl %%ebx\n"
+ "jnz .loop6\n"
+
+ "popl %%ebx\n"
+ : "=a" (samples)
+ : "a" (samples), "c" (dm_par));
+}
+
+void E_( stream_sample_1ch_to_s16 ) (s16 *s16_samples, float *left)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "pushl %%edx\n"
+
+ "movl $sqrt2_sse, %%edx\n"
+ "movss (%%edx), %%xmm7\n"
+ "shufps $0, %%xmm7, %%xmm7\n" /* sqrt2 | sqrt2 | sqrt2 | sqrt2 */
+ "movl $64, %%ebx\n"
+
+ ".align 16\n"
+".loop2:\n"
+ "movaps (%%ecx), %%xmm0\n" /* c3 | c2 | c1 | c0 */
+ "mulps %%xmm7, %%xmm0\n"
+ "movhlps %%xmm0, %%xmm2\n" /* c3 | c2 */
+
+ "cvtps2pi %%xmm0, %%mm0\n" /* c1 c0 --> mm0, int_32 */
+ "cvtps2pi %%xmm2, %%mm1\n" /* c3 c2 --> mm1, int_32 */
+
+ "packssdw %%mm0, %%mm0\n" /* c1 c1 c0 c0 --> mm0, int_16 */
+ "packssdw %%mm1, %%mm1\n" /* c3 c3 c2 c2 --> mm1, int_16 */
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 8(%%eax)\n"
+ "addl $16, %%eax\n"
+ "addl $16, %%ecx\n"
+
+ "decl %%ebx\n"
+ "jnz .loop2\n"
+
+ "popl %%edx\n"
+ "popl %%ebx\n"
+ "emms\n"
+ : "=a" (s16_samples), "=c" (left)
+ : "a" (s16_samples), "c" (left));
+}
+
+void E_( stream_sample_2ch_to_s16 ) (s16 *s16_samples, float *left, float *right)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $64, %%ebx\n"
+
+ ".align 16\n"
+".loop1:\n"
+ "movaps (%%ecx), %%xmm0\n" /* l3 | l2 | l1 | l0 */
+ "movaps (%%edx), %%xmm1\n" /* r3 | r2 | r1 | r0 */
+ "movhlps %%xmm0, %%xmm2\n" /* l3 | l2 */
+ "movhlps %%xmm1, %%xmm3\n" /* r3 | r2 */
+ "unpcklps %%xmm1, %%xmm0\n" /* r1 | l1 | r0 | l0 */
+ "unpcklps %%xmm3, %%xmm2\n" /* r3 | l3 | r2 | l2 */
+
+ "cvtps2pi %%xmm0, %%mm0\n" /* r0 l0 --> mm0, int_32 */
+ "movhlps %%xmm0, %%xmm0\n"
+ "cvtps2pi %%xmm0, %%mm1\n" /* r1 l1 --> mm1, int_32 */
+ "cvtps2pi %%xmm2, %%mm2\n" /* r2 l2 --> mm2, int_32 */
+ "movhlps %%xmm2, %%xmm2\n"
+ "cvtps2pi %%xmm2, %%mm3\n" /* r3 l3 --> mm3, int_32 */
+
+ "packssdw %%mm1, %%mm0\n" /* r1 l1 r0 l0 --> mm0, int_16 */
+ "packssdw %%mm3, %%mm2\n" /* r3 l3 r2 l2 --> mm2, int_16 */
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm2, 8(%%eax)\n"
+ "addl $16, %%eax\n"
+ "addl $16, %%ecx\n"
+ "addl $16, %%edx\n"
+
+ "decl %%ebx\n"
+ "jnz .loop1\n"
+
+ "popl %%ebx\n"
+ "emms\n"
+ : "=a" (s16_samples), "=c" (left), "=d" (right)
+ : "a" (s16_samples), "c" (left), "d" (right));
+
+}
+
--- /dev/null
+/*****************************************************************************
+ * exponent.c: A52 exponent calculations
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: exponent.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@zoy.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h"
+
+#include "internal.h"
+
+#include "exponent.h"
+
+int exponent_unpack (a52dec_t * p_a52dec)
+{
+ u16 i;
+
+ for (i = 0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ if (exp_unpack_ch (p_a52dec, UNPACK_FBW, p_a52dec->audblk.chexpstr[i],
+ p_a52dec->audblk.nchgrps[i],
+ p_a52dec->audblk.exps[i][0],
+ &p_a52dec->audblk.exps[i][1],
+ p_a52dec->audblk.fbw_exp[i]))
+ {
+ return 1;
+ }
+ }
+
+ if (p_a52dec->audblk.cplinu)
+ {
+ if (exp_unpack_ch (p_a52dec, UNPACK_CPL, p_a52dec->audblk.cplexpstr,
+ p_a52dec->audblk.ncplgrps,
+ p_a52dec->audblk.cplabsexp << 1,
+ p_a52dec->audblk.cplexps,
+ &p_a52dec->audblk.cpl_exp[p_a52dec->audblk.cplstrtmant]))
+ {
+ return 1;
+ }
+ }
+
+ if (p_a52dec->bsi.lfeon)
+ {
+ if (exp_unpack_ch (p_a52dec, UNPACK_LFE, p_a52dec->audblk.lfeexpstr,
+ 2, p_a52dec->audblk.lfeexps[0],
+ &p_a52dec->audblk.lfeexps[1],
+ p_a52dec->audblk.lfe_exp))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * exponent.h: A52 exponent calculations
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: exponent.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@zoy.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+static const s16 exps_1[128] =
+{
+ -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0
+};
+
+static const s16 exps_2[128] =
+{
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ 0, 0, 0
+};
+
+static const s16 exps_3[128] =
+{
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ 0, 0, 0
+};
+
+#define UNPACK_FBW 1
+#define UNPACK_CPL 2
+#define UNPACK_LFE 4
+
+static inline int exp_unpack_ch( a52dec_t * p_a52dec, u16 type,
+ u16 expstr, u16 ngrps, u16 initial_exp,
+ u16 exps[], u16 * dest )
+{
+ u16 i,j;
+ s16 exp_acc;
+
+ if (expstr == EXP_REUSE)
+ {
+ return 0;
+ }
+
+ /* Handle the initial absolute exponent */
+ exp_acc = initial_exp;
+ j = 0;
+
+ /* In the case of a fbw channel then the initial absolute values is
+ * also an exponent */
+ if (type != UNPACK_CPL)
+ {
+ dest[j++] = exp_acc;
+ }
+
+ /* Loop through the groups and fill the dest array appropriately */
+ switch (expstr)
+ {
+ case EXP_D15: /* 1 */
+ for (i = 0; i < ngrps; i++)
+ {
+ if (exps[i] > 124)
+ {
+ msg_Err( p_a52dec->p_fifo, "invalid exponent" );
+ return 1;
+ }
+ exp_acc += (exps_1[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ exp_acc += (exps_2[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ exp_acc += (exps_3[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ }
+ break;
+
+ case EXP_D25: /* 2 */
+ for (i = 0; i < ngrps; i++)
+ {
+ if (exps[i] > 124)
+ {
+ msg_Err( p_a52dec->p_fifo, "invalid exponent" );
+ return 1;
+ }
+ exp_acc += (exps_1[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ exp_acc += (exps_2[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ exp_acc += (exps_3[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ }
+ break;
+
+ case EXP_D45: /* 3 */
+ for (i = 0; i < ngrps; i++)
+ {
+ if (exps[i] > 124)
+ {
+ msg_Err( p_a52dec->p_fifo, "invalid exponent" );
+ return 1;
+ }
+ exp_acc += (exps_1[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ exp_acc += (exps_2[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ exp_acc += (exps_3[exps[i]] /*- 2*/);
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ }
+ break;
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * imdct.c: A52 DCT
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: imdct.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ * Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy() */
+
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+void E_( imdct_init )(imdct_t * p_imdct)
+{
+ int i;
+ float scale = 181.019;
+
+ p_imdct->pf_imdct_init( p_imdct );
+
+ /* More twiddle factors to turn IFFT into IMDCT */
+ for (i=0; i < 64; i++) {
+ p_imdct->xcos2[i] = cos(2.0f * M_PI * (8*i+1)/(4*N)) * scale;
+ p_imdct->xsin2[i] = sin(2.0f * M_PI * (8*i+1)/(4*N)) * scale;
+ }
+}
+
+void imdct (a52dec_t * p_a52dec, s16 * buffer)
+{
+ int i;
+ int doable = 0;
+ float *center=NULL, *left, *right, *left_sur, *right_sur;
+ float *delay_left, *delay_right;
+ float *delay1_left, *delay1_right, *delay1_center, *delay1_sr, *delay1_sl;
+ float right_tmp, left_tmp;
+ void (*do_imdct)(imdct_t * p_imdct, float data[], float delay[]);
+
+ /* test if dm in frequency is doable */
+ if (!(doable = p_a52dec->audblk.blksw[0]))
+ {
+ do_imdct = p_a52dec->p_imdct->pf_imdct_512;
+ }
+ else
+ {
+ do_imdct = p_a52dec->p_imdct->pf_imdct_256;
+ }
+
+ /* downmix in the frequency domain if all the channels
+ * use the same imdct */
+ for (i=0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ if (doable != p_a52dec->audblk.blksw[i])
+ {
+ do_imdct = NULL;
+ break;
+ }
+ }
+
+ if (do_imdct)
+ {
+ /* dowmix first and imdct */
+ switch(p_a52dec->bsi.acmod)
+ {
+ case 7: /* 3/2 */
+ p_a52dec->p_downmix->pf_downmix_3f_2r_to_2ch (p_a52dec->samples, &p_a52dec->dm_par);
+ break;
+ case 6: /* 2/2 */
+ p_a52dec->p_downmix->pf_downmix_2f_2r_to_2ch (p_a52dec->samples, &p_a52dec->dm_par);
+ break;
+ case 5: /* 3/1 */
+ p_a52dec->p_downmix->pf_downmix_3f_1r_to_2ch (p_a52dec->samples, &p_a52dec->dm_par);
+ break;
+ case 4: /* 2/1 */
+ p_a52dec->p_downmix->pf_downmix_2f_1r_to_2ch (p_a52dec->samples, &p_a52dec->dm_par);
+ break;
+ case 3: /* 3/0 */
+ p_a52dec->p_downmix->pf_downmix_3f_0r_to_2ch (p_a52dec->samples, &p_a52dec->dm_par);
+ break;
+ case 2:
+ break;
+ default: /* 1/0 */
+// if (p_a52dec->bsi.acmod == 1)
+ center = p_a52dec->samples;
+// else if (p_a52dec->bsi.acmod == 0)
+// center = samples[config.dual_mono_ch_sel];
+ do_imdct(p_a52dec->p_imdct, center, p_a52dec->p_imdct->delay); /* no downmix*/
+
+ p_a52dec->p_downmix->pf_stream_sample_1ch_to_s16 (buffer, center);
+
+ return;
+ break;
+ }
+
+ do_imdct (p_a52dec->p_imdct, p_a52dec->samples, p_a52dec->p_imdct->delay);
+ do_imdct (p_a52dec->p_imdct, p_a52dec->samples+256, p_a52dec->p_imdct->delay+256);
+ p_a52dec->p_downmix->pf_stream_sample_2ch_to_s16(buffer, p_a52dec->samples, p_a52dec->samples+256);
+
+ } else {
+ /* imdct and then downmix
+ * delay and samples should be saved and mixed
+ * fprintf(stderr, "time domain downmix\n"); */
+ for (i=0; i<p_a52dec->bsi.nfchans; i++)
+ {
+ if (p_a52dec->audblk.blksw[i])
+ {
+ /* There is only a C function */
+ p_a52dec->p_imdct->pf_imdct_256_nol( p_a52dec->p_imdct,
+ p_a52dec->samples+256*i, p_a52dec->p_imdct->delay1+256*i );
+ }
+ else
+ {
+ p_a52dec->p_imdct->pf_imdct_512_nol( p_a52dec->p_imdct,
+ p_a52dec->samples+256*i, p_a52dec->p_imdct->delay1+256*i );
+ }
+ }
+
+ /* mix the sample, overlap */
+ switch(p_a52dec->bsi.acmod)
+ {
+ case 7: /* 3/2 */
+ left = p_a52dec->samples;
+ center = p_a52dec->samples+256;
+ right = p_a52dec->samples+2*256;
+ left_sur = p_a52dec->samples+3*256;
+ right_sur = p_a52dec->samples+4*256;
+ delay_left = p_a52dec->p_imdct->delay;
+ delay_right = p_a52dec->p_imdct->delay+256;
+ delay1_left = p_a52dec->p_imdct->delay1;
+ delay1_center = p_a52dec->p_imdct->delay1+256;
+ delay1_right = p_a52dec->p_imdct->delay1+2*256;
+ delay1_sl = p_a52dec->p_imdct->delay1+3*256;
+ delay1_sr = p_a52dec->p_imdct->delay1+4*256;
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = p_a52dec->dm_par.unit * *left++ + p_a52dec->dm_par.clev * *center + p_a52dec->dm_par.slev * *left_sur++;
+ right_tmp= p_a52dec->dm_par.unit * *right++ + p_a52dec->dm_par.clev * *center++ + p_a52dec->dm_par.slev * *right_sur++;
+ *buffer++ = (s16)(left_tmp + *delay_left);
+ *buffer++ = (s16)(right_tmp + *delay_right);
+ *delay_left++ = p_a52dec->dm_par.unit * *delay1_left++ + p_a52dec->dm_par.clev * *delay1_center + p_a52dec->dm_par.slev * *delay1_sl++;
+ *delay_right++ = p_a52dec->dm_par.unit * *delay1_right++ + p_a52dec->dm_par.clev * *center++ + p_a52dec->dm_par.slev * *delay1_sr++;
+ }
+ break;
+ case 6: /* 2/2 */
+ left = p_a52dec->samples;
+ right = p_a52dec->samples+256;
+ left_sur = p_a52dec->samples+2*256;
+ right_sur = p_a52dec->samples+3*256;
+ delay_left = p_a52dec->p_imdct->delay;
+ delay_right = p_a52dec->p_imdct->delay+256;
+ delay1_left = p_a52dec->p_imdct->delay1;
+ delay1_right = p_a52dec->p_imdct->delay1+256;
+ delay1_sl = p_a52dec->p_imdct->delay1+2*256;
+ delay1_sr = p_a52dec->p_imdct->delay1+3*256;
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = p_a52dec->dm_par.unit * *left++ + p_a52dec->dm_par.slev * *left_sur++;
+ right_tmp= p_a52dec->dm_par.unit * *right++ + p_a52dec->dm_par.slev * *right_sur++;
+ *buffer++ = (s16)(left_tmp + *delay_left);
+ *buffer++ = (s16)(right_tmp + *delay_right);
+ *delay_left++ = p_a52dec->dm_par.unit * *delay1_left++ + p_a52dec->dm_par.slev * *delay1_sl++;
+ *delay_right++ = p_a52dec->dm_par.unit * *delay1_right++ + p_a52dec->dm_par.slev * *delay1_sr++;
+ }
+ break;
+ case 5: /* 3/1 */
+ left = p_a52dec->samples;
+ center = p_a52dec->samples+256;
+ right = p_a52dec->samples+2*256;
+ right_sur = p_a52dec->samples+3*256;
+ delay_left = p_a52dec->p_imdct->delay;
+ delay_right = p_a52dec->p_imdct->delay+256;
+ delay1_left = p_a52dec->p_imdct->delay1;
+ delay1_center = p_a52dec->p_imdct->delay1+256;
+ delay1_right = p_a52dec->p_imdct->delay1+2*256;
+ delay1_sl = p_a52dec->p_imdct->delay1+3*256;
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = p_a52dec->dm_par.unit * *left++ + p_a52dec->dm_par.clev * *center - p_a52dec->dm_par.slev * *right_sur;
+ right_tmp= p_a52dec->dm_par.unit * *right++ + p_a52dec->dm_par.clev * *center++ + p_a52dec->dm_par.slev * *right_sur++;
+ *buffer++ = (s16)(left_tmp + *delay_left);
+ *buffer++ = (s16)(right_tmp + *delay_right);
+ *delay_left++ = p_a52dec->dm_par.unit * *delay1_left++ + p_a52dec->dm_par.clev * *delay1_center + p_a52dec->dm_par.slev * *delay1_sl;
+ *delay_right++ = p_a52dec->dm_par.unit * *delay1_right++ + p_a52dec->dm_par.clev * *center++ + p_a52dec->dm_par.slev * *delay1_sl++;
+ }
+ break;
+ case 4: /* 2/1 */
+ left = p_a52dec->samples;
+ right = p_a52dec->samples+256;
+ right_sur = p_a52dec->samples+2*256;
+ delay_left = p_a52dec->p_imdct->delay;
+ delay_right = p_a52dec->p_imdct->delay+256;
+ delay1_left = p_a52dec->p_imdct->delay1;
+ delay1_right = p_a52dec->p_imdct->delay1+256;
+ delay1_sl = p_a52dec->p_imdct->delay1+2*256;
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = p_a52dec->dm_par.unit * *left++ - p_a52dec->dm_par.slev * *right_sur;
+ right_tmp= p_a52dec->dm_par.unit * *right++ + p_a52dec->dm_par.slev * *right_sur++;
+ *buffer++ = (s16)(left_tmp + *delay_left);
+ *buffer++ = (s16)(right_tmp + *delay_right);
+ *delay_left++ = p_a52dec->dm_par.unit * *delay1_left++ + p_a52dec->dm_par.slev * *delay1_sl;
+ *delay_right++ = p_a52dec->dm_par.unit * *delay1_right++ + p_a52dec->dm_par.slev * *delay1_sl++;
+ }
+ break;
+ case 3: /* 3/0 */
+ left = p_a52dec->samples;
+ center = p_a52dec->samples+256;
+ right = p_a52dec->samples+2*256;
+ delay_left = p_a52dec->p_imdct->delay;
+ delay_right = p_a52dec->p_imdct->delay+256;
+ delay1_left = p_a52dec->p_imdct->delay1;
+ delay1_center = p_a52dec->p_imdct->delay1+256;
+ delay1_right = p_a52dec->p_imdct->delay1+2*256;
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = p_a52dec->dm_par.unit * *left++ + p_a52dec->dm_par.clev * *center;
+ right_tmp= p_a52dec->dm_par.unit * *right++ + p_a52dec->dm_par.clev * *center++;
+ *buffer++ = (s16)(left_tmp + *delay_left);
+ *buffer++ = (s16)(right_tmp + *delay_right);
+ *delay_left++ = p_a52dec->dm_par.unit * *delay1_left++ + p_a52dec->dm_par.clev * *delay1_center;
+ *delay_right++ = p_a52dec->dm_par.unit * *delay1_right++ + p_a52dec->dm_par.clev * *center++;
+ }
+ break;
+ case 2: /* copy to output */
+ for (i = 0; i < 256; i++) {
+ *buffer++ = (s16) *(p_a52dec->samples+i);
+ *buffer++ = (s16) *(p_a52dec->samples+256+i);
+ }
+ break;
+ }
+ }
+}
/*****************************************************************************
- * ac3_imdct.h : AC3 IMDCT types
+ * imdct.h : A52 IMDCT types
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: ac3_imdct.h,v 1.10 2002/07/31 20:56:50 sam Exp $
+ * $Id: imdct.h,v 1.1 2002/08/04 17:23:42 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Renaud Dartus <reno@videolan.org>
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+COMMON_SOURCES = imdct_common.c
+
+imdct_SOURCES = imdct.c imdct_c.c srfft_c.c $(COMMON_SOURCES)
+imdctsse_SOURCES = imdct.c imdct_sse.c srfft_sse.c $(COMMON_SOURCES)
+imdct3dn_SOURCES = imdct.c imdct_3dn.c srfft_3dn.c $(COMMON_SOURCES)
--- /dev/null
+/*****************************************************************************
+ * imdct.c : IMDCT module
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: imdct.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Gaël Hendryckx <jimmy@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "imdct_common.h"
+
+/*****************************************************************************
+ * Module initializer
+ *****************************************************************************/
+static int Open ( vlc_object_t *p_this )
+{
+ imdct_t *p_imdct = (imdct_t *)p_this;
+
+ p_imdct->pf_imdct_init = E_( imdct_init );
+ p_imdct->pf_imdct_256 = E_( imdct_do_256 );
+ p_imdct->pf_imdct_256_nol = E_( imdct_do_256_nol );
+ p_imdct->pf_imdct_512 = E_( imdct_do_512 );
+ p_imdct->pf_imdct_512_nol = E_( imdct_do_512_nol );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#if defined( MODULE_NAME_IS_imdct )
+ set_description( _("A52 IMDCT module") );
+ set_capability( "imdct", 50 );
+ add_shortcut( "c" );
+#elif defined( MODULE_NAME_IS_imdctsse )
+ set_description( _("SSE A52 IMDCT module") );
+ set_capability( "imdct", 200 );
+ add_shortcut( "sse" );
+#elif defined( MODULE_NAME_IS_imdct3dn )
+ set_description( _("3D Now! A52 IMDCT module") );
+ set_capability( "imdct", 200 );
+ add_shortcut( "3dn" );
+ add_shortcut( "3dnow" );
+#endif
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * imdct_3dn.c: accelerated 3D Now! A52 DCT
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: imdct_3dn.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "imdct_common.h"
+#include "retables.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+void E_( fft_64p ) ( complex_t *x );
+void E_( fft_128p ) ( complex_t *a );
+
+static void imdct512_pre_ifft_twiddle_3dn (const int *pmt, complex_t *buf, float *data, float *xcos_sin_sse);
+static void imdct512_post_ifft_twiddle_3dn (complex_t *buf, float *xcos_sin_sse);
+static void imdct512_window_delay_3dn (complex_t *buf, float *data_ptr, float *window_prt, float *delay_prt);
+static void imdct512_window_delay_nol_3dn (complex_t *buf, float *data_ptr, float *window_prt, float *delay_prt);
+
+
+void E_( imdct_init ) (imdct_t * p_imdct)
+{
+ int i;
+ float scale = 181.019;
+
+ for (i=0; i < 128; i++)
+ {
+ float xcos_i = cos(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ float xsin_i = sin(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ p_imdct->xcos_sin_sse[i * 4] = xcos_i;
+ p_imdct->xcos_sin_sse[i * 4 + 1] = -xsin_i;
+ p_imdct->xcos_sin_sse[i * 4 + 2] = -xsin_i;
+ p_imdct->xcos_sin_sse[i * 4 + 3] = -xcos_i;
+ }
+}
+
+void E_( imdct_do_512 ) (imdct_t * p_imdct, float data[], float delay[])
+{
+ imdct512_pre_ifft_twiddle_3dn (pm128, p_imdct->buf, data, p_imdct->xcos_sin_sse);
+ E_( fft_128p ) (p_imdct->buf);
+ imdct512_post_ifft_twiddle_3dn (p_imdct->buf, p_imdct->xcos_sin_sse);
+ imdct512_window_delay_3dn (p_imdct->buf, data, window, delay);
+}
+
+void E_( imdct_do_512_nol ) (imdct_t * p_imdct, float data[], float delay[])
+{
+ imdct512_pre_ifft_twiddle_3dn (pm128, p_imdct->buf, data, p_imdct->xcos_sin_sse);
+ E_( fft_128p ) (p_imdct->buf);
+ imdct512_post_ifft_twiddle_3dn (p_imdct->buf, p_imdct->xcos_sin_sse);
+ imdct512_window_delay_nol_3dn (p_imdct->buf, data, window, delay);
+}
+
+static void imdct512_pre_ifft_twiddle_3dn (const int *pmt, complex_t *buf, float *data, float *xcos_sin_sse)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "pushl %%esi\n"
+
+ "movl $128, %%ebx\n" /* loop counter */
+
+ ".align 16\n"
+"0:\n"
+ "movl (%%eax), %%esi\n"
+ "movd (%%ecx, %%esi, 8), %%mm1\n" /* 2j */
+ "punpckldq %%mm1, %%mm1\n" /* 2j | 2j */
+
+ "shll $1, %%esi\n"
+
+ "movq (%%edx, %%esi, 8), %%mm0\n" /* -s_j | c_j */
+ "movq 8(%%edx, %%esi, 8), %%mm2\n" /* -c_j | -s_j */
+
+ "negl %%esi\n"
+
+ "movd 1020(%%ecx, %%esi, 4), %%mm4\n" /* 255-2j */
+ "punpckldq %%mm4, %%mm4\n" /* 255-2j | 255-2j */
+ "addl $4, %%eax\n"
+
+ "pfmul %%mm4, %%mm0\n" /* 255-2j * -s_j | 255-2j * c_j */
+ "pfmul %%mm1, %%mm2\n" /* 2j * -c_j | 2j * -s_j */
+ "addl $8, %%edi\n"
+ "pfadd %%mm2, %%mm0\n" /* 2j * -c_j + 255-2j * -s_j | 2j * -s_j + 255-2j * c_j */
+
+ "movq %%mm0, -8(%%edi)\n"
+ "decl %%ebx\n"
+ "jnz 0b\n"
+
+ "popl %%esi\n"
+ "popl %%ebx\n"
+
+ "femms\n"
+ : "=D" (buf)
+ : "a" (pmt), "c" (data), "d" (xcos_sin_sse), "D" (buf));
+}
+
+static void imdct512_post_ifft_twiddle_3dn (complex_t *buf, float *xcos_sin_sse)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $64, %%ebx\n" /* loop counter */
+
+ ".align 16\n"
+"0:\n"
+ "movq (%%eax), %%mm0\n" /* im0 | re0 */
+ "movq %%mm0, %%mm1\n" /* im0 | re0 */
+ "punpckldq %%mm0, %%mm0\n" /* re0 | re0 */
+ "punpckhdq %%mm1, %%mm1\n" /* im0 | im0 */
+
+ "movq (%%ecx), %%mm2\n" /* -s | c */
+ "movq 8(%%ecx), %%mm3\n" /* -c | -s */
+ "movq %%mm3, %%mm4\n"
+
+ "punpckhdq %%mm2,%%mm3\n" /* -s | -c */
+ "punpckldq %%mm2,%%mm4\n" /* c | -s */
+
+ "movq 8(%%eax), %%mm2\n" /* im1 | re1 */
+ "movq %%mm2, %%mm5\n" /* im1 | re1 */
+ "punpckldq %%mm2, %%mm2\n" /* re1 | re1 */
+ "punpckhdq %%mm5, %%mm5\n" /* im1 | im1 */
+
+ "pfmul %%mm3, %%mm0\n" /* -s * re0 | -c * re0 */
+ "pfmul %%mm4, %%mm1\n" /* c * im0 | -s * im0 */
+
+ "movq 16(%%ecx), %%mm6\n" /* -s1 | c1 */
+ "movq 24(%%ecx), %%mm7\n" /* -c1 | -s1 */
+ "movq %%mm7, %%mm4\n"
+
+ "punpckhdq %%mm6,%%mm7\n" /* -s1 | -c1 */
+ "punpckldq %%mm6,%%mm4\n" /* c1 | -s1 */
+
+ "pfmul %%mm7, %%mm2\n" /* -s1*re1 | -c1*re1 */
+ "pfmul %%mm4, %%mm5\n" /* c1*im1 | -s1*im1 */
+
+ "pfadd %%mm1, %%mm0\n" /* -s * re0 + c * im0 | -c * re0 - s * im0 */
+ "pfadd %%mm5, %%mm2\n" /* -s1 * re1 + c1 * im1 | -c1 * re1 - s1 * im1 */
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm2, 8(%%eax)\n"
+ "addl $32, %%ecx\n"
+ "addl $16, %%eax\n"
+ "decl %%ebx\n"
+ "jnz 0b\n"
+
+ "popl %%ebx\n"
+ "femms\n"
+ : "=a" (buf)
+ : "a" (buf), "c" (xcos_sin_sse) );
+}
+
+static void imdct512_window_delay_3dn (complex_t *buf, float *data_ptr, float *window_prt, float *delay_prt)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+
+ "pushl %%eax\n"
+ "pushl %%ebx\n"
+ "pushl %%ecx\n"
+ "pushl %%edx\n"
+ "pushl %%edi\n"
+ "pushl %%esi\n"
+ "pushl %%ebp\n"
+
+ "movl %%esi, %%ebp\n" /* buf */
+ "movl $32, %%ebx\n" /* loop count */
+ "leal 516(%%ebp), %%esi\n" /* buf[64].im */
+ "leal 504(%%ebp), %%edi\n" /* buf[63].re */
+
+
+ ".align 16\n"
+".first_128_samples:\n"
+ "movd (%%esi), %%mm0\n" /* im0 */
+ "movd 8(%%esi), %%mm2\n" /* im1 */
+ "movd (%%edi), %%mm1\n" /* re0 */
+ "movd -8(%%edi), %%mm3\n" /* re1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm0, %%mm4\n" /* -im0 */
+ "pfsub %%mm2, %%mm5\n" /* -im1 */
+
+ "punpckldq %%mm1, %%mm4\n" /* re0 | -im0 */
+ "punpckldq %%mm3, %%mm5\n" /* re1 | -im1 */
+
+ "movq (%%edx), %%mm0\n" /* w1 | w0 */
+ "movq 8(%%edx), %%mm1\n" /* w3 | w2 */
+ "movq (%%ecx), %%mm2\n" /* d1 | d0 */
+ "movq 8(%%ecx), %%mm3\n" /* d3 | d2 */
+
+ "pfmul %%mm4, %%mm0\n" /* w1*re0 | -w0*im0 */
+ "pfmul %%mm5, %%mm1\n" /* w3*re1 | -w2*im1 */
+
+ "pfadd %%mm2, %%mm0\n" /* w1*re0+d1 | -w0*im0+d0 */
+ "pfadd %%mm3, %%mm1\n" /* w3*re1+d3 | -w2*im1+d2 */
+
+ "addl $16, %%edx\n"
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 8(%%eax)\n"
+ "addl $16, %%ecx\n"
+ "addl $16, %%esi\n"
+ "addl $16, %%eax\n"
+ "addl $-16, %%edi\n"
+ "decl %%ebx\n"
+ "jnz .first_128_samples\n"
+
+ "movl %%ebp, %%esi\n" /* buf[0].re */
+ "movl $32, %%ebx\n" /* loop count */
+ "leal 1020(%%ebp), %%edi\n" /* buf[127].im */
+
+ ".align 16\n"
+".second_128_samples:\n"
+ "movd (%%esi), %%mm0\n" /* buf[i].re */
+ "movd 8(%%esi), %%mm2\n" /* re1 */
+ "movd (%%edi), %%mm1\n" /* buf[127-i].im */
+ "movd -8(%%edi), %%mm3\n" /* im1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm0, %%mm4\n" /* -re0 */
+ "pfsub %%mm2, %%mm5\n" /* -re1 */
+
+ "punpckldq %%mm1, %%mm4\n" /* im0 | -re0 */
+ "punpckldq %%mm3, %%mm5\n" /* im1 | -re1 */
+
+ "movq (%%edx), %%mm0\n" /* w1 | w0 */
+ "movq 8(%%edx), %%mm1\n" /* w3 | w2 */
+ "movq (%%ecx), %%mm2\n" /* d1 | d0 */
+ "movq 8(%%ecx), %%mm3\n" /* d3 | d2 */
+
+ "addl $16, %%esi\n"
+
+ "pfmul %%mm4, %%mm0\n" /* w1*im0 | -w0*re0 */
+ "pfmul %%mm5, %%mm1\n" /* w3*im1 | -w2*re1 */
+
+ "pfadd %%mm2, %%mm0\n" /* w1*im0+d1 | -w0*re0+d0 */
+ "pfadd %%mm3, %%mm1\n" /* w3*im1+d3 | -w2*re1+d2 */
+
+ "addl $-16, %%edi\n"
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 8(%%eax)\n"
+
+ "addl $16, %%edx\n"
+ "addl $16, %%eax\n"
+ "addl $16, %%ecx\n"
+ "decl %%ebx\n"
+ "jnz .second_128_samples\n"
+
+ "leal 512(%%ebp), %%esi\n" /* buf[64].re */
+ "leal 508(%%ebp), %%edi\n" /* buf[63].im */
+ "movl $32, %%ebx\n" /* loop count */
+ "addl $-1024, %%ecx\n" /* delay */
+
+ ".align 16\n"
+".first_128_delay:\n"
+ "movd (%%esi), %%mm0\n" /* re0 */
+ "movd 8(%%esi), %%mm2\n" /* re1 */
+ "movd (%%edi), %%mm1\n" /* im0 */
+ "movd -8(%%edi), %%mm3\n" /* im1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm0, %%mm4\n" /* -re0 */
+ "pfsub %%mm2, %%mm5\n" /* -re1 */
+
+ "punpckldq %%mm1, %%mm4\n" /* im0 | -re0 */
+ "punpckldq %%mm3, %%mm5\n" /* im1 | -re1 */
+
+
+ "movq -16(%%edx), %%mm1\n" /* w3 | w2 */
+ "movq -8(%%edx), %%mm0\n" /* w1 | w0 */
+
+ "addl $-16, %%edx\n"
+
+ "pfmul %%mm4, %%mm0\n" /* w1*im0 | -w0*re0 */
+ "pfmul %%mm5, %%mm1\n" /* w3*im1 | -w2*re1 */
+
+ "movq %%mm0, (%%ecx)\n"
+ "movq %%mm1, 8(%%ecx)\n"
+ "addl $16, %%esi\n"
+ "addl $-16, %%edi\n"
+ "addl $16, %%ecx\n"
+ "decl %%ebx\n"
+ "jnz .first_128_delay\n"
+
+ "leal 4(%%ebp), %%esi\n" /* buf[0].im */
+ "leal 1016(%%ebp), %%edi\n" /* buf[127].re */
+ "movl $32, %%ebx\n" /* loop count */
+
+ ".align 16\n"
+".second_128_delay:\n"
+ "movd (%%esi), %%mm0\n" /* im0 */
+ "movd 8(%%esi), %%mm2\n" /* im1 */
+ "movd (%%edi), %%mm1\n" /* re0 */
+ "movd -8(%%edi), %%mm3\n" /* re1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm1, %%mm4\n" /* -re0 */
+ "pfsub %%mm3, %%mm5\n" /* -re1 */
+
+ "punpckldq %%mm4, %%mm0\n" /* -re0 | im0 */
+ "punpckldq %%mm5, %%mm2\n" /* -re1 | im1 */
+
+
+ "movq -16(%%edx), %%mm1\n" /* w3 | w2 */
+ "movq -8(%%edx), %%mm3\n" /* w1 | w0 */
+
+ "addl $-16, %%edx\n"
+
+ "pfmul %%mm0, %%mm1\n" /* -w1*re0 | w0*im0 */
+ "pfmul %%mm2, %%mm3\n" /* -w3*re1 | w2*im1 */
+
+
+ "movq %%mm1, (%%ecx)\n"
+ "movq %%mm3, 8(%%ecx)\n"
+ "addl $16, %%esi\n"
+ "addl $-16, %%edi\n"
+ "addl $16, %%ecx\n"
+ "decl %%ebx\n"
+ "jnz .second_128_delay\n"
+
+ "popl %%ebp\n"
+ "popl %%esi\n"
+ "popl %%edi\n"
+ "popl %%edx\n"
+ "popl %%ecx\n"
+ "popl %%ebx\n"
+ "popl %%eax\n"
+
+ "femms\n"
+ : "=S" (buf), "=a" (data_ptr), "=c" (delay_prt), "=d" (window_prt)
+ : "S" (buf), "a" (data_ptr), "c" (delay_prt), "d" (window_prt));
+}
+
+static void imdct512_window_delay_nol_3dn (complex_t *buf, float *data_ptr, float *window_prt, float *delay_prt)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+
+ "pushl %%eax\n"
+ "pushl %%ebx\n"
+ "pushl %%ecx\n"
+ "pushl %%edx\n"
+ "pushl %%edi\n"
+ "pushl %%esi\n"
+ "pushl %%ebp\n"
+
+ "movl %%esi, %%ebp\n" /* buf */
+ "movl $32, %%ebx\n" /* loop count */
+ "leal 516(%%ebp), %%esi\n" /* buf[64].im */
+ "leal 504(%%ebp), %%edi\n" /* buf[63].re */
+
+ ".align 16\n"
+".first_128_samples2:\n"
+ "movd (%%esi), %%mm0\n" /* im0 */
+ "movd 8(%%esi), %%mm2\n" /* im1 */
+ "movd (%%edi), %%mm1\n" /* re0 */
+ "movd -8(%%edi), %%mm3\n" /* re1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm0, %%mm4\n" /* -im0 */
+ "pfsub %%mm2, %%mm5\n" /* -im1 */
+
+ "punpckldq %%mm1, %%mm4\n" /* re0 | -im0 */
+ "punpckldq %%mm3, %%mm5\n" /* re1 | -im1 */
+
+ "movq (%%edx), %%mm0\n" /* w1 | w0 */
+ "movq 8(%%edx), %%mm1\n" /* w3 | w2 */
+
+ "pfmul %%mm4, %%mm0\n" /* w1*re0 | -w0*im0 */
+ "pfmul %%mm5, %%mm1\n" /* w3*re1 | -w2*im1 */
+
+ "addl $16, %%edx\n"
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 8(%%eax)\n"
+ "addl $16, %%ecx\n"
+ "addl $16, %%esi\n"
+ "addl $16, %%eax\n"
+ "addl $-16, %%edi\n"
+ "decl %%ebx\n"
+ "jnz .first_128_samples2\n"
+
+ "movl %%ebp, %%esi\n" /* buf[0].re */
+ "movl $32, %%ebx\n" /* loop count */
+ "leal 1020(%%ebp), %%edi\n" /* buf[127].im */
+
+ ".align 16\n"
+".second_128_samples2:\n"
+ "movd (%%esi), %%mm0\n" /* buf[i].re */
+ "movd 8(%%esi), %%mm2\n" /* re1 */
+ "movd (%%edi), %%mm1\n" /* buf[127-i].im */
+ "movd -8(%%edi), %%mm3\n" /* im1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm0, %%mm4\n" /* -re0 */
+ "pfsub %%mm2, %%mm5\n" /* -re1 */
+
+ "punpckldq %%mm1, %%mm4\n" /* im0 | -re0 */
+ "punpckldq %%mm3, %%mm5\n" /* im1 | -re1 */
+
+ "movq (%%edx), %%mm0\n" /* w1 | w0 */
+ "movq 8(%%edx), %%mm1\n" /* w3 | w2 */
+
+ "addl $16, %%esi\n"
+
+ "pfmul %%mm4, %%mm0\n" /* w1*im0 | -w0*re0 */
+ "pfmul %%mm5, %%mm1\n" /* w3*im1 | -w2*re1 */
+
+ "addl $-16, %%edi\n"
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm1, 8(%%eax)\n"
+
+ "addl $16, %%edx\n"
+ "addl $16, %%eax\n"
+ "addl $16, %%ecx\n"
+ "decl %%ebx\n"
+ "jnz .second_128_samples2\n"
+
+ "leal 512(%%ebp), %%esi\n" /* buf[64].re */
+ "leal 508(%%ebp), %%edi\n" /* buf[63].im */
+ "movl $32, %%ebx\n" /* loop count */
+ "addl $-1024, %%ecx\n" /* delay */
+
+ ".align 16\n"
+".first_128_delays:\n"
+ "movd (%%esi), %%mm0\n" /* re0 */
+ "movd 8(%%esi), %%mm2\n" /* re1 */
+ "movd (%%edi), %%mm1\n" /* im0 */
+ "movd -8(%%edi), %%mm3\n" /* im1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm0, %%mm4\n" /* -re0 */
+ "pfsub %%mm2, %%mm5\n" /* -re1 */
+
+ "punpckldq %%mm1, %%mm4\n" /* im0 | -re0 */
+ "punpckldq %%mm3, %%mm5\n" /* im1 | -re1 */
+
+
+ "movq -16(%%edx), %%mm1\n" /* w3 | w2 */
+ "movq -8(%%edx), %%mm0\n" /* w1 | w0 */
+
+ "addl $-16, %%edx\n"
+
+ "pfmul %%mm4, %%mm0\n" /* w1*im0 | -w0*re0 */
+ "pfmul %%mm5, %%mm1\n" /* w3*im1 | -w2*re1 */
+
+
+ "movq %%mm0, (%%ecx)\n"
+ "movq %%mm1, 8(%%ecx)\n"
+ "addl $16, %%esi\n"
+ "addl $-16, %%edi\n"
+ "addl $16, %%ecx\n"
+ "decl %%ebx\n"
+ "jnz .first_128_delays\n"
+
+ "leal 4(%%ebp), %%esi\n" /* buf[0].im */
+ "leal 1016(%%ebp), %%edi\n" /* buf[127].re */
+ "movl $32, %%ebx\n" /* loop count */
+
+ ".align 16\n"
+".second_128_delays:\n"
+ "movd (%%esi), %%mm0\n" /* im0 */
+ "movd 8(%%esi), %%mm2\n" /* im1 */
+ "movd (%%edi), %%mm1\n" /* re0 */
+ "movd -8(%%edi), %%mm3\n" /* re1 */
+
+ "pxor %%mm4, %%mm4\n"
+ "pxor %%mm5, %%mm5\n"
+ "pfsub %%mm1, %%mm4\n" /* -re0 */
+ "pfsub %%mm3, %%mm5\n" /* -re1 */
+
+ "punpckldq %%mm4, %%mm0\n" /* -re0 | im0 */
+ "punpckldq %%mm5, %%mm2\n" /* -re1 | im1 */
+
+
+ "movq -16(%%edx), %%mm1\n" /* w3 | w2 */
+ "movq -8(%%edx), %%mm3\n" /* w1 | w0 */
+
+ "addl $-16, %%edx\n"
+
+ "pfmul %%mm0, %%mm1\n" /* -w1*re0 | w0*im0 */
+ "pfmul %%mm2, %%mm3\n" /* -w3*re1 | w2*im1 */
+
+
+ "movq %%mm1, (%%ecx)\n"
+ "movq %%mm3, 8(%%ecx)\n"
+ "addl $16, %%esi\n"
+ "addl $-16, %%edi\n"
+ "addl $16, %%ecx\n"
+ "decl %%ebx\n"
+ "jnz .second_128_delays\n"
+
+ "popl %%ebp\n"
+ "popl %%esi\n"
+ "popl %%edi\n"
+ "popl %%edx\n"
+ "popl %%ecx\n"
+ "popl %%ebx\n"
+ "popl %%eax\n"
+
+ "femms\n"
+ : "=S" (buf), "=a" (data_ptr), "=c" (delay_prt), "=d" (window_prt)
+ : "S" (buf), "a" (data_ptr), "c" (delay_prt), "d" (window_prt));
+}
+
--- /dev/null
+/*****************************************************************************
+ * imdct_c.c: A52 DCT in C
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: imdct_c.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy() */
+
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "imdct_common.h"
+#include "retables.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+void E_( fft_64p ) ( complex_t *x );
+void E_( fft_128p ) ( complex_t *x );
+
+void E_( imdct_init ) (imdct_t * p_imdct)
+{
+ int i;
+ float scale = 181.019;
+
+ /* Twiddle factors to turn IFFT into IMDCT */
+ for (i=0; i < 128; i++) {
+ p_imdct->xcos1[i] = cos(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ p_imdct->xsin1[i] = sin(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ }
+}
+
+void E_( imdct_do_512 ) (imdct_t * p_imdct, float data[], float delay[])
+{
+ int i, j;
+ float tmp_a_r, tmp_a_i;
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ /* 512 IMDCT with source and dest data in 'data'
+ * Pre IFFT complex multiply plus IFFT complex conjugate */
+
+ for( i=0; i < 128; i++) {
+ j = pm128[i];
+ /* a = (data[256-2*j-1] - data[2*j]) * (xcos1[j] + xsin1[j]);
+ * c = data[2*j] * xcos1[j];
+ * b = data[256-2*j-1] * xsin1[j];
+ * buf1[i].real = a - b + c;
+ * buf1[i].imag = b + c; */
+ p_imdct->buf[i].real = (data[256-2*j-1] * p_imdct->xcos1[j]) - (data[2*j] * p_imdct->xsin1[j]);
+ p_imdct->buf[i].imag = -1.0 * (data[2*j] * p_imdct->xcos1[j] + data[256-2*j-1] * p_imdct->xsin1[j]);
+ }
+
+ E_( fft_128p ) ( &p_imdct->buf[0] );
+
+ /* Post IFFT complex multiply plus IFFT complex conjugate */
+ for (i=0; i < 128; i++) {
+ tmp_a_r = p_imdct->buf[i].real;
+ tmp_a_i = p_imdct->buf[i].imag;
+ /* a = (tmp_a_r - tmp_a_i) * (xcos1[j] + xsin1[j]);
+ * b = tmp_a_r * xsin1[j];
+ * c = tmp_a_i * xcos1[j];
+ * buf[j].real = a - b + c;
+ * buf[j].imag = b + c; */
+ p_imdct->buf[i].real =(tmp_a_r * p_imdct->xcos1[i]) + (tmp_a_i * p_imdct->xsin1[i]);
+ p_imdct->buf[i].imag =(tmp_a_r * p_imdct->xsin1[i]) - (tmp_a_i * p_imdct->xcos1[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+ /* Window and convert to real valued signal */
+ for (i=0; i< 64; i++) {
+ *data_ptr++ = -p_imdct->buf[64+i].imag * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = p_imdct->buf[64-i-1].real * *window_ptr++ + *delay_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -p_imdct->buf[i].real * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = p_imdct->buf[128-i-1].imag * *window_ptr++ + *delay_ptr++;
+ }
+
+ /* The trailing edge of the window goes into the delay line */
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -p_imdct->buf[64+i].real * *--window_ptr;
+ *delay_ptr++ = p_imdct->buf[64-i-1].imag * *--window_ptr;
+ }
+
+ for(i=0; i<64; i++) {
+ *delay_ptr++ = p_imdct->buf[i].imag * *--window_ptr;
+ *delay_ptr++ = -p_imdct->buf[128-i-1].real * *--window_ptr;
+ }
+}
+
+
+void E_( imdct_do_512_nol ) (imdct_t * p_imdct, float data[], float delay[])
+{
+ int i, j;
+
+ float tmp_a_i;
+ float tmp_a_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ /* 512 IMDCT with source and dest data in 'data'
+ * Pre IFFT complex multiply plus IFFT cmplx conjugate */
+
+ for( i=0; i < 128; i++) {
+ /* z[i] = (X[256-2*i-1] + j * X[2*i]) * (xcos1[i] + j * xsin1[i]) */
+ j = pm128[i];
+ /* a = (data[256-2*j-1] - data[2*j]) * (xcos1[j] + xsin1[j]);
+ * c = data[2*j] * xcos1[j];
+ * b = data[256-2*j-1] * xsin1[j];
+ * buf1[i].real = a - b + c;
+ * buf1[i].imag = b + c; */
+ p_imdct->buf[i].real = (data[256-2*j-1] * p_imdct->xcos1[j]) - (data[2*j] * p_imdct->xsin1[j]);
+ p_imdct->buf[i].imag = -1.0 * (data[2*j] * p_imdct->xcos1[j] + data[256-2*j-1] * p_imdct->xsin1[j]);
+ }
+
+ E_( fft_128p ) ( &p_imdct->buf[0] );
+
+ /* Post IFFT complex multiply plus IFFT complex conjugate*/
+ for (i=0; i < 128; i++) {
+ /* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ;
+ * int j1 = i; */
+ tmp_a_r = p_imdct->buf[i].real;
+ tmp_a_i = p_imdct->buf[i].imag;
+ /* a = (tmp_a_r - tmp_a_i) * (xcos1[j] + xsin1[j]);
+ * b = tmp_a_r * xsin1[j];
+ * c = tmp_a_i * xcos1[j];
+ * buf[j].real = a - b + c;
+ * buf[j].imag = b + c; */
+ p_imdct->buf[i].real =(tmp_a_r * p_imdct->xcos1[i]) + (tmp_a_i * p_imdct->xsin1[i]);
+ p_imdct->buf[i].imag =(tmp_a_r * p_imdct->xsin1[i]) - (tmp_a_i * p_imdct->xcos1[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+ /* Window and convert to real valued signal, no overlap here*/
+ for (i=0; i< 64; i++) {
+ *data_ptr++ = -p_imdct->buf[64+i].imag * *window_ptr++;
+ *data_ptr++ = p_imdct->buf[64-i-1].real * *window_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -p_imdct->buf[i].real * *window_ptr++;
+ *data_ptr++ = p_imdct->buf[128-i-1].imag * *window_ptr++;
+ }
+
+ /* The trailing edge of the window goes into the delay line */
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -p_imdct->buf[64+i].real * *--window_ptr;
+ *delay_ptr++ = p_imdct->buf[64-i-1].imag * *--window_ptr;
+ }
+
+ for(i=0; i<64; i++) {
+ *delay_ptr++ = p_imdct->buf[i].imag * *--window_ptr;
+ *delay_ptr++ = -p_imdct->buf[128-i-1].real * *--window_ptr;
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * imdct_common.c: common A52 DCT functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: imdct_common.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "retables.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+void E_( fft_64p ) ( complex_t *x );
+
+void E_( imdct_do_256 ) (imdct_t * p_imdct, float data[],float delay[])
+{
+ int i, j, k;
+ int p, q;
+
+ float tmp_a_i;
+ float tmp_a_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ complex_t *buf1, *buf2;
+
+ buf1 = &p_imdct->buf[0];
+ buf2 = &p_imdct->buf[64];
+
+ /* Pre IFFT complex multiply plus IFFT complex conjugate */
+ for (k=0; k<64; k++) {
+ /* X1[k] = X[2*k]
+ * X2[k] = X[2*k+1] */
+
+ j = pm64[k];
+ p = 2 * (128-2*j-1);
+ q = 2 * (2 * j);
+
+ /* Z1[k] = (X1[128-2*k-1] + j * X1[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf1[k].real = data[p] * p_imdct->xcos2[j] - data[q] * p_imdct->xsin2[j];
+ buf1[k].imag = -1.0f*(data[q] * p_imdct->xcos2[j] + data[p] * p_imdct->xsin2[j]);
+ /* Z2[k] = (X2[128-2*k-1] + j * X2[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf2[k].real = data[p + 1] * p_imdct->xcos2[j] - data[q + 1] * p_imdct->xsin2[j];
+ buf2[k].imag = -1.0f*(data[q + 1] * p_imdct->xcos2[j] + data[p + 1] * p_imdct->xsin2[j]);
+ }
+
+ E_( fft_64p ) ( &buf1[0] );
+ E_( fft_64p ) ( &buf2[0] );
+
+ /* Post IFFT complex multiply */
+ for( i=0; i < 64; i++) {
+ tmp_a_r = buf1[i].real;
+ tmp_a_i = -buf1[i].imag;
+ buf1[i].real = (tmp_a_r * p_imdct->xcos2[i]) - (tmp_a_i * p_imdct->xsin2[i]);
+ buf1[i].imag = (tmp_a_r * p_imdct->xsin2[i]) + (tmp_a_i * p_imdct->xcos2[i]);
+ tmp_a_r = buf2[i].real;
+ tmp_a_i = -buf2[i].imag;
+ buf2[i].real = (tmp_a_r * p_imdct->xcos2[i]) - (tmp_a_i * p_imdct->xsin2[i]);
+ buf2[i].imag = (tmp_a_r * p_imdct->xsin2[i]) + (tmp_a_i * p_imdct->xcos2[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+ /* Window and convert to real valued signal */
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].imag * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf1[64-i-1].real * *window_ptr++ + *delay_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].real * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf1[64-i-1].imag * *window_ptr++ + *delay_ptr++;
+ }
+
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf2[i].real * *--window_ptr;
+ *delay_ptr++ = buf2[64-i-1].imag * *--window_ptr;
+ }
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = buf2[i].imag * *--window_ptr;
+ *delay_ptr++ = -buf2[64-i-1].real * *--window_ptr;
+ }
+}
+
+
+void E_( imdct_do_256_nol ) (imdct_t * p_imdct, float data[], float delay[])
+{
+ int i, j, k;
+ int p, q;
+
+ float tmp_a_i;
+ float tmp_a_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ complex_t *buf1, *buf2;
+
+ buf1 = &p_imdct->buf[0];
+ buf2 = &p_imdct->buf[64];
+
+ /* Pre IFFT complex multiply plus IFFT cmplx conjugate */
+ for(k=0; k<64; k++) {
+ /* X1[k] = X[2*k]
+ * X2[k] = X[2*k+1] */
+ j = pm64[k];
+ p = 2 * (128-2*j-1);
+ q = 2 * (2 * j);
+
+ /* Z1[k] = (X1[128-2*k-1] + j * X1[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf1[k].real = data[p] * p_imdct->xcos2[j] - data[q] * p_imdct->xsin2[j];
+ buf1[k].imag = -1.0f*(data[q] * p_imdct->xcos2[j] + data[p] * p_imdct->xsin2[j]);
+ /* Z2[k] = (X2[128-2*k-1] + j * X2[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf2[k].real = data[p + 1] * p_imdct->xcos2[j] - data[q + 1] * p_imdct->xsin2[j];
+ buf2[k].imag = -1.0f*(data[q + 1] * p_imdct->xcos2[j] + data[p + 1] * p_imdct->xsin2[j]);
+ }
+
+ E_( fft_64p ) ( &buf1[0] );
+ E_( fft_64p ) ( &buf2[0] );
+
+ /* Post IFFT complex multiply */
+ for( i=0; i < 64; i++) {
+ /* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */
+ tmp_a_r = buf1[i].real;
+ tmp_a_i = -buf1[i].imag;
+ buf1[i].real =(tmp_a_r * p_imdct->xcos2[i]) - (tmp_a_i * p_imdct->xsin2[i]);
+ buf1[i].imag =(tmp_a_r * p_imdct->xsin2[i]) + (tmp_a_i * p_imdct->xcos2[i]);
+ /* y2[n] = z2[n] * (xcos2[n] + j * xsin2[n]) ; */
+ tmp_a_r = buf2[i].real;
+ tmp_a_i = -buf2[i].imag;
+ buf2[i].real =(tmp_a_r * p_imdct->xcos2[i]) - (tmp_a_i * p_imdct->xsin2[i]);
+ buf2[i].imag =(tmp_a_r * p_imdct->xsin2[i]) + (tmp_a_i * p_imdct->xcos2[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+ /* Window and convert to real valued signal, no overlap */
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].imag * *window_ptr++;
+ *data_ptr++ = buf1[64-i-1].real * *window_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].real * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf1[64-i-1].imag * *window_ptr++ + *delay_ptr++;
+ }
+
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf2[i].real * *--window_ptr;
+ *delay_ptr++ = buf2[64-i-1].imag * *--window_ptr;
+ }
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = buf2[i].imag * *--window_ptr;
+ *delay_ptr++ = -buf2[64-i-1].real * *--window_ptr;
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * imdct_common.h: common A52 DCT headers
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: imdct_common.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+void E_( imdct_init ) ( imdct_t * p_imdct );
+void E_( imdct_do_256 ) ( imdct_t * p_imdct, float data[], float delay[] );
+void E_( imdct_do_256_nol ) ( imdct_t * p_imdct, float data[], float delay[] );
+void E_( imdct_do_512 ) ( imdct_t * p_imdct, float data[], float delay[] );
+void E_( imdct_do_512_nol ) ( imdct_t * p_imdct, float data[], float delay[] );
--- /dev/null
+/*****************************************************************************
+ * imdct_sse.c: accelerated SSE A52 DCT
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: imdct_sse.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "imdct_common.h"
+#include "retables.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+void E_( fft_64p ) ( complex_t *x );
+void E_( fft_128p ) ( complex_t *a );
+
+static void imdct512_pre_ifft_twiddle_sse ( const int *, complex_t *,
+ float *, float * );
+static void imdct512_post_ifft_twiddle_sse ( complex_t *, float * );
+static void imdct512_window_delay_sse ( complex_t *, float *,
+ float *, float * );
+static void imdct512_window_delay_nol_sse ( complex_t *, float *,
+ float *, float * );
+
+void E_( imdct_init ) (imdct_t * p_imdct)
+{
+ int i;
+ float scale = 181.019;
+
+ for (i=0; i < 128; i++)
+ {
+ float xcos_i = cos(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ float xsin_i = sin(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ p_imdct->xcos_sin_sse[i * 4] = xcos_i;
+ p_imdct->xcos_sin_sse[i * 4 + 1] = -xsin_i;
+ p_imdct->xcos_sin_sse[i * 4 + 2] = -xsin_i;
+ p_imdct->xcos_sin_sse[i * 4 + 3] = -xcos_i;
+ }
+}
+
+void E_( imdct_do_512 ) (imdct_t * p_imdct, float data[], float delay[])
+{
+ imdct512_pre_ifft_twiddle_sse( pm128, p_imdct->buf, data,
+ p_imdct->xcos_sin_sse );
+ E_( fft_128p ) ( p_imdct->buf );
+ imdct512_post_ifft_twiddle_sse( p_imdct->buf, p_imdct->xcos_sin_sse );
+ imdct512_window_delay_sse( p_imdct->buf, data, window, delay );
+}
+
+
+void E_( imdct_do_512_nol ) (imdct_t * p_imdct, float data[], float delay[])
+{
+ imdct512_pre_ifft_twiddle_sse( pm128, p_imdct->buf, data,
+ p_imdct->xcos_sin_sse );
+ E_( fft_128p ) ( p_imdct->buf );
+ imdct512_post_ifft_twiddle_sse( p_imdct->buf, p_imdct->xcos_sin_sse );
+ imdct512_window_delay_nol_sse( p_imdct->buf, data, window, delay );
+}
+
+static void imdct512_pre_ifft_twiddle_sse (const int *pmt, complex_t *buf, float *data, float *xcos_sin_sse)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebp\n"
+ "movl %%esp, %%ebp\n"
+ "addl $-4, %%esp\n" /* local variable, loop counter */
+
+ "pushl %%eax\n"
+ "pushl %%ebx\n"
+ "pushl %%ecx\n"
+ "pushl %%edx\n"
+ "pushl %%edi\n"
+ "pushl %%esi\n"
+
+ "movl %%edi, %%ebx\n" /* buf */
+ "movl $64, -4(%%ebp)\n"
+
+ ".align 16\n"
+"0:\n"
+ "movl (%%eax), %%esi\n"
+ "movl 4(%%eax), %%edi\n"
+ "movss (%%ecx, %%esi, 8), %%xmm1\n" /* 2j */
+ "movss (%%ecx, %%edi, 8), %%xmm3\n" /* 2(j+1) */
+
+ "shll $1, %%esi\n"
+ "shll $1, %%edi\n"
+
+ "movaps (%%edx, %%esi, 8), %%xmm0\n" /* -c_j | -s_j | -s_j | c_j */
+ "movaps (%%edx, %%edi, 8), %%xmm2\n" /* -c_j+1 | -s_j+1 | -s_j+1 | c_j+1 */
+
+ "negl %%esi\n"
+ "negl %%edi\n"
+
+ "movss 1020(%%ecx, %%esi, 4), %%xmm4\n" /* 255-2j */
+ "addl $8, %%eax\n"
+ "movss 1020(%%ecx, %%edi, 4), %%xmm5\n" /* 255-2(j+1) */
+
+ "shufps $0, %%xmm1, %%xmm4\n" /* 2j | 2j | 255-2j | 255-2j */
+ "shufps $0, %%xmm3, %%xmm5\n" /* 2(j+1) | 2(j+1) | 255-2(j+1) | 255-2(j+1) */
+ "mulps %%xmm4, %%xmm0\n"
+ "mulps %%xmm5, %%xmm2\n"
+ "movhlps %%xmm0, %%xmm1\n"
+ "movhlps %%xmm2, %%xmm3\n"
+ "addl $16, %%ebx\n"
+ "addps %%xmm1, %%xmm0\n"
+ "addps %%xmm3, %%xmm2\n"
+ "movlhps %%xmm2, %%xmm0\n"
+
+ "movaps %%xmm0, -16(%%ebx)\n"
+ "decl -4(%%ebp)\n"
+ "jnz 0b\n"
+
+ "popl %%esi\n"
+ "popl %%edi\n"
+ "popl %%edx\n"
+ "popl %%ecx\n"
+ "popl %%ebx\n"
+ "popl %%eax\n"
+
+ "addl $4, %%esp\n"
+ "popl %%ebp\n"
+ : "=D" (buf)
+ : "a" (pmt), "c" (data), "d" (xcos_sin_sse), "D" (buf));
+
+}
+
+static void imdct512_post_ifft_twiddle_sse (complex_t *buf, float *xcos_sin_sse)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebx\n"
+ "movl $32, %%ebx\n" /* loop counter */
+
+ ".align 16\n"
+"0:\n"
+ "movaps (%%eax), %%xmm0\n" /* im1 | re1 | im0 | re0 */
+
+ "movaps (%%ecx), %%xmm2\n" /* -c | -s | -s | c */
+ "movhlps %%xmm0, %%xmm1\n" /* im1 | re1 */
+ "movaps 16(%%ecx), %%xmm3\n" /* -c1 | -s1 | -s1 | c1 */
+
+ "shufps $0x50, %%xmm0, %%xmm0\n" /* im0 | im0 | re0 | re0 */
+ "shufps $0x50, %%xmm1, %%xmm1\n" /* im1 | im1 | re1 | re1 */
+
+ "movaps 16(%%eax), %%xmm4\n" /* im3 | re3 | im2 | re2 */
+
+ "shufps $0x27, %%xmm2, %%xmm2\n" /* c | -s | -s | -c */
+ "movhlps %%xmm4, %%xmm5\n" /* im3 | re3 */
+ "shufps $0x27, %%xmm3, %%xmm3\n" /* c1 | -s1 | -s1 | -c1 */
+
+ "movaps 32(%%ecx), %%xmm6\n" /* -c2 | -s2 | -s2 | c2 */
+ "movaps 48(%%ecx), %%xmm7\n" /* -c3 | -s3 | -s3 | c3 */
+
+ "shufps $0x50, %%xmm4, %%xmm4\n" /* im2 | im2 | re2 | re2 */
+ "shufps $0x50, %%xmm5, %%xmm5\n" /* im3 | im3 | re3 | re3 */
+
+ "mulps %%xmm2, %%xmm0\n"
+ "mulps %%xmm3, %%xmm1\n"
+
+ "shufps $0x27, %%xmm6, %%xmm6\n" /* c2 | -s2 | -s2 | -c2 */
+ "shufps $0x27, %%xmm7, %%xmm7\n" /* c3 | -s3 | -s3 | -c3 */
+
+ "movhlps %%xmm0, %%xmm2\n"
+ "movhlps %%xmm1, %%xmm3\n"
+
+ "mulps %%xmm6, %%xmm4\n"
+ "mulps %%xmm7, %%xmm5\n"
+
+ "addps %%xmm2, %%xmm0\n"
+ "addps %%xmm3, %%xmm1\n"
+
+ "movhlps %%xmm4, %%xmm6\n"
+ "movhlps %%xmm5, %%xmm7\n"
+
+ "addps %%xmm6, %%xmm4\n"
+ "addps %%xmm7, %%xmm5\n"
+
+ "movlhps %%xmm1, %%xmm0\n"
+ "movlhps %%xmm5, %%xmm4\n"
+
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm4, 16(%%eax)\n"
+ "addl $64, %%ecx\n"
+ "addl $32, %%eax\n"
+ "decl %%ebx\n"
+ "jnz 0b\n"
+
+ "popl %%ebx\n"
+ : "=a" (buf)
+ : "a" (buf), "c" (xcos_sin_sse) );
+}
+
+static void imdct512_window_delay_sse (complex_t *buf, float *data_ptr, float *window_prt, float *delay_prt)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+
+ "pushl %%eax\n"
+ "pushl %%ebx\n"
+ "pushl %%ecx\n"
+ "pushl %%edx\n"
+ "pushl %%edi\n"
+ "pushl %%esi\n"
+ "pushl %%ebp\n"
+
+ "movl %%esi, %%ebp\n" /* buf */
+ "movl $16, %%ebx\n" /* loop count */
+ "leal 516(%%ebp), %%esi\n" /* buf[64].im */
+ "leal 504(%%ebp), %%edi\n" /* buf[63].re */
+
+ ".align 16\n"
+".first_128_samples:\n"
+ "movss (%%esi), %%xmm0\n"
+ "movss 8(%%esi), %%xmm2\n"
+ "movss (%%edi), %%xmm1\n"
+ "movss -8(%%edi), %%xmm3\n"
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | im1 | 0.0 | im0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | re1 | 0.0 | re0 */
+
+ "movaps (%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+ "movaps (%%ecx), %%xmm5\n" /* d3 | d2 | d1 | d0 */
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* re1 | 0.0 | re0 | 0.0 */
+
+ "movss 16(%%esi), %%xmm6\n" /* im2 */
+ "movss 24(%%esi), %%xmm7\n" /* im3 */
+ "subps %%xmm1, %%xmm0\n" /* -re1 | im1 | -re0 | im0 */
+ "movss -16(%%edi), %%xmm2\n" /* re2 */
+ "movss -24(%%edi), %%xmm3\n" /* re3 */
+ "mulps %%xmm4, %%xmm0\n"
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | im3 | 0.0 | im2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | re3 | 0.0 | re2 */
+ "addps %%xmm5, %%xmm0\n"
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* re3 | 0.0 | re2 | 0.0 */
+ "movaps 16(%%edx), %%xmm4\n" /* w7 | w6 | w5 | w4 */
+ "movaps 16(%%ecx), %%xmm5\n" /* d7 | d6 | d5 | d4 */
+ "subps %%xmm2, %%xmm6\n" /* -re3 | im3 | -re2 | im2 */
+ "addl $32, %%edx\n"
+ "movaps %%xmm0, (%%eax)\n"
+ "addl $32, %%ecx\n"
+ "mulps %%xmm4, %%xmm6\n"
+ "addl $32, %%esi\n"
+ "addl $32, %%eax\n"
+ "addps %%xmm5, %%xmm6\n"
+ "addl $-32, %%edi\n"
+ "movaps %%xmm6, -16(%%eax)\n"
+ "decl %%ebx\n"
+ "jnz .first_128_samples\n"
+
+ "movl %%ebp, %%esi\n" /* buf[0].re */
+ "movl $16, %%ebx\n" /* loop count */
+ "leal 1020(%%ebp), %%edi\n" /* buf[127].im */
+
+ ".align 16\n"
+".second_128_samples:\n"
+ "movss (%%esi), %%xmm0\n" /* buf[i].re */
+ "movss 8(%%esi), %%xmm2\n" /* re1 */
+ "movss (%%edi), %%xmm1\n" /* buf[127-i].im */
+ "movss -8(%%edi), %%xmm3\n" /* im1 */
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | re1 | 0.0 | re0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | im1 | 0.0 | im1 */
+
+ "movaps (%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+ "movaps (%%ecx), %%xmm5\n" /* d3 | d2 | d1 | d0 */
+
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* im1 | 0.0 | im0 | 0.0 */
+ "movss 16(%%esi), %%xmm6\n" /* re2 */
+ "movss 24(%%esi), %%xmm7\n" /* re3 */
+ "movss -16(%%edi), %%xmm2\n" /* im2 */
+ "movss -24(%%edi), %%xmm3\n" /* im3 */
+ "subps %%xmm1, %%xmm0\n" /* -im1 | re1 | -im0 | re0 */
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | re3 | 0.0 | re2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | im3 | 0.0 | im2 */
+ "mulps %%xmm4, %%xmm0\n"
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* im3 | 0.0 | im2 | 0.0 */
+ "movaps 16(%%edx), %%xmm4\n" /* w7 | w6 | w5 | w4 */
+ "addl $32, %%esi\n"
+ "subps %%xmm2, %%xmm6\n" /* -im3 | re3 | -im2 | re2 */
+ "addps %%xmm5, %%xmm0\n"
+ "mulps %%xmm4, %%xmm6\n"
+ "addl $-32, %%edi\n"
+ "movaps 16(%%ecx), %%xmm5\n" /* d7 | d6 | d5 | d4 */
+ "movaps %%xmm0, (%%eax)\n"
+ "addps %%xmm5, %%xmm6\n"
+ "addl $32, %%edx\n"
+ "addl $32, %%eax\n"
+ "addl $32, %%ecx\n"
+ "movaps %%xmm6, -16(%%eax)\n"
+ "decl %%ebx\n"
+ "jnz .second_128_samples\n"
+
+ "leal 512(%%ebp), %%esi\n" /* buf[64].re */
+ "leal 508(%%ebp), %%edi\n" /* buf[63].im */
+ "movl $16, %%ebx\n" /* loop count */
+ "addl $-1024, %%ecx\n" /* delay */
+
+ ".align 16\n"
+".first_128_delay:\n"
+ "movss (%%esi), %%xmm0\n"
+ "movss 8(%%esi), %%xmm2\n"
+ "movss (%%edi), %%xmm1\n"
+ "movss -8(%%edi), %%xmm3\n"
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | re1 | 0.0 | re0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | im1 | 0.0 | im0 */
+
+ "movaps -16(%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* im1 | 0.0 | im0 | 0.0 */
+ "movss 16(%%esi), %%xmm6\n" /* re2 */
+ "movss 24(%%esi), %%xmm7\n" /* re3 */
+ "movss -16(%%edi), %%xmm2\n" /* im2 */
+ "movss -24(%%edi), %%xmm3\n" /* im3 */
+ "subps %%xmm1, %%xmm0\n" /* -im1 | re1 | -im0 | re0 */
+ "addl $-32, %%edx\n"
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | re3 | 0.0 | re2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | im3 | 0.0 | im2 */
+ "mulps %%xmm4, %%xmm0\n"
+ "movaps (%%edx), %%xmm5\n" /* w7 | w6 | w5 | w4 */
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* im3 | 0.0 | im2 | 0.0 */
+ "movaps %%xmm0, (%%ecx)\n"
+ "addl $32, %%esi\n"
+ "subps %%xmm2, %%xmm6\n" /* -im3 | re3 | -im2 | re2 */
+ "addl $-32, %%edi\n"
+ "mulps %%xmm5, %%xmm6\n"
+ "addl $32, %%ecx\n"
+ "movaps %%xmm6, -16(%%ecx)\n"
+ "decl %%ebx\n"
+ "jnz .first_128_delay\n"
+
+ "leal 4(%%ebp), %%esi\n" /* buf[0].im */
+ "leal 1016(%%ebp), %%edi\n" /* buf[127].re */
+ "movl $16, %%ebx\n" /* loop count */
+
+ ".align 16\n"
+".second_128_delay:\n"
+ "movss (%%esi), %%xmm0\n"
+ "movss 8(%%esi), %%xmm2\n"
+ "movss (%%edi), %%xmm1\n"
+ "movss -8(%%edi), %%xmm3\n"
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | im1 | 0.0 | im0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | re1 | 0.0 | re0 */
+
+ "movaps -16(%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* re1 | 0.0 | re0 | 0.0 */
+ "movss 16(%%esi), %%xmm6\n" /* im2 */
+ "movss 24(%%esi), %%xmm7\n" /* im3 */
+ "movss -16(%%edi), %%xmm2\n" /* re2 */
+ "movss -24(%%edi), %%xmm3\n" /* re3 */
+ "subps %%xmm0, %%xmm1\n" /* re1 | -im1 | re0 | -im0 */
+ "addl $-32, %%edx\n"
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | im3 | 0.0 | im2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | re3 | 0.0 | re2 */
+ "mulps %%xmm4, %%xmm1\n"
+ "movaps (%%edx), %%xmm5\n" /* w7 | w6 | w5 | w4 */
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* re3 | 0.0 | re2 | 0.0 */
+ "movaps %%xmm1, (%%ecx)\n"
+ "addl $32, %%esi\n"
+ "subps %%xmm6, %%xmm2\n" /* re | -im3 | re | -im2 */
+ "addl $-32, %%edi\n"
+ "mulps %%xmm5, %%xmm2\n"
+ "addl $32, %%ecx\n"
+ "movaps %%xmm2, -16(%%ecx)\n"
+ "decl %%ebx\n"
+ "jnz .second_128_delay\n"
+
+ "popl %%ebp\n"
+ "popl %%esi\n"
+ "popl %%edi\n"
+ "popl %%edx\n"
+ "popl %%ecx\n"
+ "popl %%ebx\n"
+ "popl %%eax\n"
+ : "=S" (buf), "=a" (data_ptr), "=c" (delay_prt), "=d" (window_prt)
+ : "S" (buf), "a" (data_ptr), "c" (delay_prt), "d" (window_prt));
+
+}
+
+static void imdct512_window_delay_nol_sse( complex_t *buf, float *data_ptr,
+ float *window_prt, float *delay_prt )
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+
+ "pushl %%eax\n"
+ "pushl %%ebx\n"
+ "pushl %%ecx\n"
+ "pushl %%edx\n"
+ "pushl %%edi\n"
+ "pushl %%esi\n"
+ "pushl %%ebp\n"
+
+ "movl %%esi, %%ebp\n" /* buf */
+ "movl $16, %%ebx\n" /* loop count */
+ "leal 516(%%ebp), %%esi\n" /* buf[64].im */
+ "leal 504(%%ebp), %%edi\n" /* buf[63].re */
+
+ ".align 16\n"
+".first_128_sample:\n"
+ "movss (%%esi), %%xmm0\n"
+ "movss 8(%%esi), %%xmm2\n"
+ "movss (%%edi), %%xmm1\n"
+ "movss -8(%%edi), %%xmm3\n"
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | im1 | 0.0 | im0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | re1 | 0.0 | re0 */
+
+ "movaps (%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* re1 | 0.0 | re0 | 0.0 */
+
+ "movss 16(%%esi), %%xmm6\n" /* im2 */
+ "movss 24(%%esi), %%xmm7\n" /* im3 */
+ "subps %%xmm1, %%xmm0\n" /* -re1 | im1 | -re0 | im0 */
+ "movss -16(%%edi), %%xmm2\n" /* re2 */
+ "movss -24(%%edi), %%xmm3\n" /* re3 */
+ "mulps %%xmm4, %%xmm0\n"
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | im3 | 0.0 | im2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | re3 | 0.0 | re2 */
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* re3 | 0.0 | re2 | 0.0 */
+ "movaps 16(%%edx), %%xmm4\n" /* w7 | w6 | w5 | w4 */
+ "subps %%xmm2, %%xmm6\n" /* -re3 | im3 | -re2 | im2 */
+ "addl $32, %%edx\n"
+ "movaps %%xmm0, (%%eax)\n"
+ "mulps %%xmm4, %%xmm6\n"
+ "addl $32, %%esi\n"
+ "addl $32, %%eax\n"
+ "addl $-32, %%edi\n"
+ "movaps %%xmm6, -16(%%eax)\n"
+ "decl %%ebx\n"
+ "jnz .first_128_sample\n"
+
+ "movl %%ebp, %%esi\n" /* buf[0].re */
+ "movl $16, %%ebx\n" /* loop count */
+ "leal 1020(%%ebp), %%edi\n" /* buf[127].im */
+
+ ".align 16\n"
+".second_128_sample:\n"
+ "movss (%%esi), %%xmm0\n" /* buf[i].re */
+ "movss 8(%%esi), %%xmm2\n" /* re1 */
+ "movss (%%edi), %%xmm1\n" /* buf[127-i].im */
+ "movss -8(%%edi), %%xmm3\n" /* im1 */
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | re1 | 0.0 | re0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | im1 | 0.0 | im1 */
+
+ "movaps (%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* im1 | 0.0 | im0 | 0.0 */
+ "movss 16(%%esi), %%xmm6\n" /* re2 */
+ "movss 24(%%esi), %%xmm7\n" /* re3 */
+ "movss -16(%%edi), %%xmm2\n" /* im2 */
+ "movss -24(%%edi), %%xmm3\n" /* im3 */
+ "subps %%xmm1, %%xmm0\n" /* -im1 | re1 | -im0 | re0 */
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | re3 | 0.0 | re2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | im3 | 0.0 | im2 */
+ "mulps %%xmm4, %%xmm0\n"
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* im3 | 0.0 | im2 | 0.0 */
+ "movaps 16(%%edx), %%xmm4\n" /* w7 | w6 | w5 | w4 */
+ "addl $32, %%esi\n"
+ "subps %%xmm2, %%xmm6\n" /* -im3 | re3 | -im2 | re2 */
+ "mulps %%xmm4, %%xmm6\n"
+ "addl $-32, %%edi\n"
+ "movaps %%xmm0, (%%eax)\n"
+ "addl $32, %%edx\n"
+ "addl $32, %%eax\n"
+ "movaps %%xmm6, -16(%%eax)\n"
+ "decl %%ebx\n"
+ "jnz .second_128_sample\n"
+
+ "leal 512(%%ebp), %%esi\n" /* buf[64].re */
+ "leal 508(%%ebp), %%edi\n" /* buf[63].im */
+ "movl $16, %%ebx\n" /* loop count */
+
+ ".align 16\n"
+".first_128_delays:\n"
+ "movss (%%esi), %%xmm0\n"
+ "movss 8(%%esi), %%xmm2\n"
+ "movss (%%edi), %%xmm1\n"
+ "movss -8(%%edi), %%xmm3\n"
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | re1 | 0.0 | re0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | im1 | 0.0 | im0 */
+
+ "movaps -16(%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* im1 | 0.0 | im0 | 0.0 */
+ "movss 16(%%esi), %%xmm6\n" /* re2 */
+ "movss 24(%%esi), %%xmm7\n" /* re3 */
+ "movss -16(%%edi), %%xmm2\n" /* im2 */
+ "movss -24(%%edi), %%xmm3\n" /* im3 */
+ "subps %%xmm1, %%xmm0\n" /* -im1 | re1 | -im0 | re0 */
+ "addl $-32, %%edx\n"
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | re3 | 0.0 | re2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | im3 | 0.0 | im2 */
+ "mulps %%xmm4, %%xmm0\n"
+ "movaps (%%edx), %%xmm5\n" /* w7 | w6 | w5 | w4 */
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* im3 | 0.0 | im2 | 0.0 */
+ "movaps %%xmm0, (%%ecx)\n"
+ "addl $32, %%esi\n"
+ "subps %%xmm2, %%xmm6\n" /* -im3 | re3 | -im2 | re2 */
+ "addl $-32, %%edi\n"
+ "mulps %%xmm5, %%xmm6\n"
+ "addl $32, %%ecx\n"
+ "movaps %%xmm6, -16(%%ecx)\n"
+ "decl %%ebx\n"
+ "jnz .first_128_delays\n"
+
+ "leal 4(%%ebp), %%esi\n" /* buf[0].im */
+ "leal 1016(%%ebp), %%edi\n" /* buf[127].re */
+ "movl $16, %%ebx\n" /* loop count */
+
+ ".align 16\n"
+".second_128_delays:\n"
+ "movss (%%esi), %%xmm0\n"
+ "movss 8(%%esi), %%xmm2\n"
+ "movss (%%edi), %%xmm1\n"
+ "movss -8(%%edi), %%xmm3\n"
+
+ "movlhps %%xmm2, %%xmm0\n" /* 0.0 | im1 | 0.0 | im0 */
+ "movlhps %%xmm3, %%xmm1\n" /* 0.0 | re1 | 0.0 | re0 */
+
+ "movaps -16(%%edx), %%xmm4\n" /* w3 | w2 | w1 | w0 */
+ "shufps $0xb1, %%xmm1, %%xmm1\n"/* re1 | 0.0 | re0 | 0.0 */
+ "movss 16(%%esi), %%xmm6\n" /* im2 */
+ "movss 24(%%esi), %%xmm7\n" /* im3 */
+ "movss -16(%%edi), %%xmm2\n" /* re2 */
+ "movss -24(%%edi), %%xmm3\n" /* re3 */
+ "subps %%xmm0, %%xmm1\n" /* re1 | -im1 | re0 | -im0 */
+ "addl $-32, %%edx\n"
+ "movlhps %%xmm7, %%xmm6\n" /* 0.0 | im3 | 0.0 | im2 */
+ "movlhps %%xmm3, %%xmm2\n" /* 0.0 | re3 | 0.0 | re2 */
+ "mulps %%xmm4, %%xmm1\n"
+ "movaps (%%edx), %%xmm5\n" /* w7 | w6 | w5 | w4 */
+ "shufps $0xb1, %%xmm2, %%xmm2\n"/* re3 | 0.0 | re2 | 0.0 */
+ "movaps %%xmm1, (%%ecx)\n"
+ "addl $32, %%esi\n"
+ "subps %%xmm6, %%xmm2\n" /* re | -im3 | re | -im2 */
+ "addl $-32, %%edi\n"
+ "mulps %%xmm5, %%xmm2\n"
+ "addl $32, %%ecx\n"
+ "movaps %%xmm2, -16(%%ecx)\n"
+ "decl %%ebx\n"
+ "jnz .second_128_delays\n"
+
+ "popl %%ebp\n"
+ "popl %%esi\n"
+ "popl %%edi\n"
+ "popl %%edx\n"
+ "popl %%ecx\n"
+ "popl %%ebx\n"
+ "popl %%eax\n"
+ : "=S" (buf), "=a" (data_ptr), "=c" (delay_prt), "=d" (window_prt)
+ : "S" (buf), "a" (data_ptr), "c" (delay_prt), "d" (window_prt));
+
+}
--- /dev/null
+/*****************************************************************************
+ * retables.h: A52 DCT tables
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: retables.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+static float window[] ATTR_ALIGN(16) = {
+ 0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130,
+ 0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443,
+ 0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061,
+ 0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121,
+ 0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770,
+ 0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153,
+ 0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389,
+ 0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563,
+ 0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699,
+ 0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757,
+ 0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626,
+ 0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126,
+ 0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019,
+ 0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031,
+ 0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873,
+ 0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269,
+ 0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981,
+ 0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831,
+ 0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716,
+ 0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610,
+ 0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560,
+ 0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674,
+ 0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099,
+ 0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994,
+ 0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513,
+ 0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788,
+ 0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919,
+ 0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974,
+ 0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993,
+ 0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999,
+ 0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000,
+ 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000
+};
+
+static const int pm128[128] =
+{
+ 0, 16, 32, 48, 64, 80, 96, 112, 8, 40, 72, 104, 24, 56, 88, 120,
+ 4, 20, 36, 52, 68, 84, 100, 116, 12, 28, 44, 60, 76, 92, 108, 124,
+ 2, 18, 34, 50, 66, 82, 98, 114, 10, 42, 74, 106, 26, 58, 90, 122,
+ 6, 22, 38, 54, 70, 86, 102, 118, 14, 46, 78, 110, 30, 62, 94, 126,
+ 1, 17, 33, 49, 65, 81, 97, 113, 9, 41, 73, 105, 25, 57, 89, 121,
+ 5, 21, 37, 53, 69, 85, 101, 117, 13, 29, 45, 61, 77, 93, 109, 125,
+ 3, 19, 35, 51, 67, 83, 99, 115, 11, 43, 75, 107, 27, 59, 91, 123,
+ 7, 23, 39, 55, 71, 87, 103, 119, 15, 31, 47, 63, 79, 95, 111, 127
+};
+
+static const int pm64[64] =
+{
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 4, 20, 36, 52, 12, 28, 44, 60,
+ 2, 10, 18, 26, 34, 42, 50, 58,
+ 6, 14, 22, 30, 38, 46, 54, 62,
+ 1, 9, 17, 25, 33, 41, 49, 57,
+ 5, 21, 37, 53, 13, 29, 45, 61,
+ 3, 11, 19, 27, 35, 43, 51, 59,
+ 7, 23, 39, 55, 15, 31, 47, 63
+};
+
--- /dev/null
+/*****************************************************************************
+ * srfft.h: A52 FFT tables
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: srfft.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+static const complex_t delta16[4] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.92387953251129, -0.38268343236509},
+ {0.70710678118655, -0.70710678118655},
+ {0.38268343236509, -0.92387953251129}};
+
+static const complex_t delta16_3[4] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.38268343236509, -0.92387953251129},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.92387953251129, 0.38268343236509}};
+
+static const complex_t delta32[8] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.98078528040323, -0.19509032201613},
+ {0.92387953251129, -0.38268343236509},
+ {0.83146961230255, -0.55557023301960},
+ {0.70710678118655, -0.70710678118655},
+ {0.55557023301960, -0.83146961230255},
+ {0.38268343236509, -0.92387953251129},
+ {0.19509032201613, -0.98078528040323}};
+
+static const complex_t delta32_3[8] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.83146961230255, -0.55557023301960},
+ {0.38268343236509, -0.92387953251129},
+ {-0.19509032201613, -0.98078528040323},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.98078528040323, -0.19509032201613},
+ {-0.92387953251129, 0.38268343236509},
+ {-0.55557023301960, 0.83146961230255}};
+
+static const complex_t delta64[16] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.99518472667220, -0.09801714032956},
+ {0.98078528040323, -0.19509032201613},
+ {0.95694033573221, -0.29028467725446},
+ {0.92387953251129, -0.38268343236509},
+ {0.88192126434836, -0.47139673682600},
+ {0.83146961230255, -0.55557023301960},
+ {0.77301045336274, -0.63439328416365},
+ {0.70710678118655, -0.70710678118655},
+ {0.63439328416365, -0.77301045336274},
+ {0.55557023301960, -0.83146961230255},
+ {0.47139673682600, -0.88192126434835},
+ {0.38268343236509, -0.92387953251129},
+ {0.29028467725446, -0.95694033573221},
+ {0.19509032201613, -0.98078528040323},
+ {0.09801714032956, -0.99518472667220}};
+
+static const complex_t delta64_3[16] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.95694033573221, -0.29028467725446},
+ {0.83146961230255, -0.55557023301960},
+ {0.63439328416365, -0.77301045336274},
+ {0.38268343236509, -0.92387953251129},
+ {0.09801714032956, -0.99518472667220},
+ {-0.19509032201613, -0.98078528040323},
+ {-0.47139673682600, -0.88192126434836},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.88192126434835, -0.47139673682600},
+ {-0.98078528040323, -0.19509032201613},
+ {-0.99518472667220, 0.09801714032956},
+ {-0.92387953251129, 0.38268343236509},
+ {-0.77301045336274, 0.63439328416365},
+ {-0.55557023301960, 0.83146961230255},
+ {-0.29028467725446, 0.95694033573221}};
+
+static const complex_t delta128[32] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.99879545620517, -0.04906767432742},
+ {0.99518472667220, -0.09801714032956},
+ {0.98917650996478, -0.14673047445536},
+ {0.98078528040323, -0.19509032201613},
+ {0.97003125319454, -0.24298017990326},
+ {0.95694033573221, -0.29028467725446},
+ {0.94154406518302, -0.33688985339222},
+ {0.92387953251129, -0.38268343236509},
+ {0.90398929312344, -0.42755509343028},
+ {0.88192126434836, -0.47139673682600},
+ {0.85772861000027, -0.51410274419322},
+ {0.83146961230255, -0.55557023301960},
+ {0.80320753148064, -0.59569930449243},
+ {0.77301045336274, -0.63439328416365},
+ {0.74095112535496, -0.67155895484702},
+ {0.70710678118655, -0.70710678118655},
+ {0.67155895484702, -0.74095112535496},
+ {0.63439328416365, -0.77301045336274},
+ {0.59569930449243, -0.80320753148064},
+ {0.55557023301960, -0.83146961230255},
+ {0.51410274419322, -0.85772861000027},
+ {0.47139673682600, -0.88192126434835},
+ {0.42755509343028, -0.90398929312344},
+ {0.38268343236509, -0.92387953251129},
+ {0.33688985339222, -0.94154406518302},
+ {0.29028467725446, -0.95694033573221},
+ {0.24298017990326, -0.97003125319454},
+ {0.19509032201613, -0.98078528040323},
+ {0.14673047445536, -0.98917650996478},
+ {0.09801714032956, -0.99518472667220},
+ {0.04906767432742, -0.99879545620517}};
+
+static const complex_t delta128_3[32] ATTR_ALIGN(16) =
+ { {1.00000000000000, 0.00000000000000},
+ {0.98917650996478, -0.14673047445536},
+ {0.95694033573221, -0.29028467725446},
+ {0.90398929312344, -0.42755509343028},
+ {0.83146961230255, -0.55557023301960},
+ {0.74095112535496, -0.67155895484702},
+ {0.63439328416365, -0.77301045336274},
+ {0.51410274419322, -0.85772861000027},
+ {0.38268343236509, -0.92387953251129},
+ {0.24298017990326, -0.97003125319454},
+ {0.09801714032956, -0.99518472667220},
+ {-0.04906767432742, -0.99879545620517},
+ {-0.19509032201613, -0.98078528040323},
+ {-0.33688985339222, -0.94154406518302},
+ {-0.47139673682600, -0.88192126434836},
+ {-0.59569930449243, -0.80320753148065},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.80320753148065, -0.59569930449243},
+ {-0.88192126434835, -0.47139673682600},
+ {-0.94154406518302, -0.33688985339222},
+ {-0.98078528040323, -0.19509032201613},
+ {-0.99879545620517, -0.04906767432742},
+ {-0.99518472667220, 0.09801714032956},
+ {-0.97003125319454, 0.24298017990326},
+ {-0.92387953251129, 0.38268343236509},
+ {-0.85772861000027, 0.51410274419322},
+ {-0.77301045336274, 0.63439328416365},
+ {-0.67155895484702, 0.74095112535496},
+ {-0.55557023301960, 0.83146961230255},
+ {-0.42755509343028, 0.90398929312344},
+ {-0.29028467725446, 0.95694033573221},
+ {-0.14673047445536, 0.98917650996478}};
+
+#define HSQRT2 0.707106781188;
+
+#define TRANSZERO(A0,A4,A8,A12) { \
+ u_r = wTB[0].real; \
+ v_i = u_r - wTB[k*2].real; \
+ u_r += wTB[k*2].real; \
+ u_i = wTB[0].imag; \
+ v_r = wTB[k*2].imag - u_i; \
+ u_i += wTB[k*2].imag; \
+ a_r = A0.real; \
+ a_i = A0.imag; \
+ a1_r = a_r; \
+ a1_r += u_r; \
+ A0.real = a1_r; \
+ a_r -= u_r; \
+ A8.real = a_r; \
+ a1_i = a_i; \
+ a1_i += u_i; \
+ A0.imag = a1_i; \
+ a_i -= u_i; \
+ A8.imag = a_i; \
+ a1_r = A4.real; \
+ a1_i = A4.imag; \
+ a_r = a1_r; \
+ a_r -= v_r; \
+ A4.real = a_r; \
+ a1_r += v_r; \
+ A12.real = a1_r; \
+ a_i = a1_i; \
+ a_i -= v_i; \
+ A4.imag = a_i; \
+ a1_i += v_i; \
+ A12.imag = a1_i; \
+ }
+
+#define TRANSHALF_16(A2,A6,A10,A14) {\
+ u_r = wTB[2].real; \
+ a_r = u_r; \
+ u_i = wTB[2].imag; \
+ u_r += u_i; \
+ u_i -= a_r; \
+ a_r = wTB[6].real; \
+ a1_r = a_r; \
+ a_i = wTB[6].imag; \
+ a_r = a_i - a_r; \
+ a_i += a1_r; \
+ v_i = u_r - a_r; \
+ u_r += a_r; \
+ v_r = u_i + a_i; \
+ u_i -= a_i; \
+ v_i *= HSQRT2; \
+ v_r *= HSQRT2; \
+ u_r *= HSQRT2; \
+ u_i *= HSQRT2; \
+ a_r = A2.real; \
+ a_i = A2.imag; \
+ a1_r = a_r; \
+ a1_r += u_r; \
+ A2.real = a1_r; \
+ a_r -= u_r; \
+ A10.real = a_r; \
+ a1_i = a_i; \
+ a1_i += u_i; \
+ A2.imag = a1_i; \
+ a_i -= u_i; \
+ A10.imag = a_i; \
+ a1_r = A6.real; \
+ a1_i = A6.imag; \
+ a_r = a1_r; \
+ a1_r += v_r; \
+ A6.real = a1_r; \
+ a_r -= v_r; \
+ A14.real = a_r; \
+ a_i = a1_i; \
+ a1_i -= v_i; \
+ A6.imag = a1_i; \
+ a_i += v_i; \
+ A14.imag = a_i; \
+ }
+
+#define TRANS(A1,A5,A9,A13,WT,WB,D,D3) { \
+ u_r = WT.real; \
+ a_r = u_r; \
+ a_r *= D.imag; \
+ u_r *= D.real; \
+ a_i = WT.imag; \
+ a1_i = a_i; \
+ a1_i *= D.real; \
+ a_i *= D.imag; \
+ u_r -= a_i; \
+ u_i = a_r; \
+ u_i += a1_i; \
+ a_r = WB.real; \
+ a1_r = a_r; \
+ a1_r *= D3.real; \
+ a_r *= D3.imag; \
+ a_i = WB.imag; \
+ a1_i = a_i; \
+ a_i *= D3.real; \
+ a1_i *= D3.imag; \
+ a1_r -= a1_i; \
+ a_r += a_i; \
+ v_i = u_r - a1_r; \
+ u_r += a1_r; \
+ v_r = a_r - u_i; \
+ u_i += a_r; \
+ a_r = A1.real; \
+ a_i = A1.imag; \
+ a1_r = a_r; \
+ a1_r += u_r; \
+ A1.real = a1_r; \
+ a_r -= u_r; \
+ A9.real = a_r; \
+ a1_i = a_i; \
+ a1_i += u_i; \
+ A1.imag = a1_i; \
+ a_i -= u_i; \
+ A9.imag = a_i; \
+ a1_r = A5.real; \
+ a1_i = A5.imag; \
+ a_r = a1_r; \
+ a1_r -= v_r; \
+ A5.real = a1_r; \
+ a_r += v_r; \
+ A13.real = a_r; \
+ a_i = a1_i; \
+ a1_i -= v_i; \
+ A5.imag = a1_i; \
+ a_i += v_i; \
+ A13.imag = a_i; \
+ }
+
--- /dev/null
+/*****************************************************************************
+ * srfft_3dn.c: accelerated 3D Now! A52 fft functions
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: srfft_3dn.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "srfft.h"
+
+void hsqrt2_3dn (void);
+void C_1_3dn (void);
+static void fft_4_3dn (complex_t *x);
+static void fft_8_3dn (complex_t *x);
+static void fft_asmb_3dn (int k, complex_t *x, complex_t *wTB,
+ const complex_t *d, const complex_t *d_3);
+
+void E_( fft_64p ) ( complex_t *a )
+{
+ fft_8_3dn(&a[0]); fft_4_3dn(&a[8]); fft_4_3dn(&a[12]);
+ fft_asmb_3dn(2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
+
+ fft_8_3dn(&a[16]), fft_8_3dn(&a[24]);
+ fft_asmb_3dn(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8_3dn(&a[32]); fft_4_3dn(&a[40]); fft_4_3dn(&a[44]);
+ fft_asmb_3dn(2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
+
+ fft_8_3dn(&a[48]); fft_4_3dn(&a[56]); fft_4_3dn(&a[60]);
+ fft_asmb_3dn(2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
+
+ fft_asmb_3dn(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+}
+
+void E_( fft_128p ) ( complex_t *a )
+{
+ fft_8_3dn(&a[0]); fft_4_3dn(&a[8]); fft_4_3dn(&a[12]);
+ fft_asmb_3dn(2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
+
+ fft_8_3dn(&a[16]), fft_8_3dn(&a[24]);
+ fft_asmb_3dn(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8_3dn(&a[32]); fft_4_3dn(&a[40]); fft_4_3dn(&a[44]);
+ fft_asmb_3dn(2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
+
+ fft_8_3dn(&a[48]); fft_4_3dn(&a[56]); fft_4_3dn(&a[60]);
+ fft_asmb_3dn(2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
+
+ fft_asmb_3dn(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+
+ fft_8_3dn(&a[64]); fft_4_3dn(&a[72]); fft_4_3dn(&a[76]);
+ /* fft_16(&a[64]); */
+ fft_asmb_3dn(2, &a[64], &a[72], &delta16[0], &delta16_3[0]);
+
+ fft_8_3dn(&a[80]); fft_8_3dn(&a[88]);
+
+ /* fft_32(&a[64]); */
+ fft_asmb_3dn(4, &a[64], &a[80],&delta32[0], &delta32_3[0]);
+
+ fft_8_3dn(&a[96]); fft_4_3dn(&a[104]), fft_4_3dn(&a[108]);
+ /* fft_16(&a[96]); */
+ fft_asmb_3dn(2, &a[96], &a[104], &delta16[0], &delta16_3[0]);
+
+ fft_8_3dn(&a[112]), fft_8_3dn(&a[120]);
+ /* fft_32(&a[96]); */
+ fft_asmb_3dn(4, &a[96], &a[112], &delta32[0], &delta32_3[0]);
+
+ /* fft_128(&a[0]); */
+ fft_asmb_3dn(16, &a[0], &a[64], &delta128[0], &delta128_3[0]);
+}
+
+void hsqrt2_3dn (void)
+{
+ __asm__ (
+ ".float 0f0.707106781188\n"
+ ".float 0f0.707106781188\n"
+ ".float 0f-0.707106781188\n"
+ ".float 0f-0.707106781188\n"
+ );
+}
+
+void C_1_3dn (void)
+{
+ __asm__ (
+ ".float 0f-1.0\n"
+ ".float 0f1.0\n"
+ ".float 0f-1.0\n"
+ ".float 0f1.0\n"
+ );
+}
+
+static void fft_4_3dn (complex_t *x)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "movq (%%eax), %%mm0\n" /* x[0] */
+ "movq 8(%%eax), %%mm1\n" /* x[1] */
+ "movq 16(%%eax), %%mm2\n" /* x[2] */
+ "movq 24(%%eax), %%mm3\n" /* x[3] */
+ "movq %%mm0, %%mm4\n" /* x[1] */
+ "movq %%mm1, %%mm5\n" /* x[1] */
+ "movq %%mm0, %%mm6\n" /* x[0] */
+ "pfadd %%mm2, %%mm0\n" /* x[0] + x[2] */
+ "pfadd %%mm3, %%mm1\n" /* x[1] + x[3] */
+ "pfsub %%mm2, %%mm4\n" /* x[0] - x[2] */
+ "pfsub %%mm3, %%mm5\n" /* x[1] - x[3] */
+
+ "pfadd %%mm1, %%mm0\n" /* x[0] + x[2] + x[1] + x[3] */
+ "pfsub %%mm1, %%mm6\n" /* x[0] + x[2] - x[1] - x[3] */
+
+ "movq %%mm0, (%%eax)\n"
+ "movq %%mm6, 16(%%eax)\n"
+
+ "pxor %%mm6, %%mm6\n"
+ "movq %%mm5, %%mm2\n" /* x[1] - x[3] */
+ "movq %%mm4, %%mm3\n" /* x[0] - x[2] */
+ "pfsub %%mm5, %%mm6\n" /* x[3] - x[1] */
+
+ "punpckhdq %%mm2,%%mm2\n" /* x[1] - x[3].im */
+ "punpckldq %%mm6,%%mm6\n" /* x[3] - x[1].re */
+ "punpckhdq %%mm6,%%mm2\n" /* x[3] - x[1].re, x[1] - x[3].im */
+
+ "pfsub %%mm2, %%mm4\n" /* x0i-x2i-x3r+x1.r,x0r-x2r-x1i+x3i */
+ "pfadd %%mm3, %%mm2\n" /* x0i-x2i+x3r-x1.r, x0r-x2r+x1i-x3.i */
+
+ "movq %%mm2, 8(%%eax)\n" /* mm4_2 + mm6_1, mm4_1 + mm5_2 */
+ "movq %%mm4, 24(%%eax)\n" /* mm4_2 - mm6_1, mm4_1 - mm5_2 */
+ "femms\n"
+ : "=a" (x)
+ : "a" (x) );
+}
+
+static void fft_8_3dn (complex_t *x)
+{
+ register float wT1_r, wT1_i, wB1_r, wB1_i, wT2_r, wT2_i, wB2_r, wB2_i;
+
+ wT1_r = x[1].real;
+ wT1_i = x[1].imag;
+ wB1_r = x[3].real;
+ wB1_i = x[3].imag;
+
+ x[1] = x[2];
+ x[2] = x[4];
+ x[3] = x[6];
+ { /* fft_4 */
+ register float yt_r, yt_i, yb_r, yb_i, u_r, u_i, vi_r, vi_i;
+
+ yt_r = x[0].real;
+ yb_r = yt_r - x[2].real;
+ yt_r += x[2].real;
+
+ u_r = x[1].real;
+ vi_i = x[3].real - u_r;
+ u_r += x[3].real;
+
+ u_i = x[1].imag;
+ vi_r = u_i - x[3].imag;
+ u_i += x[3].imag;
+
+ yt_i = yt_r;
+ yt_i += u_r;
+ x[0].real = yt_i;
+ yt_r -= u_r;
+ x[2].real = yt_r;
+ yt_i = yb_r;
+ yt_i += vi_r;
+ x[1].real = yt_i;
+ yb_r -= vi_r;
+ x[3].real = yb_r;
+
+ yt_i = x[0].imag;
+ yb_i = yt_i - x[2].imag;
+ yt_i += x[2].imag;
+
+ yt_r = yt_i;
+ yt_r += u_i;
+ x[0].imag = yt_r;
+ yt_i -= u_i;
+ x[2].imag = yt_i;
+ yt_r = yb_i;
+ yt_r += vi_i;
+ x[1].imag = yt_r;
+ yb_i -= vi_i;
+ x[3].imag = yb_i;
+ }
+
+ /* x[0] x[4] */
+ wT2_r = x[5].real;
+ wT2_r += x[7].real;
+ wT2_r += wT1_r;
+ wT2_r += wB1_r;
+ wT2_i = wT2_r;
+ wT2_r += x[0].real;
+ wT2_i = x[0].real - wT2_i;
+ x[0].real = wT2_r;
+ x[4].real = wT2_i;
+
+ wT2_i = x[5].imag;
+ wT2_i += x[7].imag;
+ wT2_i += wT1_i;
+ wT2_i += wB1_i;
+ wT2_r = wT2_i;
+ wT2_r += x[0].imag;
+ wT2_i = x[0].imag - wT2_i;
+ x[0].imag = wT2_r;
+ x[4].imag = wT2_i;
+
+ /* x[2] x[6] */
+ wT2_r = x[5].imag;
+ wT2_r -= x[7].imag;
+ wT2_r += wT1_i;
+ wT2_r -= wB1_i;
+ wT2_i = wT2_r;
+ wT2_r += x[2].real;
+ wT2_i = x[2].real - wT2_i;
+ x[2].real = wT2_r;
+ x[6].real = wT2_i;
+
+ wT2_i = x[5].real;
+ wT2_i -= x[7].real;
+ wT2_i += wT1_r;
+ wT2_i -= wB1_r;
+ wT2_r = wT2_i;
+ wT2_r += x[2].imag;
+ wT2_i = x[2].imag - wT2_i;
+ x[2].imag = wT2_i;
+ x[6].imag = wT2_r;
+
+ /* x[1] x[5] */
+ wT2_r = wT1_r;
+ wT2_r += wB1_i;
+ wT2_r -= x[5].real;
+ wT2_r -= x[7].imag;
+ wT2_i = wT1_i;
+ wT2_i -= wB1_r;
+ wT2_i -= x[5].imag;
+ wT2_i += x[7].real;
+
+ wB2_r = wT2_r;
+ wB2_r += wT2_i;
+ wT2_i -= wT2_r;
+ wB2_r *= HSQRT2;
+ wT2_i *= HSQRT2;
+ wT2_r = wB2_r;
+ wB2_r += x[1].real;
+ wT2_r = x[1].real - wT2_r;
+
+ wB2_i = x[5].real;
+ x[1].real = wB2_r;
+ x[5].real = wT2_r;
+
+ wT2_r = wT2_i;
+ wT2_r += x[1].imag;
+ wT2_i = x[1].imag - wT2_i;
+ wB2_r = x[5].imag;
+ x[1].imag = wT2_r;
+ x[5].imag = wT2_i;
+
+ /* x[3] x[7] */
+ wT1_r -= wB1_i;
+ wT1_i += wB1_r;
+ wB1_r = wB2_i - x[7].imag;
+ wB1_i = wB2_r + x[7].real;
+ wT1_r -= wB1_r;
+ wT1_i -= wB1_i;
+ wB1_r = wT1_r + wT1_i;
+ wB1_r *= HSQRT2;
+ wT1_i -= wT1_r;
+ wT1_i *= HSQRT2;
+ wB2_r = x[3].real;
+ wB2_i = wB2_r + wT1_i;
+ wB2_r -= wT1_i;
+ x[3].real = wB2_i;
+ x[7].real = wB2_r;
+ wB2_i = x[3].imag;
+ wB2_r = wB2_i + wB1_r;
+ wB2_i -= wB1_r;
+ x[3].imag = wB2_i;
+ x[7].imag = wB2_r;
+}
+
+
+static void fft_asmb_3dn (int k, complex_t *x, complex_t *wTB,
+ const complex_t *d, const complex_t *d_3)
+{
+ register complex_t *x2k, *x3k, *x4k, *wB;
+ register float a_r, a_i, a1_r, a1_i, u_r, u_i, v_r, v_i;
+
+ x2k = x + 2 * k;
+ x3k = x2k + 2 * k;
+ x4k = x3k + 2 * k;
+ wB = wTB + 2 * k;
+
+ TRANSZERO(x[0],x2k[0],x3k[0],x4k[0]);
+ TRANS(x[1],x2k[1],x3k[1],x4k[1],wTB[1],wB[1],d[1],d_3[1]);
+
+ --k;
+ for(;;) {
+ TRANS(x[2],x2k[2],x3k[2],x4k[2],wTB[2],wB[2],d[2],d_3[2]);
+ TRANS(x[3],x2k[3],x3k[3],x4k[3],wTB[3],wB[3],d[3],d_3[3]);
+ if (!--k) break;
+ x += 2;
+ x2k += 2;
+ x3k += 2;
+ x4k += 2;
+ d += 2;
+ d_3 += 2;
+ wTB += 2;
+ wB += 2;
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * srfft.c: A52 FFT in C
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: srfft_c.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "srfft.h"
+
+static void fft_8 (complex_t *x);
+
+static void fft_4(complex_t *x)
+{
+ /* delta_p = 1 here */
+ /* x[k] = sum_{i=0..3} x[i] * w^{i*k}, w=e^{-2*pi/4}
+ */
+
+ register float yt_r, yt_i, yb_r, yb_i, u_r, u_i, vi_r, vi_i;
+
+ yt_r = x[0].real;
+ yb_r = yt_r - x[2].real;
+ yt_r += x[2].real;
+
+ u_r = x[1].real;
+ vi_i = x[3].real - u_r;
+ u_r += x[3].real;
+
+ u_i = x[1].imag;
+ vi_r = u_i - x[3].imag;
+ u_i += x[3].imag;
+
+ yt_i = yt_r;
+ yt_i += u_r;
+ x[0].real = yt_i;
+ yt_r -= u_r;
+ x[2].real = yt_r;
+ yt_i = yb_r;
+ yt_i += vi_r;
+ x[1].real = yt_i;
+ yb_r -= vi_r;
+ x[3].real = yb_r;
+
+ yt_i = x[0].imag;
+ yb_i = yt_i - x[2].imag;
+ yt_i += x[2].imag;
+
+ yt_r = yt_i;
+ yt_r += u_i;
+ x[0].imag = yt_r;
+ yt_i -= u_i;
+ x[2].imag = yt_i;
+ yt_r = yb_i;
+ yt_r += vi_i;
+ x[1].imag = yt_r;
+ yb_i -= vi_i;
+ x[3].imag = yb_i;
+}
+
+
+static void fft_8 (complex_t *x)
+{
+ /* delta_p = diag{1, sqrt(i)} here */
+ /* x[k] = sum_{i=0..7} x[i] * w^{i*k}, w=e^{-2*pi/8}
+ */
+ register float wT1_r, wT1_i, wB1_r, wB1_i, wT2_r, wT2_i, wB2_r, wB2_i;
+
+ wT1_r = x[1].real;
+ wT1_i = x[1].imag;
+ wB1_r = x[3].real;
+ wB1_i = x[3].imag;
+
+ x[1] = x[2];
+ x[2] = x[4];
+ x[3] = x[6];
+ fft_4(&x[0]);
+
+
+ /* x[0] x[4] */
+ wT2_r = x[5].real;
+ wT2_r += x[7].real;
+ wT2_r += wT1_r;
+ wT2_r += wB1_r;
+ wT2_i = wT2_r;
+ wT2_r += x[0].real;
+ wT2_i = x[0].real - wT2_i;
+ x[0].real = wT2_r;
+ x[4].real = wT2_i;
+
+ wT2_i = x[5].imag;
+ wT2_i += x[7].imag;
+ wT2_i += wT1_i;
+ wT2_i += wB1_i;
+ wT2_r = wT2_i;
+ wT2_r += x[0].imag;
+ wT2_i = x[0].imag - wT2_i;
+ x[0].imag = wT2_r;
+ x[4].imag = wT2_i;
+
+ /* x[2] x[6] */
+ wT2_r = x[5].imag;
+ wT2_r -= x[7].imag;
+ wT2_r += wT1_i;
+ wT2_r -= wB1_i;
+ wT2_i = wT2_r;
+ wT2_r += x[2].real;
+ wT2_i = x[2].real - wT2_i;
+ x[2].real = wT2_r;
+ x[6].real = wT2_i;
+
+ wT2_i = x[5].real;
+ wT2_i -= x[7].real;
+ wT2_i += wT1_r;
+ wT2_i -= wB1_r;
+ wT2_r = wT2_i;
+ wT2_r += x[2].imag;
+ wT2_i = x[2].imag - wT2_i;
+ x[2].imag = wT2_i;
+ x[6].imag = wT2_r;
+
+
+ /* x[1] x[5] */
+ wT2_r = wT1_r;
+ wT2_r += wB1_i;
+ wT2_r -= x[5].real;
+ wT2_r -= x[7].imag;
+ wT2_i = wT1_i;
+ wT2_i -= wB1_r;
+ wT2_i -= x[5].imag;
+ wT2_i += x[7].real;
+
+ wB2_r = wT2_r;
+ wB2_r += wT2_i;
+ wT2_i -= wT2_r;
+ wB2_r *= HSQRT2;
+ wT2_i *= HSQRT2;
+ wT2_r = wB2_r;
+ wB2_r += x[1].real;
+ wT2_r = x[1].real - wT2_r;
+
+ wB2_i = x[5].real;
+ x[1].real = wB2_r;
+ x[5].real = wT2_r;
+
+ wT2_r = wT2_i;
+ wT2_r += x[1].imag;
+ wT2_i = x[1].imag - wT2_i;
+ wB2_r = x[5].imag;
+ x[1].imag = wT2_r;
+ x[5].imag = wT2_i;
+
+ /* x[3] x[7] */
+ wT1_r -= wB1_i;
+ wT1_i += wB1_r;
+ wB1_r = wB2_i - x[7].imag;
+ wB1_i = wB2_r + x[7].real;
+ wT1_r -= wB1_r;
+ wT1_i -= wB1_i;
+ wB1_r = wT1_r + wT1_i;
+ wB1_r *= HSQRT2;
+ wT1_i -= wT1_r;
+ wT1_i *= HSQRT2;
+ wB2_r = x[3].real;
+ wB2_i = wB2_r + wT1_i;
+ wB2_r -= wT1_i;
+ x[3].real = wB2_i;
+ x[7].real = wB2_r;
+ wB2_i = x[3].imag;
+ wB2_r = wB2_i + wB1_r;
+ wB2_i -= wB1_r;
+ x[3].imag = wB2_i;
+ x[7].imag = wB2_r;
+}
+
+
+static void fft_asmb(int k, complex_t *x, complex_t *wTB,
+ const complex_t *d, const complex_t *d_3)
+{
+ register complex_t *x2k, *x3k, *x4k, *wB;
+ register float a_r, a_i, a1_r, a1_i, u_r, u_i, v_r, v_i;
+
+ x2k = x + 2 * k;
+ x3k = x2k + 2 * k;
+ x4k = x3k + 2 * k;
+ wB = wTB + 2 * k;
+
+ TRANSZERO(x[0],x2k[0],x3k[0],x4k[0]);
+ TRANS(x[1],x2k[1],x3k[1],x4k[1],wTB[1],wB[1],d[1],d_3[1]);
+
+ --k;
+ for(;;) {
+ TRANS(x[2],x2k[2],x3k[2],x4k[2],wTB[2],wB[2],d[2],d_3[2]);
+ TRANS(x[3],x2k[3],x3k[3],x4k[3],wTB[3],wB[3],d[3],d_3[3]);
+ if (!--k) break;
+ x += 2;
+ x2k += 2;
+ x3k += 2;
+ x4k += 2;
+ d += 2;
+ d_3 += 2;
+ wTB += 2;
+ wB += 2;
+ }
+
+}
+
+static void fft_asmb16(complex_t *x, complex_t *wTB)
+{
+ register float a_r, a_i, a1_r, a1_i, u_r, u_i, v_r, v_i;
+ int k = 2;
+
+ /* transform x[0], x[8], x[4], x[12] */
+ TRANSZERO(x[0],x[4],x[8],x[12]);
+
+ /* transform x[1], x[9], x[5], x[13] */
+ TRANS(x[1],x[5],x[9],x[13],wTB[1],wTB[5],delta16[1],delta16_3[1]);
+
+ /* transform x[2], x[10], x[6], x[14] */
+ TRANSHALF_16(x[2],x[6],x[10],x[14]);
+
+ /* transform x[3], x[11], x[7], x[15] */
+ TRANS(x[3],x[7],x[11],x[15],wTB[3],wTB[7],delta16[3],delta16_3[3]);
+
+}
+
+
+void E_( fft_64p ) ( complex_t *a )
+{
+ fft_8(&a[0]); fft_4(&a[8]); fft_4(&a[12]);
+ fft_asmb16(&a[0], &a[8]);
+
+ fft_8(&a[16]), fft_8(&a[24]);
+ fft_asmb(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8(&a[32]); fft_4(&a[40]); fft_4(&a[44]);
+ fft_asmb16(&a[32], &a[40]);
+
+ fft_8(&a[48]); fft_4(&a[56]); fft_4(&a[60]);
+ fft_asmb16(&a[48], &a[56]);
+
+ fft_asmb(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+}
+
+
+void E_( fft_128p ) ( complex_t *a )
+{
+ fft_8(&a[0]); fft_4(&a[8]); fft_4(&a[12]);
+ fft_asmb16(&a[0], &a[8]);
+
+ fft_8(&a[16]), fft_8(&a[24]);
+ fft_asmb(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8(&a[32]); fft_4(&a[40]); fft_4(&a[44]);
+ fft_asmb16(&a[32], &a[40]);
+
+ fft_8(&a[48]); fft_4(&a[56]); fft_4(&a[60]);
+ fft_asmb16(&a[48], &a[56]);
+
+ fft_asmb(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+
+ fft_8(&a[64]); fft_4(&a[72]); fft_4(&a[76]);
+ /* fft_16(&a[64]); */
+ fft_asmb16(&a[64], &a[72]);
+
+ fft_8(&a[80]); fft_8(&a[88]);
+
+ /* fft_32(&a[64]); */
+ fft_asmb(4, &a[64], &a[80],&delta32[0], &delta32_3[0]);
+
+ fft_8(&a[96]); fft_4(&a[104]), fft_4(&a[108]);
+ /* fft_16(&a[96]); */
+ fft_asmb16(&a[96], &a[104]);
+
+ fft_8(&a[112]), fft_8(&a[120]);
+ /* fft_32(&a[96]); */
+ fft_asmb(4, &a[96], &a[112], &delta32[0], &delta32_3[0]);
+
+ /* fft_128(&a[0]); */
+ fft_asmb(16, &a[0], &a[64], &delta128[0], &delta128_3[0]);
+}
+
--- /dev/null
+/*****************************************************************************
+ * srfft_sse.c: accelerated SSE A52 fft functions
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: srfft_sse.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Renaud Dartus <reno@videolan.org>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <math.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+
+#include "../imdct.h"
+#include "srfft.h"
+
+
+static float hsqrt2_sse[] ATTR_ALIGN(16) =
+ { 0.707106781188, 0.707106781188, -0.707106781188, -0.707106781188 };
+
+static float C_1_sse[] ATTR_ALIGN(16) =
+ { -1.0, 1.0, -1.0, 1.0 };
+
+typedef struct {
+ int k;
+ void * C1;
+ } ck_sse_t;
+
+
+static void fft_4_sse (complex_t *x);
+static void fft_8_sse (complex_t *x);
+static void fft_asmb_sse (ck_sse_t * ck, int k, complex_t *x, complex_t *wTB,
+ const complex_t *d, const complex_t *d_3);
+
+void E_( fft_64p ) ( complex_t *a )
+{
+ ck_sse_t ck;
+ ck.C1 = C_1_sse;
+
+ fft_8_sse(&a[0]); fft_4_sse(&a[8]); fft_4_sse(&a[12]);
+ fft_asmb_sse(&ck, 2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
+
+ fft_8_sse(&a[16]), fft_8_sse(&a[24]);
+ fft_asmb_sse(&ck, 4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8_sse(&a[32]); fft_4_sse(&a[40]); fft_4_sse(&a[44]);
+ fft_asmb_sse(&ck, 2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
+
+ fft_8_sse(&a[48]); fft_4_sse(&a[56]); fft_4_sse(&a[60]);
+ fft_asmb_sse(&ck, 2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
+
+ fft_asmb_sse(&ck, 8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+}
+
+void E_( fft_128p ) ( complex_t *a )
+{
+ ck_sse_t ck;
+ ck.C1 = C_1_sse;
+
+ fft_8_sse(&a[0]); fft_4_sse(&a[8]); fft_4_sse(&a[12]);
+ fft_asmb_sse(&ck, 2, &a[0], &a[8], &delta16[0], &delta16_3[0]);
+
+ fft_8_sse(&a[16]), fft_8_sse(&a[24]);
+ fft_asmb_sse(&ck, 4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8_sse(&a[32]); fft_4_sse(&a[40]); fft_4_sse(&a[44]);
+ fft_asmb_sse(&ck, 2, &a[32], &a[40], &delta16[0], &delta16_3[0]);
+
+ fft_8_sse(&a[48]); fft_4_sse(&a[56]); fft_4_sse(&a[60]);
+ fft_asmb_sse(&ck, 2, &a[48], &a[56], &delta16[0], &delta16_3[0]);
+
+ fft_asmb_sse(&ck, 8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+
+ fft_8_sse(&a[64]); fft_4_sse(&a[72]); fft_4_sse(&a[76]);
+ /* fft_16(&a[64]); */
+ fft_asmb_sse(&ck, 2, &a[64], &a[72], &delta16[0], &delta16_3[0]);
+
+ fft_8_sse(&a[80]); fft_8_sse(&a[88]);
+
+ /* fft_32(&a[64]); */
+ fft_asmb_sse(&ck, 4, &a[64], &a[80],&delta32[0], &delta32_3[0]);
+
+ fft_8_sse(&a[96]); fft_4_sse(&a[104]), fft_4_sse(&a[108]);
+ /* fft_16(&a[96]); */
+ fft_asmb_sse(&ck, 2, &a[96], &a[104], &delta16[0], &delta16_3[0]);
+
+ fft_8_sse(&a[112]), fft_8_sse(&a[120]);
+ /* fft_32(&a[96]); */
+ fft_asmb_sse(&ck, 4, &a[96], &a[112], &delta32[0], &delta32_3[0]);
+
+ /* fft_128(&a[0]); */
+ fft_asmb_sse(&ck, 16, &a[0], &a[64], &delta128[0], &delta128_3[0]);
+}
+
+static void fft_4_sse (complex_t *x)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "movaps (%%eax), %%xmm0\n" /* x[1] | x[0] */
+ "movaps 16(%%eax), %%xmm2\n" /* x[3] | x[2] */
+ "movaps %%xmm0, %%xmm1\n" /* x[1] | x[0] */
+ "addps %%xmm2, %%xmm0\n" /* x[1] + x[3] | x[0] + x[2] */
+ "subps %%xmm2, %%xmm1\n" /* x[1] - x[3] | x[0] - x[2] */
+ "xorps %%xmm6, %%xmm6\n"
+ "movhlps %%xmm1, %%xmm4\n" /* ? | x[1] - x[3] */
+ "movhlps %%xmm0, %%xmm3\n" /* ? | x[1] + x[3] */
+ "subss %%xmm4, %%xmm6\n" /* 0 | -(x[1] - x[3]).re */
+ "movlhps %%xmm1, %%xmm0\n" /* x[0] - x[2] | x[0] + x[2] */
+ "movlhps %%xmm6, %%xmm4\n" /* 0 | -(x[1] - x[3]).re | (x[1] - x[3]).im | (x[3]-x[1]).re */
+ "movaps %%xmm0, %%xmm2\n" /* x[0] - x[2] | x[0] + x[2] */
+ "shufps $0x94, %%xmm4, %%xmm3\n" /* i*(x[1] - x[3]) | x[1] + x[3] */
+ "addps %%xmm3, %%xmm0\n"
+ "subps %%xmm3, %%xmm2\n"
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm2, 16(%%eax)\n"
+ : "=a" (x)
+ : "a" (x) );
+}
+
+static void fft_8_sse (complex_t *x)
+{
+ __asm__ __volatile__ (
+ ".align 16\n"
+
+ "movlps (%%eax), %%xmm0\n" /* x[0] */
+ "movlps 32(%%eax), %%xmm1\n" /* x[4] */
+ "movhps 16(%%eax), %%xmm0\n" /* x[2] | x[0] */
+ "movhps 48(%%eax), %%xmm1\n" /* x[6] | x[4] */
+ "movaps %%xmm0, %%xmm2\n" /* x[2] | x[0] */
+ "xorps %%xmm3, %%xmm3\n"
+ "addps %%xmm1, %%xmm0\n" /* x[2] + x[6] | x[0] + x[4] */
+ "subps %%xmm1, %%xmm2\n" /* x[2] - x[6] | x[0] - x[4] */
+ "movhlps %%xmm0, %%xmm5\n" /* x[2] + x[6] */
+ "movhlps %%xmm2, %%xmm4\n" /* x[2] - x[6] */
+ "movlhps %%xmm2, %%xmm0\n" /* x[0] - x[4] | x[0] + x[4] */
+ "subss %%xmm4, %%xmm3\n" /* (x[2]-x[6]).im | -(x[2]-x[6]).re */
+ "movaps %%xmm0, %%xmm7\n" /* x[0] - x[4] | x[0] + x[4] */
+ "movaps %%xmm3, %%xmm4\n" /* (x[2]-x[6]).im | -(x[2]-x[6]).re */
+ "movlps 8(%%eax), %%xmm1\n" /* x[1] */
+ "shufps $0x14, %%xmm4, %%xmm5\n" /* i*(x[2] - x[6]) | x[2] + x[6] */
+
+ "addps %%xmm5, %%xmm0\n" /* yt = i*(x2-x6)+x0-x4 | x2+x6+x0+x4 */
+ "subps %%xmm5, %%xmm7\n" /* yb = i*(x6-x2)+x0-x4 | -x6-x2+x0+x4 */
+
+ "movhps 24(%%eax), %%xmm1\n" /* x[3] | x[1] */
+ "movlps 40(%%eax), %%xmm2\n" /* x[5] */
+ "movhps 56(%%eax), %%xmm2\n" /* x[7] | x[5] */
+ "movaps %%xmm1, %%xmm3\n" /* x[3] | x[1] */
+ "addps %%xmm2, %%xmm1\n" /* x[3] + x[7] | x[1] + x[5] */
+ "subps %%xmm2, %%xmm3\n" /* x[3] - x[7] | x[1] - x[5] */
+ "movaps (%%ecx), %%xmm4\n" /* -1/sqrt2 | -1/sqrt2 | 1/sqrt2 | 1/sqrt2 */
+ "movaps %%xmm3, %%xmm6\n" /* x[3] - x[7] | x[1] - x[5] */
+ "mulps %%xmm4, %%xmm3\n" /* -1/s2*(x[3] - x[7]) | 1/s2*(x[1] - x[5]) */
+ "shufps $0xc8, %%xmm4, %%xmm4\n" /* -1/sqrt2 | 1/sqrt2 | -1/sqrt2 | 1/sqrt2 */
+ "shufps $0xb1, %%xmm6, %%xmm6\n" /* (x3-x7).re|(x3-x7).im|(x1-x5).re|(x1-x5).im */
+ "mulps %%xmm4, %%xmm6\n" /* (x7-x3).re/s2|(x3-x7).im/s2|(x5-x1).re/s2|(x1-x5).im/s2 */
+ "addps %%xmm3, %%xmm6\n" /* (-1-i)/sqrt2 * (x[3]-x[7]) | (1-i)/sqrt2 * (x[1] - x[5]) */
+ "movhlps %%xmm1, %%xmm5\n" /* x[3] + x[7] */
+ "movlhps %%xmm6, %%xmm1\n" /* (1+i)/sqrt2 * (x[1]-x[5]) | x[1]+x[5] */
+ "shufps $0xe4, %%xmm6, %%xmm5\n" /* (-1-i)/sqrt2 * (x[3]-x[7]) | x[3]+x[7] */
+ "movaps %%xmm1, %%xmm3\n" /* (1-i)/sqrt2 * (x[1]-x[5]) | x[1]+x[5] */
+ "addps %%xmm5, %%xmm1\n" /* u */
+ "subps %%xmm5, %%xmm3\n" /* v */
+ "movaps %%xmm0, %%xmm2\n" /* yb */
+ "movaps %%xmm7, %%xmm4\n" /* yt */
+ "movaps (%%edx), %%xmm5\n"
+ "mulps %%xmm5, %%xmm3\n"
+ "addps %%xmm1, %%xmm0\n" /* yt + u */
+ "subps %%xmm1, %%xmm2\n" /* yt - u */
+ "shufps $0xb1, %%xmm3, %%xmm3\n" /* -i * v */
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm2, 32(%%eax)\n"
+ "addps %%xmm3, %%xmm4\n" /* yb - i*v */
+ "subps %%xmm3, %%xmm7\n" /* yb + i*v */
+ "movaps %%xmm4, 16(%%eax)\n"
+ "movaps %%xmm7, 48(%%eax)\n"
+
+ : "=a" (x)
+ : "a" (x), "c" (hsqrt2_sse), "d" (C_1_sse));
+}
+
+static void fft_asmb_sse (ck_sse_t * ck, int k, complex_t *x, complex_t *wTB,
+ const complex_t *d, const complex_t *d_3)
+{
+ ck->k = k;
+
+ __asm__ __volatile__ (
+ ".align 16\n"
+ "pushl %%ebp\n"
+ "movl %%esp, %%ebp\n"
+
+ "subl $8, %%esp\n"
+
+ "pushl %%eax\n"
+ "pushl %%ebx\n"
+ "pushl %%ecx\n"
+ "pushl %%edx\n"
+ "pushl %%esi\n"
+ "pushl %%edi\n"
+
+ "movl 4(%%ecx), %%ebx\n"
+ "movl %%ebx, -4(%%ebp)\n"
+ "movl (%%ecx), %%ecx\n"
+
+ "movl %%ecx, -8(%%ebp)\n" /* k */
+ "addl $8, %%edx\n"
+ "addl $8, %%esi\n"
+ "shll $4, %%ecx\n" /* 16k */
+
+ /* TRANSZERO and TRANS */
+ ".align 16\n"
+ "movaps (%%eax), %%xmm0\n" /* x[1] | x[0] */
+ "movaps (%%edi), %%xmm1\n" /* wT[1] | wT[0] */
+ "movaps (%%edi, %%ecx), %%xmm2\n" /* wB[1] | wB[0] */
+ "movlps (%%edx), %%xmm3\n" /* d */
+ "movlps (%%esi), %%xmm4\n" /* d3 */
+ "movhlps %%xmm1, %%xmm5\n" /* wT[1] */
+ "movhlps %%xmm2, %%xmm6\n" /* wB[1] */
+ "shufps $0x50, %%xmm3, %%xmm3\n" /* d[1].im | d[1].im | d[1].re | d[1].re */
+ "shufps $0x50, %%xmm4, %%xmm4\n" /* d3[1].im | d3[1].im | d3[i].re | d3[i].re */
+ "movlhps %%xmm5, %%xmm5\n" /* wT[1] | wT[1] */
+ "movlhps %%xmm6, %%xmm6\n" /* wB[1] | wB[1] */
+ "mulps %%xmm3, %%xmm5\n"
+ "mulps %%xmm4, %%xmm6\n"
+ "movhlps %%xmm5, %%xmm7\n" /* wT[1].im * d[1].im | wT[1].re * d[1].im */
+ "movlhps %%xmm6, %%xmm5\n" /* wB[1].im * d3[1].re | wB[1].re * d3[1].re | wT[1].im * d[1].re | wT[1].re * d[1].re */
+ "shufps $0xb1, %%xmm6, %%xmm7\n" /* wB[1].re * d3[1].im | wB[i].im * d3[1].im | wT[1].re * d[1].im | wT[1].im * d[1].im */
+ "movl -4(%%ebp), %%ebx\n"
+ "movaps (%%ebx), %%xmm4\n"
+ "mulps %%xmm4, %%xmm7\n"
+ "addps %%xmm7, %%xmm5\n" /* wB[1] * d3[1] | wT[1] * d[1] */
+ "movlhps %%xmm5, %%xmm1\n" /* d[1] * wT[1] | wT[0] */
+ "shufps $0xe4, %%xmm5, %%xmm2\n" /* d3[1] * wB[1] | wB[0] */
+ "movaps %%xmm1, %%xmm3\n" /* d[1] * wT[1] | wT[0] */
+ "leal (%%eax, %%ecx, 2), %%ebx\n"
+ "addps %%xmm2, %%xmm1\n" /* u */
+ "subps %%xmm2, %%xmm3\n" /* v */
+ "mulps %%xmm4, %%xmm3\n"
+ "movaps (%%eax, %%ecx), %%xmm5\n" /* xk[1] | xk[0] */
+ "shufps $0xb1, %%xmm3, %%xmm3\n" /* -i * v */
+ "movaps %%xmm0, %%xmm2\n" /* x[1] | x[0] */
+ "movaps %%xmm5, %%xmm6\n" /* xk[1] | xk[0] */
+ "addps %%xmm1, %%xmm0\n"
+ "subps %%xmm1, %%xmm2\n"
+ "addps %%xmm3, %%xmm5\n"
+ "subps %%xmm3, %%xmm6\n"
+ "movaps %%xmm0, (%%eax)\n"
+ "movaps %%xmm2, (%%ebx)\n"
+ "movaps %%xmm5, (%%eax, %%ecx)\n"
+ "movaps %%xmm6, (%%ebx, %%ecx)\n"
+ "addl $16, %%eax\n"
+ "addl $16, %%edi\n"
+ "addl $8, %%edx\n"
+ "addl $8, %%esi\n"
+ "decl -8(%%ebp)\n"
+
+ ".align 16\n"
+"0:\n"
+ "movaps (%%edi), %%xmm0\n" /* wT[1] | wT[0] */
+ "movaps (%%edx), %%xmm1\n" /* d[1] | d[0] */
+
+ "movaps (%%edi, %%ecx), %%xmm4\n" /* wB[1] | wB[0] */
+ "movaps (%%esi), %%xmm5\n" /* d3[1] | d3[0] */
+
+ "movhlps %%xmm0, %%xmm2\n" /* wT[1] */
+ "movhlps %%xmm1, %%xmm3\n" /* d[1] */
+
+ "movhlps %%xmm4, %%xmm6\n" /* wB[1] */
+ "movhlps %%xmm5, %%xmm7\n" /* d3[1] */
+
+ "shufps $0x50, %%xmm1, %%xmm1\n" /* d[0].im | d[0].im | d[0].re | d[0].re */
+ "shufps $0x50, %%xmm3, %%xmm3\n" /* d[1].im | d[1].im | d[1].re | d[1].re */
+
+ "movlhps %%xmm0, %%xmm0\n" /* wT[0] | wT[0] */
+ "shufps $0x50, %%xmm5, %%xmm5\n" /* d3[0].im | d3[0].im | d3[0].re | d3[0].re */
+ "movlhps %%xmm2, %%xmm2\n" /* wT[1] | wT[1] */
+ "shufps $0x50, %%xmm7, %%xmm7\n" /* d3[1].im | d3[1].im | d3[1].re | d3[1].re */
+
+ "mulps %%xmm1, %%xmm0\n" /* d[0].im * wT[0].im | d[0].im * wT[0].re | d[0].re * wT[0].im | d[0].re * wT[0].re */
+ "mulps %%xmm3, %%xmm2\n" /* d[1].im * wT[1].im | d[1].im * wT[1].re | d[1].re * wT[1].im | d[1].re * wT[1].re */
+ "movlhps %%xmm4, %%xmm4\n" /* wB[0] | wB[0] */
+ "movlhps %%xmm6, %%xmm6\n" /* wB[1] | wB[1] */
+
+ "movhlps %%xmm0, %%xmm1\n" /* d[0].im * wT[0].im | d[0].im * wT[0].re */
+ "movlhps %%xmm2, %%xmm0\n" /* d[1].re * wT[1].im | d[1].re * wT[1].re | d[0].re * wT[0].im | d[0].re * wT[0].re */
+ "mulps %%xmm5, %%xmm4\n" /* wB[0].im * d3[0].im | wB[0].re * d3[0].im | wB[0].im * d3[0].re | wB[0].re * d3[0].re */
+ "mulps %%xmm7, %%xmm6\n" /* wB[1].im * d3[1].im | wB[1].re * d3[1].im | wB[1].im * d3[1].re | wB[1].re * d3[1].re */
+ "shufps $0xb1, %%xmm2, %%xmm1\n" /* d[1].im * wT[1].re | d[1].im * wT[1].im | d[0].im * wT[0].re | d[0].im * wT[0].im */
+ "movl -4(%%ebp), %%ebx\n"
+ "movaps (%%ebx), %%xmm3\n" /* 1.0 | -1.0 | 1.0 | -1.0 */
+
+ "movhlps %%xmm4, %%xmm5\n" /* wB[0].im * d3[0].im | wB[0].re * d3[0].im */
+ "mulps %%xmm3, %%xmm1\n" /* d[1].im * wT[1].re | -d[1].im * wT[1].im | d[0].im * wT[0].re | -d[0].im * wT[0].im */
+ "movlhps %%xmm6, %%xmm4\n" /* wB[1].im * d3[1].re | wB[1].re * d3[1].re | wB[0].im * d3[0].re | wB[0].im * d3[0].re */
+ "addps %%xmm1, %%xmm0\n" /* wT[1] * d[1] | wT[0] * d[0] */
+
+ "shufps $0xb1, %%xmm6, %%xmm5\n" /* wB[1].re * d3[1].im | wB[1].im * d3[1].im | wB[0].re * d3[0].im | wB[0].im * d3[0].im */
+ "mulps %%xmm3, %%xmm5\n" /* wB[1].re * d3[1].im | -wB[1].im * d3[1].im | wB[0].re * d3[0].im | -wB[0].im * d3[0].im */
+ "addps %%xmm5, %%xmm4\n" /* wB[1] * d3[1] | wB[0] * d3[0] */
+
+ "movaps %%xmm0, %%xmm1\n" /* wT[1] * d[1] | wT[0] * d[0] */
+ "addps %%xmm4, %%xmm0\n" /* u */
+ "subps %%xmm4, %%xmm1\n" /* v */
+ "movaps (%%eax), %%xmm6\n" /* x[1] | x[0] */
+ "leal (%%eax, %%ecx, 2), %%ebx\n"
+ "mulps %%xmm3, %%xmm1\n"
+ "addl $16, %%edi\n"
+ "addl $16, %%esi\n"
+ "shufps $0xb1, %%xmm1, %%xmm1\n" /* -i * v */
+ "movaps (%%eax, %%ecx), %%xmm7\n" /* xk[1] | xk[0] */
+ "movaps %%xmm6, %%xmm2\n"
+ "movaps %%xmm7, %%xmm4\n"
+ "addps %%xmm0, %%xmm6\n"
+ "subps %%xmm0, %%xmm2\n"
+ "movaps %%xmm6, (%%eax)\n"
+ "movaps %%xmm2, (%%ebx)\n"
+ "addps %%xmm1, %%xmm7\n"
+ "subps %%xmm1, %%xmm4\n"
+ "addl $16, %%edx\n"
+ "movaps %%xmm7, (%%eax, %%ecx)\n"
+ "movaps %%xmm4, (%%ebx, %%ecx)\n"
+
+ "addl $16, %%eax\n"
+ "decl -8(%%ebp)\n"
+ "jnz 0b\n"
+
+ ".align 16\n"
+"1:\n"
+ "popl %%edi\n"
+ "popl %%esi\n"
+ "popl %%edx\n"
+ "popl %%ecx\n"
+ "popl %%ebx\n"
+ "popl %%eax\n"
+
+ "addl $8, %%esp\n"
+
+ "leave\n"
+ : "=a" (x), "=D" (wTB)
+ : "c" (ck), "a" (x), "D" (wTB), "d" (d), "S" (d_3) );
+}
--- /dev/null
+/*****************************************************************************
+ * internals.h: needed by the A52 decoder
+ *****************************************************************************
+ * Copyright (C) 2000 VideoLAN
+ * $Id: internal.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Lespinasse <walken@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/* Exponent strategy constants */
+#define EXP_REUSE (0)
+#define EXP_D15 (1)
+#define EXP_D25 (2)
+#define EXP_D45 (3)
+
+/* Delta bit allocation constants */
+#define DELTA_BIT_REUSE (0)
+#define DELTA_BIT_NEW (1)
+#define DELTA_BIT_NONE (2)
+#define DELTA_BIT_RESERVED (3)
+
+/* bit_allocate.c */
+void bit_allocate (a52dec_t *);
+
+/* exponent.c */
+int exponent_unpack (a52dec_t *);
+
+/* imdct.c */
+void E_( imdct_init )(imdct_t * p_imdct);
+void imdct (a52dec_t * p_a52dec, s16 * buffer);
+
+/* mantissa.c */
+void mantissa_unpack (a52dec_t *);
+
+/* parse.c */
+int parse_bsi (a52dec_t *);
+int parse_audblk (a52dec_t *, int);
+void parse_auxdata (a52dec_t *);
+
+/* rematrix.c */
+void rematrix (a52dec_t *);
+
--- /dev/null
+/*****************************************************************************
+ * mantissa.c: A52 mantissa computation
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: mantissa.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ * Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h"
+
+#include "mantissa.h"
+
+void mantissa_unpack (a52dec_t * p_a52dec)
+{
+ int i, j;
+ u32 done_cpl = 0;
+
+ p_a52dec->mantissa.q_1_pointer = -1;
+ p_a52dec->mantissa.q_2_pointer = -1;
+ p_a52dec->mantissa.q_4_pointer = -1;
+
+ for (i=0; i< p_a52dec->bsi.nfchans; i++) {
+ for (j=0; j < p_a52dec->audblk.endmant[i]; j++)
+ *(p_a52dec->samples+i*256+j) = coeff_get_float(p_a52dec, p_a52dec->audblk.fbw_bap[i][j],
+ p_a52dec->audblk.dithflag[i], p_a52dec->audblk.fbw_exp[i][j]);
+
+ if (p_a52dec->audblk.cplinu && p_a52dec->audblk.chincpl[i] && !(done_cpl)) {
+ /* ncplmant is equal to 12 * ncplsubnd
+ * Don't dither coupling channel until channel
+ * separation so that interchannel noise is uncorrelated
+ */
+ for (j=p_a52dec->audblk.cplstrtmant; j < p_a52dec->audblk.cplendmant; j++)
+ p_a52dec->audblk.cpl_flt[j] = coeff_get_float(p_a52dec, p_a52dec->audblk.cpl_bap[j],
+ 0, p_a52dec->audblk.cpl_exp[j]);
+ done_cpl = 1;
+ }
+ }
+
+ /* uncouple the channel if necessary */
+ if (p_a52dec->audblk.cplinu) {
+ for (i=0; i< p_a52dec->bsi.nfchans; i++) {
+ if (p_a52dec->audblk.chincpl[i])
+ uncouple_channel(p_a52dec, i);
+ }
+ }
+
+ if (p_a52dec->bsi.lfeon) {
+ /* There are always 7 mantissas for lfe, no dither for lfe */
+ for (j=0; j < 7 ; j++)
+ *(p_a52dec->samples+5*256+j) = coeff_get_float(p_a52dec, p_a52dec->audblk.lfe_bap[j],
+ 0, p_a52dec->audblk.lfe_exp[j]);
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * mantissa.h: A52 mantissa computation
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: mantissa.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ * Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#define Q0 ((-2 << 15) / 3.0)
+#define Q1 (0)
+#define Q2 ((2 << 15) / 3.0)
+static const float q_1_0[ 32 ] =
+{
+ Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
+ Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
+ Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
+ 0, 0, 0, 0, 0
+};
+static const float q_1_1[ 32 ] =
+{
+ Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
+ Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
+ Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
+ 0, 0, 0, 0, 0
+};
+static const float q_1_2[ 32 ] =
+{
+ Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
+ Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
+ Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
+ 0, 0, 0, 0, 0
+};
+#undef Q0
+#undef Q1
+#undef Q2
+
+#define Q0 ((-4 << 15) / 5.0)
+#define Q1 ((-2 << 15) / 5.0)
+#define Q2 (0)
+#define Q3 ((2 << 15) / 5.0)
+#define Q4 ((4 << 15) / 5.0)
+static const float q_2_0[ 128 ] =
+{
+ Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
+ Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,
+ Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,
+ 0, 0, 0
+};
+static const float q_2_1[ 128 ] =
+{
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ 0, 0, 0
+};
+static const float q_2_2[ 128 ] =
+{
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ 0, 0, 0
+};
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+
+#define Q0 ((-10 << 15) / 11.0)
+#define Q1 ((-8 << 15) / 11.0)
+#define Q2 ((-6 << 15) / 11.0)
+#define Q3 ((-4 << 15) / 11.0)
+#define Q4 ((-2 << 15) / 11.0)
+#define Q5 (0)
+#define Q6 ((2 << 15) / 11.0)
+#define Q7 ((4 << 15) / 11.0)
+#define Q8 ((6 << 15) / 11.0)
+#define Q9 ((8 << 15) / 11.0)
+#define QA ((10 << 15) / 11.0)
+static const float q_4_0[ 128 ] =
+{
+ Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
+ Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
+ Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
+ Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3,
+ Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4,
+ Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5,
+ Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6,
+ Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7,
+ Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8,
+ Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9,
+ QA, QA, QA, QA, QA, QA, QA, QA, QA, QA, QA,
+ 0, 0, 0, 0, 0, 0, 0
+};
+static const float q_4_1[ 128 ] =
+{
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ 0, 0, 0, 0, 0, 0, 0
+};
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+#undef Q5
+#undef Q6
+#undef Q7
+#undef Q8
+#undef Q9
+#undef QA
+
+/* Lookup tables of 0.16 two's complement quantization values */
+
+static const float q_3[8] =
+{
+ (-6 << 15)/7.0, (-4 << 15)/7.0, (-2 << 15)/7.0,
+ 0 , (2 << 15)/7.0, (4 << 15)/7.0,
+ (6 << 15)/7.0, 0
+};
+
+static const float q_5[16] =
+{
+ (-14 << 15)/15.0, (-12 << 15)/15.0, (-10 << 15)/15.0,
+ (-8 << 15)/15.0, (-6 << 15)/15.0, (-4 << 15)/15.0,
+ (-2 << 15)/15.0, 0 , (2 << 15)/15.0,
+ (4 << 15)/15.0, (6 << 15)/15.0, (8 << 15)/15.0,
+ (10 << 15)/15.0, (12 << 15)/15.0, (14 << 15)/15.0,
+ 0
+};
+
+/* Conversion from bap to number of bits in the mantissas
+ * zeros account for cases 0,1,2,4 which are special cased */
+static const u16 qnttztab[16] =
+{
+ 0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16
+};
+
+static const float scale_factor[25] =
+{
+ 6.10351562500000000000000000e-05,
+ 3.05175781250000000000000000e-05,
+ 1.52587890625000000000000000e-05,
+ 7.62939453125000000000000000e-06,
+ 3.81469726562500000000000000e-06,
+ 1.90734863281250000000000000e-06,
+ 9.53674316406250000000000000e-07,
+ 4.76837158203125000000000000e-07,
+ 2.38418579101562500000000000e-07,
+ 1.19209289550781250000000000e-07,
+ 5.96046447753906250000000000e-08,
+ 2.98023223876953125000000000e-08,
+ 1.49011611938476562500000000e-08,
+ 7.45058059692382812500000000e-09,
+ 3.72529029846191406250000000e-09,
+ 1.86264514923095703125000000e-09,
+ 9.31322574615478515625000000e-10,
+ 4.65661287307739257812500000e-10,
+ 2.32830643653869628906250000e-10,
+ 1.16415321826934814453125000e-10,
+ 5.82076609134674072265625000e-11,
+ 2.91038304567337036132812500e-11,
+ 1.45519152283668518066406250e-11,
+ 7.27595761418342590332031250e-12,
+ 3.63797880709171295166015625e-12,
+};
+
+static const u16 dither_lut[256] =
+{
+ 0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055,
+ 0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb,
+ 0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198,
+ 0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176,
+ 0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf,
+ 0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321,
+ 0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202,
+ 0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec,
+ 0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761,
+ 0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f,
+ 0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac,
+ 0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642,
+ 0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb,
+ 0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415,
+ 0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536,
+ 0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8,
+ 0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c,
+ 0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2,
+ 0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1,
+ 0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f,
+ 0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6,
+ 0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58,
+ 0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b,
+ 0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95,
+ 0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918,
+ 0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6,
+ 0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5,
+ 0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b,
+ 0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82,
+ 0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c,
+ 0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f,
+ 0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1
+};
+
+static inline u16 dither_gen (mantissa_t * p_mantissa)
+{
+ s16 state;
+
+ state = dither_lut[p_mantissa->lfsr_state >> 8] ^
+ (p_mantissa->lfsr_state << 8);
+ p_mantissa->lfsr_state = (u16) state;
+ return ( (state * (s32) (0.707106 * 256.0)) >> 8 );
+}
+
+
+/* Fetch an unpacked, left justified, and properly biased/dithered mantissa value */
+static inline float coeff_get_float( a52dec_t * p_a52dec, u16 bap, u16 dithflag,
+ u16 exp )
+{
+ u16 group_code = 0;
+
+ /* If the bap is 0-5 then we have special cases to take care of */
+ switch (bap)
+ {
+ case 0:
+ if (dithflag)
+ {
+ return ( dither_gen(&p_a52dec->mantissa) * scale_factor[exp] );
+ }
+ return (0);
+
+ case 1:
+ if (p_a52dec->mantissa.q_1_pointer >= 0)
+ {
+ return (p_a52dec->mantissa.q_1[p_a52dec->mantissa.q_1_pointer--] *
+ scale_factor[exp]);
+ }
+
+ p_a52dec->total_bits_read += 5;
+ if ((group_code = GetBits (&p_a52dec->bit_stream,5)) > 26)
+ {
+ msg_Warn( p_a52dec->p_fifo, "invalid mantissa (1)" );
+ return 0;
+ }
+
+ p_a52dec->mantissa.q_1[ 1 ] = q_1_1[ group_code ];
+ p_a52dec->mantissa.q_1[ 0 ] = q_1_2[ group_code ];
+
+ p_a52dec->mantissa.q_1_pointer = 1;
+
+ return (q_1_0[group_code] * scale_factor[exp]);
+
+ case 2:
+ if (p_a52dec->mantissa.q_2_pointer >= 0)
+ {
+ return (p_a52dec->mantissa.q_2[p_a52dec->mantissa.q_2_pointer--] *
+ scale_factor[exp]);
+ }
+
+ p_a52dec->total_bits_read += 7;
+ if ((group_code = GetBits (&p_a52dec->bit_stream,7)) > 124)
+ {
+ msg_Warn( p_a52dec->p_fifo, "invalid mantissa (2)" );
+ return 0;
+ }
+
+ p_a52dec->mantissa.q_2[ 1 ] = q_2_1[ group_code ];
+ p_a52dec->mantissa.q_2[ 0 ] = q_2_2[ group_code ];
+
+ p_a52dec->mantissa.q_2_pointer = 1;
+
+ return (q_2_0[group_code] * scale_factor[exp]);
+
+ case 3:
+ p_a52dec->total_bits_read += 3;
+ if ((group_code = GetBits (&p_a52dec->bit_stream,3)) > 6)
+ {
+ msg_Warn( p_a52dec->p_fifo, "invalid mantissa (3)" );
+ return 0;
+ }
+
+ return (q_3[group_code] * scale_factor[exp]);
+
+ case 4:
+ if (p_a52dec->mantissa.q_4_pointer >= 0)
+ {
+ return (p_a52dec->mantissa.q_4[p_a52dec->mantissa.q_4_pointer--] *
+ scale_factor[exp]);
+ }
+
+ p_a52dec->total_bits_read += 7;
+ if ((group_code = GetBits (&p_a52dec->bit_stream,7)) > 120)
+ {
+ msg_Warn( p_a52dec->p_fifo, "invalid mantissa (4)" );
+ return 0;
+ }
+
+ p_a52dec->mantissa.q_4[ 0 ] = q_4_1[group_code];
+
+ p_a52dec->mantissa.q_4_pointer = 0;
+
+ return (q_4_0[group_code] * scale_factor[exp]);
+
+ case 5:
+ p_a52dec->total_bits_read += 4;
+ if ((group_code = GetBits (&p_a52dec->bit_stream,4)) > 14)
+ {
+ msg_Warn( p_a52dec->p_fifo, "invalid mantissa (5)" );
+ return 0;
+ }
+
+ return (q_5[group_code] * scale_factor[exp]);
+
+ default:
+ group_code = GetBits (&p_a52dec->bit_stream,qnttztab[bap]);
+ group_code <<= 16 - qnttztab[bap];
+ p_a52dec->total_bits_read += qnttztab[bap];
+
+ return ((s16)(group_code) * scale_factor[exp]);
+ }
+}
+
+/* Uncouple the coupling channel into a fbw channel */
+static inline void uncouple_channel (a52dec_t * p_a52dec, u32 ch)
+{
+ u32 bnd = 0;
+ u32 sub_bnd = 0;
+ u32 i,j;
+ float cpl_coord = 1.0;
+ u32 cpl_exp_tmp;
+ u32 cpl_mant_tmp;
+
+ for (i = p_a52dec->audblk.cplstrtmant; i < p_a52dec->audblk.cplendmant;)
+ {
+ if (!p_a52dec->audblk.cplbndstrc[sub_bnd++])
+ {
+ cpl_exp_tmp = p_a52dec->audblk.cplcoexp[ch][bnd] +
+ 3 * p_a52dec->audblk.mstrcplco[ch];
+ if (p_a52dec->audblk.cplcoexp[ch][bnd] == 15)
+ {
+ cpl_mant_tmp = (p_a52dec->audblk.cplcomant[ch][bnd]) << 11;
+ }
+ else
+ {
+ cpl_mant_tmp = ((0x10) | p_a52dec->audblk.cplcomant[ch][bnd]) << 10;
+ }
+ cpl_coord = (cpl_mant_tmp) * scale_factor[cpl_exp_tmp] * 8.0f;
+
+ /* Invert the phase for the right channel if necessary */
+ if (p_a52dec->bsi.acmod == 0x02 && p_a52dec->audblk.phsflginu &&
+ ch == 1 && p_a52dec->audblk.phsflg[bnd])
+ {
+ cpl_coord *= -1;
+ }
+ bnd++;
+ }
+
+ for (j=0;j < 12; j++)
+ {
+ /* Get new dither values for each channel if necessary,
+ * so the channels are uncorrelated */
+ if (p_a52dec->audblk.dithflag[ch] && !p_a52dec->audblk.cpl_bap[i])
+ {
+ *(p_a52dec->samples+ch*256+i) = cpl_coord * dither_gen(&p_a52dec->mantissa) *
+ scale_factor[p_a52dec->audblk.cpl_exp[i]];
+ } else {
+ *(p_a52dec->samples+ch*256+i) = cpl_coord * p_a52dec->audblk.cpl_flt[i];
+ }
+ i++;
+ }
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * parse.c: A52 parsing procedures
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: parse.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ * Renaud Dartus <reno@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h"
+
+#include "internal.h" /* EXP_REUSE */
+
+/* Misc LUT */
+static const u16 nfchans[] = { 2, 1, 2, 3, 3, 4, 4, 5 };
+
+struct frmsize_s
+{
+ u16 bit_rate;
+ u16 frm_size[3];
+};
+
+static const struct frmsize_s frmsizecod_tbl[] =
+{
+ { 32 ,{64 ,69 ,96 } },
+ { 32 ,{64 ,70 ,96 } },
+ { 40 ,{80 ,87 ,120 } },
+ { 40 ,{80 ,88 ,120 } },
+ { 48 ,{96 ,104 ,144 } },
+ { 48 ,{96 ,105 ,144 } },
+ { 56 ,{112 ,121 ,168 } },
+ { 56 ,{112 ,122 ,168 } },
+ { 64 ,{128 ,139 ,192 } },
+ { 64 ,{128 ,140 ,192 } },
+ { 80 ,{160 ,174 ,240 } },
+ { 80 ,{160 ,175 ,240 } },
+ { 96 ,{192 ,208 ,288 } },
+ { 96 ,{192 ,209 ,288 } },
+ { 112 ,{224 ,243 ,336 } },
+ { 112 ,{224 ,244 ,336 } },
+ { 128 ,{256 ,278 ,384 } },
+ { 128 ,{256 ,279 ,384 } },
+ { 160 ,{320 ,348 ,480 } },
+ { 160 ,{320 ,349 ,480 } },
+ { 192 ,{384 ,417 ,576 } },
+ { 192 ,{384 ,418 ,576 } },
+ { 224 ,{448 ,487 ,672 } },
+ { 224 ,{448 ,488 ,672 } },
+ { 256 ,{512 ,557 ,768 } },
+ { 256 ,{512 ,558 ,768 } },
+ { 320 ,{640 ,696 ,960 } },
+ { 320 ,{640 ,697 ,960 } },
+ { 384 ,{768 ,835 ,1152 } },
+ { 384 ,{768 ,836 ,1152 } },
+ { 448 ,{896 ,975 ,1344 } },
+ { 448 ,{896 ,976 ,1344 } },
+ { 512 ,{1024 ,1114 ,1536 } },
+ { 512 ,{1024 ,1115 ,1536 } },
+ { 576 ,{1152 ,1253 ,1728 } },
+ { 576 ,{1152 ,1254 ,1728 } },
+ { 640 ,{1280 ,1393 ,1920 } },
+ { 640 ,{1280 ,1394 ,1920 } }};
+
+static const int fscod_tbl[] = {48000, 44100, 32000};
+
+/* Some internal functions */
+static void parse_bsi_stats (a52dec_t * p_a52dec);
+static void parse_audblk_stats (a52dec_t * p_a52dec);
+
+/* Parse a syncinfo structure */
+int sync_frame (a52dec_t * p_a52dec, sync_info_t * p_sync_info)
+{
+ p_a52dec->total_bits_read = 0;
+ p_a52dec->i_available = 0;
+
+ /* sync word - should be 0x0b77 */
+ RealignBits(&p_a52dec->bit_stream);
+ while( (ShowBits (&p_a52dec->bit_stream,16)) != 0x0b77 &&
+ (!p_a52dec->p_fifo->b_die) && (!p_a52dec->p_fifo->b_error))
+ {
+ RemoveBits (&p_a52dec->bit_stream,8);
+ p_a52dec->total_bits_read += 8;
+ }
+ RemoveBits (&p_a52dec->bit_stream,16);
+ p_a52dec->total_bits_read += 16;
+
+
+ /* Get crc1 - we don't actually use this data though */
+ GetBits (&p_a52dec->bit_stream,16);
+
+ /* Get the sampling rate */
+ p_a52dec->syncinfo.fscod = GetBits (&p_a52dec->bit_stream,2);
+
+ if (p_a52dec->syncinfo.fscod >= 3)
+ {
+ p_a52dec->total_bits_read += 34;
+ return 1;
+ }
+
+ /* Get the frame size code */
+ p_a52dec->syncinfo.frmsizecod = GetBits (&p_a52dec->bit_stream,6);
+ p_a52dec->total_bits_read += 40;
+
+ if (p_a52dec->syncinfo.frmsizecod >= 38)
+ {
+ return 1;
+ }
+
+ p_sync_info->bit_rate = frmsizecod_tbl[p_a52dec->syncinfo.frmsizecod].bit_rate;
+
+ p_a52dec->syncinfo.frame_size = frmsizecod_tbl[p_a52dec->syncinfo.frmsizecod].frm_size[p_a52dec->syncinfo.fscod];
+ p_sync_info->frame_size = 2 * p_a52dec->syncinfo.frame_size;
+
+ p_sync_info->sample_rate = fscod_tbl[p_a52dec->syncinfo.fscod];
+
+ return 0;
+}
+
+/*
+ * This routine fills a bsi struct from the A52 stream
+ */
+int parse_bsi (a52dec_t * p_a52dec)
+{
+ /* Check the AC-3 version number */
+ p_a52dec->bsi.bsid = GetBits (&p_a52dec->bit_stream,5);
+
+ if (p_a52dec->bsi.bsid > 8)
+ {
+ return 1;
+ }
+
+ /* Get the audio service provided by the stream */
+ p_a52dec->bsi.bsmod = GetBits (&p_a52dec->bit_stream,3);
+
+ /* Get the audio coding mode (ie how many channels)*/
+ p_a52dec->bsi.acmod = GetBits (&p_a52dec->bit_stream,3);
+
+ /* Predecode the number of full bandwidth channels as we use this
+ * number a lot */
+ p_a52dec->bsi.nfchans = nfchans[p_a52dec->bsi.acmod];
+
+ /* If it is in use, get the centre channel mix level */
+ if ((p_a52dec->bsi.acmod & 0x1) && (p_a52dec->bsi.acmod != 0x1))
+ {
+ p_a52dec->bsi.cmixlev = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+ }
+
+ /* If it is in use, get the surround channel mix level */
+ if (p_a52dec->bsi.acmod & 0x4)
+ {
+ p_a52dec->bsi.surmixlev = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+ }
+
+ /* Get the dolby surround mode if in 2/0 mode */
+ if (p_a52dec->bsi.acmod == 0x2)
+ {
+ p_a52dec->bsi.dsurmod = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+ }
+
+ /* Is the low frequency effects channel on? */
+ p_a52dec->bsi.lfeon = GetBits (&p_a52dec->bit_stream,1);
+
+ /* Get the dialogue normalization level */
+ p_a52dec->bsi.dialnorm = GetBits (&p_a52dec->bit_stream,5);
+
+ /* Does compression gain exist? */
+ if ((p_a52dec->bsi.compre = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get compression gain */
+ p_a52dec->bsi.compr = GetBits (&p_a52dec->bit_stream,8);
+ p_a52dec->total_bits_read += 8;
+ }
+
+ /* Does language code exist? */
+ if ((p_a52dec->bsi.langcode = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get langauge code */
+ p_a52dec->bsi.langcod = GetBits (&p_a52dec->bit_stream,8);
+ p_a52dec->total_bits_read += 8;
+ }
+
+ /* Does audio production info exist? */
+ if ((p_a52dec->bsi.audprodie = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get mix level */
+ p_a52dec->bsi.mixlevel = GetBits (&p_a52dec->bit_stream,5);
+
+ /* Get room type */
+ p_a52dec->bsi.roomtyp = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 7;
+ }
+
+ /* If we're in dual mono mode then get some extra info */
+ if (p_a52dec->bsi.acmod == 0)
+ {
+ /* Get the dialogue normalization level two */
+ p_a52dec->bsi.dialnorm2 = GetBits (&p_a52dec->bit_stream,5);
+
+ /* Does compression gain two exist? */
+ if ((p_a52dec->bsi.compr2e = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get compression gain two */
+ p_a52dec->bsi.compr2 = GetBits (&p_a52dec->bit_stream,8);
+ p_a52dec->total_bits_read += 8;
+ }
+
+ /* Does language code two exist? */
+ if ((p_a52dec->bsi.langcod2e = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get langauge code two */
+ p_a52dec->bsi.langcod2 = GetBits (&p_a52dec->bit_stream,8);
+ p_a52dec->total_bits_read += 8;
+ }
+
+ /* Does audio production info two exist? */
+ if ((p_a52dec->bsi.audprodi2e = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get mix level two */
+ p_a52dec->bsi.mixlevel2 = GetBits (&p_a52dec->bit_stream,5);
+
+ /* Get room type two */
+ p_a52dec->bsi.roomtyp2 = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 7;
+ }
+ p_a52dec->total_bits_read += 8;
+ }
+
+ /* Get the copyright bit */
+ p_a52dec->bsi.copyrightb = GetBits (&p_a52dec->bit_stream,1);
+
+ /* Get the original bit */
+ p_a52dec->bsi.origbs = GetBits (&p_a52dec->bit_stream,1);
+
+ /* Does timecode one exist? */
+ if ((p_a52dec->bsi.timecod1e = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ p_a52dec->bsi.timecod1 = GetBits (&p_a52dec->bit_stream,14);
+ p_a52dec->total_bits_read += 14;
+ }
+
+ /* Does timecode two exist? */
+ if ((p_a52dec->bsi.timecod2e = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ p_a52dec->bsi.timecod2 = GetBits (&p_a52dec->bit_stream,14);
+ p_a52dec->total_bits_read += 14;
+ }
+
+ /* Does addition info exist? */
+ if ((p_a52dec->bsi.addbsie = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ u32 i;
+
+ /* Get how much info is there */
+ p_a52dec->bsi.addbsil = GetBits (&p_a52dec->bit_stream,6);
+
+ /* Get the additional info */
+ for (i=0;i<(p_a52dec->bsi.addbsil + 1);i++)
+ {
+ p_a52dec->bsi.addbsi[i] = GetBits (&p_a52dec->bit_stream,8);
+ }
+ p_a52dec->total_bits_read += 6 + 8 * (p_a52dec->bsi.addbsil + 1);
+ }
+ p_a52dec->total_bits_read += 25;
+
+ parse_bsi_stats (p_a52dec);
+
+ return 0;
+}
+
+/* More pain inducing parsing */
+int parse_audblk (a52dec_t * p_a52dec, int blknum)
+{
+ int i, j;
+
+ for (i=0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ /* Is this channel an interleaved 256 + 256 block ? */
+ p_a52dec->audblk.blksw[i] = GetBits (&p_a52dec->bit_stream,1);
+ }
+
+ for (i=0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ /* Should we dither this channel? */
+ p_a52dec->audblk.dithflag[i] = GetBits (&p_a52dec->bit_stream,1);
+ }
+
+ /* Does dynamic range control exist? */
+ if ((p_a52dec->audblk.dynrnge = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get dynamic range info */
+ p_a52dec->audblk.dynrng = GetBits (&p_a52dec->bit_stream,8);
+ p_a52dec->total_bits_read += 8;
+ }
+
+ /* If we're in dual mono mode then get the second channel DR info */
+ if (p_a52dec->bsi.acmod == 0)
+ {
+ /* Does dynamic range control two exist? */
+ if ((p_a52dec->audblk.dynrng2e = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ /* Get dynamic range info */
+ p_a52dec->audblk.dynrng2 = GetBits (&p_a52dec->bit_stream,8);
+ p_a52dec->total_bits_read += 8;
+ }
+ p_a52dec->total_bits_read += 1;
+ }
+
+ /* Does coupling strategy exist? */
+ p_a52dec->audblk.cplstre = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 2 + 2 * p_a52dec->bsi.nfchans;
+
+ if ((!blknum) && (!p_a52dec->audblk.cplstre))
+ {
+ return 1;
+ }
+
+ if (p_a52dec->audblk.cplstre)
+ {
+ /* Is coupling turned on? */
+ if ((p_a52dec->audblk.cplinu = GetBits (&p_a52dec->bit_stream,1)))
+ {
+ int nb_coupled_channels;
+
+ nb_coupled_channels = 0;
+ for (i=0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ p_a52dec->audblk.chincpl[i] = GetBits (&p_a52dec->bit_stream,1);
+ if (p_a52dec->audblk.chincpl[i])
+ {
+ nb_coupled_channels++;
+ }
+ }
+ p_a52dec->total_bits_read += p_a52dec->bsi.nfchans;
+
+ if (nb_coupled_channels < 2)
+ {
+ return 1;
+ }
+
+ if (p_a52dec->bsi.acmod == 0x2)
+ {
+ p_a52dec->audblk.phsflginu = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 1;
+ }
+ p_a52dec->audblk.cplbegf = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.cplendf = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->total_bits_read += 8;
+
+ if (p_a52dec->audblk.cplbegf > p_a52dec->audblk.cplendf + 2)
+ {
+ return 1;
+ }
+
+ p_a52dec->audblk.ncplsubnd = (p_a52dec->audblk.cplendf + 2) - p_a52dec->audblk.cplbegf + 1;
+
+ /* Calculate the start and end bins of the coupling channel */
+ p_a52dec->audblk.cplstrtmant = (p_a52dec->audblk.cplbegf * 12) + 37 ;
+ p_a52dec->audblk.cplendmant = ((p_a52dec->audblk.cplendf + 3) * 12) + 37;
+
+ /* The number of combined subbands is ncplsubnd minus each combined
+ * band */
+ p_a52dec->audblk.ncplbnd = p_a52dec->audblk.ncplsubnd;
+
+ for (i=1; i< p_a52dec->audblk.ncplsubnd; i++)
+ {
+ p_a52dec->audblk.cplbndstrc[i] = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->audblk.ncplbnd -= p_a52dec->audblk.cplbndstrc[i];
+ }
+ p_a52dec->total_bits_read += p_a52dec->audblk.ncplsubnd - 1;
+ }
+ p_a52dec->total_bits_read += 1;
+ }
+
+ if (p_a52dec->audblk.cplinu)
+ {
+ /* Loop through all the channels and get their coupling co-ords */
+ for (i=0; i < p_a52dec->bsi.nfchans;i++)
+ {
+ if (!p_a52dec->audblk.chincpl[i])
+ {
+ continue;
+ }
+
+ /* Is there new coupling co-ordinate info? */
+ p_a52dec->audblk.cplcoe[i] = GetBits (&p_a52dec->bit_stream,1);
+
+ if ((!blknum) && (!p_a52dec->audblk.cplcoe[i]))
+ {
+ return 1;
+ }
+
+ if (p_a52dec->audblk.cplcoe[i])
+ {
+ p_a52dec->audblk.mstrcplco[i] = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+ for (j=0;j < p_a52dec->audblk.ncplbnd; j++)
+ {
+ p_a52dec->audblk.cplcoexp[i][j] = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.cplcomant[i][j] = GetBits (&p_a52dec->bit_stream,4);
+ }
+ p_a52dec->total_bits_read += 8 * p_a52dec->audblk.ncplbnd;
+ }
+ }
+ p_a52dec->total_bits_read += p_a52dec->bsi.nfchans;
+
+ /* If we're in dual mono mode, there's going to be some phase info */
+ if ((p_a52dec->bsi.acmod == 0x2) && p_a52dec->audblk.phsflginu &&
+ (p_a52dec->audblk.cplcoe[0] || p_a52dec->audblk.cplcoe[1]))
+ {
+ for (j=0; j < p_a52dec->audblk.ncplbnd; j++)
+ {
+ p_a52dec->audblk.phsflg[j] = GetBits (&p_a52dec->bit_stream,1);
+ }
+ p_a52dec->total_bits_read += p_a52dec->audblk.ncplbnd;
+
+ }
+ }
+
+ /* If we're in dual mono mode, there may be a rematrix strategy */
+ if (p_a52dec->bsi.acmod == 0x2)
+ {
+ p_a52dec->audblk.rematstr = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 1;
+
+ if ((!blknum) && (!p_a52dec->audblk.rematstr))
+ {
+ return 1;
+ }
+
+ if (p_a52dec->audblk.rematstr)
+ {
+ if (p_a52dec->audblk.cplinu == 0)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ p_a52dec->audblk.rematflg[i] = GetBits (&p_a52dec->bit_stream,1);
+ }
+ p_a52dec->total_bits_read += 4;
+ }
+ if ((p_a52dec->audblk.cplbegf > 2) && p_a52dec->audblk.cplinu)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ p_a52dec->audblk.rematflg[i] = GetBits (&p_a52dec->bit_stream,1);
+ }
+ p_a52dec->total_bits_read += 4;
+ }
+ if ((p_a52dec->audblk.cplbegf <= 2) && p_a52dec->audblk.cplinu)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ p_a52dec->audblk.rematflg[i] = GetBits (&p_a52dec->bit_stream,1);
+ }
+ p_a52dec->total_bits_read += 3;
+ }
+ if ((p_a52dec->audblk.cplbegf == 0) && p_a52dec->audblk.cplinu)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ p_a52dec->audblk.rematflg[i] = GetBits (&p_a52dec->bit_stream,1);
+ }
+ p_a52dec->total_bits_read += 2;
+ }
+ }
+ }
+
+ if (p_a52dec->audblk.cplinu)
+ {
+ /* Get the coupling channel exponent strategy */
+ p_a52dec->audblk.cplexpstr = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+
+ if ((!blknum) && (p_a52dec->audblk.cplexpstr == EXP_REUSE))
+ {
+ return 1;
+ }
+
+ if (p_a52dec->audblk.cplexpstr==0)
+ {
+ p_a52dec->audblk.ncplgrps = 0;
+ }
+ else
+ {
+ p_a52dec->audblk.ncplgrps = (p_a52dec->audblk.cplendmant - p_a52dec->audblk.cplstrtmant) /
+ (3 << (p_a52dec->audblk.cplexpstr-1));
+ }
+
+ }
+
+ for (i = 0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ p_a52dec->audblk.chexpstr[i] = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+
+ if ((!blknum) && (p_a52dec->audblk.chexpstr[i] == EXP_REUSE))
+ {
+ return 1;
+ }
+ }
+
+ /* Get the exponent strategy for lfe channel */
+ if (p_a52dec->bsi.lfeon)
+ {
+ p_a52dec->audblk.lfeexpstr = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 1;
+
+ if ((!blknum) && (p_a52dec->audblk.lfeexpstr == EXP_REUSE))
+ {
+ return 1;
+ }
+ }
+
+ /* Determine the bandwidths of all the fbw channels */
+ for (i = 0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ u16 grp_size;
+
+ if (p_a52dec->audblk.chexpstr[i] != EXP_REUSE)
+ {
+ if (p_a52dec->audblk.cplinu && p_a52dec->audblk.chincpl[i])
+ {
+ p_a52dec->audblk.endmant[i] = p_a52dec->audblk.cplstrtmant;
+ }
+ else
+ {
+ p_a52dec->audblk.chbwcod[i] = GetBits (&p_a52dec->bit_stream,6);
+ p_a52dec->total_bits_read += 6;
+
+ if (p_a52dec->audblk.chbwcod[i] > 60)
+ {
+ return 1;
+ }
+
+ p_a52dec->audblk.endmant[i] = ((p_a52dec->audblk.chbwcod[i] + 12) * 3) + 37;
+ }
+
+ /* Calculate the number of exponent groups to fetch */
+ grp_size = 3 * (1 << (p_a52dec->audblk.chexpstr[i] - 1));
+ p_a52dec->audblk.nchgrps[i] = (p_a52dec->audblk.endmant[i] - 1 + (grp_size - 3)) / grp_size;
+ }
+ }
+
+ /* Get the coupling exponents if they exist */
+ if (p_a52dec->audblk.cplinu && (p_a52dec->audblk.cplexpstr != EXP_REUSE))
+ {
+ p_a52dec->audblk.cplabsexp = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->total_bits_read += 4;
+ for (i=0; i< p_a52dec->audblk.ncplgrps;i++)
+ {
+ p_a52dec->audblk.cplexps[i] = GetBits (&p_a52dec->bit_stream,7);
+ p_a52dec->total_bits_read += 7;
+
+ if (p_a52dec->audblk.cplexps[i] >= 125)
+ {
+ return 1;
+ }
+ }
+ }
+
+ /* Get the fwb channel exponents */
+ for (i=0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ if (p_a52dec->audblk.chexpstr[i] != EXP_REUSE)
+ {
+ p_a52dec->audblk.exps[i][0] = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->total_bits_read += 4;
+ for (j=1; j<=p_a52dec->audblk.nchgrps[i];j++)
+ {
+ p_a52dec->audblk.exps[i][j] = GetBits (&p_a52dec->bit_stream,7);
+ p_a52dec->total_bits_read += 7;
+ if (p_a52dec->audblk.exps[i][j] >= 125)
+ {
+ return 1;
+ }
+ }
+ p_a52dec->audblk.gainrng[i] = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+ }
+ }
+
+ /* Get the lfe channel exponents */
+ if (p_a52dec->bsi.lfeon && (p_a52dec->audblk.lfeexpstr != EXP_REUSE))
+ {
+ p_a52dec->audblk.lfeexps[0] = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.lfeexps[1] = GetBits (&p_a52dec->bit_stream,7);
+ p_a52dec->total_bits_read += 11;
+ if (p_a52dec->audblk.lfeexps[1] >= 125)
+ {
+ return 1;
+ }
+ p_a52dec->audblk.lfeexps[2] = GetBits (&p_a52dec->bit_stream,7);
+ p_a52dec->total_bits_read += 7;
+ if (p_a52dec->audblk.lfeexps[2] >= 125)
+ {
+ return 1;
+ }
+ }
+
+ /* Get the parametric bit allocation parameters */
+ p_a52dec->audblk.baie = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 1;
+
+ if ((!blknum) && (!p_a52dec->audblk.baie))
+ {
+ return 1;
+ }
+
+ if (p_a52dec->audblk.baie)
+ {
+ p_a52dec->audblk.sdcycod = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->audblk.fdcycod = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->audblk.sgaincod = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->audblk.dbpbcod = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->audblk.floorcod = GetBits (&p_a52dec->bit_stream,3);
+ p_a52dec->total_bits_read += 11;
+ }
+
+ /* Get the SNR off set info if it exists */
+ p_a52dec->audblk.snroffste = GetBits (&p_a52dec->bit_stream,1);
+ if ((!blknum) && (!p_a52dec->audblk.snroffste))
+ {
+ return 1;
+ }
+
+ if (p_a52dec->audblk.snroffste)
+ {
+ p_a52dec->audblk.csnroffst = GetBits (&p_a52dec->bit_stream,6);
+ p_a52dec->total_bits_read += 6;
+
+ if (p_a52dec->audblk.cplinu)
+ {
+ p_a52dec->audblk.cplfsnroffst = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.cplfgaincod = GetBits (&p_a52dec->bit_stream,3);
+ p_a52dec->total_bits_read += 7;
+ }
+
+ for (i = 0;i < p_a52dec->bsi.nfchans; i++)
+ {
+ p_a52dec->audblk.fsnroffst[i] = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.fgaincod[i] = GetBits (&p_a52dec->bit_stream,3);
+ }
+ p_a52dec->total_bits_read += 7 * p_a52dec->bsi.nfchans;
+ if (p_a52dec->bsi.lfeon)
+ {
+ p_a52dec->audblk.lfefsnroffst = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.lfefgaincod = GetBits (&p_a52dec->bit_stream,3);
+ p_a52dec->total_bits_read += 7;
+ }
+ }
+
+ /* Get coupling leakage info if it exists */
+ if (p_a52dec->audblk.cplinu)
+ {
+ p_a52dec->audblk.cplleake = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 1;
+ if ((!blknum) && (!p_a52dec->audblk.cplleake))
+ {
+ return 1;
+ }
+
+ if (p_a52dec->audblk.cplleake)
+ {
+ p_a52dec->audblk.cplfleak = GetBits (&p_a52dec->bit_stream,3);
+ p_a52dec->audblk.cplsleak = GetBits (&p_a52dec->bit_stream,3);
+ p_a52dec->total_bits_read += 6;
+ }
+ }
+
+ /* Get the delta bit alloaction info */
+ p_a52dec->audblk.deltbaie = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 1;
+
+ if (p_a52dec->audblk.deltbaie)
+ {
+ if (p_a52dec->audblk.cplinu)
+ {
+ p_a52dec->audblk.cpldeltbae = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+ if (p_a52dec->audblk.cpldeltbae == 3)
+ {
+ return 1;
+ }
+ }
+
+ for (i = 0;i < p_a52dec->bsi.nfchans; i++)
+ {
+ p_a52dec->audblk.deltbae[i] = GetBits (&p_a52dec->bit_stream,2);
+ p_a52dec->total_bits_read += 2;
+ if (p_a52dec->audblk.deltbae[i] == 3)
+ {
+ return 1;
+ }
+ }
+
+ if (p_a52dec->audblk.cplinu && (p_a52dec->audblk.cpldeltbae == DELTA_BIT_NEW))
+ {
+ p_a52dec->audblk.cpldeltnseg = GetBits (&p_a52dec->bit_stream,3);
+ for (i = 0;i < p_a52dec->audblk.cpldeltnseg + 1; i++)
+ {
+ p_a52dec->audblk.cpldeltoffst[i] = GetBits (&p_a52dec->bit_stream,5);
+ p_a52dec->audblk.cpldeltlen[i] = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.cpldeltba[i] = GetBits (&p_a52dec->bit_stream,3);
+ }
+ p_a52dec->total_bits_read += 12 * (p_a52dec->audblk.cpldeltnseg + 1) + 3;
+ }
+
+ for (i = 0; i < p_a52dec->bsi.nfchans; i++)
+ {
+ if (p_a52dec->audblk.deltbae[i] == DELTA_BIT_NEW)
+ {
+ p_a52dec->audblk.deltnseg[i] = GetBits (&p_a52dec->bit_stream,3);
+// if (p_a52dec->audblk.deltnseg[i] >= 8)
+// fprintf (stderr, "parse debug: p_a52dec->audblk.deltnseg[%i] == %i\n", i, p_a52dec->audblk.deltnseg[i]);
+ for (j = 0; j < p_a52dec->audblk.deltnseg[i] + 1; j++)
+ {
+ p_a52dec->audblk.deltoffst[i][j] = GetBits (&p_a52dec->bit_stream,5);
+ p_a52dec->audblk.deltlen[i][j] = GetBits (&p_a52dec->bit_stream,4);
+ p_a52dec->audblk.deltba[i][j] = GetBits (&p_a52dec->bit_stream,3);
+ }
+ p_a52dec->total_bits_read += 12 * (p_a52dec->audblk.deltnseg[i] + 1) + 3;
+ }
+ }
+ }
+
+ /* Check to see if there's any dummy info to get */
+ p_a52dec->audblk.skiple = GetBits (&p_a52dec->bit_stream,1);
+ p_a52dec->total_bits_read += 1;
+
+ if (p_a52dec->audblk.skiple)
+ {
+ p_a52dec->audblk.skipl = GetBits (&p_a52dec->bit_stream,9);
+
+ for (i = 0; i < p_a52dec->audblk.skipl ; i++)
+ {
+ GetBits (&p_a52dec->bit_stream,8);
+ }
+ p_a52dec->total_bits_read += 8 * p_a52dec->audblk.skipl + 9;
+ }
+
+ parse_audblk_stats(p_a52dec);
+
+ return 0;
+}
+
+void parse_auxdata (a52dec_t * p_a52dec)
+{
+ int i;
+ int skip_length;
+
+ skip_length = (p_a52dec->syncinfo.frame_size * 16) - p_a52dec->total_bits_read - 17 - 1;
+
+ for (i = 0; i < skip_length; i++)
+ {
+ RemoveBits (&p_a52dec->bit_stream,1);
+ }
+
+ /* get the auxdata exists bit */
+ RemoveBits (&p_a52dec->bit_stream,1);
+
+ /* Skip the CRC reserved bit */
+ RemoveBits (&p_a52dec->bit_stream,1);
+
+ /* Get the crc */
+ RemoveBits (&p_a52dec->bit_stream,16);
+}
+
+static void parse_bsi_stats (a52dec_t * p_a52dec) /* Some stats */
+{
+#if 0
+ struct mixlev_s
+ {
+ float clev;
+ char *desc;
+ };
+ static const char *service_ids[8] =
+ {
+ "CM","ME","VI","HI",
+ "D", "C","E", "VO"
+ };
+/*
+ static const struct mixlev_s cmixlev_tbl[4] =
+ {
+ {0.707, "(-3.0 dB)"}, {0.595, "(-4.5 dB)"},
+ {0.500, "(-6.0 dB)"}, {1.0, "Invalid"}
+ };
+ static const struct mixlev_s smixlev_tbl[4] =
+ {
+ {0.707, "(-3.0 dB)"}, {0.500, "(-6.0 dB)"},
+ { 0.0, "off "}, { 1.0, "Invalid"}
+ };
+ */
+
+ static int i=0;
+
+ if ( !i )
+ {
+/* if ((p_a52dec->bsi.acmod & 0x1) && (p_a52dec->bsi.acmod != 0x1))
+ printf("CentreMixLevel %s ",cmixlev_tbl[p_a52dec->bsi.cmixlev].desc);
+ if (p_a52dec->bsi.acmod & 0x4)
+ printf("SurMixLevel %s",smixlev_tbl[p_a52dec->bsi.cmixlev].desc);
+ */
+ intf_Msg ( "(a52dec_parsebsi) %s %d.%d Mode",
+ service_ids[p_a52dec->bsi.bsmod],
+ p_a52dec->bsi.nfchans,p_a52dec->bsi.lfeon);
+ }
+ i++;
+
+ if ( i > 100 )
+ i = 0;
+#endif
+}
+
+static void parse_audblk_stats (a52dec_t * p_a52dec)
+{
+#if 0
+ char *exp_strat_tbl[4] = {"R ","D15 ","D25 ","D45 "};
+ u32 i;
+ intf_ErrMsg ("(a52dec_parseaudblk) ");
+ intf_ErrMsg ("%s ",p_a52dec->audblk.cplinu ? "cpl on" : "cpl off");
+ intf_ErrMsg ("%s ",p_a52dec->audblk.baie? "bai" : " ");
+ intf_ErrMsg ("%s ",p_a52dec->audblk.snroffste? "snroffst" : " ");
+ intf_ErrMsg ("%s ",p_a52dec->audblk.deltbaie? "deltba" : " ");
+ intf_ErrMsg ("%s ",p_a52dec->audblk.phsflginu? "phsflg" : " ");
+ intf_ErrMsg ("(%s %s %s %s %s) ",exp_strat_tbl[p_a52dec->audblk.chexpstr[0]],
+ exp_strat_tbl[p_a52dec->audblk.chexpstr[1]],exp_strat_tbl[p_a52dec->audblk.chexpstr[2]],
+ exp_strat_tbl[p_a52dec->audblk.chexpstr[3]],exp_strat_tbl[p_a52dec->audblk.chexpstr[4]]);
+ intf_ErrMsg ("[");
+ for(i=0;i<p_a52dec->bsi.nfchans;i++)
+ intf_ErrMsg ("%1d",p_a52dec->audblk.blksw[i]);
+ intf_ErrMsg ("]");
+#endif
+}
+
--- /dev/null
+/*****************************************************************************
+ * rematrix.c: A52 audio rematrixing
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: rematrix.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "imdct.h"
+#include "downmix.h"
+#include "adec.h"
+
+struct rematrix_band_s {
+ u32 start;
+ u32 end;
+};
+
+static const struct rematrix_band_s rematrix_band[] = { {13,24}, {25,36}, {37 ,60}, {61,252}};
+
+static inline u32 min_value (u32 a, u32 b)
+{
+ return (a < b ? a : b);
+}
+
+/* This routine simply does stereo rematixing for the 2 channel
+ * stereo mode */
+void rematrix (a52dec_t * p_a52dec)
+{
+ u32 num_bands;
+ u32 start;
+ u32 end;
+ u32 i,j;
+ float left,right;
+
+ if (p_a52dec->audblk.cplinu || p_a52dec->audblk.cplbegf > 2)
+ num_bands = 4;
+ else if (p_a52dec->audblk.cplbegf > 0)
+ num_bands = 3;
+ else
+ num_bands = 2;
+
+ for (i=0;i < num_bands; i++) {
+ if (!p_a52dec->audblk.rematflg[i])
+ continue;
+
+ start = rematrix_band[i].start;
+ end = min_value(rematrix_band[i].end ,12 * p_a52dec->audblk.cplbegf + 36);
+
+ for (j=start;j < end; j++) {
+ left = 0.5f * ( *(p_a52dec->samples+j) + *(p_a52dec->samples+256+j) );
+ right = 0.5f * ( *(p_a52dec->samples+j) - *(p_a52dec->samples+256+j) );
+ *(p_a52dec->samples+j) = left;
+ *(p_a52dec->samples+256+j) = right;
+ }
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+cinepak_SOURCES = cinepak.c
--- /dev/null
+/*****************************************************************************
+ * cinepak.c: cinepak video decoder
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: cinepak.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> /* getpid() */
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#include "vdec_ext-plugins.h"
+#include "cinepak.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+static int InitThread ( videodec_thread_t * );
+static void EndThread ( videodec_thread_t * );
+static void DecodeThread ( videodec_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( "Cinepak video decoder" );
+ set_capability( "decoder", 70 );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to chose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ switch( p_fifo->i_fourcc )
+ {
+ case VLC_FOURCC('c','v','i','d'):
+ case VLC_FOURCC('C','V','I','D'):
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+ }
+
+ return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+ videodec_thread_t *p_vdec;
+ int b_error;
+
+ if ( !(p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) )
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+ memset( p_vdec, 0, sizeof( videodec_thread_t ) );
+
+ p_vdec->p_fifo = p_fifo;
+
+ if( InitThread( p_vdec ) != 0 )
+ {
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) )
+ {
+ DecodeThread( p_vdec );
+ }
+
+ if( ( b_error = p_vdec->p_fifo->b_error ) )
+ {
+ DecoderError( p_vdec->p_fifo );
+ }
+
+ EndThread( p_vdec );
+
+ if( b_error )
+ {
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+
+/*****************************************************************************
+ * locales Functions
+ *****************************************************************************/
+
+static inline u16 GetWBE( u8 *p_buff )
+{
+ return( (p_buff[0]<<8) + p_buff[1] );
+}
+
+static inline u32 GetDWBE( u8 *p_buff )
+{
+ return( (p_buff[0] << 24) + ( p_buff[1] <<16 ) +
+ ( p_buff[2] <<8 ) + p_buff[3] );
+}
+
+#define GET2BYTES( p ) \
+ GetWBE( p ); p+= 2;
+/* FIXME */
+#define GET3BYTES( p ) \
+ (GetDWBE( p ) >> 8); p+= 3;
+
+#define GET4BYTES( p ) \
+ GetDWBE( p ); p+= 4;
+
+#define FREE( p ) \
+ if( p ) free( p )
+
+/* get the first pes from fifo */
+static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
+{
+ pes_packet_t *p_pes;
+
+ vlc_mutex_lock( &p_fifo->data_lock );
+
+ /* if fifo is emty wait */
+ while( !p_fifo->p_first )
+ {
+ if( p_fifo->b_die )
+ {
+ vlc_mutex_unlock( &p_fifo->data_lock );
+ return( NULL );
+ }
+ vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+ }
+ p_pes = p_fifo->p_first;
+
+ vlc_mutex_unlock( &p_fifo->data_lock );
+
+ return( p_pes );
+}
+
+/* free the first pes and go to next */
+static void __PES_NEXT( decoder_fifo_t *p_fifo )
+{
+ pes_packet_t *p_next;
+
+ vlc_mutex_lock( &p_fifo->data_lock );
+
+ p_next = p_fifo->p_first->p_next;
+ p_fifo->p_first->p_next = NULL;
+ input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
+ p_fifo->p_first = p_next;
+ p_fifo->i_depth--;
+
+ if( !p_fifo->p_first )
+ {
+ /* No PES in the fifo */
+ /* pp_last no longer valid */
+ p_fifo->pp_last = &p_fifo->p_first;
+ while( !p_fifo->p_first )
+ {
+ vlc_cond_signal( &p_fifo->data_wait );
+ vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+ }
+ }
+ vlc_mutex_unlock( &p_fifo->data_lock );
+}
+
+static inline void __GetFrame( videodec_thread_t *p_vdec )
+{
+ pes_packet_t *p_pes;
+ data_packet_t *p_data;
+ byte_t *p_buffer;
+
+ p_pes = __PES_GET( p_vdec->p_fifo );
+ p_vdec->i_pts = p_pes->i_pts;
+
+ while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
+ {
+ __PES_NEXT( p_vdec->p_fifo );
+ p_pes = __PES_GET( p_vdec->p_fifo );
+ }
+ p_vdec->i_framesize = p_pes->i_pes_size;
+ if( p_pes->i_nb_data == 1 )
+ {
+ p_vdec->p_framedata = p_pes->p_first->p_payload_start;
+ return;
+ }
+ /* get a buffer and gather all data packet */
+ p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
+ p_data = p_pes->p_first;
+ do
+ {
+ p_vdec->p_fifo->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start,
+ p_data->p_payload_end - p_data->p_payload_start );
+ p_buffer += p_data->p_payload_end - p_data->p_payload_start;
+ p_data = p_data->p_next;
+ } while( p_data );
+}
+
+static inline void __NextFrame( videodec_thread_t *p_vdec )
+{
+ pes_packet_t *p_pes;
+
+ p_pes = __PES_GET( p_vdec->p_fifo );
+ if( p_pes->i_nb_data != 1 )
+ {
+ free( p_vdec->p_framedata ); /* FIXME keep this buffer */
+ }
+ __PES_NEXT( p_vdec->p_fifo );
+}
+
+static int cinepak_CheckVout( vout_thread_t *p_vout,
+ int i_width,
+ int i_height )
+{
+ if( !p_vout )
+ {
+ return( 0 );
+ }
+
+ if( ( p_vout->render.i_width != i_width )||
+ ( p_vout->render.i_height != i_height )||
+ ( p_vout->render.i_chroma != VLC_FOURCC('I','4','2','0') )||
+ ( p_vout->render.i_aspect != VOUT_ASPECT_FACTOR * i_width / i_height) )
+ {
+ return( 0 );
+ }
+ else
+ {
+ return( 1 );
+ }
+}
+
+/* Return a Vout */
+
+static vout_thread_t *cinepak_CreateVout( videodec_thread_t *p_vdec,
+ int i_width,
+ int i_height )
+{
+ vout_thread_t *p_vout;
+
+ if( (!i_width)||(!i_height) )
+ {
+ return( NULL ); /* Can't create a new vout without display size */
+ }
+
+ /* Spawn a video output if there is none. First we look for our children,
+ * then we look for any other vout that might be available. */
+ p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
+ FIND_CHILD );
+ if( !p_vout )
+ {
+ p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
+ FIND_ANYWHERE );
+ }
+
+ if( p_vout )
+ {
+ if( !cinepak_CheckVout( p_vout, i_width, i_height ) )
+ {
+ /* We are not interested in this format, close this vout */
+ vlc_object_detach_all( p_vout );
+ vlc_object_release( p_vout );
+ vout_DestroyThread( p_vout );
+ p_vout = NULL;
+ }
+ else
+ {
+ /* This video output is cool! Hijack it. */
+ vlc_object_detach_all( p_vout );
+ vlc_object_attach( p_vout, p_vdec->p_fifo );
+ vlc_object_release( p_vout );
+ }
+ }
+
+ if( p_vout == NULL )
+ {
+ msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
+
+ p_vout = vout_CreateThread( p_vdec->p_fifo,
+ i_width,
+ i_height,
+ VLC_FOURCC('I','4','2','0'),
+ VOUT_ASPECT_FACTOR * i_width / i_height );
+ }
+
+ return( p_vout );
+}
+
+void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
+ u8 *p_data,
+ int b_grayscale )
+{
+ int i, i_y[4], i_u, i_v, i_Cb, i_Cr;
+ int i_uv;
+#define SCALEBITS 12
+#define FIX( x ) ( (int)( (x) * ( 1L << SCALEBITS ) + 0.5 ) )
+
+ for( i = 0; i < 4; i++ )
+ {
+ i_y[i] = (u8)( *(p_data++) );
+ }
+ if( b_grayscale )
+ {
+ i_u = (s8)( *(p_data++) );
+ i_v = (s8)( *(p_data++) );
+ }
+ else
+ {
+ i_u = 0;
+ i_v = 0;
+ }
+
+ /*
+ | Y | | 1 -0.0655 0.0110 | | CY |
+ | Cb | = | 0 1.1656 -0.0062 | | CU |
+ | Cr | | 0 0.0467 1.4187 | | CV |
+ */
+ i_uv = ( FIX( -0.0655 ) * i_u + FIX( 0.0110 ) * i_v ) >> SCALEBITS;
+ for( i = 0; i < 4; i++ )
+ {
+ i_y[i] += i_uv;
+ }
+ i_Cb = ( FIX( 1.1656 ) * i_u + FIX( -0.0062 ) * i_v ) >> SCALEBITS;
+ i_Cr = ( FIX( 0.0467 ) * i_u + FIX( 1.4187 ) * i_v ) >> SCALEBITS;
+
+ for( i = 0; i < 4; i++ )
+ {
+ p_codebook->i_y[i] = __MIN( __MAX( 0, i_y[i] ), 255 );
+ }
+ p_codebook->i_u = __MIN( __MAX( 0, i_Cb + 128 ), 255 );
+ p_codebook->i_v = __MIN( __MAX( 0, i_Cr + 128 ), 255 );
+
+#undef FIX
+#undef SCALEBITS
+}
+
+void cinepak_Getv4( cinepak_context_t *p_context,
+ int i_strip,
+ int i_x, int i_y,
+ int i_x2, int i_y2,
+ u8 *p_data )
+{
+ u8 i_index[4];
+ int i,j;
+
+ u8 *p_dst_y, *p_dst_u, *p_dst_v;
+#define PIX_SET_Y( x, y, v ) \
+ p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
+
+#define PIX_SET_UV( i, p, x, y, v ) \
+ p[(x) + (y)* (p_context->i_stride[i])] = (v);
+
+ for( i = 0; i < 4; i++ )
+ {
+ i_index[i] = *(p_data++);
+ }
+
+ /* y plane */
+ p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x;
+ p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2);
+ p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
+
+ for( i = 0; i < 2; i++ )
+ {
+ for( j = 0; j < 2; j ++ )
+ {
+ PIX_SET_Y( 2*j + 0, 2*i + 0,
+ p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[0]);
+ PIX_SET_Y( 2*j + 1, 2*i + 0,
+ p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[1]);
+ PIX_SET_Y( 2*j + 0, 2*i + 1,
+ p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[2]);
+ PIX_SET_Y( 2*j + 1, 2*i + 1,
+ p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[3]);
+
+ PIX_SET_UV( 1, p_dst_u, j, i,
+ p_context->codebook_v4[i_strip][i_index[j+2*i]].i_u );
+ PIX_SET_UV( 2, p_dst_v, j, i,
+ p_context->codebook_v4[i_strip][i_index[j+2*i]].i_v );
+ }
+ }
+#undef PIX_SET_Y
+#undef PIX_SET_UV
+}
+
+void cinepak_Getv1( cinepak_context_t *p_context,
+ int i_strip,
+ int i_x, int i_y,
+ int i_x2, int i_y2,
+ u8 *p_data )
+{
+ u8 i_index;
+ int i,j;
+
+ u8 *p_dst_y, *p_dst_u, *p_dst_v;
+#define PIX_SET_Y( x, y, v ) \
+ p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
+
+#define PIX_SET_UV( i,p, x, y, v ) \
+ p[(x) + (y)* (p_context->i_stride[i])] = (v);
+
+ i_index = *(p_data++);
+
+ /* y plane */
+ p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x;
+ p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2);
+ p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
+
+ for( i = 0; i < 2; i++ )
+ {
+ for( j = 0; j < 2; j ++ )
+ {
+ PIX_SET_Y( 2*j + 0, 2*i + 0,
+ p_context->codebook_v1[i_strip][i_index].i_y[0] );
+ PIX_SET_Y( 2*j + 1, 2*i + 0,
+ p_context->codebook_v1[i_strip][i_index].i_y[1] );
+ PIX_SET_Y( 2*j + 0, 2*i + 1,
+ p_context->codebook_v1[i_strip][i_index].i_y[2] );
+ PIX_SET_Y( 2*j + 1, 2*i + 1,
+ p_context->codebook_v1[i_strip][i_index].i_y[3] );
+
+ PIX_SET_UV( 1,p_dst_u, j, i,
+ p_context->codebook_v1[i_strip][i_index].i_u );
+ PIX_SET_UV( 2,p_dst_v, j, i,
+ p_context->codebook_v1[i_strip][i_index].i_v );
+ }
+ }
+
+#undef PIX_SET_Y
+#undef PIX_SET_UV
+}
+
+/*****************************************************************************
+ * The function that decode one frame
+ *****************************************************************************/
+int cinepak_decode_frame( cinepak_context_t *p_context,
+ int i_length, u8 *p_data )
+{
+ int i_strip;
+
+ int i_frame_flags;
+ int i_frame_size;
+ int i_width, i_height;
+ int i_frame_strips;
+ int i_index;
+ int i_strip_x1 =0, i_strip_y1=0;
+ int i_strip_x2 =0, i_strip_y2=0;
+
+ if( i_length <= 10 )
+ {
+ /* Broken header or no data */
+ return( -1 );
+ }
+
+ /* get header */
+ i_frame_flags = *(p_data++);
+ i_frame_size = GET3BYTES( p_data );
+ i_width = GET2BYTES( p_data );
+ i_height = GET2BYTES( p_data );
+ i_frame_strips = GET2BYTES( p_data );
+
+ /* Check if we have a picture buffer with good size */
+ if( ( p_context->i_width != i_width )||
+ ( p_context->i_height != i_height ) )
+ {
+ int i;
+ for( i = 0; i < 3; i++ )
+ {
+ FREE( p_context->p_pix[i] );
+ }
+
+ p_context->i_width = i_width;
+ p_context->i_height = i_height;
+
+ p_context->i_stride[0] = ( i_width + 3)&0xfffc;
+ p_context->i_stride[1] = p_context->i_stride[2] =
+ p_context->i_stride[0] / 2;
+
+ p_context->i_lines[0] = ( i_height + 3 )&0xfffc;
+ p_context->i_lines[1] = p_context->i_lines[2] =
+ p_context->i_lines[0] /2;
+
+ for( i = 0; i < 3; i++ )
+ {
+ p_context->p_pix[i] = malloc( p_context->i_stride[i] *
+ p_context->i_lines[i] );
+ }
+ }
+
+ if( i_frame_size != i_length )
+ {
+ i_length = __MIN( i_length, i_frame_size );
+ }
+ i_length -= 10;
+
+ if( i_frame_strips >= CINEPAK_MAXSTRIP )
+ {
+ i_frame_strips = CINEPAK_MAXSTRIP;
+ }
+
+ /* Now decode each strip */
+
+ for( i_strip = 0; i_strip < i_frame_strips; i_strip++ )
+ {
+ int i_strip_id;
+ int i_strip_size;
+
+ if( i_length <= 12 )
+ {
+ break;
+ }
+
+
+ i_strip_id = GET2BYTES( p_data );
+ i_strip_size = GET2BYTES( p_data );
+ i_strip_size = __MIN( i_strip_size, i_length );
+ /* FIXME I don't really understand how it's work; */
+ i_strip_y1 = i_strip_y2 + GET2BYTES( p_data );
+ i_strip_x1 = GET2BYTES( p_data );
+ i_strip_y2 = i_strip_y2 + GET2BYTES( p_data );
+ i_strip_x2 = GET2BYTES( p_data );
+
+ i_length -= i_strip_size;
+
+ i_strip_size -= 12;
+ /* init codebook , if needed */
+ if( ( i_strip > 0 )&&( !(i_frame_flags&0x01) ) )
+ {
+ memcpy( &p_context->codebook_v1[i_strip],
+ &p_context->codebook_v1[i_strip-1],
+ sizeof(cinepak_codebook_t[256] ) );
+
+ memcpy( &p_context->codebook_v4[i_strip],
+ &p_context->codebook_v4[i_strip-1],
+ sizeof(cinepak_codebook_t[256] ) );
+ }
+
+ /* Now parse all chunk in this strip */
+ while( i_strip_size > 0 )
+ {
+ cinepak_codebook_t (*p_codebook)[CINEPAK_MAXSTRIP][256];
+ int i_mode;
+
+ int i_chunk_id;
+ int i_chunk_size;
+ u32 i_vector_flags;
+ int i_count;
+ int i;
+ int i_x, i_y; /* (0,0) begin in fact at (x1,y1) ... */
+
+ i_chunk_id = GET2BYTES( p_data );
+ i_chunk_size = GET2BYTES( p_data );
+ i_chunk_size = __MIN( i_chunk_size, i_strip_size );
+ i_strip_size -= i_chunk_size;
+
+ i_chunk_size -= 4;
+
+ i_x = 0;
+ i_y = 0;
+ if( i_chunk_size < 0 )
+ {
+ break;
+ }
+
+ switch( i_chunk_id )
+ {
+ case( 0x2000 ): /* 12bits v4 Intra*/
+ case( 0x2200 ): /* 12bits v1 Intra*/
+ case( 0x2400 ): /* 8bits v4 Intra*/
+ case( 0x2600 ): /* 8bits v1 Intra */
+ i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
+ p_codebook = ( i_chunk_id&0x0200 ) ?
+ &p_context->codebook_v1 :
+ &p_context->codebook_v4;
+
+ i_count = __MIN( i_chunk_size / ( i_mode ? 6 : 4 ), 256 );
+
+ for( i = 0; i < i_count; i++ )
+ {
+ cinepak_LoadCodebook( &((*p_codebook)[i_strip][i]),
+ p_data,
+ i_mode&~p_context->b_grayscale );
+ p_data += i_mode ? 6 : 4;
+ i_chunk_size -= i_mode ? 6 : 4;
+ }
+ break;
+
+ case( 0x2100 ): /* selective 12bits v4 Inter*/
+ case( 0x2300 ): /* selective 12bits v1 Inter*/
+ case( 0x2500 ): /* selective 8bits v4 Inter*/
+ case( 0x2700 ): /* selective 8bits v1 Inter*/
+ i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
+ p_codebook = ( i_chunk_id&0x0200 ) ?
+ &p_context->codebook_v1 :
+ &p_context->codebook_v4;
+
+ i_index = 0;
+ while( (i_chunk_size > 4)&&(i_index<256))
+ {
+ i_vector_flags = GET4BYTES( p_data );
+ i_chunk_size -= 4;
+ for( i = 0; i < 32; i++ )
+ {
+ if( ( i_chunk_size < ( i_mode ? 6 : 4 ) )||(i_index >= 256 ))
+ {
+ break;
+ }
+ if( i_vector_flags&0x80000000UL )
+ {
+ cinepak_LoadCodebook( &((*p_codebook)[i_strip][i_index]),
+ p_data,
+ i_mode&~p_context->b_grayscale );
+
+ p_data += i_mode ? 6 : 4;
+ i_chunk_size -= i_mode ? 6 : 4;
+ }
+ i_index++;
+ i_vector_flags <<= 1;
+ }
+ }
+ break;
+
+ case( 0x3000 ): /* load image Intra */
+ while( (i_chunk_size >= 4 )&&(i_y<i_strip_y2-i_strip_y1) )
+ {
+ i_vector_flags = GET4BYTES( p_data );
+ i_chunk_size -= 4;
+ i_strip_size -= 4;
+ i_length -= 4;
+
+ for( i = 0; i < 32; i++ )
+ {
+ if( ( i_y >= i_strip_y2 - i_strip_y1)||
+ ( i_chunk_size<=0) )
+ {
+ break;
+ }
+ if( i_vector_flags&0x80000000UL )
+ {
+ cinepak_Getv4( p_context,
+ i_strip,
+ i_strip_x1 + i_x,
+ i_strip_y1 + i_y,
+ i_strip_x2, i_strip_y2,
+ p_data );
+ p_data += 4;
+ i_chunk_size -= 4;
+ }
+ else
+ {
+ cinepak_Getv1( p_context,
+ i_strip,
+ i_strip_x1 + i_x,
+ i_strip_y1 + i_y,
+ i_strip_x2, i_strip_y2,
+ p_data );
+ p_data++;
+ i_chunk_size--;
+ }
+
+ i_x += 4;
+ if( i_x >= i_strip_x2 - i_strip_x1 )
+ {
+ i_x = 0;
+ i_y += 4;
+ }
+ i_vector_flags <<= 1;
+ }
+ }
+ break;
+
+ case( 0x3100 ): /* load image Inter */
+ while( ( i_chunk_size > 4 )&&( i_y < i_strip_y2 - i_strip_y1) )
+ {
+ u32 i_mask;
+ i_vector_flags = GET4BYTES( p_data );
+ i_chunk_size -= 4;
+ i_mask = 0x80000000UL;
+
+ while((i_chunk_size > 0 )&&( i_mask )&&( i_y < i_strip_y2 - i_strip_y1 ))
+ {
+ if( i_vector_flags&i_mask)
+ {
+ i_mask >>= 1;
+ if( !i_mask )
+ {
+ if( i_chunk_size < 4 )
+ {
+ break;
+ }
+ i_vector_flags = GET4BYTES( p_data );
+ i_chunk_size -= 4;
+ i_mask = 0x80000000UL;
+ }
+ if( i_vector_flags&i_mask )
+ {
+ if( i_chunk_size < 4 ) break;
+ cinepak_Getv4( p_context,
+ i_strip,
+ i_strip_x1 + i_x,
+ i_strip_y1 + i_y,
+ i_strip_x2, i_strip_y2,
+ p_data );
+ p_data += 4;
+ i_chunk_size -= 4;
+ }
+ else
+ {
+ if( i_chunk_size < 1 ) break;
+ cinepak_Getv1( p_context,
+ i_strip,
+ i_strip_x1 + i_x,
+ i_strip_y1 + i_y,
+ i_strip_x2, i_strip_y2,
+ p_data );
+ p_data++;
+ i_chunk_size--;
+ }
+ }
+ i_mask >>= 1;
+
+ i_x += 4;
+ if( i_x >= i_strip_x2 - i_strip_x1 )
+ {
+ i_x = 0;
+ i_y += 4;
+ }
+ }
+ }
+ break;
+
+ case( 0x3200 ): /* load intra picture but all v1*/
+ while( ( i_chunk_size > 0 )&&
+ ( i_y < i_strip_y2 - i_strip_y1) )
+ {
+ cinepak_Getv1( p_context,
+ i_strip,
+ i_strip_x1 + i_x,
+ i_strip_y1 + i_y,
+ i_strip_x2, i_strip_y2,
+ p_data );
+ p_data++;
+ i_chunk_size--;
+
+ i_x += 4;
+ if( i_x >= i_strip_x2 - i_strip_x1 )
+ {
+ i_x = 0;
+ i_y += 4;
+ }
+
+ }
+ break;
+
+
+
+ default:
+ break;
+
+ }
+ p_data += i_chunk_size ; /* skip remains bytes */
+
+ }
+ }
+
+
+ return( 0 );
+}
+
+
+/*****************************************************************************
+ *
+ * Functions that initialize, decode and end the decoding process
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * InitThread: initialize vdec output thread
+ *****************************************************************************
+ * This function is called from decoder_Run and performs the second step
+ * of the initialization. It returns 0 on success. Note that the thread's
+ * flag are not modified inside this function.
+ *****************************************************************************/
+
+static int InitThread( videodec_thread_t *p_vdec )
+{
+
+ /* This will be created after the first decoded frame */
+ if( !(p_vdec->p_context = malloc( sizeof( cinepak_context_t ) ) ) )
+ {
+ msg_Err( p_vdec->p_fifo, "out of memory" );
+ }
+ memset( p_vdec->p_context, 0, sizeof( cinepak_context_t ) );
+
+ if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
+ {
+ p_vdec->p_context->b_grayscale = 1;
+ }
+ else
+ {
+ p_vdec->p_context->b_grayscale = 0;
+ }
+
+ p_vdec->p_vout = NULL;
+ msg_Dbg( p_vdec->p_fifo, "cinepak decoder started" );
+ return( 0 );
+}
+
+
+/*****************************************************************************
+ * DecodeThread: Called for decode one frame
+ *****************************************************************************/
+static void DecodeThread( videodec_thread_t *p_vdec )
+{
+ int i_status;
+
+ int i_plane;
+ u8 *p_dst, *p_src;
+ picture_t *p_pic; /* videolan picture */
+
+ __GetFrame( p_vdec );
+
+ i_status = cinepak_decode_frame( p_vdec->p_context,
+ p_vdec->i_framesize,
+ p_vdec->p_framedata );
+ __NextFrame( p_vdec );
+
+ if( i_status < 0 )
+ {
+ msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
+ p_vdec->i_framesize );
+ return;
+ }
+
+ /* Check our vout */
+ if( !cinepak_CheckVout( p_vdec->p_vout,
+ p_vdec->p_context->i_width,
+ p_vdec->p_context->i_height ) )
+ {
+ p_vdec->p_vout =
+ cinepak_CreateVout( p_vdec,
+ p_vdec->p_context->i_width,
+ p_vdec->p_context->i_height );
+
+ if( !p_vdec->p_vout )
+ {
+ msg_Err( p_vdec->p_fifo, "cannot create vout" );
+ p_vdec->p_fifo->b_error = 1; /* abort */
+ return;
+ }
+ }
+
+ /* Send decoded frame to vout */
+ while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
+ {
+ if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ for( i_plane = 0; i_plane < 3; i_plane++ )
+ {
+ int i_line, i_lines;
+
+ p_dst = p_pic->p[i_plane].p_pixels;
+ p_src = p_vdec->p_context->p_pix[i_plane];
+
+ i_lines = __MIN( p_vdec->p_context->i_lines[i_plane],
+ p_pic->p[i_plane].i_lines );
+ for( i_line = 0; i_line < i_lines; i_line++ )
+ {
+ memcpy( p_dst,
+ p_src,
+ __MIN( p_pic->p[i_plane].i_pitch,
+ p_vdec->p_context->i_stride[i_plane] ) );
+ p_dst += p_pic->p[i_plane].i_pitch;
+ p_src += p_vdec->p_context->i_stride[i_plane];
+ }
+ }
+
+ vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
+ vout_DisplayPicture( p_vdec->p_vout, p_pic );
+
+ return;
+}
+
+
+/*****************************************************************************
+ * EndThread: thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+static void EndThread( videodec_thread_t *p_vdec )
+{
+ int i;
+
+ if( !p_vdec )
+ {
+ return;
+ }
+ msg_Dbg( p_vdec->p_fifo, "cinepak decoder stopped" );
+
+ for( i = 0; i < 3; i++ )
+ {
+ FREE( p_vdec->p_context->p_pix[i] );
+ }
+
+ free( p_vdec->p_context );
+
+ if( p_vdec->p_vout != NULL )
+ {
+ /* We are about to die. Reattach video output to p_vlc. */
+ vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
+ vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
+ }
+
+ free( p_vdec );
+}
+
+
--- /dev/null
+/*****************************************************************************
+ * cinepak.h: Cinepak video decoder
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: cinepak.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#define CINEPAK_MAXSTRIP 32
+
+typedef struct cinepak_codebook_s
+{
+ u8 i_y[4];
+ u8 i_u, i_v;
+
+} cinepak_codebook_t;
+
+
+typedef struct cinepak_context_s
+{
+ int b_grayscale; /* force to grayscale */
+
+ int i_width;
+ int i_height;
+
+ int i_stride_x;
+ int i_stride_y;
+
+ u8 *p_y, *p_u, *p_v;
+
+ int i_stride[3]; /* our 3 planes */
+ int i_lines[3];
+ u8 *p_pix[3];
+
+ cinepak_codebook_t codebook_v1[CINEPAK_MAXSTRIP][256];
+ cinepak_codebook_t codebook_v4[CINEPAK_MAXSTRIP][256];
+
+} cinepak_context_t;
+
+typedef struct videodec_thread_s
+{
+ decoder_fifo_t *p_fifo;
+
+ vout_thread_t *p_vout;
+
+ cinepak_context_t *p_context;
+
+ /* private */
+ mtime_t i_pts;
+ int i_framesize;
+ byte_t *p_framedata;
+} videodec_thread_t;
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+ffmpeg_SOURCES = ffmpeg.c
--- /dev/null
+/*****************************************************************************
+ * ffmpeg.c: video decoder using ffmpeg library
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: ffmpeg.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+#include <vlc/input.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> /* getpid() */
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#include "vdec_ext-plugins.h"
+#include "avcodec.h" /* ffmpeg */
+#include "ffmpeg.h"
+
+/*
+ * Local prototypes
+ */
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+static int InitThread ( videodec_thread_t * );
+static void EndThread ( videodec_thread_t * );
+static void DecodeThread ( videodec_thread_t * );
+
+
+static int b_ffmpeginit = 0;
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+#define ERROR_RESILIENCE_LONGTEXT \
+ "ffmpeg can make errors resiliences. \n"\
+ "Nevertheless, with buggy encoder (like ISO MPEG-4 encoder from M$) " \
+ "this will produce a lot of errors.\n" \
+ "Valid range is -1 to 99 (-1 disable all errors resiliences)."
+
+#define HURRY_UP_LONGTEXT \
+ "Allow the decoder to partially decode or skip frame(s) " \
+ "when there not enough time.\n It's usefull with low CPU power " \
+ "but it could produce broken pictures."
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+#if LIBAVCODEC_BUILD >= 4611
+ add_integer ( "ffmpeg-error-resilience", 0, NULL,
+ "error resilience", ERROR_RESILIENCE_LONGTEXT );
+ add_integer ( "ffmpeg-workaround-bugs", 0, NULL,
+ "workaround bugs", "0-99, seems to be for msmpeg v3\n" );
+#endif
+ add_bool( "ffmpeg-hurry-up", 0, NULL, "hurry up", HURRY_UP_LONGTEXT );
+ set_description( _("ffmpeg video decoder((MS)MPEG4,SVQ1,H263)") );
+ set_capability( "decoder", 70 );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to chose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( ffmpeg_GetFfmpegCodec( p_fifo->i_fourcc, NULL, NULL ) )
+ {
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+ }
+
+ return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+ videodec_thread_t *p_vdec;
+ int b_error;
+
+ if ( !(p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) )
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+ memset( p_vdec, 0, sizeof( videodec_thread_t ) );
+
+ p_vdec->p_fifo = p_fifo;
+
+ if( InitThread( p_vdec ) != 0 )
+ {
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) )
+ {
+ DecodeThread( p_vdec );
+ }
+
+ if( ( b_error = p_vdec->p_fifo->b_error ) )
+ {
+ DecoderError( p_vdec->p_fifo );
+ }
+
+ EndThread( p_vdec );
+
+ if( b_error )
+ {
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+
+/*****************************************************************************
+ * locales Functions
+ *****************************************************************************/
+
+#define GetWLE( p ) \
+ ( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) )
+
+#define GetDWLE( p ) \
+ ( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) + \
+ ( *((u8*)(p)+2) << 16 ) + ( *((u8*)(p)+3) << 24 ) )
+
+static void ffmpeg_ParseBitMapInfoHeader( bitmapinfoheader_t *p_bh,
+ u8 *p_data )
+{
+ p_bh->i_size = GetDWLE( p_data );
+ p_bh->i_width = GetDWLE( p_data + 4 );
+ p_bh->i_height = GetDWLE( p_data + 8 );
+ p_bh->i_planes = GetWLE( p_data + 12 );
+ p_bh->i_bitcount = GetWLE( p_data + 14 );
+ p_bh->i_compression = GetDWLE( p_data + 16 );
+ p_bh->i_sizeimage = GetDWLE( p_data + 20 );
+ p_bh->i_xpelspermeter = GetDWLE( p_data + 24 );
+ p_bh->i_ypelspermeter = GetDWLE( p_data + 28 );
+ p_bh->i_clrused = GetDWLE( p_data + 32 );
+ p_bh->i_clrimportant = GetDWLE( p_data + 36 );
+
+ if( p_bh->i_size > 40 )
+ {
+ p_bh->i_data = p_bh->i_size - 40;
+ p_bh->p_data = malloc( p_bh->i_data );
+ memcpy( p_bh->p_data, p_data + 40, p_bh->i_data );
+ }
+ else
+ {
+ p_bh->i_data = 0;
+ p_bh->p_data = NULL;
+ }
+
+}
+/* get the first pes from fifo */
+static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
+{
+ pes_packet_t *p_pes;
+
+ vlc_mutex_lock( &p_fifo->data_lock );
+
+ /* if fifo is emty wait */
+ while( !p_fifo->p_first )
+ {
+ if( p_fifo->b_die )
+ {
+ vlc_mutex_unlock( &p_fifo->data_lock );
+ return( NULL );
+ }
+ vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+ }
+ p_pes = p_fifo->p_first;
+
+ vlc_mutex_unlock( &p_fifo->data_lock );
+
+ return( p_pes );
+}
+
+/* free the first pes and go to next */
+static void __PES_NEXT( decoder_fifo_t *p_fifo )
+{
+ pes_packet_t *p_next;
+
+ vlc_mutex_lock( &p_fifo->data_lock );
+
+ p_next = p_fifo->p_first->p_next;
+ p_fifo->p_first->p_next = NULL;
+ input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
+ p_fifo->p_first = p_next;
+ p_fifo->i_depth--;
+
+ if( !p_fifo->p_first )
+ {
+ /* No PES in the fifo */
+ /* pp_last no longer valid */
+ p_fifo->pp_last = &p_fifo->p_first;
+ while( !p_fifo->p_first )
+ {
+ vlc_cond_signal( &p_fifo->data_wait );
+ vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+ }
+ }
+ vlc_mutex_unlock( &p_fifo->data_lock );
+}
+
+static inline void __GetFrame( videodec_thread_t *p_vdec )
+{
+ pes_packet_t *p_pes;
+ data_packet_t *p_data;
+ byte_t *p_buffer;
+
+ p_pes = __PES_GET( p_vdec->p_fifo );
+ p_vdec->i_pts = p_pes->i_pts;
+
+ while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
+ {
+ __PES_NEXT( p_vdec->p_fifo );
+ p_pes = __PES_GET( p_vdec->p_fifo );
+ }
+ p_vdec->i_framesize = p_pes->i_pes_size;
+ if( p_pes->i_nb_data == 1 )
+ {
+ p_vdec->p_framedata = p_pes->p_first->p_payload_start;
+ return;
+ }
+ /* get a buffer and gather all data packet */
+ p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
+ p_data = p_pes->p_first;
+ do
+ {
+ p_vdec->p_fifo->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start,
+ p_data->p_payload_end - p_data->p_payload_start );
+ p_buffer += p_data->p_payload_end - p_data->p_payload_start;
+ p_data = p_data->p_next;
+ } while( p_data );
+}
+
+static inline void __NextFrame( videodec_thread_t *p_vdec )
+{
+ pes_packet_t *p_pes;
+
+ p_pes = __PES_GET( p_vdec->p_fifo );
+ if( p_pes->i_nb_data != 1 )
+ {
+ free( p_vdec->p_framedata ); /* FIXME keep this buffer */
+ }
+ __PES_NEXT( p_vdec->p_fifo );
+}
+
+/* FIXME FIXME some of them are wrong */
+static int i_ffmpeg_PixFmtToChroma[] =
+{
+/* PIX_FMT_ANY = -1,PIX_FMT_YUV420P, PIX_FMT_YUV422,
+ PIX_FMT_RGB24, PIX_FMT_BGR24, PIX_FMT_YUV422P,
+ PIX_FMT_YUV444P, PIX_FMT_YUV410P */
+
+ 0, VLC_FOURCC('I','4','2','0'), VLC_FOURCC('I','4','2','0'),
+ VLC_FOURCC('R','V','2','4'), 0, VLC_FOURCC('Y','4','2','2'),
+ VLC_FOURCC('I','4','4','4'), 0
+};
+
+static inline u32 ffmpeg_PixFmtToChroma( int i_ffmpegchroma )
+{
+ if( ++i_ffmpegchroma > 7 )
+ {
+ return( 0 );
+ }
+ else
+ {
+ return( i_ffmpeg_PixFmtToChroma[i_ffmpegchroma] );
+ }
+}
+
+static inline int ffmpeg_FfAspect( int i_width, int i_height, int i_ffaspect )
+{
+ switch( i_ffaspect )
+ {
+ case( FF_ASPECT_4_3_625 ):
+ case( FF_ASPECT_4_3_525 ):
+ return( VOUT_ASPECT_FACTOR * 4 / 3);
+ case( FF_ASPECT_16_9_625 ):
+ case( FF_ASPECT_16_9_525 ):
+ return( VOUT_ASPECT_FACTOR * 16 / 9 );
+ case( FF_ASPECT_SQUARE ):
+ default:
+ return( VOUT_ASPECT_FACTOR * i_width / i_height );
+ }
+}
+
+static int ffmpeg_CheckVout( vout_thread_t *p_vout,
+ int i_width,
+ int i_height,
+ int i_aspect,
+ int i_chroma )
+{
+ if( !p_vout )
+ {
+ return( 0 );
+ }
+ if( !i_chroma )
+ {
+ /* we will try to make conversion */
+ i_chroma = VLC_FOURCC('I','4','2','0');
+ }
+
+ if( ( p_vout->render.i_width != i_width )||
+ ( p_vout->render.i_height != i_height )||
+ ( p_vout->render.i_chroma != i_chroma )||
+ ( p_vout->render.i_aspect !=
+ ffmpeg_FfAspect( i_width, i_height, i_aspect ) ) )
+ {
+ return( 0 );
+ }
+ else
+ {
+ return( 1 );
+ }
+}
+
+/* Return a Vout */
+
+static vout_thread_t *ffmpeg_CreateVout( videodec_thread_t *p_vdec,
+ int i_width,
+ int i_height,
+ int i_aspect,
+ int i_chroma )
+{
+ vout_thread_t *p_vout;
+
+ if( (!i_width)||(!i_height) )
+ {
+ return( NULL ); /* Can't create a new vout without display size */
+ }
+
+ if( !i_chroma )
+ {
+ /* we make conversion if possible*/
+ i_chroma = VLC_FOURCC('I','4','2','0');
+ msg_Warn( p_vdec->p_fifo, "Internal chroma conversion (FIXME)");
+ /* It's mainly for I410 -> I420 conversion that I've made,
+ it's buggy and very slow */
+ }
+
+ i_aspect = ffmpeg_FfAspect( i_width, i_height, i_aspect );
+
+ /* Spawn a video output if there is none. First we look for our children,
+ * then we look for any other vout that might be available. */
+ p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
+ FIND_CHILD );
+ if( !p_vout )
+ {
+ p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
+ FIND_ANYWHERE );
+ }
+
+ if( p_vout )
+ {
+ if( !ffmpeg_CheckVout( p_vout,
+ i_width, i_height, i_aspect,i_chroma ) )
+ {
+ /* We are not interested in this format, close this vout */
+ vlc_object_detach_all( p_vout );
+ vlc_object_release( p_vout );
+ vout_DestroyThread( p_vout );
+ p_vout = NULL;
+ }
+ else
+ {
+ /* This video output is cool! Hijack it. */
+ vlc_object_detach_all( p_vout );
+ vlc_object_attach( p_vout, p_vdec->p_fifo );
+ vlc_object_release( p_vout );
+ }
+ }
+
+ if( p_vout == NULL )
+ {
+ msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
+
+ p_vout = vout_CreateThread( p_vdec->p_fifo,
+ i_width,
+ i_height,
+ i_chroma,
+ i_aspect );
+ }
+
+ return( p_vout );
+}
+
+/* FIXME FIXME FIXME this is a big shit
+ does someone want to rewrite this function ?
+ or said to me how write a better thing
+ FIXME FIXME FIXME
+*/
+
+static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
+ AVPicture *p_avpicture,
+ videodec_thread_t *p_vdec )
+{
+ u8 *p_src, *p_dst;
+ u8 *p_plane[3];
+ int i_plane;
+
+ int i_stride, i_lines;
+ int i_height, i_width;
+ int i_y, i_x;
+
+ i_height = p_vdec->p_context->height;
+ i_width = p_vdec->p_context->width;
+
+ p_dst = p_pic->p[0].p_pixels;
+ p_src = p_avpicture->data[0];
+
+ /* copy first plane */
+ for( i_y = 0; i_y < i_height; i_y++ )
+ {
+ p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
+ p_dst += p_pic->p[0].i_pitch;
+ p_src += p_avpicture->linesize[0];
+ }
+
+ /* process each plane in a temporary buffer */
+ for( i_plane = 1; i_plane < 3; i_plane++ )
+ {
+ i_stride = p_avpicture->linesize[i_plane];
+ i_lines = i_height / 4;
+
+ p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
+ p_src = p_avpicture->data[i_plane];
+
+ /* for each source line */
+ for( i_y = 0; i_y < i_lines; i_y++ )
+ {
+ for( i_x = 0; i_x < i_stride - 1; i_x++ )
+ {
+ p_dst[2 * i_x ] = p_src[i_x];
+ p_dst[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1]) / 2;
+
+ }
+ p_dst[2 * i_stride - 2] = p_src[i_x];
+ p_dst[2 * i_stride - 1] = p_src[i_x];
+
+ p_dst += 4 * i_stride; /* process the next even lines */
+ p_src += i_stride;
+ }
+
+
+ }
+
+ for( i_plane = 1; i_plane < 3; i_plane++ )
+ {
+ i_stride = p_avpicture->linesize[i_plane];
+ i_lines = i_height / 4;
+
+ p_dst = p_plane[i_plane] + 2*i_stride;
+ p_src = p_plane[i_plane];
+
+ for( i_y = 0; i_y < i_lines - 1; i_y++ )
+ {
+ for( i_x = 0; i_x < 2 * i_stride ; i_x++ )
+ {
+ p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
+ }
+
+ p_dst += 4 * i_stride; /* process the next odd lines */
+ p_src += 4 * i_stride;
+ }
+ /* last line */
+ p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
+ }
+ /* copy to p_pic, by block
+ if I do pixel per pixel it segfault. It's why I use
+ temporaries buffers */
+ for( i_plane = 1; i_plane < 3; i_plane++ )
+ {
+
+ int i_size;
+ p_src = p_plane[i_plane];
+ p_dst = p_pic->p[i_plane].p_pixels;
+
+ i_size = __MIN( 2*i_stride, p_pic->p[i_plane].i_pitch);
+ for( i_y = 0; i_y < __MIN(p_pic->p[i_plane].i_lines, 2 * i_lines); i_y++ )
+ {
+ p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
+ p_src += 2 * i_stride;
+ p_dst += p_pic->p[i_plane].i_pitch;
+ }
+ free( p_plane[i_plane] );
+ }
+
+}
+
+static void ffmpeg_ConvertPicture( picture_t *p_pic,
+ AVPicture *p_avpicture,
+ videodec_thread_t *p_vdec )
+{
+ int i_plane;
+ int i_size;
+ int i_line;
+
+ u8 *p_dst;
+ u8 *p_src;
+ int i_src_stride;
+ int i_dst_stride;
+
+ if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
+ {
+ /* convert ffmpeg picture to our format */
+ for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
+ {
+ p_src = p_avpicture->data[i_plane];
+ p_dst = p_pic->p[i_plane].p_pixels;
+ i_src_stride = p_avpicture->linesize[i_plane];
+ i_dst_stride = p_pic->p[i_plane].i_pitch;
+
+ i_size = __MIN( i_src_stride, i_dst_stride );
+ for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
+ {
+ p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
+ p_src += i_src_stride;
+ p_dst += i_dst_stride;
+ }
+ }
+ return;
+ }
+
+ /* we need to convert to I420 */
+ switch( p_vdec->p_context->pix_fmt )
+ {
+#if LIBAVCODEC_BUILD >= 4615
+ case( PIX_FMT_YUV410P ):
+ ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
+ break;
+#endif
+ default:
+ p_vdec->p_fifo->b_error =1;
+ break;
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * Functions that initialize, decode and end the decoding process
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * InitThread: initialize vdec output thread
+ *****************************************************************************
+ * This function is called from RunDecoderoder and performs the second step
+ * of the initialization. It returns 0 on success. Note that the thread's
+ * flag are not modified inside this function.
+ *****************************************************************************/
+
+static int InitThread( videodec_thread_t *p_vdec )
+{
+ int i_ffmpeg_codec;
+ int i_tmp;
+
+ if( p_vdec->p_fifo->p_demux_data )
+ {
+ ffmpeg_ParseBitMapInfoHeader( &p_vdec->format,
+ (u8*)p_vdec->p_fifo->p_demux_data );
+ }
+ else
+ {
+ msg_Warn( p_vdec->p_fifo, "display informations missing" );
+ }
+
+ /*init ffmpeg */
+ if( !b_ffmpeginit )
+ {
+ avcodec_init();
+ avcodec_register_all();
+ b_ffmpeginit = 1;
+ msg_Dbg( p_vdec->p_fifo, "library ffmpeg initialized" );
+ }
+ else
+ {
+ msg_Dbg( p_vdec->p_fifo, "library ffmpeg already initialized" );
+ }
+ ffmpeg_GetFfmpegCodec( p_vdec->p_fifo->i_fourcc,
+ &i_ffmpeg_codec,
+ &p_vdec->psz_namecodec );
+ p_vdec->p_codec =
+ avcodec_find_decoder( i_ffmpeg_codec );
+
+ if( !p_vdec->p_codec )
+ {
+ msg_Err( p_vdec->p_fifo, "codec not found (%s)",
+ p_vdec->psz_namecodec );
+ return( -1 );
+ }
+
+ p_vdec->p_context = &p_vdec->context;
+ memset( p_vdec->p_context, 0, sizeof( AVCodecContext ) );
+
+ p_vdec->p_context->width = p_vdec->format.i_width;
+ p_vdec->p_context->height = p_vdec->format.i_height;
+
+/* XXX
+ p_vdec->p_context->workaround_bugs
+ --> seems to be for msmpeg 3 but can't know what is supposed to do
+
+ p_vdec->p_context->strict_std_compliance
+ --> strictly follow mpeg4 standard for decoder or encoder ??
+
+ p_vdec->p_context->error_resilience
+ --> don't make error resilience, because of some ms encoder witch
+ use some wrong VLC code.
+*/
+
+#if LIBAVCODEC_BUILD >= 4611
+ i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
+ p_vdec->p_context->workaround_bugs = __MAX( __MIN( i_tmp, 99 ), 0 );
+
+ i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
+ p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
+#endif
+#if LIBAVCODEC_BUILD >= 4614
+ if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
+ {
+ p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
+ }
+#endif
+
+ if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
+ {
+ msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
+ p_vdec->psz_namecodec );
+ return( -1 );
+ }
+ else
+ {
+ msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
+ p_vdec->psz_namecodec );
+ }
+
+ /* first give init data */
+ if( p_vdec->format.i_data )
+ {
+ AVPicture avpicture;
+ int b_gotpicture;
+
+ switch( i_ffmpeg_codec )
+ {
+ case( CODEC_ID_MPEG4 ):
+ avcodec_decode_video( p_vdec->p_context, &avpicture,
+ &b_gotpicture,
+ p_vdec->format.p_data,
+ p_vdec->format.i_data );
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* This will be created after the first decoded frame */
+ p_vdec->p_vout = NULL;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * DecodeThread: Called for decode one frame
+ *****************************************************************************/
+static void DecodeThread( videodec_thread_t *p_vdec )
+{
+ int i_status;
+ int b_drawpicture;
+ int b_gotpicture;
+ AVPicture avpicture; /* ffmpeg picture */
+ picture_t *p_pic; /* videolan picture */
+ /* we have to get a frame stored in a pes
+ give it to ffmpeg decoder
+ and send the image to the output */
+
+ /* TODO implement it in a better way */
+
+ if( ( config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up") )&&
+ ( p_vdec->i_frame_late > 4 ) )
+ {
+#if LIBAVCODEC_BUILD > 4603
+ b_drawpicture = 0;
+ if( p_vdec->i_frame_late < 8 )
+ {
+ p_vdec->p_context->hurry_up = 2;
+ }
+ else
+ {
+ /* too much late picture, won't decode
+ but break picture until a new I, and for mpeg4 ...*/
+ p_vdec->i_frame_late--; /* needed else it will never be decrease */
+ __PES_NEXT( p_vdec->p_fifo );
+ return;
+ }
+#else
+ if( p_vdec->i_frame_late < 8 )
+ {
+ b_drawpicture = 0; /* not really good but .. */
+ }
+ else
+ {
+ /* too much late picture, won't decode
+ but break picture until a new I, and for mpeg4 ...*/
+ p_vdec->i_frame_late--; /* needed else it will never be decrease */
+ __PES_NEXT( p_vdec->p_fifo );
+ return;
+ }
+#endif
+ }
+ else
+ {
+ b_drawpicture = 1;
+#if LIBAVCODEC_BUILD > 4603
+ p_vdec->p_context->hurry_up = 0;
+#endif
+ }
+
+ __GetFrame( p_vdec );
+
+ i_status = avcodec_decode_video( p_vdec->p_context,
+ &avpicture,
+ &b_gotpicture,
+ p_vdec->p_framedata,
+ p_vdec->i_framesize);
+
+ __NextFrame( p_vdec );
+
+ if( i_status < 0 )
+ {
+ msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
+ p_vdec->i_framesize );
+ p_vdec->i_frame_error++;
+ return;
+ }
+ /* Update frame late count*/
+ /* I don't make statistic on decoding time */
+ if( p_vdec->i_pts <= mdate())
+ {
+ p_vdec->i_frame_late++;
+ }
+ else
+ {
+ p_vdec->i_frame_late = 0;
+ }
+
+ if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture)
+ {
+ return;
+ }
+
+ /* Check our vout */
+ if( !ffmpeg_CheckVout( p_vdec->p_vout,
+ p_vdec->p_context->width,
+ p_vdec->p_context->height,
+ p_vdec->p_context->aspect_ratio_info,
+ ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
+ {
+ p_vdec->p_vout =
+ ffmpeg_CreateVout( p_vdec,
+ p_vdec->p_context->width,
+ p_vdec->p_context->height,
+ p_vdec->p_context->aspect_ratio_info,
+ ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt));
+ if( !p_vdec->p_vout )
+ {
+ msg_Err( p_vdec->p_fifo, "cannot create vout" );
+ p_vdec->p_fifo->b_error = 1; /* abort */
+ return;
+ }
+ }
+
+ /* Send decoded frame to vout */
+ while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
+ {
+ if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ ffmpeg_ConvertPicture( p_pic,
+ &avpicture,
+ p_vdec );
+
+
+ /* FIXME correct avi and use i_dts */
+ vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
+ vout_DisplayPicture( p_vdec->p_vout, p_pic );
+
+ return;
+}
+
+
+/*****************************************************************************
+ * EndThread: thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+static void EndThread( videodec_thread_t *p_vdec )
+{
+ if( !p_vdec )
+ {
+ return;
+ }
+
+ if( p_vdec->p_context != NULL)
+ {
+ avcodec_close( p_vdec->p_context );
+ msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) stopped",
+ p_vdec->psz_namecodec );
+ }
+
+ if( p_vdec->p_vout != NULL )
+ {
+ /* We are about to die. Reattach video output to p_vlc. */
+ vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
+ vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
+ }
+
+ if( p_vdec->format.p_data != NULL)
+ {
+ free( p_vdec->format.p_data );
+ }
+
+ free( p_vdec );
+}
--- /dev/null
+/*****************************************************************************
+ * ffmpeg_vdec.h: video decoder using ffmpeg library
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: ffmpeg.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/* Pour un flux video */
+typedef struct bitmapinfoheader_s
+{
+ u32 i_size; /* size of header */
+ u32 i_width;
+ u32 i_height;
+ u16 i_planes;
+ u16 i_bitcount;
+ u32 i_compression;
+ u32 i_sizeimage;
+ u32 i_xpelspermeter;
+ u32 i_ypelspermeter;
+ u32 i_clrused;
+ u32 i_clrimportant;
+
+ int i_data;
+ u8 *p_data;
+
+} bitmapinfoheader_t;
+
+/* MPEG4 video */
+#define FOURCC_DIVX VLC_FOURCC('D','I','V','X')
+#define FOURCC_divx VLC_FOURCC('d','i','v','x')
+#define FOURCC_DIV1 VLC_FOURCC('D','I','V','1')
+#define FOURCC_div1 VLC_FOURCC('d','i','v','1')
+#define FOURCC_MP4S VLC_FOURCC('M','P','4','S')
+#define FOURCC_mp4s VLC_FOURCC('m','p','4','s')
+#define FOURCC_M4S2 VLC_FOURCC('M','4','S','2')
+#define FOURCC_m4s2 VLC_FOURCC('m','4','s','2')
+#define FOURCC_xvid VLC_FOURCC('x','v','i','d')
+#define FOURCC_XVID VLC_FOURCC('X','V','I','D')
+#define FOURCC_XviD VLC_FOURCC('X','v','i','D')
+#define FOURCC_DX50 VLC_FOURCC('D','X','5','0')
+#define FOURCC_mp4v VLC_FOURCC('m','p','4','v')
+#define FOURCC_4 VLC_FOURCC( 4, 0, 0, 0 )
+
+/* MSMPEG4 v2 */
+#define FOURCC_MPG4 VLC_FOURCC('M','P','G','4')
+#define FOURCC_mpg4 VLC_FOURCC('m','p','g','4')
+#define FOURCC_DIV2 VLC_FOURCC('D','I','V','2')
+#define FOURCC_div2 VLC_FOURCC('d','i','v','2')
+#define FOURCC_MP42 VLC_FOURCC('M','P','4','2')
+#define FOURCC_mp42 VLC_FOURCC('m','p','4','2')
+
+/* MSMPEG4 v3 / M$ mpeg4 v3 */
+#define FOURCC_MPG3 VLC_FOURCC('M','P','G','3')
+#define FOURCC_mpg3 VLC_FOURCC('m','p','g','3')
+#define FOURCC_div3 VLC_FOURCC('d','i','v','3')
+#define FOURCC_MP43 VLC_FOURCC('M','P','4','3')
+#define FOURCC_mp43 VLC_FOURCC('m','p','4','3')
+
+/* DivX 3.20 */
+#define FOURCC_DIV3 VLC_FOURCC('D','I','V','3')
+#define FOURCC_DIV4 VLC_FOURCC('D','I','V','4')
+#define FOURCC_div4 VLC_FOURCC('d','i','v','4')
+#define FOURCC_DIV5 VLC_FOURCC('D','I','V','5')
+#define FOURCC_div5 VLC_FOURCC('d','i','v','5')
+#define FOURCC_DIV6 VLC_FOURCC('D','I','V','6')
+#define FOURCC_div6 VLC_FOURCC('d','i','v','6')
+
+/* AngelPotion stuff */
+#define FOURCC_AP41 VLC_FOURCC('A','P','4','1')
+
+/* ?? */
+#define FOURCC_3IV1 VLC_FOURCC('3','I','V','1')
+#define FOURCC_3IV2 VLC_FOURCC('3','I','V','2')
+
+/* H263 and H263i */
+#define FOURCC_H263 VLC_FOURCC('H','2','6','3')
+#define FOURCC_h263 VLC_FOURCC('h','2','6','3')
+#define FOURCC_U263 VLC_FOURCC('U','2','6','3')
+#define FOURCC_I263 VLC_FOURCC('I','2','6','3')
+#define FOURCC_i263 VLC_FOURCC('i','2','6','3')
+
+/* Sorenson v1 */
+#define FOURCC_SVQ1 VLC_FOURCC( 'S', 'V', 'Q', '1' )
+
+static int ffmpeg_GetFfmpegCodec( vlc_fourcc_t i_fourcc,
+ int *pi_ffmpeg_codec,
+ char **ppsz_name )
+{
+ int i_codec = 0;
+ char *psz_name = NULL;
+
+ switch( i_fourcc )
+ {
+#if LIBAVCODEC_BUILD >= 4608
+ case FOURCC_DIV1:
+ case FOURCC_div1:
+ case FOURCC_MPG4:
+ case FOURCC_mpg4:
+ i_codec = CODEC_ID_MSMPEG4V1;
+ psz_name = "MS MPEG-4 v1";
+ break;
+
+ case FOURCC_DIV2:
+ case FOURCC_div2:
+ case FOURCC_MP42:
+ case FOURCC_mp42:
+ i_codec = CODEC_ID_MSMPEG4V2;
+ psz_name = "MS MPEG-4 v2";
+ break;
+#endif
+
+ case FOURCC_MPG3:
+ case FOURCC_mpg3:
+ case FOURCC_div3:
+ case FOURCC_MP43:
+ case FOURCC_mp43:
+ case FOURCC_DIV3:
+ case FOURCC_DIV4:
+ case FOURCC_div4:
+ case FOURCC_DIV5:
+ case FOURCC_div5:
+ case FOURCC_DIV6:
+ case FOURCC_div6:
+ case FOURCC_AP41:
+ case FOURCC_3IV1:
+#if LIBAVCODEC_BUILD >= 4608
+ i_codec = CODEC_ID_MSMPEG4V3;
+#else
+ i_codec = CODEC_ID_MSMPEG4;
+#endif
+ psz_name = "MS MPEG-4 v3";
+ break;
+
+#if LIBAVCODEC_BUILD >= 4615
+ case FOURCC_SVQ1:
+ i_codec = CODEC_ID_SVQ1;
+ psz_name = "SVQ-1 (Sorenson Video v1)";
+ break;
+#endif
+
+ case FOURCC_DIVX:
+ case FOURCC_divx:
+ case FOURCC_MP4S:
+ case FOURCC_mp4s:
+ case FOURCC_M4S2:
+ case FOURCC_m4s2:
+ case FOURCC_xvid:
+ case FOURCC_XVID:
+ case FOURCC_XviD:
+ case FOURCC_DX50:
+ case FOURCC_mp4v:
+ case FOURCC_4:
+ case FOURCC_3IV2:
+
+ i_codec = CODEC_ID_MPEG4;
+ psz_name = "MPEG-4";
+ break;
+
+ case FOURCC_H263:
+ case FOURCC_h263:
+ case FOURCC_U263:
+ i_codec = CODEC_ID_H263;
+ psz_name = "H263";
+ break;
+
+ case FOURCC_I263:
+ case FOURCC_i263:
+ i_codec = CODEC_ID_H263I;
+ psz_name = "I263.I";
+ break;
+ }
+
+ if( i_codec )
+ {
+ if( pi_ffmpeg_codec ) *pi_ffmpeg_codec = i_codec;
+ if( ppsz_name ) *ppsz_name = psz_name;
+ return VLC_TRUE;
+ }
+
+ return VLC_FALSE;
+}
+
+
+typedef struct videodec_thread_s
+{
+ decoder_fifo_t *p_fifo;
+
+ bitmapinfoheader_t format;
+
+ AVCodecContext context, *p_context;
+ AVCodec *p_codec;
+ vout_thread_t *p_vout;
+
+ char *psz_namecodec;
+ /* private */
+ mtime_t i_pts;
+ int i_framesize;
+ byte_t *p_framedata;
+
+ int i_frame_error;
+ int i_frame_skip;
+ int i_frame_late; /* how may frame decoded are in late */
+
+} videodec_thread_t;
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+lpcm_SOURCES = lpcm.c
--- /dev/null
+/*****************************************************************************
+ * lpcm.c: lpcm decoder module
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: lpcm.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Henri Fallon <henri@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy(), memset() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> /* getpid() */
+#endif
+
+#include "lpcm.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+
+ void DecodeFrame ( lpcmdec_thread_t * );
+static int InitThread ( lpcmdec_thread_t * );
+static void EndThread ( lpcmdec_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("linear PCM audio decoder") );
+ set_capability( "decoder", 100 );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc != VLC_FOURCC('l','p','c','m') )
+ {
+ return VLC_EGENERIC;
+ }
+
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * RunDecoder: the lpcm decoder
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t * p_fifo )
+{
+ lpcmdec_thread_t * p_lpcmdec;
+
+ /* Allocate the memory needed to store the thread's structure */
+ if( (p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t)) )
+ == NULL)
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_lpcmdec->p_fifo = p_fifo;
+
+ if( InitThread( p_lpcmdec ) )
+ {
+ DecoderError( p_fifo );
+ free( p_lpcmdec );
+ return( -1 );
+ }
+
+ /* lpcm decoder thread's main loop */
+ while ((!p_lpcmdec->p_fifo->b_die) && (!p_lpcmdec->p_fifo->b_error))
+ {
+ DecodeFrame(p_lpcmdec);
+ }
+
+ /* If b_error is set, the lpcm decoder thread enters the error loop */
+ if (p_lpcmdec->p_fifo->b_error)
+ {
+ DecoderError( p_lpcmdec->p_fifo );
+ }
+
+ /* End of the lpcm decoder thread */
+ EndThread (p_lpcmdec);
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * InitThread : initialize an lpcm decoder thread
+ *****************************************************************************/
+static int InitThread (lpcmdec_thread_t * p_lpcmdec)
+{
+
+ /* Init the BitStream */
+ InitBitstream( &p_lpcmdec->bit_stream, p_lpcmdec->p_fifo,
+ NULL, NULL);
+
+ /* Creating the audio output fifo */
+ p_lpcmdec->p_aout_fifo =
+ aout_CreateFifo( p_lpcmdec->p_fifo, AOUT_FIFO_PCM,
+ 2, 48000, LPCMDEC_FRAME_SIZE / 2, NULL );
+ if ( p_lpcmdec->p_aout_fifo == NULL )
+ {
+ return( -1 );
+ }
+ return( 0 );
+}
+
+/*****************************************************************************
+ * DecodeFrame: decodes a frame.
+ *****************************************************************************/
+void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
+{
+ byte_t * buffer,p_temp[LPCMDEC_FRAME_SIZE];
+ vlc_bool_t b_sync;
+ int i_loop;
+
+ CurrentPTS( &p_lpcmdec->bit_stream,
+ &p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame],
+ NULL );
+ if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] )
+ {
+ p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->i_end_frame] =
+ LAST_MDATE;
+ }
+
+ buffer = ((byte_t *)p_lpcmdec->p_aout_fifo->buffer) +
+ (p_lpcmdec->p_aout_fifo->i_end_frame * LPCMDEC_FRAME_SIZE);
+
+ RemoveBits32(&p_lpcmdec->bit_stream);
+#if 0
+ byte1 = GetBits(&p_lpcmdec->bit_stream, 8) ;
+ byte2 = GetBits(&p_lpcmdec->bit_stream, 8) ;
+
+ /* I only have 2 test streams. As far as I understand
+ * after the RemoveBits and the 2 GetBits, we should be exactly
+ * where we whant : the sync word : 0x0180.
+ * If not, we got and find it. */
+ while( ( byte1 != 0x01 || byte2 != 0x80 ) && (!p_lpcmdec->p_fifo->b_die)
+ && (!p_lpcmdec->p_fifo->b_error) )
+ {
+ byte1 = byte2;
+ byte2 = GetBits(&p_lpcmdec->bit_stream, 8);
+ }
+#else
+ b_sync = 0;
+ while( ( !p_lpcmdec->p_fifo->b_die ) &&
+ ( !p_lpcmdec->p_fifo->b_error ) &&
+ ( !b_sync ) )
+ {
+ while( ( !p_lpcmdec->p_fifo->b_die ) &&
+ ( !p_lpcmdec->p_fifo->b_error ) &&
+ ( GetBits( &p_lpcmdec->bit_stream, 8 ) != 0x01 ) );
+ b_sync = ( ShowBits( &p_lpcmdec->bit_stream, 8 ) == 0x80 );
+ }
+ RemoveBits( &p_lpcmdec->bit_stream, 8 );
+#endif
+
+ GetChunk( &p_lpcmdec->bit_stream, p_temp, LPCMDEC_FRAME_SIZE);
+ if( p_lpcmdec->p_fifo->b_die || p_lpcmdec->p_fifo->b_error ) return;
+
+ for( i_loop = 0; i_loop < LPCMDEC_FRAME_SIZE/2; i_loop++ )
+ {
+ buffer[2*i_loop]=p_temp[2*i_loop+1];
+ buffer[2*i_loop+1]=p_temp[2*i_loop];
+ }
+
+ vlc_mutex_lock (&p_lpcmdec->p_aout_fifo->data_lock);
+ p_lpcmdec->p_aout_fifo->i_end_frame =
+ (p_lpcmdec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
+ vlc_cond_signal (&p_lpcmdec->p_aout_fifo->data_wait);
+ vlc_mutex_unlock (&p_lpcmdec->p_aout_fifo->data_lock);
+}
+
+/*****************************************************************************
+ * EndThread : lpcm decoder thread destruction
+ *****************************************************************************/
+static void EndThread( lpcmdec_thread_t * p_lpcmdec )
+{
+ /* If the audio output fifo was created, we destroy it */
+ if( p_lpcmdec->p_aout_fifo != NULL )
+ {
+ aout_DestroyFifo( p_lpcmdec->p_aout_fifo );
+
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock( &(p_lpcmdec->p_aout_fifo->data_lock) );
+ vlc_cond_signal( &(p_lpcmdec->p_aout_fifo->data_wait) );
+ vlc_mutex_unlock( &(p_lpcmdec->p_aout_fifo->data_lock) );
+ }
+
+ /* Destroy descriptor */
+ free( p_lpcmdec );
+}
--- /dev/null
+/*****************************************************************************
+ * lpcm.h : lpcm decoder module
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: lpcm.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+#define LPCMDEC_FRAME_SIZE (2008)
+
+/*****************************************************************************
+ * lpcmdec_thread_t : lpcm decoder thread descriptor
+ *****************************************************************************/
+typedef struct lpcmdec_thread_s
+{
+ /*
+ * Thread properties
+ */
+ vlc_thread_t thread_id; /* id for thread functions */
+
+ /*
+ * Input properties
+ */
+ decoder_fifo_t * p_fifo; /* stores the PES stream data */
+ int sync_ptr; /* sync ptr from lpcm magic header */
+
+ /*
+ * Output properties
+ */
+ aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
+
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+
+} lpcmdec_thread_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+vlc_thread_t lpcmdec_CreateThread( decoder_fifo_t * p_fifo );
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+mad_SOURCES = decoder.c libmad.c
--- /dev/null
+/***************************************************************************
+ decoder.c - description
+ -------------------
+ Plugin Module definition for using libmad audio decoder in vlc. The
+ libmad codec uses integer arithmic only. This makes it suitable for using
+ it on architectures without a hardware FPU unit, such as the StrongArm
+ CPU.
+
+ begin : Mon Nov 5 2001
+ copyright : (C) 2001 by Jean-Paul Saman
+ email : jpsaman@wxs.nl
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+
+/*****************************************************************************
+ * Libmad include files *
+ *****************************************************************************/
+#include <mad.h>
+#include "decoder.h"
+#include "libmad.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+static int InitThread ( mad_adec_thread_t * p_mad_adec );
+static void EndThread ( mad_adec_thread_t * p_mad_adec );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define DOWNSCALE_TEXT N_("Mad audio downscale routine (fast,mp321)")
+#define DOWNSCALE_LONGTEXT N_( \
+ "Specify the mad audio downscale routine you want to use. By default " \
+ "the mad plugin will use the fastest routine.")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT );
+ set_description( _("libmad MPEG 1/2/3 audio decoder") );
+ set_capability( "decoder", 100 );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to choose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','a') )
+ {
+ return VLC_EGENERIC;
+ }
+
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+ mad_adec_thread_t * p_mad_adec;
+
+ /* Allocate the memory needed to store the thread's structure */
+ p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
+
+ if (p_mad_adec == NULL)
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_mad_adec->p_fifo = p_fifo;
+ if( InitThread( p_mad_adec ) )
+ {
+ msg_Err( p_fifo, "could not initialize thread" );
+ DecoderError( p_fifo );
+ free( p_mad_adec );
+ return( -1 );
+ }
+
+ /* mad decoder thread's main loop */
+ while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
+ {
+ msg_Dbg( p_mad_adec->p_fifo, "starting libmad decoder" );
+ if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
+ {
+ msg_Err( p_mad_adec->p_fifo, "libmad decoder returned abnormally" );
+ DecoderError( p_mad_adec->p_fifo );
+ EndThread(p_mad_adec);
+ return( -1 );
+ }
+ }
+
+ /* If b_error is set, the mad decoder thread enters the error loop */
+ if (p_mad_adec->p_fifo->b_error)
+ {
+ DecoderError( p_mad_adec->p_fifo );
+ }
+
+ /* End of the mad decoder thread */
+ EndThread (p_mad_adec);
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * InitThread: initialize data before entering main loop
+ *****************************************************************************/
+static int InitThread( mad_adec_thread_t * p_mad_adec )
+{
+ decoder_fifo_t * p_fifo = p_mad_adec->p_fifo;
+ char *psz_downscale = NULL;
+
+ /*
+ * Properties of audio for libmad
+ */
+
+ /* Look what scaling method was requested by the user */
+ psz_downscale = config_GetPsz( p_fifo, "downscale" );
+
+ if ( strncmp(psz_downscale,"fast",4)==0 )
+ {
+ p_mad_adec->audio_scaling = FAST_SCALING;
+ msg_Dbg( p_fifo, "downscale fast selected" );
+ }
+ else if ( strncmp(psz_downscale,"mpg321",7)==0 )
+ {
+ p_mad_adec->audio_scaling = MPG321_SCALING;
+ msg_Dbg( p_fifo, "downscale mpg321 selected" );
+ }
+ else
+ {
+ p_mad_adec->audio_scaling = FAST_SCALING;
+ msg_Dbg( p_fifo, "downscale default fast selected" );
+ }
+
+ if (psz_downscale) free(psz_downscale);
+
+ /* Initialize the libmad decoder structures */
+ p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
+ if (p_mad_adec->libmad_decoder == NULL)
+ {
+ msg_Err( p_mad_adec->p_fifo, "out of memory" );
+ return -1;
+ }
+ p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
+
+ mad_decoder_init( p_mad_adec->libmad_decoder,
+ p_mad_adec, /* vlc's thread structure and p_fifo playbuffer */
+ libmad_input, /* input_func */
+ 0, /* header_func */
+ 0, /* filter */
+ libmad_output, /* output_func */
+ 0, /* error */
+ 0); /* message */
+
+ mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
+// mad_timer_reset(&p_mad_adec->libmad_timer);
+
+ /*
+ * Initialize the output properties
+ */
+ p_mad_adec->p_aout_fifo = NULL;
+
+ /*
+ * Initialize the input properties
+ */
+ /* Get the first data packet. */
+ vlc_mutex_lock( &p_fifo->data_lock );
+ while ( p_fifo->p_first == NULL )
+ {
+ if ( p_fifo->b_die )
+ {
+ vlc_mutex_unlock( &p_fifo->data_lock );
+ return( -1 );
+ }
+ vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+ }
+ vlc_mutex_unlock( &p_fifo->data_lock );
+ p_mad_adec->p_data = p_fifo->p_first->p_first;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * EndThread : libmad decoder thread destruction
+ *****************************************************************************/
+static void EndThread (mad_adec_thread_t * p_mad_adec)
+{
+ /* If the audio output fifo was created, we destroy it */
+ if (p_mad_adec->p_aout_fifo != NULL)
+ {
+ aout_DestroyFifo (p_mad_adec->p_aout_fifo);
+
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
+ vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
+ vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
+ }
+
+ /* mad_decoder_finish releases the memory allocated inside the struct */
+ mad_decoder_finish( p_mad_adec->libmad_decoder );
+
+ /* Unlock the modules, p_mad_adec->p_fifo is released by the decoder subsystem */
+ free( p_mad_adec->libmad_decoder );
+ free( p_mad_adec );
+}
+
--- /dev/null
+/***************************************************************************
+ mad_adec.h - description
+ -------------------
+ begin : Mon Nov 5 2001
+ copyright : (C) 2001 by Jean-Paul Saman
+ email : jpsaman@wxs.nl
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _VLC_MAD_ADEC_H_
+#define _VLC_MAD_ADEC_H_
+
+/*****************************************************************************
+ * mad_adec_thread_t : mad decoder thread descriptor
+ *****************************************************************************/
+
+enum mad_scaling { FAST_SCALING, MPG321_SCALING };
+
+typedef struct mad_adec_thread_s
+{
+ /*
+ * Decoder properties
+ */
+ struct mad_decoder *libmad_decoder;
+ mad_timer_t libmad_timer;
+ byte_t buffer[MAD_BUFFER_MDLEN];
+
+ /*
+ * Thread properties
+ */
+ vlc_thread_t thread_id; /* id for thread functions */
+
+ /*
+ * Input properties
+ */
+ decoder_fifo_t * p_fifo; /* stores the PES stream data */
+ data_packet_t * p_data;
+
+ /* Store i_pts for syncing audio frames */
+ mtime_t i_current_pts, i_next_pts;
+
+ /*
+ * Output properties
+ */
+ aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
+ enum mad_scaling audio_scaling;
+
+} mad_adec_thread_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+vlc_thread_t mad_adec_CreateThread( decoder_fifo_t * p_fifo );
+
+#endif
--- /dev/null
+/***************************************************************************
+ libmad.c - description
+ -------------------
+ Functions that are called by libmad to communicate with vlc decoder
+ infrastructure.
+
+ begin : Mon Nov 5 2001
+ copyright : (C) 2001 by Jean-Paul Saman
+ email : jpsaman@wxs.nl
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+
+/*****************************************************************************
+ * Libmad includes files
+ *****************************************************************************/
+#include <mad.h>
+#include "decoder.h"
+#include "libmad.h"
+
+static void PrintFrameInfo(struct mad_header *Header);
+
+/*****************************************************************************
+ * libmad_input: this function is called by libmad when the input buffer needs
+ * to be filled.
+ *****************************************************************************/
+enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
+{
+ mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data;
+ size_t ReadSize, Remaining;
+ unsigned char *ReadStart;
+
+ if ( p_mad_adec->p_fifo->b_die == 1 ) {
+ msg_Dbg( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" );
+ return MAD_FLOW_STOP;
+ }
+
+ if ( p_mad_adec->p_fifo->b_error == 1 ) {
+ msg_Warn( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" );
+ return MAD_FLOW_IGNORE;
+ }
+
+ /* libmad_stream_buffer does not consume the total buffer, it consumes only data
+ * for one frame only. So all data left in the buffer should be put back in front.
+ */
+ if ((p_libmad_stream->buffer==NULL) || (p_libmad_stream->error==MAD_ERROR_BUFLEN))
+ {
+ /* libmad does not consume all the buffer it's given. Some
+ * datas, part of a truncated frame, is left unused at the
+ * end of the buffer. Those datas must be put back at the
+ * beginning of the buffer and taken in account for
+ * refilling the buffer. This means that the input buffer
+ * must be large enough to hold a complete frame at the
+ * highest observable bit-rate (currently 448 kb/s). XXX=XXX
+ * Is 2016 bytes the size of the largest frame?
+ * (448000*(1152/32000))/8
+ */
+ if(p_libmad_stream->next_frame!=NULL)
+ {
+ Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
+ if( p_mad_adec->buffer != p_libmad_stream->next_frame )
+ {
+ memcpy( p_mad_adec->buffer,
+ p_libmad_stream->next_frame, Remaining );
+ }
+ ReadStart=p_mad_adec->buffer+Remaining;
+ ReadSize=(MAD_BUFFER_MDLEN)-Remaining;
+
+ /* Store time stamp of next frame */
+ p_mad_adec->i_current_pts = p_mad_adec->i_next_pts;
+ p_mad_adec->i_next_pts = p_mad_adec->p_fifo->p_first->i_pts;
+ }
+ else
+ {
+ ReadSize=(MAD_BUFFER_MDLEN);
+ ReadStart=p_mad_adec->buffer;
+ Remaining=0;
+ p_mad_adec->i_next_pts = 0;
+ p_mad_adec->i_current_pts = p_mad_adec->p_fifo->p_first->i_pts;
+ }
+
+ /* Fill-in the buffer. If an error occurs print a message
+ * and leave the decoding loop. If the end of stream is
+ * reached we also leave the loop but the return status is
+ * left untouched.
+ */
+ if( ReadSize > p_mad_adec->p_data->p_payload_end
+ - p_mad_adec->p_data->p_payload_start )
+ {
+ ReadSize = p_mad_adec->p_data->p_payload_end
+ - p_mad_adec->p_data->p_payload_start;
+ memcpy( ReadStart, p_mad_adec->p_data->p_payload_start, ReadSize );
+ NextDataPacket( p_mad_adec->p_fifo, &p_mad_adec->p_data );
+ }
+ else
+ {
+ memcpy( ReadStart, p_mad_adec->p_data->p_payload_start, ReadSize );
+ p_mad_adec->p_data->p_payload_start += ReadSize;
+ }
+
+ if ( p_mad_adec->p_fifo->b_die == 1 )
+ {
+ msg_Dbg( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" );
+ return MAD_FLOW_STOP;
+ }
+
+ if ( p_mad_adec->p_fifo->b_error == 1 )
+ {
+ msg_Warn( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" );
+ return MAD_FLOW_IGNORE;
+ }
+
+ /* Pipe the new buffer content to libmad's stream decoder facility.
+ * Libmad never copies the buffer, but just references it. So keep it in
+ * mad_adec_thread_t structure.
+ */
+ mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer,
+ Remaining + ReadSize);
+ p_libmad_stream->error=0;
+ }
+
+ return MAD_FLOW_CONTINUE;
+}
+
+/*****************************************************************************
+ * libmad_header: this function is called just after the header of a frame is
+ * decoded
+ *****************************************************************************/
+/*
+ *enum mad_flow libmad_header(void *data, struct mad_header const *p_libmad_header)
+ *{
+ * mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data;
+ *
+ * msg_Err( p_mad_adec->p_fifo, "libmad_header samplerate %d", p_libmad_header->samplerate);
+ *
+ * PrintFrameInfo(p_limad_mad_header)
+ * return MAD_FLOW_CONTINUE;
+ *}
+ */
+
+/*****************************************************************************
+ * lib_mad_filter: this function is called to filter data of a frame
+ *****************************************************************************/
+/* enum mad_flow libmad_filter(void *data, struct mad_stream const *p_libmad_stream, struct mad_frame *p_libmad_frame)
+ * {
+ * return MAD_FLOW_CONTINUE;
+ * }
+ */
+
+/*****************************************************************************
+ * support routines borrowed from mpg321 (file: mad.c), which is distributed
+ * under GPL license
+ *
+ * mpg321 was written by Joe Drew <drew@debian.org>, and based upon 'plaympeg'
+ * from the smpeg sources, which was written by various people from Loki Software
+ * (http://www.lokigames.com).
+ *
+ * It also incorporates some source from mad, written by Robert Leslie
+ *****************************************************************************/
+
+/* The following two routines and data structure are from the ever-brilliant
+ Rob Leslie.
+*/
+
+struct audio_dither {
+ mad_fixed_t error[3];
+ mad_fixed_t random;
+};
+
+/*
+* NAME: prng()
+* DESCRIPTION: 32-bit pseudo-random number generator
+*/
+static inline unsigned long prng(unsigned long state)
+{
+ return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
+}
+
+/*
+* NAME: mpg321_s24_to_s16_pcm()
+* DESCRIPTION: generic linear sample quantize and dither routine
+*/
+static inline signed int mpg321_s24_to_s16_pcm(unsigned int bits, mad_fixed_t sample,
+ struct audio_dither *dither)
+{
+ unsigned int scalebits;
+ mad_fixed_t output, mask, random;
+
+ enum {
+ MIN = -MAD_F_ONE,
+ MAX = MAD_F_ONE - 1
+ };
+
+ /* noise shape */
+ sample += dither->error[0] - dither->error[1] + dither->error[2];
+
+ dither->error[2] = dither->error[1];
+ dither->error[1] = dither->error[0] / 2;
+
+ /* bias */
+ output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1));
+
+ scalebits = MAD_F_FRACBITS + 1 - bits;
+ mask = (1L << scalebits) - 1;
+
+ /* dither */
+ random = prng(dither->random);
+ output += (random & mask) - (dither->random & mask);
+
+ dither->random = random;
+
+ /* clip */
+ if (output > MAX) {
+ output = MAX;
+
+ if (sample > MAX)
+ sample = MAX;
+ }
+ else if (output < MIN) {
+ output = MIN;
+
+ if (sample < MIN)
+ sample = MIN;
+ }
+
+ /* quantize */
+ output &= ~mask;
+
+ /* error feedback */
+ dither->error[0] = sample - output;
+
+ /* scale */
+ return output >> scalebits;
+}
+
+/*****************************************************************************
+ * s24_to_s16_pcm: Scale a 24 bit pcm sample to a 16 bit pcm sample.
+ *****************************************************************************/
+static inline mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
+{
+ /* round */
+ sample += (1L << (MAD_F_FRACBITS - 16));
+
+ /* clip */
+ if (sample >= MAD_F_ONE)
+ sample = MAD_F_ONE - 1;
+ else if (sample < -MAD_F_ONE)
+ sample = -MAD_F_ONE;
+
+ /* quantize */
+ return sample >> (MAD_F_FRACBITS + 1 - 16);
+}
+
+/*****************************************************************************
+ * libmad_ouput: this function is called just after the frame is decoded
+ *****************************************************************************/
+enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header, struct mad_pcm *p_libmad_pcm)
+{
+ mad_adec_thread_t *p_mad_adec= (mad_adec_thread_t *) data;
+ byte_t *buffer=NULL;
+ mad_fixed_t const *left_ch = p_libmad_pcm->samples[0], *right_ch = p_libmad_pcm->samples[1];
+ register int nsamples = p_libmad_pcm->length;
+ mad_fixed_t sample;
+ static struct audio_dither dither;
+
+ /* Creating the audio output fifo.
+ * Assume the samplerate and nr of channels from the first decoded frame is right for the entire audio track.
+ */
+ if (p_mad_adec->p_aout_fifo==NULL)
+ {
+ p_mad_adec->p_aout_fifo = aout_CreateFifo(
+ p_mad_adec->p_fifo,
+ AOUT_FIFO_PCM, /* fifo type */
+ 2, /*p_libmad_pcm->channels,*/ /* nr. of channels */
+ p_libmad_pcm->samplerate, /* frame rate in Hz ?*/
+ p_libmad_pcm->length*2, /* length of output buffer *2 channels*/
+ NULL ); /* buffer */
+
+ if ( p_mad_adec->p_aout_fifo == NULL )
+ {
+ return MAD_FLOW_BREAK;
+ }
+
+ msg_Dbg( p_mad_adec->p_fifo, "aout fifo created");
+ }
+
+ if (p_mad_adec->p_aout_fifo->i_rate != p_libmad_pcm->samplerate)
+ {
+ msg_Warn( p_mad_adec->p_fifo, "samplerate is changing from [%d] Hz "
+ "to [%d] Hz, sample size [%d], error_code [%0x]",
+ p_mad_adec->p_aout_fifo->i_rate, p_libmad_pcm->samplerate,
+ p_libmad_pcm->length,
+ p_mad_adec->libmad_decoder->sync->stream.error );
+ p_mad_adec->p_aout_fifo->i_rate = p_libmad_pcm->samplerate;
+ }
+
+ if( p_mad_adec->i_current_pts )
+ {
+ p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->i_end_frame]
+ = p_mad_adec->i_current_pts;
+ }
+ else
+ {
+ p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->i_end_frame]
+ = LAST_MDATE;
+ }
+// mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
+
+ buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->i_end_frame * (p_libmad_pcm->length*4));
+
+ while (nsamples--)
+ {
+ switch (p_mad_adec->audio_scaling)
+ {
+ case MPG321_SCALING:
+ sample = mpg321_s24_to_s16_pcm(16, *left_ch++, &dither);
+ break;
+ case FAST_SCALING: /* intended fall through */
+ default:
+ sample = s24_to_s16_pcm(*left_ch++);
+ break;
+ }
+
+ /* left audio channel */
+#ifndef WORDS_BIGENDIAN
+ *buffer++ = (byte_t) (sample >> 0);
+ *buffer++ = (byte_t) (sample >> 8);
+#else
+ *buffer++ = (byte_t) (sample >> 8);
+ *buffer++ = (byte_t) (sample >> 0);
+#endif
+ if (p_libmad_pcm->channels == 2)
+ {
+ /* right audio channel */
+ switch (p_mad_adec->audio_scaling)
+ {
+ case MPG321_SCALING:
+ sample = mpg321_s24_to_s16_pcm(16, *right_ch++, &dither);
+ break;
+ case FAST_SCALING: /* intended fall through */
+ default:
+ sample = s24_to_s16_pcm(*right_ch++);
+ break;
+ }
+ }
+ /* else reuse left_ch */
+#ifndef WORDS_BIGENDIAN
+ *buffer++ = (byte_t) (sample >> 0);
+ *buffer++ = (byte_t) (sample >> 8);
+#else
+ *buffer++ = (byte_t) (sample >> 8);
+ *buffer++ = (byte_t) (sample >> 0);
+#endif
+ }
+
+ /* DEBUG */
+ /*
+ if (p_libmad_pcm->channels == 1) {
+ msg_Dbg( p_mad_adec->p_fifo, "libmad_output channels [%d]", p_libmad_pcm->channels);
+ }
+ */
+
+ vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock);
+ p_mad_adec->p_aout_fifo->i_end_frame = (p_mad_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
+ vlc_cond_signal (&p_mad_adec->p_aout_fifo->data_wait);
+ vlc_mutex_unlock (&p_mad_adec->p_aout_fifo->data_lock);
+
+ return MAD_FLOW_CONTINUE;
+}
+
+/*****************************************************************************
+ * libmad_error: this function is called when an error occurs during decoding
+ *****************************************************************************/
+enum mad_flow libmad_error(void *data, struct mad_stream *p_libmad_stream, struct mad_frame *p_libmad_frame)
+{
+ enum mad_flow result = MAD_FLOW_CONTINUE;
+
+ switch (p_libmad_stream->error)
+ {
+ case MAD_ERROR_BUFLEN: /* input buffer too small (or EOF) */
+//X intf_ErrMsg("libmad error: input buffer too small (or EOF)");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BUFPTR: /* invalid (null) buffer pointer */
+//X intf_ErrMsg("libmad error: invalid (null) buffer pointer");
+ result = MAD_FLOW_STOP;
+ break;
+ case MAD_ERROR_NOMEM: /* not enough memory */
+//X intf_ErrMsg("libmad error: invalid (null) buffer pointer");
+ result = MAD_FLOW_STOP;
+ break;
+ case MAD_ERROR_LOSTSYNC: /* lost synchronization */
+//X intf_ErrMsg("libmad error: lost synchronization");
+ mad_stream_sync(p_libmad_stream);
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADLAYER: /* reserved header layer value */
+//X intf_ErrMsg("libmad error: reserved header layer value");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADBITRATE: /* forbidden bitrate value */
+//X intf_ErrMsg("libmad error: forbidden bitrate value");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADSAMPLERATE: /* reserved sample frequency value */
+//X intf_ErrMsg("libmad error: reserved sample frequency value");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADEMPHASIS: /* reserved emphasis value */
+//X intf_ErrMsg("libmad error: reserverd emphasis value");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADCRC: /* CRC check failed */
+//X intf_ErrMsg("libmad error: CRC check failed");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADBITALLOC: /* forbidden bit allocation value */
+//X intf_ErrMsg("libmad error: forbidden bit allocation value");
+ result = MAD_FLOW_IGNORE;
+ break;
+ case MAD_ERROR_BADSCALEFACTOR:/* bad scalefactor index */
+//X intf_ErrMsg("libmad error: bad scalefactor index");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADFRAMELEN: /* bad frame length */
+//X intf_ErrMsg("libmad error: bad frame length");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADBIGVALUES: /* bad big_values count */
+//X intf_ErrMsg("libmad error: bad big values count");
+ result = MAD_FLOW_IGNORE;
+ break;
+ case MAD_ERROR_BADBLOCKTYPE: /* reserved block_type */
+//X intf_ErrMsg("libmad error: reserverd block_type");
+ result = MAD_FLOW_IGNORE;
+ break;
+ case MAD_ERROR_BADSCFSI: /* bad scalefactor selection info */
+//X intf_ErrMsg("libmad error: bad scalefactor selection info");
+ result = MAD_FLOW_CONTINUE;
+ break;
+ case MAD_ERROR_BADDATAPTR: /* bad main_data_begin pointer */
+//X intf_ErrMsg("libmad error: bad main_data_begin pointer");
+ result = MAD_FLOW_STOP;
+ break;
+ case MAD_ERROR_BADPART3LEN: /* bad audio data length */
+//X intf_ErrMsg("libmad error: bad audio data length");
+ result = MAD_FLOW_IGNORE;
+ break;
+ case MAD_ERROR_BADHUFFTABLE: /* bad Huffman table select */
+//X intf_ErrMsg("libmad error: bad Huffman table select");
+ result = MAD_FLOW_IGNORE;
+ break;
+ case MAD_ERROR_BADHUFFDATA: /* Huffman data overrun */
+//X intf_ErrMsg("libmad error: Huffman data overrun");
+ result = MAD_FLOW_IGNORE;
+ break;
+ case MAD_ERROR_BADSTEREO: /* incompatible block_type for JS */
+//X intf_ErrMsg("libmad error: incompatible block_type for JS");
+ result = MAD_FLOW_IGNORE;
+ break;
+ default:
+//X intf_ErrMsg("libmad error: unknown error occured stopping decoder");
+ result = MAD_FLOW_STOP;
+ break;
+ }
+
+ return (MAD_RECOVERABLE(p_libmad_stream->error)? result: MAD_FLOW_STOP);
+ //return (MAD_FLOW_CONTINUE);
+}
+
+/*****************************************************************************
+ * libmad_message: this function is called to send a message
+ *****************************************************************************/
+/* enum mad_flow libmad_message(void *, void*, unsigned int*)
+ * {
+ * return MAD_FLOW_CONTINUE;
+ * }
+ */
+
+
+
+/****************************************************************************
+ * Print human readable informations about an audio MPEG frame. *
+ ****************************************************************************/
+static void PrintFrameInfo(struct mad_header *Header)
+{
+ const char *Layer,
+ *Mode,
+ *Emphasis;
+
+ /* Convert the layer number to it's printed representation. */
+ switch(Header->layer)
+ {
+ case MAD_LAYER_I:
+ Layer="I";
+ break;
+ case MAD_LAYER_II:
+ Layer="II";
+ break;
+ case MAD_LAYER_III:
+ Layer="III";
+ break;
+ default:
+ Layer="(unexpected layer value)";
+ break;
+ }
+
+ /* Convert the audio mode to it's printed representation. */
+ switch(Header->mode)
+ {
+ case MAD_MODE_SINGLE_CHANNEL:
+ Mode="single channel";
+ break;
+ case MAD_MODE_DUAL_CHANNEL:
+ Mode="dual channel";
+ break;
+ case MAD_MODE_JOINT_STEREO:
+ Mode="joint (MS/intensity) stereo";
+ break;
+ case MAD_MODE_STEREO:
+ Mode="normal LR stereo";
+ break;
+ default:
+ Mode="(unexpected mode value)";
+ break;
+ }
+
+ /* Convert the emphasis to it's printed representation. */
+ switch(Header->emphasis)
+ {
+ case MAD_EMPHASIS_NONE:
+ Emphasis="no";
+ break;
+ case MAD_EMPHASIS_50_15_US:
+ Emphasis="50/15 us";
+ break;
+ case MAD_EMPHASIS_CCITT_J_17:
+ Emphasis="CCITT J.17";
+ break;
+ default:
+ Emphasis="(unexpected emphasis value)";
+ break;
+ }
+
+//X intf_ErrMsg("statistics: %lu kb/s audio mpeg layer %s stream %s crc, "
+//X "%s with %s emphasis at %d Hz sample rate\n",
+//X Header->bitrate,Layer,
+//X Header->flags&MAD_FLAG_PROTECTION?"with":"without",
+//X Mode,Emphasis,Header->samplerate);
+}
--- /dev/null
+/***************************************************************************
+ mad_libmad.h - description
+ -------------------
+ begin : Mon Nov 5 2001
+ copyright : (C) 2001 by Jean-Paul Saman
+ email : jpsaman@wxs.nl
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _VLC_MAD_LIBMAD_H_
+#define _VLC_MAD_LIBMAD_H_
+
+/*
+ * Function prototypes for libmad callback functions.
+ */
+
+/*
+ * Each of the following functions will return one of:
+ * MAD_FLOW_CONTINUE = continue normally
+ * MAD_FLOW_STOP = stop decoding normally
+ * MAD_FLOW_BREAK = stop decoding and signal an error
+ * MAD_FLOW_IGNORE = ignore the current frame
+ */
+
+/* enum mad_flow (*input_func)(void *, struct mad_stream *);*/
+enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream);
+
+/* enum mad_flow (*header_func)(void *, struct mad_header const *);*/
+enum mad_flow libmad_header(void *data, struct mad_header const *p_libmad_header);
+
+/* enum mad_flow (*filter_func)(void *, struct mad_stream const *, struct mad_frame *); */
+// enum mad_flow libmad_filter(void *data, struct mad_stream const *p_libmad_stream, struct mad_frame *p_libmad_frame);
+
+/* enum mad_flow (*output_func)(void *, struct mad_header const *, struct mad_pcm *); */
+enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header, struct mad_pcm *p_libmad_pcm);
+
+/* enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); */
+enum mad_flow libmad_error(void *data, struct mad_stream *p_libmad_stream, struct mad_frame *p_libmad_frame);
+
+/* enum mad_flow (*message_func)(void *, void *, unsigned int *); */
+/* enum mad_flow libmad_message(void *, void*, unsigned int*); */
+
+#endif
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+mpeg_audio_SOURCES = decoder.c layer1.c layer2.c math.c generic.c
--- /dev/null
+/*****************************************************************************
+ * decoder.c: MPEG audio decoder thread
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: decoder.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@via.ecp.fr>
+ * Samuel Hocevar <sam@via.ecp.fr>
+ * Cyril Deguet <asmax@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+#include <vlc/aout.h>
+
+#include "generic.h"
+#include "decoder.h"
+
+#define ADEC_FRAME_SIZE (2*1152)
+
+/*****************************************************************************
+ * Local Prototypes
+ *****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+
+static void EndThread ( adec_thread_t * );
+static void DecodeThread ( adec_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("MPEG I/II layer 1/2 audio decoder") );
+ set_capability( "decoder", 50 );
+ add_requirement( FPU );
+ add_shortcut( "builtin" );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to choose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','a') )
+ {
+ return VLC_EGENERIC;
+ }
+
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * RunDecoder: initialize, go inside main loop, destroy
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+ adec_thread_t * p_adec;
+
+ /* Allocate the memory needed to store the thread's structure */
+ if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL )
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return 0;
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_adec->p_fifo = p_fifo;
+
+ /*
+ * Initilize the banks
+ */
+ p_adec->bank_0.actual = p_adec->bank_0.v1;
+ p_adec->bank_0.pos = 0;
+ p_adec->bank_1.actual = p_adec->bank_1.v1;
+ p_adec->bank_1.pos = 0;
+
+ /*
+ * Initialize bit stream
+ */
+ InitBitstream( &p_adec->bit_stream, p_adec->p_fifo, NULL, NULL );
+
+ /* We do not create the audio output fifo now, but
+ it will be created when the first frame is received */
+ p_adec->p_aout_fifo = NULL;
+
+ p_adec->i_sync = 0;
+
+ /* Audio decoder thread's main loop */
+ while( (!p_adec->p_fifo->b_die) && (!p_adec->p_fifo->b_error) )
+ {
+ DecodeThread( p_adec );
+ }
+
+ /* If b_error is set, the audio decoder thread enters the error loop */
+ if( p_adec->p_fifo->b_error )
+ {
+ DecoderError( p_adec->p_fifo );
+ }
+
+ /* End of the audio decoder thread */
+ EndThread( p_adec );
+
+ return( 0 );
+}
+
+/*
+ * Following functions are local to this module
+ */
+
+/*****************************************************************************
+ * DecodeThread: decodes a mpeg frame
+ *****************************************************************************/
+static void DecodeThread( adec_thread_t * p_adec )
+{
+ s16 *p_buffer;
+ adec_sync_info_t sync_info;
+
+ if( ! adec_SyncFrame (p_adec, &sync_info) )
+ {
+
+ /* TODO: check if audio type has changed */
+
+ /* Create the output fifo if it doesn't exist yet */
+ if( p_adec->p_aout_fifo == NULL )
+ {
+ int i_channels;
+
+ if( !config_GetInt( p_adec->p_fifo, "mono" ) )
+ {
+ msg_Dbg( p_adec->p_fifo, "setting stereo output" );
+ i_channels = 2;
+ }
+ else if( sync_info.b_stereo )
+ {
+ i_channels = 2;
+ }
+ else
+ {
+ i_channels = 1;
+ }
+ p_adec->p_aout_fifo =
+ aout_CreateFifo( p_adec->p_fifo, AOUT_FIFO_PCM, i_channels,
+ sync_info.sample_rate, ADEC_FRAME_SIZE, NULL );
+ if( p_adec->p_aout_fifo == NULL)
+ {
+ msg_Err( p_adec->p_fifo, "failed to create aout fifo" );
+ p_adec->p_fifo->b_error = 1;
+ return;
+ }
+ }
+
+ p_adec->i_sync = 1;
+
+ p_buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
+ + (p_adec->p_aout_fifo->i_end_frame * ADEC_FRAME_SIZE);
+
+ CurrentPTS( &p_adec->bit_stream,
+ &p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->i_end_frame],
+ NULL );
+ if( !p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->i_end_frame] )
+ {
+ p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->i_end_frame] =
+ LAST_MDATE;
+ }
+
+ if( adec_DecodeFrame (p_adec, p_buffer) )
+ {
+ /* Ouch, failed decoding... We'll have to resync */
+ p_adec->i_sync = 0;
+ }
+ else
+ {
+ vlc_mutex_lock (&p_adec->p_aout_fifo->data_lock);
+ p_adec->p_aout_fifo->i_end_frame =
+ (p_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
+ vlc_cond_signal (&p_adec->p_aout_fifo->data_wait);
+ vlc_mutex_unlock (&p_adec->p_aout_fifo->data_lock);
+ }
+ }
+}
+
+/*****************************************************************************
+ * EndThread : audio decoder thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+static void EndThread ( adec_thread_t *p_adec )
+{
+ /* If the audio output fifo was created, we destroy it */
+ if ( p_adec->p_aout_fifo != NULL )
+ {
+ aout_DestroyFifo ( p_adec->p_aout_fifo );
+
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock (&(p_adec->p_aout_fifo->data_lock));
+ vlc_cond_signal (&(p_adec->p_aout_fifo->data_wait));
+ vlc_mutex_unlock (&(p_adec->p_aout_fifo->data_lock));
+ }
+ /* Destroy descriptor */
+ free( p_adec );
+}
+
--- /dev/null
+/*****************************************************************************
+ * mpeg_adec.h : audio decoder thread interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: decoder.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * adec_thread_t : audio decoder thread descriptor
+ *****************************************************************************/
+typedef struct adec_thread_s
+{
+ /*
+ * Sync Information
+ */
+ int i_sync;
+ /*
+ * Input properties
+ */
+ decoder_fifo_t * p_fifo; /* stores the PES stream data */
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+ int i_read_bits;
+
+ /*
+ * Decoder properties
+ */
+ u32 header;
+ int frame_size;
+ adec_bank_t bank_0;
+ adec_bank_t bank_1;
+
+ /*
+ * Output properties
+ */
+ aout_fifo_t * p_aout_fifo; /* stores the decompressed frames */
+
+} adec_thread_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+
+/*
+ * From adec_generic.c
+ */
+int adec_SyncFrame( adec_thread_t *, adec_sync_info_t * );
+int adec_DecodeFrame( adec_thread_t * , s16 * );
+
--- /dev/null
+/*****************************************************************************
+ * generic.c: MPEG audio decoder
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: generic.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@via.ecp.fr>
+ * Cyril Deguet <asmax@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <string.h> /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "generic.h"
+#include "decoder.h"
+#include "math.h" /* DCT32(), PCM() */
+#include "layer1.h"
+#include "layer2.h"
+
+int adec_Init( adec_thread_t * p_adec )
+{
+ p_adec->bank_0.actual = p_adec->bank_0.v1;
+ p_adec->bank_0.pos = 0;
+ p_adec->bank_1.actual = p_adec->bank_1.v1;
+ p_adec->bank_1.pos = 0;
+ return 0;
+}
+
+int adec_SyncFrame( adec_thread_t * p_adec, adec_sync_info_t * p_sync_info )
+{
+ static int mpeg1_sample_rate[3] = {44100, 48000, 32000};
+ static int mpeg1_layer1_bit_rate[15] =
+ {
+ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
+ };
+ static int mpeg1_layer2_bit_rate[15] =
+ {
+ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
+ };
+ static int mpeg2_layer1_bit_rate[15] =
+ {
+ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256
+ };
+ static int mpeg2_layer2_bit_rate[15] =
+ {
+ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
+ };
+ static int * bit_rate_table[8] =
+ {
+ NULL, NULL, mpeg2_layer2_bit_rate, mpeg2_layer1_bit_rate,
+ NULL, NULL, mpeg1_layer2_bit_rate, mpeg1_layer1_bit_rate
+ };
+
+ u32 header;
+ int index;
+ int * bit_rates;
+ int sample_rate;
+ int bit_rate;
+ int frame_size;
+
+ /* We read the whole header, but only really take 8 bits */
+ header = GetBits( &p_adec->bit_stream, 8 ) << 24;
+ header |= ShowBits( &p_adec->bit_stream, 24 );
+
+ p_adec->header = header;
+
+ /* basic header check : sync word */
+ if( (header & 0xfff00000) != 0xfff00000 )
+ {
+ return 1;
+ }
+
+ /* calculate bit rate */
+ index = ( header >> 17 ) & 7; /* mpeg ID + layer */
+ bit_rates = bit_rate_table[ index ];
+ if( bit_rates == NULL )
+ {
+ return 1; /* invalid layer */
+ }
+
+ index = ( header >> 12 ) & 15; /* bit rate index */
+ if (index > 14)
+ {
+ return 1;
+ }
+ bit_rate = bit_rates[ index ];
+
+ /* mpeg 1 layer 2 : check that bitrate per channel is valid */
+
+ if( bit_rates == mpeg1_layer2_bit_rate )
+ {
+ if( (header & 0xc0) == 0xc0 )
+ { /* mono */
+ if( index > 10 )
+ {
+ return 1; /* invalid bitrate per channel */
+ }
+ }
+ else
+ { /* stereo */
+ if( (1 << index) & 0x2e )
+ {
+ return 1; /* invalid bitrate per channel */
+ }
+ }
+ }
+
+ /* calculate sample rate */
+
+ index = ( header >> 10 ) & 3; /* sample rate index */
+ if( index > 2 )
+ {
+ return 1;
+ }
+
+ sample_rate = mpeg1_sample_rate[ index ];
+
+ if( ! (header & 0x80000) )
+ {
+ sample_rate >>= 1; /* half sample rate for mpeg2 */
+ }
+
+ /* calculate frame length */
+
+ if( (header & 0x60000) == 0x60000 )
+ {
+ /* layer 1 */
+ frame_size = 48000 * bit_rate / sample_rate;
+
+ /* padding */
+ if( header & 0x200 )
+ {
+ frame_size += 4;
+ }
+ }
+ else
+ {
+ /* layer >1 */
+ frame_size = 144000 * bit_rate / sample_rate;
+
+ /* padding */
+ if( header & 0x200 )
+ {
+ frame_size ++;
+ }
+ }
+
+ /* Now we are sure we want this header, read it */
+ RemoveBits( &p_adec->bit_stream, 24 );
+ p_adec->i_read_bits = 32;
+
+ if( ! (p_adec->header & 0x10000) )
+ {
+ /* Error check, skip it */
+ RemoveBits( &p_adec->bit_stream, 16 );
+ p_adec->i_read_bits += 16;
+ }
+
+ p_sync_info->b_stereo = ((p_adec->header & 0xc0) != 0xc0);
+ p_sync_info->sample_rate = sample_rate;
+ p_sync_info->bit_rate = bit_rate;
+ p_sync_info->frame_size = frame_size;
+ p_adec->frame_size = frame_size;
+
+ return 0;
+}
+
+int adec_DecodeFrame( adec_thread_t * p_adec, s16 * buffer )
+{
+ int i_total_bytes_read;
+
+ /* parse audio data */
+
+ switch( (p_adec->header >> 17) & 3 )
+ {
+ case 2:
+ /* layer 2 */
+ if( (p_adec->header & 0xc0) == 0xc0 )
+ {
+ if( adec_layer2_mono (p_adec, buffer) )
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ if( adec_layer2_stereo (p_adec, buffer) )
+ {
+ return 1;
+ }
+ }
+ break;
+
+ case 3:
+ /* layer 1 */
+ if( (p_adec->header & 0xc0) == 0xc0 )
+ {
+ if( adec_layer1_mono (p_adec, buffer) )
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ if( adec_layer1_stereo (p_adec, buffer) )
+ {
+ return 1;
+ }
+ }
+ break;
+ }
+
+ /* Skip ancillary data */
+
+ if( (p_adec->header & 0xf000) == 0 ) /* free bitrate format */
+ {
+ return 0;
+ }
+
+ RealignBits( &p_adec->bit_stream );
+ i_total_bytes_read = ( p_adec->i_read_bits + 7 ) / 8;
+
+ if( i_total_bytes_read > p_adec->frame_size )
+ {
+ return 1; /* overrun */
+ }
+
+ while( i_total_bytes_read++ < p_adec->frame_size )
+ {
+ RemoveBits( &p_adec->bit_stream, 8 ); /* skip ancillary data */
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * audio_decoder.h : audio decoder interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: generic.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/**** audio decoder API - public audio decoder structures */
+
+typedef struct audiodec_s audiodec_t;
+
+typedef struct adec_sync_info_s {
+ int sample_rate; /* sample rate in Hz */
+ int frame_size; /* frame size in bytes */
+ int bit_rate; /* nominal bit rate in kbps */
+ int b_stereo; /* mono/stereo */
+} adec_sync_info_t;
+
+typedef struct adec_bank_s
+{
+ float v1[512];
+ float v2[512];
+ float * actual;
+ int pos;
+
+} adec_bank_t;
+
+
--- /dev/null
+/*****************************************************************************
+ * layer1.c: MPEG Layer I audio decoder
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: layer1.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <stdlib.h> /* NULL */
+#include <string.h> /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "generic.h"
+#include "decoder.h"
+#include "math.h" /* DCT32(), PCM() */
+
+/**** wkn ****/
+
+static float adec_scalefactor_table[64] =
+{ /* 2 ^ (1 - i/3) */
+ 2.0000000000000000, 1.5874010519681994, 1.2599210498948732,
+ 1.0000000000000000, 0.7937005259840998, 0.6299605249474366,
+ 0.5000000000000000, 0.3968502629920499, 0.3149802624737183,
+ 0.2500000000000000, 0.1984251314960249, 0.1574901312368591,
+ 0.1250000000000000, 0.0992125657480125, 0.0787450656184296,
+ 0.0625000000000000, 0.0496062828740062, 0.0393725328092148,
+ 0.0312500000000000, 0.0248031414370031, 0.0196862664046074,
+ 0.0156250000000000, 0.0124015707185016, 0.0098431332023037,
+ 0.0078125000000000, 0.0062007853592508, 0.0049215666011518,
+ 0.0039062500000000, 0.0031003926796254, 0.0024607833005759,
+ 0.0019531250000000, 0.0015501963398127, 0.0012303916502880,
+ 0.0009765625000000, 0.0007750981699063, 0.0006151958251440,
+ 0.0004882812500000, 0.0003875490849532, 0.0003075979125720,
+ 0.0002441406250000, 0.0001937745424766, 0.0001537989562860,
+ 0.0001220703125000, 0.0000968872712383, 0.0000768994781430,
+ 0.0000610351562500, 0.0000484436356191, 0.0000384497390715,
+ 0.0000305175781250, 0.0000242218178096, 0.0000192248695357,
+ 0.0000152587890625, 0.0000121109089048, 0.0000096124347679,
+ 0.0000076293945312, 0.0000060554544524, 0.0000048062173839,
+ 0.0000038146972656, 0.0000030277272262, 0.0000024031086920,
+ 0.0000019073486328, 0.0000015138636131, 0.0000012015543460,
+ 0.0000009536743164 /* last element is not in the standard... invalid ??? */
+};
+
+static float adec_slope_table[15] =
+{
+ 0.6666666666666666, 0.2857142857142857, 0.1333333333333333,
+ 0.0645161290322581, 0.0317460317460317, 0.0157480314960630,
+ 0.0078431372549020, 0.0039138943248532, 0.0019550342130987,
+ 0.0009770395701026, 0.0004884004884005, 0.0002441704309608,
+ 0.0001220777635354, 0.0000610370189520, 0.0000305180437934
+};
+
+static float adec_offset_table[15] =
+{
+ -0.6666666666666666, -0.8571428571428571, -0.9333333333333333,
+ -0.9677419354838710, -0.9841269841269841, -0.9921259842519685,
+ -0.9960784313725490, -0.9980430528375733, -0.9990224828934506,
+ -0.9995114802149487, -0.9997557997557998, -0.9998779147845196,
+ -0.9999389611182323, -0.9999694814905240, -0.9999847409781033
+};
+
+static u8 adec_layer1_allocation_table[15] =
+{
+ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static int adec_bound_table[4] = { 4, 8, 12, 16 };
+
+int adec_layer1_mono( adec_thread_t * p_adec, s16 * buffer )
+{
+ u8 allocation[32];
+ float slope[32];
+ float offset[32];
+ float sample[32];
+
+ int i_sb;
+ int s;
+ int i_read_bits = 0;
+
+ /*
+ * Parse the allocation tables
+ */
+
+ for (i_sb = 0; i_sb < 32; i_sb += 2)
+ {
+ u8 tmp;
+
+ /* i_read_bits will be updated at the end of the loop */
+ tmp = GetBits ( &p_adec->bit_stream, 8 );
+
+ if ( (tmp >> 4) > 14 )
+ {
+ return 1;
+ }
+
+ allocation[i_sb] = adec_layer1_allocation_table [tmp >> 4];
+
+ if ((tmp & 15) > 14)
+ {
+ return 1;
+ }
+
+ allocation[i_sb+1] = adec_layer1_allocation_table [tmp & 15];
+ }
+
+ i_read_bits += 8 * 16; /* we did 16 iterations */
+
+ /*
+ * Parse scalefactors
+ */
+
+ for ( i_sb = 0; i_sb < 32; i_sb++ )
+ {
+ if ( allocation[i_sb] )
+ {
+ int index;
+ float scalefactor;
+
+ index = GetBits( &p_adec->bit_stream, 6);
+
+ /* We also add the bits we'll take later in the sample parsing */
+ i_read_bits += 6 + 12 * allocation[i_sb];
+
+ scalefactor = adec_scalefactor_table[index];
+
+ slope[i_sb] = adec_slope_table[allocation[i_sb]-2] * scalefactor;
+ offset[i_sb] = adec_offset_table[allocation[i_sb]-2] * scalefactor;
+ }
+ }
+
+ /*
+ * Parse samples
+ */
+
+ for ( s = 0 ; s < 12; s++)
+ {
+ for (i_sb = 0; i_sb < 32; i_sb++)
+ {
+ if (!allocation[i_sb])
+ {
+ sample[i_sb] = 0;
+ }
+ else
+ {
+ int code;
+
+ /* The bits were already counted in the scalefactors parsing */
+ code = GetBits( &p_adec->bit_stream, allocation[i_sb] );
+
+ sample[i_sb] = slope[i_sb] * code + offset[i_sb];
+ }
+ }
+
+ DCT32( &p_adec->bank_0, sample );
+ PCM (&p_adec->bank_0, buffer, 1);
+ buffer += 32;
+ }
+
+ p_adec->i_read_bits += i_read_bits;
+
+ return 0;
+}
+
+int adec_layer1_stereo( adec_thread_t * p_adec, s16 * buffer )
+{
+ u8 allocation_0[32], allocation_1[32];
+ float slope_0[32], slope_1[32];
+ float offset_0[32], offset_1[32];
+ float sample_0[32], sample_1[32];
+
+ int bound;
+ int i_sb;
+ int s;
+ int i_read_bits = 0;
+
+ /*
+ * Calculate bound
+ */
+
+ bound = 32;
+ if ( (p_adec->header & 0xc0) == 0x40)
+ {
+ /* intensity stereo */
+ int index;
+ index = (p_adec->header >> 4) & 3;
+ bound = adec_bound_table[index];
+ }
+
+ /*
+ * Parse allocation
+ */
+
+ for (i_sb = 0; i_sb < bound; i_sb++)
+ {
+ u8 tmp;
+ tmp = GetBits( &p_adec->bit_stream, 8 );
+ if ((tmp >> 4) > 14)
+ {
+ return 1;
+ }
+ allocation_0[i_sb] = adec_layer1_allocation_table [tmp >> 4];
+ if ((tmp & 15) > 14)
+ {
+ return 1;
+ }
+ allocation_1[i_sb] = adec_layer1_allocation_table [tmp & 15];
+ }
+
+ for (; i_sb < 32; i_sb += 2)
+ {
+ u8 tmp;
+ tmp = GetBits( &p_adec->bit_stream, 8 );
+
+ if ((tmp >> 4) > 14)
+ {
+ return 1;
+ }
+ allocation_0[i_sb] = allocation_1[i_sb]
+ = adec_layer1_allocation_table [tmp >> 4];
+
+ if ((tmp & 15) > 14)
+ {
+ return 1;
+ }
+ allocation_0[i_sb+1] = allocation_1[i_sb+1]
+ = adec_layer1_allocation_table [tmp & 15];
+ }
+
+ i_read_bits += 4 * ( 32 + bound ); /* we read 8*bound and 4*(32-bound) */
+
+ /*
+ * Parse scalefactors
+ */
+
+ for ( i_sb = 0; i_sb < 32; i_sb++ )
+ {
+ if ( allocation_0[i_sb] )
+ {
+ int index;
+ float scalefactor;
+
+ index = GetBits( &p_adec->bit_stream, 6 );
+ i_read_bits += 6;
+
+ scalefactor = adec_scalefactor_table[index];
+
+ slope_0[i_sb] = adec_slope_table[allocation_0[i_sb]-2] * scalefactor;
+ offset_0[i_sb] = adec_offset_table[allocation_0[i_sb]-2] * scalefactor;
+ }
+
+ if (allocation_1[i_sb])
+ {
+ int index;
+ float scalefactor;
+
+ index = GetBits( &p_adec->bit_stream, 6 );
+ i_read_bits += 6;
+
+ scalefactor = adec_scalefactor_table[index];
+
+ slope_1[i_sb] = adec_slope_table[allocation_1[i_sb]-2] * scalefactor;
+ offset_1[i_sb] = adec_offset_table[allocation_1[i_sb]-2] * scalefactor;
+ }
+ }
+
+ /* parse samples */
+
+ for (s = 0; s < 12; s++)
+ {
+ for (i_sb = 0; i_sb < bound; i_sb++)
+ {
+ if (!allocation_0[i_sb])
+ {
+ sample_0[i_sb] = 0;
+ }
+ else
+ {
+ int code;
+
+ code = GetBits( &p_adec->bit_stream, allocation_0[i_sb] );
+ i_read_bits += allocation_0[i_sb];
+
+ sample_0[i_sb] = slope_0[i_sb] * code + offset_0[i_sb];
+ }
+
+ if ( !allocation_1[i_sb] )
+ {
+ sample_1[i_sb] = 0;
+ }
+ else
+ {
+ int code;
+
+ code = GetBits( &p_adec->bit_stream, allocation_1[i_sb] );
+ i_read_bits += allocation_1[i_sb];
+
+ sample_1[i_sb] = slope_1[i_sb] * code + offset_1[i_sb];
+ }
+ }
+
+ for (; i_sb < 32; i_sb++)
+ {
+ if (!allocation_0[i_sb])
+ {
+ sample_0[i_sb] = 0;
+ sample_1[i_sb] = 0;
+ }
+ else
+ {
+ int code;
+
+ code = GetBits( &p_adec->bit_stream, allocation_0[i_sb] );
+ i_read_bits += allocation_0[i_sb];
+
+ sample_0[i_sb] = slope_0[i_sb] * code + offset_0[i_sb];
+ sample_1[i_sb] = slope_1[i_sb] * code + offset_1[i_sb];
+ }
+ }
+
+ DCT32( &p_adec->bank_0, sample_0 );
+ PCM (&p_adec->bank_0, buffer, 2);
+ DCT32( &p_adec->bank_1, sample_1 );
+ PCM (&p_adec->bank_1, buffer + 1, 2);
+ buffer += 64;
+ }
+
+ p_adec->i_read_bits += i_read_bits;
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * adec_layer1.h: MPEG Layer I audio decoder
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: layer1.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+int adec_layer1_mono( adec_thread_t * p_adec, s16 * buffer );
+int adec_layer1_stereo (adec_thread_t * p_adec, s16 * buffer);
+
--- /dev/null
+/*****************************************************************************
+ * layer2.c: MPEG Layer II audio decoder
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: layer2.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <stdlib.h> /* NULL */
+#include <string.h> /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "generic.h"
+#include "decoder.h"
+#include "math.h" /* DCT32(), PCM() */
+
+/**** wkn ****/
+
+static float adec_scalefactor_table[64] =
+{ /* 2 ^ (1 - i/3) */
+ 2.0000000000000000, 1.5874010519681994, 1.2599210498948732,
+ 1.0000000000000000, 0.7937005259840998, 0.6299605249474366,
+ 0.5000000000000000, 0.3968502629920499, 0.3149802624737183,
+ 0.2500000000000000, 0.1984251314960249, 0.1574901312368591,
+ 0.1250000000000000, 0.0992125657480125, 0.0787450656184296,
+ 0.0625000000000000, 0.0496062828740062, 0.0393725328092148,
+ 0.0312500000000000, 0.0248031414370031, 0.0196862664046074,
+ 0.0156250000000000, 0.0124015707185016, 0.0098431332023037,
+ 0.0078125000000000, 0.0062007853592508, 0.0049215666011518,
+ 0.0039062500000000, 0.0031003926796254, 0.0024607833005759,
+ 0.0019531250000000, 0.0015501963398127, 0.0012303916502880,
+ 0.0009765625000000, 0.0007750981699063, 0.0006151958251440,
+ 0.0004882812500000, 0.0003875490849532, 0.0003075979125720,
+ 0.0002441406250000, 0.0001937745424766, 0.0001537989562860,
+ 0.0001220703125000, 0.0000968872712383, 0.0000768994781430,
+ 0.0000610351562500, 0.0000484436356191, 0.0000384497390715,
+ 0.0000305175781250, 0.0000242218178096, 0.0000192248695357,
+ 0.0000152587890625, 0.0000121109089048, 0.0000096124347679,
+ 0.0000076293945312, 0.0000060554544524, 0.0000048062173839,
+ 0.0000038146972656, 0.0000030277272262, 0.0000024031086920,
+ 0.0000019073486328, 0.0000015138636131, 0.0000012015543460,
+ 0.0000009536743164 /* last element is not in the standard... invalid ??? */
+};
+
+static float adec_slope_table[15] =
+{
+ 0.6666666666666666, 0.2857142857142857, 0.1333333333333333,
+ 0.0645161290322581, 0.0317460317460317, 0.0157480314960630,
+ 0.0078431372549020, 0.0039138943248532, 0.0019550342130987,
+ 0.0009770395701026, 0.0004884004884005, 0.0002441704309608,
+ 0.0001220777635354, 0.0000610370189520, 0.0000305180437934
+};
+
+static float adec_offset_table[15] =
+{
+ -0.6666666666666666, -0.8571428571428571, -0.9333333333333333,
+ -0.9677419354838710, -0.9841269841269841, -0.9921259842519685,
+ -0.9960784313725490, -0.9980430528375733, -0.9990224828934506,
+ -0.9995114802149487, -0.9997557997557998, -0.9998779147845196,
+ -0.9999389611182323, -0.9999694814905240, -0.9999847409781033
+};
+
+static int adec_bound_table[4] = { 4, 8, 12, 16 };
+
+typedef struct
+{
+ s8 nbal[32];
+ u8 * alloc[32];
+} alloc_table_t;
+
+#define L3 -1
+#define L5 -2
+#define L9 -3
+
+static void adec_layer2_get_table( u32 header, u8 freq_table[15],
+ alloc_table_t ** alloc, int * sblimit )
+{
+ static s8 table_ab0[16] =
+ {
+ 0, L3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
+ };
+ static s8 table_ab3[16] =
+ {
+ 0, L3, L5, 3, L9, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16
+ };
+ static s8 table_ab11[8] =
+ {
+ 0, L3, L5, 3, L9, 4, 5, 16
+ };
+ static s8 table_ab23[8] =
+ {
+ 0, L3, L5, 16
+ };
+ static alloc_table_t mpeg1_ab =
+ {
+ {4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,0,0},
+ {table_ab0, table_ab0, table_ab0, table_ab3,
+ table_ab3, table_ab3, table_ab3, table_ab3,
+ table_ab3, table_ab3, table_ab3, table_ab11,
+ table_ab11, table_ab11, table_ab11, table_ab11,
+ table_ab11, table_ab11, table_ab11, table_ab11,
+ table_ab11, table_ab11, table_ab11, table_ab23,
+ table_ab23, table_ab23, table_ab23, table_ab23,
+ table_ab23, table_ab23, NULL, NULL}
+ };
+
+ static s8 table_cd[16] =
+ {
+ 0, L3, L5, L9, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ };
+ static alloc_table_t mpeg1_cd =
+ {
+ {4,4,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {table_cd, table_cd, table_cd, table_cd,
+ table_cd, table_cd, table_cd, table_cd,
+ table_cd, table_cd, table_cd, table_cd,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
+ };
+
+ static s8 table_0[16] =
+ {
+ 0, L3, L5, 3, L9, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ };
+ static s8 table_4[8] =
+ {
+ 0, L3, L5, L9, 4, 5, 6, 7
+ };
+ static alloc_table_t mpeg2 =
+ {
+ {4,4,4,4,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0},
+ {table_0, table_0, table_0, table_0,
+ table_4, table_4, table_4, table_4,
+ table_4, table_4, table_4, table_4,
+ table_4, table_4, table_4, table_4,
+ table_4, table_4, table_4, table_4,
+ table_4, table_4, table_4, table_4,
+ table_4, table_4, table_4, table_4,
+ table_4, table_4, NULL, NULL}
+ };
+
+ static alloc_table_t * alloc_table [4] =
+ {
+ &mpeg2, &mpeg1_cd, &mpeg1_ab, &mpeg1_ab
+ };
+ static int sblimit_table[12] =
+ {
+ 30, 8, 27, 30, 30, 8, 27, 27, 30, 12, 27, 30
+ };
+
+ int index;
+
+ if (!(header & 0x80000))
+ {
+ index = 0; /* mpeg2 */
+ }
+ else
+ {
+ index = (header >> 12) & 15; /* mpeg1, bitrate */
+ index = freq_table [index];
+ }
+
+ *alloc = alloc_table[index];
+ index |= (header >> 8) & 12;
+ *sblimit = sblimit_table[index];
+}
+
+int adec_layer2_mono( adec_thread_t * p_adec, s16 * buffer )
+{
+ static u8 freq_table[15] = {2, 1, 1, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2};
+ static float L3_table[3] = {-2/3.0, 0, 2/3.0};
+ static float L5_table[5] = {-4/5.0, -2/5.0, 0, 2/5.0, 4/5.0};
+ static float L9_table[9] = {-8/9.0, -6/9.0, -4/9.0, -2/9.0, 0,
+ 2/9.0, 4/9.0, 6/9.0, 8/9.0};
+
+ s8 allocation[32];
+ u8 scfsi[32];
+ float slope[3][32];
+ float offset[3][32];
+ float sample[3][32];
+ alloc_table_t * alloc_table;
+
+ int sblimit;
+ int sb;
+ int gr0, gr1;
+ int s;
+ int i_read_bits = 0;
+
+ /* get the right allocation table */
+ adec_layer2_get_table (p_adec->header, freq_table, &alloc_table, &sblimit);
+
+ /* parse allocation */
+ //sblimit=27;
+
+ for (sb = 0; sb < sblimit; sb++)
+ {
+ int index;
+
+ index = GetBits( &p_adec->bit_stream, alloc_table->nbal[sb] );
+ i_read_bits += alloc_table->nbal[sb];
+
+ allocation[sb] = alloc_table->alloc[sb][index];
+ }
+
+ /* parse scfsi */
+
+ for (sb = 0; sb < sblimit; sb++)
+ {
+ if (allocation[sb])
+ {
+ scfsi[sb] = GetBits (&p_adec->bit_stream, 2);
+ i_read_bits += 2;
+ }
+ }
+
+ /* parse scalefactors */
+
+ for (sb = 0; sb < sblimit; sb++)
+ {
+ if (allocation[sb])
+ {
+ int index_0, index_1, index_2;
+
+ switch (scfsi[sb])
+ {
+ case 0:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ index_2 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 18;
+
+ if (allocation[sb] < 0)
+ {
+ slope[0][sb] = adec_scalefactor_table[index_0];
+ slope[1][sb] = adec_scalefactor_table[index_1];
+ slope[2][sb] = adec_scalefactor_table[index_2];
+ }
+ else
+ {
+ float r_scalefactor;
+ float r_slope, r_offset;
+
+ r_slope = adec_slope_table[allocation[sb]-2];
+ r_offset = adec_offset_table[allocation[sb]-2];
+
+ r_scalefactor = adec_scalefactor_table[index_0];
+ slope[0][sb] = r_slope * r_scalefactor;
+ offset[0][sb] = r_offset * r_scalefactor;
+
+ r_scalefactor = adec_scalefactor_table[index_1];
+ slope[1][sb] = r_slope * r_scalefactor;
+ offset[1][sb] = r_offset * r_scalefactor;
+
+ r_scalefactor = adec_scalefactor_table[index_2];
+ slope[2][sb] = r_slope * r_scalefactor;
+ offset[2][sb] = r_offset * r_scalefactor;
+ }
+ break;
+
+ case 1:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 12;
+
+ if (allocation[sb] < 0)
+ {
+ slope[0][sb] = slope[1][sb] =
+ adec_scalefactor_table[index_0];
+ slope[2][sb] = adec_scalefactor_table[index_1];
+ }
+ else
+ {
+ float r_scalefactor;
+ float r_slope, r_offset;
+
+ r_slope = adec_slope_table[allocation[sb]-2];
+ r_offset = adec_offset_table[allocation[sb]-2];
+
+ r_scalefactor = adec_scalefactor_table[index_0];
+ slope[0][sb] = slope[1][sb] = r_slope * r_scalefactor;
+ offset[0][sb] = offset[1][sb] =
+ r_offset * r_scalefactor;
+
+ r_scalefactor = adec_scalefactor_table[index_1];
+ slope[2][sb] = r_slope * r_scalefactor;
+ offset[2][sb] = r_offset * r_scalefactor;
+ }
+ break;
+
+ case 2:
+ index_0 = GetBits( &p_adec->bit_stream, 6 );
+ i_read_bits += 6;
+
+ if (allocation[sb] < 0)
+ {
+ slope[0][sb] = slope[1][sb] = slope[2][sb] =
+ adec_scalefactor_table[index_0];
+ }
+ else
+ {
+ float r_scalefactor;
+ float r_slope, r_offset;
+
+ r_slope = adec_slope_table[allocation[sb]-2];
+ r_offset = adec_offset_table[allocation[sb]-2];
+
+ r_scalefactor = adec_scalefactor_table[index_0];
+ slope[0][sb] = slope[1][sb] = slope[2][sb] =
+ r_slope * r_scalefactor;
+ offset[0][sb] = offset[1][sb] = offset[2][sb] =
+ r_offset * r_scalefactor;
+ }
+ break;
+
+ case 3:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 12;
+
+ if (allocation[sb] < 0)
+ {
+ slope[0][sb] = adec_scalefactor_table[index_0];
+ slope[1][sb] = slope[2][sb] =
+ adec_scalefactor_table[index_1];
+ }
+ else
+ {
+ float r_scalefactor;
+ float r_slope, r_offset;
+
+ r_slope = adec_slope_table[allocation[sb]-2];
+ r_offset = adec_offset_table[allocation[sb]-2];
+
+ r_scalefactor = adec_scalefactor_table[index_0];
+ slope[0][sb] = r_slope * r_scalefactor;
+ offset[0][sb] = r_offset * r_scalefactor;
+
+ r_scalefactor = adec_scalefactor_table[index_1];
+ slope[1][sb] = slope[2][sb] = r_slope * r_scalefactor;
+ offset[1][sb] = offset[2][sb] =
+ r_offset * r_scalefactor;
+ }
+ break;
+ }
+ }
+ }
+
+ /* parse samples */
+
+ for (gr0 = 0; gr0 < 3; gr0++)
+ {
+ for (gr1 = 0; gr1 < 4; gr1++)
+ {
+ for (sb = 0; sb < sblimit; sb++)
+ {
+ int code;
+
+ switch (allocation[sb])
+ {
+ case 0:
+ sample[0][sb] = sample[1][sb] = sample[2][sb] = 0;
+ break;
+
+ case L3:
+ code = GetBits( &p_adec->bit_stream, 5 );
+ i_read_bits += 5;
+
+ sample[0][sb] = slope[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample[1][sb] = slope[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample[2][sb] = slope[gr0][sb] * L3_table[code];
+ break;
+
+ case L5:
+ code = GetBits( &p_adec->bit_stream, 7 );
+ i_read_bits += 7;
+
+ sample[0][sb] = slope[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample[1][sb] = slope[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample[2][sb] = slope[gr0][sb] * L5_table[code];
+ break;
+
+ case L9:
+ code = GetBits( &p_adec->bit_stream, 10 );
+ i_read_bits += 10;
+
+ sample[0][sb] = slope[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample[1][sb] = slope[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample[2][sb] = slope[gr0][sb] * L9_table[code];
+ break;
+
+ default:
+ for (s = 0; s < 3; s++)
+ {
+ code = GetBits( &p_adec->bit_stream,
+ allocation[sb] );
+ i_read_bits += allocation[sb];
+
+ sample[s][sb] =
+ slope[gr0][sb] * code + offset[gr0][sb];
+ }
+ }
+ }
+
+ for (; sb < 32; sb++)
+ {
+ sample[0][sb] = sample[1][sb] = sample[2][sb] = 0;
+ }
+
+ for (s = 0; s < 3; s++)
+ {
+ DCT32( &p_adec->bank_0, sample[s] );
+ PCM( &p_adec->bank_0, buffer, 2 );
+
+ /* FIXME: one shouldn't have to do it twice ! */
+ DCT32( &p_adec->bank_1, sample[s] );
+ PCM( &p_adec->bank_1, buffer + 1, 2 );
+
+ buffer += 64;
+ }
+ }
+ }
+
+ p_adec->i_read_bits += i_read_bits;
+
+ return 0;
+}
+
+int adec_layer2_stereo( adec_thread_t * p_adec, s16 * buffer )
+{
+ static u8 freq_table[15] = {3, 0, 0, 0, 1, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3};
+ static float L3_table[3] = {-2/3.0, 0, 2/3.0};
+ static float L5_table[5] = {-4/5.0, -2/5.0, 0, 2/5.0, 4/5.0};
+ static float L9_table[9] = {-8/9.0, -6/9.0, -4/9.0, -2/9.0, 0,
+ 2/9.0, 4/9.0, 6/9.0, 8/9.0};
+
+ s8 allocation_0[32], allocation_1[32];
+ u8 scfsi_0[32], scfsi_1[32];
+ float slope_0[3][32], slope_1[3][32];
+ float offset_0[3][32], offset_1[3][32];
+ float sample_0[3][32], sample_1[3][32];
+ alloc_table_t * alloc_table;
+
+ int sblimit;
+ int bound;
+ int sb;
+ int gr0, gr1;
+ int s;
+ int i_read_bits = 0;
+
+ /* get the right allocation table */
+ adec_layer2_get_table (p_adec->header, freq_table, &alloc_table, &sblimit);
+
+ /* calculate bound */
+ bound = sblimit;
+ if ((p_adec->header & 0xc0) == 0x40) { /* intensity stereo */
+ int index;
+ index = (p_adec->header >> 4) & 3;
+ if (adec_bound_table[index] < sblimit)
+ {
+ bound = adec_bound_table[index];
+ }
+ }
+
+ /* parse allocation */
+
+ for (sb = 0; sb < bound; sb++)
+ {
+ int index;
+
+ index = GetBits( &p_adec->bit_stream, alloc_table->nbal[sb] );
+ allocation_0[sb] = alloc_table->alloc[sb][index];
+
+ index = GetBits( &p_adec->bit_stream, alloc_table->nbal[sb] );
+ allocation_1[sb] = alloc_table->alloc[sb][index];
+
+ i_read_bits += alloc_table->nbal[sb] * 2;
+ }
+
+ for (; sb < sblimit; sb++)
+ {
+ int index;
+
+ index = GetBits( &p_adec->bit_stream, alloc_table->nbal[sb] );
+ allocation_0[sb] = allocation_1[sb] = alloc_table->alloc[sb][index];
+ i_read_bits += alloc_table->nbal[sb];
+ }
+
+ /* parse scfsi */
+
+ for (sb = 0; sb < sblimit; sb++)
+ {
+ if (allocation_0[sb])
+ {
+ scfsi_0[sb] = GetBits (&p_adec->bit_stream, 2);
+ i_read_bits += 2;
+ }
+
+ if (allocation_1[sb])
+ {
+ scfsi_1[sb] = GetBits (&p_adec->bit_stream, 2);
+ i_read_bits += 2;
+ }
+ }
+
+ /* parse scalefactors */
+
+ for (sb = 0; sb < sblimit; sb++)
+ {
+ if (allocation_0[sb])
+ {
+ int index_0, index_1, index_2;
+
+ switch (scfsi_0[sb])
+ {
+ case 0:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ index_2 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 18;
+
+ if (allocation_0[sb] < 0)
+ {
+ slope_0[0][sb] = adec_scalefactor_table[index_0];
+ slope_0[1][sb] = adec_scalefactor_table[index_1];
+ slope_0[2][sb] = adec_scalefactor_table[index_2];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_0[sb]-2];
+ offset = adec_offset_table[allocation_0[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_0[0][sb] = slope * scalefactor;
+ offset_0[0][sb] = offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_1];
+ slope_0[1][sb] = slope * scalefactor;
+ offset_0[1][sb] = offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_2];
+ slope_0[2][sb] = slope * scalefactor;
+ offset_0[2][sb] = offset * scalefactor;
+ }
+ break;
+
+ case 1:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 12;
+
+ if (allocation_0[sb] < 0)
+ {
+ slope_0[0][sb] = slope_0[1][sb] =
+ adec_scalefactor_table[index_0];
+ slope_0[2][sb] = adec_scalefactor_table[index_1];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_0[sb]-2];
+ offset = adec_offset_table[allocation_0[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_0[0][sb] = slope_0[1][sb] = slope * scalefactor;
+ offset_0[0][sb] = offset_0[1][sb] =
+ offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_1];
+ slope_0[2][sb] = slope * scalefactor;
+ offset_0[2][sb] = offset * scalefactor;
+ }
+ break;
+
+ case 2:
+ index_0 = GetBits( &p_adec->bit_stream, 6 );
+ i_read_bits += 6;
+
+ if (allocation_0[sb] < 0)
+ {
+ slope_0[0][sb] = slope_0[1][sb] = slope_0[2][sb] =
+ adec_scalefactor_table[index_0];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_0[sb]-2];
+ offset = adec_offset_table[allocation_0[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_0[0][sb] = slope_0[1][sb] = slope_0[2][sb] =
+ slope * scalefactor;
+ offset_0[0][sb] = offset_0[1][sb] = offset_0[2][sb] =
+ offset * scalefactor;
+ }
+ break;
+
+ case 3:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 12;
+
+ if (allocation_0[sb] < 0)
+ {
+ slope_0[0][sb] = adec_scalefactor_table[index_0];
+ slope_0[1][sb] = slope_0[2][sb] =
+ adec_scalefactor_table[index_1];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_0[sb]-2];
+ offset = adec_offset_table[allocation_0[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_0[0][sb] = slope * scalefactor;
+ offset_0[0][sb] = offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_1];
+ slope_0[1][sb] = slope_0[2][sb] = slope * scalefactor;
+ offset_0[1][sb] = offset_0[2][sb] =
+ offset * scalefactor;
+ }
+ break;
+ }
+ }
+
+ if (allocation_1[sb])
+ {
+ int index_0, index_1, index_2;
+
+ switch (scfsi_1[sb])
+ {
+ case 0:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ index_2 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 18;
+
+ if (allocation_1[sb] < 0)
+ {
+ slope_1[0][sb] = adec_scalefactor_table[index_0];
+ slope_1[1][sb] = adec_scalefactor_table[index_1];
+ slope_1[2][sb] = adec_scalefactor_table[index_2];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_1[sb]-2];
+ offset = adec_offset_table[allocation_1[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_1[0][sb] = slope * scalefactor;
+ offset_1[0][sb] = offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_1];
+ slope_1[1][sb] = slope * scalefactor;
+ offset_1[1][sb] = offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_2];
+ slope_1[2][sb] = slope * scalefactor;
+ offset_1[2][sb] = offset * scalefactor;
+ }
+ break;
+
+ case 1:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 12;
+
+ if (allocation_1[sb] < 0)
+ {
+ slope_1[0][sb] = slope_1[1][sb] =
+ adec_scalefactor_table[index_0];
+ slope_1[2][sb] = adec_scalefactor_table[index_1];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_1[sb]-2];
+ offset = adec_offset_table[allocation_1[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_1[0][sb] = slope_1[1][sb] = slope * scalefactor;
+ offset_1[0][sb] = offset_1[1][sb] =
+ offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_1];
+ slope_1[2][sb] = slope * scalefactor;
+ offset_1[2][sb] = offset * scalefactor;
+ }
+ break;
+
+ case 2:
+ index_0 = GetBits( &p_adec->bit_stream, 6 );
+ i_read_bits += 6;
+
+ if (allocation_1[sb] < 0)
+ {
+ slope_1[0][sb] = slope_1[1][sb] = slope_1[2][sb] =
+ adec_scalefactor_table[index_0];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_1[sb]-2];
+ offset = adec_offset_table[allocation_1[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_1[0][sb] = slope_1[1][sb] = slope_1[2][sb] =
+ slope * scalefactor;
+ offset_1[0][sb] = offset_1[1][sb] = offset_1[2][sb] =
+ offset * scalefactor;
+ }
+ break;
+
+ case 3:
+ index_0 = GetBits(&p_adec->bit_stream,6);
+ index_1 = GetBits(&p_adec->bit_stream,6);
+ i_read_bits += 12;
+
+ if (allocation_1[sb] < 0)
+ {
+ slope_1[0][sb] = adec_scalefactor_table[index_0];
+ slope_1[1][sb] = slope_1[2][sb] =
+ adec_scalefactor_table[index_1];
+ }
+ else
+ {
+ float scalefactor;
+ float slope, offset;
+
+ slope = adec_slope_table[allocation_1[sb]-2];
+ offset = adec_offset_table[allocation_1[sb]-2];
+
+ scalefactor = adec_scalefactor_table[index_0];
+ slope_1[0][sb] = slope * scalefactor;
+ offset_1[0][sb] = offset * scalefactor;
+
+ scalefactor = adec_scalefactor_table[index_1];
+ slope_1[1][sb] = slope_1[2][sb] = slope * scalefactor;
+ offset_1[1][sb] = offset_1[2][sb] =
+ offset * scalefactor;
+ }
+ break;
+ }
+ }
+ }
+
+ /* parse samples */
+
+ for (gr0 = 0; gr0 < 3; gr0++)
+ {
+ for (gr1 = 0; gr1 < 4; gr1++)
+ {
+ for (sb = 0; sb < bound; sb++)
+ {
+ int code;
+
+ switch (allocation_0[sb])
+ {
+ case 0:
+ sample_0[0][sb] = sample_0[1][sb] = sample_0[2][sb] = 0;
+ break;
+
+ case L3:
+ code = GetBits( &p_adec->bit_stream, 5 );
+ i_read_bits += 5;
+
+ sample_0[0][sb] = slope_0[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample_0[1][sb] = slope_0[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample_0[2][sb] = slope_0[gr0][sb] * L3_table[code];
+ break;
+
+ case L5:
+ code = GetBits( &p_adec->bit_stream, 7 );
+ i_read_bits += 7;
+
+ sample_0[0][sb] = slope_0[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample_0[1][sb] = slope_0[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample_0[2][sb] = slope_0[gr0][sb] * L5_table[code];
+ break;
+
+ case L9:
+ code = GetBits( &p_adec->bit_stream, 10 );
+ i_read_bits += 10;
+
+ sample_0[0][sb] = slope_0[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample_0[1][sb] = slope_0[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample_0[2][sb] = slope_0[gr0][sb] * L9_table[code];
+ break;
+
+ default:
+ for (s = 0; s < 3; s++)
+ {
+ code = GetBits( &p_adec->bit_stream,
+ allocation_0[sb] );
+ i_read_bits += allocation_0[sb];
+
+ sample_0[s][sb] =
+ slope_0[gr0][sb] * code + offset_0[gr0][sb];
+ }
+ }
+
+ switch (allocation_1[sb])
+ {
+ case 0:
+ sample_1[0][sb] = sample_1[1][sb] = sample_1[2][sb] = 0;
+ break;
+
+ case L3:
+ code = GetBits( &p_adec->bit_stream, 5 );
+ i_read_bits += 5;
+
+ sample_1[0][sb] = slope_1[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample_1[1][sb] = slope_1[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample_1[2][sb] = slope_1[gr0][sb] * L3_table[code];
+ break;
+
+ case L5:
+ code = GetBits( &p_adec->bit_stream, 7 );
+ i_read_bits += 7;
+
+ sample_1[0][sb] = slope_1[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample_1[1][sb] = slope_1[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample_1[2][sb] = slope_1[gr0][sb] * L5_table[code];
+ break;
+
+ case L9:
+ code = GetBits( &p_adec->bit_stream, 10 );
+ i_read_bits += 10;
+
+ sample_1[0][sb] = slope_1[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample_1[1][sb] = slope_1[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample_1[2][sb] = slope_1[gr0][sb] * L9_table[code];
+ break;
+
+ default:
+ for (s = 0; s < 3; s++)
+ {
+ code = GetBits( &p_adec->bit_stream,
+ allocation_1[sb] );
+ i_read_bits += allocation_1[sb];
+
+ sample_1[s][sb] =
+ slope_1[gr0][sb] * code + offset_1[gr0][sb];
+ }
+ }
+ }
+
+ for (; sb < sblimit; sb++)
+ {
+ int code;
+
+ switch (allocation_0[sb])
+ {
+ case 0:
+ sample_0[0][sb] = sample_0[1][sb] = sample_0[2][sb] = 0;
+ sample_1[0][sb] = sample_1[1][sb] = sample_1[2][sb] = 0;
+ break;
+
+ case L3:
+ code = GetBits( &p_adec->bit_stream, 5 );
+ i_read_bits += 5;
+
+ sample_0[0][sb] = slope_0[gr0][sb] * L3_table[code % 3];
+ sample_1[0][sb] = slope_1[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample_0[1][sb] = slope_0[gr0][sb] * L3_table[code % 3];
+ sample_1[1][sb] = slope_1[gr0][sb] * L3_table[code % 3];
+ code /= 3;
+ sample_0[2][sb] = slope_0[gr0][sb] * L3_table[code];
+ sample_1[2][sb] = slope_1[gr0][sb] * L3_table[code];
+ break;
+
+ case L5:
+ code = GetBits( &p_adec->bit_stream, 7 );
+ i_read_bits += 7;
+
+ sample_0[0][sb] = slope_0[gr0][sb] * L5_table[code % 5];
+ sample_1[0][sb] = slope_1[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample_0[1][sb] = slope_0[gr0][sb] * L5_table[code % 5];
+ sample_1[1][sb] = slope_1[gr0][sb] * L5_table[code % 5];
+ code /= 5;
+ sample_0[2][sb] = slope_0[gr0][sb] * L5_table[code];
+ sample_1[2][sb] = slope_1[gr0][sb] * L5_table[code];
+ break;
+
+ case L9:
+ code = GetBits( &p_adec->bit_stream, 10 );
+ i_read_bits += 10;
+
+ sample_0[0][sb] = slope_0[gr0][sb] * L9_table[code % 9];
+ sample_1[0][sb] = slope_1[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample_0[1][sb] = slope_0[gr0][sb] * L9_table[code % 9];
+ sample_1[1][sb] = slope_1[gr0][sb] * L9_table[code % 9];
+ code /= 9;
+ sample_0[2][sb] = slope_0[gr0][sb] * L9_table[code];
+ sample_1[2][sb] = slope_1[gr0][sb] * L9_table[code];
+ break;
+
+ default:
+ for (s = 0; s < 3; s++)
+ {
+ code = GetBits( &p_adec->bit_stream,
+ allocation_0[sb] );
+ i_read_bits += allocation_0[sb];
+
+ sample_0[s][sb] =
+ slope_0[gr0][sb] * code + offset_0[gr0][sb];
+ sample_1[s][sb] =
+ slope_1[gr0][sb] * code + offset_1[gr0][sb];
+ }
+ }
+ }
+
+ for (; sb < 32; sb++)
+ {
+ sample_0[0][sb] = sample_0[1][sb] = sample_0[2][sb] = 0;
+ sample_1[0][sb] = sample_1[1][sb] = sample_1[2][sb] = 0;
+ }
+
+ for (s = 0; s < 3; s++)
+ {
+ DCT32( &p_adec->bank_0, sample_0[s] );
+ PCM( &p_adec->bank_0, buffer, 2 );
+
+ DCT32( &p_adec->bank_1, sample_1[s] );
+ PCM( &p_adec->bank_1, buffer + 1, 2 );
+
+ buffer += 64;
+ }
+ }
+ }
+
+ p_adec->i_read_bits += i_read_bits;
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * adec_layer2.h: MPEG Layer II audio decoder
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: layer2.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+int adec_layer2_mono ( adec_thread_t * p_adec, s16 * buffer );
+int adec_layer2_stereo ( adec_thread_t * p_adec, s16 * buffer );
+
--- /dev/null
+/*****************************************************************************
+ * math.c: Inverse Discrete Cosine Transform and Pulse Code Modulation
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: math.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <vlc/vlc.h>
+
+#include "generic.h"
+
+/*****************************************************************************
+ * DCT32: Fast 32 points Discrete Cosine Transform
+ *****************************************************************************
+ * 289 additions and multiplications
+ * F(u)=alpha(u)*SUM(x=0, x<N) f(x)*cos((2x+1)u*pi/2N)
+ * where alpha(u) = sqrt(2)/N if u=0, 2/N otherwise.
+ * See fastdct.ps, and fast.tar.gz for a (Fortran :) implementation.
+ *****************************************************************************/
+
+void DCT32( adec_bank_t *b, float *x )
+{
+ /* cosine coefficients */
+ static const float c2 = .70710678118655;
+ static const float c3 = .54119610014620;
+ static const float c4 = -1.3065629648764;
+ static const float c5 = .50979557910416;
+ static const float c6 = .89997622313642;
+ static const float c7 = -2.5629154477415;
+ static const float c8 = -.60134488693505;
+ static const float c9 = .50241928618816;
+ static const float c10 = .56694403481636;
+ static const float c11 = .78815462345125;
+ static const float c12 = 1.7224470982383;
+ static const float c13 = -5.1011486186892;
+ static const float c14 = -1.0606776859903;
+ static const float c15 = -.64682178335999;
+ static const float c16 = -.52249861493969;
+ static const float c17 = .50060299823520;
+ static const float c18 = .51544730992262;
+ static const float c19 = .55310389603444;
+ static const float c20 = .62250412303566;
+ static const float c21 = .74453627100230;
+ static const float c22 = .97256823786196;
+ static const float c23 = 1.4841646163142;
+ static const float c24 = 3.4076084184687;
+ static const float c25 = -10.190008123548;
+ static const float c26 = -2.0577810099534;
+ static const float c27 = -1.1694399334329;
+ static const float c28 = -.83934964541553;
+ static const float c29 = -.67480834145501;
+ static const float c30 = -.58293496820613;
+ static const float c31 = -.53104259108978;
+ static const float c32 = -.50547095989754;
+
+ /* temporary variables */
+ float t1 , t2 , t3 , t4 , t5 , t6 , t7 , t8 ,
+ t9 , t10 , t11 , t12 , t13 , t14 , t15 , t16 ,
+ t17 , t18 , t19 , t20 , t21 , t22 , t23 , t24 ,
+ t25 , t26 , t27 , t28 , t29 , t30 , t31 , t32 ,
+ tt1 , tt2 , tt3 , tt4 , tt5 , tt6 , tt7 , tt8 ,
+ tt9 , tt10, tt11, tt12, tt13, tt14, tt15, tt16,
+ tt17, tt18, tt19, tt20, tt21, tt22, tt23, tt24,
+ tt25, tt26, tt27, tt28, tt29, tt30, tt31, tt32, *y;
+
+ /* We unrolled the loops */
+ /* Odd-even ordering is integrated before the 1st stage */
+ t17 = c17 * (x[0] - x[31]);
+ t1 = x[0] + x[31];
+ t18 = c18 * (x[2] - x[29]);
+ t2 = x[2] + x[29];
+ t19 = c19 * (x[4] - x[27]);
+ t3 = x[4] + x[27];
+ t20 = c20 * (x[6] - x[25]);
+ t4 = x[6] + x[25];
+ t21 = c21 * (x[8] - x[23]);
+ t5 = x[8] + x[23];
+ t22 = c22 * (x[10] - x[21]);
+ t6 = x[10] + x[21];
+ t23 = c23 * (x[12] - x[19]);
+ t7 = x[12] + x[19];
+ t24 = c24 * (x[14] - x[17]);
+ t8 = x[14] + x[17];
+ t25 = c25 * (x[16] - x[15]);
+ t9 = x[16] + x[15];
+ t26 = c26 * (x[18] - x[13]);
+ t10 = x[18] + x[13];
+ t27 = c27 * (x[20] - x[11]);
+ t11 = x[20] + x[11];
+ t28 = c28 * (x[22] - x[9]);
+ t12 = x[22] + x[9];
+ t29 = c29 * (x[24] - x[7]);
+ t13 = x[24] + x[7];
+ t30 = c30 * (x[26] - x[5]);
+ t14 = x[26] + x[5];
+ t31 = c31 * (x[28] - x[3]);
+ t15 = x[28] + x[3];
+ t32 = c32 * (x[30] - x[1]);
+ t16 = x[30] + x[1];
+ /* 2nd stage */
+ tt9 = c9 * (t1 - t9);
+ tt1 = t1 + t9;
+ tt10 = c10 * (t2 - t10);
+ tt2 = t2 + t10;
+ tt11 = c11 * (t3 - t11);
+ tt3 = t3 + t11;
+ tt12 = c12 * (t4 - t12);
+ tt4 = t4 + t12;
+ tt13 = c13 * (t5 - t13);
+ tt5 = t5 + t13;
+ tt14 = c14 * (t6 - t14);
+ tt6 = t6 + t14;
+ tt15 = c15 * (t7 - t15);
+ tt7 = t7 + t15;
+ tt16 = c16 * (t8 - t16);
+ tt8 = t8 + t16;
+ tt25 = c9 * (t17 - t25);
+ tt17 = t17 + t25;
+ tt26 = c10 * (t18 - t26);
+ tt18 = t18 + t26;
+ tt27 = c11 * (t19 - t27);
+ tt19 = t19 + t27;
+ tt28 = c12 * (t20 - t28);
+ tt20 = t20 + t28;
+ tt29 = c13 * (t21 - t29);
+ tt21 = t21 + t29;
+ tt30 = c14 * (t22 - t30);
+ tt22 = t22 + t30;
+ tt31 = c15 * (t23 - t31);
+ tt23 = t23 + t31;
+ tt32 = c16 * (t24 - t32);
+ tt24 = t24 + t32;
+ /* 3rd stage */
+ t5 = c5 * (tt1 - tt5);
+ t1 = tt1 + tt5;
+ t6 = c6 * (tt2 - tt6);
+ t2 = tt2 + tt6;
+ t7 = c7 * (tt3 - tt7);
+ t3 = tt3 + tt7;
+ t8 = c8 * (tt4 - tt8);
+ t4 = tt4 + tt8;
+ t13 = c5 * (tt9 - tt13);
+ t9 = tt9 + tt13;
+ t14 = c6 * (tt10 - tt14);
+ t10 = tt10 + tt14;
+ t15 = c7 * (tt11 - tt15);
+ t11 = tt11 + tt15;
+ t16 = c8 * (tt12 - tt16);
+ t12 = tt12 + tt16;
+ t21 = c5 * (tt17 - tt21);
+ t17 = tt17 + tt21;
+ t22 = c6 * (tt18 - tt22);
+ t18 = tt18 + tt22;
+ t23 = c7 * (tt19 - tt23);
+ t19 = tt19 + tt23;
+ t24 = c8 * (tt20 - tt24);
+ t20 = tt20 + tt24;
+ t29 = c5 * (tt25 - tt29);
+ t25 = tt25 + tt29;
+ t30 = c6 * (tt26 - tt30);
+ t26 = tt26 + tt30;
+ t31 = c7 * (tt27 - tt31);
+ t27 = tt27 + tt31;
+ t32 = c8 * (tt28 - tt32);
+ t28 = tt28 + tt32;
+ /* 4th stage */
+ tt3 = c3 * (t1 - t3);
+ tt1 = t1 + t3;
+ tt4 = c4 * (t2 - t4);
+ tt2 = t2 + t4;
+ tt7 = c3 * (t5 - t7);
+ tt5 = t5 + t7;
+ tt8 = c4 * (t6 - t8);
+ tt6 = t6 + t8;
+ tt11 = c3 * (t9 - t11);
+ tt9 = t9 + t11;
+ tt12 = c4 * (t10 - t12);
+ tt10 = t10 + t12;
+ tt15 = c3 * (t13 - t15);
+ tt13 = t13 + t15;
+ tt16 = c4 * (t14 - t16);
+ tt14 = t14 + t16;
+ tt19 = c3 * (t17 - t19);
+ tt17 = t17 + t19;
+ tt20 = c4 * (t18 - t20);
+ tt18 = t18 + t20;
+ tt23 = c3 * (t21 - t23);
+ tt21 = t21 + t23;
+ tt24 = c4 * (t22 - t24);
+ tt22 = t22 + t24;
+ tt27 = c3 * (t25 - t27);
+ tt25 = t25 + t27;
+ tt28 = c4 * (t26 - t28);
+ tt26 = t26 + t28;
+ tt31 = c3 * (t29 - t31);
+ tt29 = t29 + t31;
+ tt32 = c4 * (t30 - t32);
+ tt30 = t30 + t32;
+ /* Bit-reverse ordering is integrated after the 5th stage */
+ /* Begin to split the result of the DCT (t1 to t32) in the filter bank */
+ x = b->actual + b->pos;
+ y = (b->actual == b->v1 ? b->v2 : b->v1) + b->pos;
+ x[0] = -(y[0] = c2 * (tt1 - tt2)); /* t17 */
+ x[256] = 0; y[256] = tt1 + tt2; /* t1 */
+ t25 = c2 * (tt3 - tt4);
+ t9 = tt3 + tt4;
+ t21 = c2 * (tt5 - tt6);
+ t5 = tt5 + tt6;
+ t29 = c2 * (tt7 - tt8);
+ t13 = tt7 + tt8;
+ t19 = c2 * (tt9 - tt10);
+ t3 = tt9 + tt10;
+ t27 = c2 * (tt11 - tt12);
+ t11 = tt11 + tt12;
+ t23 = c2 * (tt13 - tt14);
+ t7 = tt13 + tt14;
+ t31 = c2 * (tt15 - tt16);
+ t15 = tt15 + tt16;
+ t18 = c2 * (tt17 - tt18);
+ t2 = tt17 + tt18;
+ t26 = c2 * (tt19 - tt20);
+ t10 = tt19 + tt20;
+ t22 = c2 * (tt21 - tt22);
+ t6 = tt21 + tt22;
+ t30 = c2 * (tt23 - tt24);
+ t14 = tt23 + tt24;
+ t20 = c2 * (tt25 - tt26);
+ t4 = tt25 + tt26;
+ t28 = c2 * (tt27 - tt28);
+ t12 = tt27 + tt28;
+ t24 = c2 * (tt29 - tt30);
+ t8 = tt29 + tt30;
+ t32 = c2 * (tt31 - tt32);
+ t16 = tt31 + tt32;
+ /* Do the sums */
+ /* Keep on splitting the result */
+ y[384] = y[128] = t9 - (x[128] = -(x[384] = t25)); /* t25, t9 */
+ t10 += t26;
+ t11 += t27;
+ t12 += t28;
+ t13 += t29;
+ t14 += t30;
+ t15 += t31;
+ t16 += t32;
+ y[320] = y[192] = t5 + t13; /* t5 */
+ y[448] = y[64] = t13 + t21; /* t13 */
+ x[64] = -(x[448] = t21 - (x[192] = -(x[320] = t29))); /* t29, t21 */
+ t6 += t14;
+ t14 += t22;
+ t22 += t30;
+ t7 += t15;
+ t15 += t23;
+ t23 += t31;
+ t8 += t16;
+ t16 += t24;
+ t24 += t32;
+ y[288] = y[224] = t3 + t7; /* t3 */
+ y[352] = y[160] = t7 + t11; /* t7 */
+ y[416] = y[96] = t11 + t15; /* t11 */
+ y[480] = y[32] = t15 + t19; /* t15 */
+ x[32] = -(x[480] = t19 + t23); /* t19 */
+ x[96] = -(x[416] = t23 + t27); /* t23 */
+ x[160] = -(x[352] = t27 - (x[224] = -(x[288] = t31))); /* t31, t27 */
+ t4 += t8 ;
+ t8 += t12;
+ t12 += t16;
+ t16 += t20;
+ t20 += t24;
+ t24 += t28;
+ t28 += t32;
+ y[272] = y[240] = t2 + t4; /* t2 */
+ y[304] = y[208] = t4 + t6; /* t4 */
+ y[336] = y[176] = t6 + t8; /* t6 */
+ y[368] = y[144] = t8 + t10; /* t8 */
+ y[400] = y[112] = t10 + t12; /* t10 */
+ y[432] = y[80] = t12 + t14; /* t12 */
+ y[464] = y[48] = t14 + t16; /* t14 */
+ y[496] = y[16] = t16 + t18; /* t16 */
+ x[16] = -(x[496] = t18 + t20); /* t18 */
+ x[48] = -(x[464] = t20 + t22); /* t20 */
+ x[80] = -(x[432] = t22 + t24); /* t22 */
+ x[112] = -(x[400] = t24 + t26); /* t24 */
+ x[144] = -(x[368] = t26 + t28); /* t26 */
+ x[176] = -(x[336] = t28 + t30); /* t28 */
+ x[208] = -(x[304] = t30 - (x[240] = -(x[272] = t32))); /* t32, t30 */
+ /* Note that to be really complete, the DCT should multiply t1 by sqrt(2)/N
+ and t2 to t32 by 2/N, and would take 321 additions and multiplications.
+ But that's unuseful in this application. */
+}
+
+
+/*****************************************************************************
+ * PCM: Pulse Code Modulation
+ *****************************************************************************
+ * Compute 32 PCM samples with a convolution product
+ *****************************************************************************/
+
+void PCM(adec_bank_t *b, s16 *p_pcm, int jump)
+{
+ /* scale factor */
+#define F -32768
+ /* These values are not in the same order as in Annex 3-B.3 of the ISO/IEC
+ DIS 11172-3 */
+ static const float c[512] =
+ {
+ 0.000000000 * F, -0.000442505 * F, 0.003250122 * F, -0.007003784 * F,
+ 0.031082153 * F, -0.078628540 * F, 0.100311279 * F, -0.572036743 * F,
+ 1.144989014 * F, 0.572036743 * F, 0.100311279 * F, 0.078628540 * F,
+ 0.031082153 * F, 0.007003784 * F, 0.003250122 * F, 0.000442505 * F,
+ -0.000015259 * F, -0.000473022 * F, 0.003326416 * F, -0.007919312 * F,
+ 0.030517578 * F, -0.084182739 * F, 0.090927124 * F, -0.600219727 * F,
+ 1.144287109 * F, 0.543823242 * F, 0.108856201 * F, 0.073059082 * F,
+ 0.031478882 * F, 0.006118774 * F, 0.003173828 * F, 0.000396729 * F,
+ -0.000015259 * F, -0.000534058 * F, 0.003387451 * F, -0.008865356 * F,
+ 0.029785156 * F, -0.089706421 * F, 0.080688477 * F, -0.628295898 * F,
+ 1.142211914 * F, 0.515609741 * F, 0.116577148 * F, 0.067520142 * F,
+ 0.031738281 * F, 0.005294800 * F, 0.003082275 * F, 0.000366211 * F,
+ -0.000015259 * F, -0.000579834 * F, 0.003433228 * F, -0.009841919 * F,
+ 0.028884888 * F, -0.095169067 * F, 0.069595337 * F, -0.656219482 * F,
+ 1.138763428 * F, 0.487472534 * F, 0.123474121 * F, 0.061996460 * F,
+ 0.031845093 * F, 0.004486084 * F, 0.002990723 * F, 0.000320435 * F,
+ -0.000015259 * F, -0.000625610 * F, 0.003463745 * F, -0.010848999 * F,
+ 0.027801514 * F, -0.100540161 * F, 0.057617188 * F, -0.683914185 * F,
+ 1.133926392 * F, 0.459472656 * F, 0.129577637 * F, 0.056533813 * F,
+ 0.031814575 * F, 0.003723145 * F, 0.002899170 * F, 0.000289917 * F,
+ -0.000015259 * F, -0.000686646 * F, 0.003479004 * F, -0.011886597 * F,
+ 0.026535034 * F, -0.105819702 * F, 0.044784546 * F, -0.711318970 * F,
+ 1.127746582 * F, 0.431655884 * F, 0.134887695 * F, 0.051132202 * F,
+ 0.031661987 * F, 0.003005981 * F, 0.002792358 * F, 0.000259399 * F,
+ -0.000015259 * F, -0.000747681 * F, 0.003479004 * F, -0.012939453 * F,
+ 0.025085449 * F, -0.110946655 * F, 0.031082153 * F, -0.738372803 * F,
+ 1.120223999 * F, 0.404083252 * F, 0.139450073 * F, 0.045837402 * F,
+ 0.031387329 * F, 0.002334595 * F, 0.002685547 * F, 0.000244141 * F,
+ -0.000030518 * F, -0.000808716 * F, 0.003463745 * F, -0.014022827 * F,
+ 0.023422241 * F, -0.115921021 * F, 0.016510010 * F, -0.765029907 * F,
+ 1.111373901 * F, 0.376800537 * F, 0.143264771 * F, 0.040634155 * F,
+ 0.031005859 * F, 0.001693726 * F, 0.002578735 * F, 0.000213623 * F,
+ -0.000030518 * F, -0.000885010 * F, 0.003417969 * F, -0.015121460 * F,
+ 0.021575928 * F, -0.120697021 * F, 0.001068115 * F, -0.791213989 * F,
+ 1.101211548 * F, 0.349868774 * F, 0.146362305 * F, 0.035552979 * F,
+ 0.030532837 * F, 0.001098633 * F, 0.002456665 * F, 0.000198364 * F,
+ -0.000030518 * F, -0.000961304 * F, 0.003372192 * F, -0.016235352 * F,
+ 0.019531250 * F, -0.125259399 * F, -0.015228271 * F, -0.816864014 * F,
+ 1.089782715 * F, 0.323318481 * F, 0.148773193 * F, 0.030609131 * F,
+ 0.029937744 * F, 0.000549316 * F, 0.002349854 * F, 0.000167847 * F,
+ -0.000030518 * F, -0.001037598 * F, 0.003280640 * F, -0.017349243 * F,
+ 0.017257690 * F, -0.129562378 * F, -0.032379150 * F, -0.841949463 * F,
+ 1.077117920 * F, 0.297210693 * F, 0.150497437 * F, 0.025817871 * F,
+ 0.029281616 * F, 0.000030518 * F, 0.002243042 * F, 0.000152588 * F,
+ -0.000045776 * F, -0.001113892 * F, 0.003173828 * F, -0.018463135 * F,
+ 0.014801025 * F, -0.133590698 * F, -0.050354004 * F, -0.866363525 * F,
+ 1.063217163 * F, 0.271591187 * F, 0.151596069 * F, 0.021179199 * F,
+ 0.028533936 * F, -0.000442505 * F, 0.002120972 * F, 0.000137329 * F,
+ -0.000045776 * F, -0.001205444 * F, 0.003051758 * F, -0.019577026 * F,
+ 0.012115479 * F, -0.137298584 * F, -0.069168091 * F, -0.890090942 * F,
+ 1.048156738 * F, 0.246505737 * F, 0.152069092 * F, 0.016708374 * F,
+ 0.027725220 * F, -0.000869751 * F, 0.002014160 * F, 0.000122070 * F,
+ -0.000061035 * F, -0.001296997 * F, 0.002883911 * F, -0.020690918 * F,
+ 0.009231567 * F, -0.140670776 * F, -0.088775635 * F, -0.913055420 * F,
+ 1.031936646 * F, 0.221984863 * F, 0.151962280 * F, 0.012420654 * F,
+ 0.026840210 * F, -0.001266479 * F, 0.001907349 * F, 0.000106812 * F,
+ -0.000061035 * F, -0.001388550 * F, 0.002700806 * F, -0.021789551 * F,
+ 0.006134033 * F, -0.143676758 * F, -0.109161377 * F, -0.935195923 * F,
+ 1.014617920 * F, 0.198059082 * F, 0.151306152 * F, 0.008316040 * F,
+ 0.025909424 * F, -0.001617432 * F, 0.001785278 * F, 0.000106812 * F,
+ -0.000076294 * F, -0.001480103 * F, 0.002487183 * F, -0.022857666 * F,
+ 0.002822876 * F, -0.146255493 * F, -0.130310059 * F, -0.956481934 * F,
+ 0.996246338 * F, 0.174789429 * F, 0.150115967 * F, 0.004394531 * F,
+ 0.024932861 * F, -0.001937866 * F, 0.001693726 * F, 0.000091553 * F,
+ -0.000076294 * F, -0.001586914 * F, 0.002227783 * F, -0.023910522 * F,
+ -0.000686646 * F, -0.148422241 * F, -0.152206421 * F, -0.976852417 * F,
+ 0.976852417 * F, 0.152206421 * F, 0.148422241 * F, 0.000686646 * F,
+ 0.023910522 * F, -0.002227783 * F, 0.001586914 * F, 0.000076294 * F,
+ -0.000091553 * F, -0.001693726 * F, 0.001937866 * F, -0.024932861 * F,
+ -0.004394531 * F, -0.150115967 * F, -0.174789429 * F, -0.996246338 * F,
+ 0.956481934 * F, 0.130310059 * F, 0.146255493 * F, -0.002822876 * F,
+ 0.022857666 * F, -0.002487183 * F, 0.001480103 * F, 0.000076294 * F,
+ -0.000106812 * F, -0.001785278 * F, 0.001617432 * F, -0.025909424 * F,
+ -0.008316040 * F, -0.151306152 * F, -0.198059082 * F, -1.014617920 * F,
+ 0.935195923 * F, 0.109161377 * F, 0.143676758 * F, -0.006134033 * F,
+ 0.021789551 * F, -0.002700806 * F, 0.001388550 * F, 0.000061035 * F,
+ -0.000106812 * F, -0.001907349 * F, 0.001266479 * F, -0.026840210 * F,
+ -0.012420654 * F, -0.151962280 * F, -0.221984863 * F, -1.031936646 * F,
+ 0.913055420 * F, 0.088775635 * F, 0.140670776 * F, -0.009231567 * F,
+ 0.020690918 * F, -0.002883911 * F, 0.001296997 * F, 0.000061035 * F,
+ -0.000122070 * F, -0.002014160 * F, 0.000869751 * F, -0.027725220 * F,
+ -0.016708374 * F, -0.152069092 * F, -0.246505737 * F, -1.048156738 * F,
+ 0.890090942 * F, 0.069168091 * F, 0.137298584 * F, -0.012115479 * F,
+ 0.019577026 * F, -0.003051758 * F, 0.001205444 * F, 0.000045776 * F,
+ -0.000137329 * F, -0.002120972 * F, 0.000442505 * F, -0.028533936 * F,
+ -0.021179199 * F, -0.151596069 * F, -0.271591187 * F, -1.063217163 * F,
+ 0.866363525 * F, 0.050354004 * F, 0.133590698 * F, -0.014801025 * F,
+ 0.018463135 * F, -0.003173828 * F, 0.001113892 * F, 0.000045776 * F,
+ -0.000152588 * F, -0.002243042 * F, -0.000030518 * F, -0.029281616 * F,
+ -0.025817871 * F, -0.150497437 * F, -0.297210693 * F, -1.077117920 * F,
+ 0.841949463 * F, 0.032379150 * F, 0.129562378 * F, -0.017257690 * F,
+ 0.017349243 * F, -0.003280640 * F, 0.001037598 * F, 0.000030518 * F,
+ -0.000167847 * F, -0.002349854 * F, -0.000549316 * F, -0.029937744 * F,
+ -0.030609131 * F, -0.148773193 * F, -0.323318481 * F, -1.089782715 * F,
+ 0.816864014 * F, 0.015228271 * F, 0.125259399 * F, -0.019531250 * F,
+ 0.016235352 * F, -0.003372192 * F, 0.000961304 * F, 0.000030518 * F,
+ -0.000198364 * F, -0.002456665 * F, -0.001098633 * F, -0.030532837 * F,
+ -0.035552979 * F, -0.146362305 * F, -0.349868774 * F, -1.101211548 * F,
+ 0.791213989 * F, -0.001068115 * F, 0.120697021 * F, -0.021575928 * F,
+ 0.015121460 * F, -0.003417969 * F, 0.000885010 * F, 0.000030518 * F,
+ -0.000213623 * F, -0.002578735 * F, -0.001693726 * F, -0.031005859 * F,
+ -0.040634155 * F, -0.143264771 * F, -0.376800537 * F, -1.111373901 * F,
+ 0.765029907 * F, -0.016510010 * F, 0.115921021 * F, -0.023422241 * F,
+ 0.014022827 * F, -0.003463745 * F, 0.000808716 * F, 0.000030518 * F,
+ -0.000244141 * F, -0.002685547 * F, -0.002334595 * F, -0.031387329 * F,
+ -0.045837402 * F, -0.139450073 * F, -0.404083252 * F, -1.120223999 * F,
+ 0.738372803 * F, -0.031082153 * F, 0.110946655 * F, -0.025085449 * F,
+ 0.012939453 * F, -0.003479004 * F, 0.000747681 * F, 0.000015259 * F,
+ -0.000259399 * F, -0.002792358 * F, -0.003005981 * F, -0.031661987 * F,
+ -0.051132202 * F, -0.134887695 * F, -0.431655884 * F, -1.127746582 * F,
+ 0.711318970 * F, -0.044784546 * F, 0.105819702 * F, -0.026535034 * F,
+ 0.011886597 * F, -0.003479004 * F, 0.000686646 * F, 0.000015259 * F,
+ -0.000289917 * F, -0.002899170 * F, -0.003723145 * F, -0.031814575 * F,
+ -0.056533813 * F, -0.129577637 * F, -0.459472656 * F, -1.133926392 * F,
+ 0.683914185 * F, -0.057617188 * F, 0.100540161 * F, -0.027801514 * F,
+ 0.010848999 * F, -0.003463745 * F, 0.000625610 * F, 0.000015259 * F,
+ -0.000320435 * F, -0.002990723 * F, -0.004486084 * F, -0.031845093 * F,
+ -0.061996460 * F, -0.123474121 * F, -0.487472534 * F, -1.138763428 * F,
+ 0.656219482 * F, -0.069595337 * F, 0.095169067 * F, -0.028884888 * F,
+ 0.009841919 * F, -0.003433228 * F, 0.000579834 * F, 0.000015259 * F,
+ -0.000366211 * F, -0.003082275 * F, -0.005294800 * F, -0.031738281 * F,
+ -0.067520142 * F, -0.116577148 * F, -0.515609741 * F, -1.142211914 * F,
+ 0.628295898 * F, -0.080688477 * F, 0.089706421 * F, -0.029785156 * F,
+ 0.008865356 * F, -0.003387451 * F, 0.000534058 * F, 0.000015259 * F,
+ -0.000396729 * F, -0.003173828 * F, -0.006118774 * F, -0.031478882 * F,
+ -0.073059082 * F, -0.108856201 * F, -0.543823242 * F, -1.144287109 * F,
+ 0.600219727 * F, -0.090927124 * F, 0.084182739 * F, -0.030517578 * F,
+ 0.007919312 * F, -0.003326416 * F, 0.000473022 * F, 0.000015259 * F
+ };
+#undef F
+ int i;
+ float tmp, *v;
+ const float *f;
+
+ f = c;
+
+ switch(b->pos)
+ {
+ case 0:
+ v = b->actual;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ /* ceiling saturation */
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ /* floor saturation */
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 1:
+ v = b->actual + 1;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 2:
+ v = b->actual + 2;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 3:
+ v = b->actual + 3;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 4:
+ v = b->actual + 4;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 5:
+ v = b->actual + 5;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 6:
+ v = b->actual + 6;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 7:
+ v = b->actual + 7;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 8:
+ v = b->actual + 8;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 9:
+ v = b->actual + 9;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 10:
+ v = b->actual + 10;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 11:
+ v = b->actual + 11;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 12:
+ v = b->actual + 12;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 13:
+ v = b->actual + 13;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 14:
+ v = b->actual + 14;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v;
+ v += 15;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 15;
+ }
+ break;
+ case 15:
+ v = b->actual + 15;
+ for (i=0; i<32; i++)
+ {
+ tmp = *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ tmp += *f++ * *v--;
+ if ((tmp += *f++ * *v) > 32767)
+ {
+ *p_pcm = 0x7FFF;
+ }
+ else if (tmp < -32768)
+ {
+ *p_pcm = 0x8000;
+ }
+ else
+ {
+ *p_pcm = (s16)tmp;
+ }
+ p_pcm += jump;
+ v += 31;
+ }
+ break;
+ }
+
+ /* Set the next position in the filter bank */
+ b->pos++;
+ b->pos &= 15;
+ b->actual = (b->actual == b->v1 ? b->v2 : b->v1);
+}
--- /dev/null
+/*****************************************************************************
+ * adec_math.h : PCM and DCT
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: math.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void DCT32 ( adec_bank_t *, float * );
+void PCM ( adec_bank_t *, s16 *, int );
+
--- /dev/null
+/*****************************************************************************
+ * test.c: MPEG Layer I-II audio decoder test program
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: test.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Michel Lespinasse <walken@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "generic.h"
+#include "decoder.h"
+
+#define ADEC_FRAME_SIZE (2*1152)
+
+int main (void)
+{
+ audiodec_t decoder;
+ adec_sync_info_t sync_info;
+ adec_byte_stream_t * stream;
+ s16 buffer [ADEC_FRAME_SIZE];
+
+ int framenum;
+
+ memset (&decoder, 0, sizeof (decoder));
+ if (adec_init (&decoder))
+ {
+ return 1;
+ }
+
+ stream = adec_byte_stream (&decoder);
+ stream->p_byte = NULL;
+ stream->p_end = NULL;
+ stream->info = stdin;
+
+ framenum = 0;
+
+ while (1)
+ {
+ int i;
+
+ if (adec_sync_frame (&decoder, &sync_info))
+ {
+ return 1;
+ }
+ if (adec_decode_frame (&decoder, buffer))
+ {
+ return 1;
+ }
+
+#if 1
+ for (i = 0; i < (2*1152); i++)
+ {
+ fprintf ( stderr, "%04X\n",(u16)buffer[i] );
+ }
+#endif
+ }
+
+ return 0;
+}
+
+void adec_byte_stream_next (adec_byte_stream_t * p_byte_stream)
+{
+ static u8 buffer [1024];
+ static u8 dummy = 0;
+ FILE * fd;
+ int size;
+
+ fd = p_byte_stream->info;
+ size = fread (buffer, 1, 1024, fd);
+ if (size)
+ {
+ p_byte_stream->p_byte = buffer;
+ p_byte_stream->p_end = buffer + size;
+ }
+ else
+ { /* end of stream, read dummy zeroes */
+ p_byte_stream->p_byte = &dummy;
+ p_byte_stream->p_end = &dummy + 1;
+ }
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+ifeq ($(ARCH),hppa64)
+CFLAGS += -ffunction-sections
+endif
+
+mpeg_video_SOURCES = parser.c headers.c blocks.c synchro.c pool.c decoder.c
--- /dev/null
+/*****************************************************************************
+ * blocks.c : blocks parsing
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: blocks.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Lespinasse <walken@zoy.org>
+ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memset */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#include "vdec_ext-plugins.h"
+
+#include "decoder.h"
+#include "pool.h"
+#include "parser.h"
+#include "blocks.h"
+
+/*
+ * Welcome to vpar_blocks.c ! Here's where the heavy processor-critical parsing
+ * task is done. This file is divided in several parts :
+ * - Decoding of coded blocks
+ * - Decoding of motion vectors
+ * - Decoding of the other macroblock structures
+ * - Picture data parsing management (slices and error handling)
+ * It's a pretty long file. Good luck and have a nice day.
+ */
+
+
+/*****************************************************************************
+ * vpar_InitScanTable : Initialize scan table
+ *****************************************************************************/
+void vpar_InitScanTable( vpar_thread_t * p_vpar )
+{
+ int i;
+
+ memcpy( p_vpar->ppi_scan, pi_scan, sizeof(pi_scan) );
+ p_vpar->pf_norm_scan( p_vpar->ppi_scan );
+
+ /* If scan table has changed, we must change the quantization matrices. */
+ for( i = 0; i < 64; i++ )
+ {
+ p_vpar->pi_default_intra_quant[ p_vpar->ppi_scan[0][i] ] =
+ pi_default_intra_quant[ pi_scan[0][i] ];
+ p_vpar->pi_default_nonintra_quant[ p_vpar->ppi_scan[0][i] ] =
+ pi_default_nonintra_quant[ pi_scan[0][i] ];
+ }
+}
+
+
+/*
+ * Block parsing
+ */
+
+/*****************************************************************************
+ * GetLumaDCDiff : Get the luminance DC coefficient difference
+ *****************************************************************************/
+static inline int GetLumaDCDiff( vpar_thread_t * p_vpar )
+{
+ lookup_t * p_tab;
+ int i_size, i_dc_diff, i_code;
+
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) < 0x1F )
+ {
+ p_tab = DC_lum_5 + i_code;
+ i_size = p_tab->i_value;
+ if( i_size )
+ {
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_dc_diff = GetBits( &p_vpar->bit_stream, i_size );
+ if ((i_dc_diff & (1 << (i_size - 1))) == 0)
+ {
+ i_dc_diff -= (1 << i_size) - 1;
+ }
+ return( i_dc_diff );
+ }
+ else
+ {
+ RemoveBits( &p_vpar->bit_stream, 3 );
+ return 0;
+ }
+ }
+ else
+ {
+ p_tab = DC_long - 0x1e0 + ShowBits( &p_vpar->bit_stream, 9 );
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_size = p_tab->i_value;
+ i_dc_diff = GetBits( &p_vpar->bit_stream, i_size );
+ if ((i_dc_diff & (1 << (i_size - 1))) == 0)
+ {
+ i_dc_diff -= (1 << i_size) - 1;
+ }
+ return( i_dc_diff );
+ }
+}
+
+/*****************************************************************************
+ * GetChromaDCDiff : Get the chrominance DC coefficient difference
+ *****************************************************************************/
+static inline int GetChromaDCDiff( vpar_thread_t * p_vpar )
+{
+ lookup_t * p_tab;
+ int i_size, i_dc_diff, i_code;
+
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) < 0x1F )
+ {
+ p_tab = DC_chrom_5 + i_code;
+ i_size = p_tab->i_value;
+ if( i_size )
+ {
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_dc_diff = GetBits( &p_vpar->bit_stream, i_size );
+ if ((i_dc_diff & (1 << (i_size - 1))) == 0)
+ {
+ i_dc_diff -= (1 << i_size) - 1;
+ }
+ return( i_dc_diff );
+ }
+ else
+ {
+ RemoveBits( &p_vpar->bit_stream, 2 );
+ return 0;
+ }
+ }
+ else
+ {
+ p_tab = DC_long - 0x3e0 + ShowBits( &p_vpar->bit_stream, 10 );
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length + 1 );
+ i_size = p_tab->i_value;
+ i_dc_diff = GetBits( &p_vpar->bit_stream, i_size );
+ if ((i_dc_diff & (1 << (i_size - 1))) == 0)
+ {
+ i_dc_diff -= (1 << i_size) - 1;
+ }
+ return( i_dc_diff );
+ }
+}
+
+
+#define SATURATE(val) \
+ if ((u32)(val + 2048) > 4095) \
+ { \
+ val = (val > 0) ? 2047 : -2048; \
+ }
+
+/*****************************************************************************
+ * MPEG2IntraB14 : Decode an intra block according to ISO/IEC 13818-2 table B14
+ *****************************************************************************/
+static void MPEG2IntraB14( vpar_thread_t * p_vpar, idct_inner_t * p_idct,
+ u8 * pi_quant )
+{
+ int i_coeff, i_mismatch, i_code, i_pos, i_value, i_nc;
+ s32 i_sign;
+ dct_lookup_t * p_tab;
+
+ int i_q_scale = p_vpar->mb.i_quantizer_scale;
+ dctelem_t * p_dest = p_idct->pi_block;
+ u8 * p_scan = p_vpar->picture.pi_scan;
+
+ i_coeff = 0;
+ i_mismatch = ~p_dest[0];
+ i_nc = (p_dest[0] != 0);
+
+ for( ; ; )
+ {
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) >= 0x5 )
+ {
+ p_tab = DCT_B14AC_5 - 5 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff >= 64 )
+ {
+ /* End of block */
+ break;
+ }
+
+store_coeff:
+ i_nc++;
+ i_pos = p_scan[ i_coeff ];
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_value = (p_tab->i_level * i_q_scale * pi_quant[i_pos])
+ >> 4;
+
+ i_sign = GetSignedBits( &p_vpar->bit_stream, 1 );
+ /* if (i_sign) i_value = -i_value; */
+ i_value = (i_value ^ i_sign) - i_sign;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ i_mismatch ^= i_value;
+
+ continue;
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 8 )) >= 0x4 )
+ {
+ p_tab = DCT_B14_8 - 4 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ /* Normal coefficient */
+ goto store_coeff;
+ }
+
+ /* Escape code */
+ i_coeff += (GetBits( &p_vpar->bit_stream, 12 ) & 0x3F) - 64;
+ if( i_coeff >= 64 )
+ {
+ /* Illegal, but needed to avoid overflow */
+ msg_Warn( p_vpar->p_fifo, "intra-B14 coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ i_nc++;
+ i_pos = p_scan[i_coeff];
+ i_value = (GetSignedBits( &p_vpar->bit_stream, 12 )
+ * i_q_scale * pi_quant[i_pos]) / 16;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ i_mismatch ^= i_value;
+ continue;
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 16)) >= 0x0200 )
+ {
+ p_tab = DCT_B14_10 - 8 + (i_code >> 6);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0080 )
+ {
+ p_tab = DCT_13 - 16 + (i_code >> 3);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0020 )
+ {
+ p_tab = DCT_15 - 16 + (i_code >> 1);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else
+ {
+ p_tab = DCT_16 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+
+ msg_Warn( p_vpar->p_fifo, "intra-B14 coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ p_dest[63] ^= i_mismatch & 1;
+ RemoveBits( &p_vpar->bit_stream, 2 ); /* End of Block */
+
+ if( i_nc <= 1 )
+ {
+ if( p_dest[63] )
+ {
+ if( i_nc == 0 )
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_copy;
+ p_idct->i_sparse_pos = 63;
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_copy;
+ }
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_copy;
+ p_idct->i_sparse_pos = i_coeff - p_tab->i_run;
+ }
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_copy;
+ }
+}
+
+/*****************************************************************************
+ * MPEG2IntraB15 : Decode an intra block according to ISO/IEC 13818-2 table B15
+ *****************************************************************************/
+static void MPEG2IntraB15( vpar_thread_t * p_vpar, idct_inner_t * p_idct,
+ u8 * pi_quant )
+{
+ int i_coeff, i_mismatch, i_code, i_pos, i_value, i_nc;
+ s32 i_sign;
+ dct_lookup_t * p_tab;
+
+ int i_q_scale = p_vpar->mb.i_quantizer_scale;
+ dctelem_t * p_dest = p_idct->pi_block;
+ u8 * p_scan = p_vpar->picture.pi_scan;
+
+ i_coeff = 0;
+ i_mismatch = ~p_dest[0];
+ i_nc = (p_dest[0] != 0);
+
+ for( ; ; )
+ {
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 8 )) >= 0x4 )
+ {
+ p_tab = DCT_B15_8 - 4 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+
+store_coeff:
+ i_nc++;
+ i_pos = p_scan[ i_coeff ];
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_value = (p_tab->i_level * i_q_scale * pi_quant[i_pos])
+ >> 4;
+
+ i_sign = GetSignedBits( &p_vpar->bit_stream, 1 );
+ /* if (i_sign) i_value = -i_value; */
+ i_value = (i_value ^ i_sign) - i_sign;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ i_mismatch ^= i_value;
+
+ continue;
+ }
+ else
+ {
+ if( i_coeff >= 128 )
+ {
+ /* End of block */
+ break;
+ }
+
+ /* Escape code */
+ i_coeff += (GetBits( &p_vpar->bit_stream, 12 ) & 0x3F) - 64;
+ if( i_coeff >= 64 )
+ {
+ /* Illegal, but needed to avoid overflow */
+ msg_Warn( p_vpar->p_fifo,
+ "intra-B15 coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ i_nc++;
+ i_pos = p_scan[i_coeff];
+ i_value = (GetSignedBits( &p_vpar->bit_stream, 12 )
+ * i_q_scale * pi_quant[i_pos]) / 16;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ i_mismatch ^= i_value;
+ continue;
+ }
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 16)) >= 0x0200 )
+ {
+ p_tab = DCT_B15_10 - 8 + (i_code >> 6);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0080 )
+ {
+ p_tab = DCT_13 - 16 + (i_code >> 3);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0020 )
+ {
+ p_tab = DCT_15 - 16 + (i_code >> 1);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else
+ {
+ p_tab = DCT_16 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+
+ msg_Warn( p_vpar->p_fifo, "intra-B15 coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ p_dest[63] ^= i_mismatch & 1;
+ RemoveBits( &p_vpar->bit_stream, 4 ); /* End of Block */
+
+ if( i_nc <= 1 )
+ {
+ if( p_dest[63] )
+ {
+ if( i_nc == 0 )
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_copy;
+ p_idct->i_sparse_pos = 63;
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_copy;
+ }
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_copy;
+ p_idct->i_sparse_pos = i_coeff - p_tab->i_run;
+ }
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_copy;
+ }
+}
+
+/*****************************************************************************
+ * MPEG2NonIntra : Decode a non-intra MPEG-2 block
+ *****************************************************************************/
+static void MPEG2NonIntra( vpar_thread_t * p_vpar, idct_inner_t * p_idct,
+ u8 * pi_quant )
+{
+ int i_coeff, i_mismatch, i_code, i_pos, i_value, i_nc;
+ s32 i_sign;
+ dct_lookup_t * p_tab;
+
+ int i_q_scale = p_vpar->mb.i_quantizer_scale;
+ dctelem_t * p_dest = p_idct->pi_block;
+ u8 * p_scan = p_vpar->picture.pi_scan;
+
+ i_coeff = -1;
+ i_mismatch = 1;
+ i_nc = 0;
+
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) >= 0x5 )
+ {
+ p_tab = DCT_B14DC_5 - 5 + i_code;
+ goto coeff_1;
+ }
+ else
+ {
+ goto coeff_2;
+ }
+
+ for( ; ; )
+ {
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) >= 0x5 )
+ {
+ p_tab = DCT_B14AC_5 - 5 + i_code;
+coeff_1:
+ i_coeff += p_tab->i_run;
+ if( i_coeff >= 64 )
+ {
+ /* End of block */
+ break;
+ }
+
+store_coeff:
+ i_nc++;
+ i_pos = p_scan[ i_coeff ];
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_value = ((2 * p_tab->i_level + 1) * i_q_scale * pi_quant[i_pos])
+ >> 5;
+
+ i_sign = GetSignedBits( &p_vpar->bit_stream, 1 );
+ /* if (i_sign) i_value = -i_value; */
+ i_value = (i_value ^ i_sign) - i_sign;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ i_mismatch ^= i_value;
+
+ continue;
+ }
+coeff_2:
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 8 )) >= 0x4 )
+ {
+ p_tab = DCT_B14_8 - 4 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ /* Normal coefficient */
+ goto store_coeff;
+ }
+
+ /* Escape code */
+ i_coeff += (GetBits( &p_vpar->bit_stream, 12 ) & 0x3F) - 64;
+ if( i_coeff >= 64 )
+ {
+ /* Illegal, but needed to avoid overflow */
+ msg_Warn( p_vpar->p_fifo,
+ "MPEG2NonIntra coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ i_nc++;
+ i_pos = p_scan[i_coeff];
+ i_value = 2 * (ShowSignedBits( &p_vpar->bit_stream, 1 )
+ + GetSignedBits( &p_vpar->bit_stream, 12 )) + 1;
+
+ i_value = (i_value * i_q_scale * pi_quant[i_pos]) / 32;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ i_mismatch ^= i_value;
+ continue;
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 16)) >= 0x0200 )
+ {
+ p_tab = DCT_B14_10 - 8 + (i_code >> 6);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0080 )
+ {
+ p_tab = DCT_13 - 16 + (i_code >> 3);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0020 )
+ {
+ p_tab = DCT_15 - 16 + (i_code >> 1);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else
+ {
+ p_tab = DCT_16 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+
+ msg_Warn( p_vpar->p_fifo, "MPEG2NonIntra coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ p_dest[63] ^= i_mismatch & 1;
+ RemoveBits( &p_vpar->bit_stream, 2 ); /* End of Block */
+
+ if( i_nc <= 1 )
+ {
+ if( p_dest[63] )
+ {
+ if( i_nc == 0 )
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_add;
+ p_idct->i_sparse_pos = 63;
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_add;
+ }
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_add;
+ if( i_nc == 0 )
+ {
+ p_idct->i_sparse_pos = 0;
+ }
+ else
+ {
+ p_idct->i_sparse_pos = i_coeff - p_tab->i_run;
+ }
+ }
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_add;
+ }
+}
+
+/*****************************************************************************
+ * MPEG1Intra : Decode an MPEG-1 intra block
+ *****************************************************************************/
+static void MPEG1Intra( vpar_thread_t * p_vpar, idct_inner_t * p_idct,
+ u8 * pi_quant )
+{
+ int i_coeff, i_code, i_pos, i_value, i_nc;
+ s32 i_sign;
+ dct_lookup_t * p_tab;
+
+ int i_q_scale = p_vpar->mb.i_quantizer_scale;
+ dctelem_t * p_dest = p_idct->pi_block;
+ u8 * p_scan = p_vpar->picture.pi_scan;
+
+ i_coeff = 0;
+ i_nc = (p_dest[0] != 0);
+
+ for( ; ; )
+ {
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) >= 0x5 )
+ {
+ p_tab = DCT_B14AC_5 - 5 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff >= 64 )
+ {
+ /* End of block */
+ break;
+ }
+
+store_coeff:
+ i_nc++;
+ i_pos = p_scan[ i_coeff ];
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_value = (p_tab->i_level * i_q_scale * pi_quant[i_pos])
+ >> 4;
+
+ /* Oddification */
+ i_value = (i_value - 1) | 1;
+
+ i_sign = GetSignedBits( &p_vpar->bit_stream, 1 );
+ /* if (i_sign) i_value = -i_value; */
+ i_value = (i_value ^ i_sign) - i_sign;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+
+ continue;
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 8 )) >= 0x4 )
+ {
+ p_tab = DCT_B14_8 - 4 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ /* Normal coefficient */
+ goto store_coeff;
+ }
+
+ /* Escape code */
+ i_coeff += (GetBits( &p_vpar->bit_stream, 12 ) & 0x3F) - 64;
+ if( i_coeff >= 64 )
+ {
+ /* Illegal, but needed to avoid overflow */
+ msg_Warn( p_vpar->p_fifo,
+ "MPEG1Intra coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ i_nc++;
+ i_pos = p_scan[i_coeff];
+
+ i_value = ShowSignedBits( &p_vpar->bit_stream, 8 );
+ if( !(i_value & 0x7F) )
+ {
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ i_value = ShowBits( &p_vpar->bit_stream, 8 ) + 2 * i_value;
+ }
+
+ i_value = (i_value * i_q_scale * pi_quant[i_pos]) / 16;
+
+ /* Oddification */
+ i_value = (i_value + ~ShowSignedBits( &p_vpar->bit_stream, 1 )) | 1;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ continue;
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 16)) >= 0x0200 )
+ {
+ p_tab = DCT_B14_10 - 8 + (i_code >> 6);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0080 )
+ {
+ p_tab = DCT_13 - 16 + (i_code >> 3);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0020 )
+ {
+ p_tab = DCT_15 - 16 + (i_code >> 1);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else
+ {
+ p_tab = DCT_16 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+
+ msg_Warn( p_vpar->p_fifo, "MPEG1Intra coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ RemoveBits( &p_vpar->bit_stream, 2 ); /* End of Block */
+
+ if( i_nc <= 1 )
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_copy;
+ p_idct->i_sparse_pos = i_coeff - p_tab->i_run;
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_copy;
+ }
+}
+
+/*****************************************************************************
+ * MPEG1NonIntra : Decode a non-intra MPEG-1 block
+ *****************************************************************************/
+static void MPEG1NonIntra( vpar_thread_t * p_vpar, idct_inner_t * p_idct,
+ u8 * pi_quant )
+{
+ int i_coeff, i_code, i_pos, i_value, i_nc;
+ s32 i_sign;
+ dct_lookup_t * p_tab;
+
+ int i_q_scale = p_vpar->mb.i_quantizer_scale;
+ dctelem_t * p_dest = p_idct->pi_block;
+ u8 * p_scan = p_vpar->picture.pi_scan;
+
+ i_coeff = -1;
+ i_nc = 0;
+
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) >= 0x5 )
+ {
+ p_tab = DCT_B14DC_5 - 5 + i_code;
+ goto coeff_1;
+ }
+ else
+ {
+ goto coeff_2;
+ }
+
+ for( ; ; )
+ {
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 )) >= 0x5 )
+ {
+ p_tab = DCT_B14AC_5 - 5 + i_code;
+coeff_1:
+ i_coeff += p_tab->i_run;
+ if( i_coeff >= 64 )
+ {
+ /* End of block */
+ break;
+ }
+
+store_coeff:
+ i_nc++;
+ i_pos = p_scan[ i_coeff ];
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_value = ((2 * p_tab->i_level + 1) * i_q_scale * pi_quant[i_pos])
+ >> 5;
+
+ /* Oddification */
+ i_value = (i_value - 1) | 1;
+
+ i_sign = GetSignedBits( &p_vpar->bit_stream, 1 );
+ /* if (i_sign) i_value = -i_value; */
+ i_value = (i_value ^ i_sign) - i_sign;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+
+ continue;
+ }
+coeff_2:
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 8 )) >= 0x4 )
+ {
+ p_tab = DCT_B14_8 - 4 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ /* Normal coefficient */
+ goto store_coeff;
+ }
+
+ /* Escape code */
+ i_coeff += (GetBits( &p_vpar->bit_stream, 12 ) & 0x3F) - 64;
+ if( i_coeff >= 64 )
+ {
+ /* Illegal, but needed to avoid overflow */
+ msg_Warn( p_vpar->p_fifo,
+ "MPEG1NonIntra coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ i_nc++;
+ i_pos = p_scan[i_coeff];
+ i_value = ShowSignedBits( &p_vpar->bit_stream, 8 );
+ if( !(i_value & 0x7F) )
+ {
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ i_value = ShowBits( &p_vpar->bit_stream, 8 ) + 2 * i_value;
+ }
+ i_sign = ShowSignedBits( &p_vpar->bit_stream, 1 );
+ i_value = 2 * (i_sign + i_value) + 1;
+ i_value = (i_value * i_q_scale * pi_quant[i_pos]) / 32;
+
+ /* Oddification */
+ i_value = (i_value + ~i_sign) | 1;
+
+ SATURATE( i_value );
+ p_dest[i_pos] = i_value;
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ continue;
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 16)) >= 0x0200 )
+ {
+ p_tab = DCT_B14_10 - 8 + (i_code >> 6);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0080 )
+ {
+ p_tab = DCT_13 - 16 + (i_code >> 3);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else if( i_code >= 0x0020 )
+ {
+ p_tab = DCT_15 - 16 + (i_code >> 1);
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+ else
+ {
+ p_tab = DCT_16 + i_code;
+ i_coeff += p_tab->i_run;
+ if( i_coeff < 64 )
+ {
+ goto store_coeff;
+ }
+ }
+
+ msg_Warn( p_vpar->p_fifo, "MPEG1NonIntra coeff is out of bounds" );
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+
+ RemoveBits( &p_vpar->bit_stream, 2 ); /* End of Block */
+
+ if( i_nc <= 1 )
+ {
+ p_idct->pf_idct = p_vpar->pf_sparse_idct_add;
+ if( i_nc == 0 )
+ {
+ p_idct->i_sparse_pos = 0;
+ }
+ else
+ {
+ p_idct->i_sparse_pos = i_coeff - p_tab->i_run;
+ }
+ }
+ else
+ {
+ p_idct->pf_idct = p_vpar->pf_idct_add;
+ }
+}
+
+#undef SATURATE
+
+/*****************************************************************************
+ * *MB : decode all blocks of the macroblock
+ *****************************************************************************/
+#define DECODE_LUMABLOCK( I_B, PF_MBFUNC ) \
+ p_idct = &p_mb->p_idcts[I_B]; \
+ memset( p_idct->pi_block, 0, 64*sizeof(dctelem_t) ); \
+ p_vpar->mb.pi_dc_dct_pred[0] += GetLumaDCDiff( p_vpar ); \
+ p_idct->pi_block[0] = p_vpar->mb.pi_dc_dct_pred[0] \
+ << (3 - p_vpar->picture.i_intra_dc_precision ); \
+ PF_MBFUNC( p_vpar, p_idct, p_vpar->sequence.intra_quant.pi_matrix );
+
+#define DECODE_CHROMABLOCK( I_B, PF_MBFUNC, I_CC ) \
+ p_idct = &p_mb->p_idcts[I_B]; \
+ memset( p_idct->pi_block, 0, 64*sizeof(dctelem_t) ); \
+ p_vpar->mb.pi_dc_dct_pred[I_CC] += GetChromaDCDiff( p_vpar ); \
+ p_idct->pi_block[0] = p_vpar->mb.pi_dc_dct_pred[I_CC] \
+ << (3 - p_vpar->picture.i_intra_dc_precision ); \
+ PF_MBFUNC( p_vpar, p_idct, \
+ p_vpar->sequence.chroma_intra_quant.pi_matrix );
+
+#define DECLARE_INTRAMB( PSZ_NAME, PF_MBFUNC ) \
+static inline void PSZ_NAME( vpar_thread_t * p_vpar, macroblock_t * p_mb ) \
+{ \
+ idct_inner_t * p_idct; \
+ int i_b = 4; \
+ \
+ p_mb->p_y_data = p_mb->pp_dest[0] + p_vpar->mb.i_offset; \
+ p_mb->p_u_data = p_mb->pp_dest[1] + (p_vpar->mb.i_offset \
+ >> p_vpar->sequence.b_chroma_h_subsampled); \
+ p_mb->p_v_data = p_mb->pp_dest[2] + (p_vpar->mb.i_offset \
+ >> p_vpar->sequence.b_chroma_h_subsampled); \
+ \
+ DECODE_LUMABLOCK( 0, PF_MBFUNC ); \
+ DECODE_LUMABLOCK( 1, PF_MBFUNC ); \
+ DECODE_LUMABLOCK( 2, PF_MBFUNC ); \
+ DECODE_LUMABLOCK( 3, PF_MBFUNC ); \
+ \
+ do \
+ { \
+ DECODE_CHROMABLOCK( i_b, PF_MBFUNC, 1 ); \
+ DECODE_CHROMABLOCK( i_b + 1, PF_MBFUNC, 2 ); \
+ i_b += 2; \
+ } \
+ while( i_b < 4 + p_vpar->sequence.i_chroma_nb_blocks ); \
+}
+
+DECLARE_INTRAMB( MPEG1IntraMB, MPEG1Intra );
+DECLARE_INTRAMB( MPEG2IntraB14MB, MPEG2IntraB14 );
+DECLARE_INTRAMB( MPEG2IntraB15MB, MPEG2IntraB15 );
+
+#undef DECLARE_INTRAMB
+#undef DECODE_LUMABLOCK
+#undef DECODE_CHROMABLOCK
+
+#define DECODE_LUMABLOCK( I_B, PF_MBFUNC ) \
+ if( p_mb->i_coded_block_pattern & (1 << (11 - (I_B))) ) \
+ { \
+ p_idct = &p_mb->p_idcts[I_B]; \
+ memset( p_idct->pi_block, 0, 64*sizeof(dctelem_t) ); \
+ PF_MBFUNC( p_vpar, p_idct, \
+ p_vpar->sequence.nonintra_quant.pi_matrix ); \
+ }
+
+#define DECODE_CHROMABLOCK( I_B, PF_MBFUNC ) \
+ if( p_mb->i_coded_block_pattern & (1 << (11 - (I_B))) ) \
+ { \
+ p_idct = &p_mb->p_idcts[I_B]; \
+ memset( p_idct->pi_block, 0, 64*sizeof(dctelem_t) ); \
+ PF_MBFUNC( p_vpar, p_idct, \
+ p_vpar->sequence.chroma_nonintra_quant.pi_matrix ); \
+ }
+
+#define DECLARE_NONINTRAMB( PSZ_NAME, PF_MBFUNC ) \
+static inline void PSZ_NAME( vpar_thread_t * p_vpar, macroblock_t * p_mb ) \
+{ \
+ idct_inner_t * p_idct; \
+ int i_b = 4; \
+ \
+ p_mb->p_y_data = p_mb->pp_dest[0] + p_vpar->mb.i_offset; \
+ p_mb->p_u_data = p_mb->pp_dest[1] + (p_vpar->mb.i_offset \
+ >> p_vpar->sequence.b_chroma_h_subsampled); \
+ p_mb->p_v_data = p_mb->pp_dest[2] + (p_vpar->mb.i_offset \
+ >> p_vpar->sequence.b_chroma_h_subsampled); \
+ \
+ DECODE_LUMABLOCK( 0, PF_MBFUNC ); \
+ DECODE_LUMABLOCK( 1, PF_MBFUNC ); \
+ DECODE_LUMABLOCK( 2, PF_MBFUNC ); \
+ DECODE_LUMABLOCK( 3, PF_MBFUNC ); \
+ \
+ do \
+ { \
+ DECODE_CHROMABLOCK( i_b, PF_MBFUNC ); \
+ DECODE_CHROMABLOCK( i_b + 1, PF_MBFUNC ); \
+ i_b += 2; \
+ } \
+ while( i_b < 4 + p_vpar->sequence.i_chroma_nb_blocks ); \
+}
+
+DECLARE_NONINTRAMB( MPEG1NonIntraMB, MPEG1NonIntra );
+DECLARE_NONINTRAMB( MPEG2NonIntraMB, MPEG2NonIntra );
+
+#undef DECLARE_NONINTRAMB
+#undef DECODE_LUMABLOCK
+#undef DECODE_CHROMABLOCK
+
+
+/*
+ * Motion vectors
+ */
+
+/****************************************************************************
+ * MotionDelta : Parse the next motion delta
+ ****************************************************************************/
+static inline int MotionDelta( vpar_thread_t * p_vpar, int i_f_code )
+{
+ int i_delta, i_sign, i_code;
+ lookup_t * p_tab;
+
+ if( ShowBits( &p_vpar->bit_stream, 1 ) )
+ {
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ return 0;
+ }
+
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 6 )) >= 0x3 )
+ {
+ p_tab = MV_4 + (i_code >> 2);
+ i_delta = (p_tab->i_value << i_f_code) + 1;
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+
+ i_sign = GetSignedBits( &p_vpar->bit_stream, 1 );
+ if( i_f_code )
+ {
+ i_delta += GetBits( &p_vpar->bit_stream, i_f_code );
+ }
+
+ return (i_delta ^ i_sign) - i_sign;
+
+ }
+ else
+ {
+ p_tab = MV_10 + ShowBits( &p_vpar->bit_stream, 10 );
+ i_delta = (p_tab->i_value << i_f_code) + 1;
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+
+ i_sign = GetSignedBits( &p_vpar->bit_stream, 1 );
+ if( i_f_code )
+ {
+ i_delta += GetBits( &p_vpar->bit_stream, i_f_code );
+ }
+
+ return (i_delta ^ i_sign) - i_sign;
+ }
+}
+
+/****************************************************************************
+ * BoundMotionVector : Bound a motion_vector :-)
+ ****************************************************************************/
+static inline int BoundMotionVector( int i_vector, int i_f_code )
+{
+ int i_limit;
+
+ i_limit = 16 << i_f_code;
+
+ if( i_vector >= i_limit )
+ {
+ return i_vector - 2 * i_limit;
+ }
+ else if( i_vector < -i_limit)
+ {
+ return i_vector + 2 * i_limit;
+ }
+ else
+ {
+ return i_vector;
+ }
+}
+
+/****************************************************************************
+ * GetDMV : Decode a differential motion vector (Dual Prime Arithmetic)
+ ****************************************************************************/
+static inline int GetDMV( vpar_thread_t * p_vpar )
+{
+ dmv_lookup_t * p_tab;
+
+ p_tab = DMV_2 + ShowBits( &p_vpar->bit_stream, 2 );
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ return( p_tab->i_value );
+}
+
+/****************************************************************************
+ * Motion* : Parse motion vectors
+ ****************************************************************************/
+#define MOTION_BLOCK( b_aver, i_x, i_y, i_dest, \
+ pp_src, i_src, i_str, i_hei, \
+ b_s_half ) \
+ do { \
+ motion_inner_t * p_m_inner = p_mb->p_motions + p_mb->i_nb_motions; \
+ p_m_inner->b_average = b_aver; \
+ p_m_inner->i_x_pred = i_x; \
+ p_m_inner->i_y_pred = i_y; \
+ p_m_inner->pp_source[0] = pp_src[0]; \
+ p_m_inner->pp_source[1] = pp_src[1]; \
+ p_m_inner->pp_source[2] = pp_src[2]; \
+ p_m_inner->i_dest_offset = i_dest; \
+ p_m_inner->i_src_offset = i_src; \
+ p_m_inner->i_stride = i_str; \
+ p_m_inner->i_height = i_hei; \
+ p_m_inner->b_second_half = b_s_half; \
+ p_mb->i_nb_motions++; \
+ } while( 0 );
+
+/* MPEG-1 predictions. */
+
+static void MotionMPEG1( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y;
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ i_motion_x = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[0][0] = i_motion_x;
+
+ i_motion_y = p_motion->ppi_pmv[0][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[0][1] = i_motion_y;
+
+ if( p_motion->pi_f_code[1] )
+ {
+ i_motion_x <<= 1;
+ i_motion_y <<= 1;
+ }
+
+ MOTION_BLOCK( b_average, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[0], i_offset, i_width, 16, 0 );
+}
+
+static void MotionMPEG1Reuse( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y;
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ i_motion_x = p_motion->ppi_pmv[0][0];
+ i_motion_y = p_motion->ppi_pmv[0][1];
+
+ if( p_motion->pi_f_code[1] )
+ {
+ i_motion_x <<= 1;
+ i_motion_y <<= 1;
+ }
+
+ MOTION_BLOCK( b_average, p_motion->ppi_pmv[0][0], p_motion->ppi_pmv[0][1],
+ i_offset, p_motion->pppi_ref[0], i_offset, i_width, 16, 0 );
+}
+
+/* MPEG-2 frame predictions. */
+
+static void MotionFrameFrame( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y;
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ i_motion_x = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = p_motion->ppi_pmv[0][0] = i_motion_x;
+
+ i_motion_y = p_motion->ppi_pmv[0][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] );
+ p_motion->ppi_pmv[1][1] = p_motion->ppi_pmv[0][1] = i_motion_y;
+
+ MOTION_BLOCK( b_average, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[0], i_offset, i_width, 16, 0 );
+}
+
+static void MotionFrameField( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y, i_field_select;
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ i_field_select = GetSignedBits( &p_vpar->bit_stream, 1 );
+
+ i_motion_x = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[0][0] = i_motion_x;
+
+ i_motion_y = (p_motion->ppi_pmv[0][1] >> 1)
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ /* According to ISO/IEC 13818-2 section 7.6.3.2, the vertical motion
+ * vector is restricted to a range that implies it doesn't need to
+ * be bound. */
+ /* i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] ); */
+ p_motion->ppi_pmv[0][1] = i_motion_y << 1;
+
+ MOTION_BLOCK( b_average, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[0], i_offset + (i_field_select & i_width),
+ i_width * 2, 8, 0 );
+
+ i_field_select = GetSignedBits( &p_vpar->bit_stream, 1 );
+
+ i_motion_x = p_motion->ppi_pmv[1][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = i_motion_x;
+
+ i_motion_y = (p_motion->ppi_pmv[1][1] >> 1)
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ /* i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] ); */
+ p_motion->ppi_pmv[1][1] = i_motion_y << 1;
+
+ MOTION_BLOCK( b_average, i_motion_x, i_motion_y, i_offset + i_width,
+ p_motion->pppi_ref[0], i_offset + (i_field_select & i_width),
+ i_width * 2, 8, 0 );
+}
+
+static void MotionFrameDMV( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y;
+ int i_dmv_x, i_dmv_y;
+ int i_tmp_x, i_tmp_y;
+
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+ int m;
+
+ i_motion_x = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = p_motion->ppi_pmv[0][0] = i_motion_x;
+
+ i_dmv_x = GetDMV( p_vpar );
+
+ i_motion_y = (p_motion->ppi_pmv[0][1] >> 1)
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ /* i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] ); */
+ p_motion->ppi_pmv[1][1] = p_motion->ppi_pmv[0][1] = i_motion_y << 1;
+
+ i_dmv_y = GetDMV( p_vpar );
+
+ /* First field. */
+ MOTION_BLOCK( 0, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[0], i_offset, i_width * 2, 8, 0 );
+ m = p_vpar->picture.b_top_field_first ? 1 : 3;
+ i_tmp_x = ((i_motion_x * m + (i_motion_x > 0)) >> 1) + i_dmv_x;
+ i_tmp_y = ((i_motion_y * m + (i_motion_y > 0)) >> 1) + i_dmv_y - 1;
+ MOTION_BLOCK( 1, i_tmp_x, i_tmp_y, i_offset, p_motion->pppi_ref[0],
+ i_offset + i_width, i_width * 2, 8, 0 );
+
+ /* Second field. */
+ MOTION_BLOCK( 0, i_motion_x, i_motion_y, i_offset + i_width,
+ p_motion->pppi_ref[0], i_offset + i_width, i_width * 2, 8, 0 );
+ m = p_vpar->picture.b_top_field_first ? 3 : 1;
+ i_tmp_x = ((i_motion_x * m + (i_motion_x > 0)) >> 1) + i_dmv_x;
+ i_tmp_y = ((i_motion_y * m + (i_motion_y > 0)) >> 1) + i_dmv_y + 1;
+ MOTION_BLOCK( 1, i_tmp_x, i_tmp_y, i_offset + i_width,
+ p_motion->pppi_ref[0], i_offset, i_width * 2, 8, 0 );
+}
+
+static void MotionFrameZero( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ MOTION_BLOCK( b_average, 0, 0, i_offset, p_motion->pppi_ref[0],
+ i_offset, i_width, 16, 0 );
+}
+
+static void MotionFrameReuse( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ MOTION_BLOCK( b_average, p_motion->ppi_pmv[0][0], p_motion->ppi_pmv[0][1],
+ i_offset, p_motion->pppi_ref[0], i_offset, i_width, 16, 0 );
+}
+
+/* MPEG-2 field predictions. */
+
+static void MotionFieldField( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y;
+ vlc_bool_t b_field_select;
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ b_field_select = GetBits( &p_vpar->bit_stream, 1 );
+
+ i_motion_x = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = p_motion->ppi_pmv[0][0] = i_motion_x;
+
+ i_motion_y = p_motion->ppi_pmv[0][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] );
+ p_motion->ppi_pmv[1][1] = p_motion->ppi_pmv[0][1] = i_motion_y;
+
+ MOTION_BLOCK( b_average, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[b_field_select], i_offset, i_width, 16, 0 );
+}
+
+static void MotionField16x8( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y;
+ vlc_bool_t b_field_select;
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+
+ /* First half. */
+ b_field_select = GetBits( &p_vpar->bit_stream, 1 );
+
+ i_motion_x = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[0][0] = i_motion_x;
+
+ i_motion_y = p_motion->ppi_pmv[0][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] );
+ p_motion->ppi_pmv[0][1] = i_motion_y;
+
+ MOTION_BLOCK( b_average, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[b_field_select], i_offset, i_width, 8, 0 );
+
+ /* Second half. */
+ b_field_select = GetBits( &p_vpar->bit_stream, 1 );
+
+ i_motion_x = p_motion->ppi_pmv[1][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = i_motion_x;
+
+ i_motion_y = p_motion->ppi_pmv[1][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] );
+ p_motion->ppi_pmv[1][1] = i_motion_y;
+
+ MOTION_BLOCK( b_average, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[b_field_select], i_offset, i_width, 8, 1 );
+}
+
+static void MotionFieldDMV( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_motion_x, i_motion_y;
+ int i_dmv_x, i_dmv_y;
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+ vlc_bool_t b_current_field = p_vpar->picture.b_current_field;
+
+ i_motion_x = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_motion_x = BoundMotionVector( i_motion_x, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = p_motion->ppi_pmv[0][0] = i_motion_x;
+
+ i_dmv_x = GetDMV( p_vpar );
+
+ i_motion_y = p_motion->ppi_pmv[0][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ i_motion_y = BoundMotionVector( i_motion_y, p_motion->pi_f_code[1] );
+ p_motion->ppi_pmv[1][1] = p_motion->ppi_pmv[0][1] = i_motion_y;
+
+ i_dmv_y = GetDMV( p_vpar );
+
+ MOTION_BLOCK( 0, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[b_current_field],
+ i_offset, i_width, 16, 0 );
+
+ i_motion_x = ((i_motion_x + (i_motion_x > 0)) >> 1) + i_dmv_x;
+ i_motion_y = ((i_motion_y + (i_motion_y > 0)) >> 1) + i_dmv_y
+ + 2 * b_current_field - 1;
+ MOTION_BLOCK( 1, i_motion_x, i_motion_y, i_offset,
+ p_motion->pppi_ref[!b_current_field],
+ i_offset, i_width, 16, 0 );
+}
+
+static void MotionFieldZero( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+ vlc_bool_t b_current_field = p_vpar->picture.b_current_field;
+
+ MOTION_BLOCK( b_average, 0, 0, i_offset, p_motion->pppi_ref[b_current_field],
+ i_offset, i_width, 16, 0 );
+}
+
+static void MotionFieldReuse( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ motion_t * p_motion,
+ vlc_bool_t b_average )
+{
+ int i_offset = p_vpar->mb.i_offset;
+ int i_width = p_vpar->picture.i_lum_stride;
+ vlc_bool_t b_current_field = p_vpar->picture.b_current_field;
+
+ MOTION_BLOCK( b_average, p_motion->ppi_pmv[0][0], p_motion->ppi_pmv[0][1],
+ i_offset, p_motion->pppi_ref[b_current_field],
+ i_offset, i_width, 16, 0 );
+}
+
+/* MPEG-2 concealment motion vectors. */
+
+static void MotionFrameConceal( vpar_thread_t * p_vpar,
+ macroblock_t * p_mv,
+ motion_t * p_motion )
+{
+ int i_tmp;
+
+ i_tmp = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_tmp = BoundMotionVector( i_tmp, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = p_motion->ppi_pmv[0][0] = i_tmp;
+
+ i_tmp = p_motion->ppi_pmv[0][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ i_tmp = BoundMotionVector( i_tmp, p_motion->pi_f_code[1] );
+ p_motion->ppi_pmv[1][1] = p_motion->ppi_pmv[0][1] = i_tmp;
+
+ /* Marker bit. */
+ RemoveBits( &p_vpar->bit_stream, 1 );
+}
+
+static void MotionFieldConceal( vpar_thread_t * p_vpar,
+ macroblock_t * p_mv,
+ motion_t * p_motion )
+{
+ int i_tmp;
+
+ /* field_select */
+ RemoveBits( &p_vpar->bit_stream, 1 );
+
+ i_tmp = p_motion->ppi_pmv[0][0]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[0] );
+ i_tmp = BoundMotionVector( i_tmp, p_motion->pi_f_code[0] );
+ p_motion->ppi_pmv[1][0] = p_motion->ppi_pmv[0][0] = i_tmp;
+
+ i_tmp = p_motion->ppi_pmv[0][1]
+ + MotionDelta( p_vpar, p_motion->pi_f_code[1] );
+ i_tmp = BoundMotionVector( i_tmp, p_motion->pi_f_code[1] );
+ p_motion->ppi_pmv[1][1] = p_motion->ppi_pmv[0][1] = i_tmp;
+
+ /* Marker bit. */
+ RemoveBits( &p_vpar->bit_stream, 1 );
+}
+
+
+/*
+ * Macroblock information structures
+ */
+
+/*****************************************************************************
+ * MacroblockAddressIncrement : Get the macroblock_address_increment field
+ *****************************************************************************/
+static inline int MacroblockAddressIncrement( vpar_thread_t * p_vpar )
+{
+ lookup_t * p_tab;
+ int i_code;
+ int i_mba = 0;
+
+ for( ; ; )
+ {
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 5 ) ) >= 0x2 )
+ {
+ p_tab = MBA_5 - 2 + i_code;
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ return( i_mba + p_tab->i_value );
+ }
+ else if( (i_code = ShowBits( &p_vpar->bit_stream, 11 )) >= 0x18 )
+ {
+ p_tab = MBA_11 - 24 + i_code;
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ return( i_mba + p_tab->i_value );
+ }
+ else switch( i_code )
+ {
+ case 8:
+ /* Macroblock escape */
+ i_mba += 33;
+ /* continue... */
+ case 15:
+ /* Macroblock stuffing (MPEG-1 ONLY) */
+ RemoveBits( &p_vpar->bit_stream, 11 );
+ break;
+
+ default:
+ /* End of slice, or error */
+ return 0;
+ }
+ }
+}
+
+/*****************************************************************************
+ * CodedPattern : coded_block_pattern
+ *****************************************************************************/
+static inline int CodedPattern( vpar_thread_t * p_vpar )
+{
+ lookup_t * p_tab;
+ int i_code;
+
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 7 )) >= 0x10 )
+ {
+ p_tab = CBP_7 - 16 + i_code;
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ }
+ else
+ {
+ p_tab = CBP_9 + ShowBits( &p_vpar->bit_stream, 9 );
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ }
+ if( p_vpar->sequence.i_chroma_format == CHROMA_420 )
+ {
+ return( p_tab->i_value << 6 );
+ }
+ if( p_vpar->sequence.i_chroma_format == CHROMA_422 )
+ {
+ return( (p_tab->i_value << 6)
+ | (GetBits( &p_vpar->bit_stream, 2 ) << 4) );
+ }
+ return( (p_tab->i_value << 6)
+ | GetBits( &p_vpar->bit_stream, 6 ) );
+}
+
+/*****************************************************************************
+ * MacroblockModes : Get the macroblock_modes structure
+ *****************************************************************************/
+static inline int MacroblockModes( vpar_thread_t * p_vpar, macroblock_t * p_mb,
+ int i_coding_type, int i_structure )
+{
+ int i_mb_modes;
+ lookup_t * p_tab;
+
+ switch( i_coding_type )
+ {
+ case I_CODING_TYPE:
+ p_tab = MB_I + ShowBits( &p_vpar->bit_stream, 1 );
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_mb_modes = p_tab->i_value;
+
+ if( (i_structure == FRAME_STRUCTURE) &&
+ (!p_vpar->picture.b_frame_pred_frame_dct) )
+ {
+ i_mb_modes |= GetBits( &p_vpar->bit_stream, 1 )
+ * DCT_TYPE_INTERLACED;
+ }
+ return( i_mb_modes );
+
+ case P_CODING_TYPE:
+ p_tab = MB_P + ShowBits( &p_vpar->bit_stream, 5 );
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_mb_modes = p_tab->i_value;
+
+ if( i_structure != FRAME_STRUCTURE )
+ {
+ if( i_mb_modes & MB_MOTION_FORWARD )
+ {
+ i_mb_modes |= GetBits( &p_vpar->bit_stream, 2 )
+ * MOTION_TYPE_BASE;
+ }
+ return( i_mb_modes );
+ }
+ else if( p_vpar->picture.b_frame_pred_frame_dct )
+ {
+ if( i_mb_modes & MB_MOTION_FORWARD )
+ {
+ i_mb_modes |= MC_FRAME;
+ }
+ return( i_mb_modes );
+ }
+ else
+ {
+ if( i_mb_modes & MB_MOTION_FORWARD )
+ {
+ i_mb_modes |= GetBits( &p_vpar->bit_stream, 2 )
+ * MOTION_TYPE_BASE;
+ }
+ if( i_mb_modes & (MB_INTRA | MB_PATTERN) )
+ {
+ i_mb_modes |= GetBits( &p_vpar->bit_stream, 1 )
+ * DCT_TYPE_INTERLACED;
+ }
+ return( i_mb_modes );
+ }
+
+ case B_CODING_TYPE:
+ p_tab = MB_B + ShowBits( &p_vpar->bit_stream, 6 );
+ RemoveBits( &p_vpar->bit_stream, p_tab->i_length );
+ i_mb_modes = p_tab->i_value;
+
+ if( i_structure != FRAME_STRUCTURE )
+ {
+ if( !( i_mb_modes & MB_INTRA ) )
+ {
+ i_mb_modes |= GetBits( &p_vpar->bit_stream, 2 )
+ * MOTION_TYPE_BASE;
+ }
+ return( i_mb_modes );
+ }
+ else if( p_vpar->picture.b_frame_pred_frame_dct )
+ {
+ i_mb_modes |= MC_FRAME;
+ return( i_mb_modes );
+ }
+ else
+ {
+ if( i_mb_modes & MB_INTRA )
+ {
+ goto mb_intra;
+ }
+ i_mb_modes |= GetBits( &p_vpar->bit_stream, 2 )
+ * MOTION_TYPE_BASE;
+ if( i_mb_modes & (MB_INTRA | MB_PATTERN) )
+ {
+mb_intra:
+ i_mb_modes |= GetBits( &p_vpar->bit_stream, 1 )
+ * DCT_TYPE_INTERLACED;
+ }
+ return( i_mb_modes );
+ }
+
+ case D_CODING_TYPE:
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ return( MB_INTRA );
+
+ default:
+ return( 0 );
+ }
+}
+
+
+/*
+ * Picture data parsing management
+ */
+
+/*****************************************************************************
+ * ParseSlice : Parse the next slice structure
+ *****************************************************************************/
+#define MOTION( pf_routine, i_direction ) \
+ if( (i_direction) & MB_MOTION_FORWARD ) \
+ { \
+ pf_routine( p_vpar, p_mb, &p_vpar->mb.f_motion, 0 ); \
+ if( (i_coding_type == B_CODING_TYPE) \
+ && ((i_direction) & MB_MOTION_BACKWARD) ) \
+ { \
+ pf_routine( p_vpar, p_mb, &p_vpar->mb.b_motion, 1 ); \
+ } \
+ } \
+ else if( (i_coding_type == B_CODING_TYPE) \
+ && ((i_direction) & MB_MOTION_BACKWARD) ) \
+ { \
+ pf_routine( p_vpar, p_mb, &p_vpar->mb.b_motion, 0 ); \
+ }
+
+#define CHECK_BOUNDARIES \
+ i_offset = p_vpar->mb.i_offset; \
+ if( i_offset == p_vpar->picture.i_field_width ) \
+ { \
+ if( i_coding_type != I_CODING_TYPE || \
+ p_vpar->picture.b_concealment_mv ) \
+ { \
+ p_f_motion->pppi_ref[0][0] += i_lum_vsize; \
+ p_f_motion->pppi_ref[0][1] += i_chrom_vsize; \
+ p_f_motion->pppi_ref[0][2] += i_chrom_vsize; \
+ } \
+ if( i_coding_type == B_CODING_TYPE ) \
+ { \
+ p_b_motion->pppi_ref[0][0] += i_lum_vsize; \
+ p_b_motion->pppi_ref[0][1] += i_chrom_vsize; \
+ p_b_motion->pppi_ref[0][2] += i_chrom_vsize; \
+ } \
+ p_dest[0] += i_lum_vsize; \
+ p_dest[1] += i_chrom_vsize; \
+ p_dest[2] += i_chrom_vsize; \
+ i_offset = 0; \
+ } \
+ p_vpar->mb.i_offset = i_offset;
+
+#define PARSEERROR \
+ if( p_vpar->picture.b_error ) \
+ { \
+ /* Go to the next slice. */ \
+ p_vpar->pool.pf_free_mb( &p_vpar->pool, p_mb ); \
+ return; \
+ }
+
+static inline void ParseSlice( vpar_thread_t * p_vpar,
+ u32 i_vert_code, vlc_bool_t b_mpeg2,
+ int i_coding_type, int i_structure )
+{
+ int i_lum_offset, i_chrom_offset, i_offset, i_lum_vsize, i_chrom_vsize;
+ picture_t * pp_forward_ref[2];
+ yuv_data_t * p_dest[3];
+
+ motion_t * p_f_motion = &p_vpar->mb.f_motion;
+ motion_t * p_b_motion = &p_vpar->mb.b_motion;
+
+ /* Parse header. */
+ LoadQuantizerScale( p_vpar );
+
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* intra_slice, slice_id */
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ /* extra_information_slice */
+ while( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ }
+ }
+
+ /* Calculate the position of the macroblock. */
+ i_lum_offset = (i_vert_code - 1) * p_vpar->picture.p_picture->Y_PITCH * 16;
+ i_chrom_offset = (i_vert_code - 1) * p_vpar->picture.p_picture->U_PITCH
+ * 8 * (2 - p_vpar->sequence.b_chroma_v_subsampled);
+ i_lum_vsize = 16 * p_vpar->picture.p_picture->Y_PITCH;
+ i_chrom_vsize = 8 * (2 - p_vpar->sequence.b_chroma_v_subsampled)
+ * p_vpar->picture.p_picture->U_PITCH;
+
+ /* Initialize motion context. */
+ pp_forward_ref[0] = p_vpar->sequence.p_forward;
+
+ if( i_structure != FRAME_STRUCTURE )
+ {
+ i_lum_offset <<= 1;
+ i_chrom_offset <<= 1;
+ i_lum_vsize <<= 1;
+ i_chrom_vsize <<= 1;
+
+ pp_forward_ref[1] = p_vpar->sequence.p_forward;
+
+ if( i_coding_type != B_CODING_TYPE && p_vpar->picture.b_second_field )
+ {
+ pp_forward_ref[!p_vpar->picture.b_current_field] =
+ p_vpar->picture.p_picture;
+ }
+ if( i_coding_type != I_CODING_TYPE || p_vpar->picture.b_concealment_mv )
+ {
+ int i_tmp;
+ p_f_motion->pppi_ref[1][0] = pp_forward_ref[1]->Y_PIXELS +
+ i_lum_offset + pp_forward_ref[1]->Y_PITCH;
+ p_f_motion->pppi_ref[1][1] = pp_forward_ref[1]->U_PIXELS +
+ (i_tmp = i_chrom_offset + pp_forward_ref[1]->U_PITCH);
+ p_f_motion->pppi_ref[1][2] = pp_forward_ref[1]->V_PIXELS +
+ i_tmp;
+ }
+ if( i_coding_type == B_CODING_TYPE )
+ {
+ int i_tmp;
+ p_b_motion->pppi_ref[1][0] = p_vpar->sequence.p_backward->Y_PIXELS
+ + i_lum_offset + p_vpar->sequence.p_backward->Y_PITCH;
+ p_b_motion->pppi_ref[1][1] = p_vpar->sequence.p_backward->U_PIXELS
+ + (i_tmp = i_chrom_offset + p_vpar->sequence.p_backward->U_PITCH);
+ p_b_motion->pppi_ref[1][2] = p_vpar->sequence.p_backward->V_PIXELS
+ + i_tmp;
+ }
+ }
+
+ if( i_coding_type != I_CODING_TYPE || p_vpar->picture.b_concealment_mv )
+ {
+ p_f_motion->pppi_ref[0][0] = pp_forward_ref[0]->Y_PIXELS +
+ i_lum_offset;
+ p_f_motion->pppi_ref[0][1] = pp_forward_ref[0]->U_PIXELS +
+ i_chrom_offset;
+ p_f_motion->pppi_ref[0][2] = pp_forward_ref[0]->V_PIXELS +
+ i_chrom_offset;
+ p_f_motion->pi_f_code[0] = p_vpar->picture.ppi_f_code[0][0];
+ p_f_motion->pi_f_code[1] = p_vpar->picture.ppi_f_code[0][1];
+ p_f_motion->ppi_pmv[0][0] = p_f_motion->ppi_pmv[0][1] = 0;
+ p_f_motion->ppi_pmv[1][0] = p_f_motion->ppi_pmv[1][1] = 0;
+ }
+
+ if( i_coding_type == B_CODING_TYPE )
+ {
+ p_b_motion->pppi_ref[0][0] = p_vpar->sequence.p_backward->Y_PIXELS +
+ i_lum_offset;
+ p_b_motion->pppi_ref[0][1] = p_vpar->sequence.p_backward->U_PIXELS +
+ i_chrom_offset;
+ p_b_motion->pppi_ref[0][2] = p_vpar->sequence.p_backward->V_PIXELS +
+ i_chrom_offset;
+ p_b_motion->pi_f_code[0] = p_vpar->picture.ppi_f_code[1][0];
+ p_b_motion->pi_f_code[1] = p_vpar->picture.ppi_f_code[1][1];
+ p_b_motion->ppi_pmv[0][0] = p_b_motion->ppi_pmv[0][1] = 0;
+ p_b_motion->ppi_pmv[1][0] = p_b_motion->ppi_pmv[1][1] = 0;
+ }
+
+ /* Initialize destination pointers. */
+ p_dest[0] = p_vpar->picture.p_picture->Y_PIXELS +
+ i_lum_offset;
+ p_dest[1] = p_vpar->picture.p_picture->U_PIXELS +
+ i_chrom_offset;
+ p_dest[2] = p_vpar->picture.p_picture->V_PIXELS +
+ i_chrom_offset;
+
+ if( i_structure == BOTTOM_FIELD )
+ {
+ p_dest[0] += p_vpar->picture.p_picture->Y_PITCH;
+ p_dest[1] += p_vpar->picture.p_picture->U_PITCH;
+ p_dest[2] += p_vpar->picture.p_picture->U_PITCH;
+ }
+
+ /* Reset intra DC coefficients predictors (ISO/IEC 13818-2 7.2.1). */
+ p_vpar->mb.pi_dc_dct_pred[0] = p_vpar->mb.pi_dc_dct_pred[1]
+ = p_vpar->mb.pi_dc_dct_pred[2]
+ = 1 << (7 + p_vpar->picture.i_intra_dc_precision);
+
+ p_vpar->mb.i_offset = MacroblockAddressIncrement( p_vpar ) << 4;
+
+ while( (int)(p_vpar->mb.i_offset - p_vpar->sequence.i_width) >= 0 )
+ {
+ /* Unusual construct at the start of some slices. Jump one line. */
+ p_vpar->mb.i_offset -= p_vpar->sequence.i_width;
+
+ p_dest[0] += i_lum_vsize;
+ p_dest[1] += i_chrom_vsize;
+ p_dest[2] += i_chrom_vsize;
+
+ p_f_motion->pppi_ref[0][0] += i_lum_vsize;
+ p_f_motion->pppi_ref[0][1] += i_chrom_vsize;
+ p_f_motion->pppi_ref[0][2] += i_chrom_vsize;
+
+ p_f_motion->pppi_ref[1][0] += i_lum_vsize;
+ p_f_motion->pppi_ref[1][1] += i_chrom_vsize;
+ p_f_motion->pppi_ref[1][2] += i_chrom_vsize;
+ }
+
+ for( ; ; )
+ {
+ /* Decode macroblocks. */
+ macroblock_t * p_mb;
+ int i_mb_modes;
+
+ /* Get a macroblock structure. */
+ p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
+ p_mb->i_nb_motions = 0;
+ p_mb->pp_dest[0] = p_dest[0];
+ p_mb->pp_dest[1] = p_dest[1];
+ p_mb->pp_dest[2] = p_dest[2];
+
+ /* Parse off macroblock_modes structure. */
+ p_mb->i_mb_modes = i_mb_modes =
+ MacroblockModes( p_vpar, p_mb, i_coding_type, i_structure );
+
+ if( i_mb_modes & MB_QUANT )
+ {
+ LoadQuantizerScale( p_vpar );
+ }
+
+ if( i_mb_modes & MB_INTRA )
+ {
+ if( p_vpar->picture.b_concealment_mv )
+ {
+ if( i_structure == FRAME_STRUCTURE )
+ {
+ MotionFrameConceal( p_vpar, p_mb, p_f_motion );
+ }
+ else
+ {
+ MotionFieldConceal( p_vpar, p_mb, p_f_motion );
+ }
+ }
+ else
+ {
+ /* Reset motion vectors predictors. */
+ p_f_motion->ppi_pmv[0][0] = p_f_motion->ppi_pmv[0][1] = 0;
+ p_f_motion->ppi_pmv[1][0] = p_f_motion->ppi_pmv[1][1] = 0;
+ p_b_motion->ppi_pmv[0][0] = p_b_motion->ppi_pmv[0][1] = 0;
+ p_b_motion->ppi_pmv[1][0] = p_b_motion->ppi_pmv[1][1] = 0;
+ }
+
+ /* Decode blocks */
+ if( b_mpeg2 )
+ {
+ if( p_vpar->picture.b_intra_vlc_format )
+ {
+ MPEG2IntraB15MB( p_vpar, p_mb );
+ }
+ else
+ {
+ MPEG2IntraB14MB( p_vpar, p_mb );
+ }
+ }
+ else
+ {
+ MPEG1IntraMB( p_vpar, p_mb );
+ }
+
+ if( i_coding_type == D_CODING_TYPE )
+ {
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ }
+ }
+ else
+ {
+ /* Non-intra block */
+ if( !b_mpeg2 )
+ {
+ if( (i_mb_modes & MOTION_TYPE_MASK) == MC_FRAME )
+ {
+ MOTION( MotionMPEG1, i_mb_modes );
+ }
+ else
+ {
+ /* Non-intra MB without forward mv in a P picture. */
+ p_f_motion->ppi_pmv[0][0] = p_f_motion->ppi_pmv[0][1] = 0;
+ p_f_motion->ppi_pmv[1][0] = p_f_motion->ppi_pmv[1][1] = 0;
+ MOTION( MotionFrameZero, MB_MOTION_FORWARD );
+ }
+ }
+ else if( i_structure == FRAME_STRUCTURE )
+ {
+ switch( i_mb_modes & MOTION_TYPE_MASK )
+ {
+ case MC_FRAME:
+ MOTION( MotionFrameFrame, i_mb_modes );
+ break;
+
+ case MC_FIELD:
+ MOTION( MotionFrameField, i_mb_modes );
+ break;
+
+ case MC_DMV:
+ MOTION( MotionFrameDMV, MB_MOTION_FORWARD );
+ break;
+
+ case 0:
+ /* Non-intra MB without forward mv in a P picture. */
+ p_f_motion->ppi_pmv[0][0] = p_f_motion->ppi_pmv[0][1] = 0;
+ p_f_motion->ppi_pmv[1][0] = p_f_motion->ppi_pmv[1][1] = 0;
+ MOTION( MotionFrameZero, MB_MOTION_FORWARD );
+ }
+ }
+ else
+ {
+ /* Field structure. */
+ switch( i_mb_modes & MOTION_TYPE_MASK )
+ {
+ case MC_FIELD:
+ MOTION( MotionFieldField, i_mb_modes );
+ break;
+
+ case MC_16X8:
+ MOTION( MotionField16x8, i_mb_modes );
+ break;
+
+ case MC_DMV:
+ MOTION( MotionFieldDMV, i_mb_modes );
+ break;
+
+ case 0:
+ /* Non-intra MB without forward mv in a P picture. */
+ p_f_motion->ppi_pmv[0][0] = p_f_motion->ppi_pmv[0][1] = 0;
+ p_f_motion->ppi_pmv[1][0] = p_f_motion->ppi_pmv[1][1] = 0;
+ MOTION( MotionFieldZero, MB_MOTION_FORWARD );
+ }
+ }
+
+ /* ISO/IEC 13818-2 6.3.17.4 : Coded Block Pattern */
+ if( i_mb_modes & MB_PATTERN )
+ {
+ p_mb->i_coded_block_pattern = CodedPattern( p_vpar );
+ if( b_mpeg2 )
+ {
+ MPEG2NonIntraMB( p_vpar, p_mb );
+ }
+ else
+ {
+ MPEG1NonIntraMB( p_vpar, p_mb );
+ }
+ }
+ else
+ {
+ p_mb->i_coded_block_pattern = 0;
+ }
+
+ /* Reset intra DC coefficients predictors. */
+ p_vpar->mb.pi_dc_dct_pred[0] = p_vpar->mb.pi_dc_dct_pred[1]
+ = p_vpar->mb.pi_dc_dct_pred[2]
+ = 1 << (7 + p_vpar->picture.i_intra_dc_precision);
+ }
+
+ /* End of macroblock. */
+ PARSEERROR;
+ p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
+
+ /* Prepare context for the next macroblock. */
+ p_vpar->mb.i_offset += 16;
+ CHECK_BOUNDARIES;
+
+ if( ShowBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* Macroblock Address Increment == 1 */
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ }
+ else
+ {
+ /* Check for skipped macroblock(s). */
+ int i_mba_inc;
+
+ i_mba_inc = MacroblockAddressIncrement( p_vpar );
+ if( !i_mba_inc )
+ {
+ /* End of slice. */
+ break;
+ }
+
+ /* Reset intra DC predictors. */
+ p_vpar->mb.pi_dc_dct_pred[0] = p_vpar->mb.pi_dc_dct_pred[1]
+ = p_vpar->mb.pi_dc_dct_pred[2]
+ = 1 << (7 + p_vpar->picture.i_intra_dc_precision);
+
+ if( i_coding_type == P_CODING_TYPE )
+ {
+ p_f_motion->ppi_pmv[0][0] = p_f_motion->ppi_pmv[0][1] = 0;
+ p_f_motion->ppi_pmv[1][0] = p_f_motion->ppi_pmv[1][1] = 0;
+
+ do {
+ p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
+ p_mb->i_mb_modes = 0;
+ p_mb->i_nb_motions = 0;
+ p_mb->i_coded_block_pattern = 0;
+ p_mb->pp_dest[0] = p_dest[0];
+ p_mb->pp_dest[1] = p_dest[1];
+ p_mb->pp_dest[2] = p_dest[2];
+
+ if( i_structure == FRAME_STRUCTURE )
+ {
+ MOTION( MotionFrameZero, MB_MOTION_FORWARD );
+ }
+ else
+ {
+ MOTION( MotionFieldZero, MB_MOTION_FORWARD );
+ }
+
+ p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
+ p_vpar->mb.i_offset += 16;
+ CHECK_BOUNDARIES;
+ } while( --i_mba_inc );
+ }
+ else
+ {
+ do {
+ p_mb = p_vpar->pool.pf_new_mb( &p_vpar->pool );
+ p_mb->i_mb_modes = 0;
+ p_mb->i_nb_motions = 0;
+ p_mb->i_coded_block_pattern = 0;
+ p_mb->pp_dest[0] = p_dest[0];
+ p_mb->pp_dest[1] = p_dest[1];
+ p_mb->pp_dest[2] = p_dest[2];
+
+ if( !b_mpeg2 )
+ {
+ MOTION( MotionMPEG1Reuse, i_mb_modes );
+ }
+ else if( i_structure == FRAME_STRUCTURE )
+ {
+ MOTION( MotionFrameReuse, i_mb_modes );
+ }
+ else
+ {
+ MOTION( MotionFieldReuse, i_mb_modes );
+ }
+
+ p_vpar->pool.pf_decode_mb( &p_vpar->pool, p_mb );
+ p_vpar->mb.i_offset += 16;
+ CHECK_BOUNDARIES;
+ } while( --i_mba_inc );
+ }
+ }
+ }
+
+ NextStartCode( &p_vpar->bit_stream );
+}
+
+/*****************************************************************************
+ * PictureData : Parse off all macroblocks (ISO/IEC 13818-2 6.2.3.7)
+ *****************************************************************************/
+static inline void vpar_PictureData( vpar_thread_t * p_vpar, vlc_bool_t b_mpeg2,
+ int i_coding_type, int i_structure )
+{
+ u32 i_dummy;
+
+ NextStartCode( &p_vpar->bit_stream );
+ while( !p_vpar->picture.b_error && !p_vpar->p_fifo->b_die )
+ {
+ if( ((i_dummy = ShowBits( &p_vpar->bit_stream, 32 ))
+ < SLICE_START_CODE_MIN) ||
+ (i_dummy > SLICE_START_CODE_MAX) )
+ {
+ break;
+ }
+ RemoveBits32( &p_vpar->bit_stream );
+
+ /* Decode slice data. */
+ ParseSlice( p_vpar, i_dummy & 255, b_mpeg2, i_coding_type,
+ i_structure );
+ }
+}
+
+#define DECLARE_PICD( FUNCNAME, B_MPEG2, I_CODING_TYPE, I_STRUCTURE ) \
+void FUNCNAME( vpar_thread_t * p_vpar ) \
+{ \
+ vpar_PictureData( p_vpar, B_MPEG2, I_CODING_TYPE, I_STRUCTURE ); \
+}
+
+DECLARE_PICD( vpar_PictureDataGENERIC, p_vpar->sequence.b_mpeg2,
+ p_vpar->picture.i_coding_type, p_vpar->picture.i_structure );
+#if (VPAR_OPTIM_LEVEL > 0)
+DECLARE_PICD( vpar_PictureData2IF, 1, I_CODING_TYPE, FRAME_STRUCTURE );
+DECLARE_PICD( vpar_PictureData2PF, 1, P_CODING_TYPE, FRAME_STRUCTURE );
+DECLARE_PICD( vpar_PictureData2BF, 1, B_CODING_TYPE, FRAME_STRUCTURE );
+#endif
+#if (VPAR_OPTIM_LEVEL > 1)
+DECLARE_PICD( vpar_PictureData2IT, 1, I_CODING_TYPE, TOP_FIELD );
+DECLARE_PICD( vpar_PictureData2PT, 1, P_CODING_TYPE, TOP_FIELD );
+DECLARE_PICD( vpar_PictureData2BT, 1, B_CODING_TYPE, TOP_FIELD );
+DECLARE_PICD( vpar_PictureData2IB, 1, I_CODING_TYPE, BOTTOM_FIELD );
+DECLARE_PICD( vpar_PictureData2PB, 1, P_CODING_TYPE, BOTTOM_FIELD );
+DECLARE_PICD( vpar_PictureData2BB, 1, B_CODING_TYPE, BOTTOM_FIELD );
+DECLARE_PICD( vpar_PictureData1I, 0, I_CODING_TYPE, FRAME_STRUCTURE );
+DECLARE_PICD( vpar_PictureData1P, 0, P_CODING_TYPE, FRAME_STRUCTURE );
+DECLARE_PICD( vpar_PictureData1B, 0, B_CODING_TYPE, FRAME_STRUCTURE );
+DECLARE_PICD( vpar_PictureData1D, 0, D_CODING_TYPE, FRAME_STRUCTURE );
+#endif
+
+#undef DECLARE_PICD
+
--- /dev/null
+/*****************************************************************************
+ * video_parser.h : Variable Length Codes
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: blocks.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Jean-Marc Dressler <polux@via.ecp.fr>
+ * Stéphane Borel <stef@via.ecp.fr>
+ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Michel Lespinasse <walken@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * lookup_t : entry type for lookup tables *
+ *****************************************************************************/
+typedef struct lookup_s
+{
+ u8 i_value;
+ u8 i_length;
+} lookup_t;
+
+typedef struct dmv_lookup_s
+{
+ s8 i_value;
+ u8 i_length;
+} dmv_lookup_t;
+
+/*****************************************************************************
+ * dct_lookup_t : special entry type for lookup tables about ac coefficients
+ *****************************************************************************/
+typedef struct dct_lookup_s
+{
+ u8 i_run;
+ u8 i_level;
+ u8 i_length;
+} dct_lookup_t;
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+
+/* Motion types */
+#define MOTION_TYPE_MASK (3*64)
+#define MOTION_TYPE_BASE 64
+#define MC_FIELD (1*64)
+#define MC_FRAME (2*64)
+#define MC_16X8 (2*64)
+#define MC_DMV (3*64)
+
+/* Macroblock Address Increment types */
+#define MB_ADDRINC_ESCAPE 8
+#define MB_ADDRINC_STUFFING 15
+
+/* Error constant for lookup tables */
+#define MB_ERROR (-1)
+
+/* Scan */
+#define SCAN_ZIGZAG 0
+#define SCAN_ALT 1
+
+/* Constant for block decoding */
+#define DCT_EOB 64
+#define DCT_ESCAPE 65
+
+
+/*****************************************************************************
+ * Lookup tables for macroblock modes
+ *****************************************************************************/
+
+#define INTRA MB_INTRA
+#define QUANT MB_QUANT
+
+static lookup_t MB_I [] = {
+ {INTRA|QUANT, 2}, {INTRA, 1}
+};
+
+#define MC MB_MOTION_FORWARD
+#define CODED MB_PATTERN
+
+static lookup_t MB_P [] = {
+ {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5},
+ {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3},
+ {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
+ {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}
+};
+
+#define FWD MB_MOTION_FORWARD
+#define BWD MB_MOTION_BACKWARD
+#define INTER MB_MOTION_FORWARD|MB_MOTION_BACKWARD
+
+static lookup_t MB_B [] = {
+ {0, 0}, {INTRA|QUANT, 6},
+ {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6},
+ {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5},
+ {INTRA, 5}, {INTRA, 5},
+ {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4},
+ {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4},
+ {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
+ {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
+ {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
+ {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}
+};
+
+#undef INTRA
+#undef QUANT
+#undef MC
+#undef CODED
+#undef FWD
+#undef BWD
+#undef INTER
+
+
+/*****************************************************************************
+ * Lookup tables for motion vectors
+ *****************************************************************************/
+
+static lookup_t MV_4 [] = {
+ { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
+};
+
+static lookup_t MV_10 [] = {
+ { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10},
+ { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10},
+ {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9},
+ { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7},
+ { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7},
+ { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}
+};
+
+
+static dmv_lookup_t DMV_2 [] = {
+ { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
+};
+
+
+/*****************************************************************************
+ * Lookup tables for Coded Block Patterns
+ *****************************************************************************/
+
+static lookup_t CBP_7 [] = {
+ {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7},
+ {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7},
+ {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6},
+ {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6},
+ {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5},
+ {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5},
+ {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5},
+ {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5},
+ {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5},
+ {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5},
+ {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5},
+ {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5},
+ {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5},
+ {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5},
+ {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5},
+ {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5},
+ {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
+ {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
+ {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
+ {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
+ {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
+ {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
+ {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
+ {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
+ {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
+ {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
+ {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
+ {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}
+};
+
+static lookup_t CBP_9 [] = {
+ {0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9},
+ {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9},
+ {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8},
+ {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8},
+ {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8},
+ {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8},
+ {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8},
+ {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8},
+ {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8},
+ {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8},
+ {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8},
+ {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8},
+ {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8},
+ {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8},
+ {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8},
+ {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8}
+};
+
+
+/*****************************************************************************
+ * Lookup tables for coefficients
+ *****************************************************************************/
+
+static lookup_t DC_lum_5 [] = {
+ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}
+};
+
+static lookup_t DC_chrom_5 [] = {
+ {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
+ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}
+};
+
+static lookup_t DC_long [] = {
+ {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
+ {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
+ {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6},
+ {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
+};
+
+
+static dct_lookup_t DCT_16 [] = {
+ {129, 0, 16}, {129, 0, 16}, {129, 0, 16}, {129, 0, 16},
+ {129, 0, 16}, {129, 0, 16}, {129, 0, 16}, {129, 0, 16},
+ {129, 0, 16}, {129, 0, 16}, {129, 0, 16}, {129, 0, 16},
+ {129, 0, 16}, {129, 0, 16}, {129, 0, 16}, {129, 0, 16},
+ { 2,18, 16}, { 2,17, 16}, { 2,16, 16}, { 2,15, 16},
+ { 7, 3, 16}, { 17, 2, 16}, { 16, 2, 16}, { 15, 2, 16},
+ { 14, 2, 16}, { 13, 2, 16}, { 12, 2, 16}, { 32, 1, 16},
+ { 31, 1, 16}, { 30, 1, 16}, { 29, 1, 16}, { 28, 1, 16}
+};
+
+static dct_lookup_t DCT_15 [] = {
+ { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15},
+ { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15},
+ { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15},
+ { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15},
+ { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14},
+ { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14},
+ { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14},
+ { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14},
+ { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14},
+ { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14},
+ { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14},
+ { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14}
+};
+
+static dct_lookup_t DCT_13 [] = {
+ { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13},
+ { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13},
+ { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13},
+ { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13},
+ { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12},
+ { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12},
+ { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12},
+ { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12},
+ { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12},
+ { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12},
+ { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12},
+ { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12}
+};
+
+static dct_lookup_t DCT_B14_10 [] = {
+ { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10},
+ { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10}
+};
+
+static dct_lookup_t DCT_B14_8 [] = {
+ { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
+ { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7},
+ { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7},
+ { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6},
+ { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6},
+ { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6},
+ { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
+ { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8},
+ { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8}
+};
+
+static dct_lookup_t DCT_B14AC_5 [] = {
+ { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
+ { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
+ {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}
+};
+
+static dct_lookup_t DCT_B14DC_5 [] = {
+ { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
+ { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}
+};
+
+static dct_lookup_t DCT_B15_10 [] = {
+ { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9},
+ { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9}
+};
+
+static dct_lookup_t DCT_B15_8 [] = {
+ { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
+ { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7},
+ { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7},
+ { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6},
+ { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6},
+ { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6},
+ { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
+ { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8},
+ { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8},
+ { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
+ { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
+ { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
+ { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
+ { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
+ { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
+ { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
+ { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
+ { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
+ { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7},
+ { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7},
+ { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8},
+ { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8}
+};
+
+
+/*****************************************************************************
+ * Lookup tables for Macroblock Address Increment
+ *****************************************************************************/
+
+static lookup_t MBA_5 [] = {
+ {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
+ {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}
+};
+
+static lookup_t MBA_11 [] = {
+ {32, 11}, {31, 11}, {30, 11}, {29, 11},
+ {28, 11}, {27, 11}, {26, 11}, {25, 11},
+ {24, 11}, {23, 11}, {22, 11}, {21, 11},
+ {20, 10}, {20, 10}, {19, 10}, {19, 10},
+ {18, 10}, {18, 10}, {17, 10}, {17, 10},
+ {16, 10}, {16, 10}, {15, 10}, {15, 10},
+ {14, 8}, {14, 8}, {14, 8}, {14, 8},
+ {14, 8}, {14, 8}, {14, 8}, {14, 8},
+ {13, 8}, {13, 8}, {13, 8}, {13, 8},
+ {13, 8}, {13, 8}, {13, 8}, {13, 8},
+ {12, 8}, {12, 8}, {12, 8}, {12, 8},
+ {12, 8}, {12, 8}, {12, 8}, {12, 8},
+ {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ {10, 8}, {10, 8}, {10, 8}, {10, 8},
+ {10, 8}, {10, 8}, {10, 8}, {10, 8},
+ { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
+ { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}
+};
--- /dev/null
+/*****************************************************************************
+ * video_decoder.c : video decoder thread
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: decoder.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Michel Lespinasse <walken@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* free() */
+#include <string.h> /* memcpy(), memset() */
+#include <errno.h> /* errno */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> /* getpid() */
+#endif
+
+#include "vdec_ext-plugins.h"
+
+#include "decoder.h"
+#include "pool.h"
+#include "parser.h"
+
+/*
+ * Local prototypes
+ */
+static void RunThread ( vdec_thread_t *p_vdec );
+
+/*****************************************************************************
+ * vdec_CreateThread: create a video decoder thread
+ *****************************************************************************
+ * This function creates a new video decoder thread, and returns a pointer
+ * to its description. On error, it returns NULL.
+ *****************************************************************************/
+vdec_thread_t * vdec_CreateThread( vdec_pool_t * p_pool )
+{
+ vdec_thread_t * p_vdec;
+
+ /* Allocate the memory needed to store the thread's structure */
+ p_vdec = vlc_object_create( p_pool->p_vpar->p_fifo, sizeof(vdec_thread_t) );
+ if( p_vdec == NULL )
+ {
+ msg_Err( p_pool->p_vpar->p_fifo, "out of memory" );
+ return NULL;
+ }
+
+ /*
+ * Initialize the parser properties
+ */
+ p_vdec->p_pool = p_pool;
+
+ /* Spawn the video decoder thread */
+ if( vlc_thread_create( p_vdec, "video decoder", RunThread, 0 ) )
+ {
+ msg_Err( p_vdec, "cannot spawn video decoder thread" );
+ vlc_object_destroy( p_vdec );
+ return( NULL );
+ }
+
+ return p_vdec;
+}
+
+/*****************************************************************************
+ * vdec_DestroyThread: destroy a video decoder thread
+ *****************************************************************************/
+void vdec_DestroyThread( vdec_thread_t *p_vdec )
+{
+ /* Ask thread to kill itself */
+ p_vdec->b_die = 1;
+
+ /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
+ vlc_mutex_lock( &p_vdec->p_pool->lock );
+ vlc_cond_broadcast( &p_vdec->p_pool->wait_undecoded );
+ vlc_mutex_unlock( &p_vdec->p_pool->lock );
+
+ /* Waiting for the decoder thread to exit */
+ vlc_thread_join( p_vdec );
+
+ /* Free the object */
+ vlc_object_destroy( p_vdec );
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * vdec_InitThread: initialize video decoder thread
+ *****************************************************************************
+ * This function is called from RunThread and performs the second step of the
+ * initialization.
+ *****************************************************************************/
+void vdec_InitThread( vdec_thread_t * p_vdec )
+{
+ /* Re-nice ourself - otherwise we would steal CPU time from the video
+ * output, which would make a poor display. */
+#if defined( HAVE_NICE )
+ if( nice(VDEC_NICE) == -1 )
+#elif defined( WIN32 )
+ if( !SetThreadPriority( GetCurrentThread(),
+ THREAD_PRIORITY_BELOW_NORMAL ) )
+#else
+ if( 0 )
+#endif
+ {
+ msg_Warn( p_vdec, "couldn't nice() (%s)", strerror(errno) );
+ }
+
+ p_vdec->p_idct_data = NULL;
+
+ p_vdec->p_pool->pf_idct_init( &p_vdec->p_idct_data );
+
+ /* Mark thread as running and return */
+}
+
+/*****************************************************************************
+ * vdec_EndThread: thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+void vdec_EndThread( vdec_thread_t * p_vdec )
+{
+ if( p_vdec->p_idct_data != NULL )
+ {
+ free( p_vdec->p_idct_data );
+ }
+}
+
+/*****************************************************************************
+ * MotionBlock: does one component of the motion compensation
+ *****************************************************************************/
+static inline void MotionBlock( vdec_pool_t * p_pool, vlc_bool_t b_average,
+ int i_x_pred, int i_y_pred,
+ yuv_data_t * pp_dest[3], int i_dest_offset,
+ yuv_data_t * pp_src[3], int i_src_offset,
+ int i_stride, int i_height,
+ vlc_bool_t b_second_half, int i_chroma_format )
+{
+ int i_xy_half;
+ yuv_data_t * p_src1;
+ yuv_data_t * p_src2;
+
+ i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
+
+ p_src1 = pp_src[0] + i_src_offset
+ + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride
+ + b_second_half * (i_stride << 3);
+
+ p_pool->ppppf_motion[b_average][0][i_xy_half]
+ ( pp_dest[0] + i_dest_offset + b_second_half * (i_stride << 3),
+ p_src1, i_stride, i_height );
+
+ if( i_chroma_format != CHROMA_NONE )
+ {
+ /* Expanded at compile-time. */
+ if( i_chroma_format != CHROMA_444 )
+ {
+ i_x_pred /= 2;
+ i_stride >>= 1;
+ i_src_offset >>= 1;
+ i_dest_offset >>= 1;
+ }
+ if( i_chroma_format == CHROMA_420 )
+ {
+ i_y_pred /= 2;
+ i_height >>= 1;
+ }
+
+ i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
+
+ i_src_offset += b_second_half * (i_stride << 3);
+ i_dest_offset += b_second_half * (i_stride << 3);
+
+ p_src1 = pp_src[1] + i_src_offset
+ + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
+ p_src2 = pp_src[2] + i_src_offset
+ + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
+
+ p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
+ [i_xy_half]
+ ( pp_dest[1] + i_dest_offset, p_src1, i_stride, i_height );
+ p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
+ [i_xy_half]
+ ( pp_dest[2] + i_dest_offset, p_src2, i_stride, i_height );
+ }
+}
+
+
+/*****************************************************************************
+ * DecodeMacroblock: decode a macroblock
+ *****************************************************************************/
+#define DECODE_INTRA_BLOCK( i_b, p_dest ) \
+ p_idct = &p_mb->p_idcts[i_b]; \
+ p_idct->pf_idct( p_idct->pi_block, p_dest, \
+ i_b < 4 ? i_lum_dct_stride : i_chrom_dct_stride, \
+ p_vdec->p_idct_data, p_idct->i_sparse_pos );
+
+#define DECODE_NONINTRA_BLOCK( i_b, p_dest ) \
+ if( p_mb->i_coded_block_pattern & (1 << (11 - (i_b))) ) \
+ { \
+ DECODE_INTRA_BLOCK( i_b, p_dest ); \
+ }
+
+#define DECLARE_DECODEMB( PSZ_NAME, I_CHROMA ) \
+void PSZ_NAME ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) \
+{ \
+ int i, i_lum_dct_offset, i_lum_dct_stride; \
+ int i_chrom_dct_offset, i_chrom_dct_stride; \
+ idct_inner_t * p_idct; \
+ vdec_pool_t * p_pool = p_vdec->p_pool; \
+ vpar_thread_t * p_vpar = p_pool->p_vpar; \
+ \
+ if( p_mb->i_mb_modes & DCT_TYPE_INTERLACED ) \
+ { \
+ i_lum_dct_offset = p_vpar->picture.i_lum_stride; \
+ i_lum_dct_stride = p_vpar->picture.i_lum_stride * 2; \
+ } \
+ else \
+ { \
+ i_lum_dct_offset = p_vpar->picture.i_lum_stride * 8; \
+ i_lum_dct_stride = p_vpar->picture.i_lum_stride; \
+ } \
+ \
+ i_chrom_dct_offset = p_vpar->picture.i_chrom_stride * 8; \
+ i_chrom_dct_stride = p_vpar->picture.i_chrom_stride; \
+ \
+ if( !(p_mb->i_mb_modes & MB_INTRA) ) \
+ { \
+ /* \
+ * Motion Compensation (ISO/IEC 13818-2 section 7.6) \
+ */ \
+ for( i = 0; i < p_mb->i_nb_motions; i++ ) \
+ { \
+ motion_inner_t * p_motion = &p_mb->p_motions[i]; \
+ MotionBlock( p_pool, p_motion->b_average, \
+ p_motion->i_x_pred, p_motion->i_y_pred, \
+ p_mb->pp_dest, p_motion->i_dest_offset, \
+ p_motion->pp_source, p_motion->i_src_offset, \
+ p_motion->i_stride, p_motion->i_height, \
+ p_motion->b_second_half, I_CHROMA ); \
+ } \
+ \
+ /* \
+ * Inverse DCT (ISO/IEC 13818-2 section Annex A) and \
+ * adding prediction and coefficient data (ISO/IEC \
+ * 13818-2 section 7.6.8) \
+ */ \
+ DECODE_NONINTRA_BLOCK( 0, p_mb->p_y_data ); \
+ DECODE_NONINTRA_BLOCK( 1, p_mb->p_y_data + 8 ); \
+ DECODE_NONINTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ); \
+ DECODE_NONINTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ); \
+ if( I_CHROMA != CHROMA_NONE ) \
+ { \
+ DECODE_NONINTRA_BLOCK( 4, p_mb->p_u_data ); \
+ DECODE_NONINTRA_BLOCK( 5, p_mb->p_v_data ); \
+ if( I_CHROMA != CHROMA_420 ) \
+ { \
+ DECODE_NONINTRA_BLOCK( 6, p_mb->p_u_data \
+ + i_chrom_dct_offset ); \
+ DECODE_NONINTRA_BLOCK( 7, p_mb->p_v_data \
+ + i_chrom_dct_offset ); \
+ if( I_CHROMA == CHROMA_444 ) \
+ { \
+ DECODE_NONINTRA_BLOCK( 8, p_mb->p_u_data + 8 ); \
+ DECODE_NONINTRA_BLOCK( 9, p_mb->p_v_data + 8 ); \
+ DECODE_NONINTRA_BLOCK( 10, p_mb->p_u_data + 8 \
+ + i_chrom_dct_offset ); \
+ DECODE_NONINTRA_BLOCK( 11, p_mb->p_v_data + 8 \
+ + i_chrom_dct_offset ); \
+ } \
+ } \
+ } \
+ } \
+ else \
+ { \
+ /* Intra macroblock */ \
+ DECODE_INTRA_BLOCK( 0, p_mb->p_y_data ); \
+ DECODE_INTRA_BLOCK( 1, p_mb->p_y_data + 8 ); \
+ DECODE_INTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ); \
+ DECODE_INTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ); \
+ if( I_CHROMA != CHROMA_NONE ) \
+ { \
+ DECODE_INTRA_BLOCK( 4, p_mb->p_u_data ); \
+ DECODE_INTRA_BLOCK( 5, p_mb->p_v_data ); \
+ if( I_CHROMA != CHROMA_420 ) \
+ { \
+ DECODE_INTRA_BLOCK( 6, p_mb->p_u_data \
+ + i_chrom_dct_offset ); \
+ DECODE_INTRA_BLOCK( 7, p_mb->p_v_data \
+ + i_chrom_dct_offset ); \
+ if( I_CHROMA == CHROMA_444 ) \
+ { \
+ DECODE_INTRA_BLOCK( 8, p_mb->p_u_data + 8 ); \
+ DECODE_INTRA_BLOCK( 9, p_mb->p_v_data + 8 ); \
+ DECODE_INTRA_BLOCK( 10, p_mb->p_u_data + 8 \
+ + i_chrom_dct_offset ); \
+ DECODE_INTRA_BLOCK( 11, p_mb->p_v_data + 8 \
+ + i_chrom_dct_offset ); \
+ } \
+ } \
+ } \
+ } \
+}
+
+DECLARE_DECODEMB( vdec_DecodeMacroblockBW, CHROMA_NONE );
+DECLARE_DECODEMB( vdec_DecodeMacroblock420, CHROMA_420 );
+DECLARE_DECODEMB( vdec_DecodeMacroblock422, CHROMA_422 );
+DECLARE_DECODEMB( vdec_DecodeMacroblock444, CHROMA_444 );
+
+#undef DECLARE_DECODEMB
+
+/*****************************************************************************
+ * RunThread: video decoder thread
+ *****************************************************************************
+ * Video decoder thread. This function does only return when the thread is
+ * terminated.
+ *****************************************************************************/
+static void RunThread( vdec_thread_t *p_vdec )
+{
+ vdec_InitThread( p_vdec );
+
+ /*
+ * Main loop
+ */
+ while( !p_vdec->b_die )
+ {
+ macroblock_t * p_mb;
+
+ if( (p_mb = vpar_GetMacroblock( p_vdec->p_pool, &p_vdec->b_die )) != NULL )
+ {
+ p_vdec->p_pool->pf_vdec_decode( p_vdec, p_mb );
+
+ /* Decoding is finished, release the macroblock and free
+ * unneeded memory. */
+ p_vdec->p_pool->pf_free_mb( p_vdec->p_pool, p_mb );
+ }
+ }
+
+ /* End of thread */
+ vdec_EndThread( p_vdec );
+}
+
--- /dev/null
+/*****************************************************************************
+ * video_decoder.h : video decoder thread
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: decoder.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * vdec_thread_t: video decoder thread descriptor
+ *****************************************************************************/
+typedef struct vdec_thread_s
+{
+ VLC_COMMON_MEMBERS
+
+ /* IDCT iformations */
+ void * p_idct_data;
+
+ /* Input properties */
+ struct vdec_pool_s * p_pool;
+
+} vdec_thread_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vdec_InitThread ( vdec_thread_t * );
+void vdec_EndThread ( vdec_thread_t * );
+void vdec_DecodeMacroblockBW ( vdec_thread_t *, macroblock_t * );
+void vdec_DecodeMacroblock420( vdec_thread_t *, macroblock_t * );
+void vdec_DecodeMacroblock422( vdec_thread_t *, macroblock_t * );
+void vdec_DecodeMacroblock444( vdec_thread_t *, macroblock_t * );
+vdec_thread_t * vdec_CreateThread ( struct vdec_pool_s * );
+void vdec_DestroyThread ( vdec_thread_t * );
+
--- /dev/null
+/*****************************************************************************
+ * vpar_headers.c : headers parsing
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: headers.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* free() */
+#include <string.h> /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#include "vdec_ext-plugins.h"
+
+#include "decoder.h"
+#include "pool.h"
+#include "parser.h"
+
+/*
+ * Local prototypes
+ */
+static inline void NextStartCode( bit_stream_t * );
+static void SequenceHeader( vpar_thread_t * p_vpar );
+static void GroupHeader( vpar_thread_t * p_vpar );
+static void PictureHeader( vpar_thread_t * p_vpar );
+static void ExtensionAndUserData( vpar_thread_t * p_vpar );
+static void QuantMatrixExtension( vpar_thread_t * p_vpar );
+static void SequenceScalableExtension( vpar_thread_t * p_vpar );
+static void SequenceDisplayExtension( vpar_thread_t * p_vpar );
+static void PictureDisplayExtension( vpar_thread_t * p_vpar );
+static void PictureSpatialScalableExtension( vpar_thread_t * p_vpar );
+static void PictureTemporalScalableExtension( vpar_thread_t * p_vpar );
+static void CopyrightExtension( vpar_thread_t * p_vpar );
+
+/*
+ * Standard variables
+ */
+
+/*****************************************************************************
+ * pi_default_intra_quant : default quantization matrix
+ *****************************************************************************/
+u8 pi_default_intra_quant[] ATTR_ALIGN(16) =
+{
+ 8, 16, 19, 22, 26, 27, 29, 34,
+ 16, 16, 22, 24, 27, 29, 34, 37,
+ 19, 22, 26, 27, 29, 34, 34, 38,
+ 22, 22, 26, 27, 29, 34, 37, 40,
+ 22, 26, 27, 29, 32, 35, 40, 48,
+ 26, 27, 29, 32, 35, 40, 48, 58,
+ 26, 27, 29, 34, 38, 46, 56, 69,
+ 27, 29, 35, 38, 46, 56, 69, 83
+};
+
+/*****************************************************************************
+ * pi_default_nonintra_quant : default quantization matrix
+ *****************************************************************************/
+u8 pi_default_nonintra_quant[] ATTR_ALIGN(16) =
+{
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16
+};
+
+/*****************************************************************************
+ * pi_scan : zig-zag and alternate scan patterns
+ *****************************************************************************/
+u8 pi_scan[2][64] ATTR_ALIGN(16) =
+{
+ { /* Zig-Zag pattern */
+ 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,
+ 12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,
+ 35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,
+ 58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63
+ },
+ { /* Alternate scan pattern */
+ 0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49,
+ 41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43,
+ 51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45,
+ 53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63
+ }
+};
+
+/*
+ * Local inline functions.
+ */
+
+/*****************************************************************************
+ * ReferenceUpdate : Update the reference pointers when we have a new picture
+ *****************************************************************************/
+static void inline ReferenceUpdate( vpar_thread_t * p_vpar,
+ int i_coding_type, picture_t * p_newref )
+{
+ if( i_coding_type != B_CODING_TYPE )
+ {
+ if( p_vpar->sequence.p_forward != NULL )
+ {
+ vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
+ }
+ if( p_vpar->sequence.p_backward != NULL )
+ {
+ vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
+ vpar_SynchroDate( p_vpar ) );
+ }
+ p_vpar->sequence.p_forward = p_vpar->sequence.p_backward;
+ p_vpar->sequence.p_backward = p_newref;
+ if( p_newref != NULL )
+ {
+ vout_LinkPicture( p_vpar->p_vout, p_newref );
+ }
+ }
+ else if( p_newref != NULL )
+ {
+ /* Put date immediately. */
+ vout_DatePicture( p_vpar->p_vout, p_newref, vpar_SynchroDate(p_vpar) );
+ }
+}
+
+/*****************************************************************************
+ * ReferenceReplace : Replace the last reference pointer when we destroy
+ * a picture
+ *****************************************************************************/
+static void inline ReferenceReplace( vpar_thread_t * p_vpar,
+ int i_coding_type, picture_t * p_newref )
+{
+ if( i_coding_type != B_CODING_TYPE )
+ {
+ if( p_vpar->sequence.p_backward != NULL )
+ {
+ vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
+ }
+ p_vpar->sequence.p_backward = p_newref;
+ if( p_newref != NULL )
+ {
+ vout_LinkPicture( p_vpar->p_vout, p_newref );
+ }
+ }
+}
+
+/*****************************************************************************
+ * LoadMatrix : Load a quantization matrix
+ *****************************************************************************/
+static inline void LoadMatrix( vpar_thread_t * p_vpar,
+ quant_matrix_t * p_matrix )
+{
+ int i_dummy;
+
+ if( !p_matrix->b_allocated )
+ {
+ /* Allocate a piece of memory to load the matrix. */
+ if( (p_matrix->pi_matrix = (u8 *)malloc( 64*sizeof(u8) )) == NULL )
+ {
+ msg_Err( p_vpar->p_fifo, "out of memory" );
+ p_vpar->p_fifo->b_error = 1;
+ return;
+ }
+ p_matrix->b_allocated = 1;
+ }
+
+ for( i_dummy = 0; i_dummy < 64; i_dummy++ )
+ {
+ p_matrix->pi_matrix[p_vpar->ppi_scan[0][i_dummy]]
+ = GetBits( &p_vpar->bit_stream, 8 );
+ }
+}
+
+/*****************************************************************************
+ * LinkMatrix : Link a quantization matrix to another
+ *****************************************************************************/
+static inline void LinkMatrix( quant_matrix_t * p_matrix, u8 * pi_array )
+{
+ if( p_matrix->b_allocated )
+ {
+ /* Deallocate the piece of memory. */
+ free( p_matrix->pi_matrix );
+ p_matrix->b_allocated = 0;
+ }
+
+ p_matrix->pi_matrix = pi_array;
+}
+
+/*****************************************************************************
+ * ChromaToFourCC: Return a FourCC value used by the video output.
+ *****************************************************************************/
+static inline u64 ChromaToFourCC( int i_chroma )
+{
+ switch( i_chroma )
+ {
+ case CHROMA_420:
+ return VLC_FOURCC('I','4','2','0');
+
+ case CHROMA_422:
+ return VLC_FOURCC('I','4','2','2');
+
+ case CHROMA_444:
+ return VLC_FOURCC('I','4','4','4');
+
+ default:
+ /* This can't happen */
+ return 0xdeadbeef;
+ }
+}
+
+/*
+ * Exported functions.
+ */
+
+/*****************************************************************************
+ * vpar_NextSequenceHeader : Find the next sequence header
+ *****************************************************************************/
+int vpar_NextSequenceHeader( vpar_thread_t * p_vpar )
+{
+ while( !p_vpar->p_fifo->b_die )
+ {
+ NextStartCode( &p_vpar->bit_stream );
+ if( ShowBits( &p_vpar->bit_stream, 32 ) == SEQUENCE_HEADER_CODE )
+ {
+ return 0;
+ }
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ }
+ return 1;
+}
+
+/*****************************************************************************
+ * vpar_ParseHeader : Parse the next header
+ *****************************************************************************/
+int vpar_ParseHeader( vpar_thread_t * p_vpar )
+{
+ NextStartCode( &p_vpar->bit_stream );
+ switch( GetBits32( &p_vpar->bit_stream ) )
+ {
+ case SEQUENCE_HEADER_CODE:
+ p_vpar->c_sequences++;
+ SequenceHeader( p_vpar );
+ return 0;
+
+ case GROUP_START_CODE:
+ GroupHeader( p_vpar );
+ return 0;
+
+ case PICTURE_START_CODE:
+ PictureHeader( p_vpar );
+ return 0;
+
+ case SEQUENCE_END_CODE:
+ msg_Dbg( p_vpar->p_fifo, "sequence end code received" );
+ if( p_vpar->sequence.p_backward != NULL )
+ {
+ p_vpar->sequence.p_backward->b_force = 1;
+ }
+ ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
+ return 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Following functions are local
+ */
+
+/*****************************************************************************
+ * SequenceHeader : Parse the next sequence header
+ *****************************************************************************/
+static void SequenceHeader( vpar_thread_t * p_vpar )
+{
+#define RESERVED -1
+ static int i_frame_rate_table[16] =
+ {
+ 0,
+ 23 * 1000,
+ 24 * 1001,
+ 25 * 1001,
+ 30 * 1000,
+ 30 * 1001,
+ 50 * 1001,
+ 60 * 1000,
+ 60 * 1001,
+ RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED
+ };
+#undef RESERVED
+
+ int i_height_save, i_width_save, i_aspect;
+
+ i_height_save = p_vpar->sequence.i_height;
+ i_width_save = p_vpar->sequence.i_width;
+
+ p_vpar->sequence.i_width = GetBits( &p_vpar->bit_stream, 12 );
+ p_vpar->sequence.i_height = GetBits( &p_vpar->bit_stream, 12 );
+ i_aspect = GetBits( &p_vpar->bit_stream, 4 );
+ p_vpar->sequence.i_frame_rate =
+ i_frame_rate_table[ GetBits( &p_vpar->bit_stream, 4 ) ];
+
+ /* We don't need bit_rate_value, marker_bit, vbv_buffer_size,
+ * constrained_parameters_flag */
+ RemoveBits( &p_vpar->bit_stream, 30 );
+
+ /*
+ * Quantization matrices
+ */
+ if( GetBits( &p_vpar->bit_stream, 1 ) ) /* load_intra_quantizer_matrix */
+ {
+ LoadMatrix( p_vpar, &p_vpar->sequence.intra_quant );
+ }
+ else
+ {
+ /* Use default matrix. */
+ LinkMatrix( &p_vpar->sequence.intra_quant,
+ p_vpar->pi_default_intra_quant );
+ }
+
+ if( GetBits(&p_vpar->bit_stream, 1) ) /* load_non_intra_quantizer_matrix */
+ {
+ LoadMatrix( p_vpar, &p_vpar->sequence.nonintra_quant );
+ }
+ else
+ {
+ /* Use default matrix. */
+ LinkMatrix( &p_vpar->sequence.nonintra_quant,
+ p_vpar->pi_default_nonintra_quant );
+ }
+
+ /* Unless later overwritten by a matrix extension, we have the same
+ * matrices for luminance and chrominance. */
+ LinkMatrix( &p_vpar->sequence.chroma_intra_quant,
+ p_vpar->sequence.intra_quant.pi_matrix );
+ LinkMatrix( &p_vpar->sequence.chroma_nonintra_quant,
+ p_vpar->sequence.nonintra_quant.pi_matrix );
+
+ /*
+ * Sequence Extension
+ */
+ NextStartCode( &p_vpar->bit_stream );
+ if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
+ {
+ int i_dummy;
+
+ /* Turn the MPEG2 flag on */
+ p_vpar->sequence.b_mpeg2 = 1;
+
+ /* Parse sequence_extension */
+ RemoveBits32( &p_vpar->bit_stream );
+ /* extension_start_code_identifier, profile_and_level_indication */
+ RemoveBits( &p_vpar->bit_stream, 12 );
+ p_vpar->sequence.b_progressive = GetBits( &p_vpar->bit_stream, 1 );
+ p_vpar->sequence.i_chroma_format = GetBits( &p_vpar->bit_stream, 2 );
+ p_vpar->sequence.i_width |= GetBits( &p_vpar->bit_stream, 2 ) << 12;
+ p_vpar->sequence.i_height |= GetBits( &p_vpar->bit_stream, 2 ) << 12;
+ /* bit_rate_extension, marker_bit, vbv_buffer_size_extension,
+ * low_delay */
+ RemoveBits( &p_vpar->bit_stream, 22 );
+ /* frame_rate_extension_n */
+ i_dummy = GetBits( &p_vpar->bit_stream, 2 );
+ /* frame_rate_extension_d */
+ p_vpar->sequence.i_frame_rate *= (i_dummy + 1)
+ / (GetBits( &p_vpar->bit_stream, 5 ) + 1);
+ }
+ else
+ {
+ /* It's an MPEG-1 stream. Put adequate parameters. */
+ int i_xyratio;
+ static int pi_mpeg1ratio[15] = {
+ 10000, 10000, 6735, 7031, 7615, 8055, 8437, 8935,
+ 9157, 9815, 10255, 10695, 10950, 11575, 12015
+ };
+
+ if( i_aspect > 1 )
+ {
+ i_xyratio = p_vpar->sequence.i_height *
+ pi_mpeg1ratio[i_aspect] / p_vpar->sequence.i_width;
+ if( 7450 < i_xyratio && i_xyratio < 7550 )
+ {
+ i_aspect = 2;
+ }
+ else if( 5575 < i_xyratio && i_xyratio < 5675 )
+ {
+ i_aspect = 3;
+ }
+ else if( 4475 < i_xyratio && i_xyratio < 4575 )
+ {
+ i_aspect = 4;
+ }
+ }
+
+ p_vpar->sequence.b_mpeg2 = 0;
+ p_vpar->sequence.b_progressive = 1;
+ p_vpar->sequence.i_chroma_format = CHROMA_420;
+ }
+
+ /* check whether the input gives a particular aspect ratio */
+ if( p_vpar->p_fifo->p_demux_data
+ && ( *(int*)(p_vpar->p_fifo->p_demux_data) & 0x7 ) )
+ {
+ i_aspect = *(int*)(p_vpar->p_fifo->p_demux_data);
+ }
+
+ /* Store calculated aspect ratio */
+ switch( i_aspect )
+ {
+ case AR_3_4_PICTURE:
+ p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
+ break;
+
+ case AR_16_9_PICTURE:
+ p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR * 16 / 9;
+ break;
+
+ case AR_221_1_PICTURE:
+ p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR * 221 / 100;
+ break;
+
+ case AR_SQUARE_PICTURE:
+ default:
+ p_vpar->sequence.i_aspect = VOUT_ASPECT_FACTOR
+ * p_vpar->sequence.i_width / p_vpar->sequence.i_height;
+ break;
+ }
+
+ /* Update sizes */
+ p_vpar->sequence.i_mb_width = (p_vpar->sequence.i_width + 15) / 16;
+ p_vpar->sequence.i_mb_height = (p_vpar->sequence.b_progressive) ?
+ (p_vpar->sequence.i_height + 15) / 16 :
+ 2 * ((p_vpar->sequence.i_height + 31) / 32);
+ p_vpar->sequence.i_mb_size = p_vpar->sequence.i_mb_width
+ * p_vpar->sequence.i_mb_height;
+ p_vpar->sequence.i_width = (p_vpar->sequence.i_mb_width * 16);
+ p_vpar->sequence.i_height = (p_vpar->sequence.i_mb_height * 16);
+ p_vpar->sequence.i_size = p_vpar->sequence.i_width
+ * p_vpar->sequence.i_height;
+ switch( p_vpar->sequence.i_chroma_format )
+ {
+ case CHROMA_420:
+ p_vpar->sequence.i_chroma_nb_blocks = 2;
+ p_vpar->sequence.b_chroma_h_subsampled = 1;
+ p_vpar->sequence.b_chroma_v_subsampled = 1;
+ break;
+ case CHROMA_422:
+ p_vpar->sequence.i_chroma_nb_blocks = 4;
+ p_vpar->sequence.b_chroma_h_subsampled = 1;
+ p_vpar->sequence.b_chroma_v_subsampled = 0;
+ break;
+ case CHROMA_444:
+ p_vpar->sequence.i_chroma_nb_blocks = 6;
+ p_vpar->sequence.b_chroma_h_subsampled = 0;
+ p_vpar->sequence.b_chroma_v_subsampled = 0;
+ break;
+ }
+
+#if 0
+ if( p_vpar->sequence.i_width != i_width_save
+ || p_vpar->sequence.i_height != i_height_save )
+ {
+ /* FIXME: Warn the video output */
+ }
+#endif
+
+ /* Extension and User data */
+ ExtensionAndUserData( p_vpar );
+
+ /* Spawn a video output if there is none. First we look for our children,
+ * then we look for any other vout that might be available. */
+ p_vpar->p_vout = vlc_object_find( p_vpar->p_fifo, VLC_OBJECT_VOUT,
+ FIND_CHILD );
+ if( p_vpar->p_vout == NULL )
+ {
+ p_vpar->p_vout = vlc_object_find( p_vpar->p_fifo, VLC_OBJECT_VOUT,
+ FIND_ANYWHERE );
+ }
+
+ if( p_vpar->p_vout )
+ {
+ if( p_vpar->p_vout->render.i_width != p_vpar->sequence.i_width
+ || p_vpar->p_vout->render.i_height != p_vpar->sequence.i_height
+ || p_vpar->p_vout->render.i_chroma != ChromaToFourCC( p_vpar->sequence.i_chroma_format )
+ || p_vpar->p_vout->render.i_aspect != p_vpar->sequence.i_aspect )
+ {
+ /* We are not interested in this format, close this vout */
+ vlc_object_detach_all( p_vpar->p_vout );
+ vlc_object_release( p_vpar->p_vout );
+ vout_DestroyThread( p_vpar->p_vout );
+ p_vpar->p_vout = NULL;
+ }
+ else
+ {
+ /* This video output is cool! Hijack it. */
+ vlc_object_detach_all( p_vpar->p_vout );
+ vlc_object_attach( p_vpar->p_vout, p_vpar->p_fifo );
+ vlc_object_release( p_vpar->p_vout );
+ }
+ }
+
+ if( p_vpar->p_fifo->b_die || p_vpar->p_fifo->b_error )
+ {
+ return;
+ }
+
+ if( p_vpar->p_vout == NULL )
+ {
+ msg_Dbg( p_vpar->p_fifo, "no vout present, spawning one" );
+
+ p_vpar->p_vout = vout_CreateThread( p_vpar->p_fifo,
+ p_vpar->sequence.i_width,
+ p_vpar->sequence.i_height,
+ ChromaToFourCC( p_vpar->sequence.i_chroma_format ),
+ p_vpar->sequence.i_aspect );
+
+ /* Everything failed */
+ if( p_vpar->p_vout == NULL )
+ {
+ msg_Err( p_vpar->p_fifo, "cannot open vout, aborting" );
+ p_vpar->p_fifo->b_error = 1;
+ return;
+ }
+ }
+}
+
+/*****************************************************************************
+ * GroupHeader : Parse the next group of pictures header
+ *****************************************************************************/
+static void GroupHeader( vpar_thread_t * p_vpar )
+{
+ /* Nothing to do, we don't care. */
+ RemoveBits( &p_vpar->bit_stream, 27 );
+ ExtensionAndUserData( p_vpar );
+}
+
+/*****************************************************************************
+ * PictureHeader : Parse the next picture header
+ *****************************************************************************/
+static void PictureHeader( vpar_thread_t * p_vpar )
+{
+ int i_structure, i_previous_coding_type;
+ vlc_bool_t b_parsable = 0;
+
+ /* Retrieve the PTS. */
+ CurrentPTS( &p_vpar->bit_stream, &p_vpar->sequence.next_pts,
+ &p_vpar->sequence.next_dts );
+
+ /* Recover in case of stream discontinuity. */
+ if( p_vpar->sequence.b_expect_discontinuity )
+ {
+ ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
+ ReferenceUpdate( p_vpar, I_CODING_TYPE, NULL );
+ if( p_vpar->picture.p_picture != NULL )
+ {
+ vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
+ p_vpar->picture.p_picture = NULL;
+ }
+ p_vpar->picture.i_current_structure = 0;
+ p_vpar->sequence.b_expect_discontinuity = 0;
+ }
+
+ /* Parse the picture header. */
+ RemoveBits( &p_vpar->bit_stream, 10 ); /* temporal_reference */
+ i_previous_coding_type = p_vpar->picture.i_coding_type;
+ p_vpar->picture.i_coding_type = GetBits( &p_vpar->bit_stream, 3 );
+ RemoveBits( &p_vpar->bit_stream, 16 ); /* vbv_delay */
+
+ if( p_vpar->picture.i_coding_type == P_CODING_TYPE
+ || p_vpar->picture.i_coding_type == B_CODING_TYPE )
+ {
+ p_vpar->picture.ppi_f_code[0][1] = GetBits( &p_vpar->bit_stream, 1 );
+ p_vpar->picture.ppi_f_code[0][0] = GetBits( &p_vpar->bit_stream, 3 )
+ - 1;
+ }
+ if( p_vpar->picture.i_coding_type == B_CODING_TYPE )
+ {
+ p_vpar->picture.ppi_f_code[1][1] = GetBits( &p_vpar->bit_stream, 1 );
+ p_vpar->picture.ppi_f_code[1][0] = GetBits( &p_vpar->bit_stream, 3 )
+ - 1;
+ }
+
+ /* extra_information_picture */
+ while( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ }
+
+ /*
+ * Picture Coding Extension
+ */
+ NextStartCode( &p_vpar->bit_stream );
+ if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
+ {
+ /* Parse picture_coding_extension */
+ RemoveBits32( &p_vpar->bit_stream );
+ /* extension_start_code_identifier */
+ RemoveBits( &p_vpar->bit_stream, 4 );
+
+ /* Pre-substract 1 for later use in MotionDelta(). */
+ p_vpar->picture.ppi_f_code[0][0] = GetBits( &p_vpar->bit_stream, 4 ) -1;
+ p_vpar->picture.ppi_f_code[0][1] = GetBits( &p_vpar->bit_stream, 4 ) -1;
+ p_vpar->picture.ppi_f_code[1][0] = GetBits( &p_vpar->bit_stream, 4 ) -1;
+ p_vpar->picture.ppi_f_code[1][1] = GetBits( &p_vpar->bit_stream, 4 ) -1;
+ p_vpar->picture.i_intra_dc_precision = GetBits( &p_vpar->bit_stream, 2 );
+ i_structure = GetBits( &p_vpar->bit_stream, 2 );
+ p_vpar->picture.b_top_field_first = GetBits( &p_vpar->bit_stream, 1 );
+ p_vpar->picture.b_frame_pred_frame_dct
+ = GetBits( &p_vpar->bit_stream, 1 );
+ p_vpar->picture.b_concealment_mv = GetBits( &p_vpar->bit_stream, 1 );
+ p_vpar->picture.b_q_scale_type = GetBits( &p_vpar->bit_stream, 1 );
+ p_vpar->picture.b_intra_vlc_format = GetBits( &p_vpar->bit_stream, 1 );
+ /* Alternate scan */
+ p_vpar->picture.pi_scan =
+ p_vpar->ppi_scan[ GetBits( &p_vpar->bit_stream, 1 ) ];
+ p_vpar->picture.b_repeat_first_field = GetBits( &p_vpar->bit_stream, 1 );
+ /* chroma_420_type (obsolete) */
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ p_vpar->picture.b_progressive = GetBits( &p_vpar->bit_stream, 1 );
+
+ /* composite_display_flag */
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* v_axis, field_sequence, sub_carrier, burst_amplitude,
+ * sub_carrier_phase */
+ RemoveBits( &p_vpar->bit_stream, 20 );
+ }
+ }
+ else
+ {
+ /* MPEG-1 compatibility flags */
+ p_vpar->picture.i_intra_dc_precision = 0; /* 8 bits */
+ i_structure = FRAME_STRUCTURE;
+ p_vpar->picture.b_top_field_first = 0;
+ p_vpar->picture.b_frame_pred_frame_dct = 1;
+ p_vpar->picture.b_concealment_mv = 0;
+ p_vpar->picture.b_q_scale_type = 0;
+ p_vpar->picture.b_intra_vlc_format = 0;
+ p_vpar->picture.pi_scan = p_vpar->ppi_scan[0];
+ p_vpar->picture.b_repeat_first_field = 0;
+ p_vpar->picture.b_progressive = 1;
+ }
+
+ /* Extension and User data. */
+ ExtensionAndUserData( p_vpar );
+
+ p_vpar->pc_pictures[p_vpar->picture.i_coding_type]++;
+
+ if( p_vpar->picture.i_current_structure )
+ {
+ if ( (i_structure == FRAME_STRUCTURE ||
+ i_structure == p_vpar->picture.i_current_structure) )
+ {
+ /* We don't have the second field of the buffered frame. */
+ if( p_vpar->picture.p_picture != NULL )
+ {
+ ReferenceReplace( p_vpar,
+ p_vpar->picture.i_coding_type,
+ NULL );
+ vout_DestroyPicture( p_vpar->p_vout,
+ p_vpar->picture.p_picture );
+ p_vpar->picture.p_picture = NULL;
+ }
+
+ p_vpar->picture.i_current_structure = 0;
+
+ msg_Warn( p_vpar->p_fifo, "odd number of field pictures" );
+ }
+ else
+ {
+ /* Second field of a frame. We will decode it if, and only if we
+ * have decoded the first field. */
+ if( p_vpar->picture.p_picture == NULL )
+ {
+ if( (p_vpar->picture.i_coding_type == I_CODING_TYPE
+ && p_vpar->sequence.p_backward == NULL) )
+ {
+ /* Exceptionnally, parse the picture if it is I. We need
+ * this in case of an odd number of field pictures, if the
+ * previous picture is not intra, we desperately need a
+ * new reference picture. OK, this is kind of kludgy. */
+ p_vpar->picture.i_current_structure = 0;
+ }
+ else
+ {
+ b_parsable = 0;
+ }
+ }
+ else
+ {
+ /* We suppose we have the reference pictures, since we already
+ * decoded the first field and the second field will not need
+ * any extra reference picture. There is a special case of
+ * P field being the second field of an I field, but ISO/IEC
+ * 13818-2 section 7.6.3.5 specifies that this P field will
+ * not need any reference picture besides the I field. So far
+ * so good. */
+ b_parsable = 1;
+
+ if( p_vpar->picture.i_coding_type == P_CODING_TYPE &&
+ i_previous_coding_type == I_CODING_TYPE &&
+ p_vpar->sequence.p_forward == NULL )
+ {
+ /* This is the special case of section 7.6.3.5. Create
+ * a fake reference picture (which will not be used)
+ * but will prevent us from segfaulting in the slice
+ * parsing. */
+ static picture_t fake_picture;
+ fake_picture.i_planes = 0; /* We will use it later */
+ p_vpar->sequence.p_forward = &fake_picture;
+ }
+ }
+ }
+ }
+
+ if( !p_vpar->picture.i_current_structure )
+ {
+ /* First field of a frame, or new frame picture. */
+ int i_repeat_field;
+
+ /* Do we have the reference pictures ? */
+ b_parsable = !(((p_vpar->picture.i_coding_type == P_CODING_TYPE ||
+ p_vpar->picture.b_concealment_mv) &&
+ (p_vpar->sequence.p_backward == NULL)) ||
+ /* p_backward will become p_forward later */
+ ((p_vpar->picture.i_coding_type == B_CODING_TYPE) &&
+ (p_vpar->sequence.p_forward == NULL ||
+ p_vpar->sequence.p_backward == NULL)));
+
+ /* Compute the number of times the frame will be emitted by the
+ * decoder (number of half-periods). */
+ if( p_vpar->sequence.b_progressive )
+ {
+ i_repeat_field = (1 + p_vpar->picture.b_repeat_first_field
+ + p_vpar->picture.b_top_field_first) * 2;
+ }
+ else
+ {
+ if( p_vpar->picture.b_progressive )
+ {
+ i_repeat_field = 2 + p_vpar->picture.b_repeat_first_field;
+ }
+ else
+ {
+ i_repeat_field = 2;
+ }
+ }
+
+ /* Warn synchro we have a new picture (updates pictures index). */
+ vpar_SynchroNewPicture( p_vpar, p_vpar->picture.i_coding_type,
+ i_repeat_field );
+
+ if( b_parsable )
+ {
+ /* Does synchro say we have enough time to decode it ? */
+ b_parsable = vpar_SynchroChoose( p_vpar,
+ p_vpar->picture.i_coding_type, i_structure );
+ }
+ }
+
+ if( !b_parsable )
+ {
+ /* Update the reference pointers. */
+ ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, NULL );
+
+ /* Update context. */
+ if( i_structure != FRAME_STRUCTURE )
+ {
+ if( (p_vpar->picture.i_current_structure | i_structure)
+ == FRAME_STRUCTURE )
+ {
+ /* The frame is complete. */
+ p_vpar->picture.i_current_structure = 0;
+
+ vpar_SynchroTrash( p_vpar, p_vpar->picture.i_coding_type, i_structure );
+ }
+ else
+ {
+ p_vpar->picture.i_current_structure = i_structure;
+ }
+ }
+ else
+ {
+ /* Warn Synchro we have trashed a picture. */
+ vpar_SynchroTrash( p_vpar, p_vpar->picture.i_coding_type, i_structure );
+ }
+ p_vpar->picture.p_picture = NULL;
+
+ return;
+ }
+
+ /* OK, now we are sure we will decode the picture. */
+ p_vpar->pc_decoded_pictures[p_vpar->picture.i_coding_type]++;
+
+#define P_picture p_vpar->picture.p_picture
+ p_vpar->picture.b_error = 0;
+ p_vpar->picture.b_frame_structure = (i_structure == FRAME_STRUCTURE);
+
+ if( !p_vpar->picture.i_current_structure )
+ {
+ /* This is a new frame. Get a structure from the video_output. */
+ while( ( P_picture = vout_CreatePicture( p_vpar->p_vout,
+ p_vpar->picture.b_progressive,
+ p_vpar->picture.b_top_field_first,
+ p_vpar->picture.b_repeat_first_field ) )
+ == NULL )
+ {
+ if( p_vpar->p_fifo->b_die || p_vpar->p_fifo->b_error )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ /* Initialize values. */
+ vpar_SynchroDecode( p_vpar, p_vpar->picture.i_coding_type, i_structure );
+ P_picture->i_matrix_coefficients = p_vpar->sequence.i_matrix_coefficients;
+
+ /* Update the reference pointers. */
+ ReferenceUpdate( p_vpar, p_vpar->picture.i_coding_type, P_picture );
+ }
+
+ /* Initialize picture data for decoding. */
+ p_vpar->picture.i_current_structure |= i_structure;
+ p_vpar->picture.i_structure = i_structure;
+ p_vpar->picture.b_second_field =
+ (i_structure != p_vpar->picture.i_current_structure);
+ p_vpar->picture.b_current_field =
+ (i_structure == BOTTOM_FIELD );
+ p_vpar->picture.i_lum_stride = p_vpar->picture.p_picture->Y_PITCH
+ << ( 1 - p_vpar->picture.b_frame_structure );
+ p_vpar->picture.i_chrom_stride = p_vpar->picture.p_picture->U_PITCH
+ << ( 1 - p_vpar->picture.b_frame_structure );
+ /* We suppose the pitch is the same for U and V planes. */
+ p_vpar->picture.i_field_width = p_vpar->sequence.i_width
+ << ( 1 - p_vpar->picture.b_frame_structure );
+
+ if( !p_vpar->p_fifo->p_stream_ctrl->b_grayscale )
+ {
+ switch( p_vpar->sequence.i_chroma_format )
+ {
+ case CHROMA_422:
+ p_vpar->pool.pf_vdec_decode = vdec_DecodeMacroblock422;
+ break;
+ case CHROMA_444:
+ p_vpar->pool.pf_vdec_decode = vdec_DecodeMacroblock444;
+ break;
+ case CHROMA_420:
+ default:
+ p_vpar->pool.pf_vdec_decode = vdec_DecodeMacroblock420;
+ break;
+ }
+ }
+ else
+ {
+ p_vpar->pool.pf_vdec_decode = vdec_DecodeMacroblockBW;
+ }
+
+
+ if( p_vpar->sequence.b_mpeg2 )
+ {
+ static f_picture_data_t ppf_picture_data[4][4] =
+ {
+ {
+ NULL, NULL, NULL, NULL
+ },
+ {
+ /* TOP_FIELD */
+#if (VPAR_OPTIM_LEVEL > 1)
+ NULL, vpar_PictureData2IT, vpar_PictureData2PT,
+ vpar_PictureData2BT
+#else
+ NULL, vpar_PictureDataGENERIC, vpar_PictureDataGENERIC,
+ vpar_PictureDataGENERIC
+#endif
+ },
+ {
+ /* BOTTOM_FIELD */
+#if (VPAR_OPTIM_LEVEL > 1)
+ NULL, vpar_PictureData2IB, vpar_PictureData2PB,
+ vpar_PictureData2BB
+#else
+ NULL, vpar_PictureDataGENERIC, vpar_PictureDataGENERIC,
+ vpar_PictureDataGENERIC
+#endif
+ },
+ {
+ /* FRAME_PICTURE */
+#if (VPAR_OPTIM_LEVEL > 0)
+ NULL, vpar_PictureData2IF, vpar_PictureData2PF,
+ vpar_PictureData2BF
+#else
+ NULL, vpar_PictureDataGENERIC, vpar_PictureDataGENERIC,
+ vpar_PictureDataGENERIC
+#endif
+ }
+ };
+
+ ppf_picture_data[p_vpar->picture.i_structure]
+ [p_vpar->picture.i_coding_type]( p_vpar );
+ }
+ else
+ {
+#if (VPAR_OPTIM_LEVEL > 1)
+ static f_picture_data_t pf_picture_data[5] =
+ { NULL, vpar_PictureData1I, vpar_PictureData1P, vpar_PictureData1B,
+ vpar_PictureData1D };
+
+ pf_picture_data[p_vpar->picture.i_coding_type]( p_vpar );
+#else
+ vpar_PictureDataGENERIC( p_vpar );
+#endif
+ }
+
+ /* Wait for all the macroblocks to be decoded. */
+ p_vpar->pool.pf_wait_pool( &p_vpar->pool );
+
+ /* Re-spawn decoder threads if the user changed settings. */
+ vpar_SpawnPool( p_vpar );
+
+ if( p_vpar->p_fifo->b_die || p_vpar->p_fifo->b_error )
+ {
+ return;
+ }
+
+ if( p_vpar->sequence.p_forward != NULL &&
+ p_vpar->sequence.p_forward->i_planes == 0 )
+ {
+ /* This can only happen with the fake picture created for section
+ * 7.6.3.5. Clean up our mess. */
+ p_vpar->sequence.p_forward = NULL;
+ }
+
+ if( p_vpar->picture.b_error )
+ {
+ /* Trash picture. */
+ p_vpar->pc_malformed_pictures[p_vpar->picture.i_coding_type]++;
+
+ vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
+ p_vpar->picture.i_structure, 1 );
+ vout_DestroyPicture( p_vpar->p_vout, P_picture );
+
+ ReferenceReplace( p_vpar, p_vpar->picture.i_coding_type, NULL );
+
+ /* Prepare context for the next picture. */
+ P_picture = NULL;
+ if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE )
+ p_vpar->picture.i_current_structure = 0;
+ }
+ else if( p_vpar->picture.i_current_structure == FRAME_STRUCTURE )
+ {
+ /* Frame completely parsed. */
+ vpar_SynchroEnd( p_vpar, p_vpar->picture.i_coding_type,
+ p_vpar->picture.i_structure, 0 );
+ vout_DisplayPicture( p_vpar->p_vout, P_picture );
+
+ /* Prepare context for the next picture. */
+ P_picture = NULL;
+ p_vpar->picture.i_current_structure = 0;
+ }
+#undef P_picture
+}
+
+/*****************************************************************************
+ * ExtensionAndUserData : Parse the extension_and_user_data structure
+ *****************************************************************************/
+static void ExtensionAndUserData( vpar_thread_t * p_vpar )
+{
+ while( !p_vpar->p_fifo->b_die )
+ {
+ NextStartCode( &p_vpar->bit_stream );
+ switch( ShowBits( &p_vpar->bit_stream, 32 ) )
+ {
+ case EXTENSION_START_CODE:
+ RemoveBits32( &p_vpar->bit_stream );
+ switch( GetBits( &p_vpar->bit_stream, 4 ) )
+ {
+ case SEQUENCE_DISPLAY_EXTENSION_ID:
+ SequenceDisplayExtension( p_vpar );
+ break;
+ case QUANT_MATRIX_EXTENSION_ID:
+ QuantMatrixExtension( p_vpar );
+ break;
+ case SEQUENCE_SCALABLE_EXTENSION_ID:
+ SequenceScalableExtension( p_vpar );
+ break;
+ case PICTURE_DISPLAY_EXTENSION_ID:
+ PictureDisplayExtension( p_vpar );
+ break;
+ case PICTURE_SPATIAL_SCALABLE_EXTENSION_ID:
+ PictureSpatialScalableExtension( p_vpar );
+ break;
+ case PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID:
+ PictureTemporalScalableExtension( p_vpar );
+ break;
+ case COPYRIGHT_EXTENSION_ID:
+ CopyrightExtension( p_vpar );
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case USER_DATA_START_CODE:
+ RemoveBits32( &p_vpar->bit_stream );
+ /* Wait for the next start code */
+ break;
+
+ default:
+ return;
+ }
+ }
+}
+
+
+/*****************************************************************************
+ * SequenceDisplayExtension : Parse the sequence_display_extension structure *
+ *****************************************************************************/
+
+static void SequenceDisplayExtension( vpar_thread_t * p_vpar )
+{
+ /* We don't care sequence_display_extension. */
+ /* video_format */
+ RemoveBits( &p_vpar->bit_stream, 3 );
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* Two bytes for color_desciption */
+ RemoveBits( &p_vpar->bit_stream, 16 );
+ p_vpar->sequence.i_matrix_coefficients = GetBits( &p_vpar->bit_stream, 8 );
+ }
+ /* display_horizontal and vertical_size and a marker_bit */
+ RemoveBits( &p_vpar->bit_stream, 29 );
+}
+
+
+/*****************************************************************************
+ * QuantMatrixExtension : Load quantization matrices for luminance *
+ * and chrominance *
+ *****************************************************************************/
+
+static void QuantMatrixExtension( vpar_thread_t * p_vpar )
+{
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* Load intra_quantiser_matrix for luminance. */
+ LoadMatrix( p_vpar, &p_vpar->sequence.intra_quant );
+ }
+ else
+ {
+ /* Use the default matrix. */
+ LinkMatrix( &p_vpar->sequence.intra_quant,
+ p_vpar->pi_default_intra_quant );
+ }
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* Load non_intra_quantiser_matrix for luminance. */
+ LoadMatrix( p_vpar, &p_vpar->sequence.nonintra_quant );
+ }
+ else
+ {
+ /* Use the default matrix. */
+ LinkMatrix( &p_vpar->sequence.nonintra_quant,
+ p_vpar->pi_default_nonintra_quant );
+ }
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* Load intra_quantiser_matrix for chrominance. */
+ LoadMatrix( p_vpar, &p_vpar->sequence.chroma_intra_quant );
+ }
+ else
+ {
+ /* Link the chrominance intra matrix to the luminance one. */
+ LinkMatrix( &p_vpar->sequence.chroma_intra_quant,
+ p_vpar->sequence.intra_quant.pi_matrix );
+ }
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* Load non_intra_quantiser_matrix for chrominance. */
+ LoadMatrix( p_vpar, &p_vpar->sequence.chroma_nonintra_quant );
+ }
+ else
+ {
+ /* Link the chrominance nonintra matrix to the luminance one. */
+ LinkMatrix( &p_vpar->sequence.chroma_nonintra_quant,
+ p_vpar->sequence.nonintra_quant.pi_matrix );
+ }
+}
+
+
+/*****************************************************************************
+ * SequenceScalableExtension : Parse the sequence_scalable_extension *
+ * structure to handle scalable coding *
+ *****************************************************************************/
+
+static void SequenceScalableExtension( vpar_thread_t * p_vpar )
+{
+ /* We don't care about anything scalable except the scalable mode. */
+ switch( p_vpar->sequence.i_scalable_mode = GetBits( &p_vpar->bit_stream, 2 ) )
+ /* The length of the structure depends on the value of the scalable_mode */
+ {
+ case 1:
+ RemoveBits32( &p_vpar->bit_stream );
+ RemoveBits( &p_vpar->bit_stream, 21 );
+ break;
+ case 2:
+ RemoveBits( &p_vpar->bit_stream, 12 );
+ break;
+ default:
+ RemoveBits( &p_vpar->bit_stream, 4 );
+ }
+
+}
+/*****************************************************************************
+ * PictureDisplayExtension : Parse the picture_display_extension structure *
+ *****************************************************************************/
+
+static void PictureDisplayExtension( vpar_thread_t * p_vpar )
+{
+ /* Number of frame center offset */
+ int i_nb, i_dummy;
+ /* I am not sure it works but it should
+ (fewer tests than shown in §6.3.12) */
+ i_nb = p_vpar->sequence.b_progressive ? p_vpar->sequence.b_progressive +
+ p_vpar->picture.b_repeat_first_field +
+ p_vpar->picture.b_top_field_first
+ : ( p_vpar->picture.b_frame_structure + 1 ) +
+ p_vpar->picture.b_repeat_first_field;
+ for( i_dummy = 0; i_dummy < i_nb; i_dummy++ )
+ {
+ RemoveBits( &p_vpar->bit_stream, 17 );
+ RemoveBits( &p_vpar->bit_stream, 17 );
+ }
+}
+
+
+/*****************************************************************************
+ * PictureSpatialScalableExtension *
+ *****************************************************************************/
+
+static void PictureSpatialScalableExtension( vpar_thread_t * p_vpar )
+{
+ /* That's scalable, so we trash it */
+ RemoveBits32( &p_vpar->bit_stream );
+ RemoveBits( &p_vpar->bit_stream, 16 );
+}
+
+
+/*****************************************************************************
+ * PictureTemporalScalableExtension *
+ *****************************************************************************/
+
+static void PictureTemporalScalableExtension( vpar_thread_t * p_vpar )
+{
+ /* Scalable again, trashed again */
+ RemoveBits( &p_vpar->bit_stream, 23 );
+}
+
+
+/*****************************************************************************
+ * CopyrightExtension : Keeps some legal informations *
+ *****************************************************************************/
+
+static void CopyrightExtension( vpar_thread_t * p_vpar )
+{
+ u32 i_copyright_nb_1, i_copyright_nb_2; /* local integers */
+ p_vpar->sequence.b_copyright_flag = GetBits( &p_vpar->bit_stream, 1 );
+ /* A flag that says whether the copyright information is significant */
+ p_vpar->sequence.i_copyright_id = GetBits( &p_vpar->bit_stream, 8 );
+ /* An identifier compliant with ISO/CEI JTC 1/SC 29 */
+ p_vpar->sequence.b_original = GetBits( &p_vpar->bit_stream, 1 );
+ /* Reserved bits */
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ /* The copyright_number is split in three parts */
+ /* first part */
+ i_copyright_nb_1 = GetBits( &p_vpar->bit_stream, 20 );
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ /* second part */
+ i_copyright_nb_2 = GetBits( &p_vpar->bit_stream, 22 );
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ /* third part and sum */
+ p_vpar->sequence.i_copyright_nb = ( (u64)i_copyright_nb_1 << 44 ) |
+ ( (u64)i_copyright_nb_2 << 22 ) |
+ ( (u64)GetBits( &p_vpar->bit_stream, 22 ) );
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+idct_SOURCES = idct.c
+idctclassic_SOURCES = idctclassic.c
+idctmmx_SOURCES = idctmmx.c
+idctmmxext_SOURCES = idctmmxext.c
+idctaltivec_SOURCES = idctaltivec.c
--- /dev/null
+/*****************************************************************************
+ * block_c.h: Macroblock copy functions in C
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: block_c.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************
+ * We can keep them static since they will always contain the same values.
+ *****************************************************************************/
+static u8 pi_crop_buf[VDEC_CROPRANGE];
+static u8 *pi_crop;
+
+/*****************************************************************************
+ * InitBlock: initialize the crop table
+ *****************************************************************************/
+static void InitBlock ( )
+{
+ int i_dummy;
+
+ /* Init crop table */
+ pi_crop = pi_crop_buf + (VDEC_CROPRANGE >> 1);
+
+ for( i_dummy = -(VDEC_CROPRANGE >> 1); i_dummy < 0; i_dummy++ )
+ {
+ pi_crop[i_dummy] = 0;
+ }
+
+ for( ; i_dummy < 255; i_dummy ++ )
+ {
+ pi_crop[i_dummy] = i_dummy;
+ }
+
+ for( ; i_dummy < (VDEC_CROPRANGE >> 1) -1; i_dummy++ )
+ {
+ pi_crop[i_dummy] = 255;
+ }
+}
+
+/*****************************************************************************
+ * AddBlock: add a block
+ *****************************************************************************/
+static inline void AddBlock( dctelem_t * p_block, yuv_data_t * p_data,
+ int i_incr )
+{
+ int i = 8;
+
+ do {
+ p_data[0] = pi_crop[ p_data[0] + p_block[0] ];
+ p_data[1] = pi_crop[ p_data[1] + p_block[1] ];
+ p_data[2] = pi_crop[ p_data[2] + p_block[2] ];
+ p_data[3] = pi_crop[ p_data[3] + p_block[3] ];
+ p_data[4] = pi_crop[ p_data[4] + p_block[4] ];
+ p_data[5] = pi_crop[ p_data[5] + p_block[5] ];
+ p_data[6] = pi_crop[ p_data[6] + p_block[6] ];
+ p_data[7] = pi_crop[ p_data[7] + p_block[7] ];
+
+ p_data += i_incr;
+ p_block += 8;
+ } while( --i );
+}
+
+/*****************************************************************************
+ * CopyBlock: copy a block
+ *****************************************************************************/
+static inline void CopyBlock( dctelem_t * p_block, yuv_data_t * p_data,
+ int i_incr )
+{
+ int i = 8;
+
+ do {
+ p_data[0] = pi_crop[ p_block[0] ];
+ p_data[1] = pi_crop[ p_block[1] ];
+ p_data[2] = pi_crop[ p_block[2] ];
+ p_data[3] = pi_crop[ p_block[3] ];
+ p_data[4] = pi_crop[ p_block[4] ];
+ p_data[5] = pi_crop[ p_block[5] ];
+ p_data[6] = pi_crop[ p_block[6] ];
+ p_data[7] = pi_crop[ p_block[7] ];
+
+ p_data += i_incr;
+ p_block += 8;
+ } while( --i );
+}
+
--- /dev/null
+/*****************************************************************************
+ * block_mmx.h: Macroblock copy functions in MMX assembly
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: block_mmx.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Lespinasse <walken@zoy.org>
+ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * InitBlock: placeholder because we don't need a crop table, MMX does it for us
+ *****************************************************************************/
+static inline void InitBlock( )
+{
+ ;
+}
+
+/*****************************************************************************
+ * AddBlock: add a block
+ *****************************************************************************/
+#define ADD_MMX(offset,r1,r2,r3,r4) \
+ movq_m2r (*(p_data+2*i_incr), r1); \
+ packuswb_r2r (r4, r3); \
+ movq_r2r (r1, r2); \
+ p_data += i_incr; \
+ movq_r2m (r3, *p_data); \
+ punpcklbw_r2r (mm0, r1); \
+ paddsw_m2r (*(p_block+offset), r1); \
+ punpckhbw_r2r (mm0, r2); \
+ paddsw_m2r (*(p_block+offset+4), r2);
+
+static inline void AddBlock( dctelem_t * p_block, yuv_data_t * p_data,
+ int i_incr )
+{
+ movq_m2r (*p_data, mm1);
+ pxor_r2r (mm0, mm0);
+ movq_m2r (*(p_data + i_incr), mm3);
+ movq_r2r (mm1, mm2);
+ punpcklbw_r2r (mm0, mm1);
+ movq_r2r (mm3, mm4);
+ paddsw_m2r (*(p_block+0*8), mm1);
+ punpckhbw_r2r (mm0, mm2);
+ paddsw_m2r (*(p_block+0*8+4), mm2);
+ punpcklbw_r2r (mm0, mm3);
+ paddsw_m2r (*(p_block+1*8), mm3);
+ packuswb_r2r (mm2, mm1);
+ punpckhbw_r2r (mm0, mm4);
+ movq_r2m (mm1, *p_data);
+ paddsw_m2r (*(p_block+1*8+4), mm4);
+ ADD_MMX (2*8, mm1, mm2, mm3, mm4);
+ ADD_MMX (3*8, mm3, mm4, mm1, mm2);
+ ADD_MMX (4*8, mm1, mm2, mm3, mm4);
+ ADD_MMX (5*8, mm3, mm4, mm1, mm2);
+ ADD_MMX (6*8, mm1, mm2, mm3, mm4);
+ ADD_MMX (7*8, mm3, mm4, mm1, mm2);
+ packuswb_r2r (mm4, mm3);
+ movq_r2m (mm3, *(p_data + i_incr));
+}
+
+/*****************************************************************************
+ * CopyBlock: copy a block
+ *****************************************************************************/
+#define COPY_MMX(offset,r0,r1,r2) \
+ movq_m2r (*(p_block+offset), r0); \
+ p_data += i_incr; \
+ movq_m2r (*(p_block+offset+4), r1); \
+ movq_r2m (r2, *p_data); \
+ packuswb_r2r (r1, r0);
+
+static inline void CopyBlock( dctelem_t * p_block, yuv_data_t * p_data,
+ int i_incr )
+{
+ movq_m2r (*(p_block+0*8), mm0);
+ movq_m2r (*(p_block+0*8+4), mm1);
+ movq_m2r (*(p_block+1*8), mm2);
+ packuswb_r2r (mm1, mm0);
+ movq_m2r (*(p_block+1*8+4), mm3);
+ movq_r2m (mm0, *p_data);
+ packuswb_r2r (mm3, mm2);
+ COPY_MMX (2*8, mm0, mm1, mm2);
+ COPY_MMX (3*8, mm2, mm3, mm0);
+ COPY_MMX (4*8, mm0, mm1, mm2);
+ COPY_MMX (5*8, mm2, mm3, mm0);
+ COPY_MMX (6*8, mm0, mm1, mm2);
+ COPY_MMX (7*8, mm2, mm3, mm0);
+ movq_r2m (mm2, *(p_data + i_incr));
+}
+
--- /dev/null
+/*****************************************************************************
+ * idct.c : C IDCT module
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: idct.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Gaël Hendryckx <jimmy@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "idct.h"
+#include "block_c.h"
+
+static int Open( vlc_object_t *p_this );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("IDCT module") );
+ set_capability( "idct", 50 );
+ add_shortcut( "c" );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * NormScan : Unused in this IDCT
+ *****************************************************************************/
+static void NormScan( u8 ppi_scan[2][64] )
+{
+}
+
+/*****************************************************************************
+ * IDCT : IDCT function for normal matrices
+ *****************************************************************************/
+static inline void IDCT( dctelem_t * p_block )
+{
+ s32 tmp0, tmp1, tmp2, tmp3;
+ s32 tmp10, tmp11, tmp12, tmp13;
+ s32 z1, z2, z3, z4, z5;
+ s32 d0, d1, d2, d3, d4, d5, d6, d7;
+ dctelem_t * dataptr;
+ int rowctr;
+
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = p_block;
+
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--)
+ {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any row in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * row DCT calculations can be simplified this way.
+ */
+
+ register int * idataptr = (int*)dataptr;
+ d0 = dataptr[0];
+ d1 = dataptr[1];
+ if ( (d1 == 0) && ((idataptr[1] | idataptr[2] | idataptr[3]) == 0) )
+ {
+ /* AC terms all zero */
+ if (d0)
+ {
+ /* Compute a 32 bit value to assign. */
+ dctelem_t dcval = (dctelem_t) (d0 << PASS1_BITS);
+ register int v = (dcval & 0xffff) | (dcval << 16);
+
+ idataptr[0] = v;
+ idataptr[1] = v;
+ idataptr[2] = v;
+ idataptr[3] = v;
+ }
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+ d2 = dataptr[2];
+ d3 = dataptr[3];
+ d4 = dataptr[4];
+ d5 = dataptr[5];
+ d6 = dataptr[6];
+ d7 = dataptr[7];
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+ if (d6)
+ {
+ if (d4)
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ }
+ else
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (d4)
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
+ tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = d4 << CONST_BITS;
+ tmp11 = tmp12 = -tmp10;
+ }
+ }
+ }
+ else
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = 0;
+ }
+ }
+ }
+ }
+
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ if (d7)
+ {
+ if (d5)
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d5, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d7 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 = z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
+ z5 = MULTIPLY(d7 + d5, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z3;
+ tmp1 += z4;
+ tmp2 = z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ }
+ else
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 = z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ tmp2 = MULTIPLY(d3, FIX(0.509795579));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX2(0.785694958));
+
+ tmp0 += z3;
+ tmp1 = z2 + z5;
+ tmp2 += z3;
+ tmp3 = z1 + z5;
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z5 = MULTIPLY(z1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(1.662939224));
+ tmp3 = MULTIPLY(d1, FIX2(1.111140466));
+ z1 = MULTIPLY(z1, FIX2(0.275899379));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ tmp0 += z1;
+ tmp1 = z4 + z5;
+ tmp2 = z3 + z5;
+ tmp3 += z1;
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
+ tmp0 = MULTIPLY(d7, - FIX2(1.387039845));
+ tmp1 = MULTIPLY(d7, FIX(1.175875602));
+ tmp2 = MULTIPLY(d7, - FIX2(0.785694958));
+ tmp3 = MULTIPLY(d7, FIX2(0.275899379));
+ }
+ }
+ }
+ }
+ else
+ {
+ if (d5)
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d3 + z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 = z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z5 = MULTIPLY(z2, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX2(1.662939225));
+ tmp2 = MULTIPLY(d3, FIX2(1.111140466));
+ z2 = MULTIPLY(z2, - FIX2(1.387039845));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ tmp0 = z3 + z5;
+ tmp1 += z2;
+ tmp2 += z2;
+ tmp3 = z4 + z5;
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ tmp3 = MULTIPLY(d1, FIX2(0.601344887));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(z4, FIX2(0.785694958));
+
+ tmp0 = z1 + z5;
+ tmp1 += z4;
+ tmp2 = z2 + z5;
+ tmp3 += z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
+ tmp0 = MULTIPLY(d5, FIX(1.175875602));
+ tmp1 = MULTIPLY(d5, FIX2(0.275899380));
+ tmp2 = MULTIPLY(d5, - FIX2(1.387039845));
+ tmp3 = MULTIPLY(d5, FIX2(0.785694958));
+ }
+ }
+ }
+ else
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
+ z5 = d3 + d1;
+
+ tmp2 = MULTIPLY(d3, - FIX(1.451774981));
+ tmp3 = MULTIPLY(d1, (FIX(0.211164243) - 1));
+ z1 = MULTIPLY(d1, FIX(1.061594337));
+ z2 = MULTIPLY(d3, - FIX(2.172734803));
+ z4 = MULTIPLY(z5, FIX(0.785694958));
+ z5 = MULTIPLY(z5, FIX(1.175875602));
+
+ tmp0 = z1 - z4;
+ tmp1 = z2 + z4;
+ tmp2 += z5;
+ tmp3 += z5;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d3, - FIX2(0.785694958));
+ tmp1 = MULTIPLY(d3, - FIX2(1.387039845));
+ tmp2 = MULTIPLY(d3, - FIX2(0.275899379));
+ tmp3 = MULTIPLY(d3, FIX(1.175875602));
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d1, FIX2(0.275899379));
+ tmp1 = MULTIPLY(d1, FIX2(0.785694958));
+ tmp2 = MULTIPLY(d1, FIX(1.175875602));
+ tmp3 = MULTIPLY(d1, FIX2(1.387039845));
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = tmp1 = tmp2 = tmp3 = 0;
+ }
+ }
+ }
+ }
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[0] = (dctelem_t) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (dctelem_t) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (dctelem_t) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[6] = (dctelem_t) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[2] = (dctelem_t) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (dctelem_t) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (dctelem_t) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[4] = (dctelem_t) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ dataptr = p_block;
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--)
+ {
+ /* Columns of zeroes can be exploited in the same way as we did with rows.
+ * However, the row calculation has created many nonzero AC terms, so the
+ * simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+ d0 = dataptr[DCTSIZE*0];
+ d1 = dataptr[DCTSIZE*1];
+ d2 = dataptr[DCTSIZE*2];
+ d3 = dataptr[DCTSIZE*3];
+ d4 = dataptr[DCTSIZE*4];
+ d5 = dataptr[DCTSIZE*5];
+ d6 = dataptr[DCTSIZE*6];
+ d7 = dataptr[DCTSIZE*7];
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+ if (d6)
+ {
+ if (d4)
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, -FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ }
+ else
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
+ tmp3 = MULTIPLY(d6, FIX(0.541196100));
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (d4)
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
+ tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = d4 << CONST_BITS;
+ tmp11 = tmp12 = -tmp10;
+ }
+ }
+ }
+ else
+ {
+ if (d2)
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ }
+ else
+ {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX(0.541196100));
+ tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ else
+ {
+ if (d0)
+ {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
+ }
+ else
+ {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = 0;
+ }
+ }
+ }
+ }
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+ if (d7)
+ {
+ if (d5)
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d5, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d7 + z4, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 = z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
+ z5 = MULTIPLY(d5 + d7, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z3;
+ tmp1 += z4;
+ tmp2 = z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ }
+ else
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, FIX(0.298631336));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(z1, - FIX(0.899976223));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 = z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
+ z1 = MULTIPLY(d7, - FIX(0.899976223));
+ tmp2 = MULTIPLY(d3, FIX(0.509795579));
+ z2 = MULTIPLY(d3, - FIX(2.562915447));
+ z3 = MULTIPLY(z3, - FIX2(0.785694958));
+
+ tmp0 += z3;
+ tmp1 = z2 + z5;
+ tmp2 += z3;
+ tmp3 = z1 + z5;
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z5 = MULTIPLY(z1, FIX(1.175875602));
+
+ tmp0 = MULTIPLY(d7, - FIX2(1.662939224));
+ tmp3 = MULTIPLY(d1, FIX2(1.111140466));
+ z1 = MULTIPLY(z1, FIX2(0.275899379));
+ z3 = MULTIPLY(d7, - FIX(1.961570560));
+ z4 = MULTIPLY(d1, - FIX(0.390180644));
+
+ tmp0 += z1;
+ tmp1 = z4 + z5;
+ tmp2 = z3 + z5;
+ tmp3 += z1;
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
+ tmp0 = MULTIPLY(d7, - FIX2(1.387039845));
+ tmp1 = MULTIPLY(d7, FIX(1.175875602));
+ tmp2 = MULTIPLY(d7, - FIX2(0.785694958));
+ tmp3 = MULTIPLY(d7, FIX2(0.275899379));
+ }
+ }
+ }
+ }
+ else
+ {
+ if (d5)
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d3 + z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX(2.053119869));
+ tmp2 = MULTIPLY(d3, FIX(3.072711026));
+ tmp3 = MULTIPLY(d1, FIX(1.501321110));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(z2, - FIX(2.562915447));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(z4, - FIX(0.390180644));
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 = z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z5 = MULTIPLY(z2, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, FIX2(1.662939225));
+ tmp2 = MULTIPLY(d3, FIX2(1.111140466));
+ z2 = MULTIPLY(z2, - FIX2(1.387039845));
+ z3 = MULTIPLY(d3, - FIX(1.961570560));
+ z4 = MULTIPLY(d5, - FIX(0.390180644));
+
+ tmp0 = z3 + z5;
+ tmp1 += z2;
+ tmp2 += z2;
+ tmp3 = z4 + z5;
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z4, FIX(1.175875602));
+
+ tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
+ tmp3 = MULTIPLY(d1, FIX2(0.601344887));
+ z1 = MULTIPLY(d1, - FIX(0.899976223));
+ z2 = MULTIPLY(d5, - FIX(2.562915447));
+ z4 = MULTIPLY(z4, FIX2(0.785694958));
+
+ tmp0 = z1 + z5;
+ tmp1 += z4;
+ tmp2 = z2 + z5;
+ tmp3 += z4;
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
+ tmp0 = MULTIPLY(d5, FIX(1.175875602));
+ tmp1 = MULTIPLY(d5, FIX2(0.275899380));
+ tmp2 = MULTIPLY(d5, - FIX2(1.387039845));
+ tmp3 = MULTIPLY(d5, FIX2(0.785694958));
+ }
+ }
+ }
+ else
+ {
+ if (d3)
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
+ z5 = d3 + d1;
+
+ tmp2 = MULTIPLY(d3, - FIX(1.451774981));
+ tmp3 = MULTIPLY(d1, (FIX(0.211164243) - 1));
+ z1 = MULTIPLY(d1, FIX(1.061594337));
+ z2 = MULTIPLY(d3, - FIX(2.172734803));
+ z4 = MULTIPLY(z5, FIX(0.785694958));
+ z5 = MULTIPLY(z5, FIX(1.175875602));
+
+ tmp0 = z1 - z4;
+ tmp1 = z2 + z4;
+ tmp2 += z5;
+ tmp3 += z5;
+ }
+ else
+ {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d3, - FIX2(0.785694958));
+ tmp1 = MULTIPLY(d3, - FIX2(1.387039845));
+ tmp2 = MULTIPLY(d3, - FIX2(0.275899379));
+ tmp3 = MULTIPLY(d3, FIX(1.175875602));
+ }
+ }
+ else
+ {
+ if (d1)
+ {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d1, FIX2(0.275899379));
+ tmp1 = MULTIPLY(d1, FIX2(0.785694958));
+ tmp2 = MULTIPLY(d1, FIX(1.175875602));
+ tmp3 = MULTIPLY(d1, FIX2(1.387039845));
+ }
+ else
+ {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = tmp1 = tmp2 = tmp3 = 0;
+ }
+ }
+ }
+ }
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[DCTSIZE*0] = (dctelem_t) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*7] = (dctelem_t) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*1] = (dctelem_t) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*6] = (dctelem_t) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*2] = (dctelem_t) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*5] = (dctelem_t) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*3] = (dctelem_t) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*4] = (dctelem_t) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+static inline void RestoreCPUState( )
+{
+ ;
+}
+
+#include "idct_sparse.h"
+#include "idct_decl.h"
--- /dev/null
+/*****************************************************************************
+ * idct.h : macros for the inverse discrete cosine transform
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: idct.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Gaël Hendryckx <jimmy@via.ecp.fr>
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#define SPARSE_SCALE_FACTOR 8
+#define DCTSIZE 8 /* 8*8 DCT */
+
+/*****************************************************************************
+ * Macros
+ *****************************************************************************/
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity. This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit. But some
+ * C compilers implement >> with an unsigned shift. For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an s32 quantity.
+ * It is only applied with constant shift counts. SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS s32 shift_temp;
+#define RIGHT_SHIFT(x,shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((s32) 0)) << (32-(shft))) : \
+ (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+/*
+ * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true IDCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D IDCT,
+ * because the y0 and y4 inputs need not be divided by sqrt(N).
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (To scale up 12-bit sample data further, an
+ * intermediate s32 array would be needed.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#define CONST_BITS 8 /* Jimmy chose this constant :) */
+
+#ifdef EIGHT_BIT_SAMPLES
+#define PASS1_BITS 2
+#else
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+#define ONE ((s32) 1)
+
+#define CONST_SCALE (ONE << CONST_BITS)
+
+/* Convert a positive real constant to an integer scaled by CONST_SCALE.
+ * IMPORTANT: if your compiler doesn't do this arithmetic at compile time,
+ * you will pay a significant penalty in run time. In that case, figure
+ * the correct integer constant values and insert them by hand.
+ */
+
+#define FIX(x) ((s32) ((x) * CONST_SCALE + 0.5))
+
+/* When adding two opposite-signed fixes, the 0.5 cancels */
+#define FIX2(x) ((s32) ((x) * CONST_SCALE))
+
+/* Descale and correctly round an s32 value that's scaled by N bits.
+ * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
+ * the fudge factor is correct for either sign of X.
+ */
+
+#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+
+/* Multiply an s32 variable by an s32 constant to yield an s32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
+ * this provides a useful speedup on many machines.
+ * There is no way to specify a 16x16->32 multiply in portable C, but
+ * some C compilers will do the right thing if you provide the correct
+ * combination of casts.
+ * NB: for 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#ifdef EIGHT_BIT_SAMPLES
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
+#endif
+#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
+#define MULTIPLY(var,const) (((INT16) (var)) * ((s32) (const)))
+#endif
+#endif
+
+#ifndef MULTIPLY /* default definition */
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * idct_decl.h : common declarations, must be included at the very end
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: idct_decl.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Final declarations
+ *****************************************************************************/
+static void IDCTCopy( dctelem_t * p_block, yuv_data_t * p_dest,
+ int i_stride, void * p_unused, int i_unused )
+{
+ IDCT( p_block );
+ CopyBlock( p_block, p_dest, i_stride );
+}
+
+static void IDCTAdd( dctelem_t * p_block, yuv_data_t * p_dest,
+ int i_stride, void * p_unused, int i_unused )
+{
+ IDCT( p_block );
+ AddBlock( p_block, p_dest, i_stride );
+}
+
+static void * IDCTFunctions[] =
+ { InitIDCT, NormScan, SparseIDCTAdd, SparseIDCTCopy, IDCTAdd, IDCTCopy };
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ p_this->p_private = IDCTFunctions;
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * idct_sparse.h : Sparse IDCT functions (must be include at the end)
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: idct_sparse.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Author: Gaël Hendryckx <jimmy@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * InitIDCT : initialize data for SparseIDCT
+ *****************************************************************************/
+static void InitIDCT ( void ** pp_idct_data )
+{
+ int i;
+ dctelem_t * p_pre;
+
+ *pp_idct_data = malloc( sizeof(dctelem_t) * 64 * 64 );
+ p_pre = (dctelem_t *) *pp_idct_data;
+ memset( p_pre, 0, 64 * 64 * sizeof(dctelem_t) );
+
+ for( i = 0 ; i < 64 ; i++ )
+ {
+ p_pre[i*64+i] = 1 << SPARSE_SCALE_FACTOR;
+ IDCT( &p_pre[i*64] ) ;
+ }
+
+ InitBlock();
+
+ RestoreCPUState();
+}
+
+/*****************************************************************************
+ * SparseIDCT : IDCT function for sparse matrices
+ *****************************************************************************/
+static inline void SparseIDCT( dctelem_t * p_block, void * p_idct_data,
+ int i_sparse_pos )
+{
+ short int val;
+ int * dp;
+ int v;
+ short int * p_dest;
+ short int * p_source;
+ int coeff, rr;
+ dctelem_t * p_pre = (dctelem_t *) p_idct_data;
+
+ /* If DC Coefficient. */
+ if ( i_sparse_pos == 0 )
+ {
+ dp=(int *)p_block;
+ val=RIGHT_SHIFT((*p_block + 4), 3);
+ /* Compute int to assign. This speeds things up a bit */
+ v = ((val & 0xffff) | (val << 16));
+ dp[0] = v; dp[1] = v; dp[2] = v; dp[3] = v;
+ dp[4] = v; dp[5] = v; dp[6] = v; dp[7] = v;
+ dp[8] = v; dp[9] = v; dp[10] = v; dp[11] = v;
+ dp[12] = v; dp[13] = v; dp[14] = v; dp[15] = v;
+ dp[16] = v; dp[17] = v; dp[18] = v; dp[19] = v;
+ dp[20] = v; dp[21] = v; dp[22] = v; dp[23] = v;
+ dp[24] = v; dp[25] = v; dp[26] = v; dp[27] = v;
+ dp[28] = v; dp[29] = v; dp[30] = v; dp[31] = v;
+ return;
+ }
+ /* Some other coefficient. */
+ p_dest = (s16*)p_block;
+ p_source = (s16*)&p_pre[i_sparse_pos * 64];
+ coeff = (int)p_dest[i_sparse_pos];
+ for( rr=0 ; rr < 4 ; rr++ )
+ {
+ p_dest[0] = (p_source[0] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[1] = (p_source[1] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[2] = (p_source[2] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[3] = (p_source[3] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[4] = (p_source[4] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[5] = (p_source[5] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[6] = (p_source[6] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[7] = (p_source[7] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[8] = (p_source[8] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[9] = (p_source[9] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[10] = (p_source[10] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[11] = (p_source[11] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[12] = (p_source[12] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[13] = (p_source[13] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[14] = (p_source[14] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest[15] = (p_source[15] * coeff) >> SPARSE_SCALE_FACTOR;
+ p_dest += 16;
+ p_source += 16;
+ }
+}
+
+/*****************************************************************************
+ * Final declarations
+ *****************************************************************************/
+static void SparseIDCTCopy( dctelem_t * p_block, yuv_data_t * p_dest,
+ int i_stride, void * p_idct_data, int i_sparse_pos )
+{
+ SparseIDCT( p_block, p_idct_data, i_sparse_pos );
+ CopyBlock( p_block, p_dest, i_stride );
+}
+
+static void SparseIDCTAdd( dctelem_t * p_block, yuv_data_t * p_dest,
+ int i_stride, void * p_idct_data, int i_sparse_pos )
+{
+ SparseIDCT( p_block, p_idct_data, i_sparse_pos );
+ AddBlock( p_block, p_dest, i_stride );
+}
--- /dev/null
+/*****************************************************************************
+ * idctaltivec.c : AltiVec IDCT module
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: idctaltivec.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#ifndef __BUILD_ALTIVEC_ASM__
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h> /* int16_t .. */
+#endif
+
+#include "idct.h"
+
+static int Open( vlc_object_t *p_this );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("AltiVec IDCT module") );
+ set_capability( "idct", 200 );
+ add_shortcut( "altivec" );
+ add_requirement( ALTIVEC );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * NormScan : This IDCT uses reordered coeffs, so we patch the scan table
+ *****************************************************************************/
+static void NormScan( u8 ppi_scan[2][64] )
+{
+ int i, j;
+
+ for( i = 0; i < 64; i++ )
+ {
+ j = ppi_scan[0][i];
+ ppi_scan[0][i] = (j >> 3) | ((j & 7) << 3);
+
+ j = ppi_scan[1][i];
+ ppi_scan[1][i] = (j >> 3) | ((j & 7) << 3);
+ }
+}
+
+/*****************************************************************************
+ * Placeholders for unused functions
+ *****************************************************************************/
+static void InitIDCT( void ** pp_idct_data )
+{
+}
+
+/*****************************************************************************
+ * IDCT in AltiVec
+ *****************************************************************************/
+
+#ifndef CAN_COMPILE_C_ALTIVEC
+
+static int16_t constants[5][8] ATTR_ALIGN(16) = {
+ {23170, 13573, 6518, 21895, -23170, -21895, 32, 31},
+ {16384, 22725, 21407, 19266, 16384, 19266, 21407, 22725},
+ {22725, 31521, 29692, 26722, 22725, 26722, 29692, 31521},
+ {21407, 29692, 27969, 25172, 21407, 25172, 27969, 29692},
+ {19266, 26722, 25172, 22654, 19266, 22654, 25172, 26722}
+};
+
+/*
+ * The asm code is generated with:
+ *
+ * gcc-2.95 -fvec -D__BUILD_ALTIVEC_ASM__ -O9 -fomit-frame-pointer -mregnames -S
+ * idct_altivec.c
+ *
+ * awk '{args=""; len=split ($2, arg, ",");
+ * for (i=1; i<=len; i++) { a=arg[i]; if (i<len) a=a",";
+ * args = args sprintf ("%-6s", a) }
+ * printf ("\t\"\t%-16s%-24s\\n\"\n", $1, args) }' idct_altivec.s |
+ * unexpand -a
+ *
+ * I then do some simple trimming on the function prolog/trailers
+ */
+
+void idct_block_copy_altivec (int16_t * block, uint8_t * dest, int stride)
+{
+ asm (" \n"
+ "# stwu %r1, -128(%r1) \n"
+ "# mflr %r0 \n"
+ "# stw %r0, 132(%r1) \n"
+ "# addi %r0, %r1, 128 \n"
+ "# bl _savev25 \n"
+
+ " addi %r9, %r3, 112 \n"
+ " vspltish %v25, 4 \n"
+ " vxor %v13, %v13, %v13 \n"
+ " lis %r10, constants@ha \n"
+ " lvx %v1, 0, %r9 \n"
+ " la %r10, constants@l(%r10) \n"
+ " lvx %v5, 0, %r3 \n"
+ " addi %r9, %r3, 16 \n"
+ " lvx %v8, 0, %r10 \n"
+ " addi %r11, %r10, 32 \n"
+ " lvx %v12, 0, %r9 \n"
+ " lvx %v6, 0, %r11 \n"
+ " addi %r8, %r3, 48 \n"
+ " vslh %v1, %v1, %v25 \n"
+ " addi %r9, %r3, 80 \n"
+ " lvx %v11, 0, %r8 \n"
+ " vslh %v5, %v5, %v25 \n"
+ " lvx %v0, 0, %r9 \n"
+ " addi %r11, %r10, 64 \n"
+ " vsplth %v3, %v8, 2 \n"
+ " lvx %v7, 0, %r11 \n"
+ " addi %r9, %r3, 96 \n"
+ " vslh %v12, %v12, %v25 \n"
+ " vmhraddshs %v27, %v1, %v6, %v13 \n"
+ " addi %r8, %r3, 32 \n"
+ " vsplth %v2, %v8, 5 \n"
+ " lvx %v1, 0, %r9 \n"
+ " vslh %v11, %v11, %v25 \n"
+ " addi %r3, %r3, 64 \n"
+ " lvx %v9, 0, %r8 \n"
+ " addi %r9, %r10, 48 \n"
+ " vslh %v0, %v0, %v25 \n"
+ " lvx %v4, 0, %r9 \n"
+ " vmhraddshs %v31, %v12, %v6, %v13 \n"
+ " addi %r10, %r10, 16 \n"
+ " vmhraddshs %v30, %v0, %v7, %v13 \n"
+ " lvx %v10, 0, %r3 \n"
+ " vsplth %v19, %v8, 3 \n"
+ " vmhraddshs %v15, %v11, %v7, %v13 \n"
+ " lvx %v12, 0, %r10 \n"
+ " vsplth %v6, %v8, 4 \n"
+ " vslh %v1, %v1, %v25 \n"
+ " vsplth %v11, %v8, 1 \n"
+ " li %r9, 4 \n"
+ " vslh %v9, %v9, %v25 \n"
+ " vsplth %v7, %v8, 0 \n"
+ " vmhraddshs %v18, %v1, %v4, %v13 \n"
+ " vspltw %v8, %v8, 3 \n"
+ " vsubshs %v0, %v13, %v27 \n"
+ " vmhraddshs %v1, %v9, %v4, %v13 \n"
+ " vmhraddshs %v17, %v3, %v31, %v0 \n"
+ " vmhraddshs %v4, %v2, %v15, %v30 \n"
+ " vslh %v10, %v10, %v25 \n"
+ " vmhraddshs %v9, %v5, %v12, %v13 \n"
+ " vspltish %v25, 6 \n"
+ " vmhraddshs %v5, %v10, %v12, %v13 \n"
+ " vmhraddshs %v28, %v19, %v30, %v15 \n"
+ " vmhraddshs %v27, %v3, %v27, %v31 \n"
+ " vsubshs %v0, %v13, %v18 \n"
+ " vmhraddshs %v18, %v11, %v18, %v1 \n"
+ " vaddshs %v30, %v17, %v4 \n"
+ " vmhraddshs %v12, %v11, %v1, %v0 \n"
+ " vsubshs %v4, %v17, %v4 \n"
+ " vaddshs %v10, %v9, %v5 \n"
+ " vsubshs %v17, %v27, %v28 \n"
+ " vaddshs %v27, %v27, %v28 \n"
+ " vsubshs %v1, %v9, %v5 \n"
+ " vaddshs %v28, %v10, %v18 \n"
+ " vsubshs %v18, %v10, %v18 \n"
+ " vaddshs %v10, %v1, %v12 \n"
+ " vsubshs %v1, %v1, %v12 \n"
+ " vsubshs %v12, %v17, %v4 \n"
+ " vaddshs %v4, %v17, %v4 \n"
+ " vmhraddshs %v5, %v7, %v12, %v1 \n"
+ " vmhraddshs %v26, %v6, %v4, %v10 \n"
+ " vmhraddshs %v29, %v6, %v12, %v1 \n"
+ " vmhraddshs %v14, %v7, %v4, %v10 \n"
+ " vsubshs %v12, %v18, %v30 \n"
+ " vaddshs %v9, %v28, %v27 \n"
+ " vaddshs %v16, %v18, %v30 \n"
+ " vsubshs %v10, %v28, %v27 \n"
+ " vmrglh %v31, %v9, %v12 \n"
+ " vmrglh %v30, %v5, %v26 \n"
+ " vmrglh %v15, %v14, %v29 \n"
+ " vmrghh %v5, %v5, %v26 \n"
+ " vmrglh %v27, %v16, %v10 \n"
+ " vmrghh %v9, %v9, %v12 \n"
+ " vmrghh %v18, %v16, %v10 \n"
+ " vmrghh %v1, %v14, %v29 \n"
+ " vmrglh %v14, %v9, %v5 \n"
+ " vmrglh %v16, %v31, %v30 \n"
+ " vmrglh %v10, %v15, %v27 \n"
+ " vmrghh %v9, %v9, %v5 \n"
+ " vmrghh %v26, %v15, %v27 \n"
+ " vmrglh %v27, %v16, %v10 \n"
+ " vmrghh %v12, %v1, %v18 \n"
+ " vmrglh %v29, %v1, %v18 \n"
+ " vsubshs %v0, %v13, %v27 \n"
+ " vmrghh %v5, %v31, %v30 \n"
+ " vmrglh %v31, %v9, %v12 \n"
+ " vmrglh %v30, %v5, %v26 \n"
+ " vmrglh %v15, %v14, %v29 \n"
+ " vmhraddshs %v17, %v3, %v31, %v0 \n"
+ " vmrghh %v18, %v16, %v10 \n"
+ " vmhraddshs %v27, %v3, %v27, %v31 \n"
+ " vmhraddshs %v4, %v2, %v15, %v30 \n"
+ " vmrghh %v1, %v14, %v29 \n"
+ " vmhraddshs %v28, %v19, %v30, %v15 \n"
+ " vmrghh %v0, %v9, %v12 \n"
+ " vsubshs %v13, %v13, %v18 \n"
+ " vmrghh %v5, %v5, %v26 \n"
+ " vmhraddshs %v18, %v11, %v18, %v1 \n"
+ " vaddshs %v9, %v0, %v8 \n"
+ " vaddshs %v30, %v17, %v4 \n"
+ " vmhraddshs %v12, %v11, %v1, %v13 \n"
+ " vsubshs %v4, %v17, %v4 \n"
+ " vaddshs %v10, %v9, %v5 \n"
+ " vsubshs %v17, %v27, %v28 \n"
+ " vaddshs %v27, %v27, %v28 \n"
+ " vsubshs %v1, %v9, %v5 \n"
+ " vaddshs %v28, %v10, %v18 \n"
+ " vsubshs %v18, %v10, %v18 \n"
+ " vaddshs %v10, %v1, %v12 \n"
+ " vsubshs %v1, %v1, %v12 \n"
+ " vsubshs %v12, %v17, %v4 \n"
+ " vaddshs %v4, %v17, %v4 \n"
+ " vaddshs %v9, %v28, %v27 \n"
+ " vmhraddshs %v14, %v7, %v4, %v10 \n"
+ " vsrah %v9, %v9, %v25 \n"
+ " vmhraddshs %v5, %v7, %v12, %v1 \n"
+ " vpkshus %v0, %v9, %v9 \n"
+ " vmhraddshs %v29, %v6, %v12, %v1 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " vaddshs %v16, %v18, %v30 \n"
+ " vsrah %v31, %v14, %v25 \n"
+ " stvewx %v0, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vsrah %v15, %v16, %v25 \n"
+ " vpkshus %v0, %v31, %v31 \n"
+ " vsrah %v1, %v5, %v25 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " vsubshs %v12, %v18, %v30 \n"
+ " stvewx %v0, %r9, %r4 \n"
+ " vmhraddshs %v26, %v6, %v4, %v10 \n"
+ " vpkshus %v0, %v1, %v1 \n"
+ " add %r4, %r4, %r5 \n"
+ " vsrah %v5, %v12, %v25 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " vsrah %v30, %v29, %v25 \n"
+ " stvewx %v0, %r9, %r4 \n"
+ " vsubshs %v10, %v28, %v27 \n"
+ " vpkshus %v0, %v15, %v15 \n"
+ " add %r4, %r4, %r5 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " vsrah %v18, %v26, %v25 \n"
+ " stvewx %v0, %r9, %r4 \n"
+ " vsrah %v27, %v10, %v25 \n"
+ " vpkshus %v0, %v5, %v5 \n"
+ " add %r4, %r4, %r5 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " stvewx %v0, %r9, %r4 \n"
+ " vpkshus %v0, %v30, %v30 \n"
+ " add %r4, %r4, %r5 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " stvewx %v0, %r9, %r4 \n"
+ " vpkshus %v0, %v18, %v18 \n"
+ " add %r4, %r4, %r5 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " stvewx %v0, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vpkshus %v0, %v27, %v27 \n"
+ " stvewx %v0, 0, %r4 \n"
+ " stvewx %v0, %r9, %r4 \n"
+
+ "# addi %r0, %r1, 128 \n"
+ "# bl _restv25 \n"
+ "# lwz %r0, 132(%r1) \n"
+ "# mtlr %r0 \n"
+ "# la %r1, 128(%r1) \n"
+ );
+}
+
+void idct_block_add_altivec (int16_t * block, uint8_t * dest, int stride)
+{
+ asm (" \n"
+ "# stwu %r1, -192(%r1) \n"
+ "# mflr %r0 \n"
+ "# stw %r0, 196(%r1) \n"
+ "# addi %r0, %r1, 192 \n"
+ "# bl _savev21 \n"
+
+ " addi %r9, %r3, 112 \n"
+ " vspltish %v21, 4 \n"
+ " vxor %v1, %v1, %v1 \n"
+ " lvx %v13, 0, %r9 \n"
+ " lis %r10, constants@ha \n"
+ " vspltisw %v3, -1 \n"
+ " la %r10, constants@l(%r10) \n"
+ " lvx %v5, 0, %r3 \n"
+ " addi %r9, %r3, 16 \n"
+ " lvx %v8, 0, %r10 \n"
+ " lvx %v12, 0, %r9 \n"
+ " addi %r11, %r10, 32 \n"
+ " lvx %v6, 0, %r11 \n"
+ " addi %r8, %r3, 48 \n"
+ " vslh %v13, %v13, %v21 \n"
+ " addi %r9, %r3, 80 \n"
+ " lvx %v11, 0, %r8 \n"
+ " vslh %v5, %v5, %v21 \n"
+ " lvx %v0, 0, %r9 \n"
+ " addi %r11, %r10, 64 \n"
+ " vsplth %v2, %v8, 2 \n"
+ " lvx %v7, 0, %r11 \n"
+ " vslh %v12, %v12, %v21 \n"
+ " addi %r9, %r3, 96 \n"
+ " vmhraddshs %v24, %v13, %v6, %v1 \n"
+ " addi %r8, %r3, 32 \n"
+ " vsplth %v17, %v8, 5 \n"
+ " lvx %v13, 0, %r9 \n"
+ " vslh %v11, %v11, %v21 \n"
+ " addi %r3, %r3, 64 \n"
+ " lvx %v10, 0, %r8 \n"
+ " vslh %v0, %v0, %v21 \n"
+ " addi %r9, %r10, 48 \n"
+ " vmhraddshs %v31, %v12, %v6, %v1 \n"
+ " lvx %v4, 0, %r9 \n"
+ " addi %r10, %r10, 16 \n"
+ " vmhraddshs %v26, %v0, %v7, %v1 \n"
+ " lvx %v9, 0, %r3 \n"
+ " vsplth %v16, %v8, 3 \n"
+ " vmhraddshs %v22, %v11, %v7, %v1 \n"
+ " lvx %v6, 0, %r10 \n"
+ " lvsl %v19, 0, %r4 \n"
+ " vsubshs %v12, %v1, %v24 \n"
+ " lvsl %v0, %r5, %r4 \n"
+ " vsplth %v11, %v8, 1 \n"
+ " vslh %v10, %v10, %v21 \n"
+ " vmrghb %v19, %v3, %v19 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vslh %v13, %v13, %v21 \n"
+ " vmrghb %v3, %v3, %v0 \n"
+ " li %r9, 4 \n"
+ " vmhraddshs %v14, %v2, %v31, %v12 \n"
+ " vsplth %v7, %v8, 0 \n"
+ " vmhraddshs %v23, %v13, %v4, %v1 \n"
+ " vsplth %v18, %v8, 4 \n"
+ " vmhraddshs %v27, %v10, %v4, %v1 \n"
+ " vspltw %v8, %v8, 3 \n"
+ " vmhraddshs %v12, %v17, %v22, %v26 \n"
+ " vperm %v15, %v15, %v1, %v19 \n"
+ " vslh %v9, %v9, %v21 \n"
+ " vmhraddshs %v10, %v5, %v6, %v1 \n"
+ " vspltish %v21, 6 \n"
+ " vmhraddshs %v30, %v9, %v6, %v1 \n"
+ " vmhraddshs %v26, %v16, %v26, %v22 \n"
+ " vmhraddshs %v24, %v2, %v24, %v31 \n"
+ " vmhraddshs %v31, %v11, %v23, %v27 \n"
+ " vsubshs %v0, %v1, %v23 \n"
+ " vaddshs %v23, %v14, %v12 \n"
+ " vmhraddshs %v9, %v11, %v27, %v0 \n"
+ " vsubshs %v12, %v14, %v12 \n"
+ " vaddshs %v6, %v10, %v30 \n"
+ " vsubshs %v14, %v24, %v26 \n"
+ " vaddshs %v24, %v24, %v26 \n"
+ " vsubshs %v13, %v10, %v30 \n"
+ " vaddshs %v26, %v6, %v31 \n"
+ " vsubshs %v31, %v6, %v31 \n"
+ " vaddshs %v6, %v13, %v9 \n"
+ " vsubshs %v13, %v13, %v9 \n"
+ " vsubshs %v9, %v14, %v12 \n"
+ " vaddshs %v12, %v14, %v12 \n"
+ " vmhraddshs %v30, %v7, %v9, %v13 \n"
+ " vmhraddshs %v25, %v18, %v12, %v6 \n"
+ " vmhraddshs %v28, %v18, %v9, %v13 \n"
+ " vmhraddshs %v29, %v7, %v12, %v6 \n"
+ " vaddshs %v10, %v26, %v24 \n"
+ " vsubshs %v5, %v31, %v23 \n"
+ " vsubshs %v13, %v26, %v24 \n"
+ " vaddshs %v4, %v31, %v23 \n"
+ " vmrglh %v26, %v30, %v25 \n"
+ " vmrglh %v31, %v10, %v5 \n"
+ " vmrglh %v22, %v29, %v28 \n"
+ " vmrghh %v30, %v30, %v25 \n"
+ " vmrglh %v24, %v4, %v13 \n"
+ " vmrghh %v10, %v10, %v5 \n"
+ " vmrghh %v23, %v4, %v13 \n"
+ " vmrghh %v27, %v29, %v28 \n"
+ " vmrglh %v29, %v10, %v30 \n"
+ " vmrglh %v4, %v31, %v26 \n"
+ " vmrglh %v13, %v22, %v24 \n"
+ " vmrghh %v10, %v10, %v30 \n"
+ " vmrghh %v25, %v22, %v24 \n"
+ " vmrglh %v24, %v4, %v13 \n"
+ " vmrghh %v5, %v27, %v23 \n"
+ " vmrglh %v28, %v27, %v23 \n"
+ " vsubshs %v0, %v1, %v24 \n"
+ " vmrghh %v30, %v31, %v26 \n"
+ " vmrglh %v31, %v10, %v5 \n"
+ " vmrglh %v26, %v30, %v25 \n"
+ " vmrglh %v22, %v29, %v28 \n"
+ " vmhraddshs %v14, %v2, %v31, %v0 \n"
+ " vmrghh %v23, %v4, %v13 \n"
+ " vmhraddshs %v24, %v2, %v24, %v31 \n"
+ " vmhraddshs %v12, %v17, %v22, %v26 \n"
+ " vmrghh %v27, %v29, %v28 \n"
+ " vmhraddshs %v26, %v16, %v26, %v22 \n"
+ " vmrghh %v0, %v10, %v5 \n"
+ " vmhraddshs %v31, %v11, %v23, %v27 \n"
+ " vmrghh %v30, %v30, %v25 \n"
+ " vsubshs %v13, %v1, %v23 \n"
+ " vaddshs %v10, %v0, %v8 \n"
+ " vaddshs %v23, %v14, %v12 \n"
+ " vsubshs %v12, %v14, %v12 \n"
+ " vaddshs %v6, %v10, %v30 \n"
+ " vsubshs %v14, %v24, %v26 \n"
+ " vmhraddshs %v9, %v11, %v27, %v13 \n"
+ " vaddshs %v24, %v24, %v26 \n"
+ " vaddshs %v26, %v6, %v31 \n"
+ " vsubshs %v13, %v10, %v30 \n"
+ " vaddshs %v10, %v26, %v24 \n"
+ " vsubshs %v31, %v6, %v31 \n"
+ " vaddshs %v6, %v13, %v9 \n"
+ " vsrah %v10, %v10, %v21 \n"
+ " vsubshs %v13, %v13, %v9 \n"
+ " vaddshs %v0, %v15, %v10 \n"
+ " vsubshs %v9, %v14, %v12 \n"
+ " vaddshs %v12, %v14, %v12 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " vaddshs %v4, %v31, %v23 \n"
+ " vmhraddshs %v29, %v7, %v12, %v6 \n"
+ " stvewx %v15, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vsubshs %v5, %v31, %v23 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vmhraddshs %v30, %v7, %v9, %v13 \n"
+ " vsrah %v22, %v4, %v21 \n"
+ " vperm %v15, %v15, %v1, %v3 \n"
+ " vmhraddshs %v28, %v18, %v9, %v13 \n"
+ " vsrah %v31, %v29, %v21 \n"
+ " vsubshs %v13, %v26, %v24 \n"
+ " vaddshs %v0, %v15, %v31 \n"
+ " vsrah %v27, %v30, %v21 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " vsrah %v30, %v5, %v21 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " vsrah %v26, %v28, %v21 \n"
+ " stvewx %v15, %r9, %r4 \n"
+ " vmhraddshs %v25, %v18, %v12, %v6 \n"
+ " add %r4, %r4, %r5 \n"
+ " vsrah %v24, %v13, %v21 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vperm %v15, %v15, %v1, %v19 \n"
+ " vsrah %v23, %v25, %v21 \n"
+ " vaddshs %v0, %v15, %v27 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " stvewx %v15, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vperm %v15, %v15, %v1, %v3 \n"
+ " vaddshs %v0, %v15, %v22 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " stvewx %v15, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vperm %v15, %v15, %v1, %v19 \n"
+ " vaddshs %v0, %v15, %v30 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " stvewx %v15, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vperm %v15, %v15, %v1, %v3 \n"
+ " vaddshs %v0, %v15, %v26 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " stvewx %v15, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vperm %v15, %v15, %v1, %v19 \n"
+ " vaddshs %v0, %v15, %v23 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " stvewx %v15, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v15, 0, %r4 \n"
+ " vperm %v15, %v15, %v1, %v3 \n"
+ " vaddshs %v0, %v15, %v24 \n"
+ " vpkshus %v15, %v0, %v0 \n"
+ " stvewx %v15, 0, %r4 \n"
+ " stvewx %v15, %r9, %r4 \n"
+
+ "# addi %r0, %r1, 192 \n"
+ "# bl _restv21 \n"
+ "# lwz %r0, 196(%r1) \n"
+ "# mtlr %r0 \n"
+ "# la %r1, 192(%r1) \n"
+ );
+}
+
+#endif /* !CAN_COMPILE_C_ALTIVEC */
+#endif /* __BUILD_ALTIVEC_ASM__ */
+
+
+#if defined(CAN_COMPILE_C_ALTIVEC) || defined(__BUILD_ALTIVEC_ASM__)
+
+#define vector_s16_t vector signed short
+#define vector_u16_t vector unsigned short
+#define vector_s8_t vector signed char
+#define vector_u8_t vector unsigned char
+#define vector_s32_t vector signed int
+#define vector_u32_t vector unsigned int
+
+#define IDCT_HALF \
+ /* 1st stage */ \
+ t1 = vec_mradds (a1, vx7, vx1 ); \
+ t8 = vec_mradds (a1, vx1, vec_subs (zero, vx7)); \
+ t7 = vec_mradds (a2, vx5, vx3); \
+ t3 = vec_mradds (ma2, vx3, vx5); \
+ \
+ /* 2nd stage */ \
+ t5 = vec_adds (vx0, vx4); \
+ t0 = vec_subs (vx0, vx4); \
+ t2 = vec_mradds (a0, vx6, vx2); \
+ t4 = vec_mradds (a0, vx2, vec_subs (zero,vx6)); \
+ t6 = vec_adds (t8, t3); \
+ t3 = vec_subs (t8, t3); \
+ t8 = vec_subs (t1, t7); \
+ t1 = vec_adds (t1, t7); \
+ \
+ /* 3rd stage */ \
+ t7 = vec_adds (t5, t2); \
+ t2 = vec_subs (t5, t2); \
+ t5 = vec_adds (t0, t4); \
+ t0 = vec_subs (t0, t4); \
+ t4 = vec_subs (t8, t3); \
+ t3 = vec_adds (t8, t3); \
+ \
+ /* 4th stage */ \
+ vy0 = vec_adds (t7, t1); \
+ vy7 = vec_subs (t7, t1); \
+ vy1 = vec_mradds (c4, t3, t5); \
+ vy6 = vec_mradds (mc4, t3, t5); \
+ vy2 = vec_mradds (c4, t4, t0); \
+ vy5 = vec_mradds (mc4, t4, t0); \
+ vy3 = vec_adds (t2, t6); \
+ vy4 = vec_subs (t2, t6);
+
+#define IDCT \
+ vector_s16_t vx0, vx1, vx2, vx3, vx4, vx5, vx6, vx7; \
+ vector_s16_t vy0, vy1, vy2, vy3, vy4, vy5, vy6, vy7; \
+ vector_s16_t a0, a1, a2, ma2, c4, mc4, zero, bias; \
+ vector_s16_t t0, t1, t2, t3, t4, t5, t6, t7, t8; \
+ vector_u16_t shift; \
+ \
+ c4 = vec_splat (constants[0], 0); \
+ a0 = vec_splat (constants[0], 1); \
+ a1 = vec_splat (constants[0], 2); \
+ a2 = vec_splat (constants[0], 3); \
+ mc4 = vec_splat (constants[0], 4); \
+ ma2 = vec_splat (constants[0], 5); \
+ bias = (vector_s16_t)vec_splat ((vector_s32_t)constants[0], 3); \
+ \
+ zero = vec_splat_s16 (0); \
+ shift = vec_splat_u16 (4); \
+ \
+ vx0 = vec_mradds (vec_sl (block[0], shift), constants[1], zero); \
+ vx1 = vec_mradds (vec_sl (block[1], shift), constants[2], zero); \
+ vx2 = vec_mradds (vec_sl (block[2], shift), constants[3], zero); \
+ vx3 = vec_mradds (vec_sl (block[3], shift), constants[4], zero); \
+ vx4 = vec_mradds (vec_sl (block[4], shift), constants[1], zero); \
+ vx5 = vec_mradds (vec_sl (block[5], shift), constants[4], zero); \
+ vx6 = vec_mradds (vec_sl (block[6], shift), constants[3], zero); \
+ vx7 = vec_mradds (vec_sl (block[7], shift), constants[2], zero); \
+ \
+ IDCT_HALF \
+ \
+ vx0 = vec_mergeh (vy0, vy4); \
+ vx1 = vec_mergel (vy0, vy4); \
+ vx2 = vec_mergeh (vy1, vy5); \
+ vx3 = vec_mergel (vy1, vy5); \
+ vx4 = vec_mergeh (vy2, vy6); \
+ vx5 = vec_mergel (vy2, vy6); \
+ vx6 = vec_mergeh (vy3, vy7); \
+ vx7 = vec_mergel (vy3, vy7); \
+ \
+ vy0 = vec_mergeh (vx0, vx4); \
+ vy1 = vec_mergel (vx0, vx4); \
+ vy2 = vec_mergeh (vx1, vx5); \
+ vy3 = vec_mergel (vx1, vx5); \
+ vy4 = vec_mergeh (vx2, vx6); \
+ vy5 = vec_mergel (vx2, vx6); \
+ vy6 = vec_mergeh (vx3, vx7); \
+ vy7 = vec_mergel (vx3, vx7); \
+ \
+ vx0 = vec_adds (vec_mergeh (vy0, vy4), bias); \
+ vx1 = vec_mergel (vy0, vy4); \
+ vx2 = vec_mergeh (vy1, vy5); \
+ vx3 = vec_mergel (vy1, vy5); \
+ vx4 = vec_mergeh (vy2, vy6); \
+ vx5 = vec_mergel (vy2, vy6); \
+ vx6 = vec_mergeh (vy3, vy7); \
+ vx7 = vec_mergel (vy3, vy7); \
+ \
+ IDCT_HALF \
+ \
+ shift = vec_splat_u16 (6); \
+ vx0 = vec_sra (vy0, shift); \
+ vx1 = vec_sra (vy1, shift); \
+ vx2 = vec_sra (vy2, shift); \
+ vx3 = vec_sra (vy3, shift); \
+ vx4 = vec_sra (vy4, shift); \
+ vx5 = vec_sra (vy5, shift); \
+ vx6 = vec_sra (vy6, shift); \
+ vx7 = vec_sra (vy7, shift);
+
+static vector_s16_t constants[5] ATTR_ALIGN(16) = {
+ (vector_s16_t)(23170, 13573, 6518, 21895, -23170, -21895, 32, 31),
+ (vector_s16_t)(16384, 22725, 21407, 19266, 16384, 19266, 21407, 22725),
+ (vector_s16_t)(22725, 31521, 29692, 26722, 22725, 26722, 29692, 31521),
+ (vector_s16_t)(21407, 29692, 27969, 25172, 21407, 25172, 27969, 29692),
+ (vector_s16_t)(19266, 26722, 25172, 22654, 19266, 22654, 25172, 26722)
+};
+
+void idct_block_copy_altivec (vector_s16_t * block, unsigned char * dest,
+ int stride)
+{
+ vector_u8_t tmp;
+
+ IDCT
+
+#define COPY(dest,src) \
+ tmp = vec_packsu (src, src); \
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest); \
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+
+ COPY (dest, vx0) dest += stride;
+ COPY (dest, vx1) dest += stride;
+ COPY (dest, vx2) dest += stride;
+ COPY (dest, vx3) dest += stride;
+ COPY (dest, vx4) dest += stride;
+ COPY (dest, vx5) dest += stride;
+ COPY (dest, vx6) dest += stride;
+ COPY (dest, vx7)
+}
+
+void idct_block_add_altivec (vector_s16_t * block, unsigned char * dest,
+ int stride)
+{
+ vector_u8_t tmp;
+ vector_s16_t tmp2, tmp3;
+ vector_u8_t perm0;
+ vector_u8_t perm1;
+ vector_u8_t p0, p1, p;
+
+ IDCT
+
+ p0 = vec_lvsl (0, dest);
+ p1 = vec_lvsl (stride, dest);
+ p = vec_splat_u8 (-1);
+ perm0 = vec_mergeh (p, p0);
+ perm1 = vec_mergeh (p, p1);
+
+#define ADD(dest,src,perm) \
+ /* *(uint64_t *)&tmp = *(uint64_t *)dest; */ \
+ tmp = vec_ld (0, dest); \
+ tmp2 = (vector_s16_t)vec_perm (tmp, (vector_u8_t)zero, perm); \
+ tmp3 = vec_adds (tmp2, src); \
+ tmp = vec_packsu (tmp3, tmp3); \
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest); \
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+
+ ADD (dest, vx0, perm0) dest += stride;
+ ADD (dest, vx1, perm1) dest += stride;
+ ADD (dest, vx2, perm0) dest += stride;
+ ADD (dest, vx3, perm1) dest += stride;
+ ADD (dest, vx4, perm0) dest += stride;
+ ADD (dest, vx5, perm1) dest += stride;
+ ADD (dest, vx6, perm0) dest += stride;
+ ADD (dest, vx7, perm1)
+}
+
+#endif /* __BUILD_ALTIVEC_ASM__ || CAN_COMPILE_C_ALTIVEC */
+
+#ifndef __BUILD_ALTIVEC_ASM__
+
+static void * IDCTFunctions[] = {
+ InitIDCT, NormScan,
+ /* FIXME : it would be a nice idea to use sparse IDCT functions */
+ idct_block_add_altivec, idct_block_copy_altivec,
+ idct_block_add_altivec, idct_block_copy_altivec
+};
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ p_this->p_private = IDCTFunctions;
+ return VLC_SUCCESS;
+}
+
+#endif /* __BUILD_ALTIVEC_ASM__ */
--- /dev/null
+/*****************************************************************************
+ * idctclassic.c : Classic IDCT module
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: idctclassic.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Gaël Hendryckx <jimmy@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "idct.h"
+#include "block_c.h"
+
+static int Open( vlc_object_t *p_this );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("classic IDCT module") );
+ set_capability( "idct", 100 );
+ add_shortcut( "classic" );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * NormScan : Unused in this IDCT
+ *****************************************************************************/
+static void NormScan( u8 ppi_scan[2][64] )
+{
+}
+
+/*****************************************************************************
+ * IDCT : IDCT function for normal matrices
+ *****************************************************************************/
+static inline void IDCT( dctelem_t * p_block )
+{
+ s32 tmp0, tmp1, tmp2, tmp3;
+ s32 tmp10, tmp11, tmp12, tmp13;
+ s32 z1, z2, z3, z4, z5;
+ dctelem_t * dataptr;
+ int rowctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = p_block;
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--)
+ {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any row in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * row DCT calculations can be simplified this way.
+ */
+
+ if ((dataptr[1] | dataptr[2] | dataptr[3] | dataptr[4] |
+ dataptr[5] | dataptr[6] | dataptr[7]) == 0)
+ {
+ /* AC terms all zero */
+ dctelem_t dcval = (dctelem_t) (dataptr[0] << PASS1_BITS);
+
+ dataptr[0] = dcval;
+ dataptr[1] = dcval;
+ dataptr[2] = dcval;
+ dataptr[3] = dcval;
+ dataptr[4] = dcval;
+ dataptr[5] = dcval;
+ dataptr[6] = dcval;
+ dataptr[7] = dcval;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (s32) dataptr[2];
+ z3 = (s32) dataptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(z3, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(z2, FIX(0.765366865));
+
+ tmp0 = ((s32) dataptr[0] + (s32) dataptr[4]) << CONST_BITS;
+ tmp1 = ((s32) dataptr[0] - (s32) dataptr[4]) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (s32) dataptr[7];
+ tmp1 = (s32) dataptr[5];
+ tmp2 = (s32) dataptr[3];
+ tmp3 = (s32) dataptr[1];
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[0] = (dctelem_t) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (dctelem_t) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (dctelem_t) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[6] = (dctelem_t) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[2] = (dctelem_t) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (dctelem_t) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (dctelem_t) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[4] = (dctelem_t) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ dataptr = p_block;
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--)
+ {
+ /* Columns of zeroes can be exploited in the same way as we did with rows.
+ * However, the row calculation has created many nonzero AC terms, so the
+ * simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_COLUMN_TEST /* Adds a test but avoids calculus */
+ if ((dataptr[DCTSIZE*1] | dataptr[DCTSIZE*2] | dataptr[DCTSIZE*3] |
+ dataptr[DCTSIZE*4] | dataptr[DCTSIZE*5] | dataptr[DCTSIZE*6] |
+ dataptr[DCTSIZE*7]) == 0)
+ {
+ /* AC terms all zero */
+ dctelem_t dcval = (dctelem_t) DESCALE((s32) dataptr[0], PASS1_BITS+3);
+
+ dataptr[DCTSIZE*0] = dcval;
+ dataptr[DCTSIZE*1] = dcval;
+ dataptr[DCTSIZE*2] = dcval;
+ dataptr[DCTSIZE*3] = dcval;
+ dataptr[DCTSIZE*4] = dcval;
+ dataptr[DCTSIZE*5] = dcval;
+ dataptr[DCTSIZE*6] = dcval;
+ dataptr[DCTSIZE*7] = dcval;
+
+ dataptr++; /* advance pointer to next column */
+ continue;
+ }
+#endif
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (s32) dataptr[DCTSIZE*2];
+ z3 = (s32) dataptr[DCTSIZE*6];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.541196100));
+ tmp2 = z1 + MULTIPLY(z3, - FIX(1.847759065));
+ tmp3 = z1 + MULTIPLY(z2, FIX(0.765366865));
+
+ tmp0 = ((s32) dataptr[DCTSIZE*0] + (s32) dataptr[DCTSIZE*4]) << CONST_BITS;
+ tmp1 = ((s32) dataptr[DCTSIZE*0] - (s32) dataptr[DCTSIZE*4]) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (s32) dataptr[DCTSIZE*7];
+ tmp1 = (s32) dataptr[DCTSIZE*5];
+ tmp2 = (s32) dataptr[DCTSIZE*3];
+ tmp3 = (s32) dataptr[DCTSIZE*1];
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[DCTSIZE*0] = (dctelem_t) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*7] = (dctelem_t) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*1] = (dctelem_t) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*6] = (dctelem_t) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*2] = (dctelem_t) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*5] = (dctelem_t) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*3] = (dctelem_t) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*4] = (dctelem_t) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+static inline void RestoreCPUState( )
+{
+ ;
+}
+
+#include "idct_sparse.h"
+#include "idct_decl.h"
--- /dev/null
+/*****************************************************************************
+ * idctmmx.c : MMX IDCT module
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: idctmmx.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Michel Lespinasse <walken@zoy.org>
+ * Peter Gubanov <peter@elecard.net.ru>
+ * (from the LiViD project)
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "mmx.h"
+
+#include "idct.h"
+#include "block_mmx.h"
+
+static int Open( vlc_object_t *p_this );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("MMX IDCT module") );
+ set_capability( "idct", 150 );
+ add_shortcut( "mmx" );
+ add_requirement( MMX );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * NormScan : This IDCT uses reordered coeffs, so we patch the scan table
+ *****************************************************************************/
+static void NormScan( u8 ppi_scan[2][64] )
+{
+ int i, j;
+
+ for( i = 0; i < 64; i++ )
+ {
+ j = ppi_scan[0][i];
+ ppi_scan[0][i] = (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2);
+
+ j = ppi_scan[1][i];
+ ppi_scan[1][i] = (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2);
+ }
+}
+
+/*****************************************************************************
+ * IDCT :
+ *****************************************************************************/
+#define ROW_SHIFT 11
+#define COL_SHIFT 6
+
+#define round(bias) ((int)(((bias)+0.5) * (1<<ROW_SHIFT)))
+#define rounder(bias) {round (bias), round (bias)}
+
+#define table(c1,c2,c3,c4,c5,c6,c7) { c4, c2, c4, c6, \
+ c4, c6, -c4, -c2, \
+ c1, c3, c3, -c7, \
+ c5, c7, -c1, -c5, \
+ c4, -c6, c4, -c2, \
+ -c4, c2, c4, -c6, \
+ c5, -c1, c7, -c5, \
+ c7, c3, c3, -c1 }
+
+static inline void RowHead( dctelem_t * row, int offset, dctelem_t * table )
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_m2r (*table, mm3); // mm3 = C6 C4 C2 C4
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ punpckldq_r2r (mm0, mm0); // mm0 = x2 x0 x2 x0
+
+ movq_m2r (*(table+4), mm4); // mm4 = -C2 -C4 C6 C4
+ pmaddwd_r2r (mm0, mm3); // mm3 = C4*x0+C6*x2 C4*x0+C2*x2
+
+ movq_m2r (*(table+8), mm1); // mm1 = -C7 C3 C3 C1
+ punpckhdq_r2r (mm2, mm2); // mm2 = x6 x4 x6 x4
+}
+
+static inline void Row( dctelem_t * table, s32 * rounder )
+{
+ pmaddwd_r2r (mm2, mm4); // mm4 = -C4*x4-C2*x6 C4*x4+C6*x6
+ punpckldq_r2r (mm5, mm5); // mm5 = x3 x1 x3 x1
+
+ pmaddwd_m2r (*(table+16), mm0); // mm0 = C4*x0-C2*x2 C4*x0-C6*x2
+ punpckhdq_r2r (mm6, mm6); // mm6 = x7 x5 x7 x5
+
+ movq_m2r (*(table+12), mm7); // mm7 = -C5 -C1 C7 C5
+ pmaddwd_r2r (mm5, mm1); // mm1 = C3*x1-C7*x3 C1*x1+C3*x3
+
+ paddd_m2r (*rounder, mm3); // mm3 += rounder
+ pmaddwd_r2r (mm6, mm7); // mm7 = -C1*x5-C5*x7 C5*x5+C7*x7
+
+ pmaddwd_m2r (*(table+20), mm2); // mm2 = C4*x4-C6*x6 -C4*x4+C2*x6
+ paddd_r2r (mm4, mm3); // mm3 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+24), mm5); // mm5 = C7*x1-C5*x3 C5*x1-C1*x3
+ movq_r2r (mm3, mm4); // mm4 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+28), mm6); // mm6 = C3*x5-C1*x7 C7*x5+C3*x7
+ paddd_r2r (mm7, mm1); // mm1 = b1 b0
+
+ paddd_m2r (*rounder, mm0); // mm0 += rounder
+ psubd_r2r (mm1, mm3); // mm3 = a1-b1 a0-b0 + rounder
+
+ psrad_i2r (ROW_SHIFT, mm3); // mm3 = y6 y7
+ paddd_r2r (mm4, mm1); // mm1 = a1+b1 a0+b0 + rounder
+
+ paddd_r2r (mm2, mm0); // mm0 = a3 a2 + rounder
+ psrad_i2r (ROW_SHIFT, mm1); // mm1 = y1 y0
+
+ paddd_r2r (mm6, mm5); // mm5 = b3 b2
+ movq_r2r (mm0, mm7); // mm7 = a3 a2 + rounder
+
+ paddd_r2r (mm5, mm0); // mm0 = a3+b3 a2+b2 + rounder
+ psubd_r2r (mm5, mm7); // mm7 = a3-b3 a2-b2 + rounder
+}
+
+static inline void RowTail( dctelem_t * row, int store )
+{
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ psrad_i2r (ROW_SHIFT, mm7); // mm7 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+
+ packssdw_r2r (mm3, mm7); // mm7 = y6 y7 y4 y5
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ movq_r2r (mm7, mm4); // mm4 = y6 y7 y4 y5
+
+ pslld_i2r (16, mm7); // mm7 = y7 0 y5 0
+
+ psrld_i2r (16, mm4); // mm4 = 0 y6 0 y4
+
+ por_r2r (mm4, mm7); // mm7 = y7 y6 y5 y4
+
+ // slot
+
+ movq_r2m (mm7, *(row+store+4)); // save y7 y6 y5 y4
+}
+
+static inline void RowMid( dctelem_t * row, int store,
+ int offset, dctelem_t * table )
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ psrad_i2r (ROW_SHIFT, mm7); // mm7 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ packssdw_r2r (mm3, mm7); // mm7 = y6 y7 y4 y5
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ movq_r2r (mm7, mm1); // mm1 = y6 y7 y4 y5
+
+ punpckldq_r2r (mm0, mm0); // mm0 = x2 x0 x2 x0
+ psrld_i2r (16, mm7); // mm7 = 0 y6 0 y4
+
+ movq_m2r (*table, mm3); // mm3 = C6 C4 C2 C4
+ pslld_i2r (16, mm1); // mm1 = y7 0 y5 0
+
+ movq_m2r (*(table+4), mm4); // mm4 = -C2 -C4 C6 C4
+ por_r2r (mm1, mm7); // mm7 = y7 y6 y5 y4
+
+ movq_m2r (*(table+8), mm1); // mm1 = -C7 C3 C3 C1
+ punpckhdq_r2r (mm2, mm2); // mm2 = x6 x4 x6 x4
+
+ movq_r2m (mm7, *(row+store+4)); // save y7 y6 y5 y4
+ pmaddwd_r2r (mm0, mm3); // mm3 = C4*x0+C6*x2 C4*x0+C2*x2
+}
+
+static inline void Col( dctelem_t * col, int offset )
+{
+#define T1 13036
+#define T2 27146
+#define T3 43790
+#define C4 23170
+
+ static short _T1[] ATTR_ALIGN(8) = {T1,T1,T1,T1};
+ static short _T2[] ATTR_ALIGN(8) = {T2,T2,T2,T2};
+ static short _T3[] ATTR_ALIGN(8) = {T3,T3,T3,T3};
+ static short _C4[] ATTR_ALIGN(8) = {C4,C4,C4,C4};
+ static mmx_t scratch0, scratch1;
+
+ /* column code adapted from peter gubanov */
+ /* http://www.elecard.com/peter/idct.shtml */
+
+ movq_m2r (*_T1, mm0); // mm0 = T1
+
+ movq_m2r (*(col+offset+1*8), mm1); // mm1 = x1
+ movq_r2r (mm0, mm2); // mm2 = T1
+
+ movq_m2r (*(col+offset+7*8), mm4); // mm4 = x7
+ pmulhw_r2r (mm1, mm0); // mm0 = T1*x1
+
+ movq_m2r (*_T3, mm5); // mm5 = T3
+ pmulhw_r2r (mm4, mm2); // mm2 = T1*x7
+
+ movq_m2r (*(col+offset+5*8), mm6); // mm6 = x5
+ movq_r2r (mm5, mm7); // mm7 = T3-1
+
+ movq_m2r (*(col+offset+3*8), mm3); // mm3 = x3
+ psubsw_r2r (mm4, mm0); // mm0 = v17
+
+ movq_m2r (*_T2, mm4); // mm4 = T2
+ pmulhw_r2r (mm3, mm5); // mm5 = (T3-1)*x3
+
+ paddsw_r2r (mm2, mm1); // mm1 = u17
+ pmulhw_r2r (mm6, mm7); // mm7 = (T3-1)*x5
+
+ //slot
+
+ movq_r2r (mm4, mm2); // mm2 = T2
+ paddsw_r2r (mm3, mm5); // mm5 = T3*x3
+
+ pmulhw_m2r (*(col+offset+2*8), mm4);// mm4 = T2*x2
+ paddsw_r2r (mm6, mm7); // mm7 = T3*x5
+
+ psubsw_r2r (mm6, mm5); // mm5 = v35
+ paddsw_r2r (mm3, mm7); // mm7 = u35
+
+ movq_m2r (*(col+offset+6*8), mm3); // mm3 = x6
+ movq_r2r (mm0, mm6); // mm6 = v17
+
+ pmulhw_r2r (mm3, mm2); // mm2 = T2*x6
+ psubsw_r2r (mm5, mm0); // mm0 = b3
+
+ psubsw_r2r (mm3, mm4); // mm4 = v26
+ paddsw_r2r (mm6, mm5); // mm5 = v12
+
+ movq_r2m (mm0, scratch0); // save b3
+ movq_r2r (mm1, mm6); // mm6 = u17
+
+ paddsw_m2r (*(col+offset+2*8), mm2);// mm2 = u26
+ paddsw_r2r (mm7, mm6); // mm6 = b0
+
+ psubsw_r2r (mm7, mm1); // mm1 = u12
+ movq_r2r (mm1, mm7); // mm7 = u12
+
+ movq_m2r (*(col+offset+0*8), mm3); // mm3 = x0
+ paddsw_r2r (mm5, mm1); // mm1 = u12+v12
+
+ movq_m2r (*_C4, mm0); // mm0 = C4/2
+ psubsw_r2r (mm5, mm7); // mm7 = u12-v12
+
+ movq_r2m (mm6, scratch1); // save b0
+ pmulhw_r2r (mm0, mm1); // mm1 = b1/2
+
+ movq_r2r (mm4, mm6); // mm6 = v26
+ pmulhw_r2r (mm0, mm7); // mm7 = b2/2
+
+ movq_m2r (*(col+offset+4*8), mm5); // mm5 = x4
+ movq_r2r (mm3, mm0); // mm0 = x0
+
+ psubsw_r2r (mm5, mm3); // mm3 = v04
+ paddsw_r2r (mm5, mm0); // mm0 = u04
+
+ paddsw_r2r (mm3, mm4); // mm4 = a1
+ movq_r2r (mm0, mm5); // mm5 = u04
+
+ psubsw_r2r (mm6, mm3); // mm3 = a2
+ paddsw_r2r (mm2, mm5); // mm5 = a0
+
+ paddsw_r2r (mm1, mm1); // mm1 = b1
+ psubsw_r2r (mm2, mm0); // mm0 = a3
+
+ paddsw_r2r (mm7, mm7); // mm7 = b2
+ movq_r2r (mm3, mm2); // mm2 = a2
+
+ movq_r2r (mm4, mm6); // mm6 = a1
+ paddsw_r2r (mm7, mm3); // mm3 = a2+b2
+
+ psraw_i2r (COL_SHIFT, mm3); // mm3 = y2
+ paddsw_r2r (mm1, mm4); // mm4 = a1+b1
+
+ psraw_i2r (COL_SHIFT, mm4); // mm4 = y1
+ psubsw_r2r (mm1, mm6); // mm6 = a1-b1
+
+ movq_m2r (scratch1, mm1); // mm1 = b0
+ psubsw_r2r (mm7, mm2); // mm2 = a2-b2
+
+ psraw_i2r (COL_SHIFT, mm6); // mm6 = y6
+ movq_r2r (mm5, mm7); // mm7 = a0
+
+ movq_r2m (mm4, *(col+offset+1*8)); // save y1
+ psraw_i2r (COL_SHIFT, mm2); // mm2 = y5
+
+ movq_r2m (mm3, *(col+offset+2*8)); // save y2
+ paddsw_r2r (mm1, mm5); // mm5 = a0+b0
+
+ movq_m2r (scratch0, mm4); // mm4 = b3
+ psubsw_r2r (mm1, mm7); // mm7 = a0-b0
+
+ psraw_i2r (COL_SHIFT, mm5); // mm5 = y0
+ movq_r2r (mm0, mm3); // mm3 = a3
+
+ movq_r2m (mm2, *(col+offset+5*8)); // save y5
+ psubsw_r2r (mm4, mm3); // mm3 = a3-b3
+
+ psraw_i2r (COL_SHIFT, mm7); // mm7 = y7
+ paddsw_r2r (mm0, mm4); // mm4 = a3+b3
+
+ movq_r2m (mm5, *(col+offset+0*8)); // save y0
+ psraw_i2r (COL_SHIFT, mm3); // mm3 = y4
+
+ movq_r2m (mm6, *(col+offset+6*8)); // save y6
+ psraw_i2r (COL_SHIFT, mm4); // mm4 = y3
+
+ movq_r2m (mm7, *(col+offset+7*8)); // save y7
+
+ movq_r2m (mm3, *(col+offset+4*8)); // save y4
+
+ movq_r2m (mm4, *(col+offset+3*8)); // save y3
+}
+
+
+static s32 rounder0[] ATTR_ALIGN(8) =
+ rounder ((1 << (COL_SHIFT - 1)) - 0.5);
+static s32 rounder4[] ATTR_ALIGN(8) = rounder (0);
+static s32 rounder1[] ATTR_ALIGN(8) =
+ rounder (1.25683487303); // C1*(C1/C4+C1+C7)/2
+static s32 rounder7[] ATTR_ALIGN(8) =
+ rounder (-0.25); // C1*(C7/C4+C7-C1)/2
+static s32 rounder2[] ATTR_ALIGN(8) =
+ rounder (0.60355339059); // C2 * (C6+C2)/2
+static s32 rounder6[] ATTR_ALIGN(8) =
+ rounder (-0.25); // C2 * (C6-C2)/2
+static s32 rounder3[] ATTR_ALIGN(8) =
+ rounder (0.087788325588); // C3*(-C3/C4+C3+C5)/2
+static s32 rounder5[] ATTR_ALIGN(8) =
+ rounder (-0.441341716183); // C3*(-C5/C4+C5-C3)/2
+
+static void IDCT( dctelem_t * p_block )
+{
+ static dctelem_t table04[] ATTR_ALIGN(16) =
+ table (22725, 21407, 19266, 16384, 12873, 8867, 4520);
+ static dctelem_t table17[] ATTR_ALIGN(16) =
+ table (31521, 29692, 26722, 22725, 17855, 12299, 6270);
+ static dctelem_t table26[] ATTR_ALIGN(16) =
+ table (29692, 27969, 25172, 21407, 16819, 11585, 5906);
+ static dctelem_t table35[] ATTR_ALIGN(16) =
+ table (26722, 25172, 22654, 19266, 15137, 10426, 5315);
+
+ RowHead( p_block, 0*8, table04 );
+ Row( table04, rounder0 );
+ RowMid( p_block, 0*8, 4*8, table04 );
+ Row( table04, rounder4 );
+ RowMid( p_block, 4*8, 1*8, table17 );
+ Row( table17, rounder1 );
+ RowMid( p_block, 1*8, 7*8, table17 );
+ Row( table17, rounder7 );
+ RowMid( p_block, 7*8, 2*8, table26 );
+ Row( table26, rounder2 );
+ RowMid( p_block, 2*8, 6*8, table26 );
+ Row( table26, rounder6 );
+ RowMid( p_block, 6*8, 3*8, table35 );
+ Row( table35, rounder3 );
+ RowMid( p_block, 3*8, 5*8, table35 );
+ Row( table35, rounder5 );
+ RowTail( p_block, 5*8);
+
+ Col( p_block, 0 );
+ Col( p_block, 4 );
+}
+
+static inline void RestoreCPUState( )
+{
+ /* reenables the FPU */
+ __asm__ __volatile__ ("emms");
+}
+
+#include "idct_sparse.h"
+#include "idct_decl.h"
--- /dev/null
+/*****************************************************************************
+ * idctmmxext.c : MMX EXT IDCT module
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: idctmmxext.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Michel Lespinasse <walken@zoy.org>
+ * Peter Gubanov <peter@elecard.net.ru>
+ * (from the LiViD project)
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "mmx.h"
+
+#include "idct.h"
+#include "block_mmx.h"
+
+static int Open( vlc_object_t *p_this );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("MMX EXT IDCT module") );
+ set_capability( "idct", 200 );
+ add_shortcut( "mmxext" );
+ add_requirement( MMXEXT );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * NormScan : This IDCT uses reordered coeffs, so we patch the scan table
+ *****************************************************************************/
+static void NormScan( u8 ppi_scan[2][64] )
+{
+ int i, j;
+
+ for( i = 0; i < 64; i++ )
+ {
+ j = ppi_scan[0][i];
+ ppi_scan[0][i] = (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2);
+
+ j = ppi_scan[1][i];
+ ppi_scan[1][i] = (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2);
+ }
+}
+
+/*****************************************************************************
+ * IDCT :
+ *****************************************************************************/
+#define ROW_SHIFT 11
+#define COL_SHIFT 6
+
+#define round(bias) ((int)(((bias)+0.5) * (1<<ROW_SHIFT)))
+#define rounder(bias) {round (bias), round (bias)}
+
+#define table(c1,c2,c3,c4,c5,c6,c7) { c4, c2, -c4, -c2, \
+ c4, c6, c4, c6, \
+ c1, c3, -c1, -c5, \
+ c5, c7, c3, -c7, \
+ c4, -c6, c4, -c6, \
+ -c4, c2, c4, -c2, \
+ c5, -c1, c3, -c1, \
+ c7, c3, c7, -c5 }
+
+static inline void RowHead( dctelem_t * row, int offset, dctelem_t * table )
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_m2r (*table, mm3); // mm3 = -C2 -C4 C2 C4
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ movq_m2r (*(table+4), mm4); // mm4 = C6 C4 C6 C4
+ pmaddwd_r2r (mm0, mm3); // mm3 = -C4*x4-C2*x6 C4*x0+C2*x2
+
+ pshufw_r2r (mm2, mm2, 0x4e); // mm2 = x2 x0 x6 x4
+}
+
+static inline void Row( dctelem_t * table, s32 * rounder )
+{
+ movq_m2r (*(table+8), mm1); // mm1 = -C5 -C1 C3 C1
+ pmaddwd_r2r (mm2, mm4); // mm4 = C4*x0+C6*x2 C4*x4+C6*x6
+
+ pmaddwd_m2r (*(table+16), mm0); // mm0 = C4*x4-C6*x6 C4*x0-C6*x2
+ pshufw_r2r (mm6, mm6, 0x4e); // mm6 = x3 x1 x7 x5
+
+ movq_m2r (*(table+12), mm7); // mm7 = -C7 C3 C7 C5
+ pmaddwd_r2r (mm5, mm1); // mm1 = -C1*x5-C5*x7 C1*x1+C3*x3
+
+ paddd_m2r (*rounder, mm3); // mm3 += rounder
+ pmaddwd_r2r (mm6, mm7); // mm7 = C3*x1-C7*x3 C5*x5+C7*x7
+
+ pmaddwd_m2r (*(table+20), mm2); // mm2 = C4*x0-C2*x2 -C4*x4+C2*x6
+ paddd_r2r (mm4, mm3); // mm3 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+24), mm5); // mm5 = C3*x5-C1*x7 C5*x1-C1*x3
+ movq_r2r (mm3, mm4); // mm4 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+28), mm6); // mm6 = C7*x1-C5*x3 C7*x5+C3*x7
+ paddd_r2r (mm7, mm1); // mm1 = b1 b0
+
+ paddd_m2r (*rounder, mm0); // mm0 += rounder
+ psubd_r2r (mm1, mm3); // mm3 = a1-b1 a0-b0 + rounder
+
+ psrad_i2r (ROW_SHIFT, mm3); // mm3 = y6 y7
+ paddd_r2r (mm4, mm1); // mm1 = a1+b1 a0+b0 + rounder
+
+ paddd_r2r (mm2, mm0); // mm0 = a3 a2 + rounder
+ psrad_i2r (ROW_SHIFT, mm1); // mm1 = y1 y0
+
+ paddd_r2r (mm6, mm5); // mm5 = b3 b2
+ movq_r2r (mm0, mm4); // mm4 = a3 a2 + rounder
+
+ paddd_r2r (mm5, mm0); // mm0 = a3+b3 a2+b2 + rounder
+ psubd_r2r (mm5, mm4); // mm4 = a3-b3 a2-b2 + rounder
+}
+
+static inline void RowTail( dctelem_t * row, int store )
+{
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ psrad_i2r (ROW_SHIFT, mm4); // mm4 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+
+ packssdw_r2r (mm3, mm4); // mm4 = y6 y7 y4 y5
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ pshufw_r2r (mm4, mm4, 0xb1); // mm4 = y7 y6 y5 y4
+
+ // slot
+ movq_r2m (mm4, *(row+store+4)); // save y7 y6 y5 y4
+}
+
+static inline void RowMid( dctelem_t * row, int store,
+ int offset, dctelem_t * table)
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ psrad_i2r (ROW_SHIFT, mm4); // mm4 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ packssdw_r2r (mm3, mm4); // mm4 = y6 y7 y4 y5
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ pshufw_r2r (mm4, mm4, 0xb1); // mm4 = y7 y6 y5 y4
+
+ movq_m2r (*table, mm3); // mm3 = -C2 -C4 C2 C4
+ movq_r2m (mm4, *(row+store+4)); // save y7 y6 y5 y4
+
+ pmaddwd_r2r (mm0, mm3); // mm3 = -C4*x4-C2*x6 C4*x0+C2*x2
+
+ movq_m2r (*(table+4), mm4); // mm4 = C6 C4 C6 C4
+ pshufw_r2r (mm2, mm2, 0x4e); // mm2 = x2 x0 x6 x4
+}
+
+static inline void Col( dctelem_t * col, int offset )
+{
+#define T1 13036
+#define T2 27146
+#define T3 43790
+#define C4 23170
+
+ static short _T1[] ATTR_ALIGN(8) = {T1,T1,T1,T1};
+ static short _T2[] ATTR_ALIGN(8) = {T2,T2,T2,T2};
+ static short _T3[] ATTR_ALIGN(8) = {T3,T3,T3,T3};
+ static short _C4[] ATTR_ALIGN(8) = {C4,C4,C4,C4};
+ static mmx_t scratch0, scratch1;
+
+ /* column code adapted from peter gubanov */
+ /* http://www.elecard.com/peter/idct.shtml */
+
+ movq_m2r (*_T1, mm0); // mm0 = T1
+
+ movq_m2r (*(col+offset+1*8), mm1); // mm1 = x1
+ movq_r2r (mm0, mm2); // mm2 = T1
+
+ movq_m2r (*(col+offset+7*8), mm4); // mm4 = x7
+ pmulhw_r2r (mm1, mm0); // mm0 = T1*x1
+
+ movq_m2r (*_T3, mm5); // mm5 = T3
+ pmulhw_r2r (mm4, mm2); // mm2 = T1*x7
+
+ movq_m2r (*(col+offset+5*8), mm6); // mm6 = x5
+ movq_r2r (mm5, mm7); // mm7 = T3-1
+
+ movq_m2r (*(col+offset+3*8), mm3); // mm3 = x3
+ psubsw_r2r (mm4, mm0); // mm0 = v17
+
+ movq_m2r (*_T2, mm4); // mm4 = T2
+ pmulhw_r2r (mm3, mm5); // mm5 = (T3-1)*x3
+
+ paddsw_r2r (mm2, mm1); // mm1 = u17
+ pmulhw_r2r (mm6, mm7); // mm7 = (T3-1)*x5
+
+ //slot
+
+ movq_r2r (mm4, mm2); // mm2 = T2
+ paddsw_r2r (mm3, mm5); // mm5 = T3*x3
+
+ pmulhw_m2r (*(col+offset+2*8), mm4);// mm4 = T2*x2
+ paddsw_r2r (mm6, mm7); // mm7 = T3*x5
+
+ psubsw_r2r (mm6, mm5); // mm5 = v35
+ paddsw_r2r (mm3, mm7); // mm7 = u35
+
+ movq_m2r (*(col+offset+6*8), mm3); // mm3 = x6
+ movq_r2r (mm0, mm6); // mm6 = v17
+
+ pmulhw_r2r (mm3, mm2); // mm2 = T2*x6
+ psubsw_r2r (mm5, mm0); // mm0 = b3
+
+ psubsw_r2r (mm3, mm4); // mm4 = v26
+ paddsw_r2r (mm6, mm5); // mm5 = v12
+
+ movq_r2m (mm0, scratch0); // save b3
+ movq_r2r (mm1, mm6); // mm6 = u17
+
+ paddsw_m2r (*(col+offset+2*8), mm2);// mm2 = u26
+ paddsw_r2r (mm7, mm6); // mm6 = b0
+
+ psubsw_r2r (mm7, mm1); // mm1 = u12
+ movq_r2r (mm1, mm7); // mm7 = u12
+
+ movq_m2r (*(col+offset+0*8), mm3); // mm3 = x0
+ paddsw_r2r (mm5, mm1); // mm1 = u12+v12
+
+ movq_m2r (*_C4, mm0); // mm0 = C4/2
+ psubsw_r2r (mm5, mm7); // mm7 = u12-v12
+
+ movq_r2m (mm6, scratch1); // save b0
+ pmulhw_r2r (mm0, mm1); // mm1 = b1/2
+
+ movq_r2r (mm4, mm6); // mm6 = v26
+ pmulhw_r2r (mm0, mm7); // mm7 = b2/2
+
+ movq_m2r (*(col+offset+4*8), mm5); // mm5 = x4
+ movq_r2r (mm3, mm0); // mm0 = x0
+
+ psubsw_r2r (mm5, mm3); // mm3 = v04
+ paddsw_r2r (mm5, mm0); // mm0 = u04
+
+ paddsw_r2r (mm3, mm4); // mm4 = a1
+ movq_r2r (mm0, mm5); // mm5 = u04
+
+ psubsw_r2r (mm6, mm3); // mm3 = a2
+ paddsw_r2r (mm2, mm5); // mm5 = a0
+
+ paddsw_r2r (mm1, mm1); // mm1 = b1
+ psubsw_r2r (mm2, mm0); // mm0 = a3
+
+ paddsw_r2r (mm7, mm7); // mm7 = b2
+ movq_r2r (mm3, mm2); // mm2 = a2
+
+ movq_r2r (mm4, mm6); // mm6 = a1
+ paddsw_r2r (mm7, mm3); // mm3 = a2+b2
+
+ psraw_i2r (COL_SHIFT, mm3); // mm3 = y2
+ paddsw_r2r (mm1, mm4); // mm4 = a1+b1
+
+ psraw_i2r (COL_SHIFT, mm4); // mm4 = y1
+ psubsw_r2r (mm1, mm6); // mm6 = a1-b1
+
+ movq_m2r (scratch1, mm1); // mm1 = b0
+ psubsw_r2r (mm7, mm2); // mm2 = a2-b2
+
+ psraw_i2r (COL_SHIFT, mm6); // mm6 = y6
+ movq_r2r (mm5, mm7); // mm7 = a0
+
+ movq_r2m (mm4, *(col+offset+1*8)); // save y1
+ psraw_i2r (COL_SHIFT, mm2); // mm2 = y5
+
+ movq_r2m (mm3, *(col+offset+2*8)); // save y2
+ paddsw_r2r (mm1, mm5); // mm5 = a0+b0
+
+ movq_m2r (scratch0, mm4); // mm4 = b3
+ psubsw_r2r (mm1, mm7); // mm7 = a0-b0
+
+ psraw_i2r (COL_SHIFT, mm5); // mm5 = y0
+ movq_r2r (mm0, mm3); // mm3 = a3
+
+ movq_r2m (mm2, *(col+offset+5*8)); // save y5
+ psubsw_r2r (mm4, mm3); // mm3 = a3-b3
+
+ psraw_i2r (COL_SHIFT, mm7); // mm7 = y7
+ paddsw_r2r (mm0, mm4); // mm4 = a3+b3
+
+ movq_r2m (mm5, *(col+offset+0*8)); // save y0
+ psraw_i2r (COL_SHIFT, mm3); // mm3 = y4
+
+ movq_r2m (mm6, *(col+offset+6*8)); // save y6
+ psraw_i2r (COL_SHIFT, mm4); // mm4 = y3
+
+ movq_r2m (mm7, *(col+offset+7*8)); // save y7
+
+ movq_r2m (mm3, *(col+offset+4*8)); // save y4
+
+ movq_r2m (mm4, *(col+offset+3*8)); // save y3
+}
+
+
+static s32 rounder0[] ATTR_ALIGN(8) =
+ rounder ((1 << (COL_SHIFT - 1)) - 0.5);
+static s32 rounder4[] ATTR_ALIGN(8) = rounder (0);
+static s32 rounder1[] ATTR_ALIGN(8) =
+ rounder (1.25683487303); // C1*(C1/C4+C1+C7)/2
+static s32 rounder7[] ATTR_ALIGN(8) =
+ rounder (-0.25); // C1*(C7/C4+C7-C1)/2
+static s32 rounder2[] ATTR_ALIGN(8) =
+ rounder (0.60355339059); // C2 * (C6+C2)/2
+static s32 rounder6[] ATTR_ALIGN(8) =
+ rounder (-0.25); // C2 * (C6-C2)/2
+static s32 rounder3[] ATTR_ALIGN(8) =
+ rounder (0.087788325588); // C3*(-C3/C4+C3+C5)/2
+static s32 rounder5[] ATTR_ALIGN(8) =
+ rounder (-0.441341716183); // C3*(-C5/C4+C5-C3)/2
+
+static void IDCT( dctelem_t * p_block )
+{
+ static dctelem_t table04[] ATTR_ALIGN(16) =
+ table (22725, 21407, 19266, 16384, 12873, 8867, 4520);
+ static dctelem_t table17[] ATTR_ALIGN(16) =
+ table (31521, 29692, 26722, 22725, 17855, 12299, 6270);
+ static dctelem_t table26[] ATTR_ALIGN(16) =
+ table (29692, 27969, 25172, 21407, 16819, 11585, 5906);
+ static dctelem_t table35[] ATTR_ALIGN(16) =
+ table (26722, 25172, 22654, 19266, 15137, 10426, 5315);
+
+ RowHead( p_block, 0*8, table04 );
+ Row( table04, rounder0 );
+ RowMid( p_block, 0*8, 4*8, table04 );
+ Row( table04, rounder4 );
+ RowMid( p_block, 4*8, 1*8, table17 );
+ Row( table17, rounder1 );
+ RowMid( p_block, 1*8, 7*8, table17 );
+ Row( table17, rounder7 );
+ RowMid( p_block, 7*8, 2*8, table26 );
+ Row( table26, rounder2 );
+ RowMid( p_block, 2*8, 6*8, table26 );
+ Row( table26, rounder6 );
+ RowMid( p_block, 6*8, 3*8, table35 );
+ Row( table35, rounder3 );
+ RowMid( p_block, 3*8, 5*8, table35 );
+ Row( table35, rounder5 );
+ RowTail( p_block, 5*8);
+
+ Col( p_block, 0 );
+ Col( p_block, 4 );
+}
+
+static inline void RestoreCPUState( )
+{
+ /* reenables the FPU */
+ __asm__ __volatile__ ("emms");
+}
+
+#include "idct_sparse.h"
+#include "idct_decl.h"
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+motion_SOURCES = motion.c
+motionmmx_SOURCES = motionmmx.c
+motionmmxext_SOURCES = motionmmxext.c
+motion3dnow_SOURCES = motion3dnow.c
+motionaltivec_SOURCES = motionaltivec.c
--- /dev/null
+/*****************************************************************************
+ * motion.c : C motion compensation module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: motion.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Michel Lespinasse <walken@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * Local prototype
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("motion compensation module") );
+ set_capability( "motion compensation", 50 );
+ add_shortcut( "c" );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Simple motion compensation in C
+ *****************************************************************************/
+
+#define avg2(a,b) ((a+b+1)>>1)
+#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
+
+#define predict_o(i) (ref[i])
+#define predict_x(i) (avg2 (ref[i], ref[i+1]))
+#define predict_y(i) (avg2 (ref[i], (ref+stride)[i]))
+#define predict_xy(i) (avg4 (ref[i], ref[i+1], (ref+stride)[i], (ref+stride)[i+1]))
+
+#define put(predictor,i) dest[i] = predictor (i)
+#define avg(predictor,i) dest[i] = avg2 (predictor (i), dest[i])
+
+// mc function template
+
+#define MC_FUNC(op,xy) \
+static void MC_##op##_##xy##16_c (yuv_data_t * dest, yuv_data_t * ref, \
+ int stride, int height) \
+{ \
+ do { \
+ op (predict_##xy, 0); \
+ op (predict_##xy, 1); \
+ op (predict_##xy, 2); \
+ op (predict_##xy, 3); \
+ op (predict_##xy, 4); \
+ op (predict_##xy, 5); \
+ op (predict_##xy, 6); \
+ op (predict_##xy, 7); \
+ op (predict_##xy, 8); \
+ op (predict_##xy, 9); \
+ op (predict_##xy, 10); \
+ op (predict_##xy, 11); \
+ op (predict_##xy, 12); \
+ op (predict_##xy, 13); \
+ op (predict_##xy, 14); \
+ op (predict_##xy, 15); \
+ ref += stride; \
+ dest += stride; \
+ } while (--height); \
+} \
+static void MC_##op##_##xy##8_c (yuv_data_t * dest, yuv_data_t * ref, \
+ int stride, int height) \
+{ \
+ do { \
+ op (predict_##xy, 0); \
+ op (predict_##xy, 1); \
+ op (predict_##xy, 2); \
+ op (predict_##xy, 3); \
+ op (predict_##xy, 4); \
+ op (predict_##xy, 5); \
+ op (predict_##xy, 6); \
+ op (predict_##xy, 7); \
+ ref += stride; \
+ dest += stride; \
+ } while (--height); \
+}
+
+// definitions of the actual mc functions
+
+MC_FUNC (put,o)
+MC_FUNC (avg,o)
+MC_FUNC (put,x)
+MC_FUNC (avg,x)
+MC_FUNC (put,y)
+MC_FUNC (avg,y)
+MC_FUNC (put,xy)
+MC_FUNC (avg,xy)
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void (* ppppf_motion[2][2][4])( yuv_data_t *, yuv_data_t *, int, int ) =
+{
+ /* Copying functions */
+ {
+ /* Width == 16 */
+ { MC_put_o16_c, MC_put_x16_c, MC_put_y16_c, MC_put_xy16_c },
+ /* Width == 8 */
+ { MC_put_o8_c, MC_put_x8_c, MC_put_y8_c, MC_put_xy8_c }
+ },
+ /* Averaging functions */
+ {
+ /* Width == 16 */
+ { MC_avg_o16_c, MC_avg_x16_c, MC_avg_y16_c, MC_avg_xy16_c },
+ /* Width == 8 */
+ { MC_avg_o8_c, MC_avg_x8_c, MC_avg_y8_c, MC_avg_xy8_c }
+ }
+};
+
+static int Open ( vlc_object_t *p_this )
+{
+ p_this->p_private = ppppf_motion;
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * motion3dnow.c : 3D Now! motion compensation module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: motion3dnow.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Michel Lespinasse <walken@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "mmx.h"
+
+/*****************************************************************************
+ * Local prototype.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("3D Now! motion compensation module") );
+ set_capability( "motion compensation", 150 );
+ add_requirement( 3DNOW );
+ add_shortcut( "3dn" );
+ add_shortcut( "3dnow" );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Motion compensation in 3D Now! (OK I know this does MMXEXT too and it's ugly)
+ *****************************************************************************/
+
+#define CPU_MMXEXT 0
+#define CPU_3DNOW 1
+
+
+//CPU_MMXEXT/CPU_3DNOW adaptation layer
+
+#define pavg_r2r(src,dest) \
+do { \
+ if (cpu == CPU_MMXEXT) \
+ pavgb_r2r (src, dest); \
+ else \
+ pavgusb_r2r (src, dest); \
+} while (0)
+
+#define pavg_m2r(src,dest) \
+do { \
+ if (cpu == CPU_MMXEXT) \
+ pavgb_m2r (src, dest); \
+ else \
+ pavgusb_m2r (src, dest); \
+} while (0)
+
+
+//CPU_MMXEXT code
+
+
+static inline void MC_put1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_r2m (mm0, *dest);
+ ref += stride;
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_put1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ pavg_m2r (*dest, mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ pavg_m2r (*dest, mm0);
+ pavg_m2r (*(dest+8), mm1);
+ movq_r2m (mm0, *dest);
+ ref += stride;
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_put2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ pavg_m2r (*(ref+offset), mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_put2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ pavg_m2r (*(ref+offset), mm0);
+ pavg_m2r (*(ref+offset+8), mm1);
+ movq_r2m (mm0, *dest);
+ ref += stride;
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ pavg_m2r (*(ref+offset), mm0);
+ pavg_m2r (*dest, mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ pavg_m2r (*(ref+offset), mm0);
+ pavg_m2r (*(ref+offset+8), mm1);
+ pavg_m2r (*dest, mm0);
+ pavg_m2r (*(dest+8), mm1);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static mmx_t mask_one = {0x0101010101010101LL};
+
+static inline void MC_put4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+1), mm1);
+ movq_r2r (mm0, mm7);
+ pxor_r2r (mm1, mm7);
+ pavg_r2r (mm1, mm0);
+ ref += stride;
+
+ do {
+ movq_m2r (*ref, mm2);
+ movq_r2r (mm0, mm5);
+
+ movq_m2r (*(ref+1), mm3);
+ movq_r2r (mm2, mm6);
+
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm3, mm2);
+
+ por_r2r (mm6, mm7);
+ pxor_r2r (mm2, mm5);
+
+ pand_r2r (mm5, mm7);
+ pavg_r2r (mm2, mm0);
+
+ pand_m2r (mask_one, mm7);
+
+ psubusb_r2r (mm7, mm0);
+
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+
+ movq_r2r (mm6, mm7); // unroll !
+ movq_r2r (mm2, mm0); // unroll !
+ } while (--height);
+}
+
+static inline void MC_put4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+stride+1), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+1), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_r2m (mm0, *dest);
+
+ movq_m2r (*(ref+8), mm0);
+ movq_m2r (*(ref+stride+9), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+9), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride+8), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ ref += stride;
+ movq_r2m (mm0, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+stride+1), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+1), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_m2r (*dest, mm1);
+ pavg_r2r (mm1, mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+stride+1), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+1), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_m2r (*dest, mm1);
+ pavg_r2r (mm1, mm0);
+ movq_r2m (mm0, *dest);
+
+ movq_m2r (*(ref+8), mm0);
+ movq_m2r (*(ref+stride+9), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+9), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride+8), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_m2r (*(dest+8), mm1);
+ pavg_r2r (mm1, mm0);
+ ref += stride;
+ movq_r2m (mm0, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static void MC_avg_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_16 (height, dest, ref, stride);
+}
+
+static void MC_put_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_8 (height, dest, ref, stride);
+}
+
+static void MC_avg_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_avg_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_put_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_put_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_avg_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_put_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_put_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg4_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg4_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put4_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put4_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+
+static void MC_avg_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_16 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_avg_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_8 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_put_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_16 (height, dest, ref, stride);
+}
+
+static void MC_put_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_8 (height, dest, ref, stride);
+}
+
+static void MC_avg_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_avg_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_put_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_put_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_avg_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_avg_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_put_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_put_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_avg_xy16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg4_16 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_avg_xy8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg4_8 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_put_xy16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put4_16 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_put_xy8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put4_8 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void (* ppppf_motion[2][2][4])( yuv_data_t *, yuv_data_t *, int, int ) =
+{
+ /* Copying functions */
+ {
+ /* Width == 16 */
+ { MC_put_16_3dnow, MC_put_x16_3dnow, MC_put_y16_3dnow, MC_put_xy16_3dnow },
+ /* Width == 8 */
+ { MC_put_8_3dnow, MC_put_x8_3dnow, MC_put_y8_3dnow, MC_put_xy8_3dnow }
+ },
+ /* Averaging functions */
+ {
+ /* Width == 16 */
+ { MC_avg_16_3dnow, MC_avg_x16_3dnow, MC_avg_y16_3dnow, MC_avg_xy16_3dnow },
+ /* Width == 8 */
+ { MC_avg_8_3dnow, MC_avg_x8_3dnow, MC_avg_y8_3dnow, MC_avg_xy8_3dnow }
+ }
+};
+
+static int Open ( vlc_object_t *p_this )
+{
+ p_this->p_private = ppppf_motion;
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * motionaltivec.c : AltiVec motion compensation module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: motionaltivec.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Michel Lespinasse <walken@zoy.org>
+ * Paul Mackerras <paulus@linuxcare.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#ifndef __BUILD_ALTIVEC_ASM__
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h> /* int16_t .. */
+#endif
+
+/*****************************************************************************
+ * Local prototype
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("AltiVec motion compensation module") );
+ set_capability( "motion compensation", 150 );
+ add_requirement( ALTIVEC );
+ add_shortcut( "altivec" );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Motion compensation in AltiVec
+ *****************************************************************************/
+
+#ifndef CAN_COMPILE_C_ALTIVEC
+
+/*
+ * The asm code is generated with:
+ *
+ * gcc-2.95 -fvec -D__BUILD_ALTIVEC_ASM__ -O9 -fomit-frame-pointer -mregnames -S
+ * motion_comp_altivec.c
+ *
+ * sed 's/.L/._L/g' motion_comp_altivec.s |
+ * awk '{args=""; len=split ($2, arg, ",");
+ * for (i=1; i<=len; i++) { a=arg[i]; if (i<len) a=a",";
+ * args = args sprintf ("%-6s", a) }
+ * printf ("\t\"\t%-16s%-24s\\n\"\n", $1, args) }' |
+ * unexpand -a
+ */
+
+static void MC_put_o_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " srawi %r6, %r6, 1 \n"
+ " li %r9, 15 \n"
+ " addi %r6, %r6, -1 \n"
+ " lvsl %v12, 0, %r4 \n"
+ " mtctr %r6 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " add %r0, %r5, %r5 \n"
+ " vperm %v13, %v1, %v0, %v12 \n"
+ " add %r4, %r4, %r5 \n"
+ "._L6: \n"
+ " li %r9, 15 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " stvx %v13, 0, %r3 \n"
+ " vperm %v13, %v1, %v0, %v12 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " stvx %v13, %r5, %r3 \n"
+ " vperm %v13, %v1, %v0, %v12 \n"
+ " add %r4, %r4, %r5 \n"
+ " add %r3, %r3, %r0 \n"
+ " bdnz ._L6 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v1, 0, %r4 \n"
+ " stvx %v13, 0, %r3 \n"
+ " vperm %v13, %v1, %v0, %v12 \n"
+ " stvx %v13, %r5, %r3 \n"
+ );
+}
+
+static void MC_put_o_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v12, 0, %r4 \n"
+ " lvsl %v1, %r5, %r4 \n"
+ " vmrghb %v12, %v12, %v12 \n"
+ " srawi %r6, %r6, 1 \n"
+ " li %r9, 7 \n"
+ " vmrghb %v1, %v1, %v1 \n"
+ " addi %r6, %r6, -1 \n"
+ " vpkuhum %v10, %v12, %v12 \n"
+ " lvx %v13, 0, %r4 \n"
+ " mtctr %r6 \n"
+ " vpkuhum %v11, %v1, %v1 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v12, %v13, %v0, %v10 \n"
+ "._L11: \n"
+ " li %r9, 7 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " stvewx %v12, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vperm %v1, %v13, %v0, %v11 \n"
+ " stvewx %v12, %r9, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " li %r9, 7 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " add %r3, %r3, %r5 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " vperm %v12, %v13, %v0, %v10 \n"
+ " li %r9, 4 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " add %r3, %r3, %r5 \n"
+ " bdnz ._L11 \n"
+ " li %r9, 7 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " stvewx %v12, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vperm %v1, %v13, %v0, %v11 \n"
+ " stvewx %v12, %r9, %r3 \n"
+ " add %r3, %r3, %r5 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ );
+}
+
+static void MC_put_x_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v11, 0, %r4 \n"
+ " vspltisb %v0, 1 \n"
+ " li %r9, 16 \n"
+ " lvx %v12, 0, %r4 \n"
+ " vaddubm %v10, %v11, %v0 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v1, %v12, %v13, %v10 \n"
+ " vperm %v0, %v12, %v13, %v11 \n"
+ " mtctr %r6 \n"
+ " add %r0, %r5, %r5 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ "._L16: \n"
+ " li %r9, 16 \n"
+ " lvx %v12, 0, %r4 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " stvx %v0, 0, %r3 \n"
+ " vperm %v1, %v12, %v13, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v0, %v12, %v13, %v11 \n"
+ " lvx %v12, 0, %r4 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " stvx %v0, %r5, %r3 \n"
+ " vperm %v1, %v12, %v13, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v0, %v12, %v13, %v11 \n"
+ " add %r3, %r3, %r0 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " bdnz ._L16 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " lvx %v12, 0, %r4 \n"
+ " stvx %v0, 0, %r3 \n"
+ " vperm %v1, %v12, %v13, %v10 \n"
+ " vperm %v0, %v12, %v13, %v11 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " stvx %v0, %r5, %r3 \n"
+ );
+}
+
+static void MC_put_x_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v0, 0, %r4 \n"
+ " vspltisb %v13, 1 \n"
+ " lvsl %v10, %r5, %r4 \n"
+ " vmrghb %v0, %v0, %v0 \n"
+ " li %r9, 8 \n"
+ " lvx %v11, 0, %r4 \n"
+ " vmrghb %v10, %v10, %v10 \n"
+ " vpkuhum %v8, %v0, %v0 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " vpkuhum %v9, %v10, %v10 \n"
+ " vaddubm %v7, %v8, %v13 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v1, %v11, %v12, %v8 \n"
+ " mtctr %r6 \n"
+ " vaddubm %v13, %v9, %v13 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v0, %v11, %v12, %v7 \n"
+ " vavgub %v0, %v1, %v0 \n"
+ "._L21: \n"
+ " li %r9, 8 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " stvewx %v0, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vperm %v1, %v11, %v12, %v13 \n"
+ " stvewx %v0, %r9, %r3 \n"
+ " vperm %v0, %v11, %v12, %v9 \n"
+ " add %r4, %r4, %r5 \n"
+ " li %r9, 8 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " vavgub %v10, %v0, %v1 \n"
+ " lvx %v11, 0, %r4 \n"
+ " add %r3, %r3, %r5 \n"
+ " stvewx %v10, 0, %r3 \n"
+ " vperm %v1, %v11, %v12, %v7 \n"
+ " vperm %v0, %v11, %v12, %v8 \n"
+ " li %r9, 4 \n"
+ " stvewx %v10, %r9, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " add %r3, %r3, %r5 \n"
+ " bdnz ._L21 \n"
+ " li %r9, 8 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " stvewx %v0, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vperm %v1, %v11, %v12, %v13 \n"
+ " stvewx %v0, %r9, %r3 \n"
+ " vperm %v0, %v11, %v12, %v9 \n"
+ " add %r3, %r3, %r5 \n"
+ " vavgub %v10, %v0, %v1 \n"
+ " stvewx %v10, 0, %r3 \n"
+ " stvewx %v10, %r9, %r3 \n"
+ );
+}
+
+static void MC_put_y_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " li %r9, 15 \n"
+ " lvsl %v10, 0, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v12, %v13, %v1, %v10 \n"
+ " srawi %r6, %r6, 1 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v11, %v13, %v1, %v10 \n"
+ " mtctr %r6 \n"
+ " add %r0, %r5, %r5 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v12, %v11 \n"
+ "._L26: \n"
+ " li %r9, 15 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " stvx %v0, 0, %r3 \n"
+ " vperm %v12, %v13, %v1, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " vavgub %v0, %v12, %v11 \n"
+ " stvx %v0, %r5, %r3 \n"
+ " vperm %v11, %v13, %v1, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " add %r3, %r3, %r0 \n"
+ " vavgub %v0, %v12, %v11 \n"
+ " bdnz ._L26 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " stvx %v0, 0, %r3 \n"
+ " vperm %v12, %v13, %v1, %v10 \n"
+ " vavgub %v0, %v12, %v11 \n"
+ " stvx %v0, %r5, %r3 \n"
+ );
+}
+
+static void MC_put_y_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v13, 0, %r4 \n"
+ " lvsl %v11, %r5, %r4 \n"
+ " vmrghb %v13, %v13, %v13 \n"
+ " li %r9, 7 \n"
+ " lvx %v12, 0, %r4 \n"
+ " vmrghb %v11, %v11, %v11 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " vpkuhum %v9, %v13, %v13 \n"
+ " add %r4, %r4, %r5 \n"
+ " vpkuhum %v10, %v11, %v11 \n"
+ " vperm %v13, %v12, %v1, %v9 \n"
+ " srawi %r6, %r6, 1 \n"
+ " lvx %v12, 0, %r4 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v11, %v12, %v1, %v10 \n"
+ " mtctr %r6 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v13, %v11 \n"
+ "._L31: \n"
+ " li %r9, 7 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvx %v12, 0, %r4 \n"
+ " stvewx %v0, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vperm %v13, %v12, %v1, %v9 \n"
+ " stvewx %v0, %r9, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v13, %v11 \n"
+ " li %r9, 7 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvx %v12, 0, %r4 \n"
+ " add %r3, %r3, %r5 \n"
+ " stvewx %v0, 0, %r3 \n"
+ " vperm %v11, %v12, %v1, %v10 \n"
+ " li %r9, 4 \n"
+ " stvewx %v0, %r9, %r3 \n"
+ " vavgub %v0, %v13, %v11 \n"
+ " add %r4, %r4, %r5 \n"
+ " add %r3, %r3, %r5 \n"
+ " bdnz ._L31 \n"
+ " li %r9, 7 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvx %v12, 0, %r4 \n"
+ " stvewx %v0, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vperm %v13, %v12, %v1, %v9 \n"
+ " stvewx %v0, %r9, %r3 \n"
+ " add %r3, %r3, %r5 \n"
+ " vavgub %v0, %v13, %v11 \n"
+ " stvewx %v0, 0, %r3 \n"
+ " stvewx %v0, %r9, %r3 \n"
+ );
+}
+
+static void MC_put_xy_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v5, 0, %r4 \n"
+ " vspltisb %v3, 1 \n"
+ " li %r9, 16 \n"
+ " lvx %v1, 0, %r4 \n"
+ " vaddubm %v4, %v5, %v3 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v10, %v1, %v0, %v4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " vperm %v11, %v1, %v0, %v5 \n"
+ " addi %r6, %r6, -1 \n"
+ " lvx %v1, 0, %r4 \n"
+ " mtctr %r6 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " add %r0, %r5, %r5 \n"
+ " vperm %v10, %v1, %v0, %v4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v11, %v1, %v0, %v5 \n"
+ " vxor %v6, %v11, %v10 \n"
+ " vavgub %v7, %v11, %v10 \n"
+ " vor %v0, %v8, %v6 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vand %v0, %v3, %v0 \n"
+ " vavgub %v1, %v9, %v7 \n"
+ " vand %v0, %v0, %v13 \n"
+ " vsububm %v13, %v1, %v0 \n"
+ "._L36: \n"
+ " li %r9, 16 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " stvx %v13, 0, %r3 \n"
+ " vperm %v10, %v1, %v0, %v4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v11, %v1, %v0, %v5 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v10, %v1, %v0, %v4 \n"
+ " vavgub %v12, %v9, %v7 \n"
+ " vperm %v11, %v1, %v0, %v5 \n"
+ " vor %v13, %v8, %v6 \n"
+ " vxor %v0, %v9, %v7 \n"
+ " vxor %v6, %v11, %v10 \n"
+ " vand %v13, %v3, %v13 \n"
+ " vavgub %v7, %v11, %v10 \n"
+ " vor %v1, %v8, %v6 \n"
+ " vand %v13, %v13, %v0 \n"
+ " vxor %v0, %v9, %v7 \n"
+ " vand %v1, %v3, %v1 \n"
+ " vsububm %v13, %v12, %v13 \n"
+ " vand %v1, %v1, %v0 \n"
+ " stvx %v13, %r5, %r3 \n"
+ " vavgub %v0, %v9, %v7 \n"
+ " add %r3, %r3, %r0 \n"
+ " vsububm %v13, %v0, %v1 \n"
+ " bdnz ._L36 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v1, 0, %r4 \n"
+ " stvx %v13, 0, %r3 \n"
+ " vperm %v10, %v1, %v0, %v4 \n"
+ " vperm %v11, %v1, %v0, %v5 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vor %v0, %v8, %v6 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vand %v0, %v3, %v0 \n"
+ " vavgub %v1, %v9, %v7 \n"
+ " vand %v0, %v0, %v13 \n"
+ " vsububm %v13, %v1, %v0 \n"
+ " stvx %v13, %r5, %r3 \n"
+ );
+}
+
+static void MC_put_xy_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v4, 0, %r4 \n"
+ " vspltisb %v3, 1 \n"
+ " lvsl %v5, %r5, %r4 \n"
+ " vmrghb %v4, %v4, %v4 \n"
+ " li %r9, 8 \n"
+ " vmrghb %v5, %v5, %v5 \n"
+ " lvx %v1, 0, %r4 \n"
+ " vpkuhum %v4, %v4, %v4 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " vpkuhum %v5, %v5, %v5 \n"
+ " add %r4, %r4, %r5 \n"
+ " vaddubm %v2, %v4, %v3 \n"
+ " vperm %v11, %v1, %v0, %v4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " vaddubm %v19, %v5, %v3 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v10, %v1, %v0, %v2 \n"
+ " mtctr %r6 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v10, %v1, %v0, %v19 \n"
+ " vperm %v11, %v1, %v0, %v5 \n"
+ " vxor %v6, %v11, %v10 \n"
+ " vavgub %v7, %v11, %v10 \n"
+ " vor %v0, %v8, %v6 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vand %v0, %v3, %v0 \n"
+ " vavgub %v1, %v9, %v7 \n"
+ " vand %v0, %v0, %v13 \n"
+ " vsububm %v13, %v1, %v0 \n"
+ " ._L41: \n"
+ " li %r9, 8 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v1, 0, %r4 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vperm %v10, %v1, %v0, %v2 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ " vperm %v11, %v1, %v0, %v4 \n"
+ " add %r4, %r4, %r5 \n"
+ " li %r9, 8 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " lvx %v1, 0, %r4 \n"
+ " vavgub %v12, %v9, %v7 \n"
+ " vor %v13, %v8, %v6 \n"
+ " add %r3, %r3, %r5 \n"
+ " vperm %v10, %v1, %v0, %v19 \n"
+ " li %r9, 4 \n"
+ " vperm %v11, %v1, %v0, %v5 \n"
+ " vand %v13, %v3, %v13 \n"
+ " add %r4, %r4, %r5 \n"
+ " vxor %v0, %v9, %v7 \n"
+ " vxor %v6, %v11, %v10 \n"
+ " vavgub %v7, %v11, %v10 \n"
+ " vor %v1, %v8, %v6 \n"
+ " vand %v13, %v13, %v0 \n"
+ " vxor %v0, %v9, %v7 \n"
+ " vand %v1, %v3, %v1 \n"
+ " vsububm %v13, %v12, %v13 \n"
+ " vand %v1, %v1, %v0 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " vavgub %v0, %v9, %v7 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ " add %r3, %r3, %r5 \n"
+ " vsububm %v13, %v0, %v1 \n"
+ " bdnz ._L41 \n"
+ " li %r9, 8 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v1, 0, %r4 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " vperm %v10, %v1, %v0, %v2 \n"
+ " li %r9, 4 \n"
+ " vperm %v11, %v1, %v0, %v4 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ " add %r3, %r3, %r5 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vor %v0, %v8, %v6 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vand %v0, %v3, %v0 \n"
+ " vavgub %v1, %v9, %v7 \n"
+ " vand %v0, %v0, %v13 \n"
+ " vsububm %v13, %v1, %v0 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ );
+}
+
+static void MC_avg_o_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " li %r9, 15 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvsl %v11, 0, %r4 \n"
+ " lvx %v1, 0, %r4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v0, %v1, %v0, %v11 \n"
+ " lvx %v13, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " add %r9, %r5, %r5 \n"
+ " vavgub %v12, %v13, %v0 \n"
+ " add %r4, %r4, %r5 \n"
+ "._L46: \n"
+ " li %r11, 15 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r11, %r4 \n"
+ " lvx %v13, %r5, %r3 \n"
+ " vperm %v0, %v1, %v0, %v11 \n"
+ " stvx %v12, 0, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v12, %v13, %v0 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r11, %r4 \n"
+ " lvx %v13, %r9, %r3 \n"
+ " vperm %v0, %v1, %v0, %v11 \n"
+ " stvx %v12, %r5, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v12, %v13, %v0 \n"
+ " add %r3, %r3, %r9 \n"
+ " bdnz ._L46 \n"
+ " lvx %v0, %r11, %r4 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v13, %r5, %r3 \n"
+ " vperm %v0, %v1, %v0, %v11 \n"
+ " stvx %v12, 0, %r3 \n"
+ " vavgub %v12, %v13, %v0 \n"
+ " stvx %v12, %r5, %r3 \n"
+ );
+}
+
+static void MC_avg_o_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v12, 0, %r4 \n"
+ " li %r9, 7 \n"
+ " vmrghb %v12, %v12, %v12 \n"
+ " lvsl %v1, %r5, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " vpkuhum %v9, %v12, %v12 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " vmrghb %v1, %v1, %v1 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v0, %v13, %v0, %v9 \n"
+ " lvx %v11, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " vpkuhum %v10, %v1, %v1 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v12, %v11, %v0 \n"
+ "._L51: \n"
+ " li %r9, 7 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v11, %r5, %r3 \n"
+ " stvewx %v12, 0, %r3 \n"
+ " vperm %v0, %v13, %v0, %v10 \n"
+ " li %r9, 4 \n"
+ " stvewx %v12, %r9, %r3 \n"
+ " vavgub %v1, %v11, %v0 \n"
+ " add %r4, %r4, %r5 \n"
+ " li %r9, 7 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " add %r3, %r3, %r5 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v11, %r5, %r3 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " vperm %v0, %v13, %v0, %v9 \n"
+ " li %r9, 4 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ " vavgub %v12, %v11, %v0 \n"
+ " add %r4, %r4, %r5 \n"
+ " add %r3, %r3, %r5 \n"
+ " bdnz ._L51 \n"
+ " li %r9, 7 \n"
+ " lvx %v0, %r9, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v11, %r5, %r3 \n"
+ " stvewx %v12, 0, %r3 \n"
+ " vperm %v0, %v13, %v0, %v10 \n"
+ " li %r9, 4 \n"
+ " stvewx %v12, %r9, %r3 \n"
+ " vavgub %v1, %v11, %v0 \n"
+ " add %r3, %r3, %r5 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ );
+}
+
+static void MC_avg_x_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v8, 0, %r4 \n"
+ " vspltisb %v0, 1 \n"
+ " li %r9, 16 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " vaddubm %v7, %v8, %v0 \n"
+ " lvx %v11, 0, %r4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " vperm %v1, %v11, %v12, %v7 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v0, %v11, %v12, %v8 \n"
+ " lvx %v9, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " add %r9, %r5, %r5 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v10, %v9, %v0 \n"
+ "._L56: \n"
+ " li %r11, 16 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v12, %r11, %r4 \n"
+ " lvx %v9, %r5, %r3 \n"
+ " stvx %v10, 0, %r3 \n"
+ " vperm %v0, %v11, %v12, %v7 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v1, %v11, %v12, %v8 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v12, %r11, %r4 \n"
+ " vavgub %v1, %v1, %v0 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v13, %v11, %v12, %v7 \n"
+ " vavgub %v10, %v9, %v1 \n"
+ " vperm %v0, %v11, %v12, %v8 \n"
+ " lvx %v9, %r9, %r3 \n"
+ " stvx %v10, %r5, %r3 \n"
+ " vavgub %v0, %v0, %v13 \n"
+ " add %r3, %r3, %r9 \n"
+ " vavgub %v10, %v9, %v0 \n"
+ " bdnz ._L56 \n"
+ " lvx %v12, %r11, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v9, %r5, %r3 \n"
+ " vperm %v1, %v11, %v12, %v7 \n"
+ " stvx %v10, 0, %r3 \n"
+ " vperm %v0, %v11, %v12, %v8 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " vavgub %v10, %v9, %v0 \n"
+ " stvx %v10, %r5, %r3 \n"
+ );
+}
+
+static void MC_avg_x_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v10, 0, %r4 \n"
+ " vspltisb %v13, 1 \n"
+ " li %r9, 8 \n"
+ " vmrghb %v10, %v10, %v10 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " vpkuhum %v7, %v10, %v10 \n"
+ " srawi %r6, %r6, 1 \n"
+ " lvsl %v10, %r5, %r4 \n"
+ " vaddubm %v6, %v7, %v13 \n"
+ " vperm %v0, %v11, %v12, %v7 \n"
+ " addi %r6, %r6, -1 \n"
+ " vmrghb %v10, %v10, %v10 \n"
+ " lvx %v9, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " vperm %v1, %v11, %v12, %v6 \n"
+ " add %r4, %r4, %r5 \n"
+ " vpkuhum %v8, %v10, %v10 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " vaddubm %v13, %v8, %v13 \n"
+ " vavgub %v10, %v9, %v0 \n"
+ "._L61: \n"
+ " li %r9, 8 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v9, %r5, %r3 \n"
+ " stvewx %v10, 0, %r3 \n"
+ " vperm %v1, %v11, %v12, %v13 \n"
+ " vperm %v0, %v11, %v12, %v8 \n"
+ " li %r9, 4 \n"
+ " stvewx %v10, %r9, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " li %r9, 8 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " vavgub %v10, %v9, %v0 \n"
+ " lvx %v11, 0, %r4 \n"
+ " add %r3, %r3, %r5 \n"
+ " vperm %v1, %v11, %v12, %v6 \n"
+ " lvx %v9, %r5, %r3 \n"
+ " vperm %v0, %v11, %v12, %v7 \n"
+ " stvewx %v10, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " stvewx %v10, %r9, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " add %r3, %r3, %r5 \n"
+ " vavgub %v10, %v9, %v0 \n"
+ " bdnz ._L61 \n"
+ " li %r9, 8 \n"
+ " lvx %v12, %r9, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v9, %r5, %r3 \n"
+ " vperm %v1, %v11, %v12, %v13 \n"
+ " stvewx %v10, 0, %r3 \n"
+ " vperm %v0, %v11, %v12, %v8 \n"
+ " li %r9, 4 \n"
+ " stvewx %v10, %r9, %r3 \n"
+ " vavgub %v0, %v0, %v1 \n"
+ " add %r3, %r3, %r5 \n"
+ " vavgub %v10, %v9, %v0 \n"
+ " stvewx %v10, 0, %r3 \n"
+ " stvewx %v10, %r9, %r3 \n"
+ );
+}
+
+static void MC_avg_y_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " li %r9, 15 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvsl %v9, 0, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v11, %v13, %v1, %v9 \n"
+ " li %r11, 15 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " vperm %v10, %v13, %v1, %v9 \n"
+ " addi %r6, %r6, -1 \n"
+ " lvx %v12, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " vavgub %v0, %v11, %v10 \n"
+ " add %r9, %r5, %r5 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v12, %v0 \n"
+ "._L66: \n"
+ " li %r11, 15 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " lvx %v12, %r5, %r3 \n"
+ " vperm %v11, %v13, %v1, %v9 \n"
+ " stvx %v0, 0, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v11, %v10 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " vavgub %v0, %v12, %v0 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v12, %r9, %r3 \n"
+ " vperm %v10, %v13, %v1, %v9 \n"
+ " stvx %v0, %r5, %r3 \n"
+ " vavgub %v0, %v11, %v10 \n"
+ " add %r3, %r3, %r9 \n"
+ " vavgub %v0, %v12, %v0 \n"
+ " bdnz ._L66 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v12, %r5, %r3 \n"
+ " vperm %v11, %v13, %v1, %v9 \n"
+ " stvx %v0, 0, %r3 \n"
+ " vavgub %v0, %v11, %v10 \n"
+ " vavgub %v0, %v12, %v0 \n"
+ " stvx %v0, %r5, %r3 \n"
+ );
+}
+
+static void MC_avg_y_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v12, 0, %r4 \n"
+ " lvsl %v9, %r5, %r4 \n"
+ " vmrghb %v12, %v12, %v12 \n"
+ " li %r9, 7 \n"
+ " lvx %v11, 0, %r4 \n"
+ " vmrghb %v9, %v9, %v9 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " vpkuhum %v7, %v12, %v12 \n"
+ " add %r4, %r4, %r5 \n"
+ " vpkuhum %v8, %v9, %v9 \n"
+ " vperm %v12, %v11, %v13, %v7 \n"
+ " srawi %r6, %r6, 1 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v9, %v11, %v13, %v8 \n"
+ " lvx %v10, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v0, %v12, %v9 \n"
+ " vavgub %v1, %v10, %v0 \n"
+ "._L71: \n"
+ " li %r9, 7 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v10, %r5, %r3 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " vperm %v12, %v11, %v13, %v7 \n"
+ " li %r9, 4 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ " vavgub %v0, %v12, %v9 \n"
+ " add %r4, %r4, %r5 \n"
+ " li %r9, 7 \n"
+ " vavgub %v1, %v10, %v0 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " add %r3, %r3, %r5 \n"
+ " vperm %v9, %v11, %v13, %v8 \n"
+ " lvx %v10, %r5, %r3 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " vavgub %v0, %v12, %v9 \n"
+ " li %r9, 4 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vavgub %v1, %v10, %v0 \n"
+ " add %r3, %r3, %r5 \n"
+ " bdnz ._L71 \n"
+ " li %r9, 7 \n"
+ " lvx %v13, %r9, %r4 \n"
+ " lvx %v11, 0, %r4 \n"
+ " lvx %v10, %r5, %r3 \n"
+ " vperm %v12, %v11, %v13, %v7 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " li %r9, 4 \n"
+ " vavgub %v0, %v12, %v9 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ " add %r3, %r3, %r5 \n"
+ " vavgub %v1, %v10, %v0 \n"
+ " stvewx %v1, 0, %r3 \n"
+ " stvewx %v1, %r9, %r3 \n"
+ );
+}
+
+static void MC_avg_xy_16_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v4, 0, %r4 \n"
+ " vspltisb %v2, 1 \n"
+ " li %r9, 16 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " vaddubm %v3, %v4, %v2 \n"
+ " lvx %v13, 0, %r4 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v10, %v13, %v1, %v3 \n"
+ " li %r11, 16 \n"
+ " vperm %v11, %v13, %v1, %v4 \n"
+ " srawi %r6, %r6, 1 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v10, %v13, %v1, %v3 \n"
+ " lvx %v6, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " vperm %v11, %v13, %v1, %v4 \n"
+ " add %r9, %r5, %r5 \n"
+ " add %r4, %r4, %r5 \n"
+ " vxor %v5, %v11, %v10 \n"
+ " vavgub %v7, %v11, %v10 \n"
+ " vor %v1, %v8, %v5 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vand %v1, %v2, %v1 \n"
+ " vavgub %v0, %v9, %v7 \n"
+ " vand %v1, %v1, %v13 \n"
+ " vsububm %v0, %v0, %v1 \n"
+ " vavgub %v12, %v6, %v0 \n"
+ "._L76: \n"
+ " li %r11, 16 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " lvx %v6, %r5, %r3 \n"
+ " stvx %v12, 0, %r3 \n"
+ " vperm %v10, %v13, %v1, %v3 \n"
+ " vperm %v11, %v13, %v1, %v4 \n"
+ " add %r4, %r4, %r5 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v10, %v13, %v1, %v3 \n"
+ " vavgub %v12, %v9, %v7 \n"
+ " vperm %v11, %v13, %v1, %v4 \n"
+ " vor %v0, %v8, %v5 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vxor %v5, %v11, %v10 \n"
+ " vand %v0, %v2, %v0 \n"
+ " vavgub %v7, %v11, %v10 \n"
+ " vor %v1, %v8, %v5 \n"
+ " vand %v0, %v0, %v13 \n"
+ " vand %v1, %v2, %v1 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vsububm %v12, %v12, %v0 \n"
+ " vand %v1, %v1, %v13 \n"
+ " vavgub %v0, %v9, %v7 \n"
+ " vavgub %v12, %v6, %v12 \n"
+ " lvx %v6, %r9, %r3 \n"
+ " vsububm %v0, %v0, %v1 \n"
+ " stvx %v12, %r5, %r3 \n"
+ " vavgub %v12, %v6, %v0 \n"
+ " add %r3, %r3, %r9 \n"
+ " bdnz ._L76 \n"
+ " lvx %v1, %r11, %r4 \n"
+ " lvx %v13, 0, %r4 \n"
+ " lvx %v6, %r5, %r3 \n"
+ " vperm %v10, %v13, %v1, %v3 \n"
+ " stvx %v12, 0, %r3 \n"
+ " vperm %v11, %v13, %v1, %v4 \n"
+ " vxor %v8, %v11, %v10 \n"
+ " vavgub %v9, %v11, %v10 \n"
+ " vor %v0, %v8, %v5 \n"
+ " vxor %v13, %v9, %v7 \n"
+ " vand %v0, %v2, %v0 \n"
+ " vavgub %v1, %v9, %v7 \n"
+ " vand %v0, %v0, %v13 \n"
+ " vsububm %v1, %v1, %v0 \n"
+ " vavgub %v12, %v6, %v1 \n"
+ " stvx %v12, %r5, %r3 \n"
+ );
+}
+
+static void MC_avg_xy_8_altivec (uint8_t * dest, uint8_t * ref,
+ int stride, int height)
+{
+ asm (" \n"
+ " lvsl %v2, 0, %r4 \n"
+ " vspltisb %v19, 1 \n"
+ " lvsl %v3, %r5, %r4 \n"
+ " vmrghb %v2, %v2, %v2 \n"
+ " li %r9, 8 \n"
+ " vmrghb %v3, %v3, %v3 \n"
+ " lvx %v9, 0, %r4 \n"
+ " vpkuhum %v2, %v2, %v2 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " vpkuhum %v3, %v3, %v3 \n"
+ " add %r4, %r4, %r5 \n"
+ " vaddubm %v18, %v2, %v19 \n"
+ " vperm %v11, %v9, %v1, %v2 \n"
+ " srawi %r6, %r6, 1 \n"
+ " vaddubm %v17, %v3, %v19 \n"
+ " addi %r6, %r6, -1 \n"
+ " vperm %v10, %v9, %v1, %v18 \n"
+ " lvx %v4, 0, %r3 \n"
+ " mtctr %r6 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvx %v9, 0, %r4 \n"
+ " vavgub %v8, %v11, %v10 \n"
+ " vxor %v7, %v11, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " vperm %v10, %v9, %v1, %v17 \n"
+ " vperm %v11, %v9, %v1, %v3 \n"
+ " vxor %v5, %v11, %v10 \n"
+ " vavgub %v6, %v11, %v10 \n"
+ " vor %v1, %v7, %v5 \n"
+ " vxor %v13, %v8, %v6 \n"
+ " vand %v1, %v19, %v1 \n"
+ " vavgub %v0, %v8, %v6 \n"
+ " vand %v1, %v1, %v13 \n"
+ " vsububm %v0, %v0, %v1 \n"
+ " vavgub %v13, %v4, %v0 \n"
+ " ._L81: \n"
+ " li %r9, 8 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvx %v9, 0, %r4 \n"
+ " lvx %v4, %r5, %r3 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " vperm %v10, %v9, %v1, %v18 \n"
+ " vperm %v11, %v9, %v1, %v2 \n"
+ " li %r9, 4 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ " vxor %v7, %v11, %v10 \n"
+ " add %r4, %r4, %r5 \n"
+ " li %r9, 8 \n"
+ " vavgub %v8, %v11, %v10 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " vor %v0, %v7, %v5 \n"
+ " lvx %v9, 0, %r4 \n"
+ " vxor %v12, %v8, %v6 \n"
+ " vand %v0, %v19, %v0 \n"
+ " add %r3, %r3, %r5 \n"
+ " vperm %v10, %v9, %v1, %v17 \n"
+ " vavgub %v13, %v8, %v6 \n"
+ " li %r9, 4 \n"
+ " vperm %v11, %v9, %v1, %v3 \n"
+ " vand %v0, %v0, %v12 \n"
+ " add %r4, %r4, %r5 \n"
+ " vxor %v5, %v11, %v10 \n"
+ " vavgub %v6, %v11, %v10 \n"
+ " vor %v1, %v7, %v5 \n"
+ " vsububm %v13, %v13, %v0 \n"
+ " vxor %v0, %v8, %v6 \n"
+ " vand %v1, %v19, %v1 \n"
+ " vavgub %v13, %v4, %v13 \n"
+ " vand %v1, %v1, %v0 \n"
+ " lvx %v4, %r5, %r3 \n"
+ " vavgub %v0, %v8, %v6 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ " vsububm %v0, %v0, %v1 \n"
+ " add %r3, %r3, %r5 \n"
+ " vavgub %v13, %v4, %v0 \n"
+ " bdnz ._L81 \n"
+ " li %r9, 8 \n"
+ " lvx %v1, %r9, %r4 \n"
+ " lvx %v9, 0, %r4 \n"
+ " lvx %v4, %r5, %r3 \n"
+ " vperm %v10, %v9, %v1, %v18 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " vperm %v11, %v9, %v1, %v2 \n"
+ " li %r9, 4 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ " vxor %v7, %v11, %v10 \n"
+ " add %r3, %r3, %r5 \n"
+ " vavgub %v8, %v11, %v10 \n"
+ " vor %v0, %v7, %v5 \n"
+ " vxor %v13, %v8, %v6 \n"
+ " vand %v0, %v19, %v0 \n"
+ " vavgub %v1, %v8, %v6 \n"
+ " vand %v0, %v0, %v13 \n"
+ " vsububm %v1, %v1, %v0 \n"
+ " vavgub %v13, %v4, %v1 \n"
+ " stvewx %v13, 0, %r3 \n"
+ " stvewx %v13, %r9, %r3 \n"
+ );
+}
+
+#endif /* !CAN_COMPILE_C_ALTIVEC */
+#endif /* __BUILD_ALTIVEC_ASM__ */
+
+#if defined(CAN_COMPILE_C_ALTIVEC) || defined(__BUILD_ALTIVEC_ASM__)
+
+#define vector_s16_t vector signed short
+#define vector_u16_t vector unsigned short
+#define vector_s8_t vector signed char
+#define vector_u8_t vector unsigned char
+#define vector_s32_t vector signed int
+#define vector_u32_t vector unsigned int
+
+void MC_put_o_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm, ref0, ref1, tmp;
+
+ perm = vec_lvsl (0, ref);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ tmp = vec_perm (ref0, ref1, perm);
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ vec_st (tmp, 0, dest);
+ tmp = vec_perm (ref0, ref1, perm);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ tmp = vec_perm (ref0, ref1, perm);
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ vec_st (tmp, 0, dest);
+ tmp = vec_perm (ref0, ref1, perm);
+ vec_st (tmp, stride, dest);
+}
+
+void MC_put_o_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0, perm1, tmp0, tmp1, ref0, ref1;
+
+ tmp0 = vec_lvsl (0, ref);
+ tmp0 = vec_mergeh (tmp0, tmp0);
+ perm0 = vec_pack ((vector_u16_t)tmp0, (vector_u16_t)tmp0);
+ tmp1 = vec_lvsl (stride, ref);
+ tmp1 = vec_mergeh (tmp1, tmp1);
+ perm1 = vec_pack ((vector_u16_t)tmp1, (vector_u16_t)tmp1);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_perm (ref0, ref1, perm1);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_perm (ref0, ref1, perm1);
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+}
+
+void MC_put_x_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t permA, permB, ref0, ref1, tmp;
+
+ permA = vec_lvsl (0, ref);
+ permB = vec_add (permA, vec_splat_u8 (1));
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ tmp = vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ vec_st (tmp, 0, dest);
+ tmp = vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ tmp = vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ vec_st (tmp, 0, dest);
+ tmp = vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB));
+ vec_st (tmp, stride, dest);
+}
+
+void MC_put_x_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0A, perm0B, perm1A, perm1B, ones, tmp0, tmp1, ref0, ref1;
+
+ ones = vec_splat_u8 (1);
+ tmp0 = vec_lvsl (0, ref);
+ tmp0 = vec_mergeh (tmp0, tmp0);
+ perm0A = vec_pack ((vector_u16_t)tmp0, (vector_u16_t)tmp0);
+ perm0B = vec_add (perm0A, ones);
+ tmp1 = vec_lvsl (stride, ref);
+ tmp1 = vec_mergeh (tmp1, tmp1);
+ perm1A = vec_pack ((vector_u16_t)tmp1, (vector_u16_t)tmp1);
+ perm1B = vec_add (perm1A, ones);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ tmp0 = vec_avg (vec_perm (ref0, ref1, perm0A),
+ vec_perm (ref0, ref1, perm0B));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_avg (vec_perm (ref0, ref1, perm1A),
+ vec_perm (ref0, ref1, perm1B));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_avg (vec_perm (ref0, ref1, perm0A),
+ vec_perm (ref0, ref1, perm0B));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_avg (vec_perm (ref0, ref1, perm1A),
+ vec_perm (ref0, ref1, perm1B));
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+}
+
+void MC_put_y_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm, ref0, ref1, tmp0, tmp1, tmp;
+
+ perm = vec_lvsl (0, ref);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ tmp0 = vec_perm (ref0, ref1, perm);
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ tmp1 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (tmp0, tmp1);
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ vec_st (tmp, 0, dest);
+ tmp0 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (tmp0, tmp1);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ tmp1 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (tmp0, tmp1);
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ vec_st (tmp, 0, dest);
+ tmp0 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (tmp0, tmp1);
+ vec_st (tmp, stride, dest);
+}
+
+void MC_put_y_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0, perm1, tmp0, tmp1, tmp, ref0, ref1;
+
+ tmp0 = vec_lvsl (0, ref);
+ tmp0 = vec_mergeh (tmp0, tmp0);
+ perm0 = vec_pack ((vector_u16_t)tmp0, (vector_u16_t)tmp0);
+ tmp1 = vec_lvsl (stride, ref);
+ tmp1 = vec_mergeh (tmp1, tmp1);
+ perm1 = vec_pack ((vector_u16_t)tmp1, (vector_u16_t)tmp1);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ tmp1 = vec_perm (ref0, ref1, perm1);
+ tmp = vec_avg (tmp0, tmp1);
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+ tmp = vec_avg (tmp0, tmp1);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_perm (ref0, ref1, perm1);
+ tmp = vec_avg (tmp0, tmp1);
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+ tmp = vec_avg (tmp0, tmp1);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+}
+
+void MC_put_xy_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t permA, permB, ref0, ref1, A, B, avg0, avg1, xor0, xor1, tmp;
+ vector_u8_t ones;
+
+ ones = vec_splat_u8 (1);
+ permA = vec_lvsl (0, ref);
+ permB = vec_add (permA, ones);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ vec_st (tmp, 0, dest);
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ vec_st (tmp, 0, dest);
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+ vec_st (tmp, stride, dest);
+}
+
+void MC_put_xy_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0A, perm0B, perm1A, perm1B, ref0, ref1, A, B;
+ vector_u8_t avg0, avg1, xor0, xor1, tmp, ones;
+
+ ones = vec_splat_u8 (1);
+ perm0A = vec_lvsl (0, ref);
+ perm0A = vec_mergeh (perm0A, perm0A);
+ perm0A = vec_pack ((vector_u16_t)perm0A, (vector_u16_t)perm0A);
+ perm0B = vec_add (perm0A, ones);
+ perm1A = vec_lvsl (stride, ref);
+ perm1A = vec_mergeh (perm1A, perm1A);
+ perm1A = vec_pack ((vector_u16_t)perm1A, (vector_u16_t)perm1A);
+ perm1B = vec_add (perm1A, ones);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ A = vec_perm (ref0, ref1, perm0A);
+ B = vec_perm (ref0, ref1, perm0B);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ A = vec_perm (ref0, ref1, perm1A);
+ B = vec_perm (ref0, ref1, perm1B);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ A = vec_perm (ref0, ref1, perm0A);
+ B = vec_perm (ref0, ref1, perm0B);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ A = vec_perm (ref0, ref1, perm1A);
+ B = vec_perm (ref0, ref1, perm1B);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ A = vec_perm (ref0, ref1, perm0A);
+ B = vec_perm (ref0, ref1, perm0B);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1)));
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+}
+
+#if 0
+void MC_put_xy_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t permA, permB, ref0, ref1, A, B, C, D, tmp, zero, ones;
+ vector_u16_t splat2, temp;
+
+ ones = vec_splat_u8 (1);
+ permA = vec_lvsl (0, ref);
+ permB = vec_add (permA, ones);
+
+ zero = vec_splat_u8 (0);
+ splat2 = vec_splat_u16 (2);
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ C = vec_perm (ref0, ref1, permA);
+ D = vec_perm (ref0, ref1, permB);
+
+ temp = vec_add (vec_add ((vector_u16_t)vec_mergeh (zero, A),
+ (vector_u16_t)vec_mergeh (zero, B)),
+ vec_add ((vector_u16_t)vec_mergeh (zero, C),
+ (vector_u16_t)vec_mergeh (zero, D)));
+ temp = vec_sr (vec_add (temp, splat2), splat2);
+ tmp = vec_pack (temp, temp);
+
+ vec_st (tmp, 0, dest);
+ dest += stride;
+ tmp = vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB));
+ } while (--height);
+}
+#endif
+
+void MC_avg_o_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm, ref0, ref1, tmp, prev;
+
+ perm = vec_lvsl (0, ref);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ prev = vec_ld (0, dest);
+ tmp = vec_avg (prev, vec_perm (ref0, ref1, perm));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ tmp = vec_avg (prev, vec_perm (ref0, ref1, perm));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ prev = vec_ld (2*stride, dest);
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ tmp = vec_avg (prev, vec_perm (ref0, ref1, perm));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ tmp = vec_avg (prev, vec_perm (ref0, ref1, perm));
+ vec_st (tmp, stride, dest);
+}
+
+void MC_avg_o_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0, perm1, tmp0, tmp1, ref0, ref1, prev;
+
+ tmp0 = vec_lvsl (0, ref);
+ tmp0 = vec_mergeh (tmp0, tmp0);
+ perm0 = vec_pack ((vector_u16_t)tmp0, (vector_u16_t)tmp0);
+ tmp1 = vec_lvsl (stride, ref);
+ tmp1 = vec_mergeh (tmp1, tmp1);
+ perm1 = vec_pack ((vector_u16_t)tmp1, (vector_u16_t)tmp1);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ prev = vec_ld (0, dest);
+ tmp0 = vec_avg (prev, vec_perm (ref0, ref1, perm0));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_avg (prev, vec_perm (ref0, ref1, perm1));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_avg (prev, vec_perm (ref0, ref1, perm0));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_avg (prev, vec_perm (ref0, ref1, perm1));
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+}
+
+void MC_avg_x_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t permA, permB, ref0, ref1, tmp, prev;
+
+ permA = vec_lvsl (0, ref);
+ permB = vec_add (permA, vec_splat_u8 (1));
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ prev = vec_ld (0, dest);
+ ref += stride;
+ tmp = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB)));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ tmp = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB)));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ prev = vec_ld (2*stride, dest);
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ tmp = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB)));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ tmp = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, permA),
+ vec_perm (ref0, ref1, permB)));
+ vec_st (tmp, stride, dest);
+}
+
+void MC_avg_x_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0A, perm0B, perm1A, perm1B, ones, tmp0, tmp1, ref0, ref1;
+ vector_u8_t prev;
+
+ ones = vec_splat_u8 (1);
+ tmp0 = vec_lvsl (0, ref);
+ tmp0 = vec_mergeh (tmp0, tmp0);
+ perm0A = vec_pack ((vector_u16_t)tmp0, (vector_u16_t)tmp0);
+ perm0B = vec_add (perm0A, ones);
+ tmp1 = vec_lvsl (stride, ref);
+ tmp1 = vec_mergeh (tmp1, tmp1);
+ perm1A = vec_pack ((vector_u16_t)tmp1, (vector_u16_t)tmp1);
+ perm1B = vec_add (perm1A, ones);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ prev = vec_ld (0, dest);
+ ref += stride;
+ tmp0 = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, perm0A),
+ vec_perm (ref0, ref1, perm0B)));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, perm1A),
+ vec_perm (ref0, ref1, perm1B)));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, perm0A),
+ vec_perm (ref0, ref1, perm0B)));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp0, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp0, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_avg (prev, vec_avg (vec_perm (ref0, ref1, perm1A),
+ vec_perm (ref0, ref1, perm1B)));
+ vec_ste ((vector_u32_t)tmp1, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp1, 4, (unsigned int *)dest);
+}
+
+void MC_avg_y_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm, ref0, ref1, tmp0, tmp1, tmp, prev;
+
+ perm = vec_lvsl (0, ref);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ tmp0 = vec_perm (ref0, ref1, perm);
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ prev = vec_ld (0, dest);
+ tmp1 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ tmp0 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ ref += stride;
+ prev = vec_ld (2*stride, dest);
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ tmp1 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (15, ref);
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ tmp0 = vec_perm (ref0, ref1, perm);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+ vec_st (tmp, stride, dest);
+}
+
+void MC_avg_y_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0, perm1, tmp0, tmp1, tmp, ref0, ref1, prev;
+
+ tmp0 = vec_lvsl (0, ref);
+ tmp0 = vec_mergeh (tmp0, tmp0);
+ perm0 = vec_pack ((vector_u16_t)tmp0, (vector_u16_t)tmp0);
+ tmp1 = vec_lvsl (stride, ref);
+ tmp1 = vec_mergeh (tmp1, tmp1);
+ perm1 = vec_pack ((vector_u16_t)tmp1, (vector_u16_t)tmp1);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ prev = vec_ld (0, dest);
+ tmp1 = vec_perm (ref0, ref1, perm1);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp1 = vec_perm (ref0, ref1, perm1);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (7, ref);
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ tmp0 = vec_perm (ref0, ref1, perm0);
+ tmp = vec_avg (prev, vec_avg (tmp0, tmp1));
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+}
+
+void MC_avg_xy_16_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t permA, permB, ref0, ref1, A, B, avg0, avg1, xor0, xor1, tmp;
+ vector_u8_t ones, prev;
+
+ ones = vec_splat_u8 (1);
+ permA = vec_lvsl (0, ref);
+ permB = vec_add (permA, ones);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ prev = vec_ld (0, dest);
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_avg (prev, vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_avg (prev,
+ vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ ref += stride;
+ prev = vec_ld (2*stride, dest);
+ vec_st (tmp, stride, dest);
+ dest += 2*stride;
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_avg (prev,
+ vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (16, ref);
+ prev = vec_ld (stride, dest);
+ vec_st (tmp, 0, dest);
+ A = vec_perm (ref0, ref1, permA);
+ B = vec_perm (ref0, ref1, permB);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_avg (prev, vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+ vec_st (tmp, stride, dest);
+}
+
+void MC_avg_xy_8_altivec (unsigned char * dest, unsigned char * ref,
+ int stride, int height)
+{
+ vector_u8_t perm0A, perm0B, perm1A, perm1B, ref0, ref1, A, B;
+ vector_u8_t avg0, avg1, xor0, xor1, tmp, ones, prev;
+
+ ones = vec_splat_u8 (1);
+ perm0A = vec_lvsl (0, ref);
+ perm0A = vec_mergeh (perm0A, perm0A);
+ perm0A = vec_pack ((vector_u16_t)perm0A, (vector_u16_t)perm0A);
+ perm0B = vec_add (perm0A, ones);
+ perm1A = vec_lvsl (stride, ref);
+ perm1A = vec_mergeh (perm1A, perm1A);
+ perm1A = vec_pack ((vector_u16_t)perm1A, (vector_u16_t)perm1A);
+ perm1B = vec_add (perm1A, ones);
+
+ height = (height >> 1) - 1;
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ A = vec_perm (ref0, ref1, perm0A);
+ B = vec_perm (ref0, ref1, perm0B);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ prev = vec_ld (0, dest);
+ A = vec_perm (ref0, ref1, perm1A);
+ B = vec_perm (ref0, ref1, perm1B);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_avg (prev, vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+
+ do {
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ A = vec_perm (ref0, ref1, perm0A);
+ B = vec_perm (ref0, ref1, perm0B);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_avg (prev,
+ vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ ref += stride;
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ A = vec_perm (ref0, ref1, perm1A);
+ B = vec_perm (ref0, ref1, perm1B);
+ avg1 = vec_avg (A, B);
+ xor1 = vec_xor (A, B);
+ tmp = vec_avg (prev,
+ vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+ } while (--height);
+
+ ref0 = vec_ld (0, ref);
+ ref1 = vec_ld (8, ref);
+ prev = vec_ld (stride, dest);
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+ dest += stride;
+ A = vec_perm (ref0, ref1, perm0A);
+ B = vec_perm (ref0, ref1, perm0B);
+ avg0 = vec_avg (A, B);
+ xor0 = vec_xor (A, B);
+ tmp = vec_avg (prev, vec_sub (vec_avg (avg0, avg1),
+ vec_and (vec_and (ones, vec_or (xor0, xor1)),
+ vec_xor (avg0, avg1))));
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest);
+ vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest);
+}
+
+#endif /* CAN_COMPILE_C_ALTIVEC || __BUILD_ALTIVEC_ASM__ */
+#ifndef __BUILD_ALTIVEC_ASM__
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void (* ppppf_motion[2][2][4])( yuv_data_t *, yuv_data_t *, int, int ) =
+{
+ /* Copying functions */
+ {
+ /* Width == 16 */
+ { MC_put_o_16_altivec, MC_put_x_16_altivec, MC_put_y_16_altivec, MC_put_xy_16_altivec },
+ /* Width == 8 */
+ { MC_put_o_8_altivec, MC_put_x_8_altivec, MC_put_y_8_altivec, MC_put_xy_8_altivec }
+ },
+ /* Averaging functions */
+ {
+ /* Width == 16 */
+ { MC_avg_o_16_altivec, MC_avg_x_16_altivec, MC_avg_y_16_altivec, MC_avg_xy_16_altivec },
+ /* Width == 8 */
+ { MC_avg_o_8_altivec, MC_avg_x_8_altivec, MC_avg_y_8_altivec, MC_avg_xy_8_altivec }
+ }
+};
+
+static int Open ( vlc_object_t *p_this )
+{
+ p_this->p_private = ppppf_motion;
+ return VLC_SUCCESS;
+}
+
+#endif /* __BUILD_ALTIVEC_ASM__ */
--- /dev/null
+/*****************************************************************************
+ * motionmmx.c : MMX motion compensation module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: motionmmx.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Michel Lespinasse <walken@zoy.org>
+ * Vladimir Chernyshov <greengrass@writeme.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "mmx.h"
+
+/*****************************************************************************
+ * Local prototype.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("MMX motion compensation module") );
+ set_capability( "motion compensation", 150 );
+ add_requirement( MMX );
+ add_shortcut( "mmx" );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Motion compensation in MMX
+ *****************************************************************************/
+
+// some rounding constants
+mmx_t round1 = {0x0001000100010001LL};
+mmx_t round4 = {0x0002000200020002LL};
+
+/*
+ * This code should probably be compiled with loop unrolling
+ * (ie, -funroll-loops in gcc)becuase some of the loops
+ * use a small static number of iterations. This was written
+ * with the assumption the compiler knows best about when
+ * unrolling will help
+ */
+
+static inline void mmx_zero_reg ()
+{
+ // load 0 into mm0
+ pxor_r2r (mm0, mm0);
+}
+
+static inline void mmx_average_2_U8 (yuv_data_t * dest,
+ yuv_data_t * src1, yuv_data_t * src2)
+{
+ //
+ // *dest = (*src1 + *src2 + 1)/ 2;
+ //
+ static mmx_t mask1 = {0x0101010101010101LL};
+ static mmx_t mask7f = {0x7f7f7f7f7f7f7f7fLL};
+
+ movq_m2r (*src1, mm1); // load 8 src1 bytes
+ movq_r2r (mm1, mm2);
+ psrlq_i2r (1, mm1);
+ pand_m2r (mask7f, mm1);
+
+ movq_m2r (*src2, mm3); // load 8 src2 bytes
+ por_r2r (mm3, mm2);
+ psrlq_i2r (1, mm3);
+ pand_m2r (mask7f, mm3);
+
+ paddb_r2r (mm1, mm3);
+ pand_m2r (mask1, mm2);
+ paddb_r2r (mm3, mm2);
+ movq_r2m (mm2, *dest); // store result in dest
+}
+
+static inline void mmx_interp_average_2_U8 (yuv_data_t * dest,
+ yuv_data_t * src1, yuv_data_t * src2)
+{
+ //
+ // *dest = (*dest + (*src1 + *src2 + 1)/ 2 + 1)/ 2;
+ //
+
+ movq_m2r (*dest, mm1); // load 8 dest bytes
+ movq_r2r (mm1, mm2); // copy 8 dest bytes
+
+ movq_m2r (*src1, mm3); // load 8 src1 bytes
+ movq_r2r (mm3, mm4); // copy 8 src1 bytes
+
+ movq_m2r (*src2, mm5); // load 8 src2 bytes
+ movq_r2r (mm5, mm6); // copy 8 src2 bytes
+
+ punpcklbw_r2r (mm0, mm1); // unpack low dest bytes
+ punpckhbw_r2r (mm0, mm2); // unpack high dest bytes
+
+ punpcklbw_r2r (mm0, mm3); // unpack low src1 bytes
+ punpckhbw_r2r (mm0, mm4); // unpack high src1 bytes
+
+ punpcklbw_r2r (mm0, mm5); // unpack low src2 bytes
+ punpckhbw_r2r (mm0, mm6); // unpack high src2 bytes
+
+ paddw_r2r (mm5, mm3); // add lows
+ paddw_m2r (round1, mm3);
+ psraw_i2r (1, mm3); // /2
+
+ paddw_r2r (mm6, mm4); // add highs
+ paddw_m2r (round1, mm4);
+ psraw_i2r (1, mm4); // /2
+
+ paddw_r2r (mm3, mm1); // add lows
+ paddw_m2r (round1, mm1);
+ psraw_i2r (1, mm1); // /2
+
+ paddw_r2r (mm4, mm2); // add highs
+ paddw_m2r (round1, mm2);
+ psraw_i2r (1, mm2); // /2
+
+ packuswb_r2r (mm2, mm1); // pack (w/ saturation)
+ movq_r2m (mm1, *dest); // store result in dest
+}
+
+static inline void mmx_average_4_U8 (yuv_data_t * dest,
+ yuv_data_t * src1, yuv_data_t * src2,
+ yuv_data_t * src3, yuv_data_t * src4)
+{
+ //
+ // *dest = (*src1 + *src2 + *src3 + *src4 + 2)/ 4;
+ //
+
+ movq_m2r (*src1, mm1); // load 8 src1 bytes
+ movq_r2r (mm1, mm2); // copy 8 src1 bytes
+
+ punpcklbw_r2r (mm0, mm1); // unpack low src1 bytes
+ punpckhbw_r2r (mm0, mm2); // unpack high src1 bytes
+
+ movq_m2r (*src2, mm3); // load 8 src2 bytes
+ movq_r2r (mm3, mm4); // copy 8 src2 bytes
+
+ punpcklbw_r2r (mm0, mm3); // unpack low src2 bytes
+ punpckhbw_r2r (mm0, mm4); // unpack high src2 bytes
+
+ paddw_r2r (mm3, mm1); // add lows
+ paddw_r2r (mm4, mm2); // add highs
+
+ // now have partials in mm1 and mm2
+
+ movq_m2r (*src3, mm3); // load 8 src3 bytes
+ movq_r2r (mm3, mm4); // copy 8 src3 bytes
+
+ punpcklbw_r2r (mm0, mm3); // unpack low src3 bytes
+ punpckhbw_r2r (mm0, mm4); // unpack high src3 bytes
+
+ paddw_r2r (mm3, mm1); // add lows
+ paddw_r2r (mm4, mm2); // add highs
+
+ movq_m2r (*src4, mm5); // load 8 src4 bytes
+ movq_r2r (mm5, mm6); // copy 8 src4 bytes
+
+ punpcklbw_r2r (mm0, mm5); // unpack low src4 bytes
+ punpckhbw_r2r (mm0, mm6); // unpack high src4 bytes
+
+ paddw_r2r (mm5, mm1); // add lows
+ paddw_r2r (mm6, mm2); // add highs
+
+ // now have subtotal in mm1 and mm2
+
+ paddw_m2r (round4, mm1);
+ psraw_i2r (2, mm1); // /4
+ paddw_m2r (round4, mm2);
+ psraw_i2r (2, mm2); // /4
+
+ packuswb_r2r (mm2, mm1); // pack (w/ saturation)
+ movq_r2m (mm1, *dest); // store result in dest
+}
+
+static inline void mmx_interp_average_4_U8 (yuv_data_t * dest,
+ yuv_data_t * src1, yuv_data_t * src2,
+ yuv_data_t * src3, yuv_data_t * src4)
+{
+ //
+ // *dest = (*dest + (*src1 + *src2 + *src3 + *src4 + 2)/ 4 + 1)/ 2;
+ //
+
+ movq_m2r (*src1, mm1); // load 8 src1 bytes
+ movq_r2r (mm1, mm2); // copy 8 src1 bytes
+
+ punpcklbw_r2r (mm0, mm1); // unpack low src1 bytes
+ punpckhbw_r2r (mm0, mm2); // unpack high src1 bytes
+
+ movq_m2r (*src2, mm3); // load 8 src2 bytes
+ movq_r2r (mm3, mm4); // copy 8 src2 bytes
+
+ punpcklbw_r2r (mm0, mm3); // unpack low src2 bytes
+ punpckhbw_r2r (mm0, mm4); // unpack high src2 bytes
+
+ paddw_r2r (mm3, mm1); // add lows
+ paddw_r2r (mm4, mm2); // add highs
+
+ // now have partials in mm1 and mm2
+
+ movq_m2r (*src3, mm3); // load 8 src3 bytes
+ movq_r2r (mm3, mm4); // copy 8 src3 bytes
+
+ punpcklbw_r2r (mm0, mm3); // unpack low src3 bytes
+ punpckhbw_r2r (mm0, mm4); // unpack high src3 bytes
+
+ paddw_r2r (mm3, mm1); // add lows
+ paddw_r2r (mm4, mm2); // add highs
+
+ movq_m2r (*src4, mm5); // load 8 src4 bytes
+ movq_r2r (mm5, mm6); // copy 8 src4 bytes
+
+ punpcklbw_r2r (mm0, mm5); // unpack low src4 bytes
+ punpckhbw_r2r (mm0, mm6); // unpack high src4 bytes
+
+ paddw_r2r (mm5, mm1); // add lows
+ paddw_r2r (mm6, mm2); // add highs
+
+ paddw_m2r (round4, mm1);
+ psraw_i2r (2, mm1); // /4
+ paddw_m2r (round4, mm2);
+ psraw_i2r (2, mm2); // /4
+
+ // now have subtotal/4 in mm1 and mm2
+
+ movq_m2r (*dest, mm3); // load 8 dest bytes
+ movq_r2r (mm3, mm4); // copy 8 dest bytes
+
+ punpcklbw_r2r (mm0, mm3); // unpack low dest bytes
+ punpckhbw_r2r (mm0, mm4); // unpack high dest bytes
+
+ paddw_r2r (mm3, mm1); // add lows
+ paddw_r2r (mm4, mm2); // add highs
+
+ paddw_m2r (round1, mm1);
+ psraw_i2r (1, mm1); // /2
+ paddw_m2r (round1, mm2);
+ psraw_i2r (1, mm2); // /2
+
+ // now have end value in mm1 and mm2
+
+ packuswb_r2r (mm2, mm1); // pack (w/ saturation)
+ movq_r2m (mm1,*dest); // store result in dest
+}
+
+//-----------------------------------------------------------------------
+
+static inline void MC_avg_mmx (int width, int height,
+ yuv_data_t * dest, yuv_data_t * ref, int stride)
+{
+ mmx_zero_reg ();
+
+ do {
+ mmx_average_2_U8 (dest, dest, ref);
+
+ if (width == 16)
+ mmx_average_2_U8 (dest+8, dest+8, ref+8);
+
+ dest += stride;
+ ref += stride;
+ } while (--height);
+}
+
+static void MC_avg_16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_avg_8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_mmx (8, height, dest, ref, stride);
+}
+
+//-----------------------------------------------------------------------
+
+static inline void MC_put_mmx (int width, int height,
+ yuv_data_t * dest, yuv_data_t * ref, int stride)
+{
+ mmx_zero_reg ();
+
+ do {
+ movq_m2r (* ref, mm1); // load 8 ref bytes
+ movq_r2m (mm1,* dest); // store 8 bytes at curr
+
+ if (width == 16)
+ {
+ movq_m2r (* (ref+8), mm1); // load 8 ref bytes
+ movq_r2m (mm1,* (dest+8)); // store 8 bytes at curr
+ }
+
+ dest += stride;
+ ref += stride;
+ } while (--height);
+}
+
+static void MC_put_16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_put_8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_mmx (8, height, dest, ref, stride);
+}
+
+//-----------------------------------------------------------------------
+
+// Half pixel interpolation in the x direction
+static inline void MC_avg_x_mmx (int width, int height,
+ yuv_data_t * dest, yuv_data_t * ref, int stride)
+{
+ mmx_zero_reg ();
+
+ do {
+ mmx_interp_average_2_U8 (dest, ref, ref+1);
+
+ if (width == 16)
+ mmx_interp_average_2_U8 (dest+8, ref+8, ref+9);
+
+ dest += stride;
+ ref += stride;
+ } while (--height);
+}
+
+static void MC_avg_x16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_x_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_avg_x8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_x_mmx (8, height, dest, ref, stride);
+}
+
+//-----------------------------------------------------------------------
+
+static inline void MC_put_x_mmx (int width, int height,
+ yuv_data_t * dest, yuv_data_t * ref, int stride)
+{
+ mmx_zero_reg ();
+
+ do {
+ mmx_average_2_U8 (dest, ref, ref+1);
+
+ if (width == 16)
+ mmx_average_2_U8 (dest+8, ref+8, ref+9);
+
+ dest += stride;
+ ref += stride;
+ } while (--height);
+}
+
+static void MC_put_x16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_x_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_put_x8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_x_mmx (8, height, dest, ref, stride);
+}
+
+//-----------------------------------------------------------------------
+
+static inline void MC_avg_xy_8wide_mmx (int height, yuv_data_t * dest,
+ yuv_data_t * ref, int stride)
+{
+ pxor_r2r (mm0, mm0);
+ movq_m2r (round4, mm7);
+
+ movq_m2r (*ref, mm1); // calculate first row ref[0] + ref[1]
+ movq_r2r (mm1, mm2);
+
+ punpcklbw_r2r (mm0, mm1);
+ punpckhbw_r2r (mm0, mm2);
+
+ movq_m2r (*(ref+1), mm3);
+ movq_r2r (mm3, mm4);
+
+ punpcklbw_r2r (mm0, mm3);
+ punpckhbw_r2r (mm0, mm4);
+
+ paddw_r2r (mm3, mm1);
+ paddw_r2r (mm4, mm2);
+
+ ref += stride;
+
+ do {
+
+ movq_m2r (*ref, mm5); // calculate next row ref[0] + ref[1]
+ movq_r2r (mm5, mm6);
+
+ punpcklbw_r2r (mm0, mm5);
+ punpckhbw_r2r (mm0, mm6);
+
+ movq_m2r (*(ref+1), mm3);
+ movq_r2r (mm3, mm4);
+
+ punpcklbw_r2r (mm0, mm3);
+ punpckhbw_r2r (mm0, mm4);
+
+ paddw_r2r (mm3, mm5);
+ paddw_r2r (mm4, mm6);
+
+ movq_r2r (mm7, mm3); // calculate round4 + previous row + current row
+ movq_r2r (mm7, mm4);
+
+ paddw_r2r (mm1, mm3);
+ paddw_r2r (mm2, mm4);
+
+ paddw_r2r (mm5, mm3);
+ paddw_r2r (mm6, mm4);
+
+ psraw_i2r (2, mm3); // /4
+ psraw_i2r (2, mm4); // /4
+
+ movq_m2r (*dest, mm1); // calculate (subtotal + dest[0] + round1) / 2
+ movq_r2r (mm1, mm2);
+
+ punpcklbw_r2r (mm0, mm1);
+ punpckhbw_r2r (mm0, mm2);
+
+ paddw_r2r (mm1, mm3);
+ paddw_r2r (mm2, mm4);
+
+ paddw_m2r (round1, mm3);
+ paddw_m2r (round1, mm4);
+
+ psraw_i2r (1, mm3); // /2
+ psraw_i2r (1, mm4); // /2
+
+ packuswb_r2r (mm4, mm3); // pack (w/ saturation)
+ movq_r2m (mm3, *dest); // store result in dest
+
+ movq_r2r (mm5, mm1); // remember current row for the next pass
+ movq_r2r (mm6, mm2);
+
+ ref += stride;
+ dest += stride;
+
+ } while (--height);
+}
+
+static void MC_avg_xy16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_xy_8wide_mmx(height, dest, ref, stride);
+ MC_avg_xy_8wide_mmx(height, dest+8, ref+8, stride);
+}
+
+static void MC_avg_xy8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_xy_8wide_mmx(height, dest, ref, stride);
+}
+
+//-----------------------------------------------------------------------
+
+static inline void MC_put_xy_8wide_mmx (int height, yuv_data_t * dest,
+ yuv_data_t * ref, int stride)
+{
+ pxor_r2r (mm0, mm0);
+ movq_m2r (round4, mm7);
+
+ movq_m2r (*ref, mm1); // calculate first row ref[0] + ref[1]
+ movq_r2r (mm1, mm2);
+
+ punpcklbw_r2r (mm0, mm1);
+ punpckhbw_r2r (mm0, mm2);
+
+ movq_m2r (*(ref+1), mm3);
+ movq_r2r (mm3, mm4);
+
+ punpcklbw_r2r (mm0, mm3);
+ punpckhbw_r2r (mm0, mm4);
+
+ paddw_r2r (mm3, mm1);
+ paddw_r2r (mm4, mm2);
+
+ ref += stride;
+
+ do {
+
+ movq_m2r (*ref, mm5); // calculate next row ref[0] + ref[1]
+ movq_r2r (mm5, mm6);
+
+ punpcklbw_r2r (mm0, mm5);
+ punpckhbw_r2r (mm0, mm6);
+
+ movq_m2r (*(ref+1), mm3);
+ movq_r2r (mm3, mm4);
+
+ punpcklbw_r2r (mm0, mm3);
+ punpckhbw_r2r (mm0, mm4);
+
+ paddw_r2r (mm3, mm5);
+ paddw_r2r (mm4, mm6);
+
+ movq_r2r (mm7, mm3); // calculate round4 + previous row + current row
+ movq_r2r (mm7, mm4);
+
+ paddw_r2r (mm1, mm3);
+ paddw_r2r (mm2, mm4);
+
+ paddw_r2r (mm5, mm3);
+ paddw_r2r (mm6, mm4);
+
+ psraw_i2r (2, mm3); // /4
+ psraw_i2r (2, mm4); // /4
+
+ packuswb_r2r (mm4, mm3); // pack (w/ saturation)
+ movq_r2m (mm3, *dest); // store result in dest
+
+ movq_r2r (mm5, mm1); // advance to the next row
+ movq_r2r (mm6, mm2);
+
+ ref += stride;
+ dest += stride;
+
+ } while (--height);
+}
+
+static void MC_put_xy16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_xy_8wide_mmx(height, dest, ref, stride);
+ MC_put_xy_8wide_mmx(height, dest + 8, ref + 8, stride);
+}
+
+static void MC_put_xy8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_xy_8wide_mmx(height, dest, ref, stride);
+}
+
+//-----------------------------------------------------------------------
+
+static inline void MC_avg_y_mmx (int width, int height,
+ yuv_data_t * dest, yuv_data_t * ref, int stride)
+{
+ yuv_data_t * ref_next = ref+stride;
+
+ mmx_zero_reg ();
+
+ do {
+ mmx_interp_average_2_U8 (dest, ref, ref_next);
+
+ if (width == 16)
+ mmx_interp_average_2_U8 (dest+8, ref+8, ref_next+8);
+
+ dest += stride;
+ ref += stride;
+ ref_next += stride;
+ } while (--height);
+}
+
+static void MC_avg_y16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_y_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_avg_y8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg_y_mmx (8, height, dest, ref, stride);
+}
+
+//-----------------------------------------------------------------------
+
+static inline void MC_put_y_mmx (int width, int height,
+ yuv_data_t * dest, yuv_data_t * ref, int stride)
+{
+ yuv_data_t * ref_next = ref+stride;
+
+ mmx_zero_reg ();
+
+ do {
+ mmx_average_2_U8 (dest, ref, ref_next);
+
+ if (width == 16)
+ mmx_average_2_U8 (dest+8, ref+8, ref_next+8);
+
+ dest += stride;
+ ref += stride;
+ ref_next += stride;
+ } while (--height);
+}
+
+static void MC_put_y16_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_y_mmx (16, height, dest, ref, stride);
+}
+
+static void MC_put_y8_mmx (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put_y_mmx (8, height, dest, ref, stride);
+}
+
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void (* ppppf_motion[2][2][4])( yuv_data_t *, yuv_data_t *, int, int ) =
+{
+ /* Copying functions */
+ {
+ /* Width == 16 */
+ { MC_put_16_mmx, MC_put_x16_mmx, MC_put_y16_mmx, MC_put_xy16_mmx },
+ /* Width == 8 */
+ { MC_put_8_mmx, MC_put_x8_mmx, MC_put_y8_mmx, MC_put_xy8_mmx }
+ },
+ /* Averaging functions */
+ {
+ /* Width == 16 */
+ { MC_avg_16_mmx, MC_avg_x16_mmx, MC_avg_y16_mmx, MC_avg_xy16_mmx },
+ /* Width == 8 */
+ { MC_avg_8_mmx, MC_avg_x8_mmx, MC_avg_y8_mmx, MC_avg_xy8_mmx }
+ }
+};
+
+static int Open ( vlc_object_t *p_this )
+{
+ p_this->p_private = ppppf_motion;
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * motionmmxext.c : MMX EXT motion compensation module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: motionmmxext.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Michel Lespinasse <walken@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "mmx.h"
+
+/*****************************************************************************
+ * Local prototype.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("MMX EXT motion compensation module") );
+ set_capability( "motion compensation", 200 );
+ add_requirement( MMXEXT );
+ add_shortcut( "mmxext" );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Motion compensation in MMXEXT (OK I know this does 3DNow too and it's ugly)
+ *****************************************************************************/
+
+#define CPU_MMXEXT 0
+#define CPU_3DNOW 1
+
+
+//CPU_MMXEXT/CPU_3DNOW adaptation layer
+
+#define pavg_r2r(src,dest) \
+do { \
+ if (cpu == CPU_MMXEXT) \
+ pavgb_r2r (src, dest); \
+ else \
+ pavgusb_r2r (src, dest); \
+} while (0)
+
+#define pavg_m2r(src,dest) \
+do { \
+ if (cpu == CPU_MMXEXT) \
+ pavgb_m2r (src, dest); \
+ else \
+ pavgusb_m2r (src, dest); \
+} while (0)
+
+
+//CPU_MMXEXT code
+
+
+static inline void MC_put1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_r2m (mm0, *dest);
+ ref += stride;
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_put1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ pavg_m2r (*dest, mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ pavg_m2r (*dest, mm0);
+ pavg_m2r (*(dest+8), mm1);
+ movq_r2m (mm0, *dest);
+ ref += stride;
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_put2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ pavg_m2r (*(ref+offset), mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_put2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ pavg_m2r (*(ref+offset), mm0);
+ pavg_m2r (*(ref+offset+8), mm1);
+ movq_r2m (mm0, *dest);
+ ref += stride;
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ pavg_m2r (*(ref+offset), mm0);
+ pavg_m2r (*dest, mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int offset, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+8), mm1);
+ pavg_m2r (*(ref+offset), mm0);
+ pavg_m2r (*(ref+offset+8), mm1);
+ pavg_m2r (*dest, mm0);
+ pavg_m2r (*(dest+8), mm1);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ movq_r2m (mm1, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static mmx_t mask_one = {0x0101010101010101LL};
+
+static inline void MC_put4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+1), mm1);
+ movq_r2r (mm0, mm7);
+ pxor_r2r (mm1, mm7);
+ pavg_r2r (mm1, mm0);
+ ref += stride;
+
+ do {
+ movq_m2r (*ref, mm2);
+ movq_r2r (mm0, mm5);
+
+ movq_m2r (*(ref+1), mm3);
+ movq_r2r (mm2, mm6);
+
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm3, mm2);
+
+ por_r2r (mm6, mm7);
+ pxor_r2r (mm2, mm5);
+
+ pand_r2r (mm5, mm7);
+ pavg_r2r (mm2, mm0);
+
+ pand_m2r (mask_one, mm7);
+
+ psubusb_r2r (mm7, mm0);
+
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+
+ movq_r2r (mm6, mm7); // unroll !
+ movq_r2r (mm2, mm0); // unroll !
+ } while (--height);
+}
+
+static inline void MC_put4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+stride+1), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+1), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_r2m (mm0, *dest);
+
+ movq_m2r (*(ref+8), mm0);
+ movq_m2r (*(ref+stride+9), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+9), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride+8), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ ref += stride;
+ movq_r2m (mm0, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+stride+1), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+1), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_m2r (*dest, mm1);
+ pavg_r2r (mm1, mm0);
+ ref += stride;
+ movq_r2m (mm0, *dest);
+ dest += stride;
+ } while (--height);
+}
+
+static inline void MC_avg4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int cpu)
+{
+ do {
+ movq_m2r (*ref, mm0);
+ movq_m2r (*(ref+stride+1), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+1), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_m2r (*dest, mm1);
+ pavg_r2r (mm1, mm0);
+ movq_r2m (mm0, *dest);
+
+ movq_m2r (*(ref+8), mm0);
+ movq_m2r (*(ref+stride+9), mm1);
+ movq_r2r (mm0, mm7);
+ movq_m2r (*(ref+9), mm2);
+ pxor_r2r (mm1, mm7);
+ movq_m2r (*(ref+stride+8), mm3);
+ movq_r2r (mm2, mm6);
+ pxor_r2r (mm3, mm6);
+ pavg_r2r (mm1, mm0);
+ pavg_r2r (mm3, mm2);
+ por_r2r (mm6, mm7);
+ movq_r2r (mm0, mm6);
+ pxor_r2r (mm2, mm6);
+ pand_r2r (mm6, mm7);
+ pand_m2r (mask_one, mm7);
+ pavg_r2r (mm2, mm0);
+ psubusb_r2r (mm7, mm0);
+ movq_m2r (*(dest+8), mm1);
+ pavg_r2r (mm1, mm0);
+ ref += stride;
+ movq_r2m (mm0, *(dest+8));
+ dest += stride;
+ } while (--height);
+}
+
+static void MC_avg_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_16 (height, dest, ref, stride);
+}
+
+static void MC_put_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_8 (height, dest, ref, stride);
+}
+
+static void MC_avg_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_avg_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_put_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_put_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
+}
+
+static void MC_avg_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_put_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_put_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg4_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_avg_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg4_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put4_16 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+static void MC_put_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put4_8 (height, dest, ref, stride, CPU_MMXEXT);
+}
+
+
+static void MC_avg_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_16 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_avg_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg1_8 (height, dest, ref, stride, CPU_3DNOW);
+}
+
+static void MC_put_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_16 (height, dest, ref, stride);
+}
+
+static void MC_put_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put1_8 (height, dest, ref, stride);
+}
+
+static void MC_avg_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_avg_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_put_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_put_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
+}
+
+static void MC_avg_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_avg_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_avg2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_put_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+static void MC_put_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
+ int stride, int height)
+{
+ MC_put2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
+}
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void (* ppppf_motion[2][2][4])( yuv_data_t *, yuv_data_t *, int, int ) =
+{
+ /* Copying functions */
+ {
+ /* Width == 16 */
+ { MC_put_16_mmxext, MC_put_x16_mmxext, MC_put_y16_mmxext, MC_put_xy16_mmxext },
+ /* Width == 8 */
+ { MC_put_8_mmxext, MC_put_x8_mmxext, MC_put_y8_mmxext, MC_put_xy8_mmxext }
+ },
+ /* Averaging functions */
+ {
+ /* Width == 16 */
+ { MC_avg_16_mmxext, MC_avg_x16_mmxext, MC_avg_y16_mmxext, MC_avg_xy16_mmxext },
+ /* Width == 8 */
+ { MC_avg_8_mmxext, MC_avg_x8_mmxext, MC_avg_y8_mmxext, MC_avg_xy8_mmxext }
+ }
+};
+
+static int Open ( vlc_object_t *p_this )
+{
+ p_this->p_private = ppppf_motion;
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * video_parser.c : video parser thread
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: parser.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Samuel Hocevar <sam@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> /* getpid() */
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#include "vdec_ext-plugins.h"
+
+#include "decoder.h"
+#include "pool.h"
+#include "parser.h"
+
+/*
+ * Local prototypes
+ */
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+static int InitThread ( vpar_thread_t * );
+static void EndThread ( vpar_thread_t * );
+static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define VDEC_IDCT_TEXT N_("IDCT module")
+#define VDEC_IDCT_LONGTEXT N_( \
+ "This option allows you to select the IDCT module used by this video " \
+ "decoder. The default behavior is to automatically select the best " \
+ "module available.")
+
+#define VDEC_MOTION_TEXT N_("motion compensation module")
+#define VDEC_MOTION_LONGTEXT N_( \
+ "This option allows you to select the motion compensation module used by "\
+ "this video decoder. The default behavior is to automatically select the "\
+ "best module available.")
+
+#define VDEC_SMP_TEXT N_("use additional processors")
+#define VDEC_SMP_LONGTEXT N_( \
+ "This video decoder can benefit from a multiprocessor computer. If you " \
+ "have one, you can specify the number of processors here.")
+
+#define VPAR_SYNCHRO_TEXT N_("force synchro algorithm {I|I+|IP|IP+|IPB}")
+#define VPAR_SYNCHRO_LONGTEXT N_( \
+ "This allows you to force the synchro algorithm, by directly selecting " \
+ "the types of picture you want to decode. Please bear in mind that if " \
+ "you select more pictures than what your CPU is capable to decode, " \
+ "you won't get anything.")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_module ( "mpeg-idct", "idct", NULL, NULL,
+ VDEC_IDCT_TEXT, VDEC_IDCT_LONGTEXT );
+ add_module ( "mpeg-motion", "motion", NULL, NULL,
+ VDEC_MOTION_TEXT, VDEC_IDCT_LONGTEXT );
+ add_integer ( "vdec-smp", 0, NULL, VDEC_SMP_TEXT, VDEC_SMP_LONGTEXT );
+ add_string ( "vpar-synchro", NULL, NULL, VPAR_SYNCHRO_TEXT,
+ VPAR_SYNCHRO_LONGTEXT );
+ set_description( _("MPEG I/II video decoder module") );
+ set_capability( "decoder", 50 );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to chose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc == VLC_FOURCC('m','p','g','v') )
+ {
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+ }
+
+ return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder ( decoder_fifo_t * p_fifo )
+{
+ vpar_thread_t * p_vpar;
+ vlc_bool_t b_error;
+
+ /* Allocate the memory needed to store the thread's structure */
+ if ( (p_vpar = (vpar_thread_t *)malloc( sizeof(vpar_thread_t) )) == NULL )
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_vpar->p_fifo = p_fifo;
+ p_vpar->p_vout = NULL;
+
+ /*
+ * Initialize thread
+ */
+ p_vpar->p_fifo->b_error = InitThread( p_vpar );
+
+ /*
+ * Main loop - it is not executed if an error occured during
+ * initialization
+ */
+ while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
+ {
+ /* Find the next sequence header in the stream */
+ p_vpar->p_fifo->b_error = vpar_NextSequenceHeader( p_vpar );
+
+ while( (!p_vpar->p_fifo->b_die) && (!p_vpar->p_fifo->b_error) )
+ {
+ p_vpar->c_loops++;
+
+ /* Parse the next sequence, group or picture header */
+ if( vpar_ParseHeader( p_vpar ) )
+ {
+ /* End of sequence */
+ break;
+ }
+ }
+ }
+
+ /*
+ * Error loop
+ */
+ if( ( b_error = p_vpar->p_fifo->b_error ) )
+ {
+ DecoderError( p_vpar->p_fifo );
+ }
+
+ /* End of thread */
+ EndThread( p_vpar );
+
+ if( b_error )
+ {
+ return( -1 );
+ }
+
+ return( 0 );
+
+}
+
+/*****************************************************************************
+ * InitThread: initialize vpar output thread
+ *****************************************************************************
+ * This function is called from Run and performs the second step
+ * of the initialization. It returns 0 on success. Note that the thread's
+ * flag are not modified inside this function.
+ *****************************************************************************/
+static int InitThread( vpar_thread_t *p_vpar )
+{
+ char *psz_name;
+
+ /*
+ * Choose the best motion compensation module
+ */
+ psz_name = config_GetPsz( p_vpar->p_fifo, "mpeg-motion" );
+ p_vpar->p_motion =
+ module_Need( p_vpar->p_fifo, "motion compensation", psz_name );
+ if( psz_name ) free( psz_name );
+
+ if( p_vpar->p_motion == NULL )
+ {
+ msg_Err( p_vpar->p_fifo, "no suitable motion compensation module" );
+ free( p_vpar );
+ return( -1 );
+ }
+
+ memcpy( p_vpar->pool.ppppf_motion,
+ p_vpar->p_fifo->p_private, sizeof(void *) * 16 );
+
+ /*
+ * Choose the best IDCT module
+ */
+ psz_name = config_GetPsz( p_vpar->p_fifo, "mpeg-idct" );
+ p_vpar->p_idct = module_Need( p_vpar->p_fifo, "idct", psz_name );
+ if( psz_name ) free( psz_name );
+
+ if( p_vpar->p_idct == NULL )
+ {
+ msg_Err( p_vpar->p_fifo, "no suitable IDCT module" );
+ module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
+ free( p_vpar );
+ return( -1 );
+ }
+
+ p_vpar->pool.pf_idct_init = ((void**)p_vpar->p_fifo->p_private)[0];
+ p_vpar->pf_norm_scan = ((void**)p_vpar->p_fifo->p_private)[1];
+ p_vpar->pf_sparse_idct_add = ((void**)p_vpar->p_fifo->p_private)[2];
+ p_vpar->pf_sparse_idct_copy = ((void**)p_vpar->p_fifo->p_private)[3];
+ p_vpar->pf_idct_add = ((void**)p_vpar->p_fifo->p_private)[4];
+ p_vpar->pf_idct_copy = ((void**)p_vpar->p_fifo->p_private)[5];
+
+ /* Initialize input bitstream */
+ InitBitstream( &p_vpar->bit_stream, p_vpar->p_fifo,
+ BitstreamCallback, (void *)p_vpar );
+
+ /* Initialize parsing data */
+ p_vpar->sequence.p_forward = NULL;
+ p_vpar->sequence.p_backward = NULL;
+ p_vpar->sequence.intra_quant.b_allocated = 0;
+ p_vpar->sequence.nonintra_quant.b_allocated = 0;
+ p_vpar->sequence.chroma_intra_quant.b_allocated = 0;
+ p_vpar->sequence.chroma_nonintra_quant.b_allocated = 0;
+ p_vpar->sequence.i_matrix_coefficients = 1;
+ p_vpar->sequence.next_pts = p_vpar->sequence.next_dts = 0;
+ p_vpar->sequence.b_expect_discontinuity = 0;
+
+ p_vpar->sequence.i_width = 0;
+ p_vpar->sequence.i_height = 0;
+ p_vpar->sequence.i_frame_rate = 0;
+ p_vpar->sequence.i_scalable_mode = 0;
+ p_vpar->sequence.i_matrix_coefficients = 0;
+ p_vpar->sequence.b_mpeg2 = 0;
+ p_vpar->sequence.b_progressive = 0;
+
+ /* Initialize copyright information */
+ p_vpar->sequence.b_copyright_flag = 0;
+ p_vpar->sequence.b_original = 0;
+ p_vpar->sequence.i_copyright_id = 0;
+ p_vpar->sequence.i_copyright_nb = 0;
+
+ p_vpar->picture.p_picture = NULL;
+ p_vpar->picture.i_current_structure = 0;
+
+ /* Initialize other properties */
+ p_vpar->c_loops = 0;
+ p_vpar->c_sequences = 0;
+ memset(p_vpar->pc_pictures, 0, sizeof(p_vpar->pc_pictures));
+ memset(p_vpar->pc_decoded_pictures, 0, sizeof(p_vpar->pc_decoded_pictures));
+ memset(p_vpar->pc_malformed_pictures, 0,
+ sizeof(p_vpar->pc_malformed_pictures));
+ vpar_InitScanTable( p_vpar );
+
+ /*
+ * Initialize the synchro properties
+ */
+ vpar_SynchroInit( p_vpar );
+
+ /* Spawn optional video decoder threads */
+ vpar_InitPool( p_vpar );
+
+ /* Mark thread as running and return */
+ return( 0 );
+}
+
+/*****************************************************************************
+ * EndThread: thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+static void EndThread( vpar_thread_t *p_vpar )
+{
+#ifdef HAVE_SYS_TIMES_H
+ struct tms cpu_usage;
+ times( &cpu_usage );
+#endif
+
+ if( p_vpar->p_vout != NULL )
+ {
+ /* Release used video buffers. */
+ if( p_vpar->sequence.p_forward != NULL )
+ {
+ vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_forward );
+ }
+ if( p_vpar->sequence.p_backward != NULL )
+ {
+ vout_DatePicture( p_vpar->p_vout, p_vpar->sequence.p_backward,
+ vpar_SynchroDate( p_vpar ) );
+ vout_UnlinkPicture( p_vpar->p_vout, p_vpar->sequence.p_backward );
+ }
+ if( p_vpar->picture.p_picture != NULL )
+ {
+ vout_DestroyPicture( p_vpar->p_vout, p_vpar->picture.p_picture );
+ }
+
+ /* We are about to die. Reattach video output to p_vlc. */
+ vlc_object_detach( p_vpar->p_vout, p_vpar->p_fifo );
+ vlc_object_attach( p_vpar->p_vout, p_vpar->p_fifo->p_vlc );
+ }
+
+ msg_Dbg( p_vpar->p_fifo, "%d loops among %d sequence(s)",
+ p_vpar->c_loops, p_vpar->c_sequences );
+
+#ifdef HAVE_SYS_TIMES_H
+ msg_Dbg( p_vpar->p_fifo, "cpu usage (user: %d, system: %d)",
+ cpu_usage.tms_utime, cpu_usage.tms_stime );
+#endif
+
+ msg_Dbg( p_vpar->p_fifo, "read %d frames/fields (I %d/P %d/B %d)",
+ p_vpar->pc_pictures[I_CODING_TYPE]
+ + p_vpar->pc_pictures[P_CODING_TYPE]
+ + p_vpar->pc_pictures[B_CODING_TYPE],
+ p_vpar->pc_pictures[I_CODING_TYPE],
+ p_vpar->pc_pictures[P_CODING_TYPE],
+ p_vpar->pc_pictures[B_CODING_TYPE] );
+ msg_Dbg( p_vpar->p_fifo, "decoded %d frames/fields (I %d/P %d/B %d)",
+ p_vpar->pc_decoded_pictures[I_CODING_TYPE]
+ + p_vpar->pc_decoded_pictures[P_CODING_TYPE]
+ + p_vpar->pc_decoded_pictures[B_CODING_TYPE],
+ p_vpar->pc_decoded_pictures[I_CODING_TYPE],
+ p_vpar->pc_decoded_pictures[P_CODING_TYPE],
+ p_vpar->pc_decoded_pictures[B_CODING_TYPE] );
+ msg_Dbg( p_vpar->p_fifo,
+ "read %d malformed frames/fields (I %d/P %d/B %d)",
+ p_vpar->pc_malformed_pictures[I_CODING_TYPE]
+ + p_vpar->pc_malformed_pictures[P_CODING_TYPE]
+ + p_vpar->pc_malformed_pictures[B_CODING_TYPE],
+ p_vpar->pc_malformed_pictures[I_CODING_TYPE],
+ p_vpar->pc_malformed_pictures[P_CODING_TYPE],
+ p_vpar->pc_malformed_pictures[B_CODING_TYPE] );
+#define S p_vpar->sequence
+ msg_Dbg( p_vpar->p_fifo, "%s stream (%dx%d), %d.%d pi/s",
+ S.b_mpeg2 ? "MPEG-2" : "MPEG-1",
+ S.i_width, S.i_height, S.i_frame_rate/1001,
+ S.i_frame_rate % 1001 );
+ msg_Dbg( p_vpar->p_fifo, "%s, %s, matrix_coeff: %d",
+ S.b_progressive ? "Progressive" : "Non-progressive",
+ S.i_scalable_mode ? "scalable" : "non-scalable",
+ S.i_matrix_coefficients );
+#undef S
+
+ /* Dispose of matrices if they have been allocated. */
+ if( p_vpar->sequence.intra_quant.b_allocated )
+ {
+ free( p_vpar->sequence.intra_quant.pi_matrix );
+ }
+ if( p_vpar->sequence.nonintra_quant.b_allocated )
+ {
+ free( p_vpar->sequence.nonintra_quant.pi_matrix) ;
+ }
+ if( p_vpar->sequence.chroma_intra_quant.b_allocated )
+ {
+ free( p_vpar->sequence.chroma_intra_quant.pi_matrix );
+ }
+ if( p_vpar->sequence.chroma_nonintra_quant.b_allocated )
+ {
+ free( p_vpar->sequence.chroma_nonintra_quant.pi_matrix );
+ }
+
+ vpar_EndPool( p_vpar );
+
+ module_Unneed( p_vpar->p_fifo, p_vpar->p_idct );
+ module_Unneed( p_vpar->p_fifo, p_vpar->p_motion );
+
+ free( p_vpar );
+}
+
+/*****************************************************************************
+ * BitstreamCallback: Import parameters from the new data/PES packet
+ *****************************************************************************
+ * This function is called by input's NextDataPacket.
+ *****************************************************************************/
+static void BitstreamCallback ( bit_stream_t * p_bit_stream,
+ vlc_bool_t b_new_pes )
+{
+ vpar_thread_t * p_vpar = (vpar_thread_t *)p_bit_stream->p_callback_arg;
+
+ if( b_new_pes )
+ {
+ p_vpar->sequence.i_current_rate =
+ p_bit_stream->p_decoder_fifo->p_first->i_rate;
+
+ if( p_bit_stream->p_decoder_fifo->p_first->b_discontinuity )
+ {
+ /* Escape the current picture and reset the picture predictors. */
+ p_vpar->sequence.b_expect_discontinuity = 1;
+ p_vpar->picture.b_error = 1;
+ }
+ }
+
+ if( p_bit_stream->p_data->b_discard_payload )
+ {
+ /* 1 packet messed up, trash the slice. */
+ p_vpar->picture.b_error = 1;
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * video_parser.h : video parser thread
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: parser.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Jean-Marc Dressler <polux@via.ecp.fr>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*
+ * Block parsing structures
+ */
+
+/*****************************************************************************
+ * macroblock_parsing_t : macroblock context & predictors
+ *****************************************************************************/
+typedef struct motion_s
+{
+ u8 * pppi_ref[2][3];
+ int ppi_pmv[2][2];
+ int pi_f_code[2];
+} motion_t;
+
+typedef struct macroblock_parsing_s
+{
+ int i_offset;
+
+ motion_t b_motion;
+ motion_t f_motion;
+
+ /* Predictor for DC coefficients in intra blocks */
+ u16 pi_dc_dct_pred[3];
+ u8 i_quantizer_scale; /* scale of the quantization
+ * matrices */
+} macroblock_parsing_t;
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+extern u8 pi_default_intra_quant[64];
+extern u8 pi_default_nonintra_quant[64];
+extern u8 pi_scan[2][64];
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_InitScanTable( struct vpar_thread_s * p_vpar );
+
+typedef void (*f_picture_data_t)( struct vpar_thread_s * p_vpar );
+#define PROTO_PICD( FUNCNAME ) \
+void FUNCNAME( struct vpar_thread_s * p_vpar );
+
+PROTO_PICD( vpar_PictureDataGENERIC )
+#if (VPAR_OPTIM_LEVEL > 0)
+PROTO_PICD( vpar_PictureData2IF )
+PROTO_PICD( vpar_PictureData2PF )
+PROTO_PICD( vpar_PictureData2BF )
+#endif
+#if (VPAR_OPTIM_LEVEL > 1)
+PROTO_PICD( vpar_PictureData2IT )
+PROTO_PICD( vpar_PictureData2PT )
+PROTO_PICD( vpar_PictureData2BT )
+PROTO_PICD( vpar_PictureData2IB )
+PROTO_PICD( vpar_PictureData2PB )
+PROTO_PICD( vpar_PictureData2BB )
+PROTO_PICD( vpar_PictureData1I )
+PROTO_PICD( vpar_PictureData1P )
+PROTO_PICD( vpar_PictureData1B )
+PROTO_PICD( vpar_PictureData1D )
+#endif
+
+
+/*
+ * Headers parsing structures
+ */
+
+/*****************************************************************************
+ * quant_matrix_t : Quantization Matrix
+ *****************************************************************************/
+typedef struct quant_matrix_s
+{
+ u8 * pi_matrix;
+ vlc_bool_t b_allocated;
+ /* Has the matrix been allocated by vpar_headers ? */
+} quant_matrix_t;
+
+/*****************************************************************************
+ * sequence_t : sequence descriptor
+ *****************************************************************************
+ * This structure should only be changed when reading the sequence header,
+ * or exceptionnally some extension structures (like quant_matrix).
+ *****************************************************************************/
+typedef struct sequence_s
+{
+ u32 i_height, i_width; /* height and width of the lum
+ * comp of the picture */
+ u32 i_size; /* total number of pel of the lum comp */
+ u32 i_mb_height, i_mb_width, i_mb_size;
+ /* the same, in macroblock units */
+ unsigned int i_aspect; /* height/width display ratio */
+ unsigned int i_matrix_coefficients;/* coeffs of the YUV transform */
+ int i_chroma_format, i_scalable_mode;
+ int i_chroma_nb_blocks;
+ vlc_bool_t b_chroma_h_subsampled, b_chroma_v_subsampled;
+ int i_frame_rate; /* theoritical frame rate in fps*1001 */
+ vlc_bool_t b_mpeg2; /* guess */
+ vlc_bool_t b_progressive; /* progressive (ie.
+ * non-interlaced) frame */
+ quant_matrix_t intra_quant, nonintra_quant;
+ quant_matrix_t chroma_intra_quant, chroma_nonintra_quant;
+ /* current quantization matrices */
+
+ /* Parser context */
+ picture_t * p_forward; /* current forward reference frame */
+ picture_t * p_backward; /* current backward reference frame */
+ mtime_t next_pts, next_dts;
+ int i_current_rate;
+ vlc_bool_t b_expect_discontinuity; /* reset the frame predictors
+ * after the current frame */
+
+ /* Copyright extension */
+ vlc_bool_t b_copyright_flag; /* Whether the following
+ information is significant
+ or not. */
+ u8 i_copyright_id;
+ vlc_bool_t b_original;
+ u64 i_copyright_nb;
+} sequence_t;
+
+/*****************************************************************************
+ * picture_parsing_t : parser context descriptor
+ *****************************************************************************
+ * This structure should only be changed when reading the picture header.
+ *****************************************************************************/
+typedef struct picture_parsing_s
+{
+ /* Values from the picture_coding_extension. */
+ int ppi_f_code[2][2];
+ int i_intra_dc_precision;
+ vlc_bool_t b_frame_pred_frame_dct, b_q_scale_type;
+ vlc_bool_t b_intra_vlc_format;
+ vlc_bool_t b_progressive;
+ u8 * pi_scan;
+ vlc_bool_t b_top_field_first, b_concealment_mv;
+ vlc_bool_t b_repeat_first_field;
+ /* Relative to the current field */
+ int i_coding_type, i_structure, i_field_width;
+ vlc_bool_t b_frame_structure; /* i_structure == FRAME_STRUCTURE */
+ vlc_bool_t b_current_field; /* i_structure == TOP_FIELD */
+ vlc_bool_t b_second_field;
+
+ picture_t * p_picture; /* picture buffer from vout */
+ int i_current_structure; /* current parsed structure of
+ * p_picture (second field ?) */
+ vlc_bool_t b_error; /* parsing error, try to recover */
+
+ /* Given by the video output */
+ int i_lum_stride, i_chrom_stride;
+} picture_parsing_t;
+
+/*****************************************************************************
+ * Standard codes
+ *****************************************************************************/
+#define PICTURE_START_CODE 0x100L
+#define SLICE_START_CODE_MIN 0x101L
+#define SLICE_START_CODE_MAX 0x1AFL
+#define USER_DATA_START_CODE 0x1B2L
+#define SEQUENCE_HEADER_CODE 0x1B3L
+#define SEQUENCE_ERROR_CODE 0x1B4L
+#define EXTENSION_START_CODE 0x1B5L
+#define SEQUENCE_END_CODE 0x1B7L
+#define GROUP_START_CODE 0x1B8L
+
+/* extension start code IDs */
+#define SEQUENCE_EXTENSION_ID 1
+#define SEQUENCE_DISPLAY_EXTENSION_ID 2
+#define QUANT_MATRIX_EXTENSION_ID 3
+#define COPYRIGHT_EXTENSION_ID 4
+#define SEQUENCE_SCALABLE_EXTENSION_ID 5
+#define PICTURE_DISPLAY_EXTENSION_ID 7
+#define PICTURE_CODING_EXTENSION_ID 8
+#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID 9
+#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID 10
+
+/* scalable modes */
+#define SC_NONE 0
+#define SC_DP 1
+#define SC_SPAT 2
+#define SC_SNR 3
+#define SC_TEMP 4
+
+/* Chroma types */
+#define CHROMA_NONE 0
+#define CHROMA_420 1
+#define CHROMA_422 2
+#define CHROMA_444 3
+
+/* Pictures types */
+#define I_CODING_TYPE 1
+#define P_CODING_TYPE 2
+#define B_CODING_TYPE 3
+#define D_CODING_TYPE 4 /* MPEG-1 ONLY */
+/* other values are reserved */
+
+/* Structures */
+#define TOP_FIELD 1
+#define BOTTOM_FIELD 2
+#define FRAME_STRUCTURE 3
+
+/* Aspect ratio (ISO/IEC 13818-2 section 6.3.3, table 6-3) */
+#define AR_SQUARE_PICTURE 1 /* square pixels */
+#define AR_3_4_PICTURE 2 /* 3:4 picture (TV) */
+#define AR_16_9_PICTURE 3 /* 16:9 picture (wide screen) */
+#define AR_221_1_PICTURE 4 /* 2.21:1 picture (movie) */
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+int vpar_NextSequenceHeader( struct vpar_thread_s * p_vpar );
+int vpar_ParseHeader( struct vpar_thread_s * p_vpar );
+
+
+/*
+ * Synchronization management
+ */
+
+/*****************************************************************************
+ * video_synchro_t : timers for the video synchro
+ *****************************************************************************/
+#define MAX_PIC_AVERAGE 8
+
+/* Read the discussion on top of vpar_synchro.c for more information. */
+typedef struct video_synchro_s
+{
+ /* synchro algorithm */
+ int i_type;
+
+ /* date of the beginning of the decoding of the current picture */
+ mtime_t decoding_start;
+
+ /* stream properties */
+ unsigned int i_n_p, i_n_b;
+
+ /* decoding values */
+ mtime_t p_tau[4]; /* average decoding durations */
+ unsigned int pi_meaningful[4]; /* number of durations read */
+ /* and p_vout->render_time (read with p_vout->change_lock) */
+
+ /* stream context */
+ unsigned int i_eta_p, i_eta_b;
+ vlc_bool_t b_dropped_last; /* for special synchros below */
+ mtime_t backward_pts, current_pts;
+ int i_current_period; /* period to add to the next picture */
+ int i_backward_period; /* period to add after the next
+ * reference picture
+ * (backward_period * period / 2) */
+
+ /* statistics */
+ unsigned int i_trashed_pic, i_not_chosen_pic, i_pic;
+} video_synchro_t;
+
+/* Synchro algorithms */
+#define VPAR_SYNCHRO_DEFAULT 0
+#define VPAR_SYNCHRO_I 1
+#define VPAR_SYNCHRO_Iplus 2
+#define VPAR_SYNCHRO_IP 3
+#define VPAR_SYNCHRO_IPplus 4
+#define VPAR_SYNCHRO_IPB 5
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_SynchroInit ( struct vpar_thread_s * p_vpar );
+vlc_bool_t vpar_SynchroChoose ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure );
+void vpar_SynchroTrash ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure );
+void vpar_SynchroDecode ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure );
+void vpar_SynchroEnd ( struct vpar_thread_s * p_vpar,
+ int i_coding_type, int i_structure,
+ int i_garbage );
+mtime_t vpar_SynchroDate ( struct vpar_thread_s * p_vpar );
+void vpar_SynchroNewPicture( struct vpar_thread_s * p_vpar, int i_coding_type,
+ int i_repeat_field );
+
+
+/*
+ * Video parser structures
+ */
+
+/*****************************************************************************
+ * vpar_thread_t: video parser thread descriptor
+ *****************************************************************************/
+typedef struct vpar_thread_s
+{
+ bit_stream_t bit_stream;
+
+ /* Thread properties and locks */
+ vlc_thread_t thread_id; /* id for thread functions */
+
+ /* Input properties */
+ decoder_fifo_t * p_fifo; /* PES input fifo */
+
+ /* Output properties */
+ vout_thread_t * p_vout; /* video output thread */
+
+ /* Decoder properties */
+ vdec_pool_t pool;
+
+ /* Parser properties */
+ sequence_t sequence;
+ picture_parsing_t picture;
+ macroblock_parsing_t mb;
+ video_synchro_t synchro;
+
+ /* Scan table */
+ u8 ppi_scan[2][64];
+ /* Default quantization matrices */
+ u8 pi_default_intra_quant[64];
+ u8 pi_default_nonintra_quant[64];
+
+ /* Motion compensation plug-in used and shortcuts */
+ module_t * p_motion;
+
+ /* IDCT plug-in used and shortcuts */
+ module_t * p_idct;
+ void ( * pf_sparse_idct_add )( dctelem_t *, yuv_data_t *, int,
+ void *, int );
+ void ( * pf_idct_add ) ( dctelem_t *, yuv_data_t *, int,
+ void *, int );
+ void ( * pf_sparse_idct_copy )( dctelem_t *, yuv_data_t *, int,
+ void *, int );
+ void ( * pf_idct_copy ) ( dctelem_t *, yuv_data_t *, int,
+ void *, int );
+
+ void ( * pf_norm_scan ) ( u8 ppi_scan[2][64] );
+
+ /* Statistics */
+ count_t c_loops; /* number of loops */
+ count_t c_sequences; /* number of sequences */
+ count_t pc_pictures[4]; /* number of (coding_type) pictures read */
+ count_t pc_decoded_pictures[4]; /* number of (coding_type)
+ * pictures decoded */
+ count_t pc_malformed_pictures[4]; /* number of pictures trashed
+ * during parsing */
+} vpar_thread_t;
+
+/*****************************************************************************
+ * NextStartCode : Find the next start code
+ *****************************************************************************/
+static inline void NextStartCode( bit_stream_t * p_bit_stream )
+{
+ /* Re-align the buffer on an 8-bit boundary */
+ RealignBits( p_bit_stream );
+
+ while( ShowBits( p_bit_stream, 24 ) != 0x01L
+ && !p_bit_stream->p_decoder_fifo->b_die )
+ {
+ RemoveBits( p_bit_stream, 8 );
+ }
+}
+
+/*****************************************************************************
+ * LoadQuantizerScale
+ *****************************************************************************
+ * Quantizer scale factor (ISO/IEC 13818-2 7.4.2.2)
+ *****************************************************************************/
+static inline void LoadQuantizerScale( struct vpar_thread_s * p_vpar )
+{
+ /* Quantization coefficient table */
+ static u8 pi_non_linear_quantizer_scale[32] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10,12,14,16,18,20, 22,
+ 24,28,32,36,40,44,48,52,56,64,72,80,88,96,104,112
+ };
+ int i_q_scale_code = GetBits( &p_vpar->bit_stream, 5 );
+
+ if( p_vpar->picture.b_q_scale_type )
+ {
+ p_vpar->mb.i_quantizer_scale =
+ pi_non_linear_quantizer_scale[i_q_scale_code];
+ }
+ else
+ {
+ p_vpar->mb.i_quantizer_scale = i_q_scale_code << 1;
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * vpar_pool.c : management of the pool of decoder threads
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: pool.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h> /* memcpy(), memset() */
+#include <stdlib.h> /* realloc() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#include "vdec_ext-plugins.h"
+
+#include "decoder.h"
+#include "pool.h"
+#include "parser.h"
+
+/*
+ * Local prototypes
+ */
+static void WaitDummy( vdec_pool_t * p_pool );
+static void WaitPool( vdec_pool_t * p_pool );
+static void FreeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static void FreeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static macroblock_t * NewMacroblockDummy( vdec_pool_t * p_pool );
+static macroblock_t * NewMacroblockPool( vdec_pool_t * p_pool );
+static void DecodeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb );
+static void DecodeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb );
+
+/*****************************************************************************
+ * vpar_InitPool: Initializes the pool structure
+ *****************************************************************************/
+void vpar_InitPool( vpar_thread_t * p_vpar )
+{
+ int j;
+
+ /* Initialize mutex and cond. */
+ vlc_mutex_init( p_vpar->p_fifo, &p_vpar->pool.lock );
+ vlc_cond_init( p_vpar->p_fifo, &p_vpar->pool.wait_empty );
+ vlc_cond_init( p_vpar->p_fifo, &p_vpar->pool.wait_undecoded );
+
+ /* Spawn optional video decoder threads. */
+ p_vpar->pool.i_smp = 0;
+ p_vpar->pool.pp_vdec = NULL;
+ p_vpar->pool.p_macroblocks = NULL;
+ p_vpar->pool.pp_empty_macroblocks = NULL;
+ p_vpar->pool.pp_new_macroblocks = NULL;
+ p_vpar->pool.p_vpar = p_vpar;
+ vpar_SpawnPool( p_vpar );
+
+ /* Initialize fake video decoder structure (used when
+ * decoder == parser). */
+ p_vpar->pool.p_vdec = vlc_object_create( p_vpar->p_fifo,
+ sizeof(vdec_thread_t) );
+ if ( p_vpar->pool.p_vdec == NULL )
+ {
+ msg_Err( p_vpar->p_fifo, "out of memory" );
+ p_vpar->p_fifo->b_error = 1;
+ return;
+ }
+ p_vpar->pool.p_vdec->p_pool = &p_vpar->pool;
+ vdec_InitThread( p_vpar->pool.p_vdec );
+
+ vlc_object_attach( p_vpar->pool.p_vdec, p_vpar->p_fifo );
+
+ for( j = 0; j < 12; j++ )
+ {
+ p_vpar->pool.mb.p_idcts[j].pi_block =
+ vlc_memalign( &p_vpar->pool.mb.p_idcts[j].pi_block_orig,
+ 16, 64 * sizeof(dctelem_t) );
+ }
+}
+
+/*****************************************************************************
+ * vpar_SpawnPool: Create and cancel video decoder threads at any time
+ *****************************************************************************
+ * This function is called on startup, and everytime the user changes the
+ * number of threads to launch. Please note that *all* decoder threads must
+ * be idle during this operation, which only happens at the end of
+ * PictureHeader().
+ *****************************************************************************/
+void vpar_SpawnPool( vpar_thread_t * p_vpar )
+{
+ int i_new_smp;
+ stream_ctrl_t * p_control;
+
+ p_control = p_vpar->p_fifo->p_stream_ctrl;
+ vlc_mutex_lock( &p_control->control_lock );
+ i_new_smp = config_GetInt( p_vpar->p_fifo, "vdec-smp" );
+ vlc_mutex_unlock( &p_control->control_lock );
+
+ /* FIXME: No error check because I'm tired. Come back later... */
+
+ /* No need to lock p_vpar->pool, since decoders MUST be idle here. */
+ if( p_vpar->pool.i_smp != i_new_smp )
+ {
+ int i;
+
+ if( p_vpar->pool.i_smp > i_new_smp )
+ {
+ /* The user reduces the number of threads. */
+
+ for( i = p_vpar->pool.i_smp - 1; i >= i_new_smp; i-- )
+ {
+ int j;
+
+ vlc_object_detach_all( p_vpar->pool.pp_vdec[i] );
+ vdec_DestroyThread( p_vpar->pool.pp_vdec[i] );
+
+ for( j = 0; j < 12; j++ )
+ {
+ free( p_vpar->pool.p_macroblocks[i].p_idcts[j].pi_block_orig );
+ }
+ }
+
+ p_vpar->pool.pp_vdec = realloc( p_vpar->pool.pp_vdec,
+ i_new_smp * sizeof(vdec_thread_t *) );
+ p_vpar->pool.p_macroblocks = realloc( p_vpar->pool.p_macroblocks,
+ i_new_smp * sizeof(macroblock_t) );
+ p_vpar->pool.pp_empty_macroblocks = realloc( p_vpar->pool.pp_empty_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_empty = i_new_smp;
+ p_vpar->pool.pp_new_macroblocks = realloc( p_vpar->pool.pp_new_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_new = 0;
+ }
+ else
+ {
+ /* The user raises the number of threads. */
+
+ p_vpar->pool.pp_vdec = realloc( p_vpar->pool.pp_vdec,
+ i_new_smp * sizeof(vdec_thread_t *) );
+ p_vpar->pool.p_macroblocks = realloc( p_vpar->pool.p_macroblocks,
+ i_new_smp * sizeof(macroblock_t) );
+ p_vpar->pool.pp_empty_macroblocks = realloc( p_vpar->pool.pp_empty_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_empty = i_new_smp;
+ p_vpar->pool.pp_new_macroblocks = realloc( p_vpar->pool.pp_new_macroblocks,
+ i_new_smp * sizeof(macroblock_t *) );
+ p_vpar->pool.i_index_new = 0;
+
+ for( i = p_vpar->pool.i_smp; i < i_new_smp ; i++ )
+ {
+ int j;
+
+ for( j = 0; j < 12; j++ )
+ {
+ p_vpar->pool.p_macroblocks[i].p_idcts[j].pi_block =
+ vlc_memalign( &p_vpar->pool.p_macroblocks[i].p_idcts[j].pi_block_orig,
+ 16, 64 * sizeof(dctelem_t) );
+ }
+
+ p_vpar->pool.pp_vdec[i] = vdec_CreateThread( &p_vpar->pool );
+ vlc_object_attach( p_vpar->pool.pp_vdec[i], p_vpar->p_fifo );
+ }
+
+ }
+ for( i = 0; i < i_new_smp; i++ )
+ {
+ p_vpar->pool.pp_empty_macroblocks[i] =
+ &p_vpar->pool.p_macroblocks[i];
+ }
+ p_vpar->pool.i_smp = i_new_smp;
+ }
+
+ if( i_new_smp )
+ {
+ /* We have at least one decoder thread. */
+ p_vpar->pool.pf_wait_pool = WaitPool;
+ p_vpar->pool.pf_new_mb = NewMacroblockPool;
+ p_vpar->pool.pf_free_mb = FreeMacroblockPool;
+ p_vpar->pool.pf_decode_mb = DecodeMacroblockPool;
+ }
+ else
+ {
+ /* No decoder pool. */
+ p_vpar->pool.pf_wait_pool = WaitDummy;
+ p_vpar->pool.pf_new_mb = NewMacroblockDummy;
+ p_vpar->pool.pf_free_mb = FreeMacroblockDummy;
+ p_vpar->pool.pf_decode_mb = DecodeMacroblockDummy;
+ }
+}
+
+/*****************************************************************************
+ * vpar_EndPool: Releases the pool structure
+ *****************************************************************************/
+void vpar_EndPool( vpar_thread_t * p_vpar )
+{
+ int i;
+
+ for( i = 0; i < 12; i++ )
+ {
+ free( p_vpar->pool.mb.p_idcts[i].pi_block_orig );
+ }
+
+ for( i = 0; i < p_vpar->pool.i_smp; i++ )
+ {
+ int j;
+
+ vlc_object_detach_all( p_vpar->pool.pp_vdec[i] );
+ vdec_DestroyThread( p_vpar->pool.pp_vdec[i] );
+
+ for( j = 0; j < 12; j++ )
+ {
+ free( p_vpar->pool.p_macroblocks[i].p_idcts[j].pi_block_orig );
+ }
+ }
+
+ if( p_vpar->pool.i_smp )
+ {
+ free( p_vpar->pool.pp_vdec );
+ free( p_vpar->pool.p_macroblocks );
+ free( p_vpar->pool.pp_new_macroblocks );
+ }
+
+ /* Free fake video decoder (used when parser == decoder). */
+ vlc_object_detach_all( p_vpar->pool.p_vdec );
+ vdec_EndThread( p_vpar->pool.p_vdec );
+ vlc_object_destroy( p_vpar->pool.p_vdec );
+
+ /* Destroy lock and cond. */
+ vlc_mutex_destroy( &p_vpar->pool.lock );
+ vlc_cond_destroy( &p_vpar->pool.wait_empty );
+ vlc_cond_destroy( &p_vpar->pool.wait_undecoded );
+}
+
+/*****************************************************************************
+ * WaitPool: Wait until all decoders are idle
+ *****************************************************************************/
+static void WaitPool( vdec_pool_t * p_pool )
+{
+ vlc_mutex_lock( &p_pool->lock );
+ while( p_pool->i_index_empty != p_pool->i_smp )
+ {
+ vlc_cond_wait( &p_pool->wait_empty, &p_pool->lock );
+ }
+ vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * WaitDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void WaitDummy( vdec_pool_t * p_pool )
+{
+}
+
+/*****************************************************************************
+ * NewMacroblockPool: Get an empty macroblock from the decoder pool
+ *****************************************************************************/
+static macroblock_t * NewMacroblockPool( vdec_pool_t * p_pool )
+{
+ macroblock_t * p_mb;
+
+ vlc_mutex_lock( &p_pool->lock );
+ while( p_pool->i_index_empty == 0 )
+ {
+ vlc_cond_wait( &p_pool->wait_empty, &p_pool->lock );
+ }
+ p_mb = p_pool->pp_empty_macroblocks[ --p_pool->i_index_empty ];
+ vlc_mutex_unlock( &p_pool->lock );
+ return( p_mb );
+}
+
+/*****************************************************************************
+ * NewMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static macroblock_t * NewMacroblockDummy( vdec_pool_t * p_pool )
+{
+ return( &p_pool->mb );
+}
+
+/*****************************************************************************
+ * FreeMacroblockPool: Free a macroblock
+ *****************************************************************************/
+static void FreeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+ vlc_mutex_lock( &p_pool->lock );
+ p_pool->pp_empty_macroblocks[ p_pool->i_index_empty++ ] = p_mb;
+ vlc_cond_signal( &p_pool->wait_empty );
+ vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * FreeMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void FreeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+}
+
+/*****************************************************************************
+ * DecodeMacroblockPool: Send a macroblock to a vdec thread
+ *****************************************************************************/
+static void DecodeMacroblockPool( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+ vlc_mutex_lock( &p_pool->lock );
+ /* The undecoded macroblock LIFO cannot be full, because
+ * #macroblocks == size of the LIFO */
+ p_pool->pp_new_macroblocks[ p_pool->i_index_new++ ] = p_mb;
+ vlc_cond_signal( &p_pool->wait_undecoded );
+ vlc_mutex_unlock( &p_pool->lock );
+}
+
+/*****************************************************************************
+ * DecodeMacroblockDummy: Placeholder used when parser == decoder
+ *****************************************************************************/
+static void DecodeMacroblockDummy( vdec_pool_t * p_pool, macroblock_t * p_mb )
+{
+ p_pool->pf_vdec_decode( p_pool->p_vdec, p_mb );
+}
+
--- /dev/null
+/*****************************************************************************
+ * vpar_pool.h : video parser/video decoders communication
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: pool.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * vdec_pool_t
+ *****************************************************************************
+ * This structure is used for the communication between the parser and the
+ * decoders.
+ *****************************************************************************/
+typedef struct vdec_pool_s vdec_pool_t;
+
+struct vdec_pool_s
+{
+ /* Locks */
+ vlc_mutex_t lock; /* Structure data lock */
+ vlc_cond_t wait_empty; /* The parser blocks there when all
+ * decoder threads are busy */
+ vlc_cond_t wait_undecoded; /* The decoders block there when no
+ * macroblock has been given by the
+ * parser */
+
+ /* Video decoder threads */
+ vdec_thread_t ** pp_vdec; /* Array of video decoder threads */
+ int i_smp; /* Number of symmetrical decoder threads,
+ * hence size of the pp_vdec, p_macroblocks
+ * and pp_new_macroblocks array */
+
+ /* Macroblocks */
+ macroblock_t * p_macroblocks;
+
+ /* Empty macroblocks */
+ macroblock_t ** pp_empty_macroblocks; /* Empty macroblocks */
+ int i_index_empty; /* Last empty macroblock */
+
+ /* Undecoded macroblocks, read by the decoders */
+ macroblock_t ** pp_new_macroblocks; /* Undecoded macroblocks */
+ int i_index_new; /* Last undecoded macroblock */
+
+ /* Undecoded macroblock, used when the parser and the decoder share the
+ * same thread */
+ macroblock_t mb;
+ vdec_thread_t * p_vdec; /* Fake video decoder */
+
+ /* Pointers to usual pool functions */
+ void (* pf_wait_pool) ( vdec_pool_t * );
+ macroblock_t * (* pf_new_mb) ( vdec_pool_t * );
+ void (* pf_free_mb) ( vdec_pool_t *, macroblock_t * );
+ void (* pf_decode_mb) ( vdec_pool_t *, macroblock_t * );
+
+ /* Pointer to the decoding function - used for B&W switching */
+ void (* pf_vdec_decode) ( struct vdec_thread_s *,
+ macroblock_t * );
+ vlc_bool_t b_bw; /* Current value for B&W */
+
+ /* Access to the plug-ins needed by the video decoder thread */
+ void ( * pf_idct_init ) ( void ** );
+ void ( * ppppf_motion[2][2][4] ) ( yuv_data_t *, yuv_data_t *,
+ int, int );
+
+ struct vpar_thread_s * p_vpar;
+};
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void vpar_InitPool ( struct vpar_thread_s * );
+void vpar_SpawnPool ( struct vpar_thread_s * );
+void vpar_EndPool ( struct vpar_thread_s * );
+
+/*****************************************************************************
+ * vpar_GetMacroblock: In a vdec thread, get the next available macroblock
+ *****************************************************************************/
+static inline macroblock_t * vpar_GetMacroblock( vdec_pool_t * p_pool,
+ volatile vlc_bool_t * pb_die )
+{
+ macroblock_t * p_mb;
+
+ vlc_mutex_lock( &p_pool->lock );
+ while( p_pool->i_index_new == 0 && !*pb_die )
+ {
+ vlc_cond_wait( &p_pool->wait_undecoded, &p_pool->lock );
+ }
+
+ if( *pb_die )
+ {
+ vlc_mutex_unlock( &p_pool->lock );
+ return( NULL );
+ }
+
+ p_mb = p_pool->pp_new_macroblocks[ --p_pool->i_index_new ];
+ vlc_mutex_unlock( &p_pool->lock );
+ return( p_mb );
+}
+
--- /dev/null
+/*****************************************************************************
+ * vpar_synchro.c : frame dropping routines
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: synchro.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Samuel Hocevar <sam@via.ecp.fr>
+ * Jean-Marc Dressler <polux@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*
+ * DISCUSSION : How to Write an efficient Frame-Dropping Algorithm
+ * ==========
+ *
+ * This implementation is based on mathematical and statistical
+ * developments. Older implementations used an enslavement, considering
+ * that if we're late when reading an I picture, we will decode one frame
+ * less. It had a tendancy to derive, and wasn't responsive enough, which
+ * would have caused trouble with the stream control stuff.
+ *
+ * 1. Structure of a picture stream
+ * =============================
+ * Between 2 I's, we have for instance :
+ * I B P B P B P B P B P B I
+ * t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12
+ * Please bear in mind that B's and IP's will be inverted when displaying
+ * (decoding order != presentation order). Thus, t1 < t0.
+ *
+ * 2. Definitions
+ * ===========
+ * t[0..12] : Presentation timestamps of pictures 0..12.
+ * t : Current timestamp, at the moment of the decoding.
+ * T : Picture period, T = 1/frame_rate.
+ * tau[I,P,B] : Mean time to decode an [I,P,B] picture.
+ * tauYUV : Mean time to render a picture (given by the video_output).
+ * tau´[I,P,B] = 2 * tau[I,P,B] + tauYUV
+ * : Mean time + typical difference (estimated to tau/2, that
+ * needs to be confirmed) + render time.
+ * DELTA : A given error margin.
+ *
+ * 3. General considerations
+ * ======================
+ * We define three types of machines :
+ * 14T > tauI : machines capable of decoding all I pictures
+ * 2T > tauP : machines capable of decoding all P pictures
+ * T > tauB : machines capable of decoding all B pictures
+ *
+ * 4. Decoding of an I picture
+ * ========================
+ * On fast machines, we decode all I's.
+ * Otherwise :
+ * We can decode an I picture if we simply have enough time to decode it
+ * before displaying :
+ * t0 - t > tau´I + DELTA
+ *
+ * 5. Decoding of a P picture
+ * =======================
+ * On fast machines, we decode all P's.
+ * Otherwise :
+ * First criterion : have time to decode it.
+ * t2 - t > tau´P + DELTA
+ *
+ * Second criterion : it shouldn't prevent us from displaying the forthcoming
+ * I picture, which is more important.
+ * t12 - t > tau´P + tau´I + DELTA
+ *
+ * 6. Decoding of a B picture
+ * =======================
+ * On fast machines, we decode all B's. Otherwise :
+ * t1 - t > tau´B + DELTA
+ * Since the next displayed I or P is already decoded, we don't have to
+ * worry about it.
+ *
+ * I hope you will have a pleasant flight and do not forget your life
+ * jacket.
+ * --Meuuh (2000-12-29)
+ */
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* free() */
+#include <string.h> /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#include "vdec_ext-plugins.h"
+
+#include "decoder.h"
+#include "pool.h"
+#include "parser.h"
+
+/*
+ * Local prototypes
+ */
+static int SynchroType( decoder_fifo_t * );
+
+/* Error margins */
+#define DELTA (int)(0.075*CLOCK_FREQ)
+
+#define DEFAULT_NB_P 5
+#define DEFAULT_NB_B 1
+
+/*****************************************************************************
+ * vpar_SynchroInit : You know what ?
+ *****************************************************************************/
+void vpar_SynchroInit( vpar_thread_t * p_vpar )
+{
+ p_vpar->synchro.i_type = SynchroType( p_vpar->p_fifo );
+
+ /* We use a fake stream pattern, which is often right. */
+ p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p = DEFAULT_NB_P;
+ p_vpar->synchro.i_n_b = p_vpar->synchro.i_eta_b = DEFAULT_NB_B;
+ memset( p_vpar->synchro.p_tau, 0, 4 * sizeof(mtime_t) );
+ memset( p_vpar->synchro.pi_meaningful, 0, 4 * sizeof(unsigned int) );
+ p_vpar->synchro.b_dropped_last = 0;
+ p_vpar->synchro.current_pts = mdate() + DEFAULT_PTS_DELAY;
+ p_vpar->synchro.backward_pts = 0;
+ p_vpar->synchro.i_current_period = p_vpar->synchro.i_backward_period = 0;
+ p_vpar->synchro.i_trashed_pic = p_vpar->synchro.i_not_chosen_pic =
+ p_vpar->synchro.i_pic = 0;
+}
+
+/*****************************************************************************
+ * vpar_SynchroChoose : Decide whether we will decode a picture or not
+ *****************************************************************************/
+vlc_bool_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
+ int i_structure )
+{
+ /* For clarity reasons, we separated the special synchros code from the
+ * mathematical synchro */
+
+ if( p_vpar->synchro.i_type != VPAR_SYNCHRO_DEFAULT )
+ {
+ switch( i_coding_type )
+ {
+ case I_CODING_TYPE:
+ /* I, IP, IP+, IPB */
+ if( p_vpar->synchro.i_type == VPAR_SYNCHRO_Iplus )
+ {
+ p_vpar->synchro.b_dropped_last = 1;
+ }
+ return( 1 );
+
+ case P_CODING_TYPE:
+ if( p_vpar->synchro.i_type == VPAR_SYNCHRO_I ) /* I */
+ {
+ return( 0 );
+ }
+
+ if( p_vpar->synchro.i_type == VPAR_SYNCHRO_Iplus ) /* I+ */
+ {
+ if( p_vpar->synchro.b_dropped_last )
+ {
+ p_vpar->synchro.b_dropped_last = 0;
+ return( 1 );
+ }
+ else
+ {
+ return( 0 );
+ }
+ }
+
+ return( 1 ); /* IP, IP+, IPB */
+
+ case B_CODING_TYPE:
+ if( p_vpar->synchro.i_type <= VPAR_SYNCHRO_IP ) /* I, IP */
+ {
+ return( 0 );
+ }
+ else if( p_vpar->synchro.i_type == VPAR_SYNCHRO_IPB ) /* IPB */
+ {
+ return( 1 );
+ }
+
+ p_vpar->synchro.b_dropped_last ^= 1; /* IP+ */
+ return( !p_vpar->synchro.b_dropped_last );
+ }
+ return( 0 ); /* never reached but gcc yells at me */
+ }
+ else
+ {
+#define TAU_PRIME( coding_type ) (p_vpar->synchro.p_tau[(coding_type)] \
+ + (p_vpar->synchro.p_tau[(coding_type)] >> 1) \
+ + tau_yuv)
+#define S p_vpar->synchro
+ /* VPAR_SYNCHRO_DEFAULT */
+ mtime_t now, period, tau_yuv;
+ mtime_t pts = 0;
+ vlc_bool_t b_decode = 0;
+
+ now = mdate();
+ period = 1000000 * 1001 / p_vpar->sequence.i_frame_rate
+ * p_vpar->sequence.i_current_rate / DEFAULT_RATE;
+
+ vlc_mutex_lock( &p_vpar->p_vout->change_lock );
+ tau_yuv = p_vpar->p_vout->render_time;
+ vlc_mutex_unlock( &p_vpar->p_vout->change_lock );
+
+ switch( i_coding_type )
+ {
+ case I_CODING_TYPE:
+ if( S.backward_pts )
+ {
+ pts = S.backward_pts;
+ }
+ else
+ {
+ /* displaying order : B B P B B I
+ * ^ ^
+ * | +- current picture
+ * +- current PTS
+ */
+ pts = S.current_pts + period * (S.i_n_b + 2);
+ }
+
+ if( (1 + S.i_n_p * (S.i_n_b + 1)) * period >
+ S.p_tau[I_CODING_TYPE] )
+ {
+ b_decode = 1;
+ }
+ else
+ {
+ b_decode = (pts - now) > (TAU_PRIME(I_CODING_TYPE) + DELTA);
+ }
+ if( !b_decode )
+ msg_Warn( p_vpar->p_fifo,
+ "synchro trashing I (%lld)", pts - now );
+ break;
+
+ case P_CODING_TYPE:
+ if( S.backward_pts )
+ {
+ pts = S.backward_pts;
+ }
+ else
+ {
+ pts = S.current_pts + period * (S.i_n_b + 1);
+ }
+
+ if( (1 + S.i_n_p * (S.i_n_b + 1)) * period >
+ S.p_tau[I_CODING_TYPE] )
+ {
+ if( (S.i_n_b + 1) * period > S.p_tau[P_CODING_TYPE] )
+ {
+ /* Security in case we're _really_ late */
+ b_decode = (pts - now > 0);
+ }
+ else
+ {
+ b_decode = (pts - now) > (TAU_PRIME(P_CODING_TYPE) + DELTA);
+ /* next I */
+ b_decode &= (pts - now
+ + period
+ * ( (S.i_n_p - S.i_eta_p) * (1 + S.i_n_b) - 1 ))
+ > (TAU_PRIME(P_CODING_TYPE)
+ + TAU_PRIME(I_CODING_TYPE) + DELTA);
+ }
+ }
+ else
+ {
+ b_decode = 0;
+ }
+ break;
+
+ case B_CODING_TYPE:
+ pts = S.current_pts;
+
+ if( (S.i_n_b + 1) * period > S.p_tau[P_CODING_TYPE] )
+ {
+ b_decode = (pts - now) > (TAU_PRIME(B_CODING_TYPE) + DELTA);
+ }
+ else
+ {
+ b_decode = 0;
+ }
+ }
+
+ if( !b_decode )
+ {
+ S.i_not_chosen_pic++;
+ }
+ return( b_decode );
+#undef S
+#undef TAU_PRIME
+ }
+}
+
+/*****************************************************************************
+ * vpar_SynchroTrash : Update counters when we trash a picture
+ *****************************************************************************/
+void vpar_SynchroTrash( vpar_thread_t * p_vpar, int i_coding_type,
+ int i_structure )
+{
+ p_vpar->synchro.i_trashed_pic++;
+}
+
+/*****************************************************************************
+ * vpar_SynchroDecode : Update timers when we decide to decode a picture
+ *****************************************************************************/
+void vpar_SynchroDecode( vpar_thread_t * p_vpar, int i_coding_type,
+ int i_structure )
+{
+ p_vpar->synchro.decoding_start = mdate();
+}
+
+/*****************************************************************************
+ * vpar_SynchroEnd : Called when the image is totally decoded
+ *****************************************************************************/
+void vpar_SynchroEnd( vpar_thread_t * p_vpar, int i_coding_type,
+ int i_structure, int i_garbage )
+{
+ mtime_t tau;
+
+ if( !i_garbage )
+ {
+ tau = mdate() - p_vpar->synchro.decoding_start;
+
+ /* If duration too high, something happened (pause ?), so don't
+ * take it into account. */
+ if( tau < 3 * p_vpar->synchro.p_tau[i_coding_type]
+ || !p_vpar->synchro.pi_meaningful[i_coding_type] )
+ {
+ /* Mean with average tau, to ensure stability. */
+ p_vpar->synchro.p_tau[i_coding_type] =
+ (p_vpar->synchro.pi_meaningful[i_coding_type]
+ * p_vpar->synchro.p_tau[i_coding_type] + tau)
+ / (p_vpar->synchro.pi_meaningful[i_coding_type] + 1);
+ if( p_vpar->synchro.pi_meaningful[i_coding_type] < MAX_PIC_AVERAGE )
+ {
+ p_vpar->synchro.pi_meaningful[i_coding_type]++;
+ }
+ }
+ }
+}
+
+/*****************************************************************************
+ * vpar_SynchroDate : When an image has been decoded, ask for its date
+ *****************************************************************************/
+mtime_t vpar_SynchroDate( vpar_thread_t * p_vpar )
+{
+ /* No need to lock, since PTS are only used by the video parser. */
+ return( p_vpar->synchro.current_pts );
+}
+
+/*****************************************************************************
+ * vpar_SynchroNewPicture: Update stream structure and PTS
+ *****************************************************************************/
+void vpar_SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type,
+ int i_repeat_field )
+{
+ mtime_t period = 1000000 * 1001 / p_vpar->sequence.i_frame_rate
+ * p_vpar->sequence.i_current_rate / DEFAULT_RATE;
+#if 0
+ mtime_t now = mdate();
+#endif
+
+ switch( i_coding_type )
+ {
+ case I_CODING_TYPE:
+ if( p_vpar->synchro.i_eta_p
+ && p_vpar->synchro.i_eta_p != p_vpar->synchro.i_n_p )
+ {
+ msg_Warn( p_vpar->p_fifo,
+ "stream periodicity changed from P[%d] to P[%d]",
+ p_vpar->synchro.i_n_p, p_vpar->synchro.i_eta_p );
+ p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p;
+ }
+ p_vpar->synchro.i_eta_p = p_vpar->synchro.i_eta_b = 0;
+
+ if( p_vpar->synchro.i_type == VPAR_SYNCHRO_DEFAULT )
+ {
+ msg_Dbg( p_vpar->p_fifo, "I(%lld) P(%lld)[%d] B(%lld)[%d] YUV(%lld) : trashed %d:%d/%d",
+ p_vpar->synchro.p_tau[I_CODING_TYPE],
+ p_vpar->synchro.p_tau[P_CODING_TYPE],
+ p_vpar->synchro.i_n_p,
+ p_vpar->synchro.p_tau[B_CODING_TYPE],
+ p_vpar->synchro.i_n_b,
+ p_vpar->p_vout->render_time,
+ p_vpar->synchro.i_not_chosen_pic,
+ p_vpar->synchro.i_trashed_pic -
+ p_vpar->synchro.i_not_chosen_pic,
+ p_vpar->synchro.i_pic );
+ p_vpar->synchro.i_trashed_pic = p_vpar->synchro.i_not_chosen_pic
+ = p_vpar->synchro.i_pic = 0;
+ }
+ break;
+
+ case P_CODING_TYPE:
+ p_vpar->synchro.i_eta_p++;
+ if( p_vpar->synchro.i_eta_b
+ && p_vpar->synchro.i_eta_b != p_vpar->synchro.i_n_b )
+ {
+ msg_Warn( p_vpar->p_fifo,
+ "stream periodicity changed from B[%d] to B[%d]",
+ p_vpar->synchro.i_n_b, p_vpar->synchro.i_eta_b );
+ p_vpar->synchro.i_n_b = p_vpar->synchro.i_eta_b;
+ }
+ p_vpar->synchro.i_eta_b = 0;
+ break;
+ case B_CODING_TYPE:
+ p_vpar->synchro.i_eta_b++;
+ break;
+ }
+
+ p_vpar->synchro.current_pts += p_vpar->synchro.i_current_period
+ * (period >> 1);
+
+#define PTS_THRESHOLD (period >> 2)
+ if( i_coding_type == B_CODING_TYPE )
+ {
+ /* A video frame can be displayed 1, 2 or 3 times, according to
+ * repeat_first_field, top_field_first, progressive_sequence and
+ * progressive_frame. */
+ p_vpar->synchro.i_current_period = i_repeat_field;
+
+ if( p_vpar->sequence.next_pts )
+ {
+ if( p_vpar->sequence.next_pts - p_vpar->synchro.current_pts
+ > PTS_THRESHOLD
+ || p_vpar->synchro.current_pts - p_vpar->sequence.next_pts
+ > PTS_THRESHOLD )
+ {
+ msg_Warn( p_vpar->p_fifo,
+ "vpar synchro warning: pts != current_date (%lld)",
+ p_vpar->synchro.current_pts
+ - p_vpar->sequence.next_pts );
+ }
+ p_vpar->synchro.current_pts = p_vpar->sequence.next_pts;
+ p_vpar->sequence.next_pts = 0;
+ }
+ }
+ else
+ {
+ p_vpar->synchro.i_current_period = p_vpar->synchro.i_backward_period;
+ p_vpar->synchro.i_backward_period = i_repeat_field;
+
+ if( p_vpar->synchro.backward_pts )
+ {
+ if( p_vpar->sequence.next_dts &&
+ (p_vpar->sequence.next_dts - p_vpar->synchro.backward_pts
+ > PTS_THRESHOLD
+ || p_vpar->synchro.backward_pts - p_vpar->sequence.next_dts
+ > PTS_THRESHOLD) )
+ {
+ msg_Warn( p_vpar->p_fifo, "backward_pts != dts (%lld)",
+ p_vpar->sequence.next_dts
+ - p_vpar->synchro.backward_pts );
+ }
+ if( p_vpar->synchro.backward_pts - p_vpar->synchro.current_pts
+ > PTS_THRESHOLD
+ || p_vpar->synchro.current_pts - p_vpar->synchro.backward_pts
+ > PTS_THRESHOLD )
+ {
+ msg_Warn( p_vpar->p_fifo,
+ "backward_pts != current_pts (%lld)",
+ p_vpar->synchro.current_pts
+ - p_vpar->synchro.backward_pts );
+ }
+ p_vpar->synchro.current_pts = p_vpar->synchro.backward_pts;
+ p_vpar->synchro.backward_pts = 0;
+ }
+ else if( p_vpar->sequence.next_dts )
+ {
+ if( p_vpar->sequence.next_dts - p_vpar->synchro.current_pts
+ > PTS_THRESHOLD
+ || p_vpar->synchro.current_pts - p_vpar->sequence.next_dts
+ > PTS_THRESHOLD )
+ {
+ msg_Warn( p_vpar->p_fifo, "dts != current_pts (%lld)",
+ p_vpar->synchro.current_pts
+ - p_vpar->sequence.next_dts );
+ }
+ /* By definition of a DTS. */
+ p_vpar->synchro.current_pts = p_vpar->sequence.next_dts;
+ p_vpar->sequence.next_dts = 0;
+ }
+
+ if( p_vpar->sequence.next_pts )
+ {
+ /* Store the PTS for the next time we have to date an I picture. */
+ p_vpar->synchro.backward_pts = p_vpar->sequence.next_pts;
+ p_vpar->sequence.next_pts = 0;
+ }
+ }
+#undef PTS_THRESHOLD
+
+#if 0
+ /* Removed for incompatibility with slow motion */
+ if( p_vpar->synchro.current_pts + DEFAULT_PTS_DELAY < now )
+ {
+ /* We cannot be _that_ late, something must have happened, reinit
+ * the dates. */
+ msg_Warn( p_vpar->p_fifo, "PTS << now (%lld), resetting",
+ now - p_vpar->synchro.current_pts - DEFAULT_PTS_DELAY );
+ p_vpar->synchro.current_pts = now + DEFAULT_PTS_DELAY;
+ }
+ if( p_vpar->synchro.backward_pts
+ && p_vpar->synchro.backward_pts + DEFAULT_PTS_DELAY < now )
+ {
+ /* The same. */
+ p_vpar->synchro.backward_pts = 0;
+ }
+#endif
+
+ p_vpar->synchro.i_pic++;
+}
+
+/*****************************************************************************
+ * SynchroType: Get the user's synchro type
+ *****************************************************************************
+ * This function is called at initialization.
+ *****************************************************************************/
+static int SynchroType( decoder_fifo_t *p_this )
+{
+ char psz_synchro_tmp[5];
+ char * psz_synchro = config_GetPsz( p_this, "vpar-synchro" );
+
+ if( psz_synchro == NULL )
+ {
+ return VPAR_SYNCHRO_DEFAULT;
+ }
+
+ strncpy( psz_synchro_tmp, psz_synchro, 5);
+ free( psz_synchro );
+ psz_synchro = psz_synchro_tmp;
+
+ switch( *psz_synchro++ )
+ {
+ case 'i':
+ case 'I':
+ switch( *psz_synchro++ )
+ {
+ case '\0':
+ return VPAR_SYNCHRO_I;
+
+ case '+':
+ if( *psz_synchro ) return 0;
+ return VPAR_SYNCHRO_Iplus;
+
+ case 'p':
+ case 'P':
+ switch( *psz_synchro++ )
+ {
+ case '\0':
+ return VPAR_SYNCHRO_IP;
+
+ case '+':
+ if( *psz_synchro ) return 0;
+ return VPAR_SYNCHRO_IPplus;
+
+ case 'b':
+ case 'B':
+ if( *psz_synchro ) return 0;
+ return VPAR_SYNCHRO_IPB;
+
+ default:
+ return VPAR_SYNCHRO_DEFAULT;
+
+ }
+
+ default:
+ return VPAR_SYNCHRO_DEFAULT;
+ }
+ }
+
+ return VPAR_SYNCHRO_DEFAULT;
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+spdif_SOURCES = spdif.c
--- /dev/null
+/*****************************************************************************
+ * spdif.c: A52 pass-through to external decoder with enabled soundcard
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: spdif.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ * Juha Yrjola <jyrjola@cc.hut.fi>
+ * German Gomez Garcia <german@piraos.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* memcpy() */
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+#include <vlc/aout.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "spdif.h"
+
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+
+static int InitThread ( spdif_thread_t * );
+static void EndThread ( spdif_thread_t * );
+static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
+
+int parse_syncinfo ( spdif_thread_t * );
+
+/****************************************************************************
+ * Local structures and tables
+ ****************************************************************************/
+static const frame_size_t p_frame_size_code[64] =
+{
+ { 32 ,{64 ,69 ,96 } },
+ { 32 ,{64 ,70 ,96 } },
+ { 40 ,{80 ,87 ,120 } },
+ { 40 ,{80 ,88 ,120 } },
+ { 48 ,{96 ,104 ,144 } },
+ { 48 ,{96 ,105 ,144 } },
+ { 56 ,{112 ,121 ,168 } },
+ { 56 ,{112 ,122 ,168 } },
+ { 64 ,{128 ,139 ,192 } },
+ { 64 ,{128 ,140 ,192 } },
+ { 80 ,{160 ,174 ,240 } },
+ { 80 ,{160 ,175 ,240 } },
+ { 96 ,{192 ,208 ,288 } },
+ { 96 ,{192 ,209 ,288 } },
+ { 112 ,{224 ,243 ,336 } },
+ { 112 ,{224 ,244 ,336 } },
+ { 128 ,{256 ,278 ,384 } },
+ { 128 ,{256 ,279 ,384 } },
+ { 160 ,{320 ,348 ,480 } },
+ { 160 ,{320 ,349 ,480 } },
+ { 192 ,{384 ,417 ,576 } },
+ { 192 ,{384 ,418 ,576 } },
+ { 224 ,{448 ,487 ,672 } },
+ { 224 ,{448 ,488 ,672 } },
+ { 256 ,{512 ,557 ,768 } },
+ { 256 ,{512 ,558 ,768 } },
+ { 320 ,{640 ,696 ,960 } },
+ { 320 ,{640 ,697 ,960 } },
+ { 384 ,{768 ,835 ,1152 } },
+ { 384 ,{768 ,836 ,1152 } },
+ { 448 ,{896 ,975 ,1344 } },
+ { 448 ,{896 ,976 ,1344 } },
+ { 512 ,{1024 ,1114 ,1536 } },
+ { 512 ,{1024 ,1115 ,1536 } },
+ { 576 ,{1152 ,1253 ,1728 } },
+ { 576 ,{1152 ,1254 ,1728 } },
+ { 640 ,{1280 ,1393 ,1920 } },
+ { 640 ,{1280 ,1394 ,1920 } }
+};
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("SPDIF pass-through A52 decoder") );
+ set_capability( "decoder", 0 );
+ set_callbacks( OpenDecoder, NULL );
+ add_shortcut( "pass_through" );
+ add_shortcut( "pass" );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to chose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
+ {
+ return VLC_EGENERIC;
+ }
+
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+}
+
+/****************************************************************************
+ * RunDecoder: the whole thing
+ ****************************************************************************
+ * This function is called just after the thread is launched.
+ ****************************************************************************/
+static int RunDecoder( decoder_fifo_t *p_fifo )
+{
+ spdif_thread_t * p_spdif;
+ mtime_t i_frame_time;
+ vlc_bool_t b_sync;
+ /* PTS of the current frame */
+ mtime_t i_current_pts = 0;
+ u16 i_length;
+
+ /* Allocate the memory needed to store the thread's structure */
+ p_spdif = malloc( sizeof(spdif_thread_t) );
+
+ if( p_spdif == NULL )
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ p_spdif->p_fifo = p_fifo;
+
+ if (InitThread( p_spdif ) )
+ {
+
+ if( p_fifo->b_error )
+ {
+ msg_Err( p_fifo, "could not initialize thread" );
+ }
+
+ DecoderError( p_fifo );
+ free( p_spdif );
+ return( -1 );
+ }
+
+ /* Compute the theorical duration of an A52 frame */
+ i_frame_time = 1000000 * A52_FRAME_SIZE /
+ p_spdif->info.i_sample_rate;
+ i_length = p_spdif->info.i_frame_size;
+
+ while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
+ {
+ p_spdif->p_bytes[0] = 0x0b;
+ p_spdif->p_bytes[1] = 0x77;
+
+ /* Handle the dates */
+ if( p_spdif->i_real_pts )
+ {
+ mtime_t i_delta = p_spdif->i_real_pts - i_current_pts -
+ i_frame_time;
+ if( i_delta > i_frame_time || i_delta < -i_frame_time )
+ {
+ msg_Warn( p_fifo,
+ "date discontinuity (%d)", i_delta );
+ }
+ i_current_pts = p_spdif->i_real_pts;
+ p_spdif->i_real_pts = 0;
+ }
+ else
+ {
+ i_current_pts += i_frame_time;
+ }
+
+ // wait a little to avoid an input flood from the a52 input
+ mwait( i_current_pts - 500000 );
+
+ vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
+
+ p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->i_end_frame] =
+ i_current_pts;
+
+ p_spdif->p_aout_fifo->i_end_frame =
+ (p_spdif->p_aout_fifo->i_end_frame + 1 ) & AOUT_FIFO_SIZE;
+
+ p_spdif->p_bytes = ((u8*)(p_spdif->p_aout_fifo->buffer)) +
+ (p_spdif->p_aout_fifo->i_end_frame * i_length );
+
+ vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
+
+ /* Find syncword again in case of stream discontinuity */
+ /* Here we have p_spdif->i_pts == 0
+ * Therefore a non-zero value after a call to GetBits() means the PES
+ * has changed. */
+ b_sync = 0;
+ while( !p_spdif->p_fifo->b_die
+ && !p_spdif->p_fifo->b_error
+ && !b_sync )
+ {
+ while( !p_spdif->p_fifo->b_die
+ && !p_spdif->p_fifo->b_error
+ && GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
+ p_spdif->i_real_pts = p_spdif->i_pts;
+ p_spdif->i_pts = 0;
+ b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
+ }
+ RemoveBits( &p_spdif->bit_stream, 8 );
+
+ /* Read data from bitstream */
+ GetChunk( &p_spdif->bit_stream, p_spdif->p_bytes + 2, i_length - 2 );
+ }
+
+ /* If b_error is set, the spdif thread enters the error loop */
+ if( p_spdif->p_fifo->b_error )
+ {
+ DecoderError( p_spdif->p_fifo );
+ }
+
+ /* End of the spdif decoder thread */
+ EndThread( p_spdif );
+
+ return( 0 );
+}
+
+/****************************************************************************
+ * InitThread: initialize thread data and create output fifo
+ ****************************************************************************/
+static int InitThread( spdif_thread_t * p_spdif )
+{
+ vlc_bool_t b_sync = 0;
+
+ /* Temporary buffer to store first A52 frame */
+ p_spdif->p_bytes = malloc( SPDIF_FRAME_SIZE );
+
+ if( p_spdif->p_bytes == NULL )
+ {
+ free( p_spdif->p_bytes );
+ return( -1 );
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_spdif->p_fifo = p_spdif->p_fifo;
+
+ InitBitstream( &p_spdif->bit_stream, p_spdif->p_fifo,
+ BitstreamCallback, (void*)p_spdif );
+
+ /* Find syncword */
+ while( !p_spdif->p_fifo->b_die
+ && !p_spdif->p_fifo->b_error
+ && !b_sync )
+ {
+ while( !p_spdif->p_fifo->b_die
+ && !p_spdif->p_fifo->b_error
+ && GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
+ p_spdif->i_real_pts = p_spdif->i_pts;
+ p_spdif->i_pts = 0;
+ b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
+ }
+
+ if( p_spdif->p_fifo->b_die || p_spdif->p_fifo->b_error )
+ {
+ return -1;
+ }
+
+ RemoveBits( &p_spdif->bit_stream, 8 );
+
+ /* Check stream properties */
+ if( parse_syncinfo( p_spdif ) < 0 )
+ {
+ msg_Err( p_spdif->p_fifo, "stream not valid" );
+
+ return( -1 );
+ }
+
+ /* Check that we can handle the rate
+ * FIXME: we should check that we have the same rate for all fifos
+ * but all rates should be supported by the decoder (32, 44.1, 48) */
+ if( p_spdif->info.i_sample_rate != 48000 )
+ {
+ msg_Err( p_spdif->p_fifo,
+ "only 48000 Hz streams tested, expect weird things!" );
+ }
+
+ /* The audio output need to be ready for an A52 stream */
+ p_spdif->i_previous_format = config_GetInt( p_spdif->p_fifo,
+ "audio-format" );
+ config_PutInt( p_spdif->p_fifo, "audio-format", 8 );
+
+ /* Creating the audio output fifo */
+ p_spdif->p_aout_fifo =
+ aout_CreateFifo( p_spdif->p_fifo, AOUT_FIFO_SPDIF,
+ 1, p_spdif->info.i_sample_rate,
+ p_spdif->info.i_frame_size, NULL );
+
+ if( p_spdif->p_aout_fifo == NULL )
+ {
+ return( -1 );
+ }
+
+ msg_Dbg( p_spdif->p_fifo, "aout fifo #%d created",
+ p_spdif->p_aout_fifo->i_fifo );
+
+ /* Put read data into fifo */
+ memcpy( (u8*)(p_spdif->p_aout_fifo->buffer) +
+ (p_spdif->p_aout_fifo->i_end_frame *
+ p_spdif->info.i_frame_size ),
+ p_spdif->p_bytes, sizeof(sync_frame_t) );
+ free( p_spdif->p_bytes );
+ p_spdif->p_bytes = ((u8*)(p_spdif->p_aout_fifo->buffer) +
+ (p_spdif->p_aout_fifo->i_end_frame *
+ p_spdif->info.i_frame_size ));
+
+ GetChunk( &p_spdif->bit_stream, p_spdif->p_bytes + sizeof(sync_frame_t),
+ p_spdif->info.i_frame_size - sizeof(sync_frame_t) );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * EndThread : spdif thread destruction
+ *****************************************************************************/
+static void EndThread( spdif_thread_t * p_spdif )
+{
+ /* If the audio output fifo was created, we destroy it */
+ if( p_spdif->p_aout_fifo != NULL )
+ {
+ aout_DestroyFifo( p_spdif->p_aout_fifo );
+
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
+ vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
+ vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
+
+ }
+
+ /* restore previous setting for output format */
+ config_PutInt( p_spdif->p_fifo, "audio-format",
+ p_spdif->i_previous_format );
+
+ /* Destroy descriptor */
+ free( p_spdif );
+}
+
+/*****************************************************************************
+ * BitstreamCallback: Import parameters from the new data/PES packet
+ *****************************************************************************
+ * This function is called by input's NextDataPacket.
+ *****************************************************************************/
+static void BitstreamCallback( bit_stream_t * p_bit_stream,
+ vlc_bool_t b_new_pes )
+{
+ spdif_thread_t * p_spdif;
+
+ if( b_new_pes )
+ {
+ p_spdif = (spdif_thread_t *)p_bit_stream->p_callback_arg;
+
+/* p_bit_stream->p_byte += 3; */
+
+ p_spdif->i_pts =
+ p_bit_stream->p_decoder_fifo->p_first->i_pts;
+ p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;
+ }
+}
+
+/****************************************************************************
+ * parse_syncinfo: parse A52 sync info
+ ****************************************************************************/
+int parse_syncinfo( spdif_thread_t *p_spdif )
+{
+ int p_sample_rates[4] = { 48000, 44100, 32000, -1 };
+ int i_frame_rate_code;
+ int i_frame_size_code;
+ sync_frame_t * p_sync_frame;
+
+ /* Read sync frame */
+ GetChunk( &p_spdif->bit_stream, p_spdif->p_bytes + 2,
+ sizeof(sync_frame_t) - 2 );
+ if( p_spdif->p_fifo->b_die ) return -1;
+
+ p_sync_frame = (sync_frame_t*)p_spdif->p_bytes;
+
+ /* Compute frame rate */
+ i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03;
+ p_spdif->info.i_sample_rate = p_sample_rates[i_frame_rate_code];
+ if( p_spdif->info.i_sample_rate == -1 )
+ {
+ return -1;
+ }
+
+ /* Compute frame size */
+ i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f;
+ p_spdif->info.i_frame_size = 2 *
+ p_frame_size_code[i_frame_size_code].i_frame_size[i_frame_rate_code];
+ p_spdif->info.i_bit_rate =
+ p_frame_size_code[i_frame_size_code].i_bit_rate;
+
+ if( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 )
+ {
+ return -1;
+ }
+
+ p_spdif->info.i_bs_mod = p_sync_frame->bsi.bsidmod & 0x7;
+
+ return 0;
+}
--- /dev/null
+/*****************************************************************************
+ * spdif.h: header for A52 pass-through
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: spdif.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ ****************************************************************************/
+
+/****************************************************************************
+ * information about A52 frame
+ ****************************************************************************/
+typedef struct sync_frame_s
+{
+ struct syncinfo
+ {
+ u8 syncword[2];
+ u8 crc1[2];
+ u8 code;
+ } syncinfo;
+
+ struct bsi
+ {
+ u8 bsidmod;
+ u8 acmod;
+ } bsi;
+} sync_frame_t;
+
+typedef struct frame_size_s
+{
+ u16 i_bit_rate;
+ u16 i_frame_size[3];
+} frame_size_t;
+
+typedef struct info_s
+{
+ int i_bit_rate;
+ int i_frame_size;
+ int i_sample_rate;
+ int i_bs_mod;
+} info_t;
+
+/*****************************************************************************
+ * spdif_thread_t : A52 pass-through thread descriptor
+ *****************************************************************************/
+typedef struct spdif_thread_s
+{
+ /*
+ * Thread properties
+ */
+ vlc_thread_t thread_id; /* id for thread functions */
+
+ /*
+ * Input properties
+ */
+ decoder_fifo_t * p_fifo; /* stores the PES stream data */
+
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+ int i_available;
+
+ /*
+ * Decoder properties
+ */
+ info_t info;
+ u8 * p_bytes;
+
+ /* current pes date */
+ mtime_t i_pts;
+ mtime_t i_real_pts;
+
+ /*
+ * Output properties
+ */
+ int i_previous_format;
+ aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
+
+} spdif_thread_t;
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+spudec_SOURCES = spudec.c
--- /dev/null
+/*****************************************************************************
+ * spudec.c : spu decoder thread
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: spudec.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> /* getpid() */
+#endif
+
+#ifdef WIN32 /* getpid() for win32 is located in process.h */
+# include <process.h>
+#endif
+
+#include "spudec.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int OpenDecoder ( vlc_object_t * );
+static int RunDecoder ( decoder_fifo_t * );
+static int InitThread ( spudec_thread_t * );
+static void EndThread ( spudec_thread_t * );
+
+static int SyncPacket ( spudec_thread_t * );
+static void ParsePacket ( spudec_thread_t * );
+static int ParseControlSequences( spudec_thread_t *, subpicture_t * );
+static int ParseRLE ( spudec_thread_t *, subpicture_t *, u8 * );
+static void RenderSPU ( vout_thread_t *, picture_t *,
+ const subpicture_t * );
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("DVD subtitles decoder module") );
+ set_capability( "decoder", 50 );
+ set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to chose.
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+ decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+ if( p_fifo->i_fourcc == VLC_FOURCC('s','p','u',' ') )
+ {
+ p_fifo->pf_run = RunDecoder;
+ return VLC_SUCCESS;
+ }
+
+ return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * RunDecoder: this function is called just after the thread is created
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t * p_fifo )
+{
+ spudec_thread_t * p_spudec;
+
+ /* Allocate the memory needed to store the thread's structure */
+ p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) );
+
+ if ( p_spudec == NULL )
+ {
+ msg_Err( p_fifo, "out of memory" );
+ DecoderError( p_fifo );
+ return( -1 );
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_spudec->p_vout = NULL;
+ p_spudec->p_fifo = p_fifo;
+
+ /*
+ * Initialize thread and free configuration
+ */
+ p_spudec->p_fifo->b_error = InitThread( p_spudec );
+
+ /*
+ * Main loop - it is not executed if an error occured during
+ * initialization
+ */
+ while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
+ {
+ if( !SyncPacket( p_spudec ) )
+ {
+ ParsePacket( p_spudec );
+ }
+ }
+
+ /*
+ * Error loop
+ */
+ if( p_spudec->p_fifo->b_error )
+ {
+ DecoderError( p_spudec->p_fifo );
+
+ /* End of thread */
+ EndThread( p_spudec );
+ return -1;
+ }
+
+ /* End of thread */
+ EndThread( p_spudec );
+ return 0;
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * InitThread: initialize spu decoder thread
+ *****************************************************************************
+ * This function is called from RunThread and performs the second step of the
+ * initialization. It returns 0 on success. Note that the thread's flag are not
+ * modified inside this function.
+ *****************************************************************************/
+static int InitThread( spudec_thread_t *p_spudec )
+{
+ /* Find an available video output */
+ do
+ {
+ if( p_spudec->p_fifo->b_die || p_spudec->p_fifo->b_error )
+ {
+ return -1;
+ }
+
+ p_spudec->p_vout = vlc_object_find( p_spudec->p_fifo, VLC_OBJECT_VOUT,
+ FIND_ANYWHERE );
+
+ if( p_spudec->p_vout )
+ {
+ break;
+ }
+
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+ while( 1 );
+
+ InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo, NULL, NULL );
+
+ /* Mark thread as running and return */
+ return 0;
+}
+
+/*****************************************************************************
+ * EndThread: thread destruction
+ *****************************************************************************
+ * This function is called when the thread ends after a sucessful
+ * initialization.
+ *****************************************************************************/
+static void EndThread( spudec_thread_t *p_spudec )
+{
+ if( p_spudec->p_vout != NULL
+ && p_spudec->p_vout->p_subpicture != NULL )
+ {
+ subpicture_t * p_subpic;
+ int i_subpic;
+
+ for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
+ {
+ p_subpic = &p_spudec->p_vout->p_subpicture[i_subpic];
+
+ if( p_subpic != NULL &&
+ ( ( p_subpic->i_status == RESERVED_SUBPICTURE )
+ || ( p_subpic->i_status == READY_SUBPICTURE ) ) )
+ {
+ vout_DestroySubPicture( p_spudec->p_vout, p_subpic );
+ }
+ }
+
+ vlc_object_release( p_spudec->p_vout );
+ }
+
+ free( p_spudec );
+}
+
+/*****************************************************************************
+ * SyncPacket: get in sync with the stream
+ *****************************************************************************
+ * This function makes a few sanity checks and returns 0 if it looks like we
+ * are at the beginning of a subpicture packet.
+ *****************************************************************************/
+static int SyncPacket( spudec_thread_t *p_spudec )
+{
+ /* Re-align the buffer on an 8-bit boundary */
+ RealignBits( &p_spudec->bit_stream );
+
+ /* The total SPU packet size, often bigger than a PS packet */
+ p_spudec->i_spu_size = GetBits( &p_spudec->bit_stream, 16 );
+
+ /* The RLE stuff size (remove 4 because we just read 32 bits) */
+ p_spudec->i_rle_size = ShowBits( &p_spudec->bit_stream, 16 ) - 4;
+
+ /* If the values we got are a bit strange, skip packet */
+ if( !p_spudec->i_spu_size
+ || ( p_spudec->i_rle_size >= p_spudec->i_spu_size ) )
+ {
+ return( 1 );
+ }
+
+ RemoveBits( &p_spudec->bit_stream, 16 );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * ParsePacket: parse an SPU packet and send it to the video output
+ *****************************************************************************
+ * This function parses the SPU packet and, if valid, sends it to the
+ * video output.
+ *****************************************************************************/
+static void ParsePacket( spudec_thread_t *p_spudec )
+{
+ subpicture_t * p_spu;
+ u8 * p_src;
+ unsigned int i_offset;
+
+ msg_Dbg( p_spudec->p_fifo, "trying to gather a 0x%.2x long subtitle",
+ p_spudec->i_spu_size );
+
+ /* We cannot display a subpicture with no date */
+ if( p_spudec->p_fifo->p_first->i_pts == 0 )
+ {
+ msg_Warn( p_spudec->p_fifo, "subtitle without a date" );
+ return;
+ }
+
+ /* Allocate the subpicture internal data. */
+ p_spu = vout_CreateSubPicture( p_spudec->p_vout, MEMORY_SUBPICTURE,
+ sizeof( subpicture_sys_t )
+ + p_spudec->i_rle_size * 4 );
+ /* Rationale for the "p_spudec->i_rle_size * 4": we are going to
+ * expand the RLE stuff so that we won't need to read nibbles later
+ * on. This will speed things up a lot. Plus, we'll only need to do
+ * this stupid interlacing stuff once. */
+
+ if( p_spu == NULL )
+ {
+ return;
+ }
+
+ /* Fill the p_spu structure */
+ p_spu->pf_render = RenderSPU;
+ p_spu->p_sys->p_data = (u8*)p_spu->p_sys + sizeof( subpicture_sys_t );
+ p_spu->p_sys->b_palette = 0;
+
+ /* Get display time now. If we do it later, we may miss the PTS. */
+ p_spu->p_sys->i_pts = p_spudec->p_fifo->p_first->i_pts;
+
+ /* Allocate the temporary buffer we will parse */
+ p_src = malloc( p_spudec->i_rle_size );
+
+ if( p_src == NULL )
+ {
+ msg_Err( p_spudec->p_fifo, "out of memory" );
+ vout_DestroySubPicture( p_spudec->p_vout, p_spu );
+ return;
+ }
+
+ /* Get RLE data */
+ for( i_offset = 0; i_offset < p_spudec->i_rle_size;
+ i_offset += SPU_CHUNK_SIZE )
+ {
+ GetChunk( &p_spudec->bit_stream, p_src + i_offset,
+ ( i_offset + SPU_CHUNK_SIZE < p_spudec->i_rle_size ) ?
+ SPU_CHUNK_SIZE : p_spudec->i_rle_size - i_offset );
+
+ /* Abort subtitle parsing if we were requested to stop */
+ if( p_spudec->p_fifo->b_die )
+ {
+ free( p_src );
+ vout_DestroySubPicture( p_spudec->p_vout, p_spu );
+ return;
+ }
+ }
+
+#if 0
+ /* Dump the subtitle info */
+ intf_WarnHexDump( 5, p_spu->p_sys->p_data, p_spudec->i_rle_size );
+#endif
+
+ /* Getting the control part */
+ if( ParseControlSequences( p_spudec, p_spu ) )
+ {
+ /* There was a parse error, delete the subpicture */
+ free( p_src );
+ vout_DestroySubPicture( p_spudec->p_vout, p_spu );
+ return;
+ }
+
+ /* At this point, no more GetBit() command is needed, so we have all
+ * the data we need to tell whether the subtitle is valid. Thus we
+ * try to display it and we ignore b_die. */
+
+ if( ParseRLE( p_spudec, p_spu, p_src ) )
+ {
+ /* There was a parse error, delete the subpicture */
+ free( p_src );
+ vout_DestroySubPicture( p_spudec->p_vout, p_spu );
+ return;
+ }
+
+ msg_Dbg( p_spudec->p_fifo, "total size: 0x%x, RLE offsets: 0x%x 0x%x",
+ p_spudec->i_spu_size,
+ p_spu->p_sys->pi_offset[0], p_spu->p_sys->pi_offset[1] );
+
+ /* SPU is finished - we can ask the video output to display it */
+ vout_DisplaySubPicture( p_spudec->p_vout, p_spu );
+
+ /* Clean up */
+ free( p_src );
+}
+
+/*****************************************************************************
+ * ParseControlSequences: parse all SPU control sequences
+ *****************************************************************************
+ * This is the most important part in SPU decoding. We get dates, palette
+ * information, coordinates, and so on. For more information on the
+ * subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
+ *****************************************************************************/
+static int ParseControlSequences( spudec_thread_t *p_spudec,
+ subpicture_t * p_spu )
+{
+ /* Our current index in the SPU packet */
+ int i_index = p_spudec->i_rle_size + 4;
+
+ /* The next start-of-control-sequence index and the previous one */
+ int i_next_seq, i_cur_seq;
+
+ /* Command time and date */
+ u8 i_command;
+ int i_date;
+
+ int i, pi_alpha[4];
+
+ /* XXX: temporary variables */
+ vlc_bool_t b_force_display = 0;
+
+ /* Initialize the structure */
+ p_spu->i_start = p_spu->i_stop = 0;
+ p_spu->b_ephemer = 0;
+
+ do
+ {
+ /* Get the control sequence date */
+ i_date = GetBits( &p_spudec->bit_stream, 16 );
+
+ /* Next offset */
+ i_cur_seq = i_index;
+ i_next_seq = GetBits( &p_spudec->bit_stream, 16 );
+
+ /* Skip what we just read */
+ i_index += 4;
+
+ do
+ {
+ i_command = GetBits( &p_spudec->bit_stream, 8 );
+ i_index++;
+
+ switch( i_command )
+ {
+ case SPU_CMD_FORCE_DISPLAY:
+
+ /* 00 (force displaying) */
+ p_spu->i_start = p_spu->p_sys->i_pts + ( i_date * 11000 );
+ b_force_display = 1;
+
+ break;
+
+ /* Convert the dates in seconds to PTS values */
+ case SPU_CMD_START_DISPLAY:
+
+ /* 01 (start displaying) */
+ p_spu->i_start = p_spu->p_sys->i_pts + ( i_date * 11000 );
+
+ break;
+
+ case SPU_CMD_STOP_DISPLAY:
+
+ /* 02 (stop displaying) */
+ p_spu->i_stop = p_spu->p_sys->i_pts + ( i_date * 11000 );
+
+ break;
+
+ case SPU_CMD_SET_PALETTE:
+
+ /* 03xxxx (palette) */
+ if( p_spudec->p_fifo->p_demux_data &&
+ *(int*)p_spudec->p_fifo->p_demux_data == 0xBeeF )
+ {
+ u32 i_color;
+
+ p_spu->p_sys->b_palette = 1;
+ for( i = 0; i < 4 ; i++ )
+ {
+ i_color = ((u32*)((char*)p_spudec->p_fifo->
+ p_demux_data + sizeof(int)))[
+ GetBits(&p_spudec->bit_stream, 4) ];
+
+ /* FIXME: this job should be done sooner */
+#ifndef WORDS_BIGENDIAN
+ p_spu->p_sys->pi_yuv[3-i][0] = (i_color>>16) & 0xff;
+ p_spu->p_sys->pi_yuv[3-i][1] = (i_color>>0) & 0xff;
+ p_spu->p_sys->pi_yuv[3-i][2] = (i_color>>8) & 0xff;
+#else
+ p_spu->p_sys->pi_yuv[3-i][0] = (i_color>>8) & 0xff;
+ p_spu->p_sys->pi_yuv[3-i][1] = (i_color>>24) & 0xff;
+ p_spu->p_sys->pi_yuv[3-i][2] = (i_color>>16) & 0xff;
+#endif
+ }
+ }
+ else
+ {
+ RemoveBits( &p_spudec->bit_stream, 16 );
+ }
+ i_index += 2;
+
+ break;
+
+ case SPU_CMD_SET_ALPHACHANNEL:
+
+ /* 04xxxx (alpha channel) */
+ pi_alpha[3] = GetBits( &p_spudec->bit_stream, 4 );
+ pi_alpha[2] = GetBits( &p_spudec->bit_stream, 4 );
+ pi_alpha[1] = GetBits( &p_spudec->bit_stream, 4 );
+ pi_alpha[0] = GetBits( &p_spudec->bit_stream, 4 );
+
+ /* Ignore blank alpha palette. Sometimes spurious blank
+ * alpha palettes are present - dunno why. */
+ if( pi_alpha[0] | pi_alpha[1] | pi_alpha[2] | pi_alpha[3] )
+ {
+ p_spu->p_sys->pi_alpha[0] = pi_alpha[0];
+ p_spu->p_sys->pi_alpha[1] = pi_alpha[1];
+ p_spu->p_sys->pi_alpha[2] = pi_alpha[2];
+ p_spu->p_sys->pi_alpha[3] = pi_alpha[3];
+ }
+ else
+ {
+ msg_Warn( p_spudec->p_fifo,
+ "ignoring blank alpha palette" );
+ }
+
+ i_index += 2;
+
+ break;
+
+ case SPU_CMD_SET_COORDINATES:
+
+ /* 05xxxyyyxxxyyy (coordinates) */
+ p_spu->i_x = GetBits( &p_spudec->bit_stream, 12 );
+ p_spu->i_width = GetBits( &p_spudec->bit_stream, 12 )
+ - p_spu->i_x + 1;
+
+ p_spu->i_y = GetBits( &p_spudec->bit_stream, 12 );
+ p_spu->i_height = GetBits( &p_spudec->bit_stream, 12 )
+ - p_spu->i_y + 1;
+
+ i_index += 6;
+
+ break;
+
+ case SPU_CMD_SET_OFFSETS:
+
+ /* 06xxxxyyyy (byte offsets) */
+ p_spu->p_sys->pi_offset[0] =
+ GetBits( &p_spudec->bit_stream, 16 ) - 4;
+
+ p_spu->p_sys->pi_offset[1] =
+ GetBits( &p_spudec->bit_stream, 16 ) - 4;
+
+ i_index += 4;
+
+ break;
+
+ case SPU_CMD_END:
+
+ /* ff (end) */
+ break;
+
+ default:
+
+ /* xx (unknown command) */
+ msg_Err( p_spudec->p_fifo, "unknown command 0x%.2x",
+ i_command );
+ return( 1 );
+ }
+
+ /* We need to check for quit commands here */
+ if( p_spudec->p_fifo->b_die )
+ {
+ return( 1 );
+ }
+
+ } while( i_command != SPU_CMD_END );
+
+ } while( i_index == i_next_seq );
+
+ /* Check that the next sequence index matches the current one */
+ if( i_next_seq != i_cur_seq )
+ {
+ msg_Err( p_spudec->p_fifo, "index mismatch (0x%.4x != 0x%.4x)",
+ i_next_seq, i_cur_seq );
+ return( 1 );
+ }
+
+ if( i_index > p_spudec->i_spu_size )
+ {
+ msg_Err( p_spudec->p_fifo, "uh-oh, we went too far (0x%.4x > 0x%.4x)",
+ i_index, p_spudec->i_spu_size );
+ return( 1 );
+ }
+
+ if( !p_spu->i_start )
+ {
+ msg_Err( p_spudec->p_fifo, "no `start display' command" );
+ }
+
+ if( !p_spu->i_stop )
+ {
+ /* This subtitle will live for 5 seconds or until the next subtitle */
+ p_spu->i_stop = p_spu->i_start + 500 * 11000;
+ p_spu->b_ephemer = 1;
+ }
+
+ /* Get rid of padding bytes */
+ switch( p_spudec->i_spu_size - i_index )
+ {
+ /* Zero or one padding byte, quite usual */
+ case 1:
+ RemoveBits( &p_spudec->bit_stream, 8 );
+ i_index++;
+ case 0:
+ break;
+
+ /* More than one padding byte - this is very strange, but
+ * we can deal with it */
+ default:
+ msg_Warn( p_spudec->p_fifo,
+ "%i padding bytes, we usually get 0 or 1 of them",
+ p_spudec->i_spu_size - i_index );
+
+ while( i_index < p_spudec->i_spu_size )
+ {
+ RemoveBits( &p_spudec->bit_stream, 8 );
+ i_index++;
+ }
+
+ break;
+ }
+
+ if( b_force_display )
+ {
+ msg_Err( p_spudec->p_fifo, "\"force display\" command" );
+ msg_Err( p_spudec->p_fifo, "send mail to <sam@zoy.org> if you "
+ "want to help debugging this" );
+ }
+
+ /* Successfully parsed ! */
+ return( 0 );
+}
+
+/*****************************************************************************
+ * ParseRLE: parse the RLE part of the subtitle
+ *****************************************************************************
+ * This part parses the subtitle graphical data and stores it in a more
+ * convenient structure for later decoding. For more information on the
+ * subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
+ *****************************************************************************/
+static int ParseRLE( spudec_thread_t *p_spudec,
+ subpicture_t * p_spu, u8 * p_src )
+{
+ unsigned int i_code;
+
+ unsigned int i_width = p_spu->i_width;
+ unsigned int i_height = p_spu->i_height;
+ unsigned int i_x, i_y;
+
+ u16 *p_dest = (u16 *)p_spu->p_sys->p_data;
+
+ /* The subtitles are interlaced, we need two offsets */
+ unsigned int i_id = 0; /* Start on the even SPU layer */
+ unsigned int pi_table[ 2 ];
+ unsigned int *pi_offset;
+
+ vlc_bool_t b_empty_top = 1,
+ b_empty_bottom = 0;
+ unsigned int i_skipped_top = 0,
+ i_skipped_bottom = 0;
+
+ /* Colormap statistics */
+ int i_border = -1;
+ int stats[4]; stats[0] = stats[1] = stats[2] = stats[3] = 0;
+
+ pi_table[ 0 ] = p_spu->p_sys->pi_offset[ 0 ] << 1;
+ pi_table[ 1 ] = p_spu->p_sys->pi_offset[ 1 ] << 1;
+
+ for( i_y = 0 ; i_y < i_height ; i_y++ )
+ {
+ pi_offset = pi_table + i_id;
+
+ for( i_x = 0 ; i_x < i_width ; i_x += i_code >> 2 )
+ {
+ i_code = AddNibble( 0, p_src, pi_offset );
+
+ if( i_code < 0x04 )
+ {
+ i_code = AddNibble( i_code, p_src, pi_offset );
+
+ if( i_code < 0x10 )
+ {
+ i_code = AddNibble( i_code, p_src, pi_offset );
+
+ if( i_code < 0x040 )
+ {
+ i_code = AddNibble( i_code, p_src, pi_offset );
+
+ if( i_code < 0x0100 )
+ {
+ /* If the 14 first bits are set to 0, then it's a
+ * new line. We emulate it. */
+ if( i_code < 0x0004 )
+ {
+ i_code |= ( i_width - i_x ) << 2;
+ }
+ else
+ {
+ /* We have a boo boo ! */
+ msg_Err( p_spudec->p_fifo, "unknown RLE code "
+ "0x%.4x", i_code );
+ return( 1 );
+ }
+ }
+ }
+ }
+ }
+
+ if( ( (i_code >> 2) + i_x + i_y * i_width ) > i_height * i_width )
+ {
+ msg_Err( p_spudec->p_fifo,
+ "out of bounds, %i at (%i,%i) is out of %ix%i",
+ i_code >> 2, i_x, i_y, i_width, i_height );
+ return( 1 );
+ }
+
+ /* Try to find the border color */
+ if( p_spu->p_sys->pi_alpha[ i_code & 0x3 ] != 0x00 )
+ {
+ i_border = i_code & 0x3;
+ stats[i_border] += i_code >> 2;
+ }
+
+ if( (i_code >> 2) == i_width
+ && p_spu->p_sys->pi_alpha[ i_code & 0x3 ] == 0x00 )
+ {
+ if( b_empty_top )
+ {
+ /* This is a blank top line, we skip it */
+ i_skipped_top++;
+ }
+ else
+ {
+ /* We can't be sure the current lines will be skipped,
+ * so we store the code just in case. */
+ *p_dest++ = i_code;
+
+ b_empty_bottom = 1;
+ i_skipped_bottom++;
+ }
+ }
+ else
+ {
+ /* We got a valid code, store it */
+ *p_dest++ = i_code;
+
+ /* Valid code means no blank line */
+ b_empty_top = 0;
+ b_empty_bottom = 0;
+ i_skipped_bottom = 0;
+ }
+ }
+
+ /* Check that we didn't go too far */
+ if( i_x > i_width )
+ {
+ msg_Err( p_spudec->p_fifo, "i_x overflowed, %i > %i",
+ i_x, i_width );
+ return( 1 );
+ }
+
+ /* Byte-align the stream */
+ if( *pi_offset & 0x1 )
+ {
+ (*pi_offset)++;
+ }
+
+ /* Swap fields */
+ i_id = ~i_id & 0x1;
+ }
+
+ /* We shouldn't get any padding bytes */
+ if( i_y < i_height )
+ {
+ msg_Err( p_spudec->p_fifo, "padding bytes found in RLE sequence" );
+ msg_Err( p_spudec->p_fifo, "send mail to <sam@zoy.org> if you "
+ "want to help debugging this" );
+
+ /* Skip them just in case */
+ while( i_y < i_height )
+ {
+ *p_dest++ = i_width << 2;
+ i_y++;
+ }
+
+ return( 1 );
+ }
+
+ msg_Dbg( p_spudec->p_fifo, "valid subtitle, size: %ix%i, position: %i,%i",
+ p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y );
+
+ /* Crop if necessary */
+ if( i_skipped_top || i_skipped_bottom )
+ {
+ p_spu->i_y += i_skipped_top;
+ p_spu->i_height -= i_skipped_top + i_skipped_bottom;
+
+ msg_Dbg( p_spudec->p_fifo, "cropped to: %ix%i, position: %i,%i",
+ p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y );
+ }
+
+ /* Handle color if no palette was found */
+ if( !p_spu->p_sys->b_palette )
+ {
+ int i, i_inner = -1, i_shade = -1;
+
+ /* Set the border color */
+ p_spu->p_sys->pi_yuv[i_border][0] = 0x00;
+ p_spu->p_sys->pi_yuv[i_border][1] = 0x80;
+ p_spu->p_sys->pi_yuv[i_border][2] = 0x80;
+ stats[i_border] = 0;
+
+ /* Find the inner colors */
+ for( i = 0 ; i < 4 && i_inner == -1 ; i++ )
+ {
+ if( stats[i] )
+ {
+ i_inner = i;
+ }
+ }
+
+ for( ; i < 4 && i_shade == -1 ; i++ )
+ {
+ if( stats[i] )
+ {
+ if( stats[i] > stats[i_inner] )
+ {
+ i_shade = i_inner;
+ i_inner = i;
+ }
+ else
+ {
+ i_shade = i;
+ }
+ }
+ }
+
+ /* Set the inner color */
+ if( i_inner != -1 )
+ {
+ p_spu->p_sys->pi_yuv[i_inner][0] = 0xff;
+ p_spu->p_sys->pi_yuv[i_inner][1] = 0x80;
+ p_spu->p_sys->pi_yuv[i_inner][2] = 0x80;
+ }
+
+ /* Set the anti-aliasing color */
+ if( i_shade != -1 )
+ {
+ p_spu->p_sys->pi_yuv[i_shade][0] = 0x80;
+ p_spu->p_sys->pi_yuv[i_shade][1] = 0x80;
+ p_spu->p_sys->pi_yuv[i_shade][2] = 0x80;
+ }
+
+ msg_Dbg( p_spudec->p_fifo,
+ "using custom palette (border %i, inner %i, shade %i)",
+ i_border, i_inner, i_shade );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * RenderSPU: draw an SPU on a picture
+ *****************************************************************************
+ * This is a fast implementation of the subpicture drawing code. The data
+ * has been preprocessed once, so we don't need to parse the RLE buffer again
+ * and again. Most sanity checks are already done so that this routine can be
+ * as fast as possible.
+ *****************************************************************************/
+static void RenderSPU( vout_thread_t *p_vout, picture_t *p_pic,
+ const subpicture_t *p_spu )
+{
+ /* Common variables */
+ u16 p_clut16[4];
+ u32 p_clut32[4];
+ u8 *p_dest;
+ u8 *p_destptr = (u8 *)p_dest;
+ u16 *p_source = (u16 *)p_spu->p_sys->p_data;
+
+ int i_x, i_y;
+ int i_len, i_color, i_colprecomp, i_destalpha;
+ u8 i_cnt;
+
+ /* RGB-specific */
+ int i_xscale, i_yscale, i_width, i_height, i_ytmp, i_yreal, i_ynext;
+
+ switch( p_vout->output.i_chroma )
+ {
+ /* I420 target, no scaling */
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ case VLC_FOURCC('Y','V','1','2'):
+
+ p_dest = p_pic->Y_PIXELS + p_spu->i_x + p_spu->i_width
+ + p_pic->Y_PITCH * ( p_spu->i_y + p_spu->i_height );
+
+ /* Draw until we reach the bottom of the subtitle */
+ for( i_y = p_spu->i_height * p_pic->Y_PITCH ;
+ i_y ;
+ i_y -= p_pic->Y_PITCH )
+ {
+ /* Draw until we reach the end of the line */
+ for( i_x = p_spu->i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw the line */
+ i_color = *p_source & 0x3;
+ i_len = *p_source++ >> 2;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ break;
+
+ case 0x0f:
+ memset( p_dest - i_x - i_y,
+ p_spu->p_sys->pi_yuv[i_color][0], i_len );
+ break;
+
+ default:
+ /* To be able to divide by 16 (>>4) we add 1 to the alpha.
+ * This means Alpha 0 won't be completely transparent, but
+ * that's handled in a special case above anyway. */
+ i_colprecomp = p_spu->p_sys->pi_yuv[i_color][0]
+ * (p_spu->p_sys->pi_alpha[ i_color ] + 1);
+ i_destalpha = 15 - p_spu->p_sys->pi_alpha[ i_color ];
+
+ for ( p_destptr = p_dest - i_x - i_y;
+ p_destptr < p_dest - i_x - i_y + i_len;
+ p_destptr++ )
+ {
+ *p_destptr = ( i_colprecomp +
+ *p_destptr * i_destalpha ) >> 4;
+ }
+ break;
+
+ }
+ i_x -= i_len;
+ }
+ }
+
+ break;
+
+ /* RV16 target, scaling */
+ case VLC_FOURCC('R','V','1','6'):
+
+ /* XXX: this is a COMPLETE HACK, memcpy is unable to do u16s anyway */
+ /* FIXME: get this from the DVD */
+ for( i_color = 0; i_color < 4; i_color++ )
+ {
+ p_clut16[i_color] = 0x1111
+ * ( (u16)p_spu->p_sys->pi_yuv[i_color][0] >> 4 );
+ }
+
+ i_xscale = ( p_vout->output.i_width << 6 ) / p_vout->render.i_width;
+ i_yscale = ( p_vout->output.i_height << 6 ) / p_vout->render.i_height;
+
+ i_width = p_spu->i_width * i_xscale;
+ i_height = p_spu->i_height * i_yscale;
+
+ p_dest = p_pic->p->p_pixels + ( i_width >> 6 ) * 2
+ /* Add the picture coordinates and the SPU coordinates */
+ + ( (p_spu->i_x * i_xscale) >> 6 ) * 2
+ + ( (p_spu->i_y * i_yscale) >> 6 ) * p_pic->p->i_pitch;
+
+ /* Draw until we reach the bottom of the subtitle */
+ for( i_y = 0 ; i_y < i_height ; )
+ {
+ i_ytmp = i_y >> 6;
+ i_y += i_yscale;
+
+ /* Check whether we need to draw one line or more than one */
+ if( i_ytmp + 1 >= ( i_y >> 6 ) )
+ {
+ /* Just one line : we precalculate i_y >> 6 */
+ i_yreal = p_pic->p->i_pitch * i_ytmp;
+
+ /* Draw until we reach the end of the line */
+ for( i_x = i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw the line */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= i_xscale * ( *p_source++ >> 2 );
+ break;
+
+ case 0x0f:
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_yreal,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_yreal,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ i_x -= i_len;
+ break;
+ }
+
+ }
+ }
+ else
+ {
+ i_yreal = p_pic->p->i_pitch * i_ytmp;
+ i_ynext = p_pic->p->i_pitch * i_y >> 6;
+
+ /* Draw until we reach the end of the line */
+ for( i_x = i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw as many lines as needed */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= i_xscale * ( *p_source++ >> 2 );
+ break;
+
+ case 0x0f:
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
+ i_ytmp += p_pic->p->i_pitch )
+ {
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ }
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
+ i_ytmp += p_pic->p->i_pitch )
+ {
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ }
+ i_x -= i_len;
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+
+ /* RV32 target, scaling */
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+
+ /* XXX: this is a COMPLETE HACK, memcpy is unable to do u32s anyway */
+ /* FIXME: get this from the DVD */
+ for( i_color = 0; i_color < 4; i_color++ )
+ {
+ p_clut32[i_color] = 0x11111111
+ * ( (u16)p_spu->p_sys->pi_yuv[i_color][0] >> 4 );
+ }
+
+ i_xscale = ( p_vout->output.i_width << 6 ) / p_vout->render.i_width;
+ i_yscale = ( p_vout->output.i_height << 6 ) / p_vout->render.i_height;
+
+ i_width = p_spu->i_width * i_xscale;
+ i_height = p_spu->i_height * i_yscale;
+
+ p_dest = p_pic->p->p_pixels + ( i_width >> 6 ) * 4
+ /* Add the picture coordinates and the SPU coordinates */
+ + ( (p_spu->i_x * i_xscale) >> 6 ) * 4
+ + ( (p_spu->i_y * i_yscale) >> 6 ) * p_pic->p->i_pitch;
+
+ /* Draw until we reach the bottom of the subtitle */
+ for( i_y = 0 ; i_y < i_height ; )
+ {
+ i_ytmp = i_y >> 6;
+ i_y += i_yscale;
+
+ /* Check whether we need to draw one line or more than one */
+ if( i_ytmp + 1 >= ( i_y >> 6 ) )
+ {
+ /* Just one line : we precalculate i_y >> 6 */
+ i_yreal = p_pic->p->i_pitch * i_ytmp;
+
+ /* Draw until we reach the end of the line */
+ for( i_x = i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw the line */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= i_xscale * ( *p_source++ >> 2 );
+ break;
+
+ case 0x0f:
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ memset( p_dest - 4 * ( i_x >> 6 ) + i_yreal,
+ p_clut32[ i_color ], 4 * ( ( i_len >> 6 ) + 1 ) );
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ memset( p_dest - 4 * ( i_x >> 6 ) + i_yreal,
+ p_clut32[ i_color ], 4 * ( ( i_len >> 6 ) + 1 ) );
+ i_x -= i_len;
+ break;
+ }
+
+ }
+ }
+ else
+ {
+ i_yreal = p_pic->p->i_pitch * i_ytmp;
+ i_ynext = p_pic->p->i_pitch * i_y >> 6;
+
+ /* Draw until we reach the end of the line */
+ for( i_x = i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw as many lines as needed */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= i_xscale * ( *p_source++ >> 2 );
+ break;
+
+ case 0x0f:
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
+ i_ytmp += p_pic->p->i_pitch )
+ {
+ memset( p_dest - 4 * ( i_x >> 6 ) + i_ytmp,
+ p_clut32[ i_color ],
+ 4 * ( ( i_len >> 6 ) + 1 ) );
+ }
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
+ i_ytmp += p_pic->p->i_pitch )
+ {
+ memset( p_dest - 4 * ( i_x >> 6 ) + i_ytmp,
+ p_clut32[ i_color ],
+ 4 * ( ( i_len >> 6 ) + 1 ) );
+ }
+ i_x -= i_len;
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+
+ /* NVidia overlay, no scaling */
+ case VLC_FOURCC('Y','U','Y','2'):
+
+ p_dest = p_pic->p->p_pixels +
+ (p_spu->i_x + p_spu->i_width +
+ p_vout->output.i_width * ( p_spu->i_y + p_spu->i_height )) * 2;
+ /* Draw until we reach the bottom of the subtitle */
+ for( i_y = p_spu->i_height * p_vout->output.i_width;
+ i_y ;
+ i_y -= p_vout->output.i_width )
+ {
+ /* Draw until we reach the end of the line */
+ for( i_x = p_spu->i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw the line */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= *p_source++ >> 2;
+ break;
+
+ case 0x0f:
+ i_len = *p_source++ >> 2;
+ for( i_cnt = 0; i_cnt < i_len; i_cnt++ )
+ {
+ /* draw a pixel */
+ /* Y */
+ memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2,
+ p_spu->p_sys->pi_yuv[i_color][0], 1);
+
+ if (!(i_cnt & 0x01))
+ {
+ /* U and V */
+ memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 1,
+ 0x80, 1);
+ memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 3,
+ 0x80, 1);
+ }
+ }
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = *p_source++ >> 2;
+ for( i_cnt = 0; i_cnt < i_len; i_cnt++ )
+ {
+ /* draw a pixel */
+ /* Y */
+ memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2,
+ p_spu->p_sys->pi_yuv[i_color][0], 1);
+
+ if (!(i_cnt & 0x01))
+ {
+ /* U and V */
+ memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 1,
+ 0x80, 1);
+ memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 3,
+ 0x80, 1);
+ }
+ }
+ i_x -= i_len;
+ break;
+ }
+ }
+ }
+
+ break;
+
+
+ default:
+ msg_Err( p_vout, "unknown chroma, can't render SPU" );
+ break;
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * spudec.h : sub picture unit decoder thread interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: spudec.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+struct subpicture_sys_t
+{
+ mtime_t i_pts; /* presentation timestamp */
+
+ int pi_offset[2]; /* byte offsets to data */
+ void *p_data;
+
+ /* Color information */
+ vlc_bool_t b_palette;
+ u8 pi_alpha[4];
+ u8 pi_yuv[4][3];
+};
+
+/*****************************************************************************
+ * spudec_thread_t : sub picture unit decoder thread descriptor
+ *****************************************************************************/
+typedef struct spudec_thread_t
+{
+ /*
+ * Thread properties and locks
+ */
+ vlc_thread_t thread_id; /* id for thread functions */
+
+ /*
+ * Input properties
+ */
+ decoder_fifo_t * p_fifo; /* stores the PES stream data */
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+
+ /*
+ * Output properties
+ */
+ vout_thread_t * p_vout; /* needed to create the spu objects */
+
+ /*
+ * Private properties
+ */
+ int i_spu_size; /* size of current SPU packet */
+ int i_rle_size; /* size of the RLE part */
+
+} spudec_thread_t;
+
+/*****************************************************************************
+ * Amount of bytes we GetChunk() in one go
+ *****************************************************************************/
+#define SPU_CHUNK_SIZE 0x200
+
+/*****************************************************************************
+ * SPU commands
+ *****************************************************************************/
+#define SPU_CMD_FORCE_DISPLAY 0x00
+#define SPU_CMD_START_DISPLAY 0x01
+#define SPU_CMD_STOP_DISPLAY 0x02
+#define SPU_CMD_SET_PALETTE 0x03
+#define SPU_CMD_SET_ALPHACHANNEL 0x04
+#define SPU_CMD_SET_COORDINATES 0x05
+#define SPU_CMD_SET_OFFSETS 0x06
+#define SPU_CMD_END 0xff
+
+/*****************************************************************************
+ * AddNibble: read a nibble from a source packet and add it to our integer.
+ *****************************************************************************/
+static inline unsigned int AddNibble( unsigned int i_code,
+ u8 *p_src, int *pi_index )
+{
+ if( *pi_index & 0x1 )
+ {
+ return( i_code << 4 | ( p_src[(*pi_index)++ >> 1] & 0xf ) );
+ }
+ else
+ {
+ return( i_code << 4 | p_src[(*pi_index)++ >> 1] >> 4 );
+ }
+}
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+vlc_thread_t spudec_CreateThread( decoder_fifo_t * p_fifo );
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+lirc_SOURCES = lirc.c
--- /dev/null
+/*****************************************************************************
+ * lirc.c : lirc plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: lirc.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include <lirc/lirc_client.h>
+
+/*****************************************************************************
+ * intf_sys_t: description and status of FB interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ struct lirc_config *config;
+ vlc_mutex_t change_lock;
+
+ input_thread_t * p_input;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static void Run ( intf_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("infrared remote control module") );
+ set_capability( "interface", 0 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: initialize interface
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+ int i_fd;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return 1;
+ }
+
+ p_intf->pf_run = Run;
+
+ i_fd = lirc_init( "vlc", 1 );
+ if( i_fd == -1 )
+ {
+ msg_Err( p_intf, "lirc_init failed" );
+ free( p_intf->p_sys );
+ return 1;
+ }
+
+ /* We want polling */
+ fcntl( i_fd, F_SETFL, fcntl( i_fd, F_GETFL ) | O_NONBLOCK );
+
+ if( lirc_readconfig( NULL, &p_intf->p_sys->config, NULL ) != 0 )
+ {
+ msg_Err( p_intf, "lirc_readconfig failed" );
+ lirc_deinit();
+ free( p_intf->p_sys );
+ return 1;
+ }
+
+ p_intf->p_sys->p_input = NULL;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Close: destroy interface
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ /* Destroy structure */
+ lirc_freeconfig( p_intf->p_sys->config );
+ lirc_deinit();
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: main loop
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ char *code, *c;
+ playlist_t *p_playlist;
+ input_thread_t *p_input;
+
+ while( !p_intf->b_die )
+ {
+ /* Sleep a bit */
+ msleep( INTF_IDLE_SLEEP );
+
+ /* Update the input */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ /* We poll the lircsocket */
+ if( lirc_nextcode(&code) != 0 )
+ {
+ break;
+ }
+
+ if( code == NULL )
+ {
+ continue;
+ }
+
+ while( !p_intf->b_die
+ && lirc_code2char( p_intf->p_sys->config, code, &c ) == 0
+ && c != NULL )
+ {
+ if( !strcmp( c, "QUIT" ) )
+ {
+ p_intf->p_vlc->b_die = VLC_TRUE;
+ continue;
+ }
+
+ if( !strcmp( c, "FULLSCREEN" ) )
+ {
+ vout_thread_t *p_vout;
+ p_vout = vlc_object_find( p_intf->p_sys->p_input,
+ VLC_OBJECT_VOUT, FIND_CHILD );
+ if( p_vout )
+ {
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ vlc_object_release( p_vout );
+ }
+ continue;
+ }
+
+ if( !strcmp( c, "PLAY" ) )
+ {
+ p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ vlc_mutex_lock( &p_playlist->object_lock );
+ if( p_playlist->i_size )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ playlist_Play( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ }
+ }
+ else if( p_intf->p_sys->p_input )
+ {
+ p_input = p_intf->p_sys->p_input;
+
+ if( !strcmp( c, "PAUSE" ) )
+ {
+ input_SetStatus( p_input, INPUT_STATUS_PAUSE );
+ }
+ else if( !strcmp( c, "NEXT" ) )
+ {
+ p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ playlist_Next( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ }
+ else if( !strcmp( c, "PREV" ) )
+ {
+ p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ playlist_Prev( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ }
+ else if( !strcmp( c, "STOP" ) )
+ {
+ p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ }
+ else if( !strcmp( c, "FAST" ) )
+ {
+ input_SetStatus( p_input, INPUT_STATUS_FASTER );
+ }
+ else if( !strcmp( c, "SLOW" ) )
+ {
+ input_SetStatus( p_input, INPUT_STATUS_SLOWER );
+ }
+ }
+ }
+
+ free( code );
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+rc_SOURCES = rc.c
--- /dev/null
+/*****************************************************************************
+ * rc.c : remote control stdin/stdout plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: rc.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Peter Surda <shurdeek@panorama.sth.ac.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <errno.h> /* ENOMEM */
+#include <stdio.h>
+#include <ctype.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/types.h>
+
+#if defined( WIN32 )
+#include <winsock2.h> /* select() */
+#endif
+
+#define MAX_LINE_LENGTH 256
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+static void Run ( intf_thread_t *p_intf );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("remote control interface module") );
+ set_capability( "interface", 20 );
+ set_callbacks( Activate, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: initialize and create stuff
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*)p_this;
+
+#ifdef HAVE_ISATTY
+ /* Check that stdin is a TTY */
+ if( !isatty( 0 ) )
+ {
+ msg_Warn( p_intf, "fd 0 is not a TTY" );
+ return 1;
+ }
+#endif
+
+ /* Non-buffered stdout */
+ setvbuf( stdout, (char *)NULL, _IOLBF, 0 );
+
+ p_intf->pf_run = Run;
+
+#ifdef WIN32
+ AllocConsole();
+ freopen( "CONOUT$", "w", stdout );
+ freopen( "CONOUT$", "w", stderr );
+ freopen( "CONIN$", "r", stdin );
+ printf( VERSION_MESSAGE "\n" );
+#endif
+
+ printf( "remote control interface initialized, `h' for help\n" );
+ return 0;
+}
+
+/*****************************************************************************
+ * Run: rc thread
+ *****************************************************************************
+ * This part of the interface is in a separate thread so that we can call
+ * exec() from within it without annoying the rest of the program.
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ input_thread_t * p_input;
+
+ char p_buffer[ MAX_LINE_LENGTH + 1 ];
+ vlc_bool_t b_complete = 0;
+ input_info_category_t * p_category;
+ input_info_t * p_info;
+
+ int i_dummy;
+ off_t i_oldpos = 0;
+ off_t i_newpos;
+ fd_set fds; /* stdin changed? */
+ struct timeval tv; /* how long to wait */
+
+ double f_ratio = 1;
+ char psz_dashes[81];
+
+ memset(psz_dashes, '-', 80);
+ psz_dashes[80] = '\0';
+
+ p_input = NULL;
+
+ while( !p_intf->b_die )
+ {
+ b_complete = 0;
+
+ /* Check stdin */
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+ FD_ZERO( &fds );
+ FD_SET( STDIN_FILENO, &fds );
+
+ i_dummy = select( 32, &fds, NULL, NULL, &tv );
+ if( i_dummy > 0 )
+ {
+ int i_size = 0;
+
+ while( !p_intf->b_die
+ && i_size < MAX_LINE_LENGTH
+ && read( STDIN_FILENO, p_buffer + i_size, 1 ) > 0
+ && p_buffer[ i_size ] != '\r'
+ && p_buffer[ i_size ] != '\n' )
+ {
+ i_size++;
+ }
+
+ if( i_size == MAX_LINE_LENGTH
+ || p_buffer[ i_size ] == '\r'
+ || p_buffer[ i_size ] == '\n' )
+ {
+ p_buffer[ i_size ] = 0;
+ b_complete = 1;
+ }
+ }
+
+ /* Manage the input part */
+ if( p_input == NULL )
+ {
+ p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+ else if( p_input->b_dead )
+ {
+ vlc_object_release( p_input );
+ p_input = NULL;
+ }
+
+ if( p_input )
+ {
+ /* Get position */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( !p_input->b_die && p_input->stream.i_mux_rate )
+ {
+#define A p_input->stream.p_selected_area
+ f_ratio = 1.0 / ( 50 * p_input->stream.i_mux_rate );
+ i_newpos = A->i_tell * f_ratio;
+
+ if( i_oldpos != i_newpos )
+ {
+ i_oldpos = i_newpos;
+ printf( "pos: %li s / %li s\n", (long int)i_newpos,
+ (long int)(f_ratio * A->i_size) );
+ }
+#undef S
+ }
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+
+ /* Is there something to do? */
+ if( b_complete == 1 )
+ {
+ char *p_cmd = p_buffer;
+
+ switch( p_cmd[0] )
+ {
+ case 'a':
+ case 'A':
+ if( p_cmd[1] == ' ' )
+ {
+ playlist_t *p_playlist;
+ p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ playlist_Add( p_playlist, p_cmd + 2,
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ vlc_object_release( p_playlist );
+ }
+ }
+ break;
+
+ case 'd':
+ case 'D':
+ vlc_dumpstructure( p_intf->p_vlc );
+ break;
+
+ case 'p':
+ case 'P':
+ if( p_input )
+ {
+ input_SetStatus( p_input, INPUT_STATUS_PAUSE );
+ }
+ break;
+
+ case 'f':
+ case 'F':
+ if( p_input )
+ {
+ vout_thread_t *p_vout;
+ p_vout = vlc_object_find( p_input,
+ VLC_OBJECT_VOUT, FIND_CHILD );
+
+ if( p_vout )
+ {
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ vlc_object_release( p_vout );
+ }
+ }
+ break;
+
+ case 's':
+ case 'S':
+ ;
+ break;
+
+ case 'q':
+ case 'Q':
+ p_intf->p_vlc->b_die = VLC_TRUE;
+ break;
+
+ case 'r':
+ case 'R':
+ if( p_input )
+ {
+ for( i_dummy = 1;
+ i_dummy < MAX_LINE_LENGTH && p_cmd[ i_dummy ] >= '0'
+ && p_cmd[ i_dummy ] <= '9';
+ i_dummy++ )
+ {
+ ;
+ }
+
+ p_cmd[ i_dummy ] = 0;
+ input_Seek( p_input, (off_t)atoi( p_cmd + 1 ),
+ INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
+ /* rcreseek(f_cpos); */
+ }
+ break;
+
+ case '?':
+ case 'h':
+ case 'H':
+ printf( "help for remote control commands\n" );
+ printf( "h . . . . . . . . . . . . . . . . . . . . . help\n" );
+ printf( "a XYZ . . . . . . . . . . append XYZ to playlist\n" );
+ printf( "p . . . . . . . . . . . . . . . . . toggle pause\n" );
+ printf( "f . . . . . . . . . . . . . . toggle fullscreen\n" );
+ printf( "r X . . . seek in seconds, for instance `r 3.5'\n" );
+ printf( "q . . . . . . . . . . . . . . . . . . . . . quit\n" );
+ printf( "end of help\n" );
+ break;
+ case 'i':
+ case 'I':
+ printf( "Dumping stream info\n" );
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_category = p_input->stream.p_info;
+ while ( p_category )
+ {
+ psz_dashes[72 - strlen(p_category->psz_name) ] = '\0';
+ printf( "+--| %s |%s+\n", p_category->psz_name, psz_dashes);
+ psz_dashes[72 - strlen(p_category->psz_name) ] = '-';
+ p_info = p_category->p_info;
+ while ( p_info )
+ {
+ printf( "| %s: %s\n", p_info->psz_name,
+ p_info->psz_value );
+ p_info = p_info->p_next;
+ }
+ printf("|\n");
+ p_category = p_category->p_next;
+ }
+ psz_dashes[78] = '\0';
+ printf( "+%s+\n", psz_dashes );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ break;
+ case '\0':
+ /* Ignore empty lines */
+ break;
+ default:
+ printf( "unknown command `%s'\n", p_cmd );
+ break;
+ }
+ }
+
+ msleep( INTF_IDLE_SLEEP );
+ }
+
+ if( p_input )
+ {
+ vlc_object_release( p_input );
+ p_input = NULL;
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+a52_SOURCES = demux.c
--- /dev/null
+/*****************************************************************************
+ * a52_system.c : A52 input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: demux.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include <sys/types.h>
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define A52_PACKET_SIZE 16384
+#define MAX_PACKETS_IN_FIFO 3
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Init ( vlc_object_t * );
+static int Demux ( input_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( "A52 demuxer" );
+ set_capability( "demux", 150 );
+ set_callbacks( Init, NULL );
+ add_shortcut( "a52sys" );
+vlc_module_end();
+
+/*****************************************************************************
+ * Init: initializes ES structures
+ *****************************************************************************/
+static int Init( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ es_descriptor_t * p_es;
+ byte_t * p_peek;
+
+ /* Initialize access plug-in structures. */
+ if( p_input->i_mtu == 0 )
+ {
+ /* Improve speed. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+ }
+
+ p_input->pf_demux = Demux;
+ p_input->pf_rewind = NULL;
+
+ /* Have a peep at the show. */
+ if( input_Peek( p_input, &p_peek, 2 ) < 2 )
+ {
+ /* Stream shorter than 4 bytes... */
+ msg_Err( p_input, "cannot peek()" );
+ return( -1 );
+ }
+
+ if( *p_peek != 0x0b || *(p_peek + 1) != 0x77 )
+ {
+ if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "a52sys", 3 ) )
+ {
+ /* User forced */
+ msg_Err( p_input, "this doesn't look like an a52 stream, continuing" );
+ }
+ else
+ {
+ msg_Warn( p_input, "a52 module discarded (no startcode)" );
+ return( -1 );
+ }
+ }
+
+ if( input_InitStream( p_input, 0 ) == -1 )
+ {
+ return( -1 );
+ }
+ input_AddProgram( p_input, 0, 0 );
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xBD, 0 );
+ p_es->i_stream_id = 0xBD;
+ p_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
+ p_es->i_cat = AUDIO_ES;
+ input_SelectES( p_input, p_es );
+ p_input->stream.p_selected_area->i_tell = 0;
+ p_input->stream.p_selected_program->b_is_ok = 1;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int Demux( input_thread_t * p_input )
+{
+ ssize_t i_read;
+ decoder_fifo_t * p_fifo =
+ p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
+ pes_packet_t * p_pes;
+ data_packet_t * p_data;
+
+ i_read = input_SplitBuffer( p_input, &p_data, A52_PACKET_SIZE );
+
+ if ( i_read <= 0 )
+ {
+ return( i_read );
+ }
+
+ p_pes = input_NewPES( p_input->p_method_data );
+
+ if( p_pes == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ input_DeletePacket( p_input->p_method_data, p_data );
+ return( -1 );
+ }
+
+ p_pes->i_rate = p_input->stream.control.i_rate;
+ p_pes->p_first = p_pes->p_last = p_data;
+ p_pes->i_nb_data = 1;
+
+ vlc_mutex_lock( &p_fifo->data_lock );
+ if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
+ {
+ /* Wait for the decoder. */
+ vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+ }
+ vlc_mutex_unlock( &p_fifo->data_lock );
+
+ if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
+ |(p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_START)
+ | (input_ClockManageControl( p_input,
+ p_input->stream.p_selected_program,
+ (mtime_t)0 ) == PAUSE_S) )
+ {
+ msg_Warn( p_input, "synchro reinit" );
+ p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
+ p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
+ }
+
+ input_DecodePES( p_fifo, p_pes );
+
+ return( 1 );
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+avi_SOURCES = avi.c libioRIFF.c
--- /dev/null
+/*****************************************************************************
+ * avi.c : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: avi.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#include <errno.h>
+#include <sys/types.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include "video.h"
+
+#include "libioRIFF.h"
+#include "avi.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int AVIInit ( vlc_object_t * );
+static void __AVIEnd ( vlc_object_t * );
+static int AVIDemux ( input_thread_t * );
+
+#define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( "RIFF-AVI demuxer" );
+ set_capability( "demux", 150 );
+ set_callbacks( AVIInit, __AVIEnd );
+vlc_module_end();
+
+/*****************************************************************************
+ * Some usefull functions to manipulate memory
+ *****************************************************************************/
+static u16 GetWLE( byte_t *p_buff )
+{
+ u16 i;
+ i = (*p_buff) + ( *(p_buff + 1) <<8 );
+ return ( i );
+}
+static u32 GetDWLE( byte_t *p_buff )
+{
+ u32 i;
+ i = (*p_buff) + ( *(p_buff + 1) <<8 ) +
+ ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
+ return ( i );
+}
+static u32 GetDWBE( byte_t *p_buff )
+{
+ u32 i;
+ i = ((*p_buff)<<24) + ( *(p_buff + 1) <<16 ) +
+ ( *(p_buff + 2) <<8 ) + ( *(p_buff + 3) );
+ return ( i );
+}
+static inline off_t __EVEN( off_t i )
+{
+ return( (i & 1) ? i+1 : i );
+}
+
+
+/*****************************************************************************
+ * Functions for parsing the headers in an avi file
+ *****************************************************************************/
+static void AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
+{
+ p_avih->i_microsecperframe = GetDWLE( p_buff );
+ p_avih->i_maxbytespersec = GetDWLE( p_buff + 4);
+ p_avih->i_reserved1 = GetDWLE( p_buff + 8);
+ p_avih->i_flags = GetDWLE( p_buff + 12);
+ p_avih->i_totalframes = GetDWLE( p_buff + 16);
+ p_avih->i_initialframes = GetDWLE( p_buff + 20);
+ p_avih->i_streams = GetDWLE( p_buff + 24);
+ p_avih->i_suggestedbuffersize = GetDWLE( p_buff + 28);
+ p_avih->i_width = GetDWLE( p_buff + 32 );
+ p_avih->i_height = GetDWLE( p_buff + 36 );
+ p_avih->i_scale = GetDWLE( p_buff + 40 );
+ p_avih->i_rate = GetDWLE( p_buff + 44 );
+ p_avih->i_start = GetDWLE( p_buff + 48);
+ p_avih->i_length = GetDWLE( p_buff + 52);
+}
+static void AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
+{
+ p_strh->i_type = GetDWLE( p_buff );
+ p_strh->i_handler = GetDWLE( p_buff + 4 );
+ p_strh->i_flags = GetDWLE( p_buff + 8 );
+ p_strh->i_reserved1 = GetDWLE( p_buff + 12);
+ p_strh->i_initialframes = GetDWLE( p_buff + 16);
+ p_strh->i_scale = GetDWLE( p_buff + 20);
+ p_strh->i_rate = GetDWLE( p_buff + 24);
+ p_strh->i_start = GetDWLE( p_buff + 28);
+ p_strh->i_length = GetDWLE( p_buff + 32);
+ p_strh->i_suggestedbuffersize = GetDWLE( p_buff + 36);
+ p_strh->i_quality = GetDWLE( p_buff + 40);
+ p_strh->i_samplesize = GetDWLE( p_buff + 44);
+}
+static void AVI_Parse_BitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
+{
+ h->i_size = GetDWLE( p_data );
+ h->i_width = GetDWLE( p_data + 4 );
+ h->i_height = GetDWLE( p_data + 8 );
+ h->i_planes = GetWLE( p_data + 12 );
+ h->i_bitcount = GetWLE( p_data + 14 );
+ h->i_compression = GetDWLE( p_data + 16 );
+ h->i_sizeimage = GetDWLE( p_data + 20 );
+ h->i_xpelspermeter = GetDWLE( p_data + 24 );
+ h->i_ypelspermeter = GetDWLE( p_data + 28 );
+ h->i_clrused = GetDWLE( p_data + 32 );
+ h->i_clrimportant = GetDWLE( p_data + 36 );
+}
+static void AVI_Parse_WaveFormatEx( waveformatex_t *h, byte_t *p_data )
+{
+ h->i_formattag = GetWLE( p_data );
+ h->i_channels = GetWLE( p_data + 2 );
+ h->i_samplespersec = GetDWLE( p_data + 4 );
+ h->i_avgbytespersec= GetDWLE( p_data + 8 );
+ h->i_blockalign = GetWLE( p_data + 12 );
+ h->i_bitspersample = GetWLE( p_data + 14 );
+ h->i_size = GetWLE( p_data + 16 );
+}
+
+static inline int AVI_GetESTypeFromTwoCC( u16 i_type )
+{
+ switch( i_type )
+ {
+ case( TWOCC_wb ):
+ return( AUDIO_ES );
+ case( TWOCC_dc ):
+ case( TWOCC_db ):
+ return( VIDEO_ES );
+ default:
+ return( UNKNOWN_ES );
+ }
+}
+
+static vlc_fourcc_t AVI_AudioGetType( u32 i_type )
+{
+ switch( i_type )
+ {
+/* case( WAVE_FORMAT_PCM ):
+ return VLC_FOURCC('l','p','c','m'); */
+ case( WAVE_FORMAT_A52 ):
+ return VLC_FOURCC('a','5','2',' ');
+ case( WAVE_FORMAT_MPEG):
+ case( WAVE_FORMAT_MPEGLAYER3):
+ return VLC_FOURCC('m','p','g','a'); /* for mpeg2 layer 1 2 ou 3 */
+ default:
+ return 0;
+ }
+}
+
+/* Test if it seems that it's a key frame */
+static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
+{
+ switch( i_fourcc )
+ {
+ case FOURCC_DIV1:
+ case FOURCC_div1:
+ case FOURCC_MPG4:
+ case FOURCC_mpg4:
+ if( GetDWBE( p_byte ) != 0x00000100 )
+ /* startcode perhaps swapped, I haven't tested */
+ {
+ /* it's seems it's not an msmpegv1 stream
+ but perhaps I'm wrong so return yes */
+ return( AVIIF_KEYFRAME );
+ }
+ else
+ {
+ return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
+ }
+ case FOURCC_DIV2:
+ case FOURCC_div2:
+ case FOURCC_MP42:
+ case FOURCC_mp42:
+ case FOURCC_MPG3:
+ case FOURCC_mpg3:
+ case FOURCC_div3:
+ case FOURCC_MP43:
+ case FOURCC_mp43:
+ case FOURCC_DIV3:
+ case FOURCC_DIV4:
+ case FOURCC_div4:
+ case FOURCC_DIV5:
+ case FOURCC_div5:
+ case FOURCC_DIV6:
+ case FOURCC_div6:
+ case FOURCC_AP41:
+ case FOURCC_3IV1:
+ return( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
+ case FOURCC_DIVX:
+ case FOURCC_divx:
+ case FOURCC_MP4S:
+ case FOURCC_mp4s:
+ case FOURCC_M4S2:
+ case FOURCC_m4s2:
+ case FOURCC_xvid:
+ case FOURCC_XVID:
+ case FOURCC_XviD:
+ case FOURCC_DX50:
+ case FOURCC_mp4v:
+ case FOURCC_4:
+ if( GetDWBE( p_byte ) != 0x000001b6 )
+ {
+ /* not true , need to find the first VOP header
+ but, I'm lazy */
+ return( AVIIF_KEYFRAME );
+ }
+ else
+ {
+ return( (*(p_byte+4))&0xC0 ? 0 : AVIIF_KEYFRAME );
+ }
+ default:
+ /* I can't do it, so said yes */
+ return( AVIIF_KEYFRAME );
+ }
+
+}
+/*****************************************************************************
+ * Data and functions to manipulate pes buffer
+ *****************************************************************************/
+#define BUFFER_MAXTOTALSIZE 512*1024 /* 1/2 Mo */
+#define BUFFER_MAXSPESSIZE 1024*200
+static int AVI_PESBuffer_IsFull( AVIStreamInfo_t *p_info )
+{
+ return( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE ? 1 : 0);
+}
+static void AVI_PESBuffer_Add( input_buffers_t *p_method_data,
+ AVIStreamInfo_t *p_info,
+ pes_packet_t *p_pes,
+ int i_posc,
+ int i_posb )
+{
+ AVIESBuffer_t *p_buffer_pes;
+
+ if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
+ {
+ input_DeletePES( p_method_data, p_pes );
+ return;
+ }
+
+ if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
+ {
+ input_DeletePES( p_method_data, p_pes );
+ return;
+ }
+ p_buffer_pes->p_next = NULL;
+ p_buffer_pes->p_pes = p_pes;
+ p_buffer_pes->i_posc = i_posc;
+ p_buffer_pes->i_posb = i_posb;
+
+ if( p_info->p_pes_last )
+ {
+ p_info->p_pes_last->p_next = p_buffer_pes;
+ }
+ p_info->p_pes_last = p_buffer_pes;
+ if( !p_info->p_pes_first )
+ {
+ p_info->p_pes_first = p_buffer_pes;
+ }
+ p_info->i_pes_count++;
+ p_info->i_pes_totalsize += p_pes->i_pes_size;
+}
+static pes_packet_t *AVI_PESBuffer_Get( AVIStreamInfo_t *p_info )
+{
+ AVIESBuffer_t *p_buffer_pes;
+ pes_packet_t *p_pes;
+ if( p_info->p_pes_first )
+ {
+ p_buffer_pes = p_info->p_pes_first;
+ p_info->p_pes_first = p_buffer_pes->p_next;
+ if( !p_info->p_pes_first )
+ {
+ p_info->p_pes_last = NULL;
+ }
+ p_pes = p_buffer_pes->p_pes;
+
+ free( p_buffer_pes );
+ p_info->i_pes_count--;
+ p_info->i_pes_totalsize -= p_pes->i_pes_size;
+ return( p_pes );
+ }
+ else
+ {
+ return( NULL );
+ }
+}
+static int AVI_PESBuffer_Drop( input_buffers_t *p_method_data,
+ AVIStreamInfo_t *p_info )
+{
+ pes_packet_t *p_pes = AVI_PESBuffer_Get( p_info );
+ if( p_pes )
+ {
+ input_DeletePES( p_method_data, p_pes );
+ return( 1 );
+ }
+ else
+ {
+ return( 0 );
+ }
+}
+static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
+ AVIStreamInfo_t *p_info )
+{
+ while( p_info->p_pes_first )
+ {
+ AVI_PESBuffer_Drop( p_method_data, p_info );
+ }
+}
+
+static void AVI_ParseStreamHeader( u32 i_id, int *i_number, int *i_type )
+{
+ int c1,c2;
+
+ c1 = ( i_id ) & 0xFF;
+ c2 = ( i_id >> 8 ) & 0xFF;
+
+ if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
+ {
+ *i_number = 100; /* > max stream number */
+ *i_type = 0;
+ }
+ else
+ {
+ *i_number = (c1 - '0') * 10 + (c2 - '0' );
+ *i_type = ( i_id >> 16 ) & 0xFFFF;
+ }
+}
+
+/* Function to manipulate stream easily */
+static off_t AVI_TellAbsolute( input_thread_t *p_input )
+{
+ off_t i_pos;
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ i_pos= p_input->stream.p_selected_area->i_tell -
+ ( p_input->p_last_data - p_input->p_current_data );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( i_pos );
+}
+
+static int AVI_SeekAbsolute( input_thread_t *p_input,
+ off_t i_pos)
+{
+ off_t i_filepos;
+ /* FIXME add support for not seekable stream */
+
+ i_filepos = AVI_TellAbsolute( p_input );
+ if( i_pos != i_filepos )
+ {
+// msg_Err( p_input, "Seek --> delta %d", i_pos - i_filepos );
+ p_input->pf_seek( p_input, i_pos );
+ input_AccessReinit( p_input );
+ }
+ return( 1 );
+}
+
+
+static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
+ AVIIndexEntry_t *p_index)
+{
+ AVIIndexEntry_t *p_tmp;
+ if( p_info->p_index == NULL )
+ {
+ p_info->i_idxmax = 16384;
+ p_info->i_idxnb = 0;
+ p_info->p_index = calloc( p_info->i_idxmax,
+ sizeof( AVIIndexEntry_t ) );
+ if( p_info->p_index == NULL ) {return;}
+ }
+ if( p_info->i_idxnb >= p_info->i_idxmax )
+ {
+ p_info->i_idxmax += 16384;
+ p_tmp = realloc( (void*)p_info->p_index,
+ p_info->i_idxmax *
+ sizeof( AVIIndexEntry_t ) );
+ if( !p_tmp )
+ {
+ p_info->i_idxmax -= 16384;
+ return;
+ }
+ p_info->p_index = p_tmp;
+ }
+ /* calculate cumulate length */
+ if( p_info->i_idxnb > 0 )
+ {
+ p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
+ p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
+ }
+ else
+ {
+ p_index->i_lengthtotal = 0;
+ }
+
+ p_info->p_index[p_info->i_idxnb] = *p_index;
+ p_info->i_idxnb++;
+}
+
+static void __AVI_GetIndex( input_thread_t *p_input )
+{
+ AVIIndexEntry_t index;
+ byte_t *p_buff;
+ riffchunk_t *p_idx1;
+ int i_read;
+ int i;
+ int i_number;
+ int i_type;
+ int i_totalentry = 0;
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data ;
+
+ if( RIFF_FindAndGotoDataChunk( p_input,
+ p_avi_demux->p_riff,
+ &p_idx1,
+ FOURCC_idx1)!=0 )
+ {
+ msg_Warn( p_input, "cannot find index" );
+ RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );
+ return;
+ }
+ p_avi_demux->p_idx1 = p_idx1;
+ msg_Dbg( p_input, "loading index" );
+ for(;;)
+ {
+ i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
+ if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
+ ||( i_totalentry *16 >= p_idx1->i_size ) )
+ {
+ msg_Dbg( p_input, "read %d idx entries", i_totalentry );
+ return;
+ }
+ i_read /= 16 ;
+ for( i = 0; i < i_read; i++ )
+ {
+ byte_t *p_peek = p_buff + i * 16;
+ i_totalentry++;
+ index.i_id = GetDWLE( p_peek );
+ index.i_flags = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
+ index.i_pos = GetDWLE( p_peek+8);
+ index.i_length = GetDWLE(p_peek+12);
+ AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
+
+ if( ( i_number < p_avi_demux->i_streams )
+ &&(p_avi_demux->pp_info[i_number]->i_cat ==
+ AVI_GetESTypeFromTwoCC( i_type )))
+ {
+ __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
+ &index );
+ }
+ }
+ __RIFF_SkipBytes( p_input, 16 * i_read );
+ }
+
+}
+
+/* XXX call after get p_movi */
+static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
+{
+ int i_stream;
+ int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+
+/* FIXME some work to do :
+ * test in the file if it's true, if not do a RIFF_Find...
+*/
+#define p_info p_avi_demux->pp_info[i_stream]
+ for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
+ {
+ if( ( p_info->p_index )
+ && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
+ {
+ b_start = 0;
+ break;
+ }
+ }
+ if( !b_start )
+ {
+ for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
+ {
+ int i;
+ if( p_info->p_index )
+ {
+ for( i = 0; i < p_info->i_idxnb; i++ )
+ {
+ p_info->p_index[i].i_pos += p_avi_demux->p_movi->i_pos + 8;
+ }
+ }
+ }
+ }
+#undef p_info
+}
+
+/*****************************************************************************
+ * AVIEnd: frees unused data
+ *****************************************************************************/
+static void __AVIEnd ( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ int i;
+ demux_data_avi_file_t *p_avi_demux;
+ p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data ;
+
+ if( p_avi_demux->p_riff )
+ RIFF_DeleteChunk( p_input, p_avi_demux->p_riff );
+ if( p_avi_demux->p_hdrl )
+ RIFF_DeleteChunk( p_input, p_avi_demux->p_hdrl );
+ if( p_avi_demux->p_movi )
+ RIFF_DeleteChunk( p_input, p_avi_demux->p_movi );
+ if( p_avi_demux->p_idx1 )
+ RIFF_DeleteChunk( p_input, p_avi_demux->p_idx1 );
+ if( p_avi_demux->pp_info )
+ {
+ for( i = 0; i < p_avi_demux->i_streams; i++ )
+ {
+ if( p_avi_demux->pp_info[i] )
+ {
+ if( p_avi_demux->pp_info[i]->p_index )
+ {
+ free( p_avi_demux->pp_info[i]->p_index );
+ AVI_PESBuffer_Flush( p_input->p_method_data,
+ p_avi_demux->pp_info[i] );
+ }
+ free( p_avi_demux->pp_info[i] );
+ }
+ }
+ free( p_avi_demux->pp_info );
+ }
+}
+
+/*****************************************************************************
+ * AVIInit: check file and initializes AVI structures
+ *****************************************************************************/
+static int AVIInit( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ riffchunk_t *p_riff,*p_hdrl,*p_movi;
+ riffchunk_t *p_avih;
+ riffchunk_t *p_strl,*p_strh,*p_strf;
+ demux_data_avi_file_t *p_avi_demux;
+ es_descriptor_t *p_es = NULL; /* for not warning */
+ int i;
+
+ p_input->pf_demux = AVIDemux;
+
+ if( !( p_input->p_demux_data =
+ p_avi_demux = malloc( sizeof(demux_data_avi_file_t) ) ) )
+ {
+ msg_Err( p_input, "out of memory" );
+ return( -1 );
+ }
+ memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
+ p_avi_demux->i_rate = DEFAULT_RATE;
+ p_avi_demux->b_seekable = ( ( p_input->stream.b_seekable )
+ &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
+
+ /* Initialize access plug-in structures. */
+ if( p_input->i_mtu == 0 )
+ {
+ /* Improve speed. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+ }
+
+ if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
+ {
+ AVIEnd( p_input );
+ msg_Warn( p_input, "RIFF-AVI module discarded" );
+ return( -1 );
+ }
+ p_avi_demux->p_riff = p_riff;
+
+ if ( RIFF_DescendChunk(p_input) != 0 )
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot look for subchunk" );
+ return ( -1 );
+ }
+
+ /* it's a riff-avi file, so search for LIST-hdrl */
+ if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
+ return( -1 );
+ }
+ p_avi_demux->p_hdrl = p_hdrl;
+
+ if( RIFF_DescendChunk(p_input) != 0 )
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot look for subchunk" );
+ return ( -1 );
+ }
+ /* in LIST-hdrl search avih */
+ if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
+ &p_avih, FOURCC_avih ) != 0 )
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot find \"avih\" chunk" );
+ return( -1 );
+ }
+ AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
+ RIFF_DeleteChunk( p_input, p_avih );
+
+ if( p_avi_demux->avih.i_streams == 0 )
+ /* no stream found, perhaps it would be cool to find it */
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "no stream defined!" );
+ return( -1 );
+ }
+
+ /* create one program */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( input_InitStream( p_input, 0 ) == -1)
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot init stream" );
+ return( -1 );
+ }
+ if( input_AddProgram( p_input, 0, 0) == NULL )
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot add program" );
+ return( -1 );
+ }
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+ p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ /* now read info on each stream and create ES */
+ p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
+
+ p_avi_demux->pp_info = calloc( p_avi_demux->i_streams,
+ sizeof( AVIStreamInfo_t* ) );
+ memset( p_avi_demux->pp_info,
+ 0,
+ sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
+
+ for( i = 0 ; i < p_avi_demux->i_streams; i++ )
+ {
+#define p_info p_avi_demux->pp_info[i]
+ p_info = malloc( sizeof(AVIStreamInfo_t ) );
+ memset( p_info, 0, sizeof( AVIStreamInfo_t ) );
+
+ if( ( RIFF_FindListChunk(p_input,
+ &p_strl,p_hdrl, FOURCC_strl) != 0 )
+ ||( RIFF_DescendChunk(p_input) != 0 ))
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot find \"LIST-strl\"" );
+ return( -1 );
+ }
+
+ /* in LIST-strl search strh */
+ if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
+ &p_strh, FOURCC_strh ) != 0 )
+ {
+ RIFF_DeleteChunk( p_input, p_strl );
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot find \"strh\"" );
+ return( -1 );
+ }
+ AVI_Parse_Header( &p_info->header,
+ p_strh->p_data->p_payload_start);
+ RIFF_DeleteChunk( p_input, p_strh );
+
+ /* in LIST-strl search strf */
+ if( RIFF_FindAndLoadChunk( p_input, p_hdrl,
+ &p_strf, FOURCC_strf ) != 0 )
+ {
+ RIFF_DeleteChunk( p_input, p_strl );
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot find \"strf\"" );
+ return( -1 );
+ }
+ /* we don't get strd, it's useless for divx,opendivx,mepgaudio */
+ if( RIFF_AscendChunk(p_input, p_strl) != 0 )
+ {
+ RIFF_DeleteChunk( p_input, p_strf );
+ RIFF_DeleteChunk( p_input, p_strl );
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot go out (\"strl\")" );
+ return( -1 );
+ }
+
+ /* add one ES */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_es = input_AddES( p_input,
+ p_input->stream.p_selected_program, 1+i,
+ p_strf->i_size );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ p_es->i_stream_id =i; /* XXX: i don't use it */
+
+ switch( p_info->header.i_type )
+ {
+ case( FOURCC_auds ):
+ p_es->i_cat = AUDIO_ES;
+ AVI_Parse_WaveFormatEx( &p_info->audio_format,
+ p_strf->p_data->p_payload_start );
+ p_es->i_fourcc = AVI_AudioGetType(
+ p_info->audio_format.i_formattag );
+ break;
+
+ case( FOURCC_vids ):
+ p_es->i_cat = VIDEO_ES;
+ AVI_Parse_BitMapInfoHeader( &p_info->video_format,
+ p_strf->p_data->p_payload_start );
+
+ /* XXX quick hack for playing ffmpeg video, I don't know
+ who is doing something wrong */
+ p_info->header.i_samplesize = 0;
+ p_es->i_fourcc = p_info->video_format.i_compression;
+ break;
+ default:
+ msg_Err( p_input, "unknown stream(%d) type", i );
+ p_es->i_cat = UNKNOWN_ES;
+ break;
+ }
+ p_info->p_es = p_es;
+ p_info->i_cat = p_es->i_cat;
+ /* We copy strf for decoder in p_es->p_demux_data */
+ memcpy( p_es->p_demux_data,
+ p_strf->p_data->p_payload_start,
+ p_strf->i_size );
+ RIFF_DeleteChunk( p_input, p_strf );
+ RIFF_DeleteChunk( p_input, p_strl );
+#undef p_info
+ }
+
+
+
+ /* go out of p_hdrl */
+ if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot go out (\"hdrl\")" );
+ return( -1 );
+ }
+
+ /* go to movi chunk to get it*/
+ if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
+ {
+ msg_Err( p_input, "cannot find \"LIST-movi\"" );
+ AVIEnd( p_input );
+ return( -1 );
+ }
+ p_avi_demux->p_movi = p_movi;
+
+ /* get index XXX need to have p_movi */
+ if( p_avi_demux->b_seekable )
+ {
+ /* get index */
+ __AVI_GetIndex( p_input );
+ /* try to get i_idxoffset for each stream */
+ __AVI_UpdateIndexOffset( p_input );
+ /* to make sure to go the begining unless demux will see a seek */
+ RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
+
+ }
+ else
+ {
+ msg_Warn( p_input, "no index!" );
+ }
+
+ if( RIFF_DescendChunk( p_input ) != 0 )
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot go in (\"movi\")" );
+ return( -1 );
+ }
+
+ /* print informations on streams */
+ msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
+ p_avi_demux->i_streams,
+ p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
+ p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
+ p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
+ p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
+
+ for( i = 0; i < p_avi_demux->i_streams; i++ )
+ {
+#define p_info p_avi_demux->pp_info[i]
+ switch( p_info->p_es->i_cat )
+ {
+ case( VIDEO_ES ):
+
+ msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
+ (char*)&p_info->video_format.i_compression,
+ p_info->video_format.i_width,
+ p_info->video_format.i_height,
+ p_info->video_format.i_bitcount,
+ (float)p_info->header.i_rate /
+ (float)p_info->header.i_scale );
+ if( (p_avi_demux->p_info_video == NULL) )
+ {
+ p_avi_demux->p_info_video = p_info;
+ /* TODO add test to see if a decoder has been found */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ input_SelectES( p_input, p_info->p_es );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+ break;
+
+ case( AUDIO_ES ):
+ msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
+ p_info->audio_format.i_formattag,
+ p_info->audio_format.i_channels,
+ p_info->audio_format.i_samplespersec,
+ p_info->audio_format.i_bitspersample );
+ if( (p_avi_demux->p_info_audio == NULL) )
+ {
+ p_avi_demux->p_info_audio = p_info;
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ input_SelectES( p_input, p_info->p_es );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+ break;
+ default:
+ break;
+ }
+#undef p_info
+ }
+
+
+ /* we select the first audio and video ES */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( !p_avi_demux->p_info_video )
+ {
+ msg_Warn( p_input, "no video stream found" );
+ }
+ if( !p_avi_demux->p_info_audio )
+ {
+ msg_Warn( p_input, "no audio stream found!" );
+ }
+ p_input->stream.p_selected_program->b_is_ok = 1;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( 0 );
+}
+
+
+
+
+
+
+/*****************************************************************************
+ * Function to convert pts to chunk or byte
+ *****************************************************************************/
+
+static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
+ mtime_t i_pts )
+{
+ return( (mtime_t)((s64)i_pts *
+ (s64)p_info->header.i_rate /
+ (s64)p_info->header.i_scale /
+ (s64)1000000 ) );
+}
+static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
+ mtime_t i_pts )
+{
+ return( (mtime_t)((s64)i_pts *
+ (s64)p_info->header.i_samplesize *
+ (s64)p_info->header.i_rate /
+ (s64)p_info->header.i_scale /
+ (s64)1000000 ) );
+
+}
+static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
+{
+
+ if( p_info->header.i_samplesize )
+ {
+ /* we need a valid entry we will emulate one */
+ int i_len;
+ if( p_info->i_idxposc == p_info->i_idxnb )
+ {
+ if( p_info->i_idxposc )
+ {
+ /* use the last entry */
+ i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
+ + p_info->p_index[p_info->i_idxnb - 1].i_length
+ + p_info->i_idxposb; /* should be 0 */
+ }
+ else
+ {
+ i_len = p_info->i_idxposb;
+ /* no valid entry use only offset*/
+ }
+ }
+ else
+ {
+ i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
+ + p_info->i_idxposb;
+ }
+ return( (mtime_t)( (s64)1000000 *
+ (s64)i_len *
+ (s64)p_info->header.i_scale /
+ (s64)p_info->header.i_rate /
+ (s64)p_info->header.i_samplesize ) );
+ }
+ else
+ {
+ /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
+ return( (mtime_t)( (s64)1000000 *
+ (s64)(p_info->i_idxposc ) *
+ (s64)p_info->header.i_scale /
+ (s64)p_info->header.i_rate) );
+ }
+}
+
+
+/*****************************************************************************
+ * Functions to acces streams data
+ * Uses it, because i plane to read unseekable stream
+ * Don't work for the moment for unseekable stream
+ * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do
+ *****************************************************************************/
+
+/* FIXME FIXME change b_pad to number of bytes to skipp after reading */
+static int __AVI_GetDataInPES( input_thread_t *p_input,
+ pes_packet_t **pp_pes,
+ int i_size,
+ int b_pad )
+{
+
+ int i_read;
+ data_packet_t *p_data;
+
+
+ if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
+ {
+ return( 0 );
+ }
+
+
+ if( !i_size )
+ {
+ p_data = input_NewPacket( p_input->p_method_data, 0 );
+ (*pp_pes)->p_first = (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data = 1;
+ (*pp_pes)->i_pes_size = 0;
+ return( 0 );
+ }
+
+ if( ( i_size&1 )&&( b_pad ) )
+ {
+ b_pad = 1;
+ i_size++;
+ }
+ else
+ {
+ b_pad = 0;
+ }
+
+ do
+ {
+ i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size -
+ (*pp_pes)->i_pes_size, 1024 ) );
+ if( i_read < 0 )
+ {
+ return( (*pp_pes)->i_pes_size );
+ }
+ if( !(*pp_pes)->p_first )
+ {
+ (*pp_pes)->p_first =
+ (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data = 1;
+ (*pp_pes)->i_pes_size = i_read;
+ }
+ else
+ {
+ (*pp_pes)->p_last->p_next =
+ (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data++;
+ (*pp_pes)->i_pes_size += i_read;
+ }
+ } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
+
+ if( b_pad )
+ {
+ (*pp_pes)->i_pes_size--;
+ (*pp_pes)->p_last->p_payload_end--;
+ i_size--;
+ }
+
+ return( i_size );
+}
+
+static int __AVI_SeekAndGetChunk( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info )
+{
+ pes_packet_t *p_pes;
+ int i_length, i_ret;
+
+ i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length
+ - p_info->i_idxposb,
+ BUFFER_MAXSPESSIZE );
+
+ AVI_SeekAbsolute( p_input,
+ (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
+ p_info->i_idxposb + 8);
+
+ i_ret = __AVI_GetDataInPES( p_input, &p_pes, i_length , 0);
+
+ if( i_ret != i_length )
+ {
+ return( 0 );
+ }
+ /* TODO test key frame if i_idxposb == 0*/
+ AVI_PESBuffer_Add( p_input->p_method_data,
+ p_info,
+ p_pes,
+ p_info->i_idxposc,
+ p_info->i_idxposb );
+ return( 1 );
+}
+/* TODO check if it's correct (humm...) and optimisation ... */
+/* return 0 if we choose to get only the ck we want
+ * 1 if index is invalid
+ * 2 if there is a ck_other before ck_info and the last proced ck_info*/
+/* XXX XXX XXX avi file is some BIG shit, and sometime index give
+ * a refenrence to the same chunk BUT with a different size ( usually 0 )
+ */
+
+static inline int __AVI_GetChunkMethod( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ AVIStreamInfo_t *p_other )
+{
+ int i_info_pos;
+ int i_other_pos;
+
+ int i_info_pos_last;
+ int i_other_pos_last;
+
+ /*If we don't have a valid entry we need to parse from last
+ defined chunk and it's the only way that we return 1*/
+ if( p_info->i_idxposc >= p_info->i_idxnb )
+ {
+ return( 1 );
+ }
+
+ /* KNOW we have a valid entry for p_info */
+ /* we return 0 if we haven't an valid entry for p_other */
+ if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
+ {
+ return( 0 );
+ }
+
+ /* KNOW there are 2 streams with valid entry */
+
+ /* we return 0 if for one of the two streams we will not read
+ chunk-aligned */
+ if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
+ {
+ return( 0 );
+ }
+
+ /* KNOW we have a valid entry for the 2 streams
+ and for the 2 we want an aligned chunk (given by i_idxposc )*/
+ /* if in stream, the next chunk is back than the one we
+ have just read, it's useless to parse */
+ i_info_pos = p_info->p_index[p_info->i_idxposc].i_pos;
+ i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
+
+ i_info_pos_last = p_info->i_idxposc ?
+ p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
+ i_other_pos_last = p_other->i_idxposc ?
+ p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
+
+
+ if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
+ ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
+ {
+ return( 0 );
+ }
+
+ /* KNOW for the 2 streams, the ck we want are after the last read
+ or it's the first */
+
+ /* if the first ck_other we want isn't between ck_info_last
+ and ck_info, don't parse */
+ /* TODO fix this, use also number in buffered PES */
+ if( ( i_other_pos > i_info_pos) /* ck_other too far */
+ ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
+ {
+ return( 0 );
+ }
+
+ /* we Know we will find ck_other, and before ck_info
+ "if ck_info is too far" will be handle after */
+ return( 2 );
+}
+
+
+static inline int __AVI_ChooseSize( int l1, int l2 )
+{
+ /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
+ if( !l2 )
+ {
+ return( 0 );
+ }
+ return( !l1 ? l2 : __MIN( l1,l2 ) );
+}
+
+/* We know we will read chunk align */
+static int __AVI_GetAndPutChunkInBuffer( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ int i_size,
+ int i_ck )
+{
+
+ pes_packet_t *p_pes;
+ int i_length;
+
+ i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
+
+ /* Skip chunk header */
+
+ if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
+ {
+ return( 0 );
+ }
+ p_pes->p_first->p_payload_start += 8;
+ p_pes->i_pes_size -= 8;
+
+ i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
+
+ AVI_PESBuffer_Add( p_input->p_method_data,
+ p_info,
+ p_pes,
+ i_ck,
+ 0 );
+ /* skip unwanted bytes */
+ if( i_length != i_size)
+ {
+ msg_Err( p_input, "Chunk Size mismatch" );
+ AVI_SeekAbsolute( p_input,
+ __EVEN( AVI_TellAbsolute( p_input ) +
+ i_size - i_length ) );
+ }
+ return( 1 );
+}
+
+/* XXX Don't use this function directly ! XXX */
+static int __AVI_GetChunk( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ int b_load )
+{
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+ AVIStreamInfo_t *p_other;
+ int i_method;
+ off_t i_posmax;
+ int i;
+
+#define p_info_i p_avi_demux->pp_info[i]
+ while( p_info->p_pes_first )
+ {
+ if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc )
+ &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
+ &&( p_info->i_idxposb < p_info->p_pes_first->i_posb +
+ p_info->p_pes_first->p_pes->i_pes_size ) )
+
+ {
+ return( 1 ); /* we have it in buffer */
+ }
+ else
+ {
+ AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
+ }
+ }
+ /* up to now we handle only one audio and video streams at the same time */
+ p_other = (p_info == p_avi_demux->p_info_video ) ?
+ p_avi_demux->p_info_audio : p_avi_demux->p_info_video ;
+
+ i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
+
+ if( !i_method )
+ {
+ /* get directly the good chunk */
+ return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
+ }
+ /* We will parse
+ * because invalid index
+ * or will find ck_other before ck_info
+ */
+// msg_Warn( p_input, "method %d", i_method );
+ /* we will calculate the better position we have to reach */
+ if( i_method == 1 )
+ {
+ /* invalid index */
+ /* the position max we have already reached */
+ /* FIXME this isn't the better because sometime will fail to
+ put in buffer p_other since it could be too far */
+ AVIStreamInfo_t *p_info_max = p_info;
+
+ for( i = 0; i < p_avi_demux->i_streams; i++ )
+ {
+ if( p_info_i->i_idxnb )
+ {
+ if( p_info_max->i_idxnb )
+ {
+ if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
+ p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
+ {
+ p_info_max = p_info_i;
+ }
+ }
+ else
+ {
+ p_info_max = p_info_i;
+ }
+ }
+ }
+ if( p_info_max->i_idxnb )
+ {
+ /* be carefull that size between index and ck can sometime be
+ different without any error (and other time it's an error) */
+ i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos;
+ /* so choose this, and I know that we have already reach it */
+ }
+ else
+ {
+ i_posmax = p_avi_demux->p_movi->i_pos + 12;
+ }
+ }
+ else
+ {
+ if( !b_load )
+ {
+ return( 1 ); /* all is ok */
+ }
+ /* valid index */
+ /* we know that the entry and the last one are valid for the 2 stream */
+ /* and ck_other will come *before* index so go directly to it*/
+ i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
+ }
+
+ AVI_SeekAbsolute( p_input, i_posmax );
+ /* the first chunk we will see is :
+ * the last chunk that we have already seen for broken index
+ * the first ck for other with good index */
+ for( ; ; ) /* infinite parsing until the ck we want */
+ {
+ riffchunk_t *p_ck;
+ int i_type;
+
+ /* Get the actual chunk in the stream */
+ if( !(p_ck = RIFF_ReadChunk( p_input )) )
+ {
+ return( 0 );
+ }
+// msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size );
+ /* special case for LIST-rec chunk */
+ if( ( p_ck->i_id == FOURCC_LIST )&&( p_ck->i_type == FOURCC_rec ) )
+ {
+ RIFF_DescendChunk( p_input );
+ RIFF_DeleteChunk( p_input, p_ck );
+ continue;
+ }
+ AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
+ /* littles checks but not too much if you want to read all file */
+ if( i >= p_avi_demux->i_streams )
+ /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
+
+ {
+ RIFF_DeleteChunk( p_input, p_ck );
+ if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
+ {
+ return( 0 );
+ }
+ }
+ else
+ {
+ int i_size;
+
+ /* have we found a new entry (not present in index)? */
+ if( ( !p_info_i->i_idxnb )
+ ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
+ {
+ AVIIndexEntry_t index;
+
+ index.i_id = p_ck->i_id;
+ index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_fourcc,
+ (u8*)&p_ck->i_8bytes);
+ index.i_pos = p_ck->i_pos;
+ index.i_length = p_ck->i_size;
+ __AVI_AddEntryIndex( p_info_i, &index );
+ }
+
+
+ /* TODO check if p_other is full and then if is possible
+ go directly to the good chunk */
+ if( ( p_info_i == p_other )
+ &&( !AVI_PESBuffer_IsFull( p_other ) )
+ &&( ( !p_other->p_pes_last )||
+ ( p_other->p_pes_last->p_pes->i_pes_size !=
+ BUFFER_MAXSPESSIZE ) ) )
+ {
+ int i_ck = p_other->p_pes_last ?
+ p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
+ i_size = __AVI_ChooseSize( p_ck->i_size,
+ p_other->p_index[i_ck].i_length);
+
+ if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
+ {
+ if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other,
+ i_size, i_ck ) )
+ {
+ RIFF_DeleteChunk( p_input, p_ck );
+ return( 0 );
+ }
+ }
+ else
+ {
+ if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
+ {
+ RIFF_DeleteChunk( p_input, p_ck );
+
+ return( 0 );
+ }
+
+ }
+
+ RIFF_DeleteChunk( p_input, p_ck );
+ }
+ else
+ if( ( p_info_i == p_info)
+ &&( p_info->i_idxposc < p_info->i_idxnb ) )
+ {
+ /* the first ck_info is ok otherwise it should be
+ loaded without parsing */
+ i_size = __AVI_ChooseSize( p_ck->i_size,
+ p_info->p_index[p_info->i_idxposc].i_length);
+
+
+ RIFF_DeleteChunk( p_input, p_ck );
+
+ return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
+ p_info,
+ i_size,
+ p_info->i_idxposc ) : 1 );
+ }
+ else
+ {
+ /* skip it */
+ RIFF_DeleteChunk( p_input, p_ck );
+ if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
+ {
+ return( 0 );
+ }
+ }
+ }
+
+
+ }
+
+#undef p_info_i
+}
+
+/* be sure that i_ck will be a valid index entry */
+static int AVI_SetStreamChunk( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ int i_ck )
+{
+
+ p_info->i_idxposc = i_ck;
+ p_info->i_idxposb = 0;
+
+ if( i_ck < p_info->i_idxnb )
+ {
+ return( 1 );
+ }
+ else
+ {
+ p_info->i_idxposc = p_info->i_idxnb - 1;
+ do
+ {
+ p_info->i_idxposc++;
+ if( !__AVI_GetChunk( p_input, p_info, 0 ) )
+ {
+ return( 0 );
+ }
+ } while( p_info->i_idxposc < i_ck );
+
+ return( 1 );
+ }
+}
+
+
+/* XXX FIXME up to now, we assume that all chunk are one after one */
+static int AVI_SetStreamBytes( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ off_t i_byte )
+{
+ if( ( p_info->i_idxnb > 0 )
+ &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
+ p_info->p_index[p_info->i_idxnb - 1].i_length ) )
+ {
+ /* index is valid to find the ck */
+ /* uses dichototmie to be fast enougth */
+ int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
+ int i_idxmax = p_info->i_idxnb;
+ int i_idxmin = 0;
+ for( ;; )
+ {
+ if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
+ {
+ i_idxmax = i_idxposc ;
+ i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
+ }
+ else
+ {
+ if( p_info->p_index[i_idxposc].i_lengthtotal +
+ p_info->p_index[i_idxposc].i_length <= i_byte)
+ {
+ i_idxmin = i_idxposc ;
+ i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
+ }
+ else
+ {
+ p_info->i_idxposc = i_idxposc;
+ p_info->i_idxposb = i_byte -
+ p_info->p_index[i_idxposc].i_lengthtotal;
+ return( 1 );
+ }
+ }
+ }
+
+ }
+ else
+ {
+ p_info->i_idxposc = p_info->i_idxnb - 1;
+ p_info->i_idxposb = 0;
+ do
+ {
+ p_info->i_idxposc++;
+ if( !__AVI_GetChunk( p_input, p_info, 0 ) )
+ {
+ return( 0 );
+ }
+ } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
+ p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
+
+ p_info->i_idxposb = i_byte -
+ p_info->p_index[p_info->i_idxposc].i_lengthtotal;
+ return( 1 );
+ }
+}
+
+static pes_packet_t *AVI_ReadStreamChunkInPES( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info )
+
+{
+ if( p_info->i_idxposc > p_info->i_idxnb )
+ {
+ return( NULL );
+ }
+
+ /* we want chunk (p_info->i_idxposc,0) */
+ p_info->i_idxposb = 0;
+ if( !__AVI_GetChunk( p_input, p_info, 1) )
+ {
+ msg_Err( p_input, "Got one chunk : failed" );
+ return( NULL );
+ }
+ p_info->i_idxposc++;
+ return( AVI_PESBuffer_Get( p_info ) );
+}
+
+static pes_packet_t *AVI_ReadStreamBytesInPES( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ int i_byte )
+{
+ pes_packet_t *p_pes;
+ data_packet_t *p_data;
+ int i_count = 0;
+ int i_read;
+
+
+ if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
+ {
+ return( NULL );
+ }
+ if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
+ {
+ input_DeletePES( p_input->p_method_data, p_pes );
+ return( NULL );
+ }
+
+ p_pes->p_first =
+ p_pes->p_last = p_data;
+ p_pes->i_nb_data = 1;
+ p_pes->i_pes_size = i_byte;
+
+ while( i_byte > 0 )
+ {
+ if( !__AVI_GetChunk( p_input, p_info, 1) )
+ {
+ msg_Err( p_input, "Got one chunk : failed" );
+
+ input_DeletePES( p_input->p_method_data, p_pes );
+ return( NULL );
+ }
+
+ i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size -
+ ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
+ i_byte);
+ /* FIXME FIXME FIXME follow all data packet */
+ memcpy( p_data->p_payload_start + i_count,
+ p_info->p_pes_first->p_pes->p_first->p_payload_start +
+ p_info->i_idxposb - p_info->p_pes_first->i_posb,
+ i_read );
+
+ AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
+ i_byte -= i_read;
+ i_count += i_read;
+
+ p_info->i_idxposb += i_read;
+ if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
+ {
+ p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
+ p_info->i_idxposc++;
+ }
+ }
+ return( p_pes );
+}
+
+
+
+/* try to realign after a seek */
+static int AVI_ReAlign( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info )
+{
+ int i;
+ off_t i_pos;
+ int b_after = 0;
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+
+
+ for( i = 0; i < p_avi_demux->i_streams; i++ )
+ {
+ AVI_PESBuffer_Flush( p_input->p_method_data, p_avi_demux->pp_info[i] );
+ }
+ /* Reinit clock
+ TODO use input_ClockInit instead but need to be exported
+ p_input->stream.p_selected_program->last_cr = 0;
+ p_input->stream.p_selected_program->last_syscr = 0;
+ p_input->stream.p_selected_program->cr_ref = 0;
+ p_input->stream.p_selected_program->sysdate_ref = 0;
+ p_input->stream.p_selected_program->delta_cr = 0;
+ p_input->stream.p_selected_program->c_average_count = 0; */
+
+ i_pos = AVI_TellAbsolute( p_input );
+
+ p_info->i_idxposc--; /* in fact p_info->i_idxposc is for ck to be read */
+
+
+ if( ( p_info->i_idxposc <= 0)
+ ||( i_pos <= p_info->p_index[0].i_pos ) )
+ {
+ /* before beginning of stream */
+ return( p_info->header.i_samplesize ?
+ AVI_SetStreamBytes( p_input, p_info, 0 ) :
+ AVI_SetStreamChunk( p_input, p_info, 0 ) );
+ }
+
+ b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
+ /* now find in what chunk we are */
+ while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
+ &&( p_info->i_idxposc > 0 ) )
+ {
+ /* search before i_idxposc */
+
+ if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
+ {
+ return( 0 );
+ }
+ }
+
+ while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
+ p_info->p_index[p_info->i_idxposc].i_length + 8 )
+ {
+ /* search after i_idxposc */
+
+ if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
+ {
+ return( 0 );
+ }
+ }
+
+ /* search nearest key frame, only for video */
+ if( p_info->i_cat == VIDEO_ES )
+ {
+ if( b_after )
+ {
+ while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
+ {
+ if( !AVI_SetStreamChunk( p_input, p_info,
+ p_info->i_idxposc + 1 ) )
+ {
+ return( 0 );
+ }
+ }
+ }
+ else
+ {
+ while( ( p_info->i_idxposc > 0 ) &&
+ (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
+ {
+
+ if( !AVI_SetStreamChunk( p_input, p_info,
+ p_info->i_idxposc - 1 ) )
+ {
+
+ return( 0 );
+ }
+ }
+ }
+ }
+ return( 1 );
+}
+
+/* make difference between audio and video pts as little as possible */
+static void AVI_SynchroReInit( input_thread_t *p_input )
+{
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+
+#define p_info_video p_avi_demux->p_info_video
+#define p_info_audio p_avi_demux->p_info_audio
+ if( ( !p_info_audio )||( !p_info_video ) )
+ {
+ return;
+ }
+ /* now resynch audio video video */
+ /*don't care of AVIF_KEYFRAME */
+ if( !p_info_audio->header.i_samplesize )
+ {
+ AVI_SetStreamChunk( p_input,
+ p_info_audio,
+ AVI_PTSToChunk( p_info_audio,
+ AVI_GetPTS( p_info_video ) ) );
+ }
+ else
+ {
+ AVI_SetStreamBytes( p_input,
+ p_info_audio,
+ AVI_PTSToByte( p_info_audio,
+ AVI_GetPTS( p_info_video ) ) );
+ }
+#undef p_info_video
+#undef p_info_audio
+}
+
+/*****************************************************************************
+ * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
+ *****************************************************************************
+ * Handle multiple pes, and set pts to the good value
+ *****************************************************************************/
+static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ mtime_t i_dpts)
+{
+ int i;
+ pes_packet_t *p_pes = NULL;
+ pes_packet_t *p_pes_tmp = NULL;
+ pes_packet_t *p_pes_first = NULL;
+ mtime_t i_pts;
+
+ if( i_dpts < 1000 )
+ {
+ return( NULL ) ;
+ }
+
+ if( !p_info->header.i_samplesize )
+ {
+ int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
+ p_pes_first = NULL;
+ for( i = 0; i < i_chunk; i++ )
+ {
+ /* get pts while is valid */
+ i_pts = AVI_GetPTS( p_info );
+
+ p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
+
+ if( !p_pes_tmp )
+ {
+ return( p_pes_first );
+ }
+ p_pes_tmp->i_pts = i_pts;
+ if( !p_pes_first )
+ {
+ p_pes_first = p_pes_tmp;
+ }
+ else
+ {
+ p_pes->p_next = p_pes_tmp;
+ }
+ p_pes = p_pes_tmp;
+ }
+ return( p_pes_first );
+ }
+ else
+ {
+ /* stream is byte based */
+ int i_byte = AVI_PTSToByte( p_info, i_dpts);
+ if( i_byte < 50 ) /* to avoid some problem with audio */
+ {
+ return( NULL );
+ }
+ i_pts = AVI_GetPTS( p_info ); /* ok even with broken index */
+ p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
+
+ if( p_pes )
+ {
+ p_pes->i_pts = i_pts;
+ }
+ return( p_pes );
+ }
+}
+/*****************************************************************************
+ * AVI_DecodePES : send a pes to decoder
+ *****************************************************************************
+ * Handle multiple pes, and update pts to the good value
+ *****************************************************************************/
+static inline void AVI_DecodePES( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info,
+ pes_packet_t *p_pes )
+{
+ pes_packet_t *p_pes_next;
+ /* input_decode want only one pes, but AVI_GetFrameInPES give
+ multiple pes so send one by one */
+ while( p_pes )
+ {
+ p_pes_next = p_pes->p_next;
+ p_pes->p_next = NULL;
+ p_pes->i_pts = input_ClockGetTS( p_input,
+ p_input->stream.p_selected_program,
+ p_pes->i_pts * 9/100);
+ input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
+ p_pes = p_pes_next;
+ }
+
+}
+
+/*****************************************************************************
+ * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
+ *****************************************************************************
+ * Called by AVIDemux, that make common work
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int AVIDemux_Seekable( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info_master,
+ AVIStreamInfo_t *p_info_slave )
+{
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+
+ pes_packet_t *p_pes_master;
+ pes_packet_t *p_pes_slave;
+
+ /* check for signal from interface */
+ if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
+ {
+ /* we can supposed that is a seek */
+ /* first wait for empty buffer, arbitrary time */
+ msleep( DEFAULT_PTS_DELAY );
+ /* then try to realign in stream */
+ if( !AVI_ReAlign( p_input, p_info_master ) )
+ {
+ return( 0 ); /* assume EOF */
+ }
+ AVI_SynchroReInit( p_input );
+ }
+
+ /* take care of newly selected audio ES */
+ if( p_info_master->b_selected )
+ {
+ p_info_master->b_selected = 0;
+ AVI_SynchroReInit( p_input );
+ }
+ if( ( p_info_slave )&&( p_info_slave->b_selected ) )
+ {
+ p_info_slave->b_selected = 0;
+ AVI_SynchroReInit( p_input );
+ }
+
+ /* wait for the good time */
+ input_ClockManageRef( p_input,
+ p_input->stream.p_selected_program,
+ p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
+ /* calculate pcr, time when we must read the next data */
+ /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
+ if( p_info_slave )
+ {
+ p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
+ AVI_GetPTS( p_info_slave ) ) * 9/100;
+ }
+ else
+ {
+ p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
+ }
+
+ /* get video and audio frames */
+ p_pes_master = AVI_GetFrameInPES( p_input,
+ p_info_master,
+ 100000 ); /* 100 ms */
+ AVI_DecodePES( p_input,
+ p_info_master,
+ p_pes_master);
+
+
+ if( p_info_slave )
+ {
+ p_pes_slave = AVI_GetFrameInPES( p_input,
+ p_info_slave,
+ AVI_GetPTS( p_info_master ) -
+ AVI_GetPTS( p_info_slave) );
+ AVI_DecodePES( p_input,
+ p_info_slave,
+ p_pes_slave );
+ }
+
+
+ /* at the end ? */
+ return( p_pes_master ? 1 : 0 );
+
+}
+
+/*****************************************************************************
+ * AVIDemux_NotSeekable: reads and demuxes data packets for stream seekable
+ *****************************************************************************
+ * Called by AVIDemux, that makes common work
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+
+/* 0 if can be load/updated, 1 if skip, 2 if descend into, 3 if exit, 4 if error and need recover */
+static int __AVIDemux_ChunkAction( int i_streams_max,
+ riffchunk_t *p_ck )
+{
+ int i_stream;
+ int i_type;
+
+ AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
+ if( i_stream < i_streams_max )
+ {
+ return( 0 ); /* read and/or update stream info */
+ }
+
+ if( i_stream <= 99 )
+ {
+ /* should not happen but ... */
+ return( 1 );
+ }
+
+ /* now we know that it's not a stream */
+
+ switch( p_ck->i_id )
+ {
+ case( FOURCC_JUNK ):
+ return( 1 );
+ case( FOURCC_idx1 ):
+ return( 3 );
+ case( FOURCC_LIST ):
+ if( p_ck->i_type == FOURCC_rec )
+ {
+ return( 2 );
+ }
+ else
+ {
+ return( 1 );
+ }
+ default:
+ break;
+ }
+ /* test for ix?? */
+
+ if( ( p_ck->i_id & 0xFFFF ) == VLC_TWOCC( 'i','x' ) )
+ {
+ return( 1 );
+ }
+
+ return( 4 );
+}
+
+static int AVI_NotSeekableRecover( input_thread_t *p_input )
+{
+ byte_t *p_id;
+ u32 i_id;
+ int i_number, i_type;
+ data_packet_t *p_pack;
+
+ for( ; ; )
+ {
+ if( input_Peek( p_input, &p_id, 4 ) < 4 )
+ {
+ return( 0 ); /* Failed */
+ }
+ i_id = GetDWLE( p_id );
+ switch( i_id )
+ {
+ case( FOURCC_idx1 ):
+ case( FOURCC_JUNK ):
+ case( FOURCC_LIST ):
+ return( 1 );
+ default:
+ AVI_ParseStreamHeader( i_id, &i_number, &i_type );
+ if( i_number <= 99 )
+ {
+ switch( i_type )
+ {
+ case( TWOCC_wb ):
+ case( TWOCC_db ):
+ case( TWOCC_dc ):
+ case( TWOCC_pc ):
+ return( 1 );
+ }
+ }
+ else
+ {
+
+ }
+ }
+ /* Read 1 byte VERY unoptimised */
+ if( input_SplitBuffer( p_input, &p_pack, 1) < 1 )
+ {
+ return( 0 );
+ }
+ input_DeletePacket( p_input->p_method_data, p_pack);
+ }
+
+}
+
+static int AVIDemux_NotSeekable( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info_master,
+ AVIStreamInfo_t *p_info_slave )
+{
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+ int i_loop;
+ int i_stream;
+ int i_type;
+
+ riffchunk_t *p_ck;
+ pes_packet_t *p_pes;
+
+/*
+ i_filepos = AVI_TellAbsolute( p_input );
+ p_input->pf_seek( p_input, i_filepos );
+ input_AccessReinit( p_input );
+*/
+
+#define p_info p_avi_demux->pp_info[i_stream]
+
+ /* The managment is very basic, we will read packets, caclulate pts
+ and send it to decoder, synchro made on video, and audio is very less
+ important */
+
+ /* wait the good time */
+ input_ClockManageRef( p_input,
+ p_input->stream.p_selected_program,
+ p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
+ /* TODO be smart, seeing if we can wait for min( audio, video )
+ or there is a too big deep */
+ if( !p_info_slave )
+ {
+ p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
+ }
+ else
+ {
+ p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
+ AVI_GetPTS( p_info_slave ) ) * 9/100;
+ p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
+ }
+
+ for( i_loop = 0; i_loop < 10; i_loop++ )
+ {
+ int b_load =0;
+
+ /* first find a ck for master or slave */
+ do
+ {
+
+ if( !(p_ck = RIFF_ReadChunk( p_input ) ) )
+ {
+ msg_Err( p_input, "Badd" );
+ return( 0 ); /* assume EOF */
+ }
+ //msg_Err( p_input,"Looking ck: %4.4s %d",&p_ck->i_id, p_ck->i_size );
+
+ switch( __AVIDemux_ChunkAction( p_avi_demux->i_streams, p_ck ) )
+ {
+ case( 0 ): /* load it if possible */
+ b_load = 1;
+ break;
+ case( 1 ): /* skip it */
+ RIFF_DeleteChunk( p_input, p_ck );
+ if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
+ {
+ return( 0 );
+ }
+ b_load = 0;
+ break;
+ case( 2 ): /* descend into */
+ RIFF_DeleteChunk( p_input, p_ck );
+ RIFF_DescendChunk( p_input );
+ b_load = 0;
+ break;
+ case( 3 ): /* exit */
+ RIFF_DeleteChunk( p_input, p_ck );
+ return( 0 );
+ case( 4 ): /* Error */
+ RIFF_DeleteChunk( p_input, p_ck );
+ msg_Warn( p_input, "unknown chunk id 0x%8.8x, trying to recover", p_ck->i_id );
+ if( !AVI_NotSeekableRecover( p_input ) )
+ {
+ msg_Err( p_input, "cannot recover, dying" );
+ return( -1 );
+ }
+ else
+ {
+ msg_Warn( p_input, "recovered sucessfully" );
+ }
+ b_load = 0;
+ break;
+ }
+
+ } while( !b_load );
+
+ AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
+ /* now check if we really have to load it */
+ if( ( p_info != p_info_master )&&( p_info != p_info_slave ) )
+ {
+ b_load = 0;
+ }
+ else
+ {
+ if( p_info == p_info_master )
+ {
+ b_load = 1;
+ }
+ else
+ {
+ mtime_t i_dpts;
+ i_dpts = AVI_GetPTS( p_info_slave ) -
+ AVI_GetPTS( p_info_master );
+ if( i_dpts < 0 ) {i_dpts = - i_dpts; }
+ if( i_dpts < 600000 )
+ {
+ b_load = 1;
+ }
+ else
+ {
+ b_load = 0;
+ }
+ }
+
+ }
+
+ /* now do we can load this chunk ? */
+ if( b_load )
+ {
+
+ if( __AVI_GetDataInPES( p_input, &p_pes, p_ck->i_size + 8, 1) != p_ck->i_size + 8)
+ {
+ return( 0 );
+ }
+ p_pes->p_first->p_payload_start += 8;
+ p_pes->i_pes_size -= 8;
+ /* get PTS */
+ p_pes->i_pts = AVI_GetPTS( p_info );
+ AVI_DecodePES( p_input, p_info, p_pes );
+ }
+ else
+ {
+
+ if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
+ {
+ RIFF_DeleteChunk( p_input, p_ck );
+ return( 0 );
+ }
+ }
+
+ /* finaly update stream information */
+ if( p_info->header.i_samplesize )
+ {
+ p_info->i_idxposb += p_ck->i_size;
+ }
+ else
+ {
+ p_info->i_idxposc++;
+ }
+
+ RIFF_DeleteChunk( p_input, p_ck );
+ }
+
+ return( 1 );
+#undef p_info
+}
+/*****************************************************************************
+ * AVIDemux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ * TODO add support for unstreable file, just read a chunk and send it
+ * to the right decoder, very easy
+ *****************************************************************************/
+
+static int AVIDemux( input_thread_t *p_input )
+{
+ int i;
+ AVIStreamInfo_t *p_info_master;
+ AVIStreamInfo_t *p_info_slave;
+
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+
+ /* search new video and audio stream selected
+ if current have been unselected*/
+ if( ( !p_avi_demux->p_info_video )
+ || ( !p_avi_demux->p_info_video->p_es->p_decoder_fifo ) )
+ {
+ p_avi_demux->p_info_video = NULL;
+ for( i = 0; i < p_avi_demux->i_streams; i++ )
+ {
+ if( ( p_avi_demux->pp_info[i]->i_cat == VIDEO_ES )
+ &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
+ {
+ p_avi_demux->p_info_video = p_avi_demux->pp_info[i];
+ p_avi_demux->p_info_video->b_selected = 1;
+ break;
+ }
+ }
+ }
+ if( ( !p_avi_demux->p_info_audio )
+ ||( !p_avi_demux->p_info_audio->p_es->p_decoder_fifo ) )
+ {
+ p_avi_demux->p_info_audio = NULL;
+ for( i = 0; i < p_avi_demux->i_streams; i++ )
+ {
+ if( ( p_avi_demux->pp_info[i]->i_cat == AUDIO_ES )
+ &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
+ {
+ p_avi_demux->p_info_audio = p_avi_demux->pp_info[i];
+ p_avi_demux->p_info_audio->b_selected = 1;
+ break;
+ }
+ }
+ }
+ /* by default video is master for resync audio (after a seek .. ) */
+ if( p_avi_demux->p_info_video )
+ {
+ p_info_master = p_avi_demux->p_info_video;
+ p_info_slave = p_avi_demux->p_info_audio;
+ }
+ else
+ {
+ p_info_master = p_avi_demux->p_info_audio;
+ p_info_slave = NULL;
+ }
+
+ if( !p_info_master )
+ {
+ msg_Err( p_input, "no stream selected" );
+ return( -1 );
+ }
+
+ /* manage rate, if not default: skeep audio */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
+ {
+ if( p_avi_demux->p_info_audio)
+ {
+ p_avi_demux->p_info_audio->b_selected = 1;
+ }
+ p_avi_demux->i_rate = p_input->stream.control.i_rate;
+ }
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ p_avi_demux->i_rate = DEFAULT_RATE;
+ if( p_avi_demux->i_rate != DEFAULT_RATE )
+ {
+ p_info_slave = NULL;
+ }
+
+ if( p_avi_demux->b_seekable )
+ {
+ return( AVIDemux_Seekable( p_input,
+ p_info_master,
+ p_info_slave) );
+ }
+ else
+ {
+ return( AVIDemux_NotSeekable( p_input,
+ p_info_master,
+ p_info_slave ) );
+ }
+}
+
+
+
--- /dev/null
+/*****************************************************************************
+ * avi.h : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: avi.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#define MAX_PACKETS_IN_FIFO 2
+
+/* flags for use in <dwFlags> in AVIFileHdr */
+#define AVIF_HASINDEX 0x00000010 /* Index at end of file? */
+#define AVIF_MUSTUSEINDEX 0x00000020
+#define AVIF_ISINTERLEAVED 0x00000100
+#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames? */
+#define AVIF_WASCAPTUREFILE 0x00010000
+#define AVIF_COPYRIGHTED 0x00020000
+
+/* Flags for index */
+#define AVIIF_LIST 0x00000001L /* chunk is a 'LIST' */
+#define AVIIF_KEYFRAME 0x00000010L /* this frame is a key frame.*/
+#define AVIIF_NOTIME 0x00000100L /* this frame doesn't take any time */
+#define AVIIF_COMPUSE 0x0FFF0000L /* these bits are for compressor use */
+
+#define AVIIF_FIXKEYFRAME 0x00001000L /* invented; used to say that
+ the keyframe flag isn't a true flag
+ but have to be verified */
+
+/* AVI stuff */
+#define FOURCC_RIFF VLC_FOURCC('R','I','F','F')
+#define FOURCC_LIST VLC_FOURCC('L','I','S','T')
+#define FOURCC_JUNK VLC_FOURCC('J','U','N','K')
+#define FOURCC_AVI VLC_FOURCC('A','V','I',' ')
+#define FOURCC_WAVE VLC_FOURCC('W','A','V','E')
+
+#define FOURCC_avih VLC_FOURCC('a','v','i','h')
+#define FOURCC_hdrl VLC_FOURCC('h','d','r','l')
+#define FOURCC_movi VLC_FOURCC('m','o','v','i')
+#define FOURCC_idx1 VLC_FOURCC('i','d','x','1')
+
+#define FOURCC_strl VLC_FOURCC('s','t','r','l')
+#define FOURCC_strh VLC_FOURCC('s','t','r','h')
+#define FOURCC_strf VLC_FOURCC('s','t','r','f')
+#define FOURCC_strd VLC_FOURCC('s','t','r','d')
+
+#define FOURCC_rec VLC_FOURCC('r','e','c',' ')
+#define FOURCC_auds VLC_FOURCC('a','u','d','s')
+#define FOURCC_vids VLC_FOURCC('v','i','d','s')
+
+#define TWOCC_wb VLC_TWOCC('w','b')
+#define TWOCC_db VLC_TWOCC('d','b')
+#define TWOCC_dc VLC_TWOCC('d','c')
+#define TWOCC_pc VLC_TWOCC('p','c')
+
+/* MPEG4 video */
+#define FOURCC_DIVX VLC_FOURCC('D','I','V','X')
+#define FOURCC_divx VLC_FOURCC('d','i','v','x')
+#define FOURCC_DIV1 VLC_FOURCC('D','I','V','1')
+#define FOURCC_div1 VLC_FOURCC('d','i','v','1')
+#define FOURCC_MP4S VLC_FOURCC('M','P','4','S')
+#define FOURCC_mp4s VLC_FOURCC('m','p','4','s')
+#define FOURCC_M4S2 VLC_FOURCC('M','4','S','2')
+#define FOURCC_m4s2 VLC_FOURCC('m','4','s','2')
+#define FOURCC_xvid VLC_FOURCC('x','v','i','d')
+#define FOURCC_XVID VLC_FOURCC('X','V','I','D')
+#define FOURCC_XviD VLC_FOURCC('X','v','i','D')
+#define FOURCC_DX50 VLC_FOURCC('D','X','5','0')
+#define FOURCC_mp4v VLC_FOURCC('m','p','4','v')
+#define FOURCC_4 VLC_FOURCC( 4, 0, 0, 0 )
+
+/* MSMPEG4 v2 */
+#define FOURCC_MPG4 VLC_FOURCC('M','P','G','4')
+#define FOURCC_mpg4 VLC_FOURCC('m','p','g','4')
+#define FOURCC_DIV2 VLC_FOURCC('D','I','V','2')
+#define FOURCC_div2 VLC_FOURCC('d','i','v','2')
+#define FOURCC_MP42 VLC_FOURCC('M','P','4','2')
+#define FOURCC_mp42 VLC_FOURCC('m','p','4','2')
+
+/* MSMPEG4 v3 / M$ mpeg4 v3 */
+#define FOURCC_MPG3 VLC_FOURCC('M','P','G','3')
+#define FOURCC_mpg3 VLC_FOURCC('m','p','g','3')
+#define FOURCC_div3 VLC_FOURCC('d','i','v','3')
+#define FOURCC_MP43 VLC_FOURCC('M','P','4','3')
+#define FOURCC_mp43 VLC_FOURCC('m','p','4','3')
+
+/* DivX 3.20 */
+#define FOURCC_DIV3 VLC_FOURCC('D','I','V','3')
+#define FOURCC_DIV4 VLC_FOURCC('D','I','V','4')
+#define FOURCC_div4 VLC_FOURCC('d','i','v','4')
+#define FOURCC_DIV5 VLC_FOURCC('D','I','V','5')
+#define FOURCC_div5 VLC_FOURCC('d','i','v','5')
+#define FOURCC_DIV6 VLC_FOURCC('D','I','V','6')
+#define FOURCC_div6 VLC_FOURCC('d','i','v','6')
+
+/* AngelPotion stuff */
+#define FOURCC_AP41 VLC_FOURCC('A','P','4','1')
+
+/* ?? */
+#define FOURCC_3IV1 VLC_FOURCC('3','I','V','1')
+/* H263 and H263i */
+#define FOURCC_H263 VLC_FOURCC('H','2','6','3')
+#define FOURCC_h263 VLC_FOURCC('h','2','6','3')
+#define FOURCC_U263 VLC_FOURCC('U','2','6','3')
+#define FOURCC_I263 VLC_FOURCC('I','2','6','3')
+#define FOURCC_i263 VLC_FOURCC('i','2','6','3')
+
+/* Sound formats */
+#define WAVE_FORMAT_UNKNOWN 0x0000
+#define WAVE_FORMAT_PCM 0x0001
+#define WAVE_FORMAT_MPEG 0x0050
+#define WAVE_FORMAT_MPEGLAYER3 0x0055
+#define WAVE_FORMAT_A52 0x2000
+
+typedef struct bitmapinfoheader_s
+{
+ u32 i_size; /* size of header */
+ u32 i_width;
+ u32 i_height;
+ u16 i_planes;
+ u16 i_bitcount;
+ u32 i_compression;
+ u32 i_sizeimage;
+ u32 i_xpelspermeter;
+ u32 i_ypelspermeter;
+ u32 i_clrused;
+ u32 i_clrimportant;
+} bitmapinfoheader_t;
+
+typedef struct waveformatex_s
+{
+ u16 i_formattag;
+ u16 i_channels;
+ u32 i_samplespersec;
+ u32 i_avgbytespersec;
+ u16 i_blockalign;
+ u16 i_bitspersample;
+ u16 i_size; /* the extra size in bytes */
+} waveformatex_t;
+
+
+typedef struct MainAVIHeader_s
+{
+ u32 i_microsecperframe;
+ u32 i_maxbytespersec;
+ u32 i_reserved1; /* dwPaddingGranularity; pad to multiples of this
+ size; normally 2K */
+ u32 i_flags;
+ u32 i_totalframes;
+ u32 i_initialframes;
+ u32 i_streams;
+ u32 i_suggestedbuffersize;
+ u32 i_width;
+ u32 i_height;
+ u32 i_scale;
+ u32 i_rate;
+ u32 i_start;
+ u32 i_length;
+
+} MainAVIHeader_t;
+
+typedef struct AVIStreamHeader_s
+{
+ u32 i_type;
+ u32 i_handler;
+ u32 i_flags;
+ u32 i_reserved1; /* wPriority wLanguage */
+ u32 i_initialframes;
+ u32 i_scale;
+ u32 i_rate;
+ u32 i_start;
+ u32 i_length; /* In units above... */
+ u32 i_suggestedbuffersize;
+ u32 i_quality;
+ u32 i_samplesize;
+
+} AVIStreamHeader_t;
+
+typedef struct AVIIndexEntry_s
+{
+ u32 i_id;
+ u32 i_flags;
+ u32 i_pos;
+ u32 i_length;
+ u32 i_lengthtotal;
+} AVIIndexEntry_t;
+
+typedef struct AVIESBuffer_s
+{
+ struct AVIESBuffer_s *p_next;
+
+ pes_packet_t *p_pes;
+ int i_posc;
+ int i_posb;
+} AVIESBuffer_t;
+
+
+typedef struct AVIStreamInfo_s
+{
+
+ riffchunk_t *p_strl;
+ riffchunk_t *p_strh;
+ riffchunk_t *p_strf;
+ riffchunk_t *p_strd; /* not used */
+
+ AVIStreamHeader_t header;
+
+ u8 i_cat; /* AUDIO_ES, VIDEO_ES */
+ bitmapinfoheader_t video_format;
+ waveformatex_t audio_format;
+ es_descriptor_t *p_es;
+ int b_selected; /* newly selected */
+ AVIIndexEntry_t *p_index;
+ int i_idxnb;
+ int i_idxmax;
+
+ int i_idxposc; /* numero of chunk */
+ int i_idxposb; /* byte in the current chunk */
+
+ /* add some buffering */
+ AVIESBuffer_t *p_pes_first;
+ AVIESBuffer_t *p_pes_last;
+ int i_pes_count;
+ int i_pes_totalsize;
+} AVIStreamInfo_t;
+
+typedef struct demux_data_avi_file_s
+{
+ mtime_t i_pcr;
+ int i_rate;
+ riffchunk_t *p_riff;
+ riffchunk_t *p_hdrl;
+ riffchunk_t *p_movi;
+ riffchunk_t *p_idx1;
+
+ int b_seekable;
+
+ /* Info extrated from avih */
+ MainAVIHeader_t avih;
+
+ /* number of stream and informations*/
+ int i_streams;
+ AVIStreamInfo_t **pp_info;
+
+ /* current audio and video es */
+ AVIStreamInfo_t *p_info_video;
+ AVIStreamInfo_t *p_info_audio;
+
+} demux_data_avi_file_t;
+
--- /dev/null
+/*****************************************************************************
+ * libioRIFF.c : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: libioRIFF.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include "video.h"
+
+#include "libioRIFF.h"
+
+static inline u16 __GetWLE( byte_t *p_buff )
+{
+ return( (*p_buff) + ( *(p_buff+1) <<8 ) );
+}
+
+static inline u32 __GetDWLE( byte_t *p_buff )
+{
+ return( *(p_buff) + ( *(p_buff+1) <<8 ) +
+ ( *(p_buff+2) <<16 ) + ( *(p_buff+3) <<24 ) );
+}
+
+static inline u32 __EVEN( u32 i )
+{
+ return( (i & 1) ? ++i : i );
+}
+
+int __RIFF_TellPos( input_thread_t *p_input, u32 *pos )
+{
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ *pos= p_input->stream.p_selected_area->i_tell -
+ ( p_input->p_last_data - p_input->p_current_data );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ return 0;
+}
+
+int __RIFF_SkipBytes(input_thread_t * p_input,int nb)
+{
+ data_packet_t *p_pack;
+ int i;
+ int i_rest;
+ if( ( p_input->stream.b_seekable )&&( p_input->stream.i_method == INPUT_METHOD_FILE ) )
+ {
+ u32 i_pos;
+ __RIFF_TellPos( p_input, &i_pos);
+ p_input->pf_seek( p_input, (off_t)(i_pos + nb) );
+ input_AccessReinit( p_input );
+ }
+ else
+ {
+ msg_Warn( p_input, "cannot seek, it will take times" );
+ if( nb < 0 ) { return( -1 ); }
+ i_rest = nb;
+ while (i_rest != 0 )
+ {
+ if ( i_rest >= 4096 )
+ {
+ i = input_SplitBuffer( p_input, &p_pack, 4096);
+ }
+ else
+ {
+ i = input_SplitBuffer( p_input, &p_pack, i_rest);
+ }
+
+ if ( i < 0 ) { return ( -1 ); }
+ i_rest-=i;
+ input_DeletePacket( p_input->p_method_data, p_pack);
+ if( ( i == 0 )&&( i_rest != 0 )) { return( -1 ); }
+ }
+ }
+ return ( 0 );
+}
+
+
+void RIFF_DeleteChunk( input_thread_t *p_input, riffchunk_t *p_chunk )
+{
+ if( p_chunk != NULL)
+ {
+ if( p_chunk->p_data != NULL )
+ {
+ input_DeletePacket( p_input->p_method_data, p_chunk->p_data );
+ }
+ free( p_chunk );
+ }
+}
+
+riffchunk_t * RIFF_ReadChunk(input_thread_t * p_input)
+{
+ riffchunk_t * p_riff;
+ int count;
+ byte_t * p_peek;
+
+ if( !(p_riff = malloc( sizeof(riffchunk_t))) )
+ {
+ return( NULL );
+ }
+
+ p_riff->p_data = NULL;
+ /* peek to have the begining, 8+8 get i_8bytes */
+
+ if( ( count = input_Peek( p_input, &p_peek, 16 ) ) < 8 )
+ {
+ msg_Err( p_input, "cannot peek()" );
+ free(p_riff);
+ return( NULL );
+ }
+
+ p_riff->i_id = __GetDWLE( p_peek );
+ p_riff->i_size =__GetDWLE( p_peek + 4 );
+ p_riff->i_type = ( count >= 12 ) ? __GetDWLE( p_peek + 8 ) : 0 ;
+ memset( &p_riff->i_8bytes, 0, 8 );
+ if( count >= 12 )
+ {
+ memcpy( &p_riff->i_8bytes, p_peek + 8, count - 8 );
+ }
+ __RIFF_TellPos(p_input, &(p_riff->i_pos) );
+
+ return( p_riff );
+}
+
+/**************************************************
+ * Va au chunk juste d'apres si il en a encore *
+ * -1 si erreur , 1 si y'en a plus *
+ **************************************************/
+int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather)
+{
+ int i_len;
+ int i_lenfather;
+ riffchunk_t *p_riff;
+
+ if( ( p_riff = RIFF_ReadChunk( p_input ) ) == NULL )
+ {
+ msg_Err( p_input, "cannot read chunk" );
+ return( -1 );
+ }
+ i_len = __EVEN( p_riff->i_size );
+
+ if ( p_rifffather != NULL )
+ {
+ i_lenfather = __EVEN( p_rifffather->i_size );
+ if ( p_rifffather->i_pos + i_lenfather <= p_riff->i_pos + i_len + 8 )
+ {
+ msg_Err( p_input, "next chunk out of bounds" );
+ free( p_riff );
+ return( 1 ); /* pas dans nos frontiere */
+ }
+ }
+ if ( __RIFF_SkipBytes( p_input,i_len + 8 ) != 0 )
+ {
+ free( p_riff );
+ msg_Err( p_input, "cannot go to the next chunk" );
+ return( -1 );
+ }
+ free( p_riff );
+ return( 0 );
+}
+
+/****************************************************************
+ * Permet de rentrer dans un ck RIFF ou LIST *
+ ****************************************************************/
+int RIFF_DescendChunk(input_thread_t * p_input)
+{
+ return( __RIFF_SkipBytes(p_input,12) != 0 ? -1 : 0 );
+}
+
+/***************************************************************
+ * Permet de sortir d'un sous chunk et d'aller sur le suivant *
+ * chunk *
+ ***************************************************************/
+
+int RIFF_AscendChunk(input_thread_t * p_input ,riffchunk_t *p_riff)
+{
+ int i_skip;
+ u32 i_posactu;
+
+ __RIFF_TellPos(p_input, &i_posactu);
+ i_skip = __EVEN( p_riff->i_pos + p_riff->i_size + 8 ) - i_posactu;
+ return( (( __RIFF_SkipBytes(p_input,i_skip)) != 0) ? -1 : 0 );
+}
+
+/***************************************************************
+ * Permet de se deplacer jusqu'au premier chunk avec le bon id *
+ * *************************************************************/
+int RIFF_FindChunk(input_thread_t * p_input ,u32 i_id,riffchunk_t *p_rifffather)
+{
+ riffchunk_t *p_riff = NULL;
+ do
+ {
+ if ( p_riff )
+ {
+ free(p_riff);
+ if ( RIFF_NextChunk(p_input ,p_rifffather) != 0 )
+ {
+ return( -1 );
+ }
+ }
+ p_riff=RIFF_ReadChunk(p_input);
+ } while ( ( p_riff )&&( p_riff->i_id != i_id ) );
+
+ if ( ( !p_riff )||( p_riff->i_id != i_id ) )
+ {
+ return( -1 );
+ }
+ free( p_riff );
+ return( 0 );
+}
+
+/*****************************************************************
+ * Permet de pointer sur la zone de donné du chunk courant *
+ *****************************************************************/
+int RIFF_GoToChunkData(input_thread_t * p_input)
+{
+ return( ( __RIFF_SkipBytes(p_input,8) != 0 ) ? -1 : 0 );
+}
+
+int RIFF_LoadChunkData(input_thread_t * p_input,riffchunk_t *p_riff )
+{
+ off_t i_read = __EVEN( p_riff->i_size );
+
+ RIFF_GoToChunkData(p_input);
+ if ( input_SplitBuffer( p_input,
+ &p_riff->p_data,
+ i_read ) != i_read )
+ {
+ msg_Err( p_input, "cannot read enough data " );
+ return ( -1 );
+ }
+
+ if( p_riff->i_size&1 )
+ {
+ p_riff->p_data->p_payload_end--;
+ }
+ return( 0 );
+}
+
+int RIFF_LoadChunkDataInPES(input_thread_t * p_input,
+ pes_packet_t **pp_pes,
+ int i_size_index)
+{
+ u32 i_read;
+ data_packet_t *p_data;
+ riffchunk_t *p_riff;
+ int i_size;
+ int b_pad = 0;
+
+ if( (p_riff = RIFF_ReadChunk( p_input )) == NULL )
+ {
+ *pp_pes = NULL;
+ return( -1 );
+ }
+ RIFF_GoToChunkData(p_input);
+ *pp_pes = input_NewPES( p_input->p_method_data );
+
+ if( *pp_pes == NULL )
+ {
+ return( -1 );
+ }
+
+ if( (!p_riff->i_size) || (!i_size_index ) )
+ {
+ i_size = __MAX( i_size_index, p_riff->i_size );
+ }
+ else
+ {
+ i_size = __MIN( p_riff->i_size, i_size_index );
+ }
+
+ if( !p_riff->i_size )
+ {
+ p_data = input_NewPacket( p_input->p_method_data, 0 );
+ (*pp_pes)->p_first = p_data;
+ (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data = 1;
+ (*pp_pes)->i_pes_size = 0;
+ return( 0 );
+ }
+ if( i_size&1 )
+ {
+ i_size++;
+ b_pad = 1;
+ }
+
+ do
+ {
+ i_read = input_SplitBuffer(p_input, &p_data, i_size -
+ (*pp_pes)->i_pes_size );
+ if( i_read < 0 )
+ {
+ /* FIXME free on all packets */
+ return( -1 );
+ }
+ if( (*pp_pes)->p_first == NULL )
+ {
+ (*pp_pes)->p_first = p_data;
+ (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data = 1;
+ (*pp_pes)->i_pes_size = ( p_data->p_payload_end -
+ p_data->p_payload_start );
+ }
+ else
+ {
+ (*pp_pes)->p_last->p_next = p_data;
+ (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data++;
+ (*pp_pes)->i_pes_size += ( p_data->p_payload_end -
+ p_data->p_payload_start );
+ }
+ } while( ((*pp_pes)->i_pes_size < i_size)&&(i_read != 0) );
+
+ if( b_pad )
+ {
+ (*pp_pes)->i_pes_size--;
+ (*pp_pes)->p_last->p_payload_end--;
+ }
+ return( 0 );
+}
+
+int RIFF_GoToChunk(input_thread_t * p_input, riffchunk_t *p_riff)
+{
+ if( p_input->stream.b_seekable )
+ {
+ p_input->pf_seek( p_input, (off_t)p_riff->i_pos );
+ input_AccessReinit( p_input );
+ return( 0 );
+ }
+ return( -1 );
+}
+
+int RIFF_TestFileHeader( input_thread_t * p_input, riffchunk_t ** pp_riff, u32 i_type )
+{
+ if( !( *pp_riff = RIFF_ReadChunk( p_input ) ) )
+ {
+ return( -1 );
+ }
+ if( (*pp_riff)->i_id != VLC_FOURCC('R','I','F','F')
+ || (*pp_riff)->i_type != i_type )
+ {
+ free( *pp_riff );
+ return( -1 );
+ }
+ return( 0 );
+}
+
+
+int RIFF_FindAndLoadChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_fmt, u32 i_type )
+{
+ *pp_fmt = NULL;
+ if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
+ {
+ return( -1 );
+ }
+ if ( ( (*pp_fmt = RIFF_ReadChunk( p_input )) == NULL)
+ || ( RIFF_LoadChunkData( p_input, *pp_fmt ) != 0 ) )
+ {
+ if( *pp_fmt != NULL )
+ {
+ RIFF_DeleteChunk( p_input, *pp_fmt );
+ }
+ return( -1 );
+ }
+ return( 0 );
+}
+
+int RIFF_FindAndGotoDataChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_data, u32 i_type )
+{
+ *pp_data = NULL;
+ if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
+ {
+ return( -1 );
+ }
+ if ( ( *pp_data = RIFF_ReadChunk( p_input ) ) == NULL )
+ {
+ return( -1 );
+ }
+ if ( RIFF_GoToChunkData( p_input ) != 0 )
+ {
+ RIFF_DeleteChunk( p_input, *pp_data );
+ return( -1 );
+ }
+ return( 0 );
+}
+
+int RIFF_FindListChunk( input_thread_t *p_input, riffchunk_t **pp_riff, riffchunk_t *p_rifffather, u32 i_type )
+{
+ int i_ok;
+
+ *pp_riff = NULL;
+ i_ok = 0;
+ while( i_ok == 0 )
+ {
+ if( *pp_riff != NULL )
+ {
+ free( *pp_riff );
+ }
+ if( RIFF_FindChunk( p_input,
+ VLC_FOURCC('L','I','S','T'), p_rifffather ) != 0 )
+ {
+ return( -1 );
+ }
+ *pp_riff = RIFF_ReadChunk( p_input );
+
+ if( *pp_riff == NULL )
+ {
+ return( -1 );
+ }
+ if( (*pp_riff)->i_type != i_type )
+ {
+ if( RIFF_NextChunk( p_input, p_rifffather ) != 0 )
+ {
+ return( -1 );
+ }
+ }
+ else
+ {
+ i_ok = 1;
+ }
+ }
+ return( 0 );
+}
--- /dev/null
+/*****************************************************************************
+ * libioRIFF.h : AVI file Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: libioRIFF.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+typedef struct riffchunk_s
+{
+ u32 i_id;
+ u32 i_size;
+ u32 i_type;
+ u32 i_pos;
+ data_packet_t *p_data;
+ u64 i_8bytes; /* it's the first 8 bytes after header
+ used for key frame generation */
+} riffchunk_t;
+
+int __RIFF_TellPos( input_thread_t *p_input, u32 *pos );
+int __RIFF_SkipBytes(input_thread_t * p_input,int nb);
+void RIFF_DeleteChunk( input_thread_t *p_input, riffchunk_t *p_chunk );
+riffchunk_t *RIFF_ReadChunk(input_thread_t * p_input);
+int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather);
+int RIFF_DescendChunk(input_thread_t * p_input);
+int RIFF_AscendChunk(input_thread_t * p_input ,riffchunk_t *p_riff);
+int RIFF_FindChunk(input_thread_t * p_input,
+ u32 i_id,riffchunk_t *p_rifffather);
+int RIFF_GoToChunkData(input_thread_t * p_input);
+int RIFF_LoadChunkData(input_thread_t * p_input,
+ riffchunk_t *p_riff );
+int RIFF_LoadChunkDataInPES(input_thread_t * p_input,
+ pes_packet_t **pp_pes,
+ int i_size_index);
+
+int RIFF_GoToChunk(input_thread_t * p_input,
+ riffchunk_t *p_riff);
+int RIFF_TestFileHeader( input_thread_t * p_input,
+ riffchunk_t ** pp_riff,
+ u32 i_type );
+int RIFF_FindAndLoadChunk( input_thread_t * p_input,
+ riffchunk_t *p_riff,
+ riffchunk_t **pp_fmt,
+ u32 i_type );
+int RIFF_FindAndGotoDataChunk( input_thread_t * p_input,
+ riffchunk_t *p_riff,
+ riffchunk_t **pp_data,
+ u32 i_type );
+int RIFF_FindListChunk( input_thread_t *p_input,
+ riffchunk_t **pp_riff,
+ riffchunk_t *p_rifffather,
+ u32 i_type );
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+mp4_SOURCES = mp4.c libmp4.c
--- /dev/null
+/*****************************************************************************
+ * libmp4.c : LibMP4 library for mp4 module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: libmp4.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#include <errno.h>
+#include <sys/types.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include <zlib.h> /* for compressed moov */
+#include "libmp4.h"
+
+/*****************************************************************************
+ * Here are defined some macro to make life simpler but before using it
+ * *look* at the code.
+ *
+ * XXX: All macro are written in capital letters
+ *
+ *****************************************************************************/
+#define MP4_BOX_HEADERSIZE( p_box ) \
+ ( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 ) \
+ + ( p_box->i_type == FOURCC_uuid ? 16 : 0 ) )
+
+#define MP4_BOX_DESCEND( p_box ) \
+ MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) );
+
+#define MP4_GET1BYTE( dst ) \
+ dst = *p_peek; p_peek++; i_read--
+
+#define MP4_GET2BYTES( dst ) \
+ dst = GetWBE( p_peek ); p_peek += 2; i_read -= 2
+
+#define MP4_GET3BYTES( dst ) \
+ dst = Get24bBE( p_peek ); p_peek += 3; i_read -= 3
+
+#define MP4_GET4BYTES( dst ) \
+ dst = GetDWBE( p_peek ); p_peek += 4; i_read -= 4
+
+#define MP4_GETFOURCC( dst ) \
+ dst = GetDWLE( p_peek ); p_peek += 4; i_read -= 4
+
+#define MP4_GET8BYTES( dst ) \
+ dst = GetQWBE( p_peek ); p_peek += 8; i_read -= 8
+
+#define MP4_GETVERSIONFLAGS( p_void ) \
+ MP4_GET1BYTE( p_void->i_version ); \
+ MP4_GET3BYTES( p_void->i_flags )
+
+#define MP4_GETSTRINGZ( p_str ) \
+ if( ( i_read > 0 )&&(p_peek[0] ) ) \
+ { \
+ p_str = calloc( sizeof( char ), __MIN( strlen( p_peek ), i_read )+1);\
+ memcpy( p_str, p_peek, __MIN( strlen( p_peek ), i_read ) ); \
+ p_str[__MIN( strlen( p_peek ), i_read )] = 0; \
+ p_peek += strlen( p_str ) + 1; \
+ i_read -= strlen( p_str ) + 1; \
+ } \
+ else \
+ { \
+ p_str = NULL; \
+ }
+
+
+#define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
+ s64 i_read = p_box->i_size; \
+ u8 *p_peek, *p_buff; \
+ i_read = p_box->i_size; \
+ if( !( p_peek = p_buff = malloc( i_read ) ) ) \
+ { \
+ return( 0 ); \
+ } \
+ if( !MP4_ReadStream( p_stream, p_peek, i_read ) )\
+ { \
+ free( p_buff ); \
+ return( 0 ); \
+ } \
+ p_peek += MP4_BOX_HEADERSIZE( p_box ); \
+ i_read -= MP4_BOX_HEADERSIZE( p_box ); \
+ if( !( p_box->data.p_data = malloc( sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
+ { \
+ free( p_buff ); \
+ return( 0 ); \
+ }
+
+
+#define MP4_READBOX_EXIT( i_code ) \
+ if( !i_code ) \
+ free( p_buff ); \
+ if( i_read < 0 ) \
+ { \
+ msg_Warn( p_stream->p_input, "Not enougth data" ); \
+ } \
+ return( i_code )
+
+#define FREE( p ) \
+ if( p ) {free( p ); p = NULL; }
+
+
+
+/* Some assumptions:
+ * The input method HAVE to be seekable
+
+*/
+
+/* Some functions to manipulate memory */
+static u16 GetWLE( u8 *p_buff )
+{
+ return( (p_buff[0]) + ( p_buff[1] <<8 ) );
+}
+
+static u32 GetDWLE( u8 *p_buff )
+{
+ return( p_buff[0] + ( p_buff[1] <<8 ) +
+ ( p_buff[2] <<16 ) + ( p_buff[3] <<24 ) );
+}
+
+static u16 GetWBE( u8 *p_buff )
+{
+ return( (p_buff[0]<<8) + p_buff[1] );
+}
+
+static u32 Get24bBE( u8 *p_buff )
+{
+ return( ( p_buff[0] <<16 ) + ( p_buff[1] <<8 ) + p_buff[2] );
+}
+
+
+static u32 GetDWBE( u8 *p_buff )
+{
+ return( (p_buff[0] << 24) + ( p_buff[1] <<16 ) +
+ ( p_buff[2] <<8 ) + p_buff[3] );
+}
+
+static u64 GetQWBE( u8 *p_buff )
+{
+ return( ( (u64)GetDWBE( p_buff ) << 32 )|( (u64)GetDWBE( p_buff + 4 ) ) );
+}
+
+
+static void GetUUID( UUID_t *p_uuid, u8 *p_buff )
+{
+ memcpy( p_uuid,
+ p_buff,
+ 16 );
+}
+
+static void CreateUUID( UUID_t *p_uuid, u32 i_fourcc )
+{
+ /* made by 0xXXXXXXXX-0011-0010-8000-00aa00389b71
+ where XXXXXXXX is the fourcc */
+ /* FIXME implement this */
+}
+
+/* some functions for mp4 encoding of variables */
+
+void MP4_ConvertDate2Str( char *psz, u64 i_date )
+{
+ int i_day;
+ int i_hour;
+ int i_min;
+ int i_sec;
+
+ i_day = i_date / ( 60*60*24);
+ i_hour = ( i_date /( 60*60 ) ) % 60;
+ i_min = ( i_date / 60 ) % 60;
+ i_sec = i_date % 60;
+ /* FIXME do it correctly, date begin at 1 jan 1904 */
+ sprintf( psz, "%dd-%2.2dh:%2.2dm:%2.2ds",
+ i_day, i_hour, i_min, i_sec );
+}
+
+
+
+/*****************************************************************************
+ * Some basic functions to manipulate stream more easily in vlc
+ *
+ * MP4_TellAbsolute get file position
+ *
+ * MP4_SeekAbsolute seek in the file
+ *
+ * MP4_ReadData read data from the file in a buffer
+ *
+ *****************************************************************************/
+off_t MP4_TellAbsolute( input_thread_t *p_input )
+{
+ off_t i_pos;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ i_pos= p_input->stream.p_selected_area->i_tell -
+ ( p_input->p_last_data - p_input->p_current_data );
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( i_pos );
+}
+
+int MP4_SeekAbsolute( input_thread_t *p_input,
+ off_t i_pos)
+{
+ off_t i_filepos;
+
+ if( i_pos >= p_input->stream.p_selected_area->i_size )
+ {
+ return( 0 );
+ }
+
+ i_filepos = MP4_TellAbsolute( p_input );
+ if( i_pos != i_filepos )
+ {
+ p_input->pf_seek( p_input, i_pos );
+ input_AccessReinit( p_input );
+ }
+ return( 1 );
+}
+
+/* return 1 if success, 0 if fail */
+int MP4_ReadData( input_thread_t *p_input, u8 *p_buff, int i_size )
+{
+ data_packet_t *p_data;
+
+ int i_read;
+
+
+ if( !i_size )
+ {
+ return( 1 );
+ }
+
+ do
+ {
+ i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size, 1024 ) );
+ if( i_read <= 0 )
+ {
+ return( 0 );
+ }
+ memcpy( p_buff, p_data->p_payload_start, i_read );
+ input_DeletePacket( p_input->p_method_data, p_data );
+
+ p_buff += i_read;
+ i_size -= i_read;
+
+ } while( i_size );
+
+ return( 1 );
+}
+
+/*****************************************************************************
+ * Some basic functions to manipulate MP4_Stream_t, an abstraction o p_input
+ * in the way that you can read from a memory buffer or from an input
+ *
+ *****************************************************************************/
+
+/**** ------- First some function to make abstract from input -------- */
+
+/****************************************************************************
+ * MP4_InputStream create an stram with an input
+ *
+ ****************************************************************************/
+MP4_Stream_t *MP4_InputStream( input_thread_t *p_input )
+{
+ MP4_Stream_t *p_stream;
+
+ if( !( p_stream = malloc( sizeof( MP4_Stream_t ) ) ) )
+ {
+ return( NULL );
+ }
+ p_stream->b_memory = 0;
+ p_stream->p_input = p_input;
+ p_stream->i_start = 0;
+ p_stream->i_stop = 0;
+ p_stream->p_buffer = NULL;
+ return( p_stream );
+}
+
+
+/****************************************************************************
+ * MP4_MemoryStream create a memory stream
+ * if p_buffer == NULL, will allocate a buffer of i_size, else
+ * it uses p_buffer XXX you have to unallocate it yourself !
+ *
+ ****************************************************************************/
+MP4_Stream_t *MP4_MemoryStream( input_thread_t *p_input,
+ int i_size, u8 *p_buffer )
+{
+ MP4_Stream_t *p_stream;
+
+ if( !( p_stream = malloc( sizeof( MP4_Stream_t ) ) ) )
+ {
+ return( NULL );
+ }
+ p_stream->b_memory = 1;
+ p_stream->p_input = p_input;
+ p_stream->i_start = 0;
+ p_stream->i_stop = i_size;
+ if( !p_stream->p_buffer )
+ {
+ if( !( p_stream->p_buffer = malloc( i_size ) ) )
+ {
+ free( p_stream );
+ return( NULL );
+ }
+ }
+ else
+ {
+ p_stream->p_buffer = p_buffer;
+ }
+
+ return( p_stream );
+}
+/****************************************************************************
+ * MP4_ReadStream read from a MP4_Stream_t
+ *
+ ****************************************************************************/
+int MP4_ReadStream( MP4_Stream_t *p_stream, u8 *p_buff, int i_size )
+{
+ if( p_stream->b_memory )
+ {
+ if( i_size > p_stream->i_stop - p_stream->i_start )
+ {
+ return( 0 );
+ }
+ memcpy( p_buff,
+ p_stream->p_buffer + p_stream->i_start,
+ i_size );
+ p_stream->i_start += i_size;
+ return( 1 );
+ }
+ else
+ {
+ return( MP4_ReadData( p_stream->p_input, p_buff, i_size ) );
+ }
+}
+
+/****************************************************************************
+ * MP4_PeekStream peek from a MP4_Stream_t
+ *
+ ****************************************************************************/
+int MP4_PeekStream( MP4_Stream_t *p_stream, u8 **pp_peek, int i_size )
+{
+ if( p_stream->b_memory )
+ {
+ *pp_peek = p_stream->p_buffer + p_stream->i_start;
+
+ return( __MIN(i_size,p_stream->i_stop - p_stream->i_start ));
+ }
+ else
+ {
+ return( input_Peek( p_stream->p_input, pp_peek, i_size ) );
+ }
+}
+
+/****************************************************************************
+ * MP4_TellStream give absolute position in the stream
+ * XXX for a memory stream give position from begining of the buffer
+ ****************************************************************************/
+off_t MP4_TellStream( MP4_Stream_t *p_stream )
+{
+ if( p_stream->b_memory )
+ {
+ return( p_stream->i_start );
+ }
+ else
+ {
+ return( MP4_TellAbsolute( p_stream->p_input ) );
+ }
+}
+
+/****************************************************************************
+ * MP4_SeekStream seek in a MP4_Stream_t
+ *
+ ****************************************************************************/
+int MP4_SeekStream( MP4_Stream_t *p_stream, off_t i_pos)
+{
+ if( p_stream->b_memory )
+ {
+ if( i_pos < p_stream->i_stop )
+ {
+ p_stream->i_start = i_pos;
+ return( 1 );
+ }
+ else
+ {
+ return( 0 );
+ }
+ }
+ else
+ {
+ return( MP4_SeekAbsolute( p_stream->p_input, i_pos ) );
+ }
+}
+
+
+
+/*****************************************************************************
+ * MP4_ReadBoxCommon : Load only common parameters for all boxes
+ *****************************************************************************
+ * p_box need to be an already allocated MP4_Box_t, and all data
+ * will only be peek not read
+ *
+ * RETURN : 0 if it fail, 1 otherwise
+ *****************************************************************************/
+int MP4_ReadBoxCommon( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i_read;
+ u8 *p_peek;
+
+ if( ( ( i_read = MP4_PeekStream( p_stream, &p_peek, 32 ) ) < 8 ) )
+ {
+ return( 0 );
+ }
+ p_box->i_pos = MP4_TellStream( p_stream );
+
+ p_box->data.p_data = NULL;
+ p_box->p_father = NULL;
+ p_box->p_first = NULL;
+ p_box->p_last = NULL;
+ p_box->p_next = NULL;
+
+ MP4_GET4BYTES( p_box->i_shortsize );
+ MP4_GETFOURCC( p_box->i_type );
+
+ /* Now special case */
+
+ if( p_box->i_shortsize == 1 )
+ {
+ /* get the true size on 64 bits */
+ MP4_GET8BYTES( p_box->i_size );
+ }
+ else
+ {
+ p_box->i_size = p_box->i_shortsize;
+ /* XXX size of 0 means that the box extends to end of file */
+ }
+
+ if( p_box->i_type == FOURCC_uuid )
+ {
+ /* get extented type on 16 bytes */
+ GetUUID( &p_box->i_uuid, p_peek );
+ p_peek += 16; i_read -= 16;
+ }
+ else
+ {
+ CreateUUID( &p_box->i_uuid, p_box->i_type );
+ }
+#ifdef MP4_VERBOSE
+ /* FIXME how to write u64 ??? */
+ if( p_box->i_size )
+ {
+ msg_Dbg( p_stream->p_input, "Found Box: %c%c%c%c size %d",
+ (p_box->i_type)&0xff, (p_box->i_type>>8)&0xff,
+ (p_box->i_type>>16)&0xff, (p_box->i_type>>24)&0xff,
+ (u32)p_box->i_size );
+ }
+#endif
+
+ return( 1 );
+}
+
+
+/*****************************************************************************
+ * MP4_MP4_NextBox : Go to the next box
+ *****************************************************************************
+ * if p_box == NULL, go to the next box in witch we are( at the begining ).
+ *****************************************************************************/
+int MP4_NextBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_Box_t box;
+
+ if( !p_box )
+ {
+ MP4_ReadBoxCommon( p_stream, &box );
+ p_box = &box;
+ }
+
+ if( !p_box->i_size )
+ {
+ return( 2 ); /* Box with infinite size */
+ }
+
+ if( p_box->p_father )
+ {
+ /* check if it's within p-father */
+ if( p_box->i_size + p_box->i_pos >=
+ p_box->p_father->i_size + p_box->p_father->i_pos )
+ {
+ return( 0 ); /* out of bound */
+ }
+ }
+ return( MP4_SeekStream( p_stream, p_box->i_size + p_box->i_pos ) );
+}
+/*****************************************************************************
+ * MP4_MP4_GotoBox : Go to this particular box
+ *****************************************************************************
+ * RETURN : 0 if it fail, 1 otherwise
+ *****************************************************************************/
+int MP4_GotoBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ return( MP4_SeekStream( p_stream, p_box->i_pos ) );
+}
+
+
+/*****************************************************************************
+ * For all known box a loader is given,
+ * XXX: all common struct have to be already read by MP4_ReadBoxCommon
+ * after called one of theses functions, file position is unknown
+ * you need to call MP4_GotoBox to go where you want
+ *****************************************************************************/
+int MP4_ReadBoxContainerRaw( MP4_Stream_t *p_stream, MP4_Box_t *p_container )
+{
+ MP4_Box_t *p_box;
+
+ if( MP4_TellStream( p_stream ) + 8 >
+ p_container->i_pos + p_container->i_size )
+ {
+ /* there is no box to load */
+ return( 0 );
+ }
+
+ do
+ {
+ p_box = malloc( sizeof( MP4_Box_t ) );
+
+ if( MP4_ReadBox( p_stream, p_box , p_container ) )
+ {
+ /* chain this box with the father and the other at same level */
+ if( !p_container->p_first )
+ {
+ p_container->p_first = p_box;
+ }
+ else
+ {
+ p_container->p_last->p_next = p_box;
+ }
+ p_container->p_last = p_box;
+ }
+ else
+ {
+ /* free memory */
+ free( p_box );
+ break;
+ }
+
+ }while( MP4_NextBox( p_stream, p_box ) == 1 );
+
+ return( 1 );
+}
+
+
+int MP4_ReadBoxContainer( MP4_Stream_t *p_stream, MP4_Box_t *p_container )
+{
+
+ if( p_container->i_size <= MP4_BOX_HEADERSIZE(p_container ) + 8 )
+ {
+ /* container is empty, 8 stand for the first header in this box */
+ return( 1 );
+ }
+
+ /* enter box */
+ MP4_BOX_DESCEND( p_container );
+
+ return( MP4_ReadBoxContainerRaw( p_stream, p_container ) );
+}
+
+void MP4_FreeBox_Common( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ /* Up to now do nothing */
+}
+
+int MP4_ReadBoxSkip( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ /* Nothing to do */
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Skip box: \"%c%c%c%c\"",
+ (p_box->i_type)&0xff,
+ (p_box->i_type>>8)&0xff,
+ (p_box->i_type>>16)&0xff,
+ (p_box->i_type>>24)&0xff );
+#endif
+ return( 1 );
+}
+
+int MP4_ReadBox_ftyp( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_ftyp_t );
+
+ MP4_GETFOURCC( p_box->data.p_ftyp->i_major_brand );
+ MP4_GET4BYTES( p_box->data.p_ftyp->i_minor_version );
+
+ if( ( p_box->data.p_ftyp->i_compatible_brands_count = i_read / 4 ) )
+ {
+ int i;
+ p_box->data.p_ftyp->i_compatible_brands =
+ calloc( p_box->data.p_ftyp->i_compatible_brands_count, sizeof(u32));
+
+ for( i =0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
+ {
+ MP4_GETFOURCC( p_box->data.p_ftyp->i_compatible_brands[i] );
+ }
+ }
+ else
+ {
+ p_box->data.p_ftyp->i_compatible_brands = NULL;
+ }
+
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_ftyp( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_ftyp->i_compatible_brands );
+}
+
+
+int MP4_ReadBox_mvhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+#ifdef MP4_VERBOSE
+ char s_creation_time[128];
+ char s_modification_time[128];
+ char s_duration[128];
+#endif
+ MP4_READBOX_ENTER( MP4_Box_data_mvhd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
+
+ if( p_box->data.p_mvhd->i_version )
+ {
+ MP4_GET8BYTES( p_box->data.p_mvhd->i_creation_time );
+ MP4_GET8BYTES( p_box->data.p_mvhd->i_modification_time );
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
+ MP4_GET8BYTES( p_box->data.p_mvhd->i_duration );
+ }
+ else
+ {
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_creation_time );
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_modification_time );
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_duration );
+ }
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_rate );
+ MP4_GET2BYTES( p_box->data.p_mvhd->i_volume );
+ MP4_GET2BYTES( p_box->data.p_mvhd->i_reserved1 );
+
+
+ for( i = 0; i < 2; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_reserved2[i] );
+ }
+ for( i = 0; i < 9; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_matrix[i] );
+ }
+ for( i = 0; i < 6; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_predefined[i] );
+ }
+
+ MP4_GET4BYTES( p_box->data.p_mvhd->i_next_track_id );
+
+
+#ifdef MP4_VERBOSE
+ MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
+ MP4_ConvertDate2Str( s_modification_time,
+ p_box->data.p_mvhd->i_modification_time );
+ if( p_box->data.p_mvhd->i_rate )
+ {
+ MP4_ConvertDate2Str( s_duration,
+ p_box->data.p_mvhd->i_duration / p_box->data.p_mvhd->i_rate );
+ }
+ else
+ {
+ s_duration[0] = 0;
+ }
+ msg_Dbg( p_stream->p_input, "Read Box: \"mvhd\" creation %s modification %s time scale %d duration %s rate %f volume %f next track id %d",
+ s_creation_time,
+ s_modification_time,
+ (u32)p_box->data.p_mvhd->i_timescale,
+ s_duration,
+ (float)p_box->data.p_mvhd->i_rate / (1<<16 ),
+ (float)p_box->data.p_mvhd->i_volume / 256 ,
+ (u32)p_box->data.p_mvhd->i_next_track_id );
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+int MP4_ReadBox_tkhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+#ifdef MP4_VERBOSE
+ char s_creation_time[128];
+ char s_modification_time[128];
+ char s_duration[128];
+#endif
+ MP4_READBOX_ENTER( MP4_Box_data_tkhd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_tkhd );
+
+ if( p_box->data.p_tkhd->i_version )
+ {
+ MP4_GET8BYTES( p_box->data.p_tkhd->i_creation_time );
+ MP4_GET8BYTES( p_box->data.p_tkhd->i_modification_time );
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
+ MP4_GET8BYTES( p_box->data.p_tkhd->i_duration );
+ }
+ else
+ {
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_creation_time );
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_modification_time );
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_duration );
+ }
+
+ for( i = 0; i < 2; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved2[i] );
+ }
+ MP4_GET2BYTES( p_box->data.p_tkhd->i_layer );
+ MP4_GET2BYTES( p_box->data.p_tkhd->i_predefined );
+ MP4_GET2BYTES( p_box->data.p_tkhd->i_volume );
+ MP4_GET2BYTES( p_box->data.p_tkhd->i_reserved3 );
+
+ for( i = 0; i < 9; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_matrix[i] );
+ }
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_width );
+ MP4_GET4BYTES( p_box->data.p_tkhd->i_height );
+
+#ifdef MP4_VERBOSE
+ MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
+ MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mvhd->i_modification_time );
+ MP4_ConvertDate2Str( s_duration, p_box->data.p_mvhd->i_duration );
+
+ msg_Dbg( p_stream->p_input, "Read Box: \"tkhd\" creation %s modification %s duration %s track ID %d layer %d volume %f width %f height %f",
+ s_creation_time,
+ s_modification_time,
+ s_duration,
+ p_box->data.p_tkhd->i_track_ID,
+ p_box->data.p_tkhd->i_layer,
+ (float)p_box->data.p_tkhd->i_volume / 256 ,
+ (float)p_box->data.p_tkhd->i_width / 65536,
+ (float)p_box->data.p_tkhd->i_height / 65536 );
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+int MP4_ReadBox_tref( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+
+ if( p_box->i_size < MP4_BOX_HEADERSIZE(p_box ) + 8 )
+ {
+ /* container is empty, 8 stand for the first header in this box */
+ return( 1 );
+ }
+
+ if( !MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) ) )
+ {
+ return( 0 );
+ }
+
+ MP4_ReadBoxContainerRaw( p_stream, p_box );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"tref\" " );
+
+#endif
+ return( 1 );
+}
+
+
+
+int MP4_ReadBox_mdhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+ u16 i_language;
+#ifdef MP4_VERBOSE
+ char s_creation_time[128];
+ char s_modification_time[128];
+ char s_duration[128];
+#endif
+ MP4_READBOX_ENTER( MP4_Box_data_mdhd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_mdhd );
+
+ if( p_box->data.p_mdhd->i_version )
+ {
+ MP4_GET8BYTES( p_box->data.p_mdhd->i_creation_time );
+ MP4_GET8BYTES( p_box->data.p_mdhd->i_modification_time );
+ MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
+ MP4_GET8BYTES( p_box->data.p_mdhd->i_duration );
+ }
+ else
+ {
+ MP4_GET4BYTES( p_box->data.p_mdhd->i_creation_time );
+ MP4_GET4BYTES( p_box->data.p_mdhd->i_modification_time );
+ MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
+ MP4_GET4BYTES( p_box->data.p_mdhd->i_duration );
+ }
+ i_language = GetWBE( p_peek );
+ for( i = 0; i < 3; i++ )
+ {
+ p_box->data.p_mdhd->i_language[i] =
+ ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
+ }
+
+ MP4_GET2BYTES( p_box->data.p_mdhd->i_predefined );
+
+#ifdef MP4_VERBOSE
+ MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mdhd->i_creation_time );
+ MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mdhd->i_modification_time );
+ MP4_ConvertDate2Str( s_duration, p_box->data.p_mdhd->i_duration );
+ msg_Dbg( p_stream->p_input, "Read Box: \"mdhd\" creation %s modification %s time scale %d duration %s language %c%c%c",
+ s_creation_time,
+ s_modification_time,
+ (u32)p_box->data.p_mdhd->i_timescale,
+ s_duration,
+ p_box->data.p_mdhd->i_language[0],
+ p_box->data.p_mdhd->i_language[1],
+ p_box->data.p_mdhd->i_language[2] );
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+
+int MP4_ReadBox_hdlr( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_hdlr_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_hdlr );
+
+ MP4_GET4BYTES( p_box->data.p_hdlr->i_predefined );
+ MP4_GETFOURCC( p_box->data.p_hdlr->i_handler_type );
+
+ p_box->data.p_hdlr->psz_name = calloc( sizeof( char ), i_read + 1 );
+ memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_read );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"hdlr\" hanler type %c%c%c%c name %s",
+ ( p_box->data.p_hdlr->i_handler_type )&0xff,
+ ( p_box->data.p_hdlr->i_handler_type >> 8 )&0xff,
+ ( p_box->data.p_hdlr->i_handler_type >> 16 )&0xff,
+ ( p_box->data.p_hdlr->i_handler_type >> 24 )&0xff,
+ p_box->data.p_hdlr->psz_name );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_hdlr( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_hdlr->psz_name );
+}
+
+int MP4_ReadBox_vmhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_vmhd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_vmhd );
+
+ MP4_GET2BYTES( p_box->data.p_vmhd->i_graphics_mode );
+ for( i = 0; i < 3; i++ )
+ {
+ MP4_GET2BYTES( p_box->data.p_vmhd->i_opcolor[i] );
+ }
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"vmhd\" graphics-mode %d opcolor (%d, %d, %d)",
+ p_box->data.p_vmhd->i_graphics_mode,
+ p_box->data.p_vmhd->i_opcolor[0],
+ p_box->data.p_vmhd->i_opcolor[1],
+ p_box->data.p_vmhd->i_opcolor[2] );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+int MP4_ReadBox_smhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_smhd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_smhd );
+
+
+
+ MP4_GET2BYTES( p_box->data.p_smhd->i_balance );
+
+ MP4_GET2BYTES( p_box->data.p_smhd->i_reserved );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"smhd\" balance %f",
+ (float)p_box->data.p_smhd->i_balance / 256 );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+
+int MP4_ReadBox_hmhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_hmhd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_hmhd );
+
+ MP4_GET2BYTES( p_box->data.p_hmhd->i_max_PDU_size );
+ MP4_GET2BYTES( p_box->data.p_hmhd->i_avg_PDU_size );
+
+ MP4_GET4BYTES( p_box->data.p_hmhd->i_max_bitrate );
+ MP4_GET4BYTES( p_box->data.p_hmhd->i_avg_bitrate );
+
+ MP4_GET4BYTES( p_box->data.p_hmhd->i_reserved );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"hmhd\" maxPDU-size %d avgPDU-size %d max-bitrate %d avg-bitrate %d",
+ p_box->data.p_hmhd->i_max_PDU_size,
+ p_box->data.p_hmhd->i_avg_PDU_size,
+ p_box->data.p_hmhd->i_max_bitrate,
+ p_box->data.p_hmhd->i_avg_bitrate );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+int MP4_ReadBox_url( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_url_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_url );
+ MP4_GETSTRINGZ( p_box->data.p_url->psz_location );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"url\" url: %s",
+ p_box->data.p_url->psz_location );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+
+void MP4_FreeBox_url( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_url->psz_location )
+}
+
+int MP4_ReadBox_urn( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_urn_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_urn );
+
+ MP4_GETSTRINGZ( p_box->data.p_urn->psz_name );
+ MP4_GETSTRINGZ( p_box->data.p_urn->psz_location );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"urn\" name %s location %s",
+ p_box->data.p_urn->psz_name,
+ p_box->data.p_urn->psz_location );
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+void MP4_FreeBox_urn( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_urn->psz_name );
+ FREE( p_box->data.p_urn->psz_location );
+}
+
+
+int MP4_ReadBox_dref( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_dref_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_dref );
+
+ MP4_GET4BYTES( p_box->data.p_dref->i_entry_count );
+
+ MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
+ MP4_ReadBoxContainerRaw( p_stream, p_box );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"dref\" entry-count %d",
+ p_box->data.p_dref->i_entry_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+
+int MP4_ReadBox_stts( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+ MP4_READBOX_ENTER( MP4_Box_data_stts_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_stts );
+ MP4_GET4BYTES( p_box->data.p_stts->i_entry_count );
+
+ p_box->data.p_stts->i_sample_count =
+ calloc( sizeof( u32 ), p_box->data.p_stts->i_entry_count );
+ p_box->data.p_stts->i_sample_delta =
+ calloc( sizeof( u32 ), p_box->data.p_stts->i_entry_count );
+
+ for( i = 0; (i < p_box->data.p_stts->i_entry_count )&&( i_read >=8 ); i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_stts->i_sample_count[i] );
+ MP4_GET4BYTES( p_box->data.p_stts->i_sample_delta[i] );
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stts\" entry-count %d",
+ p_box->data.p_stts->i_entry_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_stts( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_stts->i_sample_count );
+ FREE( p_box->data.p_stts->i_sample_delta );
+
+}
+
+int MP4_ReadBox_ctts( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+ MP4_READBOX_ENTER( MP4_Box_data_ctts_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_ctts );
+
+ MP4_GET4BYTES( p_box->data.p_ctts->i_entry_count );
+
+ p_box->data.p_ctts->i_sample_count =
+ calloc( sizeof( u32 ), p_box->data.p_ctts->i_entry_count );
+ p_box->data.p_ctts->i_sample_offset =
+ calloc( sizeof( u32 ), p_box->data.p_ctts->i_entry_count );
+
+ for( i = 0; (i < p_box->data.p_ctts->i_entry_count )&&( i_read >=8 ); i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_ctts->i_sample_count[i] );
+ MP4_GET4BYTES( p_box->data.p_ctts->i_sample_offset[i] );
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"ctts\" entry-count %d",
+ p_box->data.p_ctts->i_entry_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_ctts( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_ctts->i_sample_count );
+ FREE( p_box->data.p_ctts->i_sample_offset );
+}
+
+static int MP4_ReadLengthDescriptor( u8 **pp_peek, s64 *i_read )
+{
+ int i_b;
+ int i_len = 0;
+ do
+ {
+ i_b = **pp_peek;
+
+ (*pp_peek)++;
+ (*i_read)--;
+ i_len = ( i_len << 7 ) + ( i_b&0x7f );
+ } while( i_b&0x80 );
+ return( i_len );
+}
+
+int MP4_ReadBox_esds( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+#define es_descriptor p_box->data.p_esds->es_descriptor
+ int i_len;
+ int i_flags;
+ int i_type;
+
+ MP4_READBOX_ENTER( MP4_Box_data_esds_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_esds );
+
+
+ MP4_GET1BYTE( i_type );
+ if( i_type == 0x03 ) /* MP4ESDescrTag */
+ {
+ i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
+
+ MP4_GET2BYTES( es_descriptor.i_ES_ID );
+ MP4_GET1BYTE( i_flags );
+ es_descriptor.b_stream_dependence = ( (i_flags&0x80) != 0);
+ es_descriptor.b_url = ( (i_flags&0x40) != 0);
+ es_descriptor.b_OCRstream = ( (i_flags&0x20) != 0);
+
+ es_descriptor.i_stream_priority = i_flags&0x1f;
+ if( es_descriptor.b_stream_dependence )
+ {
+ MP4_GET2BYTES( es_descriptor.i_depend_on_ES_ID );
+ }
+ if( es_descriptor.b_url )
+ {
+ int i_len;
+
+ MP4_GET1BYTE( i_len );
+ es_descriptor.psz_URL = calloc( sizeof(char), i_len + 1 );
+ memcpy( es_descriptor.psz_URL, p_peek, i_len );
+ es_descriptor.psz_URL[i_len] = 0;
+ p_peek += i_len;
+ i_read -= i_len;
+ }
+ else
+ {
+ es_descriptor.psz_URL = NULL;
+ }
+ if( es_descriptor.b_OCRstream )
+ {
+ MP4_GET2BYTES( es_descriptor.i_OCR_ES_ID );
+ }
+ MP4_GET1BYTE( i_type ); /* get next type */
+ }
+
+ if( i_type != 0x04)/* MP4DecConfigDescrTag */
+ {
+ MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */
+ }
+
+ i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
+ es_descriptor.p_decConfigDescr =
+ malloc( sizeof( MP4_descriptor_decoder_config_t ));
+
+ MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication );
+ MP4_GET1BYTE( i_flags );
+ es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2;
+ es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01;
+ MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB );
+ MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate );
+ MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate );
+ MP4_GET1BYTE( i_type );
+ if( i_type != 0x05 )/* MP4DecSpecificDescrTag */
+ {
+ MP4_READBOX_EXIT( 1 );
+ }
+
+ i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
+ es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
+ es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
+ memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
+ p_peek, i_len );
+
+ MP4_READBOX_EXIT( 1 );
+
+#undef es_descriptor
+}
+
+void MP4_FreeBox_esds( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_esds->es_descriptor.psz_URL );
+ FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
+}
+
+int MP4_ReadBox_sample_soun( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t );
+
+ for( i = 0; i < 6 ; i++ )
+ {
+ MP4_GET1BYTE( p_box->data.p_sample_soun->i_reserved1[i] );
+ }
+
+ MP4_GET2BYTES( p_box->data.p_sample_soun->i_data_reference_index );
+
+ for( i = 0; i < 2 ; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_sample_soun->i_reserved2[i] );
+ }
+
+ MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount );
+ MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize );
+ MP4_GET2BYTES( p_box->data.p_sample_soun->i_predefined );
+ MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 );
+ MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
+ MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
+
+ MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 );
+ MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"soun\" in stsd channel %d sample size %d sampl rate %f",
+ p_box->data.p_sample_soun->i_channelcount,
+ p_box->data.p_sample_soun->i_samplesize,
+ (float)p_box->data.p_sample_soun->i_sampleratehi +
+ (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+#if 0
+int MP4_ReadBox_sample_mp4a( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_sample_mp4a_t );
+
+ for( i = 0; i < 6 ; i++ )
+ {
+ MP4_GET1BYTE( p_box->data.p_sample_mp4a->i_reserved1[i] );
+ }
+
+ MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_data_reference_index );
+
+ for( i = 0; i < 2 ; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_sample_mp4a->i_reserved2[i] );
+ }
+
+ MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_channelcount );
+ MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_samplesize );
+ MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_predefined );
+ MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_reserved3 );
+ MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_sampleratehi );
+ MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_sampleratelo );
+
+ MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 );
+ MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"mp4a\" in stsd channel %d sample size %d sampl rate %f",
+ p_box->data.p_sample_mp4a->i_channelcount,
+ p_box->data.p_sample_mp4a->i_samplesize,
+ (float)p_box->data.p_sample_mp4a->i_sampleratehi +
+ (float)p_box->data.p_sample_mp4a->i_sampleratelo / 65536 );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+#endif
+
+int MP4_ReadBox_sample_vide( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
+
+ for( i = 0; i < 6 ; i++ )
+ {
+ MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] );
+ }
+
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index );
+
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined1 );
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_reserved2 );
+
+ for( i = 0; i < 3 ; i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_sample_vide->i_predefined2[i] );
+ }
+
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
+
+ MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
+ MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
+
+ MP4_GET4BYTES( p_box->data.p_sample_vide->i_reserved3 );
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined3 );
+
+ memcpy( &p_box->data.p_sample_vide->i_compressorname, p_peek, 32 );
+ p_peek += 32; i_read -= 32;
+
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
+ MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined4 );
+
+ MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
+ MP4_ReadBoxContainerRaw( p_stream, p_box );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"vide\" in stsd %dx%d depth %d",
+ p_box->data.p_sample_vide->i_width,
+ p_box->data.p_sample_vide->i_height,
+ p_box->data.p_sample_vide->i_depth );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+
+int MP4_ReadBox_stsd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+
+ MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
+
+ MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
+
+ MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
+
+ MP4_ReadBoxContainerRaw( p_stream, p_box );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stsd\" entry-count %d",
+ p_box->data.p_stsd->i_entry_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+
+int MP4_ReadBox_stsz( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
+
+ MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
+
+ MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
+
+ p_box->data.p_stsz->i_entry_size =
+ calloc( sizeof( u32 ), p_box->data.p_stsz->i_sample_count );
+
+ if( !p_box->data.p_stsz->i_sample_size )
+ {
+ for( i=0; (i<p_box->data.p_stsz->i_sample_count)&&(i_read >= 4 ); i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
+ }
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stsz\" sample-size %d sample-count %d",
+ p_box->data.p_stsz->i_sample_size,
+ p_box->data.p_stsz->i_sample_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_stsz( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_stsz->i_entry_size );
+}
+
+int MP4_ReadBox_stsc( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
+
+ MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
+
+ p_box->data.p_stsc->i_first_chunk =
+ calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
+ p_box->data.p_stsc->i_samples_per_chunk =
+ calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
+ p_box->data.p_stsc->i_sample_description_index =
+ calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
+
+ for( i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
+ {
+ MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
+ MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
+ MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stsc\" entry-count %d",
+ p_box->data.p_stsc->i_entry_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_stsc( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_stsc->i_first_chunk );
+ FREE( p_box->data.p_stsc->i_samples_per_chunk );
+ FREE( p_box->data.p_stsc->i_sample_description_index );
+}
+
+int MP4_ReadBox_stco_co64( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_co64_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
+
+ MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
+
+ p_box->data.p_co64->i_chunk_offset =
+ calloc( sizeof( u64 ), p_box->data.p_co64->i_entry_count );
+
+ for( i = 0; (i < p_box->data.p_co64->i_entry_count )&&( i_read >= 8 ); i++ )
+ {
+ if( p_box->i_type == FOURCC_stco )
+ {
+ MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
+ }
+ else
+ {
+ MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
+ }
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"co64\" entry-count %d",
+ p_box->data.p_co64->i_entry_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_stco_co64( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_co64->i_chunk_offset );
+}
+
+int MP4_ReadBox_stss( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_stss_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_stss );
+
+ MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
+
+ p_box->data.p_stss->i_sample_number =
+ calloc( sizeof( u32 ), p_box->data.p_stss->i_entry_count );
+
+ for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
+ {
+
+ MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stss\" entry-count %d",
+ p_box->data.p_stss->i_entry_count );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_stss( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_stss->i_sample_number )
+}
+
+int MP4_ReadBox_stsh( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
+
+
+ MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
+
+ p_box->data.p_stsh->i_shadowed_sample_number =
+ calloc( sizeof( u32 ), p_box->data.p_stsh->i_entry_count );
+
+ p_box->data.p_stsh->i_sync_sample_number =
+ calloc( sizeof( u32 ), p_box->data.p_stsh->i_entry_count );
+
+
+ for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
+ {
+
+ MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
+ MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stsh\" entry-count %d",
+ p_box->data.p_stsh->i_entry_count );
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_stsh( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_stsh->i_shadowed_sample_number )
+ FREE( p_box->data.p_stsh->i_sync_sample_number )
+}
+
+
+int MP4_ReadBox_stdp( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_stdp_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
+
+ p_box->data.p_stdp->i_priority =
+ calloc( sizeof( u16 ), i_read / 2 );
+
+ for( i = 0; i < i_read / 2 ; i++ )
+ {
+
+ MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count %d",
+ i_read / 2 );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_stdp( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_stdp->i_priority )
+}
+
+int MP4_ReadBox_padb( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_padb_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_padb );
+
+
+ MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
+
+ p_box->data.p_padb->i_reserved1 =
+ calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+ p_box->data.p_padb->i_pad2 =
+ calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+ p_box->data.p_padb->i_reserved2 =
+ calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+ p_box->data.p_padb->i_pad1 =
+ calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+
+
+ for( i = 0; i < i_read / 2 ; i++ )
+ {
+ p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
+ p_box->data.p_padb->i_pad2[i] = ( (*p_peek) >> 4 )&0x07;
+ p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 3 )&0x01;
+ p_box->data.p_padb->i_pad1[i] = ( (*p_peek) )&0x07;
+
+ p_peek += 1; i_read -= 1;
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count %d",
+ i_read / 2 );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_padb( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_padb->i_reserved1 );
+ FREE( p_box->data.p_padb->i_pad2 );
+ FREE( p_box->data.p_padb->i_reserved2 );
+ FREE( p_box->data.p_padb->i_pad1 );
+}
+
+int MP4_ReadBox_elst( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_padb_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_elst );
+
+
+ MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
+
+ p_box->data.p_elst->i_segment_duration =
+ calloc( sizeof( u64 ), p_box->data.p_elst->i_entry_count );
+ p_box->data.p_elst->i_media_time =
+ calloc( sizeof( u64 ), p_box->data.p_elst->i_entry_count );
+ p_box->data.p_elst->i_media_rate_integer =
+ calloc( sizeof( u16 ), p_box->data.p_elst->i_entry_count );
+ p_box->data.p_elst->i_media_rate_fraction=
+ calloc( sizeof( u16 ), p_box->data.p_elst->i_entry_count );
+
+
+ for( i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
+ {
+ if( p_box->data.p_elst->i_version == 1 )
+ {
+
+ MP4_GET8BYTES( p_box->data.p_elst->i_segment_duration[i] );
+
+ MP4_GET8BYTES( p_box->data.p_elst->i_media_time[i] );
+ }
+ else
+ {
+
+ MP4_GET4BYTES( p_box->data.p_elst->i_segment_duration[i] );
+
+ MP4_GET4BYTES( p_box->data.p_elst->i_media_time[i] );
+ }
+
+ MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
+ MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
+ }
+
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"elst\" entry-count %d",
+ i_read / 2 );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_elst( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_elst->i_segment_duration );
+ FREE( p_box->data.p_elst->i_media_time );
+ FREE( p_box->data.p_elst->i_media_rate_integer );
+ FREE( p_box->data.p_elst->i_media_rate_fraction );
+}
+
+int MP4_ReadBox_cprt( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ int i_language;
+ int i;
+
+ MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
+
+ MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
+
+ i_language = GetWBE( p_peek );
+ for( i = 0; i < 3; i++ )
+ {
+ p_box->data.p_cprt->i_language[i] =
+ ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
+ }
+ p_peek += 2; i_read -= 2;
+ MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"cprt\" language %c%c%c notice %s",
+ p_box->data.p_cprt->i_language[0],
+ p_box->data.p_cprt->i_language[1],
+ p_box->data.p_cprt->i_language[2],
+ p_box->data.p_cprt->psz_notice );
+
+#endif
+ MP4_READBOX_EXIT( 1 );
+}
+
+void MP4_FreeBox_cprt( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_cprt->psz_notice );
+}
+
+
+int MP4_ReadBox_dcom( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_dcom_t );
+
+ MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input,
+ "Read Box: \"dcom\" compression algorithm : %c%c%c%c",
+ ( p_box->data.p_dcom->i_algorithm )&0xff,
+ ( p_box->data.p_dcom->i_algorithm >> 8 )&0xff,
+ ( p_box->data.p_dcom->i_algorithm >> 16 )&0xff,
+ ( p_box->data.p_dcom->i_algorithm >> 24 )&0xff );
+#endif
+
+ MP4_READBOX_EXIT( 1 );
+}
+
+int MP4_ReadBox_cmvd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_cmvd_t );
+
+
+ MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
+
+ p_box->data.p_cmvd->i_compressed_size = i_read;
+
+ if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
+ {
+ msg_Dbg( p_stream->p_input, "Read Box: \"cmvd\" not enough memory to load data" );
+ return( 1 );
+ }
+
+ /* now copy compressed data */
+ memcpy( p_box->data.p_cmvd->p_data,
+ p_peek,
+ i_read);
+
+ p_box->data.p_cmvd->b_compressed = 1;
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input, "Read Box: \"cmvd\" compressed data size %d",
+ p_box->data.p_cmvd->i_compressed_size );
+#endif
+
+ MP4_READBOX_EXIT( 1 );
+}
+void MP4_FreeBox_cmvd( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ FREE( p_box->data.p_cmvd->p_data );
+}
+
+int MP4_ReadBox_cmov( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_Stream_t *p_stream_memory;
+ MP4_Box_t *p_umov;
+
+ MP4_Box_t *p_dcom;
+ MP4_Box_t *p_cmvd;
+ z_stream z_data;
+ u8 *p_data;
+
+ int i_result;
+
+ if( !( p_box->data.p_cmov = malloc( sizeof( MP4_Box_data_cmov_t ) ) ) )
+ {
+ msg_Err( p_stream->p_input, "out of memory" );
+ return( 0 );
+ }
+ memset( p_box->data.p_cmov, 0, sizeof( MP4_Box_data_cmov_t ) );
+
+ if( !( p_box->p_father )||
+ ( p_box->p_father->i_type != FOURCC_moov ) )
+ {
+ msg_Warn( p_stream->p_input, "Read box: \"cmov\" box alone" );
+ return( 1 );
+ }
+
+ if( !(i_result = MP4_ReadBoxContainer( p_stream, p_box ) ) )
+ {
+ return( 0 );
+ }
+
+ if( !( p_dcom = MP4_FindBox( p_box, FOURCC_dcom ) )||
+ !( p_cmvd = MP4_FindBox( p_box, FOURCC_cmvd ) )||
+ !( p_cmvd->data.p_cmvd->p_data ) )
+ {
+ msg_Warn( p_stream->p_input, "Read Box: \"cmov\" incomplete" );
+ return( 1 );
+ }
+
+ if( p_dcom->data.p_dcom->i_algorithm != FOURCC_zlib )
+ {
+ msg_Dbg( p_stream->p_input, "Read Box: \"cmov\" compression algorithm : %c%c%c%c not supported",
+ ( p_dcom->data.p_dcom->i_algorithm )&0xff,
+ ( p_dcom->data.p_dcom->i_algorithm >> 8 )&0xff,
+ ( p_dcom->data.p_dcom->i_algorithm >> 16 )&0xff,
+ ( p_dcom->data.p_dcom->i_algorithm >> 24 )&0xff );
+ return( 1 );
+ }
+
+ /* decompress data */
+ /* allocate a new buffer */
+ if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
+ {
+ msg_Err( p_stream->p_input,
+ "Read Box: \"cmov\" not enough memory to uncompress data" );
+ return( 1 );
+ }
+ /* init default structures */
+ z_data.next_in = p_cmvd->data.p_cmvd->p_data;
+ z_data.avail_in = p_cmvd->data.p_cmvd->i_compressed_size;
+ z_data.next_out = p_data;
+ z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
+ z_data.zalloc = (alloc_func)Z_NULL;
+ z_data.zfree = (free_func)Z_NULL;
+ z_data.opaque = (voidpf)Z_NULL;
+
+ /* init zlib */
+ if( ( i_result = inflateInit( &z_data ) ) != Z_OK )
+ {
+ msg_Err( p_stream->p_input,
+ "Read Box: \"cmov\" error while uncompressing data" );
+ free( p_data );
+ return( 1 );
+ }
+
+ /* uncompress */
+ i_result = inflate( &z_data, Z_NO_FLUSH );
+ if( ( i_result != Z_OK )&&( i_result != Z_STREAM_END ) )
+ {
+ msg_Err( p_stream->p_input,
+ "Read Box: \"cmov\" error while uncompressing data" );
+ free( p_data );
+ return( 1 );
+ }
+
+ if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
+ {
+ msg_Warn( p_stream->p_input,
+ "Read Box: \"cmov\" uncompressing data size mismatch" );
+ }
+ p_cmvd->data.p_cmvd->i_uncompressed_size = z_data.total_out;
+
+ /* close zlib */
+ i_result = inflateEnd( &z_data );
+ if( i_result != Z_OK )
+ {
+ msg_Warn( p_stream->p_input,
+ "Read Box: \"cmov\" error while uncompressing data (ignored)" );
+ }
+
+
+ free( p_cmvd->data.p_cmvd->p_data );
+ p_cmvd->data.p_cmvd->p_data = p_data;
+ p_cmvd->data.p_cmvd->b_compressed = 0;
+
+ msg_Dbg( p_stream->p_input,
+ "Read Box: \"cmov\" box succesfully uncompressed" );
+
+ /* now create a memory stream */
+ p_stream_memory = MP4_MemoryStream( p_stream->p_input,
+ p_cmvd->data.p_cmvd->i_uncompressed_size,
+ p_cmvd->data.p_cmvd->p_data );
+
+ /* and read uncompressd moov */
+ p_umov = malloc( sizeof( MP4_Box_t ) );
+
+ i_result = MP4_ReadBox( p_stream_memory, p_umov, NULL );
+
+ p_box->data.p_cmov->p_moov = p_umov;
+ free( p_stream_memory );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream->p_input,
+ "Read Box: \"cmov\" compressed movie header completed" );
+#endif
+ return( i_result );
+}
+
+
+/**** ------------------------------------------------------------------- ****/
+/**** "Higher level" Functions ****/
+/**** ------------------------------------------------------------------- ****/
+
+static struct
+{
+ u32 i_type;
+ int (*MP4_ReadBox_function )( MP4_Stream_t *p_stream, MP4_Box_t *p_box );
+ void (*MP4_FreeBox_function )( input_thread_t *p_input, MP4_Box_t *p_box );
+} MP4_Box_Function [] =
+{
+ /* Containers */
+ { FOURCC_moov, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_trak, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_mdia, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_moof, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_minf, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_stbl, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_dinf, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_edts, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_udta, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_nmhd, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+ { FOURCC_hnti, MP4_ReadBoxContainer, MP4_FreeBox_Common },
+
+ /* specific box */
+ { FOURCC_ftyp, MP4_ReadBox_ftyp, MP4_FreeBox_ftyp },
+ { FOURCC_cmov, MP4_ReadBox_cmov, MP4_FreeBox_Common },
+ { FOURCC_mvhd, MP4_ReadBox_mvhd, MP4_FreeBox_Common },
+ { FOURCC_tkhd, MP4_ReadBox_tkhd, MP4_FreeBox_Common },
+ { FOURCC_tref, MP4_ReadBox_tref, MP4_FreeBox_Common },
+ { FOURCC_mdhd, MP4_ReadBox_mdhd, MP4_FreeBox_Common },
+ { FOURCC_hdlr, MP4_ReadBox_hdlr, MP4_FreeBox_hdlr },
+ { FOURCC_vmhd, MP4_ReadBox_vmhd, MP4_FreeBox_Common },
+ { FOURCC_smhd, MP4_ReadBox_smhd, MP4_FreeBox_Common },
+ { FOURCC_hmhd, MP4_ReadBox_hmhd, MP4_FreeBox_Common },
+ { FOURCC_url, MP4_ReadBox_url, MP4_FreeBox_url },
+ { FOURCC_urn, MP4_ReadBox_urn, MP4_FreeBox_urn },
+ { FOURCC_dref, MP4_ReadBox_dref, MP4_FreeBox_Common },
+ { FOURCC_stts, MP4_ReadBox_stts, MP4_FreeBox_stts },
+ { FOURCC_ctts, MP4_ReadBox_ctts, MP4_FreeBox_ctts },
+ { FOURCC_stsd, MP4_ReadBox_stsd, MP4_FreeBox_Common },
+ { FOURCC_stsz, MP4_ReadBox_stsz, MP4_FreeBox_stsz },
+ { FOURCC_stsc, MP4_ReadBox_stsc, MP4_FreeBox_stsc },
+ { FOURCC_stco, MP4_ReadBox_stco_co64, MP4_FreeBox_stco_co64 },
+ { FOURCC_co64, MP4_ReadBox_stco_co64, MP4_FreeBox_stco_co64 },
+ { FOURCC_stss, MP4_ReadBox_stss, MP4_FreeBox_stss },
+ { FOURCC_stsh, MP4_ReadBox_stsh, MP4_FreeBox_stsh },
+ { FOURCC_stdp, MP4_ReadBox_stdp, MP4_FreeBox_stdp },
+ { FOURCC_padb, MP4_ReadBox_padb, MP4_FreeBox_padb },
+ { FOURCC_elst, MP4_ReadBox_elst, MP4_FreeBox_elst },
+ { FOURCC_cprt, MP4_ReadBox_cprt, MP4_FreeBox_cprt },
+ { FOURCC_esds, MP4_ReadBox_esds, MP4_FreeBox_esds },
+ { FOURCC_dcom, MP4_ReadBox_dcom, MP4_FreeBox_Common },
+ { FOURCC_cmvd, MP4_ReadBox_cmvd, MP4_FreeBox_cmvd },
+
+ /* Nothing to do with this box */
+ { FOURCC_mdat, MP4_ReadBoxSkip, MP4_FreeBox_Common },
+ { FOURCC_skip, MP4_ReadBoxSkip, MP4_FreeBox_Common },
+ { FOURCC_free, MP4_ReadBoxSkip, MP4_FreeBox_Common },
+ { FOURCC_wide, MP4_ReadBoxSkip, MP4_FreeBox_Common },
+
+ /* for codecs */
+ { FOURCC_soun, MP4_ReadBox_sample_soun, MP4_FreeBox_Common },
+ { FOURCC__mp3, MP4_ReadBox_sample_soun, MP4_FreeBox_Common },
+ { FOURCC_ms55, MP4_ReadBox_sample_soun, MP4_FreeBox_Common },
+ { FOURCC_mp4a, MP4_ReadBox_sample_soun, MP4_FreeBox_Common },
+
+ { FOURCC_vide, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_mp4v, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_SVQ1, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_DIVX, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_h263, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_cvid, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_3IV1, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_3IV2, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_mjpa, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_mjpb, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+ { FOURCC_mjqt, NULL, NULL }, /* found in mjpa/b */
+ { FOURCC_mjht, NULL, NULL },
+
+ { FOURCC_jpeg, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
+
+ { FOURCC_mp4s, NULL, MP4_FreeBox_Common },
+
+ /* XXX there is 2 box where we could find this entry stbl and tref*/
+ { FOURCC_hint, NULL, MP4_FreeBox_Common },
+
+ /* found in tref box */
+ { FOURCC_dpnd, NULL, NULL },
+ { FOURCC_ipir, NULL, NULL },
+ { FOURCC_mpod, NULL, NULL },
+
+ /* found in hnti */
+ { FOURCC_rtp, NULL, NULL },
+
+ /* Last entry */
+
+ { 0, NULL, NULL }
+};
+
+
+
+/*****************************************************************************
+ * MP4_ReadBox : parse the actual box and the children
+ * XXX : Do not go to the next box
+ *****************************************************************************/
+int MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father )
+{
+ int i_result;
+ int i_index;
+
+ if( !MP4_ReadBoxCommon( p_stream, p_box ) )
+ {
+ msg_Warn( p_stream->p_input, "Cannot read one box" );
+ return( 0 );
+ }
+ if( !p_box->i_size )
+ {
+ msg_Dbg( p_stream->p_input, "Found an empty box (null size)" );
+ return( 0 );
+ }
+ p_box->p_father = p_father;
+
+ /* Now search function to call */
+ for( i_index = 0; ; i_index++ )
+ {
+ if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
+ ( MP4_Box_Function[i_index].i_type == 0 ) )
+ {
+ break;
+ }
+ }
+ if( MP4_Box_Function[i_index].MP4_ReadBox_function == NULL )
+ {
+ msg_Warn( p_stream->p_input,
+ "Unknown box type %c%c%c%c (uncompletetly loaded)",
+ (p_box->i_type)&0xff,
+ (p_box->i_type>>8)&0xff,
+ (p_box->i_type>>16)&0xff,
+ (p_box->i_type>>24)&0xff );
+ return( 1 );
+ }
+ else
+ {
+ i_result =
+ (MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box );
+ }
+
+ if( !MP4_GotoBox( p_stream, p_box ) )
+ {
+ return( 0 );
+ }
+ return( i_result );
+}
+
+/*****************************************************************************
+ * MP4_FreeBox : free memory after read with MP4_ReadBox and all
+ * the children
+ *****************************************************************************/
+void MP4_FreeBox( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ int i_index;
+
+ MP4_Box_t *p_child;
+ MP4_Box_t *p_next;
+
+ if( !p_box )
+ {
+ return; /* hehe */
+ }
+ p_child = p_box->p_first;
+ while( p_child )
+ {
+ p_next = p_child->p_next;
+ MP4_FreeBox( p_input, p_child );
+ /* MP4_FreeBoxChildren have free all data expect p_child itself */
+ free( p_child );
+ p_child = p_next;
+ }
+
+ /* Now search function to call */
+ if( p_box->data.p_data )
+ {
+ for( i_index = 0; ; i_index++ )
+ {
+ if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
+ ( MP4_Box_Function[i_index].i_type == 0 ) )
+ {
+ break;
+ }
+ }
+ if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
+ {
+ /* Should not happen */
+ msg_Warn( p_input,
+ "cannot free box %c%c%c%c, type unknown",
+ (p_box->i_type)&0xff,
+ (p_box->i_type >> 8)&0xff,
+ (p_box->i_type >> 16)&0xff,
+ (p_box->i_type >> 24)&0xff );
+ }
+ else
+ {
+ MP4_Box_Function[i_index].MP4_FreeBox_function( p_input, p_box );
+ }
+
+ free( p_box->data.p_data );
+ p_box->data.p_data = NULL;
+ }
+
+ p_box->p_first = NULL;
+ p_box->p_last = NULL;
+
+}
+
+/*****************************************************************************
+ * MP4_ReadRoot : Parse the entire file, and create all boxes in memory
+ *****************************************************************************
+ * The first box is a virtual box "root" and is the father for all first
+ * level boxes for the file, a sort of virtual contener
+ *****************************************************************************/
+int MP4_ReadBoxRoot( input_thread_t *p_input, MP4_Box_t *p_root )
+{
+
+ MP4_Stream_t *p_stream;
+ int i_result;
+
+ MP4_SeekAbsolute( p_input, 0 ); /* Go to the begining */
+ p_root->i_pos = 0;
+ p_root->i_type = VLC_FOURCC( 'r', 'o', 'o', 't' );
+ p_root->i_shortsize = 1;
+ p_root->i_size = p_input->stream.p_selected_area->i_size;
+ CreateUUID( &p_root->i_uuid, p_root->i_type );
+
+ p_root->data.p_data = NULL;
+ p_root->p_father = NULL;
+ p_root->p_first = NULL;
+ p_root->p_last = NULL;
+ p_root->p_next = NULL;
+
+ p_stream = MP4_InputStream( p_input );
+
+ i_result = MP4_ReadBoxContainerRaw( p_stream, p_root );
+
+ free( p_stream );
+
+ if( i_result )
+ {
+ MP4_Box_t *p_child;
+ MP4_Box_t *p_moov;
+ MP4_Box_t *p_cmov;
+
+ /* check if there is a cmov, if so replace
+ compressed moov by uncompressed one */
+ if( ( p_moov = MP4_FindBox( p_root, FOURCC_moov ) )&&
+ ( p_cmov = MP4_FindBox( p_moov, FOURCC_cmov ) ) )
+ {
+ /* rename the compressed moov as a box to skip */
+ p_moov->i_type = FOURCC_skip;
+
+ /* get uncompressed p_moov */
+ p_moov = p_cmov->data.p_cmov->p_moov;
+ p_cmov->data.p_cmov->p_moov = NULL;
+
+ /* make p_root father of this new moov */
+ p_moov->p_father = p_root;
+
+ /* insert this new moov box as first child of p_root */
+ p_moov->p_next = p_child = p_root->p_first;
+ p_root->p_first = p_moov;
+ }
+ }
+ return( i_result );
+}
+
+
+static void __MP4_DumpBoxStructure( input_thread_t *p_input,
+ MP4_Box_t *p_box, int i_level )
+{
+ MP4_Box_t *p_child;
+
+ if( !i_level )
+ {
+ msg_Dbg( p_input, "Dumping root Box \"%c%c%c%c \"",
+ (p_box->i_type ) &0xff,
+ (p_box->i_type >>8 ) &0xff,
+ (p_box->i_type >>16 ) &0xff,
+ (p_box->i_type >>24) &0xff );
+ }
+ else
+ {
+ char str[512];
+ int i;
+ memset( str, (u8)' ', 512 );
+ for( i = 0; i < i_level; i++ )
+ {
+ str[i*5] = '|';
+ }
+ sprintf( str + i_level * 5, "+ %c%c%c%c size %d",
+ (p_box->i_type ) &0xff,
+ (p_box->i_type>>8 ) &0xff,
+ (p_box->i_type>>16 ) &0xff,
+ (p_box->i_type>>24 ) &0xff,
+ (u32)p_box->i_size );
+
+ msg_Dbg( p_input, "%s", str );
+ }
+ p_child = p_box->p_first;
+ while( p_child )
+ {
+ __MP4_DumpBoxStructure( p_input, p_child, i_level + 1 );
+ p_child = p_child->p_next;
+ }
+
+}
+
+void MP4_DumpBoxStructure( input_thread_t *p_input, MP4_Box_t *p_box )
+{
+ __MP4_DumpBoxStructure( p_input, p_box, 0 );
+}
+
+
+/*****************************************************************************
+ * MP4_CountBox: given a box, count how many child have the requested type
+ * FIXME : support GUUID
+ *****************************************************************************/
+int MP4_CountBox( MP4_Box_t *p_box, u32 i_type )
+{
+ int i_count;
+ MP4_Box_t *p_child;
+
+ if( !p_box )
+ {
+ return( 0 );
+ }
+
+ i_count = 0;
+ p_child = p_box->p_first;
+ while( p_child )
+ {
+ if( p_child->i_type == i_type )
+ {
+ i_count++;
+ }
+ p_child = p_child->p_next;
+ }
+
+ return( i_count );
+}
+
+
+/*****************************************************************************
+ * MP4_FindBox: find first box with i_type child of p_box
+ * return NULL if not found
+ *****************************************************************************/
+
+MP4_Box_t *MP4_FindBox( MP4_Box_t *p_box, u32 i_type )
+{
+ MP4_Box_t *p_child;
+
+ if( !p_box )
+ {
+ return( NULL );
+ }
+
+ p_child = p_box->p_first;
+ while( p_child )
+ {
+ if( p_child->i_type == i_type )
+ {
+ return( p_child );
+ }
+ p_child = p_child->p_next;
+ }
+
+ return( NULL );
+}
+
+
+/*****************************************************************************
+ * MP4_FindNextBox: find next box with thesame type and at the same level
+ * than p_box
+ *****************************************************************************/
+MP4_Box_t *MP4_FindNextBox( MP4_Box_t *p_box )
+{
+ MP4_Box_t *p_next;
+
+ if( !p_box )
+ {
+ return( NULL );
+ }
+
+ p_next = p_box->p_next;
+ while( p_next )
+ {
+ if( p_next->i_type == p_box->i_type )
+ {
+ return( p_next );
+ }
+ p_next = p_next->p_next;
+ }
+ return( NULL );
+}
+
+/*****************************************************************************
+ * MP4_FindNbBox: find the box i_number
+ *****************************************************************************/
+MP4_Box_t *MP4_FindNbBox( MP4_Box_t *p_box, u32 i_number )
+{
+ MP4_Box_t *p_child = p_box->p_first;
+
+ if( !p_child )
+ {
+ return( NULL );
+ }
+
+ while( i_number )
+ {
+ if( !( p_child = p_child->p_next ) )
+ {
+ return( NULL );
+ }
+ i_number--;
+ }
+ return( p_child );
+}
+
--- /dev/null
+/*****************************************************************************
+ * libmp4.h : LibMP4 library for mp4 module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: libmp4.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#define FOURCC_uuid VLC_FOURCC( 'u', 'u', 'i', 'd' )
+
+#define FOURCC_ftyp VLC_FOURCC( 'f', 't', 'y', 'p' )
+#define FOURCC_moov VLC_FOURCC( 'm', 'o', 'o', 'v' )
+#define FOURCC_cmov VLC_FOURCC( 'c', 'm', 'o', 'v' )
+#define FOURCC_dcom VLC_FOURCC( 'd', 'c', 'o', 'm' )
+#define FOURCC_cmvd VLC_FOURCC( 'c', 'm', 'v', 'd' )
+
+#define FOURCC_moof VLC_FOURCC( 'm', 'o', 'o', 'f' )
+#define FOURCC_mdat VLC_FOURCC( 'm', 'd', 'a', 't' )
+#define FOURCC_skip VLC_FOURCC( 's', 'k', 'i', 'p' )
+#define FOURCC_free VLC_FOURCC( 'f', 'r', 'e', 'e' )
+#define FOURCC_udta VLC_FOURCC( 'u', 'd', 't', 'a' )
+#define FOURCC_wide VLC_FOURCC( 'w', 'i', 'd', 'e' )
+
+#define FOURCC_trak VLC_FOURCC( 't', 'r', 'a', 'k' )
+#define FOURCC_mvhd VLC_FOURCC( 'm', 'v', 'h', 'd' )
+#define FOURCC_tkhd VLC_FOURCC( 't', 'k', 'h', 'd' )
+#define FOURCC_tref VLC_FOURCC( 't', 'r', 'e', 'f' )
+#define FOURCC_mdia VLC_FOURCC( 'm', 'd', 'i', 'a' )
+#define FOURCC_mdhd VLC_FOURCC( 'm', 'd', 'h', 'd' )
+#define FOURCC_hdlr VLC_FOURCC( 'h', 'd', 'l', 'r' )
+#define FOURCC_minf VLC_FOURCC( 'm', 'i', 'n', 'f' )
+#define FOURCC_vmhd VLC_FOURCC( 'v', 'm', 'h', 'd' )
+#define FOURCC_smhd VLC_FOURCC( 's', 'm', 'h', 'd' )
+#define FOURCC_hmhd VLC_FOURCC( 'h', 'm', 'h', 'd' )
+#define FOURCC_dinf VLC_FOURCC( 'd', 'i', 'n', 'f' )
+#define FOURCC_url VLC_FOURCC( 'u', 'r', 'l', ' ' )
+#define FOURCC_urn VLC_FOURCC( 'u', 'r', 'n', ' ' )
+#define FOURCC_dref VLC_FOURCC( 'd', 'r', 'e', 'f' )
+#define FOURCC_stbl VLC_FOURCC( 's', 't', 'b', 'l' )
+#define FOURCC_stts VLC_FOURCC( 's', 't', 't', 's' )
+#define FOURCC_ctts VLC_FOURCC( 'c', 't', 't', 's' )
+#define FOURCC_stsd VLC_FOURCC( 's', 't', 's', 'd' )
+#define FOURCC_stsz VLC_FOURCC( 's', 't', 's', 'z' )
+#define FOURCC_stz2 VLC_FOURCC( 's', 't', 'z', '2' )
+#define FOURCC_stsc VLC_FOURCC( 's', 't', 's', 'c' )
+#define FOURCC_stco VLC_FOURCC( 's', 't', 'c', 'o' )
+#define FOURCC_co64 VLC_FOURCC( 'c', 'o', '6', '4' )
+#define FOURCC_stss VLC_FOURCC( 's', 't', 's', 's' )
+#define FOURCC_stsh VLC_FOURCC( 's', 't', 's', 'h' )
+#define FOURCC_stdp VLC_FOURCC( 's', 't', 'd', 'p' )
+#define FOURCC_padb VLC_FOURCC( 'p', 'a', 'd', 'b' )
+#define FOURCC_edts VLC_FOURCC( 'e', 'd', 't', 's' )
+#define FOURCC_elst VLC_FOURCC( 'e', 'l', 's', 't' )
+#define FOURCC_udta VLC_FOURCC( 'u', 'd', 't', 'a' )
+#define FOURCC_mvex VLC_FOURCC( 'm', 'v', 'e', 'x' )
+#define FOURCC_trex VLC_FOURCC( 't', 'r', 'e', 'x' )
+#define FOURCC_mfhd VLC_FOURCC( 'm', 'f', 'h', 'd' )
+#define FOURCC_traf VLC_FOURCC( 't', 'r', 'a', 'f' )
+#define FOURCC_tfhd VLC_FOURCC( 't', 'f', 'h', 'd' )
+#define FOURCC_trun VLC_FOURCC( 't', 'r', 'u', 'n' )
+#define FOURCC_cprt VLC_FOURCC( 'c', 'p', 'r', 't' )
+#define FOURCC_iods VLC_FOURCC( 'i', 'o', 'd', 's' )
+
+#define FOURCC_nmhd VLC_FOURCC( 'n', 'm', 'h', 'd' )
+#define FOURCC_mp4v VLC_FOURCC( 'm', 'p', '4', 'v' )
+#define FOURCC_mp4a VLC_FOURCC( 'm', 'p', '4', 'a' )
+#define FOURCC_mp4s VLC_FOURCC( 'm', 'p', '4', 's' )
+#define FOURCC_vide VLC_FOURCC( 'v', 'i', 'd', 'e' )
+#define FOURCC_soun VLC_FOURCC( 's', 'o', 'u', 'n' )
+#define FOURCC_hint VLC_FOURCC( 'h', 'i', 'n', 't' )
+
+#define FOURCC_dpnd VLC_FOURCC( 'd', 'p', 'n', 'd' )
+#define FOURCC_ipir VLC_FOURCC( 'i', 'p', 'i', 'r' )
+#define FOURCC_mpod VLC_FOURCC( 'm', 'p', 'o', 'd' )
+#define FOURCC_hnti VLC_FOURCC( 'h', 'n', 't', 'i' )
+#define FOURCC_rtp VLC_FOURCC( 'r', 't', 'p', ' ' )
+
+#define FOURCC_isom VLC_FOURCC( 'i', 's', 'o', 'm' )
+#define FOURCC_esds VLC_FOURCC( 'e', 's', 'd', 's' )
+
+#define FOURCC_zlib VLC_FOURCC( 'z', 'l', 'i', 'b' )
+#define FOURCC_SVQ1 VLC_FOURCC( 'S', 'V', 'Q', '1' )
+#define FOURCC__mp3 VLC_FOURCC( '.', 'm', 'p', '3' )
+#define FOURCC_ms55 VLC_FOURCC( 'm', 's', 0x0, 0x55 )
+#define FOURCC_3IV1 VLC_FOURCC( '3', 'I', 'V', '1' )
+#define FOURCC_3IV2 VLC_FOURCC( '3', 'I', 'V', '2' )
+#define FOURCC_h263 VLC_FOURCC( 'h', '2', '6', '3' )
+#define FOURCC_DIVX VLC_FOURCC( 'D', 'I', 'V', 'X' )
+#define FOURCC_cvid VLC_FOURCC( 'c', 'v', 'i', 'd' )
+#define FOURCC_mjpa VLC_FOURCC( 'm', 'j', 'p', 'a' )
+#define FOURCC_mjpb VLC_FOURCC( 'm', 'j', 'q', 't' )
+#define FOURCC_mjqt VLC_FOURCC( 'm', 'j', 'h', 't' )
+#define FOURCC_mjht VLC_FOURCC( 'm', 'j', 'p', 'b' )
+
+#define FOURCC_jpeg VLC_FOURCC( 'j', 'p', 'e', 'g' )
+
+/* Do you want some debug information on all read boxes ? */
+#define MP4_VERBOSE 1
+
+/* memory stream and file stream object */
+
+typedef struct MP4_Stream_s
+{
+ int b_memory; /* do we uses a memory buffer */
+
+ input_thread_t *p_input;
+
+ off_t i_start; /* in the buffer position for memory stream */
+ off_t i_stop;
+ u8 *p_buffer;
+
+} MP4_Stream_t;
+
+struct MP4_Box_s;
+
+
+/* uuid Universal Unique IDentifiers */
+typedef struct UUID_s
+{
+ u8 b[16];
+} UUID_t;
+
+/* specific structure for all boxes */
+
+typedef struct MP4_Box_data_ftyp_s
+{
+ u32 i_major_brand;
+ u32 i_minor_version;
+
+ u32 i_compatible_brands_count;
+ u32 *i_compatible_brands;
+
+} MP4_Box_data_ftyp_t;
+
+typedef struct MP4_Box_data_mvhd_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u64 i_creation_time;
+ u64 i_modification_time;
+ u32 i_timescale;
+ u64 i_duration;
+
+ s32 i_rate;
+ s16 i_volume;
+ s16 i_reserved1;
+ u32 i_reserved2[2];
+ s32 i_matrix[9];
+ u32 i_predefined[6];
+ u32 i_next_track_id;
+
+} MP4_Box_data_mvhd_t;
+
+#define MP4_TRACK_ENABLED 0x000001
+#define MP4_TRACK_IN_MOVIE 0x000002
+#define MP4_TRACK_IN_PREVIEW 0x000004
+typedef struct MP4_Box_data_tkhd_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u64 i_creation_time;
+ u64 i_modification_time;
+ u32 i_track_ID;
+ u32 i_reserved;
+ u64 i_duration;
+
+ u32 i_reserved2[2];
+ s16 i_layer;
+ s16 i_predefined;
+
+ s16 i_volume;
+ u16 i_reserved3;
+ s32 i_matrix[9];
+ s32 i_width;
+ s32 i_height;
+
+} MP4_Box_data_tkhd_t;
+
+typedef struct MP4_Box_data_mdhd_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u64 i_creation_time;
+ u64 i_modification_time;
+ u32 i_timescale;
+ u64 i_duration;
+
+ /* one bit for pad */
+ /* unsigned int(5)[3] language difference with 0x60*/
+ unsigned char i_language[3];
+ u16 i_predefined;
+
+} MP4_Box_data_mdhd_t;
+
+typedef struct MP4_Box_data_hdlr_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_predefined;
+ u32 i_handler_type; /* "vide" "soun" "hint" "odsm"
+ "crsm" "sdsm" "m7sm" "ocsm"
+ "ipsm" "mjsm" */
+
+ unsigned char *psz_name; /* in UTF-8 */
+
+} MP4_Box_data_hdlr_t;
+
+typedef struct MP4_Box_data_vmhd_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ s16 i_graphics_mode;
+ s16 i_opcolor[3];
+
+} MP4_Box_data_vmhd_t;
+
+typedef struct MP4_Box_data_smhd_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ s16 i_balance;
+ s16 i_reserved;
+
+} MP4_Box_data_smhd_t;
+
+typedef struct MP4_Box_data_hmhd_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u16 i_max_PDU_size;
+ u16 i_avg_PDU_size;
+ u32 i_max_bitrate;
+ u32 i_avg_bitrate;
+ u32 i_reserved;
+
+} MP4_Box_data_hmhd_t;
+
+typedef struct MP4_Box_data_url_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ unsigned char *psz_location;
+
+} MP4_Box_data_url_t;
+
+typedef struct MP4_Box_data_urn_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ unsigned char *psz_name;
+ unsigned char *psz_location;
+
+} MP4_Box_data_urn_t;
+
+typedef struct MP4_Box_data_dref_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+/* XXX it's also a container with i_entry_count entry */
+} MP4_Box_data_dref_t;
+
+typedef struct MP4_Box_data_stts_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+ u32 *i_sample_count; /* these are array */
+ s32 *i_sample_delta;
+
+} MP4_Box_data_stts_t;
+
+typedef struct MP4_Box_data_ctts_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+
+ u32 *i_sample_count; /* these are array */
+ s32 *i_sample_offset;
+
+} MP4_Box_data_ctts_t;
+
+
+typedef struct MP4_Box_data_sample_soun_s
+{
+ u8 i_reserved1[6];
+ u16 i_data_reference_index;
+
+ u32 i_reserved2[2];
+ u16 i_channelcount;
+ u16 i_samplesize;
+ u16 i_predefined;
+ u16 i_reserved3;
+ u16 i_sampleratehi; /* timescale of track */
+ u16 i_sampleratelo;
+
+} MP4_Box_data_sample_soun_t;
+
+typedef struct MP4_Box_data_sample_vide_s
+{
+ u8 i_reserved1[6];
+ u16 i_data_reference_index;
+
+ u16 i_predefined1;
+ u16 i_reserved2;
+ u32 i_predefined2[3];
+
+ s16 i_width;
+ s16 i_height;
+
+ u32 i_horizresolution;
+ u32 i_vertresolution;
+
+ u32 i_reserved3;
+ u16 i_predefined3;
+
+ u8 i_compressorname[32];
+ s16 i_depth;
+
+ s16 i_predefined4;
+
+} MP4_Box_data_sample_vide_t;
+
+typedef struct MP4_Box_data_sample_hint_s
+{
+ u8 i_reserved1[6];
+ u16 i_data_reference_index;
+
+ u8 *p_data;
+
+} MP4_Box_data_sample_hint_t;
+
+typedef struct MP4_Box_data_moviehintinformation_rtp_s
+{
+ u32 i_description_format;
+ unsigned char *psz_text;
+
+} MP4_Box_data_moviehintinformation_rtp_t;
+
+
+
+typedef struct MP4_Box_data_stsd_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+
+ /* it contains SampleEntry handled as if it was Box */
+
+} MP4_Box_data_stsd_t;
+
+
+typedef struct MP4_Box_data_stsz_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_sample_size;
+ u32 i_sample_count;
+
+ u32 *i_entry_size; /* array , empty if i_sample_size != 0 */
+
+} MP4_Box_data_stsz_t;
+
+typedef struct MP4_Box_data_stz2_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_sample_size; /* 24 bits */
+ u8 i_field_size;
+ u32 i_sample_count;
+
+ u32 *i_entry_size; /* array: unsigned int(i_field_size) entry_size */
+
+} MP4_Box_data_stz2_t;
+
+typedef struct MP4_Box_data_stsc_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+
+ u32 *i_first_chunk; /* theses are arrays */
+ u32 *i_samples_per_chunk;
+ u32 *i_sample_description_index;
+
+} MP4_Box_data_stsc_t;
+
+
+typedef struct MP4_Box_data_co64_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+
+ u64 *i_chunk_offset;
+
+} MP4_Box_data_co64_t;
+
+
+typedef struct MP4_Box_data_stss_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+
+ u32 *i_sample_number;
+
+} MP4_Box_data_stss_t;
+
+typedef struct MP4_Box_data_stsh_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+
+ u32 *i_shadowed_sample_number;
+ u32 *i_sync_sample_number;
+
+} MP4_Box_data_stsh_t;
+
+typedef struct MP4_Box_data_stdp_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u16 *i_priority;
+
+} MP4_Box_data_stdp_t;
+
+typedef struct MP4_Box_data_padb_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_sample_count;
+
+ u16 *i_reserved1; /* 1bit */
+ u16 *i_pad2; /* 3bits */
+ u16 *i_reserved2; /* 1bit */
+ u16 *i_pad1; /* 3bits */
+
+
+} MP4_Box_data_padb_t;
+
+
+typedef struct MP4_Box_data_elst_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ u32 i_entry_count;
+
+ u64 *i_segment_duration;
+ s64 *i_media_time;
+ u16 *i_media_rate_integer;
+ u16 *i_media_rate_fraction;
+
+
+} MP4_Box_data_elst_t;
+
+typedef struct MP4_Box_data_cprt_s
+{
+ u8 i_version;
+ u32 i_flags;
+ /* 1 pad bit */
+ unsigned char i_language[3];
+
+ unsigned char *psz_notice;
+} MP4_Box_data_cprt_t;
+
+
+/* DecoderConfigDescriptor */
+typedef struct MP4_descriptor_decoder_config_s
+{
+ u8 i_objectTypeIndication;
+ u8 i_streamType;
+ int b_upStream;
+ int i_buffer_sizeDB;
+ int i_max_bitrate;
+ int i_avg_bitrate;
+
+ int i_decoder_specific_info_len;
+ u8 *p_decoder_specific_info;
+ /* some other stuff */
+
+} MP4_descriptor_decoder_config_t;
+
+typedef struct MP4_descriptor_SL_config_s
+{
+
+} MP4_descriptor_SL_config_t;
+
+
+typedef struct MP4_descriptor_ES_s
+{
+ u16 i_ES_ID;
+ int b_stream_dependence;
+ int b_url;
+ int b_OCRstream;
+ int i_stream_priority;
+
+ int i_depend_on_ES_ID; /* if b_stream_dependence set */
+
+ unsigned char *psz_URL;
+
+ u16 i_OCR_ES_ID; /* if b_OCRstream */
+ MP4_descriptor_decoder_config_t *p_decConfigDescr;
+
+ MP4_descriptor_SL_config_t *p_slConfigDescr;
+
+ /* some other stuff ... */
+
+} MP4_descriptor_ES_t;
+
+/* ES descriptor */
+typedef struct MP4_Box_data_esds_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+ MP4_descriptor_ES_t es_descriptor;
+
+} MP4_Box_data_esds_t;
+
+
+typedef struct MP4_Box_data_dcom_s
+{
+ u32 i_algorithm; /* fourcc */
+
+} MP4_Box_data_dcom_t;
+
+typedef struct MP4_Box_data_cmvd_s
+{
+ u32 i_uncompressed_size;
+ u32 i_compressed_size;
+
+ int b_compressed; /* Set to 1 if compressed data, 0 if uncompressed */
+ u8 *p_data;
+
+} MP4_Box_data_cmvd_t;
+
+typedef struct MP4_Box_data_cmov_s
+{
+ struct MP4_Box_s *p_moov; /* uncompressed moov */
+
+} MP4_Box_data_cmov_t;
+
+/*
+typedef struct MP4_Box_data_cmov_s
+{
+ u8 i_version;
+ u32 i_flags;
+
+} MP4_Box_data__t;
+
+*/
+
+typedef union MP4_Box_data_s
+{
+ MP4_Box_data_ftyp_t *p_ftyp;
+ MP4_Box_data_mvhd_t *p_mvhd;
+ MP4_Box_data_tkhd_t *p_tkhd;
+ MP4_Box_data_mdhd_t *p_mdhd;
+ MP4_Box_data_hdlr_t *p_hdlr;
+ MP4_Box_data_vmhd_t *p_vmhd;
+ MP4_Box_data_smhd_t *p_smhd;
+ MP4_Box_data_hmhd_t *p_hmhd;
+ MP4_Box_data_url_t *p_url;
+ MP4_Box_data_urn_t *p_urn;
+ MP4_Box_data_dref_t *p_dref;
+ MP4_Box_data_stts_t *p_stts;
+ MP4_Box_data_ctts_t *p_ctts;
+ MP4_Box_data_stsd_t *p_stsd;
+ MP4_Box_data_sample_vide_t *p_sample_vide;
+ MP4_Box_data_sample_soun_t *p_sample_soun;
+ MP4_Box_data_sample_hint_t *p_sample_hint;
+
+ MP4_Box_data_esds_t *p_esds;
+
+ MP4_Box_data_stsz_t *p_stsz;
+ MP4_Box_data_stz2_t *p_stz2;
+ MP4_Box_data_stsc_t *p_stsc;
+ MP4_Box_data_co64_t *p_co64;
+ MP4_Box_data_stss_t *p_stss;
+ MP4_Box_data_stsh_t *p_stsh;
+ MP4_Box_data_stdp_t *p_stdp;
+ MP4_Box_data_padb_t *p_padb;
+ MP4_Box_data_elst_t *p_elst;
+ MP4_Box_data_cprt_t *p_cprt;
+
+ MP4_Box_data_dcom_t *p_dcom;
+ MP4_Box_data_cmvd_t *p_cmvd;
+ MP4_Box_data_cmov_t *p_cmov;
+
+ MP4_Box_data_moviehintinformation_rtp_t p_moviehintinformation_rtp;
+
+ void *p_data; /* for unknow type */
+} MP4_Box_data_t;
+
+
+
+/* the most basic structure */
+typedef struct MP4_Box_s
+{
+ off_t i_pos; /* absolute position */
+
+ u32 i_type;
+ u32 i_shortsize;
+
+ UUID_t i_uuid; /* Set if i_type == "uuid" */
+
+ u64 i_size; /* always set so use it */
+
+ MP4_Box_data_t data; /* union of pointers on extended data depending on i_type (or i_usertype) */
+
+ struct MP4_Box_s *p_father; /* pointer on the father Box */
+
+ struct MP4_Box_s *p_first; /* pointer on the first child Box */
+ struct MP4_Box_s *p_last;
+
+ struct MP4_Box_s *p_next; /* pointer on the next boxes at the same level */
+
+} MP4_Box_t;
+
+/*---------------------------------------------------------------------------*/
+/****----------------------- High level functions ------------------------****/
+/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************
+ * Function for manipulate stream easily
+ *****************************************************************************/
+
+off_t MP4_TellAbsolute( input_thread_t *p_input );
+int MP4_SeekAbsolute( input_thread_t *p_input, off_t i_pos);
+int MP4_ReadData( input_thread_t *p_input, u8 *p_buff, int i_size );
+
+/*****************************************************************************
+ * MP4_ReadRoot : Parse the entire file, and create all boxes in memory
+ *****************************************************************************
+ * The first box is a virtual box "root" and is the father for all first
+ * level boxes
+ *
+ * RETURN : 1 if succes and 0 if it failed
+ *****************************************************************************/
+int MP4_ReadBoxRoot( input_thread_t *p_input, MP4_Box_t *p_root );
+
+/*****************************************************************************
+ * MP4_FreeBox : free memory allocated after read with MP4_ReadBox
+ * this, means also children boxes
+ * XXX : all children have to be allocated by a malloc !! and
+ * p_box isn't freeing
+ *****************************************************************************/
+void MP4_FreeBox( input_thread_t *p_input, MP4_Box_t *p_box );
+
+/*****************************************************************************
+ * MP4_DumpBoxStructure: print the structure of the p_box
+ *****************************************************************************/
+void MP4_DumpBoxStructure( input_thread_t *p_input, MP4_Box_t *p_box );
+
+/*****************************************************************************
+ * MP4_CountBox: given a box, count how many child have the requested type
+ * FIXME : support GUUID
+ *****************************************************************************/
+int MP4_CountBox( MP4_Box_t *p_box, u32 i_type );
+
+/*****************************************************************************
+ * MP4_FindBox: find first box with i_type child of p_box
+ * return NULL if not found
+ *****************************************************************************/
+MP4_Box_t *MP4_FindBox( MP4_Box_t *p_box, u32 i_type );
+
+/*****************************************************************************
+ * MP4_FindNextBox: find next box with thesame type and at the same level
+ * than p_box
+ *****************************************************************************/
+MP4_Box_t *MP4_FindNextBox( MP4_Box_t *p_box );
+
+/*****************************************************************************
+ * MP4_FindNbBox: find the box i_number
+ *****************************************************************************/
+MP4_Box_t *MP4_FindNbBox( MP4_Box_t *p_box, u32 i_number );
+
+
+/*---------------------------------------------------------------------------*/
+/****----------------------- Lower level functions -----------------------****/
+/**** ****/
+/****------Use them only when you known what they really do and need------****/
+/**** ****/
+/****---------------------------------------------------------------------****/
+/*---------------------------------------------------------------------------*/
+
+
+/**** ------- First some function to make abstract from input -------- */
+
+/****************************************************************************
+ * MP4_InputStream create an stram with an input
+ *
+ ****************************************************************************/
+MP4_Stream_t *MP4_InputStream( input_thread_t *p_input );
+
+/****************************************************************************
+ * MP4_MemoryStream create a memory stream
+ * if p_buffer == NULL, will allocate a buffer of i_size, else
+ * it uses p_buffer XXX you have to unallocate yourself !
+ *
+ ****************************************************************************/
+MP4_Stream_t *MP4_MemoryStream( input_thread_t *p_input,
+ int i_size, u8 *p_buffer );
+
+/****************************************************************************
+ * MP4_ReadStream read from a MP4_Stream_t
+ *
+ ****************************************************************************/
+int MP4_ReadStream( MP4_Stream_t *p_stream, u8 *p_buff, int i_size );
+
+/****************************************************************************
+ * MP4_PeekStream guess it ;)
+ *
+ ****************************************************************************/
+int MP4_PeekStream( MP4_Stream_t *p_stream, u8 **pp_peek, int i_size );
+
+/****************************************************************************
+ * MP4_TellStream give absolute position in the stream
+ * XXX for a memory stream give position from begining of the buffer
+ ****************************************************************************/
+off_t MP4_TellStream( MP4_Stream_t *p_stream );
+
+/****************************************************************************
+ * MP4_SeekStream seek in a MP4_Stream_t
+ *
+ ****************************************************************************/
+int MP4_SeekStream( MP4_Stream_t *p_stream, off_t i_pos);
+
+
+
+/*****************************************************************************
+ * MP4_ReadBox : parse the actual box and the children if they exist
+ *
+ * RETURN : 1 if succes and 0 if it failed
+ *****************************************************************************/
+int MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father );
+
+
+/*****************************************************************************
+ * MP4_ReadBoxCommon : Load only common parameters for all boxes
+ *****************************************************************************
+ * p_box need to be an already allocated MP4_Box_t, and all data
+ * will only be peek not read
+ *
+ * RETURN : 0 if it fail, 1 otherwise
+ *****************************************************************************/
+int MP4_ReadBoxCommon( MP4_Stream_t *p_stream, MP4_Box_t *p_box );
+
+
+/*****************************************************************************
+ * MP4_MP4_GotoBox : Go to this particular box
+ *****************************************************************************
+ * RETURN : 0 if it fail, 1 otherwise
+ *****************************************************************************/
+int MP4_GotoBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box );
+
+
+/*****************************************************************************
+ * MP4_MP4_NextBox : Go to the next box wiithin p_box->p_father
+ *****************************************************************************
+ * if p_box == NULL, go to the next box in witch we are( at the begining ).
+ *****************************************************************************/
+int MP4_NextBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box );
+
+
--- /dev/null
+/*****************************************************************************
+ * mp4.c : MP4 file input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: mp4.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#include <errno.h>
+#include <sys/types.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include "libmp4.h"
+#include "mp4.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int MP4Init ( vlc_object_t * );
+static void __MP4End ( vlc_object_t * );
+static int MP4Demux ( input_thread_t * );
+
+#define MP4End(a) __MP4End(VLC_OBJECT(a))
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( "MP4 demuxer" );
+ set_capability( "demux", 242 );
+ set_callbacks( MP4Init, __MP4End );
+vlc_module_end();
+
+/*****************************************************************************
+ * Declaration of local function
+ *****************************************************************************/
+static void MP4_ParseTrack();
+
+static int MP4_CreateChunksIndex();
+static int MP4_CreateSamplesIndex();
+
+static void MP4_StartDecoder();
+static void MP4_StopDecoder();
+
+static int MP4_ReadSample();
+static int MP4_DecodeSample();
+
+#define MP4_Set4BytesLE( p, dw ) \
+ *((u8*)p) = ( (dw)&0xff ); \
+ *((u8*)p+1) = ( ((dw)>> 8)&0xff ); \
+ *((u8*)p+2) = ( ((dw)>>16)&0xff ); \
+ *((u8*)p+3) = ( ((dw)>>24)&0xff )
+
+#define MP4_Set2BytesLE( p, dw ) \
+ *((u8*)p) = ( (dw)&0xff ); \
+ *((u8*)p+1) = ( ((dw)>> 8)&0xff )
+
+
+/*****************************************************************************
+ * MP4Init: check file and initializes MP4 structures
+ *****************************************************************************/
+static int MP4Init( vlc_object_t * p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+ u8 *p_peek;
+ u32 i_type;
+
+ demux_data_mp4_t *p_demux;
+
+ MP4_Box_t *p_moov;
+ MP4_Box_t *p_ftyp;
+
+
+ MP4_Box_t *p_mvhd;
+ MP4_Box_t *p_trak;
+
+ int i;
+ /* I need to seek */
+ if( !p_input->stream.b_seekable )
+ {
+ msg_Warn( p_input, "MP4 plugin discarded (unseekable)" );
+ return( -1 );
+
+ }
+ /* Initialize access plug-in structures. */
+ if( p_input->i_mtu == 0 )
+ {
+ /* Improve speed. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
+ }
+
+ p_input->pf_demux = MP4Demux;
+
+ /* a little test to see if it could be a mp4 */
+ if( input_Peek( p_input, &p_peek, 8 ) < 8 )
+ {
+ msg_Warn( p_input, "MP4 plugin discarded (cannot peek)" );
+ return( -1 );
+ }
+ i_type = ( p_peek[4] ) + ( p_peek[5] << 8 ) +
+ ( p_peek[6] << 16 ) + ( p_peek[7] << 24);
+ switch( i_type )
+ {
+ case( FOURCC_ftyp ):
+ case( FOURCC_moov ):
+ case( FOURCC_moof ):
+ case( FOURCC_mdat ):
+ case( FOURCC_udta ): /* should never match but ... */
+ case( FOURCC_free ):
+ case( FOURCC_skip ):
+ case( FOURCC_wide ): /* not mp4 compliant but ... */
+ break;
+ default:
+ msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
+ return( -1 );
+ }
+
+ /* create our structure that will contains all data */
+ if( !( p_input->p_demux_data =
+ p_demux = malloc( sizeof( demux_data_mp4_t ) ) ) )
+ {
+ msg_Err( p_input, "out of memory" );
+ return( -1 );
+ }
+ memset( p_demux, 0, sizeof( demux_data_mp4_t ) );
+ p_input->p_demux_data = p_demux;
+
+
+ /* Now load all boxes ( except raw data ) */
+ if( !MP4_ReadBoxRoot( p_input, &p_demux->box_root ) )
+ {
+ msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
+ return( -1 );
+ }
+
+ MP4_DumpBoxStructure( p_input, &p_demux->box_root );
+
+ if( ( p_ftyp = MP4_FindBox( &p_demux->box_root, FOURCC_ftyp ) ) )
+ {
+ switch( p_ftyp->data.p_ftyp->i_major_brand )
+ {
+ case( FOURCC_isom ):
+ msg_Info( p_input,
+ "ISO Media file (isom) version %d.",
+ p_ftyp->data.p_ftyp->i_minor_version );
+ break;
+ default:
+ msg_Info( p_input,
+ "Unrecognize major file specification (%c%c%c%c).",
+ p_ftyp->data.p_ftyp->i_major_brand&0xff,
+ ( p_ftyp->data.p_ftyp->i_major_brand >> 8)&0xff,
+ ( p_ftyp->data.p_ftyp->i_major_brand >> 16 )&0xff,
+ ( p_ftyp->data.p_ftyp->i_major_brand >> 24 )&0xff );
+ break;
+ }
+ }
+ else
+ {
+ msg_Info( p_input, "File Type box missing(assume ISO Media file)" );
+ }
+
+ /* the file need to have one moov box */
+ if( !( p_moov = MP4_FindBox( &p_demux->box_root, FOURCC_moov ) ) )
+ {
+ msg_Warn( p_input, "MP4 plugin discarded (missing moov box)" );
+ MP4End( p_input );
+ return( -1 );
+ }
+
+ if( MP4_CountBox( &p_demux->box_root, FOURCC_moov ) != 1 )
+ {
+ msg_Warn( p_input, "more than one \"moov\" box (continuying anyway)" );
+ }
+
+ if( !(p_mvhd = MP4_FindBox( p_moov, FOURCC_mvhd ) ) )
+ {
+ msg_Err( p_input, "cannot find \"mvhd\" box" );
+ MP4End( p_input );
+ return( -1 );
+ }
+ else
+ {
+ p_demux->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
+ }
+
+ p_demux->i_tracks = MP4_CountBox( p_moov, FOURCC_trak );
+ msg_Dbg( p_input, "find %d track%c",
+ p_demux->i_tracks,
+ p_demux->i_tracks ? 's':' ' );
+
+ if( !( p_trak = MP4_FindBox( p_moov, FOURCC_trak ) ) )
+ {
+ msg_Err( p_input, "cannot find /moov/trak !" );
+ MP4End( p_input );
+ return( -1 );
+ }
+
+ /* allocate memory */
+ p_demux->track = calloc( p_demux->i_tracks, sizeof( track_data_mp4_t ) );
+
+ /* now process each track and extract all usefull informations */
+ for( i = 0; i < p_demux->i_tracks; i++ )
+ {
+ MP4_ParseTrack( p_input, &p_demux->track[i], p_trak );
+
+ if( p_demux->track[i].b_ok )
+ {
+ char *psz_cat;
+ switch( p_demux->track[i].i_cat )
+ {
+ case( VIDEO_ES ):
+ psz_cat = "video";
+ break;
+ case( AUDIO_ES ):
+ psz_cat = "audio";
+ break;
+ default:
+ psz_cat = "";
+ break;
+ }
+
+ msg_Dbg( p_input, "adding track(%d) %s (%s) language %c%c%c",
+ i,
+ psz_cat,
+ p_demux->track[i].b_enable ? "enable":"disable",
+ p_demux->track[i].i_language[0],
+ p_demux->track[i].i_language[1],
+ p_demux->track[i].i_language[2] );
+ }
+ else
+ {
+ msg_Dbg( p_input, "ignoring track(%d)", i );
+ }
+
+ p_trak = MP4_FindNextBox( p_trak );
+ }
+
+ /* create one program */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( input_InitStream( p_input, 0 ) == -1)
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ msg_Err( p_input, "cannot init stream" );
+ MP4End( p_input );
+ return( -1 );
+ }
+ if( input_AddProgram( p_input, 0, 0) == NULL )
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ msg_Err( p_input, "cannot add program" );
+ MP4End( p_input );
+ return( -1 );
+ }
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+ p_input->stream.i_mux_rate = 0 ; /* FIXME */
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+
+ for( i = 0; i < p_demux->i_tracks; i++ )
+ {
+ /* start decoder for this track if enable by default*/
+ if( p_demux->track[i].b_enable )
+ {
+ MP4_StartDecoder( p_input, &p_demux->track[i] );
+ }
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.p_selected_program->b_is_ok = 1;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( 0 );
+
+}
+
+/*****************************************************************************
+ * MP4Demux: read packet and send them to decoders
+ *****************************************************************************/
+static int MP4Demux( input_thread_t *p_input )
+{
+ demux_data_mp4_t *p_demux = p_input->p_demux_data;
+ int i_track;
+
+ /* first wait for the good time to read a packet */
+
+ input_ClockManageRef( p_input,
+ p_input->stream.p_selected_program,
+ p_demux->i_pcr );
+
+
+ /* update pcr XXX in mpeg scale so in 90000 unit/s */
+ p_demux->i_pcr = MP4_GetMoviePTS( p_demux ) * 9 / 100;
+
+
+ /* we will read 100ms for each stream so ...*/
+ p_demux->i_time += __MAX( p_demux->i_timescale / 10 , 1 );
+
+
+ for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
+ {
+ if( ( !p_demux->track[i_track].b_ok )||
+ ( !p_demux->track[i_track].p_es )||
+ ( !p_demux->track[i_track].p_es->p_decoder_fifo )||
+ ( MP4_GetTrackPTS( &p_demux->track[i_track] ) >=
+ MP4_GetMoviePTS( p_demux ) ) )
+ {
+ continue; /* no need to read something */
+ }
+
+ while( MP4_GetTrackPTS( &p_demux->track[i_track] ) <
+ MP4_GetMoviePTS( p_demux ) )
+ {
+
+ pes_packet_t *p_pes;
+
+ /* read a sample */
+ if( !MP4_ReadSample( p_input ,
+ &p_demux->track[i_track],
+ &p_pes ) )
+ {
+ break;
+ }
+
+ /* send it to decoder and update time of this track
+ it also launch a new decoder if needed */
+ MP4_DecodeSample( p_input ,
+ &p_demux->track[i_track],
+ p_pes );
+ }
+
+ }
+
+ /* now check if all tracks are finished or unhandled*/
+
+ for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
+ {
+ if( ( p_demux->track[i_track].b_ok )&&
+ ( p_demux->track[i_track].i_sample < p_demux->track[i_track].i_sample_count )&&
+ ( p_demux->track[i_track].p_es )&&
+ ( p_demux->track[i_track].p_es->p_decoder_fifo ) )
+ {
+ return( 1 );
+ }
+ }
+
+ return( 0 ); /* EOF */
+}
+
+/*****************************************************************************
+ * MP4End: frees unused data
+ *****************************************************************************/
+static void __MP4End ( vlc_object_t * p_this )
+{
+#define FREE( p ) \
+ if( p ) { free( p ); }
+ int i_track;
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ demux_data_mp4_t *p_demux = p_input->p_demux_data;
+
+ msg_Dbg( p_input, "Freeing all memory" );
+ MP4_FreeBox( p_input, &p_demux->box_root );
+ for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
+ {
+ int i_chunk;
+ for( i_chunk = 0;
+ i_chunk < p_demux->track[i_track].i_chunk_count; i_chunk++ )
+ {
+ if( p_demux->track[i_track].chunk )
+ {
+ FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_count_dts);
+ FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_delta_dts );
+ }
+ }
+
+ if( !p_demux->track[i_track].i_sample_size )
+ {
+ FREE( p_demux->track[i_track].p_sample_size );
+ }
+ }
+ FREE( p_demux->track );
+#undef FREE
+}
+
+
+/****************************************************************************
+ * Local functions, specific to vlc
+ ****************************************************************************/
+
+/****************************************************************************
+ * Parse track information and create all needed data to run a track
+ * If it succeed b_ok is set to 1 else to 0
+ ****************************************************************************/
+static void MP4_ParseTrack( input_thread_t *p_input,
+ track_data_mp4_t *p_demux_track,
+ MP4_Box_t * p_trak )
+{
+ int i;
+
+ MP4_Box_t *p_tkhd = MP4_FindBox( p_trak, FOURCC_tkhd );
+ MP4_Box_t *p_tref = MP4_FindBox( p_trak, FOURCC_tref );
+ MP4_Box_t *p_edts = MP4_FindBox( p_trak, FOURCC_edts );
+ MP4_Box_t *p_mdia = MP4_FindBox( p_trak, FOURCC_mdia );
+
+ MP4_Box_t *p_mdhd;
+ MP4_Box_t *p_hdlr;
+ MP4_Box_t *p_minf;
+
+ MP4_Box_t *p_vmhd;
+ MP4_Box_t *p_smhd;
+
+ /* hint track unsuported */
+
+ /* by default, track isn't usable */
+ p_demux_track->b_ok = 0;
+
+ /* by default, we don't known the categorie */
+ p_demux_track->i_cat = UNKNOWN_ES;
+
+ if( ( !p_tkhd )||( !p_mdia ) )
+ {
+ return;
+ }
+
+ /* do we launch this track by default ? */
+ p_demux_track->b_enable = ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
+
+ p_demux_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
+ p_demux_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
+ p_demux_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;
+
+ if( !p_edts )
+ {
+// msg_Warn( p_input, "Unhandled box: edts --> FIXME" );
+ }
+
+ if( !p_tref )
+ {
+// msg_Warn( p_input, "Unhandled box: tref --> FIXME" );
+ }
+
+ p_mdhd = MP4_FindBox( p_mdia, FOURCC_mdhd );
+ p_hdlr = MP4_FindBox( p_mdia, FOURCC_hdlr );
+ p_minf = MP4_FindBox( p_mdia, FOURCC_minf );
+
+ if( ( !p_mdhd )||( !p_hdlr )||( !p_minf ) )
+ {
+ return;
+ }
+
+ p_demux_track->i_timescale = p_mdhd->data.p_mdhd->i_timescale;
+
+ for( i = 0; i < 3; i++ )
+ {
+ p_demux_track->i_language[i] = p_mdhd->data.p_mdhd->i_language[i];
+ }
+
+ switch( p_hdlr->data.p_hdlr->i_handler_type )
+ {
+ case( FOURCC_soun ):
+ if( !( p_smhd = MP4_FindBox( p_minf, FOURCC_smhd ) ) )
+ {
+ return;
+ }
+ p_demux_track->i_cat = AUDIO_ES;
+ break;
+
+ case( FOURCC_vide ):
+ if( !( p_vmhd = MP4_FindBox( p_minf, FOURCC_vmhd ) ) )
+ {
+ return;
+ }
+ p_demux_track->i_cat = VIDEO_ES;
+ break;
+
+ default:
+ return;
+ }
+/* FIXME
+ add support to:
+ p_dinf = MP4_FindBox( p_minf, FOURCC_dinf );
+*/
+ if( !( p_demux_track->p_stbl = MP4_FindBox( p_minf, FOURCC_stbl ) ) )
+ {
+ return;
+ }
+
+ if( !( p_demux_track->p_stsd = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsd ) ) )
+ {
+ return;
+ }
+
+ /* Create chunk index table */
+ if( !MP4_CreateChunksIndex( p_input,p_demux_track ) )
+ {
+ return; /* cannot create chunks index */
+ }
+
+ /* create sample index table needed for reading and seeking */
+ if( !MP4_CreateSamplesIndex( p_input, p_demux_track ) )
+ {
+ return; /* cannot create samples index */
+ }
+
+ p_demux_track->b_ok = 1;
+}
+
+
+
+/* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */
+static int MP4_CreateChunksIndex( input_thread_t *p_input,
+ track_data_mp4_t *p_demux_track )
+{
+ MP4_Box_t *p_co64; /* give offset for each chunk, same for stco and co64 */
+ MP4_Box_t *p_stsc;
+
+ int i_chunk;
+ int i_index, i_last;
+
+
+ if( ( !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stco ) )&&
+ !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_co64 ) ) )||
+ ( !(p_stsc = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsc ) ) ))
+ {
+ return( 0 );
+ }
+
+ p_demux_track->i_chunk_count = p_co64->data.p_co64->i_entry_count;
+ if( !p_demux_track->i_chunk_count )
+ {
+ msg_Warn( p_input, "No chunk defined" );
+ return( 0 );
+ }
+ p_demux_track->chunk = calloc( p_demux_track->i_chunk_count,
+ sizeof( chunk_data_mp4_t ) );
+
+ /* first we read chunk offset */
+ for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
+ {
+ p_demux_track->chunk[i_chunk].i_offset =
+ p_co64->data.p_co64->i_chunk_offset[i_chunk];
+ }
+
+ /* now we read index for SampleEntry( soun vide mp4a mp4v ...)
+ to be used for the sample XXX begin to 1
+ We construct it begining at the end */
+ i_last = p_demux_track->i_chunk_count; /* last chunk proceded */
+ i_index = p_stsc->data.p_stsc->i_entry_count;
+ if( !i_index )
+ {
+ msg_Warn( p_input, "cannot read chunk table or table empty" );
+ return( 0 );
+ }
+
+ while( i_index )
+ {
+ i_index--;
+ for( i_chunk = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
+ i_chunk < i_last; i_chunk++ )
+ {
+ p_demux_track->chunk[i_chunk].i_sample_description_index =
+ p_stsc->data.p_stsc->i_sample_description_index[i_index];
+ p_demux_track->chunk[i_chunk].i_sample_count =
+ p_stsc->data.p_stsc->i_samples_per_chunk[i_index];
+ }
+ i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
+ }
+
+ p_demux_track->chunk[i_chunk].i_sample_first = 0;
+ for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
+ {
+ p_demux_track->chunk[i_chunk].i_sample_first =
+ p_demux_track->chunk[i_chunk-1].i_sample_first +
+ p_demux_track->chunk[i_chunk-1].i_sample_count;
+
+ }
+
+ msg_Dbg( p_input, "read %d chunk", p_demux_track->i_chunk_count );
+ return( 1 );
+
+}
+
+
+
+static int MP4_CreateSamplesIndex( input_thread_t *p_input,
+ track_data_mp4_t *p_demux_track )
+{
+ MP4_Box_t *p_stts; /* makes mapping between sample and decoding time,
+ ctts make same mapping but for composition time,
+ not yet used and probably not usefull */
+ MP4_Box_t *p_stsz; /* gives sample size of each samples, there is also stz2
+ that uses a compressed form FIXME make them in libmp4
+ as a unique type */
+ /* TODO use also stss and stsh table for seeking */
+ /* FIXME use edit table */
+ int i_sample;
+ int i_chunk;
+
+ int i_index;
+ int i_index_sample_used;
+
+ u64 i_last_dts;
+
+ p_stts = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stts );
+ p_stsz = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsz ); /* FIXME and stz2 */
+
+
+ if( ( !p_stts )||( !p_stsz ) )
+ {
+ msg_Warn( p_input, "cannot read sample table" );
+ return( 0 );
+ }
+
+ p_demux_track->i_sample_count = p_stsz->data.p_stsz->i_sample_count;
+
+
+ /* for sample size, there are 2 case */
+ if( p_stsz->data.p_stsz->i_sample_size )
+ {
+ /* 1: all sample have the same size, so no need to construct a table */
+ p_demux_track->i_sample_size = p_stsz->data.p_stsz->i_sample_size;
+ p_demux_track->p_sample_size = NULL;
+ }
+ else
+ {
+ /* 2: each sample can have a different size */
+ p_demux_track->i_sample_size = 0;
+ p_demux_track->p_sample_size =
+ calloc( p_demux_track->i_sample_count, sizeof( u32 ) );
+
+ for( i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )
+ {
+ p_demux_track->p_sample_size[i_sample] =
+ p_stsz->data.p_stsz->i_entry_size[i_sample];
+ }
+ }
+ /* we have extract all information from stsz,
+ now use stts */
+
+ /* if we don't want to waste too much memory, we can't expand
+ the box !, so each chunk will contain an "extract" of this table
+ for fast research */
+
+ i_last_dts = 0;
+ i_index = 0; i_index_sample_used =0;
+ /* create and init last data for each chunk */
+ for(i_chunk = 0 ; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
+ {
+
+ int i_entry, i_sample_count, i;
+ /* save last dts */
+ p_demux_track->chunk[i_chunk].i_first_dts = i_last_dts;
+ /* count how many entries needed for this chunk
+ for p_sample_delta_dts and p_sample_count_dts */
+
+ i_entry = 0;
+ i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
+ while( i_sample_count > 0 )
+ {
+ i_sample_count -= p_stts->data.p_stts->i_sample_count[i_index+i_entry];
+ if( i_entry == 0 )
+ {
+ i_sample_count += i_index_sample_used; /* don't count already used sample
+ int this entry */
+ }
+ i_entry++;
+ }
+ /* allocate them */
+ p_demux_track->chunk[i_chunk].p_sample_count_dts =
+ calloc( i_entry, sizeof( u32 ) );
+ p_demux_track->chunk[i_chunk].p_sample_delta_dts =
+ calloc( i_entry, sizeof( u32 ) );
+
+ /* now copy */
+ i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
+ for( i = 0; i < i_entry; i++ )
+ {
+ int i_used;
+ int i_rest;
+
+ i_rest = p_stts->data.p_stts->i_sample_count[i_index] - i_index_sample_used;
+
+ i_used = __MIN( i_rest, i_sample_count );
+
+ i_index_sample_used += i_used;
+
+ p_demux_track->chunk[i_chunk].p_sample_count_dts[i] = i_used;
+
+ p_demux_track->chunk[i_chunk].p_sample_delta_dts[i] =
+ p_stts->data.p_stts->i_sample_delta[i_index];
+
+ i_last_dts += i_used *
+ p_demux_track->chunk[i_chunk].p_sample_delta_dts[i];
+
+ if( i_index_sample_used >=
+ p_stts->data.p_stts->i_sample_count[i_index] )
+ {
+ i_index++;
+ i_index_sample_used = 0;
+ }
+ }
+
+ }
+
+ msg_Dbg( p_input, "read %d samples", p_demux_track->i_sample_count );
+
+ return( 1 );
+}
+
+static void MP4_StartDecoder( input_thread_t *p_input,
+ track_data_mp4_t *p_demux_track )
+{
+ MP4_Box_t *p_sample;
+ int i;
+ int i_chunk;
+
+ int i_decoder_specific_info_len;
+ u8 *p_decoder_specific_info;
+
+ u8 *p_init;
+
+ MP4_Box_t *p_esds;
+
+
+ if( (!p_demux_track->b_ok )||( p_demux_track->i_cat == UNKNOWN_ES ) )
+ {
+ return;
+ }
+
+ msg_Dbg( p_input, "Starting decoder (track ID 0x%x)",
+ p_demux_track->i_track_ID );
+
+ /* launch decoder according in chunk we are */
+ i_chunk = p_demux_track->i_chunk;
+
+ if( !p_demux_track->chunk[i_chunk].i_sample_description_index )
+ {
+ msg_Warn( p_input,
+ "invalid SampleEntry index (track ID 0x%x)",
+ p_demux_track->i_track_ID );
+ return;
+ }
+
+ p_sample = MP4_FindNbBox( p_demux_track->p_stsd,
+ p_demux_track->chunk[i_chunk].i_sample_description_index - 1);
+
+ if( ( !p_sample )||( !p_sample->data.p_data ) )
+ {
+ msg_Warn( p_input,
+ "cannot find SampleEntry (track ID 0x%x)",
+ p_demux_track->i_track_ID );
+ return;
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_demux_track->p_es = input_AddES( p_input,
+ p_input->stream.p_selected_program,
+ p_demux_track->i_track_ID,
+ 0 );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ /* Initialise ES, first language as description */
+ for( i = 0; i < 3; i++ )
+ {
+ p_demux_track->p_es->psz_desc[i] = p_demux_track->i_language[i];
+ }
+ p_demux_track->p_es->psz_desc[4] = 0;
+
+ p_demux_track->p_es->i_stream_id = p_demux_track->i_track_ID;
+
+ /* It's a little ugly but .. there are special cases */
+ switch( p_sample->i_type )
+ {
+ case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
+ case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
+ break;
+ default:
+ p_demux_track->p_es->i_fourcc = p_sample->i_type;
+ break;
+ }
+
+ p_demux_track->p_es->i_cat = p_demux_track->i_cat;
+
+ i_decoder_specific_info_len = 0;
+ p_decoder_specific_info = NULL;
+
+ /* now see if esds is present and if so create a data packet
+ with decoder_specific_info */
+#define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
+ if( ( p_esds = MP4_FindBox( p_sample, FOURCC_esds ) )&&
+ ( p_esds->data.p_esds )&&
+ ( p_decconfig ) )
+ {
+ /* First update information based on i_objectTypeIndication */
+ switch( p_decconfig->i_objectTypeIndication )
+ {
+ case( 0x20 ): /* MPEG4 VIDEO */
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','v' );
+ break;
+ case( 0x40):
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
+ break;
+ case( 0x60):
+ case( 0x61):
+ case( 0x62):
+ case( 0x63):
+ case( 0x64):
+ case( 0x65): /* MPEG2 video */
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
+ break;
+ /* Theses are MPEG2-AAC (what is this codec ?) */
+ case( 0x66): /* main profile */
+ case( 0x67): /* Low complexity profile */
+ case( 0x68): /* Scaleable Sampling rate profile */
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
+ break;
+ /* true MPEG 2 audio */
+ case( 0x69):
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
+ break;
+ case( 0x6a): /* MPEG1 video */
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
+ break;
+ case( 0x6b): /* MPEG1 audio */
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
+ break;
+ case( 0x6c ): /* jpeg */
+ p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'j','p','e','g' );
+ break;
+ default:
+ /* Unknown entry, but don't touch i_fourcc */
+ msg_Warn( p_input,
+ "objectTypeIndication(0x%x) unknow (Track ID 0x%x)",
+ p_decconfig->i_objectTypeIndication,
+ p_demux_track->i_track_ID );
+ break;
+ }
+ i_decoder_specific_info_len =
+ p_decconfig->i_decoder_specific_info_len;
+ p_decoder_specific_info =
+ p_decconfig->p_decoder_specific_info;
+ }
+
+#undef p_decconfig
+
+ /* some last initialisation */
+ /* XXX I create a bitmapinfoheader_t or
+ waveformatex_t for each stream, up to now it's the best thing
+ I've found but it could exist a better solution :) as something
+ like adding some new fields in p_es ...
+
+ XXX I don't set all values, only thoses that are interesting or known
+ --> bitmapinfoheader_t : width and height
+ --> waveformatex_t : channels, samplerate, bitspersample
+ and at the end I add p_decoder_specific_info
+
+ TODO set more values
+
+ */
+
+ switch( p_demux_track->i_cat )
+ {
+ case( VIDEO_ES ):
+ /* now create a bitmapinfoheader_t for decoder and
+ add information found in p_esds */
+ p_init = malloc( 40 + i_decoder_specific_info_len);
+ memset( p_init, 0, 40 + i_decoder_specific_info_len);
+ MP4_Set4BytesLE( p_init, 40 + i_decoder_specific_info_len );
+ if( p_sample->data.p_sample_vide->i_width )
+ {
+ MP4_Set4BytesLE( p_init + 4,
+ p_sample->data.p_sample_vide->i_width );
+ }
+ else
+ {
+ /* use display size */
+ MP4_Set4BytesLE( p_init + 4, p_demux_track->i_width );
+ }
+ if( p_sample->data.p_sample_vide->i_height )
+ {
+ MP4_Set4BytesLE( p_init + 8,
+ p_sample->data.p_sample_vide->i_height );
+ }
+ else
+ {
+ MP4_Set4BytesLE( p_init + 8, p_demux_track->i_height );
+ }
+ if( i_decoder_specific_info_len )
+ {
+ memcpy( p_init + 40,
+ p_decoder_specific_info,
+ i_decoder_specific_info_len);
+ }
+ break;
+
+ case( AUDIO_ES ):
+ p_init = malloc( 18 + i_decoder_specific_info_len);
+ memset( p_init, 0, 18 + i_decoder_specific_info_len);
+ MP4_Set2BytesLE( p_init + 2, /* i_channel */
+ p_sample->data.p_sample_soun->i_channelcount );
+ MP4_Set4BytesLE( p_init + 4, /* samplepersec */
+ p_sample->data.p_sample_soun->i_sampleratehi );
+ MP4_Set4BytesLE( p_init + 8, /* avgbytespersec */
+ p_sample->data.p_sample_soun->i_channelcount *
+ p_sample->data.p_sample_soun->i_sampleratehi *
+ (p_sample->data.p_sample_soun->i_samplesize/8) );
+ MP4_Set2BytesLE( p_init + 14, /* bits/sample */
+ p_sample->data.p_sample_soun->i_samplesize );
+
+ MP4_Set2BytesLE( p_init + 16, /* i_size, specific info len*/
+ i_decoder_specific_info_len );
+ if( i_decoder_specific_info_len )
+ {
+ memcpy( p_init + 18,
+ p_decoder_specific_info,
+ i_decoder_specific_info_len);
+ }
+ break;
+
+ default:
+ p_init = NULL;
+ break;
+ }
+
+ p_demux_track->p_es->p_demux_data = p_init;
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ input_SelectES( p_input, p_demux_track->p_es );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ p_demux_track->b_ok = 1;
+}
+
+static void MP4_StopDecoder( input_thread_t *p_input,
+ track_data_mp4_t *p_demux_track )
+{
+ msg_Dbg( p_input, "Stopping decoder (track ID 0x%x)",
+ p_demux_track->i_track_ID );
+
+ input_UnselectES( p_input, p_demux_track->p_es );
+ p_demux_track->p_es = NULL;
+}
+
+static int MP4_ReadSample( input_thread_t *p_input,
+ track_data_mp4_t *p_demux_track,
+ pes_packet_t **pp_pes )
+{
+ int i_size;
+ off_t i_pos;
+
+ data_packet_t *p_data;
+
+
+ /* this track have already reach the end */
+ if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
+ {
+ *pp_pes = NULL;
+ return( 0 );
+ }
+ /* caculate size and position for this sample */
+ i_size = p_demux_track->i_sample_size ?
+ p_demux_track->i_sample_size :
+ p_demux_track->p_sample_size[p_demux_track->i_sample];
+ /* TODO */
+ i_pos = MP4_GetTrackPos( p_demux_track );
+
+ /* go,go go ! */
+ if( ! MP4_SeekAbsolute( p_input, i_pos ) )
+ {
+ return( 0 );
+ }
+
+ /* now create a pes */
+ if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
+ {
+ return( 0 );
+ }
+ /* and a data packet for the data */
+ if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
+ {
+ input_DeletePES( p_input->p_method_data, *pp_pes );
+ *pp_pes = NULL;
+ return( 0 );
+ }
+
+ /* initialisation of all the field */
+ (*pp_pes)->i_dts =
+ (*pp_pes)->i_pts = MP4_GetTrackPTS( p_demux_track );
+ (*pp_pes)->p_first = (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data = 1;
+ (*pp_pes)->i_pes_size = i_size;
+
+ if( !i_size )
+ {
+ return( 1 );
+ }
+
+// msg_Dbg( p_input, "will read %d bytes", i_size );
+ if( !MP4_ReadData( p_input, p_data->p_payload_start, i_size ) )
+ {
+ input_DeletePES( p_input->p_method_data, *pp_pes );
+ input_DeletePacket( p_input->p_method_data, p_data );
+ return( 0 );
+ }
+
+ return( 1 );
+}
+
+
+static int MP4_DecodeSample( input_thread_t *p_input,
+ track_data_mp4_t *p_demux_track,
+ pes_packet_t *p_pes )
+{
+
+ if( !p_pes )
+ {
+ return( 0 );
+ }
+
+ /* don't forget to convert in mpeg clock */
+ /* FIXME correct ffmpeg to use dts instead of pts that it incorrect
+ and, set it here ( and correct avi demux ) */
+ p_pes->i_dts =
+ p_pes->i_pts = input_ClockGetTS( p_input,
+ p_input->stream.p_selected_program,
+ p_pes->i_pts * 9/100);
+
+
+ input_DecodePES( p_demux_track->p_es->p_decoder_fifo, p_pes );
+
+ /* now update sample position */
+ p_demux_track->i_sample++; /* easy ;) */
+ if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
+ {
+ /* we have reach end of the track so free decoder stuff */
+ MP4_StopDecoder( p_input, p_demux_track );
+ return( 1 );
+ }
+ /* Have we changed chunk ? */
+ if( p_demux_track->i_sample >=
+ p_demux_track->chunk[p_demux_track->i_chunk].i_sample_first +
+ p_demux_track->chunk[p_demux_track->i_chunk].i_sample_count )
+ {
+ /* we haven't reached the end of the track, so see if we
+ have to change the decoder for the next frame because
+ i_sample_description_index have changed */
+
+ p_demux_track->i_chunk++;
+ if( p_demux_track->chunk[p_demux_track->i_chunk-1].i_sample_description_index
+ != p_demux_track->chunk[p_demux_track->i_chunk].i_sample_description_index )
+ {
+ /* FIXME */
+ msg_Warn( p_input,
+ "SampleEntry have changed, starting a new decoder" );
+ MP4_StopDecoder( p_input, p_demux_track );
+ MP4_StartDecoder( p_input, p_demux_track );
+ }
+ }
+
+
+ return( 1 );
+}
+
+
+
--- /dev/null
+/*****************************************************************************
+ * mp4.h : MP4 file input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: mp4.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+
+
+/*****************************************************************************
+ * Structure needed for decoder
+ *****************************************************************************/
+typedef struct bitmapinfoheader_s
+{
+ u32 i_size; /* size of header 40 + size of data follwoing this header */
+ u32 i_width;
+ u32 i_height;
+ u16 i_planes;
+ u16 i_bitcount;
+ u32 i_compression;
+ u32 i_sizeimage;
+ u32 i_xpelspermeter;
+ u32 i_ypelspermeter;
+ u32 i_clrused;
+ u32 i_clrimportant;
+} bitmapinfoheader_t;
+
+typedef struct waveformatex_s
+{
+ u16 i_format;
+ u16 i_channels;
+ u32 i_samplepersec;
+ u32 i_avgbytespersec;
+ u16 i_blockalign;
+ u16 i_bitspersample;
+ u16 i_size; /* This give size of data
+ imediatly following this header. */
+} waveformatex_t;
+
+/*****************************************************************************
+ * Contain all information about a chunk
+ *****************************************************************************/
+typedef struct chunk_data_mp4_s
+{
+ u64 i_offset; /* absolute position of this chunk in the file */
+ u32 i_sample_description_index; /* index for SampleEntry to use */
+ u32 i_sample_count; /* how many samples in this chunk */
+ u32 i_sample_first; /* index of the first sample in this chunk */
+
+ /* now provide way to calculate pts, dts, and offset without to
+ much memory and with fast acces */
+
+ /* with this we can calculate dts/pts without waste memory */
+ u64 i_first_dts;
+ u32 *p_sample_count_dts;
+ u32 *p_sample_delta_dts; /* dts delta */
+
+ /* TODO if needed add pts
+ but quickly *add* support for edts and seeking */
+
+} chunk_data_mp4_t;
+
+
+/*****************************************************************************
+ * Contain all needed information for read all track with vlc
+ *****************************************************************************/
+typedef struct track_data_mp4_s
+{
+ int b_ok; /* The track is usable */
+ int i_track_ID; /* this should be unique */
+ int b_enable; /* is the trak enable by default */
+
+ int i_cat; /* Type of the track, VIDEO_ES, AUDIO_ES, UNKNOWN_ES ... */
+ char i_language[3];
+
+ /* display size only ! */
+ int i_width;
+ int i_height;
+
+ /* more internal data */
+ u64 i_timescale; /* time scale for this track only */
+
+ /* give the next sample to read, i_chunk is to find quickly where
+ the sample is located */
+ u32 i_sample; /* next sample to read */
+ u32 i_chunk; /* chunk where next sample is stored */
+ /* total count of chunk and sample */
+ u32 i_chunk_count;
+ u32 i_sample_count;
+
+ chunk_data_mp4_t *chunk; /* always defined for each chunk */
+
+ /* sample size, p_sample_size defined only if i_sample_size == 0
+ else i_sample_size is size for all sample */
+ u32 i_sample_size;
+ u32 *p_sample_size; /* XXX perhaps add file offset if take
+ too much time to do sumations each time*/
+
+ es_descriptor_t *p_es; /* vlc es for this track */
+
+ MP4_Box_t *p_stbl; /* will contain all timing information */
+ MP4_Box_t *p_stsd; /* will contain all data to initialize decoder */
+
+ MP4_Box_t *p_sample; /* actual SampleEntry to make life simpler */
+} track_data_mp4_t;
+
+
+/*****************************************************************************
+ *
+ *****************************************************************************/
+typedef struct demux_data_mp4_s
+{
+
+ MP4_Box_t box_root; /* container for the hole file */
+
+ mtime_t i_pcr;
+
+ u64 i_time; /* time position of the presentation in movie timescale */
+ u64 i_timescale; /* movie time scale */
+
+ int i_tracks; /* number of track */
+ track_data_mp4_t *track; /* array of track */
+
+
+} demux_data_mp4_t;
+
+static inline u64 MP4_GetTrackPos( track_data_mp4_t *p_track )
+{
+ int i_sample;
+ u64 i_pos;
+
+
+ i_pos = p_track->chunk[p_track->i_chunk].i_offset;
+
+ if( p_track->i_sample_size )
+ {
+ i_pos += ( p_track->i_sample -
+ p_track->chunk[p_track->i_chunk].i_sample_first ) *
+ p_track->i_sample_size;
+ }
+ else
+ {
+ for( i_sample = p_track->chunk[p_track->i_chunk].i_sample_first;
+ i_sample < p_track->i_sample; i_sample++ )
+ {
+ i_pos += p_track->p_sample_size[i_sample];
+ }
+
+ }
+ return( i_pos );
+}
+
+/* Return time in µs of a track */
+static inline mtime_t MP4_GetTrackPTS( track_data_mp4_t *p_track )
+{
+ int i_sample;
+ int i_index;
+ u64 i_dts;
+
+ i_sample = p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first;
+ i_dts = p_track->chunk[p_track->i_chunk].i_first_dts;
+ i_index = 0;
+ while( i_sample > 0 )
+ {
+ if( i_sample > p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index] )
+ {
+ i_dts += p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index] *
+ p_track->chunk[p_track->i_chunk].p_sample_delta_dts[i_index];
+ i_sample -= p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index];
+ i_index++;
+ }
+ else
+ {
+ i_dts += i_sample *
+ p_track->chunk[p_track->i_chunk].p_sample_delta_dts[i_index];
+ i_sample = 0;
+ break;
+ }
+ }
+ return( (mtime_t)(
+ (mtime_t)1000000 *
+ (mtime_t)i_dts /
+ (mtime_t)p_track->i_timescale ) );
+}
+
+static inline mtime_t MP4_GetMoviePTS(demux_data_mp4_t *p_demux )
+{
+ return( (mtime_t)(
+ (mtime_t)1000000 *
+ (mtime_t)p_demux->i_time /
+ (mtime_t)p_demux->i_timescale )
+ );
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+es_SOURCES = es.c
+ps_SOURCES = ps.c
+ts_SOURCES = ts.c
+ts_dvbpsi_SOURCES = ts.c
+audio_SOURCES = audio.c
--- /dev/null
+/*****************************************************************************
+ * mpeg_audio.c : mpeg_audio Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: audio.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include <sys/types.h>
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+static int Demux ( input_thread_t * );
+
+/* TODO: support MPEG-2.5, not difficult */
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("ISO 13818-3 MPEG I/II audio stream demux" ) );
+ set_capability( "demux", 100 );
+ set_callbacks( Activate, NULL );
+ add_shortcut( "mpegaudio" );
+vlc_module_end();
+
+/*****************************************************************************
+ * Definitions of structures and functions used by this plugins
+ *****************************************************************************/
+
+/* XXX set this to 0 to avoid problem with PS XXX */
+/* but with some file or web radio will failed to detect */
+/* it's you to choose */
+#define MPEGAUDIO_MAXTESTPOS 0
+
+#define MPEGAUDIO_MAXFRAMESIZE 1500 /* no exactly */
+
+typedef struct mpegaudio_format_s
+{
+ u32 i_header;
+ int i_version;
+ int i_layer;
+ int i_crc;
+ int i_bitrate;
+ int i_samplingfreq;
+ int i_padding;
+ int i_extension;
+ int i_mode;
+ int i_modeext;
+ int i_copyright;
+ int i_original;
+ int i_emphasis;
+
+} mpegaudio_format_t;
+
+/* Xing Header if present */
+#define FRAMES_FLAG 0x0001 /* these flags is for i_flags */
+#define BYTES_FLAG 0x0002 /* because all is optionnal */
+#define TOC_FLAG 0x0004
+#define VBR_SCALE_FLAG 0x0008
+typedef struct mpegaudio_xing_header_s
+{
+ int i_flags; /* from Xing header data */
+ int i_frames; /* total bit stream frames from Xing header data */
+ int i_bytes; /* total bit stream bytes from Xing header data */
+ int i_vbr_scale; /* encoded vbr scale from Xing header data */
+ u8 i_toc[100]; /* for seek */
+ int i_avgbitrate; /* calculated, XXX: bits/sec not Kb */
+} mpegaudio_xing_header_t;
+
+typedef struct demux_data_mpegaudio_s
+{
+ mtime_t i_pts;
+
+ int i_framecount;
+
+ es_descriptor_t *p_es;
+ mpegaudio_format_t mpeg;
+ mpegaudio_xing_header_t xingheader;
+
+} demux_data_mpegaudio_t;
+
+
+static int mpegaudio_bitrate[2][3][16] =
+{
+ {
+ { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, /* v1 l1 */
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }, /* v1 l2 */
+ { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 } /* v1 l3 */
+ },
+
+ {
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, /* v2 l1 */
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, /* v2 l2 */
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 } /* v2 l3 */
+ }
+
+};
+
+static int mpegaudio_samplingfreq[2][4] = /* version 1 then 2 */
+{
+ { 44100, 48000, 32000, 0 },
+ { 22050, 24000, 16000, 0 }
+};
+
+static char* mpegaudio_mode[4] =
+{
+ "stereo", "joint stereo", "dual channel", "mono"
+};
+
+static inline u32 __GetDWBE( byte_t *p_buff )
+{
+ return( ( (*(p_buff)) << 24 ) + ( (*(p_buff+1)) << 16 ) +
+ ( (*(p_buff+2)) << 8 ) + ( (*(p_buff+3)) ) );
+}
+
+static int __CheckPS( input_thread_t *p_input )
+{
+ byte_t *p_buff;
+ int i_size = input_Peek( p_input, &p_buff, 8196 );
+
+ while( i_size > 0 )
+ {
+ if( !(*p_buff) && !(*(p_buff + 1))
+ && (*(p_buff + 2) == 1 ) && (*(p_buff + 3) >= 0xB9 ) )
+ {
+ return( 1 ); /* it could be ps so ...*/
+ }
+ p_buff++;
+ i_size--;
+ }
+ return( 0 );
+}
+
+/*
+#define __GetDWBE( p_buff ) \
+ ( ( (*(p_buff)) << 24 ) + ( (*(p_buff+1)) << 16 ) + \
+ ( (*(p_buff+2)) << 8 ) + ( (*(p_buff+3)) ) )
+*/
+/*****************************************************************************
+ * MPEGAudio_CheckHeader : Test the validity of the header
+ *****************************************************************************/
+static int MPEGAudio_CheckHeader( u32 i_header )
+{
+ if( ((( i_header >> 20 )&0x0FFF) != 0x0FFF ) /* header sync */
+ || (((i_header >> 17)&0x03) == 0 ) /* valid layer ?*/
+ || (((i_header >> 12)&0x0F) == 0x0F )
+ || (((i_header >> 12)&0x0F) == 0x00 ) /* valid bitrate ? */
+ || (((i_header >> 10) & 0x03) == 0x03 ) /* valide sampling freq ? */
+ || ((i_header & 0x03) == 0x02 )) /* valid emphasis ? */
+ {
+ return( 0 ); /*invalid */
+ }
+ return( 1 ); /* valid */
+}
+
+/*****************************************************************************
+ * MPEGAudio_ParseHeader : Parse a header ;)
+ *****************************************************************************/
+static void MPEGAudio_ParseHeader( u32 i_header, mpegaudio_format_t *p_mpeg )
+{
+ p_mpeg->i_header = i_header;
+ p_mpeg->i_version = 1 - ( ( i_header >> 19 ) & 0x01 );
+ p_mpeg->i_layer = 3 - ( ( i_header >> 17 ) & 0x03 );
+ p_mpeg->i_crc = 1 - (( i_header >> 16 ) & 0x01);
+ p_mpeg->i_bitrate = mpegaudio_bitrate[p_mpeg->i_version][p_mpeg->i_layer][(i_header>>12)&0x0F];
+ p_mpeg->i_samplingfreq = mpegaudio_samplingfreq[p_mpeg->i_version][(i_header>>10)&0x03];
+ p_mpeg->i_padding = (( i_header >> 9 ) & 0x01);
+ p_mpeg->i_extension = ( i_header >> 7 ) & 0x01;
+ p_mpeg->i_mode = ( i_header >> 6 ) & 0x03;
+ p_mpeg->i_modeext = ( i_header >> 4 ) & 0x03;
+ p_mpeg->i_copyright = ( i_header >> 3 ) & 0x01;
+ p_mpeg->i_original = ( i_header >> 2 ) & 0x01;
+ p_mpeg->i_emphasis = ( i_header ) & 0x03;
+}
+
+/*****************************************************************************
+ * MPEGAudio_FrameSize : give the size of a frame in the mpeg stream
+ *****************************************************************************/
+static int MPEGAudio_FrameSize( mpegaudio_format_t *p_mpeg )
+{
+ /* XXX if crc do i need to add 2 bytes or not? */
+ switch( p_mpeg->i_layer )
+ {
+ case( 0 ):
+ return( ( ( ( !p_mpeg->i_version ? 12000 : 6000 ) *
+ p_mpeg->i_bitrate ) /
+ p_mpeg->i_samplingfreq + p_mpeg->i_padding ) * 4);
+ case( 1 ):
+ case( 2 ):
+ return( ( ( !p_mpeg->i_version ? 144000 : 72000 ) *
+ p_mpeg->i_bitrate ) /
+ p_mpeg->i_samplingfreq + p_mpeg->i_padding );
+ }
+ return( 1024 ); /* must never happen, 1k to advance in stream*/
+}
+
+/*****************************************************************************
+ * MPEGAudio_DecodedFrameSize : give the length of the decoded pcm data
+ *****************************************************************************/
+static int MPEGAudio_DecodedFrameSize( mpegaudio_format_t *p_mpeg )
+{
+ switch( p_mpeg->i_layer )
+ {
+ case( 0 ): /* layer 1 */
+ return( 384);
+ case( 1 ): /* layer 2 */
+ return( 1152 );
+ case( 2 ): /* layer 3 */
+ return( !p_mpeg->i_version ? 1152 : 576 );
+ /* XXX: perhaps we have to /2 for all layer but i'm not sure */
+ }
+ return( 0 );
+}
+
+static int MPEGAudio_SkipID3Tag( input_thread_t *p_input )
+{
+ int count;
+ byte_t *p_peek;
+ byte_t version, revision;
+ int b_footer;
+ int i_size;
+
+ msg_Dbg( p_input, "Checking for ID3 tag" );
+ /* get 10 byte id3 header */
+ if( ( count = input_Peek( p_input, &p_peek, 10 ) ) < 10 )
+ {
+ msg_Err( p_input, "cannot peek()" );
+ return( -1 );
+ }
+/*
+ msg_Info( p_input, "Three first bytes are: %d %d %d",
+ p_peek[0],
+ p_peek[1],
+ p_peek[2]
+ );
+*/
+ if ( !( (p_peek[0] == 0x49) && (p_peek[1] == 0x44) && (p_peek[2] == 0x33)))
+ {
+ return( 0 );
+ }
+
+ version = p_peek[3]; /* These may become usfull later, */
+ revision = p_peek[4]; /* but we ignore them for now */
+
+ b_footer = p_peek[5] & 0x10;
+ i_size = (p_peek[6] << 21) +
+ (p_peek[7] << 14) +
+ (p_peek[8] << 7) +
+ p_peek[9]; //Is this safe?
+ if ( b_footer )
+ {
+ i_size += 10;
+ }
+ i_size += 10;
+ msg_Dbg( p_input, "ID3 tag found, skiping %d bytes", i_size );
+ if ( input_Peek( p_input, &p_peek, i_size ) < i_size )
+ {
+ msg_Err( p_input, "cannot peek()" );
+ return( -1 );
+ }
+
+ p_input->p_current_data += i_size; //seek passed end of ID3 tag
+
+ return (0);
+}
+
+/*****************************************************************************
+ * MPEGAudio_FindFrame : Find a header that could be valid.
+ *****************************************************************************
+ * The idea is to search for 2 consecutive headers that seem valid
+ * Perhaps we can search 2 header with same version or samplefreq(...) to be
+ * more secure but this seems to be enougth
+ *****************************************************************************/
+static int MPEGAudio_FindFrame( input_thread_t *p_input,
+ int *pi_pos,
+ mpegaudio_format_t *p_mpeg,
+ int i_posmax )
+{
+ byte_t *p_buff;
+ u32 i_header;
+ int i_framesize;
+
+ int i_pos = 0;
+ int i_size = input_Peek( p_input, &p_buff, i_posmax+MPEGAUDIO_MAXFRAMESIZE);
+
+ while( i_pos <= __MIN( i_posmax, i_size - 4) )
+ {
+ i_header = __GetDWBE( p_buff );
+ if( MPEGAudio_CheckHeader( i_header ) )
+ {
+ MPEGAudio_ParseHeader( i_header, p_mpeg );
+ i_framesize = MPEGAudio_FrameSize( p_mpeg );
+ if( i_pos + i_framesize + 4 > i_size )
+ {
+ *pi_pos = i_pos;
+ return( 1 );
+ }
+ else
+ {
+ if( MPEGAudio_CheckHeader( __GetDWBE( p_buff + i_framesize ) ) )
+ {
+ *pi_pos = i_pos;
+ return( 2 );
+ }
+ }
+ }
+ p_buff++;
+ i_pos++;
+ }
+
+ *pi_pos = 0;
+ return( 0 );
+}
+
+/*****************************************************************************
+ * MPEGAudio_ExtractXingHeader : extract a Xing header if exist
+ *****************************************************************************
+ * It also calcul avgbitrate, using Xing header if present or assume that
+ * the bitrate of the first frame is the same for the all file
+ *****************************************************************************/
+static void MPEGAudio_ExtractXingHeader( input_thread_t *p_input,
+ mpegaudio_xing_header_t *p_xh )
+{
+ int i_pos;
+ int i_size;
+ mpegaudio_format_t mpeg;
+ byte_t *p_buff;
+
+ p_xh->i_flags = 0; /* nothing present */
+ if( !(MPEGAudio_FindFrame( p_input, &i_pos, &mpeg, 2024 )) )
+ {
+ return; /* failed , can't */
+ }
+ p_xh->i_avgbitrate = mpeg.i_bitrate * 1000; /* default */
+
+ /* 1024 is enougth */
+ if( ( i_size = input_Peek( p_input, &p_buff, 1024 + i_pos ) ) < 8 )
+ {
+ return;
+ }
+ p_buff += i_pos;
+
+ /* calculate pos of xing header */
+ if( !mpeg.i_version )
+ {
+ p_buff += mpeg.i_mode != 3 ? 36 : 21;
+ }
+ else
+ {
+ p_buff += mpeg.i_mode != 3 ? 21 : 13;
+ }
+
+ if( (*p_buff != 'X' )||(*(p_buff+1) != 'i' )
+ ||(*(p_buff+2) != 'n' )||(*(p_buff+3) != 'g' ) )
+ {
+ return;
+ }
+ p_buff += 4;
+
+ p_xh->i_flags = __GetDWBE( p_buff );
+ p_buff += 4;
+
+ if( p_xh->i_flags&FRAMES_FLAG )
+ {
+ p_xh->i_frames = __GetDWBE( p_buff );
+ p_buff += 4;
+ }
+ if( p_xh->i_flags&BYTES_FLAG )
+ {
+ p_xh->i_bytes = __GetDWBE( p_buff );
+ p_buff += 4;
+ }
+ if( p_xh->i_flags&TOC_FLAG )
+ {
+ p_input->p_vlc->pf_memcpy( p_xh->i_toc, p_buff, 100 );
+ p_buff += 100;
+ }
+ if( p_xh->i_flags&VBR_SCALE_FLAG )
+ {
+ p_xh->i_vbr_scale = __GetDWBE( p_buff );
+ p_buff += 4;
+ }
+ if( ( p_xh->i_flags&FRAMES_FLAG )&&( p_xh->i_flags&BYTES_FLAG ) )
+ {
+ p_xh->i_avgbitrate =
+ ((u64)p_xh->i_bytes * (u64)8 * (u64)mpeg.i_samplingfreq) /
+ ((u64)p_xh->i_frames * (u64)MPEGAudio_DecodedFrameSize( &mpeg));
+ }
+}
+
+
+/*****************************************************************************
+ * Activate: initializes MPEGaudio structures
+ *****************************************************************************/
+static int Activate( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ demux_data_mpegaudio_t * p_mpegaudio;
+ mpegaudio_format_t mpeg;
+ es_descriptor_t * p_es;
+ int i_pos;
+ int b_forced;
+ input_info_category_t * p_category;
+
+ /* Set the demux function */
+ p_input->pf_demux = Demux;
+
+ /* XXX: i don't know what it's supposed to do, copied from ESInit */
+ /* Initialize access plug-in structures. */
+ if( p_input->i_mtu == 0 )
+ {
+ /* Improve speed. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+ }
+ if( ( *p_input->psz_demux )
+ &&( !strncmp( p_input->psz_demux, "mpegaudio", 10 ) ) )
+ {
+ b_forced = 1;
+ }
+ else
+ {
+ b_forced = 0;
+ }
+
+ if ( MPEGAudio_SkipID3Tag( p_input ) )
+ {
+ return -1;
+ }
+
+ /* check if it can be a ps stream */
+ if( __CheckPS( p_input ) && !b_forced )
+ {
+ return( -1 );
+ }
+
+ /* must be sure that is mpeg audio stream */
+ if( MPEGAudio_FindFrame( p_input,
+ &i_pos,
+ &mpeg,
+ (b_forced ? 2 * MPEGAUDIO_MAXFRAMESIZE :
+ MPEGAUDIO_MAXTESTPOS) )
+ < (b_forced ? 1 : 2) )
+ {
+ msg_Warn( p_input, "MPEGAudio module discarded (no frame found)" );
+ return( -1 );
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( input_InitStream( p_input, 0 ) == -1)
+ {
+ msg_Err( p_input, "cannot init stream" );
+ return( -1 );
+ }
+ if( input_AddProgram( p_input, 0, 0) == NULL )
+ {
+ msg_Err( p_input, "cannot add program" );
+ return( -1 );
+ }
+ p_input->stream.pp_programs[0]->b_is_ok = 0;
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+
+ /* create our ES */
+ p_es = input_AddES( p_input,
+ p_input->stream.p_selected_program,
+ 1, /* id */
+ 0 );
+ if( !p_es )
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ msg_Err( p_input, "out of memory" );
+ return( -1 );
+ }
+ p_es->i_stream_id = 1;
+ p_es->i_fourcc = !mpeg.i_layer ? VLC_FOURCC('m','p','g','a') /* layer 1 */
+ : VLC_FOURCC('m','p','g','a'); /* layer 2 */
+ p_es->i_cat = AUDIO_ES;
+ input_SelectES( p_input, p_es );
+
+ p_input->stream.p_selected_program->b_is_ok = 1;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ /* create p_mpegaudio and init it */
+ p_input->p_demux_data =
+ p_mpegaudio = malloc( sizeof( demux_data_mpegaudio_t ));
+
+ if( !p_mpegaudio )
+ {
+ msg_Err( p_input, "out of memory" );
+ return( -1 );
+ }
+
+ /*input_ClockInit( p_input->stream.p_selected_program );
+ done by AddProgram */
+ p_mpegaudio->p_es = p_es;
+ p_mpegaudio->mpeg = mpeg;
+ p_mpegaudio->i_framecount = 0;
+ p_mpegaudio->i_pts = 0;
+
+ /* parse Xing Header if present */
+ MPEGAudio_ExtractXingHeader( p_input, &p_mpegaudio->xingheader );
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.i_mux_rate = p_mpegaudio->xingheader.i_avgbitrate / 50 / 8;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
+ /* if i don't do that, it don't work correctly but why ??? */
+ if( p_input->stream.b_seekable )
+ {
+ p_input->pf_seek( p_input, 0 );
+ input_AccessReinit( p_input );
+ }
+ /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
+
+ /* all is ok :)) */
+ msg_Dbg( p_input, "audio MPEG-%d layer %d %s %dHz %dKb/s %s",
+ mpeg.i_version + 1,
+ mpeg.i_layer + 1,
+ mpegaudio_mode[mpeg.i_mode],
+ mpeg.i_samplingfreq,
+ p_mpegaudio->xingheader.i_avgbitrate / 1000,
+ p_mpegaudio->xingheader.i_flags ?
+ "VBR (Xing)" : ""
+ );
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_category = input_InfoCategory( p_input, "mpeg" );
+ input_AddInfo( p_category, "input type", "audio MPEG-%d",
+ mpeg.i_version +1 );
+ input_AddInfo( p_category, "layer", "%d", mpeg.i_layer + 1 );
+ input_AddInfo( p_category, "mode", mpegaudio_mode[mpeg.i_mode] );
+ input_AddInfo( p_category, "sample rate", "%dHz", mpeg.i_samplingfreq );
+ input_AddInfo( p_category, "average bitrate", "%dKb/s",
+ p_mpegaudio->xingheader.i_avgbitrate / 1000 );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int Demux( input_thread_t * p_input )
+{
+ int i_pos;
+ int i_toread;
+ pes_packet_t *p_pes;
+ mpegaudio_format_t mpeg;
+ demux_data_mpegaudio_t *p_mpegaudio =
+ (demux_data_mpegaudio_t*) p_input->p_demux_data;
+ /* look for a frame */
+ if( !MPEGAudio_FindFrame( p_input, &i_pos, &mpeg, 4096 ) )
+ {
+ msg_Warn( p_input, "cannot find next frame" );
+ return( 0 );
+ }
+
+ /* if stream has changed */
+ if( ( mpeg.i_version != p_mpegaudio->mpeg.i_version )
+ ||( mpeg.i_layer != p_mpegaudio->mpeg.i_layer )
+ ||( mpeg.i_samplingfreq != p_mpegaudio->mpeg.i_samplingfreq ) )
+ {
+ msg_Dbg( p_input, "stream has changed" );
+ p_mpegaudio->i_framecount = 0;
+ p_mpegaudio->i_pts = 0;
+ }
+
+ input_ClockManageRef( p_input,
+ p_input->stream.p_selected_program,
+ p_mpegaudio->i_pts );
+
+ /* in fact i_pos may be garbage but ... i don't want to skip it
+ it's borring ;) */
+
+ i_toread = MPEGAudio_FrameSize( &mpeg ) + i_pos;
+ /* create one pes */
+ if( !(p_pes = input_NewPES( p_input->p_method_data )) )
+ {
+ msg_Err( p_input, "cannot allocate new PES" );
+ return( -1 );
+ }
+
+ while( i_toread > 0 )
+ {
+ data_packet_t *p_data;
+ int i_read;
+
+ if( (i_read = input_SplitBuffer( p_input, &p_data, i_toread ) ) <= 0 )
+ {
+ break;
+ }
+ if( !p_pes->p_first )
+ {
+ p_pes->p_first = p_data;
+ p_pes->i_nb_data = 1;
+ p_pes->i_pes_size = i_read;
+ }
+ else
+ {
+ p_pes->p_last->p_next = p_data;
+ p_pes->i_nb_data++;
+ p_pes->i_pes_size += i_read;
+ }
+ p_pes->p_last = p_data;
+ i_toread -= i_read;
+ }
+ p_mpegaudio->i_pts = (mtime_t)90000 *
+ (mtime_t)p_mpegaudio->i_framecount *
+ (mtime_t)MPEGAudio_DecodedFrameSize( &mpeg ) /
+ (mtime_t)mpeg.i_samplingfreq;
+ p_pes->i_dts = 0;
+ p_pes->i_pts = input_ClockGetTS( p_input,
+ p_input->stream.p_selected_program,
+ p_mpegaudio->i_pts );
+
+ if( !p_mpegaudio->p_es->p_decoder_fifo )
+ {
+ msg_Err( p_input, "no audio decoder" );
+ input_DeletePES( p_input->p_method_data, p_pes );
+ return( -1 ); /* perhaps not, it's my choice */
+ }
+ else
+ {
+ input_DecodePES( p_mpegaudio->p_es->p_decoder_fifo, p_pes );
+ }
+
+ p_mpegaudio->i_framecount++;
+ p_mpegaudio->mpeg = mpeg;
+
+ return( 1 );
+}
+
+
--- /dev/null
+/*****************************************************************************
+ * mpeg_es.c : Elementary Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: es.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include <sys/types.h>
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define ES_PACKET_SIZE 65536
+#define MAX_PACKETS_IN_FIFO 3
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+static int Demux ( input_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("ISO 13818-1 MPEG Elementary Stream input") );
+ set_capability( "demux", 150 );
+ set_callbacks( Activate, NULL );
+ add_shortcut( "es" );
+vlc_module_end();
+
+/*
+ * Data reading functions
+ */
+
+/*****************************************************************************
+ * Activate: initializes ES structures
+ *****************************************************************************/
+static int Activate( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ es_descriptor_t * p_es;
+ byte_t * p_peek;
+
+ /* Set the demux function */
+ p_input->pf_demux = Demux;
+
+ /* Initialize access plug-in structures. */
+ if( p_input->i_mtu == 0 )
+ {
+ /* Improve speed. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+ }
+
+ /* Have a peep at the show. */
+ if( input_Peek( p_input, &p_peek, 4 ) < 4 )
+ {
+ /* Stream shorter than 4 bytes... */
+ msg_Err( p_input, "cannot peek()" );
+ return( -1 );
+ }
+
+ if( *p_peek || *(p_peek + 1) || *(p_peek + 2) != 1 )
+ {
+ if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "es", 3 ) )
+ {
+ /* User forced */
+ msg_Err( p_input, "this doesn't look like an MPEG ES stream, continuing" );
+ }
+ else
+ {
+ msg_Warn( p_input, "ES module discarded (no startcode)" );
+ return( -1 );
+ }
+ }
+ else if( *(p_peek + 3) > 0xb9 )
+ {
+ if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "es", 3 ) )
+ {
+ /* User forced */
+ msg_Err( p_input, "this seems to be a system stream (PS plug-in ?), but continuing" );
+ }
+ else
+ {
+ msg_Warn( p_input, "ES module discarded (system startcode)" );
+ return( -1 );
+ }
+ }
+
+ if( input_InitStream( p_input, 0 ) == -1 )
+ {
+ return( -1 );
+ }
+ input_AddProgram( p_input, 0, 0 );
+ p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xE0, 0 );
+ p_es->i_stream_id = 0xE0;
+ p_es->i_fourcc = VLC_FOURCC('m','p','g','v');
+ p_es->i_cat = VIDEO_ES;
+ input_SelectES( p_input, p_es );
+ p_input->stream.p_selected_area->i_tell = 0;
+ p_input->stream.p_selected_program->b_is_ok = 1;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int Demux( input_thread_t * p_input )
+{
+ ssize_t i_read;
+ decoder_fifo_t * p_fifo =
+ p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
+ pes_packet_t * p_pes;
+ data_packet_t * p_data;
+
+ if( p_fifo == NULL )
+ {
+ return -1;
+ }
+
+ i_read = input_SplitBuffer( p_input, &p_data, ES_PACKET_SIZE );
+
+ if ( i_read <= 0 )
+ {
+ return i_read;
+ }
+
+ p_pes = input_NewPES( p_input->p_method_data );
+
+ if( p_pes == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ input_DeletePacket( p_input->p_method_data, p_data );
+ return -1;
+ }
+
+ p_pes->i_rate = p_input->stream.control.i_rate;
+ p_pes->p_first = p_pes->p_last = p_data;
+ p_pes->i_nb_data = 1;
+
+ vlc_mutex_lock( &p_fifo->data_lock );
+
+ if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
+ {
+ /* Wait for the decoder. */
+ vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+ }
+ vlc_mutex_unlock( &p_fifo->data_lock );
+
+ if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
+ | (input_ClockManageControl( p_input,
+ p_input->stream.p_selected_program,
+ (mtime_t)0 ) == PAUSE_S) )
+ {
+ msg_Warn( p_input, "synchro reinit" );
+ p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
+ p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
+ }
+
+ input_DecodePES( p_fifo, p_pes );
+
+ return 1;
+}
+
--- /dev/null
+/*****************************************************************************
+ * mpeg_ps.c : Program Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: ps.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include <sys/types.h>
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define PS_READ_ONCE 50
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+static int Demux ( input_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("ISO 13818-1 MPEG Program Stream input") );
+ set_capability( "demux", 100 );
+ set_callbacks( Activate, NULL );
+ add_shortcut( "ps" );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: initializes PS structures
+ *****************************************************************************/
+static int Activate( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ byte_t * p_peek;
+
+ /* Set the demux function */
+ p_input->pf_demux = Demux;
+
+ /* Initialize access plug-in structures. */
+ if( p_input->i_mtu == 0 )
+ {
+ /* Improve speed. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+ }
+
+ /* Have a peep at the show. */
+ if( input_Peek( p_input, &p_peek, 4 ) < 4 )
+ {
+ /* Stream shorter than 4 bytes... */
+ msg_Err( p_input, "cannot peek()" );
+ return( -1 );
+ }
+
+ if( *p_peek || *(p_peek + 1) || *(p_peek + 2) != 1 )
+ {
+ if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "ps", 3 ) )
+ {
+ /* User forced */
+ msg_Err( p_input, "this does not look like an MPEG PS stream, continuing" );
+ }
+ else
+ {
+ msg_Warn( p_input, "this does not look like an MPEG PS stream, "
+ "but continuing anyway" );
+ }
+ }
+ else if( *(p_peek + 3) <= 0xb9 )
+ {
+ if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "ps", 3 ) )
+ {
+ /* User forced */
+ msg_Err( p_input, "this seems to be an elementary stream (ES module?), but continuing" );
+ }
+ else
+ {
+ msg_Warn( p_input, "this seems to be an elementary stream (ES module?), but continuing" );
+ }
+ }
+
+ if( input_InitStream( p_input, sizeof( stream_ps_data_t ) ) == -1 )
+ {
+ return( -1 );
+ }
+ input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
+
+ p_input->stream.p_selected_program =
+ p_input->stream.pp_programs[0] ;
+
+ if( p_input->stream.b_seekable )
+ {
+ stream_ps_data_t * p_demux_data =
+ (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
+
+ /* Pre-parse the stream to gather stream_descriptor_t. */
+ p_input->stream.pp_programs[0]->b_is_ok = 0;
+ p_demux_data->i_PSM_version = EMPTY_PSM_VERSION;
+
+ while( !p_input->b_die && !p_input->b_error
+ && !p_demux_data->b_has_PSM )
+ {
+ ssize_t i_result;
+ data_packet_t * p_data;
+
+ i_result = input_ReadPS( p_input, &p_data );
+
+ if( i_result == 0 )
+ {
+ /* EOF */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.pp_programs[0]->b_is_ok = 1;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ break;
+ }
+ else if( i_result == -1 )
+ {
+ p_input->b_error = 1;
+ break;
+ }
+
+ input_ParsePS( p_input, p_data );
+ input_DeletePacket( p_input->p_method_data, p_data );
+
+ /* File too big. */
+ if( p_input->stream.p_selected_area->i_tell >
+ INPUT_PREPARSE_LENGTH )
+ {
+ break;
+ }
+ }
+ input_AccessReinit( p_input );
+ p_input->pf_seek( p_input, (off_t)0 );
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ if( p_demux_data->b_has_PSM )
+ {
+ /* (The PSM decoder will care about spawning the decoders) */
+ p_input->stream.pp_programs[0]->b_is_ok = 1;
+ }
+#ifdef AUTO_SPAWN
+ else
+ {
+ /* (We have to do it ourselves) */
+ int i_es;
+
+ /* FIXME: we should do multiple passes in case an audio type
+ * is not present */
+ for( i_es = 0;
+ i_es < p_input->stream.pp_programs[0]->i_es_number;
+ i_es++ )
+ {
+#define p_es p_input->stream.pp_programs[0]->pp_es[i_es]
+ switch( p_es->i_fourcc )
+ {
+ case VLC_FOURCC('m','p','g','v'):
+ input_SelectES( p_input, p_es );
+ break;
+
+ case VLC_FOURCC('m','p','g','a'):
+ if( config_GetInt( p_input, "audio-channel" )
+ == (p_es->i_id & 0x1F) ||
+ ( config_GetInt( p_input, "audio-channel" ) < 0
+ && !(p_es->i_id & 0x1F) ) )
+ switch( config_GetInt( p_input, "audio-type" ) )
+ {
+ case -1:
+ case REQUESTED_MPEG:
+ input_SelectES( p_input, p_es );
+ }
+ break;
+
+ case VLC_FOURCC('a','5','2',' '):
+ if( config_GetInt( p_input, "audio-channel" )
+ == ((p_es->i_id & 0xF00) >> 8) ||
+ ( config_GetInt( p_input, "audio-channel" ) < 0
+ && !((p_es->i_id & 0xF00) >> 8) ) )
+ switch( config_GetInt( p_input, "audio-type" ) )
+ {
+ case -1:
+ case REQUESTED_A52:
+ input_SelectES( p_input, p_es );
+ }
+ break;
+
+ case VLC_FOURCC('s','p','u',' '):
+ if( config_GetInt( p_input, "spu-channel" )
+ == ((p_es->i_id & 0x1F00) >> 8) )
+ {
+ input_SelectES( p_input, p_es );
+ }
+ break;
+
+ case VLC_FOURCC('l','p','c','m'):
+ if( config_GetInt( p_input, "audio-channel" )
+ == ((p_es->i_id & 0x1F00) >> 8) ||
+ ( config_GetInt( p_input, "audio-channel" ) < 0
+ && !((p_es->i_id & 0x1F00) >> 8) ) )
+ switch( config_GetInt( p_input, "audio-type" ) )
+ {
+ case -1:
+ case REQUESTED_LPCM:
+ input_SelectES( p_input, p_es );
+ }
+ break;
+ }
+#undef p_es
+ }
+ }
+#endif
+ input_DumpStream( p_input );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+ else
+ {
+ /* The programs will be added when we read them. */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ p_input->stream.pp_programs[0]->b_is_ok = 0;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
+ * packets.
+ *****************************************************************************/
+static int Demux( input_thread_t * p_input )
+{
+ int i;
+
+ for( i = 0; i < PS_READ_ONCE; i++ )
+ {
+ data_packet_t * p_data;
+ ssize_t i_result;
+ i_result = input_ReadPS( p_input, &p_data );
+
+ if( i_result <= 0 )
+ {
+ return( i_result );
+ }
+
+ input_DemuxPS( p_input, p_data );
+ }
+
+ return( i );
+}
+
--- /dev/null
+/*****************************************************************************
+ * mpeg_ts.c : Transport Stream input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: ts.c,v 1.1 2002/08/04 17:23:42 sam Exp $
+ *
+ * Authors: Henri Fallon <henri@via.ecp.fr>
+ * Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include "iso_lang.h"
+
+#if defined MODULE_NAME_IS_ts_dvbpsi
+# ifdef HAVE_DVBPSI_DR_H
+# include <dvbpsi/dvbpsi.h>
+# include <dvbpsi/descriptor.h>
+# include <dvbpsi/pat.h>
+# include <dvbpsi/pmt.h>
+# include <dvbpsi/dr.h>
+# else
+# include "dvbpsi.h"
+# include "descriptor.h"
+# include "tables/pat.h"
+# include "tables/pmt.h"
+# include "descriptors/dr.h"
+# endif
+#endif
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define TS_READ_ONCE 200
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+static int Demux ( input_thread_t * );
+
+#if defined MODULE_NAME_IS_ts
+static void TSDemuxPSI ( input_thread_t *, data_packet_t *,
+ es_descriptor_t *, vlc_bool_t );
+static void TSDecodePAT( input_thread_t *, es_descriptor_t *);
+static void TSDecodePMT( input_thread_t *, es_descriptor_t *);
+#define PSI_CALLBACK TSDemuxPSI
+#elif defined MODULE_NAME_IS_ts_dvbpsi
+static void TS_DVBPSI_DemuxPSI ( input_thread_t *, data_packet_t *,
+ es_descriptor_t *, vlc_bool_t );
+static void TS_DVBPSI_HandlePAT ( input_thread_t *, dvbpsi_pat_t * );
+static void TS_DVBPSI_HandlePMT ( input_thread_t *, dvbpsi_pmt_t * );
+#define PSI_CALLBACK TS_DVBPSI_DemuxPSI
+#endif
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#if defined MODULE_NAME_IS_ts
+ set_description( _("ISO 13818-1 MPEG Transport Stream input") );
+ set_capability( "demux", 160 );
+ add_shortcut( "ts" );
+#elif defined MODULE_NAME_IS_ts_dvbpsi
+ set_description( _("ISO 13818-1 MPEG Transport Stream input (libdvbpsi)") );
+ set_capability( "demux", 170 );
+ add_shortcut( "ts_dvbpsi" );
+#endif
+ set_callbacks( Activate, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: initializes TS structures
+ *****************************************************************************/
+static int Activate( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ es_descriptor_t * p_pat_es;
+ es_ts_data_t * p_demux_data;
+ stream_ts_data_t * p_stream_data;
+ byte_t * p_peek;
+
+ /* Set the demux function */
+ p_input->pf_demux = Demux;
+
+ /* Initialize access plug-in structures. */
+ if( p_input->i_mtu == 0 )
+ {
+ /* Improve speed. */
+ p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+ }
+
+ /* Have a peep at the show. */
+ if( input_Peek( p_input, &p_peek, 1 ) < 1 )
+ {
+ msg_Err( p_input, "cannot peek()" );
+ return( -1 );
+ }
+
+ if( *p_peek != TS_SYNC_CODE )
+ {
+ if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "ts", 3 ) )
+ {
+ /* User forced */
+ msg_Err( p_input, "this does not look like a TS stream, continuing" );
+ }
+ else
+ {
+ msg_Warn( p_input, "TS module discarded (no sync)" );
+ return( -1 );
+ }
+ }
+
+ /* Adapt the bufsize for our only use. */
+ if( p_input->i_mtu != 0 )
+ {
+ /* Have minimum granularity to avoid bottlenecks at the input level. */
+ p_input->i_bufsize = (p_input->i_mtu / TS_PACKET_SIZE) * TS_PACKET_SIZE;
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
+ {
+ return( -1 );
+ }
+
+ p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
+ p_stream_data->i_pat_version = PAT_UNINITIALIZED ;
+
+#ifdef MODULE_NAME_IS_ts_dvbpsi
+ p_stream_data->p_pat_handle = (dvbpsi_handle *)
+ dvbpsi_AttachPAT( (dvbpsi_pat_callback) &TS_DVBPSI_HandlePAT, p_input );
+
+ if( p_stream_data->p_pat_handle == NULL )
+ {
+ msg_Err( p_input, "could not create PAT decoder" );
+ return( -1 );
+ }
+#endif
+
+ /* We'll have to catch the PAT in order to continue
+ * Then the input will catch the PMT and then the others ES
+ * The PAT es is indepedent of any program. */
+ p_pat_es = input_AddES( p_input, NULL,
+ 0x00, sizeof( es_ts_data_t ) );
+ p_demux_data = (es_ts_data_t *)p_pat_es->p_demux_data;
+ p_demux_data->b_psi = 1;
+ p_demux_data->i_psi_type = PSI_IS_PAT;
+ p_demux_data->p_psi_section = malloc(sizeof(psi_section_t));
+ p_demux_data->p_psi_section->b_is_complete = 1;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
+ * packets.
+ *****************************************************************************/
+static int Demux( input_thread_t * p_input )
+{
+ int i_read_once = (p_input->i_mtu ?
+ p_input->i_bufsize / TS_PACKET_SIZE :
+ TS_READ_ONCE);
+ int i;
+
+ for( i = 0; i < i_read_once; i++ )
+ {
+ data_packet_t * p_data;
+ ssize_t i_result;
+
+ i_result = input_ReadTS( p_input, &p_data );
+
+ if( i_result <= 0 )
+ {
+ return( i_result );
+ }
+
+ input_DemuxTS( p_input, p_data, (psi_callback_t) &PSI_CALLBACK );
+ }
+
+ return( i_read_once );
+}
+
+
+#if defined MODULE_NAME_IS_ts
+/*
+ * PSI demultiplexing and decoding without libdvbpsi
+ */
+
+/*****************************************************************************
+ * DemuxPSI : makes up complete PSI data
+ *****************************************************************************/
+static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
+ es_descriptor_t * p_es, vlc_bool_t b_unit_start )
+{
+ es_ts_data_t * p_demux_data;
+
+ p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
+
+#define p_psi (p_demux_data->p_psi_section)
+#define p (p_data->p_payload_start)
+
+ if( b_unit_start )
+ {
+ /* unit_start set to 1 -> presence of a pointer field
+ * (see ISO/IEC 13818 (2.4.4.2) which should be set to 0x00 */
+ if( (u8)p[0] != 0x00 )
+ {
+ msg_Warn( p_input,
+ "non-zero pointer field found, trying to continue" );
+ p+=(u8)p[0];
+ }
+ else
+ {
+ p++;
+ }
+
+ /* This is the begining of a new section */
+
+ if( ((u8)(p[1]) & 0xc0) != 0x80 )
+ {
+ msg_Warn( p_input, "invalid PSI packet" );
+ p_psi->b_trash = 1;
+ }
+ else
+ {
+ p_psi->i_section_length = ((p[1] & 0xF) << 8) | p[2];
+ p_psi->b_section_complete = 0;
+ p_psi->i_read_in_section = 0;
+ p_psi->i_section_number = (u8)p[6];
+
+ if( p_psi->b_is_complete || p_psi->i_section_number == 0 )
+ {
+ /* This is a new PSI packet */
+ p_psi->b_is_complete = 0;
+ p_psi->b_trash = 0;
+ p_psi->i_version_number = ( p[5] >> 1 ) & 0x1f;
+ p_psi->i_last_section_number = (u8)p[7];
+
+ /* We'll write at the begining of the buffer */
+ p_psi->p_current = p_psi->buffer;
+ }
+ else
+ {
+ if( p_psi->b_section_complete )
+ {
+ /* New Section of an already started PSI */
+ p_psi->b_section_complete = 0;
+
+ if( p_psi->i_version_number != (( p[5] >> 1 ) & 0x1f) )
+ {
+ msg_Warn( p_input,
+ "PSI version differs inside same PAT" );
+ p_psi->b_trash = 1;
+ }
+ if( p_psi->i_section_number + 1 != (u8)p[6] )
+ {
+ msg_Warn( p_input,
+ "PSI Section discontinuity, packet lost?" );
+ p_psi->b_trash = 1;
+ }
+ else
+ p_psi->i_section_number++;
+ }
+ else
+ {
+ msg_Warn( p_input, "got unexpected new PSI section" );
+ p_psi->b_trash = 1;
+ }
+ }
+ }
+ } /* b_unit_start */
+
+ if( !p_psi->b_trash )
+ {
+ /* read */
+ if( (p_data->p_payload_end - p) >=
+ ( p_psi->i_section_length - p_psi->i_read_in_section ) )
+ {
+ /* The end of the section is in this TS packet */
+ memcpy( p_psi->p_current, p,
+ (p_psi->i_section_length - p_psi->i_read_in_section) );
+
+ p_psi->b_section_complete = 1;
+ p_psi->p_current +=
+ (p_psi->i_section_length - p_psi->i_read_in_section);
+
+ if( p_psi->i_section_number == p_psi->i_last_section_number )
+ {
+ /* This was the last section of PSI */
+ p_psi->b_is_complete = 1;
+
+ switch( p_demux_data->i_psi_type)
+ {
+ case PSI_IS_PAT:
+ TSDecodePAT( p_input, p_es );
+ break;
+ case PSI_IS_PMT:
+ TSDecodePMT( p_input, p_es );
+ break;
+ default:
+ msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
+ }
+ }
+ }
+ else
+ {
+ memcpy( p_psi->buffer, p, p_data->p_payload_end - p );
+ p_psi->i_read_in_section += p_data->p_payload_end - p;
+
+ p_psi->p_current += p_data->p_payload_end - p;
+ }
+ }
+
+#undef p_psi
+#undef p
+
+ input_DeletePacket( p_input->p_method_data, p_data );
+
+ return ;
+}
+
+/*****************************************************************************
+ * DecodePAT : Decodes Programm association table and deal with it
+ *****************************************************************************/
+static void TSDecodePAT( input_thread_t * p_input, es_descriptor_t * p_es )
+{
+ stream_ts_data_t * p_stream_data;
+ es_ts_data_t * p_demux_data;
+
+ pgrm_descriptor_t * p_pgrm;
+ es_descriptor_t * p_current_es;
+ byte_t * p_current_data;
+
+ int i_section_length, i_program_id, i_pmt_pid;
+ int i_loop, i_current_section;
+
+ vlc_bool_t b_changed = 0;
+
+ p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
+ p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
+
+#define p_psi (p_demux_data->p_psi_section)
+
+ /* Not so fast, Mike ! If the PAT version has changed, we first check
+ * that its content has really changed before doing anything */
+ if( p_stream_data->i_pat_version != p_psi->i_version_number )
+ {
+ int i_programs = p_input->stream.i_pgrm_number;
+
+ p_current_data = p_psi->buffer;
+
+ do
+ {
+ i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
+ p_current_data[2];
+ i_current_section = (u8)p_current_data[6];
+
+ for( i_loop = 0;
+ ( i_loop < (i_section_length - 9) / 4 ) && !b_changed;
+ i_loop++ )
+ {
+ i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
+ | *(p_current_data + i_loop * 4 + 9);
+ i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
+ << 8 )
+ | *(p_current_data + i_loop * 4 + 11);
+
+ if( i_program_id )
+ {
+ if( (p_pgrm = input_FindProgram( p_input, i_program_id ))
+ && (p_current_es = input_FindES( p_input, i_pmt_pid ))
+ && p_current_es->p_pgrm == p_pgrm
+ && p_current_es->i_id == i_pmt_pid
+ && ((es_ts_data_t *)p_current_es->p_demux_data)->b_psi
+ && ((es_ts_data_t *)p_current_es->p_demux_data)
+ ->i_psi_type == PSI_IS_PMT )
+ {
+ i_programs--;
+ }
+ else
+ {
+ b_changed = 1;
+ }
+ }
+ }
+
+ p_current_data += 3 + i_section_length;
+
+ } while( ( i_current_section < p_psi->i_last_section_number )
+ && !b_changed );
+
+ /* If we didn't find the expected amount of programs, the PAT has
+ * changed. Otherwise, it only changed if b_changed is already != 0 */
+ b_changed = b_changed || i_programs;
+ }
+
+ if( b_changed )
+ {
+ /* PAT has changed. We are going to delete all programs and
+ * create new ones. We chose not to only change what was needed
+ * as a PAT change may mean the stream is radically changing and
+ * this is a secure method to avoid crashes */
+ es_ts_data_t * p_es_demux;
+ pgrm_ts_data_t * p_pgrm_demux;
+
+ p_current_data = p_psi->buffer;
+
+ /* Delete all programs */
+ while( p_input->stream.i_pgrm_number )
+ {
+ input_DelProgram( p_input, p_input->stream.pp_programs[0] );
+ }
+
+ do
+ {
+ i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
+ p_current_data[2];
+ i_current_section = (u8)p_current_data[6];
+
+ for( i_loop = 0; i_loop < (i_section_length - 9) / 4 ; i_loop++ )
+ {
+ i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
+ | *(p_current_data + i_loop * 4 + 9);
+ i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
+ << 8 )
+ | *(p_current_data + i_loop * 4 + 11);
+
+ /* If program = 0, we're having info about NIT not PMT */
+ if( i_program_id )
+ {
+ /* Add this program */
+ p_pgrm = input_AddProgram( p_input, i_program_id,
+ sizeof( pgrm_ts_data_t ) );
+
+ /* whatis the PID of the PMT of this program */
+ p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
+ p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
+
+ /* Add the PMT ES to this program */
+ p_current_es = input_AddES( p_input, p_pgrm,(u16)i_pmt_pid,
+ sizeof( es_ts_data_t) );
+ p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
+ p_es_demux->b_psi = 1;
+ p_es_demux->i_psi_type = PSI_IS_PMT;
+
+ p_es_demux->p_psi_section =
+ malloc( sizeof( psi_section_t ) );
+ p_es_demux->p_psi_section->b_is_complete = 0;
+ }
+ }
+
+ p_current_data += 3 + i_section_length;
+
+ } while( i_current_section < p_psi->i_last_section_number );
+
+ /* Go to the beginning of the next section */
+ p_stream_data->i_pat_version = p_psi->i_version_number;
+
+ }
+#undef p_psi
+
+}
+
+/*****************************************************************************
+ * DecodePMT : decode a given Program Stream Map
+ * ***************************************************************************
+ * When the PMT changes, it may mean a deep change in the stream, and it is
+ * careful to delete the ES and add them again. If the PMT doesn't change,
+ * there no need to do anything.
+ *****************************************************************************/
+static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
+{
+
+ pgrm_ts_data_t * p_pgrm_data;
+ es_ts_data_t * p_demux_data;
+
+ p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
+ p_pgrm_data = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;
+
+#define p_psi (p_demux_data->p_psi_section)
+
+ if( p_psi->i_version_number != p_pgrm_data->i_pmt_version )
+ {
+ es_descriptor_t * p_new_es;
+ es_ts_data_t * p_es_demux;
+ byte_t * p_current_data, * p_current_section;
+ int i_section_length,i_current_section;
+ int i_prog_info_length, i_loop;
+ int i_es_info_length, i_pid, i_stream_type;
+
+ p_current_section = p_psi->buffer;
+ p_current_data = p_psi->buffer;
+
+ p_pgrm_data->i_pcr_pid = ( ((u32)*(p_current_section + 8) & 0x1F) << 8 ) |
+ *(p_current_section + 9);
+
+
+ /* Lock stream information */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ /* Delete all ES in this program except the PSI. We start from the
+ * end because i_es_number gets decremented after each deletion. */
+ for( i_loop = p_es->p_pgrm->i_es_number ; i_loop ; )
+ {
+ i_loop--;
+ p_es_demux = (es_ts_data_t *)
+ p_es->p_pgrm->pp_es[i_loop]->p_demux_data;
+ if ( ! p_es_demux->b_psi )
+ {
+ input_DelES( p_input, p_es->p_pgrm->pp_es[i_loop] );
+ }
+ }
+
+ /* Then add what we received in this PMT */
+ do
+ {
+ i_section_length = ( ((u32)*(p_current_data + 1) & 0xF) << 8 ) |
+ *(p_current_data + 2);
+ i_current_section = (u8)p_current_data[6];
+ i_prog_info_length = ( ((u32)*(p_current_data + 10) & 0xF) << 8 ) |
+ *(p_current_data + 11);
+
+ /* For the moment we ignore program descriptors */
+ p_current_data += 12 + i_prog_info_length;
+
+ /* The end of the section, before the CRC is at
+ * p_current_section + i_section_length -1 */
+ while( p_current_data < p_current_section + i_section_length -1 )
+ {
+ i_stream_type = (int)p_current_data[0];
+ i_pid = ( ((u32)*(p_current_data + 1) & 0x1F) << 8 ) |
+ *(p_current_data + 2);
+ i_es_info_length = ( ((u32)*(p_current_data + 3) & 0xF) << 8 ) |
+ *(p_current_data + 4);
+
+ /* Add this ES to the program */
+ p_new_es = input_AddES( p_input, p_es->p_pgrm,
+ (u16)i_pid, sizeof( es_ts_data_t ) );
+
+ /* Tell the interface what kind of stream it is and select
+ * the required ones */
+ {
+ switch( i_stream_type )
+ {
+ case MPEG1_VIDEO_ES:
+ case MPEG2_VIDEO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
+ p_new_es->i_cat = VIDEO_ES;
+ break;
+ case MPEG1_AUDIO_ES:
+ case MPEG2_AUDIO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
+ p_new_es->i_cat = AUDIO_ES;
+ break;
+ case LPCM_AUDIO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
+ p_new_es->i_stream_id = 0xBD;
+ p_new_es->i_cat = AUDIO_ES;
+ break;
+ case A52_AUDIO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
+ p_new_es->i_stream_id = 0xBD;
+ p_new_es->i_cat = AUDIO_ES;
+ break;
+ /* Not sure this one is fully specification-compliant */
+ case DVD_SPU_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
+ p_new_es->i_stream_id = 0xBD;
+ p_new_es->i_cat = SPU_ES;
+ break;
+ default :
+ p_new_es->i_fourcc = 0;
+ p_new_es->i_cat = UNKNOWN_ES;
+ break;
+ }
+ }
+
+ p_current_data += 5 + i_es_info_length;
+ }
+
+ /* Go to the beginning of the next section*/
+ p_current_data += 3 + i_section_length;
+
+ p_current_section++;
+
+ } while( i_current_section < p_psi->i_last_section_number );
+
+ p_pgrm_data->i_pmt_version = p_psi->i_version_number;
+
+ /* if no program is selected :*/
+ if( !p_input->stream.p_selected_program )
+ {
+ pgrm_descriptor_t * p_pgrm_to_select;
+ u16 i_id = (u16)config_GetInt( p_input, "program" );
+
+ if( i_id != 0 ) /* if user specified a program */
+ {
+ p_pgrm_to_select = input_FindProgram( p_input, i_id );
+
+ if( p_pgrm_to_select && p_pgrm_to_select == p_es->p_pgrm )
+ p_input->pf_set_program( p_input, p_pgrm_to_select );
+ }
+ else
+ p_input->pf_set_program( p_input, p_es->p_pgrm );
+ }
+
+ /* inform interface that stream has changed */
+ p_input->stream.b_changed = 1;
+ /* Remove lock */
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+
+#undef p_psi
+}
+
+#elif defined MODULE_NAME_IS_ts_dvbpsi
+/*
+ * PSI Decoding using libdvbcss
+ */
+
+/*****************************************************************************
+ * DemuxPSI : send the PSI to the right libdvbpsi decoder
+ *****************************************************************************/
+static void TS_DVBPSI_DemuxPSI( input_thread_t * p_input,
+ data_packet_t * p_data,
+ es_descriptor_t * p_es,
+ vlc_bool_t b_unit_start )
+{
+ es_ts_data_t * p_es_demux_data;
+ pgrm_ts_data_t * p_pgrm_demux_data;
+ stream_ts_data_t * p_stream_demux_data;
+
+ p_es_demux_data = ( es_ts_data_t * ) p_es->p_demux_data;
+ p_stream_demux_data = ( stream_ts_data_t * ) p_input->stream.p_demux_data;
+
+ switch( p_es_demux_data->i_psi_type)
+ {
+ case PSI_IS_PAT:
+ dvbpsi_PushPacket(
+ ( dvbpsi_handle ) p_stream_demux_data->p_pat_handle,
+ p_data->p_demux_start );
+ break;
+ case PSI_IS_PMT:
+ p_pgrm_demux_data = ( pgrm_ts_data_t * )p_es->p_pgrm->p_demux_data;
+ dvbpsi_PushPacket(
+ ( dvbpsi_handle ) p_pgrm_demux_data->p_pmt_handle,
+ p_data->p_demux_start );
+ break;
+ default:
+ msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
+ }
+
+ input_DeletePacket( p_input->p_method_data, p_data );
+}
+
+/*****************************************************************************
+ * HandlePAT: will treat a PAT returned by dvbpsi
+ *****************************************************************************/
+
+void TS_DVBPSI_HandlePAT( input_thread_t * p_input, dvbpsi_pat_t * p_new_pat )
+{
+ dvbpsi_pat_program_t * p_pgrm;
+ pgrm_descriptor_t * p_new_pgrm;
+ pgrm_ts_data_t * p_pgrm_demux;
+ es_descriptor_t * p_current_es;
+ es_ts_data_t * p_es_demux;
+ stream_ts_data_t * p_stream_data;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
+
+ if ( !p_new_pat->b_current_next ||
+ p_stream_data->i_pat_version == PAT_UNINITIALIZED )
+ {
+ /* Delete all programs */
+ while( p_input->stream.i_pgrm_number )
+ {
+ input_DelProgram( p_input, p_input->stream.pp_programs[0] );
+ }
+
+ /* treat the new programs list */
+ p_pgrm = p_new_pat->p_first_program;
+
+ while( p_pgrm )
+ {
+ /* If program = 0, we're having info about NIT not PMT */
+ if( p_pgrm->i_number )
+ {
+ /* Add this program */
+ p_new_pgrm = input_AddProgram( p_input, p_pgrm->i_number,
+ sizeof( pgrm_ts_data_t ) );
+
+ p_pgrm_demux = (pgrm_ts_data_t *)p_new_pgrm->p_demux_data;
+ p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
+
+ /* Add the PMT ES to this program */
+ p_current_es = input_AddES( p_input, p_new_pgrm,
+ (u16) p_pgrm->i_pid,
+ sizeof( es_ts_data_t) );
+ p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
+ p_es_demux->b_psi = 1;
+ p_es_demux->i_psi_type = PSI_IS_PMT;
+
+ p_es_demux->p_psi_section = malloc( sizeof( psi_section_t ) );
+ if ( p_es_demux->p_psi_section == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ p_input->b_error = 1;
+ return;
+ }
+
+ p_es_demux->p_psi_section->b_is_complete = 0;
+
+ /* Create a PMT decoder */
+ p_pgrm_demux->p_pmt_handle = (dvbpsi_handle *)
+ dvbpsi_AttachPMT( p_pgrm->i_number,
+ (dvbpsi_pmt_callback) &TS_DVBPSI_HandlePMT,
+ p_input );
+
+ if( p_pgrm_demux->p_pmt_handle == NULL )
+ {
+ msg_Err( p_input, "could not create PMT decoder" );
+ p_input->b_error = 1;
+ return;
+ }
+
+ }
+ p_pgrm = p_pgrm->p_next;
+ }
+
+ p_stream_data->i_pat_version = p_new_pat->i_version;
+ }
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+}
+
+/*****************************************************************************
+ * HandlePMT: will treat a PMT returned by dvbpsi
+ *****************************************************************************/
+void TS_DVBPSI_HandlePMT( input_thread_t * p_input, dvbpsi_pmt_t * p_new_pmt )
+{
+ dvbpsi_pmt_es_t * p_es;
+ pgrm_descriptor_t * p_pgrm;
+ es_descriptor_t * p_new_es;
+ pgrm_ts_data_t * p_pgrm_demux;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ p_pgrm = input_FindProgram( p_input, p_new_pmt->i_program_number );
+
+ if( p_pgrm == NULL )
+ {
+ msg_Warn( p_input, "PMT of unreferenced program found" );
+ return;
+ }
+
+ p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
+ p_pgrm_demux->i_pcr_pid = p_new_pmt->i_pcr_pid;
+
+ if( !p_new_pmt->b_current_next ||
+ p_pgrm_demux->i_pmt_version == PMT_UNINITIALIZED )
+ {
+ p_es = p_new_pmt->p_first_es;
+ while( p_es )
+ {
+ /* Add this ES */
+ p_new_es = input_AddES( p_input, p_pgrm,
+ (u16)p_es->i_pid, sizeof( es_ts_data_t ) );
+ if( p_new_es == NULL )
+ {
+ msg_Err( p_input, "could not add ES %d", p_es->i_pid );
+ p_input->b_error = 1;
+ return;
+ }
+
+ switch( p_es->i_type )
+ {
+ case MPEG1_VIDEO_ES:
+ case MPEG2_VIDEO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
+ p_new_es->i_cat = VIDEO_ES;
+ break;
+ case MPEG1_AUDIO_ES:
+ case MPEG2_AUDIO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
+ p_new_es->i_cat = AUDIO_ES;
+ break;
+ case LPCM_AUDIO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
+ p_new_es->i_cat = AUDIO_ES;
+ p_new_es->i_stream_id = 0xBD;
+ break;
+ case A52_AUDIO_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
+ p_new_es->i_cat = AUDIO_ES;
+ p_new_es->i_stream_id = 0xBD;
+ break;
+ case DVD_SPU_ES:
+ p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
+ p_new_es->i_cat = SPU_ES;
+ p_new_es->i_stream_id = 0xBD;
+ break;
+ default:
+ p_new_es->i_fourcc = 0;
+ p_new_es->i_cat = UNKNOWN_ES;
+ }
+
+ if( ( p_new_es->i_cat == AUDIO_ES )
+ || (p_new_es->i_cat == SPU_ES ) )
+ {
+ dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
+ while( p_dr && ( p_dr->i_tag != 0x0a ) )
+ p_dr = p_dr->p_next;
+ if( p_dr )
+ {
+ dvbpsi_iso639_dr_t *p_decoded =
+ dvbpsi_DecodeISO639Dr( p_dr );
+ if( p_decoded->i_code_count > 0 )
+ {
+ const iso639_lang_t * p_iso;
+ p_iso = GetLang_2T(p_decoded->i_iso_639_code);
+ if(p_iso)
+ {
+ if(p_iso->psz_native_name[0])
+ strcpy( p_new_es->psz_desc,
+ p_iso->psz_native_name );
+ else
+ strcpy( p_new_es->psz_desc,
+ p_iso->psz_eng_name );
+ }
+ else
+ {
+ strncpy( p_new_es->psz_desc,
+ p_decoded->i_iso_639_code, 3 );
+ }
+ }
+ }
+ switch( p_es->i_type )
+ {
+ case MPEG1_AUDIO_ES:
+ case MPEG2_AUDIO_ES:
+ strcat( p_new_es->psz_desc, " (mpeg)" );
+ break;
+ case LPCM_AUDIO_ES:
+ strcat( p_new_es->psz_desc, " (lpcm)" );
+ break;
+ case A52_AUDIO_ES:
+ strcat( p_new_es->psz_desc, " (A52)" );
+ break;
+ }
+ }
+
+ p_es = p_es->p_next;
+ }
+
+ /* if no program is selected :*/
+ if( !p_input->stream.p_selected_program )
+ {
+ pgrm_descriptor_t * p_pgrm_to_select;
+ u16 i_id = (u16)config_GetInt( p_input, "program" );
+
+ if( i_id != 0 ) /* if user specified a program */
+ {
+ p_pgrm_to_select = input_FindProgram( p_input, i_id );
+
+ if( p_pgrm_to_select && p_pgrm_to_select == p_pgrm )
+ p_input->pf_set_program( p_input, p_pgrm_to_select );
+ }
+ else
+ p_input->pf_set_program( p_input, p_pgrm );
+ }
+ /* if the pmt belongs to the currently selected program, we
+ * reselect it to update its ES */
+ else if( p_pgrm == p_input->stream.p_selected_program )
+ {
+ p_input->pf_set_program( p_input, p_pgrm );
+ }
+
+ p_pgrm_demux->i_pmt_version = p_new_pmt->i_version;
+ p_input->stream.b_changed = 1;
+ }
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+}
+#endif
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+/*****************************************************************************
+ * aout.cpp: BeOS audio output
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: AudioOutput.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <kernel/OS.h>
+#include <View.h>
+#include <Application.h>
+#include <Message.h>
+#include <Locker.h>
+#include <media/MediaDefs.h>
+#include <game/PushGameSound.h>
+#include <malloc.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+/*****************************************************************************
+ * aout_sys_t: BeOS audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes some BeOS specific variables.
+ *****************************************************************************/
+struct aout_sys_t
+{
+ BPushGameSound * p_sound;
+ gs_audio_format * p_format;
+ void * p_buffer;
+ int i_buffer_size;
+ int i_buffer_pos;
+};
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/*****************************************************************************
+ * OpenAudio: opens a BPushGameSound
+ *****************************************************************************/
+int E_(OpenAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_aout->p_sys = (aout_sys_t*) malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Allocate gs_audio_format */
+ p_aout->p_sys->p_format = (gs_audio_format *) malloc( sizeof( gs_audio_format ) );
+ if( p_aout->p_sys->p_format == NULL )
+ {
+ free( p_aout->p_sys );
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Initialize some variables */
+ p_aout->p_sys->p_format->frame_rate = 44100.0;
+ p_aout->p_sys->p_format->channel_count = p_aout->i_channels;
+ p_aout->p_sys->p_format->format = gs_audio_format::B_GS_S16;
+ p_aout->p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
+ p_aout->p_sys->p_format->buffer_size = 4*8192;
+ p_aout->p_sys->i_buffer_pos = 0;
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ /* Allocate BPushGameSound */
+ p_aout->p_sys->p_sound = new BPushGameSound( 8192,
+ p_aout->p_sys->p_format,
+ 2, NULL );
+ if( p_aout->p_sys->p_sound == NULL )
+ {
+ free( p_aout->p_sys->p_format );
+ free( p_aout->p_sys );
+ msg_Err( p_aout, "cannot allocate BPushGameSound" );
+ return( 1 );
+ }
+
+ if( p_aout->p_sys->p_sound->InitCheck() != B_OK )
+ {
+ free( p_aout->p_sys->p_format );
+ free( p_aout->p_sys );
+ msg_Err( p_aout, "cannot initialize BPushGameSound" );
+ return( 1 );
+ }
+
+ p_aout->p_sys->p_sound->StartPlaying( );
+
+ p_aout->p_sys->p_sound->LockForCyclic( &p_aout->p_sys->p_buffer,
+ (size_t *)&p_aout->p_sys->i_buffer_size );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: sets the dsp output format
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ /* Each value is 4 bytes long (stereo signed 16 bits) */
+ int i_hard_pos = 4 * p_aout->p_sys->p_sound->CurrentPosition();
+
+ i_hard_pos = p_aout->p_sys->i_buffer_pos - i_hard_pos;
+ if( i_hard_pos < 0 )
+ {
+ i_hard_pos += p_aout->p_sys->i_buffer_size;
+ }
+
+ return( i_hard_pos );
+}
+
+/*****************************************************************************
+ * Play: plays a sound samples buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes in the dsp
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ int i_newbuf_pos;
+
+ if( (i_newbuf_pos = p_aout->p_sys->i_buffer_pos + i_size)
+ > p_aout->p_sys->i_buffer_size )
+ {
+ memcpy( (void *)((int)p_aout->p_sys->p_buffer
+ + p_aout->p_sys->i_buffer_pos),
+ buffer,
+ p_aout->p_sys->i_buffer_size - p_aout->p_sys->i_buffer_pos );
+
+ memcpy( (void *)((int)p_aout->p_sys->p_buffer),
+ buffer + p_aout->p_sys->i_buffer_size - p_aout->p_sys->i_buffer_pos,
+ i_size - ( p_aout->p_sys->i_buffer_size
+ - p_aout->p_sys->i_buffer_pos ) );
+
+ p_aout->p_sys->i_buffer_pos = i_newbuf_pos - p_aout->p_sys->i_buffer_size;
+
+ }
+ else
+ {
+ memcpy( (void *)((int)p_aout->p_sys->p_buffer + p_aout->p_sys->i_buffer_pos),
+ buffer, i_size );
+
+ p_aout->p_sys->i_buffer_pos = i_newbuf_pos;
+ }
+}
+
+/*****************************************************************************
+ * CloseAudio: closes the dsp audio device
+ *****************************************************************************/
+void E_(CloseAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+
+ p_aout->p_sys->p_sound->UnlockCyclic();
+ p_aout->p_sys->p_sound->StopPlaying( );
+ delete p_aout->p_sys->p_sound;
+ free( p_aout->p_sys->p_format );
+ free( p_aout->p_sys );
+}
+
--- /dev/null
+/*****************************************************************************
+ * beos.cpp : BeOS plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: BeOS.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(OpenIntf) ( vlc_object_t * );
+void E_(CloseIntf) ( vlc_object_t * );
+
+int E_(OpenAudio) ( vlc_object_t * );
+void E_(CloseAudio) ( vlc_object_t * );
+
+int E_(OpenVideo) ( vlc_object_t * );
+void E_(CloseVideo) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("BeOS standard API module") );
+ add_submodule();
+ set_capability( "interface", 100 );
+ set_callbacks( E_(OpenIntf), E_(CloseIntf) );
+ add_submodule();
+ set_capability( "video output", 100 );
+ set_callbacks( E_(OpenVideo), E_(CloseVideo) );
+ add_submodule();
+ set_capability( "audio output", 100 );
+ set_callbacks( E_(OpenAudio), E_(CloseAudio) );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * Bitmaps.h
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: Bitmaps.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tcastley@mail.powerup.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+// #include "Bitmaps.h"
+
+const unsigned char eject16x11_raw[] = {
+0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0x00,0x17,0x18,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0x00,0x17,0x17,0x18,0x17,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x00,0x17,0x18,0x17,0x18,0x17,0x17,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x17,0x18,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff};
+const unsigned char pause16x10_raw[] = {
+0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x3f,0x3f,0x3f,0x3f,0xff,0xff,0x00,0x3f,0x3f,0x3f,0x3f,0xff,0xff,0xff,0xff};
+const unsigned char play16x10_raw[] = {
+0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x18,0x17,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x18,0x17,0x18,0x17,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x18,0x17,0x17,0x18,0x17,0x18,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x17,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x17,0x17,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+const unsigned char skipleft24x8_raw[] = {
+0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x17,0x3f,
+0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x17,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0x00,0x00,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0x00,0x00,0x17,0x18,0x17,
+0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x17,0x17,0x18,0x17,0x17,0x3f,
+0xff,0x00,0x00,0x17,0x18,0x17,0x18,0x17,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x3f,0x3f,0x17,0x17,0x18,0x17,0x17,0x3f,0xff,0x3f,0x3f,0x17,0x17,0x18,0x17,0x17,
+0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0x17,0x17,0x18,0x3f,
+0xff,0xff,0xff,0x3f,0x3f,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0x3f,0x3f,0x17,0x3f,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0x17,
+0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+const unsigned char skipright24x8_raw[] = {
+0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x17,0x00,0x00,0xff,0xff,0xff,0xff,
+0xff,0x00,0x18,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x00,0x00,0xff,0xff,0xff,0x00,0x18,0x17,0x17,0x00,0x00,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x17,0x17,0x18,0x17,0x17,0x00,0x00,
+0xff,0x00,0x17,0x18,0x17,0x17,0x18,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x17,0x17,0x3f,0x3f,0xff,0x00,0x17,0x18,0x17,0x18,0x17,0x3f,
+0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0x3f,0xff,0xff,
+0xff,0x00,0x17,0x18,0x17,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x00,0x17,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0x00,0x17,0x3f,0x3f,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+const unsigned char skiptrackleft24x8_raw[] = {
+0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x3f,0xff,0xff,0xff,0xff,0xff,0x00,
+0x00,0x17,0x3f,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x17,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x3f,0xff,0xff,0xff,0x00,0x00,0x17,0x18,0x17,0x3f,0xff,0xff,0xff,0x00,0x00,
+0x17,0x18,0x17,0x3f,0xff,0xff,0xff,0xff,0x00,0x3f,0xff,0x00,0x00,0x17,0x18,0x17,
+0x18,0x17,0x3f,0xff,0x00,0x00,0x17,0x18,0x17,0x18,0x17,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x3f,0xff,0x3f,0x3f,0x17,0x17,0x18,0x17,0x17,0x3f,0xff,0x3f,0x3f,0x17,0x17,
+0x18,0x17,0x17,0x3f,0xff,0xff,0xff,0xff,0x00,0x3f,0xff,0xff,0xff,0x3f,0x3f,0x17,
+0x17,0x18,0x3f,0xff,0xff,0xff,0x3f,0x3f,0x17,0x17,0x18,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x3f,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0x17,0x3f,0xff,0xff,0xff,0xff,0xff,
+0x3f,0x3f,0x17,0x3f,0xff,0xff,0xff,0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0xff,0xff,0xff,0xff};
+const unsigned char skiptrackright24x8_raw[] = {
+0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x17,0x00,0x00,0xff,0xff,0xff,0xff,
+0xff,0x00,0x18,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x00,0x00,0xff,0xff,0xff,0x00,0x18,0x17,0x17,0x00,0x00,0xff,
+0xff,0xff,0x00,0x3f,0xff,0xff,0xff,0xff,0x00,0x17,0x17,0x18,0x17,0x17,0x00,0x00,
+0xff,0x00,0x17,0x18,0x17,0x17,0x18,0x00,0x00,0xff,0x00,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x17,0x18,0x17,0x17,0x3f,0x3f,0xff,0x00,0x17,0x18,0x17,0x18,0x17,0x3f,
+0x3f,0xff,0x00,0x3f,0xff,0xff,0xff,0xff,0x00,0x17,0x17,0x18,0x3f,0x3f,0xff,0xff,
+0xff,0x00,0x17,0x18,0x17,0x3f,0x3f,0xff,0xff,0xff,0x00,0x3f,0xff,0xff,0xff,0xff,
+0x00,0x17,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0x00,0x17,0x3f,0x3f,0xff,0xff,0xff,
+0xff,0xff,0x00,0x3f,0xff,0xff,0xff,0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f,0xff,0xff,0xff,0xff};
+const unsigned char stop8x8_raw[] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x3f,
+0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x3f,0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x3f,
+0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x3f,0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x3f,
+0x00,0x17,0x17,0x18,0x17,0x17,0x18,0x3f,0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};
+const unsigned char LCDLarge96x16_raw[] = {
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x8d,0x21,0x21,0x22,0x21,0x8d,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0x21,
+0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0x21,0x21,0x8d,0xff,0xff,0xff,0xff,0x8d,0x22,
+0x21,0x8d,0x21,0x21,0x22,0x21,0x8d,0xff,0x22,0x8d,0x21,0x21,0x22,0x21,0x8d,0xff,
+0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0x21,0x21,0x8d,0x21,0x22,0x21,0x21,0x8d,0x22,
+0x21,0x8d,0x21,0x22,0x21,0x21,0x8d,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0xff,0x22,0x8d,0xff,0xff,0xff,0xff,0x8d,0x22,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0x21,
+0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0x21,0x21,0x8d,0x21,0x22,0x21,0x21,0x8d,0x22,
+0x21,0x8d,0x21,0x22,0x21,0x21,0xff,0xff,0x22,0x8d,0x21,0x21,0x22,0x21,0x8d,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0x21,0x8d,0x21,0x21,0x22,0x21,0x8d,0x21,
+0x22,0x8d,0x21,0x21,0x22,0x21,0x8d,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0x8d,0xff,0xff,0xff,0xff,0xff,0xff,0x8d,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x8d,0x22,0x21,0x21,0x21,0x22,0x21,0x8d,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0x8d,0x8d,0x21,0x22,0x21,0x21,0x22,0x21,0x8d,
+0x8d,0x21,0x22,0x21,0x21,0x22,0x21,0x8d,0x8d,0x21,0x21,0x22,0x21,0x21,0x22,0x8d,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x8d,0x22,0x21,0x21,0x21,0x22,0x21,0x8d,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0x8d,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x8d,0xff,0xff,0xff,0xff,0x8d,0x22,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0x21,0x8d,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0x21,0x8d,0xff,0xff,0xff,0xff,0x8d,0x22,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0x21,0x8d,0xff,0xff,0xff,0xff,0x8d,0x22,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x8d,0x21,0x21,0x22,0x21,0x8d,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0x21,0x8d,0x21,0x21,0x22,0x21,0xff,0xff,
+0xff,0xff,0x22,0x21,0x21,0x22,0x8d,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,
+0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0x21,0x21,0x8d,0x21,0x22,0x21,0x21,0x8d,0x22,
+0xff,0xff,0xff,0xff,0xff,0xff,0x8d,0x22,0x21,0x8d,0x21,0x21,0x22,0x21,0x8d,0x21,
+0xff,0x8d,0x22,0x21,0x21,0x22,0x8d,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,
+0xff,0x22,0x21,0x21,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+const unsigned char LCDMedium64x9_raw[] = {
+0xff,0xff,0xff,0xff,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0x34,0xff,0xff,0xff,0x34,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0x34,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x34,0x34,0x34,0xff,0x8d,0xff,0xff,0xff,0x8d,0xff,0xff,0xff,0xff,0x8d,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0x8d,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0x34,0x34,
+0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0x34,0x34,0x34,0xff,0xff,0x34,0x34,0x34,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+};
+const unsigned char LCDsmall64x8_raw[] = {
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0x22,0xff,
+0x22,0x21,0x21,0xff,0xff,0x22,0x21,0x21,0xff,0x22,0xff,0xff,0xff,0x22,0xff,0x22,
+0x21,0x21,0xff,0xff,0x22,0x21,0x21,0xff,0x22,0x21,0x21,0x22,0xff,0xff,0x22,0x21,
+0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,
+0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0x22,0x21,0xff,
+0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,
+0xff,0x22,0x21,0xff,0xff,0xff,0x22,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,
+0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,0xff,0x22,0x21,0xff,
+0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,
+0xff,0x22,0x21,0xff,0xff,0xff,0x22,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x22,0x21,0x21,0xff,0x8d,0xff,0xff,0xff,0x8d,0xff,0xff,0xff,0xff,0x8d,0xff,
+0x22,0x21,0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0x22,
+0x21,0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0x8d,0xff,0x22,0x21,
+0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,
+0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,0xff,
+0xff,0xff,0x22,0x21,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,
+0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,0xff,
+0xff,0xff,0x22,0x21,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,
+0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,0xff,
+0xff,0xff,0x22,0x21,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0x22,0x21,0xff,0xff,
+0xff,0x22,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0x22,0xff,
+0x22,0x21,0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0x22,
+0x21,0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0x22,0x21,
+0x21,0xff,0xff,0x22,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+};
+
+const int32 kSpeakerIconBitmapWidth = 16;
+const int32 kSpeakerIconBitmapHeight = 9;
+const BPoint kSpeakerButtonSize(kSpeakerIconBitmapWidth - 1, kSpeakerIconBitmapHeight - 1);
+
+
+const unsigned char kSpeakerIconBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0x10,0x10,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff,0xff,
+ 0x10,0x10,0x10,0xff,0x10,0x1d,0x10,0xff,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff,
+ 0x10,0x1d,0x10,0x10,0x1d,0x1d,0x10,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff,0xff,
+ 0x10,0x1d,0x10,0x1d,0x1d,0x1d,0x10,0xff,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff,
+ 0x10,0x1d,0x10,0x1d,0x1d,0x1d,0x10,0xff,0x10,0xff,0x10,0xff,0xff,0x10,0xff,0xff,
+ 0x10,0x1d,0x10,0x1d,0x1d,0x1d,0x10,0xff,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff,
+ 0x10,0x1d,0x10,0x10,0x1d,0x1d,0x10,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff,0xff,
+ 0x10,0x10,0x10,0xff,0x10,0x1d,0x10,0xff,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x10,0x10,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff,0xff,
+};
+
+const unsigned char kPressedSpeakerIconBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,
+ 0x34,0x34,0x34,0xff,0x34,0x1d,0x34,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,
+ 0x34,0x1d,0x34,0x34,0x1d,0x1d,0x34,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,0xff,
+ 0x34,0x1d,0x34,0x1d,0x1d,0x1d,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,
+ 0x34,0x1d,0x34,0x1d,0x1d,0x1d,0x34,0xff,0x34,0xff,0x34,0xff,0xff,0x34,0xff,0xff,
+ 0x34,0x1d,0x34,0x1d,0x1d,0x1d,0x34,0xff,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,
+ 0x34,0x1d,0x34,0x34,0x1d,0x1d,0x34,0xff,0xff,0x34,0xff,0xff,0x34,0xff,0xff,0xff,
+ 0x34,0x34,0x34,0xff,0x34,0x1d,0x34,0xff,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x34,0x34,0xff,0xff,0xff,0xff,0x34,0xff,0xff,0xff,0xff,
+};
+
+
+// #pragma mark play
+
+const int32 kPlayPauseBitmapWidth = 48;
+const int32 kPlayPauseBitmapHeight = 22;
+const BPoint kPlayButtonSize(kPlayPauseBitmapWidth - 1, kPlayPauseBitmapHeight - 1);
+
+const unsigned char kPlayButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12,0x19,0xff,0xff,0xff,
+ 0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff,
+ 0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,
+ 0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,
+ 0xff,0x14,0x11,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,
+ 0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,
+ 0xff,0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff,
+ 0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff,
+ 0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c,0xff,
+ 0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19,0x3f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kDisabledPlayButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,
+ 0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1b,0x19,0x18,0x18,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0x1a,
+ 0x19,0x18,0x19,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,
+ 0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18,0x1a,0x1c,
+ 0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a,
+ 0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x16,
+ 0x16,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,
+ 0x16,0x1b,0x1b,0x1b,0x16,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x16,0x16,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,
+ 0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,
+ 0x19,0x1c,0xff,0xff,0x19,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x16,0x16,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,
+ 0x19,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x16,
+ 0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19,0x16,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,
+ 0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x18,0x18,0x1c,0xff,0xff,0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x1c,0x1c,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,
+ 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,
+ 0x19,0x19,0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x16,0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x1a,0x18,0x19,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1a,0x17,0x1a,0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18,0x1c,0x1c,
+ 0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1a,0x19,0x17,0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x19,0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,
+ 0x17,0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,
+ 0x18,0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18,0x1b,0x1c,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1a,0x19,0x17,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x19,0x1a,0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,0x1d,
+ 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,
+};
+
+
+const unsigned char kPressedPlayButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19,
+ 0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,
+ 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a,
+ 0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const unsigned char kPlayingPlayButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,
+ 0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19,
+ 0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,
+ 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,
+ 0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,
+ 0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x00,
+ 0x00,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,
+ 0x00,0x10,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x00,0x00,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,
+ 0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,
+ 0x13,0xff,0xff,0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x00,0x00,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,
+ 0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,
+ 0x34,0x34,0x34,0x34,0x34,0x34,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x00,
+ 0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,0x10,0x1d,0x19,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,
+ 0x34,0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,
+ 0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,
+ 0x13,0x10,0x3f,0xff,0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x3f,0x3f,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,
+ 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,
+ 0x34,0x34,0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff,0xff,0x17,0x11,0x13,
+ 0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x3f,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,
+ 0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x14,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c,
+ 0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,
+ 0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,
+ 0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,
+ 0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,
+ 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,
+};
+
+
+const unsigned char kPressedPlayingPlayButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19,
+ 0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,
+ 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a,
+ 0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,
+ 0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x00,0x00,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x10,0x13,
+ 0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,
+ 0x13,0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x00,0x00,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,
+ 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,
+ 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,
+ 0x34,0x34,0x34,0x34,0x34,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x34,
+ 0x34,0x34,0x34,0x00,0x00,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,
+ 0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x19,
+ 0x19,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,
+ 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x00,0x34,0x34,0x34,0x34,0x34,0x19,0x19,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x34,
+ 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,
+ 0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x12,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x19,0x19,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x10,
+ 0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c,
+ 0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,
+ 0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,
+ 0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,
+ 0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,
+ 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,
+};
+
+const unsigned char kPausedPlayButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12,0x19,0xff,0xff,0xff,
+ 0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff,
+ 0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,
+ 0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,
+ 0xff,0x14,0x11,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,
+ 0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,
+ 0xff,0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff,
+ 0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff,
+ 0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c,0xff,
+ 0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19,0x3f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const unsigned char kPressedPausedPlayButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19,
+ 0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,
+ 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a,
+ 0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,
+ 0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x10,0x13,
+ 0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,
+ 0x13,0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34,0x34,
+ 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,
+ 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,
+ 0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x19,
+ 0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x19,
+ 0x19,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34,
+ 0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x00,0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,
+ 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34,
+ 0x19,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x12,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x19,0x19,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x10,
+ 0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c,
+ 0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,
+ 0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,
+ 0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,
+ 0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,
+ 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,
+};
+
+// #pragma mark stop
+
+const int32 kStopBitmapWidth = 32;
+const int32 kStopBitmapHeight = 22;
+const BPoint kStopButtonSize(kStopBitmapWidth - 1, kStopBitmapHeight - 1);
+
+
+const unsigned char kStopButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,
+ 0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,
+ 0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12,
+ 0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,
+ 0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,
+ 0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,
+ 0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,
+ 0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,
+ 0xff,0xff,0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10,0x3f,0x19,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,
+ 0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,
+ 0xff,0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,0x10,0x19,0x19,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,
+ 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,
+ 0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x16,0x12,0x16,0x1e,0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff,0xff,
+ 0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,
+ 0x10,0x16,0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,
+ 0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19,
+ 0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,
+};
+
+
+const unsigned char kDisabledStopButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,
+ 0x1a,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,
+ 0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,
+ 0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18,0x18,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1c,0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19,
+ 0x18,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x18,
+ 0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,
+ 0x1c,0xff,0xff,0x19,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,
+ 0xff,0xff,0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x16,0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,0xff,0x19,0x16,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,
+ 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a,0x1c,0xff,0xff,
+ 0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,
+ 0x18,0x18,0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17,0x1b,0x1c,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x19,0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17,0x1a,
+ 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18,0x18,
+ 0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x18,0x17,0x18,0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1c,0x1c,0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a,0x1c,0x1c,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1d,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,
+};
+
+
+const unsigned char kPressedStopButtonBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,
+ 0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,0x12,
+ 0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,
+ 0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,
+ 0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13,
+ 0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,0x0d,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,
+ 0xff,0xff,0x13,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,0x1e,0xff,0xff,
+ 0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x0f,0x16,0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,
+ 0xff,0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,0x19,
+ 0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,
+};
+
+// #pragma mark rewind
+
+const int32 kRewindBitmapWidth = 40;
+const int32 kRewindBitmapHeight = 22;
+const BPoint kSkipButtonSize(kRewindBitmapWidth - 1, kRewindBitmapHeight - 1);
+
+const unsigned char kRewindBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12,0x19,0xff,0xff,0xff,
+ 0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff,
+ 0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,
+ 0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,
+ 0xff,0x14,0x11,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,
+ 0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,
+ 0xff,0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x00,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x00,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff,
+ 0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff,
+ 0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c,0xff,
+ 0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19,0x3f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kDisabledRewindBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a,
+ 0x1a,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18,
+ 0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,
+ 0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,
+ 0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,
+ 0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x19,0x1c,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x19,0x16,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b,0x1b,0x16,0x16,0x19,
+ 0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x16,0x16,0x19,0x19,0x19,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x16,0x16,0x19,0x19,
+ 0x19,0x19,0x19,0x1c,0x1b,0x16,0x16,0x19,0x19,0x19,0x19,0x19,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19,
+ 0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1c,0x1c,0x19,
+ 0x19,0x19,0x19,0x19,0x1c,0x1b,0x1c,0x1c,0x19,0x19,0x19,0x19,0x19,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,
+ 0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b,0x1b,
+ 0x1c,0x1c,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1c,0x1c,0x19,0x19,
+ 0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,
+ 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1c,0x1c,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,
+ 0x1c,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,
+ 0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a,
+ 0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18,
+ 0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17,
+ 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x18,0x19,0x1a,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17,
+ 0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18,
+ 0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18,
+ 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,
+ 0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a,
+ 0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kPressedRewindBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,0x12,0x19,0xff,0xff,0xff,
+ 0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a,0xff,0xff,
+ 0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,
+ 0xff,0x17,0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,
+ 0xff,0x14,0x11,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,
+ 0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,
+ 0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x00,0x00,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x00,0x00,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x19,0x19,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x19,0x19,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x19,0x19,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x19,0x19,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff,
+ 0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,0x1e,0xff,
+ 0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c,0xff,
+ 0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,
+ 0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,0x19,0x3f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+// #pragma mark skip back
+
+const unsigned char kSkipBackBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,
+ 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,
+ 0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x17,
+ 0x17,0x3f,0x1a,0x00,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17,
+ 0x17,0x17,0x3f,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,
+ 0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x3f,0x3f,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,
+ 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,
+ 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const unsigned char kDisabledSkipBackBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a,
+ 0x1a,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18,
+ 0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,
+ 0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1c,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x19,0x16,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,
+ 0x1c,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1c,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1c,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19,
+ 0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1c,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,
+ 0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1c,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,
+ 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1c,0x1c,0x1b,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,
+ 0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a,
+ 0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18,
+ 0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17,
+ 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x18,0x19,0x1a,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17,
+ 0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18,
+ 0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18,
+ 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,
+ 0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a,
+ 0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kPressedSkipBackBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,
+ 0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,
+ 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x10,0x19,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x10,
+ 0x10,0x10,0x19,0x13,0x13,0x13,0x00,0x00,0x10,0x10,0x10,0x19,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x10,0x10,
+ 0x10,0x10,0x10,0x19,0x13,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x19,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x10,
+ 0x10,0x10,0x10,0x10,0x19,0x13,0x19,0x19,0x10,0x10,0x10,0x10,0x10,
+ 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x19,0x19,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x19,0x19,0x10,0x10,
+ 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x19,0x19,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x19,
+ 0x19,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kSkippingSkipBackBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,
+ 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x34,0x34,
+ 0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x34,0x34,0x3f,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x34,0x34,0x34,
+ 0x34,0x3f,0x1a,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x3f,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x34,0x34,0x34,
+ 0x34,0x34,0x3f,0x1a,0x3f,0x3f,0x34,0x34,0x34,0x34,0x34,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,
+ 0x34,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x34,0x34,0x34,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x3f,0x3f,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x34,
+ 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,
+ 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kPressedSkippingSkipBackBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,
+ 0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,
+ 0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x19,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,
+ 0x34,0x34,0x19,0x13,0x13,0x13,0x00,0x00,0x34,0x34,0x34,0x19,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x34,
+ 0x34,0x34,0x34,0x19,0x13,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x19,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x34,
+ 0x34,0x34,0x34,0x34,0x19,0x13,0x19,0x19,0x34,0x34,0x34,0x34,0x34,
+ 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x19,0x19,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x19,0x19,0x34,0x34,
+ 0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x19,0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x19,
+ 0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+// #pragma mark skip forward
+
+const unsigned char kSkipForwardBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,
+ 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00,
+ 0x00,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,
+ 0x17,0x17,0x00,0x00,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x00,0x00,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,
+ 0x17,0x17,0x17,0x3f,0x3f,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,
+ 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,
+ 0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x3f,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,
+ 0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x3f,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,
+ 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kDisabledSkipForwardBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a,
+ 0x1a,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18,
+ 0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,
+ 0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x16,0x16,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x16,0x19,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x19,0x16,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x16,
+ 0x16,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x16,0x16,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,
+ 0x19,0x19,0x16,0x16,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x16,0x16,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19,
+ 0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,
+ 0x19,0x19,0x19,0x1c,0x1c,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x1c,
+ 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,0xff,
+ 0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,
+ 0x19,0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x1c,0x1c,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,
+ 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,
+ 0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x1c,0x1c,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,
+ 0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a,
+ 0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18,
+ 0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17,
+ 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x18,0x19,0x1a,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
+ 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17,
+ 0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18,
+ 0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+ 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18,
+ 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,
+ 0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a,
+ 0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kPressedSkipForwardBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00,
+ 0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,
+ 0x10,0x00,0x00,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x00,0x00,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,
+ 0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x00,0x10,0x10,0x10,0x10,0x10,
+ 0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,
+ 0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x00,0x10,0x10,0x10,0x10,
+ 0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x00,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x00,0x10,0x10,0x10,
+ 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x00,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x19,
+ 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kSkippingSkipForwardBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,
+ 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x00,0x00,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x00,0x34,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x00,
+ 0x00,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x00,0x00,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,
+ 0x34,0x34,0x00,0x00,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x00,0x00,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,
+ 0x34,0x34,0x34,0x3f,0x3f,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x3f,
+ 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,
+ 0x34,0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x3f,0x3f,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,
+ 0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x3f,0x3f,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,
+ 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,
+ 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,
+ 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+
+const unsigned char kPressedSkippingSkipForwardBitmapBits [] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,
+ 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x00,0x00,
+ 0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x00,0x00,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,
+ 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34,
+ 0x34,0x00,0x00,0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x00,0x00,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,
+ 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,
+ 0x34,0x34,0x34,0x34,0x00,0x00,0x13,0x00,0x34,0x34,0x34,0x34,0x34,
+ 0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,
+ 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,
+ 0x34,0x34,0x34,0x34,0x34,0x19,0x19,0x13,0x00,0x34,0x34,0x34,0x34,
+ 0x34,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,
+ 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x00,0x34,0x34,0x34,0x19,0x19,0x13,0x13,0x13,0x00,0x34,0x34,0x34,
+ 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,
+ 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x00,0x34,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x19,
+ 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,
+ 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,
+ 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,
+ 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,
+ 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,
+ 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,
+ 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,
+ 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
--- /dev/null
+/*****************************************************************************
+ * DrawingTidbits.cpp
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: DrawingTidbits.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tcastley@mail.powerup.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <Bitmap.h>
+#include <Debug.h>
+#include <Screen.h>
+
+#include "DrawingTidbits.h"
+
+inline uchar
+ShiftComponent(uchar component, float percent)
+{
+ // change the color by <percent>, make sure we aren't rounding
+ // off significant bits
+ if (percent >= 1)
+ return (uchar)(component * (2 - percent));
+ else
+ return (uchar)(255 - percent * (255 - component));
+}
+
+rgb_color
+ShiftColor(rgb_color color, float percent)
+{
+ rgb_color result = {
+ ShiftComponent(color.red, percent),
+ ShiftComponent(color.green, percent),
+ ShiftComponent(color.blue, percent),
+ 0
+ };
+
+ return result;
+}
+
+static bool
+CompareColors(const rgb_color a, const rgb_color b)
+{
+ return a.red == b.red
+ && a.green == b.green
+ && a.blue == b.blue
+ && a.alpha == b.alpha;
+}
+
+bool
+operator==(const rgb_color &a, const rgb_color &b)
+{
+ return CompareColors(a, b);
+}
+
+bool
+operator!=(const rgb_color &a, const rgb_color &b)
+{
+ return !CompareColors(a, b);
+}
+
+void
+ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to)
+{
+ ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet
+
+ BScreen screen(B_MAIN_SCREEN_ID);
+ uint32 fromIndex = screen.IndexForColor(from);
+ uint32 toIndex = screen.IndexForColor(to);
+
+ uchar *bits = (uchar *)bitmap->Bits();
+ int32 bitsLength = bitmap->BitsLength();
+ for (int32 index = 0; index < bitsLength; index++)
+ if (bits[index] == fromIndex)
+ bits[index] = toIndex;
+}
+
+void
+ReplaceTransparentColor(BBitmap *bitmap, rgb_color with)
+{
+ ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet
+
+ BScreen screen(B_MAIN_SCREEN_ID);
+ uint32 withIndex = screen.IndexForColor(with);
+
+ uchar *bits = (uchar *)bitmap->Bits();
+ int32 bitsLength = bitmap->BitsLength();
+ for (int32 index = 0; index < bitsLength; index++)
+ if (bits[index] == B_TRANSPARENT_8_BIT)
+ bits[index] = withIndex;
+}
+
--- /dev/null
+/*****************************************************************************
+ * DrawingTidbits.h
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: DrawingTidbits.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tcastley@mail.powerup.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#ifndef __DRAWING_TIBITS__
+#define __DRAWING_TIBITS__
+
+#include <GraphicsDefs.h>
+
+rgb_color ShiftColor(rgb_color , float );
+
+bool operator==(const rgb_color &, const rgb_color &);
+bool operator!=(const rgb_color &, const rgb_color &);
+
+inline rgb_color
+Color(int32 r, int32 g, int32 b, int32 alpha = 255)
+{
+ rgb_color result;
+ result.red = r;
+ result.green = g;
+ result.blue = b;
+ result.alpha = alpha;
+
+ return result;
+}
+
+const rgb_color kWhite = { 255, 255, 255, 255};
+const rgb_color kBlack = { 0, 0, 0, 255};
+
+const float kDarkness = 1.06;
+const float kDimLevel = 0.6;
+
+void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to);
+void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with);
+
+#endif
--- /dev/null
+/*****************************************************************************
+ * intf.cpp: beos interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: Interface.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * Tony Castley <tony@castley.net>
+ * Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <InterfaceKit.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include "VlcWrapper.h"
+#include "InterfaceWindow.h"
+
+/*****************************************************************************
+ * Local prototype
+ *****************************************************************************/
+static void Run ( intf_thread_t *p_intf );
+
+/*****************************************************************************
+ * OpenIntf: initialize interface
+ *****************************************************************************/
+int E_(OpenIntf) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ BScreen *screen;
+ screen = new BScreen();
+ BRect rect = screen->Frame();
+ rect.top = rect.bottom-100;
+ rect.bottom -= 50;
+ rect.left += 50;
+ rect.right = rect.left + 350;
+ delete screen;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = (intf_sys_t*) malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return( 1 );
+ }
+// p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
+ p_intf->p_sys->p_input = NULL;
+
+ p_intf->pf_run = Run;
+
+ /* Create the interface window */
+ p_intf->p_sys->p_window =
+ new InterfaceWindow( rect,
+ VOUT_TITLE " (BeOS interface)", p_intf );
+ if( p_intf->p_sys->p_window == 0 )
+ {
+ free( p_intf->p_sys );
+ msg_Err( p_intf, "cannot allocate InterfaceWindow" );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CloseIntf: destroy interface
+ *****************************************************************************/
+void E_(CloseIntf) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+// msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+
+ /* Destroy the interface window */
+ p_intf->p_sys->p_window->Lock();
+ p_intf->p_sys->p_window->Quit();
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+
+/*****************************************************************************
+ * Run: event loop
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ while( !p_intf->b_die )
+ {
+ /* Update the input */
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+ /* Manage the slider */
+ p_intf->p_sys->p_window->updateInterface();
+ }
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input =
+ (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+
+
+
+ /* Wait a bit */
+ msleep( INTF_IDLE_SLEEP );
+ }
+
+}
+
--- /dev/null
+/*****************************************************************************
+ * InterfaceWindow.cpp: beos interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: InterfaceWindow.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * Tony Castley <tony@castley.net>
+ * Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/* System headers */
+#include <kernel/OS.h>
+#include <InterfaceKit.h>
+#include <AppKit.h>
+#include <StorageKit.h>
+#include <SupportKit.h>
+#include <malloc.h>
+#include <scsi.h>
+#include <scsiprobe_driver.h>
+#include <fs_info.h>
+#include <string.h>
+
+
+/* VLC headers */
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/intf.h>
+
+/* BeOS interface headers */
+#include "MsgVals.h"
+#include "MediaControlView.h"
+#include "PlayListWindow.h"
+#include "VlcWrapper.h"
+#include "InterfaceWindow.h"
+
+
+/*****************************************************************************
+ * InterfaceWindow
+ *****************************************************************************/
+
+InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
+ intf_thread_t *p_interface )
+ : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
+ B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
+ | B_ASYNCHRONOUS_CONTROLS )
+{
+ file_panel = NULL;
+ playlist_window = NULL;
+ p_intf = p_interface;
+ p_vlc_wrapper = Intf_VLCWrapper::getVLCWrapper(p_intf);
+ BRect controlRect(0,0,0,0);
+
+ playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ b_empty_playlist = (p_playlist->i_size < 0);
+ b_mute = false;
+
+ /* set the title bar */
+ SetName( "interface" );
+ SetTitle(VOUT_TITLE);
+
+ /* set up the main menu */
+ BMenuBar *menu_bar;
+ menu_bar = new BMenuBar(controlRect, "main menu");
+ AddChild( menu_bar );
+
+ BMenu *mFile;
+ BMenu *mAudio;
+ CDMenu *cd_menu;
+ BMenu *mNavigation;
+
+ /* Add the file Menu */
+ BMenuItem *mItem;
+ menu_bar->AddItem( mFile = new BMenu( "File" ) );
+ menu_bar->ResizeToPreferred();
+ mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
+ new BMessage(OPEN_FILE), 'O') );
+
+ cd_menu = new CDMenu( "Open Disc" );
+ mFile->AddItem( cd_menu );
+
+ mFile->AddSeparatorItem();
+ mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
+ new BMessage(OPEN_PLAYLIST), 'P') );
+
+ mFile->AddSeparatorItem();
+ mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
+ new BMessage(B_ABOUT_REQUESTED), 'A') );
+ mItem->SetTarget( be_app );
+ mFile->AddItem(mItem = new BMenuItem( "Quit",
+ new BMessage(B_QUIT_REQUESTED), 'Q') );
+
+ /* Add the Audio menu */
+ menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
+ menu_bar->ResizeToPreferred();
+ mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
+ mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
+
+ /* Add the Navigation menu */
+ menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) );
+ menu_bar->ResizeToPreferred();
+ mNavigation->AddItem( new BMenuItem( "Prev Title",
+ new BMessage(PREV_TITLE)) );
+ mNavigation->AddItem( new BMenuItem( "Next Title",
+ new BMessage(NEXT_TITLE)) );
+ mNavigation->AddItem( new BMenuItem( "Prev Chapter",
+ new BMessage(PREV_CHAPTER)) );
+ mNavigation->AddItem( new BMenuItem( "Next Chapter",
+ new BMessage(NEXT_CHAPTER)) );
+
+ ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
+ controlRect = Bounds();
+ controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
+
+ p_mediaControl = new MediaControlView( controlRect );
+ p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
+ b_empty_playlist = true;
+ p_mediaControl->SetEnabled( !b_empty_playlist );
+
+ /* Show */
+ AddChild( p_mediaControl );
+ Show();
+
+}
+
+InterfaceWindow::~InterfaceWindow()
+{
+ if (playlist_window) playlist_window->ReallyQuit();
+}
+
+/*****************************************************************************
+ * InterfaceWindow::MessageReceived
+ *****************************************************************************/
+void InterfaceWindow::MessageReceived( BMessage * p_message )
+{
+ int vol_val = p_mediaControl->GetVolume(); // remember the current volume
+ int playback_status; // remember playback state
+ int i_index;
+ BAlert *alert;
+
+ Activate();
+ playback_status = p_vlc_wrapper->inputGetStatus();
+
+ switch( p_message->what )
+ {
+ case B_ABOUT_REQUESTED:
+ alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
+ alert->Go();
+ break;
+
+ case TOGGLE_ON_TOP:
+ break;
+
+ case OPEN_FILE:
+ if( file_panel )
+ {
+ file_panel->Show();
+ break;
+ }
+ file_panel = new BFilePanel();
+ file_panel->SetTarget( this );
+ file_panel->Show();
+ b_empty_playlist = false;
+ p_mediaControl->SetEnabled( !b_empty_playlist );
+ break;
+
+ case OPEN_PLAYLIST:
+ {
+ BRect rect(20,20,320,420);
+ playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ playlist_window = PlayListWindow::getPlayList(rect,
+ "Playlist", p_playlist);
+ playlist_window->Show();
+ }
+ break;
+ case OPEN_DVD:
+ {
+ const char *psz_device;
+ BString type("dvd");
+ if( p_message->FindString("device", &psz_device) != B_ERROR )
+ {
+ BString device(psz_device);
+ p_vlc_wrapper->openDisc(type, device, 0,0);
+ }
+ }
+ break;
+
+ case STOP_PLAYBACK:
+ // this currently stops playback not nicely
+ //p_vlc_wrapper->volume_mute();
+ //snooze( 400000 );
+ p_vlc_wrapper->playlistStop();
+ p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
+ break;
+
+ case START_PLAYBACK:
+ /* starts playing in normal mode */
+
+ case PAUSE_PLAYBACK:
+ /* toggle between pause and play */
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ /* pause if currently playing */
+ if ( playback_status == PLAYING_S )
+ {
+ //p_vlc_wrapper->volume_mute();
+ //snooze( 400000 );
+ p_vlc_wrapper->playlistPause();
+ }
+ else
+ {
+ //p_vlc_wrapper->volume_restore();
+ p_vlc_wrapper->playlistPlay();
+ }
+ }
+ else
+ {
+ /* Play a new file */
+ p_vlc_wrapper->playlistPlay();
+ }
+ break;
+
+ case FASTER_PLAY:
+ /* cycle the fast playback modes */
+ //p_vlc_wrapper->volume_mute();
+ //snooze( 400000 );
+ p_vlc_wrapper->playFaster();
+ break;
+
+ case SLOWER_PLAY:
+ /* cycle the slow playback modes */
+ //p_vlc_wrapper->volume_mute();
+ //snooze( 400000 );
+ p_vlc_wrapper->playSlower();
+ break;
+
+ case SEEK_PLAYBACK:
+ /* handled by semaphores */
+ break;
+
+ case VOLUME_CHG:
+ /* adjust the volume */
+// vlc_mutex_lock( &p_intf->p_sys->p_input->lock );
+// for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
+// {
+// if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
+// {
+// p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
+// }
+// else
+// {
+// p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
+// }
+// }
+// vlc_mutex_unlock( &p_aout_bank->lock );
+ break;
+
+ case VOLUME_MUTE:
+ /* toggle muting */
+ p_vlc_wrapper->toggleMute( );
+ break;
+
+ case SELECT_AUDIO:
+ {
+ int32 i = p_message->FindInt32( "audio" );
+ p_vlc_wrapper->toggleLanguage( i );
+ }
+ break;
+
+ case SELECT_SUBTITLE:
+ {
+ int32 i = p_message->FindInt32( "subtitle" );
+ p_vlc_wrapper->toggleSubtitle( i );
+ }
+ break;
+ case PREV_TITLE:
+ {
+ int i_id;
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
+
+ /* Disallow area 0 since it is used for video_ts.vob */
+ if( i_id > 0 )
+ {
+ p_vlc_wrapper->toggleTitle(i_id);
+ }
+ break;
+ }
+ case NEXT_TITLE:
+ {
+ int i_id;
+
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
+
+ if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
+ {
+ p_vlc_wrapper->toggleTitle(i_id);
+ }
+ }
+ break;
+ case PREV_CHAPTER:
+ {
+ int i_id;
+
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_part - 1;
+
+ if( i_id >= 0 )
+ {
+ p_vlc_wrapper->toggleChapter(i_id);
+ }
+ }
+ break;
+ case NEXT_CHAPTER:
+ {
+ int i_id;
+
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_part + 1;
+
+ if( i_id >= 0 )
+ {
+ p_vlc_wrapper->toggleChapter(i_id);
+ }
+ }
+ break;
+ case B_REFS_RECEIVED:
+ case B_SIMPLE_DATA:
+ {
+ entry_ref ref;
+ BList* files = new BList();
+
+ int i = 0;
+ while( p_message->FindRef( "refs", i, &ref ) == B_OK )
+ {
+ BPath path( &ref );
+
+ files->AddItem(new BString((char*)path.Path()) );
+ i++;
+ }
+ p_vlc_wrapper->openFiles(files);
+ delete files;
+ }
+ break;
+
+ default:
+ BWindow::MessageReceived( p_message );
+ break;
+ }
+
+}
+
+/*****************************************************************************
+ * InterfaceWindow::updateInterface
+ *****************************************************************************/
+void InterfaceWindow::updateInterface()
+{
+
+ if ( p_intf->p_sys->p_input != NULL )
+ {
+ if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
+ {
+ p_vlc_wrapper->setTimeAsFloat(p_mediaControl->GetSeekTo());
+ }
+ else if( Lock() )
+ {
+ p_mediaControl->SetStatus(p_intf->p_sys->p_input->stream.control.i_status,
+ p_intf->p_sys->p_input->stream.control.i_rate);
+ p_mediaControl->SetProgress(p_intf->p_sys->p_input->stream.p_selected_area->i_tell,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_size);
+ Unlock();
+ }
+ }
+
+ playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if ( b_empty_playlist != (p_playlist->i_size < 1) )
+ {
+ if (Lock())
+ {
+ b_empty_playlist = !b_empty_playlist;
+ p_mediaControl->SetEnabled( !b_empty_playlist );
+ Unlock();
+ }
+ }
+}
+
+/*****************************************************************************
+ * InterfaceWindow::QuitRequested
+ *****************************************************************************/
+bool InterfaceWindow::QuitRequested()
+{
+ p_intf->p_vlc->b_die = VLC_TRUE;
+
+ return( true );
+}
+
+/*****************************************************************************
+ * CDMenu::CDMenu
+ *****************************************************************************/
+CDMenu::CDMenu(const char *name)
+ : BMenu(name)
+{
+}
+
+/*****************************************************************************
+ * CDMenu::~CDMenu
+ *****************************************************************************/
+CDMenu::~CDMenu()
+{
+}
+
+/*****************************************************************************
+ * CDMenu::AttachedToWindow
+ *****************************************************************************/
+void CDMenu::AttachedToWindow(void)
+{
+ while (RemoveItem((long int)0) != NULL); // remove all items
+ GetCD("/dev/disk");
+ BMenu::AttachedToWindow();
+}
+
+/*****************************************************************************
+ * CDMenu::GetCD
+ *****************************************************************************/
+int CDMenu::GetCD( const char *directory )
+{
+ BVolumeRoster *volRoster;
+ BVolume *vol;
+ BDirectory *dir;
+ int status;
+ int mounted;
+ char name[B_FILE_NAME_LENGTH];
+ fs_info info;
+ dev_t dev;
+
+ volRoster = new BVolumeRoster();
+ vol = new BVolume();
+ dir = new BDirectory();
+ status = volRoster->GetNextVolume(vol);
+ status = vol->GetRootDirectory(dir);
+ while (status == B_NO_ERROR)
+ {
+ mounted = vol->GetName(name);
+ if ((mounted == B_OK) && /* Disk is currently Mounted */
+ (vol->IsReadOnly()) ) /* Disk is read-only */
+ {
+ dev = vol->Device();
+ fs_stat_dev(dev, &info);
+
+ device_geometry g;
+ int i_dev;
+ i_dev = open( info.device_name, O_RDONLY );
+
+ if( i_dev >= 0 )
+ {
+ if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
+ {
+ if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
+ {
+ BMessage *msg;
+ msg = new BMessage( OPEN_DVD );
+ msg->AddString( "device", info.device_name );
+ BMenuItem *menu_item;
+ menu_item = new BMenuItem( name, msg );
+ AddItem( menu_item );
+ }
+ close(i_dev);
+ }
+ }
+ }
+ vol->Unset();
+ status = volRoster->GetNextVolume(vol);
+ }
+}
+
+/*****************************************************************************
+ * LanguageMenu::LanguageMenu
+ *****************************************************************************/
+LanguageMenu::LanguageMenu(const char *name, int menu_kind,
+ intf_thread_t *p_interface)
+ :BMenu(name)
+{
+ kind = menu_kind;
+ p_intf = p_interface;
+}
+
+/*****************************************************************************
+ * LanguageMenu::~LanguageMenu
+ *****************************************************************************/
+LanguageMenu::~LanguageMenu()
+{
+}
+
+/*****************************************************************************
+ * LanguageMenu::AttachedToWindow
+ *****************************************************************************/
+void LanguageMenu::AttachedToWindow(void)
+{
+ while( RemoveItem((long int)0) != NULL )
+ {
+ ; // remove all items
+ }
+
+ SetRadioMode(true);
+ GetChannels();
+ BMenu::AttachedToWindow();
+}
+
+/*****************************************************************************
+ * LanguageMenu::GetChannels
+ *****************************************************************************/
+int LanguageMenu::GetChannels()
+{
+ char *psz_name;
+ bool b_active;
+ BMessage *msg;
+ int i;
+ es_descriptor_t *p_es = NULL;
+
+ /* Insert the null */
+ if( kind == SPU_ES ) //audio
+ {
+ msg = new BMessage(SELECT_SUBTITLE);
+ msg->AddInt32("subtitle", -1);
+ BMenuItem *menu_item;
+ menu_item = new BMenuItem("None", msg);
+ AddItem(menu_item);
+ menu_item->SetMarked(TRUE);
+
+ }
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return 1;
+ }
+
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ for( i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number; i++ )
+ {
+ if( kind == p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat )
+ {
+ p_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
+ }
+ }
+
+ for( i = 0; i < p_intf->p_sys->p_input->stream.i_es_number; i++ )
+ {
+ if( kind == p_intf->p_sys->p_input->stream.pp_es[i]->i_cat )
+ {
+ psz_name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc;
+ if( kind == AUDIO_ES ) //audio
+ {
+ msg = new BMessage(SELECT_AUDIO);
+ msg->AddInt32("audio", i);
+ }
+ else
+ {
+ msg = new BMessage(SELECT_SUBTITLE);
+ msg->AddInt32("subtitle", i);
+ }
+ BMenuItem *menu_item;
+ menu_item = new BMenuItem(psz_name, msg);
+ AddItem(menu_item);
+ b_active = (p_es == p_intf->p_sys->p_input->stream.pp_es[i]);
+ menu_item->SetMarked(b_active);
+ }
+ }
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+}
+
+
+
--- /dev/null
+/*****************************************************************************
+ * InterfaceWindow.h: BeOS interface window class prototype
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: InterfaceWindow.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Tony Castley <tcastley@mail.powerup.com.au>
+ * Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+/*****************************************************************************
+ * intf_sys_t: description and status of FB interface
+ *****************************************************************************/
+class MediaControlView;
+class PlayListWindow;
+
+class CDMenu : public BMenu
+{
+public:
+ CDMenu(const char *name);
+ ~CDMenu();
+ void AttachedToWindow(void);
+private:
+ int GetCD(const char *directory);
+};
+
+class LanguageMenu : public BMenu
+{
+public:
+ LanguageMenu(const char *name, int menu_kind,
+ intf_thread_t *p_interface);
+ ~LanguageMenu();
+ void AttachedToWindow(void);
+private:
+ intf_thread_t *p_intf;
+ int kind;
+ int GetChannels();
+};
+
+class InterfaceWindow : public BWindow
+{
+public:
+ InterfaceWindow( BRect frame, const char *name,
+ intf_thread_t *p_interface );
+ ~InterfaceWindow();
+
+ // standard window member
+ virtual bool QuitRequested();
+ virtual void MessageReceived(BMessage *message);
+ void updateInterface();
+
+ MediaControlView *p_mediaControl;
+
+private:
+ intf_thread_t *p_intf;
+ bool b_empty_playlist;
+ bool b_mute;
+ BFilePanel *file_panel;
+ PlayListWindow* playlist_window;
+ BMenuItem *miOnTop;
+ Intf_VLCWrapper * p_vlc_wrapper;
+};
+
--- /dev/null
+beos_SOURCES = BeOS.cpp AudioOutput.cpp VideoOutput.cpp Interface.cpp InterfaceWindow.cpp DrawingTidbits.cpp TransportButton.cpp PlayListWindow.cpp MediaControlView.cpp VlcWrapper.cpp
--- /dev/null
+/*****************************************************************************
+ * MediaControlView.cpp: beos interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: MediaControlView.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tony@castley.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/* System headers */
+#include <InterfaceKit.h>
+#include <AppKit.h>
+#include <string.h>
+
+/* VLC headers */
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+/* BeOS interface headers */
+#include "MsgVals.h"
+#include "Bitmaps.h"
+#include "TransportButton.h"
+#include "MediaControlView.h"
+
+
+MediaControlView::MediaControlView( BRect frame )
+ : BBox( frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER )
+{
+ float xStart = HORZ_SPACE;
+ float yStart = VERT_SPACE;
+ fScrubSem = B_ERROR;
+
+ BRect controlRect = BRect(xStart,yStart,
+ frame.Width() - (HORZ_SPACE * 2), 15);
+
+ /* Seek Status */
+ rgb_color fill_color = {0,255,0};
+ p_seek = new SeekSlider(controlRect, this, 0, 100, B_TRIANGLE_THUMB);
+ p_seek->SetValue(0);
+ p_seek->UseFillColor(true, &fill_color);
+ AddChild( p_seek );
+ yStart += 15 + VERT_SPACE;
+
+
+ /* Buttons */
+ /* Slow play */
+ controlRect.SetLeftTop(BPoint(xStart, yStart));
+ controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
+ xStart += kRewindBitmapWidth;
+ p_slow = new TransportButton(controlRect, B_EMPTY_STRING,
+ kSkipBackBitmapBits,
+ kPressedSkipBackBitmapBits,
+ kDisabledSkipBackBitmapBits,
+ new BMessage(SLOWER_PLAY));
+ AddChild( p_slow );
+
+ /* Play Pause */
+ controlRect.SetLeftTop(BPoint(xStart, yStart));
+ controlRect.SetRightBottom(controlRect.LeftTop() + kPlayButtonSize);
+ xStart += kPlayPauseBitmapWidth + 1.0;
+ p_play = new PlayPauseButton(controlRect, B_EMPTY_STRING,
+ kPlayButtonBitmapBits,
+ kPressedPlayButtonBitmapBits,
+ kDisabledPlayButtonBitmapBits,
+ kPlayingPlayButtonBitmapBits,
+ kPressedPlayingPlayButtonBitmapBits,
+ kPausedPlayButtonBitmapBits,
+ kPressedPausedPlayButtonBitmapBits,
+ new BMessage(START_PLAYBACK));
+
+ AddChild( p_play );
+
+ /* Fast Foward */
+ controlRect.SetLeftTop(BPoint(xStart, yStart));
+ controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
+ xStart += kRewindBitmapWidth;
+ p_fast = new TransportButton(controlRect, B_EMPTY_STRING,
+ kSkipForwardBitmapBits,
+ kPressedSkipForwardBitmapBits,
+ kDisabledSkipForwardBitmapBits,
+ new BMessage(FASTER_PLAY));
+ AddChild( p_fast );
+
+ /* Stop */
+ controlRect.SetLeftTop(BPoint(xStart, yStart));
+ controlRect.SetRightBottom(controlRect.LeftTop() + kStopButtonSize);
+ xStart += kStopBitmapWidth;
+ p_stop = new TransportButton(controlRect, B_EMPTY_STRING,
+ kStopButtonBitmapBits,
+ kPressedStopButtonBitmapBits,
+ kDisabledStopButtonBitmapBits,
+ new BMessage(STOP_PLAYBACK));
+ AddChild( p_stop );
+
+ controlRect.SetLeftTop(BPoint(xStart + 5, yStart + 6));
+ controlRect.SetRightBottom(controlRect.LeftTop() + kSpeakerButtonSize);
+ xStart += kSpeakerIconBitmapWidth;
+
+ p_mute = new TransportButton(controlRect, B_EMPTY_STRING,
+ kSpeakerIconBits,
+ kPressedSpeakerIconBits,
+ kSpeakerIconBits,
+ new BMessage(VOLUME_MUTE));
+
+ AddChild( p_mute );
+
+ /* Volume Slider */
+ p_vol = new MediaSlider(BRect(xStart,20,255,30), new BMessage(VOLUME_CHG),
+ 0, VOLUME_MAX);
+ p_vol->SetValue(VOLUME_DEFAULT);
+ p_vol->UseFillColor(true, &fill_color);
+ AddChild( p_vol );
+
+}
+
+MediaControlView::~MediaControlView()
+{
+}
+
+void MediaControlView::MessageReceived(BMessage *message)
+{
+}
+
+void MediaControlView::SetProgress(uint64 seek, uint64 size)
+{
+ p_seek->SetPosition((float)seek/size);
+}
+
+void MediaControlView::SetStatus(int status, int rate)
+{
+ switch( status )
+ {
+ case PLAYING_S:
+ case FORWARD_S:
+ case BACKWARD_S:
+ case START_S:
+ p_play->SetPlaying();
+ break;
+ case PAUSE_S:
+ p_play->SetPaused();
+ break;
+ case UNDEF_S:
+ case NOT_STARTED_S:
+ default:
+ p_play->SetStopped();
+ break;
+ }
+ if ( rate < DEFAULT_RATE )
+ {
+ }
+}
+
+void MediaControlView::SetEnabled(bool enabled)
+{
+ p_slow->SetEnabled(enabled);
+ p_play->SetEnabled(enabled);
+ p_fast->SetEnabled(enabled);
+ p_stop->SetEnabled(enabled);
+ p_mute->SetEnabled(enabled);
+ p_vol->SetEnabled(enabled);
+ p_seek->SetEnabled(enabled);
+}
+
+uint32 MediaControlView::GetSeekTo()
+{
+ return p_seek->seekTo;
+}
+
+uint32 MediaControlView::GetVolume()
+{
+ return p_vol->Value();
+}
+
+
+/*****************************************************************************
+ * MediaSlider
+ *****************************************************************************/
+MediaSlider::MediaSlider( BRect frame, BMessage *p_message,
+ int32 i_min, int32 i_max )
+ :BSlider(frame, NULL, NULL, p_message, i_min, i_max )
+{
+
+}
+
+MediaSlider::~MediaSlider()
+{
+
+}
+
+void MediaSlider::DrawThumb(void)
+{
+ BRect r;
+ BView *v;
+
+ rgb_color black = {0,0,0};
+ r = ThumbFrame();
+ v = OffscreenView();
+
+ if(IsEnabled())
+ {
+ v->SetHighColor(black);
+ }
+ else
+ {
+ v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
+ }
+
+ r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
+ v->StrokeEllipse(r);
+
+ if(IsEnabled())
+ {
+ v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+ }
+ else
+ {
+ v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
+ }
+
+ r.InsetBy(1,1);
+ v->FillEllipse(r);
+}
+
+/*****************************************************************************
+ * SeekSlider
+ *****************************************************************************/
+SeekSlider::SeekSlider( BRect frame, MediaControlView *p_owner, int32 i_min,
+ int32 i_max, thumb_style thumbType = B_TRIANGLE_THUMB )
+ :MediaSlider( frame, NULL, i_min, i_max )
+{
+ fOwner = p_owner;
+ fMouseDown = false;
+}
+
+SeekSlider::~SeekSlider()
+{
+}
+
+/*****************************************************************************
+ * SeekSlider::MouseDown
+ *****************************************************************************/
+void SeekSlider::MouseDown(BPoint where)
+{
+ BSlider::MouseDown(where);
+ seekTo = ValueForPoint(where);
+ fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
+ release_sem(fOwner->fScrubSem);
+ fMouseDown = true;
+}
+
+/*****************************************************************************
+ * SeekSlider::MouseUp
+ *****************************************************************************/
+void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
+{
+ BSlider::MouseMoved(where, code, message);
+ if (!fMouseDown)
+ return;
+ seekTo = ValueForPoint(where);
+ release_sem(fOwner->fScrubSem);
+}
+
+/*****************************************************************************
+ * SeekSlider::MouseUp
+ *****************************************************************************/
+void SeekSlider::MouseUp(BPoint where)
+{
+ BSlider::MouseUp(where);
+ seekTo = ValueForPoint(where);
+ delete_sem(fOwner->fScrubSem);
+ fOwner->fScrubSem = B_ERROR;
+ fMouseDown = false;
+}
--- /dev/null
+/*****************************************************************************
+ * MediaControlView.h: beos interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: MediaControlView.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tony@castley.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+#define HORZ_SPACE 5.0
+#define VERT_SPACE 5.0
+
+
+class TransportButton;
+class PlayPauseButton;
+class MediaSlider;
+class SeekSlider;
+
+class MediaControlView : public BBox
+{
+public:
+ MediaControlView( BRect frame );
+ ~MediaControlView();
+
+ virtual void MessageReceived(BMessage *message);
+ void SetProgress(uint64 seek, uint64 size);
+
+ void SetStatus(int status, int rate);
+ void SetEnabled(bool);
+ uint32 GetSeekTo();
+ uint32 GetVolume();
+ sem_id fScrubSem;
+ bool fSeeking;
+
+private:
+ MediaSlider * p_vol;
+ SeekSlider * p_seek;
+ TransportButton* p_slow;
+ PlayPauseButton* p_play;
+ TransportButton* p_fast;
+ TransportButton* p_stop;
+ TransportButton* p_mute;
+
+ int current_rate;
+ int current_status;
+};
+
+class MediaSlider : public BSlider
+{
+public:
+ MediaSlider(BRect frame,
+ BMessage *message,
+ int32 minValue,
+ int32 maxValue);
+ ~MediaSlider();
+ virtual void DrawThumb(void);
+};
+
+
+class SeekSlider : public MediaSlider
+{
+public:
+ SeekSlider(BRect frame,
+ MediaControlView *owner,
+ int32 minValue,
+ int32 maxValue,
+ thumb_style thumbType = B_TRIANGLE_THUMB);
+
+ ~SeekSlider();
+ uint32 seekTo;
+ virtual void MouseDown(BPoint);
+ virtual void MouseUp(BPoint pt);
+ virtual void MouseMoved(BPoint pt, uint32 c, const BMessage *m);
+private:
+ MediaControlView* fOwner;
+ bool fMouseDown;
+};
+
+
--- /dev/null
+/*****************************************************************************
+ * MsgVals.h
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: MsgVals.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tcastley@mail.powerup.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/* MsgVals.h */
+#define PLAYING 0
+#define PAUSED 1
+
+const uint32 OPEN_FILE = 'OPFL';
+const uint32 OPEN_DVD = 'OPDV';
+const uint32 OPEN_PLAYLIST = 'OPPL';
+const uint32 STOP_PLAYBACK = 'STPL';
+const uint32 START_PLAYBACK = 'PLAY';
+const uint32 PAUSE_PLAYBACK = 'PAPL';
+const uint32 FASTER_PLAY = 'FAPL';
+const uint32 SLOWER_PLAY = 'SLPL';
+const uint32 SEEK_PLAYBACK = 'SEEK';
+const uint32 VOLUME_CHG = 'VOCH';
+const uint32 VOLUME_MUTE = 'MUTE';
+const uint32 SELECT_AUDIO = 'AUDI';
+const uint32 SELECT_SUBTITLE = 'SUBT';
+const uint32 PREV_TITLE = 'PRTI';
+const uint32 NEXT_TITLE = 'NXTI';
+const uint32 PREV_CHAPTER = 'PRCH';
+const uint32 NEXT_CHAPTER = 'NXCH';
+const uint32 TOGGLE_ON_TOP = 'ONTP';
+const uint32 TOGGLE_FULL_SCREEN = 'TGFS';
+const uint32 RESIZE_100 = 'RSOR';
+const uint32 RESIZE_200 = 'RSDB';
+const uint32 ASPECT_CORRECT = 'ASCO';
+const uint32 VERT_SYNC = 'VSYN';
+const uint32 WINDOW_FEEL = 'WFEL';
+
--- /dev/null
+/*****************************************************************************
+ * PlayListWindow.cpp: beos interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: PlayListWindow.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * Tony Castley <tony@castley.net>
+ * Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/* System headers */
+#include <InterfaceKit.h>
+#include <StorageKit.h>
+#include <SupportKit.h>
+#include <string.h>
+
+/* VLC headers */
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+/* BeOS interface headers */
+#include "VlcWrapper.h"
+#include "InterfaceWindow.h"
+#include "MsgVals.h"
+#include "PlayListWindow.h"
+
+/*****************************************************************************
+ * PlayListWindow
+ *****************************************************************************/
+PlayListWindow *PlayListWindow::getPlayList( BRect frame, const char *name,
+ playlist_t *p_pl)
+{
+ static PlayListWindow *one_playlist;
+ if (one_playlist == NULL)
+ {
+ one_playlist = new PlayListWindow(frame, name, p_pl);
+ }
+ return one_playlist;
+}
+
+PlayListWindow::PlayListWindow( BRect frame, const char *name,
+ playlist_t *p_pl)
+ : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
+ B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS )
+{
+ SetName( "playlist" );
+ SetTitle(name);
+ p_playlist = p_pl;
+
+ /* set up the main menu */
+ BMenuBar *menu_bar;
+ menu_bar = new BMenuBar(BRect(0,0,0,0), "main menu");
+ AddChild( menu_bar );
+
+ BMenu *mFile;
+ /* Add the file Menu */
+ BMenuItem *mItem;
+ menu_bar->AddItem( mFile = new BMenu( "File" ) );
+ menu_bar->ResizeToPreferred();
+ mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
+ new BMessage(OPEN_FILE), 'O') );
+
+ CDMenu *cd_menu = new CDMenu( "Open Disc" );
+ mFile->AddItem( cd_menu );
+
+ BRect rect = Bounds();
+ rect.top += menu_bar->Bounds().IntegerHeight() + 1;
+ BView *p_view = new BView(rect, NULL, B_FOLLOW_ALL_SIDES, B_WILL_DRAW);
+
+ p_listview = new BListView(rect, "PlayList",
+ B_MULTIPLE_SELECTION_LIST);
+ for (int i=0; i < p_playlist->i_size; i++)
+ {
+ p_listview->AddItem(new BStringItem(p_playlist->pp_items[i]->psz_name));
+ }
+ p_view->AddChild(new BScrollView("scroll_playlist", p_listview,
+ B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
+
+ AddChild(p_view);
+}
+
+PlayListWindow::~PlayListWindow()
+{
+}
+
+/*****************************************************************************
+ * PlayListWindow::MessageReceived
+ *****************************************************************************/
+void PlayListWindow::MessageReceived( BMessage * p_message )
+{
+ Activate();
+
+ switch( p_message->what )
+ {
+ case OPEN_FILE:
+ if( file_panel )
+ {
+ file_panel->Show();
+ break;
+ }
+ file_panel = new BFilePanel();
+ file_panel->SetTarget( this );
+ file_panel->Show();
+ break;
+
+ case OPEN_DVD:
+ {
+ const char *psz_device;
+ BString type("dvd");
+ if( p_message->FindString("device", &psz_device) != B_ERROR )
+ {
+ BString device(psz_device);
+// p_vlc_wrapper->openDisc(type, device, 0,0);
+ p_listview->AddItem(new BStringItem(psz_device));
+ }
+ }
+ break;
+ case B_REFS_RECEIVED:
+ case B_SIMPLE_DATA:
+ {
+ entry_ref ref;
+ BList* files = new BList();
+
+ int i = 0;
+ while( p_message->FindRef( "refs", i, &ref ) == B_OK )
+ {
+ BPath path( &ref );
+
+ files->AddItem(new BString((char*)path.Path()) );
+ p_listview->AddItem(new BStringItem((char*)path.Path()));
+ i++;
+ }
+// p_vlc_wrapper->openFiles(files);
+ delete files;
+ }
+ break;
+ default:
+ BWindow::MessageReceived( p_message );
+ break;
+ }
+}
+
+bool PlayListWindow::QuitRequested()
+{
+ Hide();
+ return false;
+}
+
+void PlayListWindow::ReallyQuit()
+{
+ Hide();
+ Lock();
+ Quit();
+}
--- /dev/null
+/*****************************************************************************
+ * PlayListWindow.h: BeOS interface window class prototype
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: PlayListWindow.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Tony Castley <tcastley@mail.powerup.com.au>
+ * Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+class CDMenu;
+class PlayListWindow : public BWindow
+{
+public:
+ static PlayListWindow *getPlayList(BRect frame, const char *name,
+ playlist_t *p_pl);
+ ~PlayListWindow();
+ bool QuitRequested();
+ void ReallyQuit();
+
+ // standard window member
+ virtual void MessageReceived(BMessage *message);
+
+private:
+ PlayListWindow( BRect frame, const char *name, playlist_t *p_pl);
+ playlist_t *p_playlist;
+ BListView *p_listview;
+ BFilePanel *file_panel;
+};
+
+
--- /dev/null
+/*****************************************************************************
+ * TransportButton.cpp
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: TransportButton.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tcastley@mail.powerup.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <Bitmap.h>
+#include <Debug.h>
+#include <MessageFilter.h>
+#include <Screen.h>
+#include <Window.h>
+
+#include <map>
+
+#include "TransportButton.h"
+#include "DrawingTidbits.h"
+
+class BitmapStash {
+// Bitmap stash is a simple class to hold all the lazily-allocated
+// bitmaps that the TransportButton needs when rendering itself.
+// signature is a combination of the different enabled, pressed, playing, etc.
+// flavors of a bitmap. If the stash does not have a particular bitmap,
+// it turns around to ask the button to create one and stores it for next time.
+public:
+ BitmapStash(TransportButton *);
+ ~BitmapStash();
+ BBitmap *GetBitmap(uint32 signature);
+
+private:
+ TransportButton *owner;
+ map<uint32, BBitmap *> stash;
+};
+
+BitmapStash::BitmapStash(TransportButton *owner)
+ : owner(owner)
+{
+}
+
+BBitmap *
+BitmapStash::GetBitmap(uint32 signature)
+{
+ if (stash.find(signature) == stash.end()) {
+ BBitmap *newBits = owner->MakeBitmap(signature);
+ ASSERT(newBits);
+ stash[signature] = newBits;
+ }
+
+ return stash[signature];
+}
+
+BitmapStash::~BitmapStash()
+{
+ // delete all the bitmaps
+ for (map<uint32, BBitmap *>::iterator i = stash.begin(); i != stash.end(); i++)
+ delete (*i).second;
+}
+
+
+class PeriodicMessageSender {
+ // used to send a specified message repeatedly when holding down a button
+public:
+ static PeriodicMessageSender *Launch(BMessenger target,
+ const BMessage *message, bigtime_t period);
+ void Quit();
+
+private:
+ PeriodicMessageSender(BMessenger target, const BMessage *message,
+ bigtime_t period);
+ ~PeriodicMessageSender() {}
+ // use quit
+
+ static status_t TrackBinder(void *);
+ void Run();
+
+ BMessenger target;
+ BMessage message;
+
+ bigtime_t period;
+
+ bool requestToQuit;
+};
+
+
+PeriodicMessageSender::PeriodicMessageSender(BMessenger target,
+ const BMessage *message, bigtime_t period)
+ : target(target),
+ message(*message),
+ period(period),
+ requestToQuit(false)
+{
+}
+
+PeriodicMessageSender *
+PeriodicMessageSender::Launch(BMessenger target, const BMessage *message,
+ bigtime_t period)
+{
+ PeriodicMessageSender *result = new PeriodicMessageSender(target, message, period);
+ thread_id thread = spawn_thread(&PeriodicMessageSender::TrackBinder,
+ "ButtonRepeatingThread", B_NORMAL_PRIORITY, result);
+
+ if (thread <= 0 || resume_thread(thread) != B_OK) {
+ // didn't start, don't leak self
+ delete result;
+ result = 0;
+ }
+
+ return result;
+}
+
+void
+PeriodicMessageSender::Quit()
+{
+ requestToQuit = true;
+}
+
+status_t
+PeriodicMessageSender::TrackBinder(void *castToThis)
+{
+ ((PeriodicMessageSender *)castToThis)->Run();
+ return 0;
+}
+
+void
+PeriodicMessageSender::Run()
+{
+ for (;;) {
+ snooze(period);
+ if (requestToQuit)
+ break;
+ target.SendMessage(&message);
+ }
+ delete this;
+}
+
+class SkipButtonKeypressFilter : public BMessageFilter {
+public:
+ SkipButtonKeypressFilter(uint32 shortcutKey, uint32 shortcutModifier,
+ TransportButton *target);
+
+protected:
+ filter_result Filter(BMessage *message, BHandler **handler);
+
+private:
+ uint32 shortcutKey;
+ uint32 shortcutModifier;
+ TransportButton *target;
+};
+
+SkipButtonKeypressFilter::SkipButtonKeypressFilter(uint32 shortcutKey,
+ uint32 shortcutModifier, TransportButton *target)
+ : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
+ shortcutKey(shortcutKey),
+ shortcutModifier(shortcutModifier),
+ target(target)
+{
+}
+
+filter_result
+SkipButtonKeypressFilter::Filter(BMessage *message, BHandler **handler)
+{
+ if (target->IsEnabled()
+ && (message->what == B_KEY_DOWN || message->what == B_KEY_UP)) {
+ uint32 modifiers;
+ uint32 rawKeyChar = 0;
+ uint8 byte = 0;
+ int32 key = 0;
+
+ if (message->FindInt32("modifiers", (int32 *)&modifiers) != B_OK
+ || message->FindInt32("raw_char", (int32 *)&rawKeyChar) != B_OK
+ || message->FindInt8("byte", (int8 *)&byte) != B_OK
+ || message->FindInt32("key", &key) != B_OK)
+ return B_DISPATCH_MESSAGE;
+
+ modifiers &= B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY
+ | B_OPTION_KEY | B_MENU_KEY;
+ // strip caps lock, etc.
+
+ if (modifiers == shortcutModifier && rawKeyChar == shortcutKey) {
+ if (message->what == B_KEY_DOWN)
+ target->ShortcutKeyDown();
+ else
+ target->ShortcutKeyUp();
+
+ return B_SKIP_MESSAGE;
+ }
+ }
+
+ // let others deal with this
+ return B_DISPATCH_MESSAGE;
+}
+
+TransportButton::TransportButton(BRect frame, const char *name,
+ const unsigned char *normalBits,
+ const unsigned char *pressedBits,
+ const unsigned char *disabledBits,
+ BMessage *invokeMessage, BMessage *startPressingMessage,
+ BMessage *pressingMessage, BMessage *donePressingMessage, bigtime_t period,
+ uint32 key, uint32 modifiers, uint32 resizeFlags)
+ : BControl(frame, name, "", invokeMessage, resizeFlags, B_WILL_DRAW | B_NAVIGABLE),
+ bitmaps(new BitmapStash(this)),
+ normalBits(normalBits),
+ pressedBits(pressedBits),
+ disabledBits(disabledBits),
+ startPressingMessage(startPressingMessage),
+ pressingMessage(pressingMessage),
+ donePressingMessage(donePressingMessage),
+ pressingPeriod(period),
+ mouseDown(false),
+ keyDown(false),
+ messageSender(0),
+ keyPressFilter(0)
+{
+ if (key)
+ keyPressFilter = new SkipButtonKeypressFilter(key, modifiers, this);
+}
+
+
+void
+TransportButton::AttachedToWindow()
+{
+ _inherited::AttachedToWindow();
+ if (keyPressFilter)
+ Window()->AddCommonFilter(keyPressFilter);
+
+ // transparent to reduce flicker
+ SetViewColor(B_TRANSPARENT_COLOR);
+}
+
+void
+TransportButton::DetachedFromWindow()
+{
+ if (keyPressFilter) {
+ Window()->RemoveCommonFilter(keyPressFilter);
+ delete keyPressFilter;
+ }
+ _inherited::DetachedFromWindow();
+}
+
+
+TransportButton::~TransportButton()
+{
+ delete startPressingMessage;
+ delete pressingMessage;
+ delete donePressingMessage;
+ delete bitmaps;
+}
+
+void
+TransportButton::WindowActivated(bool state)
+{
+ if (!state)
+ ShortcutKeyUp();
+
+ _inherited::WindowActivated(state);
+}
+
+void
+TransportButton::SetEnabled(bool on)
+{
+ _inherited::SetEnabled(on);
+ if (!on)
+ ShortcutKeyUp();
+}
+
+const unsigned char *
+TransportButton::BitsForMask(uint32 mask) const
+{
+ switch (mask) {
+ case 0:
+ return normalBits;
+ case kDisabledMask:
+ return disabledBits;
+ case kPressedMask:
+ return pressedBits;
+ default:
+ break;
+ }
+ TRESPASS();
+ return 0;
+}
+
+
+BBitmap *
+TransportButton::MakeBitmap(uint32 mask)
+{
+ BBitmap *result = new BBitmap(Bounds(), B_COLOR_8_BIT);
+ result->SetBits(BitsForMask(mask), (Bounds().Width() + 1) * (Bounds().Height() + 1),
+ 0, B_COLOR_8_BIT);
+
+ ReplaceTransparentColor(result, Parent()->ViewColor());
+
+ return result;
+}
+
+uint32
+TransportButton::ModeMask() const
+{
+ return (IsEnabled() ? 0 : kDisabledMask)
+ | (Value() ? kPressedMask : 0);
+}
+
+void
+TransportButton::Draw(BRect)
+{
+ DrawBitmapAsync(bitmaps->GetBitmap(ModeMask()));
+}
+
+
+void
+TransportButton::StartPressing()
+{
+ SetValue(1);
+ if (startPressingMessage)
+ Invoke(startPressingMessage);
+
+ if (pressingMessage) {
+ ASSERT(pressingMessage);
+ messageSender = PeriodicMessageSender::Launch(Messenger(),
+ pressingMessage, pressingPeriod);
+ }
+}
+
+void
+TransportButton::MouseCancelPressing()
+{
+ if (!mouseDown || keyDown)
+ return;
+
+ mouseDown = false;
+
+ if (pressingMessage) {
+ ASSERT(messageSender);
+ PeriodicMessageSender *sender = messageSender;
+ messageSender = 0;
+ sender->Quit();
+ }
+
+ if (donePressingMessage)
+ Invoke(donePressingMessage);
+ SetValue(0);
+}
+
+void
+TransportButton::DonePressing()
+{
+ if (pressingMessage) {
+ ASSERT(messageSender);
+ PeriodicMessageSender *sender = messageSender;
+ messageSender = 0;
+ sender->Quit();
+ }
+
+ Invoke();
+ SetValue(0);
+}
+
+void
+TransportButton::MouseStartPressing()
+{
+ if (mouseDown)
+ return;
+
+ mouseDown = true;
+ if (!keyDown)
+ StartPressing();
+}
+
+void
+TransportButton::MouseDonePressing()
+{
+ if (!mouseDown)
+ return;
+
+ mouseDown = false;
+ if (!keyDown)
+ DonePressing();
+}
+
+void
+TransportButton::ShortcutKeyDown()
+{
+ if (!IsEnabled())
+ return;
+
+ if (keyDown)
+ return;
+
+ keyDown = true;
+ if (!mouseDown)
+ StartPressing();
+}
+
+void
+TransportButton::ShortcutKeyUp()
+{
+ if (!keyDown)
+ return;
+
+ keyDown = false;
+ if (!mouseDown)
+ DonePressing();
+}
+
+
+void
+TransportButton::MouseDown(BPoint)
+{
+ if (!IsEnabled())
+ return;
+
+ ASSERT(Window()->Flags() & B_ASYNCHRONOUS_CONTROLS);
+ SetTracking(true);
+ SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
+ MouseStartPressing();
+}
+
+void
+TransportButton::MouseMoved(BPoint point, uint32 code, const BMessage *)
+{
+ if (IsTracking() && Bounds().Contains(point) != Value()) {
+ if (!Value())
+ MouseStartPressing();
+ else
+ MouseCancelPressing();
+ }
+}
+
+void
+TransportButton::MouseUp(BPoint point)
+{
+ if (IsTracking()) {
+ if (Bounds().Contains(point))
+ MouseDonePressing();
+ else
+ MouseCancelPressing();
+ SetTracking(false);
+ }
+}
+
+void
+TransportButton::SetStartPressingMessage(BMessage *message)
+{
+ delete startPressingMessage;
+ startPressingMessage = message;
+}
+
+void
+TransportButton::SetPressingMessage(BMessage *message)
+{
+ delete pressingMessage;
+ pressingMessage = message;
+}
+
+void
+TransportButton::SetDonePressingMessage(BMessage *message)
+{
+ delete donePressingMessage;
+ donePressingMessage = message;
+}
+
+void
+TransportButton::SetPressingPeriod(bigtime_t newTime)
+{
+ pressingPeriod = newTime;
+}
+
+
+PlayPauseButton::PlayPauseButton(BRect frame, const char *name,
+ const unsigned char *normalBits, const unsigned char *pressedBits,
+ const unsigned char *disabledBits, const unsigned char *normalPlayingBits,
+ const unsigned char *pressedPlayingBits, const unsigned char *normalPausedBits,
+ const unsigned char *pressedPausedBits,
+ BMessage *invokeMessage, uint32 key, uint32 modifiers, uint32 resizeFlags)
+ : TransportButton(frame, name, normalBits, pressedBits,
+ disabledBits, invokeMessage, 0,
+ 0, 0, 0, key, modifiers, resizeFlags),
+ normalPlayingBits(normalPlayingBits),
+ pressedPlayingBits(pressedPlayingBits),
+ normalPausedBits(normalPausedBits),
+ pressedPausedBits(pressedPausedBits),
+ state(PlayPauseButton::kStopped),
+ lastPauseBlinkTime(0),
+ lastModeMask(0)
+{
+}
+
+void
+PlayPauseButton::SetStopped()
+{
+ if (state == kStopped || state == kAboutToPlay)
+ return;
+
+ state = kStopped;
+ Invalidate();
+}
+
+void
+PlayPauseButton::SetPlaying()
+{
+ if (state == kPlaying || state == kAboutToPause)
+ return;
+
+ state = kPlaying;
+ Invalidate();
+}
+
+const bigtime_t kPauseBlinkPeriod = 600000;
+
+void
+PlayPauseButton::SetPaused()
+{
+ if (state == kAboutToPlay)
+ return;
+
+ // in paused state blink the LED on and off
+ bigtime_t now = system_time();
+ if (state == kPausedLedOn || state == kPausedLedOff) {
+ if (now - lastPauseBlinkTime < kPauseBlinkPeriod)
+ return;
+
+ if (state == kPausedLedOn)
+ state = kPausedLedOff;
+ else
+ state = kPausedLedOn;
+ } else
+ state = kPausedLedOn;
+
+ lastPauseBlinkTime = now;
+ Invalidate();
+}
+
+uint32
+PlayPauseButton::ModeMask() const
+{
+ if (!IsEnabled())
+ return kDisabledMask;
+
+ uint32 result = 0;
+
+ if (Value())
+ result = kPressedMask;
+
+ if (state == kPlaying || state == kAboutToPlay)
+ result |= kPlayingMask;
+ else if (state == kAboutToPause || state == kPausedLedOn)
+ result |= kPausedMask;
+
+ return result;
+}
+
+const unsigned char *
+PlayPauseButton::BitsForMask(uint32 mask) const
+{
+ switch (mask) {
+ case kPlayingMask:
+ return normalPlayingBits;
+ case kPlayingMask | kPressedMask:
+ return pressedPlayingBits;
+ case kPausedMask:
+ return normalPausedBits;
+ case kPausedMask | kPressedMask:
+ return pressedPausedBits;
+ default:
+ return _inherited::BitsForMask(mask);
+ }
+ TRESPASS();
+ return 0;
+}
+
+
+void
+PlayPauseButton::StartPressing()
+{
+ if (state == kPlaying)
+ state = kAboutToPause;
+ else
+ state = kAboutToPlay;
+
+ _inherited::StartPressing();
+}
+
+void
+PlayPauseButton::MouseCancelPressing()
+{
+ if (state == kAboutToPause)
+ state = kPlaying;
+ else
+ state = kStopped;
+
+ _inherited::MouseCancelPressing();
+}
+
+void
+PlayPauseButton::DonePressing()
+{
+ if (state == kAboutToPause) {
+ state = kPausedLedOn;
+ lastPauseBlinkTime = system_time();
+ } else if (state == kAboutToPlay)
+ state = kPlaying;
+
+ _inherited::DonePressing();
+}
+
+
--- /dev/null
+/*****************************************************************************
+ * TransportButton.h
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: TransportButton.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Tony Castley <tcastley@mail.powerup.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#ifndef __MEDIA_BUTTON__
+#define __MEDIA_BUTTON__
+
+#include <Control.h>
+
+class BMessage;
+class BBitmap;
+class PeriodicMessageSender;
+class BitmapStash;
+
+// TransportButton must be installed into a window with B_ASYNCHRONOUS_CONTROLS on
+// currently no button focus drawing
+
+class TransportButton : public BControl {
+public:
+
+ TransportButton(BRect frame, const char *name,
+ const unsigned char *normalBits,
+ const unsigned char *pressedBits,
+ const unsigned char *disabledBits,
+ BMessage *invokeMessage, // done pressing over button
+ BMessage *startPressingMessage = 0, // just clicked button
+ BMessage *pressingMessage = 0, // periodical still pressing
+ BMessage *donePressing = 0, // tracked out of button/didn't invoke
+ bigtime_t period = 0, // pressing message period
+ uint32 key = 0, // optional shortcut key
+ uint32 modifiers = 0, // optional shortcut key modifier
+ uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP);
+
+ virtual ~TransportButton();
+
+ void SetStartPressingMessage(BMessage *);
+ void SetPressingMessage(BMessage *);
+ void SetDonePressingMessage(BMessage *);
+ void SetPressingPeriod(bigtime_t);
+
+ virtual void SetEnabled(bool);
+
+protected:
+
+ enum {
+ kDisabledMask = 0x1,
+ kPressedMask = 0x2
+ };
+
+ virtual void AttachedToWindow();
+ virtual void DetachedFromWindow();
+ virtual void Draw(BRect);
+ virtual void MouseDown(BPoint);
+ virtual void MouseMoved(BPoint, uint32 code, const BMessage *);
+ virtual void MouseUp(BPoint);
+ virtual void WindowActivated(bool);
+
+ virtual BBitmap *MakeBitmap(uint32);
+ // lazy bitmap builder
+
+ virtual uint32 ModeMask() const;
+ // mode mask corresponding to the current button state
+ // - determines which bitmap will be used
+ virtual const unsigned char *BitsForMask(uint32) const;
+ // pick the right bits based on a mode mask
+
+ // overriding class can add swapping between two pairs of bitmaps, etc.
+ virtual void StartPressing();
+ virtual void MouseCancelPressing();
+ virtual void DonePressing();
+
+private:
+ void ShortcutKeyDown();
+ void ShortcutKeyUp();
+
+ void MouseStartPressing();
+ void MouseDonePressing();
+
+ BitmapStash *bitmaps;
+ // using BitmapStash * here instead of a direct member so that the class can be private in
+ // the .cpp file
+
+ // bitmap bits used to build bitmaps for the different states
+ const unsigned char *normalBits;
+ const unsigned char *pressedBits;
+ const unsigned char *disabledBits;
+
+ BMessage *startPressingMessage;
+ BMessage *pressingMessage;
+ BMessage *donePressingMessage;
+ bigtime_t pressingPeriod;
+
+ bool mouseDown;
+ bool keyDown;
+ PeriodicMessageSender *messageSender;
+ BMessageFilter *keyPressFilter;
+
+ typedef BControl _inherited;
+
+ friend class SkipButtonKeypressFilter;
+ friend class BitmapStash;
+};
+
+class PlayPauseButton : public TransportButton {
+// Knows about playing and paused states, blinks
+// the pause LED during paused state
+public:
+ PlayPauseButton(BRect frame, const char *name,
+ const unsigned char *normalBits,
+ const unsigned char *pressedBits,
+ const unsigned char *disabledBits,
+ const unsigned char *normalPlayingBits,
+ const unsigned char *pressedPlayingBits,
+ const unsigned char *normalPausedBits,
+ const unsigned char *pressedPausedBits,
+ BMessage *invokeMessage, // done pressing over button
+ uint32 key = 0, // optional shortcut key
+ uint32 modifiers = 0, // optional shortcut key modifier
+ uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP);
+
+ // These need get called periodically to update the button state
+ // OK to call them over and over - once the state is correct, the call
+ // is very low overhead
+ void SetStopped();
+ void SetPlaying();
+ void SetPaused();
+
+protected:
+
+ virtual uint32 ModeMask() const;
+ virtual const unsigned char *BitsForMask(uint32) const;
+
+ virtual void StartPressing();
+ virtual void MouseCancelPressing();
+ virtual void DonePressing();
+
+private:
+ const unsigned char *normalPlayingBits;
+ const unsigned char *pressedPlayingBits;
+ const unsigned char *normalPausedBits;
+ const unsigned char *pressedPausedBits;
+
+ enum PlayState {
+ kStopped,
+ kAboutToPlay,
+ kPlaying,
+ kAboutToPause,
+ kPausedLedOn,
+ kPausedLedOff
+ };
+
+ enum {
+ kPlayingMask = 0x4,
+ kPausedMask = 0x8
+ };
+
+ PlayState state;
+ bigtime_t lastPauseBlinkTime;
+ uint32 lastModeMask;
+
+ typedef TransportButton _inherited;
+};
+
+#endif
--- /dev/null
+/*****************************************************************************
+ * vout.cpp: beos video output display method
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: VideoOutput.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * Tony Castley <tcastley@mail.powerup.com.au>
+ * Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <stdio.h>
+#include <string.h> /* strerror() */
+#include <InterfaceKit.h>
+#include <DirectWindow.h>
+#include <Application.h>
+#include <Bitmap.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include "VideoWindow.h"
+#include "DrawingTidbits.h"
+#include "MsgVals.h"
+
+
+/*****************************************************************************
+ * vout_sys_t: BeOS video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the BeOS specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ VideoWindow * p_window;
+
+ s32 i_width;
+ s32 i_height;
+
+ u32 source_chroma;
+ int i_index;
+};
+
+/*****************************************************************************
+ * beos_GetAppWindow : retrieve a BWindow pointer from the window name
+ *****************************************************************************/
+BWindow *beos_GetAppWindow(char *name)
+{
+ int32 index;
+ BWindow *window;
+
+ for (index = 0 ; ; index++)
+ {
+ window = be_app->WindowAt(index);
+ if (window == NULL)
+ break;
+ if (window->LockWithTimeout(20000) == B_OK)
+ {
+ if (strcmp(window->Name(), name) == 0)
+ {
+ window->Unlock();
+ break;
+ }
+ window->Unlock();
+ }
+ }
+ return window;
+}
+
+/*****************************************************************************
+ * VideoWindow constructor and destructor
+ *****************************************************************************/
+VideoWindow::VideoWindow( int v_width, int v_height,
+ BRect frame )
+ : BWindow( frame, NULL, B_TITLED_WINDOW,
+ B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
+{
+ BView *mainView = new BView( Bounds(), "mainView",
+ B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE);
+ AddChild(mainView);
+ mainView->SetViewColor(kBlack);
+
+ /* create the view to do the display */
+ view = new VLCView( Bounds() );
+ mainView->AddChild(view);
+
+ /* set the VideoWindow variables */
+ teardownwindow = false;
+ is_zoomed = false;
+ vsync = false;
+ i_buffer = 0;
+
+ /* call ScreenChanged to set vsync correctly */
+ BScreen *screen;
+ display_mode disp_mode;
+ float refresh;
+
+ screen = new BScreen(this);
+
+ screen-> GetMode(&disp_mode);
+ refresh =
+ (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
+ (disp_mode.timing.v_total));
+ if (refresh < 61)
+ {
+ vsync = true;
+ }
+ delete screen;
+
+ mode = SelectDrawingMode(v_width, v_height);
+
+ // remember current settings
+ i_width = v_width;
+ i_height = v_height;
+ FrameResized(v_width, v_height);
+
+ if (mode == OVERLAY)
+ {
+ overlay_restrictions r;
+
+ bitmap[1]->GetOverlayRestrictions(&r);
+ SetSizeLimits((i_width * r.min_width_scale) + 1, i_width * r.max_width_scale,
+ (i_height * r.min_height_scale) + 1, i_height * r.max_height_scale);
+ }
+ Show();
+}
+
+VideoWindow::~VideoWindow()
+{
+ teardownwindow = true;
+ delete bitmap[0];
+ delete bitmap[1];
+ delete bitmap[2];
+}
+
+void VideoWindow::MessageReceived( BMessage *p_message )
+{
+ switch( p_message->what )
+ {
+ case TOGGLE_FULL_SCREEN:
+ ((BWindow *)this)->Zoom();
+ break;
+ case RESIZE_100:
+ if (is_zoomed)
+ {
+ ((BWindow *)this)->Zoom();
+ }
+ ResizeTo(i_width, i_height);
+ break;
+ case RESIZE_200:
+ if (is_zoomed)
+ {
+ ((BWindow *)this)->Zoom();
+ }
+ ResizeTo(i_width * 2, i_height * 2);
+ break;
+ case VERT_SYNC:
+ vsync = !vsync;
+ break;
+ case WINDOW_FEEL:
+ {
+ int16 winFeel;
+ if (p_message->FindInt16("WinFeel", &winFeel) == B_OK)
+ {
+ SetFeel((window_feel)winFeel);
+ }
+ }
+ break;
+ default:
+ BWindow::MessageReceived( p_message );
+ break;
+ }
+}
+
+void VideoWindow::drawBuffer(int bufferIndex)
+{
+ i_buffer = bufferIndex;
+
+ // sync to the screen if required
+ if (vsync)
+ {
+ BScreen *screen;
+ screen = new BScreen(this);
+ screen-> WaitForRetrace(22000);
+ delete screen;
+ }
+ if (LockLooper())
+ {
+ // switch the overlay bitmap
+ if (mode == OVERLAY)
+ {
+ rgb_color key;
+ view->SetViewOverlay(bitmap[i_buffer],
+ bitmap[i_buffer]->Bounds() ,
+ view->Bounds(),
+ &key, B_FOLLOW_ALL,
+ B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
+ B_OVERLAY_TRANSFER_CHANNEL);
+ view->SetViewColor(key);
+ }
+ else
+ {
+ // switch the bitmap
+ view-> DrawBitmap(bitmap[i_buffer], view->Bounds() );
+ }
+ UnlockLooper();
+ }
+}
+
+void VideoWindow::Zoom(BPoint origin, float width, float height )
+{
+ if(is_zoomed)
+ {
+ is_zoomed = !is_zoomed;
+ MoveTo(winSize.left, winSize.top);
+ ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
+ be_app->ShowCursor();
+ }
+ else
+ {
+ is_zoomed = !is_zoomed;
+ BScreen *screen;
+ screen = new BScreen(this);
+ BRect rect = screen->Frame();
+ delete screen;
+ MoveTo(0,0);
+ ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
+ be_app->ObscureCursor();
+ }
+}
+
+void VideoWindow::FrameMoved(BPoint origin)
+{
+ if (is_zoomed) return ;
+ winSize = Frame();
+}
+
+void VideoWindow::FrameResized( float width, float height )
+{
+ float out_width, out_height;
+ float out_left, out_top;
+ float width_scale = width / i_width;
+ float height_scale = height / i_height;
+
+ if (width_scale <= height_scale)
+ {
+ out_width = (i_width * width_scale);
+ out_height = (i_height * width_scale);
+ out_left = 0;
+ out_top = (height - out_height) / 2;
+ }
+ else /* if the height is proportionally smaller */
+ {
+ out_width = (i_width * height_scale);
+ out_height = (i_height * height_scale);
+ out_top = 0;
+ out_left = (width - out_width) /2;
+ }
+ view->MoveTo(out_left,out_top);
+ view->ResizeTo(out_width, out_height);
+ if (!is_zoomed)
+ {
+ winSize = Frame();
+ }
+}
+
+void VideoWindow::ScreenChanged(BRect frame, color_space mode)
+{
+ BScreen *screen;
+ float refresh;
+
+ screen = new BScreen(this);
+ display_mode disp_mode;
+
+ screen-> GetMode(&disp_mode);
+ refresh =
+ (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
+ (disp_mode.timing.v_total));
+ if (refresh < 61)
+ {
+ vsync = true;
+ }
+}
+
+void VideoWindow::WindowActivated(bool active)
+{
+}
+
+int VideoWindow::SelectDrawingMode(int width, int height)
+{
+ int drawingMode = BITMAP;
+ int noOverlay = 0;
+
+// int noOverlay = !config_GetIntVariable( "overlay" );
+ for (int i = 0; i < COLOR_COUNT; i++)
+ {
+ if (noOverlay) break;
+ bitmap[0] = new BBitmap ( BRect( 0, 0, width, height ),
+ B_BITMAP_WILL_OVERLAY,
+ colspace[i].colspace);
+
+ if(bitmap[0] && bitmap[0]->InitCheck() == B_OK)
+ {
+ colspace_index = i;
+
+ bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY,
+ colspace[colspace_index].colspace);
+ bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY,
+ colspace[colspace_index].colspace);
+ if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) )
+ {
+ drawingMode = OVERLAY;
+ rgb_color key;
+ view->SetViewOverlay(bitmap[0],
+ bitmap[0]->Bounds() ,
+ view->Bounds(),
+ &key, B_FOLLOW_ALL,
+ B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL);
+ view->SetViewColor(key);
+ SetTitle(VOUT_TITLE " (Overlay)");
+ break;
+ }
+ else
+ {
+ delete bitmap[0];
+ delete bitmap[1];
+ delete bitmap[2];
+ }
+ }
+ else
+ {
+ delete bitmap[0];
+ }
+ }
+
+ if (drawingMode == BITMAP)
+ {
+ // fallback to RGB16
+ colspace_index = DEFAULT_COL;
+ SetTitle(VOUT_TITLE " (Bitmap)");
+ bitmap[0] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
+ bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
+ bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
+ }
+ return drawingMode;
+}
+
+/*****************************************************************************
+ * VLCView::VLCView
+ *****************************************************************************/
+VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_NONE,
+ B_WILL_DRAW)
+
+{
+ SetViewColor(B_TRANSPARENT_32_BIT);
+}
+
+/*****************************************************************************
+ * VLCView::~VLCView
+ *****************************************************************************/
+VLCView::~VLCView()
+{
+}
+
+/*****************************************************************************
+ * VLCVIew::MouseDown
+ *****************************************************************************/
+void VLCView::MouseDown(BPoint point)
+{
+ BMessage* msg = Window()->CurrentMessage();
+ int32 clicks = msg->FindInt32("clicks");
+
+ VideoWindow *vWindow = (VideoWindow *)Window();
+ uint32 mouseButtons;
+ BPoint where;
+ GetMouse(&where, &mouseButtons, true);
+
+ if ((mouseButtons & B_PRIMARY_MOUSE_BUTTON) && (clicks == 2))
+ {
+ Window()->Zoom();
+ return;
+ }
+ else
+ {
+ if (mouseButtons & B_SECONDARY_MOUSE_BUTTON)
+ {
+ BPopUpMenu *menu = new BPopUpMenu("context menu");
+ menu->SetRadioMode(false);
+ // Toggle FullScreen
+ BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN));
+ zoomItem->SetMarked(vWindow->is_zoomed);
+ menu->AddItem(zoomItem);
+ // Resize to 100%
+ BMenuItem *origItem = new BMenuItem("100%", new BMessage(RESIZE_100));
+ menu->AddItem(origItem);
+ // Resize to 200%
+ BMenuItem *doubleItem = new BMenuItem("200%", new BMessage(RESIZE_200));
+ menu->AddItem(doubleItem);
+ menu->AddSeparatorItem();
+ // Toggle vSync
+ BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC));
+ vsyncItem->SetMarked(vWindow->vsync);
+ menu->AddItem(vsyncItem);
+ menu->AddSeparatorItem();
+
+ // Windwo Feel Items
+ BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
+ winNormFeel->AddInt16("WinFeel", (int16)B_NORMAL_WINDOW_FEEL);
+ BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
+ normWindItem->SetMarked(vWindow->Feel() == B_NORMAL_WINDOW_FEEL);
+ menu->AddItem(normWindItem);
+
+ BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
+ winFloatFeel->AddInt16("WinFeel", (int16)B_MODAL_ALL_WINDOW_FEEL);
+ BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
+ onTopWindItem->SetMarked(vWindow->Feel() == B_MODAL_ALL_WINDOW_FEEL);
+ menu->AddItem(onTopWindItem);
+
+ BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
+ winAllFeel->AddInt16("WinFeel", (int16)B_FLOATING_ALL_WINDOW_FEEL);
+ BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
+ allSpacesWindItem->SetMarked(vWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
+ menu->AddItem(allSpacesWindItem);
+
+ menu->SetTargetForItems(this);
+ ConvertToScreen(&where);
+ menu->Go(where, true, false, true);
+ }
+ }
+}
+
+/*****************************************************************************
+ * VLCVIew::Draw
+ *****************************************************************************/
+void VLCView::Draw(BRect updateRect)
+{
+ VideoWindow *win = (VideoWindow *) Window();
+ if (win->mode == BITMAP)
+ FillRect(updateRect);
+}
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static int BeosOpenDisplay ( vout_thread_t *p_vout );
+static void BeosCloseDisplay( vout_thread_t *p_vout );
+
+/*****************************************************************************
+ * OpenVideo: allocates BeOS video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a BeOS vout method.
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+ p_vout->p_sys->i_width = p_vout->render.i_width;
+ p_vout->p_sys->i_height = p_vout->render.i_height;
+ p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = Display;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize BeOS video thread output method
+ *****************************************************************************/
+int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Open and initialize device */
+ if( BeosOpenDisplay( p_vout ) )
+ {
+ msg_Err(p_vout, "vout error: can't open display");
+ return 0;
+ }
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+
+ /* Assume we have square pixels */
+ p_vout->output.i_aspect = p_vout->p_sys->i_width
+ * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
+ p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
+ p_vout->p_sys->i_index = 0;
+
+ p_vout->b_direct = 1;
+
+ p_vout->output.i_rmask = 0x00ff0000;
+ p_vout->output.i_gmask = 0x0000ff00;
+ p_vout->output.i_bmask = 0x000000ff;
+
+ for (int buffer_index = 0 ; buffer_index < 3; buffer_index++)
+ {
+ p_pic = NULL;
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ p_pic = NULL;
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ if( p_pic == NULL )
+ {
+ return 0;
+ }
+ p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
+ p_pic->p->i_lines = p_vout->p_sys->i_height;
+
+ p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
+ p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
+ p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
+ p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate BeOS video thread output method
+ *****************************************************************************/
+void End( vout_thread_t *p_vout )
+{
+ BeosCloseDisplay( p_vout );
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy BeOS video thread output method
+ *****************************************************************************
+ * Terminate an output method created by DummyCreateOutputMethod
+ *****************************************************************************/
+void E_(CloseVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to BeOS image, waits until
+ * it is displayed and switch the two rendering buffers, preparing next frame.
+ *****************************************************************************/
+void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ VideoWindow * p_win = p_vout->p_sys->p_window;
+
+ /* draw buffer if required */
+ if (!p_win->teardownwindow)
+ {
+ p_win->drawBuffer(p_vout->p_sys->i_index);
+ }
+ /* change buffer */
+ p_vout->p_sys->i_index = ++p_vout->p_sys->i_index % 3;
+ p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * BeosOpenDisplay: open and initialize BeOS device
+ *****************************************************************************/
+static int BeosOpenDisplay( vout_thread_t *p_vout )
+{
+
+ p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
+ p_vout->p_sys->i_height - 1,
+ BRect( 20, 50,
+ 20 + p_vout->i_window_width - 1,
+ 50 + p_vout->i_window_height - 1 ));
+
+ if( p_vout->p_sys->p_window == NULL )
+ {
+ msg_Err( p_vout, "cannot allocate VideoWindow" );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * BeosDisplay: close and reset BeOS device
+ *****************************************************************************
+ * Returns all resources allocated by BeosOpenDisplay and restore the original
+ * state of the device.
+ *****************************************************************************/
+static void BeosCloseDisplay( vout_thread_t *p_vout )
+{
+ VideoWindow * p_win = p_vout->p_sys->p_window;
+ /* Destroy the video window */
+ if( p_win != NULL && !p_win->teardownwindow)
+ {
+ p_win->Lock();
+ p_win->teardownwindow = true;
+ p_win->Hide();
+ p_win->Quit();
+ }
+ p_win = NULL;
+}
+
--- /dev/null
+/*****************************************************************************
+ * VideoWindow.h: BeOS video window class prototype
+ *****************************************************************************
+ * Copyright (C) 1999, 2000, 2001 VideoLAN
+ * $Id: VideoWindow.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ * Tony Castley <tcastley@mail.powerup.com.au>
+ * Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+#define BITMAP 0
+#define OVERLAY 1
+#define OPENGL 2
+
+typedef struct colorcombo
+{
+ color_space colspace;
+ const char *name;
+ u32 chroma;
+ int planes;
+ int pixel_bytes;
+} colorcombo;
+
+colorcombo colspace[]=
+{
+ {B_YCbCr420, "B_YCbCr420", VLC_FOURCC('I','4','2','0'), 3, 2},
+ {B_YUV422, "B_YUV422", VLC_FOURCC('Y','4','2','2'), 3, 2},
+ {B_YCbCr422, "B_YCbCr422", VLC_FOURCC('Y','U','Y','2'), 3, 2},
+ {B_RGB32, "B_RGB32", VLC_FOURCC('R','V','3','2'), 1, 4},
+ {B_RGB16, "B_RGB16", VLC_FOURCC('R','V','1','6'), 1, 2}
+};
+
+#define COLOR_COUNT 5
+#define DEFAULT_COL 4
+
+
+class VLCView : public BView
+{
+public:
+ VLCView( BRect bounds);
+ ~VLCView();
+
+ void MouseDown(BPoint point);
+ void Draw(BRect updateRect);
+};
+
+
+class VideoWindow : public BWindow
+{
+public:
+ // standard constructor and destructor
+ VideoWindow( int v_width, int v_height,
+ BRect frame);
+ ~VideoWindow();
+
+ void Zoom(BPoint origin, float width, float height);
+ void FrameResized(float width, float height);
+ void FrameMoved(BPoint origin);
+ void ScreenChanged(BRect frame, color_space mode);
+ void drawBuffer(int bufferIndex);
+ void WindowActivated(bool active);
+ int SelectDrawingMode(int width, int height);
+ void MessageReceived(BMessage *message);
+
+ // this is the hook controling direct screen connection
+ int32 i_width; // incomming bitmap size
+ int32 i_height;
+ BRect winSize; // current window size
+ bool is_zoomed, vsync;
+ BBitmap *bitmap[3];
+ VLCView *view;
+ int i_buffer;
+ bool teardownwindow;
+ thread_id fDrawThreadID;
+ int mode;
+ int colspace_index;
+
+private:
+ vout_thread_t *p_vout;
+
+};
+
+
--- /dev/null
+/*****************************************************************************
+ * vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: VlcWrapper.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Florian G. Pflug <fgp@phlo.org>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ * Tony Casltey <tony@castley.net>
+ *
+ * This program is free software{} you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation{} either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY{} without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program{} if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+/* VLC headers */
+#include <SupportKit.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include "vlc_wrapper.h"
+
+Intf_VLCWrapper *Intf_VLCWrapper::getVLCWrapper(intf_thread_t *p_if)
+{
+ static Intf_VLCWrapper *one_wrapper;
+ if (one_wrapper == NULL )
+ {
+ one_wrapper = new Intf_VLCWrapper(p_if);
+ }
+ return one_wrapper;
+}
+
+Intf_VLCWrapper::Intf_VLCWrapper(intf_thread_t *p_if)
+{
+ p_intf = p_if;
+}
+
+Intf_VLCWrapper::~Intf_VLCWrapper()
+{
+}
+
+//bool Intf_VLCWrapper::manage()
+//{
+//
+// p_intf->pf_manage( p_intf );
+//
+// if ( p_intf->b_die )
+// {
+// // exit the lot
+// return( 1 );
+// }
+ /* Update the input */
+// if( p_intf->p_sys->p_input != NULL )
+// {
+// if( p_intf->p_sys->p_input->b_dead )
+// {
+// vlc_object_release( p_intf->p_sys->p_input );
+// p_intf->p_sys->p_input = NULL;
+// }
+// }
+//
+// p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+// FIND_ANYWHERE );
+
+// if ( p_intf->p_sys->p_input != NULL )
+// {
+// vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+// if( !p_intf->p_sys->p_input->b_die )
+// {
+// /* New input or stream map change */
+// if( p_intf->p_sys->p_input->stream.b_changed ||
+// p_intf->p_sys->i_part !=
+// p_intf->p_sys->p_input->stream.p_selected_area->i_part )
+// {
+// setupMenus();
+// p_intf->p_sys->b_disabled_menus = 0;
+// }
+// }
+// vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+// }
+// else if ( !p_intf->p_sys->b_disabled_menus )
+// {
+// setupMenus();
+// p_intf->p_sys->b_disabled_menus = 1;
+// }
+// return( 0 );
+//}
+
+void Intf_VLCWrapper::quit()
+{
+ p_intf->b_die = 1;
+}
+
+/* playlist control */
+
+int Intf_VLCWrapper::inputGetStatus()
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ return( p_intf->p_sys->p_input->stream.control.i_status );
+ }
+ else
+ {
+ return( UNDEF_S );
+ }
+}
+
+bool Intf_VLCWrapper::playlistPlay()
+{
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+ if( p_playlist->i_size )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ playlist_Play( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ }
+
+ return( true );
+
+}
+
+void Intf_VLCWrapper::playlistPause()
+{
+ toggleMute( );
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ playlist_Pause( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+void Intf_VLCWrapper::playlistStop()
+{
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+
+}
+
+void Intf_VLCWrapper::playlistNext()
+{
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ playlist_Next( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+void Intf_VLCWrapper::playlistPrev()
+{
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ playlist_Prev( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+void Intf_VLCWrapper::playlistSkip(int i)
+{
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ playlist_Skip( p_playlist, i );
+ vlc_object_release( p_playlist );
+}
+
+void Intf_VLCWrapper::playlistGoto(int i)
+{
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ playlist_Goto( p_playlist, i );
+ vlc_object_release( p_playlist );
+}
+
+ /* playback control */
+void Intf_VLCWrapper::playSlower()
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
+ }
+ if (p_intf->p_sys->p_input->stream.control.i_rate == DEFAULT_RATE)
+ {
+ toggleMute( );
+ }
+ else
+ {
+ toggleMute ( );
+ }
+}
+
+void Intf_VLCWrapper::playFaster()
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
+ }
+ if (p_intf->p_sys->p_input->stream.control.i_rate == DEFAULT_RATE)
+ {
+ toggleMute( );
+ }
+ else
+ {
+ toggleMute ( );
+ }
+}
+
+void Intf_VLCWrapper::toggleProgram(int i_program){}
+
+void Intf_VLCWrapper::toggleTitle(int i_title)
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_ChangeArea( p_intf->p_sys->p_input,
+ p_intf->p_sys->p_input->stream.pp_areas[i_title] );
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ //setupMenus();
+
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+void Intf_VLCWrapper::toggleChapter(int i_chapter)
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ p_intf->p_sys->p_input->stream.p_selected_area->i_part = i_chapter;
+ input_ChangeArea( p_intf->p_sys->p_input,
+ p_intf->p_sys->p_input->stream.p_selected_area );
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+// setupMenus();
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+void Intf_VLCWrapper::toggleLanguage(int i_language)
+{
+
+ int32 i_old = -1;
+ int i_cat = AUDIO_ES;
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
+ {
+ if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
+ {
+ i_old = i;
+ break;
+ }
+ }
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ msg_Info( p_intf, "Old: %d, New: %d", i_old, i_language);
+ if( i_language != -1 )
+ {
+ input_ToggleES( p_intf->p_sys->p_input,
+ p_intf->p_sys->p_input->stream.pp_selected_es[i_language],
+ VLC_TRUE );
+ }
+
+ if( (i_old != -1) && (i_old != i_language) )
+ {
+ input_ToggleES( p_intf->p_sys->p_input,
+ p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
+ VLC_FALSE );
+ }
+}
+
+void Intf_VLCWrapper::toggleSubtitle(int i_subtitle)
+{
+ int32 i_old = -1;
+ int i_cat = SPU_ES;
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
+ {
+ if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
+ {
+ i_old = i;
+ break;
+ }
+ }
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ msg_Info( p_intf, "Old: %d, New: %d", i_old, i_subtitle);
+ if( i_subtitle != -1 )
+ {
+ input_ToggleES( p_intf->p_sys->p_input,
+ p_intf->p_sys->p_input->stream.pp_selected_es[i_subtitle],
+ VLC_TRUE );
+ }
+
+ if( (i_old != -1) && (i_old != i_subtitle) )
+ {
+ input_ToggleES( p_intf->p_sys->p_input,
+ p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
+ VLC_FALSE );
+ }
+}
+
+
+void Intf_VLCWrapper::channelNext()
+{
+}
+
+void Intf_VLCWrapper::channelPrev()
+{
+}
+
+void Intf_VLCWrapper::eject(){}
+
+
+
+/* playback info */
+
+BString* Intf_VLCWrapper::getTimeAsString()
+{
+ static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return (new BString("00:00:00"));
+ }
+
+ input_OffsetToTime( p_intf->p_sys->p_input,
+ psz_currenttime,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_tell );
+
+ return(new BString(psz_currenttime));
+}
+
+float Intf_VLCWrapper::getTimeAsFloat()
+{
+ float f_time = 0.0;
+
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ f_time = (float)p_intf->p_sys->p_input->stream.p_selected_area->i_tell /
+ (float)p_intf->p_sys->p_input->stream.p_selected_area->i_size;
+ }
+ else
+ {
+ f_time = 0.0;
+ }
+ return( f_time );
+}
+
+void Intf_VLCWrapper::setTimeAsFloat(float f_position)
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_Seek( p_intf->p_sys->p_input,
+ (long long int)(p_intf->p_sys->p_input->stream.p_selected_area->i_size * f_position / 100),
+ INPUT_SEEK_SET);
+ }
+}
+
+BList *Intf_VLCWrapper::playlistAsArray()
+{
+ int i;
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ BList* p_list = new BList(p_playlist->i_size);
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+
+ for( i = 0; i < p_playlist->i_size; i++ )
+ {
+ p_list->AddItem(new BString(p_playlist->pp_items[i]->psz_name));
+ }
+
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ return( p_list );
+}
+
+ /* open file/disc/network */
+void Intf_VLCWrapper::openFiles(BList *o_files)
+{
+ BString *o_file;
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ while( ( o_file = (BString *)o_files->LastItem() ) )
+ {
+ o_files->RemoveItem(o_files->CountItems() - 1);
+ playlist_Add( p_playlist, o_file->String(),
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ delete o_file;
+ }
+
+ vlc_object_release( p_playlist );
+
+}
+
+void Intf_VLCWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
+{
+ BString o_source("");
+ o_source << o_type << ":" << o_device ;
+
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ playlist_Add( p_playlist, o_source.String(),
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ vlc_object_release( p_playlist );
+}
+
+void Intf_VLCWrapper::openNet(BString o_addr, int i_port)
+{
+}
+
+void Intf_VLCWrapper::openNetChannel(BString o_addr, int i_port)
+{
+}
+
+void Intf_VLCWrapper::openNetHTTP(BString o_addr)
+{
+}
+
+void Intf_VLCWrapper::toggleMute( )
+{
+ input_ToggleMute( p_intf->p_sys->p_input );
+}
+
+/* menus management */
+
--- /dev/null
+/*****************************************************************************
+ * vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: VlcWrapper.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Florian G. Pflug <fgp@phlo.org>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ * Tony Casltey <tony@castley.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+class InterfaceWindow;
+
+/*****************************************************************************
+ * intf_sys_t: description and status of FB interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ InterfaceWindow *p_window;
+ char i_key;
+
+ /* The input thread */
+ input_thread_t * p_input;
+
+ /* The messages window */
+// msg_subscription_t * p_sub;
+
+ /* DVD mode */
+ vlc_bool_t b_disabled_menus;
+ vlc_bool_t b_loop;
+ vlc_bool_t b_mute;
+ int i_part;
+ int i_saved_volume;
+ int i_channel;
+
+};
+
+/* Intf_VLCWrapper is a singleton class
+ (only one instance at any time) */
+class Intf_VLCWrapper
+{
+public:
+ static Intf_VLCWrapper *getVLCWrapper(intf_thread_t *p_if);
+ ~Intf_VLCWrapper();
+
+// bool manage();
+ void quit();
+ int inputGetStatus();
+ /* playlist control */
+ bool playlistPlay();
+ void playlistPause();
+ void playlistStop();
+ void playlistNext();
+ void playlistPrev();
+ void playlistSkip(int i);
+ void playlistGoto(int i);
+/* Playback Modes
+ PLAYLIST_REPEAT_CURRENT
+ PLAYLIST_FORWARD
+ PLAYLIST_BACKWARD
+ PLAYLIST_FORWARD_LOOP
+ PLAYLIST_BACKWARD_LOOP
+ PLAYLIST_RANDOM
+ PLAYLIST_REVERSE_RANDOM
+*/
+
+ /* Stream Control */
+ void playSlower();
+ void playFaster();
+
+ /* input control */
+ int getStatus();
+ void setStatus(int status);
+ void inputSeek();
+ void toggleProgram(int i_program);
+ void toggleTitle(int i_title);
+ void toggleChapter(int i_chapter);
+ void toggleLanguage(int i_language);
+ void toggleSubtitle(int i_subtitle);
+ void channelNext();
+ void channelPrev();
+ void eject();
+
+ /* playback info */
+ BString* getTimeAsString();
+ float getTimeAsFloat();
+ void setTimeAsFloat(float i_offset);
+ BList* playlistAsArray();
+
+ /* open file/disc/network */
+ void openFiles(BList *o_files);
+ void openDisc(BString o_type, BString o_device, int i_title, int i_chapter);
+ void openNet(BString o_addr, int i_port);
+ void openNetChannel(BString o_addr, int i_port);
+ void openNetHTTP(BString o_addr);
+
+ /* audio stuff */
+ void toggleMute( );
+ /* menus management */
+ void setupMenus();
+
+private:
+ Intf_VLCWrapper( intf_thread_t *p_if );
+ es_descriptor_t * p_audio_es;
+ intf_thread_t *p_intf;
+
+};
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+familiar_SOURCES = familiar.c interface.c support.c callbacks.c
--- /dev/null
+/*****************************************************************************
+ * callbacks.c : Callbacks for the Familiar Linux Gtk+ plugin.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: callbacks.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <sys/types.h> /* off_t */
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include <unistd.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "callbacks.h"
+#include "interface.h"
+#include "support.h"
+#include "familiar.h"
+
+//#include "netutils.h"
+
+/*****************************************************************************
+ * Useful function to retrieve p_intf
+ ****************************************************************************/
+void * __GtkGetIntf( GtkWidget * widget )
+{
+ void *p_data;
+
+ if( GTK_IS_MENU_ITEM( widget ) )
+ {
+ /* Look for a GTK_MENU */
+ while( widget->parent && !GTK_IS_MENU( widget ) )
+ {
+ widget = widget->parent;
+ }
+
+ /* Maybe this one has the data */
+ p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
+ if( p_data )
+ {
+ return p_data;
+ }
+
+ /* Otherwise, the parent widget has it */
+ widget = gtk_menu_get_attach_widget( GTK_MENU( widget ) );
+ }
+
+ /* We look for the top widget */
+ widget = gtk_widget_get_toplevel( GTK_WIDGET( widget ) );
+
+ p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
+
+ return p_data;
+}
+
+/*
+ * Main interface callbacks
+ */
+
+gboolean GtkExit( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ vlc_mutex_lock( &p_intf->change_lock );
+ p_intf->p_vlc->b_die = VLC_TRUE;
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return TRUE;
+}
+
+gboolean
+on_familiar_destroy_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ GtkExit( GTK_WIDGET( widget ), user_data );
+ return TRUE;
+}
+
+
+void
+on_toolbar_open_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( button );
+ if (p_intf)
+ gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
+}
+
+
+void
+on_toolbar_preferences_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( button );
+ if (p_intf)
+ gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
+}
+
+
+void
+on_toolbar_rewind_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+
+ if( p_intf )
+ {
+ if( p_intf->p_sys->p_input )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
+ }
+ }
+}
+
+
+void
+on_toolbar_pause_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+
+ if( p_intf )
+ {
+ if( p_intf->p_sys->p_input )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
+ }
+ }
+}
+
+
+void
+on_toolbar_play_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ // Display open page
+ }
+
+ /* If the playlist is empty, open a file requester instead */
+ vlc_mutex_lock( &p_playlist->object_lock );
+ if( p_playlist->i_size )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ playlist_Play( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ // Display open page
+ }
+}
+
+
+void
+on_toolbar_stop_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+}
+
+
+void
+on_toolbar_forward_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+
+ if( p_intf )
+ {
+ if( p_intf->p_sys->p_input )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
+ }
+ }
+}
+
+
+void
+on_toolbar_about_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( button );
+ if (p_intf)
+ { // Toggle notebook
+// if ( gtk_get_data( GTK_WIDGET(p_intf->p_sys->p_notebook), "visible" ) )
+// gtk_widget_hide( GTK_WIDGET(p_intf->p_sys->p_notebook) );
+// else
+ gtk_widget_show( GTK_WIDGET(p_intf->p_sys->p_notebook) );
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * callbacks.h : familiar plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: callbacks.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include <gtk/gtk.h>
+
+gboolean GtkExit ( GtkWidget *, gpointer );
+
+gboolean
+on_familiar_destroy_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data);
+
+void
+on_toolbar_open_clicked (GtkButton *button,
+ gpointer user_data);
+
+void
+on_toolbar_preferences_clicked (GtkButton *button,
+ gpointer user_data);
+
+void
+on_toolbar_rewind_clicked (GtkButton *button,
+ gpointer user_data);
+
+void
+on_toolbar_pause_clicked (GtkButton *button,
+ gpointer user_data);
+
+void
+on_toolbar_play_clicked (GtkButton *button,
+ gpointer user_data);
+
+void
+on_toolbar_stop_clicked (GtkButton *button,
+ gpointer user_data);
+
+void
+on_toolbar_forward_clicked (GtkButton *button,
+ gpointer user_data);
+
+void
+on_toolbar_about_clicked (GtkButton *button,
+ gpointer user_data);
--- /dev/null
+/*****************************************************************************
+ * familiar.c : familiar plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: familiar.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <gtk/gtk.h>
+
+#include "callbacks.h"
+#include "interface.h"
+#include "support.h"
+#include "familiar.h"
+
+/*****************************************************************************
+ * Local variables (mutex-protected).
+ *****************************************************************************/
+static void ** pp_global_data = NULL;
+
+/*****************************************************************************
+ * g_atexit: kludge to avoid the Gtk+ thread to segfault at exit
+ *****************************************************************************
+ * gtk_init() makes several calls to g_atexit() which calls atexit() to
+ * register tidying callbacks to be called at program exit. Since the Gtk+
+ * plugin is likely to be unloaded at program exit, we have to export this
+ * symbol to intercept the g_atexit() calls. Talk about crude hack.
+ *****************************************************************************/
+void g_atexit( GVoidFunc func )
+{
+ intf_thread_t *p_intf;
+
+ int i_dummy;
+
+ if( pp_global_data == NULL )
+ {
+ atexit( func );
+ return;
+ }
+
+ p_intf = (intf_thread_t *)*pp_global_data;
+ if( p_intf == NULL )
+ {
+ return;
+ }
+
+ for( i_dummy = 0;
+ i_dummy < MAX_ATEXIT && p_intf->p_sys->pf_callback[i_dummy] != NULL;
+ i_dummy++ )
+ {
+ ;
+ }
+
+ if( i_dummy >= MAX_ATEXIT - 1 )
+ {
+ msg_Err( p_intf, "too many atexit() callbacks to register" );
+ return;
+ }
+
+ p_intf->p_sys->pf_callback[i_dummy] = func;
+ p_intf->p_sys->pf_callback[i_dummy + 1] = NULL;
+}
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static void Run ( intf_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Familiar Linux Gtk+ interface module") );
+ set_capability( "interface", 70 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: initialize and create window
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return( 1 );
+ }
+
+ /* Initialize Gtk+ thread */
+ p_intf->p_sys->p_input = NULL;
+
+ p_intf->pf_run = Run;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Close: destroy interface window
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ /* Destroy structure */
+ if (p_intf->p_sys) free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: Gtk+ thread
+ *****************************************************************************
+ * this part of the interface is in a separate thread so that we can call
+ * gtk_main() from within it without annoying the rest of the program.
+ * XXX: the approach may look kludgy, and probably is, but I could not find
+ * a better way to dynamically load a Gtk+ interface at runtime.
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ /* gtk_init needs to know the command line. We don't care, so we
+ * give it an empty one */
+ char *p_args[] = { "" };
+ char **pp_args = p_args;
+ int i_args = 1;
+ int i_dummy = 0;
+
+ /* Initialize Gtk+ */
+ gtk_set_locale ();
+
+ /* gtk_init will register stuff with g_atexit, so we need to take
+ * the global lock if we want to be able to intercept the calls */
+ vlc_mutex_lock( p_intf->p_vlc->p_global_lock );
+ *p_intf->p_vlc->pp_global_data = p_intf;
+ gtk_init( &i_args, &pp_args );
+ vlc_mutex_unlock( p_intf->p_vlc->p_global_lock );
+
+ /* Create some useful widgets that will certainly be used */
+// FIXME: magic path
+ add_pixmap_directory("share");
+ p_intf->p_sys->p_window = create_familiar();
+ if (p_intf->p_sys->p_window == NULL)
+ {
+ msg_Err( p_intf, "unable to create familiar interface" );
+ }
+
+ /* Set the title of the main window */
+ gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
+ VOUT_TITLE " (Familiar Linux interface)");
+
+ /* Get the slider object */
+ p_intf->p_sys->p_notebook = GTK_NOTEBOOK( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_window ), "notebook" ) );
+// gtk_widget_hide( GTK_WIDGET(p_intf->p_sys->p_notebook) );
+
+ /* Store p_intf to keep an eye on it */
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
+ "p_intf", p_intf );
+ /* Show the control window */
+ gtk_widget_show( p_intf->p_sys->p_window );
+
+ /* Enter Gtk mode */
+ gtk_main();
+
+ /* Remove the timeout */
+ gtk_timeout_remove( i_dummy );
+}
+
--- /dev/null
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>Familiar</name>
+ <program_name>familiar</program_name>
+ <directory></directory>
+ <source_directory></source_directory>
+ <pixmaps_directory>../../share</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>False</gnome_support>
+ <gettext_support>True</gettext_support>
+ <use_widget_names>True</use_widget_names>
+ <output_main_file>False</output_main_file>
+ <output_build_files>False</output_build_files>
+ <main_source_file>interface.c</main_source_file>
+ <main_header_file>interface.h</main_header_file>
+ <handler_source_file>callbacks.c</handler_source_file>
+ <handler_header_file>callbacks.h</handler_header_file>
+ <support_source_file>support.c</support_source_file>
+ <support_header_file>support.h</support_header_file>
+</project>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>familiar</name>
+ <width>240</width>
+ <height>320</height>
+ <signal>
+ <name>destroy_event</name>
+ <handler>on_familiar_destroy_event</handler>
+ <last_modification_time>Tue, 23 Jul 2002 18:16:11 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>destroy</name>
+ <handler>gtk_main_quit</handler>
+ <last_modification_time>Tue, 23 Jul 2002 18:17:28 GMT</last_modification_time>
+ </signal>
+ <title>vlc (familiar)</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>True</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>True</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkToolbar</class>
+ <name>toolbar</name>
+ <width>112</width>
+ <height>16</height>
+ <orientation>GTK_ORIENTATION_HORIZONTAL</orientation>
+ <type>GTK_TOOLBAR_ICONS</type>
+ <space_size>5</space_size>
+ <space_style>GTK_TOOLBAR_SPACE_EMPTY</space_style>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <tooltips>True</tooltips>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_open</name>
+ <tooltip>Open file</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_open_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:28:31 GMT</last_modification_time>
+ </signal>
+ <label>Open</label>
+ <icon>familiar-openb16x16.xpm</icon>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_preferences</name>
+ <tooltip>Preferences</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_preferences_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:29:05 GMT</last_modification_time>
+ </signal>
+ <label>Preferences</label>
+ <icon>familiar-preferencesb16x16.xpm</icon>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_rewind</name>
+ <tooltip>Rewind stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_rewind_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:28:45 GMT</last_modification_time>
+ </signal>
+ <label>Rewind</label>
+ <icon>familiar-rewindb16x16.xpm</icon>
+ <child>
+ <new_group>True</new_group>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_pause</name>
+ <tooltip>Pause stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_pause_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:28:58 GMT</last_modification_time>
+ </signal>
+ <label>Pause</label>
+ <icon>familiar-pauseb16x16.xpm</icon>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_play</name>
+ <tooltip>Play stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_play_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:29:12 GMT</last_modification_time>
+ </signal>
+ <label>Play</label>
+ <icon>familiar-playb16x16.xpm</icon>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_stop</name>
+ <tooltip>Stop stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_stop_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:29:18 GMT</last_modification_time>
+ </signal>
+ <label>Stop</label>
+ <icon>familiar-stopb16x16.xpm</icon>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_forward</name>
+ <tooltip>Forward stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_forward_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:29:25 GMT</last_modification_time>
+ </signal>
+ <label>Forward</label>
+ <icon>familiar-forwardb16x16.xpm</icon>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_about</name>
+ <tooltip>About</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>on_toolbar_about_clicked</handler>
+ <last_modification_time>Wed, 24 Jul 2002 18:29:31 GMT</last_modification_time>
+ </signal>
+ <label>About</label>
+ <icon>vlc16x16.xpm</icon>
+ <child>
+ <new_group>True</new_group>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkProgressBar</class>
+ <name>progress</name>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <bar_style>GTK_PROGRESS_CONTINUOUS</bar_style>
+ <orientation>GTK_PROGRESS_LEFT_TO_RIGHT</orientation>
+ <activity_mode>True</activity_mode>
+ <show_text>False</show_text>
+ <format>%P %%</format>
+ <text_xalign>0.5</text_xalign>
+ <text_yalign>0.5</text_yalign>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkNotebook</class>
+ <name>notebook</name>
+ <can_focus>True</can_focus>
+ <show_tabs>True</show_tabs>
+ <show_border>True</show_border>
+ <tab_pos>GTK_POS_TOP</tab_pos>
+ <scrollable>False</scrollable>
+ <tab_hborder>2</tab_hborder>
+ <tab_vborder>2</tab_vborder>
+ <popup_enable>False</popup_enable>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkFixed</class>
+ <name>fixedMedia</name>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>labelUrl</name>
+ <x>4</x>
+ <y>8</y>
+ <width>38</width>
+ <height>18</height>
+ <label>URL:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkList</class>
+ <name>listMedia</name>
+ <x>8</x>
+ <y>40</y>
+ <width>220</width>
+ <height>200</height>
+ <tooltip>Select multimedia file.</tooltip>
+ <selection_mode>GTK_SELECTION_MULTIPLE</selection_mode>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>comboURL</name>
+ <x>46</x>
+ <y>6</y>
+ <width>185</width>
+ <height>24</height>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items>file://
+ftp://localhost
+http://localhost
+udp://localhost:1234/
+</items>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>combo-entry1</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text>file://</text>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>media</name>
+ <label>Media</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkFixed</class>
+ <name>fixedPreferences</name>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>buttonSave</name>
+ <x>8</x>
+ <y>216</y>
+ <width>54</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <label>Save</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>buttonApply</name>
+ <x>64</x>
+ <y>216</y>
+ <width>54</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <label>Apply</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>buttonCancel</name>
+ <x>176</x>
+ <y>216</y>
+ <width>54</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <label>Cancel</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frameDefaultURL</name>
+ <x>8</x>
+ <y>8</y>
+ <width>220</width>
+ <height>60</height>
+ <label>Default URL:</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+
+ <widget>
+ <class>GtkFixed</class>
+ <name>fixed3</name>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>comboDefaultURL</name>
+ <x>8</x>
+ <y>4</y>
+ <width>200</width>
+ <height>24</height>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items>file://
+ftp://localhost
+http://localhost
+udp://localhost:1234/
+</items>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>combo-entry2</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text>file://</text>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frameIP</name>
+ <x>8</x>
+ <y>72</y>
+ <width>220</width>
+ <height>60</height>
+ <label>IP version:</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+
+ <widget>
+ <class>GtkFixed</class>
+ <name>fixed2</name>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>rbIPv4</name>
+ <x>8</x>
+ <y>8</y>
+ <width>104</width>
+ <height>26</height>
+ <can_focus>True</can_focus>
+ <label>IPv4</label>
+ <active>True</active>
+ <draw_indicator>True</draw_indicator>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>rbIPv6</name>
+ <x>112</x>
+ <y>8</y>
+ <width>104</width>
+ <height>26</height>
+ <can_focus>True</can_focus>
+ <label>IPv6</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>preferences</name>
+ <label>Preference</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkFixed</class>
+ <name>fixedAbout</name>
+
+ <widget>
+ <class>GtkPixmap</class>
+ <name>logo</name>
+ <x>8</x>
+ <y>0</y>
+ <width>50</width>
+ <height>50</height>
+ <filename>vlc32x32.xpm</filename>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <build_insensitive>True</build_insensitive>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>labelVlc</name>
+ <x>64</x>
+ <y>8</y>
+ <width>120</width>
+ <height>40</height>
+ <label>VideoLAN Client
+ for familiar Linux</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>True</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>labelCopyright</name>
+ <x>16</x>
+ <y>56</y>
+ <width>200</width>
+ <height>18</height>
+ <label>(c) 2002, the VideoLAN Team</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>labelAuthors</name>
+ <x>16</x>
+ <y>80</y>
+ <width>200</width>
+ <height>40</height>
+ <label>Authors: The VideoLAN Team, http://www.videolan.org</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>True</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>labelAbout</name>
+ <x>16</x>
+ <y>128</y>
+ <width>200</width>
+ <height>70</height>
+ <label>The VideoLAN Client is a MPEG, MPEG 2, MP3, DivX player, that accepts input from local or network sources.</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>True</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>about</name>
+ <label>About</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
--- /dev/null
+/*****************************************************************************
+ * familiar.h: private Gtk+ interface description
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: familiar.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#define MAX_ATEXIT 10
+
+/*****************************************************************************
+ * intf_sys_t: description and status of Gtk+ interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ /* windows and widgets */
+ GtkWidget * p_window; /* main window */
+ GtkNotebook * p_notebook;
+// GtkWidget * p_notebook_about;
+// GtkWidget * p_notebook_open;
+// GtkWidget * p_notebook_preferences;
+
+ /* The input thread */
+ input_thread_t * p_input;
+
+ /* XXX: Ugly kludge, see gtk.c */
+ void ( *pf_callback[MAX_ATEXIT] ) ( void );
+};
+
+/*****************************************************************************
+ * Useful macro
+ ****************************************************************************/
+#define GtkGetIntf( widget ) __GtkGetIntf( GTK_WIDGET( widget ) )
+void * __GtkGetIntf( GtkWidget * );
+
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "callbacks.h"
+#include "interface.h"
+#include "support.h"
+
+GtkWidget*
+create_familiar (void)
+{
+ GtkWidget *familiar;
+ GtkWidget *vbox;
+ GtkWidget *toolbar;
+ GtkWidget *tmp_toolbar_icon;
+ GtkWidget *toolbar_open;
+ GtkWidget *toolbar_preferences;
+ GtkWidget *toolbar_rewind;
+ GtkWidget *toolbar_pause;
+ GtkWidget *toolbar_play;
+ GtkWidget *toolbar_stop;
+ GtkWidget *toolbar_forward;
+ GtkWidget *toolbar_about;
+ GtkWidget *progress;
+ GtkWidget *notebook;
+ GtkWidget *fixedMedia;
+ GtkWidget *labelUrl;
+ GtkWidget *listMedia;
+ GtkWidget *comboURL;
+ GList *comboURL_items = NULL;
+ GtkWidget *combo_entry1;
+ GtkWidget *media;
+ GtkWidget *fixedPreferences;
+ GtkWidget *buttonSave;
+ GtkWidget *buttonApply;
+ GtkWidget *buttonCancel;
+ GtkWidget *frameDefaultURL;
+ GtkWidget *fixed3;
+ GtkWidget *comboDefaultURL;
+ GList *comboDefaultURL_items = NULL;
+ GtkWidget *combo_entry2;
+ GtkWidget *frameIP;
+ GtkWidget *fixed2;
+ GSList *fixed2_group = NULL;
+ GtkWidget *rbIPv4;
+ GtkWidget *rbIPv6;
+ GtkWidget *preferences;
+ GtkWidget *fixedAbout;
+ GtkWidget *logo;
+ GtkWidget *labelVlc;
+ GtkWidget *labelCopyright;
+ GtkWidget *labelAuthors;
+ GtkWidget *labelAbout;
+ GtkWidget *about;
+ GtkTooltips *tooltips;
+
+ tooltips = gtk_tooltips_new ();
+
+ familiar = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (familiar, "familiar");
+ gtk_object_set_data (GTK_OBJECT (familiar), "familiar", familiar);
+ gtk_widget_set_usize (familiar, 240, 320);
+ gtk_window_set_title (GTK_WINDOW (familiar), _("vlc (familiar)"));
+ gtk_window_set_policy (GTK_WINDOW (familiar), TRUE, TRUE, TRUE);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_set_name (vbox, "vbox");
+ gtk_widget_ref (vbox);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "vbox", vbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (vbox);
+ gtk_container_add (GTK_CONTAINER (familiar), vbox);
+
+ toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
+ gtk_widget_set_name (toolbar, "toolbar");
+ gtk_widget_ref (toolbar);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar", toolbar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar);
+ gtk_box_pack_start (GTK_BOX (vbox), toolbar, TRUE, TRUE, 0);
+ gtk_widget_set_usize (toolbar, 112, 16);
+
+ tmp_toolbar_icon = create_pixmap (familiar, "familiar-openb16x16.xpm");
+ toolbar_open = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Open"),
+ _("Open file"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_open, "toolbar_open");
+ gtk_widget_ref (toolbar_open);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_open", toolbar_open,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_open);
+
+ tmp_toolbar_icon = create_pixmap (familiar, "familiar-preferencesb16x16.xpm");
+ toolbar_preferences = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Preferences"),
+ _("Preferences"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_preferences, "toolbar_preferences");
+ gtk_widget_ref (toolbar_preferences);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_preferences", toolbar_preferences,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_preferences);
+
+ gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+ tmp_toolbar_icon = create_pixmap (familiar, "familiar-rewindb16x16.xpm");
+ toolbar_rewind = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Rewind"),
+ _("Rewind stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_rewind, "toolbar_rewind");
+ gtk_widget_ref (toolbar_rewind);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_rewind", toolbar_rewind,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_rewind);
+
+ tmp_toolbar_icon = create_pixmap (familiar, "familiar-pauseb16x16.xpm");
+ toolbar_pause = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Pause"),
+ _("Pause stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_pause, "toolbar_pause");
+ gtk_widget_ref (toolbar_pause);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_pause", toolbar_pause,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_pause);
+
+ tmp_toolbar_icon = create_pixmap (familiar, "familiar-playb16x16.xpm");
+ toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Play"),
+ _("Play stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_play, "toolbar_play");
+ gtk_widget_ref (toolbar_play);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_play", toolbar_play,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_play);
+
+ tmp_toolbar_icon = create_pixmap (familiar, "familiar-stopb16x16.xpm");
+ toolbar_stop = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Stop"),
+ _("Stop stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_stop, "toolbar_stop");
+ gtk_widget_ref (toolbar_stop);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_stop", toolbar_stop,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_stop);
+
+ tmp_toolbar_icon = create_pixmap (familiar, "familiar-forwardb16x16.xpm");
+ toolbar_forward = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Forward"),
+ _("Forward stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_forward, "toolbar_forward");
+ gtk_widget_ref (toolbar_forward);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_forward", toolbar_forward,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_forward);
+
+ gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+ tmp_toolbar_icon = create_pixmap (familiar, "vlc16x16.xpm");
+ toolbar_about = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("About"),
+ _("About"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_set_name (toolbar_about, "toolbar_about");
+ gtk_widget_ref (toolbar_about);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar_about", toolbar_about,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_about);
+
+ progress = gtk_progress_bar_new ();
+ gtk_widget_set_name (progress, "progress");
+ gtk_widget_ref (progress);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "progress", progress,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (progress);
+ gtk_box_pack_start (GTK_BOX (vbox), progress, FALSE, FALSE, 0);
+ gtk_progress_set_activity_mode (GTK_PROGRESS (progress), TRUE);
+
+ notebook = gtk_notebook_new ();
+ gtk_widget_set_name (notebook, "notebook");
+ gtk_widget_ref (notebook);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "notebook", notebook,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (notebook);
+ gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
+
+ fixedMedia = gtk_fixed_new ();
+ gtk_widget_set_name (fixedMedia, "fixedMedia");
+ gtk_widget_ref (fixedMedia);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "fixedMedia", fixedMedia,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (fixedMedia);
+ gtk_container_add (GTK_CONTAINER (notebook), fixedMedia);
+
+ labelUrl = gtk_label_new (_("URL:"));
+ gtk_widget_set_name (labelUrl, "labelUrl");
+ gtk_widget_ref (labelUrl);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "labelUrl", labelUrl,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (labelUrl);
+ gtk_fixed_put (GTK_FIXED (fixedMedia), labelUrl, 4, 8);
+ gtk_widget_set_uposition (labelUrl, 4, 8);
+ gtk_widget_set_usize (labelUrl, 38, 18);
+
+ listMedia = gtk_list_new ();
+ gtk_widget_set_name (listMedia, "listMedia");
+ gtk_widget_ref (listMedia);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "listMedia", listMedia,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (listMedia);
+ gtk_fixed_put (GTK_FIXED (fixedMedia), listMedia, 8, 40);
+ gtk_widget_set_uposition (listMedia, 8, 40);
+ gtk_widget_set_usize (listMedia, 220, 200);
+ gtk_tooltips_set_tip (tooltips, listMedia, _("Select multimedia file."), NULL);
+ gtk_list_set_selection_mode (GTK_LIST (listMedia), GTK_SELECTION_MULTIPLE);
+
+ comboURL = gtk_combo_new ();
+ gtk_widget_set_name (comboURL, "comboURL");
+ gtk_widget_ref (comboURL);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "comboURL", comboURL,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (comboURL);
+ gtk_fixed_put (GTK_FIXED (fixedMedia), comboURL, 46, 6);
+ gtk_widget_set_uposition (comboURL, 46, 6);
+ gtk_widget_set_usize (comboURL, 185, 24);
+ comboURL_items = g_list_append (comboURL_items, (gpointer) _("file://"));
+ comboURL_items = g_list_append (comboURL_items, (gpointer) _("ftp://localhost"));
+ comboURL_items = g_list_append (comboURL_items, (gpointer) _("http://localhost"));
+ comboURL_items = g_list_append (comboURL_items, (gpointer) _("udp://localhost:1234/"));
+ gtk_combo_set_popdown_strings (GTK_COMBO (comboURL), comboURL_items);
+ g_list_free (comboURL_items);
+
+ combo_entry1 = GTK_COMBO (comboURL)->entry;
+ gtk_widget_set_name (combo_entry1, "combo_entry1");
+ gtk_widget_ref (combo_entry1);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "combo_entry1", combo_entry1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo_entry1);
+ gtk_entry_set_text (GTK_ENTRY (combo_entry1), _("file://"));
+
+ media = gtk_label_new (_("Media"));
+ gtk_widget_set_name (media, "media");
+ gtk_widget_ref (media);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "media", media,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (media);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0), media);
+
+ fixedPreferences = gtk_fixed_new ();
+ gtk_widget_set_name (fixedPreferences, "fixedPreferences");
+ gtk_widget_ref (fixedPreferences);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "fixedPreferences", fixedPreferences,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (fixedPreferences);
+ gtk_container_add (GTK_CONTAINER (notebook), fixedPreferences);
+
+ buttonSave = gtk_button_new_with_label (_("Save"));
+ gtk_widget_set_name (buttonSave, "buttonSave");
+ gtk_widget_ref (buttonSave);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "buttonSave", buttonSave,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (buttonSave);
+ gtk_fixed_put (GTK_FIXED (fixedPreferences), buttonSave, 8, 216);
+ gtk_widget_set_uposition (buttonSave, 8, 216);
+ gtk_widget_set_usize (buttonSave, 54, 24);
+
+ buttonApply = gtk_button_new_with_label (_("Apply"));
+ gtk_widget_set_name (buttonApply, "buttonApply");
+ gtk_widget_ref (buttonApply);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "buttonApply", buttonApply,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (buttonApply);
+ gtk_fixed_put (GTK_FIXED (fixedPreferences), buttonApply, 64, 216);
+ gtk_widget_set_uposition (buttonApply, 64, 216);
+ gtk_widget_set_usize (buttonApply, 54, 24);
+
+ buttonCancel = gtk_button_new_with_label (_("Cancel"));
+ gtk_widget_set_name (buttonCancel, "buttonCancel");
+ gtk_widget_ref (buttonCancel);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "buttonCancel", buttonCancel,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (buttonCancel);
+ gtk_fixed_put (GTK_FIXED (fixedPreferences), buttonCancel, 176, 216);
+ gtk_widget_set_uposition (buttonCancel, 176, 216);
+ gtk_widget_set_usize (buttonCancel, 54, 24);
+
+ frameDefaultURL = gtk_frame_new (_("Default URL:"));
+ gtk_widget_set_name (frameDefaultURL, "frameDefaultURL");
+ gtk_widget_ref (frameDefaultURL);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "frameDefaultURL", frameDefaultURL,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (frameDefaultURL);
+ gtk_fixed_put (GTK_FIXED (fixedPreferences), frameDefaultURL, 8, 8);
+ gtk_widget_set_uposition (frameDefaultURL, 8, 8);
+ gtk_widget_set_usize (frameDefaultURL, 220, 60);
+
+ fixed3 = gtk_fixed_new ();
+ gtk_widget_set_name (fixed3, "fixed3");
+ gtk_widget_ref (fixed3);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "fixed3", fixed3,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (fixed3);
+ gtk_container_add (GTK_CONTAINER (frameDefaultURL), fixed3);
+
+ comboDefaultURL = gtk_combo_new ();
+ gtk_widget_set_name (comboDefaultURL, "comboDefaultURL");
+ gtk_widget_ref (comboDefaultURL);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "comboDefaultURL", comboDefaultURL,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (comboDefaultURL);
+ gtk_fixed_put (GTK_FIXED (fixed3), comboDefaultURL, 8, 4);
+ gtk_widget_set_uposition (comboDefaultURL, 8, 4);
+ gtk_widget_set_usize (comboDefaultURL, 200, 24);
+ comboDefaultURL_items = g_list_append (comboDefaultURL_items, (gpointer) _("file://"));
+ comboDefaultURL_items = g_list_append (comboDefaultURL_items, (gpointer) _("ftp://localhost"));
+ comboDefaultURL_items = g_list_append (comboDefaultURL_items, (gpointer) _("http://localhost"));
+ comboDefaultURL_items = g_list_append (comboDefaultURL_items, (gpointer) _("udp://localhost:1234/"));
+ gtk_combo_set_popdown_strings (GTK_COMBO (comboDefaultURL), comboDefaultURL_items);
+ g_list_free (comboDefaultURL_items);
+
+ combo_entry2 = GTK_COMBO (comboDefaultURL)->entry;
+ gtk_widget_set_name (combo_entry2, "combo_entry2");
+ gtk_widget_ref (combo_entry2);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "combo_entry2", combo_entry2,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo_entry2);
+ gtk_entry_set_text (GTK_ENTRY (combo_entry2), _("file://"));
+
+ frameIP = gtk_frame_new (_("IP version:"));
+ gtk_widget_set_name (frameIP, "frameIP");
+ gtk_widget_ref (frameIP);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "frameIP", frameIP,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (frameIP);
+ gtk_fixed_put (GTK_FIXED (fixedPreferences), frameIP, 8, 72);
+ gtk_widget_set_uposition (frameIP, 8, 72);
+ gtk_widget_set_usize (frameIP, 220, 60);
+
+ fixed2 = gtk_fixed_new ();
+ gtk_widget_set_name (fixed2, "fixed2");
+ gtk_widget_ref (fixed2);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "fixed2", fixed2,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (fixed2);
+ gtk_container_add (GTK_CONTAINER (frameIP), fixed2);
+
+ rbIPv4 = gtk_radio_button_new_with_label (fixed2_group, _("IPv4"));
+ fixed2_group = gtk_radio_button_group (GTK_RADIO_BUTTON (rbIPv4));
+ gtk_widget_set_name (rbIPv4, "rbIPv4");
+ gtk_widget_ref (rbIPv4);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "rbIPv4", rbIPv4,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (rbIPv4);
+ gtk_fixed_put (GTK_FIXED (fixed2), rbIPv4, 8, 8);
+ gtk_widget_set_uposition (rbIPv4, 8, 8);
+ gtk_widget_set_usize (rbIPv4, 104, 26);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rbIPv4), TRUE);
+
+ rbIPv6 = gtk_radio_button_new_with_label (fixed2_group, _("IPv6"));
+ fixed2_group = gtk_radio_button_group (GTK_RADIO_BUTTON (rbIPv6));
+ gtk_widget_set_name (rbIPv6, "rbIPv6");
+ gtk_widget_ref (rbIPv6);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "rbIPv6", rbIPv6,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (rbIPv6);
+ gtk_fixed_put (GTK_FIXED (fixed2), rbIPv6, 112, 8);
+ gtk_widget_set_uposition (rbIPv6, 112, 8);
+ gtk_widget_set_usize (rbIPv6, 104, 26);
+
+ preferences = gtk_label_new (_("Preference"));
+ gtk_widget_set_name (preferences, "preferences");
+ gtk_widget_ref (preferences);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "preferences", preferences,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (preferences);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1), preferences);
+
+ fixedAbout = gtk_fixed_new ();
+ gtk_widget_set_name (fixedAbout, "fixedAbout");
+ gtk_widget_ref (fixedAbout);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "fixedAbout", fixedAbout,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (fixedAbout);
+ gtk_container_add (GTK_CONTAINER (notebook), fixedAbout);
+
+ logo = create_pixmap (familiar, "vlc32x32.xpm");
+ gtk_widget_set_name (logo, "logo");
+ gtk_widget_ref (logo);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "logo", logo,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (logo);
+ gtk_fixed_put (GTK_FIXED (fixedAbout), logo, 8, 0);
+ gtk_widget_set_uposition (logo, 8, 0);
+ gtk_widget_set_usize (logo, 50, 50);
+
+ labelVlc = gtk_label_new (_("VideoLAN Client\n for familiar Linux"));
+ gtk_widget_set_name (labelVlc, "labelVlc");
+ gtk_widget_ref (labelVlc);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "labelVlc", labelVlc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (labelVlc);
+ gtk_fixed_put (GTK_FIXED (fixedAbout), labelVlc, 64, 8);
+ gtk_widget_set_uposition (labelVlc, 64, 8);
+ gtk_widget_set_usize (labelVlc, 120, 40);
+ gtk_label_set_line_wrap (GTK_LABEL (labelVlc), TRUE);
+
+ labelCopyright = gtk_label_new (_("(c) 2002, the VideoLAN Team"));
+ gtk_widget_set_name (labelCopyright, "labelCopyright");
+ gtk_widget_ref (labelCopyright);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "labelCopyright", labelCopyright,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (labelCopyright);
+ gtk_fixed_put (GTK_FIXED (fixedAbout), labelCopyright, 16, 56);
+ gtk_widget_set_uposition (labelCopyright, 16, 56);
+ gtk_widget_set_usize (labelCopyright, 200, 18);
+
+ labelAuthors = gtk_label_new (_("Authors: The VideoLAN Team, http://www.videolan.org"));
+ gtk_widget_set_name (labelAuthors, "labelAuthors");
+ gtk_widget_ref (labelAuthors);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "labelAuthors", labelAuthors,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (labelAuthors);
+ gtk_fixed_put (GTK_FIXED (fixedAbout), labelAuthors, 16, 80);
+ gtk_widget_set_uposition (labelAuthors, 16, 80);
+ gtk_widget_set_usize (labelAuthors, 200, 40);
+ gtk_label_set_line_wrap (GTK_LABEL (labelAuthors), TRUE);
+
+ labelAbout = gtk_label_new (_("The VideoLAN Client is a MPEG, MPEG 2, MP3, DivX player, that accepts input from local or network sources."));
+ gtk_widget_set_name (labelAbout, "labelAbout");
+ gtk_widget_ref (labelAbout);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "labelAbout", labelAbout,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (labelAbout);
+ gtk_fixed_put (GTK_FIXED (fixedAbout), labelAbout, 16, 128);
+ gtk_widget_set_uposition (labelAbout, 16, 128);
+ gtk_widget_set_usize (labelAbout, 200, 70);
+ gtk_label_set_justify (GTK_LABEL (labelAbout), GTK_JUSTIFY_LEFT);
+ gtk_label_set_line_wrap (GTK_LABEL (labelAbout), TRUE);
+
+ about = gtk_label_new (_("About"));
+ gtk_widget_set_name (about, "about");
+ gtk_widget_ref (about);
+ gtk_object_set_data_full (GTK_OBJECT (familiar), "about", about,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (about);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 2), about);
+
+ gtk_signal_connect (GTK_OBJECT (familiar), "destroy_event",
+ GTK_SIGNAL_FUNC (on_familiar_destroy_event),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (familiar), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_open), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_open_clicked),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_preferences), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_preferences_clicked),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_rewind), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_rewind_clicked),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_pause), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_pause_clicked),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_play), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_play_clicked),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_stop), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_stop_clicked),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_forward), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_forward_clicked),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_about), "clicked",
+ GTK_SIGNAL_FUNC (on_toolbar_about_clicked),
+ NULL);
+
+ gtk_object_set_data (GTK_OBJECT (familiar), "tooltips", tooltips);
+
+ return familiar;
+}
+
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+GtkWidget* create_familiar (void);
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "support.h"
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar* check_file_exists (const gchar *directory,
+ const gchar *filename);
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget* create_dummy_pixmap (GtkWidget *widget);
+
+GtkWidget*
+lookup_widget (GtkWidget *widget,
+ const gchar *widget_name)
+{
+ GtkWidget *parent, *found_widget;
+
+ for (;;)
+ {
+ if (GTK_IS_MENU (widget))
+ parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
+ else
+ parent = widget->parent;
+ if (parent == NULL)
+ break;
+ widget = parent;
+ }
+
+ found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
+ widget_name);
+ if (!found_widget)
+ g_warning ("Widget not found: %s", widget_name);
+ return found_widget;
+}
+
+/* This is a dummy pixmap we use when a pixmap can't be found. */
+static char *dummy_pixmap_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"1 1 1 1",
+" c None",
+/* pixels */
+" "
+};
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget*
+create_dummy_pixmap (GtkWidget *widget)
+{
+ GdkColormap *colormap;
+ GdkPixmap *gdkpixmap;
+ GdkBitmap *mask;
+ GtkWidget *pixmap;
+
+ colormap = gtk_widget_get_colormap (widget);
+ gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
+ NULL, dummy_pixmap_xpm);
+ if (gdkpixmap == NULL)
+ g_error ("Couldn't create replacement pixmap.");
+ pixmap = gtk_pixmap_new (gdkpixmap, mask);
+ gdk_pixmap_unref (gdkpixmap);
+ gdk_bitmap_unref (mask);
+ return pixmap;
+}
+
+static GList *pixmaps_directories = NULL;
+
+/* Use this function to set the directory containing installed pixmaps. */
+void
+add_pixmap_directory (const gchar *directory)
+{
+ pixmaps_directories = g_list_prepend (pixmaps_directories,
+ g_strdup (directory));
+}
+
+/* This is an internally used function to create pixmaps. */
+GtkWidget*
+create_pixmap (GtkWidget *widget,
+ const gchar *filename)
+{
+ gchar *found_filename = NULL;
+ GdkColormap *colormap;
+ GdkPixmap *gdkpixmap;
+ GdkBitmap *mask;
+ GtkWidget *pixmap;
+ GList *elem;
+
+ if (!filename || !filename[0])
+ return create_dummy_pixmap (widget);
+
+ /* We first try any pixmaps directories set by the application. */
+ elem = pixmaps_directories;
+ while (elem)
+ {
+ found_filename = check_file_exists ((gchar*)elem->data, filename);
+ if (found_filename)
+ break;
+ elem = elem->next;
+ }
+
+ /* If we haven't found the pixmap, try the source directory. */
+ if (!found_filename)
+ {
+ found_filename = check_file_exists ("../../share", filename);
+ }
+
+ if (!found_filename)
+ {
+ g_warning (_("Couldn't find pixmap file: %s"), filename);
+ return create_dummy_pixmap (widget);
+ }
+
+ colormap = gtk_widget_get_colormap (widget);
+ gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,
+ NULL, found_filename);
+ if (gdkpixmap == NULL)
+ {
+ g_warning (_("Error loading pixmap file: %s"), found_filename);
+ g_free (found_filename);
+ return create_dummy_pixmap (widget);
+ }
+ g_free (found_filename);
+ pixmap = gtk_pixmap_new (gdkpixmap, mask);
+ gdk_pixmap_unref (gdkpixmap);
+ gdk_bitmap_unref (mask);
+ return pixmap;
+}
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar*
+check_file_exists (const gchar *directory,
+ const gchar *filename)
+{
+ gchar *full_filename;
+ struct stat s;
+ gint status;
+
+ full_filename = (gchar*) g_malloc (strlen (directory) + 1
+ + strlen (filename) + 1);
+ strcpy (full_filename, directory);
+ strcat (full_filename, G_DIR_SEPARATOR_S);
+ strcat (full_filename, filename);
+
+ status = stat (full_filename, &s);
+ if (status == 0 && S_ISREG (s.st_mode))
+ return full_filename;
+ g_free (full_filename);
+ return NULL;
+}
+
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+/*
+ * Standard gettext macros.
+ */
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# undef _
+# define _(String) dgettext (PACKAGE, String)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+
+/*
+ * Public Functions.
+ */
+
+/*
+ * This function returns a widget in a component created by Glade.
+ * Call it with the toplevel widget in the component (i.e. a window/dialog),
+ * or alternatively any widget in the component, and the name of the widget
+ * you want returned.
+ */
+GtkWidget* lookup_widget (GtkWidget *widget,
+ const gchar *widget_name);
+
+/* get_widget() is deprecated. Use lookup_widget instead. */
+#define get_widget lookup_widget
+
+/* Use this function to set the directory containing installed pixmaps. */
+void add_pixmap_directory (const gchar *directory);
+
+
+/*
+ * Private Functions.
+ */
+
+/* This is used to create the pixmaps in the interface. */
+GtkWidget* create_pixmap (GtkWidget *widget,
+ const gchar *filename);
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+COMMON_SOURCES = display.c open.c control.c menu.c playlist.c modules.c preferences.c gtk_callbacks.c
+
+gtk_SOURCES = gtk.c gtk_interface.c gtk_support.c $(COMMON_SOURCES)
+gnome_SOURCES = gnome.c gnome_interface.c gnome_support.c $(COMMON_SOURCES)
--- /dev/null
+/*****************************************************************************
+ * gtk_common.h: private Gtk+ interface description
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: common.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Drag'n'drop stuff
+ *****************************************************************************/
+#define DROP_ACCEPT_TEXT_URI_LIST 0
+#define DROP_ACCEPT_TEXT_PLAIN 1
+#define DROP_ACCEPT_STRING 2
+
+#define MAX_ATEXIT 10
+
+/*****************************************************************************
+ * intf_sys_t: description and status of Gtk+ interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ /* special actions */
+ vlc_bool_t b_playing;
+ vlc_bool_t b_popup_changed; /* display menu ? */
+ vlc_bool_t b_window_changed; /* window display toggled ? */
+ vlc_bool_t b_playlist_changed; /* playlist display toggled ? */
+ vlc_bool_t b_slider_free; /* slider status */
+
+ /* menus handlers */
+ vlc_bool_t b_program_update; /* do we need to update programs
+ menu */
+ vlc_bool_t b_title_update; /* do we need to update title menus */
+ vlc_bool_t b_chapter_update; /* do we need to update
+ chapter menus */
+ vlc_bool_t b_audio_update; /* do we need to update audio menus */
+ vlc_bool_t b_spu_update; /* do we need to update spu menus */
+
+ /* windows and widgets */
+ GtkWidget * p_window; /* main window */
+ GtkWidget * p_popup; /* popup menu */
+ GtkWidget * p_playwin; /* playlist */
+ GtkWidget * p_modules; /* module manager */
+ GtkWidget * p_about; /* about window */
+ GtkWidget * p_open; /* multiopen window */
+ GtkWidget * p_jump; /* jump window */
+
+ GtkTooltips * p_tooltips; /* tooltips */
+
+ /* The input thread */
+ input_thread_t * p_input;
+
+ /* The slider */
+ GtkFrame * p_slider_frame;
+ GtkAdjustment * p_adj; /* slider adjustment object */
+ float f_adj_oldvalue; /* previous value */
+
+ /* The messages window */
+ GtkWidget * p_messages; /* messages window */
+ GtkText * p_messages_text; /* messages frame */
+ msg_subscription_t* p_sub; /* message bank subscription */
+
+ /* Playlist management */
+ int i_playing; /* playlist selected item */
+
+ /* The window labels for DVD mode */
+ GtkLabel * p_label_title;
+ GtkLabel * p_label_chapter;
+ gint i_part; /* current chapter */
+
+ /* XXX: Ugly kludge, see gtk.c */
+ void ( *pf_callback[MAX_ATEXIT] ) ( void );
+};
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+gint GtkModeManage ( intf_thread_t * p_intf );
+void GtkDisplayDate ( GtkAdjustment *p_adj );
+
+/*****************************************************************************
+ * Useful macro
+ ****************************************************************************/
+#define GtkGetIntf( widget ) __GtkGetIntf( GTK_WIDGET( widget ) )
+void * __GtkGetIntf( GtkWidget * );
+
--- /dev/null
+/*****************************************************************************
+ * control.c : functions to handle stream control buttons.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: control.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <sys/types.h> /* off_t */
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#ifdef MODULE_NAME_IS_gnome
+# include <gnome.h>
+#else
+# include <gtk/gtk.h>
+#endif
+
+#include <string.h>
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "playlist.h"
+#include "common.h"
+
+/****************************************************************************
+ * Control functions: this is where the functions are defined
+ ****************************************************************************
+ * These functions are button-items callbacks, and are used
+ * by other callbacks
+ ****************************************************************************/
+gboolean GtkControlBack( GtkWidget *widget,
+ gpointer user_data )
+{
+ return FALSE;
+}
+
+
+gboolean GtkControlStop( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return FALSE;
+ }
+
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+
+ return TRUE;
+}
+
+
+gboolean GtkControlPlay( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ GtkFileOpenShow( widget, user_data );
+ return TRUE;
+ }
+
+ /* If the playlist is empty, open a file requester instead */
+ vlc_mutex_lock( &p_playlist->object_lock );
+ if( p_playlist->i_size )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ playlist_Play( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ GtkFileOpenShow( widget, user_data );
+ }
+
+ return TRUE;
+}
+
+
+gboolean GtkControlPause( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return FALSE;
+ }
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
+
+ return TRUE;
+}
+
+
+gboolean GtkControlSlow( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return FALSE;
+ }
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
+
+ return TRUE;
+}
+
+
+gboolean GtkControlFast( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return FALSE;
+ }
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
+
+ return TRUE;
+}
+
--- /dev/null
+/*****************************************************************************
+ * gtk_control.h: prototypes for control functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: control.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+gboolean GtkControlBack ( GtkWidget *, gpointer );
+gboolean GtkControlStop ( GtkWidget *, gpointer );
+gboolean GtkControlPlay ( GtkWidget *, gpointer );
+gboolean GtkControlPause( GtkWidget *, gpointer );
+gboolean GtkControlSlow ( GtkWidget *, gpointer );
+gboolean GtkControlFast ( GtkWidget *, gpointer );
+
--- /dev/null
+/*****************************************************************************
+ * display.c: Gtk+ tools for main interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: display.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#ifdef MODULE_NAME_IS_gnome
+# include <gnome.h>
+#else
+# include <gtk/gtk.h>
+#endif
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "menu.h"
+#include "display.h"
+#include "common.h"
+
+/*****************************************************************************
+ * GtkDisplayDate: display stream date
+ *****************************************************************************
+ * This function displays the current date related to the position in
+ * the stream. It is called whenever the slider changes its value.
+ * The lock has to be taken before you call the function.
+ *****************************************************************************/
+void GtkDisplayDate( GtkAdjustment *p_adj )
+{
+ intf_thread_t *p_intf;
+
+ p_intf = gtk_object_get_data( GTK_OBJECT( p_adj ), "p_intf" );
+
+ if( p_intf->p_sys->p_input )
+ {
+#define p_area p_intf->p_sys->p_input->stream.p_selected_area
+ char psz_time[ OFFSETTOTIME_MAX_SIZE ];
+
+ gtk_frame_set_label( GTK_FRAME( p_intf->p_sys->p_slider_frame ),
+ input_OffsetToTime( p_intf->p_sys->p_input, psz_time,
+ ( p_area->i_size * p_adj->value ) / 100 ) );
+#undef p_area
+ }
+}
+
+
+/*****************************************************************************
+ * GtkModeManage: actualise the aspect of the interface whenever the input
+ * changes.
+ *****************************************************************************
+ * The lock has to be taken before you call the function.
+ *****************************************************************************/
+gint GtkModeManage( intf_thread_t * p_intf )
+{
+ GtkWidget * p_dvd_box;
+ GtkWidget * p_file_box;
+ GtkWidget * p_network_box;
+ GtkWidget * p_slider;
+ GtkWidget * p_label;
+ GtkWidget * p_channel;
+ vlc_bool_t b_control;
+
+#define GETWIDGET( ptr, name ) GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( \
+ p_intf->p_sys->ptr ) , ( name ) ) )
+ /* hide all boxes except default file box */
+ p_file_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "file_box" ) );
+ gtk_widget_hide( GTK_WIDGET( p_file_box ) );
+
+ p_network_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "network_box" ) );
+ gtk_widget_hide( GTK_WIDGET( p_network_box ) );
+
+ p_dvd_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "dvd_box" ) );
+ gtk_widget_hide( GTK_WIDGET( p_dvd_box ) );
+
+ /* hide slider */
+ p_slider = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "slider_frame" ) );
+ gtk_widget_hide( GTK_WIDGET( p_slider ) );
+
+ /* controls unavailable */
+ b_control = 0;
+
+ /* show the box related to current input mode */
+ if( p_intf->p_sys->p_input )
+ {
+ switch( p_intf->p_sys->p_input->stream.i_method & 0xf0 )
+ {
+ case INPUT_METHOD_FILE:
+//intf_WarnMsg( 2, "intf info: file method" );
+ gtk_widget_show( GTK_WIDGET( p_file_box ) );
+ p_label = gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ),
+ "label_status" );
+ gtk_label_set_text( GTK_LABEL( p_label ),
+ p_intf->p_sys->p_input->psz_source );
+ break;
+ case INPUT_METHOD_DISC:
+//intf_WarnMsg( 2, "intf info: disc method" );
+ gtk_widget_show( GTK_WIDGET( p_dvd_box ) );
+ break;
+ case INPUT_METHOD_NETWORK:
+//intf_WarnMsg( 2, "intf info: network method" );
+ gtk_widget_show( GTK_WIDGET( p_network_box ) );
+ p_label = gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ),
+ "network_address_label" );
+ gtk_label_set_text( GTK_LABEL( p_label ),
+ p_intf->p_sys->p_input->psz_source );
+ p_channel = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "network_channel_box" ) );
+ if( config_GetInt( p_intf, "network-channel" ) )
+ {
+ gtk_widget_show( GTK_WIDGET( p_channel ) );
+ }
+ else
+ {
+ gtk_widget_hide( GTK_WIDGET( p_channel ) );
+ }
+
+ break;
+ default:
+ msg_Warn( p_intf, "cannot determine input method" );
+ gtk_widget_show( GTK_WIDGET( p_file_box ) );
+ p_label = gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ),
+ "label_status" );
+ gtk_label_set_text( GTK_LABEL( p_label ),
+ p_intf->p_sys->p_input->psz_source );
+ break;
+ }
+
+ /* initialize and show slider for seekable streams */
+ if( p_intf->p_sys->p_input->stream.b_seekable )
+ {
+ p_intf->p_sys->p_adj->value = p_intf->p_sys->f_adj_oldvalue = 0;
+ gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
+ "value_changed" );
+ gtk_widget_show( GTK_WIDGET( p_slider ) );
+ }
+
+ /* control buttons for free pace streams */
+ b_control = p_intf->p_sys->p_input->stream.b_pace_control;
+
+ /* get ready for menu regeneration */
+ p_intf->p_sys->b_program_update = 1;
+ p_intf->p_sys->b_title_update = 1;
+ p_intf->p_sys->b_chapter_update = 1;
+ p_intf->p_sys->b_audio_update = 1;
+ p_intf->p_sys->b_spu_update = 1;
+ p_intf->p_sys->i_part = 0;
+
+ p_intf->p_sys->p_input->stream.b_changed = 0;
+ msg_Dbg( p_intf, "stream has changed, refreshing interface" );
+ }
+ else
+ {
+ if( config_GetInt( p_intf, "network-channel" ) )
+ {
+ gtk_widget_show( GTK_WIDGET( p_network_box ) );
+
+ p_channel = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "network_channel_box" ) );
+ gtk_widget_show( GTK_WIDGET( p_channel ) );
+ }
+ else
+ {
+//intf_WarnMsg( 2, "intf info: default to file method" );
+ /* default mode */
+ p_label = gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_window ), "label_status" );
+ gtk_label_set_text( GTK_LABEL( p_label ), "" );
+ gtk_widget_show( GTK_WIDGET( p_file_box ) );
+ }
+
+ /* unsensitize menus */
+ gtk_widget_set_sensitive( GETWIDGET(p_window,"menubar_program"),
+ FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_window,"menubar_title"), FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_window,"menubar_chapter"),
+ FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_window,"menubar_audio"), FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_window,"menubar_subpictures"),
+ FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_popup,"popup_navigation"),
+ FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_popup,"popup_audio"), FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_popup,"popup_subpictures"),
+ FALSE );
+ }
+
+ /* set control items */
+ gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_back"), FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_eject"), !b_control);
+ gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_pause"), b_control );
+ gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_slow"), b_control );
+ gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_fast"), b_control );
+ gtk_widget_set_sensitive( GETWIDGET(p_popup, "popup_back"), FALSE );
+ gtk_widget_set_sensitive( GETWIDGET(p_popup, "popup_pause"), b_control );
+ gtk_widget_set_sensitive( GETWIDGET(p_popup, "popup_slow"), b_control );
+ gtk_widget_set_sensitive( GETWIDGET(p_popup, "popup_fast"), b_control );
+
+#undef GETWIDGET
+ return TRUE;
+}
+
+/*****************************************************************************
+ * GtkHideTooltips: show or hide the tooltips depending on the configuration
+ * option gnome-tooltips
+ *****************************************************************************/
+void GtkHideTooltips( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = vlc_object_find( p_this, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+
+ if( !p_intf )
+ {
+ return;
+ }
+
+ if( config_GetInt( p_this, "gnome-tooltips" ) )
+ {
+ gtk_tooltips_enable( p_intf->p_sys->p_tooltips );
+ }
+ else
+ {
+ gtk_tooltips_disable( p_intf->p_sys->p_tooltips );
+ }
+
+ vlc_object_release( p_intf );
+}
+
+#ifdef MODULE_NAME_IS_gnome
+/*****************************************************************************
+ * GtkHideToolbartext: show or hide the tooltips depending on the
+ * configuration option gnome-toolbartext
+ *****************************************************************************
+ * FIXME: GNOME only because of missing icons in gtk interface
+ *****************************************************************************/
+void GtkHideToolbarText( vlc_object_t *p_this )
+{
+ GtkToolbarStyle style;
+ GtkToolbar * p_toolbar;
+
+ intf_thread_t *p_intf = vlc_object_find( p_this, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+
+ if( !p_intf )
+ {
+ return;
+ }
+
+ style = config_GetInt( p_this, "gnome-toolbartext" )
+ ? GTK_TOOLBAR_BOTH
+ : GTK_TOOLBAR_ICONS;
+
+ p_toolbar = GTK_TOOLBAR(lookup_widget( p_intf->p_sys->p_window,
+ "toolbar" ));
+ gtk_toolbar_set_style( p_toolbar, style );
+
+ vlc_object_release( p_intf );
+}
+#endif
--- /dev/null
+/*****************************************************************************
+ * gtk_dsiplay.h: Gtk+ tools for main interface.
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: display.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+
+gint GtkModeManage ( intf_thread_t * p_intf );
+void GtkDisplayDate ( GtkAdjustment *p_adj );
+void GtkHideTooltips ( vlc_object_t * );
+void GtkHideToolbarText ( vlc_object_t * );
+
--- /dev/null
+/*****************************************************************************
+ * gnome.c : Gnome plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000 VideoLAN
+ * $Id: gnome.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <gnome.h>
+
+#include "gnome_callbacks.h"
+#include "gnome_interface.h"
+#include "gnome_support.h"
+#include "display.h"
+#include "common.h"
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static void Run ( intf_thread_t * );
+static gint Manage ( gpointer );
+
+/*****************************************************************************
+ * Local variables (mutex-protected).
+ *****************************************************************************/
+static void ** pp_global_data = NULL;
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define TOOLTIPS_TEXT N_("show tooltips")
+#define TOOLTIPS_LONGTEXT N_("Show tooltips for configuration options.")
+
+#define TOOLBAR_TEXT N_("show text on toolbar buttons")
+#define TOOLBAR_LONGTEXT N_("Show the text below icons on the toolbar.")
+
+#define PREFS_MAXH_TEXT N_("maximum height for the configuration windows")
+#define PREFS_MAXH_LONGTEXT N_( \
+ "You can set the maximum height that the configuration windows in the " \
+ "preferences menu will occupy.")
+
+vlc_module_begin();
+#ifdef WIN32
+ int i = 90;
+#else
+ int i = getenv( "DISPLAY" ) == NULL ? 15 : 100;
+#endif
+ pp_global_data = p_module->p_vlc->pp_global_data;
+
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_bool( "gnome-tooltips", 1, GtkHideTooltips,
+ TOOLTIPS_TEXT, TOOLTIPS_LONGTEXT );
+ add_bool( "gnome-toolbartext", 1, GtkHideToolbarText, TOOLBAR_TEXT,
+ TOOLBAR_LONGTEXT );
+ add_integer( "gnome-prefs-maxh", 480, NULL,
+ PREFS_MAXH_TEXT, PREFS_MAXH_LONGTEXT );
+
+ set_description( _("GNOME interface module") );
+ set_capability( "interface", i );
+ set_callbacks( Open, Close );
+ set_program( "gnome-vlc" );
+vlc_module_end();
+
+/*****************************************************************************
+ * g_atexit: kludge to avoid the Gnome thread to segfault at exit
+ *****************************************************************************
+ * gtk_init() makes several calls to g_atexit() which calls atexit() to
+ * register tidying callbacks to be called at program exit. Since the Gnome
+ * plugin is likely to be unloaded at program exit, we have to export this
+ * symbol to intercept the g_atexit() calls. Talk about crude hack.
+ *****************************************************************************/
+void g_atexit( GVoidFunc func )
+{
+ intf_thread_t *p_intf;
+
+ int i_dummy;
+
+ if( pp_global_data == NULL )
+ {
+ atexit( func );
+ return;
+ }
+
+ p_intf = (intf_thread_t *)*pp_global_data;
+ if( p_intf == NULL )
+ {
+ return;
+ }
+
+ for( i_dummy = 0;
+ i_dummy < MAX_ATEXIT && p_intf->p_sys->pf_callback[i_dummy] != NULL;
+ i_dummy++ )
+ {
+ ;
+ }
+
+ if( i_dummy >= MAX_ATEXIT - 1 )
+ {
+ msg_Err( p_intf, "too many atexit() callbacks to register" );
+ return;
+ }
+
+ p_intf->p_sys->pf_callback[i_dummy] = func;
+ p_intf->p_sys->pf_callback[i_dummy + 1] = NULL;
+}
+
+/*****************************************************************************
+ * Open: initialize and create window
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return( 1 );
+ }
+
+ p_intf->pf_run = Run;
+
+ p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
+
+ /* Initialize Gnome thread */
+ p_intf->p_sys->b_playing = 0;
+ p_intf->p_sys->b_popup_changed = 0;
+ p_intf->p_sys->b_window_changed = 0;
+ p_intf->p_sys->b_playlist_changed = 0;
+
+ p_intf->p_sys->p_input = NULL;
+ p_intf->p_sys->i_playing = -1;
+ p_intf->p_sys->b_slider_free = 1;
+
+ p_intf->p_sys->pf_callback[0] = NULL;
+
+ p_intf->p_sys->i_part = 0;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Close: destroy interface window
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: Gnome thread
+ *****************************************************************************
+ * this part of the interface is in a separate thread so that we can call
+ * gtk_main() from within it without annoying the rest of the program.
+ * XXX: the approach may look kludgy, and probably is, but I could not find
+ * a better way to dynamically load a Gnome interface at runtime.
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ /* gnome_init needs to know the command line. We don't care, so we
+ * give it an empty one */
+ char *p_args[] = { "" };
+ int i_args = 1;
+ int i_dummy;
+
+ /* The data types we are allowed to receive */
+ static GtkTargetEntry target_table[] =
+ {
+ { "STRING", 0, DROP_ACCEPT_STRING },
+ { "text/uri-list", 0, DROP_ACCEPT_TEXT_URI_LIST },
+ { "text/plain", 0, DROP_ACCEPT_TEXT_PLAIN }
+ };
+
+ /* Initialize Gnome */
+
+ /* gnome_init will register stuff with g_atexit, so we need to take
+ * the global lock if we want to be able to intercept the calls */
+ vlc_mutex_lock( p_intf->p_vlc->p_global_lock );
+ *p_intf->p_vlc->pp_global_data = p_intf;
+ gnome_init( p_intf->p_vlc->psz_object_name, VERSION, i_args, p_args );
+ vlc_mutex_unlock( p_intf->p_vlc->p_global_lock );
+
+ /* Create some useful widgets that will certainly be used */
+ p_intf->p_sys->p_window = create_intf_window( );
+ p_intf->p_sys->p_popup = create_intf_popup( );
+ p_intf->p_sys->p_playwin = create_intf_playlist();
+ p_intf->p_sys->p_messages = create_intf_messages();
+
+ /* Set the title of the main window */
+ gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
+ VOUT_TITLE " (Gnome interface)");
+
+ /* Accept file drops on the main window */
+ gtk_drag_dest_set( GTK_WIDGET( p_intf->p_sys->p_window ),
+ GTK_DEST_DEFAULT_ALL, target_table,
+ 1, GDK_ACTION_COPY );
+ /* Accept file drops on the playlist window */
+ gtk_drag_dest_set( GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_playwin ), "playlist_clist") ),
+ GTK_DEST_DEFAULT_ALL, target_table,
+ 1, GDK_ACTION_COPY );
+
+ /* Get the slider object */
+ p_intf->p_sys->p_slider_frame = gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_window ), "slider_frame" );
+
+ /* Configure the log window */
+ p_intf->p_sys->p_messages_text = GTK_TEXT( gtk_object_get_data(
+ GTK_OBJECT(p_intf->p_sys->p_messages ), "messages_textbox" ) );
+ gtk_text_set_line_wrap( p_intf->p_sys->p_messages_text, TRUE);
+ gtk_text_set_word_wrap( p_intf->p_sys->p_messages_text, FALSE);
+
+ /* Get the interface labels */
+ #define P_LABEL( name ) GTK_LABEL( gtk_object_get_data( \
+ GTK_OBJECT( p_intf->p_sys->p_window ), name ) )
+ p_intf->p_sys->p_label_title = P_LABEL( "title_label" );
+ p_intf->p_sys->p_label_chapter = P_LABEL( "chapter_label" );
+ #undef P_LABEL
+
+ /* Connect the date display to the slider */
+ #define P_SLIDER GTK_RANGE( gtk_object_get_data( \
+ GTK_OBJECT( p_intf->p_sys->p_window ), "slider" ) )
+ p_intf->p_sys->p_adj = gtk_range_get_adjustment( P_SLIDER );
+
+ gtk_signal_connect ( GTK_OBJECT( p_intf->p_sys->p_adj ), "value_changed",
+ GTK_SIGNAL_FUNC( GtkDisplayDate ), NULL );
+ p_intf->p_sys->f_adj_oldvalue = 0;
+ #undef P_SLIDER
+
+ p_intf->p_sys->p_tooltips = gtk_tooltips_new();
+
+ /* We don't create these ones yet because we perhaps won't need them */
+ p_intf->p_sys->p_about = NULL;
+ p_intf->p_sys->p_modules = NULL;
+ p_intf->p_sys->p_open = NULL;
+ p_intf->p_sys->p_jump = NULL;
+
+ /* Hide tooltips if the option is set */
+ if( !config_GetInt( p_intf, "gnome-tooltips" ) )
+ {
+ gtk_tooltips_disable( p_intf->p_sys->p_tooltips );
+ }
+
+ /* Hide toolbar text of the option is set */
+ if( !config_GetInt( p_intf, "gnome-toolbartext" ) )
+ {
+ gtk_toolbar_set_style(
+ GTK_TOOLBAR(lookup_widget( p_intf->p_sys->p_window, "toolbar" )),
+ GTK_TOOLBAR_ICONS );
+ }
+
+ /* Store p_intf to keep an eye on it */
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_popup),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_playwin ),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_messages ),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_adj),
+ "p_intf", p_intf );
+
+ /* Show the control window */
+ gtk_widget_show( p_intf->p_sys->p_window );
+
+ /* Sleep to avoid using all CPU - since some interfaces needs to access
+ * keyboard events, a 100ms delay is a good compromise */
+ i_dummy = gtk_timeout_add( INTF_IDLE_SLEEP / 1000, Manage, p_intf );
+
+ /* Enter gnome mode */
+ gtk_main();
+
+ /* Remove the timeout */
+ gtk_timeout_remove( i_dummy );
+
+ /* Destroy the Tooltips structure */
+ gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_tooltips) );
+
+ /* Get rid of stored callbacks so we can unload the plugin */
+ for( i_dummy = 0;
+ i_dummy < MAX_ATEXIT && p_intf->p_sys->pf_callback[i_dummy] != NULL;
+ i_dummy++ )
+ {
+ p_intf->p_sys->pf_callback[i_dummy]();
+ }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * Manage: manage main thread messages
+ *****************************************************************************
+ * In this function, called approx. 10 times a second, we check what the
+ * main program wanted to tell us.
+ *****************************************************************************/
+static gint Manage( gpointer p_data )
+{
+#define p_intf ((intf_thread_t *)p_data)
+ int i_start, i_stop;
+
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ /* If the "display popup" flag has changed */
+ if( p_intf->b_menu_change )
+ {
+ if( !GTK_IS_WIDGET( p_intf->p_sys->p_popup ) )
+ {
+ p_intf->p_sys->p_popup = create_intf_popup();
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_popup ),
+ "p_popup", p_intf );
+ }
+
+ gnome_popup_menu_do_popup( p_intf->p_sys->p_popup,
+ NULL, NULL, NULL, NULL );
+ p_intf->b_menu_change = 0;
+ }
+
+ /* Update the log window */
+ vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+ i_stop = *p_intf->p_sys->p_sub->pi_stop;
+ vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+
+ if( p_intf->p_sys->p_sub->i_start != i_stop )
+ {
+ static GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
+ static GdkColor gray = { 0, 0xaaaa, 0xaaaa, 0xaaaa };
+ static GdkColor yellow = { 0, 0xffff, 0xffff, 0x6666 };
+ static GdkColor red = { 0, 0xffff, 0x6666, 0x6666 };
+
+ static const char * ppsz_type[4] = { ": ", " error: ", " warning: ",
+ " debug: " };
+ static GdkColor * pp_color[4] = { &white, &red, &yellow, &gray };
+
+ for( i_start = p_intf->p_sys->p_sub->i_start;
+ i_start != i_stop;
+ i_start = (i_start+1) % VLC_MSG_QSIZE )
+ {
+ /* Append all messages to log window */
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+ NULL, p_intf->p_sys->p_sub->p_msg[i_start].psz_module, -1 );
+
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+ NULL, ppsz_type[p_intf->p_sys->p_sub->p_msg[i_start].i_type],
+ -1 );
+
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL,
+ pp_color[p_intf->p_sys->p_sub->p_msg[i_start].i_type], NULL,
+ p_intf->p_sys->p_sub->p_msg[i_start].psz_msg, -1 );
+
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+ NULL, "\n", -1 );
+ }
+
+ vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+ p_intf->p_sys->p_sub->i_start = i_start;
+ vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+
+ gtk_text_set_point( p_intf->p_sys->p_messages_text,
+ gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
+ }
+
+ /* Update the playlist */
+ GtkPlayListManage( p_intf );
+
+ /* Update the input */
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+ }
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+
+ if( p_intf->p_sys->p_input )
+ {
+ input_thread_t *p_input = p_intf->p_sys->p_input;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ if( !p_input->b_die )
+ {
+ /* New input or stream map change */
+ if( p_input->stream.b_changed )
+ {
+ GtkModeManage( p_intf );
+ GtkSetupMenus( p_intf );
+ p_intf->p_sys->b_playing = 1;
+ }
+
+ /* Manage the slider */
+ if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )
+ {
+ float newvalue = p_intf->p_sys->p_adj->value;
+
+#define p_area p_input->stream.p_selected_area
+ /* If the user hasn't touched the slider since the last time,
+ * then the input can safely change it */
+ if( newvalue == p_intf->p_sys->f_adj_oldvalue )
+ {
+ /* Update the value */
+ p_intf->p_sys->p_adj->value =
+ p_intf->p_sys->f_adj_oldvalue =
+ ( 100. * p_area->i_tell ) / p_area->i_size;
+
+ gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
+ "value_changed" );
+ }
+ /* Otherwise, send message to the input if the user has
+ * finished dragging the slider */
+ else if( p_intf->p_sys->b_slider_free )
+ {
+ if( newvalue > 0. && newvalue < 100. )
+ {
+ off_t i_seek = ( newvalue * p_area->i_size ) / 100;
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ input_Seek( p_input, i_seek, INPUT_SEEK_SET );
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ }
+
+ /* Update the old value */
+ p_intf->p_sys->f_adj_oldvalue = newvalue;
+ }
+#undef p_area
+ }
+
+ if( p_intf->p_sys->i_part !=
+ p_input->stream.p_selected_area->i_part )
+ {
+ p_intf->p_sys->b_chapter_update = 1;
+ GtkSetupMenus( p_intf );
+ }
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+ else if( p_intf->p_sys->b_playing && !p_intf->b_die )
+ {
+ GtkModeManage( p_intf );
+ p_intf->p_sys->b_playing = 0;
+ }
+
+ if( p_intf->b_die )
+ {
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ /* Prepare to die, young Skywalker */
+ gtk_main_quit();
+
+ /* Just in case */
+ return( FALSE );
+ }
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return( TRUE );
+
+#undef p_intf
+}
+
--- /dev/null
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>VideoLAN Client</name>
+ <program_name>vlc</program_name>
+ <directory></directory>
+ <source_directory></source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>True</gnome_support>
+ <gettext_support>True</gettext_support>
+ <output_main_file>False</output_main_file>
+ <output_build_files>False</output_build_files>
+ <backup_source_files>False</backup_source_files>
+ <main_source_file>gnome_interface.c</main_source_file>
+ <main_header_file>gnome_interface.h</main_header_file>
+ <handler_source_file>gnome_callbacks.c</handler_source_file>
+ <handler_header_file>gnome_callbacks.h</handler_header_file>
+ <support_source_file>gnome_support.c</support_source_file>
+ <support_header_file>gnome_support.h</support_header_file>
+</project>
+
+<widget>
+ <class>GnomeApp</class>
+ <name>intf_window</name>
+ <signal>
+ <name>delete_event</name>
+ <handler>GtkWindowDelete</handler>
+ <last_modification_time>Sat, 19 May 2001 03:20:57 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>drag_data_received</name>
+ <handler>GtkWindowDrag</handler>
+ <last_modification_time>Sat, 19 May 2001 02:30:24 GMT</last_modification_time>
+ </signal>
+ <title>VideoLAN Client</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>True</auto_shrink>
+ <enable_layout_config>True</enable_layout_config>
+
+ <widget>
+ <class>GnomeDock</class>
+ <child_name>GnomeApp:dock</child_name>
+ <name>dockitem</name>
+ <allow_floating>True</allow_floating>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GnomeDockItem</class>
+ <name>dockitem_menubar</name>
+ <border_width>2</border_width>
+ <placement>GNOME_DOCK_TOP</placement>
+ <band>0</band>
+ <position>0</position>
+ <offset>0</offset>
+ <locked>False</locked>
+ <exclusive>True</exclusive>
+ <never_floating>False</never_floating>
+ <never_vertical>True</never_vertical>
+ <never_horizontal>False</never_horizontal>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+
+ <widget>
+ <class>GtkMenuBar</class>
+ <name>menubar</name>
+ <border_width>2</border_width>
+ <shadow_type>GTK_SHADOW_NONE</shadow_type>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_file</name>
+ <stock_item>GNOMEUIINFO_MENU_FILE_TREE</stock_item>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_file_menu</name>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_open</name>
+ <tooltip>Open a File</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:27:02 GMT</last_modification_time>
+ </signal>
+ <label>_Open File...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_OPEN</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_disc</name>
+ <tooltip>Open a DVD or VCD</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:27:10 GMT</last_modification_time>
+ </signal>
+ <label>Open _Disc...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_CDROM</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_network</name>
+ <tooltip>Select a Network Stream</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Fri, 21 Dec 2001 13:11:28 GMT</last_modification_time>
+ </signal>
+ <label>_Network Stream...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_REFRESH</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator1</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_eject</name>
+ <tooltip>Eject disc</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscEject</handler>
+ <last_modification_time>Fri, 21 Dec 2001 13:11:28 GMT</last_modification_time>
+ </signal>
+ <label>_Eject Disc</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_TOP</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator15</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_close</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkClose</handler>
+ <last_modification_time>Mon, 15 Jul 2002 09:14:55 GMT</last_modification_time>
+ </signal>
+ <stock_item>GNOMEUIINFO_MENU_CLOSE_ITEM</stock_item>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_exit</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkExit</handler>
+ <last_modification_time>Sat, 19 May 2001 16:27:52 GMT</last_modification_time>
+ </signal>
+ <stock_item>GNOMEUIINFO_MENU_EXIT_ITEM</stock_item>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_view</name>
+ <stock_item>GNOMEUIINFO_MENU_VIEW_TREE</stock_item>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_view_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_hide_interface</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkWindowToggle</handler>
+ <last_modification_time>Sat, 19 May 2001 16:28:06 GMT</last_modification_time>
+ </signal>
+ <label>_Hide interface</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_fullscreen</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFullscreen</handler>
+ <last_modification_time>Sat, 19 May 2001 16:28:15 GMT</last_modification_time>
+ </signal>
+ <label>_Fullscreen</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator9</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_program</name>
+ <sensitive>False</sensitive>
+ <tooltip>Choose the program</tooltip>
+ <label>Progr_am</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_title</name>
+ <sensitive>False</sensitive>
+ <tooltip>Choose title</tooltip>
+ <label>_Title</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_chapter</name>
+ <sensitive>False</sensitive>
+ <tooltip>Choose chapter</tooltip>
+ <label>_Chapter</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator7</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_playlist</name>
+ <tooltip>Open the playlist window</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:28:41 GMT</last_modification_time>
+ </signal>
+ <label>_Playlist...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_INDEX</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_modules</name>
+ <sensitive>False</sensitive>
+ <tooltip>Open the module manager</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkModulesShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:28:53 GMT</last_modification_time>
+ </signal>
+ <label>_Modules...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_ATTACH</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_messages</name>
+ <tooltip>Open the messages window</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkMessagesShow</handler>
+ <last_modification_time>Wed, 20 Feb 2002 05:43:55 GMT</last_modification_time>
+ </signal>
+ <label>Messages...</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_settings</name>
+ <stock_item>GNOMEUIINFO_MENU_SETTINGS_TREE</stock_item>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_settings_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_audio</name>
+ <sensitive>False</sensitive>
+ <tooltip>Select audio channel</tooltip>
+ <label>_Audio</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_subpictures</name>
+ <sensitive>False</sensitive>
+ <tooltip>Select subtitles channel</tooltip>
+ <label>_Subtitles</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator5</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_preferences</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPreferencesShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:29:03 GMT</last_modification_time>
+ </signal>
+ <stock_item>GNOMEUIINFO_MENU_PREFERENCES_ITEM</stock_item>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_help</name>
+ <stock_item>GNOMEUIINFO_MENU_HELP_TREE</stock_item>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_help_menu</name>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>menubar_about</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkAboutShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:29:19 GMT</last_modification_time>
+ </signal>
+ <stock_item>GNOMEUIINFO_MENU_ABOUT_ITEM</stock_item>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GnomeDockItem</class>
+ <name>dockitem_toolbar</name>
+ <border_width>2</border_width>
+ <placement>GNOME_DOCK_TOP</placement>
+ <band>1</band>
+ <position>0</position>
+ <offset>2</offset>
+ <locked>False</locked>
+ <exclusive>True</exclusive>
+ <never_floating>False</never_floating>
+ <never_vertical>False</never_vertical>
+ <never_horizontal>False</never_horizontal>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+
+ <widget>
+ <class>GtkToolbar</class>
+ <name>toolbar</name>
+ <orientation>GTK_ORIENTATION_HORIZONTAL</orientation>
+ <type>GTK_TOOLBAR_BOTH</type>
+ <space_size>16</space_size>
+ <space_style>GTK_TOOLBAR_SPACE_LINE</space_style>
+ <relief>GTK_RELIEF_NONE</relief>
+ <tooltips>True</tooltips>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_file</name>
+ <tooltip>Open a File</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 03:14:43 GMT</last_modification_time>
+ </signal>
+ <label>File</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_OPEN</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_disc</name>
+ <tooltip>Open a DVD or VCD</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 03:14:38 GMT</last_modification_time>
+ </signal>
+ <label>Disc</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_CDROM</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_network</name>
+ <tooltip>Select a Network Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 03:14:33 GMT</last_modification_time>
+ </signal>
+ <label>Net</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_REFRESH</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_sat</name>
+ <tooltip>Open a Satellite Card</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkSatOpenShow</handler>
+ <last_modification_time>Mon, 25 Mar 2002 01:02:49 GMT</last_modification_time>
+ </signal>
+ <label>Sat</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_MIC</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_back</name>
+ <sensitive>False</sensitive>
+ <tooltip>Go Backward</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlBack</handler>
+ <last_modification_time>Sat, 19 May 2001 03:14:27 GMT</last_modification_time>
+ </signal>
+ <label>Back</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_BACK</stock_pixmap>
+ <child>
+ <new_group>True</new_group>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_stop</name>
+ <tooltip>Stop Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlStop</handler>
+ <last_modification_time>Sat, 19 May 2001 03:14:22 GMT</last_modification_time>
+ </signal>
+ <label>Stop</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_STOP</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_eject</name>
+ <tooltip>Eject disc</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkDiscEject</handler>
+ <last_modification_time>Fri, 21 Dec 2001 15:24:18 GMT</last_modification_time>
+ </signal>
+ <label>Eject</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_TOP</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_play</name>
+ <tooltip>Play Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlPlay</handler>
+ <last_modification_time>Wed, 05 Jun 2002 15:10:19 GMT</last_modification_time>
+ </signal>
+ <label>Play</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_FORWARD</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_pause</name>
+ <sensitive>False</sensitive>
+ <tooltip>Pause Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlPause</handler>
+ <last_modification_time>Sat, 19 May 2001 03:14:05 GMT</last_modification_time>
+ </signal>
+ <label>Pause</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_BOTTOM</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_slow</name>
+ <sensitive>False</sensitive>
+ <tooltip>Play Slower</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlSlow</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:58 GMT</last_modification_time>
+ </signal>
+ <label>Slow</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_TIMER_STOP</stock_pixmap>
+ <child>
+ <new_group>True</new_group>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_fast</name>
+ <sensitive>False</sensitive>
+ <tooltip>Play Faster</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlFast</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:53 GMT</last_modification_time>
+ </signal>
+ <label>Fast</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_TIMER</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_playlist</name>
+ <tooltip>Open Playlist</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistShow</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:48 GMT</last_modification_time>
+ </signal>
+ <label>Playlist</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_INDEX</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_prev</name>
+ <tooltip>Previous File</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistPrev</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:44 GMT</last_modification_time>
+ </signal>
+ <label>Prev</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_FIRST</stock_pixmap>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_next</name>
+ <tooltip>Next File</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistNext</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:40 GMT</last_modification_time>
+ </signal>
+ <label>Next</label>
+ <stock_pixmap>GNOME_STOCK_PIXMAP_LAST</stock_pixmap>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDock:contents</child_name>
+ <name>vbox8</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>slider_frame</name>
+ <visible>False</visible>
+ <label>-:--:--</label>
+ <label_xalign>0.05</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHScale</class>
+ <name>slider</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>GtkSliderPress</handler>
+ <last_modification_time>Sat, 19 May 2001 03:12:57 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>button_release_event</name>
+ <handler>GtkSliderRelease</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:00 GMT</last_modification_time>
+ </signal>
+ <draw_value>False</draw_value>
+ <value_pos>GTK_POS_TOP</value_pos>
+ <digits>3</digits>
+ <policy>GTK_UPDATE_CONTINUOUS</policy>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <step>1</step>
+ <page>6.25</page>
+ <page_size>0</page_size>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>file_box</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label_status</name>
+ <label></label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>dvd_box</name>
+ <visible>False</visible>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label21</name>
+ <label>Disc</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>title_chapter_box</name>
+ <homogeneous>False</homogeneous>
+ <spacing>10</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label19</name>
+ <label>Title:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>title_label</name>
+ <label>--</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button_title_prev</name>
+ <tooltip>Select previous title</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkTitlePrev</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:28 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_PREV</stock_button>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button_title_next</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkTitleNext</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:23 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_NEXT</stock_button>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVSeparator</class>
+ <name>vseparator1</name>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>dvd_chapter_box</name>
+ <homogeneous>False</homogeneous>
+ <spacing>10</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label20</name>
+ <label>Chapter:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>chapter_label</name>
+ <label>---</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button_chapter_prev</name>
+ <tooltip>Select previous chapter</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkChapterPrev</handler>
+ <last_modification_time>Tue, 29 May 2001 13:13:41 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_DOWN</stock_button>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button_chapter_next</name>
+ <tooltip>Select next chapter</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkChapterNext</handler>
+ <last_modification_time>Sat, 19 May 2001 03:13:08 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_UP</stock_button>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>network_box</name>
+ <visible>False</visible>
+ <homogeneous>True</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_address_label</name>
+ <label>No server</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>network_channel_box</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label_network</name>
+ <label>Network Channel:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_channel_spinbutton</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkJoin</handler>
+ <last_modification_time>Wed, 30 May 2001 02:28:48 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>network_channel_go_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkChannelGo</handler>
+ <last_modification_time>Wed, 30 May 2001 02:38:25 GMT</last_modification_time>
+ </signal>
+ <label>Go!</label>
+ <relief>GTK_RELIEF_NONE</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GnomeAppBar</class>
+ <child_name>GnomeApp:appbar</child_name>
+ <name>appbar</name>
+ <has_progress>False</has_progress>
+ <has_status>True</has_status>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkMenu</class>
+ <name>intf_popup</name>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_play</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlPlay</handler>
+ <last_modification_time>Sat, 19 May 2001 16:16:58 GMT</last_modification_time>
+ </signal>
+ <label>Play</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_FORWARD</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_pause</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlPause</handler>
+ <last_modification_time>Sat, 19 May 2001 16:17:31 GMT</last_modification_time>
+ </signal>
+ <label>Pause</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_BOTTOM</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_stop</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlStop</handler>
+ <last_modification_time>Sat, 19 May 2001 16:18:10 GMT</last_modification_time>
+ </signal>
+ <label>Stop</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_STOP</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_back</name>
+ <sensitive>False</sensitive>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlBack</handler>
+ <last_modification_time>Sat, 19 May 2001 16:18:21 GMT</last_modification_time>
+ </signal>
+ <label>Back</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_BACK</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_slow</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlSlow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:18:29 GMT</last_modification_time>
+ </signal>
+ <label>Slow</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_TIMER_STOP</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_fast</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlFast</handler>
+ <last_modification_time>Sat, 19 May 2001 16:18:37 GMT</last_modification_time>
+ </signal>
+ <label>Fast</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_TIMER</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator3</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_interface_toggle</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkWindowToggle</handler>
+ <last_modification_time>Sat, 19 May 2001 16:18:51 GMT</last_modification_time>
+ </signal>
+ <label>Toggle _Interface</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_fullscreen</name>
+ <tooltip>Toggle fullscreen mode</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFullscreen</handler>
+ <last_modification_time>Sat, 19 May 2001 16:19:07 GMT</last_modification_time>
+ </signal>
+ <label>_Fullscreen</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator8</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_next</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistNext</handler>
+ <last_modification_time>Sat, 19 May 2001 16:19:18 GMT</last_modification_time>
+ </signal>
+ <label>Next</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_prev</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistPrev</handler>
+ <last_modification_time>Sat, 19 May 2001 16:19:26 GMT</last_modification_time>
+ </signal>
+ <label>Prev</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_jump</name>
+ <tooltip>Got directly so specified point</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkJumpShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:34:46 GMT</last_modification_time>
+ </signal>
+ <label>_Jump...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_JUMP_TO</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_program</name>
+ <sensitive>False</sensitive>
+ <tooltip>Switch program</tooltip>
+ <label>Program</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_navigation</name>
+ <sensitive>False</sensitive>
+ <tooltip>Navigate through titles and chapters</tooltip>
+ <label>_Navigation</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_SEARCH</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_audio</name>
+ <sensitive>False</sensitive>
+ <tooltip>Select audio channel</tooltip>
+ <label>_Audio</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_VOLUME</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_subpictures</name>
+ <sensitive>False</sensitive>
+ <tooltip>Select subtitles channel</tooltip>
+ <label>_Subtitles</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_FONT</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator13</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_file</name>
+ <stock_item>GNOMEUIINFO_MENU_FILE_TREE</stock_item>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>popup_file_menu</name>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_open</name>
+ <tooltip>Open a File</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:20:08 GMT</last_modification_time>
+ </signal>
+ <label>_Open File...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_OPEN</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_disc</name>
+ <tooltip>Open a DVD or VCD</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:20:44 GMT</last_modification_time>
+ </signal>
+ <label>Open _Disc...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_CDROM</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_network</name>
+ <tooltip>Select a Network Stream</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:20:54 GMT</last_modification_time>
+ </signal>
+ <label>_Network Stream...</label>
+ <right_justify>False</right_justify>
+ <stock_icon>GNOME_STOCK_MENU_REFRESH</stock_icon>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator4</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_about</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkAboutShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:21:02 GMT</last_modification_time>
+ </signal>
+ <stock_item>GNOMEUIINFO_MENU_ABOUT_ITEM</stock_item>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_playlist</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:21:14 GMT</last_modification_time>
+ </signal>
+ <label>Playlist...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_preferences</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPreferencesShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:21:25 GMT</last_modification_time>
+ </signal>
+ <stock_item>GNOMEUIINFO_MENU_PREFERENCES_ITEM</stock_item>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator2</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkPixmapMenuItem</class>
+ <name>popup_exit</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkExit</handler>
+ <last_modification_time>Sat, 19 May 2001 16:21:45 GMT</last_modification_time>
+ </signal>
+ <stock_item>GNOMEUIINFO_MENU_EXIT_ITEM</stock_item>
+ </widget>
+</widget>
+
+<widget>
+ <class>GnomeAbout</class>
+ <name>intf_about</name>
+ <modal>False</modal>
+ <copyright>(C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 - the VideoLAN Team</copyright>
+ <authors>the VideoLAN team <videolan@videolan.org>
+http://www.videolan.org/
+</authors>
+ <comments>This is the VideoLAN client, a DVD and MPEG player. It can play MPEG and MPEG 2 files from a file or from a network source.</comments>
+</widget>
+
+<widget>
+ <class>GnomeDialog</class>
+ <name>intf_open</name>
+ <title>Open Stream</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>True</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>True</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>dialog-vbox5</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>4</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>dialog-action_area5</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button1</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkOpenOk</handler>
+ <last_modification_time>Thu, 11 Jul 2002 09:10:19 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button3</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkOpenCancel</handler>
+ <last_modification_time>Thu, 11 Jul 2002 09:10:29 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>open_vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame10</name>
+ <label>Media Resource Locator (MRL)</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox21</name>
+ <border_width>5</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>5</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox22</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label34</name>
+ <label>Open Target:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>combo2</name>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>entry_open</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label36</name>
+ <label>Alternatively, you can build an MRL using one of the following predefined targets:</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>1</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkNotebook</class>
+ <name>open_notebook</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>switch_page</name>
+ <handler>GtkOpenNotebookChanged</handler>
+ <after>True</after>
+ <last_modification_time>Tue, 09 Jul 2002 14:01:19 GMT</last_modification_time>
+ </signal>
+ <show_tabs>True</show_tabs>
+ <show_border>True</show_border>
+ <tab_pos>GTK_POS_TOP</tab_pos>
+ <scrollable>False</scrollable>
+ <tab_hborder>2</tab_hborder>
+ <tab_vborder>2</tab_vborder>
+ <popup_enable>False</popup_enable>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox20</name>
+ <border_width>5</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>5</spacing>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>combo1</name>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>entry_file</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:22:33 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox13</name>
+ <homogeneous>True</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>open_browse</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileShow</handler>
+ <last_modification_time>Wed, 10 Jul 2002 11:37:05 GMT</last_modification_time>
+ </signal>
+ <label>Browse...</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_file</name>
+ <label>File</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table5</name>
+ <border_width>5</border_width>
+ <rows>4</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>5</row_spacing>
+ <column_spacing>5</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label21</name>
+ <label>Title</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label20</name>
+ <label>Chapter</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>disc_chapter</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:45:38 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1</value>
+ <lower>1</lower>
+ <upper>65536</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label35</name>
+ <label>Disc type</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox24</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>disc_dvd</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkDiscOpenDvd</handler>
+ <last_modification_time>Sun, 13 May 2001 14:48:29 GMT</last_modification_time>
+ </signal>
+ <label>DVD</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>disc</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>disc_vcd</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkDiscOpenVcd</handler>
+ <last_modification_time>Sun, 13 May 2001 14:48:39 GMT</last_modification_time>
+ </signal>
+ <label>VCD</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>disc</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label19</name>
+ <label>Device name</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>disc_title</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:45:04 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1</value>
+ <lower>1</lower>
+ <upper>65536</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>disc_name</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:46:05 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text>/dev/dvd</text>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_disc</name>
+ <label>Disc</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table4</name>
+ <border_width>5</border_width>
+ <rows>4</rows>
+ <columns>6</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>5</row_spacing>
+ <column_spacing>5</column_spacing>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_udp</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenUDP</handler>
+ <last_modification_time>Thu, 16 May 2002 00:47:18 GMT</last_modification_time>
+ </signal>
+ <label>UDP</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_multicast</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenMulticast</handler>
+ <last_modification_time>Thu, 16 May 2002 00:47:05 GMT</last_modification_time>
+ </signal>
+ <label>UDP Multicast</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_channel</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenChannel</handler>
+ <last_modification_time>Thu, 16 May 2002 01:44:15 GMT</last_modification_time>
+ </signal>
+ <label>Channel server </label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_http</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenHTTP</handler>
+ <last_modification_time>Thu, 16 May 2002 00:47:42 GMT</last_modification_time>
+ </signal>
+ <label>HTTP</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_udp_port_label</name>
+ <label>Port</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_multicast_address_label</name>
+ <sensitive>False</sensitive>
+ <label>Address</label>
+ <justify>GTK_JUSTIFY_RIGHT</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_channel_address_label</name>
+ <sensitive>False</sensitive>
+ <label>Address</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_http_url_label</name>
+ <sensitive>False</sensitive>
+ <label>URL</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>network_multicast_address_combo</name>
+ <sensitive>False</sensitive>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>4</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>network_multicast_address</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:06 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>network_channel_address_combo</name>
+ <sensitive>False</sensitive>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>4</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>network_channel_address</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:16 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_multicast_port_label</name>
+ <sensitive>False</sensitive>
+ <label>Port</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>4</left_attach>
+ <right_attach>5</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_channel_port_label</name>
+ <sensitive>False</sensitive>
+ <label>Port</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>4</left_attach>
+ <right_attach>5</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_multicast_port</name>
+ <width>75</width>
+ <sensitive>False</sensitive>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:36 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1234</value>
+ <lower>0</lower>
+ <upper>65535</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>5</left_attach>
+ <right_attach>6</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_channel_port</name>
+ <width>75</width>
+ <sensitive>False</sensitive>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:45 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>6010</value>
+ <lower>0</lower>
+ <upper>65535</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>5</left_attach>
+ <right_attach>6</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>network_http_url</name>
+ <sensitive>False</sensitive>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:26 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>6</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_udp_port</name>
+ <width>1</width>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:56:55 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1234</value>
+ <lower>0</lower>
+ <upper>65535</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>3</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_net</name>
+ <label>Network</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table3</name>
+ <border_width>5</border_width>
+ <rows>4</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>5</row_spacing>
+ <column_spacing>5</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label24</name>
+ <label>Symbol Rate</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label25</name>
+ <label>Frequency</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label26</name>
+ <label>Polarization</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>sat_freq</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:58:00 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>11954</value>
+ <lower>10000</lower>
+ <upper>12999</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label27</name>
+ <label>FEC</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox23</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>sat_pol_vert</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkSatOpenToggle</handler>
+ <last_modification_time>Tue, 09 Jul 2002 15:16:25 GMT</last_modification_time>
+ </signal>
+ <label>Vertical</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>pol</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>sat_pol_hor</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkSatOpenToggle</handler>
+ <last_modification_time>Tue, 09 Jul 2002 15:16:36 GMT</last_modification_time>
+ </signal>
+ <label>Horizontal</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>pol</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>sat_srate</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:58:09 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>27500</value>
+ <lower>1000</lower>
+ <upper>30000</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>sat_fec</name>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items>1/2
+2/3
+3/4
+4/5
+5/6
+7/8
+</items>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>combo-entry1</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:58:26 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text>3/4</text>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_sat</name>
+ <label>Satellite</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkFileSelection</class>
+ <name>intf_file</name>
+ <border_width>10</border_width>
+ <title>Open File</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>True</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <show_file_op_buttons>False</show_file_op_buttons>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>FileSel:ok_button</child_name>
+ <name>file_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileOk</handler>
+ <last_modification_time>Thu, 11 Jul 2002 09:07:44 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>FileSel:cancel_button</child_name>
+ <name>file_cancel</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileCancel</handler>
+ <last_modification_time>Thu, 11 Jul 2002 09:07:50 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+</widget>
+
+<widget>
+ <class>GnomeDialog</class>
+ <name>intf_modules</name>
+ <title>Modules</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>False</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>dialog-vbox1</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>4</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>dialog-action_area1</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>modules_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>modules_apply</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>modules_cancel</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label12</name>
+ <label>Sorry, the module manager isn't functional yet. Please retry in a later version.</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GnomeDialog</class>
+ <name>intf_playlist</name>
+ <signal>
+ <name>destroy</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Sat, 19 May 2001 03:09:08 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>delete_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Sat, 19 May 2001 03:09:12 GMT</last_modification_time>
+ </signal>
+ <title>Playlist</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <default_width>400</default_width>
+ <default_height>300</default_height>
+ <allow_shrink>True</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>True</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>playlist_vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>4</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>playlist_action</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>100</child_min_width>
+ <child_min_height>38</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>playlist_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistOk</handler>
+ <last_modification_time>Sat, 19 May 2001 03:09:00 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>playlist_cancel</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistCancel</handler>
+ <last_modification_time>Sat, 19 May 2001 03:08:56 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>playlist_scrolledwindow</name>
+ <hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkViewport</class>
+ <name>playlist_viewport</name>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>playlist_frame</name>
+ <border_width>4</border_width>
+ <label>Playlist</label>
+ <label_xalign>0.05</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+
+ <widget>
+ <class>GtkCList</class>
+ <name>playlist_clist</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>event</name>
+ <handler>GtkPlaylistEvent</handler>
+ <last_modification_time>Sat, 19 May 2001 03:08:43 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>drag_data_received</name>
+ <handler>GtkPlaylistDragData</handler>
+ <last_modification_time>Sat, 19 May 2001 03:08:45 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>drag_motion</name>
+ <handler>GtkPlaylistDragMotion</handler>
+ <last_modification_time>Sat, 19 May 2001 03:08:49 GMT</last_modification_time>
+ </signal>
+ <columns>2</columns>
+ <column_widths>287,70</column_widths>
+ <selection_mode>GTK_SELECTION_EXTENDED</selection_mode>
+ <show_titles>True</show_titles>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>playlist_label_url</name>
+ <label>Url</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>playlist_label_duration</name>
+ <label>Duration</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuBar</class>
+ <name>playlist_menubar</name>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add</name>
+ <label>Add</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>playlist_add_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_disc</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:22:26 GMT</last_modification_time>
+ </signal>
+ <label>Disc</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_file</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:22:37 GMT</last_modification_time>
+ </signal>
+ <label>File</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_network</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Sat, 19 May 2001 16:22:52 GMT</last_modification_time>
+ </signal>
+ <label>Network</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_url</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistAddUrl</handler>
+ <last_modification_time>Sat, 19 May 2001 16:24:27 GMT</last_modification_time>
+ </signal>
+ <label>Url</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_delete</name>
+ <label>Delete</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>playlist_delete_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_delete_all</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistDeleteAll</handler>
+ <last_modification_time>Sat, 19 May 2001 03:08:11 GMT</last_modification_time>
+ </signal>
+ <label>All</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_delete_item</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistDeleteSelected</handler>
+ <last_modification_time>Sat, 19 May 2001 03:08:05 GMT</last_modification_time>
+ </signal>
+ <label>Item</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection</name>
+ <label>Selection</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>playlist_selection_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection_crop</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistCrop</handler>
+ <last_modification_time>Sat, 19 May 2001 03:07:56 GMT</last_modification_time>
+ </signal>
+ <label>Crop</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection_invert</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistInvert</handler>
+ <last_modification_time>Sat, 19 May 2001 03:07:51 GMT</last_modification_time>
+ </signal>
+ <label>Invert</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection_select</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistSelect</handler>
+ <last_modification_time>Sat, 19 May 2001 03:07:45 GMT</last_modification_time>
+ </signal>
+ <label>Select</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GnomeDialog</class>
+ <name>intf_jump</name>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>False</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>jump_vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>jump_action</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>jump_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkJumpOk</handler>
+ <last_modification_time>Sat, 19 May 2001 03:07:27 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>jump_cancel</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkJumpCancel</handler>
+ <last_modification_time>Sat, 19 May 2001 03:07:20 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>jump_frame</name>
+ <border_width>5</border_width>
+ <label>Jump to: </label>
+ <label_xalign>0.05</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>jump_box</name>
+ <border_width>5</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>jump_label3</name>
+ <label>s.</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>jump_second_spinbutton</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>jump_label1</name>
+ <label>m:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>jump_minute_spinbutton</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>59</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>jump_label2</name>
+ <label>h:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>jump_hour_spinbutton</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>10</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GnomeDialog</class>
+ <name>intf_messages</name>
+ <signal>
+ <name>destroy</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Wed, 20 Feb 2002 05:11:27 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>delete_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Wed, 20 Feb 2002 05:11:27 GMT</last_modification_time>
+ </signal>
+ <title>Messages</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>True</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>True</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>dialog-vbox6</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>4</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>dialog-action_area6</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>messages_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkMessagesOk</handler>
+ <last_modification_time>Wed, 20 Feb 2002 05:12:11 GMT</last_modification_time>
+ </signal>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow1</name>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkText</class>
+ <name>messages_textbox</name>
+ <width>600</width>
+ <height>400</height>
+ <can_focus>True</can_focus>
+ <editable>False</editable>
+ <text></text>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
--- /dev/null
+/*****************************************************************************
+ * This file is not used: everything is in gtk_callbacks.c
+ *****************************************************************************/
--- /dev/null
+/*****************************************************************************
+ * This file is not needed: everything is in gtk_callbacks.h
+ *****************************************************************************/
+#include "gtk_callbacks.h"
--- /dev/null
+/* This file was created automatically by glade and fixed by bootstrap.sh */
+
+#include <vlc/vlc.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gnome.h>
+
+#include "gnome_callbacks.h"
+#include "gnome_interface.h"
+#include "gnome_support.h"
+
+static GnomeUIInfo menubar_file_menu_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("_Open File..."),
+ N_("Open a File"),
+ (gpointer) GtkFileOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Open _Disc..."),
+ N_("Open a DVD or VCD"),
+ (gpointer) GtkDiscOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_CDROM,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Network Stream..."),
+ N_("Select a Network Stream"),
+ (gpointer) GtkNetworkOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_REFRESH,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ {
+ GNOME_APP_UI_ITEM, N_("_Eject Disc"),
+ N_("Eject disc"),
+ (gpointer) GtkDiscEject, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_TOP,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_CLOSE_ITEM (GtkClose, NULL),
+ GNOMEUIINFO_MENU_EXIT_ITEM (GtkExit, NULL),
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo menubar_view_menu_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("_Hide interface"),
+ NULL,
+ (gpointer) GtkWindowToggle, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Fullscreen"),
+ NULL,
+ (gpointer) GtkFullscreen, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ {
+ GNOME_APP_UI_ITEM, N_("Progr_am"),
+ N_("Choose the program"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Title"),
+ N_("Choose title"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Chapter"),
+ N_("Choose chapter"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ {
+ GNOME_APP_UI_ITEM, N_("_Playlist..."),
+ N_("Open the playlist window"),
+ (gpointer) GtkPlaylistShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_INDEX,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Modules..."),
+ N_("Open the module manager"),
+ (gpointer) GtkModulesShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ATTACH,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Messages..."),
+ N_("Open the messages window"),
+ (gpointer) GtkMessagesShow, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo menubar_settings_menu_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("_Audio"),
+ N_("Select audio channel"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Subtitles"),
+ N_("Select subtitles channel"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_PREFERENCES_ITEM (GtkPreferencesShow, NULL),
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo menubar_help_menu_uiinfo[] =
+{
+ GNOMEUIINFO_MENU_ABOUT_ITEM (GtkAboutShow, NULL),
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo menubar_uiinfo[] =
+{
+ GNOMEUIINFO_MENU_FILE_TREE (menubar_file_menu_uiinfo),
+ GNOMEUIINFO_MENU_VIEW_TREE (menubar_view_menu_uiinfo),
+ GNOMEUIINFO_MENU_SETTINGS_TREE (menubar_settings_menu_uiinfo),
+ GNOMEUIINFO_MENU_HELP_TREE (menubar_help_menu_uiinfo),
+ GNOMEUIINFO_END
+};
+
+GtkWidget*
+create_intf_window (void)
+{
+ GtkWidget *intf_window;
+ GtkWidget *dockitem;
+ GtkWidget *toolbar;
+ GtkWidget *tmp_toolbar_icon;
+ GtkWidget *toolbar_file;
+ GtkWidget *toolbar_disc;
+ GtkWidget *toolbar_network;
+ GtkWidget *toolbar_sat;
+ GtkWidget *toolbar_back;
+ GtkWidget *toolbar_stop;
+ GtkWidget *toolbar_eject;
+ GtkWidget *toolbar_play;
+ GtkWidget *toolbar_pause;
+ GtkWidget *toolbar_slow;
+ GtkWidget *toolbar_fast;
+ GtkWidget *toolbar_playlist;
+ GtkWidget *toolbar_prev;
+ GtkWidget *toolbar_next;
+ GtkWidget *vbox8;
+ GtkWidget *slider_frame;
+ GtkWidget *slider;
+ GtkWidget *file_box;
+ GtkWidget *label_status;
+ GtkWidget *dvd_box;
+ GtkWidget *label21;
+ GtkWidget *title_chapter_box;
+ GtkWidget *label19;
+ GtkWidget *title_label;
+ GtkWidget *button_title_prev;
+ GtkWidget *button_title_next;
+ GtkWidget *vseparator1;
+ GtkWidget *dvd_chapter_box;
+ GtkWidget *label20;
+ GtkWidget *chapter_label;
+ GtkWidget *button_chapter_prev;
+ GtkWidget *button_chapter_next;
+ GtkWidget *network_box;
+ GtkWidget *network_address_label;
+ GtkWidget *network_channel_box;
+ GtkWidget *label_network;
+ GtkObject *network_channel_spinbutton_adj;
+ GtkWidget *network_channel_spinbutton;
+ GtkWidget *network_channel_go_button;
+ GtkWidget *appbar;
+ GtkTooltips *tooltips;
+
+ tooltips = gtk_tooltips_new ();
+
+ intf_window = gnome_app_new ("VideoLAN Client", _("VideoLAN Client"));
+ gtk_object_set_data (GTK_OBJECT (intf_window), "intf_window", intf_window);
+ gtk_window_set_policy (GTK_WINDOW (intf_window), FALSE, TRUE, TRUE);
+
+ dockitem = GNOME_APP (intf_window)->dock;
+ gtk_widget_ref (dockitem);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "dockitem", dockitem,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (dockitem);
+
+ gnome_app_create_menus (GNOME_APP (intf_window), menubar_uiinfo);
+
+ gtk_widget_ref (menubar_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_file",
+ menubar_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_open",
+ menubar_file_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_disc",
+ menubar_file_menu_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_network",
+ menubar_file_menu_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[3].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator1",
+ menubar_file_menu_uiinfo[3].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[4].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_eject",
+ menubar_file_menu_uiinfo[4].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[5].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator15",
+ menubar_file_menu_uiinfo[5].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[6].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_close",
+ menubar_file_menu_uiinfo[6].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_file_menu_uiinfo[7].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_exit",
+ menubar_file_menu_uiinfo[7].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_view",
+ menubar_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_hide_interface",
+ menubar_view_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_fullscreen",
+ menubar_view_menu_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator9",
+ menubar_view_menu_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[3].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_program",
+ menubar_view_menu_uiinfo[3].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (menubar_view_menu_uiinfo[3].widget, FALSE);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[4].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_title",
+ menubar_view_menu_uiinfo[4].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (menubar_view_menu_uiinfo[4].widget, FALSE);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[5].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_chapter",
+ menubar_view_menu_uiinfo[5].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (menubar_view_menu_uiinfo[5].widget, FALSE);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[6].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator7",
+ menubar_view_menu_uiinfo[6].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[7].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_playlist",
+ menubar_view_menu_uiinfo[7].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[8].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_modules",
+ menubar_view_menu_uiinfo[8].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (menubar_view_menu_uiinfo[8].widget, FALSE);
+
+ gtk_widget_ref (menubar_view_menu_uiinfo[9].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_messages",
+ menubar_view_menu_uiinfo[9].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_settings",
+ menubar_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_settings_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_audio",
+ menubar_settings_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (menubar_settings_menu_uiinfo[0].widget, FALSE);
+
+ gtk_widget_ref (menubar_settings_menu_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_subpictures",
+ menubar_settings_menu_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (menubar_settings_menu_uiinfo[1].widget, FALSE);
+
+ gtk_widget_ref (menubar_settings_menu_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator5",
+ menubar_settings_menu_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_settings_menu_uiinfo[3].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_preferences",
+ menubar_settings_menu_uiinfo[3].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_uiinfo[3].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_help",
+ menubar_uiinfo[3].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (menubar_help_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_about",
+ menubar_help_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
+ gtk_widget_ref (toolbar);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar", toolbar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar);
+ gnome_app_add_toolbar (GNOME_APP (intf_window), GTK_TOOLBAR (toolbar), "toolbar",
+ GNOME_DOCK_ITEM_BEH_EXCLUSIVE,
+ GNOME_DOCK_TOP, 1, 0, 2);
+ gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 16);
+ gtk_toolbar_set_space_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_SPACE_LINE);
+ gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NONE);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_OPEN);
+ toolbar_file = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("File"),
+ _("Open a File"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_file", toolbar_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_file);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_CDROM);
+ toolbar_disc = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Disc"),
+ _("Open a DVD or VCD"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_disc);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_disc", toolbar_disc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_disc);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_REFRESH);
+ toolbar_network = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Net"),
+ _("Select a Network Stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_network);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_network", toolbar_network,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_network);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_MIC);
+ toolbar_sat = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Sat"),
+ _("Open a Satellite Card"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_sat);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_sat", toolbar_sat,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_sat);
+
+ gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_BACK);
+ toolbar_back = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Back"),
+ _("Go Backward"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_back);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_back", toolbar_back,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_back);
+ gtk_widget_set_sensitive (toolbar_back, FALSE);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_STOP);
+ toolbar_stop = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Stop"),
+ _("Stop Stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_stop);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_stop", toolbar_stop,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_stop);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_TOP);
+ toolbar_eject = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Eject"),
+ _("Eject disc"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_eject);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_eject", toolbar_eject,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_eject);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_FORWARD);
+ toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Play"),
+ _("Play Stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_play);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_play", toolbar_play,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_play);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_BOTTOM);
+ toolbar_pause = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Pause"),
+ _("Pause Stream"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_pause);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_pause", toolbar_pause,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_pause);
+ gtk_widget_set_sensitive (toolbar_pause, FALSE);
+
+ gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_TIMER_STOP);
+ toolbar_slow = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Slow"),
+ _("Play Slower"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_slow);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_slow", toolbar_slow,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_slow);
+ gtk_widget_set_sensitive (toolbar_slow, FALSE);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_TIMER);
+ toolbar_fast = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Fast"),
+ _("Play Faster"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_fast);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_fast", toolbar_fast,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_fast);
+ gtk_widget_set_sensitive (toolbar_fast, FALSE);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_INDEX);
+ toolbar_playlist = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Playlist"),
+ _("Open Playlist"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_playlist);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_playlist", toolbar_playlist,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_playlist);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_FIRST);
+ toolbar_prev = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Prev"),
+ _("Previous File"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_prev);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_prev", toolbar_prev,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_prev);
+
+ tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_LAST);
+ toolbar_next = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Next"),
+ _("Next File"), NULL,
+ tmp_toolbar_icon, NULL, NULL);
+ gtk_widget_ref (toolbar_next);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_next", toolbar_next,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_next);
+
+ vbox8 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_ref (vbox8);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "vbox8", vbox8,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (vbox8);
+ gnome_app_set_contents (GNOME_APP (intf_window), vbox8);
+
+ slider_frame = gtk_frame_new ("-:--:--");
+ gtk_widget_ref (slider_frame);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "slider_frame", slider_frame,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_box_pack_start (GTK_BOX (vbox8), slider_frame, TRUE, TRUE, 0);
+ gtk_frame_set_label_align (GTK_FRAME (slider_frame), 0.05, 0.5);
+
+ slider = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 1, 6.25, 0)));
+ gtk_widget_ref (slider);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "slider", slider,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (slider);
+ gtk_container_add (GTK_CONTAINER (slider_frame), slider);
+ gtk_scale_set_draw_value (GTK_SCALE (slider), FALSE);
+ gtk_scale_set_digits (GTK_SCALE (slider), 3);
+
+ file_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (file_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "file_box", file_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (file_box);
+ gtk_box_pack_start (GTK_BOX (vbox8), file_box, TRUE, TRUE, 0);
+
+ label_status = gtk_label_new ("");
+ gtk_widget_ref (label_status);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "label_status", label_status,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label_status);
+ gtk_box_pack_start (GTK_BOX (file_box), label_status, TRUE, TRUE, 0);
+
+ dvd_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (dvd_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "dvd_box", dvd_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_box_pack_start (GTK_BOX (vbox8), dvd_box, TRUE, TRUE, 0);
+
+ label21 = gtk_label_new (_("Disc"));
+ gtk_widget_ref (label21);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "label21", label21,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label21);
+ gtk_box_pack_start (GTK_BOX (dvd_box), label21, TRUE, FALSE, 0);
+
+ title_chapter_box = gtk_hbox_new (FALSE, 10);
+ gtk_widget_ref (title_chapter_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "title_chapter_box", title_chapter_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (title_chapter_box);
+ gtk_box_pack_start (GTK_BOX (dvd_box), title_chapter_box, TRUE, FALSE, 0);
+
+ label19 = gtk_label_new (_("Title:"));
+ gtk_widget_ref (label19);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "label19", label19,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label19);
+ gtk_box_pack_start (GTK_BOX (title_chapter_box), label19, FALSE, FALSE, 0);
+
+ title_label = gtk_label_new ("--");
+ gtk_widget_ref (title_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "title_label", title_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (title_label);
+ gtk_box_pack_start (GTK_BOX (title_chapter_box), title_label, FALSE, FALSE, 0);
+
+ button_title_prev = gnome_stock_button (GNOME_STOCK_BUTTON_PREV);
+ gtk_widget_ref (button_title_prev);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "button_title_prev", button_title_prev,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (button_title_prev);
+ gtk_box_pack_start (GTK_BOX (title_chapter_box), button_title_prev, FALSE, FALSE, 0);
+ gtk_tooltips_set_tip (tooltips, button_title_prev, _("Select previous title"), NULL);
+ gtk_button_set_relief (GTK_BUTTON (button_title_prev), GTK_RELIEF_NONE);
+
+ button_title_next = gnome_stock_button (GNOME_STOCK_BUTTON_NEXT);
+ gtk_widget_ref (button_title_next);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "button_title_next", button_title_next,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (button_title_next);
+ gtk_box_pack_start (GTK_BOX (title_chapter_box), button_title_next, FALSE, FALSE, 0);
+ gtk_button_set_relief (GTK_BUTTON (button_title_next), GTK_RELIEF_NONE);
+
+ vseparator1 = gtk_vseparator_new ();
+ gtk_widget_ref (vseparator1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "vseparator1", vseparator1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (vseparator1);
+ gtk_box_pack_start (GTK_BOX (dvd_box), vseparator1, FALSE, FALSE, 0);
+
+ dvd_chapter_box = gtk_hbox_new (FALSE, 10);
+ gtk_widget_ref (dvd_chapter_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "dvd_chapter_box", dvd_chapter_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (dvd_chapter_box);
+ gtk_box_pack_start (GTK_BOX (dvd_box), dvd_chapter_box, TRUE, FALSE, 0);
+
+ label20 = gtk_label_new (_("Chapter:"));
+ gtk_widget_ref (label20);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "label20", label20,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label20);
+ gtk_box_pack_start (GTK_BOX (dvd_chapter_box), label20, FALSE, FALSE, 0);
+
+ chapter_label = gtk_label_new ("---");
+ gtk_widget_ref (chapter_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "chapter_label", chapter_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (chapter_label);
+ gtk_box_pack_start (GTK_BOX (dvd_chapter_box), chapter_label, FALSE, FALSE, 0);
+
+ button_chapter_prev = gnome_stock_button (GNOME_STOCK_BUTTON_DOWN);
+ gtk_widget_ref (button_chapter_prev);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "button_chapter_prev", button_chapter_prev,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (button_chapter_prev);
+ gtk_box_pack_start (GTK_BOX (dvd_chapter_box), button_chapter_prev, FALSE, FALSE, 0);
+ gtk_tooltips_set_tip (tooltips, button_chapter_prev, _("Select previous chapter"), NULL);
+ gtk_button_set_relief (GTK_BUTTON (button_chapter_prev), GTK_RELIEF_NONE);
+
+ button_chapter_next = gnome_stock_button (GNOME_STOCK_BUTTON_UP);
+ gtk_widget_ref (button_chapter_next);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "button_chapter_next", button_chapter_next,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (button_chapter_next);
+ gtk_box_pack_start (GTK_BOX (dvd_chapter_box), button_chapter_next, FALSE, FALSE, 0);
+ gtk_tooltips_set_tip (tooltips, button_chapter_next, _("Select next chapter"), NULL);
+ gtk_button_set_relief (GTK_BUTTON (button_chapter_next), GTK_RELIEF_NONE);
+
+ network_box = gtk_hbox_new (TRUE, 0);
+ gtk_widget_ref (network_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_box", network_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_box_pack_start (GTK_BOX (vbox8), network_box, FALSE, FALSE, 0);
+
+ network_address_label = gtk_label_new (_("No server"));
+ gtk_widget_ref (network_address_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_address_label", network_address_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_address_label);
+ gtk_box_pack_start (GTK_BOX (network_box), network_address_label, FALSE, FALSE, 0);
+
+ network_channel_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (network_channel_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_channel_box", network_channel_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_box);
+ gtk_box_pack_start (GTK_BOX (network_box), network_channel_box, FALSE, FALSE, 0);
+
+ label_network = gtk_label_new (_("Network Channel:"));
+ gtk_widget_ref (label_network);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "label_network", label_network,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label_network);
+ gtk_box_pack_start (GTK_BOX (network_channel_box), label_network, TRUE, FALSE, 5);
+
+ network_channel_spinbutton_adj = gtk_adjustment_new (0, 0, 100, 1, 10, 10);
+ network_channel_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (network_channel_spinbutton_adj), 1, 0);
+ gtk_widget_ref (network_channel_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_channel_spinbutton", network_channel_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_spinbutton);
+ gtk_box_pack_start (GTK_BOX (network_channel_box), network_channel_spinbutton, FALSE, TRUE, 5);
+
+ network_channel_go_button = gtk_button_new_with_label (_("Go!"));
+ gtk_widget_ref (network_channel_go_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_channel_go_button", network_channel_go_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_go_button);
+ gtk_box_pack_start (GTK_BOX (network_channel_box), network_channel_go_button, FALSE, FALSE, 0);
+ gtk_button_set_relief (GTK_BUTTON (network_channel_go_button), GTK_RELIEF_NONE);
+
+ appbar = gnome_appbar_new (FALSE, TRUE, GNOME_PREFERENCES_NEVER);
+ gtk_widget_ref (appbar);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "appbar", appbar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (appbar);
+ gnome_app_set_statusbar (GNOME_APP (intf_window), appbar);
+
+ gtk_signal_connect (GTK_OBJECT (intf_window), "delete_event",
+ GTK_SIGNAL_FUNC (GtkWindowDelete),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (intf_window), "drag_data_received",
+ GTK_SIGNAL_FUNC (GtkWindowDrag),
+ NULL);
+ gnome_app_install_menu_hints (GNOME_APP (intf_window), menubar_uiinfo);
+ gtk_signal_connect (GTK_OBJECT (toolbar_file), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_disc), "clicked",
+ GTK_SIGNAL_FUNC (GtkDiscOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_network), "clicked",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_sat), "clicked",
+ GTK_SIGNAL_FUNC (GtkSatOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_back), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlBack),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_stop), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlStop),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_eject), "clicked",
+ GTK_SIGNAL_FUNC (GtkDiscEject),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_play), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlPlay),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_pause), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlPause),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_slow), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlSlow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_fast), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlFast),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_playlist), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_prev), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistPrev),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_next), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistNext),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (slider), "button_press_event",
+ GTK_SIGNAL_FUNC (GtkSliderPress),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (slider), "button_release_event",
+ GTK_SIGNAL_FUNC (GtkSliderRelease),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (button_title_prev), "clicked",
+ GTK_SIGNAL_FUNC (GtkTitlePrev),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (button_title_next), "clicked",
+ GTK_SIGNAL_FUNC (GtkTitleNext),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (button_chapter_prev), "clicked",
+ GTK_SIGNAL_FUNC (GtkChapterPrev),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (button_chapter_next), "clicked",
+ GTK_SIGNAL_FUNC (GtkChapterNext),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_spinbutton), "activate",
+ GTK_SIGNAL_FUNC (GtkNetworkJoin),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_go_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkChannelGo),
+ NULL);
+
+ gtk_object_set_data (GTK_OBJECT (intf_window), "tooltips", tooltips);
+
+ return intf_window;
+}
+
+static GnomeUIInfo popup_file_menu_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("_Open File..."),
+ N_("Open a File"),
+ (gpointer) GtkFileOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Open _Disc..."),
+ N_("Open a DVD or VCD"),
+ (gpointer) GtkDiscOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_CDROM,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Network Stream..."),
+ N_("Select a Network Stream"),
+ (gpointer) GtkNetworkOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_REFRESH,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_ABOUT_ITEM (GtkAboutShow, NULL),
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo intf_popup_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("Play"),
+ NULL,
+ (gpointer) GtkControlPlay, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_FORWARD,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Pause"),
+ NULL,
+ (gpointer) GtkControlPause, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BOTTOM,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Stop"),
+ NULL,
+ (gpointer) GtkControlStop, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_STOP,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Back"),
+ NULL,
+ (gpointer) GtkControlBack, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BACK,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Slow"),
+ NULL,
+ (gpointer) GtkControlSlow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_TIMER_STOP,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Fast"),
+ NULL,
+ (gpointer) GtkControlFast, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_TIMER,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ {
+ GNOME_APP_UI_ITEM, N_("Toggle _Interface"),
+ NULL,
+ (gpointer) GtkWindowToggle, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Fullscreen"),
+ N_("Toggle fullscreen mode"),
+ (gpointer) GtkFullscreen, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ {
+ GNOME_APP_UI_ITEM, N_("Next"),
+ NULL,
+ (gpointer) GtkPlaylistNext, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Prev"),
+ NULL,
+ (gpointer) GtkPlaylistPrev, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Jump..."),
+ N_("Got directly so specified point"),
+ (gpointer) GtkJumpShow, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_JUMP_TO,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Program"),
+ N_("Switch program"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Navigation"),
+ N_("Navigate through titles and chapters"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SEARCH,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Audio"),
+ N_("Select audio channel"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_VOLUME,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("_Subtitles"),
+ N_("Select subtitles channel"),
+ (gpointer) NULL, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_FONT,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_FILE_TREE (popup_file_menu_uiinfo),
+ {
+ GNOME_APP_UI_ITEM, N_("Playlist..."),
+ NULL,
+ (gpointer) GtkPlaylistShow, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_MENU_PREFERENCES_ITEM (GtkPreferencesShow, NULL),
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_EXIT_ITEM (GtkExit, NULL),
+ GNOMEUIINFO_END
+};
+
+GtkWidget*
+create_intf_popup (void)
+{
+ GtkWidget *intf_popup;
+
+ intf_popup = gtk_menu_new ();
+ gtk_object_set_data (GTK_OBJECT (intf_popup), "intf_popup", intf_popup);
+ gnome_app_fill_menu (GTK_MENU_SHELL (intf_popup), intf_popup_uiinfo,
+ NULL, FALSE, 0);
+
+ gtk_widget_ref (intf_popup_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_play",
+ intf_popup_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_pause",
+ intf_popup_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_stop",
+ intf_popup_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[3].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_back",
+ intf_popup_uiinfo[3].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (intf_popup_uiinfo[3].widget, FALSE);
+
+ gtk_widget_ref (intf_popup_uiinfo[4].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_slow",
+ intf_popup_uiinfo[4].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[5].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_fast",
+ intf_popup_uiinfo[5].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[6].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator3",
+ intf_popup_uiinfo[6].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[7].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_interface_toggle",
+ intf_popup_uiinfo[7].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[8].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_fullscreen",
+ intf_popup_uiinfo[8].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[9].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator8",
+ intf_popup_uiinfo[9].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[10].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_next",
+ intf_popup_uiinfo[10].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[11].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_prev",
+ intf_popup_uiinfo[11].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[12].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_jump",
+ intf_popup_uiinfo[12].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[13].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_program",
+ intf_popup_uiinfo[13].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (intf_popup_uiinfo[13].widget, FALSE);
+
+ gtk_widget_ref (intf_popup_uiinfo[14].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_navigation",
+ intf_popup_uiinfo[14].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (intf_popup_uiinfo[14].widget, FALSE);
+
+ gtk_widget_ref (intf_popup_uiinfo[15].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_audio",
+ intf_popup_uiinfo[15].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (intf_popup_uiinfo[15].widget, FALSE);
+
+ gtk_widget_ref (intf_popup_uiinfo[16].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_subpictures",
+ intf_popup_uiinfo[16].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_set_sensitive (intf_popup_uiinfo[16].widget, FALSE);
+
+ gtk_widget_ref (intf_popup_uiinfo[17].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator13",
+ intf_popup_uiinfo[17].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[18].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_file",
+ intf_popup_uiinfo[18].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (popup_file_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_open",
+ popup_file_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (popup_file_menu_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_disc",
+ popup_file_menu_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (popup_file_menu_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_network",
+ popup_file_menu_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (popup_file_menu_uiinfo[3].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator4",
+ popup_file_menu_uiinfo[3].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (popup_file_menu_uiinfo[4].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_about",
+ popup_file_menu_uiinfo[4].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[19].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_playlist",
+ intf_popup_uiinfo[19].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[20].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_preferences",
+ intf_popup_uiinfo[20].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[21].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator2",
+ intf_popup_uiinfo[21].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (intf_popup_uiinfo[22].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_exit",
+ intf_popup_uiinfo[22].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ return intf_popup;
+}
+
+GtkWidget*
+create_intf_about (void)
+{
+ const gchar *authors[] = {
+ "the VideoLAN team <videolan@videolan.org>",
+ "http://www.videolan.org/",
+ NULL
+ };
+ GtkWidget *intf_about;
+
+ intf_about = gnome_about_new ("VideoLAN Client", VERSION,
+ _("(C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 - the VideoLAN Team"),
+ authors,
+ _("This is the VideoLAN client, a DVD and MPEG player. It can play MPEG and MPEG 2 files from a file or from a network source."),
+ NULL);
+ gtk_object_set_data (GTK_OBJECT (intf_about), "intf_about", intf_about);
+
+ return intf_about;
+}
+
+GtkWidget*
+create_intf_open (void)
+{
+ GtkWidget *intf_open;
+ GtkWidget *dialog_vbox5;
+ GtkWidget *open_vbox;
+ GtkWidget *frame10;
+ GtkWidget *hbox21;
+ GtkWidget *hbox22;
+ GtkWidget *label34;
+ GtkWidget *combo2;
+ GtkWidget *entry_open;
+ GtkWidget *label36;
+ GtkWidget *open_notebook;
+ GtkWidget *hbox20;
+ GtkWidget *combo1;
+ GtkWidget *entry_file;
+ GtkWidget *vbox13;
+ GtkWidget *open_browse;
+ GtkWidget *open_file;
+ GtkWidget *table5;
+ GtkWidget *label21;
+ GtkWidget *label20;
+ GtkObject *disc_chapter_adj;
+ GtkWidget *disc_chapter;
+ GtkWidget *label35;
+ GtkWidget *hbox24;
+ GSList *disc_group = NULL;
+ GtkWidget *disc_dvd;
+ GtkWidget *disc_vcd;
+ GtkWidget *label19;
+ GtkObject *disc_title_adj;
+ GtkWidget *disc_title;
+ GtkWidget *disc_name;
+ GtkWidget *open_disc;
+ GtkWidget *table4;
+ GSList *table4_group = NULL;
+ GtkWidget *network_udp;
+ GtkWidget *network_multicast;
+ GtkWidget *network_channel;
+ GtkWidget *network_http;
+ GtkWidget *network_udp_port_label;
+ GtkWidget *network_multicast_address_label;
+ GtkWidget *network_channel_address_label;
+ GtkWidget *network_http_url_label;
+ GtkWidget *network_multicast_address_combo;
+ GtkWidget *network_multicast_address;
+ GtkWidget *network_channel_address_combo;
+ GtkWidget *network_channel_address;
+ GtkWidget *network_multicast_port_label;
+ GtkWidget *network_channel_port_label;
+ GtkObject *network_multicast_port_adj;
+ GtkWidget *network_multicast_port;
+ GtkObject *network_channel_port_adj;
+ GtkWidget *network_channel_port;
+ GtkWidget *network_http_url;
+ GtkObject *network_udp_port_adj;
+ GtkWidget *network_udp_port;
+ GtkWidget *open_net;
+ GtkWidget *table3;
+ GtkWidget *label24;
+ GtkWidget *label25;
+ GtkWidget *label26;
+ GtkObject *sat_freq_adj;
+ GtkWidget *sat_freq;
+ GtkWidget *label27;
+ GtkWidget *hbox23;
+ GSList *pol_group = NULL;
+ GtkWidget *sat_pol_vert;
+ GtkWidget *sat_pol_hor;
+ GtkObject *sat_srate_adj;
+ GtkWidget *sat_srate;
+ GtkWidget *sat_fec;
+ GList *sat_fec_items = NULL;
+ GtkWidget *combo_entry1;
+ GtkWidget *open_sat;
+ GtkWidget *dialog_action_area5;
+ GtkWidget *button1;
+ GtkWidget *button3;
+
+ intf_open = gnome_dialog_new (_("Open Stream"), NULL);
+ gtk_object_set_data (GTK_OBJECT (intf_open), "intf_open", intf_open);
+ gtk_window_set_modal (GTK_WINDOW (intf_open), TRUE);
+ gtk_window_set_policy (GTK_WINDOW (intf_open), FALSE, FALSE, FALSE);
+ gnome_dialog_close_hides (GNOME_DIALOG (intf_open), TRUE);
+
+ dialog_vbox5 = GNOME_DIALOG (intf_open)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_open), "dialog_vbox5", dialog_vbox5);
+ gtk_widget_show (dialog_vbox5);
+
+ open_vbox = gtk_vbox_new (FALSE, 5);
+ gtk_widget_ref (open_vbox);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_vbox", open_vbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_vbox);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox5), open_vbox, TRUE, TRUE, 0);
+
+ frame10 = gtk_frame_new (_("Media Resource Locator (MRL)"));
+ gtk_widget_ref (frame10);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "frame10", frame10,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (frame10);
+ gtk_box_pack_start (GTK_BOX (open_vbox), frame10, FALSE, TRUE, 0);
+
+ hbox21 = gtk_hbox_new (FALSE, 5);
+ gtk_widget_ref (hbox21);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox21", hbox21,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox21);
+ gtk_container_add (GTK_CONTAINER (frame10), hbox21);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox21), 5);
+
+ hbox22 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (hbox22);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox22", hbox22,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox22);
+ gtk_box_pack_start (GTK_BOX (hbox21), hbox22, FALSE, TRUE, 0);
+
+ label34 = gtk_label_new (_("Open Target:"));
+ gtk_widget_ref (label34);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label34", label34,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label34);
+ gtk_box_pack_start (GTK_BOX (hbox22), label34, FALSE, FALSE, 0);
+
+ combo2 = gtk_combo_new ();
+ gtk_widget_ref (combo2);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "combo2", combo2,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo2);
+ gtk_box_pack_start (GTK_BOX (hbox21), combo2, TRUE, TRUE, 0);
+
+ entry_open = GTK_COMBO (combo2)->entry;
+ gtk_widget_ref (entry_open);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "entry_open", entry_open,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (entry_open);
+
+ label36 = gtk_label_new (_("Alternatively, you can build an MRL using one of the following predefined targets:"));
+ gtk_widget_ref (label36);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label36", label36,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label36);
+ gtk_box_pack_start (GTK_BOX (open_vbox), label36, TRUE, TRUE, 0);
+ gtk_label_set_justify (GTK_LABEL (label36), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label36), 0, 1);
+
+ open_notebook = gtk_notebook_new ();
+ gtk_widget_ref (open_notebook);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_notebook", open_notebook,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_notebook);
+ gtk_box_pack_start (GTK_BOX (open_vbox), open_notebook, TRUE, TRUE, 0);
+
+ hbox20 = gtk_hbox_new (FALSE, 5);
+ gtk_widget_ref (hbox20);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox20", hbox20,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox20);
+ gtk_container_add (GTK_CONTAINER (open_notebook), hbox20);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox20), 5);
+
+ combo1 = gtk_combo_new ();
+ gtk_widget_ref (combo1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "combo1", combo1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo1);
+ gtk_box_pack_start (GTK_BOX (hbox20), combo1, FALSE, TRUE, 0);
+
+ entry_file = GTK_COMBO (combo1)->entry;
+ gtk_widget_ref (entry_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "entry_file", entry_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (entry_file);
+
+ vbox13 = gtk_vbox_new (TRUE, 0);
+ gtk_widget_ref (vbox13);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "vbox13", vbox13,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (vbox13);
+ gtk_box_pack_start (GTK_BOX (hbox20), vbox13, FALSE, FALSE, 0);
+
+ open_browse = gtk_button_new_with_label (_("Browse..."));
+ gtk_widget_ref (open_browse);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_browse", open_browse,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_browse);
+ gtk_box_pack_start (GTK_BOX (vbox13), open_browse, FALSE, FALSE, 0);
+
+ open_file = gtk_label_new (_("File"));
+ gtk_widget_ref (open_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_file", open_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_file);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 0), open_file);
+
+ table5 = gtk_table_new (4, 2, FALSE);
+ gtk_widget_ref (table5);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "table5", table5,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (table5);
+ gtk_container_add (GTK_CONTAINER (open_notebook), table5);
+ gtk_container_set_border_width (GTK_CONTAINER (table5), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table5), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table5), 5);
+
+ label21 = gtk_label_new (_("Title"));
+ gtk_widget_ref (label21);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label21", label21,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label21);
+ gtk_table_attach (GTK_TABLE (table5), label21, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label21), 0, 0.5);
+
+ label20 = gtk_label_new (_("Chapter"));
+ gtk_widget_ref (label20);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label20", label20,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label20);
+ gtk_table_attach (GTK_TABLE (table5), label20, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label20), 0, 0.5);
+
+ disc_chapter_adj = gtk_adjustment_new (1, 1, 65536, 1, 10, 10);
+ disc_chapter = gtk_spin_button_new (GTK_ADJUSTMENT (disc_chapter_adj), 1, 0);
+ gtk_widget_ref (disc_chapter);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_chapter", disc_chapter,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_chapter);
+ gtk_table_attach (GTK_TABLE (table5), disc_chapter, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label35 = gtk_label_new (_("Disc type"));
+ gtk_widget_ref (label35);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label35", label35,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label35);
+ gtk_table_attach (GTK_TABLE (table5), label35, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label35), 0, 0.5);
+
+ hbox24 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (hbox24);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox24", hbox24,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox24);
+ gtk_table_attach (GTK_TABLE (table5), hbox24, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+ disc_dvd = gtk_radio_button_new_with_label (disc_group, _("DVD"));
+ disc_group = gtk_radio_button_group (GTK_RADIO_BUTTON (disc_dvd));
+ gtk_widget_ref (disc_dvd);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_dvd", disc_dvd,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_dvd);
+ gtk_box_pack_start (GTK_BOX (hbox24), disc_dvd, FALSE, FALSE, 0);
+
+ disc_vcd = gtk_radio_button_new_with_label (disc_group, _("VCD"));
+ disc_group = gtk_radio_button_group (GTK_RADIO_BUTTON (disc_vcd));
+ gtk_widget_ref (disc_vcd);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_vcd", disc_vcd,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_vcd);
+ gtk_box_pack_start (GTK_BOX (hbox24), disc_vcd, FALSE, FALSE, 0);
+
+ label19 = gtk_label_new (_("Device name"));
+ gtk_widget_ref (label19);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label19", label19,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label19);
+ gtk_table_attach (GTK_TABLE (table5), label19, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ disc_title_adj = gtk_adjustment_new (1, 1, 65536, 1, 10, 10);
+ disc_title = gtk_spin_button_new (GTK_ADJUSTMENT (disc_title_adj), 1, 0);
+ gtk_widget_ref (disc_title);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_title", disc_title,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_title);
+ gtk_table_attach (GTK_TABLE (table5), disc_title, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ disc_name = gtk_entry_new ();
+ gtk_widget_ref (disc_name);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_name", disc_name,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_name);
+ gtk_table_attach (GTK_TABLE (table5), disc_name, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_entry_set_text (GTK_ENTRY (disc_name), "/dev/dvd");
+
+ open_disc = gtk_label_new (_("Disc"));
+ gtk_widget_ref (open_disc);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_disc", open_disc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_disc);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 1), open_disc);
+
+ table4 = gtk_table_new (4, 6, FALSE);
+ gtk_widget_ref (table4);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "table4", table4,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (table4);
+ gtk_container_add (GTK_CONTAINER (open_notebook), table4);
+ gtk_container_set_border_width (GTK_CONTAINER (table4), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table4), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table4), 5);
+
+ network_udp = gtk_radio_button_new_with_label (table4_group, _("UDP"));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_udp));
+ gtk_widget_ref (network_udp);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_udp", network_udp,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_udp);
+ gtk_table_attach (GTK_TABLE (table4), network_udp, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_multicast = gtk_radio_button_new_with_label (table4_group, _("UDP Multicast"));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_multicast));
+ gtk_widget_ref (network_multicast);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast", network_multicast,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_channel = gtk_radio_button_new_with_label (table4_group, _("Channel server "));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_channel));
+ gtk_widget_ref (network_channel);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel", network_channel,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel);
+ gtk_table_attach (GTK_TABLE (table4), network_channel, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_http = gtk_radio_button_new_with_label (table4_group, _("HTTP"));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_http));
+ gtk_widget_ref (network_http);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_http", network_http,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_http);
+ gtk_table_attach (GTK_TABLE (table4), network_http, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_udp_port_label = gtk_label_new (_("Port"));
+ gtk_widget_ref (network_udp_port_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_udp_port_label", network_udp_port_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_udp_port_label);
+ gtk_table_attach (GTK_TABLE (table4), network_udp_port_label, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (network_udp_port_label), 1, 0.5);
+
+ network_multicast_address_label = gtk_label_new (_("Address"));
+ gtk_widget_ref (network_multicast_address_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_address_label", network_multicast_address_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_address_label);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_address_label, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_multicast_address_label, FALSE);
+ gtk_label_set_justify (GTK_LABEL (network_multicast_address_label), GTK_JUSTIFY_RIGHT);
+ gtk_misc_set_alignment (GTK_MISC (network_multicast_address_label), 1, 0.5);
+
+ network_channel_address_label = gtk_label_new (_("Address"));
+ gtk_widget_ref (network_channel_address_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_address_label", network_channel_address_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_address_label);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_address_label, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_channel_address_label, FALSE);
+
+ network_http_url_label = gtk_label_new (_("URL"));
+ gtk_widget_ref (network_http_url_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_http_url_label", network_http_url_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_http_url_label);
+ gtk_table_attach (GTK_TABLE (table4), network_http_url_label, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_http_url_label, FALSE);
+ gtk_misc_set_alignment (GTK_MISC (network_http_url_label), 1, 0.5);
+
+ network_multicast_address_combo = gtk_combo_new ();
+ gtk_widget_ref (network_multicast_address_combo);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_address_combo", network_multicast_address_combo,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_address_combo);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_address_combo, 2, 4, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_multicast_address_combo, FALSE);
+
+ network_multicast_address = GTK_COMBO (network_multicast_address_combo)->entry;
+ gtk_widget_ref (network_multicast_address);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_address", network_multicast_address,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_address);
+
+ network_channel_address_combo = gtk_combo_new ();
+ gtk_widget_ref (network_channel_address_combo);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_address_combo", network_channel_address_combo,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_address_combo);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_address_combo, 2, 4, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_channel_address_combo, FALSE);
+
+ network_channel_address = GTK_COMBO (network_channel_address_combo)->entry;
+ gtk_widget_ref (network_channel_address);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_address", network_channel_address,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_address);
+
+ network_multicast_port_label = gtk_label_new (_("Port"));
+ gtk_widget_ref (network_multicast_port_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_port_label", network_multicast_port_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_port_label);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_port_label, 4, 5, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_multicast_port_label, FALSE);
+ gtk_misc_set_alignment (GTK_MISC (network_multicast_port_label), 1, 0.5);
+
+ network_channel_port_label = gtk_label_new (_("Port"));
+ gtk_widget_ref (network_channel_port_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_port_label", network_channel_port_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_port_label);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_port_label, 4, 5, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_channel_port_label, FALSE);
+ gtk_misc_set_alignment (GTK_MISC (network_channel_port_label), 1, 0.5);
+
+ network_multicast_port_adj = gtk_adjustment_new (1234, 0, 65535, 1, 10, 10);
+ network_multicast_port = gtk_spin_button_new (GTK_ADJUSTMENT (network_multicast_port_adj), 1, 0);
+ gtk_widget_ref (network_multicast_port);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_port", network_multicast_port,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_port);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_port, 5, 6, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_usize (network_multicast_port, 75, -2);
+ gtk_widget_set_sensitive (network_multicast_port, FALSE);
+
+ network_channel_port_adj = gtk_adjustment_new (6010, 0, 65535, 1, 10, 10);
+ network_channel_port = gtk_spin_button_new (GTK_ADJUSTMENT (network_channel_port_adj), 1, 0);
+ gtk_widget_ref (network_channel_port);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_port", network_channel_port,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_port);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_port, 5, 6, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_usize (network_channel_port, 75, -2);
+ gtk_widget_set_sensitive (network_channel_port, FALSE);
+
+ network_http_url = gtk_entry_new ();
+ gtk_widget_ref (network_http_url);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_http_url", network_http_url,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_http_url);
+ gtk_table_attach (GTK_TABLE (table4), network_http_url, 2, 6, 3, 4,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_http_url, FALSE);
+
+ network_udp_port_adj = gtk_adjustment_new (1234, 0, 65535, 1, 10, 10);
+ network_udp_port = gtk_spin_button_new (GTK_ADJUSTMENT (network_udp_port_adj), 1, 0);
+ gtk_widget_ref (network_udp_port);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_udp_port", network_udp_port,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_udp_port);
+ gtk_table_attach (GTK_TABLE (table4), network_udp_port, 2, 3, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_usize (network_udp_port, 1, -2);
+
+ open_net = gtk_label_new (_("Network"));
+ gtk_widget_ref (open_net);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_net", open_net,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_net);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 2), open_net);
+
+ table3 = gtk_table_new (4, 2, FALSE);
+ gtk_widget_ref (table3);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "table3", table3,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (table3);
+ gtk_container_add (GTK_CONTAINER (open_notebook), table3);
+ gtk_container_set_border_width (GTK_CONTAINER (table3), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table3), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table3), 5);
+
+ label24 = gtk_label_new (_("Symbol Rate"));
+ gtk_widget_ref (label24);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label24", label24,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label24);
+ gtk_table_attach (GTK_TABLE (table3), label24, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label24), 0, 0.5);
+
+ label25 = gtk_label_new (_("Frequency"));
+ gtk_widget_ref (label25);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label25", label25,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label25);
+ gtk_table_attach (GTK_TABLE (table3), label25, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label25), 0, 0.5);
+
+ label26 = gtk_label_new (_("Polarization"));
+ gtk_widget_ref (label26);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label26", label26,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label26);
+ gtk_table_attach (GTK_TABLE (table3), label26, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label26), 0, 0.5);
+
+ sat_freq_adj = gtk_adjustment_new (11954, 10000, 12999, 1, 10, 10);
+ sat_freq = gtk_spin_button_new (GTK_ADJUSTMENT (sat_freq_adj), 1, 0);
+ gtk_widget_ref (sat_freq);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_freq", sat_freq,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_freq);
+ gtk_table_attach (GTK_TABLE (table3), sat_freq, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label27 = gtk_label_new (_("FEC"));
+ gtk_widget_ref (label27);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label27", label27,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label27);
+ gtk_table_attach (GTK_TABLE (table3), label27, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label27), 0, 0.5);
+
+ hbox23 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (hbox23);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox23", hbox23,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox23);
+ gtk_table_attach (GTK_TABLE (table3), hbox23, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+ sat_pol_vert = gtk_radio_button_new_with_label (pol_group, _("Vertical"));
+ pol_group = gtk_radio_button_group (GTK_RADIO_BUTTON (sat_pol_vert));
+ gtk_widget_ref (sat_pol_vert);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_pol_vert", sat_pol_vert,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_pol_vert);
+ gtk_box_pack_start (GTK_BOX (hbox23), sat_pol_vert, FALSE, FALSE, 0);
+
+ sat_pol_hor = gtk_radio_button_new_with_label (pol_group, _("Horizontal"));
+ pol_group = gtk_radio_button_group (GTK_RADIO_BUTTON (sat_pol_hor));
+ gtk_widget_ref (sat_pol_hor);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_pol_hor", sat_pol_hor,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_pol_hor);
+ gtk_box_pack_start (GTK_BOX (hbox23), sat_pol_hor, FALSE, FALSE, 0);
+
+ sat_srate_adj = gtk_adjustment_new (27500, 1000, 30000, 1, 10, 10);
+ sat_srate = gtk_spin_button_new (GTK_ADJUSTMENT (sat_srate_adj), 1, 0);
+ gtk_widget_ref (sat_srate);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_srate", sat_srate,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_srate);
+ gtk_table_attach (GTK_TABLE (table3), sat_srate, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ sat_fec = gtk_combo_new ();
+ gtk_widget_ref (sat_fec);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_fec", sat_fec,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_fec);
+ gtk_table_attach (GTK_TABLE (table3), sat_fec, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "1/2");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "2/3");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "3/4");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "4/5");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "5/6");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "7/8");
+ gtk_combo_set_popdown_strings (GTK_COMBO (sat_fec), sat_fec_items);
+ g_list_free (sat_fec_items);
+
+ combo_entry1 = GTK_COMBO (sat_fec)->entry;
+ gtk_widget_ref (combo_entry1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "combo_entry1", combo_entry1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo_entry1);
+ gtk_entry_set_text (GTK_ENTRY (combo_entry1), "3/4");
+
+ open_sat = gtk_label_new (_("Satellite"));
+ gtk_widget_ref (open_sat);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_sat", open_sat,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_sat);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 3), open_sat);
+
+ dialog_action_area5 = GNOME_DIALOG (intf_open)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_open), "dialog_action_area5", dialog_action_area5);
+ gtk_widget_show (dialog_action_area5);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area5), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (dialog_action_area5), 8);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_open), GNOME_STOCK_BUTTON_OK);
+ button1 = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_open)->buttons)->data);
+ gtk_widget_ref (button1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "button1", button1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (button1);
+ GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_open), GNOME_STOCK_BUTTON_CANCEL);
+ button3 = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_open)->buttons)->data);
+ gtk_widget_ref (button3);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "button3", button3,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (button3);
+ GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect_after (GTK_OBJECT (open_notebook), "switch_page",
+ GTK_SIGNAL_FUNC (GtkOpenNotebookChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (entry_file), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (open_browse), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_chapter), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_dvd), "toggled",
+ GTK_SIGNAL_FUNC (GtkDiscOpenDvd),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_vcd), "toggled",
+ GTK_SIGNAL_FUNC (GtkDiscOpenVcd),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_title), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_name), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_udp), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenUDP),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_multicast), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenMulticast),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenChannel),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_http), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenHTTP),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_multicast_address), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_address), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_multicast_port), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_port), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_http_url), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_udp_port), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_freq), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_pol_vert), "toggled",
+ GTK_SIGNAL_FUNC (GtkSatOpenToggle),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_pol_hor), "toggled",
+ GTK_SIGNAL_FUNC (GtkSatOpenToggle),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_srate), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (combo_entry1), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (button1), "clicked",
+ GTK_SIGNAL_FUNC (GtkOpenOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (button3), "clicked",
+ GTK_SIGNAL_FUNC (GtkOpenCancel),
+ NULL);
+
+ return intf_open;
+}
+
+GtkWidget*
+create_intf_file (void)
+{
+ GtkWidget *intf_file;
+ GtkWidget *file_ok;
+ GtkWidget *file_cancel;
+
+ intf_file = gtk_file_selection_new (_("Open File"));
+ gtk_object_set_data (GTK_OBJECT (intf_file), "intf_file", intf_file);
+ gtk_container_set_border_width (GTK_CONTAINER (intf_file), 10);
+ gtk_window_set_modal (GTK_WINDOW (intf_file), TRUE);
+ gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (intf_file));
+
+ file_ok = GTK_FILE_SELECTION (intf_file)->ok_button;
+ gtk_object_set_data (GTK_OBJECT (intf_file), "file_ok", file_ok);
+ gtk_widget_show (file_ok);
+ GTK_WIDGET_SET_FLAGS (file_ok, GTK_CAN_DEFAULT);
+
+ file_cancel = GTK_FILE_SELECTION (intf_file)->cancel_button;
+ gtk_object_set_data (GTK_OBJECT (intf_file), "file_cancel", file_cancel);
+ gtk_widget_show (file_cancel);
+ GTK_WIDGET_SET_FLAGS (file_cancel, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect (GTK_OBJECT (file_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (file_cancel), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileCancel),
+ NULL);
+
+ return intf_file;
+}
+
+GtkWidget*
+create_intf_modules (void)
+{
+ GtkWidget *intf_modules;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *label12;
+ GtkWidget *dialog_action_area1;
+ GtkWidget *modules_ok;
+ GtkWidget *modules_apply;
+ GtkWidget *modules_cancel;
+
+ intf_modules = gnome_dialog_new (_("Modules"), NULL);
+ gtk_object_set_data (GTK_OBJECT (intf_modules), "intf_modules", intf_modules);
+ gtk_window_set_policy (GTK_WINDOW (intf_modules), FALSE, FALSE, FALSE);
+
+ dialog_vbox1 = GNOME_DIALOG (intf_modules)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_modules), "dialog_vbox1", dialog_vbox1);
+ gtk_widget_show (dialog_vbox1);
+
+ label12 = gtk_label_new (_("Sorry, the module manager isn't functional yet. Please retry in a later version."));
+ gtk_widget_ref (label12);
+ gtk_object_set_data_full (GTK_OBJECT (intf_modules), "label12", label12,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label12);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), label12, FALSE, FALSE, 0);
+
+ dialog_action_area1 = GNOME_DIALOG (intf_modules)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_modules), "dialog_action_area1", dialog_action_area1);
+ gtk_widget_show (dialog_action_area1);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (dialog_action_area1), 8);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_modules), GNOME_STOCK_BUTTON_OK);
+ modules_ok = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_modules)->buttons)->data);
+ gtk_widget_ref (modules_ok);
+ gtk_object_set_data_full (GTK_OBJECT (intf_modules), "modules_ok", modules_ok,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (modules_ok);
+ GTK_WIDGET_SET_FLAGS (modules_ok, GTK_CAN_DEFAULT);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_modules), GNOME_STOCK_BUTTON_APPLY);
+ modules_apply = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_modules)->buttons)->data);
+ gtk_widget_ref (modules_apply);
+ gtk_object_set_data_full (GTK_OBJECT (intf_modules), "modules_apply", modules_apply,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (modules_apply);
+ GTK_WIDGET_SET_FLAGS (modules_apply, GTK_CAN_DEFAULT);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_modules), GNOME_STOCK_BUTTON_CANCEL);
+ modules_cancel = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_modules)->buttons)->data);
+ gtk_widget_ref (modules_cancel);
+ gtk_object_set_data_full (GTK_OBJECT (intf_modules), "modules_cancel", modules_cancel,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (modules_cancel);
+ GTK_WIDGET_SET_FLAGS (modules_cancel, GTK_CAN_DEFAULT);
+
+ return intf_modules;
+}
+
+static GnomeUIInfo playlist_add_menu_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("Disc"),
+ NULL,
+ (gpointer) GtkDiscOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("File"),
+ NULL,
+ (gpointer) GtkFileOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Network"),
+ NULL,
+ (gpointer) GtkNetworkOpenShow, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Url"),
+ NULL,
+ (gpointer) GtkPlaylistAddUrl, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo playlist_delete_menu_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("All"),
+ NULL,
+ (gpointer) GtkPlaylistDeleteAll, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Item"),
+ NULL,
+ (gpointer) GtkPlaylistDeleteSelected, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo playlist_selection_menu_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_ITEM, N_("Crop"),
+ NULL,
+ (gpointer) GtkPlaylistCrop, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Invert"),
+ NULL,
+ (gpointer) GtkPlaylistInvert, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_ITEM, N_("Select"),
+ NULL,
+ (gpointer) GtkPlaylistSelect, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo playlist_menubar_uiinfo[] =
+{
+ {
+ GNOME_APP_UI_SUBTREE, N_("Add"),
+ NULL,
+ playlist_add_menu_uiinfo, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_SUBTREE, N_("Delete"),
+ NULL,
+ playlist_delete_menu_uiinfo, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ {
+ GNOME_APP_UI_SUBTREE, N_("Selection"),
+ NULL,
+ playlist_selection_menu_uiinfo, NULL, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ 0, (GdkModifierType) 0, NULL
+ },
+ GNOMEUIINFO_END
+};
+
+GtkWidget*
+create_intf_playlist (void)
+{
+ GtkWidget *intf_playlist;
+ GtkWidget *playlist_vbox;
+ GtkWidget *playlist_scrolledwindow;
+ GtkWidget *playlist_viewport;
+ GtkWidget *playlist_frame;
+ GtkWidget *playlist_clist;
+ GtkWidget *playlist_label_url;
+ GtkWidget *playlist_label_duration;
+ GtkWidget *playlist_menubar;
+ GtkWidget *playlist_action;
+ GtkWidget *playlist_ok;
+ GtkWidget *playlist_cancel;
+
+ intf_playlist = gnome_dialog_new (_("Playlist"), NULL);
+ gtk_object_set_data (GTK_OBJECT (intf_playlist), "intf_playlist", intf_playlist);
+ gtk_window_set_default_size (GTK_WINDOW (intf_playlist), 400, 300);
+ gtk_window_set_policy (GTK_WINDOW (intf_playlist), TRUE, TRUE, FALSE);
+ gnome_dialog_close_hides (GNOME_DIALOG (intf_playlist), TRUE);
+
+ playlist_vbox = GNOME_DIALOG (intf_playlist)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_playlist), "playlist_vbox", playlist_vbox);
+ gtk_widget_show (playlist_vbox);
+
+ playlist_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_ref (playlist_scrolledwindow);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_scrolledwindow", playlist_scrolledwindow,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_scrolledwindow);
+ gtk_box_pack_start (GTK_BOX (playlist_vbox), playlist_scrolledwindow, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (playlist_scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ playlist_viewport = gtk_viewport_new (NULL, NULL);
+ gtk_widget_ref (playlist_viewport);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_viewport", playlist_viewport,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_viewport);
+ gtk_container_add (GTK_CONTAINER (playlist_scrolledwindow), playlist_viewport);
+
+ playlist_frame = gtk_frame_new (_("Playlist"));
+ gtk_widget_ref (playlist_frame);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_frame", playlist_frame,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_frame);
+ gtk_container_add (GTK_CONTAINER (playlist_viewport), playlist_frame);
+ gtk_container_set_border_width (GTK_CONTAINER (playlist_frame), 4);
+ gtk_frame_set_label_align (GTK_FRAME (playlist_frame), 0.05, 0.5);
+
+ playlist_clist = gtk_clist_new (2);
+ gtk_widget_ref (playlist_clist);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_clist", playlist_clist,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_clist);
+ gtk_container_add (GTK_CONTAINER (playlist_frame), playlist_clist);
+ gtk_clist_set_column_width (GTK_CLIST (playlist_clist), 0, 287);
+ gtk_clist_set_column_width (GTK_CLIST (playlist_clist), 1, 70);
+ gtk_clist_set_selection_mode (GTK_CLIST (playlist_clist), GTK_SELECTION_EXTENDED);
+ gtk_clist_column_titles_show (GTK_CLIST (playlist_clist));
+
+ playlist_label_url = gtk_label_new (_("Url"));
+ gtk_widget_ref (playlist_label_url);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_label_url", playlist_label_url,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_label_url);
+ gtk_clist_set_column_widget (GTK_CLIST (playlist_clist), 0, playlist_label_url);
+
+ playlist_label_duration = gtk_label_new (_("Duration"));
+ gtk_widget_ref (playlist_label_duration);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_label_duration", playlist_label_duration,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_label_duration);
+ gtk_clist_set_column_widget (GTK_CLIST (playlist_clist), 1, playlist_label_duration);
+
+ playlist_menubar = gtk_menu_bar_new ();
+ gtk_widget_ref (playlist_menubar);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_menubar", playlist_menubar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_menubar);
+ gtk_box_pack_start (GTK_BOX (playlist_vbox), playlist_menubar, FALSE, FALSE, 0);
+ gnome_app_fill_menu (GTK_MENU_SHELL (playlist_menubar), playlist_menubar_uiinfo,
+ NULL, FALSE, 0);
+
+ gtk_widget_ref (playlist_menubar_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add",
+ playlist_menubar_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_add_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_disc",
+ playlist_add_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_add_menu_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_file",
+ playlist_add_menu_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_add_menu_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_network",
+ playlist_add_menu_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_add_menu_uiinfo[3].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_url",
+ playlist_add_menu_uiinfo[3].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_menubar_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_delete",
+ playlist_menubar_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_delete_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_delete_all",
+ playlist_delete_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_delete_menu_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_delete_item",
+ playlist_delete_menu_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_menubar_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection",
+ playlist_menubar_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_selection_menu_uiinfo[0].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection_crop",
+ playlist_selection_menu_uiinfo[0].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_selection_menu_uiinfo[1].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection_invert",
+ playlist_selection_menu_uiinfo[1].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ gtk_widget_ref (playlist_selection_menu_uiinfo[2].widget);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection_select",
+ playlist_selection_menu_uiinfo[2].widget,
+ (GtkDestroyNotify) gtk_widget_unref);
+
+ playlist_action = GNOME_DIALOG (intf_playlist)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_playlist), "playlist_action", playlist_action);
+ gtk_widget_show (playlist_action);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (playlist_action), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (playlist_action), 8);
+ gtk_button_box_set_child_size (GTK_BUTTON_BOX (playlist_action), 100, 38);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_playlist), GNOME_STOCK_BUTTON_OK);
+ playlist_ok = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_playlist)->buttons)->data);
+ gtk_widget_ref (playlist_ok);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_ok", playlist_ok,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_ok);
+ GTK_WIDGET_SET_FLAGS (playlist_ok, GTK_CAN_DEFAULT);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_playlist), GNOME_STOCK_BUTTON_CANCEL);
+ playlist_cancel = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_playlist)->buttons)->data);
+ gtk_widget_ref (playlist_cancel);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_cancel", playlist_cancel,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_cancel);
+ GTK_WIDGET_SET_FLAGS (playlist_cancel, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect (GTK_OBJECT (intf_playlist), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_hide),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (intf_playlist), "delete_event",
+ GTK_SIGNAL_FUNC (gtk_widget_hide),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_clist), "event",
+ GTK_SIGNAL_FUNC (GtkPlaylistEvent),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_clist), "drag_data_received",
+ GTK_SIGNAL_FUNC (GtkPlaylistDragData),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_clist), "drag_motion",
+ GTK_SIGNAL_FUNC (GtkPlaylistDragMotion),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_cancel), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistCancel),
+ NULL);
+
+ return intf_playlist;
+}
+
+GtkWidget*
+create_intf_jump (void)
+{
+ GtkWidget *intf_jump;
+ GtkWidget *jump_vbox;
+ GtkWidget *jump_frame;
+ GtkWidget *jump_box;
+ GtkWidget *jump_label3;
+ GtkObject *jump_second_spinbutton_adj;
+ GtkWidget *jump_second_spinbutton;
+ GtkWidget *jump_label1;
+ GtkObject *jump_minute_spinbutton_adj;
+ GtkWidget *jump_minute_spinbutton;
+ GtkWidget *jump_label2;
+ GtkObject *jump_hour_spinbutton_adj;
+ GtkWidget *jump_hour_spinbutton;
+ GtkWidget *jump_action;
+ GtkWidget *jump_ok;
+ GtkWidget *jump_cancel;
+
+ intf_jump = gnome_dialog_new (NULL, NULL);
+ gtk_object_set_data (GTK_OBJECT (intf_jump), "intf_jump", intf_jump);
+ gtk_window_set_policy (GTK_WINDOW (intf_jump), FALSE, FALSE, FALSE);
+
+ jump_vbox = GNOME_DIALOG (intf_jump)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_jump), "jump_vbox", jump_vbox);
+ gtk_widget_show (jump_vbox);
+
+ jump_frame = gtk_frame_new (_("Jump to: "));
+ gtk_widget_ref (jump_frame);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_frame", jump_frame,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_frame);
+ gtk_box_pack_start (GTK_BOX (jump_vbox), jump_frame, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (jump_frame), 5);
+ gtk_frame_set_label_align (GTK_FRAME (jump_frame), 0.05, 0.5);
+
+ jump_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (jump_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_box", jump_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_box);
+ gtk_container_add (GTK_CONTAINER (jump_frame), jump_box);
+ gtk_container_set_border_width (GTK_CONTAINER (jump_box), 5);
+
+ jump_label3 = gtk_label_new (_("s."));
+ gtk_widget_ref (jump_label3);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_label3", jump_label3,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_label3);
+ gtk_box_pack_end (GTK_BOX (jump_box), jump_label3, FALSE, FALSE, 0);
+
+ jump_second_spinbutton_adj = gtk_adjustment_new (0, 0, 100, 1, 10, 10);
+ jump_second_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (jump_second_spinbutton_adj), 1, 0);
+ gtk_widget_ref (jump_second_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_second_spinbutton", jump_second_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_second_spinbutton);
+ gtk_box_pack_end (GTK_BOX (jump_box), jump_second_spinbutton, FALSE, FALSE, 5);
+
+ jump_label1 = gtk_label_new (_("m:"));
+ gtk_widget_ref (jump_label1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_label1", jump_label1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_label1);
+ gtk_box_pack_end (GTK_BOX (jump_box), jump_label1, FALSE, FALSE, 5);
+
+ jump_minute_spinbutton_adj = gtk_adjustment_new (0, 0, 59, 1, 10, 10);
+ jump_minute_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (jump_minute_spinbutton_adj), 1, 0);
+ gtk_widget_ref (jump_minute_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_minute_spinbutton", jump_minute_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_minute_spinbutton);
+ gtk_box_pack_end (GTK_BOX (jump_box), jump_minute_spinbutton, FALSE, FALSE, 5);
+
+ jump_label2 = gtk_label_new (_("h:"));
+ gtk_widget_ref (jump_label2);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_label2", jump_label2,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_label2);
+ gtk_box_pack_end (GTK_BOX (jump_box), jump_label2, FALSE, FALSE, 5);
+
+ jump_hour_spinbutton_adj = gtk_adjustment_new (0, 0, 10, 1, 10, 10);
+ jump_hour_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (jump_hour_spinbutton_adj), 1, 0);
+ gtk_widget_ref (jump_hour_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_hour_spinbutton", jump_hour_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_hour_spinbutton);
+ gtk_box_pack_end (GTK_BOX (jump_box), jump_hour_spinbutton, FALSE, FALSE, 5);
+
+ jump_action = GNOME_DIALOG (intf_jump)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_jump), "jump_action", jump_action);
+ gtk_widget_show (jump_action);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (jump_action), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (jump_action), 8);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_jump), GNOME_STOCK_BUTTON_OK);
+ jump_ok = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_jump)->buttons)->data);
+ gtk_widget_ref (jump_ok);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_ok", jump_ok,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_ok);
+ GTK_WIDGET_SET_FLAGS (jump_ok, GTK_CAN_DEFAULT);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_jump), GNOME_STOCK_BUTTON_CANCEL);
+ jump_cancel = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_jump)->buttons)->data);
+ gtk_widget_ref (jump_cancel);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_cancel", jump_cancel,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_cancel);
+ GTK_WIDGET_SET_FLAGS (jump_cancel, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect (GTK_OBJECT (jump_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkJumpOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (jump_cancel), "clicked",
+ GTK_SIGNAL_FUNC (GtkJumpCancel),
+ NULL);
+
+ return intf_jump;
+}
+
+GtkWidget*
+create_intf_messages (void)
+{
+ GtkWidget *intf_messages;
+ GtkWidget *dialog_vbox6;
+ GtkWidget *scrolledwindow1;
+ GtkWidget *messages_textbox;
+ GtkWidget *dialog_action_area6;
+ GtkWidget *messages_ok;
+
+ intf_messages = gnome_dialog_new (_("Messages"), NULL);
+ gtk_object_set_data (GTK_OBJECT (intf_messages), "intf_messages", intf_messages);
+ gtk_window_set_policy (GTK_WINDOW (intf_messages), TRUE, TRUE, FALSE);
+ gnome_dialog_close_hides (GNOME_DIALOG (intf_messages), TRUE);
+
+ dialog_vbox6 = GNOME_DIALOG (intf_messages)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_messages), "dialog_vbox6", dialog_vbox6);
+ gtk_widget_show (dialog_vbox6);
+
+ scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_ref (scrolledwindow1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_messages), "scrolledwindow1", scrolledwindow1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (scrolledwindow1);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox6), scrolledwindow1, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+
+ messages_textbox = gtk_text_new (NULL, NULL);
+ gtk_widget_ref (messages_textbox);
+ gtk_object_set_data_full (GTK_OBJECT (intf_messages), "messages_textbox", messages_textbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (messages_textbox);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow1), messages_textbox);
+ gtk_widget_set_usize (messages_textbox, 600, 400);
+
+ dialog_action_area6 = GNOME_DIALOG (intf_messages)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_messages), "dialog_action_area6", dialog_action_area6);
+ gtk_widget_show (dialog_action_area6);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area6), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (dialog_action_area6), 8);
+
+ gnome_dialog_append_button (GNOME_DIALOG (intf_messages), GNOME_STOCK_BUTTON_OK);
+ messages_ok = GTK_WIDGET (g_list_last (GNOME_DIALOG (intf_messages)->buttons)->data);
+ gtk_widget_ref (messages_ok);
+ gtk_object_set_data_full (GTK_OBJECT (intf_messages), "messages_ok", messages_ok,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (messages_ok);
+ GTK_WIDGET_SET_FLAGS (messages_ok, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect (GTK_OBJECT (intf_messages), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_hide),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (intf_messages), "delete_event",
+ GTK_SIGNAL_FUNC (gtk_widget_hide),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (messages_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkMessagesOk),
+ NULL);
+
+ return intf_messages;
+}
+
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+GtkWidget* create_intf_window (void);
+GtkWidget* create_intf_popup (void);
+GtkWidget* create_intf_about (void);
+GtkWidget* create_intf_open (void);
+GtkWidget* create_intf_file (void);
+GtkWidget* create_intf_modules (void);
+GtkWidget* create_intf_playlist (void);
+GtkWidget* create_intf_jump (void);
+GtkWidget* create_intf_messages (void);
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gnome.h>
+
+#include "gnome_support.h"
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget* create_dummy_pixmap (GtkWidget *widget,
+ gboolean gnome_pixmap);
+
+GtkWidget*
+lookup_widget (GtkWidget *widget,
+ const gchar *widget_name)
+{
+ GtkWidget *parent, *found_widget;
+
+ for (;;)
+ {
+ if (GTK_IS_MENU (widget))
+ parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
+ else
+ parent = widget->parent;
+ if (parent == NULL)
+ break;
+ widget = parent;
+ }
+
+ found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
+ widget_name);
+ if (!found_widget)
+ g_warning ("Widget not found: %s", widget_name);
+ return found_widget;
+}
+
+/* This is a dummy pixmap we use when a pixmap can't be found. */
+static char *dummy_pixmap_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"1 1 1 1",
+" c None",
+/* pixels */
+" ",
+" "
+};
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget*
+create_dummy_pixmap (GtkWidget *widget,
+ gboolean gnome_pixmap)
+{
+ GdkColormap *colormap;
+ GdkPixmap *gdkpixmap;
+ GdkBitmap *mask;
+ GtkWidget *pixmap;
+
+ if (gnome_pixmap)
+ {
+ return gnome_pixmap_new_from_xpm_d (dummy_pixmap_xpm);
+ }
+
+ colormap = gtk_widget_get_colormap (widget);
+ gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
+ NULL, dummy_pixmap_xpm);
+ if (gdkpixmap == NULL)
+ g_error ("Couldn't create replacement pixmap.");
+ pixmap = gtk_pixmap_new (gdkpixmap, mask);
+ gdk_pixmap_unref (gdkpixmap);
+ gdk_bitmap_unref (mask);
+ return pixmap;
+}
+
+/* This is an internally used function to create pixmaps. */
+GtkWidget*
+create_pixmap (GtkWidget *widget,
+ const gchar *filename,
+ gboolean gnome_pixmap)
+{
+ GtkWidget *pixmap;
+ GdkColormap *colormap;
+ GdkPixmap *gdkpixmap;
+ GdkBitmap *mask;
+ gchar *pathname;
+
+ if (!filename || !filename[0])
+ return create_dummy_pixmap (widget, gnome_pixmap);
+
+ pathname = gnome_pixmap_file (filename);
+ if (!pathname)
+ {
+ g_warning (_("Couldn't find pixmap file: %s"), filename);
+ return create_dummy_pixmap (widget, gnome_pixmap);
+ }
+
+ if (gnome_pixmap)
+ {
+ pixmap = gnome_pixmap_new_from_file (pathname);
+ g_free (pathname);
+ return pixmap;
+ }
+
+ colormap = gtk_widget_get_colormap (widget);
+ gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,
+ NULL, pathname);
+ if (gdkpixmap == NULL)
+ {
+ g_warning (_("Couldn't create pixmap from file: %s"), pathname);
+ g_free (pathname);
+ return create_dummy_pixmap (widget, gnome_pixmap);
+ }
+ g_free (pathname);
+
+ pixmap = gtk_pixmap_new (gdkpixmap, mask);
+ gdk_pixmap_unref (gdkpixmap);
+ gdk_bitmap_unref (mask);
+ return pixmap;
+}
+
+/* This is an internally used function to create imlib images. */
+GdkImlibImage*
+create_image (const gchar *filename)
+{
+ GdkImlibImage *image;
+ gchar *pathname;
+
+ pathname = gnome_pixmap_file (filename);
+ if (!pathname)
+ {
+ g_warning (_("Couldn't find pixmap file: %s"), filename);
+ return NULL;
+ }
+
+ image = gdk_imlib_load_image (pathname);
+ g_free (pathname);
+ return image;
+}
+
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#include <gnome.h>
+
+/*
+ * Public Functions.
+ */
+
+/*
+ * This function returns a widget in a component created by Glade.
+ * Call it with the toplevel widget in the component (i.e. a window/dialog),
+ * or alternatively any widget in the component, and the name of the widget
+ * you want returned.
+ */
+GtkWidget* lookup_widget (GtkWidget *widget,
+ const gchar *widget_name);
+
+/* get_widget() is deprecated. Use lookup_widget instead. */
+#define get_widget lookup_widget
+
+
+/*
+ * Private Functions.
+ */
+
+/* This is used to create the pixmaps in the interface. */
+GtkWidget* create_pixmap (GtkWidget *widget,
+ const gchar *filename,
+ gboolean gnome_pixmap);
+
+GdkImlibImage* create_image (const gchar *filename);
+
--- /dev/null
+/*****************************************************************************
+ * gtk.c : Gtk+ plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: gtk.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <gtk/gtk.h>
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "menu.h"
+#include "display.h"
+#include "common.h"
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static void Run ( intf_thread_t * );
+static gint Manage ( gpointer );
+
+/*****************************************************************************
+ * Local variables (mutex-protected).
+ *****************************************************************************/
+static void ** pp_global_data = NULL;
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define TOOLTIPS_TEXT N_("show tooltips")
+#define TOOLTIPS_LONGTEXT N_("Show tooltips for configuration options.")
+
+#define PREFS_MAXH_TEXT N_("maximum height for the configuration windows")
+#define PREFS_MAXH_LONGTEXT N_( \
+ "You can set the maximum height that the configuration windows in the " \
+ "preferences menu will occupy.")
+
+vlc_module_begin();
+#ifdef WIN32
+ int i = 90;
+#else
+ int i = getenv( "DISPLAY" ) == NULL ? 10 : 90;
+#endif
+ pp_global_data = p_module->p_vlc->pp_global_data;
+
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_bool( "gtk-tooltips", 1, GtkHideTooltips,
+ TOOLTIPS_TEXT, TOOLTIPS_LONGTEXT );
+ add_integer( "gtk-prefs-maxh", 480, NULL,
+ PREFS_MAXH_TEXT, PREFS_MAXH_LONGTEXT );
+
+ set_description( _("Gtk+ interface module") );
+ set_capability( "interface", i );
+ set_callbacks( Open, Close );
+ set_program( "gvlc" );
+vlc_module_end();
+
+/*****************************************************************************
+ * g_atexit: kludge to avoid the Gtk+ thread to segfault at exit
+ *****************************************************************************
+ * gtk_init() makes several calls to g_atexit() which calls atexit() to
+ * register tidying callbacks to be called at program exit. Since the Gtk+
+ * plugin is likely to be unloaded at program exit, we have to export this
+ * symbol to intercept the g_atexit() calls. Talk about crude hack.
+ *****************************************************************************/
+void g_atexit( GVoidFunc func )
+{
+ intf_thread_t *p_intf;
+
+ int i_dummy;
+
+ if( pp_global_data == NULL )
+ {
+ atexit( func );
+ return;
+ }
+
+ p_intf = (intf_thread_t *)*pp_global_data;
+ if( p_intf == NULL )
+ {
+ return;
+ }
+
+ for( i_dummy = 0;
+ i_dummy < MAX_ATEXIT && p_intf->p_sys->pf_callback[i_dummy] != NULL;
+ i_dummy++ )
+ {
+ ;
+ }
+
+ if( i_dummy >= MAX_ATEXIT - 1 )
+ {
+ msg_Err( p_intf, "too many atexit() callbacks to register" );
+ return;
+ }
+
+ p_intf->p_sys->pf_callback[i_dummy] = func;
+ p_intf->p_sys->pf_callback[i_dummy + 1] = NULL;
+}
+
+/*****************************************************************************
+ * Open: initialize and create window
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return( 1 );
+ }
+
+ p_intf->pf_run = Run;
+
+ p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
+
+ /* Initialize Gtk+ thread */
+ p_intf->p_sys->b_playing = 0;
+ p_intf->p_sys->b_popup_changed = 0;
+ p_intf->p_sys->b_window_changed = 0;
+ p_intf->p_sys->b_playlist_changed = 0;
+
+ p_intf->p_sys->p_input = NULL;
+ p_intf->p_sys->i_playing = -1;
+ p_intf->p_sys->b_slider_free = 1;
+
+ p_intf->p_sys->pf_callback[0] = NULL;
+
+ p_intf->p_sys->i_part = 0;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Close: destroy interface window
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: Gtk+ thread
+ *****************************************************************************
+ * this part of the interface is in a separate thread so that we can call
+ * gtk_main() from within it without annoying the rest of the program.
+ * XXX: the approach may look kludgy, and probably is, but I could not find
+ * a better way to dynamically load a Gtk+ interface at runtime.
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ /* gtk_init needs to know the command line. We don't care, so we
+ * give it an empty one */
+ char *p_args[] = { "" };
+ char **pp_args = p_args;
+ int i_args = 1;
+ int i_dummy;
+
+ /* The data types we are allowed to receive */
+ static GtkTargetEntry target_table[] =
+ {
+ { "STRING", 0, DROP_ACCEPT_STRING },
+ { "text/uri-list", 0, DROP_ACCEPT_TEXT_URI_LIST },
+ { "text/plain", 0, DROP_ACCEPT_TEXT_PLAIN }
+ };
+
+ /* Initialize Gtk+ */
+
+ /* gtk_init will register stuff with g_atexit, so we need to take
+ * the global lock if we want to be able to intercept the calls */
+ vlc_mutex_lock( p_intf->p_vlc->p_global_lock );
+ *p_intf->p_vlc->pp_global_data = p_intf;
+ gtk_init( &i_args, &pp_args );
+ vlc_mutex_unlock( p_intf->p_vlc->p_global_lock );
+
+ /* Create some useful widgets that will certainly be used */
+ p_intf->p_sys->p_window = create_intf_window();
+ p_intf->p_sys->p_popup = create_intf_popup();
+ p_intf->p_sys->p_playwin = create_intf_playlist();
+ p_intf->p_sys->p_messages = create_intf_messages();
+ p_intf->p_sys->p_tooltips = gtk_tooltips_new();
+
+ /* Set the title of the main window */
+ gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
+ VOUT_TITLE " (Gtk+ interface)");
+
+ /* Accept file drops on the main window */
+ gtk_drag_dest_set( GTK_WIDGET( p_intf->p_sys->p_window ),
+ GTK_DEST_DEFAULT_ALL, target_table,
+ 1, GDK_ACTION_COPY );
+
+ /* Accept file drops on the playlist window */
+ gtk_drag_dest_set( GTK_WIDGET( lookup_widget( p_intf->p_sys->p_playwin,
+ "playlist_clist") ),
+ GTK_DEST_DEFAULT_ALL, target_table,
+ 1, GDK_ACTION_COPY );
+
+ /* Get the slider object */
+ p_intf->p_sys->p_slider_frame = GTK_FRAME( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_window ), "slider_frame" ) );
+
+ /* Configure the log window */
+ p_intf->p_sys->p_messages_text = GTK_TEXT( gtk_object_get_data(
+ GTK_OBJECT(p_intf->p_sys->p_messages ), "messages_textbox" ) );
+ gtk_text_set_line_wrap( p_intf->p_sys->p_messages_text, TRUE);
+ gtk_text_set_word_wrap( p_intf->p_sys->p_messages_text, FALSE);
+
+ /* Get the interface labels */
+#define P_LABEL( name ) GTK_LABEL( gtk_object_get_data( \
+ GTK_OBJECT( p_intf->p_sys->p_window ), name ) )
+ p_intf->p_sys->p_label_title = P_LABEL( "title_label" );
+ p_intf->p_sys->p_label_chapter = P_LABEL( "chapter_label" );
+#undef P_LABEL
+
+ /* Connect the date display to the slider */
+#define P_SLIDER GTK_RANGE( gtk_object_get_data( \
+ GTK_OBJECT( p_intf->p_sys->p_window ), "slider" ) )
+ p_intf->p_sys->p_adj = gtk_range_get_adjustment( P_SLIDER );
+
+ gtk_signal_connect ( GTK_OBJECT( p_intf->p_sys->p_adj ), "value_changed",
+ GTK_SIGNAL_FUNC( GtkDisplayDate ), NULL );
+ p_intf->p_sys->f_adj_oldvalue = 0;
+#undef P_SLIDER
+
+ /* We don't create these ones yet because we perhaps won't need them */
+ p_intf->p_sys->p_about = NULL;
+ p_intf->p_sys->p_modules = NULL;
+ p_intf->p_sys->p_open = NULL;
+ p_intf->p_sys->p_jump = NULL;
+
+ /* Hide tooltips if the option is set */
+ if( !config_GetInt( p_intf, "gtk-tooltips" ) )
+ {
+ gtk_tooltips_disable( p_intf->p_sys->p_tooltips );
+ }
+
+ /* Store p_intf to keep an eye on it */
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_popup),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_playwin ),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_messages ),
+ "p_intf", p_intf );
+
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_adj),
+ "p_intf", p_intf );
+
+ /* Show the control window */
+ gtk_widget_show( p_intf->p_sys->p_window );
+
+ /* Sleep to avoid using all CPU - since some interfaces needs to access
+ * keyboard events, a 100ms delay is a good compromise */
+ i_dummy = gtk_timeout_add( INTF_IDLE_SLEEP / 1000, Manage, p_intf );
+
+ /* Enter Gtk mode */
+ gtk_main();
+
+ /* Remove the timeout */
+ gtk_timeout_remove( i_dummy );
+
+ /* Destroy the Tooltips structure */
+ gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_tooltips) );
+
+ /* Launch stored callbacks */
+ for( i_dummy = 0;
+ i_dummy < MAX_ATEXIT && p_intf->p_sys->pf_callback[i_dummy] != NULL;
+ i_dummy++ )
+ {
+ p_intf->p_sys->pf_callback[i_dummy]();
+ }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * Manage: manage main thread messages
+ *****************************************************************************
+ * In this function, called approx. 10 times a second, we check what the
+ * main program wanted to tell us.
+ *****************************************************************************/
+static gint Manage( gpointer p_data )
+{
+#define p_intf ((intf_thread_t *)p_data)
+ int i_start, i_stop;
+
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ /* If the "display popup" flag has changed */
+ if( p_intf->b_menu_change )
+ {
+ if( !GTK_IS_WIDGET( p_intf->p_sys->p_popup ) )
+ {
+ p_intf->p_sys->p_popup = create_intf_popup();
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_popup ),
+ "p_intf", p_intf );
+ }
+ gtk_menu_popup( GTK_MENU( p_intf->p_sys->p_popup ),
+ NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME );
+ p_intf->b_menu_change = 0;
+ }
+
+ /* Update the log window */
+ vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+ i_stop = *p_intf->p_sys->p_sub->pi_stop;
+ vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+
+ if( p_intf->p_sys->p_sub->i_start != i_stop )
+ {
+ static GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
+ static GdkColor gray = { 0, 0xaaaa, 0xaaaa, 0xaaaa };
+ static GdkColor yellow = { 0, 0xffff, 0xffff, 0x6666 };
+ static GdkColor red = { 0, 0xffff, 0x6666, 0x6666 };
+
+ static const char * ppsz_type[4] = { ": ", " error: ", " warning: ",
+ " debug: " };
+ static GdkColor * pp_color[4] = { &white, &red, &yellow, &gray };
+
+ for( i_start = p_intf->p_sys->p_sub->i_start;
+ i_start != i_stop;
+ i_start = (i_start+1) % VLC_MSG_QSIZE )
+ {
+ /* Append all messages to log window */
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+ NULL, p_intf->p_sys->p_sub->p_msg[i_start].psz_module, -1 );
+
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+ NULL, ppsz_type[p_intf->p_sys->p_sub->p_msg[i_start].i_type],
+ -1 );
+
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL,
+ pp_color[p_intf->p_sys->p_sub->p_msg[i_start].i_type], NULL,
+ p_intf->p_sys->p_sub->p_msg[i_start].psz_msg, -1 );
+
+ gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+ NULL, "\n", -1 );
+ }
+
+ vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+ p_intf->p_sys->p_sub->i_start = i_start;
+ vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+
+ gtk_text_set_point( p_intf->p_sys->p_messages_text,
+ gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
+ }
+
+ /* Update the playlist */
+ GtkPlayListManage( p_data );
+
+ /* Update the input */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ if( p_intf->p_sys->p_input )
+ {
+ input_thread_t *p_input = p_intf->p_sys->p_input;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ if( !p_input->b_die )
+ {
+ /* New input or stream map change */
+ if( p_input->stream.b_changed )
+ {
+ GtkModeManage( p_intf );
+ GtkSetupMenus( p_intf );
+ p_intf->p_sys->b_playing = 1;
+ }
+
+ /* Manage the slider */
+ if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )
+ {
+ float newvalue = p_intf->p_sys->p_adj->value;
+
+#define p_area p_input->stream.p_selected_area
+ /* If the user hasn't touched the slider since the last time,
+ * then the input can safely change it */
+ if( newvalue == p_intf->p_sys->f_adj_oldvalue )
+ {
+ /* Update the value */
+ p_intf->p_sys->p_adj->value =
+ p_intf->p_sys->f_adj_oldvalue =
+ ( 100. * p_area->i_tell ) / p_area->i_size;
+
+ gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
+ "value_changed" );
+ }
+ /* Otherwise, send message to the input if the user has
+ * finished dragging the slider */
+ else if( p_intf->p_sys->b_slider_free )
+ {
+ off_t i_seek = ( newvalue * p_area->i_size ) / 100;
+
+ /* release the lock to be able to seek */
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ input_Seek( p_input, i_seek, INPUT_SEEK_SET );
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ /* Update the old value */
+ p_intf->p_sys->f_adj_oldvalue = newvalue;
+ }
+#undef p_area
+ }
+
+ if( p_intf->p_sys->i_part !=
+ p_input->stream.p_selected_area->i_part )
+ {
+ p_intf->p_sys->b_chapter_update = 1;
+ GtkSetupMenus( p_intf );
+ }
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+ else if( p_intf->p_sys->b_playing && !p_intf->b_die )
+ {
+ GtkModeManage( p_intf );
+ p_intf->p_sys->b_playing = 0;
+ }
+
+ if( p_intf->b_die )
+ {
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ /* Prepare to die, young Skywalker */
+ gtk_main_quit();
+
+ /* Just in case */
+ return( FALSE );
+ }
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return( TRUE );
+
+#undef p_intf
+}
--- /dev/null
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>VideoLAN Client</name>
+ <program_name>vlc</program_name>
+ <directory></directory>
+ <source_directory></source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>False</gnome_support>
+ <gettext_support>True</gettext_support>
+ <output_main_file>False</output_main_file>
+ <output_build_files>False</output_build_files>
+ <main_source_file>gtk_interface.c</main_source_file>
+ <main_header_file>gtk_interface.h</main_header_file>
+ <handler_source_file>gtk_callbacks.c</handler_source_file>
+ <handler_header_file>gtk_callbacks.h</handler_header_file>
+ <support_source_file>gtk_support.c</support_source_file>
+ <support_header_file>gtk_support.h</support_header_file>
+</project>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>intf_window</name>
+ <signal>
+ <name>drag_data_received</name>
+ <handler>GtkWindowDrag</handler>
+ <last_modification_time>Tue, 09 Jul 2002 09:09:48 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>delete_event</name>
+ <handler>GtkWindowDelete</handler>
+ <last_modification_time>Tue, 09 Jul 2002 09:09:53 GMT</last_modification_time>
+ </signal>
+ <title>VideoLAN Client</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>True</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>True</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDock:contents</child_name>
+ <name>window_vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHandleBox</class>
+ <name>menubar_handlebox</name>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+ <handle_position>GTK_POS_LEFT</handle_position>
+ <snap_edge>GTK_POS_TOP</snap_edge>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkMenuBar</class>
+ <name>menubar</name>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_file</name>
+ <label>_File</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_file_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_open</name>
+ <tooltip>Open a File</tooltip>
+ <accelerator>
+ <modifiers>0</modifiers>
+ <key>GDK_F3</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:27:36 GMT</last_modification_time>
+ </signal>
+ <label>_Open File...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_disc</name>
+ <tooltip>Open a DVD or VCD</tooltip>
+ <accelerator>
+ <modifiers>0</modifiers>
+ <key>GDK_F4</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:27:47 GMT</last_modification_time>
+ </signal>
+ <label>Open _Disc...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_network</name>
+ <tooltip>Select a Network Stream</tooltip>
+ <accelerator>
+ <modifiers>0</modifiers>
+ <key>GDK_F5</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:28:06 GMT</last_modification_time>
+ </signal>
+ <label>_Network Stream...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator4</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_eject</name>
+ <tooltip>Eject disc</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscEject</handler>
+ <last_modification_time>Fri, 21 Dec 2001 12:51:34 GMT</last_modification_time>
+ </signal>
+ <label>_Eject Disc</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator14</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_close</name>
+ <tooltip>Close the window</tooltip>
+ <accelerator>
+ <modifiers>GDK_CONTROL_MASK</modifiers>
+ <key>GDK_W</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>GtkClose</handler>
+ <last_modification_time>Mon, 15 Jul 2002 08:55:26 GMT</last_modification_time>
+ </signal>
+ <label>_Close</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_exit</name>
+ <tooltip>Exit the program</tooltip>
+ <accelerator>
+ <modifiers>GDK_CONTROL_MASK</modifiers>
+ <key>GDK_Q</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>GtkExit</handler>
+ <last_modification_time>Mon, 14 May 2001 21:28:20 GMT</last_modification_time>
+ </signal>
+ <label>E_xit</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_view</name>
+ <label>_View</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_view_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_interface_hide</name>
+ <tooltip>Hide the main interface window</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkWindowToggle</handler>
+ <last_modification_time>Mon, 14 May 2001 21:32:49 GMT</last_modification_time>
+ </signal>
+ <label>_Hide interface</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_fullscreen</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFullscreen</handler>
+ <last_modification_time>Mon, 14 May 2001 21:29:21 GMT</last_modification_time>
+ </signal>
+ <label>_Fullscreen</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator13</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_program</name>
+ <sensitive>False</sensitive>
+ <tooltip>Choose the program</tooltip>
+ <label>Progr_am</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_title</name>
+ <sensitive>False</sensitive>
+ <tooltip>Navigate through the stream</tooltip>
+ <label>_Title</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_chapter</name>
+ <sensitive>False</sensitive>
+ <label>_Chapter</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator11</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_playlist</name>
+ <tooltip>Open the playlist window</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:29:34 GMT</last_modification_time>
+ </signal>
+ <label>_Playlist...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_modules</name>
+ <sensitive>False</sensitive>
+ <tooltip>Open the module manager</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkModulesShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:29:44 GMT</last_modification_time>
+ </signal>
+ <label>_Modules...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_messages</name>
+ <tooltip>Open the messages window</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkMessagesShow</handler>
+ <last_modification_time>Tue, 19 Feb 2002 02:03:47 GMT</last_modification_time>
+ </signal>
+ <label>Messages...</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_settings</name>
+ <label>_Settings</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_settings_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_audio</name>
+ <sensitive>False</sensitive>
+ <tooltip>Select audio channel</tooltip>
+ <label>A_udio</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_subpictures</name>
+ <sensitive>False</sensitive>
+ <tooltip>Select subtitles channel</tooltip>
+ <label>_Subtitles</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator8</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_preferences</name>
+ <tooltip>Configure the application</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPreferencesShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:30:02 GMT</last_modification_time>
+ </signal>
+ <label>_Preferences...</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_help</name>
+ <label>_Help</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>menubar_help_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>menubar_about</name>
+ <tooltip>About this application</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkAboutShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:30:15 GMT</last_modification_time>
+ </signal>
+ <label>_About...</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHandleBox</class>
+ <name>toolbar_handlebox</name>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+ <handle_position>GTK_POS_LEFT</handle_position>
+ <snap_edge>GTK_POS_TOP</snap_edge>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkToolbar</class>
+ <name>toolbar</name>
+ <border_width>1</border_width>
+ <orientation>GTK_ORIENTATION_HORIZONTAL</orientation>
+ <type>GTK_TOOLBAR_BOTH</type>
+ <space_size>16</space_size>
+ <space_style>GTK_TOOLBAR_SPACE_LINE</space_style>
+ <relief>GTK_RELIEF_NONE</relief>
+ <tooltips>True</tooltips>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_open</name>
+ <tooltip>Open a File</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Mon, 08 Jul 2002 16:14:58 GMT</last_modification_time>
+ </signal>
+ <label>File</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_disc</name>
+ <tooltip>Open a DVD or VCD</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Sun, 13 May 2001 15:10:30 GMT</last_modification_time>
+ </signal>
+ <label>Disc</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_network</name>
+ <tooltip>Select a Network Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Sun, 13 May 2001 15:10:37 GMT</last_modification_time>
+ </signal>
+ <label>Net</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_sat</name>
+ <tooltip>Open a Satellite Card</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkSatOpenShow</handler>
+ <last_modification_time>Sun, 24 Mar 2002 15:08:57 GMT</last_modification_time>
+ </signal>
+ <label>Sat</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_back</name>
+ <sensitive>False</sensitive>
+ <tooltip>Go Backward</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlBack</handler>
+ <last_modification_time>Sun, 13 May 2001 15:10:47 GMT</last_modification_time>
+ </signal>
+ <label>Back</label>
+ <child>
+ <new_group>True</new_group>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_stop</name>
+ <tooltip>Stop Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlStop</handler>
+ <last_modification_time>Sun, 13 May 2001 15:10:57 GMT</last_modification_time>
+ </signal>
+ <label>Stop</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_eject</name>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkDiscEject</handler>
+ <last_modification_time>Fri, 21 Dec 2001 15:33:26 GMT</last_modification_time>
+ </signal>
+ <label>Eject</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_play</name>
+ <tooltip>Play Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlPlay</handler>
+ <last_modification_time>Sun, 13 May 2001 15:11:06 GMT</last_modification_time>
+ </signal>
+ <label>Play</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_pause</name>
+ <sensitive>False</sensitive>
+ <tooltip>Pause Stream</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlPause</handler>
+ <last_modification_time>Sun, 13 May 2001 15:11:13 GMT</last_modification_time>
+ </signal>
+ <label>Pause</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_slow</name>
+ <sensitive>False</sensitive>
+ <tooltip>Play Slower</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlSlow</handler>
+ <last_modification_time>Sun, 13 May 2001 15:11:20 GMT</last_modification_time>
+ </signal>
+ <label>Slow</label>
+ <child>
+ <new_group>True</new_group>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_fast</name>
+ <sensitive>False</sensitive>
+ <tooltip>Play Faster</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkControlFast</handler>
+ <last_modification_time>Sun, 13 May 2001 15:11:31 GMT</last_modification_time>
+ </signal>
+ <label>Fast</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_playlist</name>
+ <tooltip>Open Playlist</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistShow</handler>
+ <last_modification_time>Sun, 13 May 2001 15:11:38 GMT</last_modification_time>
+ </signal>
+ <label>Playlist</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_prev</name>
+ <tooltip>Previous File</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistPrev</handler>
+ <last_modification_time>Sun, 13 May 2001 15:11:45 GMT</last_modification_time>
+ </signal>
+ <label>Prev</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>Toolbar:button</child_name>
+ <name>toolbar_next</name>
+ <tooltip>Next File</tooltip>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistNext</handler>
+ <last_modification_time>Sun, 13 May 2001 15:11:58 GMT</last_modification_time>
+ </signal>
+ <label>Next</label>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>slider_frame</name>
+ <visible>False</visible>
+ <label>-:--:--</label>
+ <label_xalign>0.05</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHScale</class>
+ <name>slider</name>
+ <width>500</width>
+ <height>15</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_release_event</name>
+ <handler>GtkSliderRelease</handler>
+ <last_modification_time>Sun, 13 May 2001 14:40:22 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>button_press_event</name>
+ <handler>GtkSliderPress</handler>
+ <last_modification_time>Sun, 13 May 2001 14:40:38 GMT</last_modification_time>
+ </signal>
+ <draw_value>False</draw_value>
+ <value_pos>GTK_POS_TOP</value_pos>
+ <digits>3</digits>
+ <policy>GTK_UPDATE_CONTINUOUS</policy>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <step>1</step>
+ <page>6.25</page>
+ <page_size>0</page_size>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>file_box</name>
+ <width>500</width>
+ <height>24</height>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label_status</name>
+ <label></label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>dvd_box</name>
+ <width>500</width>
+ <height>24</height>
+ <visible>False</visible>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>dvd_label</name>
+ <label>Disc</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>title_box</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>title</name>
+ <label>Title:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>title_label</name>
+ <label>--</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>title_prev_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkTitlePrev</handler>
+ <last_modification_time>Sun, 13 May 2001 14:41:41 GMT</last_modification_time>
+ </signal>
+ <label>Prev</label>
+ <relief>GTK_RELIEF_NONE</relief>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>title_next_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkTitleNext</handler>
+ <last_modification_time>Sun, 13 May 2001 14:42:00 GMT</last_modification_time>
+ </signal>
+ <label>Next</label>
+ <relief>GTK_RELIEF_NONE</relief>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVSeparator</class>
+ <name>dvd_separator</name>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>chapter_box</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>chapter</name>
+ <label>Chapter:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>chapter_label</name>
+ <label>---</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>chapter_prev_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkChapterPrev</handler>
+ <last_modification_time>Sun, 13 May 2001 14:42:25 GMT</last_modification_time>
+ </signal>
+ <label>Prev</label>
+ <relief>GTK_RELIEF_NONE</relief>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>chapter_next_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkChapterNext</handler>
+ <last_modification_time>Sun, 13 May 2001 14:42:42 GMT</last_modification_time>
+ </signal>
+ <label>Next</label>
+ <relief>GTK_RELIEF_NONE</relief>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>network_box</name>
+ <width>500</width>
+ <height>24</height>
+ <visible>False</visible>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_address_label</name>
+ <label>No server</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>network_channel_box</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>channel_label</name>
+ <label>Channel:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_channel_spinbutton</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkJoin</handler>
+ <last_modification_time>Wed, 30 May 2001 02:48:10 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>network_channel_go_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkChannelGo</handler>
+ <last_modification_time>Wed, 30 May 2001 02:49:18 GMT</last_modification_time>
+ </signal>
+ <label>Go!</label>
+ <relief>GTK_RELIEF_NONE</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkStatusbar</class>
+ <name>intf_statusbar</name>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkMenu</class>
+ <name>intf_popup</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_play</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlPlay</handler>
+ <last_modification_time>Tue, 15 May 2001 13:53:43 GMT</last_modification_time>
+ </signal>
+ <label>_Play</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_pause</name>
+ <sensitive>False</sensitive>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlPause</handler>
+ <last_modification_time>Tue, 15 May 2001 13:53:37 GMT</last_modification_time>
+ </signal>
+ <label>Pause</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_stop</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlStop</handler>
+ <last_modification_time>Tue, 15 May 2001 13:53:29 GMT</last_modification_time>
+ </signal>
+ <label>Stop</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_back</name>
+ <sensitive>False</sensitive>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlBack</handler>
+ <last_modification_time>Tue, 15 May 2001 13:53:21 GMT</last_modification_time>
+ </signal>
+ <label>Back</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_slow</name>
+ <sensitive>False</sensitive>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlSlow</handler>
+ <last_modification_time>Tue, 15 May 2001 13:53:15 GMT</last_modification_time>
+ </signal>
+ <label>Slow</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_fast</name>
+ <sensitive>False</sensitive>
+ <signal>
+ <name>activate</name>
+ <handler>GtkControlFast</handler>
+ <last_modification_time>Tue, 15 May 2001 13:53:07 GMT</last_modification_time>
+ </signal>
+ <label>Fast</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator6</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_interface_toggle</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkWindowToggle</handler>
+ <last_modification_time>Tue, 15 May 2001 13:53:00 GMT</last_modification_time>
+ </signal>
+ <label>Toggle _Interface</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_fullscreen</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFullscreen</handler>
+ <last_modification_time>Tue, 15 May 2001 13:52:38 GMT</last_modification_time>
+ </signal>
+ <label>_Fullscreen</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator5</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_next</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistNext</handler>
+ <last_modification_time>Tue, 15 May 2001 13:52:31 GMT</last_modification_time>
+ </signal>
+ <label>Next</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_prev</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistPrev</handler>
+ <last_modification_time>Tue, 15 May 2001 13:52:23 GMT</last_modification_time>
+ </signal>
+ <label>Prev</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_jump</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkJumpShow</handler>
+ <last_modification_time>Tue, 15 May 2001 13:52:13 GMT</last_modification_time>
+ </signal>
+ <label>_Jump...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_program</name>
+ <sensitive>False</sensitive>
+ <label>Program</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_navigation</name>
+ <sensitive>False</sensitive>
+ <label>_Navigation</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_audio</name>
+ <sensitive>False</sensitive>
+ <label>_Audio</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_subpictures</name>
+ <sensitive>False</sensitive>
+ <label>_Subtitles</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_open</name>
+ <label>_File</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>popup_open_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_file</name>
+ <tooltip>Open a File</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:33:55 GMT</last_modification_time>
+ </signal>
+ <label>_Open File...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_disc</name>
+ <tooltip>Open a DVD or VCD</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:34:09 GMT</last_modification_time>
+ </signal>
+ <label>Open _Disc...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_network</name>
+ <tooltip>Select a Network Stream</tooltip>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:34:23 GMT</last_modification_time>
+ </signal>
+ <label>_Network Stream...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator12</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_about</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkAboutShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:34:54 GMT</last_modification_time>
+ </signal>
+ <label>_About...</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_playlist</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistShow</handler>
+ <last_modification_time>Tue, 15 May 2001 13:51:55 GMT</last_modification_time>
+ </signal>
+ <label>Playlist...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_preferences</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPreferencesShow</handler>
+ <last_modification_time>Tue, 15 May 2001 13:51:46 GMT</last_modification_time>
+ </signal>
+ <label>_Preferences...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>separator9</name>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>popup_exit</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkExit</handler>
+ <last_modification_time>Tue, 15 May 2001 13:52:03 GMT</last_modification_time>
+ </signal>
+ <label>E_xit</label>
+ <right_justify>False</right_justify>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkDialog</class>
+ <name>intf_about</name>
+ <border_width>5</border_width>
+ <title>About</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_CENTER</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox1</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area</name>
+ <border_width>10</border_width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>about_ok</name>
+ <can_default>True</can_default>
+ <has_default>True</has_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkAboutOk</handler>
+ <last_modification_time>Sun, 13 May 2001 14:47:20 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox3</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label14</name>
+ <label>VideoLAN Client</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>10</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label18</name>
+ <label>(C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 - the VideoLAN Team</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>5</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame1</name>
+ <label>Authors</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label16</name>
+ <label>the VideoLAN team <videolan@videolan.org>
+http://www.videolan.org/</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0</yalign>
+ <xpad>5</xpad>
+ <ypad>5</ypad>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label17</name>
+ <label>This is the VideoLAN client, a DVD and MPEG player. It can play MPEG and MPEG 2 files from a file or from a network source.</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>True</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>5</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkDialog</class>
+ <name>intf_open</name>
+ <border_width>5</border_width>
+ <title>Open Target</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox7</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area6</name>
+ <border_width>5</border_width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox18</name>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox19</name>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>open_ok</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkOpenOk</handler>
+ <last_modification_time>Mon, 08 Jul 2002 14:52:19 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>open_cancel</name>
+ <can_focus>True</can_focus>
+ <accelerator>
+ <modifiers>0</modifiers>
+ <key>GDK_Escape</key>
+ <signal>clicked</signal>
+ </accelerator>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkOpenCancel</handler>
+ <last_modification_time>Mon, 08 Jul 2002 14:52:36 GMT</last_modification_time>
+ </signal>
+ <label>Cancel</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>open_vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame10</name>
+ <label>Media Resource Locator (MRL)</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox21</name>
+ <border_width>5</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>5</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox22</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label34</name>
+ <label>Open Target:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>combo2</name>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>entry_open</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label36</name>
+ <label>Alternatively, you can build an MRL using one of the following predefined targets:</label>
+ <justify>GTK_JUSTIFY_LEFT</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>1</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkNotebook</class>
+ <name>open_notebook</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>switch_page</name>
+ <handler>GtkOpenNotebookChanged</handler>
+ <after>True</after>
+ <last_modification_time>Tue, 09 Jul 2002 14:01:19 GMT</last_modification_time>
+ </signal>
+ <show_tabs>True</show_tabs>
+ <show_border>True</show_border>
+ <tab_pos>GTK_POS_TOP</tab_pos>
+ <scrollable>False</scrollable>
+ <tab_hborder>2</tab_hborder>
+ <tab_vborder>2</tab_vborder>
+ <popup_enable>False</popup_enable>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox20</name>
+ <border_width>5</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>5</spacing>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>combo1</name>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>entry_file</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:22:33 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox13</name>
+ <homogeneous>True</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>open_browse</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileShow</handler>
+ <last_modification_time>Wed, 10 Jul 2002 11:37:05 GMT</last_modification_time>
+ </signal>
+ <label>Browse...</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_file</name>
+ <label>File</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table5</name>
+ <border_width>5</border_width>
+ <rows>4</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>5</row_spacing>
+ <column_spacing>5</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label21</name>
+ <label>Title</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label20</name>
+ <label>Chapter</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>disc_chapter</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:45:38 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1</value>
+ <lower>1</lower>
+ <upper>65536</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label35</name>
+ <label>Disc type</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox24</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>disc_dvd</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkDiscOpenDvd</handler>
+ <last_modification_time>Sun, 13 May 2001 14:48:29 GMT</last_modification_time>
+ </signal>
+ <label>DVD</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>disc</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>disc_vcd</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkDiscOpenVcd</handler>
+ <last_modification_time>Sun, 13 May 2001 14:48:39 GMT</last_modification_time>
+ </signal>
+ <label>VCD</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>disc</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label19</name>
+ <label>Device name</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>disc_title</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:45:04 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1</value>
+ <lower>1</lower>
+ <upper>65536</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>disc_name</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:46:05 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text>/dev/dvd</text>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_disc</name>
+ <label>Disc</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table4</name>
+ <border_width>5</border_width>
+ <rows>4</rows>
+ <columns>6</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>5</row_spacing>
+ <column_spacing>5</column_spacing>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_udp</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenUDP</handler>
+ <last_modification_time>Thu, 16 May 2002 00:47:18 GMT</last_modification_time>
+ </signal>
+ <label>UDP</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_multicast</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenMulticast</handler>
+ <last_modification_time>Thu, 16 May 2002 00:47:05 GMT</last_modification_time>
+ </signal>
+ <label>UDP Multicast</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_channel</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenChannel</handler>
+ <last_modification_time>Thu, 16 May 2002 01:44:15 GMT</last_modification_time>
+ </signal>
+ <label>Channel server </label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>network_http</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkNetworkOpenHTTP</handler>
+ <last_modification_time>Thu, 16 May 2002 00:47:42 GMT</last_modification_time>
+ </signal>
+ <label>HTTP</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_udp_port_label</name>
+ <label>Port</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_multicast_address_label</name>
+ <sensitive>False</sensitive>
+ <label>Address</label>
+ <justify>GTK_JUSTIFY_RIGHT</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_channel_address_label</name>
+ <sensitive>False</sensitive>
+ <label>Address</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_http_url_label</name>
+ <sensitive>False</sensitive>
+ <label>URL</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>network_multicast_address_combo</name>
+ <sensitive>False</sensitive>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>4</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>network_multicast_address</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:06 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>network_channel_address_combo</name>
+ <sensitive>False</sensitive>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>4</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>network_channel_address</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:16 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_multicast_port_label</name>
+ <sensitive>False</sensitive>
+ <label>Port</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>4</left_attach>
+ <right_attach>5</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>network_channel_port_label</name>
+ <sensitive>False</sensitive>
+ <label>Port</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>1</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>4</left_attach>
+ <right_attach>5</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_multicast_port</name>
+ <width>75</width>
+ <sensitive>False</sensitive>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:36 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1234</value>
+ <lower>0</lower>
+ <upper>65535</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>5</left_attach>
+ <right_attach>6</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_channel_port</name>
+ <width>75</width>
+ <sensitive>False</sensitive>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:45 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>6010</value>
+ <lower>0</lower>
+ <upper>65535</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>5</left_attach>
+ <right_attach>6</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>network_http_url</name>
+ <sensitive>False</sensitive>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:57:26 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>6</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>network_udp_port</name>
+ <width>1</width>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:56:55 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1234</value>
+ <lower>0</lower>
+ <upper>65535</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>3</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_net</name>
+ <label>Network</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table3</name>
+ <border_width>5</border_width>
+ <rows>4</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>5</row_spacing>
+ <column_spacing>5</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label24</name>
+ <label>Symbol Rate</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label25</name>
+ <label>Frequency</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label26</name>
+ <label>Polarization</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>sat_freq</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:58:00 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>11954</value>
+ <lower>10000</lower>
+ <upper>12999</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label27</name>
+ <label>FEC</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox23</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>sat_pol_vert</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkSatOpenToggle</handler>
+ <last_modification_time>Tue, 09 Jul 2002 15:16:25 GMT</last_modification_time>
+ </signal>
+ <label>Vertical</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>pol</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>sat_pol_hor</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>GtkSatOpenToggle</handler>
+ <last_modification_time>Tue, 09 Jul 2002 15:16:36 GMT</last_modification_time>
+ </signal>
+ <label>Horizontal</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>pol</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>sat_srate</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:58:09 GMT</last_modification_time>
+ </signal>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>27500</value>
+ <lower>1000</lower>
+ <upper>30000</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>sat_fec</name>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items>1/2
+2/3
+3/4
+4/5
+5/6
+7/8
+</items>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>3</top_attach>
+ <bottom_attach>4</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>combo-entry1</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>changed</name>
+ <handler>GtkOpenChanged</handler>
+ <last_modification_time>Tue, 09 Jul 2002 13:58:26 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text>3/4</text>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>open_sat</name>
+ <label>Satellite</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkFileSelection</class>
+ <name>intf_file</name>
+ <border_width>10</border_width>
+ <title>Select File</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>True</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <show_file_op_buttons>True</show_file_op_buttons>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>FileSel:ok_button</child_name>
+ <name>file_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileOk</handler>
+ <last_modification_time>Wed, 10 Jul 2002 11:32:18 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <child_name>FileSel:cancel_button</child_name>
+ <name>file_cancel</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkFileCancel</handler>
+ <last_modification_time>Wed, 10 Jul 2002 11:32:23 GMT</last_modification_time>
+ </signal>
+ <label>Cancel</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkDialog</class>
+ <name>intf_jump</name>
+ <title>Jump</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>True</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox3</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area2</name>
+ <border_width>10</border_width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>jump_ok_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkJumpOk</handler>
+ <last_modification_time>Sun, 13 May 2001 14:53:19 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>jump_cancel_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkJumpCancel</handler>
+ <last_modification_time>Sun, 13 May 2001 14:53:43 GMT</last_modification_time>
+ </signal>
+ <label>Cancel</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>jump_frame</name>
+ <border_width>5</border_width>
+ <label>Go to:</label>
+ <label_xalign>0.05</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox13</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>jump_second_label</name>
+ <label>s.</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>jump_second_spinbutton</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>60</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>jump_minute_label</name>
+ <label>m:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>jump_minute_spinbutton</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>60</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>jump_hour_label</name>
+ <label>h:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>5</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>jump_hour_spinbutton</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>12</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkDialog</class>
+ <name>intf_playlist</name>
+ <signal>
+ <name>destroy</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 15 May 2001 14:20:39 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>delete_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 15 May 2001 14:20:22 GMT</last_modification_time>
+ </signal>
+ <title>Playlist</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <default_width>400</default_width>
+ <default_height>300</default_height>
+ <allow_shrink>True</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox4</name>
+ <homogeneous>False</homogeneous>
+ <spacing>5</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area3</name>
+ <border_width>10</border_width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>playlist_ok_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistOk</handler>
+ <last_modification_time>Sat, 12 May 2001 21:16:09 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>playlist_cancel_button</name>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkPlaylistCancel</handler>
+ <last_modification_time>Sat, 12 May 2001 21:16:20 GMT</last_modification_time>
+ </signal>
+ <label>Cancel</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuBar</class>
+ <name>playlist_menubar</name>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add</name>
+ <label>Add</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>playlist_add_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_disc</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkDiscOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:59:32 GMT</last_modification_time>
+ </signal>
+ <label>Disc</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_file</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkFileOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 21:59:48 GMT</last_modification_time>
+ </signal>
+ <label>File</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_network</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkNetworkOpenShow</handler>
+ <last_modification_time>Mon, 14 May 2001 22:00:03 GMT</last_modification_time>
+ </signal>
+ <label>Network</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_add_url</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistAddUrl</handler>
+ <last_modification_time>Mon, 14 May 2001 22:00:22 GMT</last_modification_time>
+ </signal>
+ <label>Url</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_delete</name>
+ <label>Delete</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>playlist_delete_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_delete_all</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistDeleteAll</handler>
+ <last_modification_time>Sat, 12 May 2001 21:13:11 GMT</last_modification_time>
+ </signal>
+ <label>All</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_delete_selected</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistDeleteSelected</handler>
+ <last_modification_time>Sat, 12 May 2001 21:12:58 GMT</last_modification_time>
+ </signal>
+ <label>Selected</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection</name>
+ <label>Selection</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>playlist_selection_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection_crop</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistCrop</handler>
+ <last_modification_time>Sat, 12 May 2001 21:13:47 GMT</last_modification_time>
+ </signal>
+ <label>_Crop</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection_invert</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistInvert</handler>
+ <last_modification_time>Sat, 12 May 2001 21:13:55 GMT</last_modification_time>
+ </signal>
+ <label>_Invert</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>playlist_selection_select</name>
+ <signal>
+ <name>activate</name>
+ <handler>GtkPlaylistSelect</handler>
+ <last_modification_time>Sat, 12 May 2001 21:14:04 GMT</last_modification_time>
+ </signal>
+ <label>_Select</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow1</name>
+ <hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkCList</class>
+ <name>playlist_clist</name>
+ <border_width>5</border_width>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>event</name>
+ <handler>GtkPlaylistEvent</handler>
+ <last_modification_time>Sat, 12 May 2001 21:25:20 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>drag_data_received</name>
+ <handler>GtkPlaylistDragData</handler>
+ <last_modification_time>Sat, 12 May 2001 21:25:53 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>drag_motion</name>
+ <handler>GtkPlaylistDragMotion</handler>
+ <last_modification_time>Sat, 12 May 2001 21:26:23 GMT</last_modification_time>
+ </signal>
+ <columns>2</columns>
+ <column_widths>257,80</column_widths>
+ <selection_mode>GTK_SELECTION_EXTENDED</selection_mode>
+ <show_titles>True</show_titles>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label22</name>
+ <label>File</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label23</name>
+ <label>Duration</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkDialog</class>
+ <name>intf_messages</name>
+ <signal>
+ <name>delete_event</name>
+ <handler>GtkMessagesDelete</handler>
+ <last_modification_time>Tue, 19 Feb 2002 02:39:16 GMT</last_modification_time>
+ </signal>
+ <title>Messages</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <default_width>600</default_width>
+ <default_height>400</default_height>
+ <allow_shrink>True</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox6</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area5</name>
+ <border_width>5</border_width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>messages_ok</name>
+ <can_default>True</can_default>
+ <has_default>True</has_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>GtkMessagesOk</handler>
+ <last_modification_time>Tue, 19 Feb 2002 02:07:37 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow2</name>
+ <border_width>5</border_width>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkText</class>
+ <name>messages_textbox</name>
+ <can_focus>True</can_focus>
+ <editable>False</editable>
+ <text></text>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
--- /dev/null
+/*****************************************************************************
+ * gtk_callbacks.c : Callbacks for the Gtk+ plugin.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: gtk_callbacks.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ * Julien BLACHE <jb@technologeek.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <sys/types.h> /* off_t */
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include <string.h>
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "common.h"
+
+#include "netutils.h"
+
+/*****************************************************************************
+ * Useful function to retrieve p_intf
+ ****************************************************************************/
+void * __GtkGetIntf( GtkWidget * widget )
+{
+ void *p_data;
+
+ if( GTK_IS_MENU_ITEM( widget ) )
+ {
+ /* Look for a GTK_MENU */
+ while( widget->parent && !GTK_IS_MENU( widget ) )
+ {
+ widget = widget->parent;
+ }
+
+ /* Maybe this one has the data */
+ p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
+ if( p_data )
+ {
+ return p_data;
+ }
+
+ /* Otherwise, the parent widget has it */
+ widget = gtk_menu_get_attach_widget( GTK_MENU( widget ) );
+ }
+
+ /* We look for the top widget */
+ widget = gtk_widget_get_toplevel( GTK_WIDGET( widget ) );
+
+ p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
+
+ return p_data;
+}
+
+/*****************************************************************************
+ * Callbacks
+ *****************************************************************************/
+
+/*
+ * Main interface callbacks
+ */
+
+gboolean GtkExit( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ vlc_mutex_lock( &p_intf->change_lock );
+ p_intf->p_vlc->b_die = VLC_TRUE;
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return TRUE;
+}
+
+void GtkClose( GtkMenuItem *menuitem,
+ gpointer user_data )
+{
+ intf_thread_t *p_intf = GtkGetIntf( menuitem );
+ p_intf->b_die = VLC_TRUE;
+}
+
+gboolean GtkWindowDelete( GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data )
+{
+ GtkExit( GTK_WIDGET( widget ), user_data );
+
+ return TRUE;
+}
+
+
+gboolean GtkWindowToggle( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ if( GTK_WIDGET_VISIBLE(p_intf->p_sys->p_window) )
+ {
+ gtk_widget_hide( p_intf->p_sys->p_window);
+ }
+ else
+ {
+ gtk_widget_show( p_intf->p_sys->p_window );
+ }
+
+ return TRUE;
+}
+
+gboolean GtkFullscreen( GtkWidget *widget,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+ vout_thread_t *p_vout;
+
+ p_vout = vlc_object_find( p_intf->p_sys->p_input,
+ VLC_OBJECT_VOUT, FIND_CHILD );
+ if( p_vout == NULL )
+ {
+ return FALSE;
+ }
+
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ vlc_object_release( p_vout );
+ return TRUE;
+}
+
+void GtkWindowDrag( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ GtkDropDataReceived( p_intf, data, info, PLAYLIST_END );
+}
+
+
+/****************************************************************************
+ * Slider management
+ ****************************************************************************/
+
+gboolean GtkSliderRelease( GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data )
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ vlc_mutex_lock( &p_intf->change_lock );
+ p_intf->p_sys->b_slider_free = 1;
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return FALSE;
+}
+
+
+gboolean GtkSliderPress( GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ vlc_mutex_lock( &p_intf->change_lock );
+ p_intf->p_sys->b_slider_free = 0;
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return FALSE;
+}
+
+
+/****************************************************************************
+ * DVD specific items
+ ****************************************************************************/
+
+void GtkTitlePrev( GtkButton * button, gpointer user_data )
+{
+ intf_thread_t * p_intf;
+ input_area_t * p_area;
+ int i_id;
+
+ p_intf = GtkGetIntf( button );
+
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
+
+ if( i_id >= 0 )
+ {
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+
+ p_intf->p_sys->b_title_update = 1;
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ GtkSetupMenus( p_intf );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+
+void GtkTitleNext( GtkButton * button, gpointer user_data )
+{
+ intf_thread_t * p_intf;
+ input_area_t * p_area;
+ int i_id;
+
+ p_intf = GtkGetIntf( button );
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
+
+ if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
+ {
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+
+ p_intf->p_sys->b_title_update = 1;
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ GtkSetupMenus( p_intf );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+
+void GtkChapterPrev( GtkButton * button, gpointer user_data )
+{
+ intf_thread_t * p_intf;
+ input_area_t * p_area;
+
+ p_intf = GtkGetIntf( button );
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;
+
+ if( p_area->i_part > 0 )
+ {
+ p_area->i_part--;
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+
+ p_intf->p_sys->b_chapter_update = 1;
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ GtkSetupMenus( p_intf );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+
+void GtkChapterNext( GtkButton * button, gpointer user_data )
+{
+ intf_thread_t * p_intf;
+ input_area_t * p_area;
+
+ p_intf = GtkGetIntf( button );
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;
+
+ if( p_area->i_part < p_area->i_part_nb )
+ {
+ p_area->i_part++;
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+
+ p_intf->p_sys->b_chapter_update = 1;
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ GtkSetupMenus( p_intf );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+/****************************************************************************
+ * Network specific items
+ ****************************************************************************/
+void GtkNetworkJoin( GtkEditable * editable, gpointer user_data )
+{
+ int i_channel;
+
+ i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( editable ) );
+// msg_Dbg( "intf info: joining channel %d", i_channel );
+
+// network_ChannelJoin( i_channel );
+}
+
+void GtkChannelGo( GtkButton * button, gpointer user_data )
+{
+ GtkWidget * window;
+ GtkWidget * spin;
+ int i_channel;
+
+ intf_thread_t *p_intf = GtkGetIntf( button );
+
+ window = gtk_widget_get_toplevel( GTK_WIDGET (button) );
+ spin = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( window ),
+ "network_channel_spinbutton" ) );
+
+ i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spin ) );
+ msg_Dbg( p_intf, "joining channel %d", i_channel );
+
+ vlc_mutex_lock( &p_intf->change_lock );
+ network_ChannelJoin( p_intf, i_channel );
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+// input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+}
+
+
+/****************************************************************************
+ * About box
+ ****************************************************************************/
+
+gboolean GtkAboutShow( GtkWidget *widget,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
+ {
+ p_intf->p_sys->p_about = create_intf_about();
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
+ "p_intf", p_intf );
+ }
+ gtk_widget_show( p_intf->p_sys->p_about );
+ gdk_window_raise( p_intf->p_sys->p_about->window );
+
+ return TRUE;
+}
+
+void GtkAboutOk( GtkButton * button, gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( button );
+
+ gtk_widget_hide( p_intf->p_sys->p_about );
+}
+
+
+/****************************************************************************
+ * Jump box
+ ****************************************************************************/
+
+gboolean GtkJumpShow( GtkWidget *widget,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
+ {
+ p_intf->p_sys->p_jump = create_intf_jump();
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
+ "p_intf", p_intf );
+ }
+
+ gtk_widget_show( p_intf->p_sys->p_jump );
+ gdk_window_raise( p_intf->p_sys->p_jump->window );
+
+ return FALSE;
+}
+
+
+void GtkJumpOk( GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+ int i_hours, i_minutes, i_seconds;
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return;
+ }
+
+#define GET_VALUE( name ) \
+ gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
+ GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
+ i_hours = GET_VALUE( "jump_hour_spinbutton" );
+ i_minutes = GET_VALUE( "jump_minute_spinbutton" );
+ i_seconds = GET_VALUE( "jump_second_spinbutton" );
+#undef GET_VALUE
+
+ input_Seek( p_intf->p_sys->p_input,
+ i_seconds + 60 * i_minutes + 3600 * i_hours,
+ INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
+
+ gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+
+void GtkJumpCancel( GtkButton *button,
+ gpointer user_data)
+{
+ gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+/****************************************************************************
+ * Callbacks for disc ejection
+ ****************************************************************************/
+gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
+{
+ char *psz_device = NULL;
+ char *psz_parser;
+ char *psz_current;
+
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return FALSE;
+ }
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+
+ if( p_playlist->i_index < 0 )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ return FALSE;
+ }
+
+ psz_current = p_playlist->pp_items[ p_playlist->i_index ]->psz_name;
+
+ /*
+ * Get the active input
+ * Determine whether we can eject a media, ie it's a VCD or DVD
+ * If it's neither a VCD nor a DVD, then return
+ */
+
+ /*
+ * Don't really know if I must lock the stuff here, we're using it read-only
+ */
+
+ if( psz_current != NULL )
+ {
+ if( !strncmp(psz_current, "dvd:", 4) )
+ {
+ switch( psz_current[4] )
+ {
+ case '\0':
+ case '@':
+ psz_device = config_GetPsz( p_intf, "dvd" );
+ break;
+ default:
+ /* Omit the first 4 characters */
+ psz_device = strdup( psz_current + 4 );
+ break;
+ }
+ }
+ else if( !strncmp(psz_current, "vcd:", 4) )
+ {
+ switch( psz_current[4] )
+ {
+ case '\0':
+ case '@':
+ psz_device = config_GetPsz( p_intf, "vcd" );
+ break;
+ default:
+ /* Omit the first 4 characters */
+ psz_device = strdup( psz_current + 4 );
+ break;
+ }
+ }
+ else
+ {
+ psz_device = strdup( psz_current );
+ }
+ }
+
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+
+ if( psz_device == NULL )
+ {
+ return TRUE;
+ }
+
+ /* Remove what we have after @ */
+ psz_parser = psz_device;
+ for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
+ {
+ if( *psz_parser == '@' )
+ {
+ *psz_parser = '\0';
+ break;
+ }
+ }
+
+ /* If there's a stream playing, we aren't allowed to eject ! */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ msg_Dbg( p_intf, "ejecting %s", psz_device );
+
+ intf_Eject( p_intf, psz_device );
+ }
+
+ free(psz_device);
+
+ return TRUE;
+}
+
+/****************************************************************************
+ * Messages window
+ ****************************************************************************/
+
+gboolean GtkMessagesShow( GtkWidget *widget,
+ gpointer user_data)
+{
+ static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
+ static GdkColormap *colormap;
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ gtk_widget_show( p_intf->p_sys->p_messages );
+ colormap = gdk_colormap_get_system ();
+ gdk_color_alloc( colormap, &black );
+ gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
+ &black );
+
+ gdk_window_raise( p_intf->p_sys->p_messages->window );
+
+ gtk_text_set_point( p_intf->p_sys->p_messages_text,
+ gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
+
+ return TRUE;
+}
+
+
+void
+GtkMessagesOk (GtkButton *button,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( button );
+ gtk_widget_hide( p_intf->p_sys->p_messages );
+}
+
+
+gboolean
+GtkMessagesDelete (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+ gtk_widget_hide( p_intf->p_sys->p_messages );
+ return TRUE;
+}
+
+
+void
+GtkOpenNotebookChanged (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ gint page_num,
+ gpointer user_data)
+{
+ GtkOpenChanged( GTK_WIDGET( notebook ), user_data );
+}
+
--- /dev/null
+/*****************************************************************************
+ * gtk_callbacks.h : Callbacks for the gtk plugin.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: gtk_callbacks.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <gtk/gtk.h>
+
+#include "config.h"
+
+#include "control.h"
+#include "menu.h"
+#include "open.h"
+#include "modules.h"
+#include "playlist.h"
+#include "preferences.h"
+
+/* General glade callbacks */
+
+/*****************************************************************************
+ * main window callbacks: specific prototypes are in headers listed before
+ *****************************************************************************/
+
+gboolean GtkExit ( GtkWidget *, gpointer );
+gboolean GtkWindowToggle ( GtkWidget *, gpointer );
+gboolean GtkFullscreen ( GtkWidget *, gpointer );
+gboolean GtkSliderRelease ( GtkWidget *, GdkEventButton *, gpointer );
+gboolean GtkSliderPress ( GtkWidget *, GdkEventButton *, gpointer );
+gboolean GtkWindowDelete ( GtkWidget * widget, GdkEvent *, gpointer );
+gboolean GtkJumpShow ( GtkWidget *, gpointer );
+gboolean GtkAboutShow ( GtkWidget *, gpointer );
+gboolean GtkMessagesShow ( GtkWidget *, gpointer );
+void GtkTitlePrev ( GtkButton * button, gpointer );
+void GtkTitleNext ( GtkButton * button, gpointer );
+void GtkChapterPrev ( GtkButton *, gpointer );
+void GtkChapterNext ( GtkButton * button, gpointer );
+void GtkAboutOk ( GtkButton *, gpointer );
+void GtkWindowDrag ( GtkWidget *, GdkDragContext *,
+ gint, gint, GtkSelectionData *,
+ guint , guint, gpointer );
+void GtkJumpOk ( GtkButton * button, gpointer );
+void GtkJumpCancel ( GtkButton * button, gpointer user_data );
+
+void GtkNetworkJoin ( GtkEditable *, gpointer );
+void GtkChannelGo ( GtkButton *, gpointer );
+
+void GtkNetworkOpenChannel ( GtkToggleButton *, gpointer );
+
+gboolean
+GtkDiscEject (GtkWidget *widget,
+ gpointer user_data);
+
+void
+GtkMessagesOk (GtkButton *button,
+ gpointer user_data);
+
+gboolean
+GtkMessagesDelete (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data);
+
+gboolean
+GtkSatOpenShow (GtkWidget *widget,
+ gpointer user_data);
+
+void
+GtkSatOpenOk (GtkButton *button,
+ gpointer user_data);
+
+void
+GtkSatOpenCancel (GtkButton *button,
+ gpointer user_data);
+
+void
+GtkNetworkOpenUDP (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+GtkNetworkOpenMulticast (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+GtkNetworkOpenCS (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+GtkNetworkOpenHTTP (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+GtkNetworkOpenChannel (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+GtkOpenOk (GtkButton *button,
+ gpointer user_data);
+
+void
+GtkOpenCancel (GtkButton *button,
+ gpointer user_data);
+
+void
+GtkOpenChanged (GtkWidget *button,
+ gpointer user_data);
+
+void
+GtkOpenNotebookChanged (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ gint page_num,
+ gpointer user_data);
+
+void
+GtkSatOpenToggle (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+GtkFileShow (GtkButton *button,
+ gpointer user_data);
+
+void
+GtkFileOk (GtkButton *button,
+ gpointer user_data);
+
+void
+GtkFileCancel (GtkButton *button,
+ gpointer user_data);
+
+void
+GtkClose (GtkMenuItem *menuitem,
+ gpointer user_data);
--- /dev/null
+/* This file was created automatically by glade and fixed by bootstrap.sh */
+
+#include <vlc/vlc.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+GtkWidget*
+create_intf_window (void)
+{
+ GtkWidget *intf_window;
+ GtkWidget *window_vbox;
+ GtkWidget *menubar_handlebox;
+ GtkWidget *menubar;
+ guint tmp_key;
+ GtkWidget *menubar_file;
+ GtkWidget *menubar_file_menu;
+ GtkAccelGroup *menubar_file_menu_accels;
+ GtkWidget *menubar_open;
+ GtkWidget *menubar_disc;
+ GtkWidget *menubar_network;
+ GtkWidget *separator4;
+ GtkWidget *menubar_eject;
+ GtkWidget *separator14;
+ GtkWidget *menubar_close;
+ GtkWidget *menubar_exit;
+ GtkWidget *menubar_view;
+ GtkWidget *menubar_view_menu;
+ GtkAccelGroup *menubar_view_menu_accels;
+ GtkWidget *menubar_interface_hide;
+ GtkWidget *menubar_fullscreen;
+ GtkWidget *separator13;
+ GtkWidget *menubar_program;
+ GtkWidget *menubar_title;
+ GtkWidget *menubar_chapter;
+ GtkWidget *separator11;
+ GtkWidget *menubar_playlist;
+ GtkWidget *menubar_modules;
+ GtkWidget *menubar_messages;
+ GtkWidget *menubar_settings;
+ GtkWidget *menubar_settings_menu;
+ GtkAccelGroup *menubar_settings_menu_accels;
+ GtkWidget *menubar_audio;
+ GtkWidget *menubar_subpictures;
+ GtkWidget *separator8;
+ GtkWidget *menubar_preferences;
+ GtkWidget *menubar_help;
+ GtkWidget *menubar_help_menu;
+ GtkAccelGroup *menubar_help_menu_accels;
+ GtkWidget *menubar_about;
+ GtkWidget *toolbar_handlebox;
+ GtkWidget *toolbar;
+ GtkWidget *toolbar_open;
+ GtkWidget *toolbar_disc;
+ GtkWidget *toolbar_network;
+ GtkWidget *toolbar_sat;
+ GtkWidget *toolbar_back;
+ GtkWidget *toolbar_stop;
+ GtkWidget *toolbar_eject;
+ GtkWidget *toolbar_play;
+ GtkWidget *toolbar_pause;
+ GtkWidget *toolbar_slow;
+ GtkWidget *toolbar_fast;
+ GtkWidget *toolbar_playlist;
+ GtkWidget *toolbar_prev;
+ GtkWidget *toolbar_next;
+ GtkWidget *slider_frame;
+ GtkWidget *slider;
+ GtkWidget *file_box;
+ GtkWidget *label_status;
+ GtkWidget *dvd_box;
+ GtkWidget *dvd_label;
+ GtkWidget *title_box;
+ GtkWidget *title;
+ GtkWidget *title_label;
+ GtkWidget *title_prev_button;
+ GtkWidget *title_next_button;
+ GtkWidget *dvd_separator;
+ GtkWidget *chapter_box;
+ GtkWidget *chapter;
+ GtkWidget *chapter_label;
+ GtkWidget *chapter_prev_button;
+ GtkWidget *chapter_next_button;
+ GtkWidget *network_box;
+ GtkWidget *network_address_label;
+ GtkWidget *network_channel_box;
+ GtkWidget *channel_label;
+ GtkObject *network_channel_spinbutton_adj;
+ GtkWidget *network_channel_spinbutton;
+ GtkWidget *network_channel_go_button;
+ GtkWidget *intf_statusbar;
+ GtkAccelGroup *accel_group;
+ GtkTooltips *tooltips;
+
+ tooltips = gtk_tooltips_new ();
+
+ accel_group = gtk_accel_group_new ();
+
+ intf_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_object_set_data (GTK_OBJECT (intf_window), "intf_window", intf_window);
+ gtk_window_set_title (GTK_WINDOW (intf_window), _("VideoLAN Client"));
+ gtk_window_set_policy (GTK_WINDOW (intf_window), TRUE, TRUE, TRUE);
+
+ window_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_ref (window_vbox);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "window_vbox", window_vbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (window_vbox);
+ gtk_container_add (GTK_CONTAINER (intf_window), window_vbox);
+
+ menubar_handlebox = gtk_handle_box_new ();
+ gtk_widget_ref (menubar_handlebox);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_handlebox", menubar_handlebox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_handlebox);
+ gtk_box_pack_start (GTK_BOX (window_vbox), menubar_handlebox, FALSE, TRUE, 0);
+
+ menubar = gtk_menu_bar_new ();
+ gtk_widget_ref (menubar);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar", menubar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar);
+ gtk_container_add (GTK_CONTAINER (menubar_handlebox), menubar);
+
+ menubar_file = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_file)->child),
+ _("_File"));
+ gtk_widget_add_accelerator (menubar_file, "activate_item", accel_group,
+ tmp_key, GDK_MOD1_MASK, (GtkAccelFlags) 0);
+ gtk_widget_ref (menubar_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_file", menubar_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_file);
+ gtk_container_add (GTK_CONTAINER (menubar), menubar_file);
+
+ menubar_file_menu = gtk_menu_new ();
+ gtk_widget_ref (menubar_file_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_file_menu", menubar_file_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar_file), menubar_file_menu);
+ menubar_file_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (menubar_file_menu));
+
+ menubar_open = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_open)->child),
+ _("_Open File..."));
+ gtk_widget_add_accelerator (menubar_open, "activate_item", menubar_file_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_open);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_open", menubar_open,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_open);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_open);
+ gtk_tooltips_set_tip (tooltips, menubar_open, _("Open a File"), NULL);
+ gtk_widget_add_accelerator (menubar_open, "activate", accel_group,
+ GDK_F3, 0,
+ GTK_ACCEL_VISIBLE);
+
+ menubar_disc = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_disc)->child),
+ _("Open _Disc..."));
+ gtk_widget_add_accelerator (menubar_disc, "activate_item", menubar_file_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_disc);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_disc", menubar_disc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_disc);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_disc);
+ gtk_tooltips_set_tip (tooltips, menubar_disc, _("Open a DVD or VCD"), NULL);
+ gtk_widget_add_accelerator (menubar_disc, "activate", accel_group,
+ GDK_F4, 0,
+ GTK_ACCEL_VISIBLE);
+
+ menubar_network = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_network)->child),
+ _("_Network Stream..."));
+ gtk_widget_add_accelerator (menubar_network, "activate_item", menubar_file_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_network);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_network", menubar_network,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_network);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_network);
+ gtk_tooltips_set_tip (tooltips, menubar_network, _("Select a Network Stream"), NULL);
+ gtk_widget_add_accelerator (menubar_network, "activate", accel_group,
+ GDK_F5, 0,
+ GTK_ACCEL_VISIBLE);
+
+ separator4 = gtk_menu_item_new ();
+ gtk_widget_ref (separator4);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator4", separator4,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator4);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), separator4);
+ gtk_widget_set_sensitive (separator4, FALSE);
+
+ menubar_eject = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_eject)->child),
+ _("_Eject Disc"));
+ gtk_widget_add_accelerator (menubar_eject, "activate_item", menubar_file_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_eject);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_eject", menubar_eject,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_eject);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_eject);
+ gtk_tooltips_set_tip (tooltips, menubar_eject, _("Eject disc"), NULL);
+
+ separator14 = gtk_menu_item_new ();
+ gtk_widget_ref (separator14);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator14", separator14,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator14);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), separator14);
+ gtk_widget_set_sensitive (separator14, FALSE);
+
+ menubar_close = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_close)->child),
+ _("_Close"));
+ gtk_widget_add_accelerator (menubar_close, "activate_item", menubar_file_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_close);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_close", menubar_close,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_close);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_close);
+ gtk_tooltips_set_tip (tooltips, menubar_close, _("Close the window"), NULL);
+ gtk_widget_add_accelerator (menubar_close, "activate", accel_group,
+ GDK_W, GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+ menubar_exit = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_exit)->child),
+ _("E_xit"));
+ gtk_widget_add_accelerator (menubar_exit, "activate_item", menubar_file_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_exit);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_exit", menubar_exit,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_exit);
+ gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_exit);
+ gtk_tooltips_set_tip (tooltips, menubar_exit, _("Exit the program"), NULL);
+ gtk_widget_add_accelerator (menubar_exit, "activate", accel_group,
+ GDK_Q, GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+ menubar_view = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_view)->child),
+ _("_View"));
+ gtk_widget_add_accelerator (menubar_view, "activate_item", accel_group,
+ tmp_key, GDK_MOD1_MASK, (GtkAccelFlags) 0);
+ gtk_widget_ref (menubar_view);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_view", menubar_view,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_view);
+ gtk_container_add (GTK_CONTAINER (menubar), menubar_view);
+
+ menubar_view_menu = gtk_menu_new ();
+ gtk_widget_ref (menubar_view_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_view_menu", menubar_view_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar_view), menubar_view_menu);
+ menubar_view_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (menubar_view_menu));
+
+ menubar_interface_hide = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_interface_hide)->child),
+ _("_Hide interface"));
+ gtk_widget_add_accelerator (menubar_interface_hide, "activate_item", menubar_view_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_interface_hide);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_interface_hide", menubar_interface_hide,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_interface_hide);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_interface_hide);
+ gtk_tooltips_set_tip (tooltips, menubar_interface_hide, _("Hide the main interface window"), NULL);
+
+ menubar_fullscreen = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_fullscreen)->child),
+ _("_Fullscreen"));
+ gtk_widget_add_accelerator (menubar_fullscreen, "activate_item", menubar_view_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_fullscreen);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_fullscreen", menubar_fullscreen,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_fullscreen);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_fullscreen);
+
+ separator13 = gtk_menu_item_new ();
+ gtk_widget_ref (separator13);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator13", separator13,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator13);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), separator13);
+ gtk_widget_set_sensitive (separator13, FALSE);
+
+ menubar_program = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_program)->child),
+ _("Progr_am"));
+ gtk_widget_add_accelerator (menubar_program, "activate_item", menubar_view_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_program);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_program", menubar_program,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_program);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_program);
+ gtk_widget_set_sensitive (menubar_program, FALSE);
+ gtk_tooltips_set_tip (tooltips, menubar_program, _("Choose the program"), NULL);
+
+ menubar_title = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_title)->child),
+ _("_Title"));
+ gtk_widget_add_accelerator (menubar_title, "activate_item", menubar_view_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_title);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_title", menubar_title,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_title);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_title);
+ gtk_widget_set_sensitive (menubar_title, FALSE);
+ gtk_tooltips_set_tip (tooltips, menubar_title, _("Navigate through the stream"), NULL);
+
+ menubar_chapter = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_chapter)->child),
+ _("_Chapter"));
+ gtk_widget_add_accelerator (menubar_chapter, "activate_item", menubar_view_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_chapter);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_chapter", menubar_chapter,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_chapter);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_chapter);
+ gtk_widget_set_sensitive (menubar_chapter, FALSE);
+
+ separator11 = gtk_menu_item_new ();
+ gtk_widget_ref (separator11);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator11", separator11,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator11);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), separator11);
+ gtk_widget_set_sensitive (separator11, FALSE);
+
+ menubar_playlist = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_playlist)->child),
+ _("_Playlist..."));
+ gtk_widget_add_accelerator (menubar_playlist, "activate_item", menubar_view_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_playlist);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_playlist", menubar_playlist,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_playlist);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_playlist);
+ gtk_tooltips_set_tip (tooltips, menubar_playlist, _("Open the playlist window"), NULL);
+
+ menubar_modules = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_modules)->child),
+ _("_Modules..."));
+ gtk_widget_add_accelerator (menubar_modules, "activate_item", menubar_view_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_modules);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_modules", menubar_modules,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_modules);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_modules);
+ gtk_widget_set_sensitive (menubar_modules, FALSE);
+ gtk_tooltips_set_tip (tooltips, menubar_modules, _("Open the module manager"), NULL);
+
+ menubar_messages = gtk_menu_item_new_with_label (_("Messages..."));
+ gtk_widget_ref (menubar_messages);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_messages", menubar_messages,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_messages);
+ gtk_container_add (GTK_CONTAINER (menubar_view_menu), menubar_messages);
+ gtk_tooltips_set_tip (tooltips, menubar_messages, _("Open the messages window"), NULL);
+
+ menubar_settings = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_settings)->child),
+ _("_Settings"));
+ gtk_widget_add_accelerator (menubar_settings, "activate_item", accel_group,
+ tmp_key, GDK_MOD1_MASK, (GtkAccelFlags) 0);
+ gtk_widget_ref (menubar_settings);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_settings", menubar_settings,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_settings);
+ gtk_container_add (GTK_CONTAINER (menubar), menubar_settings);
+
+ menubar_settings_menu = gtk_menu_new ();
+ gtk_widget_ref (menubar_settings_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_settings_menu", menubar_settings_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar_settings), menubar_settings_menu);
+ menubar_settings_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (menubar_settings_menu));
+
+ menubar_audio = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_audio)->child),
+ _("A_udio"));
+ gtk_widget_add_accelerator (menubar_audio, "activate_item", menubar_settings_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_audio);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_audio", menubar_audio,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_audio);
+ gtk_container_add (GTK_CONTAINER (menubar_settings_menu), menubar_audio);
+ gtk_widget_set_sensitive (menubar_audio, FALSE);
+ gtk_tooltips_set_tip (tooltips, menubar_audio, _("Select audio channel"), NULL);
+
+ menubar_subpictures = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_subpictures)->child),
+ _("_Subtitles"));
+ gtk_widget_add_accelerator (menubar_subpictures, "activate_item", menubar_settings_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_subpictures);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_subpictures", menubar_subpictures,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_subpictures);
+ gtk_container_add (GTK_CONTAINER (menubar_settings_menu), menubar_subpictures);
+ gtk_widget_set_sensitive (menubar_subpictures, FALSE);
+ gtk_tooltips_set_tip (tooltips, menubar_subpictures, _("Select subtitles channel"), NULL);
+
+ separator8 = gtk_menu_item_new ();
+ gtk_widget_ref (separator8);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator8", separator8,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator8);
+ gtk_container_add (GTK_CONTAINER (menubar_settings_menu), separator8);
+ gtk_widget_set_sensitive (separator8, FALSE);
+
+ menubar_preferences = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_preferences)->child),
+ _("_Preferences..."));
+ gtk_widget_add_accelerator (menubar_preferences, "activate_item", menubar_settings_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_preferences);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_preferences", menubar_preferences,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_preferences);
+ gtk_container_add (GTK_CONTAINER (menubar_settings_menu), menubar_preferences);
+ gtk_tooltips_set_tip (tooltips, menubar_preferences, _("Configure the application"), NULL);
+
+ menubar_help = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_help)->child),
+ _("_Help"));
+ gtk_widget_add_accelerator (menubar_help, "activate_item", accel_group,
+ tmp_key, GDK_MOD1_MASK, (GtkAccelFlags) 0);
+ gtk_widget_ref (menubar_help);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_help", menubar_help,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_help);
+ gtk_container_add (GTK_CONTAINER (menubar), menubar_help);
+
+ menubar_help_menu = gtk_menu_new ();
+ gtk_widget_ref (menubar_help_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_help_menu", menubar_help_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menubar_help), menubar_help_menu);
+ menubar_help_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (menubar_help_menu));
+
+ menubar_about = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_about)->child),
+ _("_About..."));
+ gtk_widget_add_accelerator (menubar_about, "activate_item", menubar_help_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (menubar_about);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_about", menubar_about,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (menubar_about);
+ gtk_container_add (GTK_CONTAINER (menubar_help_menu), menubar_about);
+ gtk_tooltips_set_tip (tooltips, menubar_about, _("About this application"), NULL);
+
+ toolbar_handlebox = gtk_handle_box_new ();
+ gtk_widget_ref (toolbar_handlebox);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_handlebox", toolbar_handlebox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_handlebox);
+ gtk_box_pack_start (GTK_BOX (window_vbox), toolbar_handlebox, FALSE, TRUE, 0);
+
+ toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
+ gtk_widget_ref (toolbar);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar", toolbar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar);
+ gtk_container_add (GTK_CONTAINER (toolbar_handlebox), toolbar);
+ gtk_container_set_border_width (GTK_CONTAINER (toolbar), 1);
+ gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 16);
+ gtk_toolbar_set_space_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_SPACE_LINE);
+ gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NONE);
+
+ toolbar_open = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("File"),
+ _("Open a File"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_open);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_open", toolbar_open,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_open);
+
+ toolbar_disc = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Disc"),
+ _("Open a DVD or VCD"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_disc);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_disc", toolbar_disc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_disc);
+
+ toolbar_network = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Net"),
+ _("Select a Network Stream"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_network);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_network", toolbar_network,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_network);
+
+ toolbar_sat = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Sat"),
+ _("Open a Satellite Card"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_sat);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_sat", toolbar_sat,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_sat);
+
+ gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+ toolbar_back = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Back"),
+ _("Go Backward"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_back);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_back", toolbar_back,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_back);
+ gtk_widget_set_sensitive (toolbar_back, FALSE);
+
+ toolbar_stop = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Stop"),
+ _("Stop Stream"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_stop);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_stop", toolbar_stop,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_stop);
+
+ toolbar_eject = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Eject"),
+ NULL, NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_eject);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_eject", toolbar_eject,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_eject);
+
+ toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Play"),
+ _("Play Stream"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_play);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_play", toolbar_play,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_play);
+
+ toolbar_pause = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Pause"),
+ _("Pause Stream"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_pause);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_pause", toolbar_pause,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_pause);
+ gtk_widget_set_sensitive (toolbar_pause, FALSE);
+
+ gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+ toolbar_slow = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Slow"),
+ _("Play Slower"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_slow);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_slow", toolbar_slow,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_slow);
+ gtk_widget_set_sensitive (toolbar_slow, FALSE);
+
+ toolbar_fast = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Fast"),
+ _("Play Faster"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_fast);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_fast", toolbar_fast,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_fast);
+ gtk_widget_set_sensitive (toolbar_fast, FALSE);
+
+ toolbar_playlist = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Playlist"),
+ _("Open Playlist"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_playlist);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_playlist", toolbar_playlist,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_playlist);
+
+ toolbar_prev = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Prev"),
+ _("Previous File"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_prev);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_prev", toolbar_prev,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_prev);
+
+ toolbar_next = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ _("Next"),
+ _("Next File"), NULL,
+ NULL, NULL, NULL);
+ gtk_widget_ref (toolbar_next);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_next", toolbar_next,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (toolbar_next);
+
+ slider_frame = gtk_frame_new ("-:--:--");
+ gtk_widget_ref (slider_frame);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "slider_frame", slider_frame,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_box_pack_start (GTK_BOX (window_vbox), slider_frame, TRUE, TRUE, 0);
+ gtk_frame_set_label_align (GTK_FRAME (slider_frame), 0.05, 0.5);
+
+ slider = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 1, 6.25, 0)));
+ gtk_widget_ref (slider);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "slider", slider,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (slider);
+ gtk_container_add (GTK_CONTAINER (slider_frame), slider);
+ gtk_widget_set_usize (slider, 500, 15);
+ gtk_scale_set_draw_value (GTK_SCALE (slider), FALSE);
+ gtk_scale_set_digits (GTK_SCALE (slider), 3);
+
+ file_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (file_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "file_box", file_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (file_box);
+ gtk_box_pack_start (GTK_BOX (window_vbox), file_box, TRUE, TRUE, 0);
+ gtk_widget_set_usize (file_box, 500, 24);
+
+ label_status = gtk_label_new ("");
+ gtk_widget_ref (label_status);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "label_status", label_status,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label_status);
+ gtk_box_pack_start (GTK_BOX (file_box), label_status, TRUE, TRUE, 0);
+
+ dvd_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (dvd_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "dvd_box", dvd_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_box_pack_start (GTK_BOX (window_vbox), dvd_box, TRUE, TRUE, 0);
+ gtk_widget_set_usize (dvd_box, 500, 24);
+
+ dvd_label = gtk_label_new (_("Disc"));
+ gtk_widget_ref (dvd_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "dvd_label", dvd_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (dvd_label);
+ gtk_box_pack_start (GTK_BOX (dvd_box), dvd_label, TRUE, FALSE, 0);
+
+ title_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (title_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "title_box", title_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (title_box);
+ gtk_box_pack_start (GTK_BOX (dvd_box), title_box, TRUE, TRUE, 0);
+
+ title = gtk_label_new (_("Title:"));
+ gtk_widget_ref (title);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "title", title,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (title);
+ gtk_box_pack_start (GTK_BOX (title_box), title, FALSE, FALSE, 5);
+
+ title_label = gtk_label_new ("--");
+ gtk_widget_ref (title_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "title_label", title_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (title_label);
+ gtk_box_pack_start (GTK_BOX (title_box), title_label, FALSE, FALSE, 5);
+
+ title_prev_button = gtk_button_new_with_label (_("Prev"));
+ gtk_widget_ref (title_prev_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "title_prev_button", title_prev_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (title_prev_button);
+ gtk_box_pack_start (GTK_BOX (title_box), title_prev_button, FALSE, FALSE, 5);
+ gtk_button_set_relief (GTK_BUTTON (title_prev_button), GTK_RELIEF_NONE);
+
+ title_next_button = gtk_button_new_with_label (_("Next"));
+ gtk_widget_ref (title_next_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "title_next_button", title_next_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (title_next_button);
+ gtk_box_pack_start (GTK_BOX (title_box), title_next_button, FALSE, FALSE, 5);
+ gtk_button_set_relief (GTK_BUTTON (title_next_button), GTK_RELIEF_NONE);
+
+ dvd_separator = gtk_vseparator_new ();
+ gtk_widget_ref (dvd_separator);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "dvd_separator", dvd_separator,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (dvd_separator);
+ gtk_box_pack_start (GTK_BOX (dvd_box), dvd_separator, TRUE, TRUE, 0);
+
+ chapter_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (chapter_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "chapter_box", chapter_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (chapter_box);
+ gtk_box_pack_start (GTK_BOX (dvd_box), chapter_box, TRUE, TRUE, 0);
+
+ chapter = gtk_label_new (_("Chapter:"));
+ gtk_widget_ref (chapter);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "chapter", chapter,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (chapter);
+ gtk_box_pack_start (GTK_BOX (chapter_box), chapter, FALSE, FALSE, 5);
+
+ chapter_label = gtk_label_new ("---");
+ gtk_widget_ref (chapter_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "chapter_label", chapter_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (chapter_label);
+ gtk_box_pack_start (GTK_BOX (chapter_box), chapter_label, FALSE, FALSE, 5);
+
+ chapter_prev_button = gtk_button_new_with_label (_("Prev"));
+ gtk_widget_ref (chapter_prev_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "chapter_prev_button", chapter_prev_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (chapter_prev_button);
+ gtk_box_pack_start (GTK_BOX (chapter_box), chapter_prev_button, FALSE, FALSE, 5);
+ gtk_button_set_relief (GTK_BUTTON (chapter_prev_button), GTK_RELIEF_NONE);
+
+ chapter_next_button = gtk_button_new_with_label (_("Next"));
+ gtk_widget_ref (chapter_next_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "chapter_next_button", chapter_next_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (chapter_next_button);
+ gtk_box_pack_start (GTK_BOX (chapter_box), chapter_next_button, FALSE, FALSE, 5);
+ gtk_button_set_relief (GTK_BUTTON (chapter_next_button), GTK_RELIEF_NONE);
+
+ network_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (network_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_box", network_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_box_pack_start (GTK_BOX (window_vbox), network_box, TRUE, TRUE, 0);
+ gtk_widget_set_usize (network_box, 500, 24);
+
+ network_address_label = gtk_label_new (_("No server"));
+ gtk_widget_ref (network_address_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_address_label", network_address_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_address_label);
+ gtk_box_pack_start (GTK_BOX (network_box), network_address_label, TRUE, TRUE, 0);
+
+ network_channel_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (network_channel_box);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_channel_box", network_channel_box,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_box);
+ gtk_box_pack_start (GTK_BOX (network_box), network_channel_box, TRUE, FALSE, 0);
+
+ channel_label = gtk_label_new (_("Channel:"));
+ gtk_widget_ref (channel_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "channel_label", channel_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (channel_label);
+ gtk_box_pack_start (GTK_BOX (network_channel_box), channel_label, FALSE, FALSE, 5);
+
+ network_channel_spinbutton_adj = gtk_adjustment_new (0, 0, 100, 1, 10, 10);
+ network_channel_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (network_channel_spinbutton_adj), 1, 0);
+ gtk_widget_ref (network_channel_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_channel_spinbutton", network_channel_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_spinbutton);
+ gtk_box_pack_start (GTK_BOX (network_channel_box), network_channel_spinbutton, FALSE, TRUE, 0);
+
+ network_channel_go_button = gtk_button_new_with_label (_("Go!"));
+ gtk_widget_ref (network_channel_go_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "network_channel_go_button", network_channel_go_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_go_button);
+ gtk_box_pack_start (GTK_BOX (network_channel_box), network_channel_go_button, FALSE, FALSE, 0);
+ gtk_button_set_relief (GTK_BUTTON (network_channel_go_button), GTK_RELIEF_NONE);
+
+ intf_statusbar = gtk_statusbar_new ();
+ gtk_widget_ref (intf_statusbar);
+ gtk_object_set_data_full (GTK_OBJECT (intf_window), "intf_statusbar", intf_statusbar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (intf_statusbar);
+ gtk_box_pack_start (GTK_BOX (window_vbox), intf_statusbar, FALSE, FALSE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (intf_window), "drag_data_received",
+ GTK_SIGNAL_FUNC (GtkWindowDrag),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (intf_window), "delete_event",
+ GTK_SIGNAL_FUNC (GtkWindowDelete),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_open), "activate",
+ GTK_SIGNAL_FUNC (GtkFileOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_disc), "activate",
+ GTK_SIGNAL_FUNC (GtkDiscOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_network), "activate",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_eject), "activate",
+ GTK_SIGNAL_FUNC (GtkDiscEject),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_close), "activate",
+ GTK_SIGNAL_FUNC (GtkClose),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_exit), "activate",
+ GTK_SIGNAL_FUNC (GtkExit),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_interface_hide), "activate",
+ GTK_SIGNAL_FUNC (GtkWindowToggle),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_fullscreen), "activate",
+ GTK_SIGNAL_FUNC (GtkFullscreen),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_playlist), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_modules), "activate",
+ GTK_SIGNAL_FUNC (GtkModulesShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_messages), "activate",
+ GTK_SIGNAL_FUNC (GtkMessagesShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_preferences), "activate",
+ GTK_SIGNAL_FUNC (GtkPreferencesShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (menubar_about), "activate",
+ GTK_SIGNAL_FUNC (GtkAboutShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_open), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_disc), "clicked",
+ GTK_SIGNAL_FUNC (GtkDiscOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_network), "clicked",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_sat), "clicked",
+ GTK_SIGNAL_FUNC (GtkSatOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_back), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlBack),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_stop), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlStop),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_eject), "clicked",
+ GTK_SIGNAL_FUNC (GtkDiscEject),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_play), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlPlay),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_pause), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlPause),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_slow), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlSlow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_fast), "clicked",
+ GTK_SIGNAL_FUNC (GtkControlFast),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_playlist), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_prev), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistPrev),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (toolbar_next), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistNext),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (slider), "button_release_event",
+ GTK_SIGNAL_FUNC (GtkSliderRelease),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (slider), "button_press_event",
+ GTK_SIGNAL_FUNC (GtkSliderPress),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (title_prev_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkTitlePrev),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (title_next_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkTitleNext),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (chapter_prev_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkChapterPrev),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (chapter_next_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkChapterNext),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_spinbutton), "activate",
+ GTK_SIGNAL_FUNC (GtkNetworkJoin),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_go_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkChannelGo),
+ NULL);
+
+ gtk_object_set_data (GTK_OBJECT (intf_window), "tooltips", tooltips);
+
+ gtk_window_add_accel_group (GTK_WINDOW (intf_window), accel_group);
+
+ return intf_window;
+}
+
+GtkWidget*
+create_intf_popup (void)
+{
+ GtkWidget *intf_popup;
+ GtkAccelGroup *intf_popup_accels;
+ guint tmp_key;
+ GtkWidget *popup_play;
+ GtkWidget *popup_pause;
+ GtkWidget *popup_stop;
+ GtkWidget *popup_back;
+ GtkWidget *popup_slow;
+ GtkWidget *popup_fast;
+ GtkWidget *separator6;
+ GtkWidget *popup_interface_toggle;
+ GtkWidget *popup_fullscreen;
+ GtkWidget *separator5;
+ GtkWidget *popup_next;
+ GtkWidget *popup_prev;
+ GtkWidget *popup_jump;
+ GtkWidget *popup_program;
+ GtkWidget *popup_navigation;
+ GtkWidget *popup_audio;
+ GtkWidget *popup_subpictures;
+ GtkWidget *popup_open;
+ GtkWidget *popup_open_menu;
+ GtkAccelGroup *popup_open_menu_accels;
+ GtkWidget *popup_file;
+ GtkWidget *popup_disc;
+ GtkWidget *popup_network;
+ GtkWidget *separator12;
+ GtkWidget *popup_about;
+ GtkWidget *popup_playlist;
+ GtkWidget *popup_preferences;
+ GtkWidget *separator9;
+ GtkWidget *popup_exit;
+ GtkTooltips *tooltips;
+
+ tooltips = gtk_tooltips_new ();
+
+ intf_popup = gtk_menu_new ();
+ gtk_object_set_data (GTK_OBJECT (intf_popup), "intf_popup", intf_popup);
+ intf_popup_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (intf_popup));
+
+ popup_play = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_play)->child),
+ _("_Play"));
+ gtk_widget_add_accelerator (popup_play, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_play);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_play", popup_play,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_play);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_play);
+
+ popup_pause = gtk_menu_item_new_with_label (_("Pause"));
+ gtk_widget_ref (popup_pause);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_pause", popup_pause,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_pause);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_pause);
+ gtk_widget_set_sensitive (popup_pause, FALSE);
+
+ popup_stop = gtk_menu_item_new_with_label (_("Stop"));
+ gtk_widget_ref (popup_stop);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_stop", popup_stop,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_stop);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_stop);
+
+ popup_back = gtk_menu_item_new_with_label (_("Back"));
+ gtk_widget_ref (popup_back);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_back", popup_back,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_back);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_back);
+ gtk_widget_set_sensitive (popup_back, FALSE);
+
+ popup_slow = gtk_menu_item_new_with_label (_("Slow"));
+ gtk_widget_ref (popup_slow);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_slow", popup_slow,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_slow);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_slow);
+ gtk_widget_set_sensitive (popup_slow, FALSE);
+
+ popup_fast = gtk_menu_item_new_with_label (_("Fast"));
+ gtk_widget_ref (popup_fast);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_fast", popup_fast,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_fast);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_fast);
+ gtk_widget_set_sensitive (popup_fast, FALSE);
+
+ separator6 = gtk_menu_item_new ();
+ gtk_widget_ref (separator6);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator6", separator6,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator6);
+ gtk_container_add (GTK_CONTAINER (intf_popup), separator6);
+ gtk_widget_set_sensitive (separator6, FALSE);
+
+ popup_interface_toggle = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_interface_toggle)->child),
+ _("Toggle _Interface"));
+ gtk_widget_add_accelerator (popup_interface_toggle, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_interface_toggle);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_interface_toggle", popup_interface_toggle,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_interface_toggle);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_interface_toggle);
+
+ popup_fullscreen = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_fullscreen)->child),
+ _("_Fullscreen"));
+ gtk_widget_add_accelerator (popup_fullscreen, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_fullscreen);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_fullscreen", popup_fullscreen,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_fullscreen);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_fullscreen);
+
+ separator5 = gtk_menu_item_new ();
+ gtk_widget_ref (separator5);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator5", separator5,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator5);
+ gtk_container_add (GTK_CONTAINER (intf_popup), separator5);
+ gtk_widget_set_sensitive (separator5, FALSE);
+
+ popup_next = gtk_menu_item_new_with_label (_("Next"));
+ gtk_widget_ref (popup_next);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_next", popup_next,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_next);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_next);
+
+ popup_prev = gtk_menu_item_new_with_label (_("Prev"));
+ gtk_widget_ref (popup_prev);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_prev", popup_prev,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_prev);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_prev);
+
+ popup_jump = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_jump)->child),
+ _("_Jump..."));
+ gtk_widget_add_accelerator (popup_jump, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_jump);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_jump", popup_jump,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_jump);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_jump);
+
+ popup_program = gtk_menu_item_new_with_label (_("Program"));
+ gtk_widget_ref (popup_program);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_program", popup_program,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_program);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_program);
+ gtk_widget_set_sensitive (popup_program, FALSE);
+
+ popup_navigation = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_navigation)->child),
+ _("_Navigation"));
+ gtk_widget_add_accelerator (popup_navigation, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_navigation);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_navigation", popup_navigation,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_navigation);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_navigation);
+ gtk_widget_set_sensitive (popup_navigation, FALSE);
+
+ popup_audio = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_audio)->child),
+ _("_Audio"));
+ gtk_widget_add_accelerator (popup_audio, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_audio);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_audio", popup_audio,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_audio);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_audio);
+ gtk_widget_set_sensitive (popup_audio, FALSE);
+
+ popup_subpictures = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_subpictures)->child),
+ _("_Subtitles"));
+ gtk_widget_add_accelerator (popup_subpictures, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_subpictures);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_subpictures", popup_subpictures,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_subpictures);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_subpictures);
+ gtk_widget_set_sensitive (popup_subpictures, FALSE);
+
+ popup_open = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_open)->child),
+ _("_File"));
+ gtk_widget_add_accelerator (popup_open, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_open);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_open", popup_open,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_open);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_open);
+
+ popup_open_menu = gtk_menu_new ();
+ gtk_widget_ref (popup_open_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_open_menu", popup_open_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (popup_open), popup_open_menu);
+ popup_open_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (popup_open_menu));
+
+ popup_file = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_file)->child),
+ _("_Open File..."));
+ gtk_widget_add_accelerator (popup_file, "activate_item", popup_open_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_file", popup_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_file);
+ gtk_container_add (GTK_CONTAINER (popup_open_menu), popup_file);
+ gtk_tooltips_set_tip (tooltips, popup_file, _("Open a File"), NULL);
+
+ popup_disc = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_disc)->child),
+ _("Open _Disc..."));
+ gtk_widget_add_accelerator (popup_disc, "activate_item", popup_open_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_disc);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_disc", popup_disc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_disc);
+ gtk_container_add (GTK_CONTAINER (popup_open_menu), popup_disc);
+ gtk_tooltips_set_tip (tooltips, popup_disc, _("Open a DVD or VCD"), NULL);
+
+ popup_network = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_network)->child),
+ _("_Network Stream..."));
+ gtk_widget_add_accelerator (popup_network, "activate_item", popup_open_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_network);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_network", popup_network,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_network);
+ gtk_container_add (GTK_CONTAINER (popup_open_menu), popup_network);
+ gtk_tooltips_set_tip (tooltips, popup_network, _("Select a Network Stream"), NULL);
+
+ separator12 = gtk_menu_item_new ();
+ gtk_widget_ref (separator12);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator12", separator12,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator12);
+ gtk_container_add (GTK_CONTAINER (popup_open_menu), separator12);
+ gtk_widget_set_sensitive (separator12, FALSE);
+
+ popup_about = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_about)->child),
+ _("_About..."));
+ gtk_widget_add_accelerator (popup_about, "activate_item", popup_open_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_about);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_about", popup_about,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_about);
+ gtk_container_add (GTK_CONTAINER (popup_open_menu), popup_about);
+
+ popup_playlist = gtk_menu_item_new_with_label (_("Playlist..."));
+ gtk_widget_ref (popup_playlist);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_playlist", popup_playlist,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_playlist);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_playlist);
+
+ popup_preferences = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_preferences)->child),
+ _("_Preferences..."));
+ gtk_widget_add_accelerator (popup_preferences, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_preferences);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_preferences", popup_preferences,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_preferences);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_preferences);
+
+ separator9 = gtk_menu_item_new ();
+ gtk_widget_ref (separator9);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator9", separator9,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (separator9);
+ gtk_container_add (GTK_CONTAINER (intf_popup), separator9);
+ gtk_widget_set_sensitive (separator9, FALSE);
+
+ popup_exit = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (popup_exit)->child),
+ _("E_xit"));
+ gtk_widget_add_accelerator (popup_exit, "activate_item", intf_popup_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (popup_exit);
+ gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_exit", popup_exit,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (popup_exit);
+ gtk_container_add (GTK_CONTAINER (intf_popup), popup_exit);
+
+ gtk_signal_connect (GTK_OBJECT (popup_play), "activate",
+ GTK_SIGNAL_FUNC (GtkControlPlay),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_pause), "activate",
+ GTK_SIGNAL_FUNC (GtkControlPause),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_stop), "activate",
+ GTK_SIGNAL_FUNC (GtkControlStop),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_back), "activate",
+ GTK_SIGNAL_FUNC (GtkControlBack),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_slow), "activate",
+ GTK_SIGNAL_FUNC (GtkControlSlow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_fast), "activate",
+ GTK_SIGNAL_FUNC (GtkControlFast),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_interface_toggle), "activate",
+ GTK_SIGNAL_FUNC (GtkWindowToggle),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_fullscreen), "activate",
+ GTK_SIGNAL_FUNC (GtkFullscreen),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_next), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistNext),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_prev), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistPrev),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_jump), "activate",
+ GTK_SIGNAL_FUNC (GtkJumpShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_file), "activate",
+ GTK_SIGNAL_FUNC (GtkFileOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_disc), "activate",
+ GTK_SIGNAL_FUNC (GtkDiscOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_network), "activate",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_about), "activate",
+ GTK_SIGNAL_FUNC (GtkAboutShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_playlist), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_preferences), "activate",
+ GTK_SIGNAL_FUNC (GtkPreferencesShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (popup_exit), "activate",
+ GTK_SIGNAL_FUNC (GtkExit),
+ NULL);
+
+ gtk_object_set_data (GTK_OBJECT (intf_popup), "tooltips", tooltips);
+
+ return intf_popup;
+}
+
+GtkWidget*
+create_intf_about (void)
+{
+ GtkWidget *intf_about;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *vbox3;
+ GtkWidget *label14;
+ GtkWidget *label18;
+ GtkWidget *frame1;
+ GtkWidget *label16;
+ GtkWidget *label17;
+ GtkWidget *dialog_action_area;
+ GtkWidget *about_ok;
+
+ intf_about = gtk_dialog_new ();
+ gtk_object_set_data (GTK_OBJECT (intf_about), "intf_about", intf_about);
+ gtk_container_set_border_width (GTK_CONTAINER (intf_about), 5);
+ gtk_window_set_title (GTK_WINDOW (intf_about), _("About"));
+ gtk_window_set_position (GTK_WINDOW (intf_about), GTK_WIN_POS_CENTER);
+ gtk_window_set_policy (GTK_WINDOW (intf_about), FALSE, FALSE, FALSE);
+
+ dialog_vbox1 = GTK_DIALOG (intf_about)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_about), "dialog_vbox1", dialog_vbox1);
+ gtk_widget_show (dialog_vbox1);
+
+ vbox3 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_ref (vbox3);
+ gtk_object_set_data_full (GTK_OBJECT (intf_about), "vbox3", vbox3,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (vbox3);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox3, TRUE, TRUE, 0);
+
+ label14 = gtk_label_new (_("VideoLAN Client"));
+ gtk_widget_ref (label14);
+ gtk_object_set_data_full (GTK_OBJECT (intf_about), "label14", label14,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label14);
+ gtk_box_pack_start (GTK_BOX (vbox3), label14, TRUE, TRUE, 0);
+ gtk_misc_set_padding (GTK_MISC (label14), 0, 10);
+
+ label18 = gtk_label_new (_("(C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 - the VideoLAN Team"));
+ gtk_widget_ref (label18);
+ gtk_object_set_data_full (GTK_OBJECT (intf_about), "label18", label18,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label18);
+ gtk_box_pack_start (GTK_BOX (vbox3), label18, FALSE, FALSE, 0);
+ gtk_label_set_justify (GTK_LABEL (label18), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_padding (GTK_MISC (label18), 0, 5);
+
+ frame1 = gtk_frame_new (_("Authors"));
+ gtk_widget_ref (frame1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_about), "frame1", frame1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (frame1);
+ gtk_box_pack_start (GTK_BOX (vbox3), frame1, FALSE, FALSE, 0);
+
+ label16 = gtk_label_new (_("the VideoLAN team <videolan@videolan.org>\nhttp://www.videolan.org/"));
+ gtk_widget_ref (label16);
+ gtk_object_set_data_full (GTK_OBJECT (intf_about), "label16", label16,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label16);
+ gtk_container_add (GTK_CONTAINER (frame1), label16);
+ gtk_label_set_justify (GTK_LABEL (label16), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label16), 0.5, 0);
+ gtk_misc_set_padding (GTK_MISC (label16), 5, 5);
+
+ label17 = gtk_label_new (_("This is the VideoLAN client, a DVD and MPEG player. It can play MPEG and MPEG 2 files from a file or from a network source."));
+ gtk_widget_ref (label17);
+ gtk_object_set_data_full (GTK_OBJECT (intf_about), "label17", label17,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label17);
+ gtk_box_pack_start (GTK_BOX (vbox3), label17, FALSE, FALSE, 0);
+ gtk_label_set_justify (GTK_LABEL (label17), GTK_JUSTIFY_LEFT);
+ gtk_label_set_line_wrap (GTK_LABEL (label17), TRUE);
+ gtk_misc_set_padding (GTK_MISC (label17), 0, 5);
+
+ dialog_action_area = GTK_DIALOG (intf_about)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_about), "dialog_action_area", dialog_action_area);
+ gtk_widget_show (dialog_action_area);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area), 10);
+
+ about_ok = gtk_button_new_with_label (_("OK"));
+ gtk_widget_ref (about_ok);
+ gtk_object_set_data_full (GTK_OBJECT (intf_about), "about_ok", about_ok,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (about_ok);
+ gtk_box_pack_start (GTK_BOX (dialog_action_area), about_ok, FALSE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (about_ok, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect (GTK_OBJECT (about_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkAboutOk),
+ NULL);
+
+ gtk_widget_grab_default (about_ok);
+ return intf_about;
+}
+
+GtkWidget*
+create_intf_open (void)
+{
+ GtkWidget *intf_open;
+ GtkWidget *dialog_vbox7;
+ GtkWidget *open_vbox;
+ GtkWidget *frame10;
+ GtkWidget *hbox21;
+ GtkWidget *hbox22;
+ GtkWidget *label34;
+ GtkWidget *combo2;
+ GtkWidget *entry_open;
+ GtkWidget *label36;
+ GtkWidget *open_notebook;
+ GtkWidget *hbox20;
+ GtkWidget *combo1;
+ GtkWidget *entry_file;
+ GtkWidget *vbox13;
+ GtkWidget *open_browse;
+ GtkWidget *open_file;
+ GtkWidget *table5;
+ GtkWidget *label21;
+ GtkWidget *label20;
+ GtkObject *disc_chapter_adj;
+ GtkWidget *disc_chapter;
+ GtkWidget *label35;
+ GtkWidget *hbox24;
+ GSList *disc_group = NULL;
+ GtkWidget *disc_dvd;
+ GtkWidget *disc_vcd;
+ GtkWidget *label19;
+ GtkObject *disc_title_adj;
+ GtkWidget *disc_title;
+ GtkWidget *disc_name;
+ GtkWidget *open_disc;
+ GtkWidget *table4;
+ GSList *table4_group = NULL;
+ GtkWidget *network_udp;
+ GtkWidget *network_multicast;
+ GtkWidget *network_channel;
+ GtkWidget *network_http;
+ GtkWidget *network_udp_port_label;
+ GtkWidget *network_multicast_address_label;
+ GtkWidget *network_channel_address_label;
+ GtkWidget *network_http_url_label;
+ GtkWidget *network_multicast_address_combo;
+ GtkWidget *network_multicast_address;
+ GtkWidget *network_channel_address_combo;
+ GtkWidget *network_channel_address;
+ GtkWidget *network_multicast_port_label;
+ GtkWidget *network_channel_port_label;
+ GtkObject *network_multicast_port_adj;
+ GtkWidget *network_multicast_port;
+ GtkObject *network_channel_port_adj;
+ GtkWidget *network_channel_port;
+ GtkWidget *network_http_url;
+ GtkObject *network_udp_port_adj;
+ GtkWidget *network_udp_port;
+ GtkWidget *open_net;
+ GtkWidget *table3;
+ GtkWidget *label24;
+ GtkWidget *label25;
+ GtkWidget *label26;
+ GtkObject *sat_freq_adj;
+ GtkWidget *sat_freq;
+ GtkWidget *label27;
+ GtkWidget *hbox23;
+ GSList *pol_group = NULL;
+ GtkWidget *sat_pol_vert;
+ GtkWidget *sat_pol_hor;
+ GtkObject *sat_srate_adj;
+ GtkWidget *sat_srate;
+ GtkWidget *sat_fec;
+ GList *sat_fec_items = NULL;
+ GtkWidget *combo_entry1;
+ GtkWidget *open_sat;
+ GtkWidget *dialog_action_area6;
+ GtkWidget *hbox18;
+ GtkWidget *hbox19;
+ GtkWidget *open_ok;
+ GtkWidget *open_cancel;
+ GtkAccelGroup *accel_group;
+
+ accel_group = gtk_accel_group_new ();
+
+ intf_open = gtk_dialog_new ();
+ gtk_object_set_data (GTK_OBJECT (intf_open), "intf_open", intf_open);
+ gtk_container_set_border_width (GTK_CONTAINER (intf_open), 5);
+ gtk_window_set_title (GTK_WINDOW (intf_open), _("Open Target"));
+
+ dialog_vbox7 = GTK_DIALOG (intf_open)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_open), "dialog_vbox7", dialog_vbox7);
+ gtk_widget_show (dialog_vbox7);
+
+ open_vbox = gtk_vbox_new (FALSE, 5);
+ gtk_widget_ref (open_vbox);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_vbox", open_vbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_vbox);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox7), open_vbox, TRUE, TRUE, 0);
+
+ frame10 = gtk_frame_new (_("Media Resource Locator (MRL)"));
+ gtk_widget_ref (frame10);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "frame10", frame10,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (frame10);
+ gtk_box_pack_start (GTK_BOX (open_vbox), frame10, FALSE, TRUE, 0);
+
+ hbox21 = gtk_hbox_new (FALSE, 5);
+ gtk_widget_ref (hbox21);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox21", hbox21,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox21);
+ gtk_container_add (GTK_CONTAINER (frame10), hbox21);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox21), 5);
+
+ hbox22 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (hbox22);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox22", hbox22,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox22);
+ gtk_box_pack_start (GTK_BOX (hbox21), hbox22, FALSE, TRUE, 0);
+
+ label34 = gtk_label_new (_("Open Target:"));
+ gtk_widget_ref (label34);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label34", label34,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label34);
+ gtk_box_pack_start (GTK_BOX (hbox22), label34, FALSE, FALSE, 0);
+
+ combo2 = gtk_combo_new ();
+ gtk_widget_ref (combo2);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "combo2", combo2,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo2);
+ gtk_box_pack_start (GTK_BOX (hbox21), combo2, TRUE, TRUE, 0);
+
+ entry_open = GTK_COMBO (combo2)->entry;
+ gtk_widget_ref (entry_open);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "entry_open", entry_open,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (entry_open);
+
+ label36 = gtk_label_new (_("Alternatively, you can build an MRL using one of the following predefined targets:"));
+ gtk_widget_ref (label36);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label36", label36,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label36);
+ gtk_box_pack_start (GTK_BOX (open_vbox), label36, TRUE, TRUE, 0);
+ gtk_label_set_justify (GTK_LABEL (label36), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label36), 0, 1);
+
+ open_notebook = gtk_notebook_new ();
+ gtk_widget_ref (open_notebook);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_notebook", open_notebook,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_notebook);
+ gtk_box_pack_start (GTK_BOX (open_vbox), open_notebook, TRUE, TRUE, 0);
+
+ hbox20 = gtk_hbox_new (FALSE, 5);
+ gtk_widget_ref (hbox20);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox20", hbox20,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox20);
+ gtk_container_add (GTK_CONTAINER (open_notebook), hbox20);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox20), 5);
+
+ combo1 = gtk_combo_new ();
+ gtk_widget_ref (combo1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "combo1", combo1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo1);
+ gtk_box_pack_start (GTK_BOX (hbox20), combo1, FALSE, TRUE, 0);
+
+ entry_file = GTK_COMBO (combo1)->entry;
+ gtk_widget_ref (entry_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "entry_file", entry_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (entry_file);
+
+ vbox13 = gtk_vbox_new (TRUE, 0);
+ gtk_widget_ref (vbox13);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "vbox13", vbox13,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (vbox13);
+ gtk_box_pack_start (GTK_BOX (hbox20), vbox13, FALSE, FALSE, 0);
+
+ open_browse = gtk_button_new_with_label (_("Browse..."));
+ gtk_widget_ref (open_browse);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_browse", open_browse,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_browse);
+ gtk_box_pack_start (GTK_BOX (vbox13), open_browse, FALSE, FALSE, 0);
+
+ open_file = gtk_label_new (_("File"));
+ gtk_widget_ref (open_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_file", open_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_file);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 0), open_file);
+
+ table5 = gtk_table_new (4, 2, FALSE);
+ gtk_widget_ref (table5);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "table5", table5,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (table5);
+ gtk_container_add (GTK_CONTAINER (open_notebook), table5);
+ gtk_container_set_border_width (GTK_CONTAINER (table5), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table5), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table5), 5);
+
+ label21 = gtk_label_new (_("Title"));
+ gtk_widget_ref (label21);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label21", label21,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label21);
+ gtk_table_attach (GTK_TABLE (table5), label21, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label21), 0, 0.5);
+
+ label20 = gtk_label_new (_("Chapter"));
+ gtk_widget_ref (label20);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label20", label20,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label20);
+ gtk_table_attach (GTK_TABLE (table5), label20, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label20), 0, 0.5);
+
+ disc_chapter_adj = gtk_adjustment_new (1, 1, 65536, 1, 10, 10);
+ disc_chapter = gtk_spin_button_new (GTK_ADJUSTMENT (disc_chapter_adj), 1, 0);
+ gtk_widget_ref (disc_chapter);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_chapter", disc_chapter,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_chapter);
+ gtk_table_attach (GTK_TABLE (table5), disc_chapter, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label35 = gtk_label_new (_("Disc type"));
+ gtk_widget_ref (label35);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label35", label35,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label35);
+ gtk_table_attach (GTK_TABLE (table5), label35, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label35), 0, 0.5);
+
+ hbox24 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (hbox24);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox24", hbox24,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox24);
+ gtk_table_attach (GTK_TABLE (table5), hbox24, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+ disc_dvd = gtk_radio_button_new_with_label (disc_group, _("DVD"));
+ disc_group = gtk_radio_button_group (GTK_RADIO_BUTTON (disc_dvd));
+ gtk_widget_ref (disc_dvd);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_dvd", disc_dvd,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_dvd);
+ gtk_box_pack_start (GTK_BOX (hbox24), disc_dvd, FALSE, FALSE, 0);
+
+ disc_vcd = gtk_radio_button_new_with_label (disc_group, _("VCD"));
+ disc_group = gtk_radio_button_group (GTK_RADIO_BUTTON (disc_vcd));
+ gtk_widget_ref (disc_vcd);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_vcd", disc_vcd,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_vcd);
+ gtk_box_pack_start (GTK_BOX (hbox24), disc_vcd, FALSE, FALSE, 0);
+
+ label19 = gtk_label_new (_("Device name"));
+ gtk_widget_ref (label19);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label19", label19,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label19);
+ gtk_table_attach (GTK_TABLE (table5), label19, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ disc_title_adj = gtk_adjustment_new (1, 1, 65536, 1, 10, 10);
+ disc_title = gtk_spin_button_new (GTK_ADJUSTMENT (disc_title_adj), 1, 0);
+ gtk_widget_ref (disc_title);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_title", disc_title,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_title);
+ gtk_table_attach (GTK_TABLE (table5), disc_title, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ disc_name = gtk_entry_new ();
+ gtk_widget_ref (disc_name);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "disc_name", disc_name,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (disc_name);
+ gtk_table_attach (GTK_TABLE (table5), disc_name, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_entry_set_text (GTK_ENTRY (disc_name), "/dev/dvd");
+
+ open_disc = gtk_label_new (_("Disc"));
+ gtk_widget_ref (open_disc);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_disc", open_disc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_disc);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 1), open_disc);
+
+ table4 = gtk_table_new (4, 6, FALSE);
+ gtk_widget_ref (table4);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "table4", table4,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (table4);
+ gtk_container_add (GTK_CONTAINER (open_notebook), table4);
+ gtk_container_set_border_width (GTK_CONTAINER (table4), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table4), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table4), 5);
+
+ network_udp = gtk_radio_button_new_with_label (table4_group, _("UDP"));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_udp));
+ gtk_widget_ref (network_udp);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_udp", network_udp,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_udp);
+ gtk_table_attach (GTK_TABLE (table4), network_udp, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_multicast = gtk_radio_button_new_with_label (table4_group, _("UDP Multicast"));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_multicast));
+ gtk_widget_ref (network_multicast);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast", network_multicast,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_channel = gtk_radio_button_new_with_label (table4_group, _("Channel server "));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_channel));
+ gtk_widget_ref (network_channel);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel", network_channel,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel);
+ gtk_table_attach (GTK_TABLE (table4), network_channel, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_http = gtk_radio_button_new_with_label (table4_group, _("HTTP"));
+ table4_group = gtk_radio_button_group (GTK_RADIO_BUTTON (network_http));
+ gtk_widget_ref (network_http);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_http", network_http,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_http);
+ gtk_table_attach (GTK_TABLE (table4), network_http, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ network_udp_port_label = gtk_label_new (_("Port"));
+ gtk_widget_ref (network_udp_port_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_udp_port_label", network_udp_port_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_udp_port_label);
+ gtk_table_attach (GTK_TABLE (table4), network_udp_port_label, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (network_udp_port_label), 1, 0.5);
+
+ network_multicast_address_label = gtk_label_new (_("Address"));
+ gtk_widget_ref (network_multicast_address_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_address_label", network_multicast_address_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_address_label);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_address_label, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_multicast_address_label, FALSE);
+ gtk_label_set_justify (GTK_LABEL (network_multicast_address_label), GTK_JUSTIFY_RIGHT);
+ gtk_misc_set_alignment (GTK_MISC (network_multicast_address_label), 1, 0.5);
+
+ network_channel_address_label = gtk_label_new (_("Address"));
+ gtk_widget_ref (network_channel_address_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_address_label", network_channel_address_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_address_label);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_address_label, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_channel_address_label, FALSE);
+
+ network_http_url_label = gtk_label_new (_("URL"));
+ gtk_widget_ref (network_http_url_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_http_url_label", network_http_url_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_http_url_label);
+ gtk_table_attach (GTK_TABLE (table4), network_http_url_label, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_http_url_label, FALSE);
+ gtk_misc_set_alignment (GTK_MISC (network_http_url_label), 1, 0.5);
+
+ network_multicast_address_combo = gtk_combo_new ();
+ gtk_widget_ref (network_multicast_address_combo);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_address_combo", network_multicast_address_combo,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_address_combo);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_address_combo, 2, 4, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_multicast_address_combo, FALSE);
+
+ network_multicast_address = GTK_COMBO (network_multicast_address_combo)->entry;
+ gtk_widget_ref (network_multicast_address);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_address", network_multicast_address,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_address);
+
+ network_channel_address_combo = gtk_combo_new ();
+ gtk_widget_ref (network_channel_address_combo);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_address_combo", network_channel_address_combo,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_address_combo);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_address_combo, 2, 4, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_channel_address_combo, FALSE);
+
+ network_channel_address = GTK_COMBO (network_channel_address_combo)->entry;
+ gtk_widget_ref (network_channel_address);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_address", network_channel_address,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_address);
+
+ network_multicast_port_label = gtk_label_new (_("Port"));
+ gtk_widget_ref (network_multicast_port_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_port_label", network_multicast_port_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_port_label);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_port_label, 4, 5, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_multicast_port_label, FALSE);
+ gtk_misc_set_alignment (GTK_MISC (network_multicast_port_label), 1, 0.5);
+
+ network_channel_port_label = gtk_label_new (_("Port"));
+ gtk_widget_ref (network_channel_port_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_port_label", network_channel_port_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_port_label);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_port_label, 4, 5, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_channel_port_label, FALSE);
+ gtk_misc_set_alignment (GTK_MISC (network_channel_port_label), 1, 0.5);
+
+ network_multicast_port_adj = gtk_adjustment_new (1234, 0, 65535, 1, 10, 10);
+ network_multicast_port = gtk_spin_button_new (GTK_ADJUSTMENT (network_multicast_port_adj), 1, 0);
+ gtk_widget_ref (network_multicast_port);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_multicast_port", network_multicast_port,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_multicast_port);
+ gtk_table_attach (GTK_TABLE (table4), network_multicast_port, 5, 6, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_usize (network_multicast_port, 75, -2);
+ gtk_widget_set_sensitive (network_multicast_port, FALSE);
+
+ network_channel_port_adj = gtk_adjustment_new (6010, 0, 65535, 1, 10, 10);
+ network_channel_port = gtk_spin_button_new (GTK_ADJUSTMENT (network_channel_port_adj), 1, 0);
+ gtk_widget_ref (network_channel_port);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_channel_port", network_channel_port,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_channel_port);
+ gtk_table_attach (GTK_TABLE (table4), network_channel_port, 5, 6, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_usize (network_channel_port, 75, -2);
+ gtk_widget_set_sensitive (network_channel_port, FALSE);
+
+ network_http_url = gtk_entry_new ();
+ gtk_widget_ref (network_http_url);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_http_url", network_http_url,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_http_url);
+ gtk_table_attach (GTK_TABLE (table4), network_http_url, 2, 6, 3, 4,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_sensitive (network_http_url, FALSE);
+
+ network_udp_port_adj = gtk_adjustment_new (1234, 0, 65535, 1, 10, 10);
+ network_udp_port = gtk_spin_button_new (GTK_ADJUSTMENT (network_udp_port_adj), 1, 0);
+ gtk_widget_ref (network_udp_port);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "network_udp_port", network_udp_port,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (network_udp_port);
+ gtk_table_attach (GTK_TABLE (table4), network_udp_port, 2, 3, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_usize (network_udp_port, 1, -2);
+
+ open_net = gtk_label_new (_("Network"));
+ gtk_widget_ref (open_net);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_net", open_net,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_net);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 2), open_net);
+
+ table3 = gtk_table_new (4, 2, FALSE);
+ gtk_widget_ref (table3);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "table3", table3,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (table3);
+ gtk_container_add (GTK_CONTAINER (open_notebook), table3);
+ gtk_container_set_border_width (GTK_CONTAINER (table3), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table3), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table3), 5);
+
+ label24 = gtk_label_new (_("Symbol Rate"));
+ gtk_widget_ref (label24);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label24", label24,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label24);
+ gtk_table_attach (GTK_TABLE (table3), label24, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label24), 0, 0.5);
+
+ label25 = gtk_label_new (_("Frequency"));
+ gtk_widget_ref (label25);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label25", label25,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label25);
+ gtk_table_attach (GTK_TABLE (table3), label25, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label25), 0, 0.5);
+
+ label26 = gtk_label_new (_("Polarization"));
+ gtk_widget_ref (label26);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label26", label26,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label26);
+ gtk_table_attach (GTK_TABLE (table3), label26, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label26), 0, 0.5);
+
+ sat_freq_adj = gtk_adjustment_new (11954, 10000, 12999, 1, 10, 10);
+ sat_freq = gtk_spin_button_new (GTK_ADJUSTMENT (sat_freq_adj), 1, 0);
+ gtk_widget_ref (sat_freq);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_freq", sat_freq,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_freq);
+ gtk_table_attach (GTK_TABLE (table3), sat_freq, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label27 = gtk_label_new (_("FEC"));
+ gtk_widget_ref (label27);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "label27", label27,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label27);
+ gtk_table_attach (GTK_TABLE (table3), label27, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label27), 0, 0.5);
+
+ hbox23 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (hbox23);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox23", hbox23,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox23);
+ gtk_table_attach (GTK_TABLE (table3), hbox23, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+ sat_pol_vert = gtk_radio_button_new_with_label (pol_group, _("Vertical"));
+ pol_group = gtk_radio_button_group (GTK_RADIO_BUTTON (sat_pol_vert));
+ gtk_widget_ref (sat_pol_vert);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_pol_vert", sat_pol_vert,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_pol_vert);
+ gtk_box_pack_start (GTK_BOX (hbox23), sat_pol_vert, FALSE, FALSE, 0);
+
+ sat_pol_hor = gtk_radio_button_new_with_label (pol_group, _("Horizontal"));
+ pol_group = gtk_radio_button_group (GTK_RADIO_BUTTON (sat_pol_hor));
+ gtk_widget_ref (sat_pol_hor);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_pol_hor", sat_pol_hor,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_pol_hor);
+ gtk_box_pack_start (GTK_BOX (hbox23), sat_pol_hor, FALSE, FALSE, 0);
+
+ sat_srate_adj = gtk_adjustment_new (27500, 1000, 30000, 1, 10, 10);
+ sat_srate = gtk_spin_button_new (GTK_ADJUSTMENT (sat_srate_adj), 1, 0);
+ gtk_widget_ref (sat_srate);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_srate", sat_srate,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_srate);
+ gtk_table_attach (GTK_TABLE (table3), sat_srate, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ sat_fec = gtk_combo_new ();
+ gtk_widget_ref (sat_fec);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "sat_fec", sat_fec,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (sat_fec);
+ gtk_table_attach (GTK_TABLE (table3), sat_fec, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "1/2");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "2/3");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "3/4");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "4/5");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "5/6");
+ sat_fec_items = g_list_append (sat_fec_items, (gpointer) "7/8");
+ gtk_combo_set_popdown_strings (GTK_COMBO (sat_fec), sat_fec_items);
+ g_list_free (sat_fec_items);
+
+ combo_entry1 = GTK_COMBO (sat_fec)->entry;
+ gtk_widget_ref (combo_entry1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "combo_entry1", combo_entry1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (combo_entry1);
+ gtk_entry_set_text (GTK_ENTRY (combo_entry1), "3/4");
+
+ open_sat = gtk_label_new (_("Satellite"));
+ gtk_widget_ref (open_sat);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_sat", open_sat,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_sat);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (open_notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (open_notebook), 3), open_sat);
+
+ dialog_action_area6 = GTK_DIALOG (intf_open)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_open), "dialog_action_area6", dialog_action_area6);
+ gtk_widget_show (dialog_action_area6);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area6), 5);
+
+ hbox18 = gtk_hbox_new (TRUE, 5);
+ gtk_widget_ref (hbox18);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox18", hbox18,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox18);
+ gtk_box_pack_start (GTK_BOX (dialog_action_area6), hbox18, TRUE, TRUE, 0);
+
+ hbox19 = gtk_hbox_new (TRUE, 5);
+ gtk_widget_ref (hbox19);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "hbox19", hbox19,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox19);
+ gtk_box_pack_end (GTK_BOX (hbox18), hbox19, FALSE, TRUE, 0);
+
+ open_ok = gtk_button_new_with_label (_("OK"));
+ gtk_widget_ref (open_ok);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_ok", open_ok,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_ok);
+ gtk_box_pack_start (GTK_BOX (hbox19), open_ok, FALSE, TRUE, 0);
+
+ open_cancel = gtk_button_new_with_label (_("Cancel"));
+ gtk_widget_ref (open_cancel);
+ gtk_object_set_data_full (GTK_OBJECT (intf_open), "open_cancel", open_cancel,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (open_cancel);
+ gtk_box_pack_start (GTK_BOX (hbox19), open_cancel, FALSE, TRUE, 0);
+ gtk_widget_add_accelerator (open_cancel, "clicked", accel_group,
+ GDK_Escape, 0,
+ GTK_ACCEL_VISIBLE);
+
+ gtk_signal_connect_after (GTK_OBJECT (open_notebook), "switch_page",
+ GTK_SIGNAL_FUNC (GtkOpenNotebookChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (entry_file), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (open_browse), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_chapter), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_dvd), "toggled",
+ GTK_SIGNAL_FUNC (GtkDiscOpenDvd),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_vcd), "toggled",
+ GTK_SIGNAL_FUNC (GtkDiscOpenVcd),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_title), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (disc_name), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_udp), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenUDP),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_multicast), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenMulticast),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenChannel),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_http), "toggled",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenHTTP),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_multicast_address), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_address), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_multicast_port), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_channel_port), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_http_url), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (network_udp_port), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_freq), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_pol_vert), "toggled",
+ GTK_SIGNAL_FUNC (GtkSatOpenToggle),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_pol_hor), "toggled",
+ GTK_SIGNAL_FUNC (GtkSatOpenToggle),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (sat_srate), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (combo_entry1), "changed",
+ GTK_SIGNAL_FUNC (GtkOpenChanged),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (open_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkOpenOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (open_cancel), "clicked",
+ GTK_SIGNAL_FUNC (GtkOpenCancel),
+ NULL);
+
+ gtk_window_add_accel_group (GTK_WINDOW (intf_open), accel_group);
+
+ return intf_open;
+}
+
+GtkWidget*
+create_intf_file (void)
+{
+ GtkWidget *intf_file;
+ GtkWidget *file_ok;
+ GtkWidget *file_cancel;
+
+ intf_file = gtk_file_selection_new (_("Select File"));
+ gtk_object_set_data (GTK_OBJECT (intf_file), "intf_file", intf_file);
+ gtk_container_set_border_width (GTK_CONTAINER (intf_file), 10);
+ gtk_window_set_modal (GTK_WINDOW (intf_file), TRUE);
+
+ file_ok = GTK_FILE_SELECTION (intf_file)->ok_button;
+ gtk_object_set_data (GTK_OBJECT (intf_file), "file_ok", file_ok);
+ gtk_widget_show (file_ok);
+ GTK_WIDGET_SET_FLAGS (file_ok, GTK_CAN_DEFAULT);
+
+ file_cancel = GTK_FILE_SELECTION (intf_file)->cancel_button;
+ gtk_object_set_data (GTK_OBJECT (intf_file), "file_cancel", file_cancel);
+ gtk_widget_show (file_cancel);
+ GTK_WIDGET_SET_FLAGS (file_cancel, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect (GTK_OBJECT (file_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (file_cancel), "clicked",
+ GTK_SIGNAL_FUNC (GtkFileCancel),
+ NULL);
+
+ return intf_file;
+}
+
+GtkWidget*
+create_intf_jump (void)
+{
+ GtkWidget *intf_jump;
+ GtkWidget *dialog_vbox3;
+ GtkWidget *jump_frame;
+ GtkWidget *hbox13;
+ GtkWidget *jump_second_label;
+ GtkObject *jump_second_spinbutton_adj;
+ GtkWidget *jump_second_spinbutton;
+ GtkWidget *jump_minute_label;
+ GtkObject *jump_minute_spinbutton_adj;
+ GtkWidget *jump_minute_spinbutton;
+ GtkWidget *jump_hour_label;
+ GtkObject *jump_hour_spinbutton_adj;
+ GtkWidget *jump_hour_spinbutton;
+ GtkWidget *dialog_action_area2;
+ GtkWidget *jump_ok_button;
+ GtkWidget *jump_cancel_button;
+
+ intf_jump = gtk_dialog_new ();
+ gtk_object_set_data (GTK_OBJECT (intf_jump), "intf_jump", intf_jump);
+ gtk_window_set_title (GTK_WINDOW (intf_jump), _("Jump"));
+ gtk_window_set_policy (GTK_WINDOW (intf_jump), TRUE, TRUE, FALSE);
+
+ dialog_vbox3 = GTK_DIALOG (intf_jump)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_jump), "dialog_vbox3", dialog_vbox3);
+ gtk_widget_show (dialog_vbox3);
+
+ jump_frame = gtk_frame_new (_("Go to:"));
+ gtk_widget_ref (jump_frame);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_frame", jump_frame,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_frame);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox3), jump_frame, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (jump_frame), 5);
+ gtk_frame_set_label_align (GTK_FRAME (jump_frame), 0.05, 0.5);
+
+ hbox13 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_ref (hbox13);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "hbox13", hbox13,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (hbox13);
+ gtk_container_add (GTK_CONTAINER (jump_frame), hbox13);
+
+ jump_second_label = gtk_label_new (_("s."));
+ gtk_widget_ref (jump_second_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_second_label", jump_second_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_second_label);
+ gtk_box_pack_end (GTK_BOX (hbox13), jump_second_label, FALSE, FALSE, 5);
+
+ jump_second_spinbutton_adj = gtk_adjustment_new (0, 0, 60, 1, 10, 10);
+ jump_second_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (jump_second_spinbutton_adj), 1, 0);
+ gtk_widget_ref (jump_second_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_second_spinbutton", jump_second_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_second_spinbutton);
+ gtk_box_pack_end (GTK_BOX (hbox13), jump_second_spinbutton, FALSE, TRUE, 0);
+
+ jump_minute_label = gtk_label_new (_("m:"));
+ gtk_widget_ref (jump_minute_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_minute_label", jump_minute_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_minute_label);
+ gtk_box_pack_end (GTK_BOX (hbox13), jump_minute_label, FALSE, FALSE, 5);
+
+ jump_minute_spinbutton_adj = gtk_adjustment_new (0, 0, 60, 1, 10, 10);
+ jump_minute_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (jump_minute_spinbutton_adj), 1, 0);
+ gtk_widget_ref (jump_minute_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_minute_spinbutton", jump_minute_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_minute_spinbutton);
+ gtk_box_pack_end (GTK_BOX (hbox13), jump_minute_spinbutton, FALSE, TRUE, 0);
+
+ jump_hour_label = gtk_label_new (_("h:"));
+ gtk_widget_ref (jump_hour_label);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_hour_label", jump_hour_label,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_hour_label);
+ gtk_box_pack_end (GTK_BOX (hbox13), jump_hour_label, FALSE, FALSE, 5);
+
+ jump_hour_spinbutton_adj = gtk_adjustment_new (0, 0, 12, 1, 10, 10);
+ jump_hour_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (jump_hour_spinbutton_adj), 1, 0);
+ gtk_widget_ref (jump_hour_spinbutton);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_hour_spinbutton", jump_hour_spinbutton,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_hour_spinbutton);
+ gtk_box_pack_end (GTK_BOX (hbox13), jump_hour_spinbutton, FALSE, TRUE, 0);
+
+ dialog_action_area2 = GTK_DIALOG (intf_jump)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_jump), "dialog_action_area2", dialog_action_area2);
+ gtk_widget_show (dialog_action_area2);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area2), 10);
+
+ jump_ok_button = gtk_button_new_with_label (_("OK"));
+ gtk_widget_ref (jump_ok_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_ok_button", jump_ok_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_ok_button);
+ gtk_box_pack_start (GTK_BOX (dialog_action_area2), jump_ok_button, TRUE, TRUE, 0);
+
+ jump_cancel_button = gtk_button_new_with_label (_("Cancel"));
+ gtk_widget_ref (jump_cancel_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_jump), "jump_cancel_button", jump_cancel_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (jump_cancel_button);
+ gtk_box_pack_start (GTK_BOX (dialog_action_area2), jump_cancel_button, TRUE, TRUE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (jump_ok_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkJumpOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (jump_cancel_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkJumpCancel),
+ NULL);
+
+ return intf_jump;
+}
+
+GtkWidget*
+create_intf_playlist (void)
+{
+ GtkWidget *intf_playlist;
+ GtkWidget *dialog_vbox4;
+ GtkWidget *playlist_menubar;
+ GtkWidget *playlist_add;
+ GtkWidget *playlist_add_menu;
+ GtkAccelGroup *playlist_add_menu_accels;
+ GtkWidget *playlist_add_disc;
+ GtkWidget *playlist_add_file;
+ GtkWidget *playlist_add_network;
+ GtkWidget *playlist_add_url;
+ GtkWidget *playlist_delete;
+ GtkWidget *playlist_delete_menu;
+ GtkAccelGroup *playlist_delete_menu_accels;
+ GtkWidget *playlist_delete_all;
+ GtkWidget *playlist_delete_selected;
+ GtkWidget *playlist_selection;
+ GtkWidget *playlist_selection_menu;
+ GtkAccelGroup *playlist_selection_menu_accels;
+ guint tmp_key;
+ GtkWidget *playlist_selection_crop;
+ GtkWidget *playlist_selection_invert;
+ GtkWidget *playlist_selection_select;
+ GtkWidget *scrolledwindow1;
+ GtkWidget *playlist_clist;
+ GtkWidget *label22;
+ GtkWidget *label23;
+ GtkWidget *dialog_action_area3;
+ GtkWidget *playlist_ok_button;
+ GtkWidget *playlist_cancel_button;
+
+ intf_playlist = gtk_dialog_new ();
+ gtk_object_set_data (GTK_OBJECT (intf_playlist), "intf_playlist", intf_playlist);
+ gtk_window_set_title (GTK_WINDOW (intf_playlist), _("Playlist"));
+ gtk_window_set_default_size (GTK_WINDOW (intf_playlist), 400, 300);
+ gtk_window_set_policy (GTK_WINDOW (intf_playlist), TRUE, TRUE, FALSE);
+
+ dialog_vbox4 = GTK_DIALOG (intf_playlist)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_playlist), "dialog_vbox4", dialog_vbox4);
+ gtk_widget_show (dialog_vbox4);
+
+ playlist_menubar = gtk_menu_bar_new ();
+ gtk_widget_ref (playlist_menubar);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_menubar", playlist_menubar,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_menubar);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox4), playlist_menubar, FALSE, FALSE, 0);
+
+ playlist_add = gtk_menu_item_new_with_label (_("Add"));
+ gtk_widget_ref (playlist_add);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add", playlist_add,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_add);
+ gtk_container_add (GTK_CONTAINER (playlist_menubar), playlist_add);
+
+ playlist_add_menu = gtk_menu_new ();
+ gtk_widget_ref (playlist_add_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_menu", playlist_add_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (playlist_add), playlist_add_menu);
+ playlist_add_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (playlist_add_menu));
+
+ playlist_add_disc = gtk_menu_item_new_with_label (_("Disc"));
+ gtk_widget_ref (playlist_add_disc);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_disc", playlist_add_disc,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_add_disc);
+ gtk_container_add (GTK_CONTAINER (playlist_add_menu), playlist_add_disc);
+
+ playlist_add_file = gtk_menu_item_new_with_label (_("File"));
+ gtk_widget_ref (playlist_add_file);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_file", playlist_add_file,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_add_file);
+ gtk_container_add (GTK_CONTAINER (playlist_add_menu), playlist_add_file);
+
+ playlist_add_network = gtk_menu_item_new_with_label (_("Network"));
+ gtk_widget_ref (playlist_add_network);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_network", playlist_add_network,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_add_network);
+ gtk_container_add (GTK_CONTAINER (playlist_add_menu), playlist_add_network);
+
+ playlist_add_url = gtk_menu_item_new_with_label (_("Url"));
+ gtk_widget_ref (playlist_add_url);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_add_url", playlist_add_url,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_add_url);
+ gtk_container_add (GTK_CONTAINER (playlist_add_menu), playlist_add_url);
+
+ playlist_delete = gtk_menu_item_new_with_label (_("Delete"));
+ gtk_widget_ref (playlist_delete);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_delete", playlist_delete,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_delete);
+ gtk_container_add (GTK_CONTAINER (playlist_menubar), playlist_delete);
+
+ playlist_delete_menu = gtk_menu_new ();
+ gtk_widget_ref (playlist_delete_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_delete_menu", playlist_delete_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (playlist_delete), playlist_delete_menu);
+ playlist_delete_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (playlist_delete_menu));
+
+ playlist_delete_all = gtk_menu_item_new_with_label (_("All"));
+ gtk_widget_ref (playlist_delete_all);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_delete_all", playlist_delete_all,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_delete_all);
+ gtk_container_add (GTK_CONTAINER (playlist_delete_menu), playlist_delete_all);
+
+ playlist_delete_selected = gtk_menu_item_new_with_label (_("Selected"));
+ gtk_widget_ref (playlist_delete_selected);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_delete_selected", playlist_delete_selected,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_delete_selected);
+ gtk_container_add (GTK_CONTAINER (playlist_delete_menu), playlist_delete_selected);
+
+ playlist_selection = gtk_menu_item_new_with_label (_("Selection"));
+ gtk_widget_ref (playlist_selection);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection", playlist_selection,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_selection);
+ gtk_container_add (GTK_CONTAINER (playlist_menubar), playlist_selection);
+
+ playlist_selection_menu = gtk_menu_new ();
+ gtk_widget_ref (playlist_selection_menu);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection_menu", playlist_selection_menu,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (playlist_selection), playlist_selection_menu);
+ playlist_selection_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (playlist_selection_menu));
+
+ playlist_selection_crop = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (playlist_selection_crop)->child),
+ _("_Crop"));
+ gtk_widget_add_accelerator (playlist_selection_crop, "activate_item", playlist_selection_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (playlist_selection_crop);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection_crop", playlist_selection_crop,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_selection_crop);
+ gtk_container_add (GTK_CONTAINER (playlist_selection_menu), playlist_selection_crop);
+
+ playlist_selection_invert = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (playlist_selection_invert)->child),
+ _("_Invert"));
+ gtk_widget_add_accelerator (playlist_selection_invert, "activate_item", playlist_selection_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (playlist_selection_invert);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection_invert", playlist_selection_invert,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_selection_invert);
+ gtk_container_add (GTK_CONTAINER (playlist_selection_menu), playlist_selection_invert);
+
+ playlist_selection_select = gtk_menu_item_new_with_label ("");
+ tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (playlist_selection_select)->child),
+ _("_Select"));
+ gtk_widget_add_accelerator (playlist_selection_select, "activate_item", playlist_selection_menu_accels,
+ tmp_key, 0, 0);
+ gtk_widget_ref (playlist_selection_select);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_selection_select", playlist_selection_select,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_selection_select);
+ gtk_container_add (GTK_CONTAINER (playlist_selection_menu), playlist_selection_select);
+
+ scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_ref (scrolledwindow1);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "scrolledwindow1", scrolledwindow1,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (scrolledwindow1);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox4), scrolledwindow1, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ playlist_clist = gtk_clist_new (2);
+ gtk_widget_ref (playlist_clist);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_clist", playlist_clist,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_clist);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow1), playlist_clist);
+ gtk_container_set_border_width (GTK_CONTAINER (playlist_clist), 5);
+ gtk_clist_set_column_width (GTK_CLIST (playlist_clist), 0, 257);
+ gtk_clist_set_column_width (GTK_CLIST (playlist_clist), 1, 80);
+ gtk_clist_set_selection_mode (GTK_CLIST (playlist_clist), GTK_SELECTION_EXTENDED);
+ gtk_clist_column_titles_show (GTK_CLIST (playlist_clist));
+ gtk_clist_set_shadow_type (GTK_CLIST (playlist_clist), GTK_SHADOW_OUT);
+
+ label22 = gtk_label_new (_("File"));
+ gtk_widget_ref (label22);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "label22", label22,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label22);
+ gtk_clist_set_column_widget (GTK_CLIST (playlist_clist), 0, label22);
+
+ label23 = gtk_label_new (_("Duration"));
+ gtk_widget_ref (label23);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "label23", label23,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (label23);
+ gtk_clist_set_column_widget (GTK_CLIST (playlist_clist), 1, label23);
+
+ dialog_action_area3 = GTK_DIALOG (intf_playlist)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_playlist), "dialog_action_area3", dialog_action_area3);
+ gtk_widget_show (dialog_action_area3);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area3), 10);
+
+ playlist_ok_button = gtk_button_new_with_label (_("OK"));
+ gtk_widget_ref (playlist_ok_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_ok_button", playlist_ok_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_ok_button);
+ gtk_box_pack_start (GTK_BOX (dialog_action_area3), playlist_ok_button, TRUE, TRUE, 0);
+
+ playlist_cancel_button = gtk_button_new_with_label (_("Cancel"));
+ gtk_widget_ref (playlist_cancel_button);
+ gtk_object_set_data_full (GTK_OBJECT (intf_playlist), "playlist_cancel_button", playlist_cancel_button,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (playlist_cancel_button);
+ gtk_box_pack_start (GTK_BOX (dialog_action_area3), playlist_cancel_button, TRUE, TRUE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (intf_playlist), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_hide),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (intf_playlist), "delete_event",
+ GTK_SIGNAL_FUNC (gtk_widget_hide),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_add_disc), "activate",
+ GTK_SIGNAL_FUNC (GtkDiscOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_add_file), "activate",
+ GTK_SIGNAL_FUNC (GtkFileOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_add_network), "activate",
+ GTK_SIGNAL_FUNC (GtkNetworkOpenShow),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_add_url), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistAddUrl),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_delete_all), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistDeleteAll),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_delete_selected), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistDeleteSelected),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_selection_crop), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistCrop),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_selection_invert), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistInvert),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_selection_select), "activate",
+ GTK_SIGNAL_FUNC (GtkPlaylistSelect),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_clist), "event",
+ GTK_SIGNAL_FUNC (GtkPlaylistEvent),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_clist), "drag_data_received",
+ GTK_SIGNAL_FUNC (GtkPlaylistDragData),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_clist), "drag_motion",
+ GTK_SIGNAL_FUNC (GtkPlaylistDragMotion),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_ok_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistOk),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (playlist_cancel_button), "clicked",
+ GTK_SIGNAL_FUNC (GtkPlaylistCancel),
+ NULL);
+
+ return intf_playlist;
+}
+
+GtkWidget*
+create_intf_messages (void)
+{
+ GtkWidget *intf_messages;
+ GtkWidget *dialog_vbox6;
+ GtkWidget *scrolledwindow2;
+ GtkWidget *messages_textbox;
+ GtkWidget *dialog_action_area5;
+ GtkWidget *messages_ok;
+
+ intf_messages = gtk_dialog_new ();
+ gtk_object_set_data (GTK_OBJECT (intf_messages), "intf_messages", intf_messages);
+ gtk_window_set_title (GTK_WINDOW (intf_messages), _("Messages"));
+ gtk_window_set_default_size (GTK_WINDOW (intf_messages), 600, 400);
+ gtk_window_set_policy (GTK_WINDOW (intf_messages), TRUE, TRUE, FALSE);
+
+ dialog_vbox6 = GTK_DIALOG (intf_messages)->vbox;
+ gtk_object_set_data (GTK_OBJECT (intf_messages), "dialog_vbox6", dialog_vbox6);
+ gtk_widget_show (dialog_vbox6);
+
+ scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_ref (scrolledwindow2);
+ gtk_object_set_data_full (GTK_OBJECT (intf_messages), "scrolledwindow2", scrolledwindow2,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (scrolledwindow2);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox6), scrolledwindow2, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow2), 5);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+
+ messages_textbox = gtk_text_new (NULL, NULL);
+ gtk_widget_ref (messages_textbox);
+ gtk_object_set_data_full (GTK_OBJECT (intf_messages), "messages_textbox", messages_textbox,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (messages_textbox);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow2), messages_textbox);
+
+ dialog_action_area5 = GTK_DIALOG (intf_messages)->action_area;
+ gtk_object_set_data (GTK_OBJECT (intf_messages), "dialog_action_area5", dialog_action_area5);
+ gtk_widget_show (dialog_action_area5);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area5), 5);
+
+ messages_ok = gtk_button_new_with_label (_("OK"));
+ gtk_widget_ref (messages_ok);
+ gtk_object_set_data_full (GTK_OBJECT (intf_messages), "messages_ok", messages_ok,
+ (GtkDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (messages_ok);
+ gtk_box_pack_start (GTK_BOX (dialog_action_area5), messages_ok, FALSE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (messages_ok, GTK_CAN_DEFAULT);
+
+ gtk_signal_connect (GTK_OBJECT (intf_messages), "delete_event",
+ GTK_SIGNAL_FUNC (GtkMessagesDelete),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (messages_ok), "clicked",
+ GTK_SIGNAL_FUNC (GtkMessagesOk),
+ NULL);
+
+ gtk_widget_grab_default (messages_ok);
+ return intf_messages;
+}
+
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+GtkWidget* create_intf_window (void);
+GtkWidget* create_intf_popup (void);
+GtkWidget* create_intf_about (void);
+GtkWidget* create_intf_open (void);
+GtkWidget* create_intf_file (void);
+GtkWidget* create_intf_jump (void);
+GtkWidget* create_intf_playlist (void);
+GtkWidget* create_intf_messages (void);
--- /dev/null
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "gtk_support.h"
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar* check_file_exists (const gchar *directory,
+ const gchar *filename);
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget* create_dummy_pixmap (GtkWidget *widget);
+
+GtkWidget*
+lookup_widget (GtkWidget *widget,
+ const gchar *widget_name)
+{
+ GtkWidget *parent, *found_widget;
+
+ for (;;)
+ {
+ if (GTK_IS_MENU (widget))
+ parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
+ else
+ parent = widget->parent;
+ if (parent == NULL)
+ break;
+ widget = parent;
+ }
+
+ found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
+ widget_name);
+ if (!found_widget)
+ g_warning ("Widget not found: %s", widget_name);
+ return found_widget;
+}
+
+/* This is a dummy pixmap we use when a pixmap can't be found. */
+static char *dummy_pixmap_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"1 1 1 1",
+" c None",
+/* pixels */
+" "
+};
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget*
+create_dummy_pixmap (GtkWidget *widget)
+{
+ GdkColormap *colormap;
+ GdkPixmap *gdkpixmap;
+ GdkBitmap *mask;
+ GtkWidget *pixmap;
+
+ colormap = gtk_widget_get_colormap (widget);
+ gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
+ NULL, dummy_pixmap_xpm);
+ if (gdkpixmap == NULL)
+ g_error ("Couldn't create replacement pixmap.");
+ pixmap = gtk_pixmap_new (gdkpixmap, mask);
+ gdk_pixmap_unref (gdkpixmap);
+ gdk_bitmap_unref (mask);
+ return pixmap;
+}
+
+static GList *pixmaps_directories = NULL;
+
+/* Use this function to set the directory containing installed pixmaps. */
+void
+add_pixmap_directory (const gchar *directory)
+{
+ pixmaps_directories = g_list_prepend (pixmaps_directories,
+ g_strdup (directory));
+}
+
+/* This is an internally used function to create pixmaps. */
+GtkWidget*
+create_pixmap (GtkWidget *widget,
+ const gchar *filename)
+{
+ gchar *found_filename = NULL;
+ GdkColormap *colormap;
+ GdkPixmap *gdkpixmap;
+ GdkBitmap *mask;
+ GtkWidget *pixmap;
+ GList *elem;
+
+ if (!filename || !filename[0])
+ return create_dummy_pixmap (widget);
+
+ /* We first try any pixmaps directories set by the application. */
+ elem = pixmaps_directories;
+ while (elem)
+ {
+ found_filename = check_file_exists ((gchar*)elem->data, filename);
+ if (found_filename)
+ break;
+ elem = elem->next;
+ }
+
+ /* If we haven't found the pixmap, try the source directory. */
+ if (!found_filename)
+ {
+ found_filename = check_file_exists ("pixmaps", filename);
+ }
+
+ if (!found_filename)
+ {
+ g_warning (_("Couldn't find pixmap file: %s"), filename);
+ return create_dummy_pixmap (widget);
+ }
+
+ colormap = gtk_widget_get_colormap (widget);
+ gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,
+ NULL, found_filename);
+ if (gdkpixmap == NULL)
+ {
+ g_warning (_("Error loading pixmap file: %s"), found_filename);
+ g_free (found_filename);
+ return create_dummy_pixmap (widget);
+ }
+ g_free (found_filename);
+ pixmap = gtk_pixmap_new (gdkpixmap, mask);
+ gdk_pixmap_unref (gdkpixmap);
+ gdk_bitmap_unref (mask);
+ return pixmap;
+}
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar*
+check_file_exists (const gchar *directory,
+ const gchar *filename)
+{
+ gchar *full_filename;
+ struct stat s;
+ gint status;
+
+ full_filename = (gchar*) g_malloc (strlen (directory) + 1
+ + strlen (filename) + 1);
+ strcpy (full_filename, directory);
+ strcat (full_filename, G_DIR_SEPARATOR_S);
+ strcat (full_filename, filename);
+
+ status = stat (full_filename, &s);
+ if (status == 0 && S_ISREG (s.st_mode))
+ return full_filename;
+ g_free (full_filename);
+ return NULL;
+}
+
--- /dev/null
+/*
+ * This file was created automatically by glade and fixed by bootstrap.sh
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+/*
+ * Standard gettext macros.
+ */
+#if defined( ENABLE_NLS ) && defined ( HAVE_GETTEXT )
+# include <libintl.h>
+# undef _
+# define _(String) dgettext (PACKAGE, String)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+
+/*
+ * Public Functions.
+ */
+
+/*
+ * This function returns a widget in a component created by Glade.
+ * Call it with the toplevel widget in the component (i.e. a window/dialog),
+ * or alternatively any widget in the component, and the name of the widget
+ * you want returned.
+ */
+GtkWidget* lookup_widget (GtkWidget *widget,
+ const gchar *widget_name);
+
+/* get_widget() is deprecated. Use lookup_widget instead. */
+#define get_widget lookup_widget
+
+/* Use this function to set the directory containing installed pixmaps. */
+void add_pixmap_directory (const gchar *directory);
+
+
+/*
+ * Private Functions.
+ */
+
+/* This is used to create the pixmaps in the interface. */
+GtkWidget* create_pixmap (GtkWidget *widget,
+ const gchar *filename);
+
--- /dev/null
+/*****************************************************************************
+ * menu.c : functions to handle menu items.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: menu.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ * Johan Bilien <jobi@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <sys/types.h> /* off_t */
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#ifdef MODULE_NAME_IS_gnome
+# include <gnome.h>
+#else
+# include <gtk/gtk.h>
+#endif
+
+#include <string.h>
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "playlist.h"
+#include "common.h"
+
+/*
+ * Local Prototypes
+ */
+static gint GtkLanguageMenus( gpointer , GtkWidget *, es_descriptor_t *, gint,
+ void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
+
+void GtkMenubarAudioToggle ( GtkCheckMenuItem *, gpointer );
+void GtkPopupAudioToggle ( GtkCheckMenuItem *, gpointer );
+void GtkMenubarSubtitleToggle( GtkCheckMenuItem *, gpointer );
+void GtkPopupSubtitleToggle ( GtkCheckMenuItem *, gpointer );
+static gint GtkTitleMenu( gpointer, GtkWidget *,
+ void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
+static gint GtkRadioMenu( intf_thread_t *, GtkWidget *, GSList *,
+ char *, int, int, int,
+ void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) );
+
+gint GtkSetupMenus( intf_thread_t * p_intf );
+
+/****************************************************************************
+ * Gtk*Toggle: callbacks to toggle the value of a checkmenuitem
+ ****************************************************************************
+ * We need separate functions for menubar and popup here since we can't use
+ * user_data to transmit intf_* and we need to refresh the other menu.
+ ****************************************************************************/
+
+#define GTKLANGTOGGLE( window, menu, type, callback, b_update ) \
+ intf_thread_t * p_intf; \
+ GtkWidget * p_menu; \
+ es_descriptor_t * p_es; \
+ \
+ p_intf = GtkGetIntf( menuitem ); \
+ \
+ if( !p_intf->p_sys->b_update ) \
+ { \
+ p_menu = GTK_WIDGET( gtk_object_get_data( \
+ GTK_OBJECT( p_intf->p_sys->window ), (menu) ) ); \
+ p_es = (es_descriptor_t*)user_data; \
+ \
+ input_ToggleES( p_intf->p_sys->p_input, \
+ p_es, menuitem->active ); \
+ \
+ p_intf->p_sys->b_update = menuitem->active; \
+ \
+ if( p_intf->p_sys->b_update ) \
+ { \
+ GtkLanguageMenus( p_intf, p_menu, p_es, type, callback ); \
+ } \
+ \
+ p_intf->p_sys->b_update = 0; \
+ }
+
+/*
+ * Audio
+ */
+
+void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ GTKLANGTOGGLE( p_popup, "popup_audio", AUDIO_ES,
+ GtkPopupAudioToggle, b_audio_update );
+}
+
+void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ GTKLANGTOGGLE( p_window, "menubar_audio", AUDIO_ES,
+ GtkMenubarAudioToggle, b_audio_update );
+}
+
+/*
+ * Subtitles
+ */
+
+void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ GTKLANGTOGGLE( p_popup, "popup_subpictures", SPU_ES,
+ GtkPopupSubtitleToggle, b_spu_update );
+}
+
+void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ GTKLANGTOGGLE( p_window, "menubar_subpictures", SPU_ES,
+ GtkMenubarSubtitleToggle, b_spu_update );
+}
+
+#undef GTKLANGTOGGLE
+
+/*
+ * Navigation
+ */
+
+void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( menuitem );
+
+ if( menuitem->active &&
+ !p_intf->p_sys->b_title_update &&
+ !p_intf->p_sys->b_chapter_update )
+ {
+ input_area_t *p_area;
+
+ gint i_title = DATA2TITLE( user_data );
+ gint i_chapter = DATA2CHAPTER( user_data );
+
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;
+
+ if( p_area != p_intf->p_sys->p_input->stream.pp_areas[i_title] )
+ {
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_title];
+ p_intf->p_sys->b_title_update = 1;
+ }
+
+ p_area->i_part = i_chapter;
+
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ p_intf->p_sys->b_chapter_update = 1;
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ GtkSetupMenus( p_intf );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+/*
+ * Program
+ */
+#define GTKPROGRAMTOGGLE( ) \
+ intf_thread_t * p_intf = GtkGetIntf( menuitem ); \
+ \
+ if( menuitem->active && !p_intf->p_sys->b_program_update ) \
+ { \
+ u16 i_program_id = (ptrdiff_t)user_data; \
+ \
+ input_ChangeProgram( p_intf->p_sys->p_input, i_program_id ); \
+ \
+ p_intf->p_sys->b_program_update = 1; \
+ \
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock ); \
+ GtkSetupMenus( p_intf ); \
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock ); \
+ \
+ p_intf->p_sys->b_program_update = 0; \
+ \
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY ); \
+ }
+
+void GtkMenubarProgramToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ GTKPROGRAMTOGGLE( );
+}
+
+void GtkPopupProgramToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ GTKPROGRAMTOGGLE( );
+}
+
+/*
+ * Title
+ */
+
+void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( menuitem );
+
+ if( menuitem->active && !p_intf->p_sys->b_title_update )
+ {
+ gint i_title = (gint)((long)user_data);
+ input_ChangeArea( p_intf->p_sys->p_input,
+ p_intf->p_sys->p_input->stream.pp_areas[i_title] );
+
+ p_intf->p_sys->b_title_update = 1;
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ GtkSetupMenus( p_intf );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ p_intf->p_sys->b_title_update = 0;
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+
+ }
+}
+
+/*
+ * Chapter
+ */
+
+void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
+{
+ intf_thread_t * p_intf;
+ input_area_t * p_area;
+ gint i_chapter;
+ GtkWidget * p_popup_menu;
+
+ p_intf = GtkGetIntf( menuitem );
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;
+ i_chapter = (gint)((long)user_data);
+
+ if( menuitem->active && !p_intf->p_sys->b_chapter_update )
+ {
+ p_area->i_part = i_chapter;
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ p_intf->p_sys->b_chapter_update = 1;
+ p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_popup ), "popup_navigation" ) );
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ p_intf->p_sys->b_chapter_update = 0;
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+
+/****************************************************************************
+ * Functions to generate menus
+ ****************************************************************************/
+
+/*****************************************************************************
+ * GtkRadioMenu: update interactive menus of the interface
+ *****************************************************************************
+ * Sets up menus with information from input
+ * Warning: since this function is designed to be called by management
+ * function, the interface lock has to be taken
+ *****************************************************************************/
+static gint GtkRadioMenu( intf_thread_t * p_intf,
+ GtkWidget * p_root, GSList * p_menu_group,
+ char * psz_item_name,
+ int i_start, int i_end, int i_selected,
+ void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
+{
+ char psz_name[ GTK_MENU_LABEL_SIZE ];
+ GtkWidget * p_menu;
+ GtkWidget * p_submenu;
+ GtkWidget * p_item_group;
+ GtkWidget * p_item;
+ GtkWidget * p_item_selected;
+ GSList * p_group;
+ gint i_item;
+
+ /* temporary hack to avoid blank menu when an open menu is removed */
+ if( GTK_MENU_ITEM(p_root)->submenu != NULL )
+ {
+ gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
+ }
+ /* removes previous menu */
+ gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
+ gtk_widget_set_sensitive( p_root, FALSE );
+
+ p_item_group = NULL;
+ p_submenu = NULL;
+ p_item_selected = NULL;
+ p_group = p_menu_group;
+
+ p_menu = gtk_menu_new();
+ gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
+
+ for( i_item = i_start ; i_item <= i_end ; i_item++ )
+ {
+ /* we group chapters in packets of ten for small screens */
+ if( ( i_item % 10 == i_start ) && ( i_end > 20 ) )
+ {
+ if( i_item != i_start )
+ {
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
+ p_submenu );
+ gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
+ }
+
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE,
+ "%ss %d to %d", psz_item_name, i_item, i_item + 9 );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+ p_item_group = gtk_menu_item_new_with_label( psz_name );
+ gtk_widget_show( p_item_group );
+ p_submenu = gtk_menu_new();
+ gtk_object_set_data( GTK_OBJECT( p_submenu ), "p_intf", p_intf );
+ }
+
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
+ psz_item_name, i_item );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+
+ p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
+ p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
+
+ if( i_selected == i_item )
+ {
+ p_item_selected = p_item;
+ }
+
+ gtk_widget_show( p_item );
+
+ /* setup signal hanling */
+ gtk_signal_connect( GTK_OBJECT( p_item ),
+ "toggled",
+ GTK_SIGNAL_FUNC( pf_toggle ),
+ (gpointer)((long)(i_item)) );
+
+ if( i_end > 20 )
+ {
+ gtk_menu_append( GTK_MENU( p_submenu ), p_item );
+ }
+ else
+ {
+ gtk_menu_append( GTK_MENU( p_menu ), p_item );
+ }
+ }
+
+ if( i_end > 20 )
+ {
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
+ gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
+ }
+
+ /* link the new menu to the title menu item */
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
+
+ /* toggle currently selected chapter
+ * We have to release the lock since input_ToggleES needs it */
+ if( p_item_selected != NULL )
+ {
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
+ TRUE );
+ }
+
+ /* be sure that menu is sensitive, if there are several items */
+ if( i_end > i_start )
+ {
+ gtk_widget_set_sensitive( p_root, TRUE );
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************
+ * GtkProgramMenu: update the programs menu of the interface
+ *****************************************************************************
+ * Builds the program menu according to what have been found in the PAT
+ * by the input. Usefull for multi-programs streams such as DVB ones.
+ *****************************************************************************/
+static gint GtkProgramMenu( gpointer p_data,
+ GtkWidget * p_root,
+ pgrm_descriptor_t * p_pgrm,
+ void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
+{
+ intf_thread_t * p_intf;
+ GtkWidget * p_menu;
+ GtkWidget * p_item;
+ GtkWidget * p_item_active;
+ GSList * p_group;
+ char psz_name[ GTK_MENU_LABEL_SIZE ];
+ gint i;
+
+ /* cast */
+ p_intf = (intf_thread_t *)p_data;
+
+ /* temporary hack to avoid blank menu when an open menu is removed */
+ if( GTK_MENU_ITEM(p_root)->submenu != NULL )
+ {
+ gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
+ }
+ /* removes previous menu */
+ gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
+ gtk_widget_set_sensitive( p_root, FALSE );
+
+ p_group = NULL;
+
+ /* menu container */
+ p_menu = gtk_menu_new();
+ gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
+
+ p_item_active = NULL;
+
+ /* create a set of program buttons and append them to the container */
+ for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_pgrm_number ; i++ )
+ {
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE, "id %d",
+ p_intf->p_sys->p_input->stream.pp_programs[i]->i_number );
+ psz_name[GTK_MENU_LABEL_SIZE-1] = '\0';
+
+ p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
+ p_group =
+ gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
+
+ if( p_pgrm == p_intf->p_sys->p_input->stream.pp_programs[i] )
+ {
+ /* don't lose p_item when we append into menu */
+ p_item_active = p_item;
+ }
+
+ gtk_widget_show( p_item );
+
+ /* setup signal hanling */
+ gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
+ GTK_SIGNAL_FUNC( pf_toggle ),
+ (gpointer)(ptrdiff_t)( p_intf->p_sys->p_input->
+ stream.pp_programs[i]->i_number ) );
+
+ gtk_menu_append( GTK_MENU( p_menu ), p_item );
+ }
+
+ /* link the new menu to the menubar item */
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
+
+ /* activation will call signals so we can only do it
+ * when submenu is attached to menu - to get intf_window
+ * We have to release the lock since input_ToggleES needs it */
+ if( p_item_active != NULL )
+ {
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
+ TRUE );
+ }
+
+ /* be sure that menu is sensitive if more than 1 program */
+ if( p_intf->p_sys->p_input->stream.i_pgrm_number > 1 )
+ {
+ gtk_widget_set_sensitive( p_root, TRUE );
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************
+ * GtkLanguageMenus: update interactive menus of the interface
+ *****************************************************************************
+ * Sets up menus with information from input:
+ * -languages
+ * -sub-pictures
+ * Warning: since this function is designed to be called by management
+ * function, the interface lock has to be taken
+ *****************************************************************************/
+static gint GtkLanguageMenus( gpointer p_data,
+ GtkWidget * p_root,
+ es_descriptor_t * p_es,
+ gint i_cat,
+ void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
+{
+ intf_thread_t * p_intf;
+ GtkWidget * p_menu;
+ GtkWidget * p_separator;
+ GtkWidget * p_item;
+ GtkWidget * p_item_active;
+ GSList * p_group;
+ char psz_name[ GTK_MENU_LABEL_SIZE ];
+ gint i_item;
+ gint i;
+
+ p_intf = (intf_thread_t *)p_data;
+
+ /* temporary hack to avoid blank menu when an open menu is removed */
+ if( GTK_MENU_ITEM(p_root)->submenu != NULL )
+ {
+ gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
+ }
+ /* removes previous menu */
+ gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
+ gtk_widget_set_sensitive( p_root, FALSE );
+
+ p_group = NULL;
+
+ /* menu container */
+ p_menu = gtk_menu_new();
+ gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
+
+ /* special case for "off" item */
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE, _("None") );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+
+ p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
+ p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
+
+ gtk_widget_show( p_item );
+
+ /* signal hanling for off */
+ gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
+ GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
+
+ gtk_menu_append( GTK_MENU( p_menu ), p_item );
+
+ p_separator = gtk_menu_item_new();
+ gtk_widget_set_sensitive( p_separator, FALSE );
+ gtk_widget_show( p_separator );
+ gtk_menu_append( GTK_MENU( p_menu ), p_separator );
+
+ p_item_active = NULL;
+ i_item = 0;
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+#define ES p_intf->p_sys->p_input->stream.pp_es[i]
+ /* create a set of language buttons and append them to the container */
+ for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ )
+ {
+ if( ( ES->i_cat == i_cat ) &&
+ ( !ES->p_pgrm ||
+ ES->p_pgrm ==
+ p_intf->p_sys->p_input->stream.p_selected_program ) )
+ {
+ i_item++;
+ strcpy( psz_name,
+ p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc );
+ if( psz_name[0] == '\0' )
+ {
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE,
+ "Language %d", i_item );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+ }
+
+ p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
+ p_group =
+ gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
+
+ if( p_es == p_intf->p_sys->p_input->stream.pp_es[i] )
+ {
+ /* don't lose p_item when we append into menu */
+ p_item_active = p_item;
+ }
+
+ gtk_widget_show( p_item );
+
+ /* setup signal hanling */
+ gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
+ GTK_SIGNAL_FUNC( pf_toggle ),
+ (gpointer)( p_intf->p_sys->p_input->stream.pp_es[i] ) );
+
+ gtk_menu_append( GTK_MENU( p_menu ), p_item );
+ }
+ }
+
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ /* link the new menu to the menubar item */
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
+
+ /* acitvation will call signals so we can only do it
+ * when submenu is attached to menu - to get intf_window
+ * We have to release the lock since input_ToggleES needs it */
+ if( p_item_active != NULL )
+ {
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
+ TRUE );
+ }
+
+ /* be sure that menu is sensitive if non empty */
+ if( i_item > 0 )
+ {
+ gtk_widget_set_sensitive( p_root, TRUE );
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************
+ * GtkTitleMenu: sets menus for titles and chapters selection
+ *****************************************************************************
+ * Generates two types of menus:
+ * -simple list of titles
+ * -cascaded lists of chapters for each title
+ *****************************************************************************/
+static gint GtkTitleMenu( gpointer p_data,
+ GtkWidget * p_navigation,
+ void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
+{
+ intf_thread_t * p_intf;
+ char psz_name[ GTK_MENU_LABEL_SIZE ];
+ GtkWidget * p_title_menu;
+ GtkWidget * p_title_submenu;
+ GtkWidget * p_title_item;
+ GtkWidget * p_item_active;
+ GtkWidget * p_chapter_menu;
+ GtkWidget * p_chapter_submenu;
+ GtkWidget * p_title_menu_item;
+ GtkWidget * p_chapter_menu_item;
+ GtkWidget * p_item;
+ GSList * p_title_group;
+ GSList * p_chapter_group;
+ gint i_title;
+ gint i_chapter;
+ gint i_title_nb;
+ gint i_chapter_nb;
+
+ /* cast */
+ p_intf = (intf_thread_t*)p_data;
+
+ /* temporary hack to avoid blank menu when an open menu is removed */
+ if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
+ {
+ gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
+ }
+ /* removes previous menu */
+ gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
+ gtk_widget_set_sensitive( p_navigation, FALSE );
+
+ p_title_menu = gtk_menu_new();
+ p_title_group = NULL;
+ p_title_submenu = NULL;
+ p_title_menu_item = NULL;
+ p_chapter_group = NULL;
+ p_chapter_submenu = NULL;
+ p_chapter_menu_item = NULL;
+ p_item_active = NULL;
+ i_title_nb = p_intf->p_sys->p_input->stream.i_area_nb;
+
+ gtk_object_set_data( GTK_OBJECT( p_title_menu ), "p_intf", p_intf );
+
+ /* loop on titles */
+ for( i_title = 0 ; i_title < i_title_nb ; i_title++ )
+ {
+ /* we group titles in packets of ten for small screens */
+ if( ( i_title % 10 == 0 ) && ( i_title_nb > 20 ) )
+ {
+ if( i_title != 0 )
+ {
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
+ p_title_submenu );
+ gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
+ }
+
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE,
+ "%d - %d", i_title, i_title + 9 );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+ p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
+ gtk_widget_show( p_title_menu_item );
+ p_title_submenu = gtk_menu_new();
+ gtk_object_set_data( GTK_OBJECT( p_title_submenu ),
+ "p_intf", p_intf );
+ }
+
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE, _("Title %d (%d)"), i_title,
+ p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+#if 0
+ if( pf_toggle == on_menubar_title_toggle )
+ {
+ p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
+ psz_name );
+ p_title_group =
+ gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
+
+ if( p_intf->p_sys->p_input->stream.pp_areas[i_title] ==
+ p_intf->p_sys->p_input->stream.p_selected_area )
+ {
+ p_item_active = p_title_item;
+ }
+
+ /* setup signal hanling */
+ gtk_signal_connect( GTK_OBJECT( p_title_item ),
+ "toggled",
+ GTK_SIGNAL_FUNC( pf_toggle ),
+ (gpointer)(p_intf->p_sys->p_input->stream.pp_areas[i_title]) );
+
+ if( p_intf->p_sys->p_input->stream.i_area_nb > 1 )
+ {
+ /* be sure that menu is sensitive */
+ gtk_widget_set_sensitive( p_navigation, TRUE );
+ }
+ }
+ else
+#endif
+ {
+ p_title_item = gtk_menu_item_new_with_label( psz_name );
+
+#if 1
+ p_chapter_menu = gtk_menu_new();
+ gtk_object_set_data( GTK_OBJECT( p_chapter_menu ),
+ "p_intf", p_intf );
+ i_chapter_nb =
+ p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb;
+
+ for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ )
+ {
+ /* we group chapters in packets of ten for small screens */
+ if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
+ {
+ if( i_chapter != 0 )
+ {
+ gtk_menu_item_set_submenu(
+ GTK_MENU_ITEM( p_chapter_menu_item ),
+ p_chapter_submenu );
+ gtk_menu_append( GTK_MENU( p_chapter_menu ),
+ p_chapter_menu_item );
+ }
+
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE,
+ "%d - %d", i_chapter + 1, i_chapter + 10 );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+ p_chapter_menu_item =
+ gtk_menu_item_new_with_label( psz_name );
+ gtk_widget_show( p_chapter_menu_item );
+ p_chapter_submenu = gtk_menu_new();
+ gtk_object_set_data( GTK_OBJECT( p_chapter_submenu ),
+ "p_intf", p_intf );
+ }
+
+ snprintf( psz_name, GTK_MENU_LABEL_SIZE,
+ _("Chapter %d"), i_chapter + 1 );
+ psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
+
+ p_item = gtk_radio_menu_item_new_with_label(
+ p_chapter_group, psz_name );
+ p_chapter_group = gtk_radio_menu_item_group(
+ GTK_RADIO_MENU_ITEM( p_item ) );
+ gtk_widget_show( p_item );
+
+#define p_area p_intf->p_sys->p_input->stream.pp_areas[i_title]
+ if( ( p_area ==
+ p_intf->p_sys->p_input->stream.p_selected_area ) &&
+ ( p_area->i_part == i_chapter + 1 ) )
+ {
+ p_item_active = p_item;
+ }
+#undef p_area
+
+ /* setup signal hanling */
+ gtk_signal_connect( GTK_OBJECT( p_item ),
+ "toggled",
+ GTK_SIGNAL_FUNC( pf_toggle ),
+ (gpointer)POS2DATA( i_title, i_chapter + 1) );
+
+ if( i_chapter_nb > 20 )
+ {
+ gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
+ }
+ else
+ {
+ gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
+ }
+ }
+
+ if( i_chapter_nb > 20 )
+ {
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
+ p_chapter_submenu );
+ gtk_menu_append( GTK_MENU( p_chapter_menu ),
+ p_chapter_menu_item );
+ }
+
+ /* link the new menu to the title menu item */
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
+ p_chapter_menu );
+
+ if( p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
+ {
+ /* be sure that menu is sensitive */
+ gtk_widget_set_sensitive( p_navigation, TRUE );
+ }
+#else
+ GtkRadioMenu( p_intf, p_title_item, p_chapter_group, _("Chapter"),
+ p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb,
+ 1, i_title * 100,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_part +
+ p_intf->p_sys->p_input->stream.p_selected_area->i_id *100,
+ pf_toggle );
+
+#endif
+ }
+ gtk_widget_show( p_title_item );
+
+ if( i_title_nb > 20 )
+ {
+ gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
+ }
+ else
+ {
+ gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
+ }
+ }
+
+ if( i_title_nb > 20 )
+ {
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
+ p_title_submenu );
+ gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
+ }
+
+ /* be sure that menu is sensitive */
+ gtk_widget_set_sensitive( p_title_menu, TRUE );
+
+ /* link the new menu to the menubar item */
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
+
+ /* Default selected chapter
+ * We have to release the lock since input_ToggleES needs it */
+ if( p_item_active != NULL )
+ {
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
+ TRUE );
+ }
+#if 0
+ if( p_intf->p_sys->p_input->stream.i_area_nb > 1 )
+ {
+ /* be sure that menu is sensitive */
+ gtk_widget_set_sensitive( p_navigation, TRUE );
+ }
+#endif
+
+ return TRUE;
+}
+
+/*****************************************************************************
+ * GtkSetupMenus: function that generates title/chapter/audio/subpic
+ * menus with help from preceding functions
+ *****************************************************************************
+ * Function called with the lock on stream
+ *****************************************************************************/
+gint GtkSetupMenus( intf_thread_t * p_intf )
+{
+ es_descriptor_t * p_audio_es;
+ es_descriptor_t * p_spu_es;
+ GtkWidget * p_menubar_menu;
+ GtkWidget * p_popup_menu;
+ gint i;
+
+ p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
+ p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update |
+ p_intf->p_sys->b_program_update;
+ p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update |
+ p_intf->p_sys->b_program_update;
+
+ if( p_intf->p_sys->b_program_update )
+ {
+ pgrm_descriptor_t * p_pgrm;
+
+ if( p_intf->p_sys->p_input->stream.p_new_program )
+ {
+ p_pgrm = p_intf->p_sys->p_input->stream.p_new_program;
+ }
+ else
+ {
+ p_pgrm = p_intf->p_sys->p_input->stream.p_selected_program;
+ }
+
+ p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "menubar_program" ) );
+ GtkProgramMenu( p_intf, p_menubar_menu, p_pgrm,
+ GtkMenubarProgramToggle );
+
+ p_intf->p_sys->b_program_update = 1;
+ p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_popup ), "popup_program" ) );
+ GtkProgramMenu( p_intf, p_popup_menu, p_pgrm,
+ GtkPopupProgramToggle );
+
+ p_intf->p_sys->b_program_update = 0;
+ }
+
+ if( p_intf->p_sys->b_title_update )
+ {
+ char psz_title[5];
+
+ p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "menubar_title" ) );
+ GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Title"), 0,
+ p_intf->p_sys->p_input->stream.i_area_nb - 1,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_id,
+ GtkMenubarTitleToggle );
+
+ snprintf( psz_title, 4, "%d",
+ p_intf->p_sys->p_input->stream.p_selected_area->i_id );
+ psz_title[ 4 ] = '\0';
+ gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
+
+ p_intf->p_sys->b_title_update = 0;
+ }
+
+ if( p_intf->p_sys->b_chapter_update )
+ {
+ char psz_chapter[5];
+
+ p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_popup ), "popup_navigation" ) );
+ GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
+#if 0
+ GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Title"), 0,
+ p_intf->p_sys->p_input->stream.i_area_nb - 1,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_id,
+ on_menubar_chapter_toggle );
+#endif
+
+ p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "menubar_chapter" ) );
+
+ GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Chapter"), 1,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_part_nb,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_part,
+ GtkMenubarChapterToggle );
+
+
+ snprintf( psz_chapter, 4, "%d",
+ p_intf->p_sys->p_input->stream.p_selected_area->i_part );
+ psz_chapter[ 4 ] = '\0';
+ gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
+
+ p_intf->p_sys->i_part =
+ p_intf->p_sys->p_input->stream.p_selected_area->i_part;
+
+ p_intf->p_sys->b_chapter_update = 0;
+ }
+
+ /* look for selected ES */
+ p_audio_es = NULL;
+ p_spu_es = NULL;
+
+ for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
+ {
+ if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
+ {
+ p_audio_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
+ }
+
+ if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
+ {
+ p_spu_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
+ }
+ }
+
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ /* audio menus */
+ if( p_intf->p_sys->b_audio_update )
+ {
+ /* find audio root menu */
+ p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "menubar_audio" ) );
+
+ p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_popup ), "popup_audio" ) );
+
+ p_intf->p_sys->b_audio_update = 1;
+ GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
+ GtkMenubarAudioToggle );
+ p_intf->p_sys->b_audio_update = 1;
+ GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
+ GtkPopupAudioToggle );
+
+ p_intf->p_sys->b_audio_update = 0;
+ }
+
+ /* sub picture menus */
+ if( p_intf->p_sys->b_spu_update )
+ {
+ /* find spu root menu */
+ p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_window ), "menubar_subpictures" ) );
+
+ p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_popup ), "popup_subpictures" ) );
+
+ p_intf->p_sys->b_spu_update = 1;
+ GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
+ GtkMenubarSubtitleToggle );
+ p_intf->p_sys->b_spu_update = 1;
+ GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
+ GtkPopupSubtitleToggle );
+
+ p_intf->p_sys->b_spu_update = 0;
+ }
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ return TRUE;
+}
+
--- /dev/null
+/*****************************************************************************
+ * gtk_menu.h: prototypes for menu functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: menu.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+gint GtkSetupMenus( intf_thread_t * );
+
+/*****************************************************************************
+ * String sizes
+ *****************************************************************************/
+#define GTK_MENU_LABEL_SIZE 64
+
+/*****************************************************************************
+ * Convert user_data structures to title and chapter information
+ *****************************************************************************/
+#define DATA2TITLE( user_data ) ( (gint)((long)(user_data)) >> 16 )
+#define DATA2CHAPTER( user_data ) ( (gint)((long)(user_data)) & 0xffff )
+#define POS2DATA( title, chapter ) ( 0 + ( ((title) << 16) \
+ | ((chapter) & 0xffff)) )
+
--- /dev/null
+/*****************************************************************************
+ * gtk_modules.c : functions to build modules configuration boxes.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: modules.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <sys/types.h> /* off_t */
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#ifdef MODULE_NAME_IS_gnome
+# include <gnome.h>
+#else
+# include <gtk/gtk.h>
+#endif
+
+#include <string.h>
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "playlist.h"
+#include "common.h"
+
+gboolean GtkModulesShow( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t *p_intf = GtkGetIntf( widget );
+
+ if( !GTK_IS_WIDGET( p_intf->p_sys->p_modules ) )
+ {
+// p_intf->p_sys->p_modules = create_intf_modules();
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_modules ),
+ "p_intf", p_intf );
+ }
+ gtk_widget_show( p_intf->p_sys->p_modules );
+ gdk_window_raise( p_intf->p_sys->p_modules->window );
+
+ return FALSE;
+}
+
+void GtkModulesCancel( GtkButton * button, gpointer user_data )
+{
+ intf_thread_t *p_intf = GtkGetIntf( button );
+
+ gtk_widget_hide( p_intf->p_sys->p_modules );
+}
+
--- /dev/null
+/*****************************************************************************
+ * gtk_modules.h: prototypes for modules functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: modules.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+gboolean GtkModulesShow ( GtkWidget *, gpointer );
+void GtkModulesCancel ( GtkButton * button, gpointer );
+
--- /dev/null
+/*****************************************************************************
+ * gtk_open.c : functions to handle file/disc/network open widgets.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: open.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <sys/types.h> /* off_t */
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#ifdef MODULE_NAME_IS_gnome
+# include <gnome.h>
+#else
+# include <gtk/gtk.h>
+#endif
+
+#include <string.h>
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "playlist.h"
+#include "common.h"
+
+#include "netutils.h"
+
+static void GtkOpenShow( intf_thread_t *, int );
+
+static void GtkFileOpenChanged ( GtkWidget *, gpointer );
+static void GtkDiscOpenChanged ( GtkWidget *, gpointer );
+static void GtkNetworkOpenChanged ( GtkWidget *, gpointer );
+static void GtkSatOpenChanged ( GtkWidget *, gpointer );
+
+/*****************************************************************************
+ * File requester callbacks
+ *****************************************************************************
+ * The following callbacks are related to the file requester.
+ *****************************************************************************/
+void GtkFileShow( GtkButton * button, gpointer user_data )
+{
+ GtkWidget * p_file = create_intf_file();
+
+ gtk_object_set_data( GTK_OBJECT(p_file), "p_intf", GtkGetIntf( button ) );
+
+ gtk_widget_show( p_file );
+ gdk_window_raise( p_file->window );
+}
+
+void GtkFileOk( GtkButton * button, gpointer user_data )
+{
+ GtkWidget * p_file = gtk_widget_get_toplevel( GTK_WIDGET (button) );
+
+ char *psz_filename;
+ intf_thread_t * p_intf = GtkGetIntf( button );
+
+ /* add the new file to the dialog box */
+ psz_filename =
+ gtk_file_selection_get_filename( GTK_FILE_SELECTION( p_file ) );
+ gtk_entry_set_text( GTK_ENTRY( lookup_widget( p_intf->p_sys->p_open,
+ "entry_file" ) ),
+ psz_filename );
+ gtk_widget_destroy( p_file );
+}
+
+void GtkFileCancel( GtkButton * button, gpointer user_data )
+{
+ gtk_widget_destroy( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+/*****************************************************************************
+ * Open file callbacks
+ *****************************************************************************
+ * The following callbacks are related to the file tab.
+ *****************************************************************************/
+gboolean GtkFileOpenShow( GtkWidget *widget,
+ gpointer user_data )
+{
+ GtkOpenShow( GtkGetIntf( widget ), 0 );
+
+ return TRUE;
+}
+
+static void GtkFileOpenChanged( GtkWidget * button, gpointer user_data )
+{
+ GString * p_target;
+
+ p_target = g_string_new( "file://" );
+ g_string_append( p_target,
+ gtk_entry_get_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "entry_file" ) ) ) );
+ gtk_entry_set_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "entry_open" ) ),
+ p_target->str );
+ g_string_free( p_target, TRUE );
+}
+
+/*****************************************************************************
+ * Open disc callbacks
+ *****************************************************************************
+ * The following callbacks are related to the disc manager.
+ *****************************************************************************/
+gboolean GtkDiscOpenShow( GtkWidget *widget,
+ gpointer user_data)
+{
+ GtkOpenShow( GtkGetIntf( widget ), 1 );
+
+ return TRUE;
+}
+
+void GtkDiscOpenDvd( GtkToggleButton * togglebutton, gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( togglebutton );
+ char *psz_device;
+
+ if( togglebutton->active
+ && (psz_device = config_GetPsz( p_intf, "dvd" )) )
+ {
+ gtk_entry_set_text(
+ GTK_ENTRY( lookup_widget( GTK_WIDGET(togglebutton),
+ "disc_name" ) ), psz_device );
+ free( psz_device );
+ }
+}
+
+void GtkDiscOpenVcd( GtkToggleButton * togglebutton, gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( togglebutton );
+ char *psz_device;
+
+ if( togglebutton->active
+ && (psz_device = config_GetPsz( p_intf, "vcd" )) )
+ {
+ gtk_entry_set_text(
+ GTK_ENTRY( lookup_widget( GTK_WIDGET(togglebutton),
+ "disc_name" ) ), psz_device );
+ free( psz_device );
+ }
+}
+
+static void GtkDiscOpenChanged( GtkWidget * button, gpointer user_data )
+{
+ GString * p_target = g_string_new( "" );
+
+ if( GTK_TOGGLE_BUTTON( lookup_widget( GTK_WIDGET(button),
+ "disc_dvd" ) )->active )
+ {
+ g_string_append( p_target, "dvd://" );
+ }
+ else if( GTK_TOGGLE_BUTTON( lookup_widget( GTK_WIDGET(button),
+ "disc_vcd" ) )->active )
+ {
+ g_string_append( p_target, "vcd://" );
+ }
+
+ g_string_append( p_target,
+ gtk_entry_get_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "disc_name" ) ) ) );
+ g_string_sprintfa( p_target, "@%i,%i",
+ gtk_spin_button_get_value_as_int(
+ GTK_SPIN_BUTTON( lookup_widget(
+ GTK_WIDGET(button), "disc_title" ) ) ),
+ gtk_spin_button_get_value_as_int(
+ GTK_SPIN_BUTTON( lookup_widget(
+ GTK_WIDGET(button), "disc_chapter" ) ) ) );
+
+ gtk_entry_set_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "entry_open" ) ),
+ p_target->str );
+ g_string_free( p_target, TRUE );
+}
+
+/*****************************************************************************
+ * Network stream callbacks
+ *****************************************************************************
+ * The following callbacks are related to the network stream manager.
+ *****************************************************************************/
+gboolean GtkNetworkOpenShow( GtkWidget *widget,
+ gpointer user_data )
+{
+ GtkOpenShow( GtkGetIntf( widget ), 2 );
+
+ return TRUE;
+}
+
+static void GtkNetworkOpenChanged( GtkWidget *button, gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+ GString * p_target = g_string_new( "" );
+
+ unsigned int i_port;
+ vlc_bool_t b_channel;
+
+ /* Manage channel server */
+ b_channel = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(
+ lookup_widget( GTK_WIDGET(button), "network_channel" ) ) );
+ config_PutInt( p_intf, "network-channel", b_channel );
+
+#define SELECTED( s ) GTK_TOGGLE_BUTTON( lookup_widget( GTK_WIDGET(button), \
+ (s) ) )->active
+ /* Check which option was chosen */
+ if( SELECTED( "network_udp" ) )
+ {
+ g_string_append( p_target, "udp://" );
+ i_port = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(
+ lookup_widget( GTK_WIDGET(button),
+ "network_udp_port" ) ) );
+ if( i_port != 1234 )
+ {
+ g_string_sprintfa( p_target, "@:%i", i_port );
+ }
+ }
+ else if( SELECTED( "network_multicast" ) )
+ {
+ g_string_sprintfa( p_target, "udp://@%s",
+ gtk_entry_get_text( GTK_ENTRY(
+ lookup_widget( GTK_WIDGET(button),
+ "network_multicast_address" ) ) ) );
+ i_port = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(
+ lookup_widget( GTK_WIDGET(button),
+ "network_multicast_port" ) ) );
+ if( i_port != 1234 )
+ {
+ g_string_sprintfa( p_target, ":%i", i_port );
+ }
+ }
+ else if( SELECTED( "network_channel" ) )
+ {
+ char * psz_channel;
+ unsigned int i_channel_port;
+
+ if( p_intf->p_vlc->p_channel == NULL )
+ {
+ network_ChannelCreate( p_intf );
+ }
+
+ psz_channel = gtk_entry_get_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "network_channel_address" ) ) );
+ i_channel_port = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(
+ lookup_widget( GTK_WIDGET(button), "network_channel_port" ) ) );
+
+ config_PutPsz( p_intf, "channel-server", psz_channel );
+ if( i_channel_port < 65536 )
+ {
+ config_PutInt( p_intf, "channel-port", i_channel_port );
+ }
+
+ /* FIXME: we should use a playlist server instead */
+ g_string_append( p_target, "udp://" );
+ }
+ else if( SELECTED( "network_http" ) )
+ {
+ g_string_sprintfa( p_target, "http://%s",
+ gtk_entry_get_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "network_http_url" ) ) ) );
+ }
+
+ gtk_entry_set_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "entry_open" ) ),
+ p_target->str );
+ g_string_free( p_target, TRUE );
+}
+
+void GtkNetworkOpenUDP( GtkToggleButton *togglebutton,
+ gpointer user_data )
+{
+ GtkWidget * p_open;
+
+ p_open = gtk_widget_get_toplevel( GTK_WIDGET (togglebutton) );
+
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_udp_port_label" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_udp_port" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+
+ GtkNetworkOpenChanged( GTK_WIDGET( togglebutton ), user_data );
+}
+
+void GtkNetworkOpenMulticast( GtkToggleButton *togglebutton,
+ gpointer user_data )
+{
+ GtkWidget * p_open;
+
+ p_open = gtk_widget_get_toplevel( GTK_WIDGET (togglebutton) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_multicast_address_label" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_multicast_address_combo" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_multicast_port_label" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_multicast_port" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+
+ GtkNetworkOpenChanged( GTK_WIDGET( togglebutton ), user_data );
+}
+
+
+void GtkNetworkOpenChannel( GtkToggleButton *togglebutton,
+ gpointer user_data )
+{
+ GtkWidget * p_open;
+
+ p_open = gtk_widget_get_toplevel( GTK_WIDGET (togglebutton) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_channel_address_label" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_channel_address_combo" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_channel_port_label" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_channel_port" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+
+ GtkNetworkOpenChanged( GTK_WIDGET( togglebutton ), user_data );
+}
+
+void GtkNetworkOpenHTTP( GtkToggleButton *togglebutton,
+ gpointer user_data )
+{
+ GtkWidget * p_open;
+
+ p_open = gtk_widget_get_toplevel( GTK_WIDGET (togglebutton) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_http_url_label" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+ gtk_widget_set_sensitive( gtk_object_get_data( GTK_OBJECT( p_open ),
+ "network_http_url" ),
+ gtk_toggle_button_get_active( togglebutton ) );
+
+ GtkNetworkOpenChanged( GTK_WIDGET( togglebutton ), user_data );
+}
+
+/*****************************************************************************
+ * Open satellite callbacks
+ *****************************************************************************
+ * The following callbacks are related to the satellite card manager.
+ *****************************************************************************/
+gboolean GtkSatOpenShow( GtkWidget *widget,
+ gpointer user_data)
+{
+ GtkOpenShow( GtkGetIntf( widget ), 3 );
+
+ return TRUE;
+}
+
+static void GtkSatOpenChanged( GtkWidget * button, gpointer user_data )
+{
+ GString * p_target = g_string_new( "" );
+
+ g_string_sprintfa( p_target, "%s://%d,%d,%ld,%d", "satellite",
+ gtk_spin_button_get_value_as_int(
+ GTK_SPIN_BUTTON( lookup_widget(
+ GTK_WIDGET(button), "sat_freq" ) ) ),
+ !GTK_TOGGLE_BUTTON( lookup_widget( GTK_WIDGET( button ),
+ "sat_pol_vert" ) )->active,
+ strtol( gtk_entry_get_text( GTK_ENTRY( GTK_COMBO(
+ lookup_widget( GTK_WIDGET( button ), "sat_fec" )
+ )->entry ) ), NULL, 10 ),
+ gtk_spin_button_get_value_as_int(
+ GTK_SPIN_BUTTON( lookup_widget(
+ GTK_WIDGET(button), "sat_srate" ) ) ) );
+
+ gtk_entry_set_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "entry_open" ) ),
+ p_target->str );
+ g_string_free( p_target, TRUE );
+}
+
+void
+GtkSatOpenToggle (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ if( togglebutton->active )
+ {
+ GtkSatOpenChanged( GTK_WIDGET( togglebutton ), user_data );
+ }
+}
+
+/******************************
+ ******************************/
+
+static void GtkOpenShow( intf_thread_t *p_intf, int i_page )
+{
+ char *psz_var;
+ GtkWidget *p_notebook;
+
+ /* If we have already created this window, do nothing */
+ if( GTK_IS_WIDGET( p_intf->p_sys->p_open ) )
+ {
+ goto setpage;
+ }
+
+ p_intf->p_sys->p_open = create_intf_open();
+ gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_open ),
+ "p_intf", p_intf );
+
+ /* FileOpen stuff */
+ psz_var = config_GetPsz( p_intf, "search-path" );
+ if( psz_var )
+ {
+ gtk_file_selection_set_filename( GTK_FILE_SELECTION(
+ p_intf->p_sys->p_open ), psz_var );
+ free( psz_var );
+ }
+
+ /* Network stuff */
+ gtk_spin_button_set_value( GTK_SPIN_BUTTON( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_open ), "network_udp_port" ) ),
+ config_GetInt( p_intf, "server-port" ) );
+
+ psz_var = config_GetPsz( p_intf, "channel-server" );
+ if( psz_var )
+ {
+ gtk_entry_set_text( GTK_ENTRY( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_open ), "network_channel_address" ) ),
+ psz_var );
+ free( psz_var );
+ }
+
+ gtk_spin_button_set_value( GTK_SPIN_BUTTON( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_open ), "network_channel_port" ) ),
+ config_GetInt( p_intf, "channel-port" ) );
+
+ gtk_toggle_button_set_active( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_open ), "network_channel" ),
+ config_GetInt( p_intf, "network-channel" ) );
+
+ /* Set the right page */
+setpage:
+ p_notebook = lookup_widget( GTK_WIDGET( p_intf->p_sys->p_open ),
+ "open_notebook" );
+ gtk_notebook_set_page( GTK_NOTEBOOK( p_notebook ), i_page );
+
+ gtk_widget_show( p_intf->p_sys->p_open );
+ gdk_window_raise( p_intf->p_sys->p_open->window );
+}
+
+void GtkOpenOk( GtkButton * button, gpointer user_data )
+{
+ /* Check what was pressed */
+ intf_thread_t * p_intf = GtkGetIntf( button );
+ playlist_t * p_playlist;
+ GtkCList * p_playlist_clist;
+ gchar * psz_target;
+
+ /* Hide the dialog box */
+ gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+
+ /* Update the playlist */
+ p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ psz_target = gtk_entry_get_text( GTK_ENTRY( lookup_widget(
+ GTK_WIDGET(button), "entry_open" ) ) );
+ playlist_Add( p_playlist, (char*)psz_target,
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+
+ /* catch the GTK CList */
+ p_playlist_clist = GTK_CLIST( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+ /* update the plugin display */
+ GtkRebuildCList( p_playlist_clist, p_playlist );
+
+ vlc_object_release( p_playlist );
+}
+
+void GtkOpenCancel( GtkButton * button, gpointer user_data )
+{
+ gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+void GtkOpenChanged( GtkWidget * button, gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( button );
+ GtkWidget *p_notebook;
+ int i_page;
+
+ p_notebook = lookup_widget( GTK_WIDGET( p_intf->p_sys->p_open ),
+ "open_notebook" );
+ i_page = gtk_notebook_get_current_page( GTK_NOTEBOOK( p_notebook ) );
+
+ switch( i_page )
+ {
+ case 0:
+ GtkFileOpenChanged( button, NULL );
+ break;
+ case 1:
+ GtkDiscOpenChanged( button, NULL );
+ break;
+ case 2:
+ GtkNetworkOpenChanged( button, NULL );
+ break;
+ case 3:
+ GtkSatOpenChanged( button, NULL );
+ break;
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * gtk_open.h: prototypes for open functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: open.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+gboolean GtkFileOpenShow ( GtkWidget *, gpointer );
+void GtkFileOpenCancel ( GtkButton *, gpointer );
+void GtkFileOpenOk ( GtkButton *, gpointer );
+
+gboolean GtkDiscOpenShow ( GtkWidget *, gpointer );
+void GtkDiscOpenDvd ( GtkToggleButton *, gpointer );
+void GtkDiscOpenVcd ( GtkToggleButton *, gpointer );
+void GtkDiscOpenOk ( GtkButton *, gpointer );
+void GtkDiscOpenCancel ( GtkButton *, gpointer );
+
+gboolean GtkNetworkOpenShow ( GtkWidget *, gpointer );
+void GtkNetworkOpenOk ( GtkButton *, gpointer );
+void GtkNetworkOpenCancel ( GtkButton *, gpointer );
+void GtkNetworkOpenBroadcast( GtkToggleButton *, gpointer );
+void GtkNetworkOpenChannel ( GtkToggleButton *, gpointer );
+
--- /dev/null
+/*****************************************************************************
+ * gtk_playlist.c : Interface for the playlist dialog
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: playlist.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Pierre Baillet <oct@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <sys/types.h> /* for readdir and stat stuff */
+
+#if (!defined( WIN32 ) || defined(__MINGW32__))
+/* Mingw has its own version of dirent */
+# include <dirent.h>
+#endif
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef MODULE_NAME_IS_gnome
+# include <gnome.h>
+#else
+# include <gtk/gtk.h>
+#endif
+
+#include "gtk_callbacks.h"
+#include "gtk_interface.h"
+#include "gtk_support.h"
+
+#include "playlist.h"
+#include "common.h"
+
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+static void UrlDecode ( char * );
+static GList * GtkReadFiles ( intf_thread_t *, gchar * );
+
+/****************************************************************************
+ * Playlist window management
+ ****************************************************************************/
+gboolean GtkPlaylistShow( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return FALSE;
+ }
+
+ if( GTK_WIDGET_VISIBLE( p_intf->p_sys->p_playwin ) )
+ {
+ gtk_widget_hide( p_intf->p_sys->p_playwin );
+ }
+ else
+ {
+ GtkCList * p_clist;
+
+ p_clist = GTK_CLIST( gtk_object_get_data(
+ GTK_OBJECT( p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+ GtkRebuildCList( p_clist , p_playlist );
+ gtk_widget_show( p_intf->p_sys->p_playwin );
+ gdk_window_raise( p_intf->p_sys->p_playwin->window );
+ }
+
+ vlc_object_release( p_playlist );
+
+ return TRUE;
+}
+
+
+void GtkPlaylistOk( GtkButton * button, gpointer user_data )
+{
+ gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+
+void GtkPlaylistCancel( GtkButton * button, gpointer user_data )
+{
+ gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+
+
+gboolean GtkPlaylistPrev( GtkWidget *widget,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return FALSE;
+ }
+
+ playlist_Prev( p_playlist );
+ vlc_object_release( p_playlist );
+
+ return TRUE;
+}
+
+
+gboolean GtkPlaylistNext( GtkWidget *widget,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return FALSE;
+ }
+
+ playlist_Next( p_playlist );
+ vlc_object_release( p_playlist );
+
+ return TRUE;
+}
+
+/****************************************************************************
+ * Playlist core functions
+ ****************************************************************************/
+void GtkPlaylistAddUrl( GtkMenuItem * menuitem, gpointer user_data )
+{
+
+}
+
+
+void GtkPlaylistDeleteAll( GtkMenuItem * menuitem, gpointer user_data )
+{
+
+}
+
+
+void GtkPlaylistDeleteSelected( GtkMenuItem * menuitem, gpointer user_data )
+{
+ /* user wants to delete a file in the queue */
+ GList * p_selection;
+ GtkCList * p_clist;
+
+ intf_thread_t * p_intf = GtkGetIntf( menuitem);
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ /* lock the struct */
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ p_clist = GTK_CLIST( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+
+ p_selection = p_clist->selection;
+
+ if( g_list_length( p_selection ) )
+ {
+ /* reverse-sort so that we can delete from the furthest
+ * to the closest item to delete...
+ */
+ p_selection = g_list_sort( p_selection, GtkCompareItems );
+ g_list_foreach( p_selection, GtkDeleteGListItem, p_playlist );
+ /* rebuild the CList */
+ GtkRebuildCList( p_clist, p_playlist );
+ }
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ vlc_object_release( p_playlist );
+}
+
+void GtkPlaylistCrop( GtkMenuItem * menuitem, gpointer user_data )
+{
+ /* Ok, this is a really small thing, but, hey, it works and
+ might be useful, who knows ? */
+ GtkPlaylistInvert( menuitem, user_data );
+ GtkPlaylistDeleteSelected( menuitem, user_data );
+}
+
+void GtkPlaylistInvert( GtkMenuItem * menuitem, gpointer user_data )
+{
+ GtkCList * p_clist;
+ int * pi_selected;
+ int i_length;
+ int i_dummy;
+
+ /* catch the thread back */
+ intf_thread_t *p_intf = GtkGetIntf( menuitem );
+
+ /* lock the struct */
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ p_clist = GTK_CLIST( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+
+ gtk_clist_freeze( p_clist );
+
+ /* have to copy the selection to an int *
+ I wasn't able to copy the g_list to another g_list
+ glib only does pointer copies, not real copies :( */
+
+ i_length = g_list_length( p_clist->selection );
+ pi_selected = malloc( sizeof(int) * i_length );
+
+ for( i_dummy = 0 ; i_dummy < i_length ; i_dummy++ )
+ {
+ pi_selected[i_dummy] =
+ GPOINTER_TO_UINT( g_list_nth_data( p_clist->selection, i_dummy ) );
+ }
+
+ gtk_clist_select_all( p_clist );
+
+ for( i_dummy = 0; i_dummy < i_length; i_dummy++ )
+ {
+ gtk_clist_unselect_row( p_clist, pi_selected[i_dummy], 0 );
+ }
+
+ gtk_clist_thaw( p_clist );
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ free( pi_selected );
+}
+
+void GtkPlaylistSelect( GtkMenuItem * menuitem, gpointer user_data)
+{
+
+}
+
+gboolean GtkPlaylistEvent( GtkWidget * widget,
+ GdkEvent * event,
+ gpointer user_data)
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return FALSE;
+ }
+
+ if( ( event->button ).type == GDK_2BUTTON_PRESS )
+ {
+ GtkCList * p_clist;
+ gint i_row;
+ gint i_col;
+
+ p_clist = GTK_CLIST( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+
+ if( gtk_clist_get_selection_info( p_clist, (event->button).x,
+ (event->button).y, &i_row, &i_col ) == 1 )
+ {
+ playlist_Goto( p_playlist, i_row );
+ }
+
+ vlc_object_release( p_playlist );
+ return TRUE;
+ }
+
+ vlc_object_release( p_playlist );
+ return FALSE;
+}
+
+void GtkPlaylistDragData( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ GtkCList * p_clist;
+ gint i_row;
+ gint i_col;
+
+ p_clist = GTK_CLIST( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+
+ if( gtk_clist_get_selection_info( p_clist, x, y, &i_row, &i_col ) == 1 )
+ {
+ /* we are dropping somewhere into the clist items */
+ GtkDropDataReceived( p_intf, data, info, i_row - 1 );
+ }
+ else
+ {
+ /* otherwise, put that at the end of the playlist */
+ GtkDropDataReceived( p_intf, data, info, PLAYLIST_END );
+ }
+}
+
+
+gboolean GtkPlaylistDragMotion( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x,
+ gint y,
+ guint time,
+ gpointer user_data )
+{
+ GtkCList * p_clist;
+ gint i_row;
+ gint i_col;
+ int i_dummy;
+ GdkColor color;
+
+ intf_thread_t * p_intf = GtkGetIntf( widget );
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return FALSE;
+ }
+
+ p_clist = GTK_CLIST( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+
+ if( !GTK_WIDGET_TOPLEVEL(widget) )
+ {
+ gdk_window_raise( p_intf->p_sys->p_playwin->window );
+ }
+
+ color.red = 0xffff;
+ color.blue = 0xffff;
+ color.green = 0xffff;
+
+ gtk_clist_freeze( p_clist );
+
+ for( i_dummy = 0; i_dummy < p_clist->rows; i_dummy++)
+ {
+ gtk_clist_set_background( p_clist, i_dummy , &color );
+ }
+
+ color.red = 0;
+ color.blue = 0xf000;
+ color.green = 0x9000;
+ if( gtk_clist_get_selection_info( p_clist, x, y, &i_row, &i_col ) == 1 )
+ {
+ gtk_clist_set_background ( p_clist, i_row - 1, &color );
+ gtk_clist_set_background ( p_clist, i_row, &color );
+ }
+ else
+ {
+ gtk_clist_set_background ( p_clist, p_clist->rows - 1, &color );
+ }
+
+ color.red = 0xffff;
+ color.blue = 0;
+ color.green = 0;
+ vlc_mutex_lock( &p_playlist->object_lock );
+ gtk_clist_set_background( p_clist, p_playlist->i_index, &color );
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+
+ gtk_clist_thaw( p_clist );
+
+ return TRUE;
+}
+
+void GtkDropDataReceived( intf_thread_t * p_intf,
+ GtkSelectionData * p_data, guint i_info, int i_position)
+{
+ /* first we'll have to split against all the '\n' we have */
+ gchar * p_protocol;
+ gchar * p_temp;
+ gchar * p_next;
+ gchar * p_string = p_data->data ;
+ GList * p_files = NULL;
+ GtkCList * p_clist;
+
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ /* if this has been URLencoded, decode it
+ *
+ * Is it a good thing to do it in place ?
+ * probably not...
+ */
+ if( i_info == DROP_ACCEPT_TEXT_URI_LIST )
+ {
+ UrlDecode( p_string );
+ }
+
+ /* this cuts string into single file drops */
+ /* this code was borrowed from xmms, thx guys :) */
+ while( *p_string)
+ {
+ p_next = strchr( p_string, '\n' );
+ if( p_next )
+ {
+ if( *( p_next - 1 ) == '\r' )
+ {
+ *( p_next - 1) = '\0';
+ }
+ *p_next = '\0';
+ }
+
+ /* do we have a protocol or something ? */
+ p_temp = strstr( p_string, ":" );
+ if( p_temp != NULL && p_temp[0] != '\0' )
+ {
+ char i_save;
+
+ i_save = p_temp[0];
+ p_temp[0] = '\0';
+ p_protocol = strdup( p_string );
+ p_temp[0] = i_save;
+ p_temp++;
+
+ /* Allowed things are proto: or proto:// */
+ if( p_temp[0] == '/' && p_temp[1] == '/')
+ {
+ /* eat two '/'s */
+ p_temp += 2;
+ }
+ msg_Dbg( p_intf, "playlist protocol '%s', target '%s'",
+ p_protocol, p_temp );
+ }
+ else
+ {
+ p_protocol = strdup( "" );
+ }
+
+ /* if it uses the file protocol we can do something, else, sorry :(
+ * I think this is a good choice for now, as we don't have any
+ * ability to read http:// or ftp:// files
+ * what about adding dvd:// to the list of authorized proto ? */
+
+ if( strcmp( p_protocol, "file:" ) == 0 )
+ {
+ p_files = g_list_concat( p_files,
+ GtkReadFiles( p_intf, p_string ) );
+ }
+ else
+ {
+ p_files = g_list_concat( p_files,
+ g_list_append( NULL, g_strdup( p_string ) ) );
+ }
+
+ /* free the malloc and go on... */
+ free( p_protocol );
+
+ if( p_next == NULL )
+ {
+ break;
+ }
+ p_string = p_next + 1;
+ }
+
+ /* At this point, we have a nice big list maybe NULL */
+ if( p_files != NULL )
+ {
+ /* lock the interface */
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ msg_Dbg( p_intf, "adding %d elements", g_list_length( p_files ) );
+ GtkAppendList( p_playlist, i_position, p_files );
+
+ /* get the CList and rebuild it. */
+ p_clist = GTK_CLIST( lookup_widget( p_intf->p_sys->p_playwin,
+ "playlist_clist" ) );
+ GtkRebuildCList( p_clist , p_playlist );
+
+ /* unlock the interface */
+ vlc_mutex_unlock( &p_intf->change_lock );
+ }
+
+ vlc_object_release( p_playlist );
+}
+
+
+void GtkDeleteGListItem( gpointer data, gpointer param )
+{
+ int i_cur_row = (long)data;
+ playlist_t * p_playlist = param;
+
+ playlist_Delete( p_playlist, i_cur_row );
+}
+
+
+gint GtkCompareItems( gconstpointer a, gconstpointer b )
+{
+ return b - a;
+}
+
+
+/* check a file (string) against supposed valid extension */
+int GtkHasValidExtension( gchar * psz_filename )
+{
+ char * ppsz_ext[6] = { "mpg", "mpeg", "vob", "mp2", "ts", "ps" };
+ int i_ext = 6;
+ int i_dummy;
+
+ gchar * psz_ext = strrchr( psz_filename, '.' ) + sizeof( char );
+
+ for( i_dummy = 0 ; i_dummy < i_ext ; i_dummy++ )
+ {
+ if( strcmp( psz_ext, ppsz_ext[i_dummy] ) == 0 )
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* recursive function: descend into folders and build a list of
+ * valid filenames */
+static GList * GtkReadFiles( intf_thread_t * p_intf, gchar * psz_fsname )
+{
+ struct stat statbuf;
+ GList * p_current = NULL;
+
+ /* get the attributes of this file */
+ stat( psz_fsname, &statbuf );
+
+ /* is it a regular file ? */
+ if( S_ISREG( statbuf.st_mode ) )
+ {
+ if( GtkHasValidExtension( psz_fsname ) )
+ {
+ msg_Dbg( p_intf, "%s is a valid file, stacking on the playlist",
+ psz_fsname );
+ return g_list_append( NULL, g_strdup( psz_fsname ) );
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ /* is it a directory (should we check for symlinks ?) */
+ else if( S_ISDIR( statbuf.st_mode ) )
+ {
+ /* have to cd into this dir */
+ DIR * p_current_dir = opendir( psz_fsname );
+ struct dirent * p_dir_content;
+
+ msg_Dbg( p_intf, "%s is a folder", psz_fsname );
+
+ if( p_current_dir == NULL )
+ {
+ /* something went bad, get out of here ! */
+ return p_current;
+ }
+ p_dir_content = readdir( p_current_dir );
+
+ /* while we still have entries in the directory */
+ while( p_dir_content != NULL )
+ {
+ /* if it is "." or "..", forget it */
+ if( ( strcmp( p_dir_content->d_name, "." ) != 0 ) &&
+ ( strcmp( p_dir_content->d_name, ".." ) != 0 ) )
+ {
+ /* else build the new directory by adding
+ fsname "/" and the current entry name
+ (kludgy :()
+ */
+ char * psz_newfs = malloc ( 2 + strlen( psz_fsname ) +
+ strlen( p_dir_content->d_name ) * sizeof(char) );
+ strcpy( psz_newfs, psz_fsname );
+ strcpy( psz_newfs + strlen( psz_fsname ) + 1,
+ p_dir_content->d_name );
+ psz_newfs[strlen( psz_fsname )] = '/';
+
+ p_current = g_list_concat( p_current,
+ GtkReadFiles( p_intf, psz_newfs ) );
+
+ g_free( psz_newfs );
+ }
+ p_dir_content = readdir( p_current_dir );
+ }
+ return p_current;
+ }
+ return NULL;
+}
+
+/* add items in a playlist
+ * when i_pos==-1 add to the end of the list...
+ */
+int GtkAppendList( playlist_t * p_playlist, int i_pos, GList * p_list )
+{
+ guint i_dummy;
+ guint i_length;
+
+ i_length = g_list_length( p_list );
+
+ for( i_dummy = 0; i_dummy < i_length ; i_dummy++ )
+ {
+ playlist_Add( p_playlist,
+ /* ok; this is a really nasty trick to insert
+ the item where they are suppose to go but, hey
+ this works :P (btw, you are really nasty too) */
+ g_list_nth_data( p_list, i_dummy ),
+ i_dummy == 0 ? PLAYLIST_INSERT | PLAYLIST_GO : PLAYLIST_INSERT,
+ i_pos == PLAYLIST_END ? PLAYLIST_END : ( i_pos + i_dummy ) );
+ }
+
+ return 0;
+}
+
+/* statis timeouted function */
+void GtkPlayListManage( intf_thread_t * p_intf )
+{
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ GtkCList * p_clist;
+
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ /* this thing really sucks for now :( */
+
+ /* TODO speak more with src/playlist/playlist.c */
+ if( GTK_IS_WIDGET( p_intf->p_sys->p_playwin ) )
+ {
+ p_clist = GTK_CLIST( gtk_object_get_data( GTK_OBJECT(
+ p_intf->p_sys->p_playwin ), "playlist_clist" ) );
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+
+ if( p_intf->p_sys->i_playing != p_playlist->i_index )
+ {
+ GdkColor color;
+
+ color.red = 0xffff;
+ color.blue = 0;
+ color.green = 0;
+
+ gtk_clist_set_background( p_clist, p_playlist->i_index, &color );
+
+ if( p_intf->p_sys->i_playing != -1 )
+ {
+ color.red = 0xffff;
+ color.blue = 0xffff;
+ color.green = 0xffff;
+ gtk_clist_set_background( p_clist, p_intf->p_sys->i_playing,
+ &color);
+ }
+ p_intf->p_sys->i_playing = p_playlist->i_index;
+ }
+
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ }
+
+ vlc_object_release( p_playlist );
+}
+
+void GtkRebuildCList( GtkCList * p_clist, playlist_t * p_playlist )
+{
+ int i_dummy;
+ gchar * ppsz_text[2];
+ GdkColor red;
+ red.red = 65535;
+ red.blue = 0;
+ red.green = 0;
+
+ gtk_clist_freeze( p_clist );
+ gtk_clist_clear( p_clist );
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+ for( i_dummy = p_playlist->i_size ; i_dummy-- ; )
+ {
+ ppsz_text[0] = p_playlist->pp_items[i_dummy]->psz_name;
+ ppsz_text[1] = "no info";
+ gtk_clist_insert( p_clist, 0, ppsz_text );
+ }
+ vlc_mutex_unlock( &p_playlist->object_lock );
+
+ gtk_clist_set_background( p_clist, p_playlist->i_index, &red);
+ gtk_clist_thaw( p_clist );
+}
+
+/* URL-decode a file: URL path, return NULL if it's not what we expect */
+static void UrlDecode( char *encoded_path )
+{
+ char *tmp = NULL, *cur = NULL, *ext = NULL;
+ int realchar;
+
+ if( !encoded_path || *encoded_path == '\0' )
+ {
+ return;
+ }
+
+ cur = encoded_path ;
+
+ tmp = calloc(strlen(encoded_path) + 1, sizeof(char) );
+
+ while ( ( ext = strchr(cur, '%') ) != NULL)
+ {
+ strncat(tmp, cur, (ext - cur) / sizeof(char));
+ ext++;
+
+ if (!sscanf(ext, "%2x", &realchar))
+ {
+ free(tmp);
+ return;
+ }
+
+ tmp[strlen(tmp)] = (char)realchar;
+
+ cur = ext + 2;
+ }
+
+ strcat(tmp, cur);
+ strcpy(encoded_path,tmp);
+}
+
--- /dev/null
+/*****************************************************************************
+ * gtk_playlist.h : Playlist functions for the Gtk plugin.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: playlist.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Pierre Baillet <oct@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+void GtkPlaylistDeleteAll ( GtkMenuItem *, gpointer );
+void GtkPlaylistDeleteSelected( GtkMenuItem *, gpointer );
+void GtkPlaylistCrop ( GtkMenuItem *, gpointer );
+void GtkPlaylistInvert ( GtkMenuItem *, gpointer );
+void GtkPlaylistSelect ( GtkMenuItem *, gpointer );
+void GtkPlaylistOk ( GtkButton *, gpointer );
+void GtkPlaylistCancel ( GtkButton *, gpointer );
+void GtkPlaylistAddUrl ( GtkMenuItem *, gpointer );
+
+gint GtkCompareItems ( gconstpointer, gconstpointer );
+int GtkHasValidExtension ( gchar * );
+
+gboolean GtkPlaylistShow ( GtkWidget *, gpointer );
+gboolean GtkPlaylistPrev ( GtkWidget *, gpointer );
+gboolean GtkPlaylistNext ( GtkWidget *, gpointer );
+gboolean GtkPlaylistDragMotion( GtkWidget *, GdkDragContext *,
+ gint, gint, guint, gpointer );
+gboolean GtkPlaylistEvent ( GtkWidget *, GdkEvent *, gpointer );
+void GtkPlaylistDragData ( GtkWidget *, GdkDragContext *,
+ gint, gint, GtkSelectionData *,
+ guint, guint, gpointer );
+void GtkDeleteGListItem ( gpointer, gpointer );
+
+void GtkDropDataReceived ( intf_thread_t *, GtkSelectionData *, guint, int );
+int GtkAppendList ( playlist_t *, int, GList * );
+void GtkRebuildCList ( GtkCList *, playlist_t * );
+void GtkPlayListManage ( intf_thread_t * );
+
--- /dev/null
+/*****************************************************************************
+ * gtk_preferences.c: functions to handle the preferences dialog box.
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: preferences.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ * Loïc Minier <lool@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble: Our main job is to build a nice interface from the modules config
+ * structure. Once this is done, we need to track each change made by the
+ * user to the data contained in this interface so that when/if he decides to
+ * apply his changes we can quickly commit them into the modules config
+ * structure. (for this last task we use a GHashTable to accumulate the
+ * changes. To commit them, we then just have to circle through it )
+ *
+ *****************************************************************************/
+#include <sys/types.h> /* off_t */
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#ifdef MODULE_NAME_IS_gnome
+# include <gnome.h>
+#else
+# include <gtk/gtk.h>
+#endif
+
+#include <string.h>
+
+#include "gtk_support.h"
+
+#include "common.h"
+#include "preferences.h"
+
+/* local functions */
+static void GtkCreateConfigDialog( char *, intf_thread_t * );
+
+static void GtkConfigOk ( GtkButton *, gpointer );
+static void GtkConfigApply ( GtkButton *, gpointer );
+static void GtkConfigCancel ( GtkButton *, gpointer );
+static void GtkConfigSave ( GtkButton *, gpointer );
+
+static void GtkConfigDialogDestroyed ( GtkObject *, gpointer );
+
+static void GtkStringChanged ( GtkEditable *, gpointer );
+static void GtkIntChanged ( GtkEditable *, gpointer );
+static void GtkFloatChanged ( GtkEditable *, gpointer );
+static void GtkBoolChanged ( GtkToggleButton *, gpointer );
+
+static void GtkFreeHashTable ( GtkObject *object );
+static void GtkFreeHashValue ( gpointer, gpointer, gpointer );
+static gboolean GtkSaveHashValue ( gpointer, gpointer, gpointer );
+
+static void GtkModuleConfigure ( GtkButton *, gpointer );
+static void GtkModuleSelected ( GtkButton *, gpointer );
+static void GtkModuleHighlighted ( GtkCList *, int, int, GdkEventButton *,
+ gpointer );
+
+/****************************************************************************
+ * Callback for menuitems: display configuration interface window
+ ****************************************************************************/
+void GtkPreferencesShow( GtkMenuItem * menuitem, gpointer user_data )
+{
+ intf_thread_t * p_intf;
+
+ p_intf = GtkGetIntf( menuitem );
+
+ GtkCreateConfigDialog( "main", p_intf );
+}
+
+/****************************************************************************
+ * GtkCreateConfigDialog: dynamically creates the configuration dialog
+ * box from all the configuration data provided by the selected module.
+ ****************************************************************************/
+
+/* create a new tooltipped area */
+#define TOOLTIP( text ) \
+ /* create an event box to catch some events */ \
+ item_event_box = gtk_event_box_new(); \
+ /* add a tooltip on mouseover */ \
+ gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips, \
+ item_event_box, text, "" ); \
+ gtk_container_set_border_width( GTK_CONTAINER(item_event_box), 4 );
+
+/* draws a right aligned label in side of a widget */
+#define LABEL_AND_WIDGET( label_text, widget, tooltip ) \
+ gtk_table_resize( GTK_TABLE(category_table), ++rows, 2 ); \
+ item_align = gtk_alignment_new( 1, .5, 0, 0 ); \
+ item_label = gtk_label_new( label_text ); \
+ gtk_container_add( GTK_CONTAINER(item_align), item_label ); \
+ gtk_table_attach_defaults( GTK_TABLE(category_table), item_align, \
+ 0, 1, rows - 1, rows ); \
+ item_align = gtk_alignment_new( 0, .5, .5, 0 ); \
+ gtk_container_add( GTK_CONTAINER(item_align), widget ); \
+ TOOLTIP(tooltip) \
+ gtk_container_add( GTK_CONTAINER(item_event_box), item_align ); \
+ gtk_table_attach_defaults( GTK_TABLE(category_table), item_event_box, \
+ 1, 2, rows - 1, rows );
+
+static void GtkCreateConfigDialog( char *psz_module_name,
+ intf_thread_t *p_intf )
+{
+ module_t *p_module, *p_module_bis;
+ module_config_t *p_item;
+
+ guint rows = 0;
+
+ GHashTable *config_hash_table;
+
+ GtkWidget *item_event_box;
+
+ GtkWidget *config_dialog;
+ GtkWidget *config_dialog_vbox;
+ GtkWidget *config_notebook;
+
+ GtkWidget *category_table = NULL;
+ GtkWidget *category_label = NULL;
+
+#ifndef MODULE_NAME_IS_gnome
+ GtkWidget *dialog_action_area;
+#endif
+
+ GtkWidget *ok_button;
+ GtkWidget *apply_button;
+ GtkWidget *save_button;
+ GtkWidget *cancel_button;
+
+ GtkWidget *item_align;
+ GtkWidget *item_frame;
+ GtkWidget *item_hbox;
+ GtkWidget *item_label;
+ GtkWidget *item_vbox;
+ GtkWidget *item_combo;
+ GtkWidget *string_entry;
+ GtkWidget *integer_spinbutton;
+ GtkWidget *float_spinbutton;
+ GtkObject *item_adj;
+ GtkWidget *bool_checkbutton;
+ GtkWidget *module_clist;
+ GtkWidget *module_config_button;
+ GtkWidget *module_select_button;
+
+ gint category_max_height;
+
+ /* Check if the dialog box is already opened because we don't want to
+ * duplicate identical dialog windows. */
+ config_dialog = (GtkWidget *)gtk_object_get_data(
+ GTK_OBJECT(p_intf->p_sys->p_window), psz_module_name );
+ if( config_dialog )
+ {
+ /* Yeah it was open */
+ gtk_widget_grab_focus( config_dialog );
+ return;
+ }
+
+
+ /* Look for the selected module */
+ for( p_module = p_intf->p_vlc->p_module_bank->first ; p_module != NULL ;
+ p_module = p_module->next )
+ {
+
+ if( psz_module_name
+ && !strcmp( psz_module_name, p_module->psz_object_name ) )
+ {
+ break;
+ }
+ }
+ if( !p_module ) return;
+
+ /* We found it, now we can start building its configuration interface */
+ /* Create the configuration dialog box */
+
+#ifdef MODULE_NAME_IS_gnome
+ config_dialog = gnome_dialog_new( p_module->psz_longname, NULL );
+ config_dialog_vbox = GNOME_DIALOG(config_dialog)->vbox;
+#else
+ config_dialog = gtk_dialog_new();
+ gtk_window_set_title( GTK_WINDOW(config_dialog), p_module->psz_longname );
+ config_dialog_vbox = GTK_DIALOG(config_dialog)->vbox;
+#endif
+
+ gtk_object_set_data( GTK_OBJECT(config_dialog), "p_intf", p_intf );
+
+ category_max_height = config_GetInt( p_intf, MODULE_STRING "-prefs-maxh" );
+
+ gtk_window_set_policy( GTK_WINDOW(config_dialog), TRUE, TRUE, FALSE );
+ gtk_container_set_border_width( GTK_CONTAINER(config_dialog_vbox), 0 );
+
+ /* Create our config hash table and associate it with the dialog box */
+ config_hash_table = g_hash_table_new( NULL, NULL );
+ gtk_object_set_data( GTK_OBJECT(config_dialog),
+ "config_hash_table", config_hash_table );
+
+ /* Create notebook */
+ config_notebook = gtk_notebook_new();
+ gtk_notebook_set_scrollable( GTK_NOTEBOOK(config_notebook), TRUE );
+ gtk_container_add( GTK_CONTAINER(config_dialog_vbox), config_notebook );
+
+ /* Enumerate config options and add corresponding config boxes */
+ p_item = p_module->p_config;
+ do
+ {
+ switch( p_item->i_type )
+ {
+
+ case CONFIG_HINT_CATEGORY:
+ case CONFIG_HINT_END:
+
+ /*
+ * Before we start building the interface for the new category, we
+ * must close/finish the previous one we were generating.
+ */
+ if( category_table )
+ {
+ GtkWidget *_scrolled_window;
+ GtkWidget *_viewport;
+ GtkWidget *_vbox;
+ GtkRequisition _requisition;
+
+ /* create a vbox to deal with EXPAND/FILL issues in the
+ * notebook page, and pack it with the previously generated
+ * category_table */
+ _vbox = gtk_vbox_new( FALSE, 0 );
+ gtk_container_set_border_width( GTK_CONTAINER(_vbox), 4 );
+ gtk_box_pack_start( GTK_BOX(_vbox), category_table,
+ FALSE, FALSE, 0 );
+
+ /* create a new scrolled window that will contain all of the
+ * above. */
+ _scrolled_window = gtk_scrolled_window_new( NULL, NULL );
+ gtk_scrolled_window_set_policy(
+ GTK_SCROLLED_WINDOW(_scrolled_window), GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC );
+ /* add scrolled window as a notebook page */
+ gtk_notebook_append_page( GTK_NOTEBOOK(config_notebook),
+ _scrolled_window, category_label );
+ /* pack the vbox into the scrolled window */
+ _viewport = gtk_viewport_new( NULL, NULL );
+ gtk_viewport_set_shadow_type( GTK_VIEWPORT(_viewport),
+ GTK_SHADOW_NONE );
+ gtk_container_add( GTK_CONTAINER(_viewport), _vbox );
+ gtk_container_add( GTK_CONTAINER(_scrolled_window),
+ _viewport );
+
+ /* set the size of the scrolled window to the size of the
+ * child widget */
+ gtk_widget_show_all( _vbox );
+ gtk_widget_size_request( _vbox, &_requisition );
+ if( _requisition.height > category_max_height )
+ gtk_widget_set_usize( _scrolled_window, -1,
+ category_max_height );
+ else
+ gtk_widget_set_usize( _scrolled_window, -1,
+ _requisition.height );
+
+ }
+
+ /*
+ * Now we can start taking care of the new category
+ */
+
+ if( p_item->i_type == CONFIG_HINT_CATEGORY )
+ {
+ /* create a new table for right-left alignment of children */
+ category_table = gtk_table_new( 0, 0, FALSE );
+ gtk_table_set_col_spacings( GTK_TABLE(category_table), 4 );
+ rows = 0;
+
+ /* create a new category label */
+ category_label = gtk_label_new( p_item->psz_text );
+ }
+
+ break;
+
+ case CONFIG_ITEM_MODULE:
+
+ item_frame = gtk_frame_new( p_item->psz_text );
+
+ gtk_table_resize( GTK_TABLE(category_table), ++rows, 2 );
+ gtk_table_attach_defaults( GTK_TABLE(category_table), item_frame,
+ 0, 2, rows - 1, rows );
+
+ item_vbox = gtk_vbox_new( FALSE, 4 );
+ gtk_container_add( GTK_CONTAINER(item_frame), item_vbox );
+
+ /* create a new clist widget */
+ {
+ gchar * titles[] = { _("Name"), _("Description") };
+
+ module_clist = gtk_clist_new_with_titles( 2, titles );
+ }
+ gtk_object_set_data( GTK_OBJECT(module_clist), "p_intf", p_intf );
+ gtk_clist_column_titles_passive( GTK_CLIST(module_clist) );
+ gtk_clist_set_selection_mode( GTK_CLIST(module_clist),
+ GTK_SELECTION_SINGLE);
+ gtk_container_add( GTK_CONTAINER(item_vbox), module_clist );
+
+ /* build a list of available modules */
+ {
+ gchar * entry[2];
+ char * psz_capability;
+
+ for( p_module_bis = p_intf->p_vlc->p_module_bank->first ;
+ p_module_bis != NULL ;
+ p_module_bis = p_module_bis->next )
+ {
+#if 0 /* FIXME */
+ for( psz_capability = p_module_bis->pp_capabilities[0] ;
+ *psz_capability ;
+ psz_capability++ )
+ {
+ if( !strcmp( psz_capability, p_item->psz_type ) )
+ {
+ entry[0] = p_module_bis->psz_object_name;
+ entry[1] = p_module_bis->psz_longname;
+ gtk_clist_append( GTK_CLIST(module_clist), entry );
+ break;
+ }
+ }
+#endif
+ }
+ }
+
+ gtk_clist_set_column_auto_resize( GTK_CLIST(module_clist),
+ 0, TRUE );
+ gtk_clist_set_column_auto_resize( GTK_CLIST(module_clist),
+ 1, TRUE );
+
+ /* connect signals to the modules list */
+ gtk_signal_connect( GTK_OBJECT(module_clist), "select_row",
+ GTK_SIGNAL_FUNC(GtkModuleHighlighted),
+ NULL );
+
+ /* hbox holding the "select" and "configure" buttons */
+ item_hbox = gtk_hbox_new( FALSE, 4 );
+ gtk_container_add( GTK_CONTAINER(item_vbox), item_hbox);
+
+ /* add configure button */
+ module_config_button =
+ gtk_button_new_with_label( _("Configure") );
+ gtk_widget_set_sensitive( module_config_button, FALSE );
+ gtk_container_add( GTK_CONTAINER(item_hbox),
+ module_config_button );
+ gtk_object_set_data( GTK_OBJECT(module_config_button),
+ "p_intf", p_intf );
+ gtk_object_set_data( GTK_OBJECT(module_clist),
+ "config_button", module_config_button );
+
+ /* add select button */
+ module_select_button =
+ gtk_button_new_with_label( _("Select") );
+ gtk_container_add( GTK_CONTAINER(item_hbox),
+ module_select_button );
+ /* add a tooltip on mouseover */
+ gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips,
+ module_select_button,
+ p_item->psz_longtext, "" );
+
+ /* hbox holding the "selected" label and text input */
+ item_hbox = gtk_hbox_new( FALSE, 4 );
+ gtk_container_add( GTK_CONTAINER(item_vbox), item_hbox);
+ /* add new label */
+ item_label = gtk_label_new( _("Selected:") );
+ gtk_container_add( GTK_CONTAINER(item_hbox), item_label );
+
+ /* add input box with default value */
+ string_entry = gtk_entry_new();
+ gtk_object_set_data( GTK_OBJECT(module_clist),
+ "module_entry", string_entry );
+ gtk_container_add( GTK_CONTAINER(item_hbox), string_entry );
+ vlc_mutex_lock( p_item->p_lock );
+ gtk_entry_set_text( GTK_ENTRY(string_entry),
+ p_item->psz_value ? p_item->psz_value : "" );
+ vlc_mutex_unlock( p_item->p_lock );
+ /* add a tooltip on mouseover */
+ gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips,
+ string_entry, p_item->psz_longtext, "" );
+
+ /* connect signals to the buttons */
+ gtk_signal_connect( GTK_OBJECT(module_config_button), "clicked",
+ GTK_SIGNAL_FUNC(GtkModuleConfigure),
+ (gpointer)module_clist );
+ gtk_signal_connect( GTK_OBJECT(module_select_button), "clicked",
+ GTK_SIGNAL_FUNC(GtkModuleSelected),
+ (gpointer)module_clist );
+
+ /* connect signal to track changes in the text box */
+ gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
+ p_item->psz_name );
+ gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
+ GTK_SIGNAL_FUNC(GtkStringChanged),
+ (gpointer)config_dialog );
+ break;
+
+ case CONFIG_ITEM_STRING:
+ case CONFIG_ITEM_FILE:
+
+ if( !p_item->ppsz_list )
+ {
+ /* add input box with default value */
+ item_combo = string_entry = gtk_entry_new();
+ }
+ else
+ {
+ /* add combo box with default value */
+ GList *items = NULL;
+ int i;
+
+ for( i=0; p_item->ppsz_list[i]; i++ )
+ items = g_list_append( items, p_item->ppsz_list[i] );
+
+ item_combo = gtk_combo_new();
+ string_entry = GTK_COMBO(item_combo)->entry;
+ gtk_combo_set_popdown_strings( GTK_COMBO(item_combo),
+ items );
+
+ }
+
+ vlc_mutex_lock( p_item->p_lock );
+ gtk_entry_set_text( GTK_ENTRY(string_entry),
+ p_item->psz_value ? p_item->psz_value : "" );
+ vlc_mutex_unlock( p_item->p_lock );
+
+ /* connect signal to track changes in the text box */
+ gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
+ p_item->psz_name );
+ gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
+ GTK_SIGNAL_FUNC(GtkStringChanged),
+ (gpointer)config_dialog );
+
+ LABEL_AND_WIDGET( p_item->psz_text,
+ item_combo, p_item->psz_longtext );
+ break;
+
+ case CONFIG_ITEM_INTEGER:
+
+ /* add input box with default value */
+ item_adj = gtk_adjustment_new( p_item->i_value,
+ -1, 99999, 1, 10, 10 );
+ integer_spinbutton = gtk_spin_button_new( GTK_ADJUSTMENT(item_adj),
+ 1, 0 );
+
+ /* connect signal to track changes in the spinbutton value */
+ gtk_object_set_data( GTK_OBJECT(integer_spinbutton),
+ "config_option", p_item->psz_name );
+ gtk_signal_connect( GTK_OBJECT(integer_spinbutton), "changed",
+ GTK_SIGNAL_FUNC(GtkIntChanged),
+ (gpointer)config_dialog );
+
+ LABEL_AND_WIDGET( p_item->psz_text,
+ integer_spinbutton, p_item->psz_longtext );
+ break;
+
+ case CONFIG_ITEM_FLOAT:
+
+ /* add input box with default value */
+ item_adj = gtk_adjustment_new( p_item->f_value,
+ 0, 99999, 0.01, 10, 10 );
+ float_spinbutton = gtk_spin_button_new( GTK_ADJUSTMENT(item_adj),
+ 0.01, 2 );
+
+ /* connect signal to track changes in the spinbutton value */
+ gtk_object_set_data( GTK_OBJECT(float_spinbutton),
+ "config_option", p_item->psz_name );
+ gtk_signal_connect( GTK_OBJECT(float_spinbutton), "changed",
+ GTK_SIGNAL_FUNC(GtkFloatChanged),
+ (gpointer)config_dialog );
+
+ LABEL_AND_WIDGET( p_item->psz_text,
+ float_spinbutton, p_item->psz_longtext );
+ break;
+
+ case CONFIG_ITEM_BOOL:
+
+ /* add check button */
+ bool_checkbutton = gtk_check_button_new();
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(bool_checkbutton),
+ p_item->i_value );
+
+ /* connect signal to track changes in the button state */
+ gtk_object_set_data( GTK_OBJECT(bool_checkbutton), "config_option",
+ p_item->psz_name );
+ gtk_signal_connect( GTK_OBJECT(bool_checkbutton), "toggled",
+ GTK_SIGNAL_FUNC(GtkBoolChanged),
+ (gpointer)config_dialog );
+
+ LABEL_AND_WIDGET( p_item->psz_text,
+ bool_checkbutton, p_item->psz_longtext );
+ break;
+
+ }
+
+ }
+ while( p_item->i_type != CONFIG_HINT_END && p_item++ );
+
+#ifndef MODULE_NAME_IS_gnome
+ /* Now let's add the action buttons at the bottom of the page */
+ dialog_action_area = GTK_DIALOG(config_dialog)->action_area;
+ gtk_container_set_border_width( GTK_CONTAINER(dialog_action_area), 4 );
+
+ /* add a new table for the config option */
+ item_hbox = gtk_hbox_new( FALSE, 0 );
+ gtk_box_pack_end( GTK_BOX(dialog_action_area), item_hbox,
+ TRUE, FALSE, 0 );
+ item_hbox = gtk_hbox_new( FALSE, 0 );
+ gtk_box_pack_end( GTK_BOX(dialog_action_area), item_hbox,
+ TRUE, FALSE, 0 );
+#endif
+
+ /* Create the OK button */
+#ifdef MODULE_NAME_IS_gnome
+ gnome_dialog_append_button( GNOME_DIALOG(config_dialog),
+ GNOME_STOCK_BUTTON_OK );
+ ok_button =
+ GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
+
+ gnome_dialog_append_button( GNOME_DIALOG(config_dialog),
+ GNOME_STOCK_BUTTON_APPLY );
+ apply_button =
+ GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
+
+ gnome_dialog_append_button_with_pixmap(
+ GNOME_DIALOG(config_dialog), _("Save"), GNOME_STOCK_PIXMAP_SAVE );
+ save_button =
+ GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
+
+ gnome_dialog_append_button( GNOME_DIALOG(config_dialog),
+ GNOME_STOCK_BUTTON_CANCEL );
+ cancel_button =
+ GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
+#else
+ ok_button = gtk_button_new_with_label( _("OK") );
+ gtk_box_pack_start( GTK_BOX(dialog_action_area), ok_button,
+ TRUE, TRUE, 0 );
+
+ apply_button = gtk_button_new_with_label( _("Apply") );
+ gtk_box_pack_start( GTK_BOX(dialog_action_area), apply_button,
+ TRUE, TRUE, 0 );
+
+ save_button = gtk_button_new_with_label( _("Save") );
+ gtk_box_pack_start( GTK_BOX(dialog_action_area), save_button,
+ TRUE, TRUE, 0 );
+
+ cancel_button = gtk_button_new_with_label( _("Cancel") );
+ gtk_box_pack_start( GTK_BOX(dialog_action_area), cancel_button,
+ TRUE, TRUE, 0 );
+#endif
+
+ gtk_signal_connect( GTK_OBJECT(ok_button), "clicked",
+ GTK_SIGNAL_FUNC(GtkConfigOk),
+ config_dialog );
+ gtk_widget_set_sensitive( apply_button, FALSE );
+ gtk_object_set_data( GTK_OBJECT(config_dialog), "apply_button",
+ apply_button );
+ gtk_signal_connect( GTK_OBJECT(apply_button), "clicked",
+ GTK_SIGNAL_FUNC(GtkConfigApply),
+ config_dialog );
+ gtk_signal_connect( GTK_OBJECT(save_button), "clicked",
+ GTK_SIGNAL_FUNC(GtkConfigSave),
+ config_dialog );
+ gtk_signal_connect( GTK_OBJECT(cancel_button), "clicked",
+ GTK_SIGNAL_FUNC(GtkConfigCancel),
+ config_dialog );
+
+
+
+ /* Ok, job done successfully. Let's keep a reference to the dialog box */
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
+ psz_module_name, config_dialog );
+ gtk_object_set_data( GTK_OBJECT(config_dialog), "psz_module_name",
+ psz_module_name );
+
+ /* we want this ref to be destroyed if the object is destroyed */
+ gtk_signal_connect( GTK_OBJECT(config_dialog), "destroy",
+ GTK_SIGNAL_FUNC(GtkConfigDialogDestroyed),
+ (gpointer)p_intf );
+
+ gtk_widget_show_all( config_dialog );
+}
+
+#undef LABEL_AND_WIDGET
+#undef TOOLTIP
+
+/****************************************************************************
+ * GtkConfigApply: store the changes to the config inside the modules
+ * configuration structure and clear the hash table.
+ ****************************************************************************/
+void GtkConfigApply( GtkButton * button, gpointer user_data )
+{
+ intf_thread_t *p_intf;
+ GHashTable *hash_table;
+ GtkWidget *apply_button;
+
+ hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "config_hash_table" );
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "p_intf" );
+ g_hash_table_foreach_remove( hash_table, GtkSaveHashValue, (void*)p_intf );
+
+ /* change the highlight status of the Apply button */
+ apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "apply_button" );
+ gtk_widget_set_sensitive( apply_button, FALSE );
+}
+
+void GtkConfigOk( GtkButton * button, gpointer user_data )
+{
+ GtkConfigApply( button, user_data );
+ gtk_widget_destroy( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+
+void GtkConfigCancel( GtkButton * button, gpointer user_data )
+{
+ gtk_widget_destroy( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
+}
+
+void GtkConfigSave( GtkButton * button, gpointer user_data )
+{
+ intf_thread_t *p_intf;
+
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "p_intf" );
+ GtkConfigApply( button, user_data );
+ config_SaveConfigFile( p_intf, NULL );
+}
+
+/****************************************************************************
+ * GtkModuleHighlighted: display module description when an entry is selected
+ * in the clist, and activate the configure button if necessary.
+ ****************************************************************************/
+void GtkModuleHighlighted( GtkCList *module_clist, int row, int column,
+ GdkEventButton *event, gpointer user_data )
+{
+ intf_thread_t *p_intf;
+ GtkWidget *config_button;
+ module_t *p_module;
+ char *psz_name;
+
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(module_clist),
+ "p_intf" );
+
+ if( gtk_clist_get_text( GTK_CLIST(module_clist), row, 0, &psz_name ) )
+ {
+ /* look for module 'psz_name' */
+ for( p_module = p_intf->p_vlc->p_module_bank->first ;
+ p_module != NULL ;
+ p_module = p_module->next )
+ {
+ if( !strcmp( p_module->psz_object_name, psz_name ) )
+ {
+ gtk_object_set_data( GTK_OBJECT(module_clist),
+ "module_highlighted", p_module );
+ config_button = gtk_object_get_data( GTK_OBJECT(module_clist),
+ "config_button" );
+ if( p_module->i_config_items )
+ gtk_widget_set_sensitive( config_button, TRUE );
+ else
+ gtk_widget_set_sensitive( config_button, FALSE );
+
+ break;
+ }
+ }
+
+ }
+}
+
+/****************************************************************************
+ * GtkModuleConfigure: display module configuration dialog box.
+ ****************************************************************************/
+void GtkModuleConfigure( GtkButton *button, gpointer user_data )
+{
+ module_t *p_module;
+ intf_thread_t *p_intf;
+
+ p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "module_highlighted" );
+
+ if( !p_module ) return;
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(button),
+ "p_intf" );
+ GtkCreateConfigDialog( p_module->psz_object_name, (gpointer)p_intf );
+
+}
+
+/****************************************************************************
+ * GtkModuleSelected: select module.
+ ****************************************************************************/
+void GtkModuleSelected( GtkButton *button, gpointer user_data )
+{
+ module_t *p_module;
+ GtkWidget *widget;
+
+ p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "module_highlighted" );
+ widget = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "module_entry" );
+ if( !p_module ) return;
+
+ gtk_entry_set_text( GTK_ENTRY(widget), p_module->psz_object_name );
+
+}
+
+/****************************************************************************
+ * GtkStringChanged: signal called when the user changes a string value.
+ ****************************************************************************/
+static void GtkStringChanged( GtkEditable *editable, gpointer user_data )
+{
+ intf_thread_t *p_intf;
+ module_config_t *p_config;
+ GHashTable *hash_table;
+ GtkWidget *apply_button;
+
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(editable),
+ "p_intf" );
+ hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "config_hash_table" );
+ /* free old p_config */
+ p_config = (module_config_t *)g_hash_table_lookup( hash_table,
+ (gpointer)editable );
+ if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
+
+ p_config = malloc( sizeof(module_config_t) );
+ p_config->i_type = CONFIG_ITEM_STRING;
+ p_config->psz_value = gtk_editable_get_chars( editable, 0, -1 );
+ p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
+ "config_option" );
+
+ g_hash_table_insert( hash_table, (gpointer)editable,
+ (gpointer)p_config );
+
+ /* change the highlight status of the Apply button */
+ apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "apply_button" );
+ gtk_widget_set_sensitive( apply_button, TRUE );
+}
+
+/****************************************************************************
+ * GtkIntChanged: signal called when the user changes an integer value.
+ ****************************************************************************/
+static void GtkIntChanged( GtkEditable *editable, gpointer user_data )
+{
+ intf_thread_t *p_intf;
+ module_config_t *p_config;
+ GHashTable *hash_table;
+ GtkWidget *apply_button;
+
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(editable),
+ "p_intf" );
+ gtk_spin_button_update( GTK_SPIN_BUTTON(editable) );
+
+ hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "config_hash_table" );
+
+ /* free old p_config */
+ p_config = (module_config_t *)g_hash_table_lookup( hash_table,
+ (gpointer)editable );
+ if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
+
+ p_config = malloc( sizeof(module_config_t) );
+ p_config->i_type = CONFIG_ITEM_INTEGER;
+ p_config->i_value = gtk_spin_button_get_value_as_int(
+ GTK_SPIN_BUTTON(editable) );
+ p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
+ "config_option" );
+
+ g_hash_table_insert( hash_table, (gpointer)editable,
+ (gpointer)p_config );
+
+ /* change the highlight status of the Apply button */
+ apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "apply_button" );
+ gtk_widget_set_sensitive( apply_button, TRUE );
+}
+
+/****************************************************************************
+ * GtkFloatChanged: signal called when the user changes a float value.
+ ****************************************************************************/
+static void GtkFloatChanged( GtkEditable *editable, gpointer user_data )
+{
+ intf_thread_t *p_intf;
+ module_config_t *p_config;
+ GHashTable *hash_table;
+ GtkWidget *apply_button;
+
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(editable),
+ "p_intf" );
+ gtk_spin_button_update( GTK_SPIN_BUTTON(editable) );
+
+ hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "config_hash_table" );
+
+ /* free old p_config */
+ p_config = (module_config_t *)g_hash_table_lookup( hash_table,
+ (gpointer)editable );
+ if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
+
+ p_config = malloc( sizeof(module_config_t) );
+ p_config->i_type = CONFIG_ITEM_FLOAT;
+ p_config->f_value = gtk_spin_button_get_value_as_float(
+ GTK_SPIN_BUTTON(editable) );
+ p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
+ "config_option" );
+
+ g_hash_table_insert( hash_table, (gpointer)editable,
+ (gpointer)p_config );
+
+ /* change the highlight status of the Apply button */
+ apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "apply_button" );
+ gtk_widget_set_sensitive( apply_button, TRUE );
+}
+
+/****************************************************************************
+ * GtkBoolChanged: signal called when the user changes a bool value.
+ ****************************************************************************/
+static void GtkBoolChanged( GtkToggleButton *button, gpointer user_data )
+{
+ intf_thread_t *p_intf;
+ module_config_t *p_config;
+ GHashTable *hash_table;
+ GtkWidget *apply_button;
+
+ p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(button),
+ "p_intf" );
+ hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "config_hash_table" );
+
+ /* free old p_config */
+ p_config = (module_config_t *)g_hash_table_lookup( hash_table,
+ (gpointer)button );
+ if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
+
+ p_config = malloc( sizeof(module_config_t) );
+ p_config->i_type = CONFIG_ITEM_BOOL;
+ p_config->i_value = gtk_toggle_button_get_active( button );
+ p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(button),
+ "config_option" );
+
+ g_hash_table_insert( hash_table, (gpointer)button,
+ (gpointer)p_config );
+
+ /* change the highlight status of the Apply button */
+ apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+ "apply_button" );
+ gtk_widget_set_sensitive( apply_button, TRUE );
+}
+
+/****************************************************************************
+ * GtkFreeHashTable: signal called when the config hash table is destroyed.
+ ****************************************************************************/
+static void GtkFreeHashTable( GtkObject *object )
+{
+ GHashTable *hash_table = (GHashTable *)gtk_object_get_data( object,
+ "config_hash_table" );
+ intf_thread_t *p_intf = (intf_thread_t *)gtk_object_get_data( object,
+ "p_intf" );
+
+ g_hash_table_foreach( hash_table, GtkFreeHashValue, (void *)p_intf );
+ g_hash_table_destroy( hash_table );
+}
+
+/****************************************************************************
+ * GtkFreeHashValue: signal called when an element of the config hash table
+ * is destroyed.
+ ****************************************************************************/
+static void GtkFreeHashValue( gpointer key, gpointer value, gpointer user_data)
+{
+ module_config_t * p_config = (module_config_t *)value;
+
+ if( p_config->i_type == CONFIG_ITEM_STRING )
+ if( p_config->psz_value ) g_free( p_config->psz_value );
+ free( p_config );
+}
+
+/****************************************************************************
+ * GtkSaveHashValue: callback used when enumerating the hash table in
+ * GtkConfigApply().
+ ****************************************************************************/
+static gboolean GtkSaveHashValue( gpointer key, gpointer value,
+ gpointer user_data )
+{
+ intf_thread_t * p_intf = (intf_thread_t *)user_data;
+ module_config_t * p_config = (module_config_t *)value;
+
+ switch( p_config->i_type )
+ {
+
+ case CONFIG_ITEM_STRING:
+ case CONFIG_ITEM_FILE:
+ case CONFIG_ITEM_MODULE:
+ config_PutPsz( p_intf, p_config->psz_name,
+ *p_config->psz_value ? p_config->psz_value : NULL );
+ break;
+ case CONFIG_ITEM_INTEGER:
+ case CONFIG_ITEM_BOOL:
+ config_PutInt( p_intf, p_config->psz_name, p_config->i_value );
+ break;
+ case CONFIG_ITEM_FLOAT:
+ config_PutFloat( p_intf, p_config->psz_name, p_config->f_value );
+ break;
+ }
+
+ /* free the hash value we allocated */
+ if( p_config->i_type == CONFIG_ITEM_STRING )
+ g_free( p_config->psz_value );
+ free( p_config );
+
+ /* return TRUE so glib will free the hash entry */
+ return TRUE;
+}
+
+/****************************************************************************
+ * GtkConfigDialogDestroyed: callback triggered when the config dialog box is
+ * destroyed.
+ ****************************************************************************/
+static void GtkConfigDialogDestroyed( GtkObject *object, gpointer user_data )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)user_data;
+ char *psz_module_name;
+
+ psz_module_name = gtk_object_get_data( object, "psz_module_name" );
+
+ /* remove the ref to the dialog box */
+ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
+ psz_module_name, NULL );
+
+ GtkFreeHashTable( object );
+}
--- /dev/null
+/*****************************************************************************
+ * gtk_control.h: prototypes for control functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: preferences.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Stéphane Borel <stef@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+void GtkPreferencesShow( GtkMenuItem *, gpointer );
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
+*.moc.*
--- /dev/null
+MOC_SOURCES = interface.moc.cpp slider.moc.cpp disc.moc.cpp net.moc.cpp menu.moc.cpp preferences.moc.cpp pluginsbox.moc.cpp QConfigItem.moc.cpp
+
+kde_SOURCES = kde.cpp interface.cpp slider.cpp disc.cpp net.cpp menu.cpp preferences.cpp pluginsbox.cpp QConfigItem.cpp $(MOC_SOURCES)
+
+$(MOC_SOURCES): %.moc.cpp: %.h
+ $(MOC) $< -o $@
--- /dev/null
+#include "QConfigItem.h"
+#include <vlc/vlc.h>
+QConfigItem::QConfigItem(QObject *parent, QString name, int iType, int i_val) :
+ QObject(parent, name)
+{
+ type = iType;
+ iVal = i_val;
+}
+
+QConfigItem::QConfigItem(QObject *parent, QString name, int iType, float f_val) :
+ QObject(parent, name)
+{
+ type = iType;
+ fVal = f_val;
+}
+
+QConfigItem::QConfigItem(QObject *parent, QString name, int iType, QString s_val) :
+ QObject(parent, name)
+{
+ type = iType;
+ sVal = s_val;
+}
+
+QConfigItem::~QConfigItem()
+{
+ ;
+}
+
+int QConfigItem::getType()
+{
+ return type;
+}
+
+int QConfigItem::iValue()
+{
+ return iVal;
+}
+
+float QConfigItem::fValue()
+{
+ return fVal;
+}
+
+QString QConfigItem::sValue()
+{
+ return sVal;
+}
+
+void QConfigItem::setValue(int val)
+{
+ iVal = val;
+}
+
+void QConfigItem::setValue(float val)
+{
+ fVal = val;
+}
+
+void QConfigItem::setValue(double val)
+{
+ fVal = (float)val;
+}
+
+void QConfigItem::setValue(const QString &val)
+{
+ sVal = val;
+}
--- /dev/null
+#ifndef _KCONFIGITEM_H_
+#define _KCONFIGITEM_H_
+#include <qobject.h>
+#include <qstring.h>
+/*
+ A class to handle the information for one configuration item.
+*/
+
+class QConfigItem : public QObject
+{
+ Q_OBJECT
+ public:
+ QConfigItem(QObject *parent, QString name, int iType, int i_val);
+ QConfigItem(QObject *parent, QString name, int iType, float f_val);
+ QConfigItem(QObject *parent, QString name, int iType, QString s_val);
+ ~QConfigItem();
+
+ int getType();
+ float fValue();
+ int iValue();
+ QString sValue();
+
+ public slots:
+ void setValue(int val);
+ void setValue(float val);
+ void setValue(double val);
+ void setValue(const QString &val);
+
+ private:
+ int iVal, type;
+ float fVal;
+ QString sVal;
+};
+#endif
--- /dev/null
+/***************************************************************************
+ common.h - description
+ -------------------
+ begin : Mon Apr 9 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#ifndef _INTF_PLUGIN_H_
+#define _INTF_PLUGIN_H_
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#endif /* _INTF_PLUGIN_H_ */
--- /dev/null
+/***************************************************************************
+ disc.cpp - description
+ -------------------
+ begin : Sat Apr 7 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#include "disc.h"
+
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qstring.h>
+#include <qvbox.h>
+#include <qvbuttongroup.h>
+#include <qvgroupbox.h>
+#include <qwidget.h>
+#include <kdialogbase.h>
+#include <klineedit.h>
+
+KDiskDialog::KDiskDialog( QWidget *parent, const char *name )
+ :KDialogBase( parent, name, true, QString::null,
+ Ok|Cancel, Ok, true )
+{
+ QVBox *pageVBox = makeVBoxMainWidget();
+
+ QHBox *deviceSelectHBox = new QHBox( pageVBox );
+ deviceSelectHBox->setSpacing( 5 );
+ fButtonGroup = new QVButtonGroup( "Disk type", deviceSelectHBox );
+ fDVDButton = new QRadioButton( "DVD", fButtonGroup);
+ fDVDButton->setChecked( true );
+ fVCDButton = new QRadioButton( "VCD", fButtonGroup);
+ fVCDButton->setEnabled( false );
+
+ QVGroupBox *startVBox = new QVGroupBox( "Starting position", deviceSelectHBox );
+
+ QHBox *titleHBox = new QHBox( startVBox );
+ new QLabel( "Title ", titleHBox );
+ fTitle = new QSpinBox( titleHBox );
+ QHBox *chapterHBox = new QHBox( startVBox );
+ new QLabel( "Chapter ", chapterHBox );
+ fChapter = new QSpinBox( chapterHBox );
+
+ QHBox *deviceNameHBox = new QHBox( pageVBox );
+ new QLabel( "Device name ", deviceNameHBox );
+ fLineEdit = new KLineEdit( "/dev/dvd", deviceNameHBox );
+}
+
+KDiskDialog::~KDiskDialog()
+{
+}
+
+QString KDiskDialog::type() const
+{
+ if ( fDVDButton->isChecked() )
+ {
+ return ( QString("dvd") );
+ }
+ else
+ {
+ return ( QString("vcd") );
+ }
+}
+
+QString KDiskDialog::device() const
+{
+ return ( fLineEdit->text() );
+}
+
+int KDiskDialog::title() const
+{
+ return ( fTitle->value() );
+}
+
+int KDiskDialog::chapter() const
+{
+ return ( fChapter->value() );
+}
--- /dev/null
+/***************************************************************************
+ disc.h - description
+ -------------------
+ begin : Sat Apr 7 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#ifndef KDE_DISC_H
+#define KDE_DISC_H
+
+#include <kdialogbase.h>
+#include <qstring.h>
+
+class QVButtonGroup;
+class QRadioButton;
+class QSpinBox;
+class KLineEdit;
+
+/**
+ *@author andres
+ */
+
+class KDiskDialog : public KDialogBase
+{
+ Q_OBJECT
+ public:
+ KDiskDialog( QWidget *parent=0, const char *name=0 );
+ ~KDiskDialog();
+
+ QString type() const;
+ QString device() const;
+ int title() const;
+ int chapter() const;
+
+ private:
+
+ QVButtonGroup *fButtonGroup;
+ QRadioButton *fDVDButton;
+ QRadioButton *fVCDButton;
+ QSpinBox *fTitle;
+ QSpinBox *fChapter;
+ KLineEdit *fLineEdit;
+
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ interface.cpp - description
+ -------------------
+ begin : Sun Mar 25 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#include "disc.h"
+#include "interface.h"
+#include "net.h"
+#include "menu.h"
+#include "slider.h"
+#include "preferences.h"
+
+#include <iostream.h>
+
+#include <kaction.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kstdaction.h>
+#include <kurl.h>
+#include <kurldrag.h>
+#include <qcursor.h>
+#include <qdragobject.h>
+#include <qtimer.h>
+#include <kdialog.h>
+
+#define ID_STATUS_MSG 1
+#define ID_DATE 2
+#define ID_STREAM_SOURCE 3
+
+KInterface::KInterface( intf_thread_t *p_intf, QWidget *parent,
+ const char *name ) : KMainWindow(parent,name)
+{
+ setAcceptDrops(true);
+
+ this->p_intf = p_intf;
+
+ fDiskDialog = new KDiskDialog( this );
+ fNetDialog = new KNetDialog( this );
+ fTitleMenu = new KTitleMenu( p_intf, this );
+
+ fSlider = new KVLCSlider( QSlider::Horizontal, this );
+ fSlider->setMaxValue(10000);
+ connect( fSlider, SIGNAL( userChanged( int ) ), this, SLOT( slotSliderMoved( int ) ) );
+ connect( fSlider, SIGNAL( valueChanged( int ) ), this, SLOT( slotSliderChanged( int ) ) );
+ setCentralWidget(fSlider);
+
+ fTimer = new QTimer( this );
+ connect( fTimer, SIGNAL( timeout() ), this, SLOT( slotManage() ) );
+ fTimer->start( 100 );
+
+ resize( 400, 30 );
+
+ ///////////////////////////////////////////////////////////////////
+ // call inits to invoke all other construction parts
+ // XXX could we move this up ?
+ initStatusBar();
+ initActions();
+
+ // add certain calls to the popup menu
+ fileOpen->plug( fTitleMenu );
+ fileOpenRecent->plug( fTitleMenu );
+ diskOpen->plug( fTitleMenu );
+ streamOpen->plug( fTitleMenu );
+ play->plug( fTitleMenu );
+ pause->plug( fTitleMenu );
+ slow->plug( fTitleMenu );
+ fast->plug( fTitleMenu );
+ fileClose->plug( fTitleMenu );
+ fileQuit->plug( fTitleMenu );
+}
+
+KInterface::~KInterface()
+{
+ ;
+}
+
+void KInterface::initActions()
+{
+ fileOpen = KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
+ fileOpenRecent = KStdAction::openRecent(this, SLOT(slotFileOpenRecent(const KURL&)), actionCollection());
+ fileClose = KStdAction::close(this, SLOT(slotFileClose()), actionCollection());
+ preferences = KStdAction::preferences(this, SLOT(slotShowPreferences()), actionCollection());
+ fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
+ viewToolBar = KStdAction::showToolbar(this, SLOT(slotViewToolBar()), actionCollection());
+ viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection());
+
+ diskOpen = new KAction( i18n( "Open &Disk" ), 0, 0, this, SLOT( slotOpenDisk() ), actionCollection(), "open_disk" );
+ streamOpen = new KAction( i18n( "Open &Stream" ), 0, 0, this, SLOT( slotOpenStream() ), actionCollection(), "open_stream" );
+ backward = new KAction( i18n( "&Backward" ), 0, 0, this, SLOT( slotBackward() ), actionCollection(), "backward" );
+ stop = new KAction( i18n( "&Stop" ), 0, 0, this, SLOT( slotStop() ), actionCollection(), "stop" );
+ play = new KAction( i18n( "&Play" ), 0, 0, this, SLOT( slotPlay() ), actionCollection(), "play" );
+ pause = new KAction( i18n( "P&ause" ), 0, 0, this, SLOT( slotPause() ), actionCollection(), "pause" );
+ slow = new KAction( i18n( "&Slow" ), 0, 0, this, SLOT( slotSlow() ), actionCollection(), "slow" );
+ fast = new KAction( i18n( "Fas&t" ), 0, 0, this, SLOT( slotFast() ), actionCollection(), "fast" );
+ prev = new KAction( i18n( "Prev" ), 0, 0, this, SLOT( slotPrev() ), actionCollection(), "prev" );
+ next = new KAction( i18n( "Next" ), 0, 0, this, SLOT( slotNext() ), actionCollection(), "next" );
+
+ fileOpen->setStatusText(i18n("Opens an existing document"));
+ fileOpenRecent->setStatusText(i18n("Opens a recently used file"));
+ fileClose->setStatusText(i18n("Closes the actual document"));
+ fileQuit->setStatusText(i18n("Quits the application"));
+ viewToolBar->setStatusText(i18n("Enables/disables the toolbar"));
+ viewStatusBar->setStatusText(i18n("Enables/disables the statusbar"));
+
+ diskOpen->setStatusText( i18n( "Opens a disk") );
+ streamOpen->setStatusText( i18n( "Opens a network stream" ) );
+ backward->setStatusText( i18n( "Backward" ) );
+ stop->setStatusText( i18n( "Stops playback" ) );
+ play->setStatusText( i18n( "Starts playback" ) );
+ pause->setStatusText( i18n( "Pauses playback" ) );
+ slow->setStatusText( i18n( "Slow" ) );
+ fast->setStatusText( i18n( "Fast" ) );
+ prev->setStatusText( i18n( "Prev" ) );
+ next->setStatusText( i18n( "Next" ) );
+ // use the absolute path to your ktestui.rc file for testing purpose in createGUI();
+
+ createGUI("plugins/kde/ui.rc");
+}
+
+void KInterface::initStatusBar()
+{
+ ///////////////////////////////////////////////////////////////////
+ // STATUSBAR
+ // TODO: add your own items you need for displaying current application status.
+ statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG, 1, false);
+ statusBar()->setItemAlignment( ID_STATUS_MSG, AlignLeft | AlignVCenter );
+ statusBar()->insertItem( "0:00:00", ID_DATE, 0, true );
+}
+
+/////////////////////////////////////////////////////////////////////
+// SLOT IMPLEMENTATION
+/////////////////////////////////////////////////////////////////////
+
+void KInterface::slotFileOpen()
+{
+ playlist_t *p_playlist;
+
+ slotStatusMsg( i18n( "Opening file..." ) );
+ KURL url=KFileDialog::getOpenURL( QString::null,
+ i18n( "*|All files" ), this, i18n( "Open File..." ) );
+
+ if( !url.isEmpty() )
+ {
+ p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ fileOpenRecent->addURL( url );
+ playlist_Add( p_playlist, url.path(),
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ vlc_object_release( p_playlist );
+ }
+ }
+
+ slotStatusMsg( i18n( "Ready." ) );
+}
+
+void KInterface::slotFileOpenRecent(const KURL& url)
+{
+ slotStatusMsg(i18n("Opening file..."));
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KInterface::slotFileClose()
+{
+ slotStatusMsg(i18n("Closing file..."));
+
+ close();
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KInterface::slotFileQuit()
+{
+ slotStatusMsg(i18n("Exiting..."));
+ p_intf->p_vlc->b_die = VLC_TRUE;
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KInterface::slotViewToolBar()
+{
+ slotStatusMsg(i18n("Toggling toolbar..."));
+ ///////////////////////////////////////////////////////////////////
+ // turn Toolbar on or off
+ if(!viewToolBar->isChecked())
+ {
+ toolBar("mainToolBar")->hide();
+ }
+ else
+ {
+ toolBar("mainToolBar")->show();
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KInterface::slotViewStatusBar()
+{
+ slotStatusMsg(i18n("Toggle the statusbar..."));
+ ///////////////////////////////////////////////////////////////////
+ //turn Statusbar on or off
+ if(!viewStatusBar->isChecked())
+ {
+ statusBar()->hide();
+ }
+ else
+ {
+ statusBar()->show();
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KInterface::slotShowPreferences()
+{
+ // Do something
+ KPreferences(this->p_intf, "main", this, "preferences");
+}
+
+void KInterface::slotStatusMsg(const QString &text)
+{
+ ///////////////////////////////////////////////////////////////////
+ // change status message permanently
+ statusBar()->clear();
+ statusBar()->changeItem(text, ID_STATUS_MSG);
+}
+
+void KInterface::slotManage()
+{
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ /* Update the input */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = (input_thread_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ /* If the "display popup" flag has changed */
+ if( p_intf->b_menu_change )
+ {
+ fTitleMenu->popup( ( QCursor::pos() ) );
+ p_intf->b_menu_change = 0;
+ }
+
+ /* Update language/chapter menus after user request */
+#if 0
+ if( p_intf->p_sys->p_input != NULL && p_intf->p_sys->p_window != NULL &&
+ p_intf->p_sys->b_menus_update )
+ {
+// GnomeSetupMenu( p_intf );
+ }
+#endif
+
+ /* Manage the slider */
+#define p_area p_intf->p_sys->p_input->stream.p_selected_area
+ if( p_intf->p_sys->p_input && p_area->i_size )
+ {
+ fSlider->setValue( ( 10000. * p_area->i_tell ) / p_area->i_size );
+ }
+#undef p_area
+
+ if( p_intf->b_die )
+ {
+ p_intf->p_sys->p_app->quit();
+ }
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+}
+
+void KInterface::slotSliderMoved( int position )
+{
+ if( p_intf->p_sys->p_input )
+ {
+ // XXX is this locking really useful ?
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ off_t i_seek = ( position * p_intf->p_sys->p_input->stream.p_selected_area->i_size ) / 10000;
+ input_Seek( p_intf->p_sys->p_input, i_seek, INPUT_SEEK_SET );
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+ }
+}
+
+void KInterface::slotSliderChanged( int position )
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ char psz_time[ OFFSETTOTIME_MAX_SIZE ];
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+#define p_area p_intf->p_sys->p_input->stream.p_selected_area
+ statusBar()->changeItem( input_OffsetToTime( p_intf->p_sys->p_input, psz_time, ( p_area->i_size * position ) / 10000 ), ID_DATE );
+#undef p_area
+
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+void KInterface::slotOpenDisk()
+{
+ playlist_t *p_playlist;
+ int r = fDiskDialog->exec();
+ if ( r )
+ {
+ // Build source name
+ QString source;
+ source += fDiskDialog->type();
+ source += ':';
+ source += fDiskDialog->device();
+
+ source += '@';
+ source += fDiskDialog->title();
+ source += ',';
+ source += fDiskDialog->chapter();
+
+ p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ // add it to playlist
+ playlist_Add( p_playlist, source.latin1(),
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ vlc_object_release( p_playlist );
+ }
+ }
+}
+
+void KInterface::slotOpenStream()
+{
+ playlist_t *p_playlist;
+ int r = fNetDialog->exec();
+ if ( r )
+ {
+ // Build source name
+ QString source;
+ source += fNetDialog->protocol();
+ source += "://";
+ source += fNetDialog->server();
+ source += ":";
+ source += QString().setNum( fNetDialog->port() );
+
+ p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ // add it to playlist
+ playlist_Add( p_playlist, source.latin1(),
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ vlc_object_release( p_playlist );
+ }
+ }
+}
+
+void KInterface::slotPlay()
+{
+ if( p_intf->p_sys->p_input )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+void KInterface::slotPause()
+{
+ if ( p_intf->p_sys->p_input )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
+ }
+}
+
+void KInterface::slotStop()
+{
+ playlist_t *p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+}
+
+void KInterface::slotBackward()
+{
+ msg_Err( p_intf, "KInterface::slotBackward() - Unimplemented" );
+}
+
+void KInterface::slotPrev()
+{
+ playlist_t *p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ playlist_Prev( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+}
+
+void KInterface::slotNext()
+{
+ playlist_t *p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ playlist_Next( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+}
+
+void KInterface::slotSlow()
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
+ }
+}
+
+void KInterface::slotFast()
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
+ }
+}
+
+void KInterface::dragEnterEvent( QDragEnterEvent *event )
+{
+ event->accept( QUriDrag::canDecode( event ) );
+}
+
+void KInterface::dropEvent( QDropEvent *event )
+{
+ KURL::List urlList;
+
+ playlist_t *p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ if ( KURLDrag::decode( event, urlList ) )
+ {
+ for ( KURL::List::ConstIterator i = urlList.begin(); i != urlList.end(); i++ )
+ {
+ // XXX add a private function to add a KURL with checking
+ // actually a whole class for core abstraction would be neat
+ if( !(*i).isEmpty() )
+ {
+ fileOpenRecent->addURL( *i );
+ playlist_Add( p_playlist, (*i).path(),
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ }
+ }
+ }
+
+ vlc_object_release( p_playlist );
+}
--- /dev/null
+/***************************************************************************
+ interface.h - description
+ -------------------
+ begin : Sun Mar 25 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#ifndef _KDE_INTERFACE_H_
+#define _KDE_INTERFACE_H_
+
+#include "common.h"
+
+#include <kmainwindow.h>
+#include <kapplication.h>
+#include <kurl.h>
+#include <qdragobject.h>
+#include <qstring.h>
+#include <qwidget.h>
+
+class KThread;
+
+class KDiskDialog;
+class KNetDialog;
+class KRecentFilesAction;
+class KTitleMenu;
+class KToggleAction;
+class KVLCSlider;
+
+/**Main Window for the KDE vlc interface
+ *@author andres
+ */
+
+class KInterface : public KMainWindow
+{
+ Q_OBJECT
+ public:
+ KInterface(intf_thread_t *p_intf, QWidget *parent=0,
+ const char *name=0);
+ ~KInterface();
+
+ public slots:
+ /** open a file and load it into the document*/
+ void slotFileOpen();
+ /** opens a file from the recent files menu */
+ void slotFileOpenRecent(const KURL& url);
+ /** asks for saving if the file is modified, then closes the actual file and window*/
+ void slotFileClose();
+ /** closes all open windows by calling close() on each memberList item until the list is empty, then quits the application.
+ * If queryClose() returns false because the user canceled the saveModified() dialog, the closing breaks.
+ */
+ void slotFileQuit();
+ void slotShowPreferences();
+
+ /** toggles the toolbar
+ */
+ void slotViewToolBar();
+ /** toggles the statusbar
+ */
+ void slotViewStatusBar();
+ /** changes the statusbar contents for the standard label permanently, used to indicate current actions.
+ * @param text the text that is displayed in the statusbar
+ */
+ void slotStatusMsg( const QString &text );
+
+ protected:
+ /** initializes the KActions of the application */
+ void initActions();
+ /** sets up the statusbar for the main window by initialzing a statuslabel.
+ */
+ void initStatusBar();
+
+ virtual void dragEnterEvent( QDragEnterEvent *event );
+ virtual void dropEvent( QDropEvent *event );
+
+ private slots:
+ /** we use this to manage the communication with the vlc core */
+ void slotManage();
+
+ /** this slot is called when we drag the position seek bar */
+ void slotSliderMoved( int position );
+
+ /** called every time the slider changes values */
+ void slotSliderChanged( int position );
+
+ void slotOpenDisk();
+ void slotOpenStream();
+
+ void slotBackward();
+ void slotStop();
+ void slotPlay();
+ void slotPause();
+ void slotSlow();
+ void slotFast();
+ void slotPrev();
+ void slotNext();
+
+ private:
+
+ intf_thread_t *p_intf;
+
+ /** to call p_intf->pf_manage every now and then */
+ QTimer *fTimer;
+
+ /** slider which works well with user movement */
+ KVLCSlider *fSlider;
+
+ /** open dvd/vcd */
+ KDiskDialog *fDiskDialog;
+
+ /** open net stream */
+ KNetDialog *fNetDialog;
+
+ KTitleMenu *fTitleMenu;
+
+ // KAction pointers to enable/disable actions
+ KAction *fileOpen;
+ KAction *diskOpen;
+ KAction *streamOpen;
+ KRecentFilesAction *fileOpenRecent;
+ KAction *fileClose;
+ KAction *fileQuit;
+ KToggleAction *viewToolBar;
+ KToggleAction *viewStatusBar;
+ KAction *backward;
+ KAction *stop;
+ KAction *play;
+ KAction *pause;
+ KAction *slow;
+ KAction *fast;
+ KAction *prev;
+ KAction *next;
+ KAction *preferences;
+};
+
+/*****************************************************************************
+ * intf_sys_t: description and status of KDE interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ KThread *p_thread;
+
+ KApplication *p_app;
+ KInterface *p_window;
+ KAboutData *p_about;
+
+ input_thread_t *p_input;
+};
+
+#endif /* _KDE_INTERFACE_H_ */
--- /dev/null
+/*****************************************************************************
+ * kde.cpp : KDE plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: kde.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Andres Krapf <dae@chez.com> Sun Mar 25 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#include "common.h"
+
+#include "interface.h"
+
+#include <iostream>
+
+#include <kaction.h>
+#include <kapp.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kmainwindow.h>
+#include <kstdaction.h>
+#include <qwidget.h>
+
+/*****************************************************************************
+ * The local class.
+ *****************************************************************************/
+class KInterface;
+class KAboutData;
+
+class KThread
+{
+ private:
+ KThread ( KThread &thread ) { };
+ KThread &operator= ( KThread &thread ) { return ( *this ); };
+
+ intf_thread_t *p_intf;
+
+ public:
+ KThread(intf_thread_t *p_intf);
+ ~KThread();
+
+ // These methods get exported to the core
+ static int open ( vlc_object_t * );
+ static void close ( vlc_object_t * );
+ static void run ( intf_thread_t * );
+};
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#ifdef WIN32
+ int i = 90;
+#else
+ int i = getenv( "DISPLAY" ) == NULL ? 8 : 85;
+#endif
+ set_description( _("KDE interface module") );
+ set_capability( "interface", i );
+ set_program( "kvlc" );
+ //set_callbacks( E_(Open), E_(Close) );
+ set_callbacks( KThread::open, KThread::close );
+vlc_module_end();
+
+/*****************************************************************************
+ * KThread::KThread: KDE interface constructor
+ *****************************************************************************/
+KThread::KThread(intf_thread_t *p_intf)
+{
+ this->p_intf = p_intf;
+
+ p_intf->p_sys->p_about =
+ new KAboutData( "VideoLAN Client", I18N_NOOP("Kvlc"), VERSION,
+ _("This is the VideoLAN client, a DVD and MPEG player. It can play "
+ "MPEG and MPEG 2 files from a file or from a network source."),
+ KAboutData::License_GPL,
+ _("(C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 - the VideoLAN Team"),
+ 0, 0, "");
+
+ char *authors[][2] = {
+ { "the VideoLAN Team", "<videolan@videolan.org>" },
+ { NULL, NULL },
+ };
+
+ for ( int i = 0; NULL != authors[i][0]; i++ ) {
+ p_intf->p_sys->p_about->addAuthor( authors[i][0], 0, authors[i][1] );
+ }
+
+ int argc = 1;
+ char *argv[] = { p_intf->p_vlc->psz_object_name, NULL };
+ KCmdLineArgs::init( argc, argv, p_intf->p_sys->p_about );
+
+ p_intf->p_sys->p_app = new KApplication();
+ p_intf->p_sys->p_window = new KInterface(p_intf);
+ p_intf->p_sys->p_window->setCaption( VOUT_TITLE " (KDE interface)" );
+
+ p_intf->p_sys->p_input = NULL;
+}
+
+/*****************************************************************************
+ * KThread::~KThread: KDE interface destructor
+ *****************************************************************************/
+KThread::~KThread()
+{
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ /* XXX: can be deleted if the user closed the window ! */
+ //delete p_intf->p_sys->p_window;
+
+ delete p_intf->p_sys->p_app;
+ delete p_intf->p_sys->p_about;
+}
+
+/*****************************************************************************
+ * KThread::open: initialize and create window
+ *****************************************************************************/
+int KThread::open(vlc_object_t *p_this)
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return( 1 );
+ }
+
+ p_intf->pf_run = KThread::run;
+
+ p_intf->p_sys->p_thread = new KThread(p_intf);
+ return ( 0 );
+}
+
+/*****************************************************************************
+ * KThread::close: destroy interface window
+ *****************************************************************************/
+void KThread::close(vlc_object_t *p_this)
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ delete p_intf->p_sys->p_thread;
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * KThread::run: KDE thread
+ *****************************************************************************
+ * This part of the interface is in a separate thread so that we can call
+ * exec() from within it without annoying the rest of the program.
+ *****************************************************************************/
+void KThread::run(intf_thread_t *p_intf)
+{
+ p_intf->p_sys->p_window->show();
+ p_intf->p_sys->p_app->exec();
+}
+
--- /dev/null
+/***************************************************************************
+ menu.cpp - description
+ -------------------
+ begin : Thu Apr 12 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#include "interface.h"
+#include "menu.h"
+
+#include <kaction.h>
+#include <klocale.h>
+
+KTitleMenu::KTitleMenu( intf_thread_t *p_intf, QWidget *parent, const char *name ) : KPopupMenu( parent, name )
+{
+ fInterfaceThread = p_intf;
+ connect( this, SIGNAL( aboutToShow() ), this, SLOT( regenerateSlot() ) );
+ fLanguageList = new KActionMenu( "Language", 0, this );
+}
+
+KTitleMenu::~KTitleMenu()
+{
+}
+
+void KTitleMenu::regenerateSlot()
+{
+ // removal of elements and disconnection of signal/slots happen transparently on delete
+ delete fLanguageList;
+ fLanguageList = new KActionMenu( "Language", 0, this );
+
+ int i_item = 0;
+ vlc_mutex_lock( &fInterfaceThread->p_sys->p_input->stream.stream_lock );
+
+ for( int i = 0 ; i < fInterfaceThread->p_sys->p_input->stream.i_es_number ; i++ )
+ {
+ if( fInterfaceThread->p_sys->p_input->stream.pp_es[i]->i_cat /* == i_cat */ )
+ {
+ i_item++;
+ QString language( fInterfaceThread->p_sys->p_input->stream.pp_es[i]->psz_desc );
+ if ( QString::null == language )
+ {
+ language += i18n( "Language" );
+ language += " " + i_item;
+ }
+ KRadioAction *action = new KRadioAction( language, 0, this, "language_action" );
+ fLanguageList->insert( action );
+
+ if( /* p_es == */ fInterfaceThread->p_sys->p_input->stream.pp_es[i] )
+ {
+ /* don't lose p_item when we append into menu */
+ //p_item_active = p_item;
+ }
+ }
+ }
+
+ vlc_mutex_unlock( &fInterfaceThread->p_sys->p_input->stream.stream_lock );
+
+#if 0
+ /* link the new menu to the menubar item */
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
+
+ /* acitvation will call signals so we can only do it
+ * when submenu is attached to menu - to get intf_window */
+ if( p_item_active != NULL )
+ {
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
+ TRUE );
+ }
+#endif
+
+ /* be sure that menu is sensitive if non empty */
+ if ( i_item > 0 )
+ {
+ fLanguageList->setEnabled( true );
+ }
+}
+
+/** this method is called when the user selects a language */
+void KTitleMenu::languageSelectedSlot()
+{
+}
--- /dev/null
+/***************************************************************************
+ menu.h - description
+ -------------------
+ begin : Thu Apr 12 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#ifndef _KDE_MENU_H_
+#define _KDE_MENU_H_
+
+#include "common.h"
+
+#include <qwidget.h>
+#include <kpopupmenu.h>
+
+class KActionMenu;
+
+/**
+ *@author andres
+ */
+
+class KTitleMenu : public KPopupMenu
+{
+ Q_OBJECT
+ public:
+ KTitleMenu( intf_thread_t *p_intf, QWidget *parent=0,
+ const char *name=0 );
+ ~KTitleMenu();
+
+ private:
+ intf_thread_t *fInterfaceThread;
+ KActionMenu *fLanguageList;
+
+ private slots: // Private slots
+ /** this method regenerates the popup menu */
+ void regenerateSlot();
+
+ /** this method is called when the user selects a language */
+ void languageSelectedSlot();
+
+};
+
+#endif /* _KDE_MENU_H_ */
--- /dev/null
+/***************************************************************************
+ net.cpp - description
+ -------------------
+ begin : Mon Apr 9 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#include "net.h"
+
+#include <kdialogbase.h>
+#include <klineedit.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qstring.h>
+#include <qvbox.h>
+#include <qvbuttongroup.h>
+#include <qvgroupbox.h>
+#include <qwidget.h>
+
+KNetDialog::KNetDialog( QWidget *parent, const char *name )
+ :KDialogBase( parent, name, true,
+ QString::null, Ok|Cancel, Ok, true )
+{
+ QVBox *pageVBox = makeVBoxMainWidget();
+
+ QHBox *layout = new QHBox( pageVBox );
+ layout->setSpacing( 5 );
+ fButtonGroup = new QVButtonGroup( "Protocol", layout );
+ fTSButton = new QRadioButton( "TS", fButtonGroup);
+ fTSButton->setChecked( true );
+ fRTPButton = new QRadioButton( "RTP", fButtonGroup);
+ fRTPButton->setEnabled( false );
+ fHTTPButton = new QRadioButton( "HTTP", fButtonGroup);
+ fHTTPButton->setEnabled( false );
+
+ QVGroupBox *serverVBox = new QVGroupBox( "Starting position", layout );
+
+ QHBox *titleHBox = new QHBox( serverVBox );
+ new QLabel( "Address ", titleHBox );
+ fAddress = new KLineEdit( "vls", titleHBox );
+ QHBox *portHBox = new QHBox( serverVBox );
+ new QLabel( "Port ", portHBox );
+ fPort = new QSpinBox( 0, 65535, 1, portHBox );
+}
+
+KNetDialog::~KNetDialog()
+{
+}
+
+QString KNetDialog::protocol() const
+{
+ if ( fTSButton->isChecked() )
+ {
+ return ( QString( "ts" ) );
+ }
+ else if ( fRTPButton->isChecked() )
+ {
+ return ( QString( "rtp" ) );
+ }
+ else
+ {
+ return ( QString( "http" ) );
+ }
+}
+
+QString KNetDialog::server() const
+{
+ return ( fAddress->text() );
+}
+
+int KNetDialog::port() const
+{
+ return ( fPort->value() );
+}
--- /dev/null
+/***************************************************************************
+ net.h - description
+ -------------------
+ begin : Mon Apr 9 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+
+#ifndef _KDE_NET_H_
+#define _KDE_NET_H_
+
+#include <qwidget.h>
+#include <kdialogbase.h>
+
+class QVButtonGroup;
+class QRadioButton;
+class QSpinBox;
+class KLineEdit;
+
+/**
+ *@author andres
+ */
+
+class KNetDialog : public KDialogBase
+{
+ Q_OBJECT
+ public:
+ KNetDialog(QWidget *parent=0, const char *name=0);
+ ~KNetDialog();
+
+ QString protocol() const;
+ QString server() const;
+ int port() const;
+
+ private:
+ QVButtonGroup *fButtonGroup;
+ QRadioButton *fTSButton;
+ QRadioButton *fRTPButton;
+ QRadioButton *fHTTPButton;
+ KLineEdit *fAddress;
+ QSpinBox *fPort;
+
+};
+
+#endif /* _KDE_NET_H_ */
--- /dev/null
+#include "pluginsbox.h"
+#include "preferences.h"
+
+#include <qgroupbox.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qvbox.h>
+#include <klistview.h>
+#include <kbuttonbox.h>
+
+KPluginsBox::KPluginsBox(intf_thread_t *p_intf,
+ QString text, QString value, QWidget *parent,
+ int spacing, KPreferences *pref) :
+ QGroupBox( 1, Vertical, text, parent )
+{
+ owner = pref;
+ this->p_intf = p_intf;
+ QVBox *item_vbox = new QVBox( this );
+ item_vbox->setSpacing(spacing);
+
+ listView = new KListView(item_vbox);
+ listView->setAllColumnsShowFocus(true);
+ listView->addColumn(_("Name"));
+ listView->addColumn(_("Description"));
+ KButtonBox *item_bbox = new KButtonBox(item_vbox);
+ configure = item_bbox->addButton( _("Configure") );
+ configure->setEnabled(false);
+ selectButton = item_bbox->addButton( _("Select") );
+ QHBox *item_hbox = new QHBox(item_vbox);
+ item_hbox->setSpacing(spacing);
+ new QLabel( _("Selected:"), item_hbox );
+ line = new KLineEdit( value, item_hbox );
+ connect(selectButton, SIGNAL(clicked()), this, SLOT(selectClicked()));
+ connect(configure, SIGNAL(clicked()), this, SLOT(configureClicked()));
+ connect(listView, SIGNAL(selectionChanged( QListViewItem *)),
+ this, SLOT( selectionChanged( QListViewItem *)));
+}
+
+KPluginsBox::~KPluginsBox()
+{
+ ;
+}
+
+QListView* KPluginsBox::getListView()
+{
+ return listView;
+}
+
+void KPluginsBox::selectClicked()
+{
+ if (listView->selectedItem()) {
+ line->setText(listView->selectedItem()->text(0));
+ emit selectionChanged(listView->selectedItem()->text(0));
+ }
+}
+
+void KPluginsBox::configureClicked()
+{
+ if (listView->selectedItem()) {
+ new KPreferences(p_intf, listView->selectedItem()->text(0), this);
+ }
+}
+void KPluginsBox::selectionChanged( QListViewItem *item )
+{
+ selectButton->setEnabled(true);
+ /* look for module 'psz_name' */
+ configure->setEnabled(owner->isConfigureable(item->text(0)));
+}
--- /dev/null
+#ifndef _KDE_PLUGINBOX_H_
+#define _KDE_PLUGINBOX_H_
+#include <qgroupbox.h>
+#include <klistview.h>
+#include <qpushbutton.h>
+#include <klineedit.h>
+#include "preferences.h"
+class KPluginsBox : public QGroupBox
+{
+ Q_OBJECT
+ public:
+ KPluginsBox(intf_thread_t *p_intf, QString title, QString value,
+ QWidget *parent, int spacing, KPreferences *pref);
+ ~KPluginsBox();
+
+ QListView *getListView(void);
+
+ private slots:
+ void selectClicked(void);
+ void configureClicked(void);
+ void selectionChanged( QListViewItem * );
+
+ signals:
+ void selectionChanged(const QString &text);
+
+ private:
+ intf_thread_t *p_intf;
+ KListView *listView;
+ QPushButton *configure;
+ QPushButton *selectButton;
+ KLineEdit *line;
+ KPreferences *owner;
+};
+#endif
--- /dev/null
+#include <kdialogbase.h>
+#include <qmap.h>
+#include <qcheckbox.h>
+#include <qframe.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlistview.h>
+#include <qnamespace.h>
+#include <qobjectlist.h>
+#include <qspinbox.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+
+#include <kbuttonbox.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "QConfigItem.h"
+#include "pluginsbox.h"
+#include "preferences.h"
+
+/*
+ construkt a new configuration window for the given module
+*/
+KPreferences::KPreferences(intf_thread_t *p_intf, const char *psz_module_name,
+ QWidget *parent, const QString &caption) :
+ KDialogBase ( Tabbed, caption, Ok| Apply|Cancel|User1, Ok, parent,
+ "vlc preferences", true, false, "Save")
+{
+ module_t *p_module, *p_module_bis;
+ module_config_t *p_item;
+ QVBox *category_table = NULL;
+ QString *category_label;
+
+ this->p_intf = p_intf;
+
+ /* Look for the selected module */
+ for( p_module = p_intf->p_vlc->p_module_bank->first ; p_module != NULL ;
+ p_module = p_module->next )
+ {
+
+ if( psz_module_name && !strcmp( psz_module_name, p_module->psz_object_name ) )
+ break;
+ }
+ if( !p_module ) return;
+ p_item = p_module->p_config;
+ do
+ {
+ switch( p_item->i_type )
+ {
+
+ case CONFIG_HINT_CATEGORY:
+ case CONFIG_HINT_END:
+
+ /*
+ * Now we can start taking care of the new category
+ */
+ if( p_item->i_type == CONFIG_HINT_CATEGORY )
+ {
+ category_label = new QString( p_item->psz_text );
+ QFrame *page = addPage( *category_label );
+ QVBoxLayout *toplayout = new QVBoxLayout( page);
+ QScrollView *sv = new QScrollView(page);
+ sv->setResizePolicy(QScrollView::AutoOneFit);
+ sv->setFrameStyle(QScrollView::NoFrame);
+ toplayout->addWidget(sv);
+ category_table = new QVBox(sv->viewport());
+ sv->addChild(category_table);
+ toplayout->addStretch(10);
+ category_table->setSpacing(spacingHint());
+ }
+
+ break;
+
+ case CONFIG_ITEM_MODULE:
+
+ {
+
+ vlc_mutex_lock( p_item->p_lock );
+ KPluginsBox *item_frame =
+ new KPluginsBox( p_intf, p_item->psz_text,
+ p_item->psz_value ? p_item->psz_value :"",
+ category_table,
+ spacingHint(),
+ this );
+ QConfigItem *ci = new QConfigItem(this,
+ p_item->psz_name,
+ p_item->i_type,
+ p_item->psz_value);
+ connect(item_frame, SIGNAL(selectionChanged(const QString &)),
+ ci, SLOT(setValue(const QString &)));
+
+
+ /* build a list of available plugins */
+
+#if 0 /* FIXME */
+ for( p_module_bis = p_intf->p_vlc->p_module_bank->first ;
+ p_module_bis != NULL ;
+ p_module_bis = p_module_bis->next ) {
+ if( p_module_bis->i_capabilities & (1 << p_item->i_value)){
+ new QListViewItem(item_frame->getListView(),
+ p_module_bis->psz_object_name,
+ p_module_bis->psz_longname);
+ }
+ }
+#endif
+ vlc_mutex_unlock( p_item->p_lock );
+ }
+ break;
+
+ case CONFIG_ITEM_STRING:
+ case CONFIG_ITEM_FILE:
+
+ {
+ QHBox *hb = new QHBox(category_table);
+ hb->setSpacing(spacingHint());
+ new QLabel(p_item->psz_text, hb);
+ /* add input box with default value */
+ vlc_mutex_lock( p_item->p_lock );
+
+ KLineEdit *kl = new KLineEdit( p_item->psz_value ?
+ p_item->psz_value : "", hb);
+ QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
+ p_item->i_type,
+ p_item->psz_value ?
+ p_item->psz_value : "");
+ connect(kl, SIGNAL(textChanged ( const QString & )),
+ ci, SLOT(setValue( const QString &)));
+ QToolTip::add(kl, p_item->psz_longtext);
+ kl->setMaxLength(10);
+
+ vlc_mutex_unlock( p_item->p_lock );
+
+ }
+ break;
+
+ case CONFIG_ITEM_INTEGER:
+ /* add input box with default value */
+ {
+ QHBox *hb = new QHBox(category_table);
+ hb->setSpacing(spacingHint());
+ new QLabel(p_item->psz_text, hb);
+ QSpinBox *item_adj = new QSpinBox(-1, 99999, 1, hb);
+ QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
+ p_item->i_type,
+ p_item->i_value);
+ connect(item_adj, SIGNAL(valueChanged( int)),
+ ci, SLOT(setValue(int)));
+ QToolTip::add(item_adj, p_item->psz_longtext);
+ item_adj->setValue( p_item->i_value );
+ }
+ break;
+
+ case CONFIG_ITEM_FLOAT:
+ {
+ QHBox *hb = new QHBox(category_table);
+ hb->setSpacing(spacingHint());
+ new QLabel(p_item->psz_text, hb);
+ KDoubleNumInput *kdi= new KDoubleNumInput(p_item->f_value, hb);
+ kdi->setRange(-1, 99999, 0.01, false);
+ QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
+ p_item->i_type,
+ p_item->f_value);
+ connect(kdi, SIGNAL(valueChanged(double)),
+ ci, SLOT(setValue(double)));
+ QToolTip::add(kdi, p_item->psz_longtext);
+
+ }
+ break;
+
+
+ case CONFIG_ITEM_BOOL:
+
+ /* add check button */
+ {
+ QCheckBox *bool_checkbutton =
+ new QCheckBox(QString(p_item->psz_text), category_table);
+ QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
+ p_item->i_type,
+ p_item->i_value);
+ bool_checkbutton->setChecked(p_item->i_value);
+ connect(bool_checkbutton, SIGNAL(stateChanged( int)),
+ ci, SLOT(setValue(int)));
+ QToolTip::add(bool_checkbutton, p_item->psz_longtext);
+
+ }
+ break;
+
+ }
+
+ p_item++;
+ }
+ while( p_item->i_type != CONFIG_HINT_END );
+ exec();
+
+}
+
+/*
+ empty destructor, qt takes care of this (I think)
+*/
+KPreferences::~KPreferences()
+{
+}
+
+/*
+ return true if the give module is configureable
+*/
+bool KPreferences::isConfigureable(QString module)
+{
+ module_t *p_module;
+ for( p_module = p_intf->p_vlc->p_module_bank->first ;
+ p_module != NULL ;
+ p_module = p_module->next ) {
+ if( !module.compare( p_module->psz_object_name ) ) {
+ return p_module->i_config_items != 0;
+ }
+ }
+ return false;
+
+}
+
+/*
+ run when the Apply button is pressed, and by the methods for the ok
+ and save buttons
+*/
+void KPreferences::slotApply()
+{
+ QObjectList * l = queryList( "QConfigItem" );
+ QObjectListIt it( *l ); // iterate over the config items
+ QObject * obj;
+ while ( (obj=it.current()) != 0 ) {
+ ++it;
+ QConfigItem *p_config = (QConfigItem *)obj;
+ msg_Dbg( p_intf, const_cast<char *>(p_config->name()));
+ msg_Dbg( p_intf, "%d", p_config->getType());
+
+ switch( p_config->getType() ) {
+
+ case CONFIG_ITEM_STRING:
+ case CONFIG_ITEM_FILE:
+ case CONFIG_ITEM_MODULE:
+ if (p_config->sValue()) {
+ config_PutPsz( p_intf, p_config->name(),
+ strdup(p_config->sValue().latin1()));
+ }
+ else {
+ config_PutPsz( p_intf, p_config->name(), NULL );
+ }
+ break;
+ case CONFIG_ITEM_INTEGER:
+ case CONFIG_ITEM_BOOL:
+ config_PutInt( p_intf, p_config->name(), p_config->iValue() );
+ break;
+ case CONFIG_ITEM_FLOAT:
+ config_PutFloat( p_intf, p_config->name(), p_config->fValue() );
+ break;
+ }
+ }
+ delete l;
+}
+
+/*
+ run when the Ok button is pressed
+*/
+void KPreferences::slotOk()
+{
+ slotApply();
+ accept();
+}
+
+/*
+ run when the save button is pressed
+*/
+void KPreferences::slotUser1()
+{
+ slotApply();
+ config_SaveConfigFile( p_intf, NULL );
+}
--- /dev/null
+#ifndef _KDE_PREFERENCES_H_
+#define _KDE_PREFERENCES_H_
+#include "common.h"
+#include <kdialogbase.h>
+
+#include "QConfigItem.h"
+class KPreferences : KDialogBase
+{
+ Q_OBJECT
+ public:
+ KPreferences(intf_thread_t *p_intf, const char *psz_module_name,
+ QWidget *parent, const QString &caption=QString::null);
+ ~KPreferences();
+ bool isConfigureable(QString module);
+
+ public slots:
+ void slotApply();
+ void slotOk();
+ void slotUser1();
+
+ private:
+ intf_thread_t *p_intf;
+};
+#endif
--- /dev/null
+/***************************************************************************
+ slider.cpp - description
+ -------------------
+ begin : Sun Mar 25 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+/***************************************************************************
+ shamelessly copied from noatun's excellent interface
+****************************************************************************/
+
+#include "slider.h"
+
+KVLCSlider::KVLCSlider(QWidget * parent, const char * name) :
+ QSlider(parent,name), pressed(false)
+{
+}
+
+KVLCSlider::KVLCSlider(Orientation o, QWidget * parent, const char * name) :
+ QSlider(o,parent,name), pressed(false)
+{
+}
+
+KVLCSlider::KVLCSlider(int minValue, int maxValue, int pageStep, int value,
+ Orientation o, QWidget * parent, const char * name) :
+ QSlider(minValue, maxValue, pageStep, value, o, parent,name), pressed(false)
+{
+}
+
+void KVLCSlider::setValue(int i)
+{
+ if ( !pressed )
+ {
+ QSlider::setValue( i );
+ }
+}
+
+void KVLCSlider::mousePressEvent( QMouseEvent *e )
+{
+ if ( e->button() != RightButton )
+ {
+ pressed=true;
+ QSlider::mousePressEvent( e );
+ }
+}
+
+void KVLCSlider::mouseReleaseEvent( QMouseEvent *e )
+{
+ pressed=false;
+ QSlider::mouseReleaseEvent( e );
+ emit userChanged( value() );
+}
--- /dev/null
+/***************************************************************************
+ slider.h - description
+ -------------------
+ begin : Sun Apr 03 2001
+ copyright : (C) 2001 by andres
+ email : dae@chez.com
+ ***************************************************************************/
+/***************************************************************************
+ shamelessly copied from noatun's excellent interface
+****************************************************************************/
+#ifndef _KDE_SLIDER_H_
+#define _KDE_SLIDER_H_
+
+#include <qslider.h>
+
+/**
+ * This slider can be changed by the vlc while not dragged by the user
+ */
+class KVLCSlider : public QSlider
+{
+ Q_OBJECT
+ public:
+ KVLCSlider(QWidget * parent, const char * name=0);
+ KVLCSlider(Orientation, QWidget * parent, const char * name=0);
+ KVLCSlider(int minValue, int maxValue, int pageStep, int value,
+ Orientation, QWidget * parent, const char * name=0);
+
+ signals:
+ /**
+ * emmited only when the user changes the value by hand
+ */
+ void userChanged( int value );
+
+ public slots:
+ virtual void setValue( int );
+
+ protected:
+ virtual void mousePressEvent( QMouseEvent * e );
+ virtual void mouseReleaseEvent( QMouseEvent * e );
+
+ private:
+ bool pressed; // set this to true when the user drags the slider
+};
+
+#endif /* _KDE_SLIDER_H_ */
--- /dev/null
+<!DOCTYPE kpartgui>
+<kpartgui name="kvlc" version="0.1">
+
+<ActionProperties>
+ <Action name="open_disk" icon="cdrom_unmount"/>
+ <Action name="open_stream" icon="network"/>
+ <Action name="backward" icon="back"/>
+ <Action name="stop" icon="stop"/>
+ <Action name="play" icon="forward"/>
+ <Action name="pause" icon = "bottom"/>
+ <Action name="slow" icon="undo"/>
+ <Action name="fast" icon="redo"/>
+ <Action name="prev" icon="start"/>
+ <Action name="next" icon="finish"/>
+</ActionProperties>
+
+<MenuBar>
+ <Menu name="file" noMerge="1">
+ <text>&File</text>
+ <Action name="file_open"/>
+ <Action name="file_open_recent"/>
+ <Action name="open_disk"/>
+ <Action name="open_stream"/>
+ <Separator lineSeparator="true"/>
+ <Action name="file_quit"/>
+ </Menu>
+</MenuBar>
+
+<ToolBar name="mainToolBar" iconText="icononly" iconSize="16" noMerge="1">
+ <Action name="file_open"/>
+ <Action name="open_disk"/>
+ <Action name="open_stream"/>
+ <Separator lineSeparator="true"/>
+ <Action name="backward"/>
+ <Action name="stop"/>
+ <Action name="play"/>
+ <Action name="pause"/>
+ <Action name="slow"/>
+ <Action name="fast"/>
+ <Separator lineSeparator="true"/>
+ <Action name="prev"/>
+ <Action name="next"/>
+</ToolBar>
+
+</kpartgui>
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+macosx_SOURCES = macosx.m aout.m vout.m intf.m open.m playlist.m controls.m
--- /dev/null
+/*****************************************************************************
+ * aout.m: CoreAudio output plugin
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: aout.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Colin Delacroix <colin@zoy.org>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include <Carbon/Carbon.h>
+#include <CoreAudio/AudioHardware.h>
+#include <CoreAudio/HostTime.h>
+#include <AudioToolbox/AudioConverter.h>
+
+/*****************************************************************************
+ * aout_sys_t: private audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes the CoreAudio specific properties of an output thread.
+ *****************************************************************************/
+struct aout_sys_t
+{
+ AudioDeviceID device; // the audio device
+ AudioConverterRef s_converter; // the AudioConverter
+ int b_format; // format begun
+
+ AudioStreamBasicDescription s_src_stream_format;
+ AudioStreamBasicDescription s_dst_stream_format;
+
+ Ptr p_buffer; // ptr to the 32 bit float data
+ UInt32 ui_buffer_size; // audio device buffer size
+ vlc_bool_t b_buffer_data; // available buffer data?
+ vlc_mutex_t mutex_lock; // pthread locks for sync of
+ vlc_cond_t cond_sync; // Play and callback
+ mtime_t clock_diff; // diff between system clock & audio
+};
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+static int CABeginFormat ( aout_thread_t * );
+static int CAEndFormat ( aout_thread_t * );
+
+static OSStatus CAIOCallback ( AudioDeviceID inDevice,
+ const AudioTimeStamp *inNow,
+ const void *inInputData,
+ const AudioTimeStamp *inInputTime,
+ AudioBufferList *outOutputData,
+ const AudioTimeStamp *inOutputTime,
+ void *threadGlobals );
+
+/*****************************************************************************
+ * OpenAudio: opens a CoreAudio HAL device
+ *****************************************************************************/
+int E_(OpenAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+ OSStatus err;
+ UInt32 ui_param_size;
+
+ /* allocate instance */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* initialize members */
+ memset( p_aout->p_sys, 0, sizeof( aout_sys_t ) );
+
+ /* get the default output device */
+ ui_param_size = sizeof( p_aout->p_sys->device );
+ err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
+ &ui_param_size,
+ (void *)&p_aout->p_sys->device );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "failed to get the device: %d", err );
+ return( -1 );
+ }
+
+ /* get the buffer size that the device uses for IO */
+ ui_param_size = sizeof( p_aout->p_sys->ui_buffer_size );
+ err = AudioDeviceGetProperty( p_aout->p_sys->device, 0, false,
+ kAudioDevicePropertyBufferSize,
+ &ui_param_size,
+ &p_aout->p_sys->ui_buffer_size );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "failed to get device buffer size: %d", err );
+ return( -1 );
+ }
+
+ /* get a description of the data format used by the device */
+ ui_param_size = sizeof( p_aout->p_sys->s_dst_stream_format );
+ err = AudioDeviceGetProperty( p_aout->p_sys->device, 0, false,
+ kAudioDevicePropertyStreamFormat,
+ &ui_param_size,
+ &p_aout->p_sys->s_dst_stream_format );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "failed to get dst stream format: %d", err );
+ return( -1 );
+ }
+
+ if( p_aout->p_sys->s_dst_stream_format.mFormatID != kAudioFormatLinearPCM )
+ {
+ msg_Err( p_aout, "kAudioFormatLinearPCM required" );
+ return( -1 );
+ }
+
+ /* initialize mutex and cond */
+ vlc_mutex_init( p_aout, &p_aout->p_sys->mutex_lock );
+ vlc_cond_init( p_aout, &p_aout->p_sys->cond_sync );
+
+ /* initialize source stream format */
+ memcpy( &p_aout->p_sys->s_src_stream_format,
+ &p_aout->p_sys->s_dst_stream_format,
+ sizeof( p_aout->p_sys->s_src_stream_format ) );
+
+ if( CABeginFormat( p_aout ) )
+ {
+ msg_Err( p_aout, "CABeginFormat failed" );
+ return( -1 );
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: pretends to set the dsp output format
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ if( CAEndFormat( p_aout ) )
+ {
+ msg_Err( p_aout, "CAEndFormat failed" );
+ return( -1 );
+ }
+
+ switch( p_aout->i_format )
+ {
+ case AOUT_FMT_S8:
+ msg_Err( p_aout,
+ "Signed 8 not supported yet, please report stream" );
+ return( -1 );
+
+ case AOUT_FMT_U8:
+ msg_Err( p_aout,
+ "Unsigned 8 not supported yet, please report stream" );
+ return( -1 );
+
+ case AOUT_FMT_S16_LE:
+ p_aout->p_sys->s_src_stream_format.mFormatFlags &=
+ ~kLinearPCMFormatFlagIsBigEndian;
+ p_aout->p_sys->s_src_stream_format.mFormatFlags |=
+ kLinearPCMFormatFlagIsSignedInteger;
+ break;
+
+ case AOUT_FMT_S16_BE:
+ p_aout->p_sys->s_src_stream_format.mFormatFlags |=
+ kLinearPCMFormatFlagIsBigEndian;
+ p_aout->p_sys->s_src_stream_format.mFormatFlags |=
+ kLinearPCMFormatFlagIsSignedInteger;
+ break;
+
+ case AOUT_FMT_U16_LE:
+ p_aout->p_sys->s_src_stream_format.mFormatFlags &=
+ ~kLinearPCMFormatFlagIsBigEndian;
+ p_aout->p_sys->s_src_stream_format.mFormatFlags &=
+ ~kLinearPCMFormatFlagIsSignedInteger;
+ break;
+
+ case AOUT_FMT_U16_BE:
+ p_aout->p_sys->s_src_stream_format.mFormatFlags |=
+ kLinearPCMFormatFlagIsBigEndian;
+ p_aout->p_sys->s_src_stream_format.mFormatFlags &=
+ ~kLinearPCMFormatFlagIsSignedInteger;
+ break;
+
+ default:
+ msg_Err( p_aout, "audio format (0x%08x) not supported now,"
+ "please report stream", p_aout->i_format );
+ return( -1 );
+ }
+
+ /* source format is not float */
+ p_aout->p_sys->s_src_stream_format.mFormatFlags &=
+ ~kLinearPCMFormatFlagIsFloat;
+
+ /* if destination format is float, take size diff into account */
+ if( p_aout->p_sys->s_dst_stream_format.mFormatFlags &
+ kLinearPCMFormatFlagIsFloat )
+ {
+ p_aout->p_sys->s_src_stream_format.mBytesPerPacket =
+ p_aout->p_sys->s_dst_stream_format.mBytesPerPacket / 2;
+ p_aout->p_sys->s_src_stream_format.mBytesPerFrame =
+ p_aout->p_sys->s_src_stream_format.mBytesPerFrame / 2;
+ p_aout->p_sys->s_src_stream_format.mBitsPerChannel =
+ p_aout->p_sys->s_src_stream_format.mBitsPerChannel / 2;
+ }
+
+ /* set sample rate and channels per frame */
+ p_aout->p_sys->s_src_stream_format.mSampleRate = p_aout->i_rate;
+ p_aout->p_sys->s_src_stream_format.mChannelsPerFrame = p_aout->i_channels;
+
+ if( CABeginFormat( p_aout ) )
+ {
+ msg_Err( p_aout, "CABeginFormat failed" );
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: returns available bytes in buffer
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ return( 0 ); /* send data as soon as possible */
+}
+
+/*****************************************************************************
+ * CAIOCallback : callback for audio output
+ *****************************************************************************/
+static OSStatus CAIOCallback( AudioDeviceID inDevice,
+ const AudioTimeStamp *inNow,
+ const void *inInputData,
+ const AudioTimeStamp *inInputTime,
+ AudioBufferList *outOutputData,
+ const AudioTimeStamp *inOutputTime,
+ void *threadGlobals )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)threadGlobals;
+ aout_sys_t *p_sys = p_aout->p_sys;
+
+ AudioTimeStamp host_time;
+
+ host_time.mFlags = kAudioTimeStampHostTimeValid;
+ AudioDeviceTranslateTime( inDevice, inOutputTime, &host_time );
+ //intf_Msg( "%lld", AudioConvertHostTimeToNanos(host_time.mHostTime) / 1000 + p_aout->p_sys->clock_diff - p_aout->date );
+ p_aout->date = p_aout->p_sys->clock_diff + AudioConvertHostTimeToNanos(host_time.mHostTime) / 1000;
+
+ /* move data into output data buffer */
+ if( p_sys->b_buffer_data )
+ {
+ BlockMoveData( p_sys->p_buffer,
+ outOutputData->mBuffers[ 0 ].mData,
+ p_sys->ui_buffer_size );
+ }
+ else
+ {
+ memset(outOutputData->mBuffers[ 0 ].mData, 0, p_sys->ui_buffer_size);
+//X msg_Warn( p_aout, "audio output is starving, expect glitches" );
+ }
+
+ /* see Play below */
+ vlc_mutex_lock( &p_sys->mutex_lock );
+ p_sys->b_buffer_data = 0;
+ vlc_cond_signal( &p_sys->cond_sync );
+ vlc_mutex_unlock( &p_sys->mutex_lock );
+
+ return( noErr );
+}
+
+/*****************************************************************************
+ * Play: play a sound
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ OSStatus err;
+ UInt32 ui_buffer_size = p_aout->p_sys->ui_buffer_size;
+
+ /*
+ * wait for a callback to occur (to flush the buffer), so Play
+ * can't be called twice, losing the data we just wrote.
+ */
+ vlc_mutex_lock( &p_aout->p_sys->mutex_lock );
+ if ( p_aout->p_sys->b_buffer_data )
+ {
+ vlc_cond_wait( &p_aout->p_sys->cond_sync, &p_aout->p_sys->mutex_lock );
+ }
+ vlc_mutex_unlock( &p_aout->p_sys->mutex_lock );
+
+ err = AudioConverterConvertBuffer( p_aout->p_sys->s_converter,
+ i_size, buffer,
+ &ui_buffer_size,
+ p_aout->p_sys->p_buffer );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "ConvertBuffer failed: %d", err );
+ }
+ else
+ {
+ p_aout->p_sys->b_buffer_data = 1;
+ }
+}
+
+/*****************************************************************************
+ * CloseAudio: closes the CoreAudio HAL device
+ *****************************************************************************/
+void E_(CloseAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+
+ if( CAEndFormat( p_aout ) )
+ {
+ msg_Err( p_aout, "CAEndFormat failed" );
+ }
+
+ /* destroy lock and cond */
+ vlc_mutex_destroy( &p_aout->p_sys->mutex_lock );
+ vlc_cond_destroy( &p_aout->p_sys->cond_sync );
+
+ free( p_aout->p_sys );
+}
+
+/*****************************************************************************
+ * CABeginFormat: creates an AudioConverter
+ *****************************************************************************/
+static int CABeginFormat( aout_thread_t *p_aout )
+{
+ OSStatus err;
+ UInt32 ui_param_size;
+
+ if( p_aout->p_sys->b_format )
+ {
+ msg_Err( p_aout, "CABeginFormat (b_format)" );
+ return( 1 );
+ }
+
+ p_aout->p_sys->ui_buffer_size = 2 * 2 * sizeof(s16) *
+ ((s64)p_aout->i_rate * AOUT_BUFFER_DURATION) / 1000000;
+
+ /* set the buffer size that the device uses for IO */
+ ui_param_size = sizeof( p_aout->p_sys->ui_buffer_size );
+ err = AudioDeviceSetProperty( p_aout->p_sys->device, 0, 0, false,
+ kAudioDevicePropertyBufferSize,
+ ui_param_size,
+ &p_aout->p_sys->ui_buffer_size );
+ //p_aout->i_latency = p_aout->p_sys->ui_buffer_size / 2;
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioDeviceSetProperty failed: %d", err );
+ return( 1 );
+ }
+
+ /* allocate audio buffer */
+ p_aout->p_sys->p_buffer = NewPtrClear( p_aout->p_sys->ui_buffer_size );
+
+ if( p_aout->p_sys->p_buffer == nil )
+ {
+ msg_Err( p_aout, "failed to allocate audio buffer" );
+ return( 1 );
+ }
+
+ /* create a new AudioConverter */
+ err = AudioConverterNew( &p_aout->p_sys->s_src_stream_format,
+ &p_aout->p_sys->s_dst_stream_format,
+ &p_aout->p_sys->s_converter );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioConverterNew failed: %d", err );
+ DisposePtr( p_aout->p_sys->p_buffer );
+ return( 1 );
+ }
+
+ /* add callback */
+ err = AudioDeviceAddIOProc( p_aout->p_sys->device,
+ (AudioDeviceIOProc)CAIOCallback,
+ (void *)p_aout );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioDeviceAddIOProc failed: %d", err );
+ AudioConverterDispose( p_aout->p_sys->s_converter );
+ DisposePtr( p_aout->p_sys->p_buffer );
+ return( 1 );
+ }
+
+ /* open the output */
+ err = AudioDeviceStart( p_aout->p_sys->device,
+ (AudioDeviceIOProc)CAIOCallback );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioDeviceStart failed: %d", err );
+ AudioConverterDispose( p_aout->p_sys->s_converter );
+ DisposePtr( p_aout->p_sys->p_buffer );
+ return( 1 );
+ }
+
+ /* Let's pray for the following operation to be atomic... */
+ p_aout->p_sys->clock_diff = mdate()
+ - AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) / 1000
+ + (mtime_t)p_aout->p_sys->ui_buffer_size / 4 * 1000000 / (mtime_t)p_aout->i_rate
+ + p_aout->p_vlc->i_desync;
+
+ p_aout->p_sys->b_format = 1;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CAEndFormat: destroys the AudioConverter
+ *****************************************************************************/
+static int CAEndFormat( aout_thread_t *p_aout )
+{
+ OSStatus err;
+
+ if( !p_aout->p_sys->b_format )
+ {
+ msg_Err( p_aout, "CAEndFormat (!b_format)" );
+ return( 1 );
+ }
+
+ /* stop playing sound through the device */
+ err = AudioDeviceStop( p_aout->p_sys->device,
+ (AudioDeviceIOProc)CAIOCallback );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioDeviceStop failed: %d", err );
+ return( 1 );
+ }
+
+ /* remove the callback */
+ err = AudioDeviceRemoveIOProc( p_aout->p_sys->device,
+ (AudioDeviceIOProc)CAIOCallback );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: %d", err );
+ return( 1 );
+ }
+
+ /* destroy the AudioConverter */
+ err = AudioConverterDispose( p_aout->p_sys->s_converter );
+
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioConverterDispose failed: %d", err );
+ return( 1 );
+ }
+
+ /* release audio buffer */
+ DisposePtr( p_aout->p_sys->p_buffer );
+
+ p_aout->p_sys->b_format = 0;
+
+ return( 0 );
+}
--- /dev/null
+/*****************************************************************************
+ * controls.m: MacOS X interface plugin
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: controls.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <sys/param.h> /* for MAXPATHLEN */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <Cocoa/Cocoa.h>
+#include <CoreAudio/AudioHardware.h>
+
+#include "intf.h"
+#include "vout.h"
+
+/*****************************************************************************
+ * VLCControls interface
+ *****************************************************************************/
+@interface VLCControls : NSObject
+{
+ IBOutlet id o_open;
+}
+
+- (IBAction)play:(id)sender;
+- (IBAction)pause:(id)sender;
+- (IBAction)stop:(id)sender;
+- (IBAction)faster:(id)sender;
+- (IBAction)slower:(id)sender;
+
+- (IBAction)prev:(id)sender;
+- (IBAction)next:(id)sender;
+- (IBAction)loop:(id)sender;
+
+- (IBAction)volumeUp:(id)sender;
+- (IBAction)volumeDown:(id)sender;
+- (IBAction)mute:(id)sender;
+- (IBAction)fullscreen:(id)sender;
+- (IBAction)deinterlace:(id)sender;
+
+- (IBAction)toggleProgram:(id)sender;
+- (IBAction)toggleTitle:(id)sender;
+- (IBAction)toggleChapter:(id)sender;
+- (IBAction)toggleLanguage:(id)sender;
+
+@end
+
+/*****************************************************************************
+ * VLCControls implementation
+ *****************************************************************************/
+@implementation VLCControls
+
+- (IBAction)play:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ /* If the playlist is empty, open a file requester instead */
+ vlc_mutex_lock( &p_playlist->object_lock );
+ if( p_playlist->i_size )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ playlist_Play( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+
+ [o_open openFile: nil];
+ }
+}
+
+- (IBAction)pause:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return;
+ }
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
+}
+
+- (IBAction)stop:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+- (IBAction)faster:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return;
+ }
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
+}
+
+- (IBAction)slower:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return;
+ }
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
+}
+
+- (IBAction)prev:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Prev( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+- (IBAction)next:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Next( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+- (IBAction)loop:(id)sender
+{
+ NSMenuItem * o_mi = (NSMenuItem *)sender;
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ if( p_intf->p_sys->b_loop )
+ {
+ [o_mi setState: NSOffState];
+ playlist_Delete( p_playlist, p_playlist->i_size - 1 );
+ }
+ else
+ {
+ [o_mi setState: NSOnState];
+ playlist_Add( p_playlist, "vlc:loop",
+ PLAYLIST_APPEND, PLAYLIST_END );
+ }
+
+ p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
+
+ vlc_object_release( p_playlist );
+}
+
+- (IBAction)volumeUp:(id)sender
+{
+ /*
+ intf_thread_t * p_intf = [NSApp getIntf];
+ */
+
+ /* TODO, kAudioDevicePropertyVolumeScalar */
+}
+
+- (IBAction)volumeDown:(id)sender
+{
+ /*
+ intf_thread_t * p_intf = [NSApp getIntf];
+ */
+
+ /* TODO, kAudioDevicePropertyVolumeScalar */
+}
+
+- (IBAction)mute:(id)sender
+{
+ OSStatus err;
+ AudioDeviceID device;
+ UInt32 ui_param_size;
+
+ NSMenuItem * o_mi = (NSMenuItem *)sender;
+ intf_thread_t * p_intf = [NSApp getIntf];
+ UInt32 b_mute = !p_intf->p_sys->b_mute;
+
+ [o_mi setState: b_mute ? NSOnState : NSOffState];
+ p_intf->p_sys->b_mute = !p_intf->p_sys->b_mute;
+
+ ui_param_size = sizeof( device );
+ err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
+ &ui_param_size, (void *)&device );
+ if( err != noErr )
+ {
+ msg_Err( p_intf, "AudioHardwareGetProperty failed (%d)", err );
+ return;
+ }
+
+ ui_param_size = sizeof( b_mute );
+ err = AudioDeviceSetProperty( device, 0, 0, false,
+ kAudioDevicePropertyMute,
+ ui_param_size, (void *)&b_mute );
+ if( err != noErr )
+ {
+ msg_Err( p_intf, "AudioDeviceSetProperty failed (%d)", err );
+ return;
+ }
+}
+
+- (IBAction)fullscreen:(id)sender
+{
+ id o_window = [NSApp keyWindow];
+
+ if( [[o_window className] isEqualToString: @"VLCWindow"] )
+ {
+ [o_window toggleFullscreen];
+ }
+}
+
+- (IBAction)deinterlace:(id)sender
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+ BOOL bEnable = [sender state] == NSOffState;
+
+ if( bEnable )
+ {
+ config_PutPsz( p_intf, "filter", "deinterlace" );
+ config_PutPsz( p_intf, "deinterlace-mode",
+ [[sender title] lossyCString] );
+ }
+ else
+ {
+ config_PutPsz( p_intf, "filter", NULL );
+ }
+}
+
+- (IBAction)toggleProgram:(id)sender
+{
+ NSMenuItem * o_mi = (NSMenuItem *)sender;
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( [o_mi state] == NSOffState )
+ {
+ u16 i_program_id = [o_mi tag];
+
+ input_ChangeProgram( p_intf->p_sys->p_input, i_program_id );
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+- (IBAction)toggleTitle:(id)sender
+{
+ NSMenuItem * o_mi = (NSMenuItem *)sender;
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( [o_mi state] == NSOffState )
+ {
+ int i_title = [o_mi tag];
+
+#define p_input p_intf->p_sys->p_input
+ input_ChangeArea( p_input, p_input->stream.pp_areas[i_title] );
+ input_SetStatus( p_input, INPUT_STATUS_PLAY );
+#undef p_input
+ }
+}
+
+- (IBAction)toggleChapter:(id)sender
+{
+ NSMenuItem * o_mi = (NSMenuItem *)sender;
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( [o_mi state] == NSOffState )
+ {
+ int i_chapter = [o_mi tag];
+
+#define p_input p_intf->p_sys->p_input
+ p_input->stream.p_selected_area->i_part = i_chapter;
+ input_ChangeArea( p_input, p_input->stream.p_selected_area );
+ input_SetStatus( p_input, INPUT_STATUS_PLAY );
+#undef p_input
+ }
+}
+
+- (IBAction)toggleLanguage:(id)sender
+{
+ NSMenuItem * o_mi = (NSMenuItem *)sender;
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+#define p_input p_intf->p_sys->p_input
+
+ if( !p_intf->p_sys->b_audio_update )
+ {
+ NSValue * o_value = [o_mi representedObject];
+ es_descriptor_t * p_es = [o_value pointerValue];
+
+ if( [o_mi state] == NSOnState )
+ {
+ /* we just have one ES to disable */
+ input_ToggleES( p_input, p_es, 0 );
+ }
+ else
+ {
+ int i;
+ int i_cat = [o_mi tag];
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+#define ES p_input->stream.pp_selected_es[i]
+
+ /* unselect the selected ES in the same class */
+ for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
+ {
+ if( ES->i_cat == i_cat )
+ {
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ input_ToggleES( p_input, ES, 0 );
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ break;
+ }
+ }
+
+#undef ES
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ input_ToggleES( p_input, p_es, 1 );
+ }
+ }
+
+#undef p_input
+}
+
+@end
+
+@implementation VLCControls (NSMenuValidation)
+
+- (BOOL)validateMenuItem:(NSMenuItem *)o_mi
+{
+ BOOL bEnabled = TRUE;
+ NSMenu * o_menu = [o_mi menu];
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( [[o_mi title] isEqualToString: _NS("Pause")] ||
+ [[o_mi title] isEqualToString: _NS("Faster")] ||
+ [[o_mi title] isEqualToString: _NS("Slower")] )
+ {
+ if( p_intf->p_sys->p_input != NULL )
+ {
+#define p_input p_intf->p_sys->p_input
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ bEnabled = p_input->stream.b_pace_control;
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+#undef p_input
+ }
+ else
+ {
+ bEnabled = FALSE;
+ }
+ }
+ else if( [[o_mi title] isEqualToString: _NS("Stop")] )
+ {
+ bEnabled = p_intf->p_sys->p_input != NULL;
+ }
+ else if( [[o_mi title] isEqualToString: _NS("Prev")] ||
+ [[o_mi title] isEqualToString: _NS("Next")] )
+ {
+ playlist_t * p_playlist = vlc_object_find( p_intf,
+ VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ bEnabled = FALSE;
+ }
+ else
+ {
+ vlc_mutex_lock( &p_playlist->object_lock );
+ bEnabled = p_playlist->i_size > 1;
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ }
+ }
+ else if( [[o_mi title] isEqualToString: _NS("Volume Up")] ||
+ [[o_mi title] isEqualToString: _NS("Volume Down")] )
+ {
+ bEnabled = FALSE; /* not implemented yet */
+ }
+ else if( [[o_mi title] isEqualToString: _NS("Mute")] )
+ {
+ OSStatus err;
+ UInt32 b_mute;
+ AudioDeviceID device;
+ UInt32 ui_param_size;
+
+ ui_param_size = sizeof( device );
+ err = AudioHardwareGetProperty(
+ kAudioHardwarePropertyDefaultOutputDevice,
+ &ui_param_size, (void *)&device );
+ if( err != noErr )
+ {
+ msg_Err( p_intf, "AudioHardwareGetProperty failed (%d)", err );
+ }
+ else
+ {
+ ui_param_size = sizeof( b_mute );
+ err = AudioDeviceGetProperty( device, 0, 0,
+ kAudioDevicePropertyMute,
+ &ui_param_size, (void *)&b_mute );
+ if( err != noErr )
+ {
+ msg_Err( p_intf, "AudioDeviceGetProperty failed (%d)", err );
+ }
+ else
+ {
+ [o_mi setState: b_mute ? NSOnState : NSOffState];
+ p_intf->p_sys->b_mute = (vlc_bool_t)b_mute ? 1 : 0;
+ }
+ }
+ }
+ else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )
+ {
+ id o_window = [NSApp keyWindow];
+
+ if( [[o_window className] isEqualToString: @"VLCWindow"] )
+ {
+ [o_mi setState: [o_window isFullscreen] ?
+ NSOnState : NSOffState];
+ }
+ else
+ {
+ bEnabled = FALSE;
+ }
+ }
+ else if( o_menu != nil &&
+ [[o_menu title] isEqualToString: _NS("Deinterlace")] )
+ {
+ char * psz_filter = config_GetPsz( p_intf, "filter" );
+
+ if( psz_filter != NULL )
+ {
+ free( psz_filter );
+
+ psz_filter = config_GetPsz( p_intf, "deinterlace-mode" );
+ }
+
+ if( psz_filter != NULL )
+ {
+ if( strcmp( psz_filter, [[o_mi title] lossyCString] ) == 0 )
+ {
+ [o_mi setState: NSOnState];
+ }
+ else
+ {
+ [o_mi setState: NSOffState];
+ }
+
+ free( psz_filter );
+ }
+ else
+ {
+ [o_mi setState: NSOffState];
+ }
+ }
+
+ return( bEnabled );
+}
+
+@end
--- /dev/null
+/*****************************************************************************
+ * intf.h: MacOS X interface plugin
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: intf.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * VLCApplication interface
+ *****************************************************************************/
+@interface VLCApplication : NSApplication
+{
+ NSStringEncoding i_encoding;
+ intf_thread_t *p_intf;
+}
+
+- (void)initIntlSupport;
+- (NSString *)localizedString:(char *)psz;
+
+- (void)setIntf:(intf_thread_t *)p_intf;
+- (intf_thread_t *)getIntf;
+
+@end
+
+#define _NS(s) [NSApp localizedString: _(s)]
+
+/*****************************************************************************
+ * intf_sys_t: description and status of the interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ NSAutoreleasePool * o_pool;
+ NSPort * o_sendport;
+
+ /* special actions */
+ vlc_bool_t b_loop;
+ vlc_bool_t b_playing;
+ vlc_bool_t b_mute;
+
+ /* menus handlers */
+ vlc_bool_t b_chapter_update;
+ vlc_bool_t b_program_update;
+ vlc_bool_t b_title_update;
+ vlc_bool_t b_audio_update;
+ vlc_bool_t b_spu_update;
+
+ /* The input thread */
+ input_thread_t * p_input;
+
+ /* The messages window */
+ msg_subscription_t * p_sub;
+
+ /* DVD mode */
+ int i_part;
+};
+
+/*****************************************************************************
+ * VLCMain interface
+ *****************************************************************************/
+@interface VLCMain : NSObject
+{
+ IBOutlet id o_window; /* main window */
+
+ IBOutlet id o_controls; /* VLCControls */
+ IBOutlet id o_playlist; /* VLCPlaylist */
+
+ IBOutlet id o_messages; /* messages tv */
+ IBOutlet id o_msgs_panel; /* messages panel */
+ IBOutlet id o_msgs_btn_ok; /* messages btn */
+
+ /* main menu */
+
+ IBOutlet id o_mi_about;
+ IBOutlet id o_mi_hide;
+ IBOutlet id o_mi_hide_others;
+ IBOutlet id o_mi_show_all;
+ IBOutlet id o_mi_quit;
+
+ IBOutlet id o_mu_file;
+ IBOutlet id o_mi_open_file;
+ IBOutlet id o_mi_open_disc;
+ IBOutlet id o_mi_open_net;
+ IBOutlet id o_mi_open_quickly;
+ IBOutlet id o_mi_open_recent;
+ IBOutlet id o_mi_open_recent_cm;
+
+ IBOutlet id o_mu_edit;
+ IBOutlet id o_mi_cut;
+ IBOutlet id o_mi_copy;
+ IBOutlet id o_mi_paste;
+ IBOutlet id o_mi_clear;
+ IBOutlet id o_mi_select_all;
+
+ IBOutlet id o_mu_view;
+ IBOutlet id o_mi_playlist;
+ IBOutlet id o_mi_messages;
+
+ IBOutlet id o_mu_controls;
+ IBOutlet id o_mi_play;
+ IBOutlet id o_mi_pause;
+ IBOutlet id o_mi_stop;
+ IBOutlet id o_mi_faster;
+ IBOutlet id o_mi_slower;
+ IBOutlet id o_mi_previous;
+ IBOutlet id o_mi_next;
+ IBOutlet id o_mi_loop;
+ IBOutlet id o_mi_vol_up;
+ IBOutlet id o_mi_vol_down;
+ IBOutlet id o_mi_mute;
+ IBOutlet id o_mi_fullscreen;
+ IBOutlet id o_mi_deinterlace;
+ IBOutlet id o_mi_program;
+ IBOutlet id o_mi_title;
+ IBOutlet id o_mi_chapter;
+ IBOutlet id o_mi_language;
+ IBOutlet id o_mi_subtitle;
+
+ IBOutlet id o_mu_window;
+ IBOutlet id o_mi_minimize;
+ IBOutlet id o_mi_bring_atf;
+
+ /* dock menu */
+ IBOutlet id o_dmi_play;
+ IBOutlet id o_dmi_pause;
+ IBOutlet id o_dmi_stop;
+}
+
+- (void)terminate;
+
+- (void)manage;
+- (void)manageMode;
+
+- (void)setupMenus;
+- (void)setupLangMenu:(NSMenuItem *)o_mi
+ es:(es_descriptor_t *)p_es
+ category:(int)i_cat
+ selector:(SEL)pf_callback;
+
+- (IBAction)clearRecentItems:(id)sender;
+- (void)openRecentItem:(id)sender;
+
+@end
+
+@interface VLCMain (Internal)
+- (void)handlePortMessage:(NSPortMessage *)o_msg;
+@end
--- /dev/null
+/*****************************************************************************
+ * intf.m: MacOS X interface plugin
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: intf.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <sys/param.h> /* for MAXPATHLEN */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include <Cocoa/Cocoa.h>
+#include <QuickTime/QuickTime.h>
+
+#include "intf.h"
+#include "vout.h"
+#include "playlist.h"
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static void Run ( intf_thread_t *p_intf );
+
+/*****************************************************************************
+ * OpenIntf: initialize interface
+ *****************************************************************************/
+int E_(OpenIntf) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ return( 1 );
+ }
+
+ memset( p_intf->p_sys, 0, sizeof( *p_intf->p_sys ) );
+
+ p_intf->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
+ p_intf->p_sys->o_sendport = [[NSPort port] retain];
+
+ p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
+
+ p_intf->pf_run = Run;
+
+ [[VLCApplication sharedApplication] autorelease];
+ [NSApp initIntlSupport];
+ [NSApp setIntf: p_intf];
+
+ [NSBundle loadNibNamed: @"MainMenu" owner: NSApp];
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CloseIntf: destroy interface
+ *****************************************************************************/
+void E_(CloseIntf) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+
+ msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+
+ [p_intf->p_sys->o_sendport release];
+ [p_intf->p_sys->o_pool release];
+
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: main loop
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ [NSApp run];
+}
+
+/*****************************************************************************
+ * VLCApplication implementation
+ *****************************************************************************/
+@implementation VLCApplication
+
+- (id)init
+{
+ /* default encoding: ISO-8859-1 */
+ i_encoding = NSISOLatin1StringEncoding;
+
+ return( [super init] );
+}
+
+- (void)initIntlSupport
+{
+ char *psz_lang = getenv( "LANG" );
+
+ if( psz_lang == NULL )
+ {
+ return;
+ }
+
+ if( strncmp( psz_lang, "pl", 2 ) == 0 )
+ {
+ i_encoding = NSISOLatin2StringEncoding;
+ }
+ else if( strncmp( psz_lang, "ja", 2 ) == 0 )
+ {
+ i_encoding = NSJapaneseEUCStringEncoding;
+ }
+ else if( strncmp( psz_lang, "ru", 2 ) == 0 )
+ {
+#define CFSENC2NSSENC(e) CFStringConvertEncodingToNSStringEncoding(e)
+ i_encoding = CFSENC2NSSENC( kCFStringEncodingKOI8_R );
+#undef CFSENC2NSSENC
+ }
+}
+
+- (NSString *)localizedString:(char *)psz
+{
+ UInt32 uiLength = (UInt32)strlen( psz );
+ NSData * o_data = [NSData dataWithBytes: psz length: uiLength];
+ NSString *o_str = [[NSString alloc] initWithData: o_data
+ encoding: i_encoding];
+ return( [o_str autorelease] );
+}
+
+- (void)setIntf:(intf_thread_t *)_p_intf
+{
+ p_intf = _p_intf;
+}
+
+- (intf_thread_t *)getIntf
+{
+ return( p_intf );
+}
+
+- (void)terminate:(id)sender
+{
+ [self getIntf]->p_vlc->b_die = VLC_TRUE;
+}
+
+@end
+
+/*****************************************************************************
+ * VLCMain implementation
+ *****************************************************************************/
+@implementation VLCMain
+
+- (void)awakeFromNib
+{
+ NSString * pTitle = [NSString
+ stringWithCString: VOUT_TITLE " (Cocoa)"];
+
+ [o_window setTitle: pTitle];
+
+ [o_msgs_panel setTitle: _NS("Messages")];
+ [o_msgs_btn_ok setTitle: _NS("Close")];
+
+ [o_mi_about setTitle: _NS("About vlc")];
+ [o_mi_hide setTitle: _NS("Hide vlc")];
+ [o_mi_hide_others setTitle: _NS("Hide Others")];
+ [o_mi_show_all setTitle: _NS("Show All")];
+ [o_mi_quit setTitle: _NS("Quit vlc")];
+
+ [o_mu_file setTitle: _NS("File")];
+ [o_mi_open_file setTitle: _NS("Open File")];
+ [o_mi_open_disc setTitle: _NS("Open Disc")];
+ [o_mi_open_net setTitle: _NS("Open Network")];
+ [o_mi_open_quickly setTitle: _NS("Open Quickly...")];
+ [o_mi_open_recent setTitle: _NS("Open Recent")];
+ [o_mi_open_recent_cm setTitle: _NS("Clear Menu")];
+
+ [o_mu_edit setTitle: _NS("Edit")];
+ [o_mi_cut setTitle: _NS("Cut")];
+ [o_mi_copy setTitle: _NS("Copy")];
+ [o_mi_paste setTitle: _NS("Paste")];
+ [o_mi_clear setTitle: _NS("Clear")];
+ [o_mi_select_all setTitle: _NS("Select All")];
+
+ [o_mu_view setTitle: _NS("View")];
+ [o_mi_playlist setTitle: _NS("Playlist")];
+ [o_mi_messages setTitle: _NS("Messages")];
+
+ [o_mu_controls setTitle: _NS("Controls")];
+ [o_mi_play setTitle: _NS("Play")];
+ [o_mi_pause setTitle: _NS("Pause")];
+ [o_mi_stop setTitle: _NS("Stop")];
+ [o_mi_faster setTitle: _NS("Faster")];
+ [o_mi_slower setTitle: _NS("Slower")];
+ [o_mi_previous setTitle: _NS("Prev")];
+ [o_mi_next setTitle: _NS("Next")];
+ [o_mi_loop setTitle: _NS("Loop")];
+ [o_mi_vol_up setTitle: _NS("Volume Up")];
+ [o_mi_vol_down setTitle: _NS("Volume Down")];
+ [o_mi_mute setTitle: _NS("Mute")];
+ [o_mi_fullscreen setTitle: _NS("Fullscreen")];
+ [o_mi_deinterlace setTitle: _NS("Deinterlace")];
+ [o_mi_program setTitle: _NS("Program")];
+ [o_mi_title setTitle: _NS("Title")];
+ [o_mi_chapter setTitle: _NS("Chapter")];
+ [o_mi_language setTitle: _NS("Language")];
+ [o_mi_subtitle setTitle: _NS("Subtitles")];
+
+ [o_mu_window setTitle: _NS("Window")];
+ [o_mi_minimize setTitle: _NS("Minimize")];
+ [o_mi_bring_atf setTitle: _NS("Bring All to Front")];
+
+ /* dock menu */
+ [o_dmi_play setTitle: _NS("Play")];
+ [o_dmi_pause setTitle: _NS("Pause")];
+ [o_dmi_stop setTitle: _NS("Stop")];
+
+ [self manageMode];
+}
+
+- (void)applicationWillFinishLaunching:(NSNotification *)o_notification
+{
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ [NSThread detachNewThreadSelector: @selector(manage)
+ toTarget: self withObject: nil];
+
+ [p_intf->p_sys->o_sendport setDelegate: self];
+ [[NSRunLoop currentRunLoop]
+ addPort: p_intf->p_sys->o_sendport
+ forMode: NSDefaultRunLoopMode];
+}
+
+- (BOOL)application:(NSApplication *)o_app openFile:(NSString *)o_filename
+{
+ [o_playlist appendArray:
+ [NSArray arrayWithObject: o_filename] atPos: -1];
+
+ return( TRUE );
+}
+
+- (void)manage
+{
+ NSDate * o_sleep_date;
+ intf_thread_t * p_intf = [NSApp getIntf];
+ NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
+
+ while( !p_intf->b_die )
+ {
+ int i_start, i_stop;
+
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ /* update the input */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ if( p_intf->p_sys->p_input )
+ {
+ input_thread_t *p_input = p_intf->p_sys->p_input;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ if( !p_input->b_die )
+ {
+ /* New input or stream map change */
+ if( p_input->stream.b_changed )
+ {
+ [self manageMode];
+ [self setupMenus];
+ p_intf->p_sys->b_playing = 1;
+ }
+
+ if( p_intf->p_sys->i_part !=
+ p_input->stream.p_selected_area->i_part )
+ {
+ p_intf->p_sys->b_chapter_update = 1;
+ [self setupMenus];
+ }
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+ else if( p_intf->p_sys->b_playing && !p_intf->b_die )
+ {
+ [self manageMode];
+ p_intf->p_sys->b_playing = 0;
+ }
+
+ /* update the log window */
+ vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+ i_stop = *p_intf->p_sys->p_sub->pi_stop;
+ vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+
+ if( p_intf->p_sys->p_sub->i_start != i_stop )
+ {
+ NSColor *o_white = [NSColor whiteColor];
+ NSColor *o_red = [NSColor redColor];
+ NSColor *o_yellow = [NSColor yellowColor];
+ NSColor *o_gray = [NSColor grayColor];
+
+ unsigned int ui_length = [[o_messages string] length];
+
+ NSColor * pp_color[4] = { o_white, o_red, o_yellow, o_gray };
+ static const char * ppsz_type[4] = { ": ", " error: ",
+ " warning: ", " debug: " };
+
+ [o_messages setEditable: YES];
+ [o_messages setSelectedRange: NSMakeRange( ui_length, 0 )];
+ [o_messages scrollRangeToVisible: NSMakeRange( ui_length, 0 )];
+
+ for( i_start = p_intf->p_sys->p_sub->i_start;
+ i_start != i_stop;
+ i_start = (i_start+1) % VLC_MSG_QSIZE )
+ {
+ NSString *o_msg;
+ NSDictionary *o_attr;
+ NSAttributedString *o_msg_color;
+ int i_type = p_intf->p_sys->p_sub->p_msg[i_start].i_type;
+
+ o_attr = [NSDictionary dictionaryWithObject: o_gray
+ forKey: NSForegroundColorAttributeName];
+ o_msg = [NSString stringWithFormat: @"%s%s",
+ p_intf->p_sys->p_sub->p_msg[i_start].psz_module,
+ ppsz_type[i_type]];
+ o_msg_color = [[NSAttributedString alloc]
+ initWithString: o_msg attributes: o_attr];
+ [o_messages insertText: o_msg_color];
+
+ o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type]
+ forKey: NSForegroundColorAttributeName];
+ o_msg = [NSString stringWithCString:
+ p_intf->p_sys->p_sub->p_msg[i_start].psz_msg];
+ o_msg_color = [[NSAttributedString alloc]
+ initWithString: o_msg attributes: o_attr];
+ [o_messages insertText: o_msg_color];
+
+ [o_messages insertText: @"\n"];
+ }
+
+ [o_messages setEditable: NO];
+
+ vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+ p_intf->p_sys->p_sub->i_start = i_start;
+ vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+ }
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ o_sleep_date = [NSDate dateWithTimeIntervalSinceNow: 0.1];
+ [NSThread sleepUntilDate: o_sleep_date];
+ }
+
+ [self terminate];
+
+ [o_pool release];
+}
+
+- (void)terminate
+{
+ NSEvent * pEvent;
+ vout_thread_t * p_vout;
+ playlist_t * p_playlist;
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ /* release input */
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ /*
+ * Free playlists
+ */
+ msg_Dbg( p_intf, "removing all playlists" );
+ while( (p_playlist = vlc_object_find( p_intf->p_vlc, VLC_OBJECT_PLAYLIST,
+ FIND_CHILD )) )
+ {
+ vlc_object_detach_all( p_playlist );
+ vlc_object_release( p_playlist );
+ playlist_Destroy( p_playlist );
+ }
+
+ /*
+ * Free video outputs
+ */
+ msg_Dbg( p_intf, "removing all video outputs" );
+ while( (p_vout = vlc_object_find( p_intf->p_vlc,
+ VLC_OBJECT_VOUT, FIND_CHILD )) )
+ {
+ vlc_object_detach_all( p_vout );
+ vlc_object_release( p_vout );
+ vout_DestroyThread( p_vout );
+ }
+
+ [NSApp stop: nil];
+
+ /* write cached user defaults to disk */
+ [[NSUserDefaults standardUserDefaults] synchronize];
+
+ /* send a dummy event to break out of the event loop */
+ pEvent = [NSEvent mouseEventWithType: NSLeftMouseDown
+ location: NSMakePoint( 1, 1 ) modifierFlags: 0
+ timestamp: 1 windowNumber: [[NSApp mainWindow] windowNumber]
+ context: [NSGraphicsContext currentContext] eventNumber: 1
+ clickCount: 1 pressure: 0.0];
+ [NSApp postEvent: pEvent atStart: YES];
+}
+
+- (void)manageMode
+{
+ vlc_bool_t b_control = 0;
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ if( p_intf->p_sys->p_input )
+ {
+ /* control buttons for free pace streams */
+ b_control = p_intf->p_sys->p_input->stream.b_pace_control;
+
+ /* get ready for menu regeneration */
+ p_intf->p_sys->b_program_update = 1;
+ p_intf->p_sys->b_title_update = 1;
+ p_intf->p_sys->b_chapter_update = 1;
+ p_intf->p_sys->b_audio_update = 1;
+ p_intf->p_sys->b_spu_update = 1;
+ p_intf->p_sys->i_part = 0;
+
+ p_intf->p_sys->p_input->stream.b_changed = 0;
+ msg_Dbg( p_intf, "stream has changed, refreshing interface" );
+ }
+ else
+ {
+ /* unsensitize menus */
+ [o_mi_program setEnabled: FALSE];
+ [o_mi_title setEnabled: FALSE];
+ [o_mi_chapter setEnabled: FALSE];
+ [o_mi_language setEnabled: FALSE];
+ [o_mi_subtitle setEnabled: FALSE];
+ }
+}
+
+- (void)setupMenus
+{
+ int i, i_nb_items;
+ NSMenuItem * o_item;
+ NSString * o_menu_title;
+ char psz_title[ 256 ];
+
+ es_descriptor_t * p_audio_es = NULL;
+ es_descriptor_t * p_spu_es = NULL;
+
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
+ p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update |
+ p_intf->p_sys->b_program_update;
+ p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update |
+ p_intf->p_sys->b_program_update;
+
+#define p_input (p_intf->p_sys->p_input)
+
+ if( p_intf->p_sys->b_program_update )
+ {
+ NSMenu * o_program;
+ SEL pf_toggle_program;
+ pgrm_descriptor_t * p_pgrm;
+
+ if( p_input->stream.p_new_program )
+ {
+ p_pgrm = p_input->stream.p_new_program;
+ }
+ else
+ {
+ p_pgrm = p_input->stream.p_selected_program;
+ }
+
+ o_program = [o_mi_program submenu];
+ pf_toggle_program = @selector(toggleProgram:);
+
+ /* remove previous program items */
+ i_nb_items = [o_program numberOfItems];
+ for( i = 0; i < i_nb_items; i++ )
+ {
+ [o_program removeItemAtIndex: 0];
+ }
+
+ /* make (un)sensitive */
+ [o_mi_program setEnabled:
+ p_input->stream.i_pgrm_number > 1];
+
+ /* add program items */
+ for( i = 0 ; i < p_input->stream.i_pgrm_number ; i++ )
+ {
+ snprintf( psz_title, sizeof(psz_title), "id %d",
+ p_input->stream.pp_programs[i]->i_number );
+ psz_title[sizeof(psz_title) - 1] = '\0';
+
+ o_menu_title = [NSString stringWithCString: psz_title];
+
+ o_item = [o_program addItemWithTitle: o_menu_title
+ action: pf_toggle_program keyEquivalent: @""];
+ [o_item setTag: p_input->stream.pp_programs[i]->i_number];
+ [o_item setTarget: o_controls];
+
+ if( p_pgrm == p_input->stream.pp_programs[i] )
+ {
+ [o_item setState: NSOnState];
+ }
+ }
+
+ p_intf->p_sys->b_program_update = 0;
+ }
+
+ if( p_intf->p_sys->b_title_update )
+ {
+ NSMenu * o_title;
+ SEL pf_toggle_title;
+
+ o_title = [o_mi_title submenu];
+ pf_toggle_title = @selector(toggleTitle:);
+
+ /* remove previous title items */
+ i_nb_items = [o_title numberOfItems];
+ for( i = 0; i < i_nb_items; i++ )
+ {
+ [o_title removeItemAtIndex: 0];
+ }
+
+ /* make (un)sensitive */
+ [o_mi_title setEnabled:
+ p_input->stream.i_area_nb > 1];
+
+ /* add title items */
+ for( i = 1 ; i < p_input->stream.i_area_nb ; i++ )
+ {
+ snprintf( psz_title, sizeof(psz_title), "Title %d (%d)", i,
+ p_input->stream.pp_areas[i]->i_part_nb );
+ psz_title[sizeof(psz_title) - 1] = '\0';
+
+ o_menu_title = [NSString stringWithCString: psz_title];
+
+ o_item = [o_title addItemWithTitle: o_menu_title
+ action: pf_toggle_title keyEquivalent: @""];
+ [o_item setTag: i];
+ [o_item setTarget: o_controls];
+
+ if( ( p_input->stream.pp_areas[i] ==
+ p_input->stream.p_selected_area ) )
+ {
+ [o_item setState: NSOnState];
+ }
+ }
+
+ p_intf->p_sys->b_title_update = 0;
+ }
+
+ if( p_intf->p_sys->b_chapter_update )
+ {
+ NSMenu * o_chapter;
+ SEL pf_toggle_chapter;
+
+ o_chapter = [o_mi_chapter submenu];
+ pf_toggle_chapter = @selector(toggleChapter:);
+
+ /* remove previous chapter items */
+ i_nb_items = [o_chapter numberOfItems];
+ for( i = 0; i < i_nb_items; i++ )
+ {
+ [o_chapter removeItemAtIndex: 0];
+ }
+
+ /* make (un)sensitive */
+ [o_mi_chapter setEnabled:
+ p_input->stream.p_selected_area->i_part_nb > 1];
+
+ /* add chapter items */
+ for( i = 0 ; i < p_input->stream.p_selected_area->i_part_nb ; i++ )
+ {
+ snprintf( psz_title, sizeof(psz_title), "Chapter %d", i + 1 );
+ psz_title[sizeof(psz_title) - 1] = '\0';
+
+ o_menu_title = [NSString stringWithCString: psz_title];
+
+ o_item = [o_chapter addItemWithTitle: o_menu_title
+ action: pf_toggle_chapter keyEquivalent: @""];
+ [o_item setTag: i + 1];
+ [o_item setTarget: o_controls];
+
+ if( ( p_input->stream.p_selected_area->i_part == i + 1 ) )
+ {
+ [o_item setState: NSOnState];
+ }
+ }
+
+ p_intf->p_sys->i_part =
+ p_input->stream.p_selected_area->i_part;
+
+ p_intf->p_sys->b_chapter_update = 0;
+ }
+
+ for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ )
+ {
+ if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
+ {
+ p_audio_es = p_input->stream.pp_selected_es[i];
+ }
+ else if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
+ {
+ p_spu_es = p_input->stream.pp_selected_es[i];
+ }
+ }
+
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ if( p_intf->p_sys->b_audio_update )
+ {
+ [self setupLangMenu: o_mi_language es: p_audio_es
+ category: AUDIO_ES selector: @selector(toggleLanguage:)];
+
+ p_intf->p_sys->b_audio_update = 0;
+ }
+
+ if( p_intf->p_sys->b_spu_update )
+ {
+ [self setupLangMenu: o_mi_subtitle es: p_spu_es
+ category: SPU_ES selector: @selector(toggleLanguage:)];
+
+ p_intf->p_sys->b_spu_update = 0;
+ }
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+#undef p_input
+}
+
+- (void)setupLangMenu:(NSMenuItem *)o_mi
+ es:(es_descriptor_t *)p_es
+ category:(int)i_cat
+ selector:(SEL)pf_callback
+{
+ int i, i_nb_items;
+ NSMenu * o_menu = [o_mi submenu];
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ /* remove previous language items */
+ i_nb_items = [o_menu numberOfItems];
+ for( i = 0; i < i_nb_items; i++ )
+ {
+ [o_menu removeItemAtIndex: 0];
+ }
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+#define ES p_intf->p_sys->p_input->stream.pp_es[i]
+ for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ )
+ {
+ if( ( ES->i_cat == i_cat ) &&
+ ( !ES->p_pgrm ||
+ ES->p_pgrm ==
+ p_intf->p_sys->p_input->stream.p_selected_program ) )
+ {
+ NSMenuItem * o_lmi;
+ NSString * o_title;
+
+ if( *ES->psz_desc )
+ {
+ o_title = [NSString stringWithCString: ES->psz_desc];
+ }
+ else
+ {
+ char psz_title[ 256 ];
+
+ snprintf( psz_title, sizeof(psz_title), "Language 0x%x",
+ ES->i_id );
+ psz_title[sizeof(psz_title) - 1] = '\0';
+
+ o_title = [NSString stringWithCString: psz_title];
+ }
+
+ o_lmi = [o_menu addItemWithTitle: o_title
+ action: pf_callback keyEquivalent: @""];
+ [o_lmi setRepresentedObject:
+ [NSValue valueWithPointer: ES]];
+ [o_lmi setTarget: o_controls];
+ [o_lmi setTag: i_cat];
+
+ if( /*p_es == ES*/ ES->p_decoder_fifo != NULL )
+ {
+ [o_lmi setState: NSOnState];
+ }
+ }
+ }
+#undef ES
+
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ /* make (un)sensitive */
+ [o_mi setEnabled:
+ [o_menu numberOfItems] ? TRUE : FALSE];
+}
+
+- (IBAction)clearRecentItems:(id)sender
+{
+ [[NSDocumentController sharedDocumentController]
+ clearRecentDocuments: nil];
+}
+
+- (void)openRecentItem:(id)sender
+{
+ [self application: nil openFile: [sender title]];
+}
+
+@end
+
+@implementation VLCMain (NSMenuValidation)
+
+- (BOOL)validateMenuItem:(NSMenuItem *)o_mi
+{
+ BOOL bEnabled = TRUE;
+
+ /* Recent Items Menu */
+
+ if( [[o_mi title] isEqualToString: _NS("Clear Menu")] )
+ {
+ NSMenu * o_menu = [o_mi_open_recent submenu];
+ int i_nb_items = [o_menu numberOfItems];
+ NSArray * o_docs = [[NSDocumentController sharedDocumentController]
+ recentDocumentURLs];
+ UInt32 i_nb_docs = [o_docs count];
+
+ if( i_nb_items > 1 )
+ {
+ while( --i_nb_items )
+ {
+ [o_menu removeItemAtIndex: 0];
+ }
+ }
+
+ if( i_nb_docs > 0 )
+ {
+ NSURL * o_url;
+ NSString * o_doc;
+
+ [o_menu insertItem: [NSMenuItem separatorItem] atIndex: 0];
+
+ while( TRUE )
+ {
+ i_nb_docs--;
+
+ o_url = [o_docs objectAtIndex: i_nb_docs];
+
+ if( [o_url isFileURL] )
+ {
+ o_doc = [o_url path];
+ }
+ else
+ {
+ o_doc = [o_url absoluteString];
+ }
+
+ [o_menu insertItemWithTitle: o_doc
+ action: @selector(openRecentItem:)
+ keyEquivalent: @"" atIndex: 0];
+
+ if( i_nb_docs == 0 )
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ bEnabled = FALSE;
+ }
+ }
+
+ return( bEnabled );
+}
+
+@end
+
+@implementation VLCMain (Internal)
+
+- (void)handlePortMessage:(NSPortMessage *)o_msg
+{
+ NSData * o_req;
+ vout_req_t * p_req;
+
+ o_req = [[o_msg components] lastObject];
+ p_req = *((vout_req_t **)[o_req bytes]);
+
+ [p_req->o_lock lock];
+
+ if( p_req->i_type == VOUT_REQ_CREATE_WINDOW )
+ {
+ VLCView * o_view;
+
+ p_req->p_vout->p_sys->o_window = [VLCWindow alloc];
+ [p_req->p_vout->p_sys->o_window setVout: p_req->p_vout];
+ [p_req->p_vout->p_sys->o_window setReleasedWhenClosed: YES];
+
+ if( p_req->p_vout->b_fullscreen )
+ {
+ [p_req->p_vout->p_sys->o_window
+ initWithContentRect: [[NSScreen mainScreen] frame]
+ styleMask: NSBorderlessWindowMask
+ backing: NSBackingStoreBuffered
+ defer: NO screen: [NSScreen mainScreen]];
+
+ [p_req->p_vout->p_sys->o_window
+ setLevel: NSModalPanelWindowLevel];
+ }
+ else
+ {
+ unsigned int i_stylemask = NSTitledWindowMask |
+ NSMiniaturizableWindowMask |
+ NSResizableWindowMask;
+
+ [p_req->p_vout->p_sys->o_window
+ initWithContentRect: p_req->p_vout->p_sys->s_rect
+ styleMask: i_stylemask
+ backing: NSBackingStoreBuffered
+ defer: NO screen: [NSScreen mainScreen]];
+
+ if( !p_req->p_vout->p_sys->b_pos_saved )
+ {
+ [p_req->p_vout->p_sys->o_window center];
+ }
+ }
+
+ o_view = [[VLCView alloc] init];
+ [o_view setVout: p_req->p_vout];
+ [o_view setMenu: o_mu_controls];
+ [p_req->p_vout->p_sys->o_window setContentView: o_view];
+ [o_view autorelease];
+
+ [o_view lockFocus];
+ p_req->p_vout->p_sys->p_qdport = [o_view qdPort];
+ [o_view unlockFocus];
+
+ [p_req->p_vout->p_sys->o_window setTitle: [NSString
+ stringWithCString: VOUT_TITLE " (QuickTime)"]];
+ [p_req->p_vout->p_sys->o_window setAcceptsMouseMovedEvents: YES];
+ [p_req->p_vout->p_sys->o_window makeKeyAndOrderFront: nil];
+
+ p_req->i_result = 1;
+ }
+ else if( p_req->i_type == VOUT_REQ_DESTROY_WINDOW )
+ {
+ if( !p_req->p_vout->b_fullscreen )
+ {
+ NSRect s_rect;
+
+ s_rect = [[p_req->p_vout->p_sys->o_window contentView] frame];
+ p_req->p_vout->p_sys->s_rect.size = s_rect.size;
+
+ s_rect = [p_req->p_vout->p_sys->o_window frame];
+ p_req->p_vout->p_sys->s_rect.origin = s_rect.origin;
+
+ p_req->p_vout->p_sys->b_pos_saved = 1;
+ }
+
+ p_req->p_vout->p_sys->p_qdport = nil;
+ [p_req->p_vout->p_sys->o_window close];
+ p_req->p_vout->p_sys->o_window = nil;
+
+ p_req->i_result = 1;
+ }
+
+ [p_req->o_lock unlockWithCondition: 1];
+}
+
+@end
+
--- /dev/null
+/*****************************************************************************
+ * macosx.m: MacOS X plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: macosx.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Colin Delacroix <colin@zoy.org>
+ * Eugenio Jarosiewicz <ej0@cise.ufl.edu>
+ * Florian G. Pflug <fgp@phlo.org>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(OpenIntf) ( vlc_object_t * );
+void E_(CloseIntf) ( vlc_object_t * );
+
+int E_(OpenAudio) ( vlc_object_t * );
+void E_(CloseAudio) ( vlc_object_t * );
+
+int E_(OpenVideo) ( vlc_object_t * );
+void E_(CloseVideo) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("MacOS X interface, sound and video module") );
+ add_submodule();
+ set_capability( "interface", 100 );
+ set_callbacks( E_(OpenIntf), E_(CloseIntf) );
+ add_submodule();
+ set_capability( "video output", 100 );
+ set_callbacks( E_(OpenVideo), E_(CloseVideo) );
+ add_submodule();
+ set_capability( "audio output", 100 );
+ set_callbacks( E_(OpenAudio), E_(CloseAudio) );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * open.h: MacOS X plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: open.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+NSArray *GetEjectableMediaOfClass( const char *psz_class );
+
+/*****************************************************************************
+ * Intf_Open interface
+ *****************************************************************************/
+@interface VLCOpen : NSObject
+{
+ IBOutlet id o_playlist;
+
+ IBOutlet id o_disc_panel;
+ IBOutlet id o_disc_btn_ok;
+ IBOutlet id o_disc_btn_cancel;
+ IBOutlet id o_disc_lbl_type;
+ IBOutlet id o_disc_lbl_sp;
+ IBOutlet id o_disc_type;
+ IBOutlet id o_disc_title;
+ IBOutlet id o_disc_chapter;
+ IBOutlet id o_disc_device;
+
+ IBOutlet id o_net_panel;
+ IBOutlet id o_net_btn_ok;
+ IBOutlet id o_net_btn_cancel;
+ IBOutlet id o_net_box_mode;
+ IBOutlet id o_net_box_addr;
+ IBOutlet id o_net_mode;
+ IBOutlet id o_net_address;
+ IBOutlet id o_net_port;
+ IBOutlet id o_net_port_lbl;
+ IBOutlet id o_net_port_stp;
+
+ IBOutlet id o_quickly_panel;
+ IBOutlet id o_quickly_btn_ok;
+ IBOutlet id o_quickly_btn_cancel;
+ IBOutlet id o_quickly_source;
+}
+
+- (IBAction)openFile:(id)sender;
+
+- (IBAction)openDisc:(id)sender;
+- (IBAction)openDiscTypeChanged:(id)sender;
+
+- (IBAction)openNet:(id)sender;
+- (IBAction)openNetModeChanged:(id)sender;
+
+- (IBAction)openQuickly:(id)sender;
+
+- (IBAction)panelCancel:(id)sender;
+- (IBAction)panelOk:(id)sender;
+
+@end
--- /dev/null
+/*****************************************************************************
+ * open.m: MacOS X plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: open.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <sys/param.h> /* for MAXPATHLEN */
+#include <string.h>
+
+#include <paths.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IOCDMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
+
+#import <Cocoa/Cocoa.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include "netutils.h"
+
+#import "intf.h"
+#import "playlist.h"
+#import "intf_open.h"
+
+/*****************************************************************************
+ * GetEjectableMediaOfClass
+ *****************************************************************************/
+NSArray *GetEjectableMediaOfClass( const char *psz_class )
+{
+ io_object_t next_media;
+ mach_port_t master_port;
+ kern_return_t kern_result;
+ NSArray *o_devices = nil;
+ NSMutableArray *p_list = nil;
+ io_iterator_t media_iterator;
+ CFMutableDictionaryRef classes_to_match;
+
+ kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
+ if( kern_result != KERN_SUCCESS )
+ {
+ return( nil );
+ }
+
+ classes_to_match = IOServiceMatching( psz_class );
+ if( classes_to_match == NULL )
+ {
+ return( nil );
+ }
+
+ CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectable ),
+ kCFBooleanTrue );
+
+ kern_result = IOServiceGetMatchingServices( master_port, classes_to_match,
+ &media_iterator );
+ if( kern_result != KERN_SUCCESS )
+ {
+ return( nil );
+ }
+
+ p_list = [NSMutableArray arrayWithCapacity: 1];
+
+ next_media = IOIteratorNext( media_iterator );
+ if( next_media != NULL )
+ {
+ char psz_buf[0x32];
+ size_t dev_path_length;
+ CFTypeRef str_bsd_path;
+
+ do
+ {
+ str_bsd_path = IORegistryEntryCreateCFProperty( next_media,
+ CFSTR( kIOBSDName ),
+ kCFAllocatorDefault,
+ 0 );
+ if( str_bsd_path == NULL )
+ {
+ IOObjectRelease( next_media );
+ continue;
+ }
+
+ snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' );
+ dev_path_length = strlen( psz_buf );
+
+ if( CFStringGetCString( str_bsd_path,
+ (char*)&psz_buf + dev_path_length,
+ sizeof(psz_buf) - dev_path_length,
+ kCFStringEncodingASCII ) )
+ {
+ [p_list addObject: [NSString stringWithCString: psz_buf]];
+ }
+
+ CFRelease( str_bsd_path );
+
+ IOObjectRelease( next_media );
+
+ } while( ( next_media = IOIteratorNext( media_iterator ) ) != NULL );
+ }
+
+ IOObjectRelease( media_iterator );
+
+ o_devices = [NSArray arrayWithArray: p_list];
+
+ return( o_devices );
+}
+
+/*****************************************************************************
+ * VLCOpen implementation
+ *****************************************************************************/
+@implementation VLCOpen
+
+- (void)awakeFromNib
+{
+ [o_disc_panel setTitle: _NS("Open Disc")];
+ [o_disc_btn_ok setTitle: _NS("OK")];
+ [o_disc_btn_cancel setTitle: _NS("Cancel")];
+ [o_disc_lbl_type setTitle: _NS("Disc type")];
+ [o_disc_lbl_sp setTitle: _NS("Starting position")];
+ [o_disc_title setTitle: _NS("Title")];
+ [o_disc_chapter setTitle: _NS("Chapter")];
+
+ [o_net_panel setTitle: _NS("Open Network")];
+ [o_net_box_mode setTitle: _NS("Network mode")];
+ [o_net_box_addr setTitle: _NS("Address")];
+ [o_net_port_lbl setStringValue: _NS("Port")];
+
+ [o_quickly_panel setTitle: _NS("Open Quickly")];
+ [o_quickly_btn_ok setTitle: _NS("OK")];
+ [o_quickly_btn_cancel setTitle: _NS("Cancel")];
+}
+
+- (IBAction)openDisc:(id)sender
+{
+ int i_result;
+
+ [self openDiscTypeChanged: nil];
+
+ [o_disc_panel makeKeyAndOrderFront: self];
+ i_result = [NSApp runModalForWindow: o_disc_panel];
+ [o_disc_panel close];
+
+ if( i_result )
+ {
+ NSString *o_source;
+
+ NSString *o_type = [[o_disc_type selectedCell] title];
+ NSString *o_device = [o_disc_device stringValue];
+ int i_title = [o_disc_title intValue];
+ int i_chapter = [o_disc_chapter intValue];
+
+ o_source = [NSString stringWithFormat: @"%@:%@@%d,%d",
+ [o_type lowercaseString], o_device, i_title, i_chapter];
+
+ [o_playlist appendArray:
+ [NSArray arrayWithObject: o_source] atPos: -1];
+ }
+}
+
+- (IBAction)openDiscTypeChanged:(id)sender
+{
+ NSString *o_type;
+ NSArray *o_devices;
+ const char *psz_class = NULL;
+
+ [o_disc_device removeAllItems];
+
+ o_type = [[o_disc_type selectedCell] title];
+
+ if( [o_type isEqualToString: @"DVD"] )
+ {
+ psz_class = kIODVDMediaClass;
+ }
+ else
+ {
+ psz_class = kIOCDMediaClass;
+ }
+
+ o_devices = GetEjectableMediaOfClass( psz_class );
+ if( o_devices != nil )
+ {
+ int i_devices = [o_devices count];
+
+ if( i_devices )
+ {
+ int i;
+
+ for( i = 0; i < i_devices; i++ )
+ {
+ [o_disc_device
+ addItemWithObjectValue: [o_devices objectAtIndex: i]];
+ }
+
+ [o_disc_device selectItemAtIndex: 0];
+ [o_disc_btn_ok setEnabled: TRUE];
+ }
+ else
+ {
+ [o_disc_device setStringValue:
+ [NSString stringWithFormat: @"No %@s found", o_type]];
+ [o_disc_btn_ok setEnabled: FALSE];
+ }
+ }
+}
+
+- (IBAction)openFile:(id)sender
+{
+ NSOpenPanel *o_panel = [NSOpenPanel openPanel];
+
+ [o_panel setAllowsMultipleSelection: YES];
+
+ if( [o_panel runModalForDirectory: nil
+ file: nil types: nil] == NSOKButton )
+ {
+ [o_playlist appendArray: [o_panel filenames] atPos: -1];
+ }
+}
+
+- (IBAction)openNet:(id)sender
+{
+ int i_result;
+ intf_thread_t * p_intf = [NSApp getIntf];
+
+ [o_net_panel makeKeyAndOrderFront: self];
+ i_result = [NSApp runModalForWindow: o_net_panel];
+ [o_net_panel close];
+
+ if( i_result )
+ {
+ NSString * o_source = nil;
+ UInt32 i_port = [o_net_port intValue];
+ NSString * o_addr = [o_net_address stringValue];
+ NSString * o_mode = [[o_net_mode selectedCell] title];
+
+ if( i_port > 65536 )
+ {
+ NSBeep();
+ return;
+ }
+
+ if( [o_mode isEqualToString: @"UDP"] )
+ {
+ o_source = [NSString
+ stringWithFormat: @"udp:@:%i", i_port];
+ }
+ else if( [o_mode isEqualToString: @"UDP Multicase"] )
+ {
+ o_source = [NSString
+ stringWithFormat: @"udp:@%@:%i", o_addr, i_port];
+ }
+ else if( [o_mode isEqualToString: @"Channel server"] )
+ {
+ if( p_intf->p_vlc->p_channel == NULL )
+ {
+ network_ChannelCreate( p_intf );
+ }
+
+ config_PutPsz( p_intf, "channel-server",
+ (char *)[o_addr lossyCString] );
+ config_PutInt( p_intf, "channel-port", i_port );
+
+ p_intf->p_sys->b_playing = 1;
+ }
+ else if( [o_mode isEqualToString: @"HTTP"] )
+ {
+ o_source = o_addr;
+ }
+
+ if( o_source != nil )
+ {
+ [o_playlist appendArray:
+ [NSArray arrayWithObject: o_source] atPos: -1];
+ }
+ }
+}
+
+- (IBAction)openNetModeChanged:(id)sender
+{
+ NSString * o_mode;
+ SInt32 i_port = 1234;
+ NSString * o_addr = nil;
+
+ o_mode = [[o_net_mode selectedCell] title];
+
+ if( [o_mode isEqualToString: @"UDP Multicast"] )
+ {
+ o_addr = @"";
+ }
+ else if( [o_mode isEqualToString: @"Channel server"] )
+ {
+ o_addr = @"localhost";
+ i_port = 6010;
+ }
+ else if( [o_mode isEqualToString: @"HTTP"] )
+ {
+ o_addr = @"http://";
+ i_port = -1;
+ }
+
+ if( o_addr != nil )
+ {
+ [o_net_address setEnabled: TRUE];
+ [o_net_address setStringValue: o_addr];
+ }
+ else
+ {
+ [o_net_address setEnabled: FALSE];
+ }
+
+ if( i_port > -1 )
+ {
+ [o_net_port setEnabled: TRUE];
+ [o_net_port_stp setEnabled: TRUE];
+ [o_net_port setIntValue: i_port];
+ }
+ else
+ {
+ [o_net_port setEnabled: FALSE];
+ [o_net_port_stp setEnabled: FALSE];
+ }
+}
+
+- (IBAction)openQuickly:(id)sender
+{
+ int i_result;
+
+ [o_quickly_source setStringValue: @""];
+ [o_quickly_panel makeKeyAndOrderFront: self];
+ i_result = [NSApp runModalForWindow: o_quickly_panel];
+ [o_quickly_panel close];
+
+ if( i_result )
+ {
+ NSString * o_source;
+
+ o_source = [o_quickly_source stringValue];
+
+ if( [o_source length] > 0 )
+ {
+ [o_playlist appendArray:
+ [NSArray arrayWithObject: o_source] atPos: -1];
+ }
+ else
+ {
+ NSBeep();
+ }
+ }
+}
+
+- (IBAction)panelCancel:(id)sender
+{
+ [NSApp stopModalWithCode: 0];
+}
+
+- (IBAction)panelOk:(id)sender
+{
+ [NSApp stopModalWithCode: 1];
+}
+
+@end
--- /dev/null
+/*****************************************************************************
+ * playlist.h: MacOS X interface plugin
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: playlist.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * VLCPlaylistView interface
+ *****************************************************************************/
+@interface VLCPlaylistView : NSTableView
+{
+
+}
+
+@end
+
+/*****************************************************************************
+ * VLCPlaylist interface
+ *****************************************************************************/
+@interface VLCPlaylist : NSObject
+{
+ IBOutlet id o_panel;
+ IBOutlet id o_btn_close;
+ IBOutlet id o_table_view;
+}
+
+- (void)appendArray:(NSArray*)o_array atPos:(int)i_pos;
+
+@end
+
--- /dev/null
+/*****************************************************************************
+ * playlist.m: MacOS X interface plugin
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: playlist.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <sys/param.h> /* for MAXPATHLEN */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <Cocoa/Cocoa.h>
+
+#include "intf.h"
+#include "playlist.h"
+
+/*****************************************************************************
+ * VLCPlaylistView implementation
+ *****************************************************************************/
+@implementation VLCPlaylistView
+
+- (NSMenu *)menuForEvent:(NSEvent *)o_event
+{
+ /* TODO */
+
+ return( nil );
+}
+
+@end
+
+/*****************************************************************************
+ * VLCPlaylist implementation
+ *****************************************************************************/
+@implementation VLCPlaylist
+
+- (void)awakeFromNib
+{
+ [o_table_view setTarget: self];
+ [o_table_view setDelegate: self];
+ [o_table_view setDataSource: self];
+
+ [o_table_view setDoubleAction: @selector(doubleClick:)];
+
+ [o_table_view registerForDraggedTypes:
+ [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
+
+ [o_panel setTitle: _NS("Playlist")];
+ [o_btn_close setTitle: _NS("Close")];
+}
+
+- (BOOL)tableView:(NSTableView *)o_tv
+ shouldEditTableColumn:(NSTableColumn *)o_tc
+ row:(int)i_row
+{
+ return( NO );
+}
+
+- (NSDragOperation)tableView:(NSTableView*)o_tv
+ validateDrop:(id <NSDraggingInfo>)info
+ proposedRow:(int)i_row
+ proposedDropOperation:(NSTableViewDropOperation)operation
+{
+ return( NSDragOperationPrivate );
+}
+
+- (BOOL)tableView:(NSTableView*)o_tv
+ acceptDrop:(id <NSDraggingInfo>)info
+ row:(int)i_row
+ dropOperation:(NSTableViewDropOperation)operation
+{
+ NSArray * o_values;
+ NSPasteboard * o_pasteboard;
+
+ o_pasteboard = [info draggingPasteboard];
+
+ if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] )
+ {
+ o_values = [o_pasteboard propertyListForType: NSFilenamesPboardType];
+
+ [self appendArray: o_values atPos: i_row];
+
+ if( i_row != -1 )
+ {
+ [o_table_view reloadData];
+ }
+
+ return( YES );
+ }
+
+ return( NO );
+}
+
+- (void)tableView:(NSTableView *)o_tv willDisplayCell:(id)o_cell
+ forTableColumn:(NSTableColumn *)o_tc row:(int)i_row
+{
+ [o_cell setDrawsBackground: YES];
+
+ if( i_row % 2 )
+ {
+ [o_cell setBackgroundColor:
+ [NSColor colorWithDeviceRed: 0.937255
+ green: 0.968627
+ blue: 1.0
+ alpha: 1.0]];
+ }
+ else
+ {
+ [o_cell setBackgroundColor: [NSColor whiteColor]];
+ }
+}
+
+- (IBAction)doubleClick:(id)sender
+{
+ NSTableView * o_tv = sender;
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Goto( p_playlist, [o_tv clickedRow] );
+
+ vlc_object_release( p_playlist );
+}
+
+- (void)appendArray:(NSArray*)o_array atPos:(int)i_pos
+{
+ int i_items;
+ NSString * o_value;
+ NSEnumerator * o_enum;
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ if( p_intf->p_sys->b_loop )
+ {
+ playlist_Delete( p_playlist, p_playlist->i_size - 1 );
+ }
+
+ i_items = 0;
+ o_enum = [o_array objectEnumerator];
+ while( ( o_value = [o_enum nextObject] ) )
+ {
+ NSURL * o_url;
+
+ int i_mode = i_items == 0 ? PLAYLIST_INSERT | PLAYLIST_GO :
+ PLAYLIST_INSERT;
+
+ playlist_Add( p_playlist, [o_value fileSystemRepresentation],
+ i_mode, i_pos == -1 ? PLAYLIST_END : i_pos + i_items );
+
+ o_url = [NSURL fileURLWithPath: o_value];
+ if( o_url != nil )
+ {
+ [[NSDocumentController sharedDocumentController]
+ noteNewRecentDocumentURL: o_url];
+ }
+
+ i_items++;
+ }
+
+ if( p_intf->p_sys->b_loop )
+ {
+ playlist_Add( p_playlist, "vlc:loop",
+ PLAYLIST_APPEND, PLAYLIST_END );
+ }
+
+ vlc_object_release( p_playlist );
+}
+
+@end
+
+@implementation VLCPlaylist (NSTableDataSource)
+
+- (int)numberOfRowsInTableView:(NSTableView *)o_tv
+{
+ int i_count = 0;
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if( p_playlist != NULL )
+ {
+ i_count = p_playlist->i_size;
+ vlc_object_release( p_playlist );
+ }
+
+ return( i_count );
+}
+
+- (id)tableView:(NSTableView *)o_tv
+ objectValueForTableColumn:(NSTableColumn *)o_tc
+ row:(int)i_row
+{
+ id o_value = nil;
+ intf_thread_t * p_intf = [NSApp getIntf];
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if( p_playlist == NULL )
+ {
+ return( nil );
+ }
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+ o_value = [NSString stringWithCString:
+ p_playlist->pp_items[i_row]->psz_name];
+ vlc_mutex_unlock( &p_playlist->object_lock );
+
+ vlc_object_release( p_playlist );
+
+ return( o_value );
+}
+
+@end
+
--- /dev/null
+/*****************************************************************************
+ * vout.h: MacOS X interface plugin
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: vout.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Colin Delacroix <colin@zoy.org>
+ * Florian G. Pflug <fgp@phlo.org>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * VLCWindow interface
+ *****************************************************************************/
+@interface VLCWindow : NSWindow
+{
+ vout_thread_t * p_vout;
+}
+
+- (void)setVout:(vout_thread_t *)_p_vout;
+
+- (void)toggleFullscreen;
+- (BOOL)isFullscreen;
+
+@end
+
+/*****************************************************************************
+ * VLCView interface
+ *****************************************************************************/
+@interface VLCView : NSQuickDrawView
+{
+ vout_thread_t * p_vout;
+}
+
+- (void)setVout:(vout_thread_t *)_p_vout;
+
+@end
+
+/*****************************************************************************
+ * vout_sys_t: MacOS X video output method descriptor
+ *****************************************************************************/
+struct vout_sys_t
+{
+ intf_thread_t * p_intf;
+ VLCWindow * o_window;
+
+ NSRect s_rect;
+ int b_pos_saved;
+
+ vlc_bool_t b_mouse_moved;
+ vlc_bool_t b_mouse_pointer_visible;
+ mtime_t i_time_mouse_last_moved;
+
+#ifdef __QUICKTIME__
+ CodecType i_codec;
+ CGrafPtr p_qdport;
+ ImageSequence i_seq;
+ MatrixRecordPtr p_matrix;
+ DecompressorComponent img_dc;
+ ImageDescriptionHandle h_img_descr;
+#endif
+};
+
+/*****************************************************************************
+ * vout_req_t: MacOS X video output request
+ *****************************************************************************/
+#define VOUT_REQ_CREATE_WINDOW 0x00000001
+#define VOUT_REQ_DESTROY_WINDOW 0x00000002
+
+typedef struct vout_req_t
+{
+ int i_type;
+ int i_result;
+
+ NSConditionLock * o_lock;
+
+ vout_thread_t * p_vout;
+} vout_req_t;
--- /dev/null
+/*****************************************************************************
+ * vout.m: MacOS X video output plugin
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: vout.m,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Colin Delacroix <colin@zoy.org>
+ * Florian G. Pflug <fgp@phlo.org>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/aout.h>
+#include <vlc/intf.h>
+
+#include <Cocoa/Cocoa.h>
+#include <QuickTime/QuickTime.h>
+
+#include "intf.h"
+#include "vout.h"
+
+#define QT_MAX_DIRECTBUFFERS 10
+
+struct picture_sys_t
+{
+ void *p_info;
+ unsigned int i_size;
+
+ /* When using I420 output */
+ PlanarPixmapInfoYUV420 pixmap_i420;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int vout_Init ( vout_thread_t * );
+static void vout_End ( vout_thread_t * );
+static int vout_Manage ( vout_thread_t * );
+static void vout_Render ( vout_thread_t *, picture_t * );
+static void vout_Display ( vout_thread_t *, picture_t * );
+
+static int CoSendRequest ( vout_thread_t *, long );
+static int CoCreateWindow ( vout_thread_t * );
+static int CoDestroyWindow ( vout_thread_t * );
+static int CoToggleFullscreen ( vout_thread_t * );
+
+static void QTScaleMatrix ( vout_thread_t * );
+static int QTCreateSequence ( vout_thread_t * );
+static void QTDestroySequence ( vout_thread_t * );
+static int QTNewPicture ( vout_thread_t *, picture_t * );
+static void QTFreePicture ( vout_thread_t *, picture_t * );
+
+/*****************************************************************************
+ * OpenVideo: allocates MacOS X video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a MacOS X vout method.
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+ OSErr err;
+
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
+
+ p_vout->p_sys->p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+ if( p_vout->p_sys->p_intf == NULL )
+ {
+ msg_Err( p_vout, "no interface present" );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ if( p_vout->p_sys->p_intf->p_module == NULL ||
+ strcmp( p_vout->p_sys->p_intf->p_module->psz_object_name,
+ MODULE_STRING ) != 0 )
+ {
+ msg_Err( p_vout, "MacOS X interface module required" );
+ vlc_object_release( p_vout->p_sys->p_intf );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ p_vout->p_sys->h_img_descr =
+ (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
+ p_vout->p_sys->p_matrix = (MatrixRecordPtr)malloc( sizeof(MatrixRecord) );
+
+ p_vout->p_sys->b_mouse_pointer_visible = 1;
+
+ /* set window size */
+ p_vout->p_sys->s_rect.size.width = p_vout->i_window_width;
+ p_vout->p_sys->s_rect.size.height = p_vout->i_window_height;
+
+ if( ( err = EnterMovies() ) != noErr )
+ {
+ msg_Err( p_vout, "EnterMovies failed: %d", err );
+ free( p_vout->p_sys->p_matrix );
+ DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ if( vout_ChromaCmp( p_vout->render.i_chroma, VLC_FOURCC('I','4','2','0') ) )
+ {
+ err = FindCodec( kYUV420CodecType, bestSpeedCodec,
+ nil, &p_vout->p_sys->img_dc );
+ if( err == noErr && p_vout->p_sys->img_dc != 0 )
+ {
+ p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
+ p_vout->p_sys->i_codec = kYUV420CodecType;
+ }
+ else
+ {
+ msg_Err( p_vout, "failed to find an appropriate codec" );
+ }
+ }
+ else
+ {
+ msg_Err( p_vout, "chroma 0x%08x not supported",
+ p_vout->render.i_chroma );
+ }
+
+ if( p_vout->p_sys->img_dc == 0 )
+ {
+ free( p_vout->p_sys->p_matrix );
+ DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ if( CoCreateWindow( p_vout ) )
+ {
+ msg_Err( p_vout, "unable to create window" );
+ free( p_vout->p_sys->p_matrix );
+ DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ p_vout->pf_init = vout_Init;
+ p_vout->pf_end = vout_End;
+ p_vout->pf_manage = vout_Manage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = vout_Display;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * vout_Init: initialize video thread output method
+ *****************************************************************************/
+static int vout_Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure; we already found a codec,
+ * and the corresponding chroma we will be using. Since we can
+ * arbitrary scale, stick to the coordinates and aspect. */
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ SetPort( p_vout->p_sys->p_qdport );
+ QTScaleMatrix( p_vout );
+
+ if( QTCreateSequence( p_vout ) )
+ {
+ msg_Err( p_vout, "unable to create sequence" );
+ return( 1 );
+ }
+
+ /* Try to initialize up to QT_MAX_DIRECTBUFFERS direct buffers */
+ while( I_OUTPUTPICTURES < QT_MAX_DIRECTBUFFERS )
+ {
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture */
+ if( p_pic == NULL || QTNewPicture( p_vout, p_pic ) )
+ {
+ break;
+ }
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * vout_End: terminate video thread output method
+ *****************************************************************************/
+static void vout_End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ QTDestroySequence( p_vout );
+
+ /* Free the direct buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES; i_index; )
+ {
+ i_index--;
+ QTFreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
+ }
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy video thread output method
+ *****************************************************************************/
+void E_(CloseVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ if( CoDestroyWindow( p_vout ) )
+ {
+ msg_Err( p_vout, "unable to destroy window" );
+ }
+
+ ExitMovies();
+
+ free( p_vout->p_sys->p_matrix );
+ DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
+
+ vlc_object_release( p_vout->p_sys->p_intf );
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * vout_Manage: handle events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * console events. It returns a non null value on error.
+ *****************************************************************************/
+static int vout_Manage( vout_thread_t *p_vout )
+{
+ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+ {
+ if( CoToggleFullscreen( p_vout ) )
+ {
+ return( 1 );
+ }
+
+ p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+ }
+
+ if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+ {
+ QTScaleMatrix( p_vout );
+ SetDSequenceMatrix( p_vout->p_sys->i_seq,
+ p_vout->p_sys->p_matrix );
+
+ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+ }
+
+ /* hide/show mouse cursor */
+ if( p_vout->p_sys->b_mouse_moved ||
+ p_vout->p_sys->i_time_mouse_last_moved )
+ {
+ vlc_bool_t b_change = 0;
+
+ if( !p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ CGDisplayShowCursor( kCGDirectMainDisplay );
+ b_change = 1;
+ }
+#if 0
+ else if( !p_vout->p_sys->b_mouse_moved &&
+ mdate() - p_vout->p_sys->i_time_mouse_last_moved > 2000000 &&
+ p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ CGDisplayHideCursor( kCGDirectMainDisplay );
+ b_change = 1;
+ }
+#endif
+
+ if( b_change )
+ {
+ p_vout->p_sys->i_time_mouse_last_moved = 0;
+ p_vout->p_sys->b_mouse_moved = 0;
+ p_vout->p_sys->b_mouse_pointer_visible =
+ !p_vout->p_sys->b_mouse_pointer_visible;
+ }
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * vout_Display: displays previously rendered output
+ *****************************************************************************
+ * This function sends the currently rendered image to the display.
+ *****************************************************************************/
+static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ OSErr err;
+ CodecFlags flags;
+
+ if( ( err = DecompressSequenceFrameS(
+ p_vout->p_sys->i_seq,
+ p_pic->p_sys->p_info,
+ p_pic->p_sys->i_size,
+ codecFlagUseImageBuffer, &flags, nil ) != noErr ) )
+ {
+ msg_Err( p_vout, "DecompressSequenceFrameS failed: %d", err );
+ }
+ else
+ {
+ QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil );
+ }
+}
+
+/*****************************************************************************
+ * CoSendRequest: send request to interface thread
+ *****************************************************************************
+ * Returns 0 on success, 1 otherwise
+ *****************************************************************************/
+static int CoSendRequest( vout_thread_t *p_vout, long i_request )
+{
+ NSArray *o_array;
+ NSPortMessage *o_msg;
+ struct vout_req_t req;
+ struct vout_req_t *p_req = &req;
+ NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
+ NSPort *recvPort = [[NSPort port] retain];
+
+ memset( &req, 0, sizeof(req) );
+ req.i_type = i_request;
+ req.p_vout = p_vout;
+
+ req.o_lock = [[NSConditionLock alloc] initWithCondition: 0];
+
+ o_array = [NSArray arrayWithObject:
+ [NSData dataWithBytes: &p_req length: sizeof(void *)]];
+ o_msg = [[NSPortMessage alloc]
+ initWithSendPort: p_vout->p_sys->p_intf->p_sys->o_sendport
+ receivePort: recvPort components: o_array];
+
+ [o_msg sendBeforeDate: [NSDate distantPast]];
+
+ [req.o_lock lockWhenCondition: 1];
+ [req.o_lock unlock];
+
+ [o_msg release];
+ [req.o_lock release];
+
+ [recvPort release];
+ [o_pool release];
+
+ return( !req.i_result );
+}
+
+/*****************************************************************************
+ * CoCreateWindow: create new window
+ *****************************************************************************
+ * Returns 0 on success, 1 otherwise
+ *****************************************************************************/
+static int CoCreateWindow( vout_thread_t *p_vout )
+{
+ if( CoSendRequest( p_vout, VOUT_REQ_CREATE_WINDOW ) )
+ {
+ msg_Err( p_vout, "CoSendRequest (CREATE_WINDOW) failed" );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CoDestroyWindow: destroy window
+ *****************************************************************************
+ * Returns 0 on success, 1 otherwise
+ *****************************************************************************/
+static int CoDestroyWindow( vout_thread_t *p_vout )
+{
+ if( !p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ CGDisplayShowCursor( kCGDirectMainDisplay );
+ p_vout->p_sys->b_mouse_pointer_visible = 1;
+ }
+
+ if( CoSendRequest( p_vout, VOUT_REQ_DESTROY_WINDOW ) )
+ {
+ msg_Err( p_vout, "CoSendRequest (DESTROY_WINDOW) failed" );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CoToggleFullscreen: toggle fullscreen
+ *****************************************************************************
+ * Returns 0 on success, 1 otherwise
+ *****************************************************************************/
+static int CoToggleFullscreen( vout_thread_t *p_vout )
+{
+ QTDestroySequence( p_vout );
+
+ if( CoDestroyWindow( p_vout ) )
+ {
+ msg_Err( p_vout, "unable to destroy window" );
+ return( 1 );
+ }
+
+ p_vout->b_fullscreen = !p_vout->b_fullscreen;
+
+ if( p_vout->b_fullscreen )
+ {
+ HideMenuBar();
+ }
+ else
+ {
+ ShowMenuBar();
+ }
+
+ if( CoCreateWindow( p_vout ) )
+ {
+ msg_Err( p_vout, "unable to create window" );
+ return( 1 );
+ }
+
+ SetPort( p_vout->p_sys->p_qdport );
+ QTScaleMatrix( p_vout );
+
+ if( QTCreateSequence( p_vout ) )
+ {
+ msg_Err( p_vout, "unable to create sequence" );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * QTScaleMatrix: scale matrix
+ *****************************************************************************/
+static void QTScaleMatrix( vout_thread_t *p_vout )
+{
+ Rect s_rect;
+ int i_width, i_height;
+ Fixed factor_x, factor_y;
+ int i_offset_x = 0;
+ int i_offset_y = 0;
+
+ GetPortBounds( p_vout->p_sys->p_qdport, &s_rect );
+
+ i_width = s_rect.right - s_rect.left;
+ i_height = s_rect.bottom - s_rect.top;
+
+ if( i_height * p_vout->output.i_aspect < i_width * VOUT_ASPECT_FACTOR )
+ {
+ int i_adj_width = i_height * p_vout->output.i_aspect /
+ VOUT_ASPECT_FACTOR;
+
+ factor_x = FixDiv( Long2Fix( i_adj_width ),
+ Long2Fix( p_vout->output.i_width ) );
+ factor_y = FixDiv( Long2Fix( i_height ),
+ Long2Fix( p_vout->output.i_height ) );
+
+ i_offset_x = (i_width - i_adj_width) / 2;
+ }
+ else
+ {
+ int i_adj_height = i_width * VOUT_ASPECT_FACTOR /
+ p_vout->output.i_aspect;
+
+ factor_x = FixDiv( Long2Fix( i_width ),
+ Long2Fix( p_vout->output.i_width ) );
+ factor_y = FixDiv( Long2Fix( i_adj_height ),
+ Long2Fix( p_vout->output.i_height ) );
+
+ i_offset_y = (i_height - i_adj_height) / 2;
+ }
+
+ SetIdentityMatrix( p_vout->p_sys->p_matrix );
+
+ ScaleMatrix( p_vout->p_sys->p_matrix,
+ factor_x, factor_y,
+ Long2Fix(0), Long2Fix(0) );
+
+ TranslateMatrix( p_vout->p_sys->p_matrix,
+ Long2Fix(i_offset_x),
+ Long2Fix(i_offset_y) );
+}
+
+/*****************************************************************************
+ * QTCreateSequence: create a new sequence
+ *****************************************************************************
+ * Returns 0 on success, 1 otherwise
+ *****************************************************************************/
+static int QTCreateSequence( vout_thread_t *p_vout )
+{
+ OSErr err;
+ ImageDescriptionPtr p_descr;
+
+ HLock( (Handle)p_vout->p_sys->h_img_descr );
+ p_descr = *p_vout->p_sys->h_img_descr;
+
+ p_descr->idSize = sizeof(ImageDescription);
+ p_descr->cType = p_vout->p_sys->i_codec;
+ p_descr->version = 1;
+ p_descr->revisionLevel = 0;
+ p_descr->vendor = 'appl';
+ p_descr->width = p_vout->output.i_width;
+ p_descr->height = p_vout->output.i_height;
+ p_descr->hRes = Long2Fix(72);
+ p_descr->vRes = Long2Fix(72);
+ p_descr->spatialQuality = codecLosslessQuality;
+ p_descr->frameCount = 1;
+ p_descr->clutID = -1;
+ p_descr->dataSize = 0;
+ p_descr->depth = 24;
+
+ HUnlock( (Handle)p_vout->p_sys->h_img_descr );
+
+ if( ( err = DecompressSequenceBeginS(
+ &p_vout->p_sys->i_seq,
+ p_vout->p_sys->h_img_descr,
+ NULL, 0,
+ p_vout->p_sys->p_qdport,
+ NULL, NULL,
+ p_vout->p_sys->p_matrix,
+ 0, NULL,
+ codecFlagUseImageBuffer,
+ codecLosslessQuality,
+ p_vout->p_sys->img_dc ) ) )
+ {
+ msg_Err( p_vout, "DecompressSequenceBeginS failed: %d", err );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * QTDestroySequence: destroy sequence
+ *****************************************************************************/
+static void QTDestroySequence( vout_thread_t *p_vout )
+{
+ CDSequenceEnd( p_vout->p_sys->i_seq );
+}
+
+/*****************************************************************************
+ * QTNewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, 1 otherwise
+ *****************************************************************************/
+static int QTNewPicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ int i_width = p_vout->output.i_width;
+ int i_height = p_vout->output.i_height;
+
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+ if( p_pic->p_sys == NULL )
+ {
+ return( -1 );
+ }
+
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('I','4','2','0'):
+
+ p_pic->p_sys->p_info = (void *)&p_pic->p_sys->pixmap_i420;
+ p_pic->p_sys->i_size = sizeof(PlanarPixmapInfoYUV420);
+
+ /* Allocate the memory buffer */
+ p_pic->p_data = vlc_memalign( &p_pic->p_data_orig,
+ 16, i_width * i_height * 3 / 2 );
+
+ /* Y buffer */
+ p_pic->Y_PIXELS = p_pic->p_data;
+ p_pic->p[Y_PLANE].i_lines = i_height;
+ p_pic->p[Y_PLANE].i_pitch = i_width;
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = i_width;
+
+ /* U buffer */
+ p_pic->U_PIXELS = p_pic->Y_PIXELS + i_height * i_width;
+ p_pic->p[U_PLANE].i_lines = i_height / 2;
+ p_pic->p[U_PLANE].i_pitch = i_width / 2;
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = i_width / 2;
+
+ /* V buffer */
+ p_pic->V_PIXELS = p_pic->U_PIXELS + i_height * i_width / 4;
+ p_pic->p[V_PLANE].i_lines = i_height / 2;
+ p_pic->p[V_PLANE].i_pitch = i_width / 2;
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = i_width / 2;
+
+ /* We allocated 3 planes */
+ p_pic->i_planes = 3;
+
+#define P p_pic->p_sys->pixmap_i420
+ P.componentInfoY.offset = (void *)p_pic->Y_PIXELS
+ - p_pic->p_sys->p_info;
+ P.componentInfoCb.offset = (void *)p_pic->U_PIXELS
+ - p_pic->p_sys->p_info;
+ P.componentInfoCr.offset = (void *)p_pic->V_PIXELS
+ - p_pic->p_sys->p_info;
+
+ P.componentInfoY.rowBytes = i_width;
+ P.componentInfoCb.rowBytes = i_width / 2;
+ P.componentInfoCr.rowBytes = i_width / 2;
+#undef P
+
+ break;
+
+ default:
+ /* Unknown chroma, tell the guy to get lost */
+ free( p_pic->p_sys );
+ msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
+ p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );
+ p_pic->i_planes = 0;
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * QTFreePicture: destroy a picture allocated with QTNewPicture
+ *****************************************************************************/
+static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('I','4','2','0'):
+ free( p_pic->p_data_orig );
+ break;
+ }
+
+ free( p_pic->p_sys );
+}
+
+/*****************************************************************************
+ * VLCWindow implementation
+ *****************************************************************************/
+@implementation VLCWindow
+
+- (void)setVout:(vout_thread_t *)_p_vout
+{
+ p_vout = _p_vout;
+}
+
+- (void)toggleFullscreen
+{
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+}
+
+- (BOOL)isFullscreen
+{
+ return( p_vout->b_fullscreen );
+}
+
+- (BOOL)canBecomeKeyWindow
+{
+ return( YES );
+}
+
+- (void)keyDown:(NSEvent *)o_event
+{
+ unichar key = 0;
+
+ if( [[o_event characters] length] )
+ {
+ key = [[o_event characters] characterAtIndex: 0];
+ }
+
+ switch( key )
+ {
+ case (unichar)0xf700: /* up-arrow */
+ {
+ aout_thread_t * p_aout = vlc_object_find( p_vout, VLC_OBJECT_AOUT,
+ FIND_ANYWHERE );
+ if( p_aout != NULL )
+ {
+ if( p_aout->i_volume + VOLUME_STEP <= VOLUME_MAX )
+ {
+ p_aout->i_volume += VOLUME_STEP;
+ }
+
+ vlc_object_release( p_aout );
+ }
+ }
+ break;
+
+ case (unichar)0xf701: /* down-arrow */
+ {
+ aout_thread_t * p_aout = vlc_object_find( p_vout, VLC_OBJECT_AOUT,
+ FIND_ANYWHERE );
+ if( p_aout != NULL )
+ {
+ if( p_aout->i_volume - VOLUME_STEP >= VOLUME_MIN )
+ {
+ p_aout->i_volume -= VOLUME_STEP;
+ }
+
+ vlc_object_release( p_aout );
+ }
+ }
+ break;
+
+ case 'f': case 'F':
+ [self toggleFullscreen];
+ break;
+
+ case (unichar)0x1b: /* escape */
+ if( [self isFullscreen] )
+ {
+ [self toggleFullscreen];
+ }
+ break;
+
+ case 'q': case 'Q':
+ p_vout->p_vlc->b_die = VLC_TRUE;
+ break;
+
+ case ' ':
+ input_SetStatus( p_vout, INPUT_STATUS_PAUSE );
+ break;
+
+ default:
+ [super keyDown: o_event];
+ break;
+ }
+}
+
+@end
+
+/*****************************************************************************
+ * VLCView implementation
+ *****************************************************************************/
+@implementation VLCView
+
+- (void)setVout:(vout_thread_t *)_p_vout
+{
+ p_vout = _p_vout;
+}
+
+- (void)drawRect:(NSRect)rect
+{
+ [[NSColor blackColor] set];
+ NSRectFill( rect );
+ [super drawRect: rect];
+
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+}
+
+@end
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+ncurses_SOURCES = ncurses.c
--- /dev/null
+/*****************************************************************************
+ * ncurses.c : NCurses plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: ncurses.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+#include <errno.h> /* ENOMEM */
+#include <stdio.h>
+#include <time.h>
+
+#include <curses.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static void Run ( intf_thread_t * );
+static void FullScreen ( intf_thread_t * );
+static void Play ( intf_thread_t * );
+static void Stop ( intf_thread_t * );
+static void Next ( intf_thread_t * );
+static void Eject ( intf_thread_t * );
+static void Pause ( intf_thread_t * );
+static void PrevTitle ( intf_thread_t * );
+static void NextTitle ( intf_thread_t * );
+static void PrevChapter ( intf_thread_t * );
+static void NextChapter ( intf_thread_t * );
+
+static int HandleKey ( intf_thread_t *, int );
+static void Redraw ( intf_thread_t *, time_t * );
+static int PrintFullLine ( const char *p_fmt, ... );
+static void ManageSlider ( intf_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("ncurses interface module") );
+ set_capability( "interface", 10 );
+ set_callbacks( Open, Close );
+ add_shortcut( "curses" );
+vlc_module_end();
+
+/*****************************************************************************
+ * intf_sys_t: description and status of ncurses interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ input_thread_t * p_input;
+
+ float f_slider_state;
+ float f_slider_state_old;
+};
+
+/*****************************************************************************
+ * Open: initialize and create window
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return( 1 );
+ }
+
+ p_intf->p_sys->p_input = NULL;
+
+ p_intf->pf_run = Run;
+
+ /* Initialize the curses library */
+ initscr();
+ /* Don't do NL -> CR/NL */
+ nonl();
+ /* Take input chars one at a time */
+ cbreak();
+ /* Don't echo */
+ noecho();
+
+ curs_set(0);
+ timeout(0);
+
+ clear();
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Close: destroy interface window
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ /* Close the ncurses interface */
+ endwin();
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: ncurses thread
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ signed char i_key;
+ time_t t_last_refresh;
+
+ /*
+ * force drawing the interface for the first time
+ */
+ t_last_refresh = ( time( 0 ) - 1);
+
+ while( !p_intf->b_die )
+ {
+ msleep( INTF_IDLE_SLEEP );
+
+ /* Update the input */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ while( (i_key = getch()) != -1 )
+ {
+ /*
+ * HandleKey returns 1 if the screen needs to be redrawn
+ */
+ if ( HandleKey( p_intf, i_key ) )
+ {
+ Redraw( p_intf, &t_last_refresh );
+ }
+ }
+
+ /*
+ * redraw the screen every second
+ */
+ if ( (time(0) - t_last_refresh) >= 1 )
+ {
+ ManageSlider ( p_intf );
+ Redraw( p_intf, &t_last_refresh );
+ }
+ }
+}
+
+/* following functions are local */
+
+static int HandleKey( intf_thread_t *p_intf, int i_key )
+{
+ switch( i_key )
+ {
+ case 'q':
+ case 'Q':
+ p_intf->b_die = 1;
+ return 0;
+
+ case 'f':
+ FullScreen( p_intf );
+ return 1;
+
+ case 'p':
+ Play( p_intf );
+ return 1;
+
+ case ' ':
+ Pause( p_intf );
+ return 1;
+
+ case 's':
+ Stop( p_intf );
+ return 1;
+
+ case 'n':
+ Next( p_intf );
+ return 1;
+
+ case 'e':
+ Eject( p_intf );
+ return 1;
+
+ case '[':
+ PrevTitle( p_intf );
+ break;
+
+ case ']':
+ NextTitle( p_intf );
+ break;
+
+ case '<':
+ PrevChapter( p_intf );
+ break;
+
+ case '>':
+ NextChapter( p_intf );
+ break;
+
+ case KEY_RIGHT:
+ p_intf->p_sys->f_slider_state += 100;
+ ManageSlider ( p_intf );
+ break;
+
+ case KEY_LEFT:
+ p_intf->p_sys->f_slider_state--;
+ ManageSlider ( p_intf );
+ break;
+
+ /*
+ * ^l should clear and redraw the screen
+ */
+ case 0x0c:
+ clear();
+ return 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int PrintFullLine ( const char *p_fmt, ... )
+{
+ va_list vl_args;
+ char * p_buf = NULL;
+ int i_len;
+
+ va_start ( vl_args, p_fmt );
+ vasprintf ( &p_buf, p_fmt, vl_args );
+ va_end ( vl_args );
+
+ if ( p_buf == NULL )
+ {
+//X msg_Err( p_input, "intf error: %s", strerror ( ENOMEM ) );
+ return ( -1 );
+ }
+
+ i_len = strlen( p_buf );
+
+ /*
+ * make sure we don't exceed the border on the right side
+ */
+ if ( i_len > COLS )
+ {
+ p_buf[COLS] = '\0';
+ i_len = COLS;
+ printw( "%s", p_buf );
+ }
+ else
+ {
+ printw( "%s", p_buf );
+ hline( ' ', COLS - i_len );
+ }
+
+ free ( p_buf );
+
+ return i_len;
+}
+
+static void
+Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh )
+{
+ int row = 0;
+
+ move ( row, 0 );
+
+ attrset ( A_REVERSE );
+ PrintFullLine( VOUT_TITLE " (ncurses interface)" );
+ attroff ( A_REVERSE );
+
+ row++;
+
+ row++;
+ move ( row, 0 );
+
+ if ( p_intf->p_sys->p_input != NULL )
+ {
+ PrintFullLine ( " DVD Chapter:%3d DVD Title:%3d",
+ p_intf->p_sys->p_input->stream.p_selected_area->i_part,
+ p_intf->p_sys->p_input->stream.p_selected_area->i_id );
+ }
+
+ row++;
+ mvaddch ( row, 0, ACS_ULCORNER );
+ mvhline ( row, 1, ACS_HLINE, COLS-2 );
+ mvaddch ( row, COLS-1, ACS_URCORNER );
+
+ row++;
+ mvaddch ( row, 0, ACS_VLINE );
+ attrset ( A_REVERSE );
+ mvhline ( row, 1, ' ', ( (int) p_intf->p_sys->f_slider_state % COLS-2) );
+ attroff ( A_REVERSE );
+ mvaddch ( row, COLS-1, ACS_VLINE );
+
+ row++;
+ mvaddch ( row, 0, ACS_LLCORNER );
+ mvhline ( row, 1, ACS_HLINE, COLS-2 );
+ mvaddch ( row, COLS-1, ACS_LRCORNER );
+
+ refresh();
+
+ *t_last_refresh = time( 0 );
+}
+
+static void FullScreen( intf_thread_t *p_intf )
+{
+ vout_thread_t *p_vout;
+
+ p_vout = vlc_object_find( p_intf->p_sys->p_input,
+ VLC_OBJECT_VOUT, FIND_CHILD );
+ if( p_vout == NULL )
+ {
+ return;
+ }
+
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ vlc_object_release( p_vout );
+}
+
+static void Eject ( intf_thread_t *p_intf )
+{
+ char *psz_device = NULL, *psz_parser, *psz_name;
+
+ /*
+ * Get the active input
+ * Determine whether we can eject a media, ie it's a VCD or DVD
+ * If it's neither a VCD nor a DVD, then return
+ */
+
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+
+ if( p_playlist->i_index < 0 )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ return;
+ }
+
+ psz_name = p_playlist->pp_items[ p_playlist->i_index ]->psz_name;
+
+ if( psz_name )
+ {
+ if( !strncmp(psz_name, "dvd:", 4) )
+ {
+ switch( psz_name[4] )
+ {
+ case '\0':
+ case '@':
+ psz_device = config_GetPsz( p_intf, "dvd_device" );
+ break;
+ default:
+ /* Omit the first 4 characters */
+ psz_device = strdup( psz_name + 4 );
+ break;
+ }
+ }
+ else if( !strncmp(psz_name, "vcd:", 4) )
+ {
+ switch( psz_name[4] )
+ {
+ case '\0':
+ case '@':
+ psz_device = config_GetPsz( p_intf, "vcd_device" );
+ break;
+ default:
+ /* Omit the first 4 characters */
+ psz_device = strdup( psz_name + 4 );
+ break;
+ }
+ }
+ else
+ {
+ psz_device = strdup( psz_name );
+ }
+ }
+
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+
+ if( psz_device == NULL )
+ {
+ return;
+ }
+
+ /* Remove what we have after @ */
+ psz_parser = psz_device;
+ for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
+ {
+ if( *psz_parser == '@' )
+ {
+ *psz_parser = '\0';
+ break;
+ }
+ }
+
+ /* If there's a stream playing, we aren't allowed to eject ! */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+//X msg_Dbg( p_input, "ejecting %s", psz_device );
+
+ intf_Eject( p_intf, psz_device );
+ }
+
+ free(psz_device);
+ return;
+}
+
+static void Play ( intf_thread_t *p_intf )
+{
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist )
+ {
+ vlc_mutex_lock( &p_playlist->object_lock );
+
+ if( p_playlist->i_size )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ playlist_Play( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ }
+ }
+}
+
+static void Pause ( intf_thread_t *p_intf )
+{
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ return;
+ }
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
+
+ return;
+}
+
+static void Stop ( intf_thread_t *p_intf )
+{
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+
+ return;
+}
+
+static void Next ( intf_thread_t *p_intf )
+{
+ int i_id;
+ input_area_t * p_area;
+
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id+1;
+
+ if ( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
+ {
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
+
+ input_ChangeArea( p_intf->p_sys->p_input,
+ (input_area_t *) p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+static void ManageSlider ( intf_thread_t *p_intf )
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ if( p_intf->p_sys->p_input->stream.b_seekable &&
+ p_intf->p_sys->p_input->stream.control.i_status == PLAYING_S )
+ {
+ float newvalue = p_intf->p_sys->f_slider_state;
+
+#define p_area p_intf->p_sys->p_input->stream.p_selected_area
+
+ /* If the user hasn't touched the slider since the last time,
+ * then the input can safely change it */
+ if( newvalue == p_intf->p_sys->f_slider_state_old )
+ {
+ /* Update the value */
+ p_intf->p_sys->f_slider_state =
+ p_intf->p_sys->f_slider_state_old =
+ ( 100 * p_area->i_tell ) / p_area->i_size;
+ }
+ /* Otherwise, send message to the input if the user has
+ * finished dragging the slider */
+ else
+ {
+ off_t i_seek = ( newvalue * p_area->i_size ) / 100;
+
+ /* release the lock to be able to seek */
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ input_Seek( p_intf, i_seek, INPUT_SEEK_SET );
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+
+ /* Update the old value */
+ p_intf->p_sys->f_slider_state_old = newvalue;
+ }
+# undef p_area
+ }
+
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+static void PrevTitle ( intf_thread_t *p_intf )
+{
+ input_area_t * p_area;
+ int i_id;
+
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
+
+ /* Disallow area 0 since it is used for video_ts.vob */
+ if ( i_id > 0 )
+ {
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+static void NextTitle ( intf_thread_t *p_intf )
+{
+ input_area_t * p_area;
+ int i_id;
+
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
+
+ if ( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
+ {
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+static void PrevChapter ( intf_thread_t *p_intf )
+{
+ input_area_t * p_area;
+
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;
+
+ if ( p_area->i_part > 0 )
+ {
+ p_area->i_part--;
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+static void NextChapter( intf_thread_t *p_intf )
+{
+ input_area_t * p_area;
+
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;
+
+ if ( p_area->i_part < p_area->i_part_nb )
+ {
+ p_area->i_part++;
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
+
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+qnx_SOURCES = qnx.c aout.c vout.c
--- /dev/null
+/*****************************************************************************
+ * aout.c : QNX audio output
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ *
+ * Authors: Henri Fallon <henri@videolan.org>
+ * Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include <sys/asoundlib.h>
+
+struct aout_sys_t
+{
+ snd_pcm_t * p_pcm_handle;
+ int i_card;
+ int i_device;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/*****************************************************************************
+ * Open : creates a handle and opens an alsa device
+ *****************************************************************************
+ * This function opens an alsa device, through the alsa API
+ *****************************************************************************/
+int E_(OpenAudio)( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+ int i_ret;
+
+ /* allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* open audio device */
+ if( ( i_ret = snd_pcm_open_preferred( &p_aout->p_sys->p_pcm_handle,
+ &p_aout->p_sys->i_card,
+ &p_aout->p_sys->i_device,
+ SND_PCM_OPEN_PLAYBACK ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to open audio device (%s)",
+ snd_strerror( i_ret ) );
+ free( p_aout->p_sys );
+ return( 1 );
+ }
+
+ /* disable mmap */
+ if( ( i_ret = snd_pcm_plugin_set_disable( p_aout->p_sys->p_pcm_handle,
+ PLUGIN_DISABLE_MMAP ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to disable mmap (%s)", snd_strerror(i_ret) );
+ Close( p_this );
+ free( p_aout->p_sys );
+ return( 1 );
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat : set the audio output format
+ *****************************************************************************
+ * This function prepares the device, sets the rate, format, the mode
+ * ("play as soon as you have data"), and buffer information.
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ int i_ret;
+ int i_bytes_per_sample;
+ snd_pcm_channel_info_t pi;
+ snd_pcm_channel_params_t pp;
+
+ memset( &pi, 0, sizeof(pi) );
+ memset( &pp, 0, sizeof(pp) );
+
+ pi.channel = SND_PCM_CHANNEL_PLAYBACK;
+ if( ( i_ret = snd_pcm_plugin_info( p_aout->p_sys->p_pcm_handle,
+ &pi ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to get plugin info (%s)",
+ snd_strerror( i_ret ) );
+ return( 1 );
+ }
+
+ pp.mode = SND_PCM_MODE_BLOCK;
+ pp.channel = SND_PCM_CHANNEL_PLAYBACK;
+ pp.start_mode = SND_PCM_START_FULL;
+ pp.stop_mode = SND_PCM_STOP_STOP;
+
+ pp.buf.block.frags_max = 1;
+ pp.buf.block.frags_min = 1;
+
+ pp.format.interleave = 1;
+ pp.format.rate = p_aout->i_rate;
+ pp.format.voices = p_aout->i_channels;
+
+ switch( p_aout->i_format )
+ {
+ case AOUT_FMT_S16_LE:
+ pp.format.format = SND_PCM_SFMT_S16_LE;
+ i_bytes_per_sample = 2;
+ break;
+
+ default:
+ pp.format.format = SND_PCM_SFMT_S16_BE;
+ i_bytes_per_sample = 2;
+ break;
+ }
+
+ pp.buf.block.frag_size =
+ (((s64)p_aout->i_rate * AOUT_BUFFER_DURATION) / 1000000) *
+ p_aout->i_channels * i_bytes_per_sample;
+
+ /* set parameters */
+ if( ( i_ret = snd_pcm_plugin_params( p_aout->p_sys->p_pcm_handle,
+ &pp ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to set parameters (%s)", snd_strerror(i_ret) );
+ return( 1 );
+ }
+
+ /* prepare channel */
+ if( ( i_ret = snd_pcm_plugin_prepare( p_aout->p_sys->p_pcm_handle,
+ SND_PCM_CHANNEL_PLAYBACK ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to prepare channel (%s)",
+ snd_strerror( i_ret ) );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************
+ * This function returns the number of used byte in the queue.
+ * It also deals with errors : indeed if the device comes to run out
+ * of data to play, it switches to the "underrun" status. It has to
+ * be flushed and re-prepared
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ int i_ret;
+ snd_pcm_channel_status_t status;
+
+ /* get current pcm status */
+ memset( &status, 0, sizeof(status) );
+ if( ( i_ret = snd_pcm_plugin_status( p_aout->p_sys->p_pcm_handle,
+ &status ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to get device status (%s)",
+ snd_strerror( i_ret ) );
+ return( -1 );
+ }
+
+ /* check for underrun */
+ switch( status.status )
+ {
+ case SND_PCM_STATUS_READY:
+ case SND_PCM_STATUS_UNDERRUN:
+ if( ( i_ret = snd_pcm_plugin_prepare( p_aout->p_sys->p_pcm_handle,
+ SND_PCM_CHANNEL_PLAYBACK ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to prepare channel (%s)",
+ snd_strerror( i_ret ) );
+ }
+ break;
+ }
+
+ return( status.count );
+}
+
+/*****************************************************************************
+ * Play : plays a sample
+ *****************************************************************************
+ * Plays a sample using the snd_pcm_write function from the alsa API
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ int i_ret;
+
+ if( ( i_ret = snd_pcm_plugin_write( p_aout->p_sys->p_pcm_handle,
+ (void *) buffer,
+ (size_t) i_size ) ) <= 0 )
+ {
+ msg_Err( p_aout, "unable to write data (%s)", snd_strerror(i_ret) );
+ }
+}
+
+/*****************************************************************************
+ * CloseAudio: close the audio device
+ *****************************************************************************/
+static void E_(CloseAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+ int i_ret;
+
+ if( ( i_ret = snd_pcm_close( p_aout->p_sys->p_pcm_handle ) ) < 0 )
+ {
+ msg_Err( p_aout, "unable to close audio device (%s)",
+ snd_strerror( i_ret ) );
+ }
+
+ free( p_aout->p_sys );
+}
--- /dev/null
+/*****************************************************************************
+ * qnx.c : QNX RTOS plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ ******************************************************************************/
+int E_(OpenAudio) ( vlc_object_t * );
+void E_(CloseAudio) ( vlc_object_t * );
+
+int E_(OpenVideo) ( vlc_object_t * );
+void E_(CloseVideo) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("QNX RTOS module") );
+ add_submodule();
+ set_capability( "video output", 100 );
+ set_callbacks( E_(OpenVideo), E_(CloseVideo) );
+ add_submodule();
+ set_capability( "audio output", 100 );
+ set_callbacks( E_(OpenAudio), E_(CloseAudio) );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * vout.c: QNX RTOS video output display method
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ *
+ * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
+ * Pascal Levesque <Pascal.Levesque@mindready.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <photon/PtWidget.h>
+#include <photon/PtWindow.h>
+#include <photon/PtLabel.h>
+#include <photon/PdDirect.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+/*****************************************************************************
+ * vout_sys_t: video output QNX method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the QNX specific properties of an output thread. QNX video
+ * output is performed through regular resizable windows. Windows can be
+ * dynamically resized to adapt to the size of the streams.
+ *****************************************************************************/
+#define MAX_DIRECTBUFFERS 2
+
+#define MODE_NORMAL_MEM 0
+#define MODE_SHARED_MEM 1
+#define MODE_VIDEO_MEM 2
+#define MODE_VIDEO_OVERLAY 3
+
+struct vout_sys_t
+{
+ /* video mode */
+ int i_mode;
+
+ /* internal stuff */
+ PtWidget_t * p_window;
+
+ /* Color palette for 8bpp */
+ PgColor_t p_colors[255];
+
+ /* [shared] memory blit */
+ int i_img_type;
+
+ /* video memory blit */
+
+ /* video overlay */
+ PgVideoChannel_t * p_channel;
+ int i_vc_flags;
+ int i_vc_format;
+
+ int i_screen_depth;
+ int i_bytes_per_pixel;
+ int i_bytes_per_line;
+
+ /* position & dimensions */
+ PhPoint_t pos;
+ PhDim_t dim;
+ PhPoint_t old_pos;
+ PhDim_t old_dim;
+ PhDim_t screen_dim;
+ PhRect_t frame;
+};
+
+
+/*****************************************************************************
+ * picture_sys_t: direct buffer method descriptor
+ *****************************************************************************
+ * This structure is part of the picture descriptor, it describes the
+ * XVideo specific properties of a direct buffer.
+ *****************************************************************************/
+struct picture_sys_t
+{
+ /* [shared] memory blit */
+ PhImage_t * p_image;
+
+ /* video memory blit and video overlay */
+ PdOffscreenContext_t * p_ctx[3]; /* 0: y, 1: u, 2: v */
+ char * p_buf[3];
+};
+
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int QNXInit ( vout_thread_t * );
+static void QNXEnd ( vout_thread_t * );
+static int QNXManage ( vout_thread_t * );
+static void QNXDisplay ( vout_thread_t *, picture_t * );
+
+static int QNXInitDisplay ( vout_thread_t * );
+static int QNXCreateWnd ( vout_thread_t * );
+static int QNXDestroyWnd ( vout_thread_t * );
+
+static int NewPicture ( vout_thread_t *, picture_t *, int );
+static void FreePicture ( vout_thread_t *, picture_t * );
+static int ResizeOverlayOutput ( vout_thread_t * );
+static void SetPalette ( vout_thread_t *, u16 *, u16 *, u16 * );
+
+/*****************************************************************************
+ * OpenVideo: allocate QNX video thread output method
+ *****************************************************************************
+ * This function allocate and initialize a QNX vout method. It uses some of the
+ * vout properties to choose the window size, and change them according to the
+ * actual properties of the display.
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ /* init connection to photon */
+ if( PtInit( "/dev/photon" ) != 0 )
+ {
+ msg_Err( p_vout, "unable to connect to photon" );
+ return( 1 );
+ }
+
+ /* allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
+
+ p_vout->b_fullscreen = config_GetInt( p_vout, "fullscreen" );
+ p_vout->p_sys->i_mode = config_GetInt( p_vout, "overlay" ) ?
+ MODE_VIDEO_OVERLAY : MODE_VIDEO_MEM;
+ p_vout->p_sys->dim.w = p_vout->i_window_width;
+ p_vout->p_sys->dim.h = p_vout->i_window_height;
+
+ /* init display and create window */
+ if( QNXInitDisplay( p_vout ) || QNXCreateWnd( p_vout ) )
+ {
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ p_vout->pf_init = QNXInit;
+ p_vout->pf_end = QNXEnd;
+ p_vout->pf_manage = QNXManage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = QNXDisplay;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * QNXInit: initialize QNX video thread output method
+ *****************************************************************************
+ * This function create the buffers needed by the output thread. It is called
+ * at the beginning of the thread, but also each time the window is resized.
+ *****************************************************************************/
+static int QNXInit( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ switch( p_vout->p_sys->i_mode )
+ {
+ case MODE_NORMAL_MEM:
+ case MODE_SHARED_MEM:
+ p_vout->output.i_width = p_vout->p_sys->dim.w;
+ p_vout->output.i_height = p_vout->p_sys->dim.h;
+
+ /* Assume we have square pixels */
+ p_vout->output.i_aspect = p_vout->p_sys->dim.w
+ * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
+ break;
+
+ case MODE_VIDEO_MEM:
+ p_vout->output.i_width = p_vout->p_sys->dim.w;
+ p_vout->output.i_height = p_vout->p_sys->dim.h;
+
+ /* Assume we have square pixels */
+ p_vout->output.i_aspect = p_vout->p_sys->dim.w
+ * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
+ break;
+
+ case MODE_VIDEO_OVERLAY:
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ if (ResizeOverlayOutput(p_vout))
+ {
+ return (1);
+ }
+ break;
+
+ default:
+ /* This shouldn't happen ! */
+ break;
+ }
+
+ /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
+ while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
+ {
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture */
+ if( p_pic == NULL || NewPicture( p_vout, p_pic, I_OUTPUTPICTURES ) )
+ {
+ break;
+ }
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * QNXEnd: terminate QNX video thread output method
+ *****************************************************************************
+ * Destroy the buffers created by QNXInit. It is called at the end of
+ * the thread, but also each time the window is resized.
+ *****************************************************************************/
+static void QNXEnd( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the direct buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
+ }
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy QNX video thread output method
+ *****************************************************************************
+ * Terminate an output method created by QNXCreate
+ *****************************************************************************/
+void E_(CloseVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ /* destroy the window */
+ QNXDestroyWnd( p_vout );
+
+ /* destroy structure */
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * QNXManage: handle QNX events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It allows
+ * window resizing. It returns a non null value on error.
+ *****************************************************************************/
+static int QNXManage( vout_thread_t *p_vout )
+{
+ int i_ev, i_buflen;
+ PhEvent_t *p_event;
+ vlc_bool_t b_repos = 0;
+
+ if (p_vout->b_die == 1)
+ {
+ return ( 0 );
+ }
+
+ /* allocate buffer for event */
+ i_buflen = sizeof( PhEvent_t ) * 4;
+ if( ( p_event = malloc( i_buflen ) ) == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ /* event loop */
+ do
+ {
+ memset( p_event, 0, i_buflen );
+ i_ev = PhEventPeek( p_event, i_buflen );
+
+ if( i_ev == Ph_RESIZE_MSG )
+ {
+ i_buflen = PhGetMsgSize( p_event );
+ if( ( p_event = realloc( p_event, i_buflen ) ) == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+ }
+ else if( i_ev == Ph_EVENT_MSG )
+ {
+ PtEventHandler( p_event );
+
+ if( p_event->type == Ph_EV_WM )
+ {
+ PhWindowEvent_t *p_ev = PhGetData( p_event );
+
+ switch( p_ev->event_f )
+ {
+ case Ph_WM_CLOSE:
+ p_vout->p_vlc->b_die = 1;
+ break;
+
+ case Ph_WM_MOVE:
+ p_vout->p_sys->pos.x = p_ev->pos.x;
+ p_vout->p_sys->pos.y = p_ev->pos.y;
+ b_repos = 1;
+ break;
+
+ case Ph_WM_RESIZE:
+ p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
+ p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
+ p_vout->p_sys->dim.w = p_ev->size.w;
+ p_vout->p_sys->dim.h = p_ev->size.h;
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ break;
+ }
+ }
+ else if( p_event->type == Ph_EV_KEY )
+ {
+ PhKeyEvent_t *p_ev = PhGetData( p_event );
+ long i_key = p_ev->key_sym;
+
+ if( ( p_ev->key_flags & Pk_KF_Key_Down ) &&
+ ( p_ev->key_flags & Pk_KF_Sym_Valid ) )
+ {
+ switch( i_key )
+ {
+ case Pk_q:
+ case Pk_Q:
+ p_vout->p_vlc->b_die = 1;
+ break;
+
+ case Pk_f:
+ case Pk_F:
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ break;
+
+ case Pk_c:
+ case Pk_C:
+ p_vout->b_grayscale = ! p_vout->b_grayscale;
+ p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
+ break;
+
+ default:
+ if( i_key >= Pk_0 && i_key <= Pk_9 )
+ {
+// network_ChannelJoin( i_key );
+ }
+ break;
+ }
+ }
+ }
+ }
+ } while( i_ev != -1 && i_ev != 0 );
+
+ free( p_event );
+
+ /*
+ * fullscreen
+ */
+ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+ {
+ PhDim_t dim;
+
+ p_vout->b_fullscreen = !p_vout->b_fullscreen;
+ p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+
+ if( p_vout->b_fullscreen )
+ {
+ p_vout->p_sys->old_pos.x = p_vout->p_sys->pos.x;
+ p_vout->p_sys->old_pos.y = p_vout->p_sys->pos.y;
+ p_vout->p_sys->pos.x = p_vout->p_sys->pos.y = 0;
+ dim.w = p_vout->p_sys->screen_dim.w + 1;
+ dim.h = p_vout->p_sys->screen_dim.h + 1;
+ }
+ else
+ {
+ p_vout->p_sys->pos.x = p_vout->p_sys->old_pos.x;
+ p_vout->p_sys->pos.y = p_vout->p_sys->old_pos.y;
+ dim.w = p_vout->p_sys->old_dim.w + 1;
+ dim.h = p_vout->p_sys->old_dim.h + 1;
+ }
+
+ /* modify render flags, border */
+ PtSetResource( p_vout->p_sys->p_window,
+ Pt_ARG_WINDOW_RENDER_FLAGS,
+ p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
+ Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
+
+ /* set position and dimension */
+ PtSetResource( p_vout->p_sys->p_window,
+ Pt_ARG_POS, &p_vout->p_sys->pos, 0 );
+ PtSetResource( p_vout->p_sys->p_window,
+ Pt_ARG_DIM, &dim, 0 );
+
+ /* mark as damaged to force redraw */
+ PtDamageWidget( p_vout->p_sys->p_window );
+ }
+
+ /*
+ * size change
+ */
+ if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+ {
+ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+
+ if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
+ {
+ ResizeOverlayOutput(p_vout);
+ }
+#if 0
+ else
+ {
+ p_vout->output.i_width = p_vout->p_sys->dim.w;
+ p_vout->output.i_height = p_vout->p_sys->dim.h;
+ p_vout->i_changes |= VOUT_YUV_CHANGE;
+
+ QNXEnd( p_vout );
+ if( QNXInit( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot resize display" );
+ return( 1 );
+ }
+ }
+#endif
+
+ msg_Dbg( p_vout, "video display resized (%dx%d)",
+ p_vout->p_sys->dim.w, p_vout->p_sys->dim.h );
+ }
+
+ /*
+ * position change, move video channel
+ */
+ if( b_repos && p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
+ {
+ ResizeOverlayOutput(p_vout);
+ }
+
+ return( i_ev == -1 );
+}
+
+/*****************************************************************************
+ * QNXDisplay: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to QNX server, wait until
+ * it is displayed and switch the two rendering buffer, preparing next frame.
+ *****************************************************************************/
+static void QNXDisplay( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
+ p_vout->p_sys->i_mode == MODE_SHARED_MEM )
+ {
+ PhPoint_t pos = { 0, 0 };
+
+ PgSetRegion( PtWidgetRid( p_vout->p_sys->p_window ) );
+ if (p_vout->p_sys->i_screen_depth == 8)
+ {
+ PgSetPalette( p_vout->p_sys->p_colors, 0, 0, 255, Pg_PALSET_SOFT, 0);
+ }
+ PgDrawPhImagemx( &pos, p_pic->p_sys->p_image, 0 );
+ PgFlush();
+ }
+ else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
+ {
+ PhRect_t rc = { { 0, 0 }, { p_vout->output.i_width, p_vout->output.i_height } };
+
+// PgSetRegion( PtWidgetRid ( p_vout->p_sys->p_window ) );
+ PgContextBlit( p_pic->p_sys->p_ctx[0], &rc, NULL, &rc );
+ PgFlush();
+ }
+}
+
+/*****************************************************************************
+ * QNXInitDisplay: check screen resolution, depth, amount of video ram, etc
+ *****************************************************************************/
+static int QNXInitDisplay( vout_thread_t * p_vout )
+{
+ PgHWCaps_t hwcaps;
+ PgDisplaySettings_t cfg;
+ PgVideoModeInfo_t minfo;
+
+ /* get graphics card hw capabilities */
+ if( PgGetGraphicsHWCaps( &hwcaps ) != 0 )
+ {
+ msg_Err( p_vout, "unable to get gfx card capabilities" );
+ return( 1 );
+ }
+
+ /* get current video mode */
+ if( PgGetVideoMode( &cfg ) != 0 )
+ {
+ msg_Err( p_vout, "unable to get current video mode" );
+ return( 1 );
+ }
+
+ /* get video mode info */
+ if( PgGetVideoModeInfo( cfg.mode, &minfo ) != 0 )
+ {
+ msg_Err( p_vout, "unable to get info for video mode" );
+ return( 1 );
+ }
+
+ /* switch to normal mode if no overlay support */
+// printf("minfo.mode_capabilities1: 0x%x\n", minfo.mode_capabilities1);
+
+ if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY &&
+ !( minfo.mode_capabilities1 & PgVM_MODE_CAP1_VIDEO_OVERLAY ) )
+ {
+ msg_Err( p_vout, "no overlay support detected" );
+ p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
+ }
+
+ if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
+ {
+ int i = 0;
+ PgScalerCaps_t vcaps;
+
+ if( ( p_vout->p_sys->p_channel =
+ PgCreateVideoChannel( Pg_VIDEO_CHANNEL_SCALER, 0 ) ) == NULL )
+ {
+ msg_Err( p_vout, "unable to create video channel" );
+ printf("errno = %d\n", errno);
+ p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
+ }
+ else
+ {
+ vcaps.size = sizeof( vcaps );
+ while( PgGetScalerCapabilities( p_vout->p_sys->p_channel,
+ i++, &vcaps ) == 0 )
+ {
+ printf("vcaps.format = 0x%x\n", vcaps.format);
+ if( vcaps.format == Pg_VIDEO_FORMAT_YV12 ||
+ vcaps.format == Pg_VIDEO_FORMAT_YUV420 ||
+ vcaps.format == Pg_VIDEO_FORMAT_YUY2 ||
+ vcaps.format == Pg_VIDEO_FORMAT_UYVY ||
+ vcaps.format == Pg_VIDEO_FORMAT_RGB555 ||
+ vcaps.format == Pg_VIDEO_FORMAT_RGB565 ||
+ vcaps.format == Pg_VIDEO_FORMAT_RGB8888 )
+ {
+ p_vout->p_sys->i_vc_flags = vcaps.flags;
+ p_vout->p_sys->i_vc_format = vcaps.format;
+ }
+
+ vcaps.size = sizeof( vcaps );
+ }
+
+ if( p_vout->p_sys->i_vc_format == 0 )
+ {
+ msg_Warn( p_vout, "need YV12, YUY2 or RGB8888 overlay" );
+
+ p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
+ }
+ }
+ }
+
+ /* use video ram if we have enough available */
+ if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM &&
+ (minfo.bits_per_pixel != 8) &&
+ hwcaps.currently_available_video_ram >=
+ ( ( minfo.width * minfo.height * minfo.bits_per_pixel * MAX_DIRECTBUFFERS) / 8 ) )
+ {
+ p_vout->p_sys->i_mode = MODE_VIDEO_MEM;
+ printf("Using video memory...\n");
+ }
+
+ p_vout->p_sys->i_img_type = minfo.type;
+ p_vout->p_sys->screen_dim.w = minfo.width;
+ p_vout->p_sys->screen_dim.h = minfo.height;
+ p_vout->p_sys->i_screen_depth = minfo.bits_per_pixel;
+
+ switch( p_vout->p_sys->i_screen_depth )
+ {
+ case 8:
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
+ p_vout->p_sys->i_bytes_per_pixel = 1;
+ p_vout->output.pf_setpalette = SetPalette;
+ break;
+
+ case 15:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
+ p_vout->p_sys->i_bytes_per_pixel = 2;
+ p_vout->output.i_rmask = 0x7c00;
+ p_vout->output.i_gmask = 0x03e0;
+ p_vout->output.i_bmask = 0x001f;
+ break;
+
+ case 16:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
+ p_vout->p_sys->i_bytes_per_pixel = 2;
+ p_vout->output.i_rmask = 0xf800;
+ p_vout->output.i_gmask = 0x07e0;
+ p_vout->output.i_bmask = 0x001f;
+ break;
+
+ case 24:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
+ p_vout->p_sys->i_bytes_per_pixel = 3;
+ p_vout->output.i_rmask = 0xff0000;
+ p_vout->output.i_gmask = 0x00ff00;
+ p_vout->output.i_bmask = 0x0000ff;
+ break;
+
+ case 32:
+ default:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
+ p_vout->p_sys->i_bytes_per_pixel = 4;
+ p_vout->output.i_rmask = 0xff0000;
+ p_vout->output.i_gmask = 0x00ff00;
+ p_vout->output.i_bmask = 0x0000ff;
+ break;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * QNXCreateWnd: create and realize the main window
+ *****************************************************************************/
+static int QNXCreateWnd( vout_thread_t * p_vout )
+{
+ PtArg_t args[8];
+ PhPoint_t pos = { 0, 0 };
+ PgColor_t color = Pg_BLACK;
+
+ if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
+ {
+ if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
+ {
+ color = PgGetOverlayChromaColor();
+ }
+ }
+
+ /* fullscreen, set dimension */
+ if( p_vout->b_fullscreen )
+ {
+ p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
+ p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
+ p_vout->output.i_width = p_vout->p_sys->dim.w = p_vout->p_sys->screen_dim.w;
+ p_vout->output.i_height = p_vout->p_sys->dim.h = p_vout->p_sys->screen_dim.h;
+ }
+
+ /* set window parameters */
+ PtSetArg( &args[0], Pt_ARG_POS, &pos, 0 );
+ PtSetArg( &args[1], Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
+ PtSetArg( &args[2], Pt_ARG_FILL_COLOR, color, 0 );
+ PtSetArg( &args[3], Pt_ARG_WINDOW_TITLE, "VideoLan Client", 0 );
+ PtSetArg( &args[4], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE );
+ PtSetArg( &args[5], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
+ Ph_WM_MOVE | Ph_WM_RESIZE | Ph_WM_CLOSE );
+ PtSetArg( &args[6], Pt_ARG_WINDOW_RENDER_FLAGS,
+ p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
+ Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
+
+ /* create window */
+ p_vout->p_sys->p_window = PtCreateWidget( PtWindow, Pt_NO_PARENT, 7, args);
+ if( p_vout->p_sys->p_window == NULL )
+ {
+ msg_Err( p_vout, "unable to create window" );
+ return( 1 );
+ }
+
+ /* realize the window widget */
+ if( PtRealizeWidget( p_vout->p_sys->p_window ) != 0 )
+ {
+ msg_Err( p_vout, "unable to realize window widget" );
+ PtDestroyWidget( p_vout->p_sys->p_window );
+ return( 1 );
+ }
+
+ /* get window frame size */
+ if( PtWindowFrameSize( NULL, p_vout->p_sys->p_window,
+ &p_vout->p_sys->frame ) != 0 )
+ {
+ msg_Err( p_vout, "unable to get window frame size" );
+ PtDestroyWidget( p_vout->p_sys->p_window );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * QNXDestroyWnd: unrealize and destroy the main window
+ *****************************************************************************/
+static int QNXDestroyWnd( vout_thread_t * p_vout )
+{
+ /* destroy the window widget */
+ PtUnrealizeWidget( p_vout->p_sys->p_window );
+// PtDestroyWidget( p_vout->p_sys->p_window );
+
+ /* destroy video channel */
+ if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
+ {
+ PgDestroyVideoChannel( p_vout->p_sys->p_channel );
+ }
+
+ return( 0 );
+}
+
+
+/*****************************************************************************
+ * NewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic, int index )
+{
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+ if( p_pic->p_sys == NULL )
+ {
+ return -1;
+ }
+
+ switch( p_vout->p_sys->i_mode )
+ {
+ case MODE_NORMAL_MEM:
+ case MODE_SHARED_MEM:
+ /* create images for [shared] memory blit */
+ if( !( p_pic->p_sys->p_image = PhCreateImage( NULL,
+ p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
+ p_vout->p_sys->i_img_type, NULL, 0,
+ p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
+ msg_Err( p_vout, "cannot create image" );
+ free( p_pic->p_sys );
+ return( -1 );
+ }
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->image;
+ p_pic->p->i_lines = p_pic->p_sys->p_image->size.h;
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->bpl;
+ p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
+ p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
+ * p_pic->p_sys->p_image->size.w;
+ p_pic->i_planes = 1;
+ break;
+
+ case MODE_VIDEO_MEM:
+ /* create offscreen contexts for video memory blit */
+ if( ( p_pic->p_sys->p_ctx[0] = PdCreateOffscreenContext( 0,
+ p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
+ Pg_OSC_MEM_PAGE_ALIGN) ) == NULL )
+ {
+ msg_Err( p_vout, "unable to create offscreen context" );
+ free( p_pic->p_sys );
+ return( -1 );
+ }
+
+ /* get context pointers */
+ if( ( p_pic->p_sys->p_buf[0] =
+ PdGetOffscreenContextPtr ( p_pic->p_sys->p_ctx[0] ) ) == NULL )
+ {
+ msg_Err( p_vout, "unable to get offscreen context ptr" );
+ PhDCRelease ( p_pic->p_sys->p_ctx[0] );
+ p_pic->p_sys->p_ctx[0] = NULL;
+ free( p_pic->p_sys );
+ return( -1 );
+ }
+
+ p_vout->p_sys->i_bytes_per_line = p_pic->p_sys->p_ctx[0]->pitch;
+ memset( p_pic->p_sys->p_buf[0], 0,
+ p_vout->p_sys->i_bytes_per_line * p_vout->p_sys->dim.h );
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_buf[0];
+ p_pic->p->i_lines = p_pic->p_sys->p_ctx[0]->dim.h;
+ p_pic->p->i_pitch = p_pic->p_sys->p_ctx[0]->pitch;
+ p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
+ p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
+ * p_pic->p_sys->p_ctx[0]->dim.w;
+ p_pic->i_planes = 1;
+ break;
+
+ case MODE_VIDEO_OVERLAY:
+ if (index == 0)
+ {
+ p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane1;
+ p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane1;
+ p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane1;
+ }
+ else
+ {
+ p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane2;
+ p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane2;
+ p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane2;
+ }
+
+ p_pic->p_sys->p_buf[Y_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[Y_PLANE] );
+ if( p_pic->p_sys->p_buf[Y_PLANE] == NULL )
+ {
+ msg_Err( p_vout, "unable to get video channel ctx ptr" );
+ return( 1 );
+ }
+
+ switch (p_vout->p_sys->i_vc_format)
+ {
+ case Pg_VIDEO_FORMAT_YUV420:
+ p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
+
+ p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
+ p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
+
+ if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
+ p_pic->p_sys->p_buf[V_PLANE] == NULL )
+ {
+ msg_Err( p_vout, "unable to get video channel ctx ptr" );
+ return( 1 );
+ }
+
+ p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
+ p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
+ p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+
+ p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
+ p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+
+ p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
+ p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ case Pg_VIDEO_FORMAT_YV12:
+ p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
+
+ p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
+ p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
+
+ if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
+ p_pic->p_sys->p_buf[V_PLANE] == NULL )
+ {
+ msg_Err( p_vout, "unable to get video channel ctx ptr" );
+ return( 1 );
+ }
+
+ p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
+ p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
+ p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+
+ p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
+ p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+
+ p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
+ p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ case Pg_VIDEO_FORMAT_UYVY:
+ case Pg_VIDEO_FORMAT_YUY2:
+ if (p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_UYVY)
+ {
+ p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
+ }
+ else
+ {
+ p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
+ }
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
+ p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
+ p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
+ p_pic->p->i_pixel_pitch = 4;
+ p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+
+ case Pg_VIDEO_FORMAT_RGB555:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
+ p_vout->output.i_rmask = 0x001f;
+ p_vout->output.i_gmask = 0x03e0;
+ p_vout->output.i_bmask = 0x7c00;
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
+ p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
+ p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
+ p_pic->p->i_pixel_pitch = 2;
+ p_pic->p->i_visible_pitch = 2 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
+
+ p_pic->i_planes = 1;
+ break;
+
+ case Pg_VIDEO_FORMAT_RGB565:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
+ p_vout->output.i_rmask = 0x001f;
+ p_vout->output.i_gmask = 0x07e0;
+ p_vout->output.i_bmask = 0xf800;
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
+ p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
+ p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
+ p_pic->p->i_pixel_pitch = 4;
+ p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
+
+ p_pic->i_planes = 1;
+ break;
+
+ case Pg_VIDEO_FORMAT_RGB8888:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
+ p_vout->output.i_rmask = 0x000000ff;
+ p_vout->output.i_gmask = 0x0000ff00;
+ p_vout->output.i_bmask = 0x00ff0000;
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
+ p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
+ p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
+ p_pic->p->i_pixel_pitch = 4;
+ p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
+
+ p_pic->i_planes = 1;
+ break;
+ }
+
+#if 0
+ switch( p_vout->output.i_chroma )
+ {
+#ifdef MODULE_NAME_IS_xvideo
+ case VLC_FOURCC('Y','2','1','1'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[0];
+ p_pic->p->i_lines = p_vout->output.i_height;
+ /* XXX: this just looks so plain wrong... check it out ! */
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
+ p_pic->p->i_pixel_pitch = 4;
+ p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+#endif
+
+#endif
+
+ default:
+ /* This shouldn't happen ! */
+ break;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreePicture: destroy a picture allocated with NewPicture
+ *****************************************************************************
+ * Destroy XImage AND associated data. If using Shm, detach shared memory
+ * segment from server and process, then free it. The XDestroyImage manpage
+ * says that both the image structure _and_ the data pointed to by the
+ * image structure are freed, so no need to free p_image->data.
+ *****************************************************************************/
+static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ if( ( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
+ p_vout->p_sys->i_mode == MODE_SHARED_MEM ) &&
+ p_pic->p_sys->p_image )
+ {
+ PhReleaseImage( p_pic->p_sys->p_image );
+ free( p_pic->p_sys->p_image );
+ }
+ else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM &&
+ p_pic->p_sys->p_ctx[0] )
+ {
+ PhDCRelease( p_pic->p_sys->p_ctx[0] );
+ }
+
+ free( p_pic->p_sys );
+}
+
+
+static int ResizeOverlayOutput(vout_thread_t *p_vout)
+{
+ int i_width, i_height, i_x, i_y;
+ int i_ret;
+ PgScalerProps_t props;
+
+ props.size = sizeof( props );
+ props.format = p_vout->p_sys->i_vc_format;
+ props.flags = Pg_SCALER_PROP_SCALER_ENABLE |
+ Pg_SCALER_PROP_DOUBLE_BUFFER;
+
+ /* enable chroma keying if available */
+ if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
+ {
+ props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE;
+ }
+
+ /* set viewport position */
+ props.viewport.ul.x = p_vout->p_sys->pos.x;
+ props.viewport.ul.y = p_vout->p_sys->pos.y;
+ if( !p_vout->b_fullscreen )
+ {
+ props.viewport.ul.x += p_vout->p_sys->frame.ul.x;
+ props.viewport.ul.y += p_vout->p_sys->frame.ul.y;
+ }
+
+ /* set viewport dimension */
+ vout_PlacePicture( p_vout, p_vout->p_sys->dim.w,
+ p_vout->p_sys->dim.h,
+ &i_x, &i_y, &i_width, &i_height );
+
+ props.viewport.ul.x += i_x;
+ props.viewport.ul.y += i_y;
+ props.viewport.lr.x = i_width + props.viewport.ul.x;
+ props.viewport.lr.y = i_height + props.viewport.ul.y;
+
+ /* set source dimension */
+ props.src_dim.w = p_vout->output.i_width;
+ props.src_dim.h = p_vout->output.i_height;
+
+ /* configure scaler channel */
+ i_ret = PgConfigScalerChannel( p_vout->p_sys->p_channel, &props );
+
+ if( i_ret == -1 )
+ {
+ msg_Err( p_vout, "unable to configure video channel" );
+ return( 1 );
+ }
+
+ return ( 0 );
+}
+
+
+/*****************************************************************************
+ * SetPalette: sets an 8 bpp palette
+ *****************************************************************************
+ * This function sets the palette given as an argument. It does not return
+ * anything, but could later send information on which colors it was unable
+ * to set.
+ *****************************************************************************/
+static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
+{
+ int i;
+
+ /* allocate palette */
+ for( i = 0; i < 255; i++ )
+ {
+ /* kludge: colors are indexed reversely because color 255 seems
+ * to be reserved for black even if we try to set it to white */
+ p_vout->p_sys->p_colors[ i ] = PgRGB( red[ i ] >> 8, green[ i ] >> 8, blue[ i ] >> 8 );
+ }
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
+*.moc
--- /dev/null
+qt_SOURCES = qt.cpp intf.cpp
+MOC_QT = intf.moc
+
+EXTRA_DEP = $(MOC_QT)
+
+$(MOC_QT): %.moc: %.cpp
+ $(MOC) -i $< -o $@
+
--- /dev/null
+/*****************************************************************************
+ * intf.cpp: Qt interface
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: intf.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qtoolbar.h>
+#include <qtoolbutton.h>
+#include <qwhatsthis.h>
+#include <qpushbutton.h>
+#include <qfiledialog.h>
+#include <qslider.h>
+#include <qlcdnumber.h>
+#include <qmenubar.h>
+#include <qstatusbar.h>
+#include <qmessagebox.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qiconset.h>
+
+#include <qvbox.h>
+#include <qhbox.h>
+
+/*****************************************************************************
+ * Local Qt slider class
+ *****************************************************************************/
+class IntfSlider : public QSlider
+{
+ Q_OBJECT
+
+public:
+ IntfSlider( intf_thread_t *, QWidget * ); /* Constructor and destructor */
+ ~IntfSlider();
+
+ bool b_free; /* Is the slider free ? */
+
+ int oldvalue ( void ) { return i_oldvalue; };
+ void setOldValue( int i_value ) { i_oldvalue = i_value; };
+
+private slots:
+ void SlideStart ( void ) { b_free = FALSE; };
+ void SlideStop ( void ) { b_free = TRUE; };
+
+private:
+ intf_thread_t *p_intf;
+ int i_oldvalue;
+};
+
+/*****************************************************************************
+ * Local Qt interface window class
+ *****************************************************************************/
+class IntfWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ IntfWindow( intf_thread_t * );
+ ~IntfWindow();
+
+private slots:
+ void Manage ( void );
+
+ void FileOpen ( void );
+ void FileQuit ( void );
+
+ void PlaybackPlay ( void );
+ void PlaybackPause ( void );
+ void PlaybackSlow ( void );
+ void PlaybackFast ( void );
+
+ void PlaylistPrev ( void );
+ void PlaylistNext ( void );
+
+ void DateDisplay ( int );
+ void About ( void );
+
+ void Unimplemented( void ) { msg_Warn( p_intf, "unimplemented" ); };
+
+private:
+ intf_thread_t *p_intf;
+
+ IntfSlider *p_slider;
+
+ QToolBar *p_toolbar;
+ QPopupMenu *p_popup;
+ QLabel *p_date;
+};
+
+#include "intf.moc"
+
+#define SLIDER_MIN 0x00000
+#define SLIDER_MAX 0x10000
+#define SLIDER_STEP (SLIDER_MAX >> 4)
+
+/*****************************************************************************
+ * intf_sys_t: description and status of Qt interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ QApplication *p_app;
+ IntfWindow *p_window;
+
+ input_thread_t *p_input;
+};
+
+/*****************************************************************************
+ * Local prototype
+ *****************************************************************************/
+static void Run ( intf_thread_t *p_intf );
+
+/*****************************************************************************
+ * Open: initialize and create window
+ *****************************************************************************/
+int E_(Open) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+ char *pp_argv[] = { "" };
+ int i_argc = 1;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return 1;
+ }
+
+ p_intf->pf_run = Run;
+
+ /* Create the C++ objects */
+ p_intf->p_sys->p_app = new QApplication( i_argc, pp_argv );
+ p_intf->p_sys->p_window = new IntfWindow( p_intf );
+
+ /* Tell the world we are here */
+ p_intf->p_sys->p_window->setCaption( VOUT_TITLE " (Qt interface)" );
+
+ p_intf->p_sys->p_input = NULL;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Close: destroy interface window
+ *****************************************************************************/
+void E_(Close) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ /* Get rid of the C++ objects */
+ delete p_intf->p_sys->p_window;
+ delete p_intf->p_sys->p_app;
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: Qt thread
+ *****************************************************************************
+ * This part of the interface is in a separate thread so that we can call
+ * exec() from within it without annoying the rest of the program.
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ p_intf->p_sys->p_window->show();
+
+ p_intf->p_sys->p_app->exec();
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * IntfWindow: interface window creator
+ *****************************************************************************
+ * This function creates the interface window, and populates it with a
+ * menu bar, a toolbar and a slider.
+ *****************************************************************************/
+IntfWindow::IntfWindow( intf_thread_t *p_intf )
+ :QMainWindow( 0 )
+{
+ setUsesTextLabel( TRUE );
+
+ this->p_intf = p_intf;
+
+ /*
+ * Create the toolbar
+ */
+
+ p_toolbar = new QToolBar( this, "toolbar" );
+ p_toolbar->setHorizontalStretchable( TRUE );
+
+ QIconSet * set = new QIconSet();
+ QPixmap pixmap = set->pixmap( QIconSet::Automatic, QIconSet::Normal );
+
+#define addbut( l, t, s ) new QToolButton( pixmap, l, t, this, s, p_toolbar );
+ addbut( "Open", "Open a File", SLOT(FileOpen()) );
+ addbut( "Disc", "Open a DVD or VCD", SLOT(Unimplemented()) );
+ addbut( "Net", "Select a Network Stream", SLOT(Unimplemented()) );
+ p_toolbar->addSeparator();
+ addbut( "Back", "Rewind Stream", SLOT(Unimplemented()) );
+ addbut( "Stop", "Stop Stream", SLOT(Unimplemented()) );
+ addbut( "Play", "Play Stream", SLOT(PlaybackPlay()) );
+ addbut( "Pause", "Pause Stream", SLOT(PlaybackPause()) );
+ addbut( "Slow", "Play Slower", SLOT(PlaybackSlow()) );
+ addbut( "Fast", "Play Faster", SLOT(PlaybackFast()) );
+ p_toolbar->addSeparator();
+ addbut( "Playlist", "Open Playlist", SLOT(Unimplemented()) );
+ addbut( "Prev", "Previous File", SLOT(PlaylistPrev()) );
+ addbut( "Next", "Next File", SLOT(PlaylistNext()) );
+#undef addbut
+
+ /*
+ * Create the menubar
+ */
+
+ QPopupMenu * p_tmpmenu = new QPopupMenu( this );
+
+#define instmp( x, y... ) p_tmpmenu->insertItem( x, this, ## y )
+ menuBar()->insertItem( "&File", p_tmpmenu );
+ instmp( "&Open File...", SLOT(FileOpen()), Key_F3 );
+ instmp( "Open &Disc...", SLOT(Unimplemented()), Key_F4 );
+ instmp( "&Network Stream...", SLOT(Unimplemented()), Key_F5 );
+ p_tmpmenu->insertSeparator();
+ instmp( "&Exit", SLOT(FileQuit()), CTRL+Key_Q );
+
+ p_tmpmenu = new QPopupMenu( this );
+ menuBar()->insertItem( "&View", p_tmpmenu );
+ instmp( "&Playlist...", SLOT(Unimplemented()) );
+ instmp( "&Modules...", SLOT(Unimplemented()) );
+
+ p_tmpmenu = new QPopupMenu( this );
+ menuBar()->insertItem( "&Settings", p_tmpmenu );
+ instmp( "&Preferences...", SLOT(Unimplemented()) );
+
+ p_tmpmenu = new QPopupMenu( this );
+ menuBar()->insertItem( "&Help", p_tmpmenu );
+ instmp( "&About...", SLOT(About()) );
+#undef instmp
+
+ /*
+ * Create the popup menu
+ */
+
+ p_popup = new QPopupMenu( /* floating menu */ );
+
+#define inspop( x, y... ) p_popup->insertItem( x, this, ## y )
+ inspop( "&Play", SLOT(PlaybackPlay()) );
+ inspop( "Pause", SLOT(PlaybackPause()) );
+ inspop( "&Slow", SLOT(PlaybackSlow()) );
+ inspop( "&Fast", SLOT(PlaybackFast()) );
+ p_popup->insertSeparator();
+ inspop( "&Open File...", SLOT(FileOpen()), Key_F3 );
+ inspop( "Open &Disc...", SLOT(Unimplemented()), Key_F4 );
+ inspop( "&Network Stream...", SLOT(Unimplemented()), Key_F5 );
+ p_popup->insertSeparator();
+ inspop( "&About...", SLOT(About()) );
+ inspop( "&Exit", SLOT(FileQuit()) );
+#undef inspop
+
+ /* Activate the statusbar */
+ statusBar();
+
+ /* Add the vertical box */
+ QVBox * p_vbox = new QVBox( this );
+ setCentralWidget( p_vbox );
+
+ /* The horizontal box */
+ QHBox * p_hbox = new QHBox( p_vbox );
+
+ /* The date label */
+ p_date = new QLabel( p_hbox );
+ p_date->setAlignment( AlignHCenter | AlignVCenter );
+ p_date->setText( "-:--:--" );
+
+ /* The status label */
+ QLabel *p_label = new QLabel( p_hbox );
+ p_label->setAlignment( AlignHCenter | AlignVCenter );
+ p_label->setText( "Status: foo" );
+
+ /* The bar label */
+ p_label = new QLabel( p_hbox );
+ p_label->setAlignment( AlignHCenter | AlignVCenter );
+ p_label->setText( "Bar: baz quux" );
+
+ /* Create the slider and connect it to the date label */
+ p_slider = new IntfSlider( p_intf, p_vbox );
+
+ connect( p_slider, SIGNAL(valueChanged(int)),
+ this, SLOT(DateDisplay(int)) );
+
+ /* The timer */
+ QTimer *p_timer = new QTimer( this );
+ connect( p_timer, SIGNAL(timeout()), this, SLOT(Manage()) );
+ p_timer->start( INTF_IDLE_SLEEP / 1000 );
+
+ /* Everything worked fine */
+ resize( 620, 30 );
+}
+
+/*****************************************************************************
+ * ~IntfWindow: interface window destructor
+ *****************************************************************************
+ * This function is called when the interface window is destroyed.
+ *****************************************************************************/
+IntfWindow::~IntfWindow( void )
+{
+ /* FIXME: remove everything cleanly */
+}
+
+/*****************************************************************************
+ * DateDisplay: display date
+ *****************************************************************************
+ * This function displays the current date in the date label.
+ *****************************************************************************/
+void IntfWindow::DateDisplay( int i_range )
+{
+ if( p_intf->p_sys->p_input )
+ {
+ char psz_time[ OFFSETTOTIME_MAX_SIZE ];
+
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
+ p_date->setText( input_OffsetToTime( p_intf->p_sys->p_input, psz_time,
+ ( p_intf->p_sys->p_input->stream.p_selected_area->i_size * i_range )
+ / SLIDER_MAX ) );
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
+ }
+}
+
+/*****************************************************************************
+ * FileOpen: open a file
+ *****************************************************************************
+ * This function opens a file requester and adds the selected file to
+ * the playlist.
+ *****************************************************************************/
+void IntfWindow::FileOpen( void )
+{
+ playlist_t *p_playlist;
+ QString file = QFileDialog::getOpenFileName( QString::null,
+ QString::null, this );
+
+ if( file.isEmpty() )
+ {
+ statusBar()->message( "No file loaded", 2000 );
+ }
+ else
+ {
+ p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Add( p_playlist, file.latin1(),
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+ vlc_object_release( p_playlist );
+ }
+}
+
+/*****************************************************************************
+ * FileQuit: terminate vlc
+ *****************************************************************************/
+void IntfWindow::FileQuit( void )
+{
+ p_intf->p_vlc->b_die = VLC_TRUE;
+}
+
+/*****************************************************************************
+ * About: display the "about" box
+ *****************************************************************************
+ * This function displays a simple "about" box with copyright information.
+ *****************************************************************************/
+void IntfWindow::About( void )
+{
+ QMessageBox::about( this, "About",
+ "VideoLAN Client\n"
+ "(C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 - the VideoLAN Team\n"
+ "\n"
+ "This is the VideoLAN client, a DVD and MPEG player.\n"
+ "It can play MPEG and MPEG 2 files from a file "
+ "or from a network source.\n"
+ "\n"
+ "More information: http://www.videolan.org/" );
+}
+
+/*****************************************************************************
+ * Manage: manage main thread messages
+ *****************************************************************************
+ * In this function, called approx. 10 times a second, we check what the
+ * main program wanted to tell us.
+ *****************************************************************************/
+void IntfWindow::Manage( void )
+{
+ /* Update the input */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = (input_thread_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ /* Manage the slider */
+ if( p_intf->p_sys->p_input && p_intf->p_sys->p_input->stream.b_seekable )
+ {
+ int i_value = p_slider->value();
+
+#define p_area p_intf->p_sys->p_input->stream.p_selected_area
+ /* If the user hasn't touched the slider since the last time,
+ * then the input can safely change it */
+ if( i_value == p_slider->oldvalue() )
+ {
+ i_value = ( SLIDER_MAX * p_area->i_tell ) / p_area->i_size;
+
+ p_slider->setValue( i_value );
+ p_slider->setOldValue( i_value );
+ }
+ /* Otherwise, send message to the input if the user has
+ * finished dragging the slider */
+ else if( p_slider->b_free )
+ {
+ off_t i_seek = ( i_value * p_area->i_size ) / SLIDER_MAX;
+
+ input_Seek( p_intf->p_sys->p_input, i_seek, INPUT_SEEK_SET );
+
+ /* Update the old value */
+ p_slider->setOldValue( i_value );
+ }
+#undef p_area
+ }
+
+ /* If the "display popup" flag has changed, popup the context menu */
+ if( p_intf->b_menu_change )
+ {
+ p_popup->popup( QCursor::pos() );
+ p_intf->b_menu_change = 0;
+ }
+
+ if( p_intf->b_die )
+ {
+ qApp->quit();
+ }
+}
+
+/*****************************************************************************
+ * PlaybackPlay: play
+ *****************************************************************************/
+void IntfWindow::PlaybackPlay( void )
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
+ }
+}
+
+/*****************************************************************************
+ * PlaybackPause: pause
+ *****************************************************************************/
+void IntfWindow::PlaybackPause( void )
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
+ }
+}
+
+/*****************************************************************************
+ * PlaybackSlow: slow
+ *****************************************************************************/
+void IntfWindow::PlaybackSlow( void )
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
+ }
+}
+
+/*****************************************************************************
+ * PlaybackFast: fast
+ *****************************************************************************/
+void IntfWindow::PlaybackFast( void )
+{
+ if( p_intf->p_sys->p_input != NULL )
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
+ }
+}
+
+/*****************************************************************************
+ * PlaylistPrev: previous playlist entry
+ *****************************************************************************/
+void IntfWindow::PlaylistPrev( void )
+{
+ playlist_t *p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Prev( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+/*****************************************************************************
+ * PlaylistNext: next playlist entry
+ *****************************************************************************/
+void IntfWindow::PlaylistNext( void )
+{
+ playlist_t *p_playlist = (playlist_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_Next( p_playlist );
+ vlc_object_release( p_playlist );
+}
+
+/*****************************************************************************
+ * IntfSlider: slider creator
+ *****************************************************************************
+ * This function creates the slider, sets its default values, and connects
+ * the interesting signals.
+ *****************************************************************************/
+IntfSlider::IntfSlider( intf_thread_t *p_intf, QWidget *p_parent )
+ :QSlider( Horizontal, p_parent )
+{
+ this->p_intf = p_intf;
+
+ setRange( SLIDER_MIN, SLIDER_MAX );
+ setPageStep( SLIDER_STEP );
+
+ setValue( SLIDER_MIN );
+ setOldValue( SLIDER_MIN );
+
+ setTracking( TRUE );
+ b_free = TRUE;
+
+ connect( this, SIGNAL(sliderMoved(int)), this, SLOT(SlideStart()) );
+ connect( this, SIGNAL(sliderPressed()), this, SLOT(SlideStart()) );
+ connect( this, SIGNAL(sliderReleased()), this, SLOT(SlideStop()) );
+}
+
+/*****************************************************************************
+ * ~IntfSlider: slider destructor
+ *****************************************************************************
+ * This function is called when the interface slider is destroyed.
+ *****************************************************************************/
+IntfSlider::~IntfSlider( void )
+{
+ /* We don't need to remove anything */
+}
+
+
--- /dev/null
+/*****************************************************************************
+ * qt.cpp : Qt plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: qt.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(Open) ( vlc_object_t * );
+void E_(Close) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#ifdef WIN32
+ int i = 80;
+#else
+ int i = getenv( "DISPLAY" ) == NULL ? 7 : 80;
+#endif
+ set_description( _("Qt interface module") );
+ set_capability( "interface", i );
+ set_program( "qvlc" );
+ set_callbacks( E_(Open), E_(Close) );
+vlc_module_end();
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+#
+# Borland C++ project
+# we override everything by setting win32_CUSTOM
+#
+win32_CUSTOM = yes
+
+../win32.so: Makefile
+ rm -f win32.mak
+ $(BCBUILDER)/Bin/bpr2mak win32.bpr -s | sed 's#^LIBPATH = .*#&;$$(RELEASELIBPATH)# ; s#^USERDEFINES = .*#& -DWIN32 -D__PLUGIN__ -D__VLC__ -DMODULE_NAME_IS_win32 -DMODULE_NAME=win32#' > win32.mak
+ $(BCBUILDER)/Bin/make -f win32.mak -b
+
+
--- /dev/null
+/*****************************************************************************\r
+ * about.cpp: The "About" dialog box\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "about.h"\r
+#include "win32_common.h"\r
+\r
+//---------------------------------------------------------------------------\r
+//#pragma package(smart_init)\r
+#pragma resource "*.dfm"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+//---------------------------------------------------------------------------\r
+__fastcall TAboutDlg::TAboutDlg( TComponent* Owner )\r
+ : TForm( Owner )\r
+{\r
+ Image1->Picture->Icon = p_intfGlobal->p_sys->p_window->Icon;\r
+ LabelVersion->Caption = "Version " VLC_VERSION;\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
--- /dev/null
+object AboutDlg: TAboutDlg\r
+ Left = 442\r
+ Top = 281\r
+ BorderStyle = bsDialog\r
+ Caption = 'About'\r
+ ClientHeight = 214\r
+ ClientWidth = 286\r
+ Color = clBtnFace\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clWindowText\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ Icon.Data = {\r
+ 0000010001003030000001001800A81C00001600000028000000300000006000\r
+ 00000100180000000000001B0000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000069375900000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000120E0A4011253E0F18000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000F0B\r
+ 084143CA08070016430F08040800000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000003127291203174647E8464AE808010840E54039E6390B0C06\r
+ 0E0A1C0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0070CD0079DD0079DD0070CD0000000000000000000C1008261D6E4647E54547\r
+ E64748E105040039E6393AE53939E63936D33308030100000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000070CD0079DD0079DE007DE40088F9008CFF008CFF0088F9007CE302\r
+ 6EC70B09124641DC4444DF4546E34446E54847E003040040E6403AEA3A3EE33E\r
+ 3CE33C39E639080F010801050000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0079DD0077D90070CB0078D8007BDC007BDC007BDC\r
+ 007BDC007BDC007BDD007EE32E232D0804084553F14250F34252ED4449DB4844\r
+ DC4645E208010540E5401C78150D18053CE63C3AE63A39EA393CD83C241A2006\r
+ 0402000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0079DD007ADF007BDE007BDC0072\r
+ CC005188004877004876004876004876034976054A760B4D7731434221175B42\r
+ 54EC4253EE4252F60B05104250F44252EB4546DA08010539E6392BAA2B080105\r
+ 3CE63C39E7393AE63A39E93939E839081208181C080000000000000000000000\r
+ 000000000000000000000000000000000000000070CD0079DD0079DD007CE300\r
+ 88F90089F90075D2005188004877005188008CFF008CFF008CFF008CFF008CFF\r
+ 1092FF2099FF31A0FF1408294840DB4550E1464EEA0C060B0B05084654F64653\r
+ F64453EF080E033AE63A2BAA2B03030339E33939DF3939E639080F083DDB3D24\r
+ 9C24434B3B000000000000000000000000000000000000000000000000000000\r
+ 0063B60085F3008BFE0088F9007FE90088F90080E8005CA0008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF048DFF1594FF259BFF35A2FF0C04103F38C754\r
+ 5AF7505BF10C08100801084352F64652F44253F30813053AE63A39E639030403\r
+ 1C521826A1250812010807032454131558150000000000000000000000000000\r
+ 000000000000000000000000000000000000000070CD007CE30079DD00000000\r
+ 7CE30089FA008CFF0089FA008CFF008CFF008CFF008CFF008CFF008CFF098FFF\r
+ 1996FF2A9DFF3AA4FF0804103A2AA34E58F74E58F40B0B120803054652F34548\r
+ E64451F305130532CA323AE23A03070308070307040008040139E63939E43931\r
+ B42F5E1347000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000061B10000000079DD008CFF008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF0E91FF1E98FF2E9FFF3FA6FF040408382BAF4D\r
+ 5AEF555AF70F12250501050F04160804074250F3121A123AE93A39E239080803\r
+ 0D2F08010401268C2539E7393DE63D3FE23E0804100000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 79DD008CFF008CFF008CFF008CFF008CFF008CFF008CFF008CFF028CFF1293FF\r
+ 239AFF33A1FF43A8FF0802083A2AA3565BF7555AF71714330501050104000801\r
+ 07424FF12828203AEA3A39E639030703182F1008340801040139E7393DE83D39\r
+ E939080400000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0088F9008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF078EFF1795FF279CFF38A3FF48AAFF0808005151F155\r
+ 5AF30804030804000504050800082E358E0E0C1F1D192439E53940E640080400\r
+ 2AA12739E63908020708010539E8393BE93B0804080000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000007CE3008CFF008CFF008CFF058EFD1D96F92398F8269AFA31A0FC42A8FF\r
+ 4FAEFF5CB3FF65B7FF0C08084F5AF14E57F50B04080804043639A54647E81C13\r
+ 49363AA70804080F120835953439E7393EE63E39DF3939EA39081105308A2B3F\r
+ E73F080601000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000047BDB1D96F92398F82498F83BA0\r
+ F399C1E1B1C9DDBCD4E7CBE0F3D9EDFFDCEEFFDEEFFFCDE8FF080808575BF750\r
+ 58F624125A5057F34845DF4A41E0150E30C55734E3723EC56E33A23D27050105\r
+ 39E43939E63939E6393CE63C14420C3BE03B192A090000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000004\r
+ 04042D88D399C1E1B1C9DDB1C9DCB7CBDBCFD3D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFF9FCFF0C08085D61F15B61EF555AF64A4FE13937BB0E0A12DE74\r
+ 39E1733CDE713CDF753AE67541C36B342C231F17141B3AE63A39E7393DE83D39\r
+ E93939DE39000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000001818186893B8C3CCD2D5D5D6D5D5D6D5D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFFFFFFFFFFFF140C145C5EF668\r
+ 63F75555EA10061CC3673FDF713A0C1104080403080105080007070407D56F36\r
+ DE743EDE72401C200C29452939E63939E73939EA390000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000343434A2B4C2D5D5D6D6D6D6D6D6D6D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFFEFEFF20161C5C5EF6373EAE0E0413E2713DE1763CCD6A3C2A0D\r
+ 08A44B2CDE743EBD612F080401030403E1713CDE7239DE713AE1723C22201139\r
+ C13341E641000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001B1B1B99AEBED5D5D6D5D5D6D5D5\r
+ D6CFD3D7B8CBDBBFD5E7CEE2F3DCEFFFDFF0FFE2F1FFE9F4FF10100C3639A46E\r
+ 4540DE7239DE713DE1713C07000784261CDE7639E3743E0812001F0407D86E36\r
+ E3753EE57540E57541DE763CDE733DD26637493C387E2F7B0000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00001B1B1B99AEBFCED3D7B7CBDBB1C9DD99C1E140A2F339A2FA49AAFC59B2FF\r
+ 66B8FF74BEFF92CBFFD9ECFF0F0402C66531DE7139E2733D854B1E0A01084D11\r
+ 0DE3733EE1723CDF713ADF753AE1763C1D0A08290708E57140E1763CDE733DC7\r
+ 6B34080408000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001818187FA5C399C1E13BA0F32498\r
+ F81D96F91091FD1C97FF2C9EFF3CA5FF4DACFF5DB3FF71BBFF8DC8FF9FD0FF08\r
+ 0400080406B95C2EDE7239070B070803014D1615DE723CDE7540E5714030090D\r
+ 0504003A120FE67541DE75390808044A0C290000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000707071778C81C92F3058EFD008CFF008CFF1092FF2099FF31A0FF41A7FF\r
+ 51AEFF62B5FF72BCFF7BBFFF7BBBF96E9FCD0808080806041D0508E571403E22\r
+ 0C200708080405070407070007080303B05F31DE723967301908010500000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000007CE3008CFF008C\r
+ FF048DFF1594FF259BFF35A2FF46A9FF56B0FF66B7FF77BEFF7BBFFF6DAAE300\r
+ 0000000000000000000000080401200C088D4024E17141E57140DF713ADE713E\r
+ DE76390801070000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000079DD008CFF008CFF098FFF1996FF2A9DFF3AA4FF4AABFF\r
+ 5BB2FF6BB9FF7BBFFF7BBFFF6AA5DD0000000000000000000000000000001D1A\r
+ 0C1A0F08110903441912E57140623B1E08020300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000079DD008CFF008C\r
+ FF0E91FF1E98FF2E9FFF3FA6FF4FADFF5FB4FF70BBFF7BBFFF78BAF96299CD00\r
+ 00000000000000000000000000000000000000003914100000005A2411000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0088F9078EFD2C9CF940A3F850ACFA60B4FC70BCFF\r
+ 7DC2FF87C6FF7EC0FF6DAAE30000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000707071A85DD40A2\r
+ F3A0C3E1B7CBDDC6D8E7D4E5F3E2F1FFE5F2FFD9ECFF9FD0FF7AACDD05050500\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001818187FA5C3B8CBDBD0D4D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFAFCFFE2EDF99FB7CD1C1C1C0000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000001B1B1B99AEBFD4D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFEFEFFD1DAE33E3E3E00000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001D1D1D7B9BB4CACED1D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFC9D2DD2121210000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000343434A5B5\r
+ C2CFD3D7BFCEDBC9D9E7D7E6F3E6F3FFECF5FFF0F4F9AEBDCD23232300000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000018181887A8C3A6C6E169B3F367B6FA77BEFC88C6FF\r
+ 9FD0FFB4CBE33939390000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000040404338C\r
+ D749A8F947A9FD54AFFF64B6FF74BDFF7EC0FF76ABDD05050500000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000001F7DCD369FF948AAFF58B1FF69B8FF79BFFF\r
+ 78BAF96299CD0000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003592E34DACFF5DB3FF6DBAFF7BBFFF6DAAE300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003890DD51AEFF62B5FF72BCFF7BBFFF\r
+ 6AA5DD0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003B8FD84C9CE3589FDE69A9E375B6F46299CD00000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003376B00000000000000000005788B6\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000006CC61A83DD247FCC00000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000006DC71A83DD2686D71F6EB1\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFE1FDFFF0000FFFFE0078FFF0000FFFE\r
+ 000007FF0000FFF0000001FF0000FF80000000FF0000FF000000003F0000FF00\r
+ 0000000F0000FE00000000070000F800000000070000F8000000000F0000FC00\r
+ 000000070000FE00000000070000FF80000000070000FFC0000000070000FFE0\r
+ 000000070000FFE0000000070000FFE0000000070000FFE0000000070000FFF0\r
+ 000000070000FFF0000000030000FFF0000000070000FFF00000000F0000FFF0\r
+ 0000003F0000FFF8000E00FF0000FFF8000F01FF0000FFF8000FD7FF0000FFF8\r
+ 001FFFFF0000FFFC001FFFFF0000FFFC001FFFFF0000FFFC003FFFFF0000FFFC\r
+ 003FFFFF0000FFFE003FFFFF0000FFFE007FFFFF0000FFFE007FFFFF0000FFFE\r
+ 007FFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF\r
+ 01FFFFFF0000FFFF01FFFFFF0000FFFF81FFFFFF0000FFFFC3FFFFFF0000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000}\r
+ OldCreateOrder = False\r
+ PixelsPerInch = 96\r
+ TextHeight = 13\r
+ object Label1: TLabel\r
+ Left = 114\r
+ Top = 18\r
+ Width = 132\r
+ Height = 20\r
+ Caption = 'VideoLAN Client'\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clWindowText\r
+ Font.Height = -16\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = [fsBold]\r
+ ParentFont = False\r
+ end\r
+ object Label2: TLabel\r
+ Left = 10\r
+ Top = 64\r
+ Width = 267\r
+ Height = 13\r
+ Caption = '(C) Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002'\r
+ end\r
+ object Label4: TLabel\r
+ Left = 15\r
+ Top = 123\r
+ Width = 253\r
+ Height = 39\r
+ Caption = \r
+ 'This is the VideoLAN Client, a DVD, MPEG and DivX player. It can' +\r
+ ' play MPEG and MPEG 2 files from a file or from a network source' +\r
+ '.'\r
+ WordWrap = True\r
+ end\r
+ object Label3: TLabel\r
+ Left = 38\r
+ Top = 80\r
+ Width = 227\r
+ Height = 13\r
+ Caption = 'The VideoLAN Team <videolan@videolan.org>'\r
+ end\r
+ object Image1: TImage\r
+ Left = 32\r
+ Top = 8\r
+ Width = 49\r
+ Height = 49\r
+ end\r
+ object Label5: TLabel\r
+ Left = 82\r
+ Top = 96\r
+ Width = 121\r
+ Height = 13\r
+ Caption = 'http://www.videolan.org/'\r
+ end\r
+ object LabelVersion: TLabel\r
+ Left = 114\r
+ Top = 40\r
+ Width = 59\r
+ Height = 13\r
+ Caption = 'Version x.y.z'\r
+ end\r
+ object BitBtnOk: TBitBtn\r
+ Left = 64\r
+ Top = 178\r
+ Width = 145\r
+ Height = 25\r
+ Caption = 'OK'\r
+ Default = True\r
+ ModalResult = 1\r
+ TabOrder = 0\r
+ end\r
+end\r
--- /dev/null
+/*****************************************************************************\r
+ * about.h: The "About" dialog box\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#ifndef aboutH\r
+#define aboutH\r
+//---------------------------------------------------------------------------\r
+#include <Classes.hpp>\r
+#include <Controls.hpp>\r
+#include <StdCtrls.hpp>\r
+#include <Forms.hpp>\r
+#include <Buttons.hpp>\r
+#include <ExtCtrls.hpp>\r
+#include <Graphics.hpp>\r
+//---------------------------------------------------------------------------\r
+class TAboutDlg : public TForm\r
+{\r
+__published: // IDE-managed Components\r
+ TLabel *Label1;\r
+ TLabel *Label2;\r
+ TLabel *Label4;\r
+ TBitBtn *BitBtnOk;\r
+ TLabel *Label3;\r
+ TImage *Image1;\r
+ TLabel *Label5;\r
+ TLabel *LabelVersion;\r
+private: // User declarations\r
+public: // User declarations\r
+ __fastcall TAboutDlg( TComponent* Owner );\r
+};\r
+//---------------------------------------------------------------------------\r
+#endif\r
--- /dev/null
+/*****************************************************************************\r
+ * control.cpp: functions to handle stream control buttons.\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "win32_common.h"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+/****************************************************************************\r
+ * Control functions: this is where the functions are defined\r
+ ****************************************************************************\r
+ * These functions are used by toolbuttons callbacks\r
+ ****************************************************************************/\r
+bool ControlBack( TObject *Sender )\r
+{\r
+ /* FIXME: TODO */\r
+ \r
+ return false;\r
+}\r
+\r
+\r
+bool ControlStop( TObject *Sender )\r
+{\r
+ playlist_t * p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ playlist_Stop( p_playlist );\r
+ vlc_object_release( p_playlist );\r
+\r
+ return true;\r
+}\r
+\r
+\r
+bool ControlPlay( TObject *Sender )\r
+{\r
+ playlist_t * p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ p_intfGlobal->p_sys->p_window->MenuOpenFileClick( Sender );\r
+ return false;\r
+ }\r
+\r
+ vlc_mutex_lock( &p_playlist->object_lock );\r
+ if( p_playlist->i_size )\r
+ {\r
+ vlc_mutex_unlock( &p_playlist->object_lock );\r
+ playlist_Play( p_playlist );\r
+ vlc_object_release( p_playlist );\r
+ }\r
+ else\r
+ {\r
+ vlc_mutex_unlock( &p_playlist->object_lock );\r
+ vlc_object_release( p_playlist );\r
+ p_intfGlobal->p_sys->p_window->MenuOpenFileClick( Sender );\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+\r
+bool ControlPause( TObject *Sender )\r
+{\r
+ if( p_intfGlobal->p_sys->p_input != NULL )\r
+ {\r
+ input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PAUSE );\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+\r
+bool ControlSlow( TObject *Sender )\r
+{\r
+ if( p_intfGlobal->p_sys->p_input != NULL )\r
+ {\r
+ input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_SLOWER );\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+\r
+bool ControlFast( TObject *Sender )\r
+{\r
+ if( p_intfGlobal->p_sys->p_input != NULL )\r
+ {\r
+ input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_FASTER );\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
--- /dev/null
+/*****************************************************************************\r
+ * control.h: prototypes for control functions.\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+bool ControlBack ( TObject *Sender );\r
+bool ControlStop ( TObject *Sender );\r
+bool ControlPlay ( TObject *Sender );\r
+bool ControlPause( TObject *Sender );\r
+bool ControlSlow ( TObject *Sender );\r
+bool ControlFast ( TObject *Sender );\r
+\r
--- /dev/null
+/*****************************************************************************\r
+ * disc.cpp: "Open disc" dialog box.\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "disc.h"\r
+#include "win32_common.h"\r
+\r
+//---------------------------------------------------------------------------\r
+//#pragma package(smart_init)\r
+#pragma link "CSPIN"\r
+#pragma resource "*.dfm"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+//---------------------------------------------------------------------------\r
+__fastcall TDiscDlg::TDiscDlg( TComponent* Owner )\r
+ : TForm( Owner )\r
+{\r
+ /* Simulate a click to get the correct device name */\r
+ RadioGroupTypeClick( RadioGroupType );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TDiscDlg::FormShow( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuOpenDisc->Checked = true;\r
+ p_intfGlobal->p_sys->p_window->PopupOpenDisc->Checked = true;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TDiscDlg::FormHide( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuOpenDisc->Checked = false;\r
+ p_intfGlobal->p_sys->p_window->PopupOpenDisc->Checked = false;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TDiscDlg::BitBtnCancelClick( TObject *Sender )\r
+{\r
+ Hide();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TDiscDlg::BitBtnOkClick( TObject *Sender )\r
+{\r
+ AnsiString Device, Source, Method, Title, Chapter;\r
+ playlist_t * p_playlist;\r
+\r
+ p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ { \r
+ return;\r
+ } \r
+\r
+ Hide();\r
+\r
+ Device = EditDevice->Text;\r
+\r
+ /* Check which method was activated */\r
+ if( RadioGroupType->ItemIndex == 0 )\r
+ {\r
+ Method = "dvd";\r
+ }\r
+ else\r
+ {\r
+ Method = "vcd";\r
+ }\r
+\r
+ /* Select title and chapter */\r
+ Title.sprintf( "%d", SpinEditTitle->Value );\r
+ Chapter.sprintf( "%d", SpinEditChapter->Value );\r
+\r
+ /* Build source name and add it to playlist */\r
+ Source = Method + ":" + Device + "@" + Title + "," + Chapter;\r
+ playlist_Add( p_playlist, Source.c_str(),\r
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );\r
+\r
+ /* update the display */\r
+ p_intfGlobal->p_sys->p_playwin->UpdateGrid( p_playlist );\r
+\r
+ vlc_object_release( p_playlist );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TDiscDlg::RadioGroupTypeClick( TObject *Sender )\r
+{\r
+ TRadioGroup *RadioGroupType = (TRadioGroup *)Sender;\r
+ char *psz_device;\r
+\r
+ if( RadioGroupType->ItemIndex == 0 )\r
+ {\r
+ psz_device = config_GetPsz( p_intfGlobal, "dvd" );\r
+ }\r
+ else\r
+ {\r
+ psz_device = config_GetPsz( p_intfGlobal, "vcd" );\r
+ }\r
+\r
+ if( psz_device )\r
+ {\r
+ EditDevice->Text = psz_device;\r
+ free( psz_device );\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
--- /dev/null
+object DiscDlg: TDiscDlg\r
+ Left = 503\r
+ Top = 366\r
+ BorderStyle = bsDialog\r
+ Caption = 'Open disc'\r
+ ClientHeight = 170\r
+ ClientWidth = 258\r
+ Color = clBtnFace\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clWindowText\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ Icon.Data = {\r
+ 0000010001003030000001001800A81C00001600000028000000300000006000\r
+ 00000100180000000000001B0000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000069375900000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000120E0A4011253E0F18000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000F0B\r
+ 084143CA08070016430F08040800000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000003127291203174647E8464AE808010840E54039E6390B0C06\r
+ 0E0A1C0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0070CD0079DD0079DD0070CD0000000000000000000C1008261D6E4647E54547\r
+ E64748E105040039E6393AE53939E63936D33308030100000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000070CD0079DD0079DE007DE40088F9008CFF008CFF0088F9007CE302\r
+ 6EC70B09124641DC4444DF4546E34446E54847E003040040E6403AEA3A3EE33E\r
+ 3CE33C39E639080F010801050000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0079DD0077D90070CB0078D8007BDC007BDC007BDC\r
+ 007BDC007BDC007BDD007EE32E232D0804084553F14250F34252ED4449DB4844\r
+ DC4645E208010540E5401C78150D18053CE63C3AE63A39EA393CD83C241A2006\r
+ 0402000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0079DD007ADF007BDE007BDC0072\r
+ CC005188004877004876004876004876034976054A760B4D7731434221175B42\r
+ 54EC4253EE4252F60B05104250F44252EB4546DA08010539E6392BAA2B080105\r
+ 3CE63C39E7393AE63A39E93939E839081208181C080000000000000000000000\r
+ 000000000000000000000000000000000000000070CD0079DD0079DD007CE300\r
+ 88F90089F90075D2005188004877005188008CFF008CFF008CFF008CFF008CFF\r
+ 1092FF2099FF31A0FF1408294840DB4550E1464EEA0C060B0B05084654F64653\r
+ F64453EF080E033AE63A2BAA2B03030339E33939DF3939E639080F083DDB3D24\r
+ 9C24434B3B000000000000000000000000000000000000000000000000000000\r
+ 0063B60085F3008BFE0088F9007FE90088F90080E8005CA0008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF048DFF1594FF259BFF35A2FF0C04103F38C754\r
+ 5AF7505BF10C08100801084352F64652F44253F30813053AE63A39E639030403\r
+ 1C521826A1250812010807032454131558150000000000000000000000000000\r
+ 000000000000000000000000000000000000000070CD007CE30079DD00000000\r
+ 7CE30089FA008CFF0089FA008CFF008CFF008CFF008CFF008CFF008CFF098FFF\r
+ 1996FF2A9DFF3AA4FF0804103A2AA34E58F74E58F40B0B120803054652F34548\r
+ E64451F305130532CA323AE23A03070308070307040008040139E63939E43931\r
+ B42F5E1347000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000061B10000000079DD008CFF008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF0E91FF1E98FF2E9FFF3FA6FF040408382BAF4D\r
+ 5AEF555AF70F12250501050F04160804074250F3121A123AE93A39E239080803\r
+ 0D2F08010401268C2539E7393DE63D3FE23E0804100000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 79DD008CFF008CFF008CFF008CFF008CFF008CFF008CFF008CFF028CFF1293FF\r
+ 239AFF33A1FF43A8FF0802083A2AA3565BF7555AF71714330501050104000801\r
+ 07424FF12828203AEA3A39E639030703182F1008340801040139E7393DE83D39\r
+ E939080400000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0088F9008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF078EFF1795FF279CFF38A3FF48AAFF0808005151F155\r
+ 5AF30804030804000504050800082E358E0E0C1F1D192439E53940E640080400\r
+ 2AA12739E63908020708010539E8393BE93B0804080000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000007CE3008CFF008CFF008CFF058EFD1D96F92398F8269AFA31A0FC42A8FF\r
+ 4FAEFF5CB3FF65B7FF0C08084F5AF14E57F50B04080804043639A54647E81C13\r
+ 49363AA70804080F120835953439E7393EE63E39DF3939EA39081105308A2B3F\r
+ E73F080601000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000047BDB1D96F92398F82498F83BA0\r
+ F399C1E1B1C9DDBCD4E7CBE0F3D9EDFFDCEEFFDEEFFFCDE8FF080808575BF750\r
+ 58F624125A5057F34845DF4A41E0150E30C55734E3723EC56E33A23D27050105\r
+ 39E43939E63939E6393CE63C14420C3BE03B192A090000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000004\r
+ 04042D88D399C1E1B1C9DDB1C9DCB7CBDBCFD3D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFF9FCFF0C08085D61F15B61EF555AF64A4FE13937BB0E0A12DE74\r
+ 39E1733CDE713CDF753AE67541C36B342C231F17141B3AE63A39E7393DE83D39\r
+ E93939DE39000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000001818186893B8C3CCD2D5D5D6D5D5D6D5D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFFFFFFFFFFFF140C145C5EF668\r
+ 63F75555EA10061CC3673FDF713A0C1104080403080105080007070407D56F36\r
+ DE743EDE72401C200C29452939E63939E73939EA390000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000343434A2B4C2D5D5D6D6D6D6D6D6D6D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFFEFEFF20161C5C5EF6373EAE0E0413E2713DE1763CCD6A3C2A0D\r
+ 08A44B2CDE743EBD612F080401030403E1713CDE7239DE713AE1723C22201139\r
+ C13341E641000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001B1B1B99AEBED5D5D6D5D5D6D5D5\r
+ D6CFD3D7B8CBDBBFD5E7CEE2F3DCEFFFDFF0FFE2F1FFE9F4FF10100C3639A46E\r
+ 4540DE7239DE713DE1713C07000784261CDE7639E3743E0812001F0407D86E36\r
+ E3753EE57540E57541DE763CDE733DD26637493C387E2F7B0000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00001B1B1B99AEBFCED3D7B7CBDBB1C9DD99C1E140A2F339A2FA49AAFC59B2FF\r
+ 66B8FF74BEFF92CBFFD9ECFF0F0402C66531DE7139E2733D854B1E0A01084D11\r
+ 0DE3733EE1723CDF713ADF753AE1763C1D0A08290708E57140E1763CDE733DC7\r
+ 6B34080408000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001818187FA5C399C1E13BA0F32498\r
+ F81D96F91091FD1C97FF2C9EFF3CA5FF4DACFF5DB3FF71BBFF8DC8FF9FD0FF08\r
+ 0400080406B95C2EDE7239070B070803014D1615DE723CDE7540E5714030090D\r
+ 0504003A120FE67541DE75390808044A0C290000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000707071778C81C92F3058EFD008CFF008CFF1092FF2099FF31A0FF41A7FF\r
+ 51AEFF62B5FF72BCFF7BBFFF7BBBF96E9FCD0808080806041D0508E571403E22\r
+ 0C200708080405070407070007080303B05F31DE723967301908010500000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000007CE3008CFF008C\r
+ FF048DFF1594FF259BFF35A2FF46A9FF56B0FF66B7FF77BEFF7BBFFF6DAAE300\r
+ 0000000000000000000000080401200C088D4024E17141E57140DF713ADE713E\r
+ DE76390801070000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000079DD008CFF008CFF098FFF1996FF2A9DFF3AA4FF4AABFF\r
+ 5BB2FF6BB9FF7BBFFF7BBFFF6AA5DD0000000000000000000000000000001D1A\r
+ 0C1A0F08110903441912E57140623B1E08020300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000079DD008CFF008C\r
+ FF0E91FF1E98FF2E9FFF3FA6FF4FADFF5FB4FF70BBFF7BBFFF78BAF96299CD00\r
+ 00000000000000000000000000000000000000003914100000005A2411000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0088F9078EFD2C9CF940A3F850ACFA60B4FC70BCFF\r
+ 7DC2FF87C6FF7EC0FF6DAAE30000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000707071A85DD40A2\r
+ F3A0C3E1B7CBDDC6D8E7D4E5F3E2F1FFE5F2FFD9ECFF9FD0FF7AACDD05050500\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001818187FA5C3B8CBDBD0D4D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFAFCFFE2EDF99FB7CD1C1C1C0000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000001B1B1B99AEBFD4D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFEFEFFD1DAE33E3E3E00000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001D1D1D7B9BB4CACED1D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFC9D2DD2121210000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000343434A5B5\r
+ C2CFD3D7BFCEDBC9D9E7D7E6F3E6F3FFECF5FFF0F4F9AEBDCD23232300000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000018181887A8C3A6C6E169B3F367B6FA77BEFC88C6FF\r
+ 9FD0FFB4CBE33939390000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000040404338C\r
+ D749A8F947A9FD54AFFF64B6FF74BDFF7EC0FF76ABDD05050500000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000001F7DCD369FF948AAFF58B1FF69B8FF79BFFF\r
+ 78BAF96299CD0000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003592E34DACFF5DB3FF6DBAFF7BBFFF6DAAE300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003890DD51AEFF62B5FF72BCFF7BBFFF\r
+ 6AA5DD0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003B8FD84C9CE3589FDE69A9E375B6F46299CD00000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003376B00000000000000000005788B6\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000006CC61A83DD247FCC00000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000006DC71A83DD2686D71F6EB1\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFE1FDFFF0000FFFFE0078FFF0000FFFE\r
+ 000007FF0000FFF0000001FF0000FF80000000FF0000FF000000003F0000FF00\r
+ 0000000F0000FE00000000070000F800000000070000F8000000000F0000FC00\r
+ 000000070000FE00000000070000FF80000000070000FFC0000000070000FFE0\r
+ 000000070000FFE0000000070000FFE0000000070000FFE0000000070000FFF0\r
+ 000000070000FFF0000000030000FFF0000000070000FFF00000000F0000FFF0\r
+ 0000003F0000FFF8000E00FF0000FFF8000F01FF0000FFF8000FD7FF0000FFF8\r
+ 001FFFFF0000FFFC001FFFFF0000FFFC001FFFFF0000FFFC003FFFFF0000FFFC\r
+ 003FFFFF0000FFFE003FFFFF0000FFFE007FFFFF0000FFFE007FFFFF0000FFFE\r
+ 007FFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF\r
+ 01FFFFFF0000FFFF01FFFFFF0000FFFF81FFFFFF0000FFFFC3FFFFFF0000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000}\r
+ OldCreateOrder = False\r
+ OnHide = FormHide\r
+ OnShow = FormShow\r
+ PixelsPerInch = 96\r
+ TextHeight = 13\r
+ object LabelDevice: TLabel\r
+ Left = 8\r
+ Top = 105\r
+ Width = 63\r
+ Height = 13\r
+ Caption = 'Device name'\r
+ end\r
+ object GroupBoxPosition: TGroupBox\r
+ Left = 96\r
+ Top = 8\r
+ Width = 153\r
+ Height = 81\r
+ Caption = 'Starting position'\r
+ TabOrder = 1\r
+ object LabelTitle: TLabel\r
+ Left = 16\r
+ Top = 24\r
+ Width = 20\r
+ Height = 13\r
+ Caption = 'Title'\r
+ end\r
+ object LabelChapter: TLabel\r
+ Left = 16\r
+ Top = 52\r
+ Width = 37\r
+ Height = 13\r
+ Caption = 'Chapter'\r
+ end\r
+ object SpinEditTitle: TCSpinEdit\r
+ Left = 64\r
+ Top = 19\r
+ Width = 73\r
+ Height = 22\r
+ TabStop = True\r
+ MaxValue = 65535\r
+ MinValue = 1\r
+ ParentColor = False\r
+ TabOrder = 0\r
+ Value = 1\r
+ end\r
+ object SpinEditChapter: TCSpinEdit\r
+ Left = 64\r
+ Top = 47\r
+ Width = 73\r
+ Height = 22\r
+ TabStop = True\r
+ MaxValue = 65535\r
+ MinValue = 1\r
+ ParentColor = False\r
+ TabOrder = 1\r
+ Value = 1\r
+ end\r
+ end\r
+ object RadioGroupType: TRadioGroup\r
+ Left = 8\r
+ Top = 8\r
+ Width = 81\r
+ Height = 81\r
+ Caption = 'Disc type'\r
+ ItemIndex = 0\r
+ Items.Strings = (\r
+ 'DVD'\r
+ 'VCD')\r
+ TabOrder = 0\r
+ OnClick = RadioGroupTypeClick\r
+ end\r
+ object BitBtnOk: TBitBtn\r
+ Left = 8\r
+ Top = 136\r
+ Width = 113\r
+ Height = 25\r
+ Caption = 'OK'\r
+ Default = True\r
+ ModalResult = 1\r
+ TabOrder = 3\r
+ OnClick = BitBtnOkClick\r
+ end\r
+ object BitBtnCancel: TBitBtn\r
+ Left = 136\r
+ Top = 136\r
+ Width = 113\r
+ Height = 25\r
+ Caption = 'Cancel'\r
+ ModalResult = 2\r
+ TabOrder = 4\r
+ OnClick = BitBtnCancelClick\r
+ end\r
+ object EditDevice: TEdit\r
+ Left = 88\r
+ Top = 101\r
+ Width = 161\r
+ Height = 21\r
+ TabOrder = 2\r
+ Text = 'F:\'\r
+ end\r
+end\r
--- /dev/null
+/*****************************************************************************\r
+ * disc.h: "Open disc" dialog box.\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#ifndef discH\r
+#define discH\r
+//---------------------------------------------------------------------------\r
+#include <Classes.hpp>\r
+#include <Controls.hpp>\r
+#include <StdCtrls.hpp>\r
+#include <Forms.hpp>\r
+#include <Buttons.hpp>\r
+#include <ComCtrls.hpp>\r
+#include <ExtCtrls.hpp>\r
+#include "CSPIN.h"\r
+//---------------------------------------------------------------------------\r
+class TDiscDlg : public TForm\r
+{\r
+__published: // IDE-managed Components\r
+ TLabel *LabelDevice;\r
+ TGroupBox *GroupBoxPosition;\r
+ TLabel *LabelTitle;\r
+ TLabel *LabelChapter;\r
+ TRadioGroup *RadioGroupType;\r
+ TBitBtn *BitBtnOk;\r
+ TBitBtn *BitBtnCancel;\r
+ TEdit *EditDevice;\r
+ TCSpinEdit *SpinEditTitle;\r
+ TCSpinEdit *SpinEditChapter;\r
+ void __fastcall FormShow(TObject *Sender);\r
+ void __fastcall FormHide(TObject *Sender);\r
+ void __fastcall BitBtnCancelClick(TObject *Sender);\r
+ void __fastcall BitBtnOkClick(TObject *Sender);\r
+ void __fastcall RadioGroupTypeClick(TObject *Sender);\r
+private: // User declarations\r
+public: // User declarations\r
+ __fastcall TDiscDlg( TComponent* Owner );\r
+};\r
+//---------------------------------------------------------------------------\r
+#endif\r
--- /dev/null
+USEUNIT("win32.cpp");\r
+USEUNIT("intf_win32.cpp");\r
+USEFORM("mainframe.cpp", MainFrameDlg);\r
+USEFORM("network.cpp", NetworkDlg);\r
+USEFORM("playlist.cpp", PlaylistDlg);\r
+USEFORM("preferences.cpp", PreferencesDlg);\r
+USEFORM("about.cpp", AboutDlg);\r
+USEFORM("disc.cpp", DiscDlg);\r
+USEUNIT("control.cpp");\r
+USE("win32_common.h", File);\r
+USEUNIT("menu.cpp");\r
+USEFORM("messages.cpp", MessagesDlg);\r
+//---------------------------------------------------------------------------\r
+This file is used by the project manager only and should be treated like the project file\r
+
+\rDllEntryPoint
\ No newline at end of file
--- /dev/null
+/*****************************************************************************\r
+ * intfwin.cpp: Win32 interface plugin for vlc\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+/*****************************************************************************\r
+ * Preamble\r
+ *****************************************************************************/\r
+#include <vcl.h>\r
+#include <stdlib.h> /* malloc(), free() */\r
+#include <errno.h> /* ENOMEM */\r
+#include <string.h> /* strerror() */\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "mainframe.h"\r
+#include "menu.h"\r
+#include "win32_common.h"\r
+\r
+intf_thread_t *p_intfGlobal;\r
+\r
+/*****************************************************************************\r
+ * Local prototypes.\r
+ *****************************************************************************/\r
+static void intf_Run ( intf_thread_t *p_intf );\r
+\r
+int Win32Manage( void *p_data );\r
+\r
+/*****************************************************************************\r
+ * Open: initialize interface\r
+ *****************************************************************************/\r
+int E_(Open)( vlc_object_t *p_this )\r
+{\r
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;\r
+\r
+ /* Allocate instance and initialize some members */\r
+ p_intf->p_sys = (intf_sys_t *) malloc( sizeof( intf_sys_t ) );\r
+ if( p_intf->p_sys == NULL )\r
+ {\r
+ msg_Err( p_intf, "out of memory" );\r
+ return( 1 );\r
+ };\r
+\r
+ p_intfGlobal = p_intf;\r
+ p_intf->pf_run = intf_Run;\r
+\r
+ p_intf->p_sys->p_sub = msg_Subscribe( p_intf );\r
+\r
+ /* Initialize Win32 thread */\r
+ p_intf->p_sys->b_playing = 0;\r
+ p_intf->p_sys->b_popup_changed = 0;\r
+\r
+ p_intf->p_sys->p_input = NULL;\r
+ p_intf->p_sys->i_playing = -1;\r
+ p_intf->p_sys->b_slider_free = 1;\r
+\r
+ return( 0 );\r
+}\r
+\r
+/*****************************************************************************\r
+ * Close: destroy interface\r
+ *****************************************************************************/\r
+void E_(Close)( vlc_object_t *p_this )\r
+{\r
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;\r
+\r
+ if( p_intf->p_sys->p_input )\r
+ {\r
+ vlc_object_release( p_intf->p_sys->p_input );\r
+ }\r
+\r
+ msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );\r
+\r
+ /* Destroy structure */\r
+ free( p_intf->p_sys );\r
+}\r
+\r
+/*****************************************************************************\r
+ * intf_Run: main loop\r
+ *****************************************************************************/\r
+static void intf_Run( intf_thread_t *p_intf )\r
+{\r
+ p_intf->p_sys->p_window = new TMainFrameDlg( NULL );\r
+ p_intf->p_sys->p_playwin = new TPlaylistDlg( NULL );\r
+ p_intf->p_sys->p_messages = new TMessagesDlg( NULL );\r
+\r
+ /* show main window and wait until it is closed */\r
+ p_intf->p_sys->p_window->ShowModal();\r
+\r
+ if( p_intf->p_sys->p_disc ) delete p_intf->p_sys->p_disc;\r
+ if( p_intf->p_sys->p_network ) delete p_intf->p_sys->p_network;\r
+ if( p_intf->p_sys->p_preferences ) delete p_intf->p_sys->p_preferences;\r
+ delete p_intf->p_sys->p_messages;\r
+ delete p_intf->p_sys->p_playwin;\r
+}\r
+\r
+/*****************************************************************************\r
+ * Win32Manage: manage main thread messages\r
+ *****************************************************************************\r
+ * In this function, called approx. 10 times a second, we check what the\r
+ * main program wanted to tell us.\r
+ *****************************************************************************/\r
+int Win32Manage( intf_thread_t *p_intf )\r
+{\r
+ vlc_mutex_lock( &p_intf->change_lock );\r
+\r
+ /* If the "display popup" flag has changed */\r
+ if( p_intf->b_menu_change )\r
+ {\r
+ /* FIXME: It would be nice to close the popup when the user left-clicks\r
+ elsewhere, or to actualize the position when he right-clicks again,\r
+ but i couldn't find a way to close it :-( */\r
+ TPoint MousePos = Mouse->CursorPos;\r
+ p_intf->p_sys->p_window->PopupMenuMain->Popup( MousePos.x, MousePos.y );\r
+ p_intf->b_menu_change = 0;\r
+ }\r
+\r
+ /* Update the log window */\r
+ p_intf->p_sys->p_messages->UpdateLog();\r
+\r
+ /* Update the playlist */\r
+ p_intf->p_sys->p_playwin->Manage( p_intf );\r
+\r
+ /* Update the input */\r
+ if( p_intf->p_sys->p_input == NULL )\r
+ {\r
+ p_intf->p_sys->p_input = (input_thread_t *)\r
+ vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );\r
+ }\r
+ else if( p_intf->p_sys->p_input->b_dead )\r
+ {\r
+ vlc_object_release( p_intf->p_sys->p_input );\r
+ p_intf->p_sys->p_input = NULL;\r
+ }\r
+ \r
+ if( p_intf->p_sys->p_input )\r
+ {\r
+ input_thread_t *p_input = p_intf->p_sys->p_input;\r
+\r
+ vlc_mutex_lock( &p_input->stream.stream_lock );\r
+\r
+ if( !p_input->b_die )\r
+ {\r
+ /* New input or stream map change */\r
+ if( p_input->stream.b_changed )\r
+ {\r
+ p_intf->p_sys->p_window->ModeManage();\r
+ SetupMenus( p_intf );\r
+ p_intf->p_sys->b_playing = 1;\r
+ }\r
+\r
+ /* Manage the slider */\r
+ if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )\r
+ {\r
+ TTrackBar * TrackBar = p_intf->p_sys->p_window->TrackBar;\r
+ off_t NewValue = TrackBar->Position;\r
+\r
+#define p_area p_input->stream.p_selected_area\r
+ /* If the user hasn't touched the slider since the last time,\r
+ * then the input can safely change it */\r
+ if( NewValue == p_intf->p_sys->OldValue )\r
+ {\r
+ /* Update the value */\r
+ TrackBar->Position = p_intf->p_sys->OldValue =\r
+ ( (off_t)SLIDER_MAX_VALUE * p_area->i_tell ) /\r
+ p_area->i_size;\r
+ }\r
+ /* Otherwise, send message to the input if the user has\r
+ * finished dragging the slider */\r
+ else if( p_intf->p_sys->b_slider_free )\r
+ {\r
+ off_t i_seek = ( NewValue * p_area->i_size ) /\r
+ (off_t)SLIDER_MAX_VALUE;\r
+\r
+ /* release the lock to be able to seek */\r
+ vlc_mutex_unlock( &p_input->stream.stream_lock );\r
+ input_Seek( p_input, i_seek, INPUT_SEEK_SET );\r
+ vlc_mutex_lock( &p_input->stream.stream_lock );\r
+\r
+ /* Update the old value */\r
+ p_intf->p_sys->OldValue = NewValue;\r
+ }\r
+\r
+ /* Update the display */\r
+// TrackBar->Invalidate();\r
+ \r
+# undef p_area\r
+ }\r
+\r
+ if( p_intf->p_sys->i_part !=\r
+ p_input->stream.p_selected_area->i_part )\r
+ {\r
+// p_intf->p_sys->b_chapter_update = 1;\r
+ SetupMenus( p_intf );\r
+ }\r
+ }\r
+\r
+ vlc_mutex_unlock( &p_input->stream.stream_lock );\r
+ }\r
+ else if( p_intf->p_sys->b_playing && !p_intf->b_die )\r
+ {\r
+ p_intf->p_sys->p_window->ModeManage();\r
+ p_intf->p_sys->b_playing = 0;\r
+ }\r
+\r
+ if( p_intf->b_die )\r
+ {\r
+ vlc_mutex_unlock( &p_intf->change_lock );\r
+\r
+ /* Prepare to die, young Skywalker */\r
+ p_intf->p_sys->p_window->ModalResult = mrOk;\r
+\r
+ /* Just in case */\r
+ return( FALSE );\r
+ }\r
+ \r
+ vlc_mutex_unlock( &p_intf->change_lock );\r
+\r
+ return( TRUE );\r
+}\r
+\r
--- /dev/null
+/*****************************************************************************\r
+ * mainframe.cpp: Win32 interface plugin for vlc\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+#include <vlc/vout.h>\r
+\r
+#include "mainframe.h"\r
+#include "menu.h"\r
+#include "control.h"\r
+#include "disc.h"\r
+#include "network.h"\r
+#include "about.h"\r
+#include "preferences.h"\r
+#include "messages.h"\r
+#include "playlist.h"\r
+#include "win32_common.h"\r
+\r
+#include "netutils.h"\r
+\r
+//---------------------------------------------------------------------------\r
+//#pragma package(smart_init)\r
+#pragma link "CSPIN"\r
+#pragma resource "*.dfm"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+extern int Win32Manage( intf_thread_t *p_intf );\r
+\r
+//---------------------------------------------------------------------------\r
+__fastcall TMainFrameDlg::TMainFrameDlg( TComponent* Owner )\r
+ : TForm( Owner )\r
+{\r
+ Application->ShowHint = true;\r
+ Application->OnHint = DisplayHint;\r
+\r
+ TimerManage->Interval = INTF_IDLE_SLEEP / 1000;\r
+\r
+ TrackBar->Max = SLIDER_MAX_VALUE;\r
+\r
+ /* default height and caption */\r
+ ClientHeight = 37 + ToolBar->Height;\r
+ Caption = VOUT_TITLE " (Win32 interface)";\r
+\r
+ StringListPref = new TStringList();\r
+}\r
+//---------------------------------------------------------------------------\r
+__fastcall TMainFrameDlg::~TMainFrameDlg()\r
+{\r
+ delete StringListPref;\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Event handlers\r
+ ****************************************************************************/\r
+void __fastcall TMainFrameDlg::TimerManageTimer( TObject *Sender )\r
+{\r
+ Win32Manage( p_intfGlobal );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::DisplayHint( TObject *Sender )\r
+{\r
+ StatusBar->SimpleText = GetLongHint( Application->Hint );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::TrackBarChange( TObject *Sender )\r
+{\r
+ /* This function displays the current date related to the position in\r
+ * the stream. It is called whenever the slider changes its value.\r
+ * The lock has to be taken before the function is called */\r
+\r
+// vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+\r
+ if( p_intfGlobal->p_sys->p_input != NULL )\r
+ {\r
+#define p_area p_intfGlobal->p_sys->p_input->stream.p_selected_area\r
+ char psz_time[ OFFSETTOTIME_MAX_SIZE ];\r
+ off_t Value = TrackBar->Position;\r
+\r
+ GroupBoxSlider->Caption =\r
+ input_OffsetToTime( p_intfGlobal->p_sys->p_input, psz_time,\r
+ ( p_area->i_size * Value ) / (off_t)SLIDER_MAX_VALUE );\r
+#undef p_area\r
+ }\r
+\r
+// vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::FormClose( TObject *Sender,\r
+ TCloseAction &Action )\r
+{\r
+ intf_thread_t *p_intf = p_intfGlobal;\r
+\r
+ vlc_mutex_lock( &p_intf->change_lock );\r
+ p_intf->p_vlc->b_die = VLC_TRUE;\r
+ vlc_mutex_unlock( &p_intf->change_lock );\r
+\r
+ /* we don't destroy the form immediatly */\r
+ Action = caHide;\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Menu callbacks\r
+ ****************************************************************************/\r
+void __fastcall TMainFrameDlg::MenuOpenFileClick( TObject *Sender )\r
+{\r
+ AnsiString FileName;\r
+ playlist_t * p_playlist;\r
+\r
+ p_playlist = (playlist_t *)vlc_object_find( p_intfGlobal,\r
+ VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ if( OpenDialog1->Execute() )\r
+ {\r
+ /* add the new file to the interface playlist */\r
+ FileName = OpenDialog1->FileName;\r
+ playlist_Add( p_playlist, (char*)FileName.c_str(),\r
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );\r
+\r
+ /* update the plugin display */\r
+ p_intfGlobal->p_sys->p_playwin->UpdateGrid( p_playlist );\r
+ };\r
+\r
+ vlc_object_release( p_playlist );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuOpenDiscClick( TObject *Sender )\r
+{\r
+ TDiscDlg *p_disc = p_intfGlobal->p_sys->p_disc;\r
+ if( p_disc == NULL )\r
+ {\r
+ p_disc = new TDiscDlg( this );\r
+ p_intfGlobal->p_sys->p_disc = p_disc;\r
+ }\r
+ p_disc->Show();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuNetworkStreamClick( TObject *Sender )\r
+{\r
+ TNetworkDlg *p_network = p_intfGlobal->p_sys->p_network;\r
+ if( p_network == NULL )\r
+ {\r
+ p_network = new TNetworkDlg( this );\r
+ p_intfGlobal->p_sys->p_network = p_network;\r
+ }\r
+ p_network->Show();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuExitClick( TObject *Sender )\r
+{\r
+ Close();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuHideinterfaceClick( TObject *Sender )\r
+{\r
+ this->SendToBack();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuFullscreenClick( TObject *Sender )\r
+{\r
+ vout_thread_t *p_vout;\r
+\r
+ p_vout = (vout_thread_t *)vlc_object_find( p_intfGlobal->p_sys->p_input,\r
+ VLC_OBJECT_VOUT, FIND_CHILD );\r
+ if( p_vout == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;\r
+ vlc_object_release( p_vout );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuPlaylistClick( TObject *Sender )\r
+{\r
+ TPlaylistDlg *p_playwin = p_intfGlobal->p_sys->p_playwin;\r
+ if( p_playwin->Visible )\r
+ {\r
+ p_playwin->Hide();\r
+ }\r
+ else\r
+ {\r
+ playlist_t * p_playlist;\r
+ p_playlist = (playlist_t *)vlc_object_find( p_intfGlobal,\r
+ VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ p_playwin->UpdateGrid( p_playlist );\r
+ vlc_object_release( p_playlist );\r
+ p_playwin->Show();\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuMessagesClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_messages->Show();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuPreferencesClick( TObject *Sender )\r
+{\r
+ CreatePreferences( "main" );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::MenuAboutClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_about = new TAboutDlg( this );\r
+ p_intfGlobal->p_sys->p_about->ShowModal();\r
+ delete p_intfGlobal->p_sys->p_about;\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Toolbar callbacks\r
+ ****************************************************************************/\r
+void __fastcall TMainFrameDlg::ToolButtonFileClick( TObject *Sender )\r
+{\r
+ MenuOpenFileClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonDiscClick( TObject *Sender )\r
+{\r
+ MenuOpenDiscClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonNetClick( TObject *Sender )\r
+{\r
+ MenuNetworkStreamClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonPlaylistClick( TObject *Sender )\r
+{\r
+ MenuPlaylistClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonBackClick( TObject *Sender )\r
+{\r
+ ControlBack( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonStopClick( TObject *Sender )\r
+{\r
+ ControlStop( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonPlayClick( TObject *Sender )\r
+{\r
+ ControlPlay( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonPauseClick( TObject *Sender )\r
+{\r
+ ControlPause( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonSlowClick( TObject *Sender )\r
+{\r
+ ControlSlow( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonFastClick( TObject *Sender )\r
+{\r
+ ControlFast( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonPrevClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_playwin->Previous();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonNextClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_playwin->Next();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ToolButtonEjectClick( TObject *Sender )\r
+{\r
+ AnsiString Device = "";\r
+ char * psz_current;\r
+ playlist_t * p_playlist;\r
+\r
+ p_playlist = (playlist_t *)vlc_object_find( p_intfGlobal,\r
+ VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ /*\r
+ * Get the active input\r
+ * Determine whether we can eject a media, ie it's a VCD or DVD\r
+ * If it's neither a VCD nor a DVD, then return\r
+ */\r
+\r
+ vlc_mutex_lock( &p_playlist->object_lock );\r
+ psz_current = p_playlist->pp_items[ p_playlist->i_index ]->psz_name;\r
+\r
+ if( psz_current != NULL )\r
+ {\r
+ if( strncmp( psz_current, "dvd", 3 )\r
+ || strncmp( psz_current, "vcd", 3 ) )\r
+ {\r
+ /* Determine the device name by omitting the first 4 characters\r
+ * and keeping 3 characters */\r
+ Device = strdup( ( psz_current + 4 ) );\r
+ Device = Device.SubString( 1, 2 );\r
+ }\r
+ }\r
+\r
+ vlc_mutex_unlock( &p_playlist->object_lock );\r
+ vlc_object_release( p_playlist );\r
+\r
+ if( Device == "" )\r
+ {\r
+ return;\r
+ }\r
+\r
+ /* If there's a stream playing, we aren't allowed to eject ! */\r
+ if( p_intfGlobal->p_sys->p_input == NULL )\r
+ {\r
+ msg_Dbg( p_intfGlobal, "ejecting %s", Device.c_str() );\r
+\r
+ intf_Eject( p_intfGlobal, Device.c_str() );\r
+ }\r
+}\r
+//--------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Popup callbacks\r
+ ****************************************************************************/\r
+void __fastcall TMainFrameDlg::PopupCloseClick( TObject *Sender )\r
+{\r
+ /* We do nothing, we just need a click on a menu item\r
+ * to close the popup. Don't ask me why... */\r
+ return;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupPlayClick( TObject *Sender )\r
+{\r
+ ToolButtonPlayClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupPauseClick( TObject *Sender )\r
+{\r
+ ToolButtonPauseClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupStopClick( TObject *Sender )\r
+{\r
+ ToolButtonStopClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupBackClick( TObject *Sender )\r
+{\r
+ ToolButtonBackClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupSlowClick( TObject *Sender )\r
+{\r
+ ToolButtonSlowClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupFastClick( TObject *Sender )\r
+{\r
+ ToolButtonFastClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupToggleInterfaceClick( TObject *Sender )\r
+{\r
+ this->BringToFront();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupFullscreenClick( TObject *Sender )\r
+{\r
+ MenuFullscreenClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupNextClick( TObject *Sender )\r
+{\r
+ ToolButtonNextClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupPrevClick( TObject *Sender )\r
+{\r
+ ToolButtonPrevClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupJumpClick( TObject *Sender )\r
+{\r
+ // TODO\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupPlaylistClick( TObject *Sender )\r
+{\r
+ MenuPlaylistClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupPreferencesClick( TObject *Sender )\r
+{\r
+ MenuPreferencesClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupExitClick( TObject *Sender )\r
+{\r
+ MenuExitClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupOpenFileClick( TObject *Sender )\r
+{\r
+ MenuOpenFileClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupOpenDiscClick( TObject *Sender )\r
+{\r
+ MenuOpenDiscClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::PopupNetworkStreamClick( TObject *Sender )\r
+{\r
+ MenuNetworkStreamClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Callbacks for DVD/VCD navigation\r
+ ****************************************************************************/\r
+void __fastcall TMainFrameDlg::ButtonTitlePrevClick( TObject *Sender )\r
+{\r
+ intf_thread_t * p_intf;\r
+ input_area_t * p_area;\r
+ int i_id;\r
+\r
+ p_intf = p_intfGlobal;\r
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;\r
+\r
+ /* Disallow area 0 since it is used for video_ts.vob */\r
+ if( i_id > 0 )\r
+ {\r
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];\r
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );\r
+\r
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );\r
+\r
+ p_intf->p_sys->b_title_update = 1;\r
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ SetupMenus( p_intf );\r
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ButtonTitleNextClick( TObject *Sender )\r
+{\r
+ intf_thread_t * p_intf;\r
+ input_area_t * p_area;\r
+ int i_id;\r
+\r
+ p_intf = p_intfGlobal;\r
+ i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;\r
+\r
+ if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )\r
+ {\r
+ p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id]; \r
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );\r
+ \r
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );\r
+\r
+ p_intf->p_sys->b_title_update = 1;\r
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ SetupMenus( p_intf );\r
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ButtonChapterPrevClick( TObject *Sender )\r
+{\r
+ intf_thread_t * p_intf = p_intfGlobal;\r
+ input_area_t * p_area;\r
+\r
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;\r
+\r
+ if( p_area->i_part > 0 )\r
+ {\r
+ p_area->i_part--;\r
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );\r
+\r
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );\r
+\r
+ p_intf->p_sys->b_chapter_update = 1;\r
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ SetupMenus( p_intf );\r
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMainFrameDlg::ButtonChapterNextClick( TObject *Sender )\r
+{\r
+ intf_thread_t * p_intf = p_intfGlobal;\r
+ input_area_t * p_area;\r
+\r
+ p_area = p_intf->p_sys->p_input->stream.p_selected_area;\r
+ \r
+ if( p_area->i_part < p_area->i_part_nb )\r
+ {\r
+ p_area->i_part++;\r
+ input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );\r
+\r
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );\r
+\r
+ p_intf->p_sys->b_chapter_update = 1;\r
+ vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ SetupMenus( p_intf );\r
+ vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Callback for the 'go!' button\r
+ ****************************************************************************/\r
+void __fastcall TMainFrameDlg::ButtonGoClick( TObject *Sender )\r
+{\r
+ intf_thread_t *p_intf = p_intfGlobal;\r
+ int i_channel;\r
+\r
+ i_channel = SpinEditChannel->Value;\r
+ msg_Dbg( p_intf, "joining channel %d", i_channel );\r
+\r
+ vlc_mutex_lock( &p_intf->change_lock );\r
+ network_ChannelJoin( p_intf, i_channel );\r
+ vlc_mutex_unlock( &p_intf->change_lock );\r
+\r
+// input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * ModeManage: actualise the aspect of the interface whenever the input\r
+ * changes.\r
+ *****************************************************************************\r
+ * The lock has to be taken before you call the function.\r
+ *****************************************************************************/\r
+void __fastcall TMainFrameDlg::ModeManage()\r
+{\r
+ intf_thread_t * p_intf = p_intfGlobal;\r
+ TGroupBox * ActiveGB;\r
+ int i_Height;\r
+ bool b_control;\r
+\r
+ /* hide all boxes */\r
+ GroupBoxFile->Visible = false;\r
+ GroupBoxNetwork->Visible = false;\r
+ GroupBoxDisc->Visible = false;\r
+\r
+ /* hide slider */\r
+ GroupBoxSlider->Hide();\r
+\r
+ /* controls unavailable */\r
+ b_control = 0;\r
+\r
+ /* show the box related to current input mode */\r
+ if( p_intf->p_sys->p_input != NULL )\r
+ {\r
+ switch( p_intf->p_sys->p_input->stream.i_method & 0xf0 )\r
+ { \r
+ case INPUT_METHOD_FILE:\r
+ GroupBoxFile->Visible = true;\r
+ ActiveGB = GroupBoxFile;\r
+ LabelFileName->Caption = p_intf->p_sys->p_input->psz_source;\r
+ break;\r
+ case INPUT_METHOD_DISC:\r
+ GroupBoxDisc->Visible = true;\r
+ ActiveGB = GroupBoxDisc;\r
+ break;\r
+ case INPUT_METHOD_NETWORK:\r
+ GroupBoxNetwork->Visible = true;\r
+ ActiveGB = GroupBoxNetwork;\r
+ LabelServer->Caption = p_intf->p_sys->p_input->psz_source;\r
+ if( config_GetInt( p_intf, "network-channel" ) )\r
+ {\r
+ LabelChannel->Visible = true;\r
+ }\r
+ else\r
+ {\r
+ LabelChannel->Visible = false;\r
+ }\r
+ break;\r
+ default:\r
+ msg_Warn( p_intf, "cannot determine input method" );\r
+ GroupBoxFile->Visible = true;\r
+ ActiveGB = GroupBoxFile;\r
+ LabelFileName->Caption = p_intf->p_sys->p_input->psz_source;\r
+ break;\r
+ }\r
+\r
+ i_Height = StatusBar->Height + ActiveGB->Height + ToolBar->Height + 54;\r
+\r
+ /* initialize and show slider for seekable streams */\r
+ if( p_intf->p_sys->p_input->stream.b_seekable )\r
+ {\r
+ TrackBar->Position = p_intf->p_sys->OldValue = 0;\r
+ GroupBoxSlider->Show();\r
+ i_Height += GroupBoxSlider->Height;\r
+ }\r
+\r
+ /* control buttons for free pace streams */\r
+ b_control = p_intf->p_sys->p_input->stream.b_pace_control;\r
+\r
+ /* get ready for menu regeneration */\r
+ p_intf->p_sys->b_program_update = 1;\r
+ p_intf->p_sys->b_title_update = 1;\r
+ p_intf->p_sys->b_chapter_update = 1;\r
+ p_intf->p_sys->b_audio_update = 1;\r
+ p_intf->p_sys->b_spu_update = 1;\r
+ p_intf->p_sys->i_part = 0;\r
+\r
+ p_intf->p_sys->p_input->stream.b_changed = 0;\r
+ msg_Dbg( p_intf, "stream has changed, refreshing interface" );\r
+ }\r
+ else\r
+ {\r
+ i_Height = StatusBar->Height + ToolBar->Height + 47;\r
+\r
+ if( config_GetInt( p_intf, "network-channel" ) )\r
+ {\r
+ GroupBoxNetwork->Visible = true;\r
+ LabelChannel->Visible = true;\r
+ i_Height += GroupBoxNetwork->Height + 7;\r
+ }\r
+ else\r
+ {\r
+ /* add space between tolbar and statusbar when\r
+ * nothing is displayed; isn't it nicer ? :) */ \r
+ i_Height += 17;\r
+ }\r
+\r
+ /* unsensitize menus */\r
+ MenuProgram->Enabled = false;\r
+ MenuTitle->Enabled = false;\r
+ MenuChapter->Enabled = false;\r
+ MenuAudio->Enabled = false;\r
+ MenuSubtitles->Enabled = false;\r
+ PopupNavigation->Enabled = false;\r
+ PopupAudio->Enabled = false;\r
+ PopupSubtitles->Enabled = false;\r
+ }\r
+\r
+ /* resize main window */\r
+ this->Height = i_Height;\r
+\r
+ /* set control items */\r
+ ToolButtonBack->Enabled = false;\r
+ ToolButtonStop->Enabled = true;\r
+ ToolButtonEject->Enabled = !b_control;\r
+ ToolButtonPause->Enabled = b_control;\r
+ ToolButtonSlow->Enabled = b_control;\r
+ ToolButtonFast->Enabled = b_control;\r
+ PopupBack->Enabled = false;\r
+ PopupPause->Enabled = b_control;\r
+ PopupSlow->Enabled = b_control;\r
+ PopupFast->Enabled = b_control;\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * CreateConfig: create a configuration dialog and save it for further use\r
+ *****************************************************************************\r
+ * Check if the dialog box is already opened, if so this will save us\r
+ * quite a bit of work. (the interface will be destroyed when you actually\r
+ * close the main window, but remember that it is only hidden if you\r
+ * clicked on the action buttons). This trick also allows us not to\r
+ * duplicate identical dialog windows.\r
+ *****************************************************************************/\r
+void __fastcall TMainFrameDlg::CreatePreferences( AnsiString Name )\r
+{\r
+ TPreferencesDlg *Preferences;\r
+ int i_index, i_pos;\r
+\r
+ i_index = StringListPref->IndexOf( Name );\r
+ if( i_index != -1 )\r
+ {\r
+ /* config dialog already exists */\r
+ Preferences = (TPreferencesDlg *)StringListPref->Objects[i_index];\r
+ }\r
+ else\r
+ {\r
+ /* create the config dialog */\r
+ Preferences = new TPreferencesDlg( this );\r
+ Preferences->CreateConfigDialog( Name.c_str() );\r
+\r
+ /* save it */\r
+ i_pos = StringListPref->Add( Name );\r
+ StringListPref->Objects[i_pos] = Preferences;\r
+ }\r
+\r
+ /* display the dialog */\r
+ Preferences->Show();\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
--- /dev/null
+object MainFrameDlg: TMainFrameDlg\r
+ Left = 314\r
+ Top = 198\r
+ Width = 541\r
+ Height = 306\r
+ BorderIcons = [biSystemMenu, biMinimize]\r
+ Caption = 'VideoLAN Client (win32 interface)'\r
+ Color = clBtnFace\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clWindowText\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ Icon.Data = {\r
+ 0000010001003030000001000800A80E00001600000028000000300000006000\r
+ 00000100080000000000800A0000000000000000000000010000000000000402\r
+ 04002486D4009CC2E4007CA6C400E4E2E40004528C003CA2F4001C82DC0054B2\r
+ FC003C8EDC00B4CADC00046EC4001C92F40034363400D4D6D400FFFFFF006CAA\r
+ E4006CB2F4000476DC0044AAFC009CD2FC00A4B6C4001C6EB4001C9AFC00548A\r
+ B4007CC2FC000486F400B4CAE4001416140034A2FC00CCD2D400147ACC006CBA\r
+ FC006CA6DC00CCE2F400045EA400349EFC00044A7400FCFEFC0064BAFC005C9E\r
+ DC00C4CED4000C92FC00BCD6E400F4F2F4007C9AB4008CCAFC0044A2FC007CBA\r
+ FC00CCEAFC001C5E8C000482EC0064B6FC000472D400047EEC002C9EFC00048E\r
+ FC001C1E1C001C96FC00CCDAE4000C0A0C00348ED400A4C6E4009CAEBC00248A\r
+ E4005CB6FC003492E400BCCEDC003C3E3C00047EE4004CAEFC00ACBECC00447A\r
+ A400249EFC008CC6FC003CA6FC00247ECC0074BEFC007CAEDC001C5674001496\r
+ FC00ECF6FC00649ACC00DCEEFC00040604002C8AD400A4C2E40084AAC400145A\r
+ 8C0044A2F4001C86DC005CB2FC003C92DC00BCCADC000472CC003C3A3C00E4F2\r
+ FC0054AEFC0074B6F400047ADC004CAAFC009CB6CC00249AFC006C92BC0084C6\r
+ FC00048AFC001C1A1C003CA2FC00CCD2DC001C7ECC0074BAFC0074AADC00D4E6\r
+ F4000462B4000C4E74004C9EE400CCCED4001492FC00C4DAE40094CAFC0044A6\r
+ FC007CBEFC002C628C000476D4000C8EFC0024222400D4DAE4003476B400F4F6\r
+ FC006C9ECC00E4EEFC0000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000008383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 838383831C1C1C1C838383838383838383838383838383838383838383838383\r
+ 838383838383838383838383838383831C1C1C1C5E12635E1C1C1C8383838383\r
+ 838383838383838383838383838383838383838383838383838383831C1C1C1C\r
+ 5E6312456969691A455E1C1C1C83838383838383838383838383838383838383\r
+ 8383838383838383831C1C1C5E127B5E7B63636363636345691A45125E1C1C83\r
+ 8383838383838383838383838383838383838383831C1C1C1C5E126363635E05\r
+ 25252525252572585E6345691A455E1C1C838383838383838383838383838383\r
+ 8383831C1C5E1263451A697B05250569696969692A17244B584F7A5E69696963\r
+ 5E1C83838383838383838383838383838383831C711A69694525252369696969\r
+ 3869383875661D785B344D4825694569695E1C1C838383838383838383838383\r
+ 838383831C5E45121C45696969383869386938383A376B645B206E795B250045\r
+ 691A711C83838383838383838383838383838383831C1C231C63696938696938\r
+ 6938692A17374B46412079796E520012455E1C83838383838383838383838383\r
+ 838383838383831C1C1238386938386938693875661D1361344D7919101C230B\r
+ 1C1C838383838383838383838383838383838383838383831C5E696938693869\r
+ 38693850666B135B20797979211C1C1C83838383838383838383838383838383\r
+ 83838383838383831C1C45693869383A17662413465B34342079796E521C8383\r
+ 838383838383838383838383838383838383838383838383831C633A663A0602\r
+ 0A2B22535382312E684A19101C83838383838383838383838383838383838383\r
+ 8383838383838383831C01020A0A0A1E1E042C26262626606053146F54838383\r
+ 838383838383838383838383838383838383838383838383831C67290E1E0E0E\r
+ 0E042C2626262626262682656A83838383838383838383838383838383838383\r
+ 8383838383838383831C0D3F0E0E0E0E0E042C262626262626267E4483838383\r
+ 83838383838383838383838383838383838383838383838383836A3F0E0E0E6C\r
+ 5D2B22538260602626266C7D8383838383838383838383838383838383838383\r
+ 838383838383838383836A3F6C5D1B025924645B274D77536080477D83838383\r
+ 83838383838383838383838383838383838383838383838383831C0302590C3A\r
+ 753A376B465B6E4A141B0D838383838383838383838383838383838383838383\r
+ 83838383838383838383541F0C3838382A661D4B61344D7930813C8383838383\r
+ 8383838383838383838383838383838383838383838383838383831C45386938\r
+ 75661D1308344D7910101C838383838383838383838383838383838383838383\r
+ 83838383838383838383831C126938383A376B645B207979211C838383838383\r
+ 8383838383838383838383838383838383838383838383838383831C6338692A\r
+ 17374B463420796E521C83838383838383838383838383838383838383838383\r
+ 83838383838383838383831C5E6938662F615B4D19681910101C838383838383\r
+ 838383838383838383838383838383838383838383838383838383835407593E\r
+ 5D2B70608253144E1C8383838383838383838383838383838383838383838383\r
+ 8383838383838383838383831C030A1E0E042C26262682656A83838383838383\r
+ 838383838383838383838383838383838383838383838383838383836A3F0E0E\r
+ 0E042C2626267E446A8383838383838383838383838383838383838383838383\r
+ 838383838383838383838383392D740E0E042C2626266C7D8383838383838383\r
+ 838383838383838383838383838383838383838383838383838383831C0D156C\r
+ 433B70606080477D838383838383838383838383838383838383838383838383\r
+ 838383838383838383838383831C573E1134794A141B5F6A8383838383838383\r
+ 83838383838383838383838383838383838383838383838383838383831C3D78\r
+ 6461344D796F1C83838383838383838383838383838383838383838383838383\r
+ 838383838383838383838383831C4C24645B347930521C838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383831C42\r
+ 465B2079101C8383838383838383838383838383838383838383838383838383\r
+ 83838383838383838383838383831C0946344D79211C83838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383831C3D\r
+ 73731062521C8383838383838383838383838383838383838383838383838383\r
+ 83838383838383838383838383831C7F0000001C1C8383838383838383838383\r
+ 838383838383838383838383838383838383838383838383838383838383831C\r
+ 0B074C4C1C838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383831C0B0701161C8383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 1C1C1C1C83838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 8383838383838383838383838383838383838383838383838383838383838383\r
+ 838383838383838383838383838383838383838383838383838383838383FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFF\r
+ FFFFFFFF0000FFFFFC3FFFFF0000FFFFC007FFFF0000FFFC0001FFFF0000FFE0\r
+ 00007FFF0000FE0000001FFF0000F80000000FFF0000F800000003FF0000FC00\r
+ 000003FF0000FE00000007FF0000FF8000000FFF0000FFC000003FFF0000FFC0\r
+ 0000FFFF0000FFE00001FFFF0000FFE00001FFFF0000FFE00001FFFF0000FFE0\r
+ 0003FFFF0000FFF00003FFFF0000FFF00003FFFF0000FFF00007FFFF0000FFF0\r
+ 0007FFFF0000FFF80007FFFF0000FFF8000FFFFF0000FFF8000FFFFF0000FFF8\r
+ 000FFFFF0000FFFC001FFFFF0000FFFC001FFFFF0000FFFC001FFFFF0000FFFC\r
+ 003FFFFF0000FFFC003FFFFF0000FFFE003FFFFF0000FFFE007FFFFF0000FFFE\r
+ 007FFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF\r
+ 01FFFFFF0000FFFF81FFFFFF0000FFFF81FFFFFF0000FFFFC3FFFFFF0000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000}\r
+ Menu = MainMenu1\r
+ OldCreateOrder = False\r
+ PopupMenu = PopupMenuMain\r
+ ShowHint = True\r
+ OnClose = FormClose\r
+ PixelsPerInch = 96\r
+ TextHeight = 13\r
+ object ToolBar: TToolBar\r
+ Left = 0\r
+ Top = 0\r
+ Width = 533\r
+ Height = 50\r
+ ButtonHeight = 46\r
+ ButtonWidth = 39\r
+ Caption = 'ToolBar'\r
+ EdgeBorders = [ebTop, ebBottom]\r
+ Flat = True\r
+ Images = ImageListToolbar\r
+ ShowCaptions = True\r
+ TabOrder = 0\r
+ object ToolButtonFile: TToolButton\r
+ Left = 0\r
+ Top = 0\r
+ Hint = 'Open a file'\r
+ Caption = 'File'\r
+ ImageIndex = 0\r
+ OnClick = ToolButtonFileClick\r
+ end\r
+ object ToolButtonDisc: TToolButton\r
+ Left = 39\r
+ Top = 0\r
+ Hint = 'Open a DVD or VCD'\r
+ Caption = 'Disc'\r
+ ImageIndex = 1\r
+ OnClick = ToolButtonDiscClick\r
+ end\r
+ object ToolButtonNet: TToolButton\r
+ Left = 78\r
+ Top = 0\r
+ Hint = 'Open a network stream'\r
+ Caption = 'Net'\r
+ ImageIndex = 2\r
+ OnClick = ToolButtonNetClick\r
+ end\r
+ object ToolButtonSep1: TToolButton\r
+ Left = 117\r
+ Top = 0\r
+ Width = 8\r
+ Caption = 'ToolButtonSep1'\r
+ ImageIndex = 3\r
+ Style = tbsSeparator\r
+ end\r
+ object ToolButtonBack: TToolButton\r
+ Left = 125\r
+ Top = 0\r
+ Caption = 'Back'\r
+ Enabled = False\r
+ ImageIndex = 3\r
+ OnClick = ToolButtonBackClick\r
+ end\r
+ object ToolButtonPlay: TToolButton\r
+ Left = 164\r
+ Top = 0\r
+ Hint = 'Play stream'\r
+ Caption = 'Play'\r
+ ImageIndex = 5\r
+ OnClick = ToolButtonPlayClick\r
+ end\r
+ object ToolButtonPause: TToolButton\r
+ Left = 203\r
+ Top = 0\r
+ Hint = 'Pause stream'\r
+ Caption = 'Pause'\r
+ Enabled = False\r
+ ImageIndex = 6\r
+ OnClick = ToolButtonPauseClick\r
+ end\r
+ object ToolButtonStop: TToolButton\r
+ Left = 242\r
+ Top = 0\r
+ Hint = 'Stop stream'\r
+ Caption = 'Stop'\r
+ Enabled = False\r
+ ImageIndex = 4\r
+ OnClick = ToolButtonStopClick\r
+ end\r
+ object ToolButtonEject: TToolButton\r
+ Left = 281\r
+ Top = 0\r
+ Hint = 'Eject disc'\r
+ Caption = 'Eject'\r
+ Enabled = False\r
+ ImageIndex = 7\r
+ OnClick = ToolButtonEjectClick\r
+ end\r
+ object ToolButton1: TToolButton\r
+ Left = 320\r
+ Top = 0\r
+ Width = 8\r
+ Caption = 'ToolButton1'\r
+ ImageIndex = 13\r
+ Style = tbsSeparator\r
+ end\r
+ object ToolButtonSlow: TToolButton\r
+ Left = 328\r
+ Top = 0\r
+ Hint = 'Play slower'\r
+ Caption = 'Slow'\r
+ Enabled = False\r
+ ImageIndex = 8\r
+ OnClick = ToolButtonSlowClick\r
+ end\r
+ object ToolButtonFast: TToolButton\r
+ Left = 367\r
+ Top = 0\r
+ Hint = 'Play faster'\r
+ Caption = 'Fast'\r
+ Enabled = False\r
+ ImageIndex = 9\r
+ OnClick = ToolButtonFastClick\r
+ end\r
+ object ToolButtonSep2: TToolButton\r
+ Left = 406\r
+ Top = 0\r
+ Width = 8\r
+ Caption = 'ToolButtonSep2'\r
+ ImageIndex = 9\r
+ Style = tbsSeparator\r
+ end\r
+ object ToolButtonPlaylist: TToolButton\r
+ Left = 414\r
+ Top = 0\r
+ Hint = 'Open playlist'\r
+ Caption = 'Playlist'\r
+ ImageIndex = 10\r
+ Style = tbsCheck\r
+ OnClick = ToolButtonPlaylistClick\r
+ end\r
+ object ToolButtonPrev: TToolButton\r
+ Left = 453\r
+ Top = 0\r
+ Hint = 'Previous file'\r
+ Caption = 'Prev'\r
+ ImageIndex = 11\r
+ OnClick = ToolButtonPrevClick\r
+ end\r
+ object ToolButtonNext: TToolButton\r
+ Left = 492\r
+ Top = 0\r
+ Hint = 'Next file'\r
+ Caption = 'Next'\r
+ ImageIndex = 12\r
+ OnClick = ToolButtonNextClick\r
+ end\r
+ end\r
+ object StatusBar: TStatusBar\r
+ Left = 0\r
+ Top = 241\r
+ Width = 533\r
+ Height = 19\r
+ Panels = <>\r
+ ParentShowHint = False\r
+ ShowHint = False\r
+ SimplePanel = True\r
+ end\r
+ object GroupBoxFile: TGroupBox\r
+ Left = 0\r
+ Top = 90\r
+ Width = 533\r
+ Height = 32\r
+ Align = alTop\r
+ TabOrder = 2\r
+ Visible = False\r
+ object LabelFileName: TLabel\r
+ Left = 2\r
+ Top = 15\r
+ Width = 529\r
+ Height = 15\r
+ Align = alClient\r
+ Alignment = taCenter\r
+ Caption = 'File read'\r
+ end\r
+ end\r
+ object GroupBoxNetwork: TGroupBox\r
+ Left = 0\r
+ Top = 154\r
+ Width = 533\r
+ Height = 40\r
+ Align = alTop\r
+ TabOrder = 3\r
+ Visible = False\r
+ object LabelChannel: TLabel\r
+ Left = 288\r
+ Top = 16\r
+ Width = 42\r
+ Height = 13\r
+ Caption = 'Channel:'\r
+ end\r
+ object LabelServer: TLabel\r
+ Left = 64\r
+ Top = 16\r
+ Width = 49\r
+ Height = 13\r
+ Caption = 'No server!'\r
+ end\r
+ object ButtonGo: TButton\r
+ Left = 384\r
+ Top = 10\r
+ Width = 25\r
+ Height = 25\r
+ Caption = 'Go!'\r
+ TabOrder = 0\r
+ OnClick = ButtonGoClick\r
+ end\r
+ object SpinEditChannel: TCSpinEdit\r
+ Left = 336\r
+ Top = 11\r
+ Width = 41\r
+ Height = 22\r
+ TabStop = True\r
+ MaxValue = 99\r
+ ParentColor = False\r
+ TabOrder = 1\r
+ end\r
+ end\r
+ object GroupBoxDisc: TGroupBox\r
+ Left = 0\r
+ Top = 122\r
+ Width = 533\r
+ Height = 32\r
+ Align = alTop\r
+ TabOrder = 4\r
+ Visible = False\r
+ object LabelDisc: TLabel\r
+ Left = 32\r
+ Top = 11\r
+ Width = 21\r
+ Height = 13\r
+ Caption = 'Disc'\r
+ end\r
+ object LabelTitle: TLabel\r
+ Left = 96\r
+ Top = 11\r
+ Width = 23\r
+ Height = 13\r
+ Caption = 'Title:'\r
+ end\r
+ object LabelChapter: TLabel\r
+ Left = 296\r
+ Top = 11\r
+ Width = 40\r
+ Height = 13\r
+ Caption = 'Chapter:'\r
+ end\r
+ object LabelTitleCurrent: TLabel\r
+ Left = 126\r
+ Top = 11\r
+ Width = 9\r
+ Height = 13\r
+ Caption = '---'\r
+ end\r
+ object LabelChapterCurrent: TLabel\r
+ Left = 342\r
+ Top = 11\r
+ Width = 9\r
+ Height = 13\r
+ Caption = '---'\r
+ end\r
+ object ButtonTitlePrev: TButton\r
+ Left = 152\r
+ Top = 8\r
+ Width = 33\r
+ Height = 19\r
+ Hint = 'Jump to previous title'\r
+ Caption = 'Prev'\r
+ TabOrder = 0\r
+ OnClick = ButtonTitlePrevClick\r
+ end\r
+ object ButtonTitleNext: TButton\r
+ Left = 184\r
+ Top = 8\r
+ Width = 33\r
+ Height = 19\r
+ Hint = 'Jump to next title'\r
+ Caption = 'Next'\r
+ TabOrder = 1\r
+ OnClick = ButtonTitleNextClick\r
+ end\r
+ object ButtonChapterPrev: TButton\r
+ Left = 368\r
+ Top = 8\r
+ Width = 33\r
+ Height = 19\r
+ Hint = 'Jump to previous chapter'\r
+ Caption = 'Prev'\r
+ TabOrder = 2\r
+ OnClick = ButtonChapterPrevClick\r
+ end\r
+ object ButtonChapterNext: TButton\r
+ Left = 400\r
+ Top = 8\r
+ Width = 33\r
+ Height = 19\r
+ Hint = 'Jump to next chapter'\r
+ Caption = 'Next'\r
+ TabOrder = 3\r
+ OnClick = ButtonChapterNextClick\r
+ end\r
+ end\r
+ object GroupBoxSlider: TGroupBox\r
+ Left = 0\r
+ Top = 50\r
+ Width = 533\r
+ Height = 40\r
+ Align = alTop\r
+ Caption = '0:00:00'\r
+ TabOrder = 5\r
+ Visible = False\r
+ object TrackBar: TTrackBar\r
+ Left = 2\r
+ Top = 15\r
+ Width = 529\r
+ Height = 21\r
+ Align = alTop\r
+ Orientation = trHorizontal\r
+ Frequency = 1\r
+ Position = 0\r
+ SelEnd = 0\r
+ SelStart = 0\r
+ TabOrder = 0\r
+ TickMarks = tmBottomRight\r
+ TickStyle = tsNone\r
+ OnChange = TrackBarChange\r
+ end\r
+ end\r
+ object MainMenu1: TMainMenu\r
+ Left = 40\r
+ Top = 208\r
+ object MenuFile: TMenuItem\r
+ Caption = '&File'\r
+ object MenuOpenFile: TMenuItem\r
+ Caption = '&Open file...'\r
+ Hint = 'Open a file'\r
+ ShortCut = 114\r
+ OnClick = MenuOpenFileClick\r
+ end\r
+ object MenuOpenDisc: TMenuItem\r
+ Caption = 'Open &disc...'\r
+ Hint = 'Open a DVD or VCD'\r
+ ShortCut = 115\r
+ OnClick = MenuOpenDiscClick\r
+ end\r
+ object MenuNetworkStream: TMenuItem\r
+ Caption = '&Network stream...'\r
+ Hint = 'Select a network stream'\r
+ ShortCut = 116\r
+ OnClick = MenuNetworkStreamClick\r
+ end\r
+ object N8: TMenuItem\r
+ Caption = '-'\r
+ Visible = False\r
+ end\r
+ object MenuEjectDisc: TMenuItem\r
+ Caption = '&Eject Disc'\r
+ Hint = 'Eject disc'\r
+ Visible = False\r
+ OnClick = ToolButtonEjectClick\r
+ end\r
+ object N1: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object MenuExit: TMenuItem\r
+ Caption = 'E&xit'\r
+ Hint = 'Exit the program'\r
+ ShortCut = 16465\r
+ OnClick = MenuExitClick\r
+ end\r
+ end\r
+ object MenuView: TMenuItem\r
+ Caption = '&View'\r
+ object MenuHideinterface: TMenuItem\r
+ Caption = '&Hide interface'\r
+ Hint = 'Hide the main interface window'\r
+ OnClick = MenuHideinterfaceClick\r
+ end\r
+ object MenuFullscreen: TMenuItem\r
+ Caption = '&Fullscreen'\r
+ Hint = 'Toggle fullscreen'\r
+ OnClick = MenuFullscreenClick\r
+ end\r
+ object N2: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object MenuProgram: TMenuItem\r
+ Caption = 'Progr&am'\r
+ Enabled = False\r
+ Hint = 'Select program'\r
+ end\r
+ object MenuTitle: TMenuItem\r
+ Caption = '&Title'\r
+ Enabled = False\r
+ Hint = 'Select title'\r
+ end\r
+ object MenuChapter: TMenuItem\r
+ Caption = '&Chapter'\r
+ Enabled = False\r
+ Hint = 'Select chapter'\r
+ end\r
+ object MenuAngle: TMenuItem\r
+ Caption = 'An&gle'\r
+ Enabled = False\r
+ Hint = 'Select angle'\r
+ end\r
+ object N3: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object MenuPlaylist: TMenuItem\r
+ Caption = '&Playlist...'\r
+ Hint = 'Open the playlist window'\r
+ OnClick = MenuPlaylistClick\r
+ end\r
+ object MenuModules: TMenuItem\r
+ Caption = '&Modules...'\r
+ Enabled = False\r
+ Hint = 'Open the modules window'\r
+ end\r
+ object MenuMessages: TMenuItem\r
+ Caption = 'Me&ssages...'\r
+ Hint = 'Open the messages window'\r
+ OnClick = MenuMessagesClick\r
+ end\r
+ end\r
+ object MenuSettings: TMenuItem\r
+ Caption = '&Settings'\r
+ object MenuAudio: TMenuItem\r
+ Caption = '&Audio'\r
+ Enabled = False\r
+ Hint = 'Select audio language'\r
+ end\r
+ object MenuSubtitles: TMenuItem\r
+ Caption = '&Subtitles'\r
+ Enabled = False\r
+ Hint = 'Select subtitles language'\r
+ end\r
+ object N4: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object MenuPreferences: TMenuItem\r
+ Caption = '&Preferences...'\r
+ Hint = 'Configure the application'\r
+ OnClick = MenuPreferencesClick\r
+ end\r
+ end\r
+ object MenuHelp: TMenuItem\r
+ Caption = '&Help'\r
+ object MenuAbout: TMenuItem\r
+ Caption = '&About...'\r
+ Hint = 'About this application'\r
+ OnClick = MenuAboutClick\r
+ end\r
+ end\r
+ end\r
+ object OpenDialog1: TOpenDialog\r
+ Filter = 'All Files (*.*)|*.*'\r
+ Left = 8\r
+ Top = 208\r
+ end\r
+ object ImageListToolbar: TImageList\r
+ Height = 26\r
+ Width = 32\r
+ Left = 104\r
+ Top = 208\r
+ Bitmap = {\r
+ 494C01010D000E00040020001A00FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600\r
+ 00000000000036000000280000008000000068000000010020000000000000D0\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000034653F00000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000034653F0034653F000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000007AA9830054855D00325B\r
+ 3A00000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000007AA983007AA983000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000080AC88007AA983006B9A\r
+ 7400497C5300325B3A0000000000000000000000000000000000000000000000\r
+ 000000000000000000008CB896008CB896000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000090BB9D007AA983007AA9\r
+ 83007AA983006B9A7400497C530040704B000000000000000000000000000000\r
+ 0000000000000000000090BB9D008CB896000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000090BB9D007AA983007AA9\r
+ 83007AA983007AA983007AA983006B9A7400497C530040584400000000000000\r
+ 0000000000000000000090BB9D0090BB9D000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000090BB9D0080AC88007AA9\r
+ 830080AC88007AA983007AA9830076A47E007AA983006B9A740054855D00325B\r
+ 3A00000000000000000090BB9D0090BB9D000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000FCFDFC00EFF4F000EFF4\r
+ F000EFF4F000ECF2ED00D7E4D900D7E4D900D7E4D900D7E4D900EFF4F000ACC7\r
+ B1000000000000000000FCFDFC00FCFDFC000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000FCFDFC00EFF4F000EFF4\r
+ F000ECF2ED00ECF2ED00ECF2ED00E2EBE400EFF4F000C7DACB00181818000000\r
+ 00000000000000000000FCFDFC00FCFDFC000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000FCFDFC00FCFDFC00EFF4\r
+ F000EFF4F000ECF2ED00EFF4F000C7DACB000000000000000000000000000000\r
+ 00000000000000000000FCFDFC00FCFDFC000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000FCFDFC00EFF4F000ECF2\r
+ ED00EFF4F000C7DACB0000000000000000000000000000000000000000000000\r
+ 00000000000000000000FCFDFC00FCFDFC000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000FCFDFC00EFF4F000D7E4\r
+ D900000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000FCFDFC00FCFDFC000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E2EBE400000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000DFEAE100E2EBE4000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000084A8B40091B1BB009BB8C1009BB8\r
+ C10084A8B40084A8B40043555C00000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000006B63\r
+ C0003D359000000000000000000000000000463DA40000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000006986900091B1BB009BB8C1009BB8C10091B1\r
+ BB0084A8B40084A8B400546B7300000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00006158BC003D3590000000000000000000463DA40000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000004861490000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000546B730084A8B40084A8B4009BB8C1009BB8C1009BB8\r
+ C10084A8B40084A8B4006986900043555C000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000006158BC004E44B5004E44B5000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000005977\r
+ 5A0059775A0059775A0059775A0059775A006D926E0059775A00000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000698690009BB8C1009BB8C1009BB8C1009BB8C10091B1\r
+ BB0084A8B40084A8B40069869000546B73000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000004E44B5004E44B5000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000006D92\r
+ 6E006D926E006D926E006D926E006D926E008E9594006D926E00000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E00000000000546B730084A8B40091B1BB009BB8C1009BB8C10091B1BB009BB8\r
+ C10084A8B40084A8B40084A8B400698690000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000B3B5B500B3B5B500B3B5B500B3B5B5007A7A7A0000000000000000000000\r
+ 000000000000000000004E44B5006158BC003D35900000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000B2B5B500B2B5B500B2B5B500B2B5B5007A7A7A0000000000000000000000\r
+ 0000000000000000000000000000000000006D926E0000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E000000000006986900084A8B4009BB8C1009BB8C1009BB8C1009BB8C10091B1\r
+ BB0084A8B40084A8B40084A8B400698690003342460000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000003059370030593700000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000030593700000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000B3B5B500E5E8\r
+ E800D5D7D700FDFDFD00FDFDFD00E5E8E800D5D7D700ABB3B200939796000000\r
+ 0000000000004E44B50000000000000000006158BC00362F8100000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000B2B5B500E5E8\r
+ E800D5D7D700FDFDFD00FDFDFD00E5E8E800D5D7D700ABB3B200939796000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E0000000\r
+ 000069869000708F990091B1BB009BB8C1009BB8C1009BB8C10091B1BB009BB8\r
+ C10091B1BB0084A8B40084A8B40084A8B40043555C0000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000051885B0051885B00000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00003D73470063A76F0051885B00000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000B9C0BF00D5D7D700FDFD\r
+ FD00BCC4C200BCC4C200BCC4C200BCC4C200D5D7D700D5D7D700D5D7D700ABB3\r
+ B2000C0B1500443C9F000000000000000000000000004E44B500000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000B9C0BF00D5D7D700FDFD\r
+ FD00BCC4C200BCC4C200BCC4C200BCC4C200D5D7D700D5D7D700D5D7D700ABB3\r
+ B200000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000084A8B4000000000084A8B4009BB8C1009BB8C10091B1BB009BB8C10084A8\r
+ B40084A8B40084A8B40084A8B40084A8B400546B730000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000568C6000568C6000000000000000\r
+ 00000000000000000000000000000000000000000000000000003D734700447C\r
+ 4E00679A710079A98200568C6000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000ABB3B200D5D7D700E5E8E800ABB3\r
+ B200B9C0BF00B9C0BF00BCC4C200CCD4D200BCC4C200CCD4D200D5D7D700D5D7\r
+ D7004F4F4F000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000ABB3B200D5D7D700E5E8E800ABB3\r
+ B200B9C0BF00B9C0BF00BCC4C200CCD4D200BCC4C200CCD4D200D5D7D700D5D7\r
+ D700B2B5B5000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E0000000\r
+ 000084A8B400000000009BB8C1009BB8C1009BB8C10091B1BB0091B1BB0084A8\r
+ B40084A8B40084A8B40084A8B40084A8B400546B730000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000005C9267005C926700000000000000\r
+ 00000000000000000000000000000000000030593700447C4E00679A710079A9\r
+ 820073A47D0079A982005C926700000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000CCD4D200FDFDFD00A3ABA900ABB3\r
+ B200BCC4C200BCC4C200BCC4C200CCD4D200CCD4D200CCD4D200CCD4D200CCD4\r
+ D200D5D7D7000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000CCD4D200FDFDFD00A3ABA900ABB3\r
+ B200BCC4C200BCC4C200BCC4C200CCD4D200CCD4D200CCD4D200CCD4D200CCD4\r
+ D200D5D7D7000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E0000000\r
+ 0000698690000000000091B1BB0091B1BB006986900084A8B40084A8B4006986\r
+ 900084A8B40084A8B40084A8B40084A8B4006986900000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000005C9267005C926700000000000000\r
+ 000000000000000000004A6F5100447C4E00679A710079A9820079A9820079A9\r
+ 820079A9820079A982005C926700000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000B3B5B500D5D7D700BCC4C200A3ABA900B3B5\r
+ B500BCC4C200CCD4D200ABB3B200D5D7D700D5D7D700D5D7D700CCD4D200E5E8\r
+ E800D5D7D7008E95940000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000B2B5B500D5D7D700BCC4C200A3ABA900B2B5\r
+ B500BCC4C200CCD4D200ABB3B200D5D7D700D5D7D700D5D7D700CCD4D200E5E8\r
+ E800D5D7D7008E95940000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E0000000\r
+ 0000546B7300000000009BB8C100698690000000000084A8B400698690000000\r
+ 000084A8B400698690000000000069869000546B730000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000005C9267005C926700000000000000\r
+ 00003059370049815400679A710079A9820073A47D0079A9820079A9820079A9\r
+ 820079A9820079A98200679A7100000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000D5D7D700FDFDFD00A3ABA900A3ABA900B3B5\r
+ B500C3CBC9008E9594000000000093979600D5D7D700D5D7D700D5D7D700D5D7\r
+ D700D5D7D7009397960000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000D5D7D700FDFDFD00A3ABA900A3ABA900B2B5\r
+ B500C3CBC9008E9594000000000093979600D5D7D700D5D7D700D5D7D700D5D7\r
+ D700D5D7D7009397960000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000091B1BB00698690000000000084A8B4005A737A000000\r
+ 0000708F9900546B730000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000C3D7C600C3D7C600000000000000\r
+ 0000ACC7B100F8FAF800E4ECE500DAE6DC00DAE6DC00E4ECE500ECF2ED00ECF2\r
+ ED00ECF2ED00ECF2ED00C3D7C600000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000D5D7D700FDFDFD0093979600A3ABA900B3B5\r
+ B500C3CBC900000000000000000000000000CCD4D200CCD4D200CCD4D200CCD4\r
+ D200D5D7D7008E95940000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000D5D7D700FDFDFD0093979600A3ABA900B2B5\r
+ B500C3CBC900000000000000000000000000CCD4D200CCD4D200CCD4D200CCD4\r
+ D200D5D7D7008E95940000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E000E0E4E00000000000AAC3CA0069869000000000005A737A00334246000000\r
+ 000000000000000000008C9C9400E0E4E000E0E4E00000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000C3D7C600C3D7C600000000000000\r
+ 000000000000121B1200E4ECE500F8FAF800ECF2ED00E4ECE500ECF2ED00ECF2\r
+ ED00ECF2ED00ECF2ED00C3D7C600000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000D5D7D700FDFDFD0099A09F009BA3A100B3B5\r
+ B5000000000000000000C9D0CF000000000000000000C9D0CF00C3CBC900C9D0\r
+ CF00D5D7D7009397960000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000D5D7D700FDFDFD0099A09F009BA3A100B2B5\r
+ B5000000000000000000C9D0CF000000000000000000C9D0CF00C3CBC900C9D0\r
+ CF00D5D7D7008E95940000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E000E0E4E00000000000AAC3CA0069869000000000000000000000000000A3A5\r
+ A300E0E4E000E0E4E000E0E4E000E0E4E000E0E4E00000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000C3D7C600C3D7C600000000000000\r
+ 000000000000000000000000000000000000DAE6DC00F8FAF800F8FAF800ECF2\r
+ ED00ECF2ED00F8FAF800C3D7C600000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000B3B5B500D5D7D700ABB3B2009BA3A1000000\r
+ 000000000000BCC4C200C9D0CF00C3CBC9000000000000000000BCC4C200E5E8\r
+ E800D5D7D7008E95940000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000B2B5B500D5D7D700ABB3B2009BA3A1000000\r
+ 000000000000BCC4C200C9D0CF00C3CBC9000000000000000000BCC4C200E5E8\r
+ E800D5D7D7008E95940000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E000E0E4E00000000000B8CDD30069869000000000008C9C9400E0E4E000E0E4\r
+ E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4E00000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000C3D7C600C3D7C600000000000000\r
+ 0000000000000000000000000000000000000000000000000000E4ECE500F8FA\r
+ F800F8FAF800ECF2ED00C3D7C600000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000D5D7D700E5E8E800939796009BA3\r
+ A100ABB3B200B3B5B500B9C0BF00B9C0BF00C3CBC9000000000000000000C9D0\r
+ CF00D5D7D7000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000D5D7D700E5E8E800939796009BA3\r
+ A100ABB3B200B2B5B500B9C0BF00B9C0BF00C3CBC9000000000000000000C9D0\r
+ CF00D5D7D7000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000AAC3CA00698690000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000C3D7C600C3D7C600000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000E4ECE500F8FAF800C3D7C600000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000ABB3B200FDFDFD00CCD4D2009397\r
+ 960099A09F00A3ABA900A3ABA900ABB3B200B3B5B500B3B5B5000F111100D5D7\r
+ D700B3B5B5000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000ABB3B200FDFDFD00CCD4D2009397\r
+ 960099A09F00A3ABA900A3ABA900ABB3B200B2B5B500B2B5B5000F111100D5D7\r
+ D700B2B5B5000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E000E0E4E0000000000069869000546B7300000000008C9C9400E0E4E000E0E4\r
+ E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4E00000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000C3D7C600C3D7C600000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000C3D7C600000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000D5D7D700FDFDFD00E5E8\r
+ E800B3B5B5009BA3A1009BA3A100A3ABA900C3CBC900FDFDFD00D5D7D700D5D7\r
+ D700000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000D5D7D700FDFDFD00E5E8\r
+ E800B2B5B5009BA3A1009BA3A100A3ABA900C3CBC900FDFDFD00D5D7D700D5D7\r
+ D700000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E000E0E4E000E0E4E00000000000000000008C9C9400E0E4E000E0E4E000E0E4\r
+ E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4E00000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000D5D7D700FDFD\r
+ FD00FDFDFD00FDFDFD00FDFDFD00FDFDFD00FDFDFD00CCD4D200ABB3B2000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000D5D7D700FDFD\r
+ FD00FDFDFD00FDFDFD00FDFDFD00FDFDFD00FDFDFD00CCD4D200ABB3B2000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000E0E4E000E0E4E000E0E4\r
+ E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4\r
+ E000E0E4E000E0E4E000E0E4E000E0E4E000E0E4E00000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000D5D7D700FDFDFD00FDFDFD00D5D7D700ABB3B20000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000D5D7D700FDFDFD00FDFDFD00D5D7D700ABB3B20000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000060616000A0927000A0927000A0927000D0D31000D0D31000A0927000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000B4BEBD00B4BE\r
+ BD00BDC2BD00BDC2C500BDC2BD00BDC2BD006493750064937500649375006493\r
+ 75005A8568005A85680000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000060616000A09\r
+ 27006E6DA0008B89B8008B89B8007E7CB2006E6DA0004F4E82003F3E63000A09\r
+ 2700060616000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000003465\r
+ 3F00000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000002E5836002E58\r
+ 36002E583600000000000000000000000000000000002E5836002E5836002E58\r
+ 3600000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000D8D9\r
+ DA00EEEEF600EBE7EB00EEEEF600EBE7EB0083AB8B0078A8870078A8870078A8\r
+ 87005A8568000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000060616007775A6009A99\r
+ C400A09FC7009A99C4009A99C4009A99C4009A99C4007775A6007775A6005F5E\r
+ 9000484775000A09270000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000000000000080AC\r
+ 880054855D00325B3A0000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000051885B005188\r
+ 5B0051885B000000000000000000000000000000000051885B0051885B005188\r
+ 5B00000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000EBE7\r
+ EB00EBE7EB00F6F2F600F6F2F600F6F2F60078A8870078A8870083AB8B00739D\r
+ 7B005A8568000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000060616008B89B8009A99\r
+ C400B6B5CC00B9B7D700A9A7C900B9B7D700A9A7C9009A99C4008B89B8006968\r
+ 9F00484775000A09270000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000008CB8\r
+ 96007AA883006B9A7400497C5300325B3A000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000568C6000568C\r
+ 6000568C600000000000000000000000000000000000568C6000568C6000568C\r
+ 6000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000EBE7EB00F6EEF600F6F2F600F6F2F60078A8870078A88700739D83006493\r
+ 7500000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000606160071719900A9A7C900B9B7\r
+ D700C7C7DB0006061600C8C7E000C8C7E000B0AFC9000A0927008B89B8009A99\r
+ C4006E6DA000484775000A092700000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000008CB8\r
+ 960080AC88007AA883007AA883006B9A7400497C530040704B00000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000005C9267005C92\r
+ 67005C926700000000000000000000000000000000005C9267005C9267005C92\r
+ 6700000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000EBE7EB00EBE7EB00F6F2F600F6F2F60078A8870078A88700739D83005A85\r
+ 6800000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000060616008D8CAD00C7C7DB00D1D1\r
+ DE00060616000606160006061600DBDBE60006061600060616000A0927009A99\r
+ C4007E7CB20069689F000A092700000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000000000000090BB\r
+ 9D007AA883007AA883007AA883007AA883007AA883006B9A7400497C53004058\r
+ 4400000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000005C9267005C92\r
+ 67005C926700000000000000000000000000000000005C9267005C9267005C92\r
+ 6700000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000EBE7EB00EEEEF600F6F2F60078A88700739D8300739D7B000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000A092700B0AFC900DBDBE600DBDB\r
+ E600DBDBE6000000000000000000060616000000000006061600B6B5CC00A9A7\r
+ C9009B9AB8006E6DA0000D0D3100000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000000000000090BB\r
+ 9D0080AC88007AA883007AA883007AA883007AA883007AA883007AA883006B9A\r
+ 74004F815900325B3A0000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000005C9267005C92\r
+ 67005C926700000000000000000000000000000000005C9267005C9267005C92\r
+ 6700000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000EBE7EB00EEEEF600F6F2F60083AB8B00739D7B005A8568000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000006061600B6B5CC00DBDBE600DBDB\r
+ E600E1E1ED00D1D1DE00060616000000000006061600D1D1DE00D1D1DE00B0AF\r
+ C900A9A7C9008B89B8000A092700000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000002B2B2B00F9FB\r
+ F900ECF2ED00ECF2ED00ECF2ED00ECF2ED00E2EBE400D7E4D900D7E4D900D7E4\r
+ D900EFF4F000ACC7B10000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000C3D7C600C3D7\r
+ C600C3D7C60000000000000000000000000000000000C3D7C600C3D7C600C3D7\r
+ C600000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000EBE7EB00EBE7EB0083AB8B0064937500000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000006061600C7C7DB00E1E1ED00DBDB\r
+ E600E1E1ED000606160000000000060616000000000006061600A5A5B500C7C7\r
+ DB00A9A7C9008B89B8000A092700000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000F9FB\r
+ F900ECF2ED00EFF4F000EFF4F000ECF2ED00ECF2ED00E2EBE400EFF4F000C7DA\r
+ CB00181818000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000C3D7C600C3D7\r
+ C600C3D7C60000000000000000000000000000000000C3D7C600C3D7C600C3D7\r
+ C600000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000EBE7EB00EBE7EB0078A887005A856800000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000B0AFC900E8E8F200E1E1\r
+ ED00060616000606160006061600E1E1ED00000000000606160006061600B3B2\r
+ BF00A9A7C9007775A6000D0D3100000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000F9FB\r
+ F900F9FBF900EFF4F000ECF2ED00ECF2ED00EFF4F000C7DACB00000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000C3D7C600C3D7\r
+ C600C3D7C60000000000000000000000000000000000C3D7C600C3D7C600C3D7\r
+ C600000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000010101000D8D9DA0078A8870000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000009797A200E8E8F200E1E1\r
+ ED00DBDBE60006061600DBDBE600DBDBE600DBDBE60000000000B6B5CC00C7C7\r
+ DB008B89B800403F700006061600000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000F9FB\r
+ F900EFF4F000ECF2ED00ECF2ED00C7DACB000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000C3D7C600C3D7\r
+ C600C3D7C60000000000000000000000000000000000C3D7C600C3D7C600C3D7\r
+ C600000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000010101000D8D9DA00739D830000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000DBDBE600E8E8\r
+ F200E8E8F200DBDBE600DBDBE600DBDBE600DBDBE600DBDBE600B9B7D700B9B7\r
+ D700717199000D0D310000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000F9FB\r
+ F900ECF2ED00D7E4D90000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000C3D7C600C3D7\r
+ C600C3D7C60000000000000000000000000000000000C3D7C600C3D7C600C3D7\r
+ C600000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000009797A200D1D1\r
+ DE00E8E8F200E1E1ED00DBDBE600DBDBE600DBDBE600D1D1DE00C8C7E0007E7C\r
+ B2003F3E63000D0D310000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000E2EB\r
+ E400000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000C3D7C600C3D7\r
+ C600C3D7C60000000000000000000000000000000000C3D7C600C3D7C600C3D7\r
+ C600000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000101010000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000A5A5B500B6B5CC00C7C7DB00C8C7E000B6B5CC009B9AB800615E7D000606\r
+ 16000A0927000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000CDD2CD00D8D9\r
+ DA00D8D9DA00D8D9DA00D8D9DA00D8D9DA0078A8870078A88700739D7B0078A8\r
+ 8700649375006493750000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000006061600060616000606160006061600060616000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000CDD2CD00D8D9\r
+ DA00D8D9DA00D8D9DA00D8D9DA00D8D9DA0087B2940087B2940087B2940087B2\r
+ 940078A887006493750000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000007B909900000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000007B9099007B9099007B90990000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000AAA7A700B4C2BD00B4D6D500B5D6E600AABBE700ACB9DA000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00007B909900000000007B9099007B9099007B9099007B9099007B9099000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000ACAE\r
+ CD00B7B6C800B6B6B800A8B8B600B4D6D500B5D6E600AABBE700ACB9DA009C91\r
+ DE00AA8AC6000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000003C604C0035554300000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00007B909900000000007B9099007B9099007B9099007B9099007B9099007B90\r
+ 9900000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000A8B8B600ACB9\r
+ DA00B7B6C800B7B6C800A8B8B600B4D2CD00B5D6E600AABBE700A4A7E600AC89\r
+ D500A47DB400A885BD0000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000416752004167520047725B00416752003C604C00416752000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000305937000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000007B90\r
+ 99007B909900000000007B9099007B9099007B9099007B9099007B9099007B90\r
+ 99007B9099007B90990000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000009CA8A400A8B8B600ACAE\r
+ CD00ACCED500ACAECD00B6B6B800ABC8C800B5D6E600B4CAEB009C91DE00A885\r
+ BD00AA8AC600B491CD00B489C500000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000003555\r
+ 43003C604C000000000000000000000000004167520035554300000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000003D73470063A7\r
+ 6F0051885B000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000007B90\r
+ 9900F7FEFF00000000007B9099007B9099007B9099007B9099007B9099007B90\r
+ 99007B9099007B9099007B9099007B9099000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000009C9D9C009CA79C00A7B4\r
+ AA00A8B8B600ACB9DA00B7B6C800A7B4AA00B5D6E600ACB9DA00AA8AC600AA8A\r
+ C600B491CD00B48DD500CD95D500000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000003555\r
+ 4300000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000003D73470049815400679A710079A9\r
+ 8200568C60000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000007B9099007B90\r
+ 9900F7FEFF00000000007B9099007B9099007B9099007B9099007B9099007B90\r
+ 99007B9099007B9099007B9099007B9099000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000AAA7A700AAA7A700AAA7A7009C9D\r
+ 9C00AAA7A700A8B8B6006A696A0000000000000000006A696A00B491CD00B491\r
+ CD00CD95D500DEA1D500E6AAD500DEA5CD000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000355543000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000030593700447C4E00679A710079A9820079A9820079A9\r
+ 82005C9267000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000007B909900F7FE\r
+ FF00F7FEFF00000000007B9099007B9099007B9099007B9099007B9099007B90\r
+ 99007B9099007B9099007B9099007B9099000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000D5CACD00CDC8C500C7BBBA00C7BB\r
+ BA00B4B2AC006A696A00000000000000000000000000000000006A696A00F6BE\r
+ DE00EEB6DE00EEB6DE00F6BEDE00F6BEDE000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00004A6F5100447C4E00679A710079A9820073A47D0079A9820079A9820079A9\r
+ 82005C9267000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000007B9099007B909900F7FE\r
+ FF00F7FEFF00F7FEFF0000000000000000007B9099007B9099007B9099007B90\r
+ 99007B9099007B9099007B9099007B9099000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000F6DAEB00F6DAEB00F6DAEB00F6DA\r
+ EB00F6DAEB00000000000000000000000000000000000000000000000000F6DA\r
+ EB00F6BEDE00EED2EA00F6DAEB00F6DAEB000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000305937004981\r
+ 5400679A710079A9820073A47D0079A9820079A9820079A9820079A9820079A9\r
+ 82005C9267000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000007B9099007B909900F7FE\r
+ FF00F7FEFF00F7FEFF00F7FEFF00F7FEFF0000000000000000007B9099007B90\r
+ 99007B9099007B9099007B9099007B9099000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000E8C8E900EED2EA00EED2EA00EED2\r
+ EA00E8C8E900000000000000000000000000000000000000000000000000AAA7\r
+ A700B4AEA800C7BBBA00C7BBBA00D5BEBD000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000002B45370000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000ACC7B100F8FA\r
+ F800ECF2ED00DAE6DC00DAE6DC00E4ECE500ECF2ED00ECF2ED00ECF2ED00F8FA\r
+ F800C3D7C6002132240000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000007B9099007B9099007B9099007B90\r
+ 99007B909900F7FEFF00F7FEFF00F7FEFF00F7FEFF00F7FEFF00000000000000\r
+ 00007B9099007B9099007B9099007B9099000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000E8C8E900E8C8E900E8C8E900CDB2\r
+ E600CDB2E6006A696A00000000000000000000000000000000006A696A00A7B4\r
+ AA0094938B0094938B00A49D9400AAA7A7000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00002B4537000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000121B\r
+ 1200DAE6DC00F8FAF800ECF2ED00ECF2ED00ECF2ED00ECF2ED00ECF2ED00ECF2\r
+ ED00C3D7C6000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000007B9099007B909900000000000000\r
+ 00007B9099007B9099007B9099007B909900F7FEFF00F7FEFF00F7FEFF00F7FE\r
+ FF0000000000000000007B9099007B9099000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000CDB2E600CDB2E600CDB2E600B7AA\r
+ E600AABBE700ABC8C8006A696A0000000000000000006A696A00B5D6E600B4D6\r
+ D500A7B4AA00A49D940094938B0083857B000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000041675200416752000000000000000000000000003555\r
+ 4300355543000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000DAE6DC00F8FAF800ECF2ED00ECF2ED00ECF2ED00ECF2\r
+ ED00C3D7C6000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000007B9099007B9099007B9099007B909900F7FE\r
+ FF00F7FEFF00F7FEFF0000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000C5ACE600A4A7E600ACB9\r
+ DA00ABC8C800ACC2BD00A7B4AA00CDC8C500F6DAEB00D8B9E600B7AAE600B5D6\r
+ E600ABC8C800A7B4AA009CA79C00000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000004167520047725B0041675200416752003C604C00355543000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000E4ECE500F8FAF800F8FAF800F8FA\r
+ F800C3D7C6000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000000000000000000000007B9099007B90\r
+ 9900000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000009CA5DE00ACB9DA00ABC8\r
+ C800ACC2BD00A7B4AA00B4C2BD00D5CACD00F6DAEB00E8C8E900C5ACE600B4CA\r
+ EB00B5D6E600ABC8C8009CA8A400000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000416752003C604C000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000E4ECE500F8FA\r
+ F800C3D7C6000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000ACB9DA00ABC8\r
+ C800ACC2BD00B4B2AC00C5C2BD00DED3D500F6DAEB00E8C8E900CDB2E600B7AA\r
+ E600B5D6E600ACCED50000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000C3D7C6000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000A8B8\r
+ B600ACC2BD00B6B6B800CDC8C500DED3D500F6DAEB00EED2EA00D8B9E600C5AC\r
+ E600A4A7E6000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000B4B2AC00CDC8C500DED3D500F6DAEB00E8C8E900D5B6DE000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000424D3E000000000000003E000000\r
+ 2800000080000000680000000100010000000000800600000000000000000000\r
+ 000000000000000000000000FFFFFF00FFFFFFFF000000000000000000000000\r
+ FFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000\r
+ FFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000\r
+ FFFFFFFF000000000000000000000000FF3FF87F000000000000000000000000\r
+ FF0FF87F000000000000000000000000FF03F87F000000000000000000000000\r
+ FF00F87F000000000000000000000000FF00387F000000000000000000000000\r
+ FF00087F000000000000000000000000FF00007F000000000000000000000000\r
+ FF00007F000000000000000000000000FF00087F000000000000000000000000\r
+ FF00387F000000000000000000000000FF00F87F000000000000000000000000\r
+ FF03F87F000000000000000000000000FF0FF87F000000000000000000000000\r
+ FF3FF87F000000000000000000000000FFFFFFFF000000000000000000000000\r
+ FFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000\r
+ FFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000\r
+ FFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC73FFFFFFEFFFFFE00FFFFFFFFFF\r
+ FFFFC23FFFFFFE7FFFFC00FFFFFFFFFFFFFFE03FFFFFC03FFFF8007FFFFFFFFF\r
+ FFFFF07FFFFFC01FFF00007FFFFFFFFFFFF0787FFFF0401FFF00007FFE1FFCFF\r
+ FFC0183FFFC0003FFF00003FFE1FF0FFFF80001FFF800E7FFF00003FFE1FC0FF\r
+ FF00011FFF0006FFFF00003FFE1F00FFFE00039FFE0003FFFF00003FFE1C00FF\r
+ FE0003FFFE0003FFFF00003FFE1000FFFC0001FFFC0001FFFF00003FFE0000FF\r
+ FC0001FFFC0001FFFF00003FFE0000FFFC0001FFFC0001FFFF00003FFE1000FF\r
+ FC0001FFFC0001FFFF00003FFE1C00FFFC0001FFFC0001FFFF00003FFE1F00FF\r
+ FE0003FFFE0003FFFF00003FFE1FC0FFFE0003FFFE0003FFFF00003FFE1FF0FF\r
+ FF0007FFFF0007FFFF00003FFE1FFCFFFF800FFFFF800FFFFF00003FFFFFFFFF\r
+ FFC01FFFFFC01FFFFF00003FFFFFFFFFFFF07FFFFFF07FFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFF8001FFFFF01FFFFFCFFFFFFF8307FFFF8001FF\r
+ FFC007FFFFC3FFFFFF8307FFFFC003FFFF8003FFFFC0FFFFFF8307FFFFC003FF\r
+ FF8003FFFFC03FFFFF8307FFFFE007FFFF0001FFFFC00FFFFF8307FFFFE007FF\r
+ FF0001FFFFC003FFFF8307FFFFF00FFFFF0001FFFFC000FFFF8307FFFFF00FFF\r
+ FF0001FFFFC000FFFF8307FFFFF81FFFFF0001FFFFC003FFFF8307FFFFF81FFF\r
+ FF0001FFFFC00FFFFF8307FFFFFC3FFFFF0001FFFFC03FFFFF8307FFFFFC3FFF\r
+ FF8003FFFFC0FFFFFF8307FFFFFE7FFFFF8003FFFFC3FFFFFF8307FFFF8001FF\r
+ FFC007FFFFCFFFFFFF8307FFFF8001FFFFF01FFFFFFFFFFFFFFFFFFFFF8001FF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFF8001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9FFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFF07FFFFFF81FFFFFFF7FFFFFFFFFFFFFF01FFFFFE007FFFFFF3FFFFFFFFFFF\r
+ FFE00FFFFFC003FFFFF81FFFFFFFF3FFFFE003FFFF8001FFFFE00FFFFFFFC3FF\r
+ FFC000FFFF0000FFFFC01FFFFFFF03FFFFC0007FFF0000FFFFC737FFFFFC03FF\r
+ FF80007FFE00007FFF8F7BFFFFF003FFFF80007FFE01807FFF9FF9FFFFC003FF\r
+ FF00007FFE03C07FFF9FF9FFFF0003FFFF00007FFE03C07FFFDEF1FFFF0003FF\r
+ FE00007FFE01807FFFECE3FFFFC003FFFE00007FFE00007FFFF803FFFFF003FF\r
+ FF30007FFF0000FFFFF007FFFFFC03FFFFFE07FFFF0000FFFFF81FFFFFFF03FF\r
+ FFFFCFFFFF8001FFFFFCFFFFFFFFC3FFFFFFFFFFFFC003FFFFFEFFFFFFFFF3FF\r
+ FFFFFFFFFFE007FFFFFFFFFFFFFFFFFFFFFFFFFFFFF81FFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000\r
+ 000000000000}\r
+ end\r
+ object PopupMenuMain: TPopupMenu\r
+ AutoPopup = False\r
+ Left = 72\r
+ Top = 208\r
+ object PopupClose: TMenuItem\r
+ Caption = '&Close this popup'\r
+ OnClick = PopupCloseClick\r
+ end\r
+ object N9: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object PopupPlay: TMenuItem\r
+ Caption = '&Play'\r
+ OnClick = PopupPlayClick\r
+ end\r
+ object PopupPause: TMenuItem\r
+ Caption = 'Pause'\r
+ OnClick = PopupPauseClick\r
+ end\r
+ object PopupStop: TMenuItem\r
+ Caption = 'Stop'\r
+ OnClick = PopupStopClick\r
+ end\r
+ object PopupBack: TMenuItem\r
+ Caption = 'Back'\r
+ OnClick = PopupBackClick\r
+ end\r
+ object PopupSlow: TMenuItem\r
+ Caption = 'Slow'\r
+ OnClick = PopupSlowClick\r
+ end\r
+ object PopupFast: TMenuItem\r
+ Caption = 'Fast'\r
+ OnClick = PopupFastClick\r
+ end\r
+ object N5: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object PopupToggleInterface: TMenuItem\r
+ Caption = 'Toggle &Interface'\r
+ OnClick = PopupToggleInterfaceClick\r
+ end\r
+ object PopupFullscreen: TMenuItem\r
+ Caption = '&Fullscreen'\r
+ OnClick = PopupFullscreenClick\r
+ end\r
+ object N6: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object PopupNext: TMenuItem\r
+ Caption = 'Next'\r
+ OnClick = PopupNextClick\r
+ end\r
+ object PopupPrev: TMenuItem\r
+ Caption = 'Prev'\r
+ OnClick = PopupPrevClick\r
+ end\r
+ object PopupJump: TMenuItem\r
+ Caption = '&Jump...'\r
+ OnClick = PopupJumpClick\r
+ end\r
+ object PopupProgram: TMenuItem\r
+ Caption = 'Program'\r
+ end\r
+ object PopupNavigation: TMenuItem\r
+ Caption = 'Navigation'\r
+ end\r
+ object PopupAudio: TMenuItem\r
+ Caption = 'Audio'\r
+ end\r
+ object PopupSubtitles: TMenuItem\r
+ Caption = 'Subtitles'\r
+ end\r
+ object PopupFile: TMenuItem\r
+ Caption = 'File'\r
+ object PopupOpenFile: TMenuItem\r
+ Caption = 'Open file...'\r
+ OnClick = PopupOpenFileClick\r
+ end\r
+ object PopupOpenDisc: TMenuItem\r
+ Caption = 'Open disc...'\r
+ OnClick = PopupOpenDiscClick\r
+ end\r
+ object PopupNetworkStream: TMenuItem\r
+ Caption = 'Network stream...'\r
+ OnClick = PopupNetworkStreamClick\r
+ end\r
+ end\r
+ object PopupPlaylist: TMenuItem\r
+ Caption = 'Playlist...'\r
+ OnClick = PopupPlaylistClick\r
+ end\r
+ object PopupPreferences: TMenuItem\r
+ Caption = 'Preferences...'\r
+ OnClick = PopupPreferencesClick\r
+ end\r
+ object N7: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object PopupExit: TMenuItem\r
+ Caption = 'E&xit'\r
+ OnClick = PopupExitClick\r
+ end\r
+ end\r
+ object TimerManage: TTimer\r
+ OnTimer = TimerManageTimer\r
+ Left = 136\r
+ Top = 208\r
+ end\r
+end\r
--- /dev/null
+/*****************************************************************************\r
+ * mainframe.h: Prototype for main window\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+\r
+#ifndef mainframeH\r
+#define mainframeH\r
+//---------------------------------------------------------------------------\r
+#include <Classes.hpp>\r
+#include <Controls.hpp>\r
+#include <StdCtrls.hpp>\r
+#include <Forms.hpp>\r
+#include <ComCtrls.hpp>\r
+#include <Dialogs.hpp>\r
+#include <ImgList.hpp>\r
+#include <Menus.hpp>\r
+#include <ToolWin.hpp>\r
+#include <AppEvnts.hpp>\r
+#include <ExtCtrls.hpp>\r
+#include "CSPIN.h"\r
+//---------------------------------------------------------------------------\r
+class TMainFrameDlg : public TForm\r
+{\r
+__published: // IDE-managed Components\r
+ TToolBar *ToolBar;\r
+ TToolButton *ToolButtonFile;\r
+ TToolButton *ToolButtonDisc;\r
+ TToolButton *ToolButtonNet;\r
+ TToolButton *ToolButtonSep1;\r
+ TToolButton *ToolButtonBack;\r
+ TToolButton *ToolButtonStop;\r
+ TToolButton *ToolButtonEject;\r
+ TToolButton *ToolButtonPlay;\r
+ TToolButton *ToolButtonPause;\r
+ TToolButton *ToolButtonSlow;\r
+ TToolButton *ToolButtonFast;\r
+ TToolButton *ToolButtonSep2;\r
+ TToolButton *ToolButtonPlaylist;\r
+ TToolButton *ToolButtonPrev;\r
+ TToolButton *ToolButtonNext;\r
+ TMainMenu *MainMenu1;\r
+ TMenuItem *MenuFile;\r
+ TMenuItem *MenuOpenFile;\r
+ TMenuItem *MenuOpenDisc;\r
+ TMenuItem *MenuNetworkStream;\r
+ TMenuItem *N1;\r
+ TMenuItem *MenuExit;\r
+ TMenuItem *MenuView;\r
+ TMenuItem *MenuHideinterface;\r
+ TMenuItem *MenuFullscreen;\r
+ TMenuItem *N2;\r
+ TMenuItem *MenuTitle;\r
+ TMenuItem *MenuChapter;\r
+ TMenuItem *MenuAngle;\r
+ TMenuItem *N3;\r
+ TMenuItem *MenuPlaylist;\r
+ TMenuItem *MenuModules;\r
+ TMenuItem *MenuMessages;\r
+ TMenuItem *MenuSettings;\r
+ TMenuItem *MenuAudio;\r
+ TMenuItem *MenuSubtitles;\r
+ TMenuItem *N4;\r
+ TMenuItem *MenuPreferences;\r
+ TMenuItem *MenuHelp;\r
+ TMenuItem *MenuAbout;\r
+ TOpenDialog *OpenDialog1;\r
+ TImageList *ImageListToolbar;\r
+ TPopupMenu *PopupMenuMain;\r
+ TMenuItem *PopupPlay;\r
+ TMenuItem *PopupPause;\r
+ TMenuItem *PopupStop;\r
+ TMenuItem *PopupBack;\r
+ TMenuItem *PopupSlow;\r
+ TMenuItem *PopupFast;\r
+ TMenuItem *N5;\r
+ TMenuItem *PopupToggleInterface;\r
+ TMenuItem *PopupFullscreen;\r
+ TMenuItem *N6;\r
+ TMenuItem *PopupNext;\r
+ TMenuItem *PopupPrev;\r
+ TMenuItem *PopupJump;\r
+ TMenuItem *PopupNavigation;\r
+ TMenuItem *PopupProgram;\r
+ TMenuItem *PopupAudio;\r
+ TMenuItem *PopupSubtitles;\r
+ TMenuItem *PopupFile;\r
+ TMenuItem *PopupPlaylist;\r
+ TMenuItem *PopupPreferences;\r
+ TMenuItem *N7;\r
+ TMenuItem *PopupExit;\r
+ TStatusBar *StatusBar;\r
+ TGroupBox *GroupBoxFile;\r
+ TLabel *LabelFileName;\r
+ TGroupBox *GroupBoxNetwork;\r
+ TLabel *LabelChannel;\r
+ TLabel *LabelServer;\r
+ TGroupBox *GroupBoxDisc;\r
+ TMenuItem *N8;\r
+ TMenuItem *MenuEjectDisc;\r
+ TMenuItem *MenuProgram;\r
+ TLabel *LabelDisc;\r
+ TLabel *LabelTitle;\r
+ TButton *ButtonTitlePrev;\r
+ TButton *ButtonTitleNext;\r
+ TButton *ButtonChapterPrev;\r
+ TButton *ButtonChapterNext;\r
+ TLabel *LabelChapter;\r
+ TLabel *LabelTitleCurrent;\r
+ TLabel *LabelChapterCurrent;\r
+ TButton *ButtonGo;\r
+ TGroupBox *GroupBoxSlider;\r
+ TTrackBar *TrackBar;\r
+ TTimer *TimerManage;\r
+ TMenuItem *PopupOpenFile;\r
+ TMenuItem *PopupOpenDisc;\r
+ TMenuItem *PopupNetworkStream;\r
+ TMenuItem *PopupClose;\r
+ TMenuItem *N9;\r
+ TCSpinEdit *SpinEditChannel;\r
+ TToolButton *ToolButton1;\r
+ void __fastcall TimerManageTimer( TObject *Sender );\r
+ void __fastcall TrackBarChange( TObject *Sender );\r
+ void __fastcall FormClose( TObject *Sender, TCloseAction &Action );\r
+ void __fastcall MenuOpenFileClick( TObject *Sender );\r
+ void __fastcall MenuOpenDiscClick( TObject *Sender );\r
+ void __fastcall MenuNetworkStreamClick( TObject *Sender );\r
+ void __fastcall MenuExitClick( TObject *Sender );\r
+ void __fastcall MenuHideinterfaceClick( TObject *Sender );\r
+ void __fastcall MenuFullscreenClick( TObject *Sender );\r
+ void __fastcall MenuPlaylistClick( TObject *Sender );\r
+ void __fastcall MenuMessagesClick( TObject *Sender );\r
+ void __fastcall MenuPreferencesClick( TObject *Sender );\r
+ void __fastcall MenuAboutClick( TObject *Sender );\r
+ void __fastcall ToolButtonFileClick( TObject *Sender );\r
+ void __fastcall ToolButtonDiscClick( TObject *Sender );\r
+ void __fastcall ToolButtonNetClick( TObject *Sender );\r
+ void __fastcall ToolButtonPlaylistClick( TObject *Sender );\r
+ void __fastcall ToolButtonBackClick( TObject *Sender );\r
+ void __fastcall ToolButtonStopClick( TObject *Sender );\r
+ void __fastcall ToolButtonPlayClick( TObject *Sender );\r
+ void __fastcall ToolButtonPauseClick( TObject *Sender );\r
+ void __fastcall ToolButtonSlowClick( TObject *Sender );\r
+ void __fastcall ToolButtonFastClick( TObject *Sender );\r
+ void __fastcall ToolButtonPrevClick( TObject *Sender );\r
+ void __fastcall ToolButtonNextClick( TObject *Sender );\r
+ void __fastcall ToolButtonEjectClick( TObject *Sender );\r
+ void __fastcall PopupCloseClick( TObject *Sender );\r
+ void __fastcall PopupPlayClick( TObject *Sender );\r
+ void __fastcall PopupPauseClick( TObject *Sender );\r
+ void __fastcall PopupStopClick( TObject *Sender );\r
+ void __fastcall PopupBackClick( TObject *Sender );\r
+ void __fastcall PopupSlowClick( TObject *Sender );\r
+ void __fastcall PopupFastClick( TObject *Sender );\r
+ void __fastcall PopupToggleInterfaceClick( TObject *Sender );\r
+ void __fastcall PopupFullscreenClick( TObject *Sender );\r
+ void __fastcall PopupNextClick( TObject *Sender );\r
+ void __fastcall PopupPrevClick( TObject *Sender );\r
+ void __fastcall PopupJumpClick( TObject *Sender );\r
+ void __fastcall PopupPlaylistClick( TObject *Sender );\r
+ void __fastcall PopupPreferencesClick( TObject *Sender );\r
+ void __fastcall PopupExitClick( TObject *Sender );\r
+ void __fastcall PopupOpenFileClick( TObject *Sender );\r
+ void __fastcall PopupOpenDiscClick( TObject *Sender );\r
+ void __fastcall PopupNetworkStreamClick( TObject *Sender );\r
+ void __fastcall ButtonTitlePrevClick( TObject *Sender );\r
+ void __fastcall ButtonTitleNextClick( TObject *Sender );\r
+ void __fastcall ButtonChapterPrevClick( TObject *Sender );\r
+ void __fastcall ButtonChapterNextClick( TObject *Sender );\r
+ void __fastcall ButtonGoClick( TObject *Sender );\r
+private: // User declarations\r
+public: // User declarations\r
+ TStringList *StringListPref; /* stores config dialogs */\r
+ __fastcall TMainFrameDlg( TComponent* Owner );\r
+ virtual __fastcall ~TMainFrameDlg();\r
+ void __fastcall DisplayHint( TObject *Sender );\r
+ void __fastcall ModeManage();\r
+ void __fastcall CreatePreferences( AnsiString Name );\r
+ void __fastcall MenuProgramClick( TObject *Sender );\r
+ void __fastcall MenuAudioClick( TObject *Sender );\r
+ void __fastcall MenuSubtitleClick( TObject *Sender );\r
+ void __fastcall MenuTitleClick( TObject *Sender );\r
+ void __fastcall MenuChapterClick( TObject *Sender );\r
+ void __fastcall PopupProgramClick( TObject *Sender );\r
+ void __fastcall PopupAudioClick( TObject *Sender );\r
+ void __fastcall PopupSubtitleClick( TObject *Sender );\r
+ void __fastcall PopupNavigationClick( TObject *Sender );\r
+};\r
+//---------------------------------------------------------------------------\r
+#endif\r
--- /dev/null
+/*****************************************************************************\r
+ * menu.cpp: functions to handle menu items\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+//#pragma hdrstop\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "menu.h"\r
+#include "win32_common.h"\r
+\r
+\r
+/****************************************************************************\r
+ * Local Prototypes\r
+ ****************************************************************************/\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+static TMenuItem *Index2Item( TMenuItem *, int, bool );\r
+static int Item2Index( TMenuItem *, TMenuItem * );\r
+static void __fastcall LangChange( TMenuItem *, TMenuItem *, TMenuItem *, int );\r
+static void __fastcall ProgramChange( TMenuItem *, TMenuItem * );\r
+\r
+static void __fastcall RadioMenu( TMenuItem *, AnsiString,\r
+ int, int, TNotifyEvent );\r
+static void __fastcall ProgramMenu( TMenuItem *, pgrm_descriptor_t *,\r
+ TNotifyEvent );\r
+static void __fastcall LanguageMenu( TMenuItem *t, es_descriptor_t *,\r
+ int, TNotifyEvent );\r
+static void __fastcall NavigationMenu( TMenuItem *, TNotifyEvent );\r
+\r
+\r
+static TMenuItem *Index2Item( TMenuItem *Root, int i_index, bool SingleColumn )\r
+{\r
+ if( SingleColumn || ( i_index < 20 ) )\r
+ {\r
+ return Root->Items[i_index];\r
+ }\r
+ else\r
+ {\r
+ return Root->Items[i_index / 10]->Items[i_index % 10];\r
+ }\r
+}\r
+\r
+static int Item2Index( TMenuItem *Root, TMenuItem *Item )\r
+{\r
+ if( Item->Parent == Root )\r
+ {\r
+ return Item->MenuIndex;\r
+ }\r
+ else\r
+ {\r
+ return( 10 * Item->Parent->MenuIndex + Item->MenuIndex );\r
+ }\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * LangChange: change audio or subtitles languages\r
+ ****************************************************************************\r
+ * Toggle the language, and update the selected menuitems.\r
+ ****************************************************************************/\r
+static void __fastcall LangChange( TMenuItem *RootCurrent, TMenuItem *Item,\r
+ TMenuItem *RootOther, int i_cat )\r
+{\r
+ intf_thread_t * p_intf = p_intfGlobal;\r
+ es_descriptor_t * p_es;\r
+ es_descriptor_t * p_es_old;\r
+ int i_index;\r
+ int i_es;\r
+\r
+ /* find the selected ES */\r
+ i_es = Item->Tag;\r
+\r
+ /* find selected menu item */\r
+ i_index = Item2Index( RootCurrent, Item ) - 1;\r
+ if( i_index < 0 )\r
+ {\r
+ /* 'None' was selected */\r
+ p_es = NULL;\r
+ }\r
+ else\r
+ {\r
+ vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+ p_es = p_intfGlobal->p_sys->p_input->stream.pp_es[i_es];\r
+ vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+ }\r
+\r
+ /* find the current ES */\r
+ if( i_cat == AUDIO_ES )\r
+ {\r
+ p_es_old = p_intf->p_sys->p_audio_es_old;\r
+ p_intf->p_sys->p_audio_es_old = p_es;\r
+ }\r
+ else\r
+ {\r
+ p_es_old = p_intf->p_sys->p_spu_es_old;\r
+ p_intf->p_sys->p_spu_es_old = p_es;\r
+ }\r
+\r
+ /* exchange them */\r
+ input_ToggleES( p_intfGlobal->p_sys->p_input, p_es_old, false );\r
+ input_ToggleES( p_intfGlobal->p_sys->p_input, p_es, true );\r
+\r
+ Item->Checked = true;\r
+ Index2Item( RootOther, i_index + 1, true )->Checked = true;\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * ProgramChange: change the program\r
+ ****************************************************************************\r
+ * Toggle the program, and update the selected menuitems.\r
+ ****************************************************************************/\r
+static void __fastcall ProgramChange( TMenuItem *Item, TMenuItem *RootOther )\r
+{\r
+ intf_thread_t * p_intf = p_intfGlobal;\r
+ int i_program = Item->Tag;\r
+\r
+ /* toggle the program */\r
+ input_ChangeProgram( p_intfGlobal->p_sys->p_input, (u16)i_program );\r
+\r
+ /* check selected menu items */\r
+ Item->Checked = true;\r
+ Index2Item( RootOther, i_program - 1, true )->Checked = true;\r
+\r
+ /* update audio/subtitles menus */\r
+ p_intf->p_sys->b_audio_update = 1;\r
+ p_intf->p_sys->b_spu_update = 1;\r
+ vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+ SetupMenus( p_intf );\r
+ vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+ p_intf->p_sys->b_audio_update = 0;\r
+ p_intf->p_sys->b_spu_update = 0;\r
+\r
+ input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * TMainFrameDlg::*Click: callbacks for the menuitems\r
+ ****************************************************************************\r
+ * These functions need to be in a class, or we won't be able to pass them\r
+ * as arguments (since TNotifyEvent uses __closure)\r
+ ****************************************************************************/\r
+\r
+ /*\r
+ * Audio\r
+ */\r
+\r
+void __fastcall TMainFrameDlg::MenuAudioClick( TObject *Sender )\r
+{\r
+ LangChange( MenuAudio, (TMenuItem *)Sender, PopupAudio, AUDIO_ES );\r
+}\r
+\r
+void __fastcall TMainFrameDlg::PopupAudioClick( TObject *Sender )\r
+{\r
+ LangChange( PopupAudio, (TMenuItem *)Sender, MenuAudio, AUDIO_ES );\r
+}\r
+\r
+/*\r
+ * Subtitles\r
+ */\r
+\r
+void __fastcall TMainFrameDlg::MenuSubtitleClick( TObject *Sender )\r
+{\r
+ LangChange( MenuSubtitles, (TMenuItem *)Sender, PopupSubtitles, SPU_ES );\r
+}\r
+\r
+void __fastcall TMainFrameDlg::PopupSubtitleClick( TObject *Sender )\r
+{\r
+ LangChange( PopupSubtitles, (TMenuItem *)Sender, MenuSubtitles, SPU_ES );\r
+}\r
+\r
+/*\r
+ * Program\r
+ */\r
+\r
+void __fastcall TMainFrameDlg::MenuProgramClick( TObject *Sender )\r
+{\r
+ ProgramChange( (TMenuItem *)Sender, PopupProgram );\r
+}\r
+\r
+void __fastcall TMainFrameDlg::PopupProgramClick( TObject *Sender )\r
+{\r
+ ProgramChange( (TMenuItem *)Sender, MenuProgram );\r
+}\r
+\r
+/*\r
+ * Navigation\r
+ */\r
+\r
+void __fastcall TMainFrameDlg::PopupNavigationClick( TObject *Sender )\r
+{\r
+ TMenuItem * Item = (TMenuItem *)Sender;\r
+ TMenuItem * ItemTitle;\r
+ input_area_t * p_area;\r
+ int i_title = DATA2TITLE( Item->Tag );\r
+ int i_chapter = DATA2CHAPTER( Item->Tag );\r
+\r
+ p_area = p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title];\r
+ p_area->i_part = i_chapter;\r
+\r
+ input_ChangeArea( p_intfGlobal->p_sys->p_input, (input_area_t*)p_area );\r
+\r
+ Item->Checked = true;\r
+ ItemTitle = Index2Item( MenuTitle, i_title - 1, false );\r
+ if( ItemTitle->Checked )\r
+ {\r
+ /* same title, new chapter */\r
+ Index2Item( MenuChapter, i_chapter - 1, false )->Checked = true;\r
+ }\r
+ else\r
+ {\r
+ /* new title => we must rebuild the chapter menu */\r
+ vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+ RadioMenu( MenuChapter, "Chapter",\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part_nb,\r
+ i_chapter, MenuChapterClick );\r
+ vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+ }\r
+\r
+ input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
+}\r
+\r
+/*\r
+ * Title\r
+ */\r
+\r
+void __fastcall TMainFrameDlg::MenuTitleClick( TObject *Sender )\r
+{\r
+ TMenuItem * Item = (TMenuItem *)Sender;\r
+ TMenuItem * ItemTitle;\r
+ int i_title = Item->Tag;\r
+\r
+ input_ChangeArea( p_intfGlobal->p_sys->p_input,\r
+ p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title] );\r
+ Item->Checked = true;\r
+ ItemTitle = Index2Item( PopupNavigation, i_title - 1, false );\r
+ Index2Item( ItemTitle, 0, false )->Checked = true;\r
+\r
+ input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
+}\r
+\r
+/*\r
+ * Chapter\r
+ */\r
+\r
+void __fastcall TMainFrameDlg::MenuChapterClick( TObject *Sender )\r
+{\r
+ TMenuItem * Item = (TMenuItem *)Sender;\r
+ TMenuItem * ItemTitle;\r
+ input_area_t * p_area;\r
+ int i_title;\r
+ int i_chapter = Item->Tag;\r
+\r
+ p_area = p_intfGlobal->p_sys->p_input->stream.p_selected_area;\r
+ p_area->i_part = i_chapter;\r
+\r
+ input_ChangeArea( p_intfGlobal->p_sys->p_input, (input_area_t*)p_area );\r
+\r
+ i_title = p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_id;\r
+ ItemTitle = Index2Item( PopupNavigation, i_title - 1, false );\r
+ Index2Item( ItemTitle, i_chapter - 1, false )->Checked = true;\r
+\r
+ input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * Functions to generate menus\r
+ ****************************************************************************/\r
+\r
+/*****************************************************************************\r
+ * RadioMenu: update interactive menus of the interface\r
+ *****************************************************************************\r
+ * Sets up menus with information from input\r
+ * Warning: since this function is designed to be called by management\r
+ * function, the interface lock has to be taken\r
+ *****************************************************************************/\r
+static void __fastcall RadioMenu( TMenuItem * Root, AnsiString ItemName,\r
+ int i_nb, int i_selected,\r
+ TNotifyEvent MenuItemClick )\r
+{\r
+ TMenuItem * ItemGroup;\r
+ TMenuItem * Item;\r
+ TMenuItem * ItemActive;\r
+ AnsiString Name;\r
+ int i_item;\r
+\r
+ /* remove previous menu */\r
+ Root->Enabled = false;\r
+ Root->Clear();\r
+\r
+ ItemActive = NULL;\r
+\r
+ for( i_item = 0; i_item < i_nb; i_item++ )\r
+ {\r
+ /* we group titles/chapters in packets of ten for small screens */\r
+ if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )\r
+ {\r
+ if( i_item != 0 )\r
+ {\r
+ Root->Add( ItemGroup );\r
+ }\r
+\r
+ Name.sprintf( "%ss %d to %d", ItemName, i_item + 1, i_item + 10 );\r
+ ItemGroup = new TMenuItem( Root );\r
+ ItemGroup->Hint = Name;\r
+\r
+ /* set the accelerator character */\r
+ Name.Insert( "&", Name.Length() - 1 );\r
+ ItemGroup->Caption = Name;\r
+ }\r
+\r
+ Name.sprintf( "%s %d", ItemName, i_item + 1 );\r
+ Item = new TMenuItem( Root );\r
+ Item->RadioItem = true;\r
+ Item->Hint = Name;\r
+\r
+ /* set the accelerator character */\r
+ Name.Insert( "&", Name.Length() );\r
+ Item->Caption = Name;\r
+\r
+ /* FIXME: temporary hack to save i_item with the Item\r
+ * It will be used in the callback. */\r
+ Item->Tag = i_item + 1;\r
+\r
+ if( i_selected == i_item + 1 )\r
+ {\r
+ ItemActive = Item;\r
+ }\r
+ \r
+ /* setup signal handling */\r
+ Item->OnClick = MenuItemClick;\r
+\r
+ if( i_nb > 20 )\r
+ {\r
+ ItemGroup->Add( Item );\r
+ }\r
+ else\r
+ {\r
+ Root->Add( Item );\r
+ }\r
+ }\r
+\r
+// if( ( i_nb > 20 ) && ( i_item % 10 ) ) ?\r
+ if( i_nb > 20 )\r
+ {\r
+ Root->Add( ItemGroup );\r
+ }\r
+\r
+ /* check currently selected chapter */\r
+ if( ItemActive != NULL )\r
+ {\r
+ ItemActive->Checked = true;\r
+ }\r
+\r
+ /* be sure that menu is enabled, if there are several items */\r
+ if( i_nb > 1 )\r
+ {\r
+ Root->Enabled = true;\r
+ }\r
+}\r
+\r
+\r
+/*****************************************************************************\r
+ * ProgramMenu: update the programs menu of the interface\r
+ *****************************************************************************\r
+ * Builds the program menu according to what have been found in the PAT \r
+ * by the input. Useful for multi-programs streams such as DVB ones.\r
+ *****************************************************************************/\r
+static void __fastcall ProgramMenu( TMenuItem * Root,\r
+ pgrm_descriptor_t * p_pgrm,\r
+ TNotifyEvent MenuItemClick )\r
+{\r
+ TMenuItem * Item;\r
+ TMenuItem * ItemActive;\r
+ AnsiString Name;\r
+ int i;\r
+\r
+ /* remove previous menu */\r
+ Root->Clear();\r
+ Root->Enabled = false;\r
+\r
+ ItemActive = NULL;\r
+\r
+ /* create a set of program buttons and append them to the container */\r
+ for( i = 0; i < p_intfGlobal->p_sys->p_input->stream.i_pgrm_number; i++ )\r
+ {\r
+ Name.sprintf( "id %d",\r
+ p_intfGlobal->p_sys->p_input->stream.pp_programs[i]->i_number );\r
+\r
+ Item = new TMenuItem( Root );\r
+ Item->Caption = Name;\r
+ Item->Hint = Name;\r
+ Item->RadioItem = true;\r
+ Item->OnClick = MenuItemClick;\r
+\r
+ /* FIXME: temporary hack to save the program id with the Item\r
+ * It will be used in the callback. */\r
+ Item->Tag = i + 1;\r
+\r
+ if( p_pgrm == p_intfGlobal->p_sys->p_input->stream.pp_programs[i] )\r
+ {\r
+ /* don't lose Item when we append into menu */\r
+ ItemActive = Item;\r
+ }\r
+\r
+ /* Add the item to the submenu */\r
+ Root->Add( Item );\r
+ }\r
+\r
+ /* check currently selected program */\r
+ if( ItemActive != NULL )\r
+ {\r
+ ItemActive->Checked = true;\r
+ }\r
+\r
+ /* be sure that menu is enabled if more than 1 program */\r
+ if( p_intfGlobal->p_sys->p_input->stream.i_pgrm_number > 1 )\r
+ {\r
+ Root->Enabled = true;\r
+ }\r
+}\r
+\r
+\r
+/*****************************************************************************\r
+ * LanguageMenus: update interactive menus of the interface\r
+ *****************************************************************************\r
+ * Sets up menus with information from input:\r
+ * - languages\r
+ * - sub-pictures\r
+ * Warning: since this function is designed to be called by management\r
+ * function, the interface lock has to be taken\r
+ *****************************************************************************/\r
+static void __fastcall LanguageMenu( TMenuItem * Root, es_descriptor_t * p_es,\r
+ int i_cat, TNotifyEvent MenuItemClick )\r
+{\r
+ TMenuItem * Separator;\r
+ TMenuItem * Item;\r
+ TMenuItem * ItemActive;\r
+ AnsiString Name;\r
+ int i_item;\r
+ int i;\r
+\r
+ /* remove previous menu */\r
+ Root->Clear();\r
+ Root->Enabled = false;\r
+\r
+ /* special case for "off" item */\r
+ Name = "None";\r
+ Item = new TMenuItem( Root );\r
+ Item->RadioItem = true;\r
+ Item->Hint = Name;\r
+ Item->Caption = Name;\r
+ Item->OnClick = MenuItemClick;\r
+ Item->Tag = -1;\r
+ Root->Add( Item );\r
+\r
+ /* separator item */\r
+ Separator = new TMenuItem( Root );\r
+ Separator->Caption = "-";\r
+ Root->Add( Separator );\r
+\r
+ ItemActive = NULL;\r
+ i_item = 0;\r
+\r
+ vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+\r
+#define ES p_intfGlobal->p_sys->p_input->stream.pp_es[i]\r
+ /* create a set of language buttons and append them to the Root */\r
+ for( i = 0; i < p_intfGlobal->p_sys->p_input->stream.i_es_number; i++ )\r
+ {\r
+ if( ( ES->i_cat == i_cat ) &&\r
+ ( !ES->p_pgrm ||\r
+ ES->p_pgrm ==\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_program ) )\r
+ {\r
+ i_item++;\r
+ Name = p_intfGlobal->p_sys->p_input->stream.pp_es[i]->psz_desc;\r
+ if( Name.IsEmpty() )\r
+ {\r
+ Name.sprintf( "Language %d", i_item );\r
+ }\r
+\r
+ Item = new TMenuItem( Root );\r
+ Item->RadioItem = true;\r
+ Item->Hint = Name;\r
+ Item->Caption = Name;\r
+ Item->Tag = i;\r
+\r
+ if( p_es == p_intfGlobal->p_sys->p_input->stream.pp_es[i] )\r
+ {\r
+ /* don't lose Item when we append into menu */\r
+ ItemActive = Item;\r
+ }\r
+\r
+ /* setup signal hanling */\r
+ Item->OnClick = MenuItemClick;\r
+ Root->Add( Item );\r
+ }\r
+ }\r
+#undef ES\r
+\r
+ vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+\r
+ /* check currently selected item */\r
+ if( ItemActive != NULL )\r
+ {\r
+ ItemActive->Checked = true;\r
+ }\r
+\r
+ /* be sure that menu is enabled if non empty */\r
+ if( i_item > 0 )\r
+ {\r
+ Root->Enabled = true;\r
+ }\r
+}\r
+\r
+\r
+/*****************************************************************************\r
+ * NavigationMenu: sets menus for titles and chapters selection\r
+ *****************************************************************************\r
+ * Generates two types of menus:\r
+ * -simple list of titles\r
+ * -cascaded lists of chapters for each title\r
+ *****************************************************************************/\r
+static void __fastcall NavigationMenu( TMenuItem * Root,\r
+ TNotifyEvent MenuItemClick )\r
+{\r
+ TMenuItem * TitleGroup;\r
+ TMenuItem * TitleItem;\r
+ TMenuItem * ItemActive;\r
+ TMenuItem * ChapterGroup;\r
+ TMenuItem * ChapterItem;\r
+ AnsiString Name;\r
+ int i_title;\r
+ int i_chapter;\r
+ int i_title_nb;\r
+ int i_chapter_nb;\r
+\r
+\r
+ /* remove previous menu */\r
+ Root->Enabled = false;\r
+ Root->Clear();\r
+\r
+ ItemActive = NULL;\r
+ i_title_nb = p_intfGlobal->p_sys->p_input->stream.i_area_nb;\r
+ \r
+ /* loop on titles */\r
+ for( i_title = 1; i_title < i_title_nb; i_title++ )\r
+ {\r
+ /* we group titles in packets of ten for small screens */\r
+ if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )\r
+ {\r
+ if( i_title != 1 )\r
+ {\r
+ Root->Add( TitleGroup );\r
+ }\r
+\r
+ Name.sprintf( "%d - %d", i_title, i_title + 9 );\r
+ TitleGroup = new TMenuItem( Root );\r
+ TitleGroup->RadioItem = true;\r
+ TitleGroup->Hint = Name;\r
+ TitleGroup->Caption = Name;\r
+ }\r
+\r
+ Name.sprintf( "Title %d (%d)", i_title,\r
+ p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb );\r
+\r
+ {\r
+ TitleItem = new TMenuItem( Root );\r
+ TitleItem->RadioItem = true;\r
+ TitleItem->Hint = Name;\r
+ TitleItem->Caption = Name;\r
+\r
+ i_chapter_nb =\r
+ p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb;\r
+\r
+ /* loop on chapters */\r
+ for( i_chapter = 0; i_chapter < i_chapter_nb; i_chapter++ )\r
+ {\r
+ /* we group chapters in packets of ten for small screens */\r
+ if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )\r
+ {\r
+ if( i_chapter != 0 )\r
+ {\r
+ TitleItem->Add( ChapterGroup );\r
+ }\r
+\r
+ Name.sprintf( "%d - %d", i_chapter + 1, i_chapter + 10 );\r
+ ChapterGroup = new TMenuItem( TitleItem );\r
+ ChapterGroup->RadioItem = true;\r
+ ChapterGroup->Hint = Name;\r
+ ChapterGroup->Caption = Name;\r
+ }\r
+\r
+ Name.sprintf( "Chapter %d", i_chapter + 1 );\r
+\r
+ ChapterItem = new TMenuItem( TitleItem );\r
+ ChapterItem->RadioItem = true;\r
+ ChapterItem->Hint = Name;\r
+ ChapterItem->Caption = Name;\r
+\r
+ /* FIXME: temporary hack to save i_title and i_chapter with\r
+ * ChapterItem, since we will need them in the callback */\r
+ ChapterItem->Tag = (int)POS2DATA( i_title, i_chapter + 1 );\r
+\r
+#define p_area p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]\r
+ if( ( p_area ==\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area ) &&\r
+ ( p_area->i_part == i_chapter + 1 ) )\r
+ {\r
+ ItemActive = ChapterItem;\r
+ }\r
+#undef p_area\r
+\r
+ /* setup signal hanling */\r
+ ChapterItem->OnClick = MenuItemClick;\r
+\r
+ if( i_chapter_nb > 20 )\r
+ {\r
+ ChapterGroup->Add( ChapterItem );\r
+ }\r
+ else\r
+ {\r
+ TitleItem->Add( ChapterItem );\r
+ }\r
+ }\r
+\r
+ if( i_chapter_nb > 20 )\r
+ {\r
+ TitleItem->Add( ChapterGroup );\r
+ }\r
+\r
+ if( p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb\r
+ > 1 )\r
+ {\r
+ /* be sure that menu is sensitive */\r
+ Root->Enabled = true;\r
+ }\r
+ }\r
+\r
+ if( i_title_nb > 20 )\r
+ {\r
+ TitleGroup->Add( TitleItem );\r
+ }\r
+ else\r
+ {\r
+ Root->Add( TitleItem );\r
+ }\r
+ }\r
+\r
+ if( i_title_nb > 20 )\r
+ {\r
+ Root->Add( TitleGroup );\r
+ }\r
+\r
+ /* Default selected chapter */\r
+ if( ItemActive != NULL )\r
+ {\r
+ ItemActive->Checked = true;\r
+ }\r
+\r
+ /* be sure that menu is sensitive */\r
+ Root->Enabled = true;\r
+}\r
+\r
+\r
+/*****************************************************************************\r
+ * SetupMenus: function that generates title/chapter/audio/subpic\r
+ * menus with help from preceding functions\r
+ *****************************************************************************/\r
+int __fastcall SetupMenus( intf_thread_t * p_intf )\r
+{\r
+ TMainFrameDlg * p_window = p_intf->p_sys->p_window;\r
+ es_descriptor_t * p_audio_es;\r
+ es_descriptor_t * p_spu_es;\r
+ int i;\r
+\r
+ p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;\r
+ p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update |\r
+ p_intf->p_sys->b_program_update;\r
+ p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update |\r
+ p_intf->p_sys->b_program_update;\r
+\r
+ if( p_intf->p_sys->b_program_update )\r
+ { \r
+ pgrm_descriptor_t * p_pgrm;\r
+\r
+ if( p_intfGlobal->p_sys->p_input->stream.p_new_program )\r
+ {\r
+ p_pgrm = p_intfGlobal->p_sys->p_input->stream.p_new_program;\r
+ }\r
+ else\r
+ {\r
+ p_pgrm = p_intfGlobal->p_sys->p_input->stream.p_selected_program;\r
+ }\r
+\r
+ ProgramMenu( p_window->MenuProgram, p_pgrm,\r
+ p_window->MenuProgramClick );\r
+ ProgramMenu( p_window->PopupProgram, p_pgrm,\r
+ p_window->PopupProgramClick );\r
+\r
+ p_intf->p_sys->b_program_update = 0;\r
+ }\r
+\r
+ if( p_intf->p_sys->b_title_update )\r
+ {\r
+ RadioMenu( p_window->MenuTitle, "Title",\r
+//why "-1" ?\r
+ p_intfGlobal->p_sys->p_input->stream.i_area_nb - 1,\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_id,\r
+ p_window->MenuTitleClick );\r
+\r
+ AnsiString CurrentTitle;\r
+ CurrentTitle.sprintf( "%d",\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_id );\r
+ p_window->LabelTitleCurrent->Caption = CurrentTitle;\r
+\r
+ p_intf->p_sys->b_title_update = 0;\r
+ }\r
+\r
+ if( p_intf->p_sys->b_chapter_update )\r
+ {\r
+ RadioMenu( p_window->MenuChapter, "Chapter",\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part_nb,\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part,\r
+ p_window->MenuChapterClick );\r
+\r
+ NavigationMenu( p_window->PopupNavigation,\r
+ p_window->PopupNavigationClick );\r
+\r
+ AnsiString CurrentChapter;\r
+ CurrentChapter.sprintf( "%d",\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part );\r
+ p_window->LabelChapterCurrent->Caption = CurrentChapter;\r
+\r
+ p_intf->p_sys->i_part =\r
+ p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part;\r
+\r
+ p_intf->p_sys->b_chapter_update = 0;\r
+ }\r
+\r
+ /* look for selected ES */\r
+ p_audio_es = NULL;\r
+ p_spu_es = NULL;\r
+\r
+ for( i = 0; i < p_intfGlobal->p_sys->p_input->stream.i_selected_es_number; i++ )\r
+ {\r
+ if( p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i]->i_cat\r
+ == AUDIO_ES )\r
+ {\r
+ p_audio_es = p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i];\r
+ p_intfGlobal->p_sys->p_audio_es_old = p_audio_es;\r
+ }\r
+\r
+ if( p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i]->i_cat\r
+ == SPU_ES )\r
+ {\r
+ p_spu_es = p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i];\r
+ p_intfGlobal->p_sys->p_spu_es_old = p_spu_es;\r
+ }\r
+ }\r
+\r
+ vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+\r
+ /* audio menus */\r
+ if( p_intf->p_sys->b_audio_update )\r
+ {\r
+ LanguageMenu( p_window->MenuAudio, p_audio_es, AUDIO_ES,\r
+ p_window->MenuAudioClick );\r
+ LanguageMenu( p_window->PopupAudio, p_audio_es, AUDIO_ES,\r
+ p_window->PopupAudioClick );\r
+\r
+ p_intf->p_sys->b_audio_update = 0;\r
+ }\r
+\r
+ /* sub picture menus */\r
+ if( p_intf->p_sys->b_spu_update )\r
+ {\r
+ LanguageMenu( p_window->PopupSubtitles, p_spu_es, SPU_ES,\r
+ p_window->PopupSubtitleClick );\r
+ LanguageMenu( p_window->MenuSubtitles, p_spu_es, SPU_ES,\r
+ p_window->MenuSubtitleClick );\r
+\r
+ p_intf->p_sys->b_spu_update = 0;\r
+ }\r
+\r
+ vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
+\r
+ return true;\r
+}\r
+\r
+\r
+\r
--- /dev/null
+/*****************************************************************************\r
+ * menu.h: prototypes for menu functions\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+int __fastcall SetupMenus( intf_thread_t * );\r
+\r
+/*****************************************************************************\r
+ * Convert user_data structures to title and chapter information\r
+ *****************************************************************************/\r
+#define DATA2TITLE( data ) ( (int)((long)(data)) >> 16 )\r
+#define DATA2CHAPTER( data ) ( (int)((long)(data)) & 0xffff )\r
+#define POS2DATA( title, chapter ) ( NULL + ( ((title) << 16) \\r
+ | ((chapter) & 0xffff)) )\r
+\r
--- /dev/null
+/*****************************************************************************\r
+ * messages.cpp: log window.\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "win32_common.h"\r
+#include "messages.h"\r
+\r
+//---------------------------------------------------------------------------\r
+#pragma package(smart_init)\r
+#pragma resource "*.dfm"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+//---------------------------------------------------------------------------\r
+__fastcall TMessagesDlg::TMessagesDlg( TComponent* Owner )\r
+ : TForm( Owner )\r
+{\r
+ Icon = p_intfGlobal->p_sys->p_window->Icon;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMessagesDlg::ButtonOKClick( TObject *Sender )\r
+{\r
+ Hide();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMessagesDlg::FormHide( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuMessages->Checked = false;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMessagesDlg::FormShow( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuMessages->Checked = true;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TMessagesDlg::UpdateLog()\r
+{\r
+ msg_subscription_t *p_sub = p_intfGlobal->p_sys->p_sub;\r
+ int i_start, i_stop, i_del, i_count;\r
+ int i_max_lines;\r
+\r
+ vlc_mutex_lock( p_sub->p_lock );\r
+ i_stop = *p_sub->pi_stop;\r
+ vlc_mutex_unlock( p_sub->p_lock );\r
+\r
+ if( p_sub->i_start != i_stop )\r
+ {\r
+ for( i_start = p_sub->i_start;\r
+ i_start != i_stop;\r
+ i_start = (i_start+1) % VLC_MSG_QSIZE )\r
+ {\r
+ /* Append all messages to log window */\r
+ switch( p_sub->p_msg[i_start].i_type )\r
+ {\r
+ case VLC_MSG_ERR:\r
+ RichEditMessages->SelAttributes->Color = clRed;\r
+ break;\r
+ case VLC_MSG_WARN:\r
+ RichEditMessages->SelAttributes->Color = clBlack;\r
+ break;\r
+ default:\r
+ RichEditMessages->SelAttributes->Color = clBlue;\r
+ break;\r
+ }\r
+\r
+ /* Limit log size */\r
+ i_count = RichEditMessages->Lines->Count;\r
+ i_max_lines = config_GetInt( p_intfGlobal, "intfwin-max-lines" );\r
+ if( i_max_lines > 0 )\r
+ {\r
+ for( i_del = 0; i_del <= i_count - i_max_lines; i_del++ )\r
+ {\r
+ RichEditMessages->Lines->Delete( 0 );\r
+ }\r
+ }\r
+\r
+ /* Add message */\r
+ if( i_max_lines )\r
+ {\r
+ RichEditMessages->Lines->Add( p_sub->p_msg[i_start].psz_msg );\r
+ }\r
+ }\r
+\r
+ vlc_mutex_lock( p_sub->p_lock );\r
+ p_sub->i_start = i_start;\r
+ vlc_mutex_unlock( p_sub->p_lock );\r
+ } \r
+}\r
+//---------------------------------------------------------------------------\r
--- /dev/null
+object MessagesDlg: TMessagesDlg\r
+ Left = 325\r
+ Top = 160\r
+ Width = 440\r
+ Height = 502\r
+ Caption = 'Messages'\r
+ Color = clBtnFace\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clPurple\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ OldCreateOrder = False\r
+ OnHide = FormHide\r
+ OnShow = FormShow\r
+ PixelsPerInch = 96\r
+ TextHeight = 13\r
+ object RichEditMessages: TRichEdit\r
+ Left = 0\r
+ Top = 0\r
+ Width = 432\r
+ Height = 424\r
+ Align = alTop\r
+ Anchors = [akLeft, akTop, akRight, akBottom]\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clBlack\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ ParentFont = False\r
+ ReadOnly = True\r
+ ScrollBars = ssBoth\r
+ TabOrder = 0\r
+ WantReturns = False\r
+ end\r
+ object ButtonOK: TButton\r
+ Left = 144\r
+ Top = 437\r
+ Width = 145\r
+ Height = 25\r
+ Anchors = [akBottom]\r
+ Caption = 'OK'\r
+ TabOrder = 1\r
+ OnClick = ButtonOKClick\r
+ end\r
+end\r
--- /dev/null
+/*****************************************************************************\r
+ * messages.h: log window\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#ifndef messagesH\r
+#define messagesH\r
+//---------------------------------------------------------------------------\r
+#include <Classes.hpp>\r
+#include <Controls.hpp>\r
+#include <StdCtrls.hpp>\r
+#include <Forms.hpp>\r
+#include <ComCtrls.hpp>\r
+#include <Menus.hpp>\r
+//---------------------------------------------------------------------------\r
+class TMessagesDlg : public TForm\r
+{\r
+__published: // IDE-managed Components\r
+ TRichEdit *RichEditMessages;\r
+ TButton *ButtonOK;\r
+ void __fastcall ButtonOKClick( TObject *Sender );\r
+ void __fastcall FormHide( TObject *Sender );\r
+ void __fastcall FormShow( TObject *Sender );\r
+private: // User declarations\r
+public: // User declarations\r
+ __fastcall TMessagesDlg( TComponent* Owner );\r
+ void __fastcall UpdateLog();\r
+};\r
+//---------------------------------------------------------------------------\r
+#endif\r
--- /dev/null
+/*****************************************************************************\r
+ * network.cpp: the "network" dialog box\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "network.h"\r
+#include "win32_common.h"\r
+\r
+#include "netutils.h"\r
+\r
+//---------------------------------------------------------------------------\r
+//#pragma package(smart_init)\r
+#pragma link "CSPIN"\r
+#pragma resource "*.dfm"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+//---------------------------------------------------------------------------\r
+__fastcall TNetworkDlg::TNetworkDlg( TComponent* Owner )\r
+ : TForm( Owner )\r
+{\r
+ char *psz_channel_server;\r
+\r
+ OldRadioValue = 0;\r
+\r
+ /* server port */\r
+ SpinEditUDPPort->Value = config_GetInt( p_intfGlobal, "server-port" );\r
+ SpinEditMulticastPort->Value = config_GetInt( p_intfGlobal, "server-port" );\r
+\r
+ /* channel server */\r
+ if( config_GetInt( p_intfGlobal, "network-channel" ) )\r
+ {\r
+ RadioButtonCS->Checked = true;\r
+ RadioButtonCSEnter( RadioButtonCS );\r
+ }\r
+\r
+ psz_channel_server = config_GetPsz( p_intfGlobal, "channel-server" );\r
+ if( psz_channel_server )\r
+ {\r
+ ComboBoxCSAddress->Text = psz_channel_server;\r
+ free( psz_channel_server );\r
+ }\r
+\r
+ SpinEditCSPort->Value = config_GetInt( p_intfGlobal, "channel-port" );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::FormShow( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuNetworkStream->Checked = true;\r
+ p_intfGlobal->p_sys->p_window->PopupNetworkStream->Checked = true;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::FormHide( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuNetworkStream->Checked = false;\r
+ p_intfGlobal->p_sys->p_window->PopupNetworkStream->Checked = false;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::BitBtnCancelClick( TObject *Sender )\r
+{\r
+ Hide();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::BitBtnOkClick( TObject *Sender )\r
+{\r
+ AnsiString Source, Address;\r
+ AnsiString Channel = ComboBoxCSAddress->Text;\r
+ unsigned int i_channel_port = SpinEditCSPort->Value;\r
+ unsigned int i_port;\r
+ playlist_t * p_playlist;\r
+\r
+ p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ { \r
+ return;\r
+ } \r
+\r
+ Hide();\r
+\r
+ /* Check which option was chosen */\r
+ switch( OldRadioValue )\r
+ {\r
+ /* UDP */\r
+ case 0:\r
+ config_PutInt( p_intfGlobal, "network-channel", FALSE );\r
+ i_port = SpinEditUDPPort->Value;\r
+\r
+ /* Build source name */\r
+ Source = "udp:@:" + IntToStr( i_port );\r
+\r
+ playlist_Add( p_playlist, Source.c_str(),\r
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );\r
+\r
+ /* update the display */\r
+ p_intfGlobal->p_sys->p_playwin->UpdateGrid( p_playlist );\r
+ break;\r
+\r
+ /* UDP Multicast */\r
+ case 1:\r
+ config_PutInt( p_intfGlobal, "network-channel", FALSE );\r
+ Address = ComboBoxMulticastAddress->Text;\r
+ i_port = SpinEditMulticastPort->Value;\r
+\r
+ /* Build source name */\r
+ Source = "udp:@" + Address + ":" + IntToStr( i_port );\r
+\r
+ playlist_Add( p_playlist, Source.c_str(),\r
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );\r
+\r
+ /* update the display */\r
+ p_intfGlobal->p_sys->p_playwin->UpdateGrid( p_playlist );\r
+ break;\r
+\r
+ /* Channel server */\r
+ case 2:\r
+ config_PutInt( p_intfGlobal, "network-channel", TRUE );\r
+ config_PutPsz( p_intfGlobal, "channel-server", Channel.c_str() );\r
+ config_PutInt( p_intfGlobal, "channel-port", i_channel_port );\r
+\r
+ if( p_intfGlobal->p_vlc->p_channel == NULL )\r
+ {\r
+ network_ChannelCreate( p_intfGlobal );\r
+ }\r
+\r
+ p_intfGlobal->p_sys->b_playing = 1;\r
+ break;\r
+\r
+ /* HTTP */\r
+ case 3:\r
+ config_PutInt( p_intfGlobal, "network-channel", FALSE );\r
+ Address = EditHTTPURL->Text;\r
+\r
+ /* Build source name with a basic test */\r
+ if( Address.SubString( 1, 4 ) == "http" )\r
+ {\r
+ Source = Address;\r
+ }\r
+ else\r
+ {\r
+ Source = "http://" + Address;\r
+ }\r
+\r
+ playlist_Add( p_playlist, Source.c_str(),\r
+ PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );\r
+\r
+ /* update the display */\r
+ p_intfGlobal->p_sys->p_playwin->UpdateGrid( p_playlist );\r
+ break;\r
+ }\r
+\r
+ vlc_object_release( p_playlist );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::ChangeEnabled( int i_selected )\r
+{\r
+ switch( i_selected )\r
+ {\r
+ case 0:\r
+ LabelUDPPort->Enabled = NOT( LabelUDPPort->Enabled );\r
+ SpinEditUDPPort->Enabled = NOT( SpinEditUDPPort->Enabled );\r
+ break;\r
+ case 1:\r
+ LabelMulticastAddress->Enabled =\r
+ NOT( LabelMulticastAddress->Enabled );\r
+ ComboBoxMulticastAddress->Enabled =\r
+ NOT( ComboBoxMulticastAddress->Enabled );\r
+ LabelMulticastPort->Enabled = NOT( LabelMulticastPort->Enabled );\r
+ SpinEditMulticastPort->Enabled = NOT( SpinEditMulticastPort->Enabled );\r
+ break;\r
+ case 2:\r
+ LabelCSAddress->Enabled = NOT( LabelCSAddress->Enabled );\r
+ ComboBoxCSAddress->Enabled = NOT( ComboBoxCSAddress->Enabled );\r
+ LabelCSPort->Enabled = NOT( LabelCSPort->Enabled );\r
+ SpinEditCSPort->Enabled = NOT( SpinEditCSPort->Enabled );\r
+ break;\r
+ case 3:\r
+ LabelHTTPURL->Enabled = NOT( LabelHTTPURL->Enabled );\r
+ EditHTTPURL->Enabled = NOT( EditHTTPURL->Enabled );\r
+ break;\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::RadioButtonUDPEnter( TObject *Sender )\r
+{\r
+ ChangeEnabled( OldRadioValue );\r
+ OldRadioValue = 0;\r
+ ChangeEnabled( OldRadioValue );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::RadioButtonMulticastEnter( TObject *Sender )\r
+{\r
+ ChangeEnabled( OldRadioValue );\r
+ OldRadioValue = 1;\r
+ ChangeEnabled( OldRadioValue );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::RadioButtonCSEnter( TObject *Sender )\r
+{\r
+ ChangeEnabled( OldRadioValue );\r
+ OldRadioValue = 2;\r
+ ChangeEnabled( OldRadioValue );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TNetworkDlg::RadioButtonHTTPEnter( TObject *Sender )\r
+{\r
+ ChangeEnabled( OldRadioValue );\r
+ OldRadioValue = 3;\r
+ ChangeEnabled( OldRadioValue );\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
--- /dev/null
+object NetworkDlg: TNetworkDlg\r
+ Left = 369\r
+ Top = 301\r
+ BorderStyle = bsDialog\r
+ Caption = 'Open network'\r
+ ClientHeight = 206\r
+ ClientWidth = 482\r
+ Color = clBtnFace\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clWindowText\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ Icon.Data = {\r
+ 0000010001003030000001001800A81C00001600000028000000300000006000\r
+ 00000100180000000000001B0000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000069375900000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000120E0A4011253E0F18000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000F0B\r
+ 084143CA08070016430F08040800000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000003127291203174647E8464AE808010840E54039E6390B0C06\r
+ 0E0A1C0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0070CD0079DD0079DD0070CD0000000000000000000C1008261D6E4647E54547\r
+ E64748E105040039E6393AE53939E63936D33308030100000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000070CD0079DD0079DE007DE40088F9008CFF008CFF0088F9007CE302\r
+ 6EC70B09124641DC4444DF4546E34446E54847E003040040E6403AEA3A3EE33E\r
+ 3CE33C39E639080F010801050000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0079DD0077D90070CB0078D8007BDC007BDC007BDC\r
+ 007BDC007BDC007BDD007EE32E232D0804084553F14250F34252ED4449DB4844\r
+ DC4645E208010540E5401C78150D18053CE63C3AE63A39EA393CD83C241A2006\r
+ 0402000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0079DD007ADF007BDE007BDC0072\r
+ CC005188004877004876004876004876034976054A760B4D7731434221175B42\r
+ 54EC4253EE4252F60B05104250F44252EB4546DA08010539E6392BAA2B080105\r
+ 3CE63C39E7393AE63A39E93939E839081208181C080000000000000000000000\r
+ 000000000000000000000000000000000000000070CD0079DD0079DD007CE300\r
+ 88F90089F90075D2005188004877005188008CFF008CFF008CFF008CFF008CFF\r
+ 1092FF2099FF31A0FF1408294840DB4550E1464EEA0C060B0B05084654F64653\r
+ F64453EF080E033AE63A2BAA2B03030339E33939DF3939E639080F083DDB3D24\r
+ 9C24434B3B000000000000000000000000000000000000000000000000000000\r
+ 0063B60085F3008BFE0088F9007FE90088F90080E8005CA0008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF048DFF1594FF259BFF35A2FF0C04103F38C754\r
+ 5AF7505BF10C08100801084352F64652F44253F30813053AE63A39E639030403\r
+ 1C521826A1250812010807032454131558150000000000000000000000000000\r
+ 000000000000000000000000000000000000000070CD007CE30079DD00000000\r
+ 7CE30089FA008CFF0089FA008CFF008CFF008CFF008CFF008CFF008CFF098FFF\r
+ 1996FF2A9DFF3AA4FF0804103A2AA34E58F74E58F40B0B120803054652F34548\r
+ E64451F305130532CA323AE23A03070308070307040008040139E63939E43931\r
+ B42F5E1347000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000061B10000000079DD008CFF008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF0E91FF1E98FF2E9FFF3FA6FF040408382BAF4D\r
+ 5AEF555AF70F12250501050F04160804074250F3121A123AE93A39E239080803\r
+ 0D2F08010401268C2539E7393DE63D3FE23E0804100000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 79DD008CFF008CFF008CFF008CFF008CFF008CFF008CFF008CFF028CFF1293FF\r
+ 239AFF33A1FF43A8FF0802083A2AA3565BF7555AF71714330501050104000801\r
+ 07424FF12828203AEA3A39E639030703182F1008340801040139E7393DE83D39\r
+ E939080400000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0088F9008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF078EFF1795FF279CFF38A3FF48AAFF0808005151F155\r
+ 5AF30804030804000504050800082E358E0E0C1F1D192439E53940E640080400\r
+ 2AA12739E63908020708010539E8393BE93B0804080000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000007CE3008CFF008CFF008CFF058EFD1D96F92398F8269AFA31A0FC42A8FF\r
+ 4FAEFF5CB3FF65B7FF0C08084F5AF14E57F50B04080804043639A54647E81C13\r
+ 49363AA70804080F120835953439E7393EE63E39DF3939EA39081105308A2B3F\r
+ E73F080601000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000047BDB1D96F92398F82498F83BA0\r
+ F399C1E1B1C9DDBCD4E7CBE0F3D9EDFFDCEEFFDEEFFFCDE8FF080808575BF750\r
+ 58F624125A5057F34845DF4A41E0150E30C55734E3723EC56E33A23D27050105\r
+ 39E43939E63939E6393CE63C14420C3BE03B192A090000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000004\r
+ 04042D88D399C1E1B1C9DDB1C9DCB7CBDBCFD3D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFF9FCFF0C08085D61F15B61EF555AF64A4FE13937BB0E0A12DE74\r
+ 39E1733CDE713CDF753AE67541C36B342C231F17141B3AE63A39E7393DE83D39\r
+ E93939DE39000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000001818186893B8C3CCD2D5D5D6D5D5D6D5D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFFFFFFFFFFFF140C145C5EF668\r
+ 63F75555EA10061CC3673FDF713A0C1104080403080105080007070407D56F36\r
+ DE743EDE72401C200C29452939E63939E73939EA390000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000343434A2B4C2D5D5D6D6D6D6D6D6D6D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFFEFEFF20161C5C5EF6373EAE0E0413E2713DE1763CCD6A3C2A0D\r
+ 08A44B2CDE743EBD612F080401030403E1713CDE7239DE713AE1723C22201139\r
+ C13341E641000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001B1B1B99AEBED5D5D6D5D5D6D5D5\r
+ D6CFD3D7B8CBDBBFD5E7CEE2F3DCEFFFDFF0FFE2F1FFE9F4FF10100C3639A46E\r
+ 4540DE7239DE713DE1713C07000784261CDE7639E3743E0812001F0407D86E36\r
+ E3753EE57540E57541DE763CDE733DD26637493C387E2F7B0000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00001B1B1B99AEBFCED3D7B7CBDBB1C9DD99C1E140A2F339A2FA49AAFC59B2FF\r
+ 66B8FF74BEFF92CBFFD9ECFF0F0402C66531DE7139E2733D854B1E0A01084D11\r
+ 0DE3733EE1723CDF713ADF753AE1763C1D0A08290708E57140E1763CDE733DC7\r
+ 6B34080408000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001818187FA5C399C1E13BA0F32498\r
+ F81D96F91091FD1C97FF2C9EFF3CA5FF4DACFF5DB3FF71BBFF8DC8FF9FD0FF08\r
+ 0400080406B95C2EDE7239070B070803014D1615DE723CDE7540E5714030090D\r
+ 0504003A120FE67541DE75390808044A0C290000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000707071778C81C92F3058EFD008CFF008CFF1092FF2099FF31A0FF41A7FF\r
+ 51AEFF62B5FF72BCFF7BBFFF7BBBF96E9FCD0808080806041D0508E571403E22\r
+ 0C200708080405070407070007080303B05F31DE723967301908010500000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000007CE3008CFF008C\r
+ FF048DFF1594FF259BFF35A2FF46A9FF56B0FF66B7FF77BEFF7BBFFF6DAAE300\r
+ 0000000000000000000000080401200C088D4024E17141E57140DF713ADE713E\r
+ DE76390801070000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000079DD008CFF008CFF098FFF1996FF2A9DFF3AA4FF4AABFF\r
+ 5BB2FF6BB9FF7BBFFF7BBFFF6AA5DD0000000000000000000000000000001D1A\r
+ 0C1A0F08110903441912E57140623B1E08020300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000079DD008CFF008C\r
+ FF0E91FF1E98FF2E9FFF3FA6FF4FADFF5FB4FF70BBFF7BBFFF78BAF96299CD00\r
+ 00000000000000000000000000000000000000003914100000005A2411000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0088F9078EFD2C9CF940A3F850ACFA60B4FC70BCFF\r
+ 7DC2FF87C6FF7EC0FF6DAAE30000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000707071A85DD40A2\r
+ F3A0C3E1B7CBDDC6D8E7D4E5F3E2F1FFE5F2FFD9ECFF9FD0FF7AACDD05050500\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001818187FA5C3B8CBDBD0D4D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFAFCFFE2EDF99FB7CD1C1C1C0000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000001B1B1B99AEBFD4D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFEFEFFD1DAE33E3E3E00000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001D1D1D7B9BB4CACED1D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFC9D2DD2121210000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000343434A5B5\r
+ C2CFD3D7BFCEDBC9D9E7D7E6F3E6F3FFECF5FFF0F4F9AEBDCD23232300000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000018181887A8C3A6C6E169B3F367B6FA77BEFC88C6FF\r
+ 9FD0FFB4CBE33939390000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000040404338C\r
+ D749A8F947A9FD54AFFF64B6FF74BDFF7EC0FF76ABDD05050500000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000001F7DCD369FF948AAFF58B1FF69B8FF79BFFF\r
+ 78BAF96299CD0000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003592E34DACFF5DB3FF6DBAFF7BBFFF6DAAE300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003890DD51AEFF62B5FF72BCFF7BBFFF\r
+ 6AA5DD0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003B8FD84C9CE3589FDE69A9E375B6F46299CD00000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003376B00000000000000000005788B6\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000006CC61A83DD247FCC00000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000006DC71A83DD2686D71F6EB1\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFE1FDFFF0000FFFFE0078FFF0000FFFE\r
+ 000007FF0000FFF0000001FF0000FF80000000FF0000FF000000003F0000FF00\r
+ 0000000F0000FE00000000070000F800000000070000F8000000000F0000FC00\r
+ 000000070000FE00000000070000FF80000000070000FFC0000000070000FFE0\r
+ 000000070000FFE0000000070000FFE0000000070000FFE0000000070000FFF0\r
+ 000000070000FFF0000000030000FFF0000000070000FFF00000000F0000FFF0\r
+ 0000003F0000FFF8000E00FF0000FFF8000F01FF0000FFF8000FD7FF0000FFF8\r
+ 001FFFFF0000FFFC001FFFFF0000FFFC001FFFFF0000FFFC003FFFFF0000FFFC\r
+ 003FFFFF0000FFFE003FFFFF0000FFFE007FFFFF0000FFFE007FFFFF0000FFFE\r
+ 007FFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF\r
+ 01FFFFFF0000FFFF01FFFFFF0000FFFF81FFFFFF0000FFFFC3FFFFFF0000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000}\r
+ OldCreateOrder = False\r
+ OnHide = FormHide\r
+ OnShow = FormShow\r
+ PixelsPerInch = 96\r
+ TextHeight = 13\r
+ object BitBtnOk: TBitBtn\r
+ Left = 40\r
+ Top = 168\r
+ Width = 177\r
+ Height = 25\r
+ TabOrder = 0\r
+ OnClick = BitBtnOkClick\r
+ Kind = bkOK\r
+ end\r
+ object BitBtnCancel: TBitBtn\r
+ Left = 256\r
+ Top = 168\r
+ Width = 177\r
+ Height = 25\r
+ TabOrder = 1\r
+ OnClick = BitBtnCancelClick\r
+ Kind = bkCancel\r
+ end\r
+ object GroupBoxMode: TGroupBox\r
+ Left = 8\r
+ Top = 8\r
+ Width = 465\r
+ Height = 145\r
+ Caption = 'Network mode'\r
+ TabOrder = 2\r
+ object LabelUDPPort: TLabel\r
+ Left = 148\r
+ Top = 26\r
+ Width = 22\r
+ Height = 13\r
+ Caption = 'Port:'\r
+ end\r
+ object LabelMulticastPort: TLabel\r
+ Left = 364\r
+ Top = 54\r
+ Width = 22\r
+ Height = 13\r
+ Caption = 'Port:'\r
+ Enabled = False\r
+ end\r
+ object LabelCSPort: TLabel\r
+ Left = 364\r
+ Top = 82\r
+ Width = 22\r
+ Height = 13\r
+ Caption = 'Port:'\r
+ Enabled = False\r
+ end\r
+ object LabelMulticastAddress: TLabel\r
+ Left = 139\r
+ Top = 54\r
+ Width = 41\r
+ Height = 13\r
+ Caption = 'Address:'\r
+ Enabled = False\r
+ end\r
+ object LabelCSAddress: TLabel\r
+ Left = 139\r
+ Top = 82\r
+ Width = 41\r
+ Height = 13\r
+ Caption = 'Address:'\r
+ Enabled = False\r
+ end\r
+ object LabelHTTPURL: TLabel\r
+ Left = 147\r
+ Top = 110\r
+ Width = 25\r
+ Height = 13\r
+ Caption = 'URL:'\r
+ Enabled = False\r
+ end\r
+ object RadioButtonUDP: TRadioButton\r
+ Left = 16\r
+ Top = 24\r
+ Width = 97\r
+ Height = 17\r
+ Caption = 'UDP'\r
+ Checked = True\r
+ TabOrder = 0\r
+ TabStop = True\r
+ OnEnter = RadioButtonUDPEnter\r
+ end\r
+ object RadioButtonMulticast: TRadioButton\r
+ Left = 16\r
+ Top = 52\r
+ Width = 97\r
+ Height = 17\r
+ Caption = 'UDP Multicast'\r
+ TabOrder = 1\r
+ OnEnter = RadioButtonMulticastEnter\r
+ end\r
+ object RadioButtonCS: TRadioButton\r
+ Left = 16\r
+ Top = 80\r
+ Width = 97\r
+ Height = 17\r
+ Caption = 'Channel Server'\r
+ TabOrder = 2\r
+ OnEnter = RadioButtonCSEnter\r
+ end\r
+ object RadioButtonHTTP: TRadioButton\r
+ Left = 16\r
+ Top = 108\r
+ Width = 97\r
+ Height = 17\r
+ Caption = 'HTTP'\r
+ TabOrder = 3\r
+ OnEnter = RadioButtonHTTPEnter\r
+ end\r
+ object ComboBoxMulticastAddress: TComboBox\r
+ Left = 184\r
+ Top = 50\r
+ Width = 161\r
+ Height = 21\r
+ Enabled = False\r
+ ItemHeight = 13\r
+ TabOrder = 5\r
+ end\r
+ object ComboBoxCSAddress: TComboBox\r
+ Left = 184\r
+ Top = 78\r
+ Width = 161\r
+ Height = 21\r
+ Enabled = False\r
+ ItemHeight = 13\r
+ TabOrder = 7\r
+ Text = 'vlcs'\r
+ Items.Strings = (\r
+ 'vlcs')\r
+ end\r
+ object EditHTTPURL: TEdit\r
+ Left = 184\r
+ Top = 106\r
+ Width = 265\r
+ Height = 21\r
+ Enabled = False\r
+ TabOrder = 9\r
+ end\r
+ object SpinEditUDPPort: TCSpinEdit\r
+ Left = 184\r
+ Top = 21\r
+ Width = 57\r
+ Height = 22\r
+ TabStop = True\r
+ MaxValue = 65535\r
+ ParentColor = False\r
+ TabOrder = 4\r
+ Value = 1234\r
+ end\r
+ object SpinEditMulticastPort: TCSpinEdit\r
+ Left = 392\r
+ Top = 49\r
+ Width = 57\r
+ Height = 22\r
+ TabStop = True\r
+ Enabled = False\r
+ MaxValue = 65535\r
+ ParentColor = False\r
+ TabOrder = 6\r
+ Value = 1234\r
+ end\r
+ object SpinEditCSPort: TCSpinEdit\r
+ Left = 392\r
+ Top = 77\r
+ Width = 57\r
+ Height = 22\r
+ TabStop = True\r
+ Enabled = False\r
+ MaxValue = 65535\r
+ ParentColor = False\r
+ TabOrder = 8\r
+ Value = 6010\r
+ end\r
+ end\r
+end\r
--- /dev/null
+/*****************************************************************************\r
+ * network.h: the "network" dialog box\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#ifndef networkH\r
+#define networkH\r
+//---------------------------------------------------------------------------\r
+#include <Classes.hpp>\r
+#include <Controls.hpp>\r
+#include <StdCtrls.hpp>\r
+#include <Forms.hpp>\r
+#include <Buttons.hpp>\r
+#include <ComCtrls.hpp>\r
+#include <ExtCtrls.hpp>\r
+#include "CSPIN.h"\r
+//---------------------------------------------------------------------------\r
+\r
+#define NOT( var ) ( (var) ? false : true )\r
+\r
+class TNetworkDlg : public TForm\r
+{\r
+__published: // IDE-managed Components\r
+ TBitBtn *BitBtnOk;\r
+ TBitBtn *BitBtnCancel;\r
+ TGroupBox *GroupBoxMode;\r
+ TRadioButton *RadioButtonUDP;\r
+ TRadioButton *RadioButtonMulticast;\r
+ TRadioButton *RadioButtonCS;\r
+ TRadioButton *RadioButtonHTTP;\r
+ TLabel *LabelUDPPort;\r
+ TLabel *LabelMulticastPort;\r
+ TLabel *LabelCSPort;\r
+ TLabel *LabelMulticastAddress;\r
+ TComboBox *ComboBoxMulticastAddress;\r
+ TLabel *LabelCSAddress;\r
+ TComboBox *ComboBoxCSAddress;\r
+ TEdit *EditHTTPURL;\r
+ TLabel *LabelHTTPURL;\r
+ TCSpinEdit *SpinEditUDPPort;\r
+ TCSpinEdit *SpinEditMulticastPort;\r
+ TCSpinEdit *SpinEditCSPort;\r
+ void __fastcall FormShow( TObject *Sender );\r
+ void __fastcall FormHide( TObject *Sender );\r
+ void __fastcall BitBtnCancelClick( TObject *Sender );\r
+ void __fastcall BitBtnOkClick( TObject *Sender );\r
+ void __fastcall RadioButtonUDPEnter( TObject *Sender );\r
+ void __fastcall RadioButtonMulticastEnter( TObject *Sender );\r
+ void __fastcall RadioButtonCSEnter( TObject *Sender );\r
+ void __fastcall RadioButtonHTTPEnter( TObject *Sender );\r
+private: // User declarations\r
+ int OldRadioValue;\r
+ void __fastcall ChangeEnabled( int i_selected );\r
+public: // User declarations\r
+ __fastcall TNetworkDlg( TComponent* Owner );\r
+};\r
+//---------------------------------------------------------------------------\r
+#endif\r
--- /dev/null
+/*****************************************************************************\r
+ * playlist.cpp: Interface for the playlist dialog\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "playlist.h"\r
+#include "win32_common.h"\r
+\r
+//---------------------------------------------------------------------------\r
+//#pragma package(smart_init)\r
+#pragma resource "*.dfm"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+//---------------------------------------------------------------------------\r
+__fastcall TPlaylistDlg::TPlaylistDlg( TComponent* Owner )\r
+ : TForm( Owner )\r
+{\r
+ Icon = p_intfGlobal->p_sys->p_window->Icon;\r
+}\r
+//---------------------------------------------------------------------------\r
+char * __fastcall TPlaylistDlg::rindex( char *s, char c )\r
+{\r
+ char *ref = s;\r
+\r
+ s = s + strlen( s ) - 2;\r
+ while( ( s > ref ) && ( *s != c ) )\r
+ {\r
+ s--;\r
+ }\r
+ if( *s == c )\r
+ {\r
+ return( s );\r
+ }\r
+ else\r
+ {\r
+ return( NULL );\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Event handlers\r
+ ****************************************************************************/\r
+void __fastcall TPlaylistDlg::FormShow( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuPlaylist->Checked = true;\r
+ p_intfGlobal->p_sys->p_window->PopupPlaylist->Checked = true;\r
+ p_intfGlobal->p_sys->p_window->ToolButtonPlaylist->Down = true;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::FormHide( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuPlaylist->Checked = false;\r
+ p_intfGlobal->p_sys->p_window->PopupPlaylist->Checked = false;\r
+ p_intfGlobal->p_sys->p_window->ToolButtonPlaylist->Down = false;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::BitBtnOkClick( TObject *Sender )\r
+{\r
+ Hide();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::ListViewPlaylistDblClick( TObject *Sender )\r
+{\r
+ TListItem *Item;\r
+ TListItem *ItemStart;\r
+ TItemStates Focused;\r
+\r
+ playlist_t * p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ /* search the selected item */\r
+ if( ListViewPlaylist->SelCount > 0 )\r
+ {\r
+ if( ListViewPlaylist->SelCount == 1 )\r
+ {\r
+ Item = ListViewPlaylist->Selected;\r
+ }\r
+ else\r
+ {\r
+ Focused << isFocused;\r
+ ItemStart = ListViewPlaylist->Items->Item[0];\r
+\r
+ Item = ListViewPlaylist->GetNextItem( ItemStart, sdAll, Focused );\r
+ }\r
+\r
+ playlist_Goto( p_playlist, Item->Index - 1 );\r
+ }\r
+\r
+ vlc_object_release( p_playlist );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::ListViewPlaylistKeyDown( TObject *Sender,\r
+ WORD &Key, TShiftState Shift )\r
+{\r
+ /* 'suppr' or 'backspace' */\r
+ if( ( Key == VK_DELETE ) || ( Key == VK_BACK ) )\r
+ {\r
+ MenuDeleteSelectedClick( Sender );\r
+ }\r
+\r
+ /* 'enter' */\r
+ if( Key == VK_RETURN )\r
+ {\r
+ PopupPlayClick( Sender );\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::ListViewPlaylistCustomDrawItem(\r
+ TCustomListView *Sender, TListItem *Item, TCustomDrawState State,\r
+ bool &DefaultDraw)\r
+{\r
+ TRect Rect = Item->DisplayRect( drBounds );\r
+\r
+ /* set the background color */\r
+ if( Item->Index == p_intfGlobal->p_sys->i_playing )\r
+ {\r
+ Sender->Canvas->Brush->Color = clRed;\r
+ }\r
+ else\r
+ {\r
+ Sender->Canvas->Brush->Color = clWhite;\r
+ }\r
+\r
+ Sender->Canvas->FillRect( Rect );\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Menu callbacks\r
+ ****************************************************************************/\r
+void __fastcall TPlaylistDlg::MenuAddFileClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuOpenFileClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::MenuAddDiscClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuOpenDiscClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::MenuAddNetClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->MenuNetworkStreamClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::MenuAddUrlClick( TObject *Sender )\r
+{\r
+ /* TODO */\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::MenuDeleteSelectedClick( TObject *Sender )\r
+{\r
+#if 0 /* PLAYLIST TARASS */\r
+ /* user wants to delete a file in the queue */\r
+ int i_pos;\r
+ playlist_t *p_playlist = p_intfGlobal->p_vlc->p_playlist;\r
+\r
+ /* lock the struct */\r
+ vlc_mutex_lock( &p_intfGlobal->change_lock );\r
+\r
+ /* delete the items from the last to the first */\r
+ for( i_pos = p_playlist->i_size - 1; i_pos >= 0; i_pos-- )\r
+ {\r
+ if( ListViewPlaylist->Items->Item[i_pos]->Selected )\r
+ {\r
+ DeleteItem( i_pos );\r
+ }\r
+ }\r
+\r
+ /* Rebuild the ListView */\r
+ UpdateGrid( p_playlist );\r
+\r
+ vlc_mutex_unlock( &p_intfGlobal->change_lock );\r
+#endif\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::MenuDeleteAllClick( TObject *Sender )\r
+{\r
+#if 0 /* PLAYLIST TARASS */\r
+ int i_pos;\r
+ playlist_t *p_playlist = p_intfGlobal->p_vlc->p_playlist;\r
+\r
+ /* lock the struct */\r
+ vlc_mutex_lock( &p_intfGlobal->change_lock );\r
+\r
+ /* delete the items from the last to the first */\r
+ for( i_pos = p_playlist->i_size - 1; i_pos >= 0; i_pos-- )\r
+ {\r
+ DeleteItem( i_pos );\r
+ }\r
+\r
+ /* Rebuild the ListView */\r
+ UpdateGrid( p_playlist );\r
+\r
+ vlc_mutex_unlock( &p_intfGlobal->change_lock );\r
+#endif\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::MenuSelectionInvertClick( TObject *Sender )\r
+{\r
+#if 0 /* PLAYLIST TARASS */\r
+#define NOT( var ) ( (var) ? false : true )\r
+ int i_pos;\r
+ playlist_t *p_playlist = p_intfGlobal->p_vlc->p_playlist;\r
+ TListItems *Items = ListViewPlaylist->Items;\r
+\r
+ /* delete the items from the last to the first */\r
+ for( i_pos = p_playlist->i_size - 1; i_pos >= 0; i_pos-- )\r
+ {\r
+ Items->Item[i_pos]->Selected = NOT( Items->Item[i_pos]->Selected );\r
+ }\r
+#undef NOT\r
+#endif\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::MenuSelectionCropClick( TObject *Sender )\r
+{\r
+ MenuSelectionInvertClick( Sender );\r
+ MenuDeleteSelectedClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Popup callbacks\r
+ ****************************************************************************/\r
+void __fastcall TPlaylistDlg::PopupPlayClick( TObject *Sender )\r
+{\r
+ ListViewPlaylistDblClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::PopupInvertSelectionClick( TObject *Sender )\r
+{\r
+ MenuSelectionInvertClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::PopupCropSelectionClick( TObject *Sender )\r
+{\r
+ MenuSelectionCropClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::PopupDeleteSelectedClick( TObject *Sender )\r
+{\r
+ MenuDeleteSelectedClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::PopupDeleteAllClick( TObject *Sender )\r
+{\r
+ MenuDeleteAllClick( Sender );\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+/*****************************************************************************\r
+ * Useful functions, needed by the event handlers\r
+ ****************************************************************************/\r
+void __fastcall TPlaylistDlg::UpdateGrid( playlist_t * p_playlist )\r
+{\r
+ int i_dummy;\r
+ char *FileName;\r
+ TListItem *Item;\r
+\r
+ ListViewPlaylist->Items->BeginUpdate();\r
+\r
+ /* Clear the list... */\r
+ ListViewPlaylist->Items->Clear();\r
+\r
+ /* ...and rebuild it */\r
+ for( i_dummy = 0; i_dummy < p_playlist->i_size; i_dummy++ )\r
+ {\r
+#ifdef WIN32\r
+ /* Position of the last '\' in the string */\r
+ FileName = rindex( p_playlist->pp_items[i_dummy]->psz_name, '\\' );\r
+#else\r
+ /* Position of the last '/' in the string */\r
+ FileName = rindex( p_playlist->pp_items[i_dummy]->psz_name, '/' );\r
+#endif\r
+ if( ( FileName == NULL ) || ( *(FileName + 1) == '\0' ) )\r
+ {\r
+ FileName = p_playlist->pp_items[i_dummy]->psz_name;\r
+ }\r
+ else\r
+ {\r
+ /* Skip leading '\' or '/' */\r
+ FileName++;\r
+ }\r
+\r
+ Item = ListViewPlaylist->Items->Add();\r
+ Item->Caption = FileName;\r
+ Item->SubItems->Add( "no info" );\r
+ }\r
+ /* TODO: Set background color ? */\r
+\r
+ ListViewPlaylist->Items->EndUpdate();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::Manage( intf_thread_t * p_intf )\r
+{\r
+ playlist_t * p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ vlc_mutex_lock( &p_playlist->object_lock );\r
+\r
+ if( p_intf->p_sys->i_playing != p_playlist->i_index )\r
+ {\r
+ p_intf->p_sys->i_playing = p_playlist->i_index;\r
+\r
+ /* update the background color */\r
+ UpdateGrid( p_playlist );\r
+ }\r
+\r
+ vlc_mutex_unlock( &p_playlist->object_lock );\r
+ vlc_object_release( p_playlist );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::DeleteItem( int i_pos )\r
+{\r
+ playlist_t * p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ playlist_Delete( p_playlist, i_pos );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::Previous()\r
+{\r
+ playlist_t * p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ playlist_Prev( p_playlist );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPlaylistDlg::Next()\r
+{\r
+ playlist_t * p_playlist = (playlist_t *)\r
+ vlc_object_find( p_intfGlobal, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
+ if( p_playlist == NULL )\r
+ {\r
+ return;\r
+ }\r
+\r
+ playlist_Next( p_playlist );\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
--- /dev/null
+object PlaylistDlg: TPlaylistDlg\r
+ Left = 447\r
+ Top = 197\r
+ Width = 335\r
+ Height = 436\r
+ Caption = 'Playlist'\r
+ Color = clBtnFace\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clWindowText\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ Menu = MainMenuPlaylist\r
+ OldCreateOrder = False\r
+ OnHide = FormHide\r
+ OnShow = FormShow\r
+ PixelsPerInch = 96\r
+ TextHeight = 13\r
+ object BitBtnOk: TBitBtn\r
+ Left = 76\r
+ Top = 356\r
+ Width = 176\r
+ Height = 25\r
+ Anchors = [akBottom]\r
+ Caption = 'OK'\r
+ ModalResult = 1\r
+ TabOrder = 0\r
+ OnClick = BitBtnOkClick\r
+ end\r
+ object ListViewPlaylist: TListView\r
+ Left = 11\r
+ Top = 10\r
+ Width = 305\r
+ Height = 331\r
+ Anchors = [akTop, akBottom]\r
+ Columns = <\r
+ item\r
+ Caption = 'Filename'\r
+ Width = 200\r
+ end\r
+ item\r
+ Alignment = taCenter\r
+ Caption = 'Duration'\r
+ Width = 100\r
+ end>\r
+ HideSelection = False\r
+ MultiSelect = True\r
+ ReadOnly = True\r
+ RowSelect = True\r
+ PopupMenu = PopupMenuPlaylist\r
+ TabOrder = 1\r
+ ViewStyle = vsReport\r
+ OnCustomDrawItem = ListViewPlaylistCustomDrawItem\r
+ OnDblClick = ListViewPlaylistDblClick\r
+ OnKeyDown = ListViewPlaylistKeyDown\r
+ end\r
+ object MainMenuPlaylist: TMainMenu\r
+ Left = 24\r
+ Top = 352\r
+ object MenuAdd: TMenuItem\r
+ Caption = '&Add'\r
+ object MenuAddFile: TMenuItem\r
+ Caption = '&File'\r
+ OnClick = MenuAddFileClick\r
+ end\r
+ object MenuAddDisc: TMenuItem\r
+ Caption = '&Disc'\r
+ OnClick = MenuAddDiscClick\r
+ end\r
+ object MenuAddNet: TMenuItem\r
+ Caption = '&Network'\r
+ OnClick = MenuAddNetClick\r
+ end\r
+ object MenuAddUrl: TMenuItem\r
+ Caption = '&Url'\r
+ Enabled = False\r
+ OnClick = MenuAddUrlClick\r
+ end\r
+ end\r
+ object MenuDelete: TMenuItem\r
+ Caption = '&Delete'\r
+ object MenuDeleteAll: TMenuItem\r
+ Caption = '&All'\r
+ OnClick = MenuDeleteAllClick\r
+ end\r
+ object MenuDeleteSelected: TMenuItem\r
+ Caption = '&Selected'\r
+ OnClick = MenuDeleteSelectedClick\r
+ end\r
+ end\r
+ object MenuSelection: TMenuItem\r
+ Caption = '&Selection'\r
+ object MenuSelectionCrop: TMenuItem\r
+ Caption = '&Crop'\r
+ OnClick = MenuSelectionCropClick\r
+ end\r
+ object MenuSelectionInvert: TMenuItem\r
+ Caption = '&Invert'\r
+ OnClick = MenuSelectionInvertClick\r
+ end\r
+ end\r
+ end\r
+ object PopupMenuPlaylist: TPopupMenu\r
+ Left = 272\r
+ Top = 352\r
+ object PopupPlay: TMenuItem\r
+ Caption = '&Play'\r
+ OnClick = PopupPlayClick\r
+ end\r
+ object N1: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object PopupInvertSelection: TMenuItem\r
+ Caption = '&Invert selection'\r
+ OnClick = PopupInvertSelectionClick\r
+ end\r
+ object PopupCropSelection: TMenuItem\r
+ Caption = '&Crop selection'\r
+ OnClick = PopupCropSelectionClick\r
+ end\r
+ object N2: TMenuItem\r
+ Caption = '-'\r
+ end\r
+ object PopupDeleteSelected: TMenuItem\r
+ Caption = '&Delete selected'\r
+ OnClick = PopupDeleteSelectedClick\r
+ end\r
+ object PopupDeleteAll: TMenuItem\r
+ Caption = 'Delete &all'\r
+ OnClick = PopupDeleteAllClick\r
+ end\r
+ end\r
+end\r
--- /dev/null
+/*****************************************************************************\r
+ * playlist.h: Interface for the playlist dialog\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#ifndef playlistH\r
+#define playlistH\r
+//---------------------------------------------------------------------------\r
+#include <Classes.hpp>\r
+#include <Controls.hpp>\r
+#include <StdCtrls.hpp>\r
+#include <Forms.hpp>\r
+#include <Buttons.hpp>\r
+#include <Menus.hpp>\r
+#include <Grids.hpp>\r
+#include <ComCtrls.hpp>\r
+\r
+//---------------------------------------------------------------------------\r
+class TPlaylistDlg : public TForm\r
+{\r
+__published: // IDE-managed Components\r
+ TBitBtn *BitBtnOk;\r
+ TMainMenu *MainMenuPlaylist;\r
+ TMenuItem *MenuAdd;\r
+ TMenuItem *MenuAddFile;\r
+ TMenuItem *MenuAddDisc;\r
+ TMenuItem *MenuAddNet;\r
+ TMenuItem *MenuAddUrl;\r
+ TMenuItem *MenuDelete;\r
+ TMenuItem *MenuDeleteAll;\r
+ TMenuItem *MenuDeleteSelected;\r
+ TMenuItem *MenuSelection;\r
+ TMenuItem *MenuSelectionCrop;\r
+ TMenuItem *MenuSelectionInvert;\r
+ TListView *ListViewPlaylist;\r
+ TPopupMenu *PopupMenuPlaylist;\r
+ TMenuItem *PopupPlay;\r
+ TMenuItem *N1;\r
+ TMenuItem *PopupDeleteAll;\r
+ TMenuItem *PopupDeleteSelected;\r
+ TMenuItem *N2;\r
+ TMenuItem *PopupInvertSelection;\r
+ TMenuItem *PopupCropSelection;\r
+ void __fastcall FormShow( TObject *Sender );\r
+ void __fastcall FormHide( TObject *Sender );\r
+ void __fastcall BitBtnOkClick( TObject *Sender );\r
+ void __fastcall ListViewPlaylistDblClick( TObject *Sender );\r
+ void __fastcall ListViewPlaylistKeyDown( TObject *Sender, WORD &Key,\r
+ TShiftState Shift );\r
+ void __fastcall ListViewPlaylistCustomDrawItem( TCustomListView *Sender,\r
+ TListItem *Item, TCustomDrawState State, bool &DefaultDraw );\r
+ void __fastcall MenuAddFileClick( TObject *Sender );\r
+ void __fastcall MenuAddDiscClick( TObject *Sender );\r
+ void __fastcall MenuAddNetClick( TObject *Sender );\r
+ void __fastcall MenuAddUrlClick( TObject *Sender );\r
+ void __fastcall MenuDeleteSelectedClick( TObject *Sender );\r
+ void __fastcall MenuDeleteAllClick( TObject *Sender );\r
+ void __fastcall MenuSelectionInvertClick( TObject *Sender );\r
+ void __fastcall MenuSelectionCropClick( TObject *Sender );\r
+ void __fastcall PopupPlayClick( TObject *Sender );\r
+ void __fastcall PopupInvertSelectionClick( TObject *Sender );\r
+ void __fastcall PopupCropSelectionClick( TObject *Sender );\r
+ void __fastcall PopupDeleteSelectedClick( TObject *Sender );\r
+ void __fastcall PopupDeleteAllClick( TObject *Sender );\r
+private: // User declarations\r
+ char * __fastcall rindex( char *s, char c );\r
+public: // User declarations\r
+ __fastcall TPlaylistDlg( TComponent* Owner );\r
+ void __fastcall UpdateGrid( playlist_t * p_playlist );\r
+ void __fastcall Manage( intf_thread_t * p_intf );\r
+ void __fastcall DeleteItem( int i_pos );\r
+ void __fastcall Previous();\r
+ void __fastcall Next();\r
+};\r
+//---------------------------------------------------------------------------\r
+#endif\r
--- /dev/null
+/*****************************************************************************\r
+ * preferences.cpp: the "Preferences" dialog box\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include <vcl.h>\r
+#pragma hdrstop\r
+\r
+#include <stdlib.h> /* malloc(), free() */\r
+#include <string.h> /* strcmp */\r
+\r
+#include <vlc/vlc.h>\r
+#include <vlc/intf.h>\r
+\r
+#include "preferences.h"\r
+#include "win32_common.h"\r
+\r
+//---------------------------------------------------------------------------\r
+//#pragma package(smart_init)\r
+#pragma link "CSPIN"\r
+#pragma resource "*.dfm"\r
+\r
+extern intf_thread_t *p_intfGlobal;\r
+\r
+\r
+/****************************************************************************\r
+ * Functions to help components creation\r
+ ****************************************************************************/\r
+__fastcall TGroupBoxPref::TGroupBoxPref( TComponent* Owner,\r
+ module_config_t *p_config_arg ) : TGroupBox( Owner )\r
+{\r
+ p_config = p_config_arg;\r
+ Caption = p_config->psz_text;\r
+}\r
+//---------------------------------------------------------------------------\r
+TListView * __fastcall TGroupBoxPref::CreateListView( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, TViewStyle ViewStyle )\r
+{\r
+ TListView *ListView = new TListView( Parent );\r
+ ListView->Parent = Parent;\r
+ ListView->ViewStyle = ViewStyle;\r
+ ListView->Left = Left;\r
+ ListView->Width = Width;\r
+ ListView->Top = Top;\r
+ ListView->Height = Height;\r
+ return ListView;\r
+}\r
+//---------------------------------------------------------------------------\r
+TButton * __fastcall TGroupBoxPref::CreateButton( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Caption )\r
+{\r
+ TButton *Button = new TButton( Parent );\r
+ Button->Parent = Parent;\r
+ Button->Left = Left;\r
+ Button->Width = Width;\r
+ Button->Top = Top;\r
+ Button->Height = Height;\r
+ Button->Caption = Caption;\r
+ return Button;\r
+}\r
+//---------------------------------------------------------------------------\r
+TCheckBox * __fastcall TGroupBoxPref::CreateCheckBox( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Caption )\r
+{\r
+ TCheckBox *CheckBox = new TCheckBox( Parent );\r
+ CheckBox->Parent = Parent;\r
+ CheckBox->Left = Left;\r
+ CheckBox->Width = Width;\r
+ CheckBox->Top = Top;\r
+ CheckBox->Height = Height;\r
+ CheckBox->Caption = Caption;\r
+ return CheckBox;\r
+}\r
+//---------------------------------------------------------------------------\r
+TLabel * __fastcall TGroupBoxPref::CreateLabel( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Caption,\r
+ bool WordWrap )\r
+{\r
+ TLabel *Label = new TLabel( Parent );\r
+ Label->Parent = Parent;\r
+ Label->Caption = Caption;\r
+ Label->Left = Left;\r
+ Label->Width = Width;\r
+ Label->Top = Top;\r
+ Label->Height = Height;\r
+ Label->WordWrap = WordWrap;\r
+ return Label;\r
+}\r
+//---------------------------------------------------------------------------\r
+TEdit * __fastcall TGroupBoxPref::CreateEdit( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Text )\r
+{\r
+ TEdit *Edit = new TEdit( Parent );\r
+ Edit->Parent = Parent;\r
+ Edit->Left = Left;\r
+ Edit->Width = Width;\r
+ Edit->Top = Top;\r
+ Edit->Height = Height;\r
+ Edit->Text = Text;\r
+ return Edit;\r
+}\r
+//---------------------------------------------------------------------------\r
+TCSpinEdit * __fastcall TGroupBoxPref::CreateSpinEdit( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height,\r
+ long Min, long Max, long Value )\r
+{\r
+ TCSpinEdit *SpinEdit = new TCSpinEdit( Parent );\r
+ SpinEdit->Parent = Parent;\r
+ SpinEdit->Left = Left;\r
+ SpinEdit->Width = Width;\r
+ SpinEdit->Top = Top;\r
+ SpinEdit->Height = Height;\r
+ SpinEdit->MinValue = Min;\r
+ SpinEdit->MaxValue = Max;\r
+ SpinEdit->Value = Value;\r
+ return SpinEdit;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxPref::UpdateChanges()\r
+{\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * GroupBox for module management\r
+ ****************************************************************************/\r
+__fastcall TGroupBoxPlugin::TGroupBoxPlugin( TComponent* Owner,\r
+ module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
+{\r
+ /* init listview */\r
+ ListView = CreateListView( this, 16, 164, 24, 160, vsReport );\r
+ ListView->ReadOnly = true;\r
+ ListView->Columns->Add();\r
+ ListView->Columns->Items[0]->Width = 160;\r
+ ListView->Columns->Items[0]->Caption = "Name";//p_config->psz_text;\r
+ ListView->OnSelectItem = ListViewSelectItem;\r
+\r
+ /* init description label */\r
+ LabelDesc = CreateLabel( this, 230, 225, 50, 52,\r
+ p_config->psz_longtext, true );\r
+\r
+ /* init hint label */\r
+ LabelHint = CreateLabel( this, 230, 225, 135, 13, "", false );\r
+\r
+ /* init configure button */\r
+ ButtonConfig = CreateButton( this, 16, 70, 192, 25, "Configure" );\r
+ ButtonConfig->Enabled = false;\r
+ ButtonConfig->OnClick = ButtonConfigClick;\r
+\r
+ /* init select button */\r
+ ButtonSelect = CreateButton( this, 110, 70, 192, 25, "Select" );\r
+ ButtonSelect->OnClick = ButtonSelectClick;\r
+\r
+ /* init 'Selected' label */\r
+ LabelSelected = CreateLabel( this, 230, 45, 198, 13, "Selected", false );\r
+\r
+ /* init 'Selected' edit */\r
+ Edit = CreateEdit( this, 280, 164, 194, 21, "" );\r
+ vlc_mutex_lock( p_config->p_lock );\r
+ Edit->Text = p_config->psz_value ? p_config->psz_value : "";\r
+ vlc_mutex_unlock( p_config->p_lock );\r
+\r
+ Height = 233;\r
+};\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxPlugin::ListViewSelectItem( TObject *Sender,\r
+ TListItem *Item, bool Selected )\r
+{\r
+ module_t *p_module;\r
+ AnsiString Name;\r
+\r
+ Name = Item->Caption;\r
+ if( Name != "" )\r
+ {\r
+ /* look for module 'Name' */\r
+ for( p_module = p_intfGlobal->p_vlc->p_module_bank->first ;\r
+ p_module != NULL ;\r
+ p_module = p_module->next )\r
+ {\r
+ if( strcmp( p_module->psz_object_name, Name.c_str() ) == 0 )\r
+ {\r
+ ModuleSelected = p_module;\r
+ LabelHint->Caption = p_module->psz_longname ?\r
+ p_module->psz_longname : "";\r
+ ButtonConfig->Enabled = p_module->i_config_items ? true : false;\r
+\r
+ break;\r
+ }\r
+ }\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxPlugin::ButtonSelectClick( TObject *Sender )\r
+{\r
+ if( !ModuleSelected ) return;\r
+ Edit->Text = ModuleSelected->psz_object_name;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxPlugin::ButtonConfigClick( TObject *Sender )\r
+{\r
+ p_intfGlobal->p_sys->p_window->\r
+ CreatePreferences( ModuleSelected->psz_object_name );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxPlugin::UpdateChanges()\r
+{\r
+ /* XXX: Necessary, since c_str() returns only a temporary pointer... */\r
+ free( p_config->psz_value );\r
+ p_config->psz_value = (char *)malloc( Edit->Text.Length() + 1 );\r
+ strcpy( p_config->psz_value, Edit->Text.c_str() );\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * GroupBox for string management\r
+ ****************************************************************************/\r
+__fastcall TGroupBoxString::TGroupBoxString( TComponent* Owner,\r
+ module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
+{\r
+ /* init description label */\r
+ LabelDesc = CreateLabel( this, 230, 225, 24, 26,\r
+ p_config->psz_longtext, true );\r
+\r
+ /* init edit */\r
+ Edit = CreateEdit( this, 16, 164, 24, 21, "" );\r
+ vlc_mutex_lock( p_config->p_lock );\r
+ Edit->Text = p_config->psz_value ? p_config->psz_value : "";\r
+ vlc_mutex_unlock( p_config->p_lock );\r
+\r
+ /* vertical alignment */\r
+ Height = LabelDesc->Height + 24;\r
+ LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
+ Edit->Top = Top + ( Height - Edit->Height ) / 2 + 4;\r
+};\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxString::UpdateChanges()\r
+{\r
+ /* XXX: Necessary, since c_str() returns only a temporary pointer... */\r
+ free( p_config->psz_value );\r
+ p_config->psz_value = (char *)malloc( Edit->Text.Length() + 1 );\r
+ strcpy( p_config->psz_value, Edit->Text.c_str() );\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * GroupBox for integer management\r
+ ****************************************************************************/\r
+__fastcall TGroupBoxInteger::TGroupBoxInteger( TComponent* Owner,\r
+ module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
+{\r
+ /* init description label */\r
+ LabelDesc = CreateLabel( this, 230, 225, 19, 26,\r
+ p_config->psz_longtext, true );\r
+\r
+ /* init spinedit */\r
+ SpinEdit = CreateSpinEdit( this, 16, 164, 24, 21,\r
+ -1, 100000, p_config->i_value );\r
+\r
+ /* vertical alignment */\r
+ Height = LabelDesc->Height + 24;\r
+ LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
+ SpinEdit->Top = Top + ( Height - SpinEdit->Height ) / 2 + 4;\r
+};\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxInteger::UpdateChanges()\r
+{\r
+ /* Warning: we're casting from long to int */\r
+ p_config->i_value = (int)SpinEdit->Value;\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * GroupBox for boolean management\r
+ ****************************************************************************/\r
+__fastcall TGroupBoxBool::TGroupBoxBool( TComponent* Owner,\r
+ module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
+{\r
+ /* init description label */\r
+ LabelDesc = CreateLabel( this, 230, 225, 19, 26,\r
+ p_config->psz_longtext, true );\r
+\r
+ /* init checkbox */\r
+ CheckBox = CreateCheckBox( this, 16, 184, 28, 17, p_config->psz_text );\r
+ CheckBox->Checked = p_config->i_value;\r
+\r
+ /* vertical alignment */\r
+ Height = LabelDesc->Height + 24;\r
+ LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
+ CheckBox->Top = Top + ( Height - CheckBox->Height ) / 2 + 4;\r
+};\r
+//---------------------------------------------------------------------------\r
+void __fastcall TGroupBoxBool::UpdateChanges()\r
+{\r
+ p_config->i_value = CheckBox->Checked ? 1 : 0;\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * Callbacks for the dialog\r
+ ****************************************************************************/\r
+//---------------------------------------------------------------------------\r
+__fastcall TPreferencesDlg::TPreferencesDlg( TComponent* Owner )\r
+ : TForm( Owner )\r
+{\r
+ Icon = p_intfGlobal->p_sys->p_window->Icon;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::FormClose( TObject *Sender,\r
+ TCloseAction &Action )\r
+{\r
+ Action = caHide;\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::FormShow( TObject *Sender )\r
+{\r
+/*\r
+ p_intfGlobal->p_sys->p_window->MenuPreferences->Checked = true;\r
+ p_intfGlobal->p_sys->p_window->PopupPreferences->Checked = true;\r
+*/\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::FormHide( TObject *Sender )\r
+{\r
+/*\r
+ p_intfGlobal->p_sys->p_window->MenuPreferences->Checked = false;\r
+ p_intfGlobal->p_sys->p_window->PopupPreferences->Checked = false;\r
+*/\r
+}\r
+\r
+\r
+/****************************************************************************\r
+ * CreateConfigDialog: dynamically creates the configuration dialog\r
+ * box from all the configuration data provided by the selected module.\r
+ ****************************************************************************/\r
+#define ADD_PANEL \\r
+{ \\r
+ Panel = new TPanel( this ); \\r
+ Panel->Parent = ScrollBox; \\r
+ Panel->Caption = ""; \\r
+ Panel->BevelOuter = bvNone; \\r
+ Panel->Height = 12; \\r
+}\r
+\r
+void __fastcall TPreferencesDlg::CreateConfigDialog( char *psz_module_name )\r
+{\r
+ module_t *p_module, *p_module_plugins;\r
+ module_config_t *p_item;\r
+ int i_pages, i_ctrl;\r
+ \r
+ TTabSheet *TabSheet;\r
+ TScrollBox *ScrollBox;\r
+ TPanel *Panel;\r
+ TGroupBoxPlugin *GroupBoxPlugin;\r
+ TGroupBoxString *GroupBoxString;\r
+ TGroupBoxInteger *GroupBoxInteger;\r
+ TGroupBoxBool *GroupBoxBool;\r
+ TListItem *ListItem;\r
+\r
+ /* Look for the selected module */\r
+ for( p_module = p_intfGlobal->p_vlc->p_module_bank->first ; p_module != NULL ;\r
+ p_module = p_module->next )\r
+ {\r
+ if( psz_module_name\r
+ && !strcmp( psz_module_name, p_module->psz_object_name ) )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ if( !p_module ) return;\r
+\r
+ /*\r
+ * We found it, now we can start building its configuration interface\r
+ */\r
+\r
+ /* Enumerate config options and add corresponding config boxes */\r
+ p_item = p_module->p_config;\r
+ do\r
+ {\r
+ switch( p_item->i_type )\r
+ {\r
+ case CONFIG_HINT_CATEGORY:\r
+\r
+ /* create a new tabsheet. */\r
+ TabSheet = new TTabSheet( this );\r
+ TabSheet->PageControl = PageControlPref;\r
+ TabSheet->Caption = p_item->psz_text;\r
+ TabSheet->Visible = true;\r
+\r
+ /* pack a scrollbox into the tabsheet */\r
+ ScrollBox = new TScrollBox( this );\r
+ ScrollBox->Parent = TabSheet;\r
+ ScrollBox->Align = alClient;\r
+ ScrollBox->BorderStyle = bsNone;\r
+ ScrollBox->HorzScrollBar->Tracking = true;\r
+ ScrollBox->VertScrollBar->Tracking = true;\r
+\r
+ break;\r
+\r
+ case CONFIG_ITEM_MODULE:\r
+\r
+ /* add new groupbox for the config option */\r
+ GroupBoxPlugin = new TGroupBoxPlugin( this, p_item );\r
+ GroupBoxPlugin->Parent = ScrollBox;\r
+\r
+ /* add panel as separator */\r
+ ADD_PANEL;\r
+\r
+#if 0 /* FIXME */\r
+ /* build a list of available plugins */\r
+ for( p_module_plugins = p_intfGlobal->p_vlc->p_module_bank->first ;\r
+ p_module_plugins != NULL ;\r
+ p_module_plugins = p_module_plugins->next )\r
+ {\r
+ if( p_module_plugins->i_capabilities &\r
+ ( 1 << p_item->i_value ) )\r
+ {\r
+ ListItem = GroupBoxPlugin->ListView->Items->Add();\r
+ ListItem->Caption = p_module_plugins->psz_object_name;\r
+ }\r
+ }\r
+#endif\r
+\r
+ break;\r
+\r
+ case CONFIG_ITEM_FILE:\r
+\r
+ case CONFIG_ITEM_STRING:\r
+\r
+ /* add new groupbox for the config option */\r
+ GroupBoxString = new TGroupBoxString( this, p_item );\r
+ GroupBoxString->Parent = ScrollBox;\r
+\r
+ /* add panel as separator */\r
+ ADD_PANEL;\r
+\r
+ break;\r
+\r
+ case CONFIG_ITEM_INTEGER:\r
+\r
+ /* add new groupbox for the config option */\r
+ GroupBoxInteger = new TGroupBoxInteger( this, p_item );\r
+ GroupBoxInteger->Parent = ScrollBox;\r
+\r
+ /* add panel as separator */\r
+ ADD_PANEL;\r
+\r
+ break;\r
+\r
+ case CONFIG_ITEM_BOOL:\r
+\r
+ /* add new groupbox for the config option */\r
+ GroupBoxBool = new TGroupBoxBool( this, p_item );\r
+ GroupBoxBool->Parent = ScrollBox;\r
+\r
+ /* add panel as separator */\r
+ ADD_PANEL;\r
+\r
+ break;\r
+ }\r
+ \r
+ p_item++;\r
+ }\r
+ while( p_item->i_type != CONFIG_HINT_END );\r
+\r
+ /* Reorder groupboxes inside the tabsheets */\r
+ for( i_pages = 0; i_pages < PageControlPref->PageCount; i_pages++ )\r
+ {\r
+ /* get scrollbox from the tabsheet */\r
+ ScrollBox = (TScrollBox *)PageControlPref->Pages[i_pages]->Controls[0];\r
+\r
+ for( i_ctrl = ScrollBox->ControlCount - 1; i_ctrl >= 0 ; i_ctrl-- )\r
+ {\r
+ ScrollBox->Controls[i_ctrl]->Align = alTop;\r
+ }\r
+ }\r
+\r
+ /* set active tabsheet\r
+ * FIXME: i don't know why, but both lines are necessary */\r
+ PageControlPref->ActivePageIndex = 1;\r
+ PageControlPref->ActivePageIndex = 0;\r
+}\r
+#undef ADD_PANEL\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::ButtonOkClick( TObject *Sender )\r
+{\r
+ ButtonApplyClick( Sender );\r
+ Hide();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::ButtonApplyClick( TObject *Sender )\r
+{\r
+ TScrollBox *ScrollBox;\r
+ TGroupBoxPref *GroupBox;\r
+ int i, j;\r
+\r
+ for( i = 0; i < PageControlPref->PageCount; i++ )\r
+ {\r
+ /* get scrollbox from the tabsheet */\r
+ ScrollBox = (TScrollBox *)PageControlPref->Pages[i]->Controls[0];\r
+\r
+ for( j = 0; j < ScrollBox->ControlCount ; j++ )\r
+ {\r
+ /* skip the panels */\r
+ if( ScrollBox->Controls[j]->InheritsFrom( __classid( TGroupBoxPref ) ) )\r
+ {\r
+ GroupBox = (TGroupBoxPref *)ScrollBox->Controls[j];\r
+ GroupBox->UpdateChanges();\r
+ SaveValue( GroupBox->p_config );\r
+ }\r
+ }\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::ButtonSaveClick( TObject *Sender )\r
+{\r
+ ButtonApplyClick( Sender );\r
+ config_SaveConfigFile( p_intfGlobal, NULL );\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::ButtonCancelClick( TObject *Sender )\r
+{\r
+ Hide();\r
+}\r
+//---------------------------------------------------------------------------\r
+void __fastcall TPreferencesDlg::SaveValue( module_config_t *p_config )\r
+{\r
+ switch( p_config->i_type )\r
+ {\r
+ case CONFIG_ITEM_STRING:\r
+ case CONFIG_ITEM_FILE:\r
+ case CONFIG_ITEM_MODULE:\r
+ config_PutPsz( p_intfGlobal, p_config->psz_name,\r
+ *p_config->psz_value ? p_config->psz_value : NULL );\r
+ break;\r
+ case CONFIG_ITEM_INTEGER:\r
+ case CONFIG_ITEM_BOOL:\r
+ config_PutInt( p_intfGlobal, p_config->psz_name,\r
+ p_config->i_value );\r
+ break;\r
+ }\r
+}\r
+//---------------------------------------------------------------------------\r
+\r
--- /dev/null
+object PreferencesDlg: TPreferencesDlg\r
+ Left = 309\r
+ Top = 124\r
+ Width = 522\r
+ Height = 582\r
+ Caption = 'Preferences'\r
+ Color = clBtnFace\r
+ Font.Charset = DEFAULT_CHARSET\r
+ Font.Color = clWindowText\r
+ Font.Height = -11\r
+ Font.Name = 'MS Sans Serif'\r
+ Font.Style = []\r
+ Icon.Data = {\r
+ 0000010001003030000001001800A81C00001600000028000000300000006000\r
+ 00000100180000000000001B0000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000069375900000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000120E0A4011253E0F18000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000F0B\r
+ 084143CA08070016430F08040800000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000003127291203174647E8464AE808010840E54039E6390B0C06\r
+ 0E0A1C0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0070CD0079DD0079DD0070CD0000000000000000000C1008261D6E4647E54547\r
+ E64748E105040039E6393AE53939E63936D33308030100000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000070CD0079DD0079DE007DE40088F9008CFF008CFF0088F9007CE302\r
+ 6EC70B09124641DC4444DF4546E34446E54847E003040040E6403AEA3A3EE33E\r
+ 3CE33C39E639080F010801050000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0079DD0077D90070CB0078D8007BDC007BDC007BDC\r
+ 007BDC007BDC007BDD007EE32E232D0804084553F14250F34252ED4449DB4844\r
+ DC4645E208010540E5401C78150D18053CE63C3AE63A39EA393CD83C241A2006\r
+ 0402000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0079DD007ADF007BDE007BDC0072\r
+ CC005188004877004876004876004876034976054A760B4D7731434221175B42\r
+ 54EC4253EE4252F60B05104250F44252EB4546DA08010539E6392BAA2B080105\r
+ 3CE63C39E7393AE63A39E93939E839081208181C080000000000000000000000\r
+ 000000000000000000000000000000000000000070CD0079DD0079DD007CE300\r
+ 88F90089F90075D2005188004877005188008CFF008CFF008CFF008CFF008CFF\r
+ 1092FF2099FF31A0FF1408294840DB4550E1464EEA0C060B0B05084654F64653\r
+ F64453EF080E033AE63A2BAA2B03030339E33939DF3939E639080F083DDB3D24\r
+ 9C24434B3B000000000000000000000000000000000000000000000000000000\r
+ 0063B60085F3008BFE0088F9007FE90088F90080E8005CA0008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF048DFF1594FF259BFF35A2FF0C04103F38C754\r
+ 5AF7505BF10C08100801084352F64652F44253F30813053AE63A39E639030403\r
+ 1C521826A1250812010807032454131558150000000000000000000000000000\r
+ 000000000000000000000000000000000000000070CD007CE30079DD00000000\r
+ 7CE30089FA008CFF0089FA008CFF008CFF008CFF008CFF008CFF008CFF098FFF\r
+ 1996FF2A9DFF3AA4FF0804103A2AA34E58F74E58F40B0B120803054652F34548\r
+ E64451F305130532CA323AE23A03070308070307040008040139E63939E43931\r
+ B42F5E1347000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000061B10000000079DD008CFF008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF008CFF0E91FF1E98FF2E9FFF3FA6FF040408382BAF4D\r
+ 5AEF555AF70F12250501050F04160804074250F3121A123AE93A39E239080803\r
+ 0D2F08010401268C2539E7393DE63D3FE23E0804100000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 79DD008CFF008CFF008CFF008CFF008CFF008CFF008CFF008CFF028CFF1293FF\r
+ 239AFF33A1FF43A8FF0802083A2AA3565BF7555AF71714330501050104000801\r
+ 07424FF12828203AEA3A39E639030703182F1008340801040139E7393DE83D39\r
+ E939080400000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000070CD0088F9008CFF008CFF008CFF008C\r
+ FF008CFF008CFF008CFF078EFF1795FF279CFF38A3FF48AAFF0808005151F155\r
+ 5AF30804030804000504050800082E358E0E0C1F1D192439E53940E640080400\r
+ 2AA12739E63908020708010539E8393BE93B0804080000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000007CE3008CFF008CFF008CFF058EFD1D96F92398F8269AFA31A0FC42A8FF\r
+ 4FAEFF5CB3FF65B7FF0C08084F5AF14E57F50B04080804043639A54647E81C13\r
+ 49363AA70804080F120835953439E7393EE63E39DF3939EA39081105308A2B3F\r
+ E73F080601000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000047BDB1D96F92398F82498F83BA0\r
+ F399C1E1B1C9DDBCD4E7CBE0F3D9EDFFDCEEFFDEEFFFCDE8FF080808575BF750\r
+ 58F624125A5057F34845DF4A41E0150E30C55734E3723EC56E33A23D27050105\r
+ 39E43939E63939E6393CE63C14420C3BE03B192A090000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000004\r
+ 04042D88D399C1E1B1C9DDB1C9DCB7CBDBCFD3D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFF9FCFF0C08085D61F15B61EF555AF64A4FE13937BB0E0A12DE74\r
+ 39E1733CDE713CDF753AE67541C36B342C231F17141B3AE63A39E7393DE83D39\r
+ E93939DE39000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000001818186893B8C3CCD2D5D5D6D5D5D6D5D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFFFFFFFFFFFF140C145C5EF668\r
+ 63F75555EA10061CC3673FDF713A0C1104080403080105080007070407D56F36\r
+ DE743EDE72401C200C29452939E63939E73939EA390000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000343434A2B4C2D5D5D6D6D6D6D6D6D6D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFFEFEFF20161C5C5EF6373EAE0E0413E2713DE1763CCD6A3C2A0D\r
+ 08A44B2CDE743EBD612F080401030403E1713CDE7239DE713AE1723C22201139\r
+ C13341E641000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001B1B1B99AEBED5D5D6D5D5D6D5D5\r
+ D6CFD3D7B8CBDBBFD5E7CEE2F3DCEFFFDFF0FFE2F1FFE9F4FF10100C3639A46E\r
+ 4540DE7239DE713DE1713C07000784261CDE7639E3743E0812001F0407D86E36\r
+ E3753EE57540E57541DE763CDE733DD26637493C387E2F7B0000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00001B1B1B99AEBFCED3D7B7CBDBB1C9DD99C1E140A2F339A2FA49AAFC59B2FF\r
+ 66B8FF74BEFF92CBFFD9ECFF0F0402C66531DE7139E2733D854B1E0A01084D11\r
+ 0DE3733EE1723CDF713ADF753AE1763C1D0A08290708E57140E1763CDE733DC7\r
+ 6B34080408000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000001818187FA5C399C1E13BA0F32498\r
+ F81D96F91091FD1C97FF2C9EFF3CA5FF4DACFF5DB3FF71BBFF8DC8FF9FD0FF08\r
+ 0400080406B95C2EDE7239070B070803014D1615DE723CDE7540E5714030090D\r
+ 0504003A120FE67541DE75390808044A0C290000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000707071778C81C92F3058EFD008CFF008CFF1092FF2099FF31A0FF41A7FF\r
+ 51AEFF62B5FF72BCFF7BBFFF7BBBF96E9FCD0808080806041D0508E571403E22\r
+ 0C200708080405070407070007080303B05F31DE723967301908010500000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000007CE3008CFF008C\r
+ FF048DFF1594FF259BFF35A2FF46A9FF56B0FF66B7FF77BEFF7BBFFF6DAAE300\r
+ 0000000000000000000000080401200C088D4024E17141E57140DF713ADE713E\r
+ DE76390801070000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000079DD008CFF008CFF098FFF1996FF2A9DFF3AA4FF4AABFF\r
+ 5BB2FF6BB9FF7BBFFF7BBFFF6AA5DD0000000000000000000000000000001D1A\r
+ 0C1A0F08110903441912E57140623B1E08020300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000079DD008CFF008C\r
+ FF0E91FF1E98FF2E9FFF3FA6FF4FADFF5FB4FF70BBFF7BBFFF78BAF96299CD00\r
+ 00000000000000000000000000000000000000003914100000005A2411000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000070CD0088F9078EFD2C9CF940A3F850ACFA60B4FC70BCFF\r
+ 7DC2FF87C6FF7EC0FF6DAAE30000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000707071A85DD40A2\r
+ F3A0C3E1B7CBDDC6D8E7D4E5F3E2F1FFE5F2FFD9ECFF9FD0FF7AACDD05050500\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001818187FA5C3B8CBDBD0D4D7D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFAFCFFE2EDF99FB7CD1C1C1C0000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000001B1B1B99AEBFD4D5\r
+ D6D6D6D6D6D6D6E3E3E3F1F1F1FFFFFFFFFFFFFEFEFFD1DAE33E3E3E00000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000001D1D1D7B9BB4CACED1D6D6D6D5D5D6E2E2E3F0F0F1FEFEFF\r
+ FEFEFFFEFEFFC9D2DD2121210000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000343434A5B5\r
+ C2CFD3D7BFCEDBC9D9E7D7E6F3E6F3FFECF5FFF0F4F9AEBDCD23232300000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000018181887A8C3A6C6E169B3F367B6FA77BEFC88C6FF\r
+ 9FD0FFB4CBE33939390000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000040404338C\r
+ D749A8F947A9FD54AFFF64B6FF74BDFF7EC0FF76ABDD05050500000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000001F7DCD369FF948AAFF58B1FF69B8FF79BFFF\r
+ 78BAF96299CD0000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003592E34DACFF5DB3FF6DBAFF7BBFFF6DAAE300000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003890DD51AEFF62B5FF72BCFF7BBFFF\r
+ 6AA5DD0000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 003B8FD84C9CE3589FDE69A9E375B6F46299CD00000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000000000000000000000000000003376B00000000000000000005788B6\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 00000000006CC61A83DD247FCC00000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000006DC71A83DD2686D71F6EB1\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 0000000000000000000000000000000000000000000000000000000000000000\r
+ 000000000000000000000000000000000000000000000000000000000000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFE1FDFFF0000FFFFE0078FFF0000FFFE\r
+ 000007FF0000FFF0000001FF0000FF80000000FF0000FF000000003F0000FF00\r
+ 0000000F0000FE00000000070000F800000000070000F8000000000F0000FC00\r
+ 000000070000FE00000000070000FF80000000070000FFC0000000070000FFE0\r
+ 000000070000FFE0000000070000FFE0000000070000FFE0000000070000FFF0\r
+ 000000070000FFF0000000030000FFF0000000070000FFF00000000F0000FFF0\r
+ 0000003F0000FFF8000E00FF0000FFF8000F01FF0000FFF8000FD7FF0000FFF8\r
+ 001FFFFF0000FFFC001FFFFF0000FFFC001FFFFF0000FFFC003FFFFF0000FFFC\r
+ 003FFFFF0000FFFE003FFFFF0000FFFE007FFFFF0000FFFE007FFFFF0000FFFE\r
+ 007FFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF\r
+ 01FFFFFF0000FFFF01FFFFFF0000FFFF81FFFFFF0000FFFFC3FFFFFF0000FFFF\r
+ FFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000}\r
+ OldCreateOrder = False\r
+ Position = poDefaultPosOnly\r
+ OnClose = FormClose\r
+ OnHide = FormHide\r
+ OnShow = FormShow\r
+ PixelsPerInch = 96\r
+ TextHeight = 13\r
+ object PageControlPref: TPageControl\r
+ Left = 8\r
+ Top = 8\r
+ Width = 497\r
+ Height = 497\r
+ TabOrder = 1\r
+ end\r
+ object ButtonApply: TButton\r
+ Left = 146\r
+ Top = 520\r
+ Width = 105\r
+ Height = 25\r
+ Caption = 'Apply'\r
+ TabOrder = 0\r
+ OnClick = ButtonApplyClick\r
+ end\r
+ object ButtonSave: TButton\r
+ Left = 265\r
+ Top = 520\r
+ Width = 105\r
+ Height = 25\r
+ Caption = 'Save'\r
+ TabOrder = 2\r
+ OnClick = ButtonSaveClick\r
+ end\r
+ object ButtonOK: TButton\r
+ Left = 26\r
+ Top = 520\r
+ Width = 105\r
+ Height = 25\r
+ Caption = 'OK'\r
+ TabOrder = 3\r
+ OnClick = ButtonOkClick\r
+ end\r
+ object ButtonCancel: TButton\r
+ Left = 386\r
+ Top = 520\r
+ Width = 105\r
+ Height = 25\r
+ Caption = 'Cancel'\r
+ TabOrder = 4\r
+ OnClick = ButtonCancelClick\r
+ end\r
+end\r
--- /dev/null
+/*****************************************************************************\r
+ * preferences.h: the "Preferences" dialog box\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#ifndef preferencesH\r
+#define preferencesH\r
+//---------------------------------------------------------------------------\r
+#include <Classes.hpp>\r
+#include <Controls.hpp>\r
+#include <StdCtrls.hpp>\r
+#include <Forms.hpp>\r
+#include <Buttons.hpp>\r
+#include <ComCtrls.hpp>\r
+#include <ExtCtrls.hpp>\r
+#include "CSPIN.h"\r
+//---------------------------------------------------------------------------\r
+class TGroupBoxPref : public TGroupBox\r
+{\r
+public:\r
+ __fastcall TGroupBoxPref( TComponent* Owner, module_config_t *p_config_arg );\r
+ module_config_t *p_config;\r
+ virtual void __fastcall UpdateChanges();\r
+ TListView * __fastcall CreateListView( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, TViewStyle ViewStyle );\r
+ TButton * __fastcall CreateButton( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Caption );\r
+ TCheckBox * __fastcall CreateCheckBox( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Caption );\r
+ TLabel * __fastcall CreateLabel( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Caption,\r
+ bool WordWrap );\r
+ TEdit * __fastcall CreateEdit( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height, AnsiString Text );\r
+ TCSpinEdit * __fastcall CreateSpinEdit( TWinControl *Parent,\r
+ int Left, int Width, int Top, int Height,\r
+ long Min, long Max, long Value );\r
+};\r
+//---------------------------------------------------------------------------\r
+class TGroupBoxPlugin : public TGroupBoxPref\r
+{\r
+public:\r
+ __fastcall TGroupBoxPlugin( TComponent* Owner, module_config_t *p_config );\r
+ TListView *ListView;\r
+ TButton *ButtonConfig;\r
+ TButton *ButtonSelect;\r
+ TLabel *LabelDesc;\r
+ TLabel *LabelHint;\r
+ TLabel *LabelSelected;\r
+ TEdit *Edit;\r
+ module_t *ModuleSelected;\r
+ void __fastcall UpdateChanges();\r
+ void __fastcall ListViewSelectItem( TObject *Sender, TListItem *Item,\r
+ bool Selected );\r
+ void __fastcall ButtonSelectClick( TObject *Sender );\r
+ void __fastcall ButtonConfigClick( TObject *Sender );\r
+};\r
+//---------------------------------------------------------------------------\r
+class TGroupBoxString : public TGroupBoxPref\r
+{\r
+public:\r
+ __fastcall TGroupBoxString( TComponent* Owner, module_config_t *p_config );\r
+ TLabel *LabelDesc;\r
+ TEdit *Edit;\r
+ void __fastcall UpdateChanges();\r
+};\r
+//---------------------------------------------------------------------------\r
+class TGroupBoxInteger : public TGroupBoxPref\r
+{\r
+public:\r
+ __fastcall TGroupBoxInteger( TComponent* Owner, module_config_t *p_config );\r
+ TLabel *LabelDesc;\r
+ TCSpinEdit *SpinEdit;\r
+ void __fastcall UpdateChanges();\r
+};\r
+//---------------------------------------------------------------------------\r
+class TGroupBoxBool : public TGroupBoxPref\r
+{\r
+public:\r
+ __fastcall TGroupBoxBool( TComponent* Owner, module_config_t *p_config );\r
+ TLabel *LabelDesc;\r
+ TCheckBox *CheckBox;\r
+ void __fastcall UpdateChanges();\r
+};\r
+//---------------------------------------------------------------------------\r
+class TPreferencesDlg : public TForm\r
+{\r
+__published: // IDE-managed Components\r
+ TPageControl *PageControlPref;\r
+ TButton *ButtonApply;\r
+ TButton *ButtonSave;\r
+ TButton *ButtonOK;\r
+ TButton *ButtonCancel;\r
+ void __fastcall FormShow( TObject *Sender );\r
+ void __fastcall FormHide( TObject *Sender );\r
+ void __fastcall ButtonOkClick( TObject *Sender );\r
+ void __fastcall ButtonApplyClick( TObject *Sender );\r
+ void __fastcall ButtonSaveClick( TObject *Sender );\r
+ void __fastcall ButtonCancelClick( TObject *Sender );\r
+ void __fastcall FormClose( TObject *Sender, TCloseAction &Action );\r
+private: // User declarations\r
+public: // User declarations\r
+ __fastcall TPreferencesDlg( TComponent* Owner );\r
+ void __fastcall CreateConfigDialog( char *psz_module_name );\r
+ void __fastcall SaveValue( module_config_t *p_config );\r
+};\r
+//---------------------------------------------------------------------------\r
+#endif\r
--- /dev/null
+<?xml version='1.0' encoding='utf-8' ?>\r
+<!-- C++Builder XML Project -->\r
+<PROJECT>\r
+ <MACROS>\r
+ <VERSION value="BCB.05.03"/>\r
+ <PROJECT value="..\intfwin.so"/>\r
+ <OBJFILES value="win32.obj intf.obj mainframe.obj network.obj playlist.obj \r
+ preferences.obj about.obj disc.obj control.obj menu.obj messages.obj"/>\r
+ <RESFILES value=""/>\r
+ <DEFFILE value=""/>\r
+ <RESDEPEN value="$(RESFILES) mainframe.dfm network.dfm playlist.dfm preferences.dfm \r
+ about.dfm disc.dfm messages.dfm"/>\r
+ <LIBFILES value=""/>\r
+ <LIBRARIES value="VCLX50.lib bcbsmp50.lib VCL50.lib"/>\r
+ <SPARELIBS value="VCL50.lib bcbsmp50.lib VCLX50.lib"/>\r
+ <PACKAGES value="VCL50.bpi VCLX50.bpi bcbsmp50.bpi QRPT50.bpi VCLDB50.bpi VCLBDE50.bpi \r
+ ibsmp50.bpi VCLDBX50.bpi TEEUI50.bpi TEEDB50.bpi TEE50.bpi TEEQR50.bpi \r
+ VCLIB50.bpi bcbie50.bpi VCLIE50.bpi INETDB50.bpi INET50.bpi NMFAST50.bpi"/>\r
+ <PATHCPP value=".;"/>\r
+ <PATHPAS value=".;"/>\r
+ <PATHRC value=".;"/>\r
+ <PATHASM value=".;"/>\r
+ <DEBUGLIBPATH value="$(BCB)\lib\debug"/>\r
+ <RELEASELIBPATH value="$(BCB)\lib\release"/>\r
+ <LINKER value="tlink32"/>\r
+ <USERDEFINES value="_DEBUG"/>\r
+ <SYSDEFINES value="NO_STRICT"/>\r
+ <MAINSOURCE value="intfwin.bpf"/>\r
+ <INCLUDEPATH value="..\..\win32;$(BCB)\include;$(BCB)\include\vcl;..\..\include;..\..\src\misc"/>\r
+ <LIBPATH value="..\..\win32;$(BCB)\lib\obj;$(BCB)\lib"/>\r
+ <WARNINGS value="-w-par"/>\r
+ </MACROS>\r
+ <OPTIONS>\r
+ <CFLAG1 value="-WD -Od -H=$(BCB)\lib\vcl50.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- \r
+ -tWD -tWM -c"/>\r
+ <PFLAGS value="-$Y+ -$W -$O- -v -JPHNE -M"/>\r
+ <RFLAGS value=""/>\r
+ <AFLAGS value="/mx /w2 /zi"/>\r
+ <LFLAGS value="-D"" -aa -Tpd -x -Gn -Gi -v"/>\r
+ </OPTIONS>\r
+ <LINKER>\r
+ <ALLOBJ value="c0d32.obj sysinit.obj $(OBJFILES)"/>\r
+ <ALLRES value="$(RESFILES)"/>\r
+ <ALLLIB value="$(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib"/>\r
+ </LINKER>\r
+ <IDEOPTIONS>\r
+[Version Info]\r
+IncludeVerInfo=0\r
+AutoIncBuild=0\r
+MajorVer=1\r
+MinorVer=0\r
+Release=0\r
+Build=0\r
+Debug=0\r
+PreRelease=0\r
+Special=0\r
+Private=0\r
+DLL=0\r
+Locale=1036\r
+CodePage=1252\r
+\r
+[Version Info Keys]\r
+CompanyName=\r
+FileDescription=\r
+FileVersion=1.0.0.0\r
+InternalName=\r
+LegalCopyright=\r
+LegalTrademarks=\r
+OriginalFilename=\r
+ProductName=\r
+ProductVersion=1.0.0.0\r
+Comments=\r
+\r
+[HistoryLists\hlIncludePath]\r
+Count1=\r
+Item0=..\win32;..\..\win32;$(BCB)\include;$(BCB)\include\vcl;..\..\include;..\..\src\misc\r
+\r
+[HistoryLists\hlLibraryPath]\r
+Count=1\r
+Item0=..\win32;..\..\win32;$(BCB)\lib\obj;$(BCB)\lib\r
+\r
+[HistoryLists\hlDebugSourcePath]\r
+Count=1\r
+Item0=$(BCB)\source\vcl\r
+\r
+[HistoryLists\hlConditionals]\r
+Count=1\r
+Item0=_DEBUG\r
+\r
+[Debugging]\r
+DebugSourceDirs=$(BCB)\source\vcl\r
+\r
+[Parameters]\r
+RunParams=\r
+HostApplication=\r
+RemoteHost=\r
+RemotePath=\r
+RemoteDebug=0\r
+\r
+[Compiler]\r
+ShowInfoMsgs=0\r
+LinkDebugVcl=0\r
+LinkCGLIB=0\r
+\r
+[Language]\r
+ActiveLang=\r
+ProjectLang=\r
+RootDir=\r
+ </IDEOPTIONS>\r
+</PROJECT>\r
--- /dev/null
+/*****************************************************************************
+ * win32.cpp : Win32 interface plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ *
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "win32.h" /* Borland specific */
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(Open) ( vlc_object_t * );
+void E_(Close) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+#define MAX_LINES_TEXT N_("maximum number of lines in the log window")
+#define MAX_LINES_LONGTEXT N_( \
+ "You can set the maximum number of lines that the log window will display."\
+ " Enter -1 if you want to keep all messages." )
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_integer( "intfwin-max-lines", 500, NULL, MAX_LINES_TEXT, MAX_LINES_LONGTEXT );
+ set_description( _("Win32 interface module") );
+ set_capability( "interface", 100 );
+ set_callbacks( E_(Open), E_(Close) );
+ add_shortcut( "win" );
+ add_shortcut( "win32" );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************\r
+ * win32.h : Win32 interface plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ *
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+\r
+/*****************************************************************************\r
+ * Exported interface functions.
+ *****************************************************************************/
+extern "C" __declspec(dllexport)\r
+ int __VLC_SYMBOL( vlc_entry ) ( module_t *p_module );\r
--- /dev/null
+/*****************************************************************************\r
+ * win32_common.h: private win32 interface description\r
+ *****************************************************************************\r
+ * Copyright (C) 2002 VideoLAN\r
+ *\r
+ * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
+ *****************************************************************************/\r
+\r
+#include "about.h"\r
+#include "disc.h"\r
+#include "mainframe.h"\r
+#include "menu.h"\r
+#include "messages.h"\r
+#include "network.h"\r
+#include "playlist.h"\r
+#include "preferences.h"\r
+\r
+VLC_DECLARE_STRUCT(es_descriptor_t)\r
+\r
+/*****************************************************************************\r
+ * The TrackBar is graduated from 0 to SLIDER_MAX_VALUE.\r
+ * SLIDER_MAX_VALUE is set to the higher acceptable value (2^31 - 1), in order\r
+ * to obtain the best precision in date calculation\r
+ *****************************************************************************/\r
+#define SLIDER_MAX_VALUE 2147483647\r
+\r
+/*****************************************************************************\r
+ * intf_sys_t: description and status of Win32 interface\r
+ *****************************************************************************/\r
+struct intf_sys_t\r
+{\r
+ /* special actions */\r
+ vlc_bool_t b_playing;\r
+ vlc_bool_t b_popup_changed; /* display popup menu ? */\r
+ vlc_bool_t b_slider_free; /* slider status */\r
+\r
+ /* menus handlers */\r
+ vlc_bool_t b_program_update; /* do we need to update programs \r
+ menu */\r
+ vlc_bool_t b_title_update; /* do we need to update title menus */\r
+ vlc_bool_t b_chapter_update; /* do we need to update chapter\r
+ menus */\r
+ vlc_bool_t b_audio_update; /* do we need to update audio menus */\r
+ vlc_bool_t b_spu_update; /* do we need to update spu menus */\r
+\r
+ /* windows and widgets */\r
+ TMainFrameDlg * p_window; /* main window */\r
+ TPlaylistDlg * p_playwin; /* playlist */\r
+ TPopupMenu * p_popup; /* popup menu */\r
+ TAboutDlg * p_about; /* about window */\r
+ TDiscDlg * p_disc; /* disc selection window */\r
+ TNetworkDlg * p_network; /* network stream window */\r
+ TPreferencesDlg * p_preferences; /* preferences window */\r
+\r
+ /* The slider */\r
+ off_t OldValue; /* previous value */\r
+\r
+ /* The messages window */\r
+ TMessagesDlg * p_messages; /* messages window */\r
+ msg_subscription_t* p_sub; /* message bank subscription */\r
+\r
+ /* Playlist management */\r
+ int i_playing; /* playlist selected item */\r
+\r
+ /* The window labels for DVD mode */\r
+ TLabel * p_label_title;\r
+ TLabel * p_label_chapter;\r
+ int i_part; /* current chapter */\r
+\r
+ /* Language information */\r
+ es_descriptor_t * p_audio_es_old;\r
+ es_descriptor_t * p_spu_es_old;\r
+\r
+ /* The input thread */\r
+ input_thread_t * p_input;\r
+};\r
+\r
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+dummy_SOURCES = dummy.c aout.c vout.c interface.c input.c decoder.c
--- /dev/null
+/*****************************************************************************
+ * aout_dummy.c : dummy audio output plugin
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: aout.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/*****************************************************************************
+ * OpenAudio: opens a dummy audio device
+ *****************************************************************************/
+int E_(OpenAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * SetFormat: pretends to set the dsp output format
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: returns available bytes in buffer
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ return( sizeof(s16) * i_buffer_limit + 1 ); /* value big enough to sleep */
+}
+
+/*****************************************************************************
+ * Play: pretends to play a sound
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ ;
+}
+
--- /dev/null
+/*****************************************************************************
+ * dec_dummy.c: dummy decoder plugin for vlc.
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: decoder.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> /* write(), close() */
+#endif
+
+#include <sys/types.h> /* open() */
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <stdio.h> /* sprintf() */
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Run ( decoder_fifo_t * );
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************
+ * Always returns 0 because we are the dummy decoder!
+ *****************************************************************************/
+int E_(OpenDecoder) ( vlc_object_t *p_this )
+{
+ ((decoder_fifo_t*)p_this)->pf_run = Run;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Run: this function is called just after the thread is created
+ *****************************************************************************/
+static int Run ( decoder_fifo_t *p_fifo )
+{
+ bit_stream_t bit_stream;
+ mtime_t last_date = mdate();
+ size_t i_bytes = 0;
+
+ char psz_file[100];
+ int i_fd;
+
+ sprintf( psz_file, "stream.%i", p_fifo->i_object_id );
+ i_fd = open( psz_file, O_WRONLY | O_CREAT | O_TRUNC, 00644 );
+
+ if( i_fd == -1 )
+ {
+ msg_Err( p_fifo, "cannot create `%s'", psz_file );
+ p_fifo->b_error = 1;
+ DecoderError( p_fifo );
+ return -1;
+ }
+
+ msg_Dbg( p_fifo, "dumping stream to file `%s'", psz_file );
+
+ InitBitstream( &bit_stream, p_fifo, NULL, NULL );
+
+ while( !p_fifo->b_die && !p_fifo->b_error )
+ {
+ byte_t byte;
+
+ byte = GetBits( &bit_stream, 8 );
+ i_bytes++;
+
+ write( i_fd, &byte, 1 );
+
+ if( mdate() < last_date + 2000000 )
+ {
+ continue;
+ }
+
+ msg_Dbg( p_fifo, "dumped %i bytes", i_bytes );
+
+ i_bytes = 0;
+ last_date = mdate();
+ }
+
+ if( i_bytes )
+ {
+ msg_Dbg( p_fifo, "dumped %i bytes", i_bytes );
+ }
+
+ close( i_fd );
+
+ if( p_fifo->b_error )
+ {
+ DecoderError( p_fifo );
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * dummy.c : dummy plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: dummy.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#include "dummy.h"
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define CHROMA_TEXT N_("dummy image chroma format")
+#define CHROMA_LONGTEXT N_( \
+ "Force the dummy video output to create images using a specific chroma " \
+ "format instead of trying to improve performances by using the most " \
+ "efficient one.")
+
+vlc_module_begin();
+ set_description( _("dummy functions module") );
+ add_shortcut( "vlc" );
+ add_submodule();
+ set_capability( "interface", 0 );
+ set_callbacks( E_(OpenIntf), NULL );
+ add_submodule();
+ set_capability( "access", 0 );
+ set_callbacks( E_(OpenAccess), NULL );
+ add_submodule();
+ set_capability( "demux", 0 );
+ set_callbacks( E_(OpenDemux), E_(CloseDemux) );
+ add_submodule();
+ set_capability( "decoder", 0 );
+ set_callbacks( E_(OpenDecoder), NULL );
+ add_submodule();
+ set_capability( "audio output", 0 );
+ set_callbacks( E_(OpenAudio), NULL );
+ add_submodule();
+ set_capability( "video output", 0 );
+ set_callbacks( E_(OpenVideo), NULL );
+ add_category_hint( N_("Video"), NULL );
+ add_string( "dummy-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * dummy.h : dummy plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001, 2002 VideoLAN
+ * $Id: dummy.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(OpenIntf) ( vlc_object_t * );
+
+int E_(OpenAccess) ( vlc_object_t * );
+
+int E_(OpenDemux) ( vlc_object_t * );
+void E_(CloseDemux) ( vlc_object_t * );
+
+int E_(OpenDecoder) ( vlc_object_t * );
+
+int E_(OpenAudio) ( vlc_object_t * );
+
+int E_(OpenVideo) ( vlc_object_t * );
+
--- /dev/null
+/*****************************************************************************
+ * input_dummy.c: dummy input plugin, to manage "vlc:***" special options
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: input.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/input.h>
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Demux ( input_thread_t * );
+
+/*****************************************************************************
+ * access_sys_t: private input data
+ *****************************************************************************/
+struct demux_sys_t
+{
+ /* The real command */
+ int i_command;
+
+ /* Used for the pause command */
+ mtime_t expiration;
+};
+
+#define COMMAND_NOP 0
+#define COMMAND_QUIT 1
+#define COMMAND_LOOP 2
+#define COMMAND_PAUSE 3
+
+/*****************************************************************************
+ * OpenAccess: open the target, ie. do nothing
+ *****************************************************************************/
+int E_(OpenAccess) ( vlc_object_t *p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+
+ p_input->stream.i_method = INPUT_METHOD_NONE;
+
+ /* Force dummy demux plug-in */
+ p_input->psz_demux = "vlc";
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * OpenDemux: initialize the target, ie. parse the command
+ *****************************************************************************/
+int E_(OpenDemux) ( vlc_object_t *p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+ char * psz_name = p_input->psz_name;
+ int i_len = strlen( psz_name );
+ struct demux_sys_t * p_method;
+ int i_arg;
+
+ p_input->stream.b_seekable = 0;
+ p_input->pf_demux = Demux;
+ p_input->pf_rewind = NULL;
+
+ p_method = malloc( sizeof( struct demux_sys_t ) );
+ if( p_method == NULL )
+ {
+ msg_Err( p_input, "out of memory" );
+ return -1;
+ }
+
+ p_input->p_demux_data = p_method;
+ p_input->stream.p_demux_data = NULL;
+
+ /* Check for a "vlc:nop" command */
+ if( i_len == 3 && !strncasecmp( psz_name, "nop", 3 ) )
+ {
+ msg_Info( p_input, "command `nop'" );
+ p_method->i_command = COMMAND_NOP;
+ return 0;
+ }
+
+ /* Check for a "vlc:quit" command */
+ if( i_len == 4 && !strncasecmp( psz_name, "quit", 4 ) )
+ {
+ msg_Info( p_input, "command `quit'" );
+ p_method->i_command = COMMAND_QUIT;
+ return 0;
+ }
+
+ /* Check for a "vlc:loop" command */
+ if( i_len == 4 && !strncasecmp( psz_name, "loop", 4 ) )
+ {
+ msg_Info( p_input, "command `loop'" );
+ p_method->i_command = COMMAND_LOOP;
+ return 0;
+ }
+
+ /* Check for a "vlc:pause:***" command */
+ if( i_len > 6 && !strncasecmp( psz_name, "pause:", 6 ) )
+ {
+ i_arg = atoi( psz_name + 6 );
+ msg_Info( p_input, "command `pause %i'", i_arg );
+ p_method->i_command = COMMAND_PAUSE;
+ p_method->expiration = mdate() + (mtime_t)i_arg * (mtime_t)1000000;
+ return 0;
+ }
+
+ msg_Err( p_input, "unknown command `%s'", psz_name );
+ free( p_input->p_demux_data );
+ p_input->b_error = 1;
+
+ return -1;
+}
+
+/*****************************************************************************
+ * CloseDemux: initialize the target, ie. parse the command
+ *****************************************************************************/
+void E_(CloseDemux) ( vlc_object_t *p_this )
+{
+ input_thread_t *p_input = (input_thread_t *)p_this;
+
+ free( p_input->p_demux_data );
+}
+
+/*****************************************************************************
+ * Demux: do what the command says
+ *****************************************************************************/
+static int Demux( input_thread_t *p_input )
+{
+ struct demux_sys_t * p_method = p_input->p_demux_data;
+ playlist_t *p_playlist;
+
+ p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_PARENT );
+
+ if( p_playlist == NULL )
+ {
+ msg_Err( p_input, "we are not attached to a playlist" );
+ p_input->b_error = 1;
+ return 1;
+ }
+
+ switch( p_method->i_command )
+ {
+ case COMMAND_QUIT:
+ p_input->p_vlc->b_die = 1;
+ break;
+
+ case COMMAND_LOOP:
+ playlist_Goto( p_playlist, 0 );
+ break;
+
+ case COMMAND_PAUSE:
+ if( mdate() < p_method->expiration )
+ {
+ msleep( 10000 );
+ }
+ else
+ {
+ p_input->b_eof = 1;
+ }
+ break;
+
+ case COMMAND_NOP:
+ default:
+ p_input->b_eof = 1;
+ break;
+ }
+
+ vlc_object_release( p_playlist );
+
+ return 1;
+}
+
--- /dev/null
+/*****************************************************************************
+ * intf_dummy.c: dummy interface plugin
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: interface.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static void Run ( intf_thread_t * );
+
+/*****************************************************************************
+ * Open: initialize dummy interface
+ *****************************************************************************/
+int E_(OpenIntf) ( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t*) p_this;
+#ifdef WIN32
+ AllocConsole();
+ freopen( "CONOUT$", "w", stdout );
+ freopen( "CONOUT$", "w", stderr );
+ freopen( "CONIN$", "r", stdin );
+ msg_Info( p_intf, VERSION_MESSAGE );
+ msg_Info( p_intf, _("\nUsing the dummy interface plugin...") );
+#endif
+
+ p_intf->pf_run = Run;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Run: main loop
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ while( !p_intf->b_die )
+ {
+ /* Wait a bit */
+ msleep( INTF_IDLE_SLEEP );
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * vout_dummy.c: Dummy video output display method for testing purposes
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: vout.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#define DUMMY_WIDTH 16
+#define DUMMY_HEIGHT 16
+#define DUMMY_MAX_DIRECTBUFFERS 10
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+/*****************************************************************************
+ * OpenVideo: activates dummy video thread output method
+ *****************************************************************************
+ * This function initializes a dummy vout method.
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = Display;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Init: initialize dummy video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index, i_chroma;
+ char *psz_chroma;
+ picture_t *p_pic;
+ vlc_bool_t b_chroma = 0;
+
+ psz_chroma = config_GetPsz( p_vout, "dummy-chroma" );
+ if( psz_chroma )
+ {
+ if( strlen( psz_chroma ) >= 4 )
+ {
+ i_chroma = (unsigned char)psz_chroma[0] << 0;
+ i_chroma |= (unsigned char)psz_chroma[1] << 8;
+ i_chroma |= (unsigned char)psz_chroma[2] << 16;
+ i_chroma |= (unsigned char)psz_chroma[3] << 24;
+
+ b_chroma = 1;
+ }
+
+ free( psz_chroma );
+ }
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure */
+ if( b_chroma )
+ {
+ msg_Dbg( p_vout, "forcing chroma 0x%.8x (%4.4s)",
+ i_chroma, (char*)&i_chroma );
+ p_vout->output.i_chroma = i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+ }
+ else
+ {
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
+ p_vout->output.i_rmask = 0xf800;
+ p_vout->output.i_gmask = 0x07e0;
+ p_vout->output.i_bmask = 0x001f;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+ }
+
+ /* Try to initialize DUMMY_MAX_DIRECTBUFFERS direct buffers */
+ while( I_OUTPUTPICTURES < DUMMY_MAX_DIRECTBUFFERS )
+ {
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture */
+ if( p_pic == NULL )
+ {
+ break;
+ }
+
+ vout_AllocatePicture( p_vout, p_pic, p_vout->output.i_width,
+ p_vout->output.i_height,
+ p_vout->output.i_chroma );
+
+ if( p_pic->i_planes == 0 )
+ {
+ break;
+ }
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate dummy video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Manage: handle dummy events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * console events. It returns a non null value on error.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Render: render previously calculated output
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* No need to do anything, the fake direct buffers stay as they are */
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* No need to do anything, the fake direct buffers stay as they are */
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+logger_SOURCES = logger.c
--- /dev/null
+/*****************************************************************************
+ * logger.c : file logging plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: logger.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <errno.h> /* ENOMEM */
+#include <stdio.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#define MODE_TEXT 0
+#define MODE_HTML 1
+
+#define LOG_FILE "vlc-log.txt"
+#define LOG_STRING( msg, file ) fwrite( msg, strlen( msg ), 1, file );
+
+#define TEXT_HEADER "-- logger module started --\n"
+#define TEXT_FOOTER "-- logger module stopped --\n"
+
+#define HTML_HEADER \
+ "<html>\n" \
+ " <head>\n" \
+ " <title>vlc log</title>\n" \
+ " </head>\n" \
+ " <body bgcolor=\"#000000\" text=\"#aaaaaa\">\n" \
+ " <pre>\n" \
+ " <b>-- logger module started --</b>\n"
+#define HTML_FOOTER \
+ " <b>-- logger module stopped --</b>\n" \
+ " </pre>\n" \
+ " </body>\n" \
+ "</html>\n"
+
+/*****************************************************************************
+ * intf_sys_t: description and status of log interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ int i_mode;
+
+ FILE * p_file; /* The log file */
+ msg_subscription_t *p_sub;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static void Run ( intf_thread_t * );
+
+static void FlushQueue ( msg_subscription_t *, FILE *, int );
+static void TextPrint ( const msg_item_t *, FILE * );
+static void HtmlPrint ( const msg_item_t *, FILE * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( "logfile", NULL, NULL, N_("log filename"), N_("Specify the log filename.") );
+ add_string( "logmode", NULL, NULL, N_("log format"), N_("Specify the log format. Available choices are \"text\" (default) and \"html\"") );
+ set_description( _("file logging interface module") );
+ set_capability( "interface", 0 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: initialize and create stuff
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+ char *psz_mode, *psz_file;
+
+#ifdef WIN32
+ AllocConsole();
+ freopen( "CONOUT$", "w", stdout );
+ freopen( "CONOUT$", "w", stderr );
+ freopen( "CONIN$", "r", stdin );
+ msg_Info( p_intf, VERSION_MESSAGE );
+ msg_Info( p_intf, _("\nUsing the logger interface plugin...") );
+#endif
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return -1;
+ }
+
+ psz_mode = config_GetPsz( p_intf, "logmode" );
+ if( psz_mode )
+ {
+ if( !strcmp( psz_mode, "text" ) )
+ {
+ p_intf->p_sys->i_mode = MODE_TEXT;
+ }
+ else if( !strcmp( psz_mode, "html" ) )
+ {
+ p_intf->p_sys->i_mode = MODE_HTML;
+ }
+ else
+ {
+ msg_Err( p_intf, "invalid log mode `%s', using `text'", psz_mode );
+ p_intf->p_sys->i_mode = MODE_TEXT;
+ }
+
+ free( psz_mode );
+ }
+ else
+ {
+ msg_Warn( p_intf, "no log mode specified, using `text'" );
+ p_intf->p_sys->i_mode = MODE_TEXT;
+ }
+
+ psz_file = config_GetPsz( p_intf, "logfile" );
+ if( !psz_file )
+ {
+ switch( p_intf->p_sys->i_mode )
+ {
+ case MODE_HTML:
+ psz_file = strdup( "vlc-log.html" );
+ break;
+ case MODE_TEXT:
+ default:
+ psz_file = strdup( "vlc-log.txt" );
+ break;
+ }
+
+ msg_Warn( p_intf, "no log filename provided, using `%s'", psz_file );
+ }
+
+ /* Open the log file and remove any buffering for the stream */
+ msg_Dbg( p_intf, "opening logfile `%s'", psz_file );
+ p_intf->p_sys->p_file = fopen( psz_file, "wt" );
+ setvbuf( p_intf->p_sys->p_file, NULL, _IONBF, 0 );
+
+ p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
+
+ if( p_intf->p_sys->p_file == NULL )
+ {
+ msg_Err( p_intf, "error opening logfile `%s'", psz_file );
+ free( p_intf->p_sys );
+ msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+ free( psz_file );
+ return -1;
+ }
+
+ free( psz_file );
+
+ switch( p_intf->p_sys->i_mode )
+ {
+ case MODE_HTML:
+ LOG_STRING( HTML_HEADER, p_intf->p_sys->p_file );
+ break;
+ case MODE_TEXT:
+ default:
+ LOG_STRING( TEXT_HEADER, p_intf->p_sys->p_file );
+ break;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Close: destroy interface stuff
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Flush the queue and unsubscribe from the message queue */
+ FlushQueue( p_intf->p_sys->p_sub, p_intf->p_sys->p_file,
+ p_intf->p_sys->i_mode );
+ msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+
+ switch( p_intf->p_sys->i_mode )
+ {
+ case MODE_HTML:
+ LOG_STRING( HTML_FOOTER, p_intf->p_sys->p_file );
+ break;
+ case MODE_TEXT:
+ default:
+ LOG_STRING( TEXT_FOOTER, p_intf->p_sys->p_file );
+ break;
+ }
+
+ /* Close the log file */
+ fclose( p_intf->p_sys->p_file );
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: rc thread
+ *****************************************************************************
+ * This part of the interface is in a separate thread so that we can call
+ * exec() from within it without annoying the rest of the program.
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ while( !p_intf->b_die )
+ {
+ FlushQueue( p_intf->p_sys->p_sub, p_intf->p_sys->p_file,
+ p_intf->p_sys->i_mode );
+
+ msleep( INTF_IDLE_SLEEP );
+ }
+}
+
+/*****************************************************************************
+ * FlushQueue: flush the message queue into the log file
+ *****************************************************************************/
+static void FlushQueue( msg_subscription_t *p_sub, FILE *p_file, int i_mode )
+{
+ int i_start, i_stop;
+
+ vlc_mutex_lock( p_sub->p_lock );
+ i_stop = *p_sub->pi_stop;
+ vlc_mutex_unlock( p_sub->p_lock );
+
+ if( p_sub->i_start != i_stop )
+ {
+ /* Append all messages to log file */
+ for( i_start = p_sub->i_start;
+ i_start != i_stop;
+ i_start = (i_start+1) % VLC_MSG_QSIZE )
+ {
+ switch( i_mode )
+ {
+ case MODE_HTML:
+ HtmlPrint( &p_sub->p_msg[i_start], p_file );
+ break;
+ case MODE_TEXT:
+ default:
+ TextPrint( &p_sub->p_msg[i_start], p_file );
+ break;
+ }
+ }
+
+ vlc_mutex_lock( p_sub->p_lock );
+ p_sub->i_start = i_start;
+ vlc_mutex_unlock( p_sub->p_lock );
+ }
+}
+
+static const char *ppsz_type[4] = { ": ", " error: ",
+ " warning: ", " debug: " };
+
+static void TextPrint( const msg_item_t *p_msg, FILE *p_file )
+{
+ LOG_STRING( p_msg->psz_module, p_file );
+ LOG_STRING( ppsz_type[p_msg->i_type], p_file );
+ LOG_STRING( p_msg->psz_msg, p_file );
+ LOG_STRING( "\n", p_file );
+}
+
+static void HtmlPrint( const msg_item_t *p_msg, FILE *p_file )
+{
+ static const char *ppsz_color[4] = { "<font color=\"#ffffff\">",
+ "<font color=\"#ff6666\">",
+ "<font color=\"#ffff66\">",
+ "<font color=\"#aaaaaa\">" };
+
+ LOG_STRING( p_msg->psz_module, p_file );
+ LOG_STRING( ppsz_type[p_msg->i_type], p_file );
+ LOG_STRING( ppsz_color[p_msg->i_type], p_file );
+ LOG_STRING( p_msg->psz_msg, p_file );
+ LOG_STRING( "</font>\n", p_file );
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+memcpy_SOURCES = memcpy.c
+memcpymmx_SOURCES = memcpy.c
+memcpymmxext_SOURCES = memcpy.c
+memcpy3dn_SOURCES = memcpy.c
+memcpyaltivec_SOURCES = memcpyaltivec.c
--- /dev/null
+/*****************************************************************************
+ * fastmemcpy.h : fast memcpy routines
+ *****************************************************************************
+ * $Id: fastmemcpy.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: various Linux kernel hackers
+ * various MPlayer hackers
+ * Nick Kurshev <nickols_k@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*
+ aclib - advanced C library ;)
+ This file contains functions which improve and expand standard C-library
+*/
+
+#define BLOCK_SIZE 4096
+#define CONFUSION_FACTOR 0
+//Feel free to fine-tune the above 2, it might be possible to get some speedup with them :)
+
+//#define STATISTICS
+
+#ifndef HAVE_SSE2
+/*
+ P3 processor has only one SSE decoder so can execute only 1 sse insn per
+ cpu clock, but it has 3 mmx decoders (include load/store unit)
+ and executes 3 mmx insns per cpu clock.
+ P4 processor has some chances, but after reading:
+ http://www.emulators.com/pentium4.htm
+ I have doubts. Anyway SSE2 version of this code can be written better.
+*/
+#undef HAVE_SSE
+#endif
+
+
+/*
+ This part of code was taken by me from Linux-2.4.3 and slightly modified
+for MMX, MMX2, SSE instruction set. I have done it since linux uses page aligned
+blocks but mplayer uses weakly ordered data and original sources can not
+speedup them. Only using PREFETCHNTA and MOVNTQ together have effect!
+
+>From IA-32 Intel Architecture Software Developer's Manual Volume 1,
+
+Order Number 245470:
+"10.4.6. Cacheability Control, Prefetch, and Memory Ordering Instructions"
+
+Data referenced by a program can be temporal (data will be used again) or
+non-temporal (data will be referenced once and not reused in the immediate
+future). To make efficient use of the processor's caches, it is generally
+desirable to cache temporal data and not cache non-temporal data. Overloading
+the processor's caches with non-temporal data is sometimes referred to as
+"polluting the caches".
+The non-temporal data is written to memory with Write-Combining semantics.
+
+The PREFETCHh instructions permits a program to load data into the processor
+at a suggested cache level, so that it is closer to the processors load and
+store unit when it is needed. If the data is already present in a level of
+the cache hierarchy that is closer to the processor, the PREFETCHh instruction
+will not result in any data movement.
+But we should you PREFETCHNTA: Non-temporal data fetch data into location
+close to the processor, minimizing cache pollution.
+
+The MOVNTQ (store quadword using non-temporal hint) instruction stores
+packed integer data from an MMX register to memory, using a non-temporal hint.
+The MOVNTPS (store packed single-precision floating-point values using
+non-temporal hint) instruction stores packed floating-point data from an
+XMM register to memory, using a non-temporal hint.
+
+The SFENCE (Store Fence) instruction controls write ordering by creating a
+fence for memory store operations. This instruction guarantees that the results
+of every store instruction that precedes the store fence in program order is
+globally visible before any store instruction that follows the fence. The
+SFENCE instruction provides an efficient way of ensuring ordering between
+procedures that produce weakly-ordered data and procedures that consume that
+data.
+
+If you have questions please contact with me: Nick Kurshev: nickols_k@mail.ru.
+*/
+
+// 3dnow memcpy support from kernel 2.4.2
+// by Pontscho/fresh!mindworkz
+
+#if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX )
+
+#undef HAVE_MMX1
+#if defined(HAVE_MMX) && !defined(HAVE_MMX2) && !defined(HAVE_3DNOW) && !defined(HAVE_SSE)
+/* means: mmx v.1. Note: Since we added alignment of destinition it speedups
+ of memory copying on PentMMX, Celeron-1 and P2 upto 12% versus
+ standard (non MMX-optimized) version.
+ Note: on K6-2+ it speedups memory copying upto 25% and
+ on K7 and P3 about 500% (5 times). */
+#define HAVE_MMX1
+#endif
+
+
+#undef HAVE_K6_2PLUS
+#if !defined( HAVE_MMX2) && defined( HAVE_3DNOW)
+#define HAVE_K6_2PLUS
+#endif
+
+/* for small memory blocks (<256 bytes) this version is faster */
+#define small_memcpy(to,from,n)\
+{\
+register unsigned long int dummy;\
+__asm__ __volatile__(\
+ "rep; movsb"\
+ :"=&D"(to), "=&S"(from), "=&c"(dummy)\
+/* It's most portable way to notify compiler */\
+/* that edi, esi and ecx are clobbered in asm block. */\
+/* Thanks to A'rpi for hint!!! */\
+ :"0" (to), "1" (from),"2" (n)\
+ : "memory");\
+}
+
+#ifdef HAVE_SSE
+#define MMREG_SIZE 16
+#else
+#define MMREG_SIZE 64 //8
+#endif
+
+/* Small defines (for readability only) ;) */
+#ifdef HAVE_K6_2PLUS
+#define PREFETCH "prefetch"
+/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */
+#define EMMS "femms"
+#else
+#define PREFETCH "prefetchnta"
+#define EMMS "emms"
+#endif
+
+#ifdef HAVE_MMX2
+#define MOVNTQ "movntq"
+#else
+#define MOVNTQ "movq"
+#endif
+
+#ifdef HAVE_MMX1
+#define MIN_LEN 0x800 /* 2K blocks */
+#else
+#define MIN_LEN 0x40 /* 64-byte blocks */
+#endif
+
+void * fast_memcpy(void * to, const void * from, size_t len)
+{
+ void *retval;
+ size_t i;
+ retval = to;
+#ifdef STATISTICS
+ {
+ static int freq[33];
+ static int t=0;
+ int i;
+ for(i=0; len>(1<<i); i++);
+ freq[i]++;
+ t++;
+ if(1024*1024*1024 % t == 0)
+ for(i=0; i<32; i++)
+ printf("freq < %8d %4d\n", 1<<i, freq[i]);
+ }
+#endif
+#ifndef HAVE_MMX1
+ /* PREFETCH has effect even for MOVSB instruction ;) */
+ __asm__ __volatile__ (
+ PREFETCH" (%0)\n"
+ PREFETCH" 64(%0)\n"
+ PREFETCH" 128(%0)\n"
+ PREFETCH" 192(%0)\n"
+ PREFETCH" 256(%0)\n"
+ : : "r" (from) );
+#endif
+ if(len >= MIN_LEN)
+ {
+ register unsigned long int delta;
+ /* Align destinition to MMREG_SIZE -boundary */
+ delta = ((unsigned long int)to)&(MMREG_SIZE-1);
+ if(delta)
+ {
+ delta=MMREG_SIZE-delta;
+ len -= delta;
+ small_memcpy(to, from, delta);
+ }
+ i = len >> 6; /* len/64 */
+ len&=63;
+ /*
+ This algorithm is top effective when the code consequently
+ reads and writes blocks which have size of cache line.
+ Size of cache line is processor-dependent.
+ It will, however, be a minimum of 32 bytes on any processors.
+ It would be better to have a number of instructions which
+ perform reading and writing to be multiple to a number of
+ processor's decoders, but it's not always possible.
+ */
+#ifdef HAVE_SSE /* Only P3 (may be Cyrix3) */
+ if(((unsigned long)from) & 15)
+ /* if SRC is misaligned */
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+ PREFETCH" 320(%0)\n"
+ "movups (%0), %%xmm0\n"
+ "movups 16(%0), %%xmm1\n"
+ "movups 32(%0), %%xmm2\n"
+ "movups 48(%0), %%xmm3\n"
+ "movntps %%xmm0, (%1)\n"
+ "movntps %%xmm1, 16(%1)\n"
+ "movntps %%xmm2, 32(%1)\n"
+ "movntps %%xmm3, 48(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+ else
+ /*
+ Only if SRC is aligned on 16-byte boundary.
+ It allows to use movaps instead of movups, which required data
+ to be aligned or a general-protection exception (#GP) is generated.
+ */
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+ PREFETCH" 320(%0)\n"
+ "movaps (%0), %%xmm0\n"
+ "movaps 16(%0), %%xmm1\n"
+ "movaps 32(%0), %%xmm2\n"
+ "movaps 48(%0), %%xmm3\n"
+ "movntps %%xmm0, (%1)\n"
+ "movntps %%xmm1, 16(%1)\n"
+ "movntps %%xmm2, 32(%1)\n"
+ "movntps %%xmm3, 48(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+#else
+ // Align destination at BLOCK_SIZE boundary
+ for(; ((int)to & (BLOCK_SIZE-1)) && i>0; i--)
+ {
+ __asm__ __volatile__ (
+#ifndef HAVE_MMX1
+ PREFETCH" 320(%0)\n"
+#endif
+ "movq (%0), %%mm0\n"
+ "movq 8(%0), %%mm1\n"
+ "movq 16(%0), %%mm2\n"
+ "movq 24(%0), %%mm3\n"
+ "movq 32(%0), %%mm4\n"
+ "movq 40(%0), %%mm5\n"
+ "movq 48(%0), %%mm6\n"
+ "movq 56(%0), %%mm7\n"
+ MOVNTQ" %%mm0, (%1)\n"
+ MOVNTQ" %%mm1, 8(%1)\n"
+ MOVNTQ" %%mm2, 16(%1)\n"
+ MOVNTQ" %%mm3, 24(%1)\n"
+ MOVNTQ" %%mm4, 32(%1)\n"
+ MOVNTQ" %%mm5, 40(%1)\n"
+ MOVNTQ" %%mm6, 48(%1)\n"
+ MOVNTQ" %%mm7, 56(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+
+// printf(" %d %d\n", (int)from&1023, (int)to&1023);
+ // Pure Assembly cuz gcc is a bit unpredictable ;)
+# if 0
+ if(i>=BLOCK_SIZE/64)
+ asm volatile(
+ "xorl %%eax, %%eax \n\t"
+ ".balign 16 \n\t"
+ "1: \n\t"
+ "movl (%0, %%eax), %%ebx \n\t"
+ "movl 32(%0, %%eax), %%ebx \n\t"
+ "movl 64(%0, %%eax), %%ebx \n\t"
+ "movl 96(%0, %%eax), %%ebx \n\t"
+ "addl $128, %%eax \n\t"
+ "cmpl %3, %%eax \n\t"
+ " jb 1b \n\t"
+
+ "xorl %%eax, %%eax \n\t"
+
+ ".balign 16 \n\t"
+ "2: \n\t"
+ "movq (%0, %%eax), %%mm0\n"
+ "movq 8(%0, %%eax), %%mm1\n"
+ "movq 16(%0, %%eax), %%mm2\n"
+ "movq 24(%0, %%eax), %%mm3\n"
+ "movq 32(%0, %%eax), %%mm4\n"
+ "movq 40(%0, %%eax), %%mm5\n"
+ "movq 48(%0, %%eax), %%mm6\n"
+ "movq 56(%0, %%eax), %%mm7\n"
+ MOVNTQ" %%mm0, (%1, %%eax)\n"
+ MOVNTQ" %%mm1, 8(%1, %%eax)\n"
+ MOVNTQ" %%mm2, 16(%1, %%eax)\n"
+ MOVNTQ" %%mm3, 24(%1, %%eax)\n"
+ MOVNTQ" %%mm4, 32(%1, %%eax)\n"
+ MOVNTQ" %%mm5, 40(%1, %%eax)\n"
+ MOVNTQ" %%mm6, 48(%1, %%eax)\n"
+ MOVNTQ" %%mm7, 56(%1, %%eax)\n"
+ "addl $64, %%eax \n\t"
+ "cmpl %3, %%eax \n\t"
+ "jb 2b \n\t"
+
+#if CONFUSION_FACTOR > 0
+ // a few percent speedup on out of order executing CPUs
+ "movl %5, %%eax \n\t"
+ "2: \n\t"
+ "movl (%0), %%ebx \n\t"
+ "movl (%0), %%ebx \n\t"
+ "movl (%0), %%ebx \n\t"
+ "movl (%0), %%ebx \n\t"
+ "decl %%eax \n\t"
+ " jnz 2b \n\t"
+#endif
+
+ "xorl %%eax, %%eax \n\t"
+ "addl %3, %0 \n\t"
+ "addl %3, %1 \n\t"
+ "subl %4, %2 \n\t"
+ "cmpl %4, %2 \n\t"
+ " jae 1b \n\t"
+ : "+r" (from), "+r" (to), "+r" (i)
+ : "r" (BLOCK_SIZE), "i" (BLOCK_SIZE/64), "i" (CONFUSION_FACTOR)
+ : "%eax", "%ebx"
+ );
+#endif
+
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+#ifndef HAVE_MMX1
+ PREFETCH" 320(%0)\n"
+#endif
+ "movq (%0), %%mm0\n"
+ "movq 8(%0), %%mm1\n"
+ "movq 16(%0), %%mm2\n"
+ "movq 24(%0), %%mm3\n"
+ "movq 32(%0), %%mm4\n"
+ "movq 40(%0), %%mm5\n"
+ "movq 48(%0), %%mm6\n"
+ "movq 56(%0), %%mm7\n"
+ MOVNTQ" %%mm0, (%1)\n"
+ MOVNTQ" %%mm1, 8(%1)\n"
+ MOVNTQ" %%mm2, 16(%1)\n"
+ MOVNTQ" %%mm3, 24(%1)\n"
+ MOVNTQ" %%mm4, 32(%1)\n"
+ MOVNTQ" %%mm5, 40(%1)\n"
+ MOVNTQ" %%mm6, 48(%1)\n"
+ MOVNTQ" %%mm7, 56(%1)\n"
+ :: "r" (from), "r" (to) : "memory");
+ ((const unsigned char *)from)+=64;
+ ((unsigned char *)to)+=64;
+ }
+
+#endif /* Have SSE */
+#ifdef HAVE_MMX2
+ /* since movntq is weakly-ordered, a "sfence"
+ * is needed to become ordered again. */
+ __asm__ __volatile__ ("sfence":::"memory");
+#endif
+#ifndef HAVE_SSE
+ /* enables to use FPU */
+ __asm__ __volatile__ (EMMS:::"memory");
+#endif
+ }
+ /*
+ * Now do the tail of the block
+ */
+ if(len) small_memcpy(to, from, len);
+ return retval;
+}
+
+
+#endif /* #if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX ) */
--- /dev/null
+/*****************************************************************************
+ * memcpy.c : classic memcpy module
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: memcpy.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_SSE
+#undef HAVE_SSE2
+#undef HAVE_3DNOW
+#undef HAVE_ALTIVEC
+
+#if defined( MODULE_NAME_IS_memcpy3dn )
+# define PRIORITY 100
+# define HAVE_3DNOW
+#elif defined( MODULE_NAME_IS_memcpymmx )
+# define PRIORITY 100
+# define HAVE_MMX
+#elif defined( MODULE_NAME_IS_memcpymmxext )
+# define PRIORITY 200
+# define HAVE_MMX2
+#else
+# define PRIORITY 50
+#endif
+
+/*****************************************************************************
+ * Extern prototype
+ *****************************************************************************/
+#ifndef MODULE_NAME_IS_memcpy
+# define fast_memcpy E_(fast_memcpy)
+# include "fastmemcpy.h"
+#endif
+
+/*****************************************************************************
+ * Module initializer
+ *****************************************************************************/
+static int Activate ( vlc_object_t *p_this )
+{
+#ifdef MODULE_NAME_IS_memcpy
+ p_this->p_vlc->pf_memcpy = memcpy;
+#else
+ p_this->p_vlc->pf_memcpy = fast_memcpy;
+#endif
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#ifdef MODULE_NAME_IS_memcpy
+ set_description( _("libc memcpy module") );
+ add_shortcut( "c" );
+ add_shortcut( "libc" );
+#elif defined( MODULE_NAME_IS_memcpy3dn )
+ set_description( _("3D Now! memcpy module") );
+ add_requirement( 3DNOW );
+ add_shortcut( "3dn" );
+ add_shortcut( "3dnow" );
+ add_shortcut( "memcpy3dn" );
+ add_shortcut( "memcpy3dnow" );
+#elif defined( MODULE_NAME_IS_memcpymmx )
+ set_description( _("MMX memcpy module") );
+ add_requirement( MMX );
+ add_shortcut( "mmx" );
+ add_shortcut( "memcpymmx" );
+#elif defined( MODULE_NAME_IS_memcpymmxext )
+ set_description( _("MMX EXT memcpy module") );
+ add_requirement( MMXEXT );
+ add_shortcut( "mmxext" );
+ add_shortcut( "memcpymmxext" );
+#endif
+ set_capability( "memcpy", PRIORITY );
+ set_callbacks( Activate, NULL );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * memcpyaltivec.c : AltiVec memcpy module
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: memcpyaltivec.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#ifndef __BUILD_ALTIVEC_ASM__
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static void * fast_memcpy ( void * to, const void * from, size_t len );
+
+/*****************************************************************************
+ * Module initializer.
+ *****************************************************************************/
+static int Activate ( vlc_object_t *p_this )
+{
+ p_this->p_vlc->pf_memcpy = fast_memcpy;
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("AltiVec memcpy module") );
+ set_capability( "memcpy", 100 );
+ set_callbacks( Activate, NULL );
+ add_shortcut( "altivec" );
+vlc_module_end();
+
+#else
+typedef unsigned long size_t;
+#endif /* __BUILD_ALTIVEC_ASM__ */
+
+#if defined(CAN_COMPILE_C_ALTIVEC) || defined( __BUILD_ALTIVEC_ASM__ )
+
+#define vector_s16_t vector signed short
+#define vector_u16_t vector unsigned short
+#define vector_s8_t vector signed char
+#define vector_u8_t vector unsigned char
+#define vector_s32_t vector signed int
+#define vector_u32_t vector unsigned int
+#define MMREG_SIZE 16
+
+#define SMALL_MEMCPY(to, from, len) \
+{ \
+ unsigned char * end = to + len; \
+ while( to < end ) \
+ { \
+ *to++ = *from++; \
+ } \
+}
+
+static void * fast_memcpy( void * _to, const void * _from, size_t len )
+{
+ void * retval = _to;
+ unsigned char * to = (unsigned char *)_to;
+ unsigned char * from = (unsigned char *)_from;
+
+ if( len > 16 )
+ {
+ /* Align destination to MMREG_SIZE -boundary */
+ register unsigned long int delta;
+
+ delta = ((unsigned long)to)&(MMREG_SIZE-1);
+ if( delta )
+ {
+ delta = MMREG_SIZE - delta;
+ len -= delta;
+ SMALL_MEMCPY(to, from, delta);
+ }
+
+ if( len & ~(MMREG_SIZE-1) )
+ {
+ vector_u8_t perm, ref0, ref1, tmp;
+
+ perm = vec_lvsl( 0, from );
+ ref0 = vec_ld( 0, from );
+ ref1 = vec_ld( 15, from );
+ from += 16;
+ len -= 16;
+ tmp = vec_perm( ref0, ref1, perm );
+ while( len & ~(MMREG_SIZE-1) )
+ {
+ ref0 = vec_ld( 0, from );
+ ref1 = vec_ld( 15, from );
+ from += 16;
+ len -= 16;
+ vec_st( tmp, 0, to );
+ tmp = vec_perm( ref0, ref1, perm );
+ to += 16;
+ }
+ vec_st( tmp, 0, to );
+ to += 16;
+ }
+ }
+
+ if( len )
+ {
+ SMALL_MEMCPY( to, from, len );
+ }
+
+ return retval;
+}
+
+#endif
+
+#if !defined(CAN_COMPILE_C_ALTIVEC) && !defined(__BUILD_ALTIVEC_ASM__)
+
+/*
+ * The asm code is generated with:
+ *
+ * gcc-2.95 -fvec -D__BUILD_ALTIVEC_ASM__ -O9 -fomit-frame-pointer -mregnames -S * memcpyaltivec.c
+ *
+ * sed 's/.L/._L/g' memcpyaltivec.s |
+ * awk '{args=""; len=split ($2, arg, ",");
+ * for (i=1; i<=len; i++) { a=arg[i]; if (i<len) a=a",";
+ * args = args sprintf ("%-6s", a) }
+ * printf ("\t\"\t%-16s%-24s\\n\"\n", $1, args) }' |
+ * unexpand -a
+ */
+
+static void * fast_memcpy( void * _to, const void * _from, size_t len )
+{
+ asm (" \n"
+ " cmplwi %cr0, %r5, 16 \n"
+ " mr %r9, %r3 \n"
+ " bc 4, 1, ._L3 \n"
+ " andi. %r0, %r3, 15 \n"
+ " bc 12, 2, ._L4 \n"
+ " subfic %r0, %r0, 16 \n"
+ " add %r11, %r3, %r0 \n"
+ " cmplw %cr0, %r3, %r11 \n"
+ " subf %r5, %r0, %r5 \n"
+ " bc 4, 0, ._L4 \n"
+ " ._L7: \n"
+ " lbz %r0, 0(%r4) \n"
+ " stb %r0, 0(%r9) \n"
+ " addi %r9, %r9, 1 \n"
+ " cmplw %cr0, %r9, %r11 \n"
+ " addi %r4, %r4, 1 \n"
+ " bc 12, 0, ._L7 \n"
+ " ._L4: \n"
+ " rlwinm. %r0, %r5, 0, 0, 27 \n"
+ " bc 12, 2, ._L3 \n"
+ " addi %r5, %r5, -16 \n"
+ " li %r11, 15 \n"
+ " lvsl %v12, 0, %r4 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r11, %r4 \n"
+ " rlwinm. %r0, %r5, 0, 0, 27 \n"
+ " vperm %v13, %v1, %v0, %v12 \n"
+ " addi %r4, %r4, 16 \n"
+ " bc 12, 2, ._L11 \n"
+ " ._L12: \n"
+ " addi %r5, %r5, -16 \n"
+ " li %r11, 15 \n"
+ " lvx %v1, 0, %r4 \n"
+ " lvx %v0, %r11, %r4 \n"
+ " rlwinm. %r0, %r5, 0, 0, 27 \n"
+ " stvx %v13, 0, %r9 \n"
+ " vperm %v13, %v1, %v0, %v12 \n"
+ " addi %r4, %r4, 16 \n"
+ " addi %r9, %r9, 16 \n"
+ " bc 4, 2, ._L12 \n"
+ " ._L11: \n"
+ " stvx %v13, 0, %r9 \n"
+ " addi %r9, %r9, 16 \n"
+ " ._L3: \n"
+ " cmpwi %cr0, %r5, 0 \n"
+ " bclr 12, 2 \n"
+ " add %r5, %r9, %r5 \n"
+ " cmplw %cr0, %r9, %r5 \n"
+ " bclr 4, 0 \n"
+ " ._L17: \n"
+ " lbz %r0, 0(%r4) \n"
+ " stb %r0, 0(%r9) \n"
+ " addi %r9, %r9, 1 \n"
+ " cmplw %cr0, %r9, %r5 \n"
+ " addi %r4, %r4, 1 \n"
+ " bc 12, 0, ._L17 \n"
+ );
+}
+
+#endif
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+ipv4_SOURCES = ipv4.c
+ipv6_SOURCES = ipv6.c
--- /dev/null
+/*****************************************************************************
+ * ipv4.c: IPv4 network abstraction layer
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: ipv4.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Mathias Kretschmer <mathias@research.att.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#elif defined( _MSC_VER ) && defined( _WIN32 )
+# include <io.h>
+#endif
+
+#ifdef WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# ifndef IN_MULTICAST
+# define IN_MULTICAST(a) IN_CLASSD(a)
+# endif
+#else
+# include <netdb.h> /* hostent ... */
+# include <sys/socket.h>
+# include <netinet/in.h>
+# ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h> /* inet_ntoa(), inet_aton() */
+# endif
+#endif
+
+#include "network.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int NetOpen( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("IPv4 network abstraction layer") );
+ set_capability( "network", 50 );
+ set_callbacks( NetOpen, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * BuildAddr: utility function to build a struct sockaddr_in
+ *****************************************************************************/
+static int BuildAddr( struct sockaddr_in * p_socket,
+ const char * psz_address, int i_port )
+{
+ /* Reset struct */
+ memset( p_socket, 0, sizeof( struct sockaddr_in ) );
+ p_socket->sin_family = AF_INET; /* family */
+ p_socket->sin_port = htons( i_port );
+ if( !*psz_address )
+ {
+ p_socket->sin_addr.s_addr = INADDR_ANY;
+ }
+ else
+ {
+ struct hostent * p_hostent;
+
+ /* Try to convert address directly from in_addr - this will work if
+ * psz_address is dotted decimal. */
+#ifdef HAVE_ARPA_INET_H
+ if( !inet_aton( psz_address, &p_socket->sin_addr ) )
+#else
+ if( (p_socket->sin_addr.s_addr = inet_addr( psz_address )) == -1 )
+#endif
+ {
+ /* We have a fqdn, try to find its address */
+ if ( (p_hostent = gethostbyname( psz_address )) == NULL )
+ {
+//X intf_ErrMsg( "BuildLocalAddr: unknown host %s", psz_address );
+ return( -1 );
+ }
+
+ /* Copy the first address of the host in the socket address */
+ memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
+ p_hostent->h_length );
+ }
+ }
+ return( 0 );
+}
+
+/*****************************************************************************
+ * OpenUDP: open a UDP socket
+ *****************************************************************************
+ * psz_bind_addr, i_bind_port : address and port used for the bind()
+ * system call. If psz_bind_addr == "", the socket is bound to
+ * INADDR_ANY and broadcast reception is enabled. If i_bind_port == 0,
+ * 1234 is used. If psz_bind_addr is a multicast (class D) address,
+ * join the multicast group.
+ * psz_server_addr, i_server_port : address and port used for the connect()
+ * system call. It can avoid receiving packets from unauthorized IPs.
+ * Its use leads to great confusion and is currently discouraged.
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
+{
+ char * psz_bind_addr = p_socket->psz_bind_addr;
+ int i_bind_port = p_socket->i_bind_port;
+ char * psz_server_addr = p_socket->psz_server_addr;
+ int i_server_port = p_socket->i_server_port;
+#ifdef WIN32
+ char * psz_bind_win32; /* WIN32 multicast kludge */
+#endif
+
+ int i_handle, i_opt, i_opt_size;
+ struct sockaddr_in sock;
+
+ if( i_bind_port == 0 )
+ {
+ i_bind_port = config_GetInt( p_this, "server-port" );
+ }
+
+ /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
+ * protocol */
+ if( (i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 )
+ {
+ msg_Err( p_this, "cannot create socket (%s)", strerror(errno) );
+ return( -1 );
+ }
+
+ /* We may want to reuse an already used socket */
+ i_opt = 1;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
+ (void *) &i_opt, sizeof( i_opt ) ) == -1 )
+ {
+ msg_Err( p_this, "cannot configure socket (SO_REUSEADDR: %s)",
+ strerror(errno));
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
+ * packet loss caused by scheduling problems */
+ i_opt = 0x80000;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF,
+ (void *) &i_opt, sizeof( i_opt ) ) == -1 )
+ {
+ msg_Warn( p_this, "cannot configure socket (SO_RCVBUF: %s)",
+ strerror(errno));
+ }
+
+ /* Check if we really got what we have asked for, because Linux, etc.
+ * will silently limit the max buffer size to net.core.rmem_max which
+ * is typically only 65535 bytes */
+ i_opt = 0;
+ i_opt_size = sizeof( i_opt );
+ if( getsockopt( i_handle, SOL_SOCKET, SO_RCVBUF,
+ (void*) &i_opt, &i_opt_size ) == -1 )
+ {
+ msg_Warn( p_this, "cannot query socket (SO_RCVBUF: %s)",
+ strerror(errno) );
+ }
+ else if( i_opt < 0x80000 )
+ {
+ msg_Warn( p_this, "socket buffer size is 0x%x instead of 0x%x",
+ i_opt, 0x80000 );
+ }
+
+
+ /* Build the local socket */
+
+#ifdef WIN32
+ /* Under Win32 and for the multicast, we bind on INADDR_ANY,
+ * so let's call BuildAddr with "" instead of psz_bind_addr */
+ psz_bind_win32 = psz_bind_addr ;
+
+ /* Check if this is a multicast socket */
+ if (IN_MULTICAST( ntohl( inet_addr(psz_bind_addr) ) ) )
+ {
+ psz_bind_win32 = "";
+ }
+ if ( BuildAddr( &sock, psz_bind_win32, i_bind_port ) == -1 )
+#else
+ if ( BuildAddr( &sock, psz_bind_addr, i_bind_port ) == -1 )
+#endif
+ {
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Bind it */
+ if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 )
+ {
+ msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Allow broadcast reception if we bound on INADDR_ANY */
+ if( !*psz_bind_addr )
+ {
+ i_opt = 1;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST,
+ (void*) &i_opt, sizeof( i_opt ) ) == -1 )
+ {
+ msg_Warn( p_this, "cannot configure socket (SO_BROADCAST: %s)",
+ strerror(errno) );
+ }
+ }
+
+ /* Join the multicast group if the socket is a multicast address */
+#ifndef IN_MULTICAST
+# define IN_MULTICAST(a) IN_CLASSD(a)
+#endif
+
+#ifndef WIN32
+ if( IN_MULTICAST( ntohl(sock.sin_addr.s_addr) ) )
+ {
+ struct ip_mreq imr;
+ imr.imr_interface.s_addr = INADDR_ANY;
+ imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
+#else
+ if( IN_MULTICAST( ntohl(inet_addr(psz_bind_addr) ) ) )
+ {
+ struct ip_mreq imr;
+ imr.imr_interface.s_addr = INADDR_ANY;
+ imr.imr_multiaddr.s_addr = inet_addr(psz_bind_addr);
+#endif
+ if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char*)&imr, sizeof(struct ip_mreq) ) == -1 )
+ {
+ msg_Err( p_this, "failed to join IP multicast group (%s)",
+ strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+ }
+
+ if( *psz_server_addr )
+ {
+ /* Build socket for remote connection */
+ if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
+ {
+ msg_Err( p_this, "cannot build remote address" );
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Connect the socket */
+ if( connect( i_handle, (struct sockaddr *) &sock,
+ sizeof( sock ) ) == (-1) )
+ {
+ msg_Err( p_this, "cannot connect socket (%s)", strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+ }
+
+ p_socket->i_handle = i_handle;
+ p_socket->i_mtu = config_GetInt( p_this, "mtu" );
+ return( 0 );
+}
+
+/*****************************************************************************
+ * OpenTCP: open a TCP socket
+ *****************************************************************************
+ * psz_server_addr, i_server_port : address and port used for the connect()
+ * system call. If i_server_port == 0, 80 is used.
+ * Other parameters are ignored.
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
+{
+ char * psz_server_addr = p_socket->psz_server_addr;
+ int i_server_port = p_socket->i_server_port;
+
+ int i_handle;
+ struct sockaddr_in sock;
+
+ if( i_server_port == 0 )
+ {
+ i_server_port = 80;
+ }
+
+ /* Open a SOCK_STREAM (TCP) socket, in the AF_INET domain, automatic (0)
+ * protocol */
+ if( (i_handle = socket( AF_INET, SOCK_STREAM, 0 )) == -1 )
+ {
+ msg_Err( p_this, "cannot create socket (%s)", strerror(errno) );
+ return( -1 );
+ }
+
+ /* Build remote address */
+ if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
+ {
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Connect the socket */
+ if( connect( i_handle, (struct sockaddr *) &sock,
+ sizeof( sock ) ) == (-1) )
+ {
+ msg_Err( p_this, "cannot connect socket (%s)", strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+
+ p_socket->i_handle = i_handle;
+ p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * NetOpen: wrapper around OpenUDP and OpenTCP
+ *****************************************************************************/
+static int NetOpen( vlc_object_t * p_this )
+{
+ network_socket_t * p_socket = p_this->p_private;
+
+ if( p_socket->i_type == NETWORK_UDP )
+ {
+ return OpenUDP( p_this, p_socket );
+ }
+ else
+ {
+ return OpenTCP( p_this, p_socket );
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * ipv6.c: IPv6 network abstraction layer
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: ipv6.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Alexis Guillard <alexis.guillard@bt.com>
+ * Christophe Massiot <massiot@via.ecp.fr>
+ * Remco Poortinga <poortinga@telin.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <vlc/vlc.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#elif defined( _MSC_VER ) && defined( _WIN32 )
+# include <io.h>
+#endif
+
+#ifdef WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
+# include <netdb.h> /* hostent ... */
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <net/if.h>
+# ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h> /* inet_ntoa(), inet_aton() */
+# endif
+#endif
+
+#include "network.h"
+
+#if defined(WIN32)
+static const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}};
+/* the following will have to be removed when w32api defines them */
+#ifndef IPPROTO_IPV6
+# define IPPROTO_IPV6 41
+#endif
+#ifndef IPV6_JOIN_GROUP
+# define IPV6_JOIN_GROUP 20
+#endif
+#endif
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("IPv6 network abstraction layer") );
+ set_capability( "network", 40 );
+ set_callbacks( Open, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * BuildAddr: utility function to build a struct sockaddr_in6
+ *****************************************************************************/
+static int BuildAddr( struct sockaddr_in6 * p_socket,
+ char * psz_address, int i_port )
+{
+ char * psz_multicast_interface = "";
+
+#if defined(WIN32)
+ /* Try to get getaddrinfo() and freeaddrinfo() from wship6.dll */
+ typedef int (CALLBACK * GETADDRINFO) ( const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res );
+ typedef void (CALLBACK * FREEADDRINFO) ( struct addrinfo FAR *ai );
+
+ struct addrinfo hints, *res;
+ GETADDRINFO _getaddrinfo = NULL;
+ FREEADDRINFO _freeaddrinfo = NULL;
+
+ HINSTANCE wship6_dll = LoadLibrary("wship6.dll");
+ if( wship6_dll )
+ {
+ _getaddrinfo = (GETADDRINFO) GetProcAddress( wship6_dll,
+ "getaddrinfo" );
+ _freeaddrinfo = (FREEADDRINFO) GetProcAddress( wship6_dll,
+ "freeaddrinfo" );
+ }
+ if( !_getaddrinfo || !_freeaddrinfo )
+ {
+//X msg_Err( p_this, "no IPv6 stack installed" );
+ if( wship6_dll ) FreeLibrary( wship6_dll );
+ return( -1 );
+ }
+#endif
+
+ /* Reset struct */
+ memset( p_socket, 0, sizeof( struct sockaddr_in6 ) );
+ p_socket->sin6_family = AF_INET6; /* family */
+ p_socket->sin6_port = htons( i_port );
+ if( !*psz_address )
+ {
+ p_socket->sin6_addr = in6addr_any;
+ }
+ else if( psz_address[0] == '['
+ && psz_address[strlen(psz_address) - 1] == ']' )
+ {
+ psz_address++;
+ /* see if there is an interface name in there... */
+ if( (psz_multicast_interface = strchr(psz_address, '%')) != NULL )
+ {
+ *psz_multicast_interface = '\0';
+ psz_multicast_interface++;
+//X msg_Dbg( p_this, "Interface name specified: \"%s\"",
+// psz_multicast_interface );
+ /* now convert that interface name to an index */
+#if !defined( WIN32 )
+ p_socket->sin6_scope_id = if_nametoindex(psz_multicast_interface);
+#else
+ /* FIXME: for now we always use the default interface */
+ p_socket->sin6_scope_id = 0;
+//X msg_Warn( 3, "Using default interface. This has to be FIXED!");
+#endif
+//X msg_Warn( p_this, " = #%i\n", p_socket->sin6_scope_id );
+ }
+ psz_address[strlen(psz_address) - 1] = '\0' ;
+
+#if !defined( WIN32 )
+ inet_pton(AF_INET6, psz_address, &p_socket->sin6_addr.s6_addr);
+
+#else
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if( _getaddrinfo( psz_address, NULL, &hints, &res ) )
+ {
+ FreeLibrary( wship6_dll );
+ return( -1 );
+ }
+ memcpy( &p_socket->sin6_addr,
+ &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
+ sizeof(struct in6_addr) );
+ _freeaddrinfo( res );
+
+#endif
+ }
+ else
+ {
+#ifdef HAVE_GETHOSTBYNAME2
+ struct hostent * p_hostent;
+
+ /* We have a fqdn, try to find its address */
+ if ( (p_hostent = gethostbyname2( psz_address, AF_INET6 )) == NULL )
+ {
+//X intf_ErrMsg( "ipv6 error: unknown host %s", psz_address );
+ return( -1 );
+ }
+
+ /* Copy the first address of the host in the socket address */
+ memcpy( &p_socket->sin6_addr, p_hostent->h_addr_list[0],
+ p_hostent->h_length );
+
+#elif defined(WIN32)
+ if( _getaddrinfo( psz_address, NULL, &hints, &res ) )
+ {
+ FreeLibrary( wship6_dll );
+ return( -1 );
+ }
+ memcpy( &p_socket->sin6_addr,
+ &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
+ sizeof(struct in6_addr) );
+ _freeaddrinfo( res );
+
+#else
+//X intf_ErrMsg( "ipv6 error: IPv6 address %s is invalid", psz_address );
+ return( -1 );
+#endif
+ }
+
+#if defined(WIN32)
+ FreeLibrary( wship6_dll );
+#endif
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * OpenUDP: open a UDP socket
+ *****************************************************************************
+ * psz_bind_addr, i_bind_port : address and port used for the bind()
+ * system call. If psz_bind_addr == NULL, the socket is bound to
+ * in6addr_any and broadcast reception is enabled. If i_bind_port == 0,
+ * 1234 is used. If psz_bind_addr is a multicast (class D) address,
+ * join the multicast group.
+ * psz_server_addr, i_server_port : address and port used for the connect()
+ * system call. It can avoid receiving packets from unauthorized IPs.
+ * Its use leads to great confusion and is currently discouraged.
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
+{
+ char * psz_bind_addr = p_socket->psz_bind_addr;
+ int i_bind_port = p_socket->i_bind_port;
+ char * psz_server_addr = p_socket->psz_server_addr;
+ int i_server_port = p_socket->i_server_port;
+
+ int i_handle, i_opt, i_opt_size;
+ struct sockaddr_in6 sock;
+
+ if( i_bind_port == 0 )
+ {
+//X i_bind_port = config_GetInt( "server-port" );
+ }
+
+ /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET6 domain, automatic (0)
+ * protocol */
+ if( (i_handle = socket( AF_INET6, SOCK_DGRAM, 0 )) == -1 )
+ {
+ msg_Err( p_this, "cannot create socket (%s)", strerror(errno) );
+ return( -1 );
+ }
+
+ /* We may want to reuse an already used socket */
+ i_opt = 1;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
+ (void *) &i_opt, sizeof( i_opt ) ) == -1 )
+ {
+ msg_Err( p_this, "cannot configure socket (SO_REUSEADDR: %s)",
+ strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
+ * packet loss caused by scheduling problems */
+ i_opt = 0x80000;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF,
+ (void *) &i_opt, sizeof( i_opt ) ) == -1 )
+ {
+ msg_Warn( p_this, "cannot configure socket (SO_RCVBUF: %s)",
+ strerror(errno) );
+ }
+
+ /* Check if we really got what we have asked for, because Linux, etc.
+ * will silently limit the max buffer size to net.core.rmem_max which
+ * is typically only 65535 bytes */
+ i_opt = 0;
+ i_opt_size = sizeof( i_opt );
+ if( getsockopt( i_handle, SOL_SOCKET, SO_RCVBUF,
+ (void*) &i_opt, &i_opt_size ) == -1 )
+ {
+ msg_Warn( p_this, "cannot query socket (SO_RCVBUF: %s)",
+ strerror(errno) );
+ }
+ else if( i_opt < 0x80000 )
+ {
+ msg_Warn( p_this, "socket buffer size is 0x%x instead of 0x%x",
+ i_opt, 0x80000 );
+ }
+
+ /* Build the local socket */
+ if ( BuildAddr( &sock, psz_bind_addr, i_bind_port ) == -1 )
+ {
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Bind it */
+ if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 )
+ {
+ msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Allow broadcast reception if we bound on in6addr_any */
+ if( !*psz_bind_addr )
+ {
+ i_opt = 1;
+ if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST,
+ (void*) &i_opt, sizeof( i_opt ) ) == -1 )
+ {
+ msg_Warn( p_this, "ipv6 warning: cannot configure socket "
+ "(SO_BROADCAST: %s)", strerror(errno) );
+ }
+ }
+
+ /* Join the multicast group if the socket is a multicast address */
+ if( IN6_IS_ADDR_MULTICAST(&sock.sin6_addr) )
+ {
+ struct ipv6_mreq imr;
+ int res;
+
+ imr.ipv6mr_interface = sock.sin6_scope_id;
+ imr.ipv6mr_multiaddr = sock.sin6_addr;
+ res = setsockopt(i_handle, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void*) &imr,
+ sizeof(imr));
+
+ if( res == -1 )
+ {
+//X intf_ErrMsg( "ipv6 error: setsockopt JOIN_GROUP failed" );
+ }
+ }
+
+
+ if( *psz_server_addr )
+ {
+ /* Build socket for remote connection */
+ if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
+ {
+ msg_Err( p_this, "cannot build remote address" );
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Connect the socket */
+ if( connect( i_handle, (struct sockaddr *) &sock,
+ sizeof( sock ) ) == (-1) )
+ {
+ msg_Err( p_this, "cannot connect socket (%s)", strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+ }
+
+ p_socket->i_handle = i_handle;
+ p_socket->i_mtu = config_GetInt( p_this, "mtu" );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * OpenTCP: open a TCP socket
+ *****************************************************************************
+ * psz_server_addr, i_server_port : address and port used for the connect()
+ * system call. If i_server_port == 0, 80 is used.
+ * Other parameters are ignored.
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
+{
+ char * psz_server_addr = p_socket->psz_server_addr;
+ int i_server_port = p_socket->i_server_port;
+
+ int i_handle;
+ struct sockaddr_in6 sock;
+
+ if( i_server_port == 0 )
+ {
+ i_server_port = 80;
+ }
+
+ /* Open a SOCK_STREAM (TCP) socket, in the AF_INET6 domain, automatic (0)
+ * protocol */
+ if( (i_handle = socket( AF_INET6, SOCK_STREAM, 0 )) == -1 )
+ {
+ msg_Err( p_this, "cannot create socket (%s)", strerror(errno) );
+ return( -1 );
+ }
+
+ /* Build remote address */
+ if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
+ {
+ close( i_handle );
+ return( -1 );
+ }
+
+ /* Connect the socket */
+ if( connect( i_handle, (struct sockaddr *) &sock,
+ sizeof( sock ) ) == (-1) )
+ {
+ msg_Err( p_this, "cannot connect socket (%s)", strerror(errno) );
+ close( i_handle );
+ return( -1 );
+ }
+
+ p_socket->i_handle = i_handle;
+ p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Open: wrapper around OpenUDP and OpenTCP
+ *****************************************************************************/
+static int Open( vlc_object_t * p_this )
+{
+ network_socket_t * p_socket = p_this->p_private;
+
+ if( p_socket->i_type == NETWORK_UDP )
+ {
+ return OpenUDP( p_this, p_socket );
+ }
+ else
+ {
+ return OpenTCP( p_this, p_socket );
+ }
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+null_SOURCES = null.c
--- /dev/null
+/*****************************************************************************
+ * null.c : NULL module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2001 VideoLAN
+ * $Id: null.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("the module that does nothing") );
+vlc_module_end();
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+i420_rgb_SOURCES = i420_rgb.c i420_rgb8.c i420_rgb16.c
+i420_rgb_mmx_SOURCES = i420_rgb.c i420_rgb16.c
+i420_yuy2_SOURCES = i420_yuy2.c
+i420_yuy2_mmx_SOURCES = i420_yuy2.c
+i422_yuy2_SOURCES = i422_yuy2.c
+i422_yuy2_mmx_SOURCES = i422_yuy2.c
+i420_ymga_SOURCES = i420_ymga.c
+i420_ymga_mmx_SOURCES = i420_ymga.c
--- /dev/null
+/*****************************************************************************
+ * i420_rgb.c : YUV to bitmap RGB conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: i420_rgb.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <math.h> /* exp(), pow() */
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "i420_rgb.h"
+#if defined (MODULE_NAME_IS_i420_rgb)
+# include "i420_rgb_c.h"
+#endif
+
+/*****************************************************************************
+ * Local and extern prototypes.
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+static void Deactivate ( vlc_object_t * );
+
+#if defined (MODULE_NAME_IS_i420_rgb)
+static void SetGammaTable ( int *pi_table, double f_gamma );
+static void SetYUV ( vout_thread_t * );
+static void Set8bppPalette ( vout_thread_t *, u8 * );
+#endif
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+vlc_module_begin();
+#if defined (MODULE_NAME_IS_i420_rgb)
+ set_description( _("I420,IYUV,YV12 to "
+ "RGB,RV15,RV16,RV24,RV32 conversions") );
+ set_capability( "chroma", 80 );
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+ set_description( _( "MMX I420,IYUV,YV12 to "
+ "RV15,RV16,RV24,RV32 conversions") );
+ set_capability( "chroma", 100 );
+ add_requirement( MMX );
+#endif
+ set_callbacks( Activate, Deactivate );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: allocate a chroma function
+ *****************************************************************************
+ * This function allocates and initializes a chroma function
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+#if defined (MODULE_NAME_IS_i420_rgb)
+ size_t i_tables_size;
+#endif
+
+ if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
+ {
+ return -1;
+ }
+
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('Y','V','1','2'):
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ switch( p_vout->output.i_chroma )
+ {
+#if defined (MODULE_NAME_IS_i420_rgb)
+ case VLC_FOURCC('R','G','B','2'):
+ p_vout->chroma.pf_convert = E_(I420_RGB8);
+ break;
+#endif
+ case VLC_FOURCC('R','V','1','5'):
+ p_vout->chroma.pf_convert = E_(I420_RGB15);
+ break;
+
+ case VLC_FOURCC('R','V','1','6'):
+ p_vout->chroma.pf_convert = E_(I420_RGB16);
+ break;
+
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+ p_vout->chroma.pf_convert = E_(I420_RGB32);
+ break;
+
+ default:
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) );
+ if( p_vout->chroma.p_sys == NULL )
+ {
+ return -1;
+ }
+
+ switch( p_vout->output.i_chroma )
+ {
+#if defined (MODULE_NAME_IS_i420_rgb)
+ case VLC_FOURCC('R','G','B','2'):
+ p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH );
+ break;
+#endif
+
+ case VLC_FOURCC('R','V','1','5'):
+ case VLC_FOURCC('R','V','1','6'):
+ p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH * 2 );
+ break;
+
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+ p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH * 4 );
+ break;
+
+ default:
+ p_vout->chroma.p_sys->p_buffer = NULL;
+ break;
+ }
+
+ if( p_vout->chroma.p_sys->p_buffer == NULL )
+ {
+ free( p_vout->chroma.p_sys );
+ return -1;
+ }
+
+ p_vout->chroma.p_sys->p_offset = malloc( p_vout->output.i_width
+ * ( ( p_vout->output.i_chroma
+ == VLC_FOURCC('R','G','B','2') ) ? 2 : 1 )
+ * sizeof( int ) );
+ if( p_vout->chroma.p_sys->p_offset == NULL )
+ {
+ free( p_vout->chroma.p_sys->p_buffer );
+ free( p_vout->chroma.p_sys );
+ return -1;
+ }
+
+#if defined (MODULE_NAME_IS_i420_rgb)
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('R','G','B','2'):
+ i_tables_size = sizeof( u8 ) * PALETTE_TABLE_SIZE;
+ break;
+ case VLC_FOURCC('R','V','1','5'):
+ case VLC_FOURCC('R','V','1','6'):
+ i_tables_size = sizeof( u16 ) * RGB_TABLE_SIZE;
+ break;
+ default: /* RV24, RV32 */
+ i_tables_size = sizeof( u32 ) * RGB_TABLE_SIZE;
+ break;
+ }
+
+ p_vout->chroma.p_sys->p_base = malloc( i_tables_size );
+ if( p_vout->chroma.p_sys->p_base == NULL )
+ {
+ free( p_vout->chroma.p_sys->p_offset );
+ free( p_vout->chroma.p_sys->p_buffer );
+ free( p_vout->chroma.p_sys );
+ return -1;
+ }
+
+ SetYUV( p_vout );
+#endif
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Deactivate: free the chroma function
+ *****************************************************************************
+ * This function frees the previously allocated chroma function
+ *****************************************************************************/
+static void Deactivate( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+#if defined (MODULE_NAME_IS_i420_rgb)
+ free( p_vout->chroma.p_sys->p_base );
+#endif
+ free( p_vout->chroma.p_sys->p_offset );
+ free( p_vout->chroma.p_sys->p_buffer );
+ free( p_vout->chroma.p_sys );
+}
+
+#if defined (MODULE_NAME_IS_i420_rgb)
+/*****************************************************************************
+ * SetGammaTable: return intensity table transformed by gamma curve.
+ *****************************************************************************
+ * pi_table is a table of 256 entries from 0 to 255.
+ *****************************************************************************/
+static void SetGammaTable( int *pi_table, double f_gamma )
+{
+ int i_y; /* base intensity */
+
+ /* Use exp(gamma) instead of gamma */
+ f_gamma = exp( f_gamma );
+
+ /* Build gamma table */
+ for( i_y = 0; i_y < 256; i_y++ )
+ {
+ pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
+ }
+}
+
+/*****************************************************************************
+ * SetYUV: compute tables and set function pointers
+ *****************************************************************************/
+static void SetYUV( vout_thread_t *p_vout )
+{
+ int pi_gamma[256]; /* gamma table */
+ int i_index; /* index in tables */
+
+ /* Build gamma table */
+ SetGammaTable( pi_gamma, p_vout->f_gamma );
+
+ /*
+ * Set pointers and build YUV tables
+ */
+
+ /* Color: build red, green and blue tables */
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('R','G','B','2'):
+ p_vout->chroma.p_sys->p_rgb8 = (u8 *)p_vout->chroma.p_sys->p_base;
+ Set8bppPalette( p_vout, p_vout->chroma.p_sys->p_rgb8 );
+ break;
+
+ case VLC_FOURCC('R','V','1','5'):
+ case VLC_FOURCC('R','V','1','6'):
+ p_vout->chroma.p_sys->p_rgb16 = (u16 *)p_vout->chroma.p_sys->p_base;
+ for( i_index = 0; i_index < RED_MARGIN; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
+ p_vout->chroma.p_sys->p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
+ }
+ for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
+ p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
+ }
+ for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
+ p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
+ }
+ for( i_index = 0; i_index < 256; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
+ p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
+ p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
+ }
+ break;
+
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+ p_vout->chroma.p_sys->p_rgb32 = (u32 *)p_vout->chroma.p_sys->p_base;
+ for( i_index = 0; i_index < RED_MARGIN; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
+ p_vout->chroma.p_sys->p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
+ }
+ for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
+ p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
+ }
+ for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
+ p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
+ }
+ for( i_index = 0; i_index < 256; i_index++ )
+ {
+ p_vout->chroma.p_sys->p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
+ p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
+ p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
+ }
+ break;
+ }
+}
+
+static void Set8bppPalette( vout_thread_t *p_vout, u8 *p_rgb8 )
+{
+ #define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 )
+
+ int y,u,v;
+ int r,g,b;
+ int i = 0, j = 0;
+ u16 red[ 256 ], green[ 256 ], blue[ 256 ];
+ unsigned char p_lookup[PALETTE_TABLE_SIZE];
+
+ /* This loop calculates the intersection of an YUV box and the RGB cube. */
+ for ( y = 0; y <= 256; y += 16, i += 128 - 81 )
+ {
+ for ( u = 0; u <= 256; u += 32 )
+ {
+ for ( v = 0; v <= 256; v += 32 )
+ {
+ r = y + ( (V_RED_COEF*(v-128)) >> SHIFT );
+ g = y + ( (U_GREEN_COEF*(u-128)
+ + V_GREEN_COEF*(v-128)) >> SHIFT );
+ b = y + ( (U_BLUE_COEF*(u-128)) >> SHIFT );
+
+ if( r >= 0x00 && g >= 0x00 && b >= 0x00
+ && r <= 0xff && g <= 0xff && b <= 0xff )
+ {
+ /* This one should never happen unless someone
+ * fscked up my code */
+ if( j == 256 )
+ {
+ msg_Err( p_vout, "no colors left in palette" );
+ break;
+ }
+
+ /* Clip the colors */
+ red[ j ] = CLIP( r );
+ green[ j ] = CLIP( g );
+ blue[ j ] = CLIP( b );
+
+ /* Allocate color */
+ p_lookup[ i ] = 1;
+ p_rgb8[ i++ ] = j;
+ j++;
+ }
+ else
+ {
+ p_lookup[ i ] = 0;
+ p_rgb8[ i++ ] = 0;
+ }
+ }
+ }
+ }
+
+ /* The colors have been allocated, we can set the palette */
+ p_vout->output.pf_setpalette( p_vout, red, green, blue );
+
+#if 0
+ /* There will eventually be a way to know which colors
+ * couldn't be allocated and try to find a replacement */
+ p_vout->i_white_pixel = 0xff;
+ p_vout->i_black_pixel = 0x00;
+ p_vout->i_gray_pixel = 0x44;
+ p_vout->i_blue_pixel = 0x3b;
+#endif
+
+ /* This loop allocates colors that got outside the RGB cube */
+ for ( i = 0, y = 0; y <= 256; y += 16, i += 128 - 81 )
+ {
+ for ( u = 0; u <= 256; u += 32 )
+ {
+ for ( v = 0; v <= 256; v += 32, i++ )
+ {
+ int u2, v2, dist, mindist = 100000000;
+
+ if( p_lookup[ i ] || y == 0 )
+ {
+ continue;
+ }
+
+ /* Heavy. yeah. */
+ for( u2 = 0; u2 <= 256; u2 += 32 )
+ {
+ for( v2 = 0; v2 <= 256; v2 += 32 )
+ {
+ j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
+ dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
+
+ /* Find the nearest color */
+ if( p_lookup[ j ] && dist < mindist )
+ {
+ p_rgb8[ i ] = p_rgb8[ j ];
+ mindist = dist;
+ }
+
+ j -= 128;
+
+ /* Find the nearest color */
+ if( p_lookup[ j ] && dist + 128 < mindist )
+ {
+ p_rgb8[ i ] = p_rgb8[ j ];
+ mindist = dist + 128;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * i420_rgb.h : YUV to bitmap RGB conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000 VideoLAN
+ * $Id: i420_rgb.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * chroma_sys_t: chroma method descriptor
+ *****************************************************************************
+ * This structure is part of the chroma transformation descriptor, it
+ * describes the yuv2rgb specific properties.
+ *****************************************************************************/
+struct chroma_sys_t
+{
+ u8 *p_buffer;
+ int *p_offset;
+
+#ifdef MODULE_NAME_IS_i420_rgb
+ /* Pre-calculated conversion tables */
+ void *p_base; /* base for all conversion tables */
+ u8 *p_rgb8; /* RGB 8 bits table */
+ u16 *p_rgb16; /* RGB 16 bits table */
+ u32 *p_rgb32; /* RGB 32 bits table */
+#endif
+};
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+#ifdef MODULE_NAME_IS_i420_rgb
+void E_(I420_RGB8) ( vout_thread_t *, picture_t *, picture_t * );
+#endif
+void E_(I420_RGB15)( vout_thread_t *, picture_t *, picture_t * );
+void E_(I420_RGB16)( vout_thread_t *, picture_t *, picture_t * );
+void E_(I420_RGB32)( vout_thread_t *, picture_t *, picture_t * );
+
+/*****************************************************************************
+ * CONVERT_*_PIXEL: pixel conversion macros
+ *****************************************************************************
+ * These conversion routines are used by YUV conversion functions.
+ * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
+ * which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
+ * CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
+ *****************************************************************************/
+#define CONVERT_Y_PIXEL( BPP ) \
+ /* Only Y sample is present */ \
+ p_ybase = p_yuv + *p_y++; \
+ *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
+ p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
+ + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
+
+#define CONVERT_YUV_PIXEL( BPP ) \
+ /* Y, U and V samples are present */ \
+ i_uval = *p_u++; \
+ i_vval = *p_v++; \
+ i_red = (V_RED_COEF * i_vval) >> SHIFT; \
+ i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
+ i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
+ CONVERT_Y_PIXEL( BPP ) \
+
+#define CONVERT_4YUV_PIXEL( CHROMA ) \
+ *p_pic++ = p_lookup[ \
+ (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
+ + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
+ + ((*p_v + dither20[i_real_y]) >> 5) ]; \
+ *p_pic++ = p_lookup[ \
+ (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
+ + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
+ + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
+ *p_pic++ = p_lookup[ \
+ (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
+ + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
+ + ((*p_v + dither22[i_real_y]) >> 5) ]; \
+ *p_pic++ = p_lookup[ \
+ (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
+ + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
+ + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
+
+#define CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
+ *p_pic++ = p_lookup[ \
+ ( ((*p_y + dither10[i_real_y]) >> 4) << 7) \
+ + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
+ + ((*p_v + dither20[i_real_y]) >> 5) ]; \
+ p_y += *p_offset++; \
+ p_u += *p_offset; \
+ p_v += *p_offset++; \
+ *p_pic++ = p_lookup[ \
+ ( ((*p_y + dither11[i_real_y]) >> 4) << 7) \
+ + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
+ + ((*p_v + dither21[i_real_y]) >> 5) ]; \
+ p_y += *p_offset++; \
+ p_u += *p_offset; \
+ p_v += *p_offset++; \
+ *p_pic++ = p_lookup[ \
+ ( ((*p_y + dither12[i_real_y]) >> 4) << 7) \
+ + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
+ + ((*p_v + dither22[i_real_y]) >> 5) ]; \
+ p_y += *p_offset++; \
+ p_u += *p_offset; \
+ p_v += *p_offset++; \
+ *p_pic++ = p_lookup[ \
+ ( ((*p_y + dither13[i_real_y]) >> 4) << 7) \
+ + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
+ + ((*p_v + dither23[i_real_y]) >> 5) ]; \
+ p_y += *p_offset++; \
+ p_u += *p_offset; \
+ p_v += *p_offset++; \
+
+/*****************************************************************************
+ * SCALE_WIDTH: scale a line horizontally
+ *****************************************************************************
+ * This macro scales a line using rendering buffer and offset array. It works
+ * for 1, 2 and 4 Bpp.
+ *****************************************************************************/
+#define SCALE_WIDTH \
+ if( b_hscale ) \
+ { \
+ /* Horizontal scaling, conversion has been done to buffer. \
+ * Rewind buffer and offset, then copy and scale line */ \
+ p_buffer = p_buffer_start; \
+ p_offset = p_offset_start; \
+ for( i_x = p_vout->output.i_width / 16; i_x--; ) \
+ { \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ } \
+ for( i_x = p_vout->output.i_width & 15; i_x--; ) \
+ { \
+ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
+ } \
+ p_pic += i_right_margin; \
+ } \
+ else \
+ { \
+ /* No scaling, conversion has been done directly in picture memory. \
+ * Increment of picture pointer to end of line is still needed */ \
+ (u8*)p_pic += p_dest->p->i_pitch; \
+ } \
+
+/*****************************************************************************
+ * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
+ *****************************************************************************
+ * This macro scales a line using an offset array.
+ *****************************************************************************/
+#define SCALE_WIDTH_DITHER( CHROMA ) \
+ if( b_hscale ) \
+ { \
+ /* Horizontal scaling - we can't use a buffer due to dithering */ \
+ p_offset = p_offset_start; \
+ for( i_x = p_vout->output.i_width / 16; i_x--; ) \
+ { \
+ CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
+ CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
+ CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
+ CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
+ } \
+ } \
+ else \
+ { \
+ for( i_x = p_vout->render.i_width / 16; i_x--; ) \
+ { \
+ CONVERT_4YUV_PIXEL( CHROMA ) \
+ CONVERT_4YUV_PIXEL( CHROMA ) \
+ CONVERT_4YUV_PIXEL( CHROMA ) \
+ CONVERT_4YUV_PIXEL( CHROMA ) \
+ } \
+ } \
+ /* Increment of picture pointer to end of line is still needed */ \
+ p_pic += i_right_margin; \
+ \
+ /* Increment the Y coordinate in the matrix, modulo 4 */ \
+ i_real_y = (i_real_y + 1) & 0x3; \
+
+/*****************************************************************************
+ * SCALE_HEIGHT: handle vertical scaling
+ *****************************************************************************
+ * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
+ * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
+ * and 4 Bpp.
+ *****************************************************************************/
+#define SCALE_HEIGHT( CHROMA, BPP ) \
+ /* If line is odd, rewind 4:2:0 U and V samples */ \
+ if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
+ { \
+ p_u -= i_chroma_width; \
+ p_v -= i_chroma_width; \
+ } \
+ \
+ /* \
+ * Handle vertical scaling. The current line can be copied or next one \
+ * can be ignored. \
+ */ \
+ switch( i_vscale ) \
+ { \
+ case -1: /* vertical scaling factor is < 1 */ \
+ while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
+ { \
+ /* Height reduction: skip next source line */ \
+ p_y += p_vout->render.i_width; \
+ i_y++; \
+ if( (CHROMA == 420) || (CHROMA == 422) ) \
+ { \
+ if( i_y & 0x1 ) \
+ { \
+ p_u += i_chroma_width; \
+ p_v += i_chroma_width; \
+ } \
+ } \
+ else if( CHROMA == 444 ) \
+ { \
+ p_u += p_vout->render.i_width; \
+ p_v += p_vout->render.i_width; \
+ } \
+ } \
+ i_scale_count += p_vout->render.i_height; \
+ break; \
+ case 1: /* vertical scaling factor is > 1 */ \
+ while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
+ { \
+ /* Height increment: copy previous picture line */ \
+ p_vout->p_vlc->pf_memcpy( p_pic, p_pic_start, \
+ p_vout->output.i_width * BPP ); \
+ (u8*)p_pic += p_dest->p->i_pitch; \
+ } \
+ i_scale_count += p_vout->output.i_height; \
+ break; \
+ } \
+
+/*****************************************************************************
+ * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
+ *****************************************************************************
+ * This macro handles vertical scaling for a picture. CHROMA may be 420,
+ * 422 or 444 for RGB conversion, or 400 for gray conversion.
+ *****************************************************************************/
+#define SCALE_HEIGHT_DITHER( CHROMA ) \
+ \
+ /* If line is odd, rewind 4:2:0 U and V samples */ \
+ if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
+ { \
+ p_u -= i_chroma_width; \
+ p_v -= i_chroma_width; \
+ } \
+ \
+ /* \
+ * Handle vertical scaling. The current line can be copied or next one \
+ * can be ignored. \
+ */ \
+ \
+ switch( i_vscale ) \
+ { \
+ case -1: /* vertical scaling factor is < 1 */ \
+ while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
+ { \
+ /* Height reduction: skip next source line */ \
+ p_y += p_vout->render.i_width; \
+ i_y++; \
+ if( (CHROMA == 420) || (CHROMA == 422) ) \
+ { \
+ if( i_y & 0x1 ) \
+ { \
+ p_u += i_chroma_width; \
+ p_v += i_chroma_width; \
+ } \
+ } \
+ else if( CHROMA == 444 ) \
+ { \
+ p_u += p_vout->render.i_width; \
+ p_v += p_vout->render.i_width; \
+ } \
+ } \
+ i_scale_count += p_vout->render.i_height; \
+ break; \
+ case 1: /* vertical scaling factor is > 1 */ \
+ while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
+ { \
+ p_y -= p_vout->render.i_width; \
+ p_u -= i_chroma_width; \
+ p_v -= i_chroma_width; \
+ SCALE_WIDTH_DITHER( CHROMA ); \
+ } \
+ i_scale_count += p_vout->output.i_height; \
+ break; \
+ } \
+
--- /dev/null
+/*****************************************************************************
+ * i420_rgb16.c : YUV to bitmap RGB conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000 VideoLAN
+ * $Id: i420_rgb16.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "i420_rgb.h"
+#if defined (MODULE_NAME_IS_i420_rgb)
+# include "i420_rgb_c.h"
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+# include "i420_rgb_mmx.h"
+#endif
+
+static void SetOffset( int, int, int, int, vlc_bool_t *, int *, int * );
+
+/*****************************************************************************
+ * I420_RGB15: color YUV 4:2:0 to RGB 15 bpp
+ *****************************************************************************
+ * Horizontal alignment needed:
+ * - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
+ * - output: 1 pixel (2 bytes), margins allowed
+ * Vertical alignment needed:
+ * - input: 2 lines (2 Y lines, 1 U/V line)
+ * - output: 1 line
+ *****************************************************************************/
+void E_(I420_RGB15)( vout_thread_t *p_vout, picture_t *p_src,
+ picture_t *p_dest )
+{
+ /* We got this one from the old arguments */
+ u16 *p_pic = (u16*)p_dest->p->p_pixels;
+ u8 *p_y = p_src->Y_PIXELS;
+ u8 *p_u = p_src->U_PIXELS;
+ u8 *p_v = p_src->V_PIXELS;
+
+ vlc_bool_t b_hscale; /* horizontal scaling type */
+ int i_vscale; /* vertical scaling type */
+ int i_x, i_y; /* horizontal and vertical indexes */
+ int i_right_margin;
+ int i_rewind;
+ int i_scale_count; /* scale modulo counter */
+ int i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
+ u16 * p_pic_start; /* beginning of the current line for copy */
+#if defined (MODULE_NAME_IS_i420_rgb)
+ int i_uval, i_vval; /* U and V samples */
+ int i_red, i_green, i_blue; /* U and V modified samples */
+ u16 * p_yuv = p_vout->chroma.p_sys->p_rgb16;
+ u16 * p_ybase; /* Y dependant conversion table */
+#endif
+
+ /* Conversion buffer pointer */
+ u16 * p_buffer_start = (u16*)p_vout->chroma.p_sys->p_buffer;
+ u16 * p_buffer;
+
+ /* Offset array pointer */
+ int * p_offset_start = p_vout->chroma.p_sys->p_offset;
+ int * p_offset;
+
+ i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
+
+ if( p_vout->render.i_width & 7 )
+ {
+ i_rewind = 8 - ( p_vout->render.i_width & 7 );
+ }
+ else
+ {
+ i_rewind = 0;
+ }
+
+ /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
+ * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
+ * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
+ SetOffset( p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->output.i_width, p_vout->output.i_height,
+ &b_hscale, &i_vscale, p_offset_start );
+
+ /*
+ * Perform conversion
+ */
+ i_scale_count = ( i_vscale == 1 ) ?
+ p_vout->output.i_height : p_vout->render.i_height;
+ for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
+ {
+ p_pic_start = p_pic;
+ p_buffer = b_hscale ? p_buffer_start : p_pic;
+
+ for ( i_x = p_vout->render.i_width / 8; i_x--; )
+ {
+#if defined (MODULE_NAME_IS_i420_rgb)
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+ __asm__( MMX_INIT_16
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ __asm__( ".align 8"
+ MMX_YUV_MUL
+ MMX_YUV_ADD
+ MMX_UNPACK_15
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ p_y += 8;
+ p_u += 4;
+ p_v += 4;
+ p_buffer += 8;
+#endif
+ }
+
+ /* Here we do some unaligned reads and duplicate conversions, but
+ * at least we have all the pixels */
+ if( i_rewind )
+ {
+ p_y -= i_rewind;
+ p_u -= i_rewind >> 1;
+ p_v -= i_rewind >> 1;
+ p_buffer -= i_rewind;
+#if defined (MODULE_NAME_IS_i420_rgb)
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+ __asm__( MMX_INIT_16
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ __asm__( ".align 8"
+ MMX_YUV_MUL
+ MMX_YUV_ADD
+ MMX_UNPACK_15
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ p_y += 8;
+ p_u += 4;
+ p_v += 4;
+ p_buffer += 8;
+#endif
+ }
+ SCALE_WIDTH;
+ SCALE_HEIGHT( 420, 2 );
+ }
+}
+
+/*****************************************************************************
+ * I420_RGB16: color YUV 4:2:0 to RGB 16 bpp
+ *****************************************************************************
+ * Horizontal alignment needed:
+ * - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
+ * - output: 1 pixel (2 bytes), margins allowed
+ * Vertical alignment needed:
+ * - input: 2 lines (2 Y lines, 1 U/V line)
+ * - output: 1 line
+ *****************************************************************************/
+void E_(I420_RGB16)( vout_thread_t *p_vout, picture_t *p_src,
+ picture_t *p_dest )
+{
+ /* We got this one from the old arguments */
+ u16 *p_pic = (u16*)p_dest->p->p_pixels;
+ u8 *p_y = p_src->Y_PIXELS;
+ u8 *p_u = p_src->U_PIXELS;
+ u8 *p_v = p_src->V_PIXELS;
+
+ vlc_bool_t b_hscale; /* horizontal scaling type */
+ int i_vscale; /* vertical scaling type */
+ int i_x, i_y; /* horizontal and vertical indexes */
+ int i_right_margin;
+ int i_rewind;
+ int i_scale_count; /* scale modulo counter */
+ int i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
+ u16 * p_pic_start; /* beginning of the current line for copy */
+#if defined (MODULE_NAME_IS_i420_rgb)
+ int i_uval, i_vval; /* U and V samples */
+ int i_red, i_green, i_blue; /* U and V modified samples */
+ u16 * p_yuv = p_vout->chroma.p_sys->p_rgb16;
+ u16 * p_ybase; /* Y dependant conversion table */
+#endif
+
+ /* Conversion buffer pointer */
+ u16 * p_buffer_start = (u16*)p_vout->chroma.p_sys->p_buffer;
+ u16 * p_buffer;
+
+ /* Offset array pointer */
+ int * p_offset_start = p_vout->chroma.p_sys->p_offset;
+ int * p_offset;
+
+ i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
+
+ if( p_vout->render.i_width & 7 )
+ {
+ i_rewind = 8 - ( p_vout->render.i_width & 7 );
+ }
+ else
+ {
+ i_rewind = 0;
+ }
+
+ /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
+ * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
+ * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
+ SetOffset( p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->output.i_width, p_vout->output.i_height,
+ &b_hscale, &i_vscale, p_offset_start );
+
+ /*
+ * Perform conversion
+ */
+ i_scale_count = ( i_vscale == 1 ) ?
+ p_vout->output.i_height : p_vout->render.i_height;
+ for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
+ {
+ p_pic_start = p_pic;
+ p_buffer = b_hscale ? p_buffer_start : p_pic;
+
+ for ( i_x = p_vout->render.i_width / 8; i_x--; )
+ {
+#if defined (MODULE_NAME_IS_i420_rgb)
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+ __asm__( MMX_INIT_16
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ __asm__( ".align 8"
+ MMX_YUV_MUL
+ MMX_YUV_ADD
+ MMX_UNPACK_16
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ p_y += 8;
+ p_u += 4;
+ p_v += 4;
+ p_buffer += 8;
+#endif
+ }
+
+ /* Here we do some unaligned reads and duplicate conversions, but
+ * at least we have all the pixels */
+ if( i_rewind )
+ {
+ p_y -= i_rewind;
+ p_u -= i_rewind >> 1;
+ p_v -= i_rewind >> 1;
+ p_buffer -= i_rewind;
+#if defined (MODULE_NAME_IS_i420_rgb)
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+ CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+ __asm__( MMX_INIT_16
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ __asm__( ".align 8"
+ MMX_YUV_MUL
+ MMX_YUV_ADD
+ MMX_UNPACK_16
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ p_y += 8;
+ p_u += 4;
+ p_v += 4;
+ p_buffer += 8;
+#endif
+ }
+ SCALE_WIDTH;
+ SCALE_HEIGHT( 420, 2 );
+ }
+}
+
+/*****************************************************************************
+ * I420_RGB32: color YUV 4:2:0 to RGB 32 bpp
+ *****************************************************************************
+ * Horizontal alignment needed:
+ * - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
+ * - output: 1 pixel (2 bytes), margins allowed
+ * Vertical alignment needed:
+ * - input: 2 lines (2 Y lines, 1 U/V line)
+ * - output: 1 line
+ *****************************************************************************/
+void E_(I420_RGB32)( vout_thread_t *p_vout, picture_t *p_src,
+ picture_t *p_dest )
+{
+ /* We got this one from the old arguments */
+ u32 *p_pic = (u32*)p_dest->p->p_pixels;
+ u8 *p_y = p_src->Y_PIXELS;
+ u8 *p_u = p_src->U_PIXELS;
+ u8 *p_v = p_src->V_PIXELS;
+
+ vlc_bool_t b_hscale; /* horizontal scaling type */
+ int i_vscale; /* vertical scaling type */
+ int i_x, i_y; /* horizontal and vertical indexes */
+ int i_right_margin;
+ int i_rewind;
+ int i_scale_count; /* scale modulo counter */
+ int i_chroma_width = p_vout->render.i_width / 4; /* chroma width */
+ u32 * p_pic_start; /* beginning of the current line for copy */
+#if defined (MODULE_NAME_IS_i420_rgb)
+ int i_uval, i_vval; /* U and V samples */
+ int i_red, i_green, i_blue; /* U and V modified samples */
+ u32 * p_yuv = p_vout->chroma.p_sys->p_rgb32;
+ u32 * p_ybase; /* Y dependant conversion table */
+#endif
+
+ /* Conversion buffer pointer */
+ u32 * p_buffer_start = (u32*)p_vout->chroma.p_sys->p_buffer;
+ u32 * p_buffer;
+
+ /* Offset array pointer */
+ int * p_offset_start = p_vout->chroma.p_sys->p_offset;
+ int * p_offset;
+
+ i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
+
+ if( p_vout->render.i_width & 7 )
+ {
+ i_rewind = 8 - ( p_vout->render.i_width & 7 );
+ }
+ else
+ {
+ i_rewind = 0;
+ }
+
+ /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
+ * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
+ * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
+ SetOffset( p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->output.i_width, p_vout->output.i_height,
+ &b_hscale, &i_vscale, p_offset_start );
+
+ /*
+ * Perform conversion
+ */
+ i_scale_count = ( i_vscale == 1 ) ?
+ p_vout->output.i_height : p_vout->render.i_height;
+ for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
+ {
+ p_pic_start = p_pic;
+ p_buffer = b_hscale ? p_buffer_start : p_pic;
+
+ for ( i_x = p_vout->render.i_width / 8; i_x--; )
+ {
+#if defined (MODULE_NAME_IS_i420_rgb)
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+ __asm__( MMX_INIT_32
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ __asm__( ".align 8"
+ MMX_YUV_MUL
+ MMX_YUV_ADD
+ MMX_UNPACK_32
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ p_y += 8;
+ p_u += 4;
+ p_v += 4;
+ p_buffer += 8;
+#endif
+ }
+
+ /* Here we do some unaligned reads and duplicate conversions, but
+ * at least we have all the pixels */
+ if( i_rewind )
+ {
+ p_y -= i_rewind;
+ p_u -= i_rewind >> 1;
+ p_v -= i_rewind >> 1;
+ p_buffer -= i_rewind;
+#if defined (MODULE_NAME_IS_i420_rgb)
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+ CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
+#elif defined (MODULE_NAME_IS_i420_rgb_mmx)
+ __asm__( MMX_INIT_32
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ __asm__( ".align 8"
+ MMX_YUV_MUL
+ MMX_YUV_ADD
+ MMX_UNPACK_32
+ : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
+
+ p_y += 8;
+ p_u += 4;
+ p_v += 4;
+ p_buffer += 8;
+#endif
+ }
+ SCALE_WIDTH;
+ SCALE_HEIGHT( 420, 4 );
+ }
+}
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * SetOffset: build offset array for conversion functions
+ *****************************************************************************
+ * This function will build an offset array used in later conversion functions.
+ * It will also set horizontal and vertical scaling indicators.
+ *****************************************************************************/
+static void SetOffset( int i_width, int i_height, int i_pic_width,
+ int i_pic_height, vlc_bool_t *pb_hscale,
+ int *pi_vscale, int *p_offset )
+{
+ int i_x; /* x position in destination */
+ int i_scale_count; /* modulo counter */
+
+ /*
+ * Prepare horizontal offset array
+ */
+ if( i_pic_width - i_width == 0 )
+ {
+ /* No horizontal scaling: YUV conversion is done directly to picture */
+ *pb_hscale = 0;
+ }
+ else if( i_pic_width - i_width > 0 )
+ {
+ /* Prepare scaling array for horizontal extension */
+ *pb_hscale = 1;
+ i_scale_count = i_pic_width;
+ for( i_x = i_width; i_x--; )
+ {
+ while( (i_scale_count -= i_width) > 0 )
+ {
+ *p_offset++ = 0;
+ }
+ *p_offset++ = 1;
+ i_scale_count += i_pic_width;
+ }
+ }
+ else /* if( i_pic_width - i_width < 0 ) */
+ {
+ /* Prepare scaling array for horizontal reduction */
+ *pb_hscale = 1;
+ i_scale_count = i_width;
+ for( i_x = i_pic_width; i_x--; )
+ {
+ *p_offset = 1;
+ while( (i_scale_count -= i_pic_width) > 0 )
+ {
+ *p_offset += 1;
+ }
+ p_offset++;
+ i_scale_count += i_width;
+ }
+ }
+
+ /*
+ * Set vertical scaling indicator
+ */
+ if( i_pic_height - i_height == 0 )
+ {
+ *pi_vscale = 0;
+ }
+ else if( i_pic_height - i_height > 0 )
+ {
+ *pi_vscale = 1;
+ }
+ else /* if( i_pic_height - i_height < 0 ) */
+ {
+ *pi_vscale = -1;
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * i420_rgb8.c : YUV to bitmap RGB conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000 VideoLAN
+ * $Id: i420_rgb8.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "i420_rgb.h"
+#include "i420_rgb_c.h"
+
+static void SetOffset( int, int, int, int, vlc_bool_t *, int *, int * );
+
+/*****************************************************************************
+ * I420_RGB8: color YUV 4:2:0 to RGB 8 bpp
+ *****************************************************************************/
+void E_(I420_RGB8)( vout_thread_t *p_vout, picture_t *p_src, picture_t *p_dest )
+{
+ /* We got this one from the old arguments */
+ u8 *p_pic = (u8*)p_dest->p->p_pixels;
+ u8 *p_y = p_src->Y_PIXELS;
+ u8 *p_u = p_src->U_PIXELS;
+ u8 *p_v = p_src->V_PIXELS;
+
+ vlc_bool_t b_hscale; /* horizontal scaling type */
+ int i_vscale; /* vertical scaling type */
+ int i_x, i_y; /* horizontal and vertical indexes */
+ int i_real_y; /* y % 4 */
+ int i_right_margin;
+ int i_scale_count; /* scale modulo counter */
+ int i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
+
+ /* Lookup table */
+ u8 * p_lookup = p_vout->chroma.p_sys->p_base;
+
+ /* Offset array pointer */
+ int * p_offset_start = p_vout->chroma.p_sys->p_offset;
+ int * p_offset;
+
+ /* The dithering matrices */
+ static int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
+ static int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
+ static int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
+ static int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
+
+ static int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
+ static int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
+ static int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
+ static int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
+
+ SetOffset( p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->output.i_width, p_vout->output.i_height,
+ &b_hscale, &i_vscale, p_offset_start );
+
+ i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
+
+ /*
+ * Perform conversion
+ */
+ i_scale_count = ( i_vscale == 1 ) ?
+ p_vout->output.i_height : p_vout->render.i_height;
+ for( i_y = 0, i_real_y = 0; i_y < p_vout->render.i_height; i_y++ )
+ {
+ /* Do horizontal and vertical scaling */
+ SCALE_WIDTH_DITHER( 420 );
+ SCALE_HEIGHT_DITHER( 420 );
+ }
+}
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * SetOffset: build offset array for conversion functions
+ *****************************************************************************
+ * This function will build an offset array used in later conversion functions.
+ * It will also set horizontal and vertical scaling indicators. The p_offset
+ * structure has interleaved Y and U/V offsets.
+ *****************************************************************************/
+static void SetOffset( int i_width, int i_height, int i_pic_width,
+ int i_pic_height, vlc_bool_t *pb_hscale,
+ int *pi_vscale, int *p_offset )
+{
+ int i_x; /* x position in destination */
+ int i_scale_count; /* modulo counter */
+
+ /*
+ * Prepare horizontal offset array
+ */
+ if( i_pic_width - i_width == 0 )
+ {
+ /* No horizontal scaling: YUV conversion is done directly to picture */
+ *pb_hscale = 0;
+ }
+ else if( i_pic_width - i_width > 0 )
+ {
+ int i_dummy = 0;
+
+ /* Prepare scaling array for horizontal extension */
+ *pb_hscale = 1;
+ i_scale_count = i_pic_width;
+ for( i_x = i_width; i_x--; )
+ {
+ while( (i_scale_count -= i_width) > 0 )
+ {
+ *p_offset++ = 0;
+ *p_offset++ = 0;
+ }
+ *p_offset++ = 1;
+ *p_offset++ = i_dummy;
+ i_dummy = 1 - i_dummy;
+ i_scale_count += i_pic_width;
+ }
+ }
+ else /* if( i_pic_width - i_width < 0 ) */
+ {
+ int i_remainder = 0;
+ int i_jump;
+
+ /* Prepare scaling array for horizontal reduction */
+ *pb_hscale = 1;
+ i_scale_count = i_width;
+ for( i_x = i_pic_width; i_x--; )
+ {
+ i_jump = 1;
+ while( (i_scale_count -= i_pic_width) > 0 )
+ {
+ i_jump += 1;
+ }
+ *p_offset++ = i_jump;
+ *p_offset++ = ( i_jump += i_remainder ) >> 1;
+ i_remainder = i_jump & 1;
+ i_scale_count += i_width;
+ }
+ }
+
+ /*
+ * Set vertical scaling indicator
+ */
+ if( i_pic_height - i_height == 0 )
+ {
+ *pi_vscale = 0;
+ }
+ else if( i_pic_height - i_height > 0 )
+ {
+ *pi_vscale = 1;
+ }
+ else /* if( i_pic_height - i_height < 0 ) */
+ {
+ *pi_vscale = -1;
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * chroma_common.h: YUV transformation functions
+ * Provides functions to perform the YUV conversion. The functions provided here
+ * are a complete and portable C implementation, and may be replaced in certain
+ * case by optimized functions.
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: i420_rgb_c.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+
+/* Margins and offsets in conversion tables - Margins are used in case a RGB
+ * RGB conversion would give a value outside the 0-255 range. Offsets have been
+ * calculated to avoid using the same cache line for 2 tables. conversion tables
+ * are 2*MARGIN + 256 long and stores pixels.*/
+#define RED_MARGIN 178
+#define GREEN_MARGIN 135
+#define BLUE_MARGIN 224
+#define RED_OFFSET 1501 /* 1323 to 1935 */
+#define GREEN_OFFSET 135 /* 0 to 526 */
+#define BLUE_OFFSET 818 /* 594 to 1298 */
+#define RGB_TABLE_SIZE 1935 /* total table size */
+
+#define GRAY_MARGIN 384
+#define GRAY_TABLE_SIZE 1024 /* total table size */
+
+#define PALETTE_TABLE_SIZE 2176 /* YUV -> 8bpp palette lookup table */
+
+/* macros used for YUV pixel conversions */
+#define SHIFT 20
+#define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
+#define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
+#define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
+#define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
+
--- /dev/null
+/*****************************************************************************
+ * transforms_yuvmmx.h: MMX YUV transformation assembly
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: i420_rgb_mmx.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Olie Lho <ollie@sis.com.tw>
+ * Gaël Hendryckx <jimmy@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+
+/* hope these constant values are cache line aligned */
+#define UNUSED_LONGLONG(foo) \
+ static const unsigned long long foo __asm__ (#foo) __attribute__((unused))
+UNUSED_LONGLONG(mmx_80w) = 0x0080008000800080;
+UNUSED_LONGLONG(mmx_10w) = 0x1010101010101010;
+UNUSED_LONGLONG(mmx_00ffw) = 0x00ff00ff00ff00ff;
+UNUSED_LONGLONG(mmx_Y_coeff) = 0x253f253f253f253f;
+
+UNUSED_LONGLONG(mmx_U_green) = 0xf37df37df37df37d;
+UNUSED_LONGLONG(mmx_U_blue) = 0x4093409340934093;
+UNUSED_LONGLONG(mmx_V_red) = 0x3312331233123312;
+UNUSED_LONGLONG(mmx_V_green) = 0xe5fce5fce5fce5fc;
+
+UNUSED_LONGLONG(mmx_mask_f8) = 0xf8f8f8f8f8f8f8f8;
+UNUSED_LONGLONG(mmx_mask_fc) = 0xfcfcfcfcfcfcfcfc;
+#undef UNUSED_LONGLONG
+
+#define MMX_INIT_16 " \n\
+movd (%1), %%mm0 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%2), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+pxor %%mm4, %%mm4 # zero mm4 \n\
+movq (%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+#movl $0, (%3) # cache preload for image \n\
+"
+
+#define MMX_INIT_16_GRAY " \n\
+movq (%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+#movl $0, (%3) # cache preload for image \n\
+"
+
+#define MMX_INIT_32 " \n\
+movd (%1), %%mm0 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movl $0, (%3) # cache preload for image \n\
+movd (%2), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+pxor %%mm4, %%mm4 # zero mm4 \n\
+movq (%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+"
+
+/*
+ * Do the multiply part of the conversion for even and odd pixels,
+ * register usage:
+ * mm0 -> Cblue, mm1 -> Cred, mm2 -> Cgreen even pixels,
+ * mm3 -> Cblue, mm4 -> Cred, mm5 -> Cgreen odd pixels,
+ * mm6 -> Y even, mm7 -> Y odd
+ */
+
+#define MMX_YUV_MUL " \n\
+# convert the chroma part \n\
+punpcklbw %%mm4, %%mm0 # scatter 4 Cb 00 u3 00 u2 00 u1 00 u0 \n\
+punpcklbw %%mm4, %%mm1 # scatter 4 Cr 00 v3 00 v2 00 v1 00 v0 \n\
+psubsw mmx_80w, %%mm0 # Cb -= 128 \n\
+psubsw mmx_80w, %%mm1 # Cr -= 128 \n\
+psllw $3, %%mm0 # Promote precision \n\
+psllw $3, %%mm1 # Promote precision \n\
+movq %%mm0, %%mm2 # Copy 4 Cb 00 u3 00 u2 00 u1 00 u0 \n\
+movq %%mm1, %%mm3 # Copy 4 Cr 00 v3 00 v2 00 v1 00 v0 \n\
+pmulhw mmx_U_green, %%mm2 # Mul Cb with green coeff -> Cb green \n\
+pmulhw mmx_V_green, %%mm3 # Mul Cr with green coeff -> Cr green \n\
+pmulhw mmx_U_blue, %%mm0 # Mul Cb -> Cblue 00 b3 00 b2 00 b1 00 b0 \n\
+pmulhw mmx_V_red, %%mm1 # Mul Cr -> Cred 00 r3 00 r2 00 r1 00 r0 \n\
+paddsw %%mm3, %%mm2 # Cb green + Cr green -> Cgreen \n\
+ \n\
+# convert the luma part \n\
+psubusb mmx_10w, %%mm6 # Y -= 16 \n\
+movq %%mm6, %%mm7 # Copy 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+pand mmx_00ffw, %%mm6 # get Y even 00 Y6 00 Y4 00 Y2 00 Y0 \n\
+psrlw $8, %%mm7 # get Y odd 00 Y7 00 Y5 00 Y3 00 Y1 \n\
+psllw $3, %%mm6 # Promote precision \n\
+psllw $3, %%mm7 # Promote precision \n\
+pmulhw mmx_Y_coeff, %%mm6 # Mul 4 Y even 00 y6 00 y4 00 y2 00 y0 \n\
+pmulhw mmx_Y_coeff, %%mm7 # Mul 4 Y odd 00 y7 00 y5 00 y3 00 y1 \n\
+"
+
+/*
+ * Do the addition part of the conversion for even and odd pixels,
+ * register usage:
+ * mm0 -> Cblue, mm1 -> Cred, mm2 -> Cgreen even pixels,
+ * mm3 -> Cblue, mm4 -> Cred, mm5 -> Cgreen odd pixels,
+ * mm6 -> Y even, mm7 -> Y odd
+ */
+
+#define MMX_YUV_ADD " \n\
+# Do horizontal and vertical scaling \n\
+movq %%mm0, %%mm3 # Copy Cblue \n\
+movq %%mm1, %%mm4 # Copy Cred \n\
+movq %%mm2, %%mm5 # Copy Cgreen \n\
+paddsw %%mm6, %%mm0 # Y even + Cblue 00 B6 00 B4 00 B2 00 B0 \n\
+paddsw %%mm7, %%mm3 # Y odd + Cblue 00 B7 00 B5 00 B3 00 B1 \n\
+paddsw %%mm6, %%mm1 # Y even + Cred 00 R6 00 R4 00 R2 00 R0 \n\
+paddsw %%mm7, %%mm4 # Y odd + Cred 00 R7 00 R5 00 R3 00 R1 \n\
+paddsw %%mm6, %%mm2 # Y even + Cgreen 00 G6 00 G4 00 G2 00 G0 \n\
+paddsw %%mm7, %%mm5 # Y odd + Cgreen 00 G7 00 G5 00 G3 00 G1 \n\
+ \n\
+# Limit RGB even to 0..255 \n\
+packuswb %%mm0, %%mm0 # B6 B4 B2 B0 / B6 B4 B2 B0 \n\
+packuswb %%mm1, %%mm1 # R6 R4 R2 R0 / R6 R4 R2 R0 \n\
+packuswb %%mm2, %%mm2 # G6 G4 G2 G0 / G6 G4 G2 G0 \n\
+ \n\
+# Limit RGB odd to 0..255 \n\
+packuswb %%mm3, %%mm3 # B7 B5 B3 B1 / B7 B5 B3 B1 \n\
+packuswb %%mm4, %%mm4 # R7 R5 R3 R1 / R7 R5 R3 R1 \n\
+packuswb %%mm5, %%mm5 # G7 G5 G3 G1 / G7 G5 G3 G1 \n\
+ \n\
+# Interleave RGB even and odd \n\
+punpcklbw %%mm3, %%mm0 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
+punpcklbw %%mm4, %%mm1 # R7 R6 R5 R4 R3 R2 R1 R0 \n\
+punpcklbw %%mm5, %%mm2 # G7 G6 G5 G4 G3 G2 G1 G0 \n\
+"
+
+/*
+ * Grayscale case, only use Y
+ */
+
+#define MMX_YUV_GRAY " \n\
+# convert the luma part \n\
+psubusb mmx_10w, %%mm6 \n\
+movq %%mm6, %%mm7 \n\
+pand mmx_00ffw, %%mm6 \n\
+psrlw $8, %%mm7 \n\
+psllw $3, %%mm6 \n\
+psllw $3, %%mm7 \n\
+pmulhw mmx_Y_coeff, %%mm6 \n\
+pmulhw mmx_Y_coeff, %%mm7 \n\
+packuswb %%mm6, %%mm6 \n\
+packuswb %%mm7, %%mm7 \n\
+punpcklbw %%mm7, %%mm6 \n\
+"
+
+#define MMX_UNPACK_16_GRAY " \n\
+movq %%mm6, %%mm5 \n\
+pand mmx_mask_f8, %%mm6 \n\
+pand mmx_mask_fc, %%mm5 \n\
+movq %%mm6, %%mm7 \n\
+psrlw $3, %%mm7 \n\
+pxor %%mm3, %%mm3 \n\
+movq %%mm7, %%mm2 \n\
+movq %%mm5, %%mm0 \n\
+punpcklbw %%mm3, %%mm5 \n\
+punpcklbw %%mm6, %%mm7 \n\
+psllw $3, %%mm5 \n\
+por %%mm5, %%mm7 \n\
+movq %%mm7, (%3) \n\
+punpckhbw %%mm3, %%mm0 \n\
+punpckhbw %%mm6, %%mm2 \n\
+psllw $3, %%mm0 \n\
+movq 8(%0), %%mm6 \n\
+por %%mm0, %%mm2 \n\
+movq %%mm2, 8(%3) \n\
+"
+
+
+/*
+ * convert RGB plane to RGB 15 bits,
+ * mm0 -> B, mm1 -> R, mm2 -> G,
+ * mm4 -> GB, mm5 -> AR pixel 4-7,
+ * mm6 -> GB, mm7 -> AR pixel 0-3
+ */
+
+#define MMX_UNPACK_15 " \n\
+# mask unneeded bits off \n\
+pand mmx_mask_f8, %%mm0 # b7b6b5b4 b3______ b7b6b5b4 b3______ \n\
+psrlw $3,%%mm0 # ______b7 b6b5b4b3 ______b7 b6b5b4b3 \n\
+pand mmx_mask_f8, %%mm2 # g7g6g5g4 g3______ g7g6g5g4 g3______ \n\
+pand mmx_mask_f8, %%mm1 # r7r6r5r4 r3______ r7r6r5r4 r3______ \n\
+psrlw $1,%%mm1 # __r7r6r5 r4r3____ __r7r6r5 r4r3____ \n\
+pxor %%mm4, %%mm4 # zero mm4 \n\
+movq %%mm0, %%mm5 # Copy B7-B0 \n\
+movq %%mm2, %%mm7 # Copy G7-G0 \n\
+ \n\
+# convert rgb24 plane to rgb15 pack for pixel 0-3 \n\
+punpcklbw %%mm4, %%mm2 # ________ ________ g7g6g5g4 g3______ \n\
+punpcklbw %%mm1, %%mm0 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
+psllw $2,%%mm2 # ________ ____g7g6 g5g4g3__ ________ \n\
+por %%mm2, %%mm0 # r7r6r5r4 r3__g7g6 g5g4g3b7 b6b5b4b3 \n\
+movq 8(%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+movq %%mm0, (%3) # store pixel 0-3 \n\
+ \n\
+# convert rgb24 plane to rgb16 pack for pixel 0-3 \n\
+punpckhbw %%mm4, %%mm7 # ________ ________ g7g6g5g4 g3______ \n\
+punpckhbw %%mm1, %%mm5 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
+psllw $2,%%mm7 # ________ ____g7g6 g5g4g3__ ________ \n\
+movd 4(%1), %%mm0 # Load 4 Cb __ __ __ __ u3 u2 u1 u0 \n\
+por %%mm7, %%mm5 # r7r6r5r4 r3__g7g6 g5g4g3b7 b6b5b4b3 \n\
+movd 4(%2), %%mm1 # Load 4 Cr __ __ __ __ v3 v2 v1 v0 \n\
+movq %%mm5, 8(%3) # store pixel 4-7 \n\
+"
+
+/*
+ * convert RGB plane to RGB 16 bits,
+ * mm0 -> B, mm1 -> R, mm2 -> G,
+ * mm4 -> GB, mm5 -> AR pixel 4-7,
+ * mm6 -> GB, mm7 -> AR pixel 0-3
+ */
+
+#define MMX_UNPACK_16 " \n\
+# mask unneeded bits off \n\
+pand mmx_mask_f8, %%mm0 # b7b6b5b4 b3______ b7b6b5b4 b3______ \n\
+pand mmx_mask_fc, %%mm2 # g7g6g5g4 g3g2____ g7g6g5g4 g3g2____ \n\
+pand mmx_mask_f8, %%mm1 # r7r6r5r4 r3______ r7r6r5r4 r3______ \n\
+psrlw $3,%%mm0 # ______b7 b6b5b4b3 ______b7 b6b5b4b3 \n\
+pxor %%mm4, %%mm4 # zero mm4 \n\
+movq %%mm0, %%mm5 # Copy B7-B0 \n\
+movq %%mm2, %%mm7 # Copy G7-G0 \n\
+ \n\
+# convert rgb24 plane to rgb16 pack for pixel 0-3 \n\
+punpcklbw %%mm4, %%mm2 # ________ ________ g7g6g5g4 g3g2____ \n\
+punpcklbw %%mm1, %%mm0 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
+psllw $3,%%mm2 # ________ __g7g6g5 g4g3g2__ ________ \n\
+por %%mm2, %%mm0 # r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 \n\
+movq 8(%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+movq %%mm0, (%3) # store pixel 0-3 \n\
+ \n\
+# convert rgb24 plane to rgb16 pack for pixel 0-3 \n\
+punpckhbw %%mm4, %%mm7 # ________ ________ g7g6g5g4 g3g2____ \n\
+punpckhbw %%mm1, %%mm5 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
+psllw $3,%%mm7 # ________ __g7g6g5 g4g3g2__ ________ \n\
+movd 4(%1), %%mm0 # Load 4 Cb __ __ __ __ u3 u2 u1 u0 \n\
+por %%mm7, %%mm5 # r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 \n\
+movd 4(%2), %%mm1 # Load 4 Cr __ __ __ __ v3 v2 v1 v0 \n\
+movq %%mm5, 8(%3) # store pixel 4-7 \n\
+"
+
+/*
+ * convert RGB plane to RGB packed format,
+ * mm0 -> B, mm1 -> R, mm2 -> G, mm3 -> 0,
+ * mm4 -> GB, mm5 -> AR pixel 4-7,
+ * mm6 -> GB, mm7 -> AR pixel 0-3
+ */
+
+#define MMX_UNPACK_32 " \n\
+pxor %%mm3, %%mm3 # zero mm3 \n\
+movq %%mm0, %%mm6 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
+movq %%mm1, %%mm7 # R7 R6 R5 R4 R3 R2 R1 R0 \n\
+movq %%mm0, %%mm4 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
+movq %%mm1, %%mm5 # R7 R6 R5 R4 R3 R2 R1 R0 \n\
+punpcklbw %%mm2, %%mm6 # G3 B3 G2 B2 G1 B1 G0 B0 \n\
+punpcklbw %%mm3, %%mm7 # 00 R3 00 R2 00 R1 00 R0 \n\
+punpcklwd %%mm7, %%mm6 # 00 R1 B1 G1 00 R0 B0 G0 \n\
+movq %%mm6, (%3) # Store ARGB1 ARGB0 \n\
+movq %%mm0, %%mm6 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
+punpcklbw %%mm2, %%mm6 # G3 B3 G2 B2 G1 B1 G0 B0 \n\
+punpckhwd %%mm7, %%mm6 # 00 R3 G3 B3 00 R2 B3 G2 \n\
+movq %%mm6, 8(%3) # Store ARGB3 ARGB2 \n\
+punpckhbw %%mm2, %%mm4 # G7 B7 G6 B6 G5 B5 G4 B4 \n\
+punpckhbw %%mm3, %%mm5 # 00 R7 00 R6 00 R5 00 R4 \n\
+punpcklwd %%mm5, %%mm4 # 00 R5 B5 G5 00 R4 B4 G4 \n\
+movq %%mm4, 16(%3) # Store ARGB5 ARGB4 \n\
+movq %%mm0, %%mm4 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
+punpckhbw %%mm2, %%mm4 # G7 B7 G6 B6 G5 B5 G4 B4 \n\
+punpckhwd %%mm5, %%mm4 # 00 R7 G7 B7 00 R6 B6 G6 \n\
+movq %%mm4, 24(%3) # Store ARGB7 ARGB6 \n\
+ \n\
+#movd 4(%1), %%mm0 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+#movd 4(%2), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+#pxor %%mm4, %%mm4 # zero mm4 \n\
+#movq 8(%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+"
+
--- /dev/null
+/*****************************************************************************
+ * i420_ymga.c : YUV to YUV conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: i420_ymga.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#define SRC_FOURCC "I420,IYUV,YV12"
+#define DEST_FOURCC "YMGA"
+
+/*****************************************************************************
+ * Local and extern prototypes.
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+static void I420_YMGA ( vout_thread_t *, picture_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#if defined (MODULE_NAME_IS_i420_ymga)
+ set_description( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) );
+ set_capability( "chroma", 80 );
+#elif defined (MODULE_NAME_IS_i420_ymga_mmx)
+ set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
+ set_capability( "chroma", 100 );
+ add_requirement( MMX );
+#endif
+ set_callbacks( Activate, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: allocate a chroma function
+ *****************************************************************************
+ * This function allocates and initializes a chroma function
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
+ {
+ return -1;
+ }
+
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('Y','V','1','2'):
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('Y','M','G','A'):
+ p_vout->chroma.pf_convert = I420_YMGA;
+ break;
+
+ default:
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * I420_YMGA: planar YUV 4:2:0 to Matrox's planar/packed YUV 4:2:0
+ *****************************************************************************/
+static void I420_YMGA( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_uv = p_dest->U_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x;
+
+ /* Copy the Y part */
+ p_vout->p_vlc->pf_memcpy( p_dest->Y_PIXELS, p_source->Y_PIXELS,
+ p_dest->p[Y_PLANE].i_pitch * p_dest->p[Y_PLANE].i_lines );
+
+ /* Copy the U:V part */
+ for( i_x = p_dest->p[U_PLANE].i_pitch * p_dest->p[U_PLANE].i_lines / 64;
+ i_x--; )
+ {
+#if defined (MODULE_NAME_IS_i420_ymga)
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+ *p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
+#else
+ __asm__( ".align 32 \n\
+ movd (%0), %%mm0 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+ movd 4(%0), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+ movd 8(%0), %%mm4 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+ movd 12(%0), %%mm6 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+ movd (%1), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+ movd 4(%1), %%mm3 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+ movd 8(%1), %%mm5 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+ movd 12(%1), %%mm7 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+ punpcklbw %%mm1, %%mm0 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+ punpcklbw %%mm3, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+ punpcklbw %%mm5, %%mm4 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+ punpcklbw %%mm7, %%mm6 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+ movq %%mm0, (%2) # Store CrCb \n\
+ movq %%mm2, 8(%2) # Store CrCb \n\
+ movq %%mm4, 16(%2) # Store CrCb \n\
+ movq %%mm6, 24(%2) # Store CrCb"
+ : : "r" (p_v), "r" (p_u), "r" (p_uv) );
+
+ p_v += 16; p_u += 16; p_uv += 32;
+#endif
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * i420_yuy2.c : YUV to YUV conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: i420_yuy2.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "i420_yuy2.h"
+
+#define SRC_FOURCC "I420,IYUV,YV12"
+
+#if defined (MODULE_NAME_IS_i420_yuy2)
+# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
+#else
+# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
+#endif
+
+/*****************************************************************************
+ * Local and extern prototypes.
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+
+static void I420_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
+static void I420_YVYU ( vout_thread_t *, picture_t *, picture_t * );
+static void I420_UYVY ( vout_thread_t *, picture_t *, picture_t * );
+static void I420_IUYV ( vout_thread_t *, picture_t *, picture_t * );
+static void I420_cyuv ( vout_thread_t *, picture_t *, picture_t * );
+#if defined (MODULE_NAME_IS_i420_yuy2)
+static void I420_Y211 ( vout_thread_t *, picture_t *, picture_t * );
+#endif
+
+#ifdef MODULE_NAME_IS_i420_yuy2_mmx
+static unsigned long long i_00ffw;
+static unsigned long long i_80w;
+#endif
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+vlc_module_begin();
+#if defined (MODULE_NAME_IS_i420_yuy2)
+ set_description( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) );
+ set_capability( "chroma", 80 );
+#elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
+ set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
+ set_capability( "chroma", 100 );
+ add_requirement( MMX );
+ /* Initialize MMX-specific constants */
+ i_00ffw = 0x00ff00ff00ff00ff;
+ i_80w = 0x0000000080808080;
+#endif
+ set_callbacks( Activate, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: allocate a chroma function
+ *****************************************************************************
+ * This function allocates and initializes a chroma function
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
+ {
+ return -1;
+ }
+
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('Y','V','1','2'):
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('Y','U','Y','2'):
+ case VLC_FOURCC('Y','U','N','V'):
+ p_vout->chroma.pf_convert = I420_YUY2;
+ break;
+
+ case VLC_FOURCC('Y','V','Y','U'):
+ p_vout->chroma.pf_convert = I420_YVYU;
+ break;
+
+ case VLC_FOURCC('U','Y','V','Y'):
+ case VLC_FOURCC('U','Y','N','V'):
+ case VLC_FOURCC('Y','4','2','2'):
+ p_vout->chroma.pf_convert = I420_UYVY;
+ break;
+
+ case VLC_FOURCC('I','U','Y','V'):
+ p_vout->chroma.pf_convert = I420_IUYV;
+ break;
+
+ case VLC_FOURCC('c','y','u','v'):
+ p_vout->chroma.pf_convert = I420_cyuv;
+ break;
+
+#if defined (MODULE_NAME_IS_i420_yuy2)
+ case VLC_FOURCC('Y','2','1','1'):
+ p_vout->chroma.pf_convert = I420_Y211;
+ break;
+#endif
+
+ default:
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
+ *****************************************************************************/
+static void I420_YUY2( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
+ u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ const int i_source_margin = p_source->p->i_pitch
+ - p_source->p->i_visible_pitch;
+ const int i_dest_margin = p_dest->p->i_pitch
+ - p_dest->p->i_visible_pitch;
+
+ for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
+ {
+ p_line1 = p_line2;
+ p_line2 += p_dest->p->i_pitch;
+
+ p_y1 = p_y2;
+ p_y2 += p_source->p[Y_PLANE].i_pitch;
+
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+#if defined (MODULE_NAME_IS_i420_yuy2)
+ C_YUV420_YUYV( );
+ C_YUV420_YUYV( );
+ C_YUV420_YUYV( );
+ C_YUV420_YUYV( );
+#else
+ MMX_CALL( MMX_YUV420_YUYV );
+#endif
+ }
+
+ p_y1 += i_source_margin;
+ p_y2 += i_source_margin;
+ p_line1 += i_dest_margin;
+ p_line2 += i_dest_margin;
+ }
+}
+
+/*****************************************************************************
+ * I420_YVYU: planar YUV 4:2:0 to packed YVYU 4:2:2
+ *****************************************************************************/
+static void I420_YVYU( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
+ u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ const int i_source_margin = p_source->p->i_pitch
+ - p_source->p->i_visible_pitch;
+ const int i_dest_margin = p_dest->p->i_pitch
+ - p_dest->p->i_visible_pitch;
+
+ for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
+ {
+ p_line1 = p_line2;
+ p_line2 += p_dest->p->i_pitch;
+
+ p_y1 = p_y2;
+ p_y2 += p_source->p[Y_PLANE].i_pitch;
+
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+#if defined (MODULE_NAME_IS_i420_yuy2)
+ C_YUV420_YVYU( );
+ C_YUV420_YVYU( );
+ C_YUV420_YVYU( );
+ C_YUV420_YVYU( );
+#else
+ MMX_CALL( MMX_YUV420_YVYU );
+#endif
+ }
+
+ p_y1 += i_source_margin;
+ p_y2 += i_source_margin;
+ p_line1 += i_dest_margin;
+ p_line2 += i_dest_margin;
+ }
+}
+
+/*****************************************************************************
+ * I420_UYVY: planar YUV 4:2:0 to packed UYVY 4:2:2
+ *****************************************************************************/
+static void I420_UYVY( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
+ u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ const int i_source_margin = p_source->p->i_pitch
+ - p_source->p->i_visible_pitch;
+ const int i_dest_margin = p_dest->p->i_pitch
+ - p_dest->p->i_visible_pitch;
+
+ for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
+ {
+ p_line1 = p_line2;
+ p_line2 += p_dest->p->i_pitch;
+
+ p_y1 = p_y2;
+ p_y2 += p_source->p[Y_PLANE].i_pitch;
+
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+#if defined (MODULE_NAME_IS_i420_yuy2)
+ C_YUV420_UYVY( );
+ C_YUV420_UYVY( );
+ C_YUV420_UYVY( );
+ C_YUV420_UYVY( );
+#else
+ MMX_CALL( MMX_YUV420_UYVY );
+#endif
+ }
+
+ p_y1 += i_source_margin;
+ p_y2 += i_source_margin;
+ p_line1 += i_dest_margin;
+ p_line2 += i_dest_margin;
+ }
+}
+
+/*****************************************************************************
+ * I420_IUYV: planar YUV 4:2:0 to interleaved packed UYVY 4:2:2
+ *****************************************************************************/
+static void I420_IUYV( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ /* FIXME: TODO ! */
+ msg_Err( p_vout, "I420_IUYV unimplemented, please harass <sam@zoy.org>" );
+}
+
+/*****************************************************************************
+ * I420_cyuv: planar YUV 4:2:0 to upside-down packed UYVY 4:2:2
+ *****************************************************************************/
+static void I420_cyuv( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line1 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch
+ + p_dest->p->i_pitch;
+ u8 *p_line2 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
+ u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ const int i_source_margin = p_source->p->i_pitch
+ - p_source->p->i_visible_pitch;
+ const int i_dest_margin = p_dest->p->i_pitch
+ - p_dest->p->i_visible_pitch;
+
+ for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
+ {
+ p_line1 -= 3 * p_dest->p->i_pitch;
+ p_line2 -= 3 * p_dest->p->i_pitch;
+
+ p_y1 = p_y2;
+ p_y2 += p_source->p[Y_PLANE].i_pitch;
+
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+#if defined (MODULE_NAME_IS_i420_yuy2)
+ C_YUV420_UYVY( );
+ C_YUV420_UYVY( );
+ C_YUV420_UYVY( );
+ C_YUV420_UYVY( );
+#else
+ MMX_CALL( MMX_YUV420_UYVY );
+#endif
+ }
+
+ p_y1 += i_source_margin;
+ p_y2 += i_source_margin;
+ p_line1 += i_dest_margin;
+ p_line2 += i_dest_margin;
+ }
+}
+
+/*****************************************************************************
+ * I420_Y211: planar YUV 4:2:0 to packed YUYV 2:1:1
+ *****************************************************************************/
+#if defined (MODULE_NAME_IS_i420_yuy2)
+static void I420_Y211( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
+ u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ const int i_source_margin = p_source->p->i_pitch
+ - p_source->p->i_visible_pitch;
+ const int i_dest_margin = p_dest->p->i_pitch
+ - p_dest->p->i_visible_pitch;
+
+ for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
+ {
+ p_line1 = p_line2;
+ p_line2 += p_dest->p->i_pitch;
+
+ p_y1 = p_y2;
+ p_y2 += p_source->p[Y_PLANE].i_pitch;
+
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+ C_YUV420_Y211( );
+ C_YUV420_Y211( );
+ }
+
+ p_y1 += i_source_margin;
+ p_y2 += i_source_margin;
+ p_line1 += i_dest_margin;
+ p_line2 += i_dest_margin;
+ }
+}
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * i420_yuy2.h : YUV to YUV conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: i420_yuy2.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#ifdef MODULE_NAME_IS_i420_yuy2_mmx
+
+#define MMX_CALL(MMX_INSTRUCTIONS) \
+ do { \
+ __asm__ __volatile__( \
+ ".align 8 \n\t" \
+ MMX_INSTRUCTIONS \
+ : \
+ : "r" (p_line1), "r" (p_line2), "r" (p_y1), "r" (p_y2), \
+ "r" (p_u), "r" (p_v) ); \
+ p_line1 += 16; p_line2 += 16; p_y1 += 8; p_y2 += 8; p_u += 4; p_v += 4; \
+ } while(0); \
+
+#define MMX_YUV420_YUYV " \n\
+movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movd (%4), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%5), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+punpcklbw %%mm2, %%mm1 # v3 u3 v2 u2 v1 u1 v0 u0 \n\
+movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
+punpcklbw %%mm1, %%mm2 # v1 y3 u1 y2 v0 y1 u0 y0 \n\
+movq %%mm2, (%0) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # v3 y7 u3 y6 v2 y5 u2 y4 \n\
+movq %%mm0, 8(%0) # Store high YUYV \n\
+movq (%3), %%mm0 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+movq %%mm0, %%mm2 # Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+punpcklbw %%mm1, %%mm2 # v1 Y3 u1 Y2 v0 Y1 u0 Y0 \n\
+movq %%mm2, (%1) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # v3 Y7 u3 Y6 v2 Y5 u2 Y4 \n\
+movq %%mm0, 8(%1) # Store high YUYV \n\
+"
+
+#define MMX_YUV420_YVYU " \n\
+movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movd (%4), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%5), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
+punpcklbw %%mm1, %%mm2 # u1 y3 v1 y2 u0 y1 v0 y0 \n\
+movq %%mm2, (%0) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # u3 y7 v3 y6 u2 y5 v2 y4 \n\
+movq %%mm0, 8(%0) # Store high YUYV \n\
+movq (%3), %%mm0 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+movq %%mm0, %%mm2 # Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+punpcklbw %%mm1, %%mm2 # u1 Y3 v1 Y2 u0 Y1 v0 Y0 \n\
+movq %%mm2, (%1) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # u3 Y7 v3 Y6 u2 Y5 v2 Y4 \n\
+movq %%mm0, 8(%1) # Store high YUYV \n\
+"
+
+#define MMX_YUV420_UYVY " \n\
+movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movq (%3), %%mm3 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+movd (%4), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%5), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+punpcklbw %%mm0, %%mm2 # y3 v1 y2 u1 y1 v0 y0 u0 \n\
+movq %%mm2, (%0) # Store low UYVY \n\
+movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+punpckhbw %%mm0, %%mm2 # y3 v1 y2 u1 y1 v0 y0 u0 \n\
+movq %%mm2, 8(%0) # Store high UYVY \n\
+movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+punpcklbw %%mm3, %%mm2 # Y3 v1 Y2 u1 Y1 v0 Y0 u0 \n\
+movq %%mm2, (%1) # Store low UYVY \n\
+punpckhbw %%mm3, %%mm1 # Y7 v3 Y6 u3 Y5 v2 Y4 u2 \n\
+movq %%mm1, 8(%1) # Store high UYVY \n\
+"
+
+/* FIXME: this code does not work ! Chroma seems to be wrong. */
+#define MMX_YUV420_Y211 " \n\
+movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movq (%3), %%mm1 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+movd (%4), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%5), %%mm3 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+pand i_00ffw, %%mm0 # get Y even 00 Y6 00 Y4 00 Y2 00 Y0 \n\
+packuswb %%mm0, %%mm0 # pack Y y6 y4 y2 y0 y6 y4 y2 y0 \n\
+pand i_00ffw, %%mm2 # get U even 00 u6 00 u4 00 u2 00 u0 \n\
+packuswb %%mm2, %%mm2 # pack U 00 00 u2 u0 00 00 u2 u0 \n\
+pand i_00ffw, %%mm3 # get V even 00 v6 00 v4 00 v2 00 v0 \n\
+packuswb %%mm3, %%mm3 # pack V 00 00 v2 v0 00 00 v2 v0 \n\
+punpcklbw %%mm3, %%mm2 # 00 00 00 00 v2 u2 v0 u0 \n\
+psubsw i_80w, %%mm2 # U,V -= 128 \n\
+punpcklbw %%mm2, %%mm0 # v2 y6 u2 y4 v0 y2 u0 y0 \n\
+movq %%mm0, (%0) # Store YUYV \n\
+pand i_00ffw, %%mm1 # get Y even 00 Y6 00 Y4 00 Y2 00 Y0 \n\
+packuswb %%mm1, %%mm1 # pack Y Y6 Y4 Y2 Y0 Y6 Y4 Y2 Y0 \n\
+punpcklbw %%mm2, %%mm1 # v2 Y6 u2 Y4 v0 Y2 u0 Y0 \n\
+movq %%mm1, (%1) # Store YUYV \n\
+"
+
+#else
+
+#define C_YUV420_YUYV( ) \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_u)++; \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_v)++; \
+
+#define C_YUV420_YVYU( ) \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_v)++; \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_u)++; \
+
+#define C_YUV420_UYVY( ) \
+ *(p_line1)++ = *(p_line2)++ = *(p_u)++; \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_v)++; \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+
+#define C_YUV420_Y211( ) \
+ *(p_line1)++ = *(p_y1); ((u16*)p_y1)++; \
+ *(p_line2)++ = *(p_y2); ((u16*)p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_u) - 0x80; ((u16*)p_u)++; \
+ *(p_line1)++ = *(p_y1); ((u16*)p_y1)++; \
+ *(p_line2)++ = *(p_y2); ((u16*)p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_v) - 0x80; ((u16*)p_v)++; \
+
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * i422_yuy2.c : YUV to YUV conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: i422_yuy2.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <string.h> /* strerror() */
+#include <stdlib.h> /* malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "i422_yuy2.h"
+
+#define SRC_FOURCC "I422"
+#if defined (MODULE_NAME_IS_i422_yuy2)
+# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
+#else
+# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
+#endif
+
+/*****************************************************************************
+ * Local and extern prototypes.
+ *****************************************************************************/
+static int Activate ( vlc_object_t * );
+
+static void I422_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
+static void I422_YVYU ( vout_thread_t *, picture_t *, picture_t * );
+static void I422_UYVY ( vout_thread_t *, picture_t *, picture_t * );
+static void I422_IUYV ( vout_thread_t *, picture_t *, picture_t * );
+static void I422_cyuv ( vout_thread_t *, picture_t *, picture_t * );
+#if defined (MODULE_NAME_IS_i422_yuy2)
+static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
+#endif
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+#if defined (MODULE_NAME_IS_i422_yuy2)
+ set_description( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) );
+ set_capability( "chroma", 80 );
+#elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
+ set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
+ set_capability( "chroma", 100 );
+ add_requirement( MMX );
+#endif
+ set_callbacks( Activate, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: allocate a chroma function
+ *****************************************************************************
+ * This function allocates and initializes a chroma function
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
+ {
+ return -1;
+ }
+
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('I','4','2','2'):
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('Y','U','Y','2'):
+ case VLC_FOURCC('Y','U','N','V'):
+ p_vout->chroma.pf_convert = I422_YUY2;
+ break;
+
+ case VLC_FOURCC('Y','V','Y','U'):
+ p_vout->chroma.pf_convert = I422_YVYU;
+ break;
+
+ case VLC_FOURCC('U','Y','V','Y'):
+ case VLC_FOURCC('U','Y','N','V'):
+ case VLC_FOURCC('Y','4','2','2'):
+ p_vout->chroma.pf_convert = I422_UYVY;
+ break;
+
+ case VLC_FOURCC('I','U','Y','V'):
+ p_vout->chroma.pf_convert = I422_IUYV;
+ break;
+
+ case VLC_FOURCC('c','y','u','v'):
+ p_vout->chroma.pf_convert = I422_cyuv;
+ break;
+
+#if defined (MODULE_NAME_IS_i422_yuy2)
+ case VLC_FOURCC('Y','2','1','1'):
+ p_vout->chroma.pf_convert = I422_Y211;
+ break;
+#endif
+
+ default:
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
+ *****************************************************************************/
+static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line = p_dest->p->p_pixels;
+ u8 *p_y = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ for( i_y = p_vout->render.i_height ; i_y-- ; )
+ {
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+#if defined (MODULE_NAME_IS_i422_yuy2)
+ C_YUV422_YUYV( p_line, p_y, p_u, p_v );
+ C_YUV422_YUYV( p_line, p_y, p_u, p_v );
+ C_YUV422_YUYV( p_line, p_y, p_u, p_v );
+ C_YUV422_YUYV( p_line, p_y, p_u, p_v );
+#else
+ __asm__( ".align 8" MMX_YUV422_YUYV
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+
+ __asm__( ".align 8" MMX_YUV422_YUYV
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+#endif
+ }
+ }
+}
+
+/*****************************************************************************
+ * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
+ *****************************************************************************/
+static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line = p_dest->p->p_pixels;
+ u8 *p_y = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ for( i_y = p_vout->render.i_height ; i_y-- ; )
+ {
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+#if defined (MODULE_NAME_IS_i422_yuy2)
+ C_YUV422_YVYU( p_line, p_y, p_u, p_v );
+ C_YUV422_YVYU( p_line, p_y, p_u, p_v );
+ C_YUV422_YVYU( p_line, p_y, p_u, p_v );
+ C_YUV422_YVYU( p_line, p_y, p_u, p_v );
+#else
+ __asm__( ".align 8" MMX_YUV422_YVYU
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+
+ __asm__( ".align 8" MMX_YUV422_YVYU
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+#endif
+ }
+ }
+}
+
+/*****************************************************************************
+ * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
+ *****************************************************************************/
+static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line = p_dest->p->p_pixels;
+ u8 *p_y = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ for( i_y = p_vout->render.i_height ; i_y-- ; )
+ {
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+#if defined (MODULE_NAME_IS_i422_yuy2)
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+#else
+ __asm__( ".align 8" MMX_YUV422_UYVY
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+
+ __asm__( ".align 8" MMX_YUV422_UYVY
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+#endif
+ }
+ }
+}
+
+/*****************************************************************************
+ * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
+ *****************************************************************************/
+static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ /* FIXME: TODO ! */
+ msg_Err( p_vout, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
+}
+
+/*****************************************************************************
+ * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
+ *****************************************************************************/
+static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
+ u8 *p_y = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ for( i_y = p_vout->render.i_height ; i_y-- ; )
+ {
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+ p_line -= 2 * p_dest->p->i_pitch;
+
+#if defined (MODULE_NAME_IS_i422_yuy2)
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+ C_YUV422_UYVY( p_line, p_y, p_u, p_v );
+#else
+ __asm__( ".align 8" MMX_YUV422_UYVY
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+
+ __asm__( ".align 8" MMX_YUV422_UYVY
+ : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
+
+ p_line += 8; p_y += 4; p_u += 2; p_v += 2;
+#endif
+ }
+ }
+}
+
+/*****************************************************************************
+ * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
+ *****************************************************************************/
+#if defined (MODULE_NAME_IS_i422_yuy2)
+static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
+ picture_t *p_dest )
+{
+ u8 *p_line = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
+ u8 *p_y = p_source->Y_PIXELS;
+ u8 *p_u = p_source->U_PIXELS;
+ u8 *p_v = p_source->V_PIXELS;
+
+ int i_x, i_y;
+
+ for( i_y = p_vout->render.i_height ; i_y-- ; )
+ {
+ for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
+ {
+ C_YUV422_Y211( p_line, p_y, p_u, p_v );
+ C_YUV422_Y211( p_line, p_y, p_u, p_v );
+ }
+ }
+}
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * i422_yuy2.h : YUV to YUV conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: i422_yuy2.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#ifdef MODULE_NAME_IS_i422_yuy2_mmx
+
+#define MMX_YUV422_YUYV " \n\
+movq (%1), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movd (%2), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%3), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+punpcklbw %%mm2, %%mm1 # v3 u3 v2 u2 v1 u1 v0 u0 \n\
+movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
+punpcklbw %%mm1, %%mm2 # v1 y3 u1 y2 v0 y1 u0 y0 \n\
+movq %%mm2, (%0) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # v3 y7 u3 y6 v2 y5 u2 y4 \n\
+movq %%mm0, 8(%0) # Store high YUYV \n\
+"
+
+#define MMX_YUV422_YVYU " \n\
+movq (%1), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movd (%2), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%3), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
+punpcklbw %%mm1, %%mm2 # u1 y3 v1 y2 u0 y1 v0 y0 \n\
+movq %%mm2, (%0) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # u3 y7 v3 y6 u2 y5 v2 y4 \n\
+movq %%mm0, 8(%0) # Store high YUYV \n\
+"
+
+#define MMX_YUV422_UYVY " \n\
+movq (%1), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movd (%2), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%3), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
+punpcklbw %%mm0, %%mm2 # y3 v1 y2 u1 y1 v0 y0 u0 \n\
+movq %%mm2, (%0) # Store low UYVY \n\
+punpckhbw %%mm0, %%mm1 # y7 v3 y6 u3 y5 v2 y4 u2 \n\
+movq %%mm1, 8(%0) # Store high UYVY \n\
+"
+
+#define MMX_YUV422_Y211 " \n\
+"
+
+#else
+
+#define C_YUV422_YUYV( p_line, p_y, p_u, p_v ) \
+ *(p_line)++ = *(p_y)++; \
+ *(p_line)++ = *(p_u)++; \
+ *(p_line)++ = *(p_y)++; \
+ *(p_line)++ = *(p_v)++; \
+
+#define C_YUV422_YVYU( p_line, p_y, p_u, p_v ) \
+ *(p_line)++ = *(p_y)++; \
+ *(p_line)++ = *(p_v)++; \
+ *(p_line)++ = *(p_y)++; \
+ *(p_line)++ = *(p_u)++; \
+
+#define C_YUV422_UYVY( p_line, p_y, p_u, p_v ) \
+ *(p_line)++ = *(p_u)++; \
+ *(p_line)++ = *(p_y)++; \
+ *(p_line)++ = *(p_v)++; \
+ *(p_line)++ = *(p_y)++; \
+
+#define C_YUV422_Y211( p_line, p_y, p_u, p_v ) \
+ *(p_line)++ = *(p_y); ((u16*)p_y)++; \
+ *(p_line)++ = *(p_u) - 0x80; ((u16*)p_u)++; \
+ *(p_line)++ = *(p_y); ((u16*)p_y)++; \
+ *(p_line)++ = *(p_v) - 0x80; ((u16*)p_v)++; \
+
+#endif
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+transform_SOURCES = transform.c
+invert_SOURCES = invert.c
+distort_SOURCES = distort.c
+wall_SOURCES = wall.c
+clone_SOURCES = clone.c
+crop_SOURCES = crop.c
--- /dev/null
+/*****************************************************************************
+ * clone.c : Clone video plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: clone.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "filter_common.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+
+static void RemoveAllVout ( vout_thread_t *p_vout );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define COUNT_TEXT N_("Number of clones")
+#define COUNT_LONGTEXT N_("Select the number of video windows in which to "\
+ "clone the video")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_integer( "clone-count", 2, NULL, COUNT_TEXT, COUNT_LONGTEXT );
+ set_description( _("image clone video module") );
+ set_capability( "video filter", 0 );
+ add_shortcut( "clone" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Clone video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Clone specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ int i_clones;
+ vout_thread_t **pp_vout;
+};
+
+/*****************************************************************************
+ * Create: allocates Clone video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Clone vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = NULL;
+
+ /* Look what method was requested */
+ p_vout->p_sys->i_clones = config_GetInt( p_vout, "clone-count" );
+
+ p_vout->p_sys->i_clones = __MAX( 1, __MIN( 99, p_vout->p_sys->i_clones ) );
+
+ msg_Dbg( p_vout, "spawning %i clone(s)", p_vout->p_sys->i_clones );
+
+ p_vout->p_sys->pp_vout = malloc( p_vout->p_sys->i_clones *
+ sizeof(vout_thread_t *) );
+ if( p_vout->p_sys->pp_vout == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize Clone video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index, i_vout;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure */
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ /* Try to open the real video output */
+ msg_Dbg( p_vout, "spawning the real video outputs" );
+
+ for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
+ {
+ p_vout->p_sys->pp_vout[ i_vout ] =
+ vout_CreateThread( p_vout,
+ p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->render.i_chroma, p_vout->render.i_aspect );
+ if( p_vout->p_sys->pp_vout[ i_vout ] == NULL )
+ {
+ msg_Err( p_vout, "failed to clone %i vout threads",
+ p_vout->p_sys->i_clones );
+ p_vout->p_sys->i_clones = i_vout;
+ RemoveAllVout( p_vout );
+ return 0;
+ }
+ }
+
+ ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate Clone video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy Clone video thread output method
+ *****************************************************************************
+ * Terminate an output method created by CloneCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ RemoveAllVout( p_vout );
+
+ free( p_vout->p_sys->pp_vout );
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Render: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to Clone image, waits
+ * until it is displayed and switch the two rendering buffers, preparing next
+ * frame.
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ picture_t *p_outpic = NULL;
+ int i_vout, i_plane;
+
+ for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
+ {
+ while( ( p_outpic =
+ vout_CreatePicture( p_vout->p_sys->pp_vout[ i_vout ], 0, 0, 0 )
+ ) == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ vout_DestroyPicture(
+ p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
+ return;
+ }
+
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ vout_DatePicture( p_vout->p_sys->pp_vout[ i_vout ],
+ p_outpic, p_pic->date );
+ vout_LinkPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
+
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ u8 *p_in, *p_in_end, *p_out;
+ int i_in_pitch = p_pic->p[i_plane].i_pitch;
+ const int i_out_pitch = p_outpic->p[i_plane].i_pitch;
+
+ p_in = p_pic->p[i_plane].p_pixels;
+
+ p_in_end = p_in + p_outpic->p[i_plane].i_lines
+ * p_pic->p[i_plane].i_pitch;
+
+ p_out = p_outpic->p[i_plane].p_pixels;
+
+ while( p_in < p_in_end )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in, i_out_pitch );
+ p_in += i_in_pitch;
+ p_out += i_out_pitch;
+ }
+ }
+
+ vout_UnlinkPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
+ vout_DisplayPicture( p_vout->p_sys->pp_vout[ i_vout ], p_outpic );
+ }
+}
+
+/*****************************************************************************
+ * RemoveAllVout: destroy all the child video output threads
+ *****************************************************************************/
+static void RemoveAllVout( vout_thread_t *p_vout )
+{
+ while( p_vout->p_sys->i_clones )
+ {
+ --p_vout->p_sys->i_clones;
+ vout_DestroyThread( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] );
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * crop.c : Crop video plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: crop.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "filter_common.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+
+static void UpdateStats ( vout_thread_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define GEOMETRY_TEXT N_("Crop geometry")
+#define GEOMETRY_LONGTEXT N_("Set the geometry of the zone to crop")
+
+#define AUTOCROP_TEXT N_("Automatic cropping")
+#define AUTOCROP_LONGTEXT N_("Activate automatic black border cropping")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( "crop-geometry", NULL, NULL, GEOMETRY_TEXT, GEOMETRY_LONGTEXT );
+ add_bool( "autocrop", 0, NULL, AUTOCROP_TEXT, AUTOCROP_LONGTEXT );
+ set_description( _("image crop video module") );
+ set_capability( "video filter", 0 );
+ add_shortcut( "crop" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Crop video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Crop specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ vout_thread_t *p_vout;
+
+ unsigned int i_x, i_y;
+ unsigned int i_width, i_height, i_aspect;
+
+ vlc_bool_t b_autocrop;
+
+ /* Autocrop specific variables */
+ unsigned int i_lastchange;
+ vlc_bool_t b_changed;
+};
+
+/*****************************************************************************
+ * Create: allocates Crop video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Crop vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return 1;
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = NULL;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Init: initialize Crop video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ char *psz_var;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ p_vout->p_sys->i_lastchange = 0;
+ p_vout->p_sys->b_changed = 0;
+
+ /* Initialize the output structure */
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ /* Shall we use autocrop ? */
+ p_vout->p_sys->b_autocrop = config_GetInt( p_vout, "autocrop" );
+
+ /* Get geometry value from the user */
+ psz_var = config_GetPsz( p_vout, "crop-geometry" );
+ if( psz_var )
+ {
+ char *psz_parser, *psz_tmp;
+
+ psz_parser = psz_tmp = psz_var;
+ while( *psz_tmp && *psz_tmp != 'x' ) psz_tmp++;
+
+ if( *psz_tmp )
+ {
+ psz_tmp[0] = '\0';
+ p_vout->p_sys->i_width = atoi( psz_parser );
+
+ psz_parser = ++psz_tmp;
+ while( *psz_tmp && *psz_tmp != '+' ) psz_tmp++;
+
+ if( *psz_tmp )
+ {
+ psz_tmp[0] = '\0';
+ p_vout->p_sys->i_height = atoi( psz_parser );
+
+ psz_parser = ++psz_tmp;
+ while( *psz_tmp && *psz_tmp != '+' ) psz_tmp++;
+
+ if( *psz_tmp )
+ {
+ psz_tmp[0] = '\0';
+ p_vout->p_sys->i_x = atoi( psz_parser );
+ p_vout->p_sys->i_y = atoi( ++psz_tmp );
+ }
+ else
+ {
+ p_vout->p_sys->i_x = atoi( psz_parser );
+ p_vout->p_sys->i_y =
+ ( p_vout->output.i_height - p_vout->p_sys->i_height ) / 2;
+ }
+ }
+ else
+ {
+ p_vout->p_sys->i_height = atoi( psz_parser );
+ p_vout->p_sys->i_x =
+ ( p_vout->output.i_width - p_vout->p_sys->i_width ) / 2;
+ p_vout->p_sys->i_y =
+ ( p_vout->output.i_height - p_vout->p_sys->i_height ) / 2;
+ }
+ }
+ else
+ {
+ p_vout->p_sys->i_width = atoi( psz_parser );
+ p_vout->p_sys->i_height = p_vout->output.i_height;
+ p_vout->p_sys->i_x =
+ ( p_vout->output.i_width - p_vout->p_sys->i_width ) / 2;
+ p_vout->p_sys->i_y =
+ ( p_vout->output.i_height - p_vout->p_sys->i_height ) / 2;
+ }
+
+ /* Check for validity */
+ if( p_vout->p_sys->i_x + p_vout->p_sys->i_width
+ > p_vout->output.i_width )
+ {
+ p_vout->p_sys->i_x = 0;
+ if( p_vout->p_sys->i_width > p_vout->output.i_width )
+ {
+ p_vout->p_sys->i_width = p_vout->output.i_width;
+ }
+ }
+
+ if( p_vout->p_sys->i_y + p_vout->p_sys->i_height
+ > p_vout->output.i_height )
+ {
+ p_vout->p_sys->i_y = 0;
+ if( p_vout->p_sys->i_height > p_vout->output.i_height )
+ {
+ p_vout->p_sys->i_height = p_vout->output.i_height;
+ }
+ }
+
+ free( psz_var );
+ }
+ else
+ {
+ p_vout->p_sys->i_width = p_vout->output.i_width;
+ p_vout->p_sys->i_height = p_vout->output.i_height;
+ p_vout->p_sys->i_x = p_vout->p_sys->i_y = 0;
+ }
+
+ /* Pheeew. Parsing done. */
+ msg_Dbg( p_vout, "cropping at %ix%i+%i+%i, %sautocropping",
+ p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ p_vout->p_sys->i_x, p_vout->p_sys->i_y,
+ p_vout->p_sys->b_autocrop ? "" : "not " );
+
+ /* Set current output image properties */
+ p_vout->p_sys->i_aspect = p_vout->output.i_aspect
+ * p_vout->output.i_height / p_vout->p_sys->i_height
+ * p_vout->p_sys->i_width / p_vout->output.i_width;
+
+ /* Try to open the real video output */
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ p_vout->render.i_chroma, p_vout->p_sys->i_aspect );
+ if( p_vout->p_sys->p_vout == NULL )
+ {
+ msg_Err( p_vout, "failed to create vout" );
+ return 0;
+ }
+
+ ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * End: terminate Crop video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy Crop video thread output method
+ *****************************************************************************
+ * Terminate an output method created by CropCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ vout_DestroyThread( p_vout->p_sys->p_vout );
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Manage: handle Crop events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * console events. It returns a non null value on error.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ if( !p_vout->p_sys->b_changed )
+ {
+ return 0;
+ }
+
+ vout_DestroyThread( p_vout->p_sys->p_vout );
+
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ p_vout->render.i_chroma, p_vout->p_sys->i_aspect );
+ if( p_vout->p_sys->p_vout == NULL )
+ {
+ msg_Err( p_vout, "failed to create vout" );
+ return 1;
+ }
+
+ p_vout->p_sys->b_changed = 0;
+ p_vout->p_sys->i_lastchange = 0;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Render: display previously rendered output
+ *****************************************************************************
+ * This function sends the currently rendered image to Crop image, waits
+ * until it is displayed and switches the two rendering buffers, preparing next
+ * frame.
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ picture_t *p_outpic = NULL;
+ int i_plane;
+
+ if( p_vout->p_sys->b_changed )
+ {
+ return;
+ }
+
+ while( ( p_outpic =
+ vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 )
+ ) == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ vout_DestroyPicture( p_vout->p_sys->p_vout, p_outpic );
+ return;
+ }
+
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
+ vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
+
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ u8 *p_in, *p_out, *p_out_end;
+ int i_in_pitch = p_pic->p[i_plane].i_pitch;
+ const int i_out_pitch = p_outpic->p[i_plane].i_pitch;
+
+ p_in = p_pic->p[i_plane].p_pixels
+ /* Skip the right amount of lines */
+ + i_in_pitch * ( p_pic->p[i_plane].i_lines * p_vout->p_sys->i_y
+ / p_vout->output.i_height )
+ /* Skip the right amount of columns */
+ + i_in_pitch * p_vout->p_sys->i_x / p_vout->output.i_width;
+
+ p_out = p_outpic->p[i_plane].p_pixels;
+ p_out_end = p_out + i_out_pitch * p_outpic->p[i_plane].i_lines;
+
+ while( p_out < p_out_end )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in, i_out_pitch );
+ p_in += i_in_pitch;
+ p_out += i_out_pitch;
+ }
+ }
+
+ vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
+
+ /* The source image may still be in the cache ... parse it! */
+ if( !p_vout->p_sys->b_autocrop )
+ {
+ return;
+ }
+
+ UpdateStats( p_vout, p_pic );
+}
+
+static void UpdateStats( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ u8 *p_in = p_pic->p[0].p_pixels;
+ int i_pitch = p_pic->p[0].i_pitch;
+ int i_lines = p_pic->p[0].i_lines;
+ int i_firstwhite = -1, i_lastwhite = -1, i;
+
+ /* Determine where black borders are */
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('I','4','2','0'):
+ /* XXX: Do not laugh ! I know this is very naive. But it's just a
+ * proof of concept code snippet... */
+ for( i = i_lines ; i-- ; )
+ {
+ const int i_col = i * i_pitch / i_lines;
+
+ if( p_in[i_col/2] > 40
+ && p_in[i_pitch / 2] > 40
+ && p_in[i_pitch/2 + i_col/2] > 40 )
+ {
+ if( i_lastwhite == -1 )
+ {
+ i_lastwhite = i;
+ }
+ i_firstwhite = i;
+ }
+ p_in += i_pitch;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Decide whether it's worth changing the size */
+ if( i_lastwhite == -1 )
+ {
+ p_vout->p_sys->i_lastchange = 0;
+ return;
+ }
+
+ if( i_lastwhite - i_firstwhite < p_vout->p_sys->i_height / 2 )
+ {
+ p_vout->p_sys->i_lastchange = 0;
+ return;
+ }
+
+ if( i_lastwhite - i_firstwhite < p_vout->p_sys->i_height + 16
+ && i_lastwhite - i_firstwhite + 16 > p_vout->p_sys->i_height )
+ {
+ p_vout->p_sys->i_lastchange = 0;
+ return;
+ }
+
+ /* We need at least 25 images to make up our mind */
+ p_vout->p_sys->i_lastchange++;
+ if( p_vout->p_sys->i_lastchange < 25 )
+ {
+ return;
+ }
+
+ /* Tune a few values */
+ if( i_firstwhite & 1 )
+ {
+ i_firstwhite--;
+ }
+
+ if( !(i_lastwhite & 1) )
+ {
+ i_lastwhite++;
+ }
+
+ /* Change size */
+ p_vout->p_sys->i_y = i_firstwhite;
+ p_vout->p_sys->i_height = i_lastwhite - i_firstwhite + 1;
+
+ p_vout->p_sys->i_aspect = p_vout->output.i_aspect
+ * p_vout->output.i_height / p_vout->p_sys->i_height
+ * p_vout->p_sys->i_width / p_vout->output.i_width;
+
+ p_vout->p_sys->b_changed = 1;
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+deinterlace_SOURCES = deinterlace.c
--- /dev/null
+/*****************************************************************************
+ * deinterlace.c : deinterlacer plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: deinterlace.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "../filter_common.h"
+
+#define DEINTERLACE_DISCARD 1
+#define DEINTERLACE_MEAN 2
+#define DEINTERLACE_BLEND 3
+#define DEINTERLACE_BOB 4
+#define DEINTERLACE_LINEAR 5
+
+/*****************************************************************************
+ * Local protypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+
+static void RenderBob ( vout_thread_t *, picture_t *, picture_t *, int );
+static void RenderMean ( vout_thread_t *, picture_t *, picture_t * );
+static void RenderBlend ( vout_thread_t *, picture_t *, picture_t * );
+static void RenderLinear ( vout_thread_t *, picture_t *, picture_t *, int );
+
+static void Merge ( void *, const void *, const void *, size_t );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define MODE_TEXT N_("Deinterlace mode")
+#define MODE_LONGTEXT N_("one of \"discard\", \"blend\", \"mean\", \"bob\" or \"linear\"")
+
+static char *mode_list[] = { "discard", "blend", "mean", "bob", "linear", NULL };
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string_from_list( "deinterlace-mode", "discard", mode_list, NULL,
+ MODE_TEXT, MODE_LONGTEXT );
+ set_description( _("deinterlacing module") );
+ set_capability( "video filter", 0 );
+ add_shortcut( "deinterlace" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Deinterlace video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Deinterlace specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ int i_mode; /* Deinterlace mode */
+ vlc_bool_t b_double_rate; /* Shall we double the framerate? */
+
+ mtime_t last_date;
+ mtime_t next_date;
+
+ vout_thread_t *p_vout;
+};
+
+/*****************************************************************************
+ * Create: allocates Deinterlace video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Deinterlace vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ char *psz_method;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return 1;
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = NULL;
+
+ p_vout->p_sys->i_mode = DEINTERLACE_DISCARD;
+ p_vout->p_sys->b_double_rate = 0;
+ p_vout->p_sys->last_date = 0;
+
+ /* Look what method was requested */
+ psz_method = config_GetPsz( p_vout, "deinterlace-mode" );
+
+ if( psz_method == NULL )
+ {
+ msg_Err( p_vout, "configuration variable %s empty",
+ "deinterlace-mode" );
+ msg_Err( p_vout, "no deinterlace mode provided, using \"discard\"" );
+ }
+ else
+ {
+ if( !strcmp( psz_method, "discard" ) )
+ {
+ p_vout->p_sys->i_mode = DEINTERLACE_DISCARD;
+ }
+ else if( !strcmp( psz_method, "mean" ) )
+ {
+ p_vout->p_sys->i_mode = DEINTERLACE_MEAN;
+ }
+ else if( !strcmp( psz_method, "blend" )
+ || !strcmp( psz_method, "average" )
+ || !strcmp( psz_method, "combine-fields" ) )
+ {
+ p_vout->p_sys->i_mode = DEINTERLACE_BLEND;
+ }
+ else if( !strcmp( psz_method, "bob" )
+ || !strcmp( psz_method, "progressive-scan" ) )
+ {
+ p_vout->p_sys->i_mode = DEINTERLACE_BOB;
+ p_vout->p_sys->b_double_rate = 1;
+ }
+ else if( !strcmp( psz_method, "linear" ) )
+ {
+ p_vout->p_sys->i_mode = DEINTERLACE_LINEAR;
+ p_vout->p_sys->b_double_rate = 1;
+ }
+ else
+ {
+ msg_Err( p_vout, "no valid deinterlace mode provided, "
+ "using \"discard\"" );
+ }
+
+ free( psz_method );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Init: initialize Deinterlace video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure, full of directbuffers since we want
+ * the decoder to output directly to our structures. */
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ case VLC_FOURCC('Y','V','1','2'):
+ case VLC_FOURCC('I','4','2','2'):
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+ break;
+
+ default:
+ return 0; /* unknown chroma */
+ break;
+ }
+
+ /* Try to open the real video output, with half the height our images */
+ msg_Dbg( p_vout, "spawning the real video output" );
+
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ case VLC_FOURCC('Y','V','1','2'):
+ switch( p_vout->p_sys->i_mode )
+ {
+ case DEINTERLACE_BOB:
+ case DEINTERLACE_MEAN:
+ case DEINTERLACE_DISCARD:
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->output.i_width, p_vout->output.i_height / 2,
+ p_vout->output.i_chroma, p_vout->output.i_aspect );
+ break;
+
+ case DEINTERLACE_BLEND:
+ case DEINTERLACE_LINEAR:
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->output.i_width, p_vout->output.i_height,
+ p_vout->output.i_chroma, p_vout->output.i_aspect );
+ break;
+ }
+ break;
+
+ case VLC_FOURCC('I','4','2','2'):
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->output.i_width, p_vout->output.i_height,
+ VLC_FOURCC('I','4','2','0'), p_vout->output.i_aspect );
+ break;
+
+ default:
+ break;
+ }
+
+ /* Everything failed */
+ if( p_vout->p_sys->p_vout == NULL )
+ {
+ msg_Err( p_vout, "cannot open vout, aborting" );
+
+ return 0;
+ }
+
+ ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * End: terminate Deinterlace video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy Deinterlace video thread output method
+ *****************************************************************************
+ * Terminate an output method created by DeinterlaceCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ vout_DestroyThread( p_vout->p_sys->p_vout );
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Render: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to Deinterlace image,
+ * waits until it is displayed and switch the two rendering buffers, preparing
+ * next frame.
+ *****************************************************************************/
+static void Render ( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ picture_t *pp_outpic[2];
+
+ /* Get a new picture */
+ while( ( pp_outpic[0] = vout_CreatePicture( p_vout->p_sys->p_vout,
+ 0, 0, 0 ) )
+ == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ vout_DatePicture( p_vout->p_sys->p_vout, pp_outpic[0], p_pic->date );
+
+ /* If we are using double rate, get an additional new picture */
+ if( p_vout->p_sys->b_double_rate )
+ {
+ while( ( pp_outpic[1] = vout_CreatePicture( p_vout->p_sys->p_vout,
+ 0, 0, 0 ) )
+ == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ vout_DestroyPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ /* 20ms is a bit arbitrary, but it's only for the first image we get */
+ if( !p_vout->p_sys->last_date )
+ {
+ vout_DatePicture( p_vout->p_sys->p_vout, pp_outpic[1],
+ p_pic->date + 20000 );
+ }
+ else
+ {
+ vout_DatePicture( p_vout->p_sys->p_vout, pp_outpic[1],
+ (3 * p_pic->date - p_vout->p_sys->last_date) / 2 );
+ }
+ p_vout->p_sys->last_date = p_pic->date;
+ }
+
+ switch( p_vout->p_sys->i_mode )
+ {
+ case DEINTERLACE_DISCARD:
+ RenderBob( p_vout, pp_outpic[0], p_pic, 0 );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
+ break;
+
+ case DEINTERLACE_BOB:
+ RenderBob( p_vout, pp_outpic[0], p_pic, 0 );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
+ RenderBob( p_vout, pp_outpic[1], p_pic, 1 );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[1] );
+ break;
+
+ case DEINTERLACE_LINEAR:
+ RenderLinear( p_vout, pp_outpic[0], p_pic, 0 );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
+ RenderLinear( p_vout, pp_outpic[1], p_pic, 1 );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[1] );
+ break;
+
+ case DEINTERLACE_MEAN:
+ RenderMean( p_vout, pp_outpic[0], p_pic );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
+ break;
+
+ case DEINTERLACE_BLEND:
+ RenderBlend( p_vout, pp_outpic[0], p_pic );
+ vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
+ break;
+ }
+}
+
+/*****************************************************************************
+ * RenderBob: renders a bob picture
+ *****************************************************************************/
+static void RenderBob( vout_thread_t *p_vout,
+ picture_t *p_outpic, picture_t *p_pic, int i_field )
+{
+ int i_plane;
+
+ /* Copy image and skip lines */
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ u8 *p_in, *p_out_end, *p_out;
+ int i_increment;
+
+ p_in = p_pic->p[i_plane].p_pixels
+ + i_field * p_pic->p[i_plane].i_pitch;
+
+ p_out = p_outpic->p[i_plane].p_pixels;
+ p_out_end = p_out + p_outpic->p[i_plane].i_pitch
+ * p_outpic->p[i_plane].i_lines;
+
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ case VLC_FOURCC('Y','V','1','2'):
+
+ for( ; p_out < p_out_end ; )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+
+ p_out += p_pic->p[i_plane].i_pitch;
+ p_in += 2 * p_pic->p[i_plane].i_pitch;
+ }
+ break;
+
+ case VLC_FOURCC('I','4','2','2'):
+
+ i_increment = 2 * p_pic->p[i_plane].i_pitch;
+
+ if( i_plane == Y_PLANE )
+ {
+ for( ; p_out < p_out_end ; )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+ p_out += p_pic->p[i_plane].i_pitch;
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+ p_out += p_pic->p[i_plane].i_pitch;
+ p_in += i_increment;
+ }
+ }
+ else
+ {
+ for( ; p_out < p_out_end ; )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+ p_out += p_pic->p[i_plane].i_pitch;
+ p_in += i_increment;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*****************************************************************************
+ * RenderLinear: displays previously rendered output
+ *****************************************************************************/
+static void RenderLinear( vout_thread_t *p_vout,
+ picture_t *p_outpic, picture_t *p_pic, int i_field )
+{
+ int i_plane;
+
+ /* Copy image and skip lines */
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ u8 *p_in, *p_out_end, *p_out;
+
+ p_in = p_pic->p[i_plane].p_pixels
+ + i_field * p_pic->p[i_plane].i_pitch;
+
+ p_out = p_outpic->p[i_plane].p_pixels;
+ p_out_end = p_out + p_outpic->p[i_plane].i_pitch
+ * p_outpic->p[i_plane].i_lines;
+
+ if( i_field == 0 )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+ p_in += 2 * p_pic->p[i_plane].i_pitch;
+ p_out += p_pic->p[i_plane].i_pitch;
+ }
+
+ p_out_end -= p_outpic->p[i_plane].i_pitch;
+
+ for( ; p_out < p_out_end ; )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+
+ p_out += p_pic->p[i_plane].i_pitch;
+
+ Merge( p_out, p_in, p_in + 2 * p_pic->p[i_plane].i_pitch,
+ p_pic->p[i_plane].i_pitch );
+
+ p_in += 2 * p_pic->p[i_plane].i_pitch;
+ p_out += p_pic->p[i_plane].i_pitch;
+ }
+
+#if 0
+ if( i_field == 0 )
+ {
+ p_in -= 2 * p_pic->p[i_plane].i_pitch;
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+ }
+#endif
+ }
+}
+
+static void RenderMean( vout_thread_t *p_vout,
+ picture_t *p_outpic, picture_t *p_pic )
+{
+ int i_plane;
+
+ /* Copy image and skip lines */
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ u8 *p_in, *p_out_end, *p_out;
+
+ p_in = p_pic->p[i_plane].p_pixels;
+
+ p_out = p_outpic->p[i_plane].p_pixels;
+ p_out_end = p_out + p_outpic->p[i_plane].i_pitch
+ * p_outpic->p[i_plane].i_lines;
+
+ /* All lines: mean value */
+ for( ; p_out < p_out_end ; )
+ {
+ Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
+ p_pic->p[i_plane].i_pitch );
+
+ p_out += p_pic->p[i_plane].i_pitch;
+ p_in += 2 * p_pic->p[i_plane].i_pitch;
+ }
+ }
+}
+
+static void RenderBlend( vout_thread_t *p_vout,
+ picture_t *p_outpic, picture_t *p_pic )
+{
+ int i_plane;
+
+ /* Copy image and skip lines */
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ u8 *p_in, *p_out_end, *p_out;
+
+ p_in = p_pic->p[i_plane].p_pixels;
+
+ p_out = p_outpic->p[i_plane].p_pixels;
+ p_out_end = p_out + p_outpic->p[i_plane].i_pitch
+ * p_outpic->p[i_plane].i_lines;
+
+ /* First line: simple copy */
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_pic->p[i_plane].i_pitch );
+ p_out += p_pic->p[i_plane].i_pitch;
+
+ /* Remaining lines: mean value */
+ for( ; p_out < p_out_end ; )
+ {
+ Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
+ p_pic->p[i_plane].i_pitch );
+
+ p_out += p_pic->p[i_plane].i_pitch;
+ p_in += p_pic->p[i_plane].i_pitch;
+ }
+ }
+}
+
+static void Merge( void *p_dest, const void *p_s1,
+ const void *p_s2, size_t i_bytes )
+{
+ u8* p_end = (u8*)p_dest + i_bytes - 8;
+
+ while( (u8*)p_dest < p_end )
+ {
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ }
+
+ p_end += 8;
+
+ while( (u8*)p_dest < p_end )
+ {
+ *(u8*)p_dest++ = ( (u16)(*(u8*)p_s1++) + (u16)(*(u8*)p_s2++) ) >> 1;
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * distort.c : Misc video effects plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: distort.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <math.h> /* sin(), cos() */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "filter_common.h"
+
+#define DISTORT_MODE_WAVE 1
+#define DISTORT_MODE_RIPPLE 2
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+
+static void DistortWave ( vout_thread_t *, picture_t *, picture_t * );
+static void DistortRipple ( vout_thread_t *, picture_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define MODE_TEXT N_("Distort mode")
+#define MODE_LONGTEXT N_("one of \"wave\" and \"ripple\"")
+
+static char *mode_list[] = { "wave", "ripple", NULL };
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string_from_list( "distort-mode", "wave", mode_list, NULL,
+ MODE_TEXT, MODE_LONGTEXT );
+ set_description( _("miscellaneous video effects module") );
+ set_capability( "video filter", 0 );
+ add_shortcut( "distort" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Distort video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Distort specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ int i_mode;
+ vout_thread_t *p_vout;
+
+ /* For the wave mode */
+ double f_angle;
+ mtime_t last_date;
+};
+
+/*****************************************************************************
+ * Create: allocates Distort video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Distort vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ char *psz_method, *psz_method_tmp;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = NULL;
+
+ p_vout->p_sys->i_mode = 0;
+ /* Look what method was requested from command line*/
+ if( !(psz_method = psz_method_tmp = config_GetPsz( p_vout, "filter" )) )
+ {
+ msg_Err( p_vout, "configuration variable %s empty", "filter" );
+ return( 1 );
+ }
+ while( *psz_method && *psz_method != ':' )
+ {
+ psz_method++;
+ }
+
+ if( !strcmp( psz_method, ":wave" ) )
+ {
+ p_vout->p_sys->i_mode = DISTORT_MODE_WAVE;
+ }
+ else if( !strcmp( psz_method, ":ripple" ) )
+ {
+ p_vout->p_sys->i_mode = DISTORT_MODE_RIPPLE;
+ }
+ free( psz_method_tmp );
+ if( !p_vout->p_sys->i_mode )
+ {
+ /* No method given in commandline. Look what method was
+ requested in configuration system */
+ if( !(psz_method = psz_method_tmp
+ = config_GetPsz( p_vout, "distort-mode" )) )
+ {
+ msg_Err( p_vout, "configuration variable %s empty, using 'wave'",
+ "distort-mode" );
+ p_vout->p_sys->i_mode = DISTORT_MODE_WAVE;
+ }
+ else {
+
+ if( !strcmp( psz_method, "wave" ) )
+ {
+ p_vout->p_sys->i_mode = DISTORT_MODE_WAVE;
+ }
+ else if( !strcmp( psz_method, "ripple" ) )
+ {
+ p_vout->p_sys->i_mode = DISTORT_MODE_RIPPLE;
+ }
+
+ else
+ {
+ msg_Err( p_vout, "no valid distort mode provided, "
+ "using wave" );
+ p_vout->p_sys->i_mode = DISTORT_MODE_WAVE;
+ }
+ }
+ }
+ free( psz_method_tmp );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize Distort video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure */
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ /* Try to open the real video output */
+ msg_Dbg( p_vout, "spawning the real video output" );
+
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->render.i_chroma, p_vout->render.i_aspect );
+
+ /* Everything failed */
+ if( p_vout->p_sys->p_vout == NULL )
+ {
+ msg_Err( p_vout, "cannot open vout, aborting" );
+
+ return( 0 );
+ }
+
+ ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+
+ p_vout->p_sys->f_angle = 0.0;
+ p_vout->p_sys->last_date = 0;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate Distort video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy Distort video thread output method
+ *****************************************************************************
+ * Terminate an output method created by DistortCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ vout_DestroyThread( p_vout->p_sys->p_vout );
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Render: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to Distort image, waits
+ * until it is displayed and switch the two rendering buffers, preparing next
+ * frame.
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ picture_t *p_outpic;
+
+ /* This is a new frame. Get a structure from the video_output. */
+ while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
+ == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
+
+ switch( p_vout->p_sys->i_mode )
+ {
+ case DISTORT_MODE_WAVE:
+ DistortWave( p_vout, p_pic, p_outpic );
+ break;
+
+ case DISTORT_MODE_RIPPLE:
+ DistortRipple( p_vout, p_pic, p_outpic );
+ break;
+
+ default:
+ break;
+ }
+
+ vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
+}
+
+/*****************************************************************************
+ * DistortWave: draw a wave effect on the picture
+ *****************************************************************************/
+static void DistortWave( vout_thread_t *p_vout, picture_t *p_inpic,
+ picture_t *p_outpic )
+{
+ int i_index;
+ double f_angle;
+ mtime_t new_date = mdate();
+
+ p_vout->p_sys->f_angle += (new_date - p_vout->p_sys->last_date) / 200000.0;
+ p_vout->p_sys->last_date = new_date;
+ f_angle = p_vout->p_sys->f_angle;
+
+ for( i_index = 0 ; i_index < p_inpic->i_planes ; i_index++ )
+ {
+ int i_line, i_num_lines, i_offset;
+ u8 black_pixel;
+ u8 *p_in, *p_out;
+
+ p_in = p_inpic->p[i_index].p_pixels;
+ p_out = p_outpic->p[i_index].p_pixels;
+
+ i_num_lines = p_inpic->p[i_index].i_lines;
+
+ black_pixel = ( i_index == Y_PLANE ) ? 0x00 : 0x80;
+
+ /* Ok, we do 3 times the sin() calculation for each line. So what ? */
+ for( i_line = 0 ; i_line < i_num_lines ; i_line++ )
+ {
+ /* Calculate today's offset, don't go above 1/20th of the screen */
+ i_offset = (double)(p_inpic->p[i_index].i_pitch)
+ * sin( f_angle + 10.0 * (double)i_line
+ / (double)i_num_lines )
+ / 20.0;
+
+ if( i_offset )
+ {
+ if( i_offset < 0 )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in - i_offset,
+ p_inpic->p[i_index].i_pitch + i_offset );
+ p_in += p_inpic->p[i_index].i_pitch;
+ p_out += p_outpic->p[i_index].i_pitch;
+ memset( p_out + i_offset, black_pixel, -i_offset );
+ }
+ else
+ {
+ p_vout->p_vlc->pf_memcpy( p_out + i_offset, p_in,
+ p_inpic->p[i_index].i_pitch - i_offset );
+ memset( p_out, black_pixel, i_offset );
+ p_in += p_inpic->p[i_index].i_pitch;
+ p_out += p_outpic->p[i_index].i_pitch;
+ }
+ }
+ else
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_inpic->p[i_index].i_pitch );
+ p_in += p_inpic->p[i_index].i_pitch;
+ p_out += p_outpic->p[i_index].i_pitch;
+ }
+
+ }
+ }
+}
+
+/*****************************************************************************
+ * DistortRipple: draw a ripple effect at the bottom of the picture
+ *****************************************************************************/
+static void DistortRipple( vout_thread_t *p_vout, picture_t *p_inpic,
+ picture_t *p_outpic )
+{
+ int i_index;
+ double f_angle;
+ mtime_t new_date = mdate();
+
+ p_vout->p_sys->f_angle -= (p_vout->p_sys->last_date - new_date) / 100000.0;
+ p_vout->p_sys->last_date = new_date;
+ f_angle = p_vout->p_sys->f_angle;
+
+ for( i_index = 0 ; i_index < p_inpic->i_planes ; i_index++ )
+ {
+ int i_line, i_first_line, i_num_lines, i_offset;
+ u8 black_pixel;
+ u8 *p_in, *p_out;
+
+ black_pixel = ( i_index == Y_PLANE ) ? 0x00 : 0x80;
+
+ i_num_lines = p_inpic->p[i_index].i_lines;
+
+ i_first_line = i_num_lines * 4 / 5;
+
+ p_in = p_inpic->p[i_index].p_pixels;
+ p_out = p_outpic->p[i_index].p_pixels;
+
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ i_first_line * p_inpic->p[i_index].i_pitch );
+
+ p_in += i_first_line * p_inpic->p[i_index].i_pitch;
+ p_out += i_first_line * p_outpic->p[i_index].i_pitch;
+
+ /* Ok, we do 3 times the sin() calculation for each line. So what ? */
+ for( i_line = i_first_line ; i_line < i_num_lines ; i_line++ )
+ {
+ /* Calculate today's offset, don't go above 1/20th of the screen */
+ i_offset = (double)(p_inpic->p[i_index].i_pitch)
+ * sin( f_angle + 2.0 * (double)i_line
+ / (double)( 1 + i_line
+ - i_first_line) )
+ * (double)(i_line - i_first_line)
+ / (double)i_num_lines
+ / 8.0;
+
+ if( i_offset )
+ {
+ if( i_offset < 0 )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in - i_offset,
+ p_inpic->p[i_index].i_pitch + i_offset );
+ p_in -= p_inpic->p[i_index].i_pitch;
+ p_out += p_outpic->p[i_index].i_pitch;
+ memset( p_out + i_offset, black_pixel, -i_offset );
+ }
+ else
+ {
+ p_vout->p_vlc->pf_memcpy( p_out + i_offset, p_in,
+ p_inpic->p[i_index].i_pitch - i_offset );
+ memset( p_out, black_pixel, i_offset );
+ p_in -= p_inpic->p[i_index].i_pitch;
+ p_out += p_outpic->p[i_index].i_pitch;
+ }
+ }
+ else
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in,
+ p_inpic->p[i_index].i_pitch );
+ p_in -= p_inpic->p[i_index].i_pitch;
+ p_out += p_outpic->p[i_index].i_pitch;
+ }
+
+ }
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * filter_common.h: Common filter functions
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: filter_common.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+#define ALLOCATE_DIRECTBUFFERS( i_max ) \
+ /* Try to initialize i_max direct buffers */ \
+ while( I_OUTPUTPICTURES < ( i_max ) ) \
+ { \
+ p_pic = NULL; \
+ \
+ /* Find an empty picture slot */ \
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) \
+ { \
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) \
+ { \
+ p_pic = p_vout->p_picture + i_index; \
+ break; \
+ } \
+ } \
+ \
+ if( p_pic == NULL ) \
+ { \
+ break; \
+ } \
+ \
+ /* Allocate the picture */ \
+ vout_AllocatePicture( p_vout, p_pic, \
+ p_vout->output.i_width, \
+ p_vout->output.i_height, \
+ p_vout->output.i_chroma ); \
+ \
+ if( !p_pic->i_planes ) \
+ { \
+ break; \
+ } \
+ \
+ p_pic->i_status = DESTROYED_PICTURE; \
+ p_pic->i_type = DIRECT_PICTURE; \
+ \
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; \
+ \
+ I_OUTPUTPICTURES++; \
+ } \
+
--- /dev/null
+/*****************************************************************************
+ * invert.c : Invert video plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: invert.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "filter_common.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("invert video module") );
+ set_capability( "video filter", 0 );
+ add_shortcut( "invert" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Invert video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Invert specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ vout_thread_t *p_vout;
+};
+
+/*****************************************************************************
+ * Create: allocates Invert video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Invert vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = NULL;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize Invert video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure */
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ /* Try to open the real video output */
+ msg_Dbg( p_vout, "spawning the real video output" );
+
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->render.i_chroma, p_vout->render.i_aspect );
+
+ /* Everything failed */
+ if( p_vout->p_sys->p_vout == NULL )
+ {
+ msg_Err( p_vout, "can't open vout, aborting" );
+
+ return( 0 );
+ }
+
+ ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate Invert video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy Invert video thread output method
+ *****************************************************************************
+ * Terminate an output method created by InvertCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ vout_DestroyThread( p_vout->p_sys->p_vout );
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Render: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to Invert image, waits
+ * until it is displayed and switch the two rendering buffers, preparing next
+ * frame.
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ picture_t *p_outpic;
+ int i_index;
+
+ /* This is a new frame. Get a structure from the video_output. */
+ while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
+ == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
+ vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
+
+ for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+ {
+ u8 *p_in, *p_in_end, *p_out;
+
+ p_in = p_pic->p[i_index].p_pixels;
+ p_in_end = p_in - 64 + p_pic->p[i_index].i_lines
+ * p_pic->p[i_index].i_pitch;
+
+ p_out = p_outpic->p[i_index].p_pixels;
+
+ for( ; p_in < p_in_end ; )
+ {
+ /* Do 64 pixels at a time */
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ *((u64*)p_out)++ = ~( *((u64*)p_in)++ );
+ }
+
+ p_in_end += 64;
+
+ for( ; p_in < p_in_end ; )
+ {
+ /* Do 1 pixel at a time */
+ *p_out++ = ~( *p_in++ );
+ }
+ }
+
+ vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
+
+ vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
+}
+
--- /dev/null
+/*****************************************************************************
+ * transform.c : transform image plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: transform.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "filter_common.h"
+
+#define TRANSFORM_MODE_HFLIP 1
+#define TRANSFORM_MODE_VFLIP 2
+#define TRANSFORM_MODE_90 3
+#define TRANSFORM_MODE_180 4
+#define TRANSFORM_MODE_270 5
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define TYPE_TEXT N_("Transform type")
+#define TYPE_LONGTEXT N_("One of '90', '180', '270', 'hflip' and 'vflip'")
+
+static char *type_list[] = { "90", "180", "270", "hflip", "vflip", NULL };
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string_from_list( "transform-type", "90", type_list, NULL,
+ TYPE_TEXT, TYPE_LONGTEXT);
+ set_description( _("image transformation module") );
+ set_capability( "video filter", 0 );
+ add_shortcut( "transform" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Transform video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Transform specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ int i_mode;
+ vlc_bool_t b_rotation;
+ vout_thread_t *p_vout;
+};
+
+/*****************************************************************************
+ * Create: allocates Transform video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Transform vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ char *psz_method;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = NULL;
+
+ /* Look what method was requested */
+ psz_method = config_GetPsz( p_vout, "transform-type" );
+
+ if( psz_method == NULL )
+ {
+ msg_Err( p_vout, "configuration variable %s empty", "transform-type" );
+ msg_Err( p_vout, "no valid transform mode provided, using '90'" );
+ p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
+ p_vout->p_sys->b_rotation = 1;
+ }
+ else
+ {
+ if( !strcmp( psz_method, "hflip" ) )
+ {
+ p_vout->p_sys->i_mode = TRANSFORM_MODE_HFLIP;
+ p_vout->p_sys->b_rotation = 0;
+ }
+ else if( !strcmp( psz_method, "vflip" ) )
+ {
+ p_vout->p_sys->i_mode = TRANSFORM_MODE_VFLIP;
+ p_vout->p_sys->b_rotation = 0;
+ }
+ else if( !strcmp( psz_method, "90" ) )
+ {
+ p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
+ p_vout->p_sys->b_rotation = 1;
+ }
+ else if( !strcmp( psz_method, "180" ) )
+ {
+ p_vout->p_sys->i_mode = TRANSFORM_MODE_180;
+ p_vout->p_sys->b_rotation = 0;
+ }
+ else if( !strcmp( psz_method, "270" ) )
+ {
+ p_vout->p_sys->i_mode = TRANSFORM_MODE_270;
+ p_vout->p_sys->b_rotation = 1;
+ }
+ else
+ {
+ msg_Err( p_vout, "no valid transform mode provided, using '90'" );
+ p_vout->p_sys->i_mode = TRANSFORM_MODE_90;
+ p_vout->p_sys->b_rotation = 1;
+ }
+
+ free( psz_method );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize Transform video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure */
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ /* Try to open the real video output */
+ msg_Dbg( p_vout, "spawning the real video output" );
+
+ if( p_vout->p_sys->b_rotation )
+ {
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->render.i_height, p_vout->render.i_width,
+ p_vout->render.i_chroma,
+ (u64)VOUT_ASPECT_FACTOR * (u64)VOUT_ASPECT_FACTOR
+ / (u64)p_vout->render.i_aspect );
+ }
+ else
+ {
+ p_vout->p_sys->p_vout =
+ vout_CreateThread( p_vout,
+ p_vout->render.i_width, p_vout->render.i_height,
+ p_vout->render.i_chroma, p_vout->render.i_aspect );
+ }
+
+ /* Everything failed */
+ if( p_vout->p_sys->p_vout == NULL )
+ {
+ msg_Err( p_vout, "cannot open vout, aborting" );
+ return( 0 );
+ }
+
+ ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate Transform video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy Transform video thread output method
+ *****************************************************************************
+ * Terminate an output method created by TransformCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ vout_DestroyThread( p_vout->p_sys->p_vout );
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Render: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to Transform image, waits
+ * until it is displayed and switch the two rendering buffers, preparing next
+ * frame.
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ picture_t *p_outpic;
+ int i_index;
+
+ /* This is a new frame. Get a structure from the video_output. */
+ while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
+ == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
+ vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
+
+ switch( p_vout->p_sys->i_mode )
+ {
+ case TRANSFORM_MODE_90:
+ for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+ {
+ int i_pitch = p_pic->p[i_index].i_pitch;
+
+ u8 *p_in = p_pic->p[i_index].p_pixels;
+
+ u8 *p_out = p_outpic->p[i_index].p_pixels;
+ u8 *p_out_end = p_out + p_outpic->p[i_index].i_lines
+ * p_outpic->p[i_index].i_pitch;
+
+ for( ; p_out < p_out_end ; )
+ {
+ u8 *p_line_end;
+
+ p_line_end = p_in + p_pic->p[i_index].i_lines
+ * p_pic->p[i_index].i_pitch;
+
+ for( ; p_in < p_line_end ; )
+ {
+ p_line_end -= i_pitch;
+ *(--p_out_end) = *p_line_end;
+ }
+
+ p_in++;
+ }
+ }
+ break;
+
+ case TRANSFORM_MODE_180:
+ for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+ {
+ u8 *p_in = p_pic->p[i_index].p_pixels;
+ u8 *p_in_end = p_in + p_pic->p[i_index].i_lines
+ * p_pic->p[i_index].i_pitch;
+
+ u8 *p_out = p_outpic->p[i_index].p_pixels;
+
+ for( ; p_in < p_in_end ; )
+ {
+ *p_out++ = *(--p_in_end);
+ }
+ }
+ break;
+
+ case TRANSFORM_MODE_270:
+ for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+ {
+ int i_pitch = p_pic->p[i_index].i_pitch;
+
+ u8 *p_in = p_pic->p[i_index].p_pixels;
+
+ u8 *p_out = p_outpic->p[i_index].p_pixels;
+ u8 *p_out_end = p_out + p_outpic->p[i_index].i_lines
+ * p_outpic->p[i_index].i_pitch;
+
+ for( ; p_out < p_out_end ; )
+ {
+ u8 *p_in_end;
+
+ p_in_end = p_in + p_pic->p[i_index].i_lines
+ * p_pic->p[i_index].i_pitch;
+
+ for( ; p_in < p_in_end ; )
+ {
+ p_in_end -= i_pitch;
+ *p_out++ = *p_in_end;
+ }
+
+ p_in++;
+ }
+ }
+ break;
+
+ case TRANSFORM_MODE_VFLIP:
+ for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+ {
+ u8 *p_in = p_pic->p[i_index].p_pixels;
+ u8 *p_in_end = p_in + p_pic->p[i_index].i_lines
+ * p_pic->p[i_index].i_pitch;
+
+ u8 *p_out = p_outpic->p[i_index].p_pixels;
+
+ for( ; p_in < p_in_end ; )
+ {
+ p_in_end -= p_pic->p[i_index].i_pitch;
+ p_vout->p_vlc->pf_memcpy( p_out, p_in_end,
+ p_pic->p[i_index].i_pitch );
+ p_out += p_pic->p[i_index].i_pitch;
+ }
+ }
+ break;
+
+ case TRANSFORM_MODE_HFLIP:
+ for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+ {
+ u8 *p_in = p_pic->p[i_index].p_pixels;
+ u8 *p_in_end = p_in + p_pic->p[i_index].i_lines
+ * p_pic->p[i_index].i_pitch;
+
+ u8 *p_out = p_outpic->p[i_index].p_pixels;
+
+ for( ; p_in < p_in_end ; )
+ {
+ u8 *p_line_end = p_in + p_pic->p[i_index].i_pitch;
+
+ for( ; p_in < p_line_end ; )
+ {
+ *p_out++ = *(--p_line_end);
+ }
+
+ p_in += p_pic->p[i_index].i_pitch;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
+
+ vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
+}
+
--- /dev/null
+/*****************************************************************************
+ * wall.c : Wall video plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: wall.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "filter_common.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+
+static void RemoveAllVout ( vout_thread_t *p_vout );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define COLS_TEXT N_("Number of columns")
+#define COLS_LONGTEXT N_("Select the number of horizontal videowindows in " \
+ "which to split the video")
+
+#define ROWS_TEXT N_("Number of rows")
+#define ROWS_LONGTEXT N_("Select the number of vertical videowindows in " \
+ "which to split the video")
+
+#define ACTIVE_TEXT N_("Active windows")
+#define ACTIVE_LONGTEXT N_("comma separated list of active windows, " \
+ "defaults to all")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_integer( "wall-cols", 3, NULL, COLS_TEXT, COLS_LONGTEXT );
+ add_integer( "wall-rows", 3, NULL, ROWS_TEXT, ROWS_LONGTEXT );
+ add_string( "wall-active", NULL, NULL, ACTIVE_TEXT, ACTIVE_LONGTEXT );
+ set_description( _("image wall video module") );
+ set_capability( "video filter", 0 );
+ add_shortcut( "wall" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Wall video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Wall specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ int i_col;
+ int i_row;
+ int i_vout;
+ struct vout_list_t
+ {
+ vlc_bool_t b_active;
+ int i_width;
+ int i_height;
+ vout_thread_t *p_vout;
+ } *pp_vout;
+};
+
+/*****************************************************************************
+ * Create: allocates Wall video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Wall vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ char *psz_method, *psz_tmp, *psz_method_tmp;
+ int i_vout;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = NULL;
+
+ /* Look what method was requested */
+ p_vout->p_sys->i_col = config_GetInt( p_vout, "wall-cols" );
+ p_vout->p_sys->i_row = config_GetInt( p_vout, "wall-rows" );
+
+ p_vout->p_sys->i_col = __MAX( 1, __MIN( 15, p_vout->p_sys->i_col ) );
+ p_vout->p_sys->i_row = __MAX( 1, __MIN( 15, p_vout->p_sys->i_row ) );
+
+ msg_Dbg( p_vout, "opening a %i x %i wall",
+ p_vout->p_sys->i_col, p_vout->p_sys->i_row );
+
+ p_vout->p_sys->pp_vout = malloc( p_vout->p_sys->i_row *
+ p_vout->p_sys->i_col *
+ sizeof(struct vout_list_t) );
+ if( p_vout->p_sys->pp_vout == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ psz_method_tmp = psz_method = config_GetPsz( p_vout, "wall-active" );
+
+ /* If no trailing vout are specified, take them all */
+ if( psz_method == NULL )
+ {
+ for( i_vout = p_vout->p_sys->i_row * p_vout->p_sys->i_col;
+ i_vout--; )
+ {
+ p_vout->p_sys->pp_vout[i_vout].b_active = 1;
+ }
+ }
+ /* If trailing vout are specified, activate only the requested ones */
+ else
+ {
+ for( i_vout = p_vout->p_sys->i_row * p_vout->p_sys->i_col;
+ i_vout--; )
+ {
+ p_vout->p_sys->pp_vout[i_vout].b_active = 0;
+ }
+
+ while( *psz_method )
+ {
+ psz_tmp = psz_method;
+ while( *psz_tmp && *psz_tmp != ',' )
+ {
+ psz_tmp++;
+ }
+
+ if( *psz_tmp )
+ {
+ *psz_tmp = '\0';
+ i_vout = atoi( psz_method );
+ psz_method = psz_tmp + 1;
+ }
+ else
+ {
+ i_vout = atoi( psz_method );
+ psz_method = psz_tmp;
+ }
+
+ if( i_vout >= 0 &&
+ i_vout < p_vout->p_sys->i_row * p_vout->p_sys->i_col )
+ {
+ p_vout->p_sys->pp_vout[i_vout].b_active = 1;
+ }
+ }
+ }
+
+ free( psz_method_tmp );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize Wall video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index, i_row, i_col, i_width, i_height;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure */
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ /* Try to open the real video output */
+ msg_Dbg( p_vout, "spawning the real video outputs" );
+
+ p_vout->p_sys->i_vout = 0;
+
+ /* FIXME: use bresenham instead of those ugly divisions */
+ for( i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
+ {
+ for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++ )
+ {
+ if( i_col + 1 < p_vout->p_sys->i_col )
+ {
+ i_width = ( p_vout->render.i_width
+ / p_vout->p_sys->i_col ) & ~0x1;
+ }
+ else
+ {
+ i_width = p_vout->render.i_width
+ - ( ( p_vout->render.i_width
+ / p_vout->p_sys->i_col ) & ~0x1 ) * i_col;
+ }
+
+ if( i_row + 1 < p_vout->p_sys->i_row )
+ {
+ i_height = ( p_vout->render.i_height
+ / p_vout->p_sys->i_row ) & ~0x3;
+ }
+ else
+ {
+ i_height = p_vout->render.i_height
+ - ( ( p_vout->render.i_height
+ / p_vout->p_sys->i_row ) & ~0x3 ) * i_row;
+ }
+
+ p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].i_width = i_width;
+ p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].i_height = i_height;
+
+ if( !p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].b_active )
+ {
+ p_vout->p_sys->i_vout++;
+ continue;
+ }
+
+ p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout =
+ vout_CreateThread( p_vout, i_width, i_height,
+ p_vout->render.i_chroma,
+ p_vout->render.i_aspect
+ * p_vout->render.i_height / i_height
+ * i_width / p_vout->render.i_width );
+ if( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout == NULL )
+ {
+ msg_Err( p_vout, "failed to get %ix%i vout threads",
+ p_vout->p_sys->i_col, p_vout->p_sys->i_row );
+ RemoveAllVout( p_vout );
+ return 0;
+ }
+
+ p_vout->p_sys->i_vout++;
+ }
+ }
+
+ ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate Wall video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the fake output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy Wall video thread output method
+ *****************************************************************************
+ * Terminate an output method created by WallCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ RemoveAllVout( p_vout );
+
+ free( p_vout->p_sys->pp_vout );
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Render: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to Wall image, waits
+ * until it is displayed and switch the two rendering buffers, preparing next
+ * frame.
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ picture_t *p_outpic = NULL;
+ int i_col, i_row, i_vout, i_plane;
+ int pi_left_skip[VOUT_MAX_PLANES], pi_top_skip[VOUT_MAX_PLANES];
+
+ i_vout = 0;
+
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ pi_top_skip[i_plane] = 0;
+ }
+
+ for( i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
+ {
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ pi_left_skip[i_plane] = 0;
+ }
+
+ for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++ )
+ {
+ if( !p_vout->p_sys->pp_vout[ i_vout ].b_active )
+ {
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ pi_left_skip[i_plane] +=
+ p_vout->p_sys->pp_vout[ i_vout ].i_width
+ * p_pic->p[i_plane].i_pitch / p_vout->output.i_width;
+ }
+ i_vout++;
+ continue;
+ }
+
+ while( ( p_outpic =
+ vout_CreatePicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
+ 0, 0, 0 )
+ ) == NULL )
+ {
+ if( p_vout->b_die || p_vout->b_error )
+ {
+ vout_DestroyPicture(
+ p_vout->p_sys->pp_vout[ i_vout ].p_vout, p_outpic );
+ return;
+ }
+
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ vout_DatePicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
+ p_outpic, p_pic->date );
+ vout_LinkPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
+ p_outpic );
+
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ u8 *p_in, *p_in_end, *p_out;
+ int i_in_pitch = p_pic->p[i_plane].i_pitch;
+ int i_out_pitch = p_outpic->p[i_plane].i_pitch;
+
+ p_in = p_pic->p[i_plane].p_pixels
+ + pi_top_skip[i_plane] + pi_left_skip[i_plane];
+
+ p_in_end = p_in + p_outpic->p[i_plane].i_lines
+ * p_pic->p[i_plane].i_pitch;
+
+ p_out = p_outpic->p[i_plane].p_pixels;
+
+ while( p_in < p_in_end )
+ {
+ p_vout->p_vlc->pf_memcpy( p_out, p_in, i_out_pitch );
+ p_in += i_in_pitch;
+ p_out += i_out_pitch;
+ }
+
+ pi_left_skip[i_plane] += i_out_pitch;
+ }
+
+ vout_UnlinkPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
+ p_outpic );
+ vout_DisplayPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
+ p_outpic );
+
+ i_vout++;
+ }
+
+ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+ {
+ pi_top_skip[i_plane] += p_vout->p_sys->pp_vout[ i_vout ].i_height
+ * p_pic->p[i_plane].i_lines
+ / p_vout->output.i_height
+ * p_pic->p[i_plane].i_pitch;
+ }
+ }
+}
+
+/*****************************************************************************
+ * RemoveAllVout: destroy all the child video output threads
+ *****************************************************************************/
+static void RemoveAllVout( vout_thread_t *p_vout )
+{
+ while( p_vout->p_sys->i_vout )
+ {
+ --p_vout->p_sys->i_vout;
+ if( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].b_active )
+ {
+ vout_DestroyThread(
+ p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout );
+ }
+ }
+}
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+aa_SOURCES = aa.c
--- /dev/null
+/*****************************************************************************
+ * vout_aa.c: Aa video output display method for testing purposes
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: aa.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <aalib.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/intf.h>
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Render ( vout_thread_t *, picture_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static void SetPalette ( vout_thread_t *, u16 *, u16 *, u16 * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("ASCII-art video output module") );
+ set_capability( "video output", 10 );
+ add_shortcut( "aalib" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: aa video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the aa specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ struct aa_context* aa_context;
+ aa_palette palette;
+ int i_width; /* width of main window */
+ int i_height; /* height of main window */
+};
+
+/*****************************************************************************
+ * Create: allocates aa video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a aa vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Don't parse any options, but take $AAOPTS into account */
+ aa_parseoptions( NULL, NULL, NULL, NULL );
+
+ if (!(p_vout->p_sys->aa_context = aa_autoinit(&aa_defparams)))
+ {
+ msg_Err( p_vout, "cannot initialize aalib" );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = Render;
+ p_vout->pf_display = Display;
+
+ p_vout->p_sys->i_width = aa_imgwidth(p_vout->p_sys->aa_context);
+ p_vout->p_sys->i_height = aa_imgheight(p_vout->p_sys->aa_context);
+ aa_autoinitkbd( p_vout->p_sys->aa_context, 0 );
+ aa_autoinitmouse( p_vout->p_sys->aa_context, AA_MOUSEPRESSMASK );
+ aa_hidemouse( p_vout->p_sys->aa_context );
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize aa video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic = NULL;
+
+ I_OUTPUTPICTURES = 0;
+
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
+ p_vout->output.i_width = p_vout->p_sys->i_width;
+ p_vout->output.i_height = p_vout->p_sys->i_height;
+ p_vout->output.i_aspect = p_vout->p_sys->i_width
+ * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
+ p_vout->output.pf_setpalette = SetPalette;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ if( p_pic == NULL )
+ {
+ return -1;
+ }
+
+ /* Allocate the picture */
+ p_pic->p->p_pixels = aa_image( p_vout->p_sys->aa_context );
+ p_pic->p->i_lines = p_vout->p_sys->i_height;
+ p_pic->p->i_pitch = p_vout->p_sys->i_width;
+ p_pic->p->i_pixel_pitch = 1;
+ p_pic->p->i_visible_pitch = p_vout->p_sys->i_width;
+ p_pic->i_planes = 1;
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+ I_OUTPUTPICTURES++;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * End: terminate aa video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ ;
+}
+
+/*****************************************************************************
+ * Destroy: destroy aa video thread output method
+ *****************************************************************************
+ * Terminate an output method created by AaCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ aa_close( p_vout->p_sys->aa_context );
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Manage: handle aa events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * console events. It returns a non null value on error.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ int event, x, y, b;
+ event = aa_getevent( p_vout->p_sys->aa_context, 0 );
+ switch ( event )
+ {
+ case AA_MOUSE:
+ aa_getmouse( p_vout->p_sys->aa_context, &x, &y, &b );
+ if ( b & AA_BUTTON3 )
+ {
+ intf_thread_t *p_intf;
+ p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF, FIND_ANYWHERE );
+ if( p_intf )
+ {
+ p_intf->b_menu_change = 1;
+ vlc_object_release( p_intf );
+ }
+ }
+ break;
+ case AA_RESIZE:
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ aa_resize( p_vout->p_sys->aa_context );
+ p_vout->p_sys->i_width = aa_imgwidth( p_vout->p_sys->aa_context );
+ p_vout->p_sys->i_height = aa_imgheight( p_vout->p_sys->aa_context );
+ break;
+ default:
+ break;
+ }
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Render: render previously calculated output
+ *****************************************************************************/
+static void Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ aa_fastrender( p_vout->p_sys->aa_context, 0, 0,
+ aa_imgwidth( p_vout->p_sys->aa_context ),
+ aa_imgheight( p_vout->p_sys->aa_context ) );
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* No need to do anything, the fake direct buffers stay as they are */
+ int i_width, i_height, i_x, i_y;
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+
+ aa_flush(p_vout->p_sys->aa_context);
+}
+
+/*****************************************************************************
+ * SetPalette: set the 8bpp palette
+ *****************************************************************************/
+static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
+{
+ int i;
+
+ /* Fill colors with color information */
+ for( i = 0; i < 256; i++ )
+ {
+ aa_setpalette( p_vout->p_sys->palette, 256 -i,
+ red[ i ], green[ i ], blue[ i ] );
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+directx_SOURCES = directx.c vout.c events.c aout.c
--- /dev/null
+/*****************************************************************************
+ * aout.c: Windows DirectX audio output method
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: aout.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <fcntl.h> /* open(), O_WRONLY */
+#include <string.h> /* strerror() */
+
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include <mmsystem.h>
+#include <dsound.h>
+
+/*****************************************************************************
+ * DirectSound GUIDs.
+ * Defining them here allows us to get rid of the dxguid library during
+ * the linking stage.
+ *****************************************************************************/
+#include <initguid.h>
+DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
+
+/*****************************************************************************
+ * notification_thread_t: DirectX event thread
+ *****************************************************************************/
+typedef struct notification_thread_t
+{
+ VLC_COMMON_MEMBERS
+
+ aout_thread_t * p_aout;
+ DSBPOSITIONNOTIFY p_events[2]; /* play notification events */
+
+} notification_thread_t;
+
+/*****************************************************************************
+ * aout_sys_t: directx audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes the direct sound specific properties of an audio device.
+ *****************************************************************************/
+
+struct aout_sys_t
+{
+ LPDIRECTSOUND p_dsobject; /* main Direct Sound object */
+
+ LPDIRECTSOUNDBUFFER p_dsbuffer_primary; /* the actual sound card buffer
+ (not used directly) */
+
+ LPDIRECTSOUNDBUFFER p_dsbuffer; /* the sound buffer we use (direct sound
+ * takes care of mixing all the
+ * secondary buffers into the primary) */
+
+ LPDIRECTSOUNDNOTIFY p_dsnotify; /* the position notify interface */
+
+ HINSTANCE hdsound_dll; /* handle of the opened dsound dll */
+
+ long l_buffer_size; /* secondary sound buffer size */
+ long l_write_position; /* next write position for the buffer */
+
+ volatile vlc_bool_t b_buffer_underflown; /* buffer underflow detection */
+ volatile long l_data_played_from_beginning; /* for underflow detection */
+ volatile long l_data_written_from_beginning; /* for underflow detection */
+
+ vlc_mutex_t buffer_lock; /* audio buffer lock */
+
+ notification_thread_t * p_notif; /* DirectSoundThread id */
+};
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/* local functions */
+static int DirectxCreateSecondaryBuffer ( aout_thread_t * );
+static void DirectxDestroySecondaryBuffer( aout_thread_t * );
+static int DirectxInitDSound ( aout_thread_t * );
+static void DirectSoundThread ( notification_thread_t * );
+
+/*****************************************************************************
+ * OpenAudio: open the audio device
+ *****************************************************************************
+ * This function opens and setups Direct Sound.
+ *****************************************************************************/
+int E_(OpenAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+ HRESULT dsresult;
+ DSBUFFERDESC dsbuffer_desc;
+
+ msg_Dbg( p_aout, "Open" );
+
+ /* Allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Initialize some variables */
+ p_aout->p_sys->p_dsobject = NULL;
+ p_aout->p_sys->p_dsbuffer_primary = NULL;
+ p_aout->p_sys->p_dsbuffer = NULL;
+ p_aout->p_sys->p_dsnotify = NULL;
+ p_aout->p_sys->l_data_written_from_beginning = 0;
+ p_aout->p_sys->l_data_played_from_beginning = 0;
+ vlc_mutex_init( p_aout, &p_aout->p_sys->buffer_lock );
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ /* Initialise DirectSound */
+ if( DirectxInitDSound( p_aout ) )
+ {
+ msg_Warn( p_aout, "cannot initialize DirectSound" );
+ return( 1 );
+ }
+
+ /* Obtain (not create) Direct Sound primary buffer */
+ memset( &dsbuffer_desc, 0, sizeof(DSBUFFERDESC) );
+ dsbuffer_desc.dwSize = sizeof(DSBUFFERDESC);
+ dsbuffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ msg_Warn( p_aout, "create direct sound primary buffer" );
+ dsresult = IDirectSound_CreateSoundBuffer(p_aout->p_sys->p_dsobject,
+ &dsbuffer_desc,
+ &p_aout->p_sys->p_dsbuffer_primary,
+ NULL);
+ if( dsresult != DS_OK )
+ {
+ msg_Warn( p_aout, "cannot create direct sound primary buffer" );
+ IDirectSound_Release( p_aout->p_sys->p_dsobject );
+ p_aout->p_sys->p_dsobject = NULL;
+ p_aout->p_sys->p_dsbuffer_primary = NULL;
+ return( 1 );
+ }
+
+
+ /* Now we need to setup DirectSound play notification */
+
+ /* first we need to create the notification events */
+ p_aout->p_sys->p_notif->p_events[0].hEventNotify =
+ CreateEvent( NULL, FALSE, FALSE, NULL );
+ p_aout->p_sys->p_notif->p_events[1].hEventNotify =
+ CreateEvent( NULL, FALSE, FALSE, NULL );
+
+ /* then launch the notification thread */
+ msg_Dbg( p_aout, "creating DirectSoundThread" );
+ p_aout->p_sys->p_notif =
+ vlc_object_create( p_aout, sizeof(notification_thread_t) );
+ p_aout->p_sys->p_notif->p_aout = p_aout;
+ if( vlc_thread_create( p_aout->p_sys->p_notif,
+ "DirectSound Notification Thread", DirectSoundThread, 1 ) )
+ {
+ msg_Err( p_aout, "cannot create DirectSoundThread" );
+ /* Let's go on anyway */
+ }
+
+ vlc_object_attach( p_aout->p_sys->p_notif, p_aout );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: reset the audio device and sets its format
+ *****************************************************************************
+ * This functions set a new audio format.
+ * For this we need to close the current secondary buffer and create another
+ * one with the desired format.
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ HRESULT dsresult;
+ WAVEFORMATEX *p_waveformat;
+ unsigned long i_size_struct;
+
+ msg_Dbg( p_aout, "SetFormat" );
+
+ /* Set the format of Direct Sound primary buffer */
+
+ /* first we need to know the current format */
+ dsresult = IDirectSoundBuffer_GetFormat( p_aout->p_sys->p_dsbuffer_primary,
+ NULL, 0, &i_size_struct );
+ if( dsresult == DS_OK )
+ {
+ p_waveformat = malloc( i_size_struct );
+ dsresult = IDirectSoundBuffer_GetFormat(
+ p_aout->p_sys->p_dsbuffer_primary,
+ p_waveformat, i_size_struct,
+ NULL );
+ }
+
+ if( dsresult == DS_OK )
+ {
+ /* Here we'll change the format */
+ p_waveformat->nChannels = 2;
+ p_waveformat->nSamplesPerSec = (p_aout->i_rate < 44100) ? 44100
+ : p_aout->i_rate;
+ p_waveformat->wBitsPerSample = 16;
+ p_waveformat->nBlockAlign = p_waveformat->wBitsPerSample / 8 *
+ p_waveformat->nChannels;
+ p_waveformat->nAvgBytesPerSec = p_waveformat->nSamplesPerSec *
+ p_waveformat->nBlockAlign;
+
+ dsresult = IDirectSoundBuffer_SetFormat(
+ p_aout->p_sys->p_dsbuffer_primary,
+ p_waveformat );
+ }
+ else msg_Warn( p_aout, "cannot get primary buffer format" );
+
+ if( dsresult != DS_OK )
+ msg_Warn( p_aout, "cannot set primary buffer format" );
+
+
+ /* Now we need to take care of Direct Sound secondary buffer */
+
+ vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
+
+ /* first release the current secondary buffer */
+ DirectxDestroySecondaryBuffer( p_aout );
+
+ /* then create a new secondary buffer */
+ if( DirectxCreateSecondaryBuffer( p_aout ) )
+ {
+ msg_Warn( p_aout, "cannot create buffer" );
+ vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
+ return( 1 );
+ }
+
+ vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************
+ * returns the number of bytes in the audio buffer that have not yet been
+ * sent to the sound device.
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ long l_play_position, l_notused, l_result;
+ HRESULT dsresult;
+
+ if( p_aout->p_sys->b_buffer_underflown )
+ {
+ msg_Warn( p_aout, "GetBufInfo underflow" );
+ return( i_buffer_limit );
+ }
+
+ dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
+ &l_play_position, &l_notused);
+ if( dsresult != DS_OK )
+ {
+ msg_Warn( p_aout, "GetBufInfo cannot get current pos" );
+ return( i_buffer_limit );
+ }
+
+ l_result = (p_aout->p_sys->l_write_position >= l_play_position) ?
+ (p_aout->p_sys->l_write_position - l_play_position)
+ : (p_aout->p_sys->l_buffer_size - l_play_position
+ + p_aout->p_sys->l_write_position);
+
+#if 0
+ msg_Dbg( p_aout, "GetBufInfo: %i", i_result);
+#endif
+ return l_result;
+}
+
+/*****************************************************************************
+ * Play: play a sound buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes
+ * Don't forget that DirectSound buffers are circular buffers.
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ VOID *p_write_position, *p_start_buffer;
+ long l_bytes1, l_bytes2, l_play_position;
+ HRESULT dsresult;
+
+ /* protect buffer access (because of DirectSoundThread) */
+ vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
+
+ if( p_aout->p_sys->b_buffer_underflown )
+ {
+ /* there has been an underflow so we need to play the new sample
+ * as soon as possible. This is why we query the play position */
+ dsresult = IDirectSoundBuffer_GetCurrentPosition(
+ p_aout->p_sys->p_dsbuffer,
+ &l_play_position,
+ &p_aout->p_sys->l_write_position );
+ if( dsresult != DS_OK )
+ {
+ msg_Warn( p_aout, "cannot get buffer position" );
+ p_aout->p_sys->l_write_position = 0;
+ }
+
+ msg_Warn( p_aout, "Play underflow" );
+ /* reinitialise the underflow detection counters */
+ p_aout->p_sys->b_buffer_underflown = 0;
+ p_aout->p_sys->l_data_written_from_beginning = 0;
+
+#define WRITE_P p_aout->p_sys->l_write_position
+#define PLAY_P l_play_position
+#define BUF_SIZE p_aout->p_sys->l_buffer_size
+ p_aout->p_sys->l_data_played_from_beginning = -(WRITE_P %(BUF_SIZE/2));
+ if( PLAY_P < BUF_SIZE/2 && WRITE_P > BUF_SIZE/2 )
+ {
+ p_aout->p_sys->l_data_played_from_beginning -= (BUF_SIZE/2);
+ }
+ if( PLAY_P > BUF_SIZE/2 && WRITE_P < BUF_SIZE/2 )
+ {
+ p_aout->p_sys->l_data_played_from_beginning -= (BUF_SIZE/2);
+ }
+#undef WRITE_P
+#undef PLAY_P
+#undef BUF_SIZE
+ }
+
+ /* Before copying anything, we have to lock the buffer */
+ dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
+ p_aout->p_sys->l_write_position, /* Offset of lock start */
+ i_size, /* Number of bytes to lock */
+ &p_write_position, /* Address of lock start */
+ &l_bytes1, /* Count of bytes locked before wrap around */
+ &p_start_buffer, /* Buffer adress (if wrap around) */
+ &l_bytes2, /* Count of bytes after wrap around */
+ 0); /* Flags */
+ if( dsresult == DSERR_BUFFERLOST )
+ {
+ IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
+ dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
+ p_aout->p_sys->l_write_position,
+ i_size,
+ &p_write_position,
+ &l_bytes1,
+ &p_start_buffer,
+ &l_bytes2,
+ 0);
+
+ }
+ if( dsresult != DS_OK )
+ {
+ msg_Warn( p_aout, "Play cannot lock buffer" );
+ vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
+ return;
+ }
+
+ /* Now do the actual memcpy (two memcpy because the buffer is circular) */
+ memcpy( p_write_position, buffer, l_bytes1 );
+ if( p_start_buffer != NULL )
+ {
+ memcpy( p_start_buffer, buffer + l_bytes1, l_bytes2 );
+ }
+
+ /* Now the data has been copied, unlock the buffer */
+ IDirectSoundBuffer_Unlock( p_aout->p_sys->p_dsbuffer,
+ p_write_position, l_bytes1, p_start_buffer, l_bytes2 );
+
+ /* Update the write position index of the buffer*/
+ p_aout->p_sys->l_write_position += i_size;
+ p_aout->p_sys->l_write_position %= p_aout->p_sys->l_buffer_size;
+ p_aout->p_sys->l_data_written_from_beginning += i_size;
+
+ vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
+
+ /* The play function has no effect if the buffer is already playing */
+ dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
+ 0, /* Unused */
+ 0, /* Unused */
+ DSBPLAY_LOOPING ); /* Flags */
+ if( dsresult == DSERR_BUFFERLOST )
+ {
+ IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
+ dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
+ 0, /* Unused */
+ 0, /* Unused */
+ DSBPLAY_LOOPING ); /* Flags */
+ }
+ if( dsresult != DS_OK )
+ {
+ msg_Warn( p_aout, "Play cannot play buffer" );
+ return;
+ }
+
+}
+
+/*****************************************************************************
+ * CloseAudio: close the audio device
+ *****************************************************************************/
+void E_(CloseAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+
+ msg_Dbg( p_aout, "Close" );
+
+ /* kill the position notification thread, if any */
+ vlc_object_detach_all( p_aout->p_sys->p_notif );
+ if( p_aout->p_sys->p_notif->b_thread )
+ {
+ p_aout->p_sys->p_notif->b_die = 1;
+ vlc_thread_join( p_aout->p_sys->p_notif );
+ }
+ vlc_object_destroy( p_aout->p_sys->p_notif );
+
+ /* release the secondary buffer */
+ DirectxDestroySecondaryBuffer( p_aout );
+
+ /* then release the primary buffer */
+ if( p_aout->p_sys->p_dsbuffer_primary != NULL )
+ {
+ IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer_primary );
+ p_aout->p_sys->p_dsbuffer_primary = NULL;
+ }
+
+ /* finally release the DirectSound object */
+ if( p_aout->p_sys->p_dsobject != NULL )
+ {
+ IDirectSound_Release( p_aout->p_sys->p_dsobject );
+ p_aout->p_sys->p_dsobject = NULL;
+ }
+
+ /* free DSOUND.DLL */
+ if( p_aout->p_sys->hdsound_dll != NULL )
+ {
+ FreeLibrary( p_aout->p_sys->hdsound_dll );
+ p_aout->p_sys->hdsound_dll = NULL;
+ }
+
+ /* Close the Output. */
+ if ( p_aout->p_sys != NULL )
+ {
+ free( p_aout->p_sys );
+ p_aout->p_sys = NULL;
+ }
+}
+
+/*****************************************************************************
+ * DirectxInitDSound
+ *****************************************************************************
+ *****************************************************************************/
+static int DirectxInitDSound( aout_thread_t *p_aout )
+{
+ HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
+
+ p_aout->p_sys->hdsound_dll = LoadLibrary("DSOUND.DLL");
+ if( p_aout->p_sys->hdsound_dll == NULL )
+ {
+ msg_Warn( p_aout, "cannot open DSOUND.DLL" );
+ return( 1 );
+ }
+
+ OurDirectSoundCreate = (void *)GetProcAddress( p_aout->p_sys->hdsound_dll,
+ "DirectSoundCreate" );
+
+ if( OurDirectSoundCreate == NULL )
+ {
+ msg_Warn( p_aout, "GetProcAddress FAILED" );
+ FreeLibrary( p_aout->p_sys->hdsound_dll );
+ p_aout->p_sys->hdsound_dll = NULL;
+ return( 1 );
+ }
+
+ /* Create the direct sound object */
+ if( OurDirectSoundCreate(NULL, &p_aout->p_sys->p_dsobject, NULL) != DS_OK )
+ {
+ msg_Warn( p_aout, "cannot create a direct sound device" );
+ p_aout->p_sys->p_dsobject = NULL;
+ FreeLibrary( p_aout->p_sys->hdsound_dll );
+ p_aout->p_sys->hdsound_dll = NULL;
+ return( 1 );
+ }
+
+ /* Set DirectSound Cooperative level, ie what control we want over Windows
+ * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
+ * settings of the primary buffer, but also that only the sound of our
+ * application will be hearable when it will have the focus.
+ * !!! (this is not really working as intended yet because to set the
+ * cooperative level you need the window handle of your application, and
+ * I don't know of any easy way to get it. Especially since we might play
+ * sound without any video, and so what window handle should we use ???
+ * The hack for now is to use the Desktop window handle - it seems to be
+ * working */
+ if( IDirectSound_SetCooperativeLevel(p_aout->p_sys->p_dsobject,
+ GetDesktopWindow(),
+ DSSCL_EXCLUSIVE) )
+ {
+ msg_Warn( p_aout, "cannot set direct sound cooperative level" );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * DirectxCreateSecondaryBuffer
+ *****************************************************************************
+ * This function creates the buffer we'll use to play audio.
+ * In DirectSound there are two kinds of buffers:
+ * - the primary buffer: which is the actual buffer that the soundcard plays
+ * - the secondary buffer(s): these buffers are the one actually used by
+ * applications and DirectSound takes care of mixing them into the primary.
+ *
+ * Once you create a secondary buffer, you cannot change its format anymore so
+ * you have to release the current and create another one.
+ *****************************************************************************/
+static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
+{
+ WAVEFORMATEX waveformat;
+ DSBUFFERDESC dsbdesc;
+ DSBCAPS dsbcaps;
+
+ /* First set the buffer format */
+ memset(&waveformat, 0, sizeof(WAVEFORMATEX));
+ waveformat.wFormatTag = WAVE_FORMAT_PCM;
+ waveformat.nChannels = p_aout->i_channels;
+ waveformat.nSamplesPerSec = p_aout->i_rate;
+ waveformat.wBitsPerSample = 16;
+ waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
+ waveformat.nChannels;
+ waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
+ waveformat.nBlockAlign;
+
+ /* Then fill in the descriptor */
+ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
+ | DSBCAPS_CTRLPOSITIONNOTIFY /* We need notification */
+ | DSBCAPS_GLOBALFOCUS; /* Allows background playing */
+ dsbdesc.dwBufferBytes = waveformat.nAvgBytesPerSec * 2; /* 2 sec buffer */
+ dsbdesc.lpwfxFormat = &waveformat;
+
+ if( IDirectSound_CreateSoundBuffer( p_aout->p_sys->p_dsobject,
+ &dsbdesc,
+ &p_aout->p_sys->p_dsbuffer,
+ NULL) != DS_OK )
+ {
+ msg_Warn( p_aout, "cannot create direct sound secondary buffer" );
+ p_aout->p_sys->p_dsbuffer = NULL;
+ return( 1 );
+ }
+
+ /* backup the size of the secondary sound buffer */
+ memset(&dsbcaps, 0, sizeof(DSBCAPS));
+ dsbcaps.dwSize = sizeof(DSBCAPS);
+ IDirectSoundBuffer_GetCaps( p_aout->p_sys->p_dsbuffer, &dsbcaps );
+ p_aout->p_sys->l_buffer_size = dsbcaps.dwBufferBytes;
+ p_aout->p_sys->l_write_position = 0;
+
+ msg_Dbg( p_aout, "DirectxCreateSecondaryBuffer: %li",
+ p_aout->p_sys->l_buffer_size );
+
+ /* Now the secondary buffer is created, we need to setup its position
+ * notification */
+ p_aout->p_sys->p_notif->p_events[0].dwOffset = 0; /* notif position */
+ p_aout->p_sys->p_notif->p_events[1].dwOffset = dsbcaps.dwBufferBytes / 2;
+
+ /* Get the IDirectSoundNotify interface */
+ if FAILED( IDirectSoundBuffer_QueryInterface( p_aout->p_sys->p_dsbuffer,
+ &IID_IDirectSoundNotify,
+ (LPVOID *)&p_aout->p_sys->p_dsnotify ) )
+ {
+ msg_Warn( p_aout, "cannot get Notify interface" );
+ /* Go on anyway */
+ p_aout->p_sys->p_dsnotify = NULL;
+ return( 0 );
+ }
+
+ if FAILED( IDirectSoundNotify_SetNotificationPositions(
+ p_aout->p_sys->p_dsnotify,
+ 2,
+ p_aout->p_sys->p_notif->p_events ) )
+ {
+ msg_Warn( p_aout, "cannot set position Notification" );
+ /* Go on anyway */
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * DirectxCreateSecondaryBuffer
+ *****************************************************************************
+ * This function destroy the secondary buffer.
+ *****************************************************************************/
+static void DirectxDestroySecondaryBuffer( aout_thread_t *p_aout )
+{
+ /* make sure the buffer isn't playing */
+ if( p_aout->p_sys->p_dsbuffer != NULL )
+ {
+ IDirectSoundBuffer_Stop( p_aout->p_sys->p_dsbuffer );
+ }
+
+ if( p_aout->p_sys->p_dsnotify != NULL )
+ {
+ IDirectSoundNotify_Release( p_aout->p_sys->p_dsnotify );
+ p_aout->p_sys->p_dsnotify = NULL;
+ }
+
+ if( p_aout->p_sys->p_dsbuffer != NULL )
+ {
+ IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
+ p_aout->p_sys->p_dsbuffer = NULL;
+ }
+}
+
+/*****************************************************************************
+ * DirectSoundThread: this thread will capture play notification events.
+ *****************************************************************************
+ * As Direct Sound uses circular buffers, we need to use event notification to
+ * manage them.
+ * Using event notification implies blocking the thread until the event is
+ * signaled so we really need to run this in a separate thread.
+ *****************************************************************************/
+static void DirectSoundThread( notification_thread_t *p_notif )
+{
+ HANDLE notification_events[2];
+ VOID *p_write_position, *p_start_buffer;
+ long l_bytes1, l_bytes2;
+ HRESULT dsresult;
+ long l_buffer_size, l_play_position, l_data_in_buffer;
+
+ aout_thread_t *p_aout = p_notif->p_aout;
+
+#define P_EVENTS p_aout->p_sys->p_notif->p_events
+ notification_events[0] = P_EVENTS[0].hEventNotify;
+ notification_events[1] = P_EVENTS[1].hEventNotify;
+
+ /* Tell the main thread that we are ready */
+ vlc_thread_ready( p_notif );
+
+ /* this thread must be high-priority */
+ if( !SetThreadPriority( GetCurrentThread(),
+ THREAD_PRIORITY_ABOVE_NORMAL ) )
+ {
+ msg_Warn( p_notif, "DirectSoundThread could not renice itself" );
+ }
+
+ msg_Dbg( p_notif, "DirectSoundThread ready" );
+
+ while( !p_notif->b_die )
+ {
+ /* wait for the position notification */
+ l_play_position = WaitForMultipleObjects( 2, notification_events,
+ 0, INFINITE );
+ vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
+
+ if( p_notif->b_die )
+ {
+ break;
+ }
+
+ /* check for buffer underflow (bodge for wrap around) */
+ l_buffer_size = p_aout->p_sys->l_buffer_size;
+ l_play_position = (l_play_position - WAIT_OBJECT_0) * l_buffer_size/2;
+ p_aout->p_sys->l_data_played_from_beginning += (l_buffer_size/2);
+ l_data_in_buffer = p_aout->p_sys->l_data_written_from_beginning -
+ p_aout->p_sys->l_data_played_from_beginning;
+
+ /* detect wrap-around */
+ if( l_data_in_buffer < (-l_buffer_size/2) )
+ {
+ msg_Dbg( p_notif, "DirectSoundThread wrap around: %li",
+ l_data_in_buffer );
+ l_data_in_buffer += l_buffer_size;
+ }
+
+ /* detect underflow */
+ if( l_data_in_buffer <= 0 )
+ {
+ msg_Warn( p_notif,
+ "DirectSoundThread underflow: %li", l_data_in_buffer );
+ p_aout->p_sys->b_buffer_underflown = 1;
+ p_aout->p_sys->l_write_position =
+ (l_play_position + l_buffer_size/2) % l_buffer_size;
+ l_data_in_buffer = l_buffer_size / 2;
+ p_aout->p_sys->l_data_played_from_beginning -= (l_buffer_size/2);
+ }
+
+
+ /* Clear the data which has already been played */
+
+ /* Before copying anything, we have to lock the buffer */
+ dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
+ p_aout->p_sys->l_write_position, /* Offset of lock start */
+ l_buffer_size - l_data_in_buffer, /* Number of bytes */
+ &p_write_position, /* Address of lock start */
+ &l_bytes1, /* Count of bytes locked before wrap around */
+ &p_start_buffer, /* Buffer adress (if wrap around) */
+ &l_bytes2, /* Count of bytes after wrap around */
+ 0); /* Flags */
+ if( dsresult == DSERR_BUFFERLOST )
+ {
+ IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
+ dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
+ p_aout->p_sys->l_write_position,
+ l_buffer_size - l_data_in_buffer,
+ &p_write_position,
+ &l_bytes1,
+ &p_start_buffer,
+ &l_bytes2,
+ 0);
+ }
+ if( dsresult != DS_OK )
+ {
+ msg_Warn( p_notif, "Play cannot lock buffer" );
+ vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
+ return;
+ }
+
+ /* Now do the actual memcpy (two because the buffer is circular) */
+ memset( p_write_position, 0, l_bytes1 );
+ if( p_start_buffer != NULL )
+ {
+ memset( p_start_buffer, 0, l_bytes2 );
+ }
+
+ /* Now the data has been copied, unlock the buffer */
+ IDirectSoundBuffer_Unlock( p_aout->p_sys->p_dsbuffer,
+ p_write_position, l_bytes1, p_start_buffer, l_bytes2 );
+
+ vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
+
+ }
+
+ /* free the events */
+ CloseHandle( notification_events[0] );
+ CloseHandle( notification_events[1] );
+
+ msg_Dbg( p_notif, "DirectSoundThread exiting" );
+
+}
--- /dev/null
+/*****************************************************************************
+ * directx.c : Windows DirectX plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: directx.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t * );
+void E_(CloseVideo) ( vlc_object_t * );
+
+int E_(OpenAudio) ( vlc_object_t * );
+void E_(CloseAudio) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define HW_YUV_TEXT N_("use hardware YUV->RGB conversions")
+#define HW_YUV_LONGTEXT N_( \
+ "Try to use hardware acceleration for YUV->RGB conversions. " \
+ "This option doesn't have any effect when using overlays." )
+#define SYSMEM_TEXT N_("use video buffers in system memory")
+#define SYSMEM_LONGTEXT N_( \
+ "Create video buffers in system memory instead of video memory. This " \
+ "isn't recommended as usually using video memory allows to benefit from " \
+ "more hardware acceleration (like rescaling or YUV->RGB conversions). " \
+ "This option doesn't have any effect when using overlays." )
+
+vlc_module_begin();
+ add_category_hint( N_("Video"), NULL );
+ add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT );
+ add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT );
+ set_description( _("DirectX extension module") );
+ add_submodule();
+ set_capability( "video output", 150 );
+ set_callbacks( E_(OpenVideo), E_(CloseVideo) );
+ add_submodule();
+ set_capability( "audio output", 150 );
+ set_callbacks( E_(OpenAudio), E_(CloseAudio) );
+vlc_module_end();
+
+#if 0 /* FIXME */
+ /* check if we registered a window class because we need to
+ * unregister it */
+ WNDCLASS wndclass;
+ if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
+ UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * events.c: Windows DirectX video output events handler
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: events.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * Preamble: This file contains the functions related to the creation of
+ * a window and the handling of its messages (events).
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include "netutils.h"
+
+#include <windows.h>
+#include <windowsx.h>
+#include <shellapi.h>
+
+#include <ddraw.h>
+
+#include "vout.h"
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int DirectXCreateWindow( vout_thread_t *p_vout );
+static void DirectXCloseWindow ( vout_thread_t *p_vout );
+static void DirectXUpdateRects( vout_thread_t *p_vout );
+static long FAR PASCAL DirectXEventProc ( HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam );
+
+/*****************************************************************************
+ * DirectXEventThread: Create video window & handle its messages
+ *****************************************************************************
+ * This function creates a video window and then enters an infinite loop
+ * that handles the messages sent to that window.
+ * The main goal of this thread is to isolate the Win32 PeekMessage function
+ * because this one can block for a long time.
+ *****************************************************************************/
+void DirectXEventThread( event_thread_t *p_event )
+{
+ MSG msg;
+ POINT old_mouse_pos;
+
+ /* Initialisation */
+
+ /* Create a window for the video */
+ /* Creating a window under Windows also initializes the thread's event
+ * message qeue */
+ if( DirectXCreateWindow( p_event->p_vout ) )
+ {
+ msg_Err( p_event, "out of memory" );
+ p_event->b_dead = 1;
+ }
+
+ /* signal the creation of the window */
+ vlc_thread_ready( p_event );
+
+ /* Main loop */
+ /* GetMessage will sleep if there's no message in the queue */
+ while( !p_event->b_die
+ && GetMessage( &msg, p_event->p_vout->p_sys->hwnd, 0, 0 ) )
+ {
+ /* Check if we are asked to exit */
+ if( p_event->b_die )
+ break;
+
+ switch( msg.message )
+ {
+
+ case WM_NCMOUSEMOVE:
+ case WM_MOUSEMOVE:
+ if( (abs(GET_X_LPARAM(msg.lParam) - old_mouse_pos.x) > 2 ||
+ (abs(GET_Y_LPARAM(msg.lParam) - old_mouse_pos.y)) > 2 ) )
+ {
+ GetCursorPos( &old_mouse_pos );
+ p_event->p_vout->p_sys->i_lastmoved = mdate();
+
+ if( p_event->p_vout->p_sys->b_cursor_hidden )
+ {
+ p_event->p_vout->p_sys->b_cursor_hidden = 0;
+ ShowCursor( TRUE );
+ }
+ }
+ break;
+
+ case WM_VLC_HIDE_MOUSE:
+ GetCursorPos( &old_mouse_pos );
+ ShowCursor( FALSE );
+ break;
+
+ case WM_RBUTTONUP:
+ {
+ intf_thread_t *p_intf;
+ p_intf = vlc_object_find( p_event, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+ if( p_intf )
+ {
+ p_intf->b_menu_change = 1;
+ vlc_object_release( p_intf );
+ }
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ p_event->p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ break;
+
+ case WM_KEYDOWN:
+ /* the key events are first processed here. The next
+ * message processed by this main message loop will be the
+ * char translation of the key event */
+ msg_Dbg( p_event, "WM_KEYDOWN" );
+ switch( msg.wParam )
+ {
+ case VK_ESCAPE:
+ /* exit application */
+ p_event->p_vlc->b_die = 1;
+ break;
+
+ case VK_F1: network_ChannelJoin( p_event, 1 ); break;
+ case VK_F2: network_ChannelJoin( p_event, 2 ); break;
+ case VK_F3: network_ChannelJoin( p_event, 3 ); break;
+ case VK_F4: network_ChannelJoin( p_event, 4 ); break;
+ case VK_F5: network_ChannelJoin( p_event, 5 ); break;
+ case VK_F6: network_ChannelJoin( p_event, 6 ); break;
+ case VK_F7: network_ChannelJoin( p_event, 7 ); break;
+ case VK_F8: network_ChannelJoin( p_event, 8 ); break;
+ case VK_F9: network_ChannelJoin( p_event, 9 ); break;
+ case VK_F10: network_ChannelJoin( p_event, 10 ); break;
+ case VK_F11: network_ChannelJoin( p_event, 11 ); break;
+ case VK_F12: network_ChannelJoin( p_event, 12 ); break;
+ }
+ TranslateMessage(&msg);
+ break;
+
+ case WM_CHAR:
+ switch( msg.wParam )
+ {
+ case 'q':
+ case 'Q':
+ /* exit application */
+ p_event->p_vlc->b_die = 1;
+ break;
+
+ case 'f': /* switch to fullscreen */
+ case 'F':
+ p_event->p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ break;
+
+ case 'c': /* toggle grayscale */
+ case 'C':
+ p_event->p_vout->b_grayscale = ! p_event->p_vout->b_grayscale;
+ p_event->p_vout->p_sys->i_changes |= VOUT_GRAYSCALE_CHANGE;
+ break;
+
+ case 'i': /* toggle info */
+ case 'I':
+ p_event->p_vout->b_info = ! p_event->p_vout->b_info;
+ p_event->p_vout->p_sys->i_changes |= VOUT_INFO_CHANGE;
+ break;
+
+ case 's': /* toggle scaling */
+ case 'S':
+ p_event->p_vout->b_scale = ! p_event->p_vout->b_scale;
+ p_event->p_vout->p_sys->i_changes |= VOUT_SCALE_CHANGE;
+ break;
+
+ case ' ': /* toggle interface */
+ p_event->p_vout->b_interface = ! p_event->p_vout->b_interface;
+ p_event->p_vout->p_sys->i_changes |= VOUT_INTF_CHANGE;
+ break;
+
+ default:
+ break;
+ }
+
+ default:
+ /* Messages we don't handle directly are dispatched to the
+ * window procedure */
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ break;
+
+ } /* End Switch */
+
+ } /* End Main loop */
+
+ if( msg.message == WM_QUIT )
+ {
+ msg_Warn( p_event, "WM_QUIT... should not happen!!" );
+ p_event->p_vout->p_sys->hwnd = NULL; /* Window already destroyed */
+ }
+
+ msg_Dbg( p_event, "DirectXEventThread Terminating" );
+
+ /* clear the changes formerly signaled */
+ p_event->p_vout->p_sys->i_changes = 0;
+
+ DirectXCloseWindow( p_event->p_vout );
+}
+
+
+/* following functions are local */
+
+/*****************************************************************************
+ * DirectXCreateWindow: create a window for the video.
+ *****************************************************************************
+ * Before creating a direct draw surface, we need to create a window in which
+ * the video will be displayed. This window will also allow us to capture the
+ * events.
+ *****************************************************************************/
+static int DirectXCreateWindow( vout_thread_t *p_vout )
+{
+ HINSTANCE hInstance;
+ WNDCLASSEX wc; /* window class components */
+ RECT rect_window;
+ COLORREF colorkey;
+ HDC hdc;
+ HICON vlc_icon = NULL;
+ char vlc_path[_MAX_PATH+1];
+
+ msg_Dbg( p_vout, "DirectXCreateWindow" );
+
+ /* get this module's instance */
+ hInstance = GetModuleHandle(NULL);
+
+ /* Create a BRUSH that will be used by Windows to paint the window
+ * background.
+ * This window background is important for us as it will be used by the
+ * graphics card to display the overlay.
+ * This is why we carefully choose the color for this background, the goal
+ * being to choose a color which isn't complete black but nearly. We
+ * obviously don't want to use black as a colorkey for the overlay because
+ * black is one of the most used color and thus would give us undesirable
+ * effects */
+ /* the first step is to find the colorkey we want to use. The difficulty
+ * comes from the potential dithering (depends on the display depth)
+ * because we need to know the real RGB value of the chosen colorkey */
+ hdc = GetDC( NULL );
+ for( colorkey = 5; colorkey < 0xFF /*all shades of red*/; colorkey++ )
+ {
+ if( colorkey == GetNearestColor( hdc, colorkey ) )
+ break;
+ }
+ msg_Dbg( p_vout, "background color: %i", colorkey );
+
+ /* create the actual brush */
+ p_vout->p_sys->hbrush = CreateSolidBrush(colorkey);
+ p_vout->p_sys->i_rgb_colorkey = (int)colorkey;
+
+ /* Get the current size of the display and its colour depth */
+ p_vout->p_sys->rect_display.right = GetDeviceCaps( hdc, HORZRES );
+ p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES );
+ p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL );
+ msg_Dbg( p_vout, "screen dimensions %ix%i colour depth %i",
+ p_vout->p_sys->rect_display.right,
+ p_vout->p_sys->rect_display.bottom,
+ p_vout->p_sys->i_display_depth );
+
+ ReleaseDC( NULL, hdc );
+
+ /* Get the Icon from the main app */
+ vlc_icon = NULL;
+ if( GetModuleFileName( NULL, vlc_path, _MAX_PATH ) )
+ {
+ vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
+ }
+
+
+ /* fill in the window class structure */
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.style = CS_DBLCLKS; /* style: dbl click */
+ wc.lpfnWndProc = (WNDPROC)DirectXEventProc; /* event handler */
+ wc.cbClsExtra = 0; /* no extra class data */
+ wc.cbWndExtra = 0; /* no extra window data */
+ wc.hInstance = hInstance; /* instance */
+ wc.hIcon = vlc_icon; /* load the vlc icon */
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* load a default cursor */
+ wc.hbrBackground = p_vout->p_sys->hbrush; /* background color */
+ wc.lpszMenuName = NULL; /* no menu */
+ wc.lpszClassName = "VLC DirectX"; /* use a special class */
+ wc.hIconSm = vlc_icon; /* load the vlc icon */
+
+ /* register the window class */
+ if (!RegisterClassEx(&wc))
+ {
+ WNDCLASS wndclass;
+
+ /* free window background brush */
+ if( p_vout->p_sys->hbrush )
+ {
+ DeleteObject( p_vout->p_sys->hbrush );
+ p_vout->p_sys->hbrush = NULL;
+ }
+
+ if( vlc_icon )
+ DestroyIcon( vlc_icon );
+
+ /* Check why it failed. If it's because one already exists then fine */
+ if( !GetClassInfo( hInstance, "VLC DirectX", &wndclass ) )
+ {
+ msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED" );
+ return (1);
+ }
+ }
+
+ /* when you create a window you give the dimensions you wish it to have.
+ * Unfortunatly these dimensions will include the borders and title bar.
+ * We use the following function to find out the size of the window
+ * corresponding to the useable surface we want */
+ rect_window.top = 10;
+ rect_window.left = 10;
+ rect_window.right = rect_window.left + p_vout->p_sys->i_window_width;
+ rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height;
+ AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );
+
+ /* create the window */
+ p_vout->p_sys->hwnd = CreateWindow("VLC DirectX",/* name of window class */
+ VOUT_TITLE " (DirectX Output)", /* window title bar text */
+ WS_OVERLAPPEDWINDOW
+ | WS_SIZEBOX, /* window style */
+ CW_USEDEFAULT, /* default X coordinate */
+ 0, /* default Y coordinate */
+ rect_window.right - rect_window.left, /* window width */
+ rect_window.bottom - rect_window.top, /* window height */
+ NULL, /* no parent window */
+ NULL, /* no menu in this window */
+ hInstance, /* handle of this program instance */
+ NULL); /* no additional arguments */
+
+ if (p_vout->p_sys->hwnd == NULL) {
+ msg_Warn( p_vout, "DirectXCreateWindow create window FAILED" );
+ return (1);
+ }
+
+ /* store a p_vout pointer into the window local storage (for later use
+ * in DirectXEventProc).
+ * We need to use SetWindowLongPtr when it is available in mingw */
+ SetWindowLong( p_vout->p_sys->hwnd, GWL_USERDATA, (LONG)p_vout );
+
+ /* now display the window */
+ ShowWindow(p_vout->p_sys->hwnd, SW_SHOW);
+
+ return ( 0 );
+}
+
+/*****************************************************************************
+ * DirectXCloseWindow: close the window created by DirectXCreateWindow
+ *****************************************************************************
+ * This function returns all resources allocated by DirectXCreateWindow.
+ *****************************************************************************/
+static void DirectXCloseWindow( vout_thread_t *p_vout )
+{
+ msg_Dbg( p_vout, "DirectXCloseWindow" );
+
+ if( p_vout->p_sys->hwnd != NULL )
+ {
+ DestroyWindow( p_vout->p_sys->hwnd );
+ p_vout->p_sys->hwnd = NULL;
+ }
+
+ /* We don't unregister the Window Class because it could lead to race
+ * conditions and it will be done anyway by the system when the app will
+ * exit */
+}
+
+/*****************************************************************************
+ * DirectXUpdateRects:
+ *****************************************************************************
+ * This function is called when the window position and size is changed, and
+ * its job is to update the source and destination RECTs used to display the
+ * picture.
+ *****************************************************************************/
+static void DirectXUpdateRects( vout_thread_t *p_vout )
+{
+ int i_width, i_height, i_x, i_y;
+
+#define rect_src p_vout->p_sys->rect_src
+#define rect_src_clipped p_vout->p_sys->rect_src_clipped
+#define rect_dest p_vout->p_sys->rect_dest
+#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
+#define rect_display p_vout->p_sys->rect_display
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
+ p_vout->p_sys->i_window_height,
+ &i_x, &i_y, &i_width, &i_height );
+
+ /* Destination image position and dimensions */
+ rect_dest.left = i_x + p_vout->p_sys->i_window_x;
+ rect_dest.top = i_y + p_vout->p_sys->i_window_y;
+ rect_dest.right = rect_dest.left + i_width;
+ rect_dest.bottom = rect_dest.top + i_height;
+
+
+ /* UpdateOverlay directdraw function doesn't automatically clip to the
+ * display size so we need to do it otherwise it will fails */
+
+ /* Clip the destination window */
+ IntersectRect( &rect_dest_clipped, &rect_dest, &rect_display );
+
+#if 0
+ msg_Dbg( p_vout, "DirectXUpdateRects image_dst_clipped coords:"
+ " %i,%i,%i,%i",
+ rect_dest_clipped.left, rect_dest_clipped.top,
+ rect_dest_clipped.right, rect_dest_clipped.bottom );
+#endif
+
+ /* the 2 following lines are to fix a bug when clicking on the desktop */
+ if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
+ (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
+ {
+ SetRectEmpty( &rect_src_clipped );
+ return;
+ }
+
+ /* src image dimensions */
+ rect_src.left = 0;
+ rect_src.top = 0;
+ rect_src.right = p_vout->render.i_width;
+ rect_src.bottom = p_vout->render.i_height;
+
+ /* Clip the source image */
+ rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) *
+ p_vout->render.i_width / (rect_dest.right - rect_dest.left);
+ rect_src_clipped.right = p_vout->render.i_width -
+ (rect_dest.right - rect_dest_clipped.right) * p_vout->render.i_width /
+ (rect_dest.right - rect_dest.left);
+ rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) *
+ p_vout->render.i_height / (rect_dest.bottom - rect_dest.top);
+ rect_src_clipped.bottom = p_vout->render.i_height -
+ (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->render.i_height /
+ (rect_dest.bottom - rect_dest.top);
+
+#if 0
+ msg_Dbg( p_vout, "DirectXUpdateRects image_src_clipped"
+ " coords: %i,%i,%i,%i",
+ rect_src_clipped.left, rect_src_clipped.top,
+ rect_src_clipped.right, rect_src_clipped.bottom );
+#endif
+
+#undef rect_src
+#undef rect_src_clipped
+#undef rect_dest
+#undef rect_dest_clipped
+#undef rect_display
+}
+
+/*****************************************************************************
+ * DirectXEventProc: This is the window event processing function.
+ *****************************************************************************
+ * On Windows, when you create a window you have to attach an event processing
+ * function to it. The aim of this function is to manage "Queued Messages" and
+ * "Nonqueued Messages".
+ * Queued Messages are those picked up and retransmitted by vout_Manage
+ * (using the GetMessage and DispatchMessage functions).
+ * Nonqueued Messages are those that Windows will send directly to this
+ * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
+ *****************************************************************************/
+static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam )
+{
+ vout_thread_t *p_vout =
+ (vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA );
+
+ switch( message )
+ {
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ RECT rect_window;
+ POINT point_window;
+
+ /* update the window position */
+ point_window.x = 0;
+ point_window.y = 0;
+ ClientToScreen( hwnd, &point_window );
+ p_vout->p_sys->i_window_x = point_window.x;
+ p_vout->p_sys->i_window_y = point_window.y;
+
+ /* update the window size */
+ GetClientRect( hwnd, &rect_window );
+ p_vout->p_sys->i_window_width = rect_window.right;
+ p_vout->p_sys->i_window_height = rect_window.bottom;
+
+ DirectXUpdateRects( p_vout );
+ if( p_vout->p_sys->b_using_overlay &&
+ !p_vout->p_sys->p_event->b_die )
+ DirectXUpdateOverlay( p_vout );
+
+ /* signal the size change */
+ if( !p_vout->p_sys->b_using_overlay &&
+ !p_vout->p_sys->p_event->b_die )
+ p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;
+
+ return 0;
+ }
+ break;
+
+ /* the user wants to close the window */
+ case WM_CLOSE:
+ msg_Dbg( p_vout, "WinProc WM_CLOSE" );
+ /* exit application */
+ p_vout->p_vlc->b_die = 1;
+ return 0;
+ break;
+
+ /* the window has been closed so shut down everything now */
+ case WM_DESTROY:
+ msg_Dbg( p_vout, "WinProc WM_DESTROY" );
+ /* just destroy the window */
+ PostQuitMessage( 0 );
+ return 0;
+ break;
+
+ case WM_SYSCOMMAND:
+ switch (wParam)
+ {
+ case SC_SCREENSAVE: /* catch the screensaver */
+ case SC_MONITORPOWER: /* catch the monitor turn-off */
+ msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND" );
+ return 0; /* this stops them from happening */
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ if( !p_vout->p_sys->b_using_overlay )
+ {
+ /* We want to eliminate unnecessary background redraws which create
+ * an annoying flickering */
+ int i_width, i_height, i_x, i_y;
+ RECT rect_temp;
+ GetClipBox( (HDC)wParam, &rect_temp );
+#if 0
+ msg_Dbg( p_vout, "WinProc WM_ERASEBKGND %i,%i,%i,%i",
+ rect_temp.left, rect_temp.top,
+ rect_temp.right, rect_temp.bottom );
+#endif
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
+ p_vout->p_sys->i_window_height,
+ &i_x, &i_y, &i_width, &i_height );
+ ExcludeClipRect( (HDC)wParam, i_x, i_y,
+ i_x + i_width, i_y + i_height );
+ }
+ break;
+
+ default:
+ //msg_Dbg( p_vout, "WinProc WM Default %i", message );
+ break;
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
--- /dev/null
+/*****************************************************************************
+ * vout.c: Windows DirectX video output display method
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: vout.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble:
+ *
+ * This plugin will use YUV overlay if supported, using overlay will result in
+ * the best video quality (hardware interpolation when rescaling the picture)
+ * and the fastest display as it requires less processing.
+ *
+ * If YUV overlay is not supported this plugin will use RGB offscreen video
+ * surfaces that will be blitted onto the primary surface (display) to
+ * effectively display the pictures. This fallback method also enables us to
+ * display video in window mode.
+ *
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include <ddraw.h>
+
+#include "netutils.h"
+
+#include "vout.h"
+
+/*****************************************************************************
+ * DirectDraw GUIDs.
+ * Defining them here allows us to get rid of the dxguid library during
+ * the linking stage.
+ *****************************************************************************/
+#include <initguid.h>
+DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t * );
+void E_(CloseVideo) ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static int NewPictureVec ( vout_thread_t *, picture_t *, int );
+static void FreePictureVec ( vout_thread_t *, picture_t *, int );
+static int UpdatePictureStruct( vout_thread_t *, picture_t *, int );
+
+static int DirectXInitDDraw ( vout_thread_t *p_vout );
+static void DirectXCloseDDraw ( vout_thread_t *p_vout );
+static int DirectXCreateDisplay ( vout_thread_t *p_vout );
+static void DirectXCloseDisplay ( vout_thread_t *p_vout );
+static int DirectXCreateSurface ( vout_thread_t *p_vout,
+ LPDIRECTDRAWSURFACE2 *, int, int, int );
+static void DirectXCloseSurface ( vout_thread_t *p_vout,
+ LPDIRECTDRAWSURFACE2 );
+static int DirectXCreateClipper ( vout_thread_t *p_vout );
+static void DirectXGetDDrawCaps ( vout_thread_t *p_vout );
+static int DirectXGetSurfaceDesc ( picture_t *p_pic );
+
+/*****************************************************************************
+ * OpenVideo: allocate DirectX video thread output method
+ *****************************************************************************
+ * This function allocates and initialize the DirectX vout method.
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return 1;
+ }
+
+ /* Initialisations */
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = Display;
+
+ p_vout->p_sys->p_ddobject = NULL;
+ p_vout->p_sys->p_display = NULL;
+ p_vout->p_sys->p_current_surface = NULL;
+ p_vout->p_sys->p_clipper = NULL;
+ p_vout->p_sys->hbrush = NULL;
+ p_vout->p_sys->hwnd = NULL;
+ p_vout->p_sys->i_changes = 0;
+ p_vout->p_sys->b_caps_overlay_clipping = 0;
+ SetRectEmpty( &p_vout->p_sys->rect_display );
+ p_vout->p_sys->b_using_overlay = config_GetInt( p_vout, "overlay" );
+ p_vout->p_sys->b_use_sysmem = config_GetInt( p_vout, "directx-use-sysmem");
+ p_vout->p_sys->b_hw_yuv = config_GetInt( p_vout, "directx-hw-yuv" );
+
+ p_vout->p_sys->b_cursor_hidden = 0;
+ p_vout->p_sys->i_lastmoved = mdate();
+
+ /* Set main window's size */
+ p_vout->p_sys->i_window_width = p_vout->i_window_width;
+ p_vout->p_sys->i_window_height = p_vout->i_window_height;
+
+ /* Create the DirectXEventThread, this thread is created by us to isolate
+ * the Win32 PeekMessage function calls. We want to do this because
+ * Windows can stay blocked inside this call for a long time, and when
+ * this happens it thus blocks vlc's video_output thread.
+ * DirectXEventThread will take care of the creation of the video
+ * window (because PeekMessage has to be called from the same thread which
+ * created the window). */
+ msg_Dbg( p_vout, "creating DirectXEventThread" );
+ p_vout->p_sys->p_event =
+ vlc_object_create( p_vout, sizeof(event_thread_t) );
+ p_vout->p_sys->p_event->p_vout = p_vout;
+ if( vlc_thread_create( p_vout->p_sys->p_event,
+ "DirectX Events Thread", DirectXEventThread, 1 ) )
+ {
+ msg_Err( p_vout, "cannot create DirectXEventThread" );
+ vlc_object_destroy( p_vout->p_sys->p_event );
+ p_vout->p_sys->p_event = NULL;
+ goto error;
+ }
+
+ if( p_vout->p_sys->p_event->b_error )
+ {
+ msg_Err( p_vout, "DirectXEventThread failed" );
+ goto error;
+ }
+
+ vlc_object_attach( p_vout->p_sys->p_event, p_vout );
+
+ msg_Dbg( p_vout, "DirectXEventThread running" );
+
+ /* Initialise DirectDraw */
+ if( DirectXInitDDraw( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot initialize DirectDraw" );
+ goto error;
+ }
+
+ /* Create the directx display */
+ if( DirectXCreateDisplay( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot initialize DirectDraw" );
+ goto error;
+ }
+
+ return 0;
+
+ error:
+ E_(CloseVideo)( VLC_OBJECT(p_vout) );
+ return 1;
+
+}
+
+/*****************************************************************************
+ * Init: initialize DirectX video thread output method
+ *****************************************************************************
+ * This function create the directx surfaces needed by the output thread.
+ * It is called at the beginning of the thread.
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_chroma_backup;
+
+ /* Initialize the output structure.
+ * Since DirectDraw can do rescaling for us, stick to the default
+ * coordinates and aspect. */
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+#define MAX_DIRECTBUFFERS 1
+ /* Right now we use only 1 directbuffer because we don't want the
+ * video decoder to decode directly into direct buffers as they are
+ * created into video memory and video memory is _really_ slow */
+
+ /* Choose the chroma we will try first. */
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('Y','U','Y','2'):
+ case VLC_FOURCC('Y','U','N','V'):
+ p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
+ break;
+ case VLC_FOURCC('U','Y','V','Y'):
+ case VLC_FOURCC('U','Y','N','V'):
+ case VLC_FOURCC('Y','4','2','2'):
+ p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
+ break;
+ case VLC_FOURCC('Y','V','Y','U'):
+ p_vout->output.i_chroma = VLC_FOURCC('Y','V','Y','U');
+ break;
+ default:
+ p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
+ break;
+ }
+
+ NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+
+ i_chroma_backup = p_vout->output.i_chroma;
+
+ if( !I_OUTPUTPICTURES )
+ {
+ /* hmmm, it didn't work! Let's try commonly supported chromas */
+ p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
+ NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+ if( !I_OUTPUTPICTURES )
+ {
+ /* hmmm, it didn't work! Let's try commonly supported chromas */
+ p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
+ NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+ }
+ }
+
+ if( !I_OUTPUTPICTURES )
+ {
+ /* If it still didn't work then don't try to use an overlay */
+ p_vout->output.i_chroma = i_chroma_backup;
+ p_vout->p_sys->b_using_overlay = 0;
+ NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
+ }
+
+ /* Change the window title bar text */
+ if( p_vout->p_sys->b_using_overlay )
+ SetWindowText( p_vout->p_sys->hwnd,
+ VOUT_TITLE " (hardware YUV overlay DirectX output)" );
+ else if( p_vout->p_sys->b_hw_yuv )
+ SetWindowText( p_vout->p_sys->hwnd,
+ VOUT_TITLE " (hardware YUV DirectX output)" );
+ else SetWindowText( p_vout->p_sys->hwnd,
+ VOUT_TITLE " (software RGB DirectX output)" );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * End: terminate Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create.
+ * It is called at the end of the thread.
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
+ return;
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+void E_(CloseVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ msg_Dbg( p_vout, "CloseVideo" );
+
+ DirectXCloseDisplay( p_vout );
+ DirectXCloseDDraw( p_vout );
+
+ if( p_vout->p_sys->p_event )
+ {
+ vlc_object_detach_all( p_vout->p_sys->p_event );
+
+ /* Kill DirectXEventThread */
+ p_vout->p_sys->p_event->b_die = 1;
+
+ /* we need to be sure DirectXEventThread won't stay stuck in
+ * GetMessage, so we send a fake message */
+ if( p_vout->p_sys->hwnd )
+ PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
+
+ vlc_thread_join( p_vout->p_sys->p_event );
+ vlc_object_destroy( p_vout->p_sys->p_event );
+ }
+
+ if( p_vout->p_sys )
+ {
+ free( p_vout->p_sys );
+ p_vout->p_sys = NULL;
+ }
+}
+
+/*****************************************************************************
+ * Manage: handle Sys events
+ *****************************************************************************
+ * This function should be called regularly by the video output thread.
+ * It returns a non null value if an error occured.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ WINDOWPLACEMENT window_placement;
+
+ /* We used to call the Win32 PeekMessage function here to read the window
+ * messages. But since window can stay blocked into this function for a
+ * long time (for example when you move your window on the screen), I
+ * decided to isolate PeekMessage in another thread. */
+
+ /*
+ * Scale Change
+ */
+ if( p_vout->i_changes & VOUT_SCALE_CHANGE
+ || p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE)
+ {
+ msg_Dbg( p_vout, "Scale Change" );
+ if( !p_vout->p_sys->b_using_overlay )
+ InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
+ else
+ DirectXUpdateOverlay( p_vout );
+ p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
+ p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE;
+ }
+
+ /*
+ * Size Change
+ */
+ if( p_vout->i_changes & VOUT_SIZE_CHANGE
+ || p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE )
+ {
+ msg_Dbg( p_vout, "Size Change" );
+ if( !p_vout->p_sys->b_using_overlay )
+ InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
+ else
+ DirectXUpdateOverlay( p_vout );
+ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+ p_vout->p_sys->i_changes &= ~VOUT_SIZE_CHANGE;
+ }
+
+ /*
+ * Fullscreen change
+ */
+ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
+ || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
+ {
+ p_vout->b_fullscreen = ! p_vout->b_fullscreen;
+
+ /* We need to switch between Maximized and Normal sized window */
+ window_placement.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement( p_vout->p_sys->hwnd, &window_placement );
+ if( p_vout->b_fullscreen )
+ {
+ /* Maximized window */
+ window_placement.showCmd = SW_SHOWMAXIMIZED;
+ /* Change window style, no borders and no title bar */
+ SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, 0 );
+
+ }
+ else
+ {
+ /* Normal window */
+ window_placement.showCmd = SW_SHOWNORMAL;
+ /* Change window style, borders and title bar */
+ SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
+ WS_OVERLAPPEDWINDOW | WS_SIZEBOX | WS_VISIBLE );
+ }
+
+ SetWindowPlacement( p_vout->p_sys->hwnd, &window_placement );
+
+ p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+ p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+ }
+
+ /*
+ * Pointer change
+ */
+ if( (!p_vout->p_sys->b_cursor_hidden) &&
+ ( (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 ) )
+ {
+ /* Hide the mouse automatically */
+ p_vout->p_sys->b_cursor_hidden = 1;
+ PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
+ }
+
+ /* Check if the event thread is still running */
+ if( p_vout->p_sys->p_event->b_die )
+ return 1; /* exit */
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************
+ * This function sends the currently rendered image to the display, wait until
+ * it is displayed and switch the two rendering buffers, preparing next frame.
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ HRESULT dxresult;
+
+ if( (p_vout->p_sys->p_display == NULL) )
+ {
+ msg_Warn( p_vout, "no display!!" );
+ return;
+ }
+
+ if( !p_vout->p_sys->b_using_overlay )
+ {
+ DDBLTFX ddbltfx;
+
+ /* We ask for the "NOTEARING" option */
+ memset( &ddbltfx, 0, sizeof(DDBLTFX) );
+ ddbltfx.dwSize = sizeof(DDBLTFX);
+ ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
+
+ /* Blit video surface to display */
+ dxresult = IDirectDrawSurface2_Blt(p_vout->p_sys->p_display,
+ &p_vout->p_sys->rect_dest_clipped,
+ p_pic->p_sys->p_surface,
+ &p_vout->p_sys->rect_src_clipped,
+ DDBLT_ASYNC, &ddbltfx );
+ if ( dxresult == DDERR_SURFACELOST )
+ {
+ /* Our surface can be lost so be sure
+ * to check this and restore it if needed */
+ IDirectDrawSurface2_Restore( p_vout->p_sys->p_display );
+
+ /* Now that the surface has been restored try to display again */
+ dxresult = IDirectDrawSurface2_Blt(p_vout->p_sys->p_display,
+ &p_vout->p_sys->rect_dest_clipped,
+ p_pic->p_sys->p_surface,
+ &p_vout->p_sys->rect_src_clipped,
+ DDBLT_ASYNC, &ddbltfx );
+ }
+
+ if( dxresult != DD_OK )
+ {
+ msg_Warn( p_vout, "could not Blit the surface" );
+ return;
+ }
+
+ }
+ else /* using overlay */
+ {
+
+ /* Flip the overlay buffers if we are using back buffers */
+ if( p_pic->p_sys->p_front_surface == p_pic->p_sys->p_surface )
+ return;
+
+ dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
+ NULL, DDFLIP_WAIT );
+ if ( dxresult == DDERR_SURFACELOST )
+ {
+ /* Our surface can be lost so be sure
+ * to check this and restore it if needed */
+ IDirectDrawSurface2_Restore( p_vout->p_sys->p_display );
+ IDirectDrawSurface2_Restore( p_pic->p_sys->p_front_surface );
+
+ /* Now that the surface has been restored try to display again */
+ dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
+ NULL, DDFLIP_WAIT );
+ DirectXUpdateOverlay( p_vout );
+ }
+
+ if( dxresult != DD_OK )
+ msg_Warn( p_vout, "could not flip overlay surface" );
+
+ if( !DirectXGetSurfaceDesc( p_pic ) )
+ {
+ /* AAARRGG */
+ msg_Err( p_vout, "cannot get surface desc" );
+ return;
+ }
+
+ if( !UpdatePictureStruct( p_vout, p_pic, p_vout->output.i_chroma ) )
+ {
+ /* AAARRGG */
+ msg_Err( p_vout, "invalid pic chroma" );
+ return;
+ }
+
+ /* set currently displayed pic */
+ p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
+ }
+
+}
+
+
+/* following functions are local */
+
+/*****************************************************************************
+ * DirectXInitDDraw: Takes care of all the DirectDraw initialisations
+ *****************************************************************************
+ * This function initialise and allocate resources for DirectDraw.
+ *****************************************************************************/
+static int DirectXInitDDraw( vout_thread_t *p_vout )
+{
+ HRESULT dxresult;
+ HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
+ LPDIRECTDRAW p_ddobject;
+
+ msg_Dbg( p_vout, "DirectXInitDDraw" );
+
+ /* load direct draw DLL */
+ p_vout->p_sys->hddraw_dll = LoadLibrary("DDRAW.DLL");
+ if( p_vout->p_sys->hddraw_dll == NULL )
+ {
+ msg_Warn( p_vout, "DirectXInitDDraw failed loading ddraw.dll" );
+ goto error;
+ }
+
+ OurDirectDrawCreate =
+ (void *)GetProcAddress(p_vout->p_sys->hddraw_dll, "DirectDrawCreate");
+ if ( OurDirectDrawCreate == NULL )
+ {
+ msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" );
+ goto error;
+ }
+
+ /* Initialize DirectDraw now */
+ dxresult = OurDirectDrawCreate( NULL, &p_ddobject, NULL );
+ if( dxresult != DD_OK )
+ {
+ msg_Err( p_vout, "DirectXInitDDraw cannot initialize DDraw" );
+ goto error;
+ }
+
+ /* Get the IDirectDraw2 interface */
+ dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2,
+ (LPVOID *)&p_vout->p_sys->p_ddobject );
+ /* Release the unused interface */
+ IDirectDraw_Release( p_ddobject );
+ if( dxresult != DD_OK )
+ {
+ msg_Err( p_vout, "cannot get IDirectDraw2 interface" );
+ goto error;
+ }
+
+ /* Set DirectDraw Cooperative level, ie what control we want over Windows
+ * display */
+ dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
+ p_vout->p_sys->hwnd, DDSCL_NORMAL );
+ if( dxresult != DD_OK )
+ {
+ msg_Err( p_vout, "cannot set direct draw cooperative level" );
+ goto error;
+ }
+
+ /* Probe the capabilities of the hardware */
+ DirectXGetDDrawCaps( p_vout );
+
+ msg_Dbg( p_vout, "End DirectXInitDDraw" );
+ return 0;
+
+ error:
+ if( p_vout->p_sys->p_ddobject )
+ IDirectDraw2_Release( p_vout->p_sys->p_ddobject );
+ if( p_vout->p_sys->hddraw_dll )
+ FreeLibrary( p_vout->p_sys->hddraw_dll );
+ p_vout->p_sys->hddraw_dll = NULL;
+ p_vout->p_sys->p_ddobject = NULL;
+ return 1;
+}
+
+/*****************************************************************************
+ * DirectXCreateDisplay: create the DirectDraw display.
+ *****************************************************************************
+ * Create and initialize display according to preferences specified in the vout
+ * thread fields.
+ *****************************************************************************/
+static int DirectXCreateDisplay( vout_thread_t *p_vout )
+{
+ HRESULT dxresult;
+ DDSURFACEDESC ddsd;
+ LPDIRECTDRAWSURFACE p_display;
+ DDPIXELFORMAT pixel_format;
+
+ msg_Dbg( p_vout, "DirectXCreateDisplay" );
+
+ /* Now get the primary surface. This surface is what you actually see
+ * on your screen */
+ memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
+ ddsd.dwSize = sizeof(DDSURFACEDESC);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+ &ddsd,
+ &p_display, NULL );
+ if( dxresult != DD_OK )
+ {
+ msg_Err( p_vout, "cannot get direct draw primary surface" );
+ return 1;
+ }
+
+ dxresult = IDirectDrawSurface_QueryInterface( p_display,
+ &IID_IDirectDrawSurface2,
+ (LPVOID *)&p_vout->p_sys->p_display );
+ /* Release the old interface */
+ IDirectDrawSurface_Release( p_display );
+ if ( dxresult != DD_OK )
+ {
+ msg_Err( p_vout, "cannot get IDirectDrawSurface2 interface" );
+ return 1;
+ }
+
+ /* The clipper will be used only in non-overlay mode */
+ DirectXCreateClipper( p_vout );
+
+
+#if 1
+ /* compute the colorkey pixel value from the RGB value we've got */
+ memset( &pixel_format, 0, sizeof( DDPIXELFORMAT ));
+ pixel_format.dwSize = sizeof( DDPIXELFORMAT );
+ dxresult = IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
+ &pixel_format );
+ if( dxresult != DD_OK )
+ msg_Warn( p_vout, "DirectXUpdateOverlay GetPixelFormat failed" );
+ p_vout->p_sys->i_colorkey = (DWORD)((( p_vout->p_sys->i_rgb_colorkey
+ * pixel_format.dwRBitMask) / 255)
+ & pixel_format.dwRBitMask);
+#endif
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * DirectXCreateClipper: Create a clipper that will be used when blitting the
+ * RGB surface to the main display.
+ *****************************************************************************
+ * This clipper prevents us to modify by mistake anything on the screen
+ * which doesn't belong to our window. For example when a part of our video
+ * window is hidden by another window.
+ *****************************************************************************/
+static int DirectXCreateClipper( vout_thread_t *p_vout )
+{
+ HRESULT dxresult;
+
+ msg_Dbg( p_vout, "DirectXCreateClipper" );
+
+ /* Create the clipper */
+ dxresult = IDirectDraw2_CreateClipper( p_vout->p_sys->p_ddobject, 0,
+ &p_vout->p_sys->p_clipper, NULL );
+ if( dxresult != DD_OK )
+ {
+ msg_Warn( p_vout, "DirectXCreateClipper cannot create clipper" );
+ goto error;
+ }
+
+ /* associate the clipper to the window */
+ dxresult = IDirectDrawClipper_SetHWnd(p_vout->p_sys->p_clipper, 0,
+ p_vout->p_sys->hwnd);
+ if( dxresult != DD_OK )
+ {
+ msg_Warn( p_vout,
+ "DirectXCreateClipper cannot attach clipper to window" );
+ goto error;
+ }
+
+ /* associate the clipper with the surface */
+ dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display,
+ p_vout->p_sys->p_clipper);
+ if( dxresult != DD_OK )
+ {
+ msg_Warn( p_vout,
+ "DirectXCreateClipper cannot attach clipper to surface" );
+ goto error;
+ }
+
+ return 0;
+
+ error:
+ if( p_vout->p_sys->p_clipper )
+ IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
+ p_vout->p_sys->p_clipper = NULL;
+ return 1;
+
+}
+
+/*****************************************************************************
+ * DirectXCreateSurface: create an YUV overlay or RGB surface for the video.
+ *****************************************************************************
+ * The best method of display is with an YUV overlay because the YUV->RGB
+ * conversion is done in hardware.
+ * You can also create a plain RGB surface.
+ * ( Maybe we could also try an RGB overlay surface, which could have hardware
+ * scaling and which would also be faster in window mode because you don't
+ * need to do any blitting to the main display...)
+ *****************************************************************************/
+static int DirectXCreateSurface( vout_thread_t *p_vout,
+ LPDIRECTDRAWSURFACE2 *pp_surface_final,
+ int i_chroma, int b_overlay,
+ int i_backbuffers )
+{
+ HRESULT dxresult;
+ LPDIRECTDRAWSURFACE p_surface;
+ DDSURFACEDESC ddsd;
+
+ /* Create the video surface */
+ if( b_overlay )
+ {
+ /* Now try to create the YUV overlay surface.
+ * This overlay will be displayed on top of the primary surface.
+ * A color key is used to determine whether or not the overlay will be
+ * displayed, ie the overlay will be displayed in place of the primary
+ * surface wherever the primary surface will have this color.
+ * The video window has been created with a background of this color so
+ * the overlay will be only displayed on top of this window */
+
+ memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
+ ddsd.dwSize = sizeof(DDSURFACEDESC);
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+ ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
+ ddsd.dwFlags = DDSD_CAPS |
+ DDSD_HEIGHT |
+ DDSD_WIDTH |
+ DDSD_PIXELFORMAT;
+ ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY |
+ DDSCAPS_VIDEOMEMORY;
+ ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP
+ : 0 );
+ ddsd.dwHeight = p_vout->render.i_height;
+ ddsd.dwWidth = p_vout->render.i_width;
+ ddsd.dwBackBufferCount = i_backbuffers;
+
+ dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+ &ddsd,
+ &p_surface, NULL );
+ if( dxresult != DD_OK )
+ {
+ *pp_surface_final = NULL;
+ return 0;
+ }
+ }
+
+ if( !b_overlay )
+ {
+ vlc_bool_t b_rgb_surface =
+ ( i_chroma == VLC_FOURCC('R','G','B','2') )
+ || ( i_chroma == VLC_FOURCC('R','V','1','5') )
+ || ( i_chroma == VLC_FOURCC('R','V','1','6') )
+ || ( i_chroma == VLC_FOURCC('R','V','2','4') )
+ || ( i_chroma == VLC_FOURCC('R','V','3','2') );
+
+ memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
+ ddsd.dwSize = sizeof(DDSURFACEDESC);
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ ddsd.dwFlags = DDSD_HEIGHT |
+ DDSD_WIDTH |
+ DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ ddsd.dwHeight = p_vout->render.i_height;
+ ddsd.dwWidth = p_vout->render.i_width;
+
+ if( p_vout->p_sys->b_use_sysmem )
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+ else
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
+
+ if( !b_rgb_surface )
+ {
+ ddsd.dwFlags |= DDSD_PIXELFORMAT;
+ ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
+ ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
+ }
+
+ dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
+ &ddsd,
+ &p_surface, NULL );
+ if( dxresult != DD_OK )
+ {
+ *pp_surface_final = NULL;
+ return 0;
+ }
+ }
+
+ /* Now that the surface is created, try to get a newer DirectX interface */
+ dxresult = IDirectDrawSurface_QueryInterface( p_surface,
+ &IID_IDirectDrawSurface2,
+ (LPVOID *)pp_surface_final );
+ IDirectDrawSurface_Release( p_surface ); /* Release the old interface */
+ if ( dxresult != DD_OK )
+ {
+ msg_Err( p_vout, "cannot get IDirectDrawSurface2 interface" );
+ *pp_surface_final = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+/*****************************************************************************
+ * DirectXUpdateOverlay: Move or resize overlay surface on video display.
+ *****************************************************************************
+ * This function is used to move or resize an overlay surface on the screen.
+ * Ususally the overlay is moved by the user and thus, by a move or resize
+ * event (in Manage).
+ *****************************************************************************/
+void DirectXUpdateOverlay( vout_thread_t *p_vout )
+{
+ DDOVERLAYFX ddofx;
+ DWORD dwFlags;
+ HRESULT dxresult;
+
+ if( p_vout->p_sys->p_current_surface == NULL ||
+ !p_vout->p_sys->b_using_overlay )
+ return;
+
+ /* The new window dimensions should already have been computed by the
+ * caller of this function */
+
+ /* Position and show the overlay */
+ memset(&ddofx, 0, sizeof(DDOVERLAYFX));
+ ddofx.dwSize = sizeof(DDOVERLAYFX);
+ ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey;
+ ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey;
+
+ dwFlags = DDOVER_SHOW;
+ if( !p_vout->p_sys->b_caps_overlay_clipping )
+ dwFlags |= DDOVER_KEYDESTOVERRIDE;
+
+ dxresult = IDirectDrawSurface2_UpdateOverlay(
+ p_vout->p_sys->p_current_surface,
+ &p_vout->p_sys->rect_src_clipped,
+ p_vout->p_sys->p_display,
+ &p_vout->p_sys->rect_dest_clipped,
+ dwFlags,
+ &ddofx );
+ if(dxresult != DD_OK)
+ {
+ msg_Warn( p_vout,
+ "DirectXUpdateOverlay cannot move or resize overlay" );
+ }
+
+}
+
+/*****************************************************************************
+ * DirectXCloseDDraw: Release the DDraw object allocated by DirectXInitDDraw
+ *****************************************************************************
+ * This function returns all resources allocated by DirectXInitDDraw.
+ *****************************************************************************/
+static void DirectXCloseDDraw( vout_thread_t *p_vout )
+{
+ msg_Dbg( p_vout, "DirectXCloseDDraw" );
+ if( p_vout->p_sys->p_ddobject != NULL )
+ {
+ IDirectDraw2_Release(p_vout->p_sys->p_ddobject);
+ p_vout->p_sys->p_ddobject = NULL;
+ }
+
+ if( p_vout->p_sys->hddraw_dll != NULL )
+ {
+ FreeLibrary( p_vout->p_sys->hddraw_dll );
+ p_vout->p_sys->hddraw_dll = NULL;
+ }
+}
+
+/*****************************************************************************
+ * DirectXCloseDisplay: close and reset the DirectX display device
+ *****************************************************************************
+ * This function returns all resources allocated by DirectXCreateDisplay.
+ *****************************************************************************/
+static void DirectXCloseDisplay( vout_thread_t *p_vout )
+{
+ msg_Dbg( p_vout, "DirectXCloseDisplay" );
+
+ if( p_vout->p_sys->p_clipper != NULL )
+ {
+ msg_Dbg( p_vout, "DirectXCloseDisplay clipper" );
+ IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
+ p_vout->p_sys->p_clipper = NULL;
+ }
+
+ if( p_vout->p_sys->p_display != NULL )
+ {
+ msg_Dbg( p_vout, "DirectXCloseDisplay display" );
+ IDirectDrawSurface2_Release( p_vout->p_sys->p_display );
+ p_vout->p_sys->p_display = NULL;
+ }
+}
+
+/*****************************************************************************
+ * DirectXCloseSurface: close the YUV overlay or RGB surface.
+ *****************************************************************************
+ * This function returns all resources allocated for the surface.
+ *****************************************************************************/
+static void DirectXCloseSurface( vout_thread_t *p_vout,
+ LPDIRECTDRAWSURFACE2 p_surface )
+{
+ msg_Dbg( p_vout, "DirectXCloseSurface" );
+ if( p_surface != NULL )
+ {
+ IDirectDrawSurface2_Release( p_surface );
+ }
+}
+
+/*****************************************************************************
+ * NewPictureVec: allocate a vector of identical pictures
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
+ int i_num_pics )
+{
+ int i;
+ vlc_bool_t b_result_ok;
+ LPDIRECTDRAWSURFACE2 p_surface;
+
+ msg_Dbg( p_vout, "NewPictureVec" );
+
+ I_OUTPUTPICTURES = 0;
+
+ /* First we try to use an YUV overlay surface.
+ * The overlay surface that we create won't be used to decode directly
+ * into it because accessing video memory directly is way to slow (remember
+ * that pictures are decoded macroblock per macroblock). Instead the video
+ * will be decoded in picture buffers in system memory which will then be
+ * memcpy() to the overlay surface. */
+ if( p_vout->p_sys->b_using_overlay )
+ {
+ /* Triple buffering rocks! it doesn't have any processing overhead
+ * (you don't have to wait for the vsync) and provides for a very nice
+ * video quality (no tearing). */
+
+ b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+ p_vout->output.i_chroma,
+ p_vout->p_sys->b_using_overlay,
+ 2 /* number of backbuffers */ );
+
+ if( !b_result_ok )
+ /* Try to reduce the number of backbuffers */
+ b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+ p_vout->output.i_chroma,
+ p_vout->p_sys->b_using_overlay,
+ 0 /* number of backbuffers */);
+
+ if( b_result_ok )
+ {
+ DDSCAPS dds_caps;
+ picture_t front_pic;
+ picture_sys_t front_pic_sys;
+ front_pic.p_sys = &front_pic_sys;
+
+ /* Allocate internal structure */
+ p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
+ if( p_pic[0].p_sys == NULL )
+ {
+ DirectXCloseSurface( p_vout, p_surface );
+ return -1;
+ }
+
+ /* set front buffer */
+ p_pic[0].p_sys->p_front_surface = p_surface;
+
+ /* Get the back buffer */
+ memset( &dds_caps, 0, sizeof( DDSCAPS ) );
+ dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
+ if( DD_OK != IDirectDrawSurface2_GetAttachedSurface(
+ p_surface, &dds_caps,
+ &p_pic[0].p_sys->p_surface ) )
+ {
+ msg_Warn( p_vout, "NewPictureVec could not get back buffer" );
+ /* front buffer is the same as back buffer */
+ p_pic[0].p_sys->p_surface = p_surface;
+ }
+
+
+ p_vout->p_sys->p_current_surface = front_pic.p_sys->p_surface =
+ p_pic[0].p_sys->p_front_surface;
+
+ /* reset the front buffer memory */
+ if( DirectXGetSurfaceDesc( &front_pic ) &&
+ UpdatePictureStruct( p_vout, &front_pic,
+ p_vout->output.i_chroma ) )
+ {
+ int i,j;
+ for( i = 0; i < front_pic.i_planes; i++ )
+ for( j = 0; j < front_pic.p[i].i_lines; j++)
+ memset( front_pic.p[i].p_pixels + j *
+ front_pic.p[i].i_pitch, 127,
+ front_pic.p[i].i_visible_pitch );
+ }
+
+ DirectXUpdateOverlay( p_vout );
+ I_OUTPUTPICTURES = 1;
+ msg_Dbg( p_vout, "DirectX YUV overlay created successfully" );
+ }
+ }
+
+ /* As we can't have an overlay, we'll try to create a plain offscreen
+ * surface. This surface will reside in video memory because there's a
+ * better chance then that we'll be able to use some kind of hardware
+ * acceleration like rescaling, blitting or YUV->RGB conversions.
+ * We then only need to blit this surface onto the main display when we
+ * want to display it */
+ if( !p_vout->p_sys->b_using_overlay )
+ {
+
+ if( p_vout->p_sys->b_hw_yuv )
+ b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+ p_vout->output.i_chroma,
+ p_vout->p_sys->b_using_overlay,
+ 0 /* no back buffers */ );
+
+ if( !p_vout->p_sys->b_hw_yuv || !b_result_ok )
+ {
+ /* Our last choice is to use a plain RGB surface */
+ DDPIXELFORMAT ddpfPixelFormat;
+
+ ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
+ &ddpfPixelFormat );
+
+ if( ddpfPixelFormat.dwFlags & DDPF_RGB )
+ {
+ switch( ddpfPixelFormat.dwRGBBitCount )
+ {
+ case 8: /* FIXME: set the palette */
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
+ break;
+ case 15:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
+ break;
+ case 16:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
+ break;
+ case 24:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
+ break;
+ case 32:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
+ break;
+ default:
+ msg_Err( p_vout, "unknown screen depth" );
+ return 0;
+ }
+ p_vout->output.i_rmask = ddpfPixelFormat.dwRBitMask;
+ p_vout->output.i_gmask = ddpfPixelFormat.dwGBitMask;
+ p_vout->output.i_bmask = ddpfPixelFormat.dwBBitMask;
+ }
+
+ p_vout->p_sys->b_hw_yuv = 0;
+
+ b_result_ok = DirectXCreateSurface( p_vout, &p_surface,
+ p_vout->output.i_chroma,
+ p_vout->p_sys->b_using_overlay,
+ 0 /* no back buffers */ );
+ }
+
+ if( b_result_ok )
+ {
+ /* Allocate internal structure */
+ p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
+ if( p_pic[0].p_sys == NULL )
+ {
+ DirectXCloseSurface( p_vout, p_surface );
+ return -1;
+ }
+ p_pic[0].p_sys->p_surface = p_pic[0].p_sys->p_front_surface
+ = p_surface;
+
+ I_OUTPUTPICTURES = 1;
+
+ msg_Dbg( p_vout, "DirectX plain surface created successfully" );
+ }
+ }
+
+
+ /* Now that we've got all our direct-buffers, we can finish filling in the
+ * picture_t structures */
+ for( i = 0; i < I_OUTPUTPICTURES; i++ )
+ {
+ p_pic[i].i_status = DESTROYED_PICTURE;
+ p_pic[i].i_type = DIRECT_PICTURE;
+ PP_OUTPUTPICTURE[i] = &p_pic[i];
+
+ if( !DirectXGetSurfaceDesc( &p_pic[i] ) )
+ {
+ /* AAARRGG */
+ FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
+ I_OUTPUTPICTURES = 0;
+ return -1;
+ }
+
+ if( !UpdatePictureStruct(p_vout, &p_pic[i], p_vout->output.i_chroma) )
+ {
+
+ /* Unknown chroma, tell the guy to get lost */
+ msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
+ p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );
+ FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
+ I_OUTPUTPICTURES = 0;
+ return -1;
+ }
+ }
+
+ msg_Dbg( p_vout, "End NewPictureVec");
+ return 0;
+}
+
+/*****************************************************************************
+ * FreePicture: destroy a picture vector allocated with NewPictureVec
+ *****************************************************************************
+ *
+ *****************************************************************************/
+static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
+ int i_num_pics )
+{
+ int i;
+
+ for( i = 0; i < i_num_pics; i++ )
+ {
+ DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
+
+ for( i = 0; i < i_num_pics; i++ )
+ {
+ free( p_pic[i].p_sys );
+ }
+ }
+}
+
+/*****************************************************************************
+ * UpdatePictureStruct: updates the internal data in the picture_t structure
+ *****************************************************************************
+ * This will setup stuff for use by the video_output thread
+ *****************************************************************************/
+static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
+ int i_chroma )
+{
+
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('R','G','B','2'):
+ case VLC_FOURCC('R','V','1','5'):
+ case VLC_FOURCC('R','V','1','6'):
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+ p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
+ p_pic->p->i_lines = p_vout->output.i_height;
+ p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('R','G','B','2'):
+ p_pic->p->i_pixel_pitch = 1;
+ break;
+ case VLC_FOURCC('R','V','1','5'):
+ case VLC_FOURCC('R','V','1','6'):
+ p_pic->p->i_pixel_pitch = 2;
+ break;
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+ p_pic->p->i_pixel_pitch = 4;
+ break;
+ default:
+ return -1;
+ }
+ p_pic->p->i_visible_pitch = p_vout->output.i_width *
+ p_pic->p->i_pixel_pitch;
+ p_pic->i_planes = 1;
+ break;
+
+ case VLC_FOURCC('Y','V','1','2'):
+
+ p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
+ p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
+ p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
+ p_pic->p[Y_PLANE].i_pixel_pitch;
+
+ p_pic->V_PIXELS = p_pic->Y_PIXELS
+ + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
+ p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width *
+ p_pic->p[V_PLANE].i_pixel_pitch;
+
+ p_pic->U_PIXELS = p_pic->V_PIXELS
+ + p_pic->p[V_PLANE].i_lines * p_pic->p[V_PLANE].i_pitch;
+ p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width *
+ p_pic->p[U_PLANE].i_pixel_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ case VLC_FOURCC('I','Y','U','V'):
+
+ p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
+ p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
+ p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
+ p_pic->p[Y_PLANE].i_pixel_pitch;
+
+ p_pic->U_PIXELS = p_pic->Y_PIXELS
+ + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
+ p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width *
+ p_pic->p[U_PLANE].i_pixel_pitch;
+
+ p_pic->V_PIXELS = p_pic->U_PIXELS
+ + p_pic->p[U_PLANE].i_lines * p_pic->p[U_PLANE].i_pitch;
+ p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width *
+ p_pic->p[V_PLANE].i_pixel_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ case VLC_FOURCC('Y','U','Y','2'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
+ p_pic->p->i_lines = p_vout->output.i_height;
+ p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
+ p_pic->p->i_pixel_pitch = 2;
+ p_pic->p->i_visible_pitch = p_vout->output.i_width *
+ p_pic->p->i_pixel_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+
+ default:
+ /* Not supported */
+ return 0;
+
+ }
+
+ return 1;
+}
+
+/*****************************************************************************
+ * DirectXGetDDrawCaps: Probe the capabilities of the hardware
+ *****************************************************************************
+ * It is nice to know which features are supported by the hardware so we can
+ * find ways to optimize our rendering.
+ *****************************************************************************/
+static void DirectXGetDDrawCaps( vout_thread_t *p_vout )
+{
+ DDCAPS ddcaps;
+ HRESULT dxresult;
+
+ /* This is just an indication of whether or not we'll support overlay,
+ * but with this test we don't know if we support YUV overlay */
+ memset( &ddcaps, 0, sizeof( DDCAPS ));
+ ddcaps.dwSize = sizeof(DDCAPS);
+ dxresult = IDirectDraw2_GetCaps( p_vout->p_sys->p_ddobject,
+ &ddcaps, NULL );
+ if(dxresult != DD_OK )
+ {
+ msg_Warn( p_vout, "cannot get caps" );
+ }
+ else
+ {
+ BOOL bHasOverlay, bHasOverlayFourCC, bCanClipOverlay,
+ bHasColorKey, bCanStretch;
+
+ /* Determine if the hardware supports overlay surfaces */
+ bHasOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAY) ==
+ DDCAPS_OVERLAY) ? TRUE : FALSE;
+ /* Determine if the hardware supports overlay surfaces */
+ bHasOverlayFourCC = ((ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ==
+ DDCAPS_OVERLAYFOURCC) ? TRUE : FALSE;
+ /* Determine if the hardware supports overlay surfaces */
+ bCanClipOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAYCANTCLIP) ==
+ 0 ) ? TRUE : FALSE;
+ /* Determine if the hardware supports colorkeying */
+ bHasColorKey = ((ddcaps.dwCaps & DDCAPS_COLORKEY) ==
+ DDCAPS_COLORKEY) ? TRUE : FALSE;
+ /* Determine if the hardware supports scaling of the overlay surface */
+ bCanStretch = ((ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ==
+ DDCAPS_OVERLAYSTRETCH) ? TRUE : FALSE;
+ msg_Dbg( p_vout, "DirectDraw Capabilities: overlay=%i yuvoverlay=%i "
+ "can_clip_overlay=%i colorkey=%i stretch=%i",
+ bHasOverlay, bHasOverlayFourCC, bCanClipOverlay,
+ bHasColorKey, bCanStretch );
+
+ /* Overlay clipping support is interesting for us as it means we can
+ * get rid of the colorkey alltogether */
+ p_vout->p_sys->b_caps_overlay_clipping = bCanClipOverlay;
+
+ }
+}
+
+/*****************************************************************************
+ * DirectXGetSurfaceDesc: Get some more information about the surface
+ *****************************************************************************
+ * This function get and stores the surface descriptor which among things
+ * has the pointer to the picture data.
+ *****************************************************************************/
+static int DirectXGetSurfaceDesc( picture_t *p_pic )
+{
+ HRESULT dxresult;
+
+ /* Lock the surface to get a valid pointer to the picture buffer */
+ memset( &p_pic->p_sys->ddsd, 0, sizeof( DDSURFACEDESC ));
+ p_pic->p_sys->ddsd.dwSize = sizeof(DDSURFACEDESC);
+ dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface,
+ NULL, &p_pic->p_sys->ddsd,
+ DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
+ NULL );
+ if ( dxresult == DDERR_SURFACELOST )
+ {
+ /* Your surface can be lost so be sure
+ * to check this and restore it if needed */
+ dxresult = IDirectDrawSurface2_Restore( p_pic->p_sys->p_surface );
+ dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
+ &p_pic->p_sys->ddsd,
+ DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
+ NULL);
+ }
+ if( dxresult != DD_OK )
+ {
+//X msg_Err( p_vout, "DirectXGetSurfaceDesc cannot lock surface" );
+ return 0;
+ }
+
+ /* Unlock the Surface */
+ dxresult = IDirectDrawSurface2_Unlock( p_pic->p_sys->p_surface, NULL );
+
+ return 1;
+}
--- /dev/null
+/*****************************************************************************
+ * vout.h: Windows DirectX video output header file
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000 VideoLAN
+ * $Id: vout.h,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * event_thread_t: DirectX event thread
+ *****************************************************************************/
+typedef struct event_thread_t
+{
+ VLC_COMMON_MEMBERS
+
+ vout_thread_t * p_vout;
+
+} event_thread_t;
+
+/*****************************************************************************
+ * vout_sys_t: video output DirectX method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the DirectX specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ LPDIRECTDRAW2 p_ddobject; /* DirectDraw object */
+ LPDIRECTDRAWSURFACE2 p_display; /* Display device */
+ LPDIRECTDRAWSURFACE2 p_current_surface; /* surface currently displayed */
+ LPDIRECTDRAWCLIPPER p_clipper; /* clipper used for blitting */
+ HINSTANCE hddraw_dll; /* handle of the opened ddraw dll */
+ HBRUSH hbrush; /* window backgound brush (color) */
+ HWND hwnd; /* Handle of the main window */
+
+ vlc_bool_t b_using_overlay; /* Are we using an overlay surface */
+ vlc_bool_t b_use_sysmem; /* Should we use system memory for surfaces */
+ vlc_bool_t b_hw_yuv; /* Should we use hardware YUV->RGB conversions */
+
+ /* size of the display */
+ RECT rect_display;
+ int i_display_depth;
+
+ /* Window position and size */
+ int i_window_x;
+ int i_window_y;
+ int i_window_width;
+ int i_window_height;
+
+ /* Coordinates of src and dest images (used when blitting to display) */
+ RECT rect_src;
+ RECT rect_src_clipped;
+ RECT rect_dest;
+ RECT rect_dest_clipped;
+
+ /* DDraw capabilities */
+ int b_caps_overlay_clipping;
+
+ int i_rgb_colorkey; /* colorkey in RGB used by the overlay */
+ int i_colorkey; /* colorkey used by the overlay */
+
+ volatile u16 i_changes; /* changes made to the video display */
+
+ /* Mouse */
+ volatile vlc_bool_t b_cursor_hidden;
+ volatile mtime_t i_lastmoved;
+
+ event_thread_t * p_event;
+};
+
+/*****************************************************************************
+ * picture_sys_t: direct buffer method descriptor
+ *****************************************************************************
+ * This structure is part of the picture descriptor, it describes the
+ * DirectX specific properties of a direct buffer.
+ *****************************************************************************/
+struct picture_sys_t
+{
+ LPDIRECTDRAWSURFACE2 p_surface;
+ DDSURFACEDESC ddsd;
+ LPDIRECTDRAWSURFACE2 p_front_surface;
+};
+
+/*****************************************************************************
+ * Prototypes from vout.c
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Prototypes from events.c
+ *****************************************************************************/
+void DirectXEventThread ( event_thread_t *p_event );
+void DirectXUpdateOverlay( vout_thread_t *p_vout );
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define WM_VLC_HIDE_MOUSE WM_APP
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+fb_SOURCES = fb.c
--- /dev/null
+/*****************************************************************************
+ * fb.c : framebuffer plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: fb.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <signal.h> /* SIGUSR1, SIGUSR2 */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* close() */
+
+#include <termios.h> /* struct termios */
+#include <sys/ioctl.h>
+#include <sys/mman.h> /* mmap() */
+
+#include <linux/fb.h>
+#include <linux/vt.h> /* VT_* */
+#include <linux/kd.h> /* KD* */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static int OpenDisplay ( vout_thread_t * );
+static void CloseDisplay ( vout_thread_t * );
+static void SwitchDisplay ( int i_signal );
+static void TextMode ( int i_tty );
+static void GfxMode ( int i_tty );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define FB_DEV_VAR "fbdev"
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( FB_DEV_VAR, "/dev/fb0", NULL, N_("framebuffer device"), NULL );
+ set_description( _("Linux console framebuffer module") );
+ set_capability( "video output", 30 );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: video output framebuffer method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the FB specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ /* System informations */
+ int i_tty; /* tty device handle */
+ struct termios old_termios;
+
+ /* Original configuration informations */
+ struct sigaction sig_usr1; /* USR1 previous handler */
+ struct sigaction sig_usr2; /* USR2 previous handler */
+ struct vt_mode vt_mode; /* previous VT mode */
+
+ /* Framebuffer information */
+ int i_fd; /* device handle */
+ struct fb_var_screeninfo old_info; /* original mode informations */
+ struct fb_var_screeninfo var_info; /* current mode informations */
+ vlc_bool_t b_pan; /* does device supports panning ? */
+ struct fb_cmap fb_cmap; /* original colormap */
+ u16 *p_palette; /* original palette */
+
+ /* Video information */
+ int i_width;
+ int i_height;
+ int i_bytes_per_pixel;
+
+ /* Video memory */
+ byte_t * p_video; /* base adress */
+ size_t i_page_size; /* page size */
+};
+
+/*****************************************************************************
+ * Create: allocates FB video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a FB vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ struct sigaction sig_tty; /* sigaction for tty change */
+ struct vt_mode vt_mode; /* vt current mode */
+ struct termios new_termios;
+
+ /* Allocate instance and initialize some members */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ return( 1 );
+ };
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = Display;
+
+ /* Set tty and fb devices */
+ p_vout->p_sys->i_tty = 0; /* 0 == /dev/tty0 == current console */
+
+ GfxMode( p_vout->p_sys->i_tty );
+
+ /* Set keyboard settings */
+ if (tcgetattr(0, &p_vout->p_sys->old_termios) == -1)
+ {
+ msg_Err( p_vout, "tcgetattr failed" );
+ }
+
+ if (tcgetattr(0, &new_termios) == -1)
+ {
+ msg_Err( p_vout, "tcgetattr failed" );
+ }
+
+ /* new_termios.c_lflag &= ~ (ICANON | ISIG);
+ new_termios.c_lflag |= (ECHO | ECHOCTL); */
+ new_termios.c_lflag &= ~ (ICANON);
+ new_termios.c_lflag &= ~(ECHO | ECHOCTL);
+ new_termios.c_iflag = 0;
+ new_termios.c_cc[VMIN] = 1;
+ new_termios.c_cc[VTIME] = 0;
+
+ if (tcsetattr(0, TCSAFLUSH, &new_termios) == -1)
+ {
+ msg_Err( p_vout, "tcsetattr failed" );
+ }
+
+ ioctl( p_vout->p_sys->i_tty, VT_RELDISP, VT_ACKACQ );
+
+ /* Set-up tty signal handler to be aware of tty changes */
+ memset( &sig_tty, 0, sizeof( sig_tty ) );
+ sig_tty.sa_handler = SwitchDisplay;
+ sigemptyset( &sig_tty.sa_mask );
+ if( sigaction( SIGUSR1, &sig_tty, &p_vout->p_sys->sig_usr1 ) ||
+ sigaction( SIGUSR2, &sig_tty, &p_vout->p_sys->sig_usr2 ) )
+ {
+ msg_Err( p_vout, "cannot set signal handler (%s)", strerror(errno) );
+ tcsetattr(0, 0, &p_vout->p_sys->old_termios);
+ TextMode( p_vout->p_sys->i_tty );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ /* Set-up tty according to new signal handler */
+ if( -1 == ioctl( p_vout->p_sys->i_tty,
+ VT_GETMODE, &p_vout->p_sys->vt_mode ) )
+ {
+ msg_Err( p_vout, "cannot get terminal mode (%s)", strerror(errno) );
+ sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
+ sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
+ tcsetattr(0, 0, &p_vout->p_sys->old_termios);
+ TextMode( p_vout->p_sys->i_tty );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+ memcpy( &vt_mode, &p_vout->p_sys->vt_mode, sizeof( vt_mode ) );
+ vt_mode.mode = VT_PROCESS;
+ vt_mode.waitv = 0;
+ vt_mode.relsig = SIGUSR1;
+ vt_mode.acqsig = SIGUSR2;
+
+ if( -1 == ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &vt_mode ) )
+ {
+ msg_Err( p_vout, "cannot set terminal mode (%s)", strerror(errno) );
+ sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
+ sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
+ tcsetattr(0, 0, &p_vout->p_sys->old_termios);
+ TextMode( p_vout->p_sys->i_tty );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ if( OpenDisplay( p_vout ) )
+ {
+ ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &p_vout->p_sys->vt_mode );
+ sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
+ sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
+ tcsetattr(0, 0, &p_vout->p_sys->old_termios);
+ TextMode( p_vout->p_sys->i_tty );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize framebuffer video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure: RGB with square pixels, whatever
+ * the input format is, since it's the only format we know */
+ switch( p_vout->p_sys->var_info.bits_per_pixel )
+ {
+ case 8: /* FIXME: set the palette */
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); break;
+ case 15:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break;
+ case 16:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break;
+ case 24:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break;
+ case 32:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break;
+ default:
+ msg_Err( p_vout, "unknown screen depth %i",
+ p_vout->p_sys->var_info.bits_per_pixel );
+ return 0;
+ }
+
+ /* Only useful for p_vout->p_sys->var_info.bits_per_pixel != 8 */
+ p_vout->output.i_rmask = ( (1 << p_vout->p_sys->var_info.red.length) - 1 )
+ << p_vout->p_sys->var_info.red.offset;
+ p_vout->output.i_gmask = ( (1 << p_vout->p_sys->var_info.green.length) - 1 )
+ << p_vout->p_sys->var_info.green.offset;
+ p_vout->output.i_bmask = ( (1 << p_vout->p_sys->var_info.blue.length) - 1 )
+ << p_vout->p_sys->var_info.blue.offset;
+
+ p_vout->output.i_width = p_vout->p_sys->i_width;
+ p_vout->output.i_height = p_vout->p_sys->i_height;
+
+ /* Assume we have square pixels */
+ p_vout->output.i_aspect = p_vout->p_sys->i_width
+ * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
+
+ /* Clear the screen */
+ memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
+
+ /* Try to initialize 1 direct buffer */
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture */
+ if( p_pic == NULL )
+ {
+ return 0;
+ }
+
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_pic->p->p_pixels = p_vout->p_sys->p_video;
+ p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
+ p_pic->p->i_lines = p_vout->p_sys->var_info.yres;
+
+ if( p_vout->p_sys->var_info.xres_virtual )
+ {
+ p_pic->p->i_pitch = p_vout->p_sys->var_info.xres_virtual
+ * p_vout->p_sys->i_bytes_per_pixel;
+ }
+ else
+ {
+ p_pic->p->i_pitch = p_vout->p_sys->var_info.xres
+ * p_vout->p_sys->i_bytes_per_pixel;
+ }
+
+ p_pic->p->i_visible_pitch = p_vout->p_sys->var_info.xres
+ * p_vout->p_sys->i_bytes_per_pixel;
+
+ p_pic->i_planes = 1;
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * End: terminate framebuffer video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ /* Clear the screen */
+ memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
+}
+
+/*****************************************************************************
+ * Destroy: destroy FB video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ CloseDisplay( p_vout );
+
+ /* Reset the terminal */
+ ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &p_vout->p_sys->vt_mode );
+
+ /* Remove signal handlers */
+ sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
+ sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
+
+ /* Reset the keyboard state */
+ tcsetattr( 0, 0, &p_vout->p_sys->old_termios );
+
+ /* Return to text mode */
+ TextMode( p_vout->p_sys->i_tty );
+
+ /* Destroy structure */
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Manage: handle FB events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * console events. It returns a non null value on error.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+#if 0
+ u8 buf;
+
+ if ( read(0, &buf, 1) == 1)
+ {
+ switch( buf )
+ {
+ case 'q':
+ p_vout->p_vlc->b_die = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+
+ /*
+ * Size change
+ */
+ if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+ {
+ msg_Dbg( p_vout, "reinitializing framebuffer screen" );
+ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+
+ /* Destroy XImages to change their size */
+ End( p_vout );
+
+ /* Recreate XImages. If SysInit failed, the thread can't go on. */
+ if( Init( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot reinit framebuffer screen" );
+ return( 1 );
+ }
+
+ /* Clear screen */
+ memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
+
+#if 0
+ /* Tell the video output thread that it will need to rebuild YUV
+ * tables. This is needed since conversion buffer size may have changed */
+ p_vout->i_changes |= VOUT_YUV_CHANGE;
+#endif
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************
+ * This function send the currently rendered image to FB image, waits until
+ * it is displayed and switch the two rendering buffers, preparing next frame.
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* swap the two Y offsets if the drivers supports panning */
+ if( p_vout->p_sys->b_pan )
+ {
+ p_vout->p_sys->var_info.yoffset = 0;
+ //p_vout->p_sys->var_info.yoffset = p_vout->p_sys->var_info.yres;
+
+ /* the X offset should be 0, but who knows ...
+ * some other app might have played with the framebuffer */
+ p_vout->p_sys->var_info.xoffset = 0;
+
+ ioctl( p_vout->p_sys->i_fd,
+ FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );
+ }
+}
+
+#if 0
+static void SetPalette( vout_thread_t *p_vout,
+ u16 *red, u16 *green, u16 *blue, u16 *transp )
+{
+ struct fb_cmap cmap = { 0, 256, red, green, blue, transp };
+
+ ioctl( p_vout->p_sys->i_fd, FBIOPUTCMAP, &cmap );
+}
+#endif
+
+/* following functions are local */
+
+/*****************************************************************************
+ * OpenDisplay: initialize framebuffer
+ *****************************************************************************/
+static int OpenDisplay( vout_thread_t *p_vout )
+{
+ char *psz_device; /* framebuffer device path */
+ struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
+
+ /* Open framebuffer device */
+ if( !(psz_device = config_GetPsz( p_vout, FB_DEV_VAR )) )
+ {
+ msg_Err( p_vout, "don't know which fb device to open" );
+ return( 1 );
+ }
+
+ p_vout->p_sys->i_fd = open( psz_device, O_RDWR);
+
+ if( p_vout->p_sys->i_fd == -1 )
+ {
+ msg_Err( p_vout, "cannot open %s (%s)", psz_device, strerror(errno) );
+ free( psz_device );
+ return( 1 );
+ }
+ free( psz_device );
+
+ /* Get framebuffer device informations */
+ if( ioctl( p_vout->p_sys->i_fd,
+ FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
+ {
+ msg_Err( p_vout, "cannot get fb info (%s)", strerror(errno) );
+ close( p_vout->p_sys->i_fd );
+ return( 1 );
+ }
+
+ if( ioctl( p_vout->p_sys->i_fd,
+ FBIOGET_VSCREENINFO, &p_vout->p_sys->old_info ) )
+ {
+ msg_Err( p_vout, "cannot get 2nd fb info (%s)", strerror(errno) );
+ close( p_vout->p_sys->i_fd );
+ return( 1 );
+ }
+
+ /* Set some attributes */
+ p_vout->p_sys->var_info.activate = FB_ACTIVATE_NXTOPEN;
+ p_vout->p_sys->var_info.xoffset = 0;
+ p_vout->p_sys->var_info.yoffset = 0;
+
+ if( ioctl( p_vout->p_sys->i_fd,
+ FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
+ {
+ msg_Err( p_vout, "cannot set fb info (%s)", strerror(errno) );
+ close( p_vout->p_sys->i_fd );
+ return( 1 );
+ }
+
+ /* Get some informations again, in the definitive configuration */
+ if( ioctl( p_vout->p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info )
+ || ioctl( p_vout->p_sys->i_fd,
+ FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
+ {
+ msg_Err( p_vout, "cannot get additional fb info (%s)",
+ strerror(errno) );
+
+ /* Restore fb config */
+ ioctl( p_vout->p_sys->i_fd,
+ FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
+
+ close( p_vout->p_sys->i_fd );
+ return( 1 );
+ }
+
+ /* FIXME: if the image is full-size, it gets cropped on the left
+ * because of the xres / xres_virtual slight difference */
+ msg_Dbg( p_vout, "%ix%i (virtual %ix%i)",
+ p_vout->p_sys->var_info.xres, p_vout->p_sys->var_info.yres,
+ p_vout->p_sys->var_info.xres_virtual,
+ p_vout->p_sys->var_info.yres_virtual );
+
+ p_vout->p_sys->i_height = p_vout->p_sys->var_info.yres;
+ p_vout->p_sys->i_width = p_vout->p_sys->var_info.xres_virtual
+ ? p_vout->p_sys->var_info.xres_virtual
+ : p_vout->p_sys->var_info.xres;
+
+ p_vout->p_sys->p_palette = NULL;
+ p_vout->p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
+
+ switch( p_vout->p_sys->var_info.bits_per_pixel )
+ {
+ case 8:
+ p_vout->p_sys->p_palette = malloc( 8 * 256 * sizeof( u16 ) );
+ p_vout->p_sys->fb_cmap.start = 0;
+ p_vout->p_sys->fb_cmap.len = 256;
+ p_vout->p_sys->fb_cmap.red = p_vout->p_sys->p_palette;
+ p_vout->p_sys->fb_cmap.green = p_vout->p_sys->p_palette + 256 * sizeof( u16 );
+ p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->p_palette + 2 * 256 * sizeof( u16 );
+ p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->p_palette + 3 * 256 * sizeof( u16 );
+
+ /* Save the colormap */
+ ioctl( p_vout->p_sys->i_fd, FBIOGETCMAP, &p_vout->p_sys->fb_cmap );
+
+ p_vout->p_sys->i_bytes_per_pixel = 1;
+ break;
+
+ case 15:
+ case 16:
+ p_vout->p_sys->i_bytes_per_pixel = 2;
+ break;
+
+ case 24:
+ p_vout->p_sys->i_bytes_per_pixel = 3;
+ break;
+
+ case 32:
+ p_vout->p_sys->i_bytes_per_pixel = 4;
+ break;
+
+ default:
+ msg_Err( p_vout, "screen depth %d is not supported",
+ p_vout->p_sys->var_info.bits_per_pixel );
+
+ /* Restore fb config */
+ ioctl( p_vout->p_sys->i_fd,
+ FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
+
+ close( p_vout->p_sys->i_fd );
+ return 1;
+ }
+
+ p_vout->p_sys->i_page_size = p_vout->p_sys->i_width *
+ p_vout->p_sys->i_height * p_vout->p_sys->i_bytes_per_pixel;
+
+ /* Map a framebuffer at the beginning */
+ p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->i_page_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ p_vout->p_sys->i_fd, 0 );
+
+ if( p_vout->p_sys->p_video == ((void*)-1) )
+ {
+ msg_Err( p_vout, "cannot map video memory (%s)", strerror(errno) );
+
+ if( p_vout->p_sys->var_info.bits_per_pixel == 8 )
+ {
+ free( p_vout->p_sys->p_palette );
+ }
+
+ /* Restore fb config */
+ ioctl( p_vout->p_sys->i_fd,
+ FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
+
+ close( p_vout->p_sys->i_fd );
+ return( 1 );
+ }
+
+ msg_Dbg( p_vout, "framebuffer type=%d, visual=%d, ypanstep=%d, "
+ "ywrap=%d, accel=%d", fix_info.type, fix_info.visual,
+ fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CloseDisplay: terminate FB video thread output method
+ *****************************************************************************/
+static void CloseDisplay( vout_thread_t *p_vout )
+{
+ /* Clear display */
+ memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
+
+ /* Restore palette */
+ if( p_vout->p_sys->var_info.bits_per_pixel == 8 );
+ {
+ ioctl( p_vout->p_sys->i_fd,
+ FBIOPUTCMAP, &p_vout->p_sys->fb_cmap );
+ free( p_vout->p_sys->p_palette );
+ }
+
+ /* Restore fb config */
+ ioctl( p_vout->p_sys->i_fd,
+ FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
+
+ /* Close fb */
+ close( p_vout->p_sys->i_fd );
+}
+
+/*****************************************************************************
+ * SwitchDisplay: VT change signal handler
+ *****************************************************************************
+ * This function activates or deactivates the output of the thread. It is
+ * called by the VT driver, on terminal change.
+ *****************************************************************************/
+static void SwitchDisplay(int i_signal)
+{
+#if 0
+ vout_thread_t *p_vout;
+
+ vlc_mutex_lock( &p_vout_bank->lock );
+
+ /* XXX: only test the first video output */
+ if( p_vout_bank->i_count )
+ {
+ p_vout = p_vout_bank->pp_vout[0];
+
+ switch( i_signal )
+ {
+ case SIGUSR1: /* vt has been released */
+ p_vout->b_active = 0;
+ ioctl( p_vout->p_sys->i_tty, VT_RELDISP, 1 );
+ break;
+ case SIGUSR2: /* vt has been acquired */
+ p_vout->b_active = 1;
+ ioctl( p_vout->p_sys->i_tty, VT_RELDISP, VT_ACTIVATE );
+ /* handle blanking */
+ vlc_mutex_lock( &p_vout->change_lock );
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ vlc_mutex_unlock( &p_vout->change_lock );
+ break;
+ }
+ }
+
+ vlc_mutex_unlock( &p_vout_bank->lock );
+#endif
+}
+
+/*****************************************************************************
+ * TextMode and GfxMode : switch tty to text/graphic mode
+ *****************************************************************************
+ * These functions toggle the tty mode.
+ *****************************************************************************/
+static void TextMode( int i_tty )
+{
+ /* return to text mode */
+ if( -1 == ioctl(i_tty, KDSETMODE, KD_TEXT) )
+ {
+//X msg_Err( p_vout, "failed ioctl KDSETMODE KD_TEXT" );
+ }
+}
+
+static void GfxMode( int i_tty )
+{
+ /* switch to graphic mode */
+ if( -1 == ioctl(i_tty, KDSETMODE, KD_GRAPHICS) )
+ {
+//X msg_Err( p_vout, "failed ioctl KDSETMODE KD_GRAPHICS" );
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+ggi_SOURCES = ggi.c
--- /dev/null
+/*****************************************************************************
+ * ggi.c : GGI plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: ggi.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+#include <errno.h> /* ENOMEM */
+
+#include <ggi/ggi.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static int OpenDisplay ( vout_thread_t * );
+static void CloseDisplay ( vout_thread_t * );
+static void SetPalette ( vout_thread_t *, u16 *, u16 *, u16 * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define DISPLAY_TEXT N_("X11 display name")
+#define DISPLAY_LONGTEXT N_("Specify the X11 hardware display you want to use."\
+ "\nBy default vlc will use the value of the DISPLAY"\
+ " environment variable.")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( "ggi-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT );
+ set_description( "General Graphics Interface video output" );
+ set_capability( "video output", 30 );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: video output GGI method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the GGI specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ /* GGI system informations */
+ ggi_visual_t p_display; /* display device */
+
+ ggi_mode mode; /* mode descriptor */
+ int i_bits_per_pixel;
+
+ /* Buffer information */
+ ggi_directbuffer * pp_buffer[2]; /* buffers */
+ int i_index;
+
+ vlc_bool_t b_must_acquire; /* must be acquired before writing */
+};
+
+/*****************************************************************************
+ * Create: allocate GGI video thread output method
+ *****************************************************************************
+ * This function allocate and initialize a GGI vout method. It uses some of the
+ * vout properties to choose the correct mode, and change them according to the
+ * mode actually used.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Open and initialize device */
+ if( OpenDisplay( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot initialize GGI display" );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = Display;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize GGI video thread output method
+ *****************************************************************************
+ * This function initialize the GGI display device.
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+#define p_b p_vout->p_sys->pp_buffer
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ p_vout->output.i_width = p_vout->p_sys->mode.visible.x;
+ p_vout->output.i_height = p_vout->p_sys->mode.visible.y;
+ p_vout->output.i_aspect = p_vout->p_sys->mode.visible.x
+ * VOUT_ASPECT_FACTOR
+ / p_vout->p_sys->mode.visible.y;
+
+ switch( p_vout->p_sys->i_bits_per_pixel )
+ {
+ case 8:
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
+ p_vout->output.pf_setpalette = SetPalette;
+ break;
+ case 15:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break;
+ case 16:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break;
+ case 24:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break;
+ case 32:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break;
+ default:
+ msg_Err( p_vout, "unknown screen depth %i",
+ p_vout->p_sys->i_bits_per_pixel );
+ return 0;
+ }
+
+ /* Only useful for bits_per_pixel != 8 */
+ p_vout->output.i_rmask = p_b[ 0 ]->buffer.plb.pixelformat->red_mask;
+ p_vout->output.i_gmask = p_b[ 0 ]->buffer.plb.pixelformat->green_mask;
+ p_vout->output.i_bmask = p_b[ 0 ]->buffer.plb.pixelformat->blue_mask;
+
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ if( p_pic == NULL )
+ {
+ return 0;
+ }
+
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_vout->p_sys->i_index = 0;
+ p_pic->p->p_pixels = p_b[ 0 ]->write;
+ p_pic->p->i_pixel_pitch = p_b[ 0 ]->buffer.plb.pixelformat->size / 8;
+ p_pic->p->i_lines = p_vout->p_sys->mode.visible.y;
+
+ p_pic->p->i_pitch = p_b[ 0 ]->buffer.plb.stride;
+
+ if( p_b[ 0 ]->buffer.plb.pixelformat->size / 8
+ * p_vout->p_sys->mode.visible.x
+ != p_b[ 0 ]->buffer.plb.stride )
+ {
+ p_pic->p->i_visible_pitch = p_b[ 0 ]->buffer.plb.pixelformat->size
+ / 8 * p_vout->p_sys->mode.visible.x;
+ }
+ else
+ {
+ p_pic->p->i_visible_pitch = p_b[ 0 ]->buffer.plb.stride;
+ }
+
+ p_pic->i_planes = 1;
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+
+ /* Acquire first buffer */
+ if( p_vout->p_sys->b_must_acquire )
+ {
+ ggiResourceAcquire( p_b[ 0 ]->resource,
+ GGI_ACTYPE_WRITE );
+ }
+
+ /* Listen to the keyboard and the mouse buttons */
+ ggiSetEventMask( p_vout->p_sys->p_display,
+ emKeyboard | emPtrButtonPress | emPtrButtonRelease );
+
+ /* Set asynchronous display mode -- usually quite faster */
+ ggiAddFlags( p_vout->p_sys->p_display, GGIFLAG_ASYNC );
+
+ return( 0 );
+#undef p_b
+}
+
+/*****************************************************************************
+ * End: terminate GGI video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+#define p_b p_vout->p_sys->pp_buffer
+ /* Release buffer */
+ if( p_vout->p_sys->b_must_acquire )
+ {
+ ggiResourceRelease( p_b[ p_vout->p_sys->i_index ]->resource );
+ }
+#undef p_b
+}
+
+/*****************************************************************************
+ * Destroy: destroy GGI video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ CloseDisplay( p_vout );
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Manage: handle GGI events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It returns
+ * a non null value if an error occured.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ struct timeval tv = { 0, 1000 }; /* 1 millisecond */
+ gii_event_mask mask;
+ gii_event event;
+
+ mask = emKeyboard | emPtrButtonPress | emPtrButtonRelease;
+
+ ggiEventPoll( p_vout->p_sys->p_display, mask, &tv );
+
+ while( ggiEventsQueued( p_vout->p_sys->p_display, mask) )
+ {
+ ggiEventRead( p_vout->p_sys->p_display, &event, mask);
+
+ switch( event.any.type )
+ {
+ case evKeyRelease:
+
+ switch( event.key.sym )
+ {
+ case 'q':
+ case 'Q':
+ case GIIUC_Escape:
+ /* FIXME pass message ! */
+ p_vout->p_vlc->b_die = 1;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case evPtrButtonRelease:
+
+ switch( event.pbutton.button )
+ {
+ case GII_PBUTTON_RIGHT:
+ {
+ intf_thread_t *p_intf;
+ p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+ if( p_intf )
+ {
+ p_intf->b_menu_change = 1;
+ vlc_object_release( p_intf );
+ }
+ }
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+#define p_b p_vout->p_sys->pp_buffer
+ p_pic->p->p_pixels = p_b[ p_vout->p_sys->i_index ]->write;
+
+ /* Change display frame */
+ if( p_vout->p_sys->b_must_acquire )
+ {
+ ggiResourceRelease( p_b[ p_vout->p_sys->i_index ]->resource );
+ }
+ ggiSetDisplayFrame( p_vout->p_sys->p_display,
+ p_b[ p_vout->p_sys->i_index ]->frame );
+
+ /* Swap buffers and change write frame */
+ p_vout->p_sys->i_index ^= 1;
+ p_pic->p->p_pixels = p_b[ p_vout->p_sys->i_index ]->write;
+
+ if( p_vout->p_sys->b_must_acquire )
+ {
+ ggiResourceAcquire( p_b[ p_vout->p_sys->i_index ]->resource,
+ GGI_ACTYPE_WRITE );
+ }
+ ggiSetWriteFrame( p_vout->p_sys->p_display,
+ p_b[ p_vout->p_sys->i_index ]->frame );
+
+ /* Flush the output so that it actually displays */
+ ggiFlush( p_vout->p_sys->p_display );
+#undef p_b
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * OpenDisplay: open and initialize GGI device
+ *****************************************************************************
+ * Open and initialize display according to preferences specified in the vout
+ * thread fields.
+ *****************************************************************************/
+static int OpenDisplay( vout_thread_t *p_vout )
+{
+#define p_b p_vout->p_sys->pp_buffer
+ ggi_color col_fg; /* foreground color */
+ ggi_color col_bg; /* background color */
+ int i_index; /* all purposes index */
+ char *psz_display;
+
+ /* Initialize library */
+ if( ggiInit() )
+ {
+ msg_Err( p_vout, "cannot initialize GGI library" );
+ return( 1 );
+ }
+
+ /* Open display */
+ psz_display = config_GetPsz( p_vout, "ggi_display" );
+
+ p_vout->p_sys->p_display = ggiOpen( psz_display, NULL );
+ if( psz_display ) free( psz_display );
+
+ if( p_vout->p_sys->p_display == NULL )
+ {
+ msg_Err( p_vout, "cannot open GGI default display" );
+ ggiExit();
+ return( 1 );
+ }
+
+ /* Find most appropriate mode */
+ p_vout->p_sys->mode.frames = 2; /* 2 buffers */
+ p_vout->p_sys->mode.visible.x = config_GetInt( p_vout, "width" );
+ p_vout->p_sys->mode.visible.y = config_GetInt( p_vout, "height" );
+ p_vout->p_sys->mode.virt.x = GGI_AUTO;
+ p_vout->p_sys->mode.virt.y = GGI_AUTO;
+ p_vout->p_sys->mode.size.x = GGI_AUTO;
+ p_vout->p_sys->mode.size.y = GGI_AUTO;
+ p_vout->p_sys->mode.graphtype = GT_15BIT; /* minimum usable depth */
+ p_vout->p_sys->mode.dpp.x = GGI_AUTO;
+ p_vout->p_sys->mode.dpp.y = GGI_AUTO;
+ ggiCheckMode( p_vout->p_sys->p_display, &p_vout->p_sys->mode );
+
+ /* FIXME: Check that returned mode has some minimum properties */
+
+ /* Set mode */
+ if( ggiSetMode( p_vout->p_sys->p_display, &p_vout->p_sys->mode ) )
+ {
+ msg_Err( p_vout, "cannot set GGI mode" );
+ ggiClose( p_vout->p_sys->p_display );
+ ggiExit();
+ return( 1 );
+ }
+
+ /* Check buffers properties */
+ p_vout->p_sys->b_must_acquire = 0;
+ for( i_index = 0; i_index < 2; i_index++ )
+ {
+ /* Get buffer address */
+ p_vout->p_sys->pp_buffer[ i_index ] =
+ (ggi_directbuffer *)ggiDBGetBuffer( p_vout->p_sys->p_display,
+ i_index );
+ if( p_b[ i_index ] == NULL )
+ {
+ msg_Err( p_vout, "double buffering is not possible" );
+ ggiClose( p_vout->p_sys->p_display );
+ ggiExit();
+ return( 1 );
+ }
+
+ /* Check buffer properties */
+ if( ! ( p_b[ i_index ]->type & GGI_DB_SIMPLE_PLB )
+ || ( p_b[ i_index ]->page_size != 0 )
+ || ( p_b[ i_index ]->write == NULL )
+ || ( p_b[ i_index ]->noaccess != 0 )
+ || ( p_b[ i_index ]->align != 0 ) )
+ {
+ msg_Err( p_vout, "incorrect video memory type" );
+ ggiClose( p_vout->p_sys->p_display );
+ ggiExit();
+ return( 1 );
+ }
+
+ /* Check if buffer needs to be acquired before write */
+ if( ggiResourceMustAcquire( p_b[ i_index ]->resource ) )
+ {
+ p_vout->p_sys->b_must_acquire = 1;
+ }
+ }
+
+ /* Set graphic context colors */
+ col_fg.r = col_fg.g = col_fg.b = -1;
+ col_bg.r = col_bg.g = col_bg.b = 0;
+ if( ggiSetGCForeground(p_vout->p_sys->p_display,
+ ggiMapColor(p_vout->p_sys->p_display,&col_fg)) ||
+ ggiSetGCBackground(p_vout->p_sys->p_display,
+ ggiMapColor(p_vout->p_sys->p_display,&col_bg)) )
+ {
+ msg_Err( p_vout, "cannot set colors" );
+ ggiClose( p_vout->p_sys->p_display );
+ ggiExit();
+ return( 1 );
+ }
+
+ /* Set clipping for text */
+ if( ggiSetGCClipping( p_vout->p_sys->p_display, 0, 0,
+ p_vout->p_sys->mode.visible.x,
+ p_vout->p_sys->mode.visible.y ) )
+ {
+ msg_Err( p_vout, "cannot set clipping" );
+ ggiClose( p_vout->p_sys->p_display );
+ ggiExit();
+ return( 1 );
+ }
+
+ /* FIXME: set palette in 8bpp */
+ p_vout->p_sys->i_bits_per_pixel = p_b[ 0 ]->buffer.plb.pixelformat->depth;
+
+ return( 0 );
+#undef p_b
+}
+
+/*****************************************************************************
+ * CloseDisplay: close and reset GGI device
+ *****************************************************************************
+ * This function returns all resources allocated by OpenDisplay and restore
+ * the original state of the device.
+ *****************************************************************************/
+static void CloseDisplay( vout_thread_t *p_vout )
+{
+ /* Restore original mode and close display */
+ ggiClose( p_vout->p_sys->p_display );
+
+ /* Exit library */
+ ggiExit();
+}
+
+/*****************************************************************************
+ * SetPalette: sets an 8 bpp palette
+ *****************************************************************************/
+static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
+{
+ ggi_color colors[256];
+ int i;
+
+ /* Fill colors with color information */
+ for( i = 0; i < 256; i++ )
+ {
+ colors[ i ].r = red[ i ];
+ colors[ i ].g = green[ i ];
+ colors[ i ].b = blue[ i ];
+ colors[ i ].a = 0;
+ }
+
+ /* Set palette */
+ if( ggiSetPalette( p_vout->p_sys->p_display, 0, 256, colors ) < 0 )
+ {
+ msg_Err( p_vout, "failed setting palette" );
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+glide_SOURCES = glide.c
--- /dev/null
+/*****************************************************************************
+ * glide.c : 3dfx Glide plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: glide.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#ifndef __linux__
+# include <conio.h> /* for glide ? */
+#endif
+#include <glide.h>
+#include <linutil.h> /* Glide kbhit() and getch() */
+
+#define GLIDE_WIDTH 800
+#define GLIDE_HEIGHT 600
+#define GLIDE_BITS_PER_PLANE 16
+#define GLIDE_BYTES_PER_PIXEL 2
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static int OpenDisplay ( vout_thread_t * );
+static void CloseDisplay ( vout_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("3dfx Glide module") );
+ set_capability( "video output", 20 );
+ add_shortcut( "3dfx" );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: Glide video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Glide specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ GrLfbInfo_t p_buffer_info; /* back buffer info */
+
+ u8* pp_buffer[2];
+ int i_index;
+};
+
+/*****************************************************************************
+ * Create: allocates Glide video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Glide vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Open and initialize device */
+ if( OpenDisplay( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot open display" );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = Display;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize Glide video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ /* FIXME: we don't set i_chroma !! */
+ p_vout->output.i_rmask = 0xf800;
+ p_vout->output.i_gmask = 0x07e0;
+ p_vout->output.i_bmask = 0x001f;
+
+ I_OUTPUTPICTURES = 0;
+
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ if( p_pic == NULL )
+ {
+ return -1;
+ }
+
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_pic->i_planes = 1;
+
+ p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index];
+ p_pic->p->i_lines = GLIDE_HEIGHT;
+ p_pic->p->i_pitch = p_vout->p_sys->p_buffer_info.strideInBytes;
+ /*1024 * GLIDE_BYTES_PER_PIXEL*/
+ p_pic->p->i_pixel_pitch = GLIDE_BYTES_PER_PIXEL;
+ p_pic->p->i_visible_pitch = GLIDE_WIDTH * GLIDE_BYTES_PER_PIXEL;
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ 0 ] = p_pic;
+
+ I_OUTPUTPICTURES = 1;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * End: terminate Glide video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ ;
+}
+
+/*****************************************************************************
+ * Destroy: destroy Glide video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ CloseDisplay( p_vout );
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Manage: handle Glide events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * console events. It returns a non null value on error.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ int buf;
+
+ /* very Linux specific - see tlib.c in Glide for other versions */
+ while( kbhit() )
+ {
+ buf = getch();
+
+ switch( (char)buf )
+ {
+ case 'q':
+ p_vout->p_vlc->b_die = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+
+{
+ grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
+
+ grBufferSwap( 0 );
+
+ if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
+ GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
+ &p_vout->p_sys->p_buffer_info) == FXFALSE )
+ {
+ msg_Err( p_vout, "cannot take 3dfx back buffer lock" );
+ }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * OpenDisplay: open and initialize 3dfx device
+ *****************************************************************************/
+
+static int OpenDisplay( vout_thread_t *p_vout )
+{
+ static char version[80];
+ GrHwConfiguration hwconfig;
+ GrScreenResolution_t resolution = GR_RESOLUTION_800x600;
+ GrLfbInfo_t p_front_buffer_info; /* front buffer info */
+
+ grGlideGetVersion( version );
+ grGlideInit();
+
+ if( !grSstQueryHardware(&hwconfig) )
+ {
+ msg_Err( p_vout, "cannot get 3dfx hardware config" );
+ return( 1 );
+ }
+
+ grSstSelect( 0 );
+ if( !grSstWinOpen( 0, resolution, GR_REFRESH_60Hz,
+ GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1 ) )
+ {
+ msg_Err( p_vout, "cannot open 3dfx screen" );
+ return( 1 );
+ }
+
+ /* disable dithering */
+ //grDitherMode( GR_DITHER_DISABLE );
+
+ /* clear both buffers */
+ grRenderBuffer( GR_BUFFER_BACKBUFFER );
+ grBufferClear( 0, 0, 0 );
+ grRenderBuffer( GR_BUFFER_FRONTBUFFER );
+ grBufferClear( 0, 0, 0 );
+ grRenderBuffer( GR_BUFFER_BACKBUFFER );
+
+ p_vout->p_sys->p_buffer_info.size = sizeof( GrLfbInfo_t );
+ p_front_buffer_info.size = sizeof( GrLfbInfo_t );
+
+ /* lock the buffers to find their adresses */
+ if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER,
+ GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
+ &p_front_buffer_info) == FXFALSE )
+ {
+ msg_Err( p_vout, "cannot take 3dfx front buffer lock" );
+ grGlideShutdown();
+ return( 1 );
+ }
+ grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER );
+
+ if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
+ GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
+ &p_vout->p_sys->p_buffer_info) == FXFALSE )
+ {
+ msg_Err( p_vout, "cannot take 3dfx back buffer lock" );
+ grGlideShutdown();
+ return( 1 );
+ }
+ grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
+
+ grBufferClear( 0, 0, 0 );
+
+ p_vout->p_sys->pp_buffer[0] = p_vout->p_sys->p_buffer_info.lfbPtr;
+ p_vout->p_sys->pp_buffer[1] = p_front_buffer_info.lfbPtr;
+ p_vout->p_sys->i_index = 0;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CloseDisplay: close and reset 3dfx device
+ *****************************************************************************
+ * Returns all resources allocated by OpenDisplay and restore the original
+ * state of the device.
+ *****************************************************************************/
+static void CloseDisplay( vout_thread_t *p_vout )
+{
+ /* unlock the hidden buffer */
+ grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
+
+ /* shutdown Glide */
+ grGlideShutdown();
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+mga_SOURCES = mga.c
+xmga_SOURCES = xmga.c
--- /dev/null
+/*****************************************************************************
+ * mga.c : Matrox Graphic Array plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: mga.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <unistd.h> /* close() */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+#include <fcntl.h> /* open() */
+#include <sys/ioctl.h> /* ioctl() */
+#include <sys/mman.h> /* PROT_WRITE */
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#ifdef SYS_BSD
+#include <sys/types.h> /* typedef ushort */
+#endif
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static int NewPicture ( vout_thread_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Matrox Graphic Array video module") );
+ set_capability( "video output", 10 );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: video output MGA method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the MGA specific properties of an output thread.
+ *****************************************************************************/
+#ifndef __LINUX_MGAVID_H
+# define __LINUX_MGAVID_H
+
+# define MGA_VID_CONFIG _IOR('J', 1, mga_vid_config_t)
+# define MGA_VID_ON _IO ('J', 2)
+# define MGA_VID_OFF _IO ('J', 3)
+# define MGA_VID_FSEL _IOR('J', 4, int)
+# define MGA_G200 0x1234
+# define MGA_G400 0x5678
+
+# define MGA_VID_FORMAT_YV12 0x32315659
+# define MGA_VID_FORMAT_IYUV (('I'<<24)|('Y'<<16)|('U'<<8)|'V')
+# define MGA_VID_FORMAT_I420 (('I'<<24)|('4'<<16)|('2'<<8)|'0')
+# define MGA_VID_FORMAT_YUY2 (('Y'<<24)|('U'<<16)|('Y'<<8)|'2')
+# define MGA_VID_FORMAT_UYVY (('U'<<24)|('Y'<<16)|('V'<<8)|'Y')
+
+# define MGA_VID_VERSION 0x0201
+
+# define MGA_NUM_FRAMES 1
+
+typedef struct mga_vid_config_t
+{
+ u16 version;
+ u16 card_type;
+ u32 ram_size;
+ u32 src_width;
+ u32 src_height;
+ u32 dest_width;
+ u32 dest_height;
+ u32 x_org;
+ u32 y_org;
+ u8 colkey_on;
+ u8 colkey_red;
+ u8 colkey_green;
+ u8 colkey_blue;
+ u32 format;
+ u32 frame_size;
+ u32 num_frames;
+} mga_vid_config_t;
+#endif
+
+struct vout_sys_t
+{
+ mga_vid_config_t mga;
+ int i_fd;
+ byte_t * p_video;
+};
+
+struct picture_sys_t
+{
+ int i_frame;
+};
+
+#define CEIL32(x) (((x)+31)&~31)
+
+/*****************************************************************************
+ * Create: allocates dummy video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a dummy vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ p_vout->p_sys->i_fd = open( "/dev/mga_vid", O_RDWR );
+ if( p_vout->p_sys->i_fd == -1 )
+ {
+ msg_Err( p_vout, "cannot open MGA driver /dev/mga_vid" );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = NULL;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = Display;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize dummy video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* create the MGA output */
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ /* Set coordinates and aspect ratio */
+ p_vout->p_sys->mga.src_width = CEIL32(p_vout->output.i_width);
+ p_vout->p_sys->mga.src_height = p_vout->output.i_height;
+ vout_PlacePicture( p_vout, 1024, 768,
+ &p_vout->p_sys->mga.x_org, &p_vout->p_sys->mga.y_org,
+ &p_vout->p_sys->mga.dest_width,
+ &p_vout->p_sys->mga.dest_height );
+
+ /* Initialize a video buffer */
+ p_vout->p_sys->mga.colkey_on = 0;
+ p_vout->p_sys->mga.num_frames = MGA_NUM_FRAMES;
+ p_vout->p_sys->mga.frame_size = CEIL32(p_vout->output.i_width)
+ * p_vout->output.i_height * 2;
+ p_vout->p_sys->mga.version = MGA_VID_VERSION;
+
+ /* Assume we only do YMGA for the moment. XXX: mga_vid calls this
+ * YV12, but it's actually some strange format with packed UV. */
+ p_vout->output.i_chroma = VLC_FOURCC('Y','M','G','A');
+ p_vout->p_sys->mga.format = MGA_VID_FORMAT_YV12;
+
+ if( ioctl(p_vout->p_sys->i_fd, MGA_VID_CONFIG, &p_vout->p_sys->mga) )
+ {
+ msg_Err( p_vout, "MGA config ioctl failed" );
+ return -1;
+ }
+
+ if( p_vout->p_sys->mga.card_type == MGA_G200 )
+ {
+ msg_Dbg( p_vout, "detected MGA G200 (%d MB Ram)",
+ p_vout->p_sys->mga.ram_size );
+ }
+ else
+ {
+ msg_Dbg( p_vout, "detected MGA G400/G450 (%d MB Ram)",
+ p_vout->p_sys->mga.ram_size );
+ }
+
+ p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->mga.frame_size
+ * MGA_NUM_FRAMES,
+ PROT_WRITE, MAP_SHARED,
+ p_vout->p_sys->i_fd, 0 );
+
+ /* Try to initialize up to MGA_NUM_FRAMES direct buffers */
+ while( I_OUTPUTPICTURES < MGA_NUM_FRAMES )
+ {
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture */
+ if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
+ {
+ break;
+ }
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ /* Blank the windows */
+ for( i_index = 0; i_index < I_OUTPUTPICTURES; i_index++ )
+ {
+ memset( p_vout->p_sys->p_video
+ + p_vout->p_sys->mga.frame_size * i_index,
+ 0x00, p_vout->p_sys->mga.frame_size / 2 );
+ memset( p_vout->p_sys->p_video
+ + p_vout->p_sys->mga.frame_size * ( 2*i_index + 1 ) / 2,
+ 0x80, p_vout->p_sys->mga.frame_size / 2 );
+ }
+
+ /* Display the image */
+ ioctl( p_vout->p_sys->i_fd, MGA_VID_ON, 0 );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate dummy video thread output method
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ ioctl( p_vout->p_sys->i_fd, MGA_VID_OFF, 0 );
+
+ /* Free the output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ }
+}
+
+/*****************************************************************************
+ * Destroy: destroy dummy video thread output method
+ *****************************************************************************
+ * Terminate an output method created by DummyCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ close( p_vout->p_sys->i_fd );
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ ioctl( p_vout->p_sys->i_fd, MGA_VID_FSEL, &p_pic->p_sys->i_frame );
+}
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * NewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_pic->p_data = p_vout->p_sys->p_video + I_OUTPUTPICTURES
+ * p_vout->p_sys->mga.frame_size;
+
+ p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+ if( p_pic->p_sys == NULL )
+ {
+ return -1;
+ }
+
+ p_pic->Y_PIXELS = p_pic->p_data;
+ p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
+ p_pic->p[Y_PLANE].i_pitch = CEIL32( p_vout->output.i_width );
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width;
+
+ p_pic->U_PIXELS = p_pic->p_data + p_vout->p_sys->mga.frame_size * 2/4;
+ p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[U_PLANE].i_pitch = CEIL32( p_vout->output.i_width ) / 2;
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+
+ p_pic->V_PIXELS = p_pic->p_data + p_vout->p_sys->mga.frame_size * 3/4;
+ p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[V_PLANE].i_pitch = CEIL32( p_vout->output.i_width ) / 2;
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+
+ p_pic->p_sys->i_frame = I_OUTPUTPICTURES;
+
+ p_pic->i_planes = 3;
+
+ return 0;
+}
+
--- /dev/null
+/*****************************************************************************
+ * xmga.c : X11 MGA plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: xmga.c,v 1.1 2002/08/04 17:23:43 sam Exp $
+ *
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#ifdef HAVE_MACHINE_PARAM_H
+/* BSD */
+#include <machine/param.h>
+#include <sys/types.h> /* typedef ushort */
+#include <sys/ipc.h>
+#endif
+
+#ifndef WIN32
+#include <netinet/in.h> /* BSD: struct in_addr */
+#endif
+
+#include <sys/shm.h> /* shmget(), shmctl() */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/dpms.h>
+
+#include "netutils.h" /* network_ChannelJoin */
+
+//#include "mga.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Create ( vlc_object_t * );
+static void Destroy ( vlc_object_t * );
+
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void MGADisplay( vout_thread_t *, picture_t * );
+
+static int CreateWindow ( vout_thread_t * );
+static void DestroyWindow ( vout_thread_t * );
+
+static int NewPicture ( vout_thread_t *, picture_t * );
+static void FreePicture ( vout_thread_t *, picture_t * );
+
+static void ToggleFullScreen ( vout_thread_t * );
+
+static void EnableXScreenSaver ( vout_thread_t * );
+static void DisableXScreenSaver ( vout_thread_t * );
+
+static void CreateCursor ( vout_thread_t * );
+static void DestroyCursor ( vout_thread_t * );
+static void ToggleCursor ( vout_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+#define ALT_FS_TEXT N_("alternate fullscreen method")
+#define ALT_FS_LONGTEXT N_( \
+ "There are two ways to make a fullscreen window, unfortunately each one " \
+ "has its drawbacks.\n" \
+ "1) Let the window manager handle your fullscreen window (default). But " \
+ "things like taskbars will likely show on top of the video.\n" \
+ "2) Completly bypass the window manager, but then nothing will be able " \
+ "to show on top of the video.")
+
+#define DISPLAY_TEXT N_("X11 display name")
+#define DISPLAY_LONGTEXT N_( \
+ "Specify the X11 hardware display you want to use. By default vlc will " \
+ "use the value of the DISPLAY environment variable.")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( "xmga-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT );
+ add_bool( "xmga-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT );
+ set_description( _("X11 MGA module") );
+ set_capability( "video output", 60 );
+ set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*****************************************************************************
+ * vout_sys_t: video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the X11 and XVideo specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ /* Internal settings and properties */
+ Display * p_display; /* display pointer */
+
+ Visual * p_visual; /* visual pointer */
+ int i_screen; /* screen number */
+ Window window; /* root window */
+ GC gc; /* graphic context instance handler */
+
+ vlc_bool_t b_shm; /* shared memory extension flag */
+
+#ifdef MODULE_NAME_IS_xvideo
+ Window yuv_window; /* sub-window for displaying yuv video
+ data */
+ int i_xvport;
+#else
+ Colormap colormap; /* colormap used (8bpp only) */
+
+ int i_screen_depth;
+ int i_bytes_per_pixel;
+ int i_bytes_per_line;
+ int i_red_mask;
+ int i_green_mask;
+ int i_blue_mask;
+#endif
+
+ /* X11 generic properties */
+ Atom wm_protocols;
+ Atom wm_delete_window;
+
+ int i_width; /* width of main window */
+ int i_height; /* height of main window */
+ vlc_bool_t b_altfullscreen; /* which fullscreen method */
+
+ /* Backup of window position and size before fullscreen switch */
+ int i_width_backup;
+ int i_height_backup;
+ int i_xpos_backup;
+ int i_ypos_backup;
+ int i_width_backup_2;
+ int i_height_backup_2;
+ int i_xpos_backup_2;
+ int i_ypos_backup_2;
+
+ /* Screen saver properties */
+ int i_ss_timeout; /* timeout */
+ int i_ss_interval; /* interval between changes */
+ int i_ss_blanking; /* blanking mode */
+ int i_ss_exposure; /* exposure mode */
+ BOOL b_ss_dpms; /* DPMS mode */
+
+ /* Mouse pointer properties */
+ vlc_bool_t b_mouse_pointer_visible;
+ mtime_t i_time_mouse_last_moved; /* used to auto-hide pointer*/
+ Cursor blank_cursor; /* the hidden cursor */
+ mtime_t i_time_button_last_pressed; /* to track dbl-clicks */
+ Pixmap cursor_pixmap;
+};
+
+/*****************************************************************************
+ * mwmhints_t: window manager hints
+ *****************************************************************************
+ * Fullscreen needs to be able to hide the wm decorations so we provide
+ * this structure to make it easier.
+ *****************************************************************************/
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define PROP_MWM_HINTS_ELEMENTS 5
+typedef struct mwmhints_t
+{
+ u32 flags;
+ u32 functions;
+ u32 decorations;
+ s32 input_mode;
+ u32 status;
+} mwmhints_t;
+
+/*****************************************************************************
+ * Chroma defines
+ *****************************************************************************/
+#ifdef MODULE_NAME_IS_xvideo
+# define MAX_DIRECTBUFFERS 5
+#else
+# define MAX_DIRECTBUFFERS 2
+#endif
+
+/*****************************************************************************
+ * Create: allocate X11 video thread output method
+ *****************************************************************************
+ * This function allocate and initialize a X11 vout method. It uses some of the
+ * vout properties to choose the window size, and change them according to the
+ * actual properties of the display.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ char *psz_display;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Open display, unsing the "display" config variable or the DISPLAY
+ * environment variable */
+ psz_display = config_GetPsz( p_vout, "xmga-display" );
+ p_vout->p_sys->p_display = XOpenDisplay( psz_display );
+
+ if( p_vout->p_sys->p_display == NULL ) /* error */
+ {
+ msg_Err( p_vout, "cannot open display %s",
+ XDisplayName( psz_display ) );
+ free( p_vout->p_sys );
+ if( psz_display ) free( psz_display );
+ return( 1 );
+ }
+ if( psz_display ) free( psz_display );
+
+ p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
+
+ /* Create blank cursor (for mouse cursor autohiding) */
+ p_vout->p_sys->b_mouse_pointer_visible = 1;
+ CreateCursor( p_vout );
+
+ /* Spawn base window - this window will include the video output window,
+ * but also command buttons, subtitles and other indicators */
+ if( CreateWindow( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot create X11 window" );
+ DestroyCursor( p_vout );
+ XCloseDisplay( p_vout->p_sys->p_display );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ /* Disable screen saver */
+ DisableXScreenSaver( p_vout );
+
+ /* Misc init */
+ p_vout->p_sys->b_altfullscreen = 0;
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = MGADisplay;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Destroy: destroy X11 video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* Restore cursor if it was blanked */
+ if( !p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ }
+
+ DestroyCursor( p_vout );
+ EnableXScreenSaver( p_vout );
+ DestroyWindow( p_vout );
+
+ XCloseDisplay( p_vout->p_sys->p_display );
+
+ /* Destroy structure */
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Init: initialize X11 video thread output method
+ *****************************************************************************
+ * This function create the XImages needed by the output thread. It is called
+ * at the beginning of the thread, but also each time the window is resized.
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+#ifdef MODULE_NAME_IS_xvideo
+ /* Initialize the output structure; we already found an XVideo port,
+ * and the corresponding chroma we will be using. Since we can
+ * arbitrary scale, stick to the coordinates and aspect. */
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+#else
+ /* Initialize the output structure: RGB with square pixels, whatever
+ * the input format is, since it's the only format we know */
+ switch( p_vout->p_sys->i_screen_depth )
+ {
+ case 8: /* FIXME: set the palette */
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); break;
+ case 15:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break;
+ case 16:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break;
+ case 24:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break;
+ case 32:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break;
+ default:
+ msg_Err( p_vout, "unknown screen depth %i",
+ p_vout->p_sys->i_screen_depth );
+ return( 0 );
+ }
+
+ p_vout->output.i_width = p_vout->p_sys->i_width;
+ p_vout->output.i_height = p_vout->p_sys->i_height;
+
+ /* Assume we have square pixels */
+ p_vout->output.i_aspect = p_vout->p_sys->i_width
+ * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
+#endif
+
+ /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
+ while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
+ {
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture */
+ if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
+ {
+ break;
+ }
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * MGADisplay: displays previously rendered output
+ *****************************************************************************
+ * This function sends the currently rendered image to X11 server.
+ * (The Xv extension takes care of "double-buffering".)
+ *****************************************************************************/
+static void MGADisplay( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ int i_width, i_height, i_x, i_y;
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+}
+
+/*****************************************************************************
+ * Manage: handle X11 events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * X11 events and allows window resizing. It returns a non null value on
+ * error.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ XEvent xevent; /* X11 event */
+ vlc_bool_t b_resized; /* window has been resized */
+ char i_key; /* ISO Latin-1 key */
+ KeySym x_key_symbol;
+
+ /* Handle X11 events: ConfigureNotify events are parsed to know if the
+ * output window's size changed, MapNotify and UnmapNotify to know if the
+ * window is mapped (and if the display is useful), and ClientMessages
+ * to intercept window destruction requests */
+
+ b_resized = 0;
+ while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask | KeyPressMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | Button1MotionMask , &xevent )
+ == True )
+ {
+ /* ConfigureNotify event: prepare */
+ if( (xevent.type == ConfigureNotify)
+ && ((xevent.xconfigure.width != p_vout->p_sys->i_width)
+ || (xevent.xconfigure.height != p_vout->p_sys->i_height)) )
+ {
+ /* Update dimensions */
+ b_resized = 1;
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ p_vout->p_sys->i_width = xevent.xconfigure.width;
+ p_vout->p_sys->i_height = xevent.xconfigure.height;
+ }
+ /* Keyboard event */
+ else if( xevent.type == KeyPress )
+ {
+ /* We may have keys like F1 trough F12, ESC ... */
+ x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
+ xevent.xkey.keycode, 0 );
+ switch( x_key_symbol )
+ {
+ case XK_Escape:
+ p_vout->p_vlc->b_die = 1;
+ break;
+ case XK_Menu:
+ p_vout->p_vlc->p_intf->b_menu_change = 1;
+ break;
+ case XK_Left:
+ input_Seek( p_vout, -5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Right:
+ input_Seek( p_vout, 5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Up:
+ input_Seek( p_vout, 60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Down:
+ input_Seek( p_vout, -60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Home:
+ input_Seek( p_vout, 0, INPUT_SEEK_BYTES | INPUT_SEEK_SET );
+ break;
+ case XK_End:
+ input_Seek( p_vout, 0, INPUT_SEEK_BYTES | INPUT_SEEK_END );
+ break;
+ case XK_Page_Up:
+ input_Seek( p_vout, 900, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Page_Down:
+ input_Seek( p_vout, -900, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_space:
+ input_SetStatus( p_input_bank->pp_input[0],
+ INPUT_STATUS_PAUSE );
+ break;
+
+ case XK_F1: network_ChannelJoin( p_vout, 1 ); break;
+ case XK_F2: network_ChannelJoin( p_vout, 2 ); break;
+ case XK_F3: network_ChannelJoin( p_vout, 3 ); break;
+ case XK_F4: network_ChannelJoin( p_vout, 4 ); break;
+ case XK_F5: network_ChannelJoin( p_vout, 5 ); break;
+ case XK_F6: network_ChannelJoin( p_vout, 6 ); break;
+ case XK_F7: network_ChannelJoin( p_vout, 7 ); break;
+ case XK_F8: network_ChannelJoin( p_vout, 8 ); break;
+ case XK_F9: network_ChannelJoin( p_vout, 9 ); break;
+ case XK_F10: network_ChannelJoin( p_vout, 10 ); break;
+ case XK_F11: network_ChannelJoin( p_vout, 11 ); break;
+ case XK_F12: network_ChannelJoin( p_vout, 12 ); break;
+
+ default:
+ /* "Normal Keys"
+ * The reason why I use this instead of XK_0 is that
+ * with XLookupString, we don't have to care about
+ * keymaps. */
+
+ if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
+ {
+ /* FIXME: handle stuff here */
+ switch( i_key )
+ {
+ case 'q':
+ case 'Q':
+ p_vout->p_vlc->b_die = 1;
+ break;
+ case 'f':
+ case 'F':
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ }
+ /* Mouse click */
+ else if( xevent.type == ButtonPress )
+ {
+ switch( ((XButtonEvent *)&xevent)->button )
+ {
+ case Button1:
+ /* In this part we will eventually manage
+ * clicks for DVD navigation for instance. */
+
+ /* detect double-clicks */
+ if( ( ((XButtonEvent *)&xevent)->time -
+ p_vout->p_sys->i_time_button_last_pressed ) < 300 )
+ {
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ }
+
+ p_vout->p_sys->i_time_button_last_pressed =
+ ((XButtonEvent *)&xevent)->time;
+ break;
+
+ case Button4:
+ input_Seek( p_vout, 15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+
+ case Button5:
+ input_Seek( p_vout, -15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ }
+ }
+ /* Mouse release */
+ else if( xevent.type == ButtonRelease )
+ {
+ switch( ((XButtonEvent *)&xevent)->button )
+ {
+ case Button3:
+ /* FIXME: need locking ! */
+ p_vout->p_vlc->p_intf->b_menu_change = 1;
+ break;
+ }
+ }
+ /* Mouse move */
+ else if( xevent.type == MotionNotify )
+ {
+ p_vout->p_sys->i_time_mouse_last_moved = mdate();
+ if( ! p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ }
+ }
+ /* Other event */
+ else
+ {
+ msg_Warn( p_vout, "unhandled event %d received", xevent.type );
+ }
+ }
+
+ /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
+ * are handled - according to the man pages, the format is always 32
+ * in this case */
+ while( XCheckTypedEvent( p_vout->p_sys->p_display,
+ ClientMessage, &xevent ) )
+ {
+ if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
+ && (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
+ {
+ p_vout->p_vlc->b_die = 1;
+ }
+ }
+
+ /*
+ * Fullscreen Change
+ */
+ if ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+ {
+ ToggleFullScreen( p_vout );
+ p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+
+ }
+
+ /*
+ * Size change
+ */
+ if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+ {
+ int i_width, i_height, i_x, i_y;
+
+ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+
+ msg_Dbg( p_vout, "video display resized (%dx%d)",
+ p_vout->p_sys->i_width, p_vout->p_sys->i_height );
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
+ p_vout->p_sys->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+ }
+
+ /* Autohide Cursour */
+ if( mdate() - p_vout->p_sys->i_time_mouse_last_moved > 2000000 )
+ {
+ /* Hide the mouse automatically */
+ if( p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * End: terminate X11 video thread output method
+ *****************************************************************************
+ * Destroy the X11 XImages created by Init. It is called at the end of
+ * the thread, but also each time the window is resized.
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the direct buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
+ }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * CreateWindow: open and set-up X11 main window
+ *****************************************************************************/
+static int CreateWindow( vout_thread_t *p_vout )
+{
+ XSizeHints xsize_hints;
+ XSetWindowAttributes xwindow_attributes;
+ XGCValues xgcvalues;
+ XEvent xevent;
+
+ vlc_bool_t b_expose;
+ vlc_bool_t b_configure_notify;
+ vlc_bool_t b_map_notify;
+
+ /* Set main window's size */
+ p_vout->p_sys->i_width = p_vout->i_window_width;
+ p_vout->p_sys->i_height = p_vout->i_window_height;
+
+ /* Prepare window manager hints and properties */
+ xsize_hints.base_width = p_vout->p_sys->i_width;
+ xsize_hints.base_height = p_vout->p_sys->i_height;
+ xsize_hints.flags = PSize;
+ p_vout->p_sys->wm_protocols = XInternAtom( p_vout->p_sys->p_display,
+ "WM_PROTOCOLS", True );
+ p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
+ "WM_DELETE_WINDOW", True );
+
+ /* Prepare window attributes */
+ xwindow_attributes.backing_store = Always; /* save the hidden part */
+ xwindow_attributes.background_pixel = BlackPixel(p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen);
+ xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
+
+
+ /* Create the window and set hints - the window must receive
+ * ConfigureNotify events, and until it is displayed, Expose and
+ * MapNotify events. */
+
+ p_vout->p_sys->window =
+ XCreateWindow( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 0, 0,
+ p_vout->p_sys->i_width,
+ p_vout->p_sys->i_height,
+ 0,
+ 0, InputOutput, 0,
+ CWBackingStore | CWBackPixel | CWEventMask,
+ &xwindow_attributes );
+
+ /* Set window manager hints and properties: size hints, command,
+ * window's name, and accepted protocols */
+ XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ &xsize_hints );
+ XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ p_vout->p_vlc->ppsz_argv, p_vout->p_vlc->i_argc );
+ XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ VOUT_TITLE " (XMGA output)"
+ );
+
+ if( (p_vout->p_sys->wm_protocols == None) /* use WM_DELETE_WINDOW */
+ || (p_vout->p_sys->wm_delete_window == None)
+ || !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ &p_vout->p_sys->wm_delete_window, 1 ) )
+ {
+ /* WM_DELETE_WINDOW is not supported by window manager */
+ msg_Err( p_vout, "missing or bad window manager" );
+ }
+
+ /* Creation of a graphic context that doesn't generate a GraphicsExpose
+ * event when using functions like XCopyArea */
+ xgcvalues.graphics_exposures = False;
+ p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ GCGraphicsExposures, &xgcvalues);
+
+ /* Send orders to server, and wait until window is displayed - three
+ * events must be received: a MapNotify event, an Expose event allowing
+ * drawing in the window, and a ConfigureNotify to get the window
+ * dimensions. Once those events have been received, only ConfigureNotify
+ * events need to be received. */
+ b_expose = 0;
+ b_configure_notify = 0;
+ b_map_notify = 0;
+ XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
+ do
+ {
+ XNextEvent( p_vout->p_sys->p_display, &xevent);
+ if( (xevent.type == Expose)
+ && (xevent.xexpose.window == p_vout->p_sys->window) )
+ {
+ b_expose = 1;
+ }
+ else if( (xevent.type == MapNotify)
+ && (xevent.xmap.window == p_vout->p_sys->window) )
+ {
+ b_map_notify = 1;
+ }
+ else if( (xevent.type == ConfigureNotify)
+ && (xevent.xconfigure.window == p_vout->p_sys->window) )
+ {
+ b_configure_notify = 1;
+ p_vout->p_sys->i_width = xevent.xconfigure.width;
+ p_vout->p_sys->i_height = xevent.xconfigure.height;
+ }
+ } while( !( b_expose && b_configure_notify && b_map_notify ) );
+
+ XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask | KeyPressMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask );
+
+ /* If the cursor was formerly blank than blank it again */
+ if( !p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ ToggleCursor( p_vout );
+ }
+
+ XSync( p_vout->p_sys->p_display, False );
+
+ /* At this stage, the window is open, displayed, and ready to
+ * receive data */
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * DestroyWindow: destroy the window
+ *****************************************************************************
+ *
+ *****************************************************************************/
+static void DestroyWindow( vout_thread_t *p_vout )
+{
+ XSync( p_vout->p_sys->p_display, False );
+
+ XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
+ XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
+ XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
+}
+
+/*****************************************************************************
+ * NewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ switch( p_vout->output.i_chroma )
+ {
+ /* XXX ?? */
+
+ default:
+ /* Unknown chroma, tell the guy to get lost */
+ msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
+ p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );
+ p_pic->i_planes = 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreePicture: destroy a picture allocated with NewPicture
+ *****************************************************************************
+ * Destroy XImage AND associated data. If using Shm, detach shared memory
+ * segment from server and process, then free it. The XDestroyImage manpage
+ * says that both the image structure _and_ the data pointed to by the
+ * image structure are freed, so no need to free p_image->data.
+ *****************************************************************************/
+static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ XSync( p_vout->p_sys->p_display, False );
+}
+
+/*****************************************************************************
+ * ToggleFullScreen: Enable or disable full screen mode
+ *****************************************************************************
+ * This function will switch between fullscreen and window mode.
+ *
+ *****************************************************************************/
+static void ToggleFullScreen ( vout_thread_t *p_vout )
+{
+ Atom prop;
+ mwmhints_t mwmhints;
+ int i_xpos, i_ypos, i_width, i_height;
+ XEvent xevent;
+ XSetWindowAttributes attributes;
+
+ p_vout->b_fullscreen = !p_vout->b_fullscreen;
+
+ if( p_vout->b_fullscreen )
+ {
+ Window next_parent, parent, *p_dummy, dummy1;
+ unsigned int dummy2, dummy3;
+
+ msg_Dbg( p_vout, "entering fullscreen mode" );
+
+ /* Only check the fullscreen method when we actually go fullscreen,
+ * because to go back to window mode we need to know in which
+ * fullscreen mode we where */
+ p_vout->p_sys->b_altfullscreen = config_GetInt( p_vout,
+ "xmga-altfullscreen" );
+
+ /* Save current window coordinates so they can be restored when
+ * we exit from fullscreen mode. This is the tricky part because
+ * this heavily depends on the behaviour of the window manager.
+ * When you use XMoveWindow some window managers will adjust the top
+ * of the window to the coordinates you gave, but others will instead
+ * adjust the top of the client area to the coordinates
+ * (don't forget windows have decorations). */
+
+ /* First, get the position and size of the client area */
+ XGetGeometry( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ &dummy1,
+ &dummy2,
+ &dummy3,
+ &p_vout->p_sys->i_width_backup_2,
+ &p_vout->p_sys->i_height_backup_2,
+ &dummy2, &dummy3 );
+ XTranslateCoordinates( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 0,
+ 0,
+ &p_vout->p_sys->i_xpos_backup_2,
+ &p_vout->p_sys->i_ypos_backup_2,
+ &dummy1 );
+
+ /* Then try to get the position and size of the whole window */
+
+ /* find the real parent of our window (created by the window manager),
+ * the one which is a direct child of the root window */
+ next_parent = parent = p_vout->p_sys->window;
+ while( next_parent != DefaultRootWindow( p_vout->p_sys->p_display ) )
+ {
+ parent = next_parent;
+ XQueryTree( p_vout->p_sys->p_display,
+ parent,
+ &dummy1,
+ &next_parent,
+ &p_dummy,
+ &dummy2 );
+ XFree((void *)p_dummy);
+ }
+
+ XGetGeometry( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ &dummy1,
+ &dummy2,
+ &dummy3,
+ &p_vout->p_sys->i_width_backup,
+ &p_vout->p_sys->i_height_backup,
+ &dummy2, &dummy3 );
+
+ XTranslateCoordinates( p_vout->p_sys->p_display,
+ parent,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 0,
+ 0,
+ &p_vout->p_sys->i_xpos_backup,
+ &p_vout->p_sys->i_ypos_backup,
+ &dummy1 );
+
+ /* fullscreen window size and position */
+ i_xpos = 0;
+ i_ypos = 0;
+ i_width = DisplayWidth( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen );
+ i_height = DisplayHeight( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen );
+
+ }
+ else
+ {
+ msg_Dbg( p_vout, "leaving fullscreen mode" );
+
+ i_xpos = p_vout->p_sys->i_xpos_backup;
+ i_ypos = p_vout->p_sys->i_ypos_backup;
+ i_width = p_vout->p_sys->i_width_backup;
+ i_height = p_vout->p_sys->i_height_backup;
+ }
+
+ /* To my knowledge there are two ways to create a borderless window.
+ * There's the generic way which is to tell x to bypass the window manager,
+ * but this creates problems with the focus of other applications.
+ * The other way is to use the motif property "_MOTIF_WM_HINTS" which
+ * luckily seems to be supported by most window managers.
+ */
+ if( !p_vout->p_sys->b_altfullscreen )
+ {
+ mwmhints.flags = MWM_HINTS_DECORATIONS;
+ mwmhints.decorations = !p_vout->b_fullscreen;
+
+ prop = XInternAtom( p_vout->p_sys->p_display, "_MOTIF_WM_HINTS",
+ False );
+ XChangeProperty( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ prop, prop, 32, PropModeReplace,
+ (unsigned char *)&mwmhints,
+ PROP_MWM_HINTS_ELEMENTS );
+ }
+ else
+ {
+ /* brute force way to remove decorations */
+ attributes.override_redirect = p_vout->b_fullscreen;
+ XChangeWindowAttributes( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ CWOverrideRedirect,
+ &attributes);
+ }
+
+ /* We need to unmap and remap the window if we want the window
+ * manager to take our changes into effect */
+ XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
+
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+ while( xevent.type != UnmapNotify )
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+
+ XMapRaised( p_vout->p_sys->p_display, p_vout->p_sys->window);
+
+ while( xevent.type != MapNotify )
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+
+ XMoveResizeWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ i_xpos,
+ i_ypos,
+ i_width,
+ i_height );
+
+ /* Purge all ConfigureNotify events, this is needed to fix a bug where we
+ * would lose the original size of the window */
+ while( xevent.type != ConfigureNotify )
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+ while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent ) );
+
+
+ /* We need to check that the window was really restored where we wanted */
+ if( !p_vout->b_fullscreen )
+ {
+ Window dummy1;
+ unsigned int dummy2, dummy3, dummy4, dummy5;
+
+ /* Check the position */
+ XTranslateCoordinates( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 0,
+ 0,
+ &dummy2,
+ &dummy3,
+ &dummy1 );
+ if( dummy2 != p_vout->p_sys->i_xpos_backup_2 ||
+ dummy3 != p_vout->p_sys->i_ypos_backup_2 )
+ {
+ /* Ok it didn't work... second try */
+
+ XMoveWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ p_vout->p_sys->i_xpos_backup_2,
+ p_vout->p_sys->i_ypos_backup_2 );
+
+ /* Purge all ConfigureNotify events, this is needed to fix a bug
+ * where we would lose the original size of the window */
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+ while( xevent.type != ConfigureNotify )
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+ while( XCheckWindowEvent( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ StructureNotifyMask, &xevent ) );
+ }
+
+ /* Check the size */
+ XGetGeometry( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ &dummy1,
+ &dummy2,
+ &dummy3,
+ &dummy4,
+ &dummy5,
+ &dummy2, &dummy3 );
+
+ if( dummy4 != p_vout->p_sys->i_width_backup_2 ||
+ dummy5 != p_vout->p_sys->i_height_backup_2 )
+ {
+ /* Ok it didn't work... third try */
+
+ XResizeWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ p_vout->p_sys->i_width_backup_2,
+ p_vout->p_sys->i_height_backup_2 );
+
+ /* Purge all ConfigureNotify events, this is needed to fix a bug
+ * where we would lose the original size of the window */
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+ while( xevent.type != ConfigureNotify )
+ XWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+ StructureNotifyMask, &xevent );
+ while( XCheckWindowEvent( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ StructureNotifyMask, &xevent ) );
+ }
+ }
+
+ if( p_vout->p_sys->b_altfullscreen )
+ XSetInputFocus(p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ RevertToParent,
+ CurrentTime);
+
+ /* signal that the size needs to be updated */
+ p_vout->p_sys->i_width = i_width;
+ p_vout->p_sys->i_height = i_height;
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+
+}
+
+/*****************************************************************************
+ * EnableXScreenSaver: enable screen saver
+ *****************************************************************************
+ * This function enables the screen saver on a display after it has been
+ * disabled by XDisableScreenSaver.
+ * FIXME: what happens if multiple vlc sessions are running at the same
+ * time ???
+ *****************************************************************************/
+static void EnableXScreenSaver( vout_thread_t *p_vout )
+{
+ int dummy;
+
+ XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
+ p_vout->p_sys->i_ss_interval,
+ p_vout->p_sys->i_ss_blanking,
+ p_vout->p_sys->i_ss_exposure );
+
+ /* Restore DPMS settings */
+ if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
+ {
+ if( p_vout->p_sys->b_ss_dpms )
+ {
+ DPMSEnable( p_vout->p_sys->p_display );
+ }
+ }
+}
+
+/*****************************************************************************
+ * DisableXScreenSaver: disable screen saver
+ *****************************************************************************
+ * See XEnableXScreenSaver
+ *****************************************************************************/
+static void DisableXScreenSaver( vout_thread_t *p_vout )
+{
+ int dummy;
+
+ /* Save screen saver informations */
+ XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
+ &p_vout->p_sys->i_ss_interval,
+ &p_vout->p_sys->i_ss_blanking,
+ &p_vout->p_sys->i_ss_exposure );
+
+ /* Disable screen saver */
+ XSetScreenSaver( p_vout->p_sys->p_display, 0,
+ p_vout->p_sys->i_ss_interval,
+ p_vout->p_sys->i_ss_blanking,
+ p_vout->p_sys->i_ss_exposure );
+
+ /* Disable DPMS */
+ if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
+ {
+ CARD16 dummy;
+ /* Save DPMS current state */
+ DPMSInfo( p_vout->p_sys->p_display, &dummy,
+ &p_vout->p_sys->b_ss_dpms );
+ DPMSDisable( p_vout->p_sys->p_display );
+ }
+}
+
+/*****************************************************************************
+ * CreateCursor: create a blank mouse pointer
+ *****************************************************************************/
+static void CreateCursor( vout_thread_t *p_vout )
+{
+ XColor cursor_color;
+
+ p_vout->p_sys->cursor_pixmap =
+ XCreatePixmap( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 1, 1, 1 );
+
+ XParseColor( p_vout->p_sys->p_display,
+ XCreateColormap( p_vout->p_sys->p_display,
+ DefaultRootWindow(
+ p_vout->p_sys->p_display ),
+ DefaultVisual(
+ p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen ),
+ AllocNone ),
+ "black", &cursor_color );
+
+ p_vout->p_sys->blank_cursor =
+ XCreatePixmapCursor( p_vout->p_sys->p_display,
+ p_vout->p_sys->cursor_pixmap,
+ p_vout->p_sys->cursor_pixmap,
+ &cursor_color, &cursor_color, 1, 1 );
+}
+
+/*****************************************************************************
+ * DestroyCursor: destroy the blank mouse pointer
+ *****************************************************************************/
+static void DestroyCursor( vout_thread_t *p_vout )
+{
+ XFreePixmap( p_vout->p_sys->p_display, p_vout->p_sys->cursor_pixmap );
+}
+
+/*****************************************************************************
+ * ToggleCursor: hide or show the mouse pointer
+ *****************************************************************************
+ * This function hides the X pointer if it is visible by setting the pointer
+ * sprite to a blank one. To show it again, we disable the sprite.
+ *****************************************************************************/
+static void ToggleCursor( vout_thread_t *p_vout )
+{
+ if( p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ XDefineCursor( p_vout->p_sys->p_display,
+ p_vout->p_sys->window,
+ p_vout->p_sys->blank_cursor );
+ p_vout->p_sys->b_mouse_pointer_visible = 0;
+ }
+ else
+ {
+ XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
+ p_vout->p_sys->b_mouse_pointer_visible = 1;
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+sdl_SOURCES = sdl.c vout.c aout.c
--- /dev/null
+/*****************************************************************************
+ * aout_sdl.c : audio sdl functions library
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: aout.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * Pierre Baillet <oct@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <fcntl.h> /* open(), O_WRONLY */
+#include <string.h> /* strerror() */
+#include <unistd.h> /* write(), close() */
+#include <stdlib.h> /* calloc(), malloc(), free() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+
+#include SDL_INCLUDE_FILE
+
+/*****************************************************************************
+ * aout_sys_t: dsp audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes the dsp specific properties of an audio device.
+ *****************************************************************************/
+
+/* the overflow limit is used to prevent the fifo from growing too big */
+#define OVERFLOWLIMIT 100000
+
+struct aout_sys_t
+{
+ byte_t * audio_buf;
+ int i_audio_end;
+
+ vlc_bool_t b_active;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+static void SDLCallback ( void *, Uint8 *, int );
+
+/*****************************************************************************
+ * OpenAudio: open the audio device
+ *****************************************************************************
+ * This function opens the dsp as a usual non-blocking write-only file, and
+ * modifies the p_aout->i_fd with the file's descriptor.
+ *****************************************************************************/
+int E_(OpenAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+
+ SDL_AudioSpec desired;
+
+ if( SDL_WasInit( SDL_INIT_AUDIO ) != 0 )
+ {
+ return( 1 );
+ }
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ /* Allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Initialize library */
+ if( SDL_Init( SDL_INIT_AUDIO
+#ifndef WIN32
+ /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
+ | SDL_INIT_EVENTTHREAD
+#endif
+#ifdef DEBUG
+ /* In debug mode you may want vlc to dump a core instead of staying
+ * stuck */
+ | SDL_INIT_NOPARACHUTE
+#endif
+ ) < 0 )
+ {
+ msg_Err( p_aout, "cannot initialize SDL (%s)", SDL_GetError() );
+ free( p_aout->p_sys );
+ return( 1 );
+ }
+
+ p_aout->p_sys->i_audio_end = 0;
+ p_aout->p_sys->audio_buf = malloc( OVERFLOWLIMIT );
+
+ /* Initialize some variables */
+
+ /* TODO: write conversion beetween AOUT_FORMAT_DEFAULT
+ * AND AUDIO* from SDL. */
+ desired.freq = p_aout->i_rate;
+#ifdef WORDS_BIGENDIAN
+ desired.format = AUDIO_S16MSB; /* stereo 16 bits */
+#else
+ desired.format = AUDIO_S16LSB; /* stereo 16 bits */
+#endif
+ desired.channels = p_aout->i_channels;
+ desired.callback = SDLCallback;
+ desired.userdata = p_aout->p_sys;
+ desired.samples = 1024;
+
+ /* Open the sound device
+ * we just ask the SDL to wrap at the good frequency if the one we
+ * ask for is unavailable. This is done by setting the second parar
+ * to NULL
+ */
+ if( SDL_OpenAudio( &desired, NULL ) < 0 )
+ {
+ msg_Err( p_aout, "SDL_OpenAudio failed (%s)", SDL_GetError() );
+ SDL_QuitSubSystem( SDL_INIT_AUDIO );
+ free( p_aout->p_sys );
+ return( -1 );
+ }
+
+ p_aout->p_sys->b_active = 1;
+ SDL_PauseAudio( 0 );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: reset the audio device and sets its format
+ *****************************************************************************
+ * This functions resets the audio device, tries to initialize the output
+ * format with the value contained in the dsp structure, and if this value
+ * could not be set, the default value returned by ioctl is set. It then
+ * does the same for the stereo mode, and for the output rate.
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ /* TODO: finish and clean this */
+ SDL_AudioSpec desired;
+
+ /*i_format = p_aout->i_format;*/
+ desired.freq = p_aout->i_rate; /* Set the output rate */
+#ifdef WORDS_BIGENDIAN
+ desired.format = AUDIO_S16MSB; /* stereo 16 bits */
+#else
+ desired.format = AUDIO_S16LSB; /* stereo 16 bits */
+#endif
+ desired.channels = p_aout->i_channels;
+ desired.callback = SDLCallback;
+ desired.userdata = p_aout->p_sys;
+ desired.samples = 2048;
+
+ /* Open the sound device */
+ SDL_PauseAudio( 1 );
+ SDL_CloseAudio();
+
+ if( SDL_OpenAudio( &desired, NULL ) < 0 )
+ {
+ p_aout->p_sys->b_active = 0;
+ return( -1 );
+ }
+
+ p_aout->p_sys->b_active = 1;
+ SDL_PauseAudio( 0 );
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************
+ * returns the number of bytes in the audio buffer compared to the size of
+ * i_buffer_limit...
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ if(i_buffer_limit > p_aout->p_sys->i_audio_end)
+ {
+ /* returning 0 here juste gives awful sound in the speakers :/ */
+ return( i_buffer_limit );
+ }
+ return( p_aout->p_sys->i_audio_end - i_buffer_limit);
+}
+
+/*****************************************************************************
+ * Play: play a sound samples buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes in the dsp
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
+{
+ byte_t * audio_buf = p_aout->p_sys->audio_buf;
+
+ SDL_LockAudio(); /* Stop callbacking */
+
+ p_aout->p_sys->audio_buf = realloc( audio_buf,
+ p_aout->p_sys->i_audio_end + i_size);
+ memcpy( p_aout->p_sys->audio_buf + p_aout->p_sys->i_audio_end,
+ buffer, i_size);
+
+ p_aout->p_sys->i_audio_end += i_size;
+
+ SDL_UnlockAudio(); /* go on callbacking */
+}
+
+/*****************************************************************************
+ * CloseAudio: close the audio device
+ *****************************************************************************/
+void E_(CloseAudio) ( vlc_object_t *p_this )
+{
+ aout_thread_t * p_aout = (aout_thread_t *)p_this;
+
+ if( p_aout->p_sys->b_active )
+ {
+ SDL_PauseAudio( 1 ); /* pause audio */
+
+ if( p_aout->p_sys->audio_buf != NULL ) /* do we have a buffer now ? */
+ {
+ free( p_aout->p_sys->audio_buf );
+ }
+ }
+
+ SDL_CloseAudio();
+
+ SDL_QuitSubSystem( SDL_INIT_AUDIO );
+
+ free( p_aout->p_sys ); /* Close the Output. */
+}
+
+/*****************************************************************************
+ * SDLCallback: what to do once SDL has played sound samples
+ *****************************************************************************/
+static void SDLCallback( void *userdata, byte_t *stream, int len )
+{
+ aout_sys_t * p_sys = userdata;
+
+ if( p_sys->i_audio_end > OVERFLOWLIMIT )
+ {
+//X msg_Err( p_aout, "aout_SDLCallback overflowed" );
+
+ free( p_sys->audio_buf );
+ p_sys->audio_buf = NULL;
+
+ p_sys->i_audio_end = 0;
+ /* we've gone to slow, increase output freq */
+ }
+
+ /* if we are not in underrun */
+ if( p_sys->i_audio_end > len )
+ {
+ p_sys->i_audio_end -= len;
+ memcpy( stream, p_sys->audio_buf, len );
+ memmove( p_sys->audio_buf, p_sys->audio_buf + len, p_sys->i_audio_end );
+ }
+}
+
--- /dev/null
+/*****************************************************************************
+ * sdl.c : SDL plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000, 2001 VideoLAN
+ * $Id: sdl.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Pierre Baillet <oct@zoy.org>
+ * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * External prototypes
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t * );
+void E_(CloseVideo) ( vlc_object_t * );
+
+int E_(OpenAudio) ( vlc_object_t * );
+void E_(CloseAudio) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Simple DirectMedia Layer module") );
+ add_submodule();
+ set_capability( "video output", 40 );
+ set_callbacks( E_(OpenVideo), E_(CloseVideo) );
+ add_submodule();
+ set_capability( "audio output", 40 );
+ set_callbacks( E_(OpenAudio), E_(CloseAudio) );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * vout_sdl.c: SDL video output display method
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: vout.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Pierre Baillet <oct@zoy.org>
+ * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include <sys/types.h>
+#ifndef WIN32
+# include <netinet/in.h> /* BSD: struct in_addr */
+#endif
+
+#include SDL_INCLUDE_FILE
+
+#include "netutils.h"
+
+#define SDL_MAX_DIRECTBUFFERS 10
+#define SDL_DEFAULT_BPP 16
+
+/*****************************************************************************
+ * vout_sys_t: video output SDL method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the SDL specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ SDL_Surface * p_display; /* display device */
+
+ int i_width;
+ int i_height;
+
+ /* For YUV output */
+ SDL_Overlay * p_overlay; /* An overlay we keep to grab the XVideo port */
+
+ /* For RGB output */
+ int i_surfaces;
+
+ vlc_bool_t b_cursor;
+ vlc_bool_t b_cursor_autohidden;
+ mtime_t i_lastmoved;
+ mtime_t i_lastpressed; /* to track dbl-clicks */
+};
+
+/*****************************************************************************
+ * picture_sys_t: direct buffer method descriptor
+ *****************************************************************************
+ * This structure is part of the picture descriptor, it describes the
+ * SDL specific properties of a direct buffer.
+ *****************************************************************************/
+struct picture_sys_t
+{
+ SDL_Overlay *p_overlay;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Init ( vout_thread_t * );
+static void End ( vout_thread_t * );
+static int Manage ( vout_thread_t * );
+static void Display ( vout_thread_t *, picture_t * );
+
+static int OpenDisplay ( vout_thread_t * );
+static void CloseDisplay ( vout_thread_t * );
+static int NewPicture ( vout_thread_t *, picture_t * );
+static void SetPalette ( vout_thread_t *, u16 *, u16 *, u16 * );
+
+/*****************************************************************************
+ * OpenVideo: allocate SDL video thread output method
+ *****************************************************************************
+ * This function allocate and initialize a SDL vout method. It uses some of the
+ * vout properties to choose the correct mode, and change them according to the
+ * mode actually used.
+ *****************************************************************************/
+int E_(OpenVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+#ifdef HAVE_SETENV
+ char *psz_method;
+#endif
+
+ if( SDL_WasInit( SDL_INIT_VIDEO ) != 0 )
+ {
+ return( 1 );
+ }
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ p_vout->pf_init = Init;
+ p_vout->pf_end = End;
+ p_vout->pf_manage = Manage;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = Display;
+
+#ifdef HAVE_SETENV
+ psz_method = config_GetPsz( p_vout, "vout" );
+ if( psz_method )
+ {
+ while( *psz_method && *psz_method != ':' )
+ {
+ psz_method++;
+ }
+
+ if( *psz_method )
+ {
+ setenv( "SDL_VIDEODRIVER", psz_method + 1, 1 );
+ }
+ }
+#endif
+
+ /* Initialize library */
+ if( SDL_Init( SDL_INIT_VIDEO
+#ifndef WIN32
+ /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
+ | SDL_INIT_EVENTTHREAD
+#endif
+#ifdef DEBUG
+ /* In debug mode you may want vlc to dump a core instead of staying
+ * stuck */
+ | SDL_INIT_NOPARACHUTE
+#endif
+ ) < 0 )
+ {
+ msg_Err( p_vout, "cannot initialize SDL (%s)", SDL_GetError() );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ p_vout->p_sys->b_cursor = 1;
+ p_vout->p_sys->b_cursor_autohidden = 0;
+ p_vout->p_sys->i_lastmoved = mdate();
+
+ if( OpenDisplay( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot set up SDL (%s)", SDL_GetError() );
+ SDL_QuitSubSystem( SDL_INIT_VIDEO );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Init: initialize SDL video thread output method
+ *****************************************************************************
+ * This function initialize the SDL display device.
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ p_vout->p_sys->i_surfaces = 0;
+
+ I_OUTPUTPICTURES = 0;
+
+ /* Initialize the output structure */
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ /* All we have is an RGB image with square pixels */
+ p_vout->output.i_width = p_vout->p_sys->i_width;
+ p_vout->output.i_height = p_vout->p_sys->i_height;
+ p_vout->output.i_aspect = p_vout->output.i_width
+ * VOUT_ASPECT_FACTOR
+ / p_vout->output.i_height;
+ }
+ else
+ {
+ /* We may need to convert the chroma, but at least we keep the
+ * aspect ratio */
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+ }
+
+ /* Try to initialize SDL_MAX_DIRECTBUFFERS direct buffers */
+ while( I_OUTPUTPICTURES < SDL_MAX_DIRECTBUFFERS )
+ {
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture if we found one */
+ if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
+ {
+ break;
+ }
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * End: terminate Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by OpenVideo
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the output buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ /* RGB picture */
+ }
+ else
+ {
+ SDL_UnlockYUVOverlay(
+ PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
+ SDL_FreeYUVOverlay(
+ PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
+ }
+ free( PP_OUTPUTPICTURE[ i_index ]->p_sys );
+ }
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by vout_SDLCreate
+ *****************************************************************************/
+void E_(CloseVideo) ( vlc_object_t *p_this )
+{
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+ CloseDisplay( p_vout );
+ SDL_QuitSubSystem( SDL_INIT_VIDEO );
+
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * Manage: handle Sys events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It returns
+ * a non null value if an error occured.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+ SDL_Event event; /* SDL event */
+
+ /* Process events */
+ while( SDL_PollEvent(&event) )
+ {
+ switch( event.type )
+ {
+ case SDL_VIDEORESIZE: /* Resizing of window */
+ /* Update dimensions */
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ p_vout->i_window_width = p_vout->p_sys->i_width = event.resize.w;
+ p_vout->i_window_height = p_vout->p_sys->i_height = event.resize.h;
+ break;
+
+ case SDL_MOUSEMOTION:
+ if( p_vout->p_sys->b_cursor &&
+ (abs(event.motion.xrel) > 2 || abs(event.motion.yrel) > 2) )
+ {
+ if( p_vout->p_sys->b_cursor_autohidden )
+ {
+ p_vout->p_sys->b_cursor_autohidden = 0;
+ SDL_ShowCursor( 1 );
+ }
+ else
+ {
+ p_vout->p_sys->i_lastmoved = mdate();
+ }
+ }
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ switch( event.button.button )
+ {
+ case SDL_BUTTON_RIGHT:
+ {
+ intf_thread_t *p_intf;
+ p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+ if( p_intf )
+ {
+ p_intf->b_menu_change = 1;
+ vlc_object_release( p_intf );
+ }
+ }
+ break;
+ }
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ switch( event.button.button )
+ {
+ case SDL_BUTTON_LEFT:
+ /* In this part we will eventually manage
+ * clicks for DVD navigation for instance. */
+
+ /* detect double-clicks */
+ if( ( mdate() - p_vout->p_sys->i_lastpressed ) < 300000 )
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+
+ p_vout->p_sys->i_lastpressed = mdate();
+ break;
+
+ case 4:
+ input_Seek( p_vout, 15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+
+ case 5:
+ input_Seek( p_vout, -15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ }
+ break;
+
+ case SDL_QUIT:
+ p_vout->p_vlc->b_die = 1;
+ break;
+
+ case SDL_KEYDOWN: /* if a key is pressed */
+
+ switch( event.key.keysym.sym )
+ {
+ case SDLK_ESCAPE:
+ if( p_vout->b_fullscreen )
+ {
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ }
+ else
+ {
+ p_vout->p_vlc->b_die = 1;
+ }
+ break;
+
+ case SDLK_q: /* quit */
+ p_vout->p_vlc->b_die = 1;
+ break;
+
+ case SDLK_f: /* switch to fullscreen */
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ break;
+
+ case SDLK_c: /* toggle grayscale */
+ p_vout->b_grayscale = ! p_vout->b_grayscale;
+ p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
+ break;
+
+ case SDLK_i: /* toggle info */
+ p_vout->b_info = ! p_vout->b_info;
+ p_vout->i_changes |= VOUT_INFO_CHANGE;
+ break;
+
+ case SDLK_s: /* toggle scaling */
+ p_vout->b_scale = ! p_vout->b_scale;
+ p_vout->i_changes |= VOUT_SCALE_CHANGE;
+ break;
+
+ case SDLK_SPACE: /* toggle interface */
+ p_vout->b_interface = ! p_vout->b_interface;
+ p_vout->i_changes |= VOUT_INTF_CHANGE;
+ break;
+
+ case SDLK_MENU:
+ {
+ intf_thread_t *p_intf;
+ p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+ if( p_intf )
+ {
+ p_intf->b_menu_change = 1;
+ vlc_object_release( p_intf );
+ }
+ }
+ break;
+
+ case SDLK_LEFT:
+ input_Seek( p_vout, -5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+
+ case SDLK_RIGHT:
+ input_Seek( p_vout, 5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+
+ case SDLK_UP:
+ input_Seek( p_vout, 60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+
+ case SDLK_DOWN:
+ input_Seek( p_vout, -60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+
+ case SDLK_F1: network_ChannelJoin( p_vout, 1 ); break;
+ case SDLK_F2: network_ChannelJoin( p_vout, 2 ); break;
+ case SDLK_F3: network_ChannelJoin( p_vout, 3 ); break;
+ case SDLK_F4: network_ChannelJoin( p_vout, 4 ); break;
+ case SDLK_F5: network_ChannelJoin( p_vout, 5 ); break;
+ case SDLK_F6: network_ChannelJoin( p_vout, 6 ); break;
+ case SDLK_F7: network_ChannelJoin( p_vout, 7 ); break;
+ case SDLK_F8: network_ChannelJoin( p_vout, 8 ); break;
+ case SDLK_F9: network_ChannelJoin( p_vout, 9 ); break;
+ case SDLK_F10: network_ChannelJoin( p_vout, 10 ); break;
+ case SDLK_F11: network_ChannelJoin( p_vout, 11 ); break;
+ case SDLK_F12: network_ChannelJoin( p_vout, 12 ); break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Fullscreen change */
+ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+ {
+ p_vout->b_fullscreen = ! p_vout->b_fullscreen;
+
+ p_vout->p_sys->b_cursor_autohidden = 0;
+ SDL_ShowCursor( p_vout->p_sys->b_cursor &&
+ ! p_vout->p_sys->b_cursor_autohidden );
+
+ p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ }
+
+ /*
+ * Size change
+ */
+ if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+ {
+ msg_Dbg( p_vout, "video display resized (%dx%d)",
+ p_vout->p_sys->i_width, p_vout->p_sys->i_height );
+
+ CloseDisplay( p_vout );
+ OpenDisplay( p_vout );
+
+ /* We don't need to signal the vout thread about the size change if
+ * we can handle rescaling ourselves */
+ if( p_vout->p_sys->p_overlay != NULL )
+ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+
+ }
+
+ /* Pointer change */
+ if( ! p_vout->p_sys->b_cursor_autohidden &&
+ ( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) )
+ {
+ /* Hide the mouse automatically */
+ p_vout->p_sys->b_cursor_autohidden = 1;
+ SDL_ShowCursor( 0 );
+ }
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Display: displays previously rendered output
+ *****************************************************************************
+ * This function sends the currently rendered image to the display.
+ *****************************************************************************/
+static void Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ int x, y, w, h;
+ SDL_Rect disp;
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ &x, &y, &w, &h );
+ disp.x = x;
+ disp.y = y;
+ disp.w = w;
+ disp.h = h;
+
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ /* RGB picture */
+ SDL_Flip( p_vout->p_sys->p_display );
+ }
+ else
+ {
+ /* Overlay picture */
+ SDL_UnlockYUVOverlay( p_pic->p_sys->p_overlay);
+ SDL_DisplayYUVOverlay( p_pic->p_sys->p_overlay , &disp );
+ SDL_LockYUVOverlay( p_pic->p_sys->p_overlay);
+ }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * OpenDisplay: open and initialize SDL device
+ *****************************************************************************
+ * Open and initialize display according to preferences specified in the vout
+ * thread fields.
+ *****************************************************************************/
+static int OpenDisplay( vout_thread_t *p_vout )
+{
+ Uint32 i_flags;
+ int i_bpp;
+
+ /* Set main window's size */
+ p_vout->p_sys->i_width = p_vout->b_fullscreen ? p_vout->output.i_width :
+ p_vout->i_window_width;
+ p_vout->p_sys->i_height = p_vout->b_fullscreen ? p_vout->output.i_height :
+ p_vout->i_window_height;
+
+ /* Initialize flags and cursor */
+ i_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
+ i_flags |= p_vout->b_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
+
+ i_bpp = SDL_VideoModeOK( p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ SDL_DEFAULT_BPP, i_flags );
+ if( i_bpp == 0 )
+ {
+ msg_Err( p_vout, "no video mode available" );
+ return( 1 );
+ }
+
+ p_vout->p_sys->p_display = SDL_SetVideoMode( p_vout->p_sys->i_width,
+ p_vout->p_sys->i_height,
+ i_bpp, i_flags );
+
+ if( p_vout->p_sys->p_display == NULL )
+ {
+ msg_Err( p_vout, "cannot set video mode" );
+ return( 1 );
+ }
+
+ SDL_LockSurface( p_vout->p_sys->p_display );
+
+ /* Choose the chroma we will try first. */
+ switch( p_vout->render.i_chroma )
+ {
+ case VLC_FOURCC('Y','U','Y','2'):
+ case VLC_FOURCC('Y','U','N','V'):
+ p_vout->output.i_chroma = SDL_YUY2_OVERLAY;
+ break;
+ case VLC_FOURCC('U','Y','V','Y'):
+ case VLC_FOURCC('U','Y','N','V'):
+ case VLC_FOURCC('Y','4','2','2'):
+ p_vout->output.i_chroma = SDL_UYVY_OVERLAY;
+ break;
+ case VLC_FOURCC('Y','V','Y','U'):
+ p_vout->output.i_chroma = SDL_YVYU_OVERLAY;
+ break;
+ case VLC_FOURCC('Y','V','1','2'):
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ default:
+ p_vout->output.i_chroma = SDL_YV12_OVERLAY;
+ break;
+ }
+
+ p_vout->p_sys->p_overlay =
+ SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+ p_vout->p_sys->p_display );
+ /* FIXME: if the first overlay we find is software, don't stop,
+ * because we may find a hardware one later ... */
+
+ /* If this best choice failed, fall back to other chromas */
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ p_vout->output.i_chroma = SDL_IYUV_OVERLAY;
+ p_vout->p_sys->p_overlay =
+ SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+ p_vout->p_sys->p_display );
+ }
+
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ p_vout->output.i_chroma = SDL_YV12_OVERLAY;
+ p_vout->p_sys->p_overlay =
+ SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+ p_vout->p_sys->p_display );
+ }
+
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ p_vout->output.i_chroma = SDL_YUY2_OVERLAY;
+ p_vout->p_sys->p_overlay =
+ SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+ p_vout->p_sys->p_display );
+ }
+
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ msg_Warn( p_vout, "no SDL overlay for 0x%.8x (%4.4s)",
+ p_vout->render.i_chroma, (char*)&p_vout->render.i_chroma );
+
+ switch( p_vout->p_sys->p_display->format->BitsPerPixel )
+ {
+ case 8:
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
+ p_vout->output.pf_setpalette = SetPalette;
+ break;
+ case 15:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
+ break;
+ case 16:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
+ break;
+ case 24:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
+ break;
+ case 32:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
+ break;
+ default:
+ msg_Err( p_vout, "unknown screen depth %i",
+ p_vout->p_sys->p_display->format->BitsPerPixel );
+ SDL_UnlockSurface( p_vout->p_sys->p_display );
+ SDL_FreeSurface( p_vout->p_sys->p_display );
+ return( -1 );
+ }
+
+ p_vout->output.i_rmask = p_vout->p_sys->p_display->format->Rmask;
+ p_vout->output.i_gmask = p_vout->p_sys->p_display->format->Gmask;
+ p_vout->output.i_bmask = p_vout->p_sys->p_display->format->Bmask;
+
+ SDL_WM_SetCaption( VOUT_TITLE " (software RGB SDL output)",
+ VOUT_TITLE " (software RGB SDL output)" );
+ }
+ else
+ {
+ if( p_vout->p_sys->p_overlay->hw_overlay )
+ {
+ SDL_WM_SetCaption( VOUT_TITLE " (hardware YUV SDL output)",
+ VOUT_TITLE " (hardware YUV SDL output)" );
+ }
+ else
+ {
+ SDL_WM_SetCaption( VOUT_TITLE " (software YUV SDL output)",
+ VOUT_TITLE " (software YUV SDL output)" );
+ }
+ }
+
+ SDL_EventState( SDL_KEYUP, SDL_IGNORE ); /* ignore keys up */
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * CloseDisplay: close and reset SDL device
+ *****************************************************************************
+ * This function returns all resources allocated by OpenDisplay and restore
+ * the original state of the device.
+ *****************************************************************************/
+static void CloseDisplay( vout_thread_t *p_vout )
+{
+ SDL_FreeYUVOverlay( p_vout->p_sys->p_overlay );
+ SDL_UnlockSurface ( p_vout->p_sys->p_display );
+ SDL_FreeSurface( p_vout->p_sys->p_display );
+}
+
+/*****************************************************************************
+ * NewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ int i_width = p_vout->output.i_width;
+ int i_height = p_vout->output.i_height;
+
+ if( p_vout->p_sys->p_overlay == NULL )
+ {
+ /* RGB picture */
+ if( p_vout->p_sys->i_surfaces )
+ {
+ /* We already allocated this surface, return */
+ return -1;
+ }
+
+ p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+ if( p_pic->p_sys == NULL )
+ {
+ return -1;
+ }
+
+ switch( p_vout->p_sys->p_display->format->BitsPerPixel )
+ {
+ case 8:
+ p_pic->p->i_pixel_pitch = 1;
+ break;
+ case 15:
+ case 16:
+ p_pic->p->i_pixel_pitch = 2;
+ break;
+ case 24:
+ case 32:
+ p_pic->p->i_pixel_pitch = 4;
+ break;
+ default:
+ return( -1 );
+ }
+
+ p_pic->p->p_pixels = p_vout->p_sys->p_display->pixels;
+ p_pic->p->i_lines = p_vout->p_sys->p_display->h;
+ p_pic->p->i_pitch = p_vout->p_sys->p_display->pitch;
+ p_pic->p->i_visible_pitch =
+ p_pic->p->i_pixel_pitch * p_vout->p_sys->p_display->w;
+
+ p_vout->p_sys->i_surfaces++;
+
+ p_pic->i_planes = 1;
+ }
+ else
+ {
+ p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+ if( p_pic->p_sys == NULL )
+ {
+ return -1;
+ }
+
+ p_pic->p_sys->p_overlay =
+ SDL_CreateYUVOverlay( i_width, i_height,
+ p_vout->output.i_chroma,
+ p_vout->p_sys->p_display );
+
+ if( p_pic->p_sys->p_overlay == NULL )
+ {
+ free( p_pic->p_sys );
+ return -1;
+ }
+
+ SDL_LockYUVOverlay( p_pic->p_sys->p_overlay );
+
+ p_pic->Y_PIXELS = p_pic->p_sys->p_overlay->pixels[0];
+ p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_overlay->h;
+ p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[0];
+
+ switch( p_vout->output.i_chroma )
+ {
+ case SDL_YV12_OVERLAY:
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+
+ p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
+ p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+
+ p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
+ p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ case SDL_IYUV_OVERLAY:
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+
+ p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
+ p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+
+ p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
+ p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ default:
+ p_pic->p[Y_PLANE].i_pixel_pitch = 2;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * SetPalette: sets an 8 bpp palette
+ *****************************************************************************/
+static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
+{
+ SDL_Color colors[256];
+ int i;
+
+ /* Fill colors with color information */
+ for( i = 0; i < 256; i++ )
+ {
+ colors[ i ].r = red[ i ] >> 8;
+ colors[ i ].g = green[ i ] >> 8;
+ colors[ i ].b = blue[ i ] >> 8;
+ }
+
+ /* Set palette */
+ if( SDL_SetColors( p_vout->p_sys->p_display, colors, 0, 256 ) == 0 )
+ {
+ msg_Err( p_vout, "failed setting palette" );
+ }
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+x11_SOURCES = x11.c xcommon.c
+xvideo_SOURCES = xvideo.c xcommon.c
--- /dev/null
+/*****************************************************************************
+ * x11.c : X11 plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: x11.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * David Kennedy <dkennedy@tinytoad.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+extern int E_(Activate) ( vlc_object_t * );
+extern void E_(Deactivate) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define ALT_FS_TEXT N_("alternate fullscreen method")
+#define ALT_FS_LONGTEXT N_( \
+ "There are two ways to make a fullscreen window, unfortunately each one " \
+ "has its drawbacks.\n" \
+ "1) Let the window manager handle your fullscreen window (default). But " \
+ "things like taskbars will likely show on top of the video.\n" \
+ "2) Completly bypass the window manager, but then nothing will be able " \
+ "to show on top of the video.")
+
+#define DISPLAY_TEXT N_("X11 display name")
+#define DISPLAY_LONGTEXT N_( \
+ "Specify the X11 hardware display you want to use. By default vlc will " \
+ "use the value of the DISPLAY environment variable.")
+
+#define DRAWABLE_TEXT N_("X11 drawable")
+#define DRAWABLE_LONGTEXT N_( \
+ "Specify a X11 drawable to use instead of opening a new window. This " \
+ "option is DANGEROUS, use with care.")
+
+#define SHM_TEXT N_("use shared memory")
+#define SHM_LONGTEXT N_( \
+ "Use shared memory to communicate between vlc and the X server.")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( "x11-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT );
+ add_bool( "x11-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT );
+ add_integer( "x11-drawable", -1, NULL, DRAWABLE_TEXT, DRAWABLE_LONGTEXT );
+#ifdef HAVE_SYS_SHM_H
+ add_bool( "x11-shm", 1, NULL, SHM_TEXT, SHM_LONGTEXT );
+#endif
+ set_description( _("X11 module") );
+ set_capability( "video output", 50 );
+ set_callbacks( E_(Activate), E_(Deactivate) );
+vlc_module_end();
+
--- /dev/null
+/*****************************************************************************
+ * xcommon.c: Functions common to the X11 and XVideo plugins
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: xcommon.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * David Kennedy <dkennedy@tinytoad.com>
+ * Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#ifdef HAVE_MACHINE_PARAM_H
+ /* BSD */
+# include <machine/param.h>
+# include <sys/types.h> /* typedef ushort */
+# include <sys/ipc.h>
+#endif
+
+#ifndef WIN32
+# include <netinet/in.h> /* BSD: struct in_addr */
+#endif
+
+#ifdef HAVE_SYS_SHM_H
+# include <sys/shm.h> /* shmget(), shmctl() */
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#ifdef HAVE_SYS_SHM_H
+# include <X11/extensions/XShm.h>
+#endif
+#ifdef DPMSINFO_IN_DPMS_H
+# include <X11/extensions/dpms.h>
+#endif
+
+#ifdef MODULE_NAME_IS_xvideo
+# include <X11/extensions/Xv.h>
+# include <X11/extensions/Xvlib.h>
+#endif
+
+#include "netutils.h" /* network_ChannelJoin */
+
+#include "xcommon.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+int E_(Activate) ( vlc_object_t * );
+void E_(Deactivate) ( vlc_object_t * );
+
+static int InitVideo ( vout_thread_t * );
+static void EndVideo ( vout_thread_t * );
+static void DisplayVideo ( vout_thread_t *, picture_t * );
+static int ManageVideo ( vout_thread_t * );
+
+static int InitDisplay ( vout_thread_t * );
+
+static int CreateWindow ( vout_thread_t *, x11_window_t * );
+static void DestroyWindow ( vout_thread_t *, x11_window_t * );
+
+static int NewPicture ( vout_thread_t *, picture_t * );
+static void FreePicture ( vout_thread_t *, picture_t * );
+
+static IMAGE_TYPE *CreateImage ( vout_thread_t *,
+ Display *, EXTRA_ARGS, int, int );
+#ifdef HAVE_SYS_SHM_H
+static IMAGE_TYPE *CreateShmImage ( vout_thread_t *,
+ Display *, EXTRA_ARGS_SHM, int, int );
+#endif
+
+static void ToggleFullScreen ( vout_thread_t * );
+
+static void EnableXScreenSaver ( vout_thread_t * );
+static void DisableXScreenSaver ( vout_thread_t * );
+
+static void CreateCursor ( vout_thread_t * );
+static void DestroyCursor ( vout_thread_t * );
+static void ToggleCursor ( vout_thread_t * );
+
+#ifdef MODULE_NAME_IS_xvideo
+static int XVideoGetPort ( vout_thread_t *, vlc_fourcc_t, vlc_fourcc_t * );
+static void XVideoReleasePort( vout_thread_t *, int );
+#endif
+
+#ifdef MODULE_NAME_IS_x11
+static void SetPalette ( vout_thread_t *, u16 *, u16 *, u16 * );
+#endif
+
+/*****************************************************************************
+ * Activate: allocate X11 video thread output method
+ *****************************************************************************
+ * This function allocate and initialize a X11 vout method. It uses some of the
+ * vout properties to choose the window size, and change them according to the
+ * actual properties of the display.
+ *****************************************************************************/
+int E_(Activate) ( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ char * psz_display;
+#ifdef MODULE_NAME_IS_xvideo
+ char * psz_chroma;
+ vlc_fourcc_t i_chroma = 0;
+ vlc_bool_t b_chroma = 0;
+#endif
+
+ p_vout->pf_init = InitVideo;
+ p_vout->pf_end = EndVideo;
+ p_vout->pf_manage = ManageVideo;
+ p_vout->pf_render = NULL;
+ p_vout->pf_display = DisplayVideo;
+
+ /* Allocate structure */
+ p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+ if( p_vout->p_sys == NULL )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( 1 );
+ }
+
+ /* Open display, unsing the "display" config variable or the DISPLAY
+ * environment variable */
+ psz_display = config_GetPsz( p_vout, MODULE_STRING "-display" );
+
+ p_vout->p_sys->p_display = XOpenDisplay( psz_display );
+
+ if( p_vout->p_sys->p_display == NULL ) /* error */
+ {
+ msg_Err( p_vout, "cannot open display %s",
+ XDisplayName( psz_display ) );
+ free( p_vout->p_sys );
+ if( psz_display ) free( psz_display );
+ return( 1 );
+ }
+ if( psz_display ) free( psz_display );
+
+ /* Get a screen ID matching the XOpenDisplay return value */
+ p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
+
+#ifdef MODULE_NAME_IS_xvideo
+ psz_chroma = config_GetPsz( p_vout, "xvideo-chroma" );
+ if( psz_chroma )
+ {
+ if( strlen( psz_chroma ) >= 4 )
+ {
+ i_chroma = (unsigned char)psz_chroma[0] << 0;
+ i_chroma |= (unsigned char)psz_chroma[1] << 8;
+ i_chroma |= (unsigned char)psz_chroma[2] << 16;
+ i_chroma |= (unsigned char)psz_chroma[3] << 24;
+
+ b_chroma = 1;
+ }
+
+ free( psz_chroma );
+ }
+
+ if( b_chroma )
+ {
+ msg_Dbg( p_vout, "forcing chroma 0x%.8x (%4.4s)",
+ i_chroma, (char*)&i_chroma );
+ }
+ else
+ {
+ i_chroma = p_vout->render.i_chroma;
+ }
+
+ /* Check that we have access to an XVideo port providing this chroma */
+ p_vout->p_sys->i_xvport = XVideoGetPort( p_vout, i_chroma,
+ &p_vout->output.i_chroma );
+ if( p_vout->p_sys->i_xvport < 0 )
+ {
+ /* If a specific chroma format was requested, then we don't try to
+ * be cleverer than the user. He knows pretty well what he wants. */
+ if( b_chroma )
+ {
+ XCloseDisplay( p_vout->p_sys->p_display );
+ free( p_vout->p_sys );
+ return 1;
+ }
+
+ /* It failed, but it's not completely lost ! We try to open an
+ * XVideo port for an YUY2 picture. We'll need to do an YUV
+ * conversion, but at least it has got scaling. */
+ p_vout->p_sys->i_xvport =
+ XVideoGetPort( p_vout, VLC_FOURCC('Y','U','Y','2'),
+ &p_vout->output.i_chroma );
+ if( p_vout->p_sys->i_xvport < 0 )
+ {
+ /* It failed, but it's not completely lost ! We try to open an
+ * XVideo port for a simple 16bpp RGB picture. We'll need to do
+ * an YUV conversion, but at least it has got scaling. */
+ p_vout->p_sys->i_xvport =
+ XVideoGetPort( p_vout, VLC_FOURCC('R','V','1','6'),
+ &p_vout->output.i_chroma );
+ if( p_vout->p_sys->i_xvport < 0 )
+ {
+ XCloseDisplay( p_vout->p_sys->p_display );
+ free( p_vout->p_sys );
+ return 1;
+ }
+ }
+ }
+#endif
+
+ /* Create blank cursor (for mouse cursor autohiding) */
+ p_vout->p_sys->i_time_mouse_last_moved = mdate();
+ p_vout->p_sys->b_mouse_pointer_visible = 1;
+ CreateCursor( p_vout );
+
+ /* Set main window's size */
+ p_vout->p_sys->original_window.i_width = p_vout->i_window_width;
+ p_vout->p_sys->original_window.i_height = p_vout->i_window_height;
+
+ /* Spawn base window - this window will include the video output window,
+ * but also command buttons, subtitles and other indicators */
+ if( CreateWindow( p_vout, &p_vout->p_sys->original_window ) )
+ {
+ msg_Err( p_vout, "cannot create X11 window" );
+ DestroyCursor( p_vout );
+ XCloseDisplay( p_vout->p_sys->p_display );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ /* Open and initialize device. */
+ if( InitDisplay( p_vout ) )
+ {
+ msg_Err( p_vout, "cannot initialize X11 display" );
+ DestroyCursor( p_vout );
+ DestroyWindow( p_vout, &p_vout->p_sys->original_window );
+ XCloseDisplay( p_vout->p_sys->p_display );
+ free( p_vout->p_sys );
+ return( 1 );
+ }
+
+ /* Disable screen saver */
+ DisableXScreenSaver( p_vout );
+
+ /* Misc init */
+ p_vout->p_sys->b_altfullscreen = 0;
+ p_vout->p_sys->i_time_button_last_pressed = 0;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Deactivate: destroy X11 video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Open
+ *****************************************************************************/
+void E_(Deactivate) ( vlc_object_t *p_this )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ /* If the fullscreen window is still open, close it */
+ if( p_vout->b_fullscreen )
+ {
+ ToggleFullScreen( p_vout );
+ }
+
+ /* Restore cursor if it was blanked */
+ if( !p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ }
+
+#ifdef MODULE_NAME_IS_x11
+ /* Destroy colormap */
+ if( XDefaultDepth(p_vout->p_sys->p_display, p_vout->p_sys->i_screen) == 8 )
+ {
+ XFreeColormap( p_vout->p_sys->p_display, p_vout->p_sys->colormap );
+ }
+#else
+ XVideoReleasePort( p_vout, p_vout->p_sys->i_xvport );
+#endif
+
+ DestroyCursor( p_vout );
+ EnableXScreenSaver( p_vout );
+ DestroyWindow( p_vout, &p_vout->p_sys->original_window );
+
+ XCloseDisplay( p_vout->p_sys->p_display );
+
+ /* Destroy structure */
+ free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * InitVideo: initialize X11 video thread output method
+ *****************************************************************************
+ * This function create the XImages needed by the output thread. It is called
+ * at the beginning of the thread, but also each time the window is resized.
+ *****************************************************************************/
+static int InitVideo( vout_thread_t *p_vout )
+{
+ int i_index;
+ picture_t *p_pic;
+
+ I_OUTPUTPICTURES = 0;
+
+#ifdef MODULE_NAME_IS_xvideo
+ /* Initialize the output structure; we already found an XVideo port,
+ * and the corresponding chroma we will be using. Since we can
+ * arbitrary scale, stick to the coordinates and aspect. */
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+ switch( p_vout->output.i_chroma )
+ {
+ case VLC_FOURCC('R','V','1','5'):
+ p_vout->output.i_rmask = 0x001f;
+ p_vout->output.i_gmask = 0x07e0;
+ p_vout->output.i_bmask = 0xf800;
+ break;
+ case VLC_FOURCC('R','V','1','6'):
+ p_vout->output.i_rmask = 0x001f;
+ p_vout->output.i_gmask = 0x03e0;
+ p_vout->output.i_bmask = 0x7c00;
+ break;
+ }
+
+#else
+ /* Initialize the output structure: RGB with square pixels, whatever
+ * the input format is, since it's the only format we know */
+ switch( p_vout->p_sys->i_screen_depth )
+ {
+ case 8: /* FIXME: set the palette */
+ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); break;
+ case 15:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break;
+ case 16:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break;
+ case 24:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break;
+ case 32:
+ p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break;
+ default:
+ msg_Err( p_vout, "unknown screen depth %i",
+ p_vout->p_sys->i_screen_depth );
+ return( 0 );
+ }
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
+ p_vout->p_sys->p_win->i_height,
+ &i_index, &i_index,
+ &p_vout->output.i_width, &p_vout->output.i_height );
+
+ /* Assume we have square pixels */
+ p_vout->output.i_aspect = p_vout->output.i_width
+ * VOUT_ASPECT_FACTOR / p_vout->output.i_height;
+#endif
+
+ /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
+ while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
+ {
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+ {
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+ {
+ p_pic = p_vout->p_picture + i_index;
+ break;
+ }
+ }
+
+ /* Allocate the picture */
+ if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
+ {
+ break;
+ }
+
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
+
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+ I_OUTPUTPICTURES++;
+ }
+
+ return( 0 );
+}
+
+ /*****************************************************************************
+ * DisplayVideo: displays previously rendered output
+ *****************************************************************************
+ * This function sends the currently rendered image to X11 server.
+ * (The Xv extension takes care of "double-buffering".)
+ *****************************************************************************/
+static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ int i_width, i_height, i_x, i_y;
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
+ p_vout->p_sys->p_win->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+
+#ifdef HAVE_SYS_SHM_H
+ if( p_vout->p_sys->b_shm )
+ {
+ /* Display rendered image using shared memory extension */
+# ifdef MODULE_NAME_IS_xvideo
+ XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
+ p_vout->p_sys->p_win->video_window,
+ p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
+ 0 /*src_x*/, 0 /*src_y*/,
+ p_vout->output.i_width, p_vout->output.i_height,
+ 0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height,
+ False /* Don't put True here or you'll waste your CPU */ );
+# else
+ XShmPutImage( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->video_window,
+ p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
+ 0 /*src_x*/, 0 /*src_y*/, 0 /*dest_x*/, 0 /*dest_y*/,
+ p_vout->output.i_width, p_vout->output.i_height,
+ False /* Don't put True here ! */ );
+# endif
+ }
+ else
+#endif /* HAVE_SYS_SHM_H */
+ {
+ /* Use standard XPutImage -- this is gonna be slow ! */
+#ifdef MODULE_NAME_IS_xvideo
+ XvPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
+ p_vout->p_sys->p_win->video_window,
+ p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
+ 0 /*src_x*/, 0 /*src_y*/,
+ p_vout->output.i_width, p_vout->output.i_height,
+ 0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height );
+#else
+ XPutImage( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->video_window,
+ p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
+ 0 /*src_x*/, 0 /*src_y*/, 0 /*dest_x*/, 0 /*dest_y*/,
+ p_vout->output.i_width, p_vout->output.i_height );
+#endif
+ }
+
+ /* Make sure the command is sent now - do NOT use XFlush !*/
+ XSync( p_vout->p_sys->p_display, False );
+}
+
+/*****************************************************************************
+ * ManageVideo: handle X11 events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * X11 events and allows window resizing. It returns a non null value on
+ * error.
+ *****************************************************************************/
+static int ManageVideo( vout_thread_t *p_vout )
+{
+ XEvent xevent; /* X11 event */
+ char i_key; /* ISO Latin-1 key */
+ KeySym x_key_symbol;
+
+ /* Handle X11 events: ConfigureNotify events are parsed to know if the
+ * output window's size changed, MapNotify and UnmapNotify to know if the
+ * window is mapped (and if the display is useful), and ClientMessages
+ * to intercept window destruction requests */
+
+ while( XCheckWindowEvent( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ StructureNotifyMask | KeyPressMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | Button1MotionMask , &xevent )
+ == True )
+ {
+ /* ConfigureNotify event: prepare */
+ if( xevent.type == ConfigureNotify )
+ {
+ if( (xevent.xconfigure.width != p_vout->p_sys->p_win->i_width)
+ || (xevent.xconfigure.height != p_vout->p_sys->p_win->i_height) )
+ {
+ /* Update dimensions */
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ p_vout->p_sys->p_win->i_width = xevent.xconfigure.width;
+ p_vout->p_sys->p_win->i_height = xevent.xconfigure.height;
+ }
+ }
+ /* Keyboard event */
+ else if( xevent.type == KeyPress )
+ {
+ /* We may have keys like F1 trough F12, ESC ... */
+ x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
+ xevent.xkey.keycode, 0 );
+ switch( x_key_symbol )
+ {
+ case XK_Escape:
+ if( p_vout->b_fullscreen )
+ {
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ }
+ else
+ {
+ p_vout->p_vlc->b_die = 1;
+ }
+ break;
+ case XK_Menu:
+ {
+ intf_thread_t *p_intf;
+ p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+ if( p_intf )
+ {
+ p_intf->b_menu_change = 1;
+ vlc_object_release( p_intf );
+ }
+ }
+ break;
+ case XK_Left:
+ input_Seek( p_vout, -5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Right:
+ input_Seek( p_vout, 5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Up:
+ input_Seek( p_vout, 60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Down:
+ input_Seek( p_vout, -60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Home:
+ input_Seek( p_vout, 0, INPUT_SEEK_BYTES | INPUT_SEEK_SET );
+ break;
+ case XK_End:
+ input_Seek( p_vout, 0, INPUT_SEEK_BYTES | INPUT_SEEK_END );
+ break;
+ case XK_Page_Up:
+ input_Seek( p_vout, 900, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_Page_Down:
+ input_Seek( p_vout, -900, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ case XK_space:
+ input_SetStatus( p_vout, INPUT_STATUS_PAUSE );
+ break;
+
+ case XK_F1: network_ChannelJoin( p_vout, 1 ); break;
+ case XK_F2: network_ChannelJoin( p_vout, 2 ); break;
+ case XK_F3: network_ChannelJoin( p_vout, 3 ); break;
+ case XK_F4: network_ChannelJoin( p_vout, 4 ); break;
+ case XK_F5: network_ChannelJoin( p_vout, 5 ); break;
+ case XK_F6: network_ChannelJoin( p_vout, 6 ); break;
+ case XK_F7: network_ChannelJoin( p_vout, 7 ); break;
+ case XK_F8: network_ChannelJoin( p_vout, 8 ); break;
+ case XK_F9: network_ChannelJoin( p_vout, 9 ); break;
+ case XK_F10: network_ChannelJoin( p_vout, 10 ); break;
+ case XK_F11: network_ChannelJoin( p_vout, 11 ); break;
+ case XK_F12: network_ChannelJoin( p_vout, 12 ); break;
+
+ default:
+ /* "Normal Keys"
+ * The reason why I use this instead of XK_0 is that
+ * with XLookupString, we don't have to care about
+ * keymaps. */
+
+ if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
+ {
+ /* FIXME: handle stuff here */
+ switch( i_key )
+ {
+ case 'q':
+ case 'Q':
+ p_vout->p_vlc->b_die = 1;
+ break;
+ case 'f':
+ case 'F':
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ }
+ /* Mouse click */
+ else if( xevent.type == ButtonPress )
+ {
+ int i_width, i_height, i_x, i_y;
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
+ p_vout->p_sys->p_win->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+
+ p_vout->i_mouse_x = ( xevent.xmotion.x - i_x )
+ * p_vout->render.i_width / i_width;
+ p_vout->i_mouse_y = ( xevent.xmotion.y - i_y )
+ * p_vout->render.i_height / i_height;
+ p_vout->i_mouse_button = 1;
+
+ switch( ((XButtonEvent *)&xevent)->button )
+ {
+ case Button1:
+ /* In this part we will eventually manage
+ * clicks for DVD navigation for instance. */
+
+ /* detect double-clicks */
+ if( ( ((XButtonEvent *)&xevent)->time -
+ p_vout->p_sys->i_time_button_last_pressed ) < 300 )
+ {
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ }
+
+ p_vout->p_sys->i_time_button_last_pressed =
+ ((XButtonEvent *)&xevent)->time;
+ break;
+
+ case Button4:
+ input_Seek( p_vout, 15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+
+ case Button5:
+ input_Seek( p_vout, -15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
+ break;
+ }
+ }
+ /* Mouse release */
+ else if( xevent.type == ButtonRelease )
+ {
+ switch( ((XButtonEvent *)&xevent)->button )
+ {
+ case Button3:
+ {
+ intf_thread_t *p_intf;
+ p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
+ FIND_ANYWHERE );
+ if( p_intf )
+ {
+ p_intf->b_menu_change = 1;
+ vlc_object_release( p_intf );
+ }
+ }
+ break;
+ }
+ }
+ /* Mouse move */
+ else if( xevent.type == MotionNotify )
+ {
+ int i_width, i_height, i_x, i_y;
+
+ /* somewhat different use for vout_PlacePicture:
+ * here the values are needed to give to mouse coordinates
+ * in the original picture space */
+ vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
+ p_vout->p_sys->p_win->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+
+ p_vout->i_mouse_x = ( xevent.xmotion.x - i_x )
+ * p_vout->render.i_width / i_width;
+ p_vout->i_mouse_y = ( xevent.xmotion.y - i_y )
+ * p_vout->render.i_height / i_height;
+
+ p_vout->p_sys->i_time_mouse_last_moved = mdate();
+ if( ! p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ }
+ }
+ /* Reparent move -- XXX: why are we getting this ? */
+ else if( xevent.type == ReparentNotify )
+ {
+ ;
+ }
+ /* Other event */
+ else
+ {
+ msg_Warn( p_vout, "unhandled event %d received", xevent.type );
+ }
+ }
+
+ /* Handle events for video output sub-window */
+ while( XCheckWindowEvent( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->video_window,
+ ExposureMask, &xevent ) == True )
+ {
+ /* Window exposed (only handled if stream playback is paused) */
+ if( xevent.type == Expose )
+ {
+ if( ((XExposeEvent *)&xevent)->count == 0 )
+ {
+ /* (if this is the last a collection of expose events...) */
+#if 0
+ if( p_vout->p_vlc->p_input_bank->pp_input[0] != NULL )
+ {
+ if( PAUSE_S == p_vout->p_vlc->p_input_bank->pp_input[0]
+ ->stream.control.i_status )
+ {
+ /* XVideoDisplay( p_vout )*/;
+ }
+ }
+#endif
+ }
+ }
+ }
+
+ /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
+ * are handled - according to the man pages, the format is always 32
+ * in this case */
+ while( XCheckTypedEvent( p_vout->p_sys->p_display,
+ ClientMessage, &xevent ) )
+ {
+ if( (xevent.xclient.message_type == p_vout->p_sys->p_win->wm_protocols)
+ && (xevent.xclient.data.l[0]
+ == p_vout->p_sys->p_win->wm_delete_window ) )
+ {
+ p_vout->p_vlc->b_die = 1;
+ }
+ }
+
+ /*
+ * Fullscreen Change
+ */
+ if ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+ {
+ ToggleFullScreen( p_vout );
+ p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+ }
+
+ /*
+ * Size change
+ *
+ * (Needs to be placed after VOUT_FULLSREEN_CHANGE because we can activate
+ * the size flag inside the fullscreen routine)
+ */
+ if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+ {
+ int i_width, i_height, i_x, i_y;
+
+ p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+
+ msg_Dbg( p_vout, "video display resized (%dx%d)",
+ p_vout->p_sys->p_win->i_width,
+ p_vout->p_sys->p_win->i_height );
+
+#ifdef MODULE_NAME_IS_x11
+ /* We need to signal the vout thread about the size change because it
+ * is doing the rescaling */
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+#endif
+
+ vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
+ p_vout->p_sys->p_win->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+
+ XResizeWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->video_window, i_width, i_height );
+
+ XMoveWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->video_window, i_x, i_y );
+ }
+
+ /* Autohide Cursour */
+ if( mdate() - p_vout->p_sys->i_time_mouse_last_moved > 2000000 )
+ {
+ /* Hide the mouse automatically */
+ if( p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * EndVideo: terminate X11 video thread output method
+ *****************************************************************************
+ * Destroy the X11 XImages created by Init. It is called at the end of
+ * the thread, but also each time the window is resized.
+ *****************************************************************************/
+static void EndVideo( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the direct buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
+ {
+ i_index--;
+ FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
+ }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * CreateWindow: open and set-up X11 main window
+ *****************************************************************************/
+static int CreateWindow( vout_thread_t *p_vout, x11_window_t *p_win )
+{
+ XSizeHints xsize_hints;
+ XSetWindowAttributes xwindow_attributes;
+ XGCValues xgcvalues;
+ XEvent xevent;
+
+ vlc_bool_t b_expose;
+ vlc_bool_t b_configure_notify;
+ vlc_bool_t b_map_notify;
+
+ long long int i_drawable;
+
+ /* Prepare window manager hints and properties */
+ xsize_hints.base_width = p_win->i_width;
+ xsize_hints.base_height = p_win->i_height;
+ xsize_hints.flags = PSize;
+ p_win->wm_protocols =
+ XInternAtom( p_vout->p_sys->p_display, "WM_PROTOCOLS", True );
+ p_win->wm_delete_window =
+ XInternAtom( p_vout->p_sys->p_display, "WM_DELETE_WINDOW", True );
+
+ /* Prepare window attributes */
+ xwindow_attributes.backing_store = Always; /* save the hidden part */
+ xwindow_attributes.background_pixel = BlackPixel(p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen);
+ xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
+
+ /* Check whether someone provided us with a window ID */
+ i_drawable = p_vout->b_fullscreen ?
+ -1 : config_GetInt( p_vout, MODULE_STRING "-drawable");
+
+ if( i_drawable == -1 )
+ {
+ p_vout->p_sys->b_createwindow = 1;
+
+ /* Create the window and set hints - the window must receive
+ * ConfigureNotify events, and until it is displayed, Expose and
+ * MapNotify events. */
+
+ p_win->base_window =
+ XCreateWindow( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 0, 0,
+ p_win->i_width, p_win->i_height,
+ 0,
+ 0, InputOutput, 0,
+ CWBackingStore | CWBackPixel | CWEventMask,
+ &xwindow_attributes );
+
+ if( !p_vout->b_fullscreen )
+ {
+ /* Set window manager hints and properties: size hints, command,
+ * window's name, and accepted protocols */
+ XSetWMNormalHints( p_vout->p_sys->p_display,
+ p_win->base_window, &xsize_hints );
+ XSetCommand( p_vout->p_sys->p_display, p_win->base_window,
+ p_vout->p_vlc->ppsz_argv, p_vout->p_vlc->i_argc );
+
+ XStoreName( p_vout->p_sys->p_display, p_win->base_window,
+#ifdef MODULE_NAME_IS_x11
+ VOUT_TITLE " (X11 output)"
+#else
+ VOUT_TITLE " (XVideo output)"
+#endif
+ );
+ }
+ }
+ else
+ {
+ p_vout->p_sys->b_createwindow = 0;
+ p_win->base_window = i_drawable;
+
+ XChangeWindowAttributes( p_vout->p_sys->p_display,
+ p_win->base_window,
+ CWBackingStore | CWBackPixel | CWEventMask,
+ &xwindow_attributes );
+ }
+
+ if( (p_win->wm_protocols == None) /* use WM_DELETE_WINDOW */
+ || (p_win->wm_delete_window == None)
+ || !XSetWMProtocols( p_vout->p_sys->p_display, p_win->base_window,
+ &p_win->wm_delete_window, 1 ) )
+ {
+ /* WM_DELETE_WINDOW is not supported by window manager */
+ msg_Warn( p_vout, "missing or bad window manager" );
+ }
+
+ /* Creation of a graphic context that doesn't generate a GraphicsExpose
+ * event when using functions like XCopyArea */
+ xgcvalues.graphics_exposures = False;
+ p_win->gc = XCreateGC( p_vout->p_sys->p_display,
+ p_win->base_window,
+ GCGraphicsExposures, &xgcvalues );
+
+ if( p_vout->p_sys->b_createwindow )
+ {
+ /* Send orders to server, and wait until window is displayed - three
+ * events must be received: a MapNotify event, an Expose event allowing
+ * drawing in the window, and a ConfigureNotify to get the window
+ * dimensions. Once those events have been received, only
+ * ConfigureNotify events need to be received. */
+ b_expose = 0;
+ b_configure_notify = 0;
+ b_map_notify = 0;
+ XMapWindow( p_vout->p_sys->p_display, p_win->base_window );
+ do
+ {
+ XNextEvent( p_vout->p_sys->p_display, &xevent);
+ if( (xevent.type == Expose)
+ && (xevent.xexpose.window == p_win->base_window) )
+ {
+ b_expose = 1;
+ }
+ else if( (xevent.type == MapNotify)
+ && (xevent.xmap.window == p_win->base_window) )
+ {
+ b_map_notify = 1;
+ }
+ else if( (xevent.type == ConfigureNotify)
+ && (xevent.xconfigure.window == p_win->base_window) )
+ {
+ b_configure_notify = 1;
+ p_win->i_width = xevent.xconfigure.width;
+ p_win->i_height = xevent.xconfigure.height;
+ }
+ } while( !( b_expose && b_configure_notify && b_map_notify ) );
+ }
+ else
+ {
+ /* Get the window's geometry information */
+ Window dummy1;
+ unsigned int dummy2, dummy3;
+ XGetGeometry( p_vout->p_sys->p_display, p_win->base_window,
+ &dummy1, &dummy2, &dummy3,
+ &p_win->i_width,
+ &p_win->i_height,
+ &dummy2, &dummy3 );
+ }
+
+ XSelectInput( p_vout->p_sys->p_display, p_win->base_window,
+ StructureNotifyMask | KeyPressMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask );
+
+#ifdef MODULE_NAME_IS_x11
+ if( p_vout->p_sys->b_createwindow &&
+ XDefaultDepth(p_vout->p_sys->p_display, p_vout->p_sys->i_screen) == 8 )
+ {
+ /* Allocate a new palette */
+ p_vout->p_sys->colormap =
+ XCreateColormap( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ DefaultVisual( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen ),
+ AllocAll );
+
+ xwindow_attributes.colormap = p_vout->p_sys->colormap;
+ XChangeWindowAttributes( p_vout->p_sys->p_display, p_win->base_window,
+ CWColormap, &xwindow_attributes );
+ }
+#endif
+
+ /* Create video output sub-window. */
+ p_win->video_window = XCreateSimpleWindow(
+ p_vout->p_sys->p_display,
+ p_win->base_window, 0, 0,
+ p_win->i_width, p_win->i_height,
+ 0,
+ BlackPixel( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen ),
+ WhitePixel( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen ) );
+
+ XSetWindowBackground( p_vout->p_sys->p_display, p_win->video_window,
+ BlackPixel( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen ) );
+
+ XMapWindow( p_vout->p_sys->p_display, p_win->video_window );
+ XSelectInput( p_vout->p_sys->p_display, p_win->video_window,
+ ExposureMask );
+
+ /* make sure the video window will be centered in the next ManageVideo() */
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+
+ /* If the cursor was formerly blank than blank it again */
+ if( !p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ ToggleCursor( p_vout );
+ ToggleCursor( p_vout );
+ }
+
+ /* Do NOT use XFlush here ! */
+ XSync( p_vout->p_sys->p_display, False );
+
+ /* At this stage, the window is open, displayed, and ready to
+ * receive data */
+ p_vout->p_sys->p_win = p_win;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * DestroyWindow: destroy the window
+ *****************************************************************************
+ *
+ *****************************************************************************/
+static void DestroyWindow( vout_thread_t *p_vout, x11_window_t *p_win )
+{
+ /* Do NOT use XFlush here ! */
+ XSync( p_vout->p_sys->p_display, False );
+
+ XDestroyWindow( p_vout->p_sys->p_display, p_win->video_window );
+ XUnmapWindow( p_vout->p_sys->p_display, p_win->base_window );
+ XFreeGC( p_vout->p_sys->p_display, p_win->gc );
+ XDestroyWindow( p_vout->p_sys->p_display, p_win->base_window );
+}
+
+/*****************************************************************************
+ * NewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* We know the chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+ if( p_pic->p_sys == NULL )
+ {
+ return -1;
+ }
+
+#ifdef HAVE_SYS_SHM_H
+ if( p_vout->p_sys->b_shm )
+ {
+ /* Create image using XShm extension */
+ p_pic->p_sys->p_image =
+ CreateShmImage( p_vout, p_vout->p_sys->p_display,
+# ifdef MODULE_NAME_IS_xvideo
+ p_vout->p_sys->i_xvport, p_vout->output.i_chroma,
+# else
+ p_vout->p_sys->p_visual,
+ p_vout->p_sys->i_screen_depth,
+# endif
+ &p_pic->p_sys->shminfo,
+ p_vout->output.i_width, p_vout->output.i_height );
+ }
+ else
+#endif /* HAVE_SYS_SHM_H */
+ {
+ /* Create image without XShm extension */
+ p_pic->p_sys->p_image =
+ CreateImage( p_vout, p_vout->p_sys->p_display,
+#ifdef MODULE_NAME_IS_xvideo
+ p_vout->p_sys->i_xvport, p_vout->output.i_chroma,
+#else
+ p_vout->p_sys->p_visual,
+ p_vout->p_sys->i_screen_depth,
+ p_vout->p_sys->i_bytes_per_pixel,
+#endif
+ p_vout->output.i_width, p_vout->output.i_height );
+ }
+
+ if( p_pic->p_sys->p_image == NULL )
+ {
+ free( p_pic->p_sys );
+ return -1;
+ }
+
+ switch( p_vout->output.i_chroma )
+ {
+#ifdef MODULE_NAME_IS_xvideo
+ case VLC_FOURCC('I','4','2','0'):
+
+ p_pic->Y_PIXELS = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[0];
+ p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
+ p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_image->pitches[0];
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+
+ p_pic->U_PIXELS = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[1];
+ p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_image->pitches[1];
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+
+ p_pic->V_PIXELS = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[2];
+ p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_image->pitches[2];
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ case VLC_FOURCC('Y','V','1','2'):
+
+ p_pic->Y_PIXELS = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[0];
+ p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
+ p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_image->pitches[0];
+ p_pic->p[Y_PLANE].i_pixel_pitch = 1;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+
+ p_pic->U_PIXELS = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[2];
+ p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_image->pitches[2];
+ p_pic->p[U_PLANE].i_pixel_pitch = 1;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+
+ p_pic->V_PIXELS = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[1];
+ p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_image->pitches[1];
+ p_pic->p[V_PLANE].i_pixel_pitch = 1;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+
+ p_pic->i_planes = 3;
+ break;
+
+ case VLC_FOURCC('Y','2','1','1'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[0];
+ p_pic->p->i_lines = p_vout->output.i_height;
+ /* XXX: this just looks so plain wrong... check it out ! */
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
+ p_pic->p->i_pixel_pitch = 4;
+ p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+
+ case VLC_FOURCC('Y','U','Y','2'):
+ case VLC_FOURCC('U','Y','V','Y'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[0];
+ p_pic->p->i_lines = p_vout->output.i_height;
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0];
+ p_pic->p->i_pixel_pitch = 4;
+ p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+
+ case VLC_FOURCC('R','V','1','5'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[0];
+ p_pic->p->i_lines = p_vout->output.i_height;
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0];
+ p_pic->p->i_pixel_pitch = 2;
+ p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+
+ case VLC_FOURCC('R','V','1','6'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->offsets[0];
+ p_pic->p->i_lines = p_vout->output.i_height;
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0];
+ p_pic->p->i_pixel_pitch = 2;
+ p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
+
+ p_pic->i_planes = 1;
+ break;
+
+#else
+ case VLC_FOURCC('R','G','B','2'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->xoffset;
+ p_pic->p->i_lines = p_pic->p_sys->p_image->height;
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->bytes_per_line;
+ p_pic->p->i_pixel_pitch = p_pic->p_sys->p_image->depth;
+ p_pic->p->i_visible_pitch = p_pic->p_sys->p_image->width;
+
+ p_pic->i_planes = 1;
+
+ break;
+
+ case VLC_FOURCC('R','V','1','6'):
+ case VLC_FOURCC('R','V','1','5'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->xoffset;
+ p_pic->p->i_lines = p_pic->p_sys->p_image->height;
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->bytes_per_line;
+ p_pic->p->i_pixel_pitch = p_pic->p_sys->p_image->depth;
+ p_pic->p->i_visible_pitch = 2 * p_pic->p_sys->p_image->width;
+
+ p_pic->i_planes = 1;
+
+ break;
+
+ case VLC_FOURCC('R','V','3','2'):
+ case VLC_FOURCC('R','V','2','4'):
+
+ p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ + p_pic->p_sys->p_image->xoffset;
+ p_pic->p->i_lines = p_pic->p_sys->p_image->height;
+ p_pic->p->i_pitch = p_pic->p_sys->p_image->bytes_per_line;
+ p_pic->p->i_pixel_pitch = p_pic->p_sys->p_image->depth;
+ p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_image->width;
+
+ p_pic->i_planes = 1;
+
+ break;
+#endif
+
+ default:
+ /* Unknown chroma, tell the guy to get lost */
+ IMAGE_FREE( p_pic->p_sys->p_image );
+ free( p_pic->p_sys );
+ msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
+ p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );
+ p_pic->i_planes = 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreePicture: destroy a picture allocated with NewPicture
+ *****************************************************************************
+ * Destroy XImage AND associated data. If using Shm, detach shared memory
+ * segment from server and process, then free it. The XDestroyImage manpage
+ * says that both the image structure _and_ the data pointed to by the
+ * image structure are freed, so no need to free p_image->data.
+ *****************************************************************************/
+static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+ /* The order of operations is correct */
+#ifdef HAVE_SYS_SHM_H
+ if( p_vout->p_sys->b_shm )
+ {
+ XShmDetach( p_vout->p_sys->p_display, &p_pic->p_sys->shminfo );
+ IMAGE_FREE( p_pic->p_sys->p_image );
+
+ shmctl( p_pic->p_sys->shminfo.shmid, IPC_RMID, 0 );
+ if( shmdt( p_pic->p_sys->shminfo.shmaddr ) )
+ {
+ msg_Err( p_vout, "cannot detach shared memory (%s)",
+ strerror(errno) );
+ }
+ }
+ else
+#endif
+ {
+ IMAGE_FREE( p_pic->p_sys->p_image );
+ }
+
+ /* Do NOT use XFlush here ! */
+ XSync( p_vout->p_sys->p_display, False );
+
+ free( p_pic->p_sys );
+}
+
+/*****************************************************************************
+ * ToggleFullScreen: Enable or disable full screen mode
+ *****************************************************************************
+ * This function will switch between fullscreen and window mode.
+ *****************************************************************************/
+static void ToggleFullScreen ( vout_thread_t *p_vout )
+{
+ Atom prop;
+ mwmhints_t mwmhints;
+ XSetWindowAttributes attributes;
+
+ p_vout->b_fullscreen = !p_vout->b_fullscreen;
+
+ if( p_vout->b_fullscreen )
+ {
+ msg_Dbg( p_vout, "entering fullscreen mode" );
+ p_vout->p_sys->p_win = &p_vout->p_sys->fullscreen_window;
+
+ /* Only check the fullscreen method when we actually go fullscreen,
+ * because to go back to window mode we need to know in which
+ * fullscreen mode we were */
+ p_vout->p_sys->b_altfullscreen =
+ config_GetInt( p_vout, MODULE_STRING "-altfullscreen" );
+
+ /* fullscreen window size and position */
+ p_vout->p_sys->p_win->i_width =
+ DisplayWidth( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
+ p_vout->p_sys->p_win->i_height =
+ DisplayHeight( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
+
+ CreateWindow( p_vout, p_vout->p_sys->p_win );
+
+ /* To my knowledge there are two ways to create a borderless window.
+ * There's the generic way which is to tell x to bypass the window
+ * manager, but this creates problems with the focus of other
+ * applications.
+ * The other way is to use the motif property "_MOTIF_WM_HINTS" which
+ * luckily seems to be supported by most window managers. */
+ if( !p_vout->p_sys->b_altfullscreen )
+ {
+ mwmhints.flags = MWM_HINTS_DECORATIONS;
+ mwmhints.decorations = !p_vout->b_fullscreen;
+
+ prop = XInternAtom( p_vout->p_sys->p_display, "_MOTIF_WM_HINTS",
+ False );
+ XChangeProperty( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ prop, prop, 32, PropModeReplace,
+ (unsigned char *)&mwmhints,
+ PROP_MWM_HINTS_ELEMENTS );
+ }
+ else
+ {
+ /* brute force way to remove decorations */
+ attributes.override_redirect = p_vout->b_fullscreen;
+ XChangeWindowAttributes( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ CWOverrideRedirect,
+ &attributes);
+ }
+
+ XReparentWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 0, 0 );
+ XMoveResizeWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ 0, 0,
+ p_vout->p_sys->p_win->i_width,
+ p_vout->p_sys->p_win->i_height );
+ }
+ else
+ {
+ msg_Dbg( p_vout, "leaving fullscreen mode" );
+ DestroyWindow( p_vout, &p_vout->p_sys->fullscreen_window );
+ p_vout->p_sys->p_win = &p_vout->p_sys->original_window;
+ }
+
+ XSync( p_vout->p_sys->p_display, True );
+
+ if( !p_vout->b_fullscreen || p_vout->p_sys->b_altfullscreen )
+ {
+ XSetInputFocus(p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ RevertToParent,
+ CurrentTime);
+ }
+
+ /* signal that the size needs to be updated */
+ p_vout->i_changes |= VOUT_SIZE_CHANGE;
+}
+
+/*****************************************************************************
+ * EnableXScreenSaver: enable screen saver
+ *****************************************************************************
+ * This function enables the screen saver on a display after it has been
+ * disabled by XDisableScreenSaver.
+ * FIXME: what happens if multiple vlc sessions are running at the same
+ * time ???
+ *****************************************************************************/
+static void EnableXScreenSaver( vout_thread_t *p_vout )
+{
+#ifdef DPMSINFO_IN_DPMS_H
+ int dummy;
+#endif
+
+ XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
+ p_vout->p_sys->i_ss_interval,
+ p_vout->p_sys->i_ss_blanking,
+ p_vout->p_sys->i_ss_exposure );
+
+ /* Restore DPMS settings */
+#ifdef DPMSINFO_IN_DPMS_H
+ if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
+ {
+ if( p_vout->p_sys->b_ss_dpms )
+ {
+ DPMSEnable( p_vout->p_sys->p_display );
+ }
+ }
+#endif
+}
+
+/*****************************************************************************
+ * DisableXScreenSaver: disable screen saver
+ *****************************************************************************
+ * See XEnableXScreenSaver
+ *****************************************************************************/
+static void DisableXScreenSaver( vout_thread_t *p_vout )
+{
+#ifdef DPMSINFO_IN_DPMS_H
+ int dummy;
+#endif
+
+ /* Save screen saver informations */
+ XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
+ &p_vout->p_sys->i_ss_interval,
+ &p_vout->p_sys->i_ss_blanking,
+ &p_vout->p_sys->i_ss_exposure );
+
+ /* Disable screen saver */
+ XSetScreenSaver( p_vout->p_sys->p_display, 0,
+ p_vout->p_sys->i_ss_interval,
+ p_vout->p_sys->i_ss_blanking,
+ p_vout->p_sys->i_ss_exposure );
+
+ /* Disable DPMS */
+#ifdef DPMSINFO_IN_DPMS_H
+ if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
+ {
+ CARD16 unused;
+ /* Save DPMS current state */
+ DPMSInfo( p_vout->p_sys->p_display, &unused,
+ &p_vout->p_sys->b_ss_dpms );
+ DPMSDisable( p_vout->p_sys->p_display );
+ }
+#endif
+}
+
+/*****************************************************************************
+ * CreateCursor: create a blank mouse pointer
+ *****************************************************************************/
+static void CreateCursor( vout_thread_t *p_vout )
+{
+ XColor cursor_color;
+
+ p_vout->p_sys->cursor_pixmap =
+ XCreatePixmap( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 1, 1, 1 );
+
+ XParseColor( p_vout->p_sys->p_display,
+ XCreateColormap( p_vout->p_sys->p_display,
+ DefaultRootWindow(
+ p_vout->p_sys->p_display ),
+ DefaultVisual(
+ p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen ),
+ AllocNone ),
+ "black", &cursor_color );
+
+ p_vout->p_sys->blank_cursor =
+ XCreatePixmapCursor( p_vout->p_sys->p_display,
+ p_vout->p_sys->cursor_pixmap,
+ p_vout->p_sys->cursor_pixmap,
+ &cursor_color, &cursor_color, 1, 1 );
+}
+
+/*****************************************************************************
+ * DestroyCursor: destroy the blank mouse pointer
+ *****************************************************************************/
+static void DestroyCursor( vout_thread_t *p_vout )
+{
+ XFreePixmap( p_vout->p_sys->p_display, p_vout->p_sys->cursor_pixmap );
+}
+
+/*****************************************************************************
+ * ToggleCursor: hide or show the mouse pointer
+ *****************************************************************************
+ * This function hides the X pointer if it is visible by setting the pointer
+ * sprite to a blank one. To show it again, we disable the sprite.
+ *****************************************************************************/
+static void ToggleCursor( vout_thread_t *p_vout )
+{
+ if( p_vout->p_sys->b_mouse_pointer_visible )
+ {
+ XDefineCursor( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ p_vout->p_sys->blank_cursor );
+ p_vout->p_sys->b_mouse_pointer_visible = 0;
+ }
+ else
+ {
+ XUndefineCursor( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window );
+ p_vout->p_sys->b_mouse_pointer_visible = 1;
+ }
+}
+
+#ifdef MODULE_NAME_IS_xvideo
+/*****************************************************************************
+ * XVideoGetPort: get YUV12 port
+ *****************************************************************************/
+static int XVideoGetPort( vout_thread_t *p_vout,
+ vlc_fourcc_t i_chroma, vlc_fourcc_t *pi_newchroma )
+{
+ XvAdaptorInfo *p_adaptor;
+ unsigned int i;
+ int i_adaptor, i_num_adaptors, i_requested_adaptor;
+ int i_selected_port;
+
+ switch( XvQueryExtension( p_vout->p_sys->p_display, &i, &i, &i, &i, &i ) )
+ {
+ case Success:
+ break;
+
+ case XvBadExtension:
+ msg_Warn( p_vout, "XvBadExtension" );
+ return( -1 );
+
+ case XvBadAlloc:
+ msg_Warn( p_vout, "XvBadAlloc" );
+ return( -1 );
+
+ default:
+ msg_Warn( p_vout, "XvQueryExtension failed" );
+ return( -1 );
+ }
+
+ switch( XvQueryAdaptors( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ &i_num_adaptors, &p_adaptor ) )
+ {
+ case Success:
+ break;
+
+ case XvBadExtension:
+ msg_Warn( p_vout, "XvBadExtension for XvQueryAdaptors" );
+ return( -1 );
+
+ case XvBadAlloc:
+ msg_Warn( p_vout, "XvBadAlloc for XvQueryAdaptors" );
+ return( -1 );
+
+ default:
+ msg_Warn( p_vout, "XvQueryAdaptors failed" );
+ return( -1 );
+ }
+
+ i_selected_port = -1;
+ i_requested_adaptor = config_GetInt( p_vout, "xvideo-adaptor" );
+
+ for( i_adaptor = 0; i_adaptor < i_num_adaptors; ++i_adaptor )
+ {
+ XvImageFormatValues *p_formats;
+ int i_format, i_num_formats;
+ int i_port;
+
+ /* If we requested an adaptor and it's not this one, we aren't
+ * interested */
+ if( i_requested_adaptor != -1 && i_adaptor != i_requested_adaptor )
+ {
+ continue;
+ }
+
+ /* If the adaptor doesn't have the required properties, skip it */
+ if( !( p_adaptor[ i_adaptor ].type & XvInputMask ) ||
+ !( p_adaptor[ i_adaptor ].type & XvImageMask ) )
+ {
+ continue;
+ }
+
+ /* Check that adaptor supports our requested format... */
+ p_formats = XvListImageFormats( p_vout->p_sys->p_display,
+ p_adaptor[i_adaptor].base_id,
+ &i_num_formats );
+
+ for( i_format = 0;
+ i_format < i_num_formats && ( i_selected_port == -1 );
+ i_format++ )
+ {
+ /* Code removed, we can get this through xvinfo anyway */
+#if 0
+ XvEncodingInfo *p_enc;
+ int i_enc, i_num_encodings;
+ XvAttribute *p_attr;
+ int i_attr, i_num_attributes;
+#endif
+
+ /* If this is not the format we want, or at least a
+ * similar one, forget it */
+ if( !vout_ChromaCmp( p_formats[ i_format ].id, i_chroma ) )
+ {
+ continue;
+ }
+
+ /* Look for the first available port supporting this format */
+ for( i_port = p_adaptor[i_adaptor].base_id;
+ ( i_port < p_adaptor[i_adaptor].base_id
+ + p_adaptor[i_adaptor].num_ports )
+ && ( i_selected_port == -1 );
+ i_port++ )
+ {
+ if( XvGrabPort( p_vout->p_sys->p_display, i_port, CurrentTime )
+ == Success )
+ {
+ i_selected_port = i_port;
+ *pi_newchroma = p_formats[ i_format ].id;
+ }
+ }
+
+ /* If no free port was found, forget it */
+ if( i_selected_port == -1 )
+ {
+ continue;
+ }
+
+ /* If we found a port, print information about it */
+ msg_Dbg( p_vout, "adaptor %i, port %i, format 0x%x (%4.4s) %s",
+ i_adaptor, i_selected_port, p_formats[ i_format ].id,
+ (char *)&p_formats[ i_format ].id,
+ ( p_formats[ i_format ].format == XvPacked ) ?
+ "packed" : "planar" );
+
+#if 0
+ msg_Dbg( p_vout, " encoding list:" );
+
+ if( XvQueryEncodings( p_vout->p_sys->p_display, i_selected_port,
+ &i_num_encodings, &p_enc )
+ != Success )
+ {
+ msg_Dbg( p_vout, " XvQueryEncodings failed" );
+ continue;
+ }
+
+ for( i_enc = 0; i_enc < i_num_encodings; i_enc++ )
+ {
+ msg_Dbg( p_vout, " id=%ld, name=%s, size=%ldx%ld,"
+ " numerator=%d, denominator=%d",
+ p_enc[i_enc].encoding_id, p_enc[i_enc].name,
+ p_enc[i_enc].width, p_enc[i_enc].height,
+ p_enc[i_enc].rate.numerator,
+ p_enc[i_enc].rate.denominator );
+ }
+
+ if( p_enc != NULL )
+ {
+ XvFreeEncodingInfo( p_enc );
+ }
+
+ msg_Dbg( p_vout, " attribute list:" );
+ p_attr = XvQueryPortAttributes( p_vout->p_sys->p_display,
+ i_selected_port,
+ &i_num_attributes );
+ for( i_attr = 0; i_attr < i_num_attributes; i_attr++ )
+ {
+ msg_Dbg( p_vout, " name=%s, flags=[%s%s ], min=%i, max=%i",
+ p_attr[i_attr].name,
+ (p_attr[i_attr].flags & XvGettable) ? " get" : "",
+ (p_attr[i_attr].flags & XvSettable) ? " set" : "",
+ p_attr[i_attr].min_value, p_attr[i_attr].max_value );
+ }
+
+ if( p_attr != NULL )
+ {
+ XFree( p_attr );
+ }
+#endif
+ }
+
+ if( p_formats != NULL )
+ {
+ XFree( p_formats );
+ }
+
+ }
+
+ if( i_num_adaptors > 0 )
+ {
+ XvFreeAdaptorInfo( p_adaptor );
+ }
+
+ if( i_selected_port == -1 )
+ {
+ if( i_requested_adaptor == -1 )
+ {
+ msg_Warn( p_vout, "no free XVideo port found for format "
+ "0x%.8x (%4.4s)", i_chroma, (char*)&i_chroma );
+ }
+ else
+ {
+ msg_Warn( p_vout, "XVideo adaptor %i does not have a free "
+ "XVideo port for format 0x%.8x (%4.4s)",
+ i_requested_adaptor, i_chroma, (char*)&i_chroma );
+ }
+ }
+
+ return( i_selected_port );
+}
+
+/*****************************************************************************
+ * XVideoReleasePort: release YUV12 port
+ *****************************************************************************/
+static void XVideoReleasePort( vout_thread_t *p_vout, int i_port )
+{
+ XvUngrabPort( p_vout->p_sys->p_display, i_port, CurrentTime );
+}
+#endif
+
+/*****************************************************************************
+ * InitDisplay: open and initialize X11 device
+ *****************************************************************************
+ * Create a window according to video output given size, and set other
+ * properties according to the display properties.
+ *****************************************************************************/
+static int InitDisplay( vout_thread_t *p_vout )
+{
+#ifdef MODULE_NAME_IS_x11
+ XPixmapFormatValues * p_formats; /* pixmap formats */
+ XVisualInfo * p_xvisual; /* visuals informations */
+ XVisualInfo xvisual_template; /* visual template */
+ int i_count; /* array size */
+#endif
+
+#ifdef HAVE_SYS_SHM_H
+ p_vout->p_sys->b_shm = 0;
+
+ if( config_GetInt( p_vout, MODULE_STRING "-shm" ) )
+ {
+# ifdef SYS_DARWIN
+ /* FIXME: As of 2001-03-16, XFree4 for MacOS X does not support Xshm */
+# else
+ p_vout->p_sys->b_shm =
+ ( XShmQueryExtension( p_vout->p_sys->p_display ) == True );
+# endif
+
+ if( !p_vout->p_sys->b_shm )
+ {
+ msg_Warn( p_vout, "XShm video extension is unavailable" );
+ }
+ }
+ else
+ {
+ msg_Dbg( p_vout, "disabling XShm video extension" );
+ }
+
+#else
+ msg_Warn( p_vout, "XShm video extension is unavailable" );
+
+#endif
+
+#ifdef MODULE_NAME_IS_xvideo
+ /* XXX The brightness and contrast values should be read from environment
+ * XXX variables... */
+#if 0
+ XVideoSetAttribute( p_vout, "XV_BRIGHTNESS", 0.5 );
+ XVideoSetAttribute( p_vout, "XV_CONTRAST", 0.5 );
+#endif
+#endif
+
+#ifdef MODULE_NAME_IS_x11
+ /* Initialize structure */
+ p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
+
+ /* Get screen depth */
+ p_vout->p_sys->i_screen_depth = XDefaultDepth( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen );
+ switch( p_vout->p_sys->i_screen_depth )
+ {
+ case 8:
+ /*
+ * Screen depth is 8bpp. Use PseudoColor visual with private colormap.
+ */
+ xvisual_template.screen = p_vout->p_sys->i_screen;
+ xvisual_template.class = DirectColor;
+ p_xvisual = XGetVisualInfo( p_vout->p_sys->p_display,
+ VisualScreenMask | VisualClassMask,
+ &xvisual_template, &i_count );
+ if( p_xvisual == NULL )
+ {
+ msg_Err( p_vout, "no PseudoColor visual available" );
+ return( 1 );
+ }
+ p_vout->p_sys->i_bytes_per_pixel = 1;
+ p_vout->output.pf_setpalette = SetPalette;
+ break;
+ case 15:
+ case 16:
+ case 24:
+ default:
+ /*
+ * Screen depth is higher than 8bpp. TrueColor visual is used.
+ */
+ xvisual_template.screen = p_vout->p_sys->i_screen;
+ xvisual_template.class = TrueColor;
+ p_xvisual = XGetVisualInfo( p_vout->p_sys->p_display,
+ VisualScreenMask | VisualClassMask,
+ &xvisual_template, &i_count );
+ if( p_xvisual == NULL )
+ {
+ msg_Err( p_vout, "no TrueColor visual available" );
+ return( 1 );
+ }
+
+ p_vout->output.i_rmask = p_xvisual->red_mask;
+ p_vout->output.i_gmask = p_xvisual->green_mask;
+ p_vout->output.i_bmask = p_xvisual->blue_mask;
+
+ /* There is no difference yet between 3 and 4 Bpp. The only way
+ * to find the actual number of bytes per pixel is to list supported
+ * pixmap formats. */
+ p_formats = XListPixmapFormats( p_vout->p_sys->p_display, &i_count );
+ p_vout->p_sys->i_bytes_per_pixel = 0;
+
+ for( ; i_count-- ; p_formats++ )
+ {
+ /* Under XFree4.0, the list contains pixmap formats available
+ * through all video depths ; so we have to check against current
+ * depth. */
+ if( p_formats->depth == p_vout->p_sys->i_screen_depth )
+ {
+ if( p_formats->bits_per_pixel / 8
+ > p_vout->p_sys->i_bytes_per_pixel )
+ {
+ p_vout->p_sys->i_bytes_per_pixel = p_formats->bits_per_pixel / 8;
+ }
+ }
+ }
+ break;
+ }
+ p_vout->p_sys->p_visual = p_xvisual->visual;
+ XFree( p_xvisual );
+#endif
+
+ return( 0 );
+}
+
+#ifdef HAVE_SYS_SHM_H
+/*****************************************************************************
+ * CreateShmImage: create an XImage or XvImage using shared memory extension
+ *****************************************************************************
+ * Prepare an XImage or XvImage for display function.
+ * The order of the operations respects the recommandations of the mit-shm
+ * document by J.Corbet and K.Packard. Most of the parameters were copied from
+ * there. See http://ftp.xfree86.org/pub/XFree86/4.0/doc/mit-shm.TXT
+ *****************************************************************************/
+static IMAGE_TYPE * CreateShmImage( vout_thread_t *p_vout,
+ Display* p_display, EXTRA_ARGS_SHM,
+ int i_width, int i_height )
+{
+ IMAGE_TYPE *p_image;
+
+ /* Create XImage / XvImage */
+#ifdef MODULE_NAME_IS_xvideo
+ p_image = XvShmCreateImage( p_display, i_xvport, i_chroma, 0,
+ i_width, i_height, p_shm );
+#else
+ p_image = XShmCreateImage( p_display, p_visual, i_depth, ZPixmap, 0,
+ p_shm, i_width, i_height );
+#endif
+ if( p_image == NULL )
+ {
+ msg_Err( p_vout, "image creation failed" );
+ return( NULL );
+ }
+
+ /* Allocate shared memory segment - 0776 set the access permission
+ * rights (like umask), they are not yet supported by all X servers */
+ p_shm->shmid = shmget( IPC_PRIVATE, DATA_SIZE(p_image), IPC_CREAT | 0776 );
+ if( p_shm->shmid < 0 )
+ {
+ msg_Err( p_vout, "cannot allocate shared image data (%s)",
+ strerror( errno ) );
+ IMAGE_FREE( p_image );
+ return( NULL );
+ }
+
+ /* Attach shared memory segment to process (read/write) */
+ p_shm->shmaddr = p_image->data = shmat( p_shm->shmid, 0, 0 );
+ if(! p_shm->shmaddr )
+ {
+ msg_Err( p_vout, "cannot attach shared memory (%s)",
+ strerror(errno));
+ IMAGE_FREE( p_image );
+ shmctl( p_shm->shmid, IPC_RMID, 0 );
+ return( NULL );
+ }
+
+ /* Read-only data. We won't be using XShmGetImage */
+ p_shm->readOnly = True;
+
+ /* Attach shared memory segment to X server */
+ if( XShmAttach( p_display, p_shm ) == False )
+ {
+ msg_Err( p_vout, "cannot attach shared memory to X server" );
+ IMAGE_FREE( p_image );
+ shmctl( p_shm->shmid, IPC_RMID, 0 );
+ shmdt( p_shm->shmaddr );
+ return( NULL );
+ }
+
+ /* Send image to X server. This instruction is required, since having
+ * built a Shm XImage and not using it causes an error on XCloseDisplay,
+ * and remember NOT to use XFlush ! */
+ XSync( p_display, False );
+
+#if 0
+ /* Mark the shm segment to be removed when there are no more
+ * attachements, so it is automatic on process exit or after shmdt */
+ shmctl( p_shm->shmid, IPC_RMID, 0 );
+#endif
+
+ return( p_image );
+}
+#endif
+
+/*****************************************************************************
+ * CreateImage: create an XImage or XvImage
+ *****************************************************************************
+ * Create a simple image used as a buffer.
+ *****************************************************************************/
+static IMAGE_TYPE * CreateImage( vout_thread_t *p_vout,
+ Display *p_display, EXTRA_ARGS,
+ int i_width, int i_height )
+{
+ byte_t * p_data; /* image data storage zone */
+ IMAGE_TYPE *p_image;
+#ifdef MODULE_NAME_IS_x11
+ int i_quantum; /* XImage quantum (see below) */
+ int i_bytes_per_line;
+#endif
+
+ /* Allocate memory for image */
+#ifdef MODULE_NAME_IS_xvideo
+ p_data = (byte_t *) malloc( i_width * i_height * 2 ); /* XXX */
+#else
+ i_bytes_per_line = i_width * i_bytes_per_pixel;
+ p_data = (byte_t *) malloc( i_bytes_per_line * i_height );
+#endif
+ if( !p_data )
+ {
+ msg_Err( p_vout, "out of memory" );
+ return( NULL );
+ }
+
+#ifdef MODULE_NAME_IS_x11
+ /* Optimize the quantum of a scanline regarding its size - the quantum is
+ a diviser of the number of bits between the start of two scanlines. */
+ if( i_bytes_per_line & 0xf )
+ {
+ i_quantum = 0x8;
+ }
+ else if( i_bytes_per_line & 0x10 )
+ {
+ i_quantum = 0x10;
+ }
+ else
+ {
+ i_quantum = 0x20;
+ }
+#endif
+
+ /* Create XImage. p_data will be automatically freed */
+#ifdef MODULE_NAME_IS_xvideo
+ p_image = XvCreateImage( p_display, i_xvport, i_chroma,
+ p_data, i_width, i_height );
+#else
+ p_image = XCreateImage( p_display, p_visual, i_depth, ZPixmap, 0,
+ p_data, i_width, i_height, i_quantum, 0 );
+#endif
+ if( p_image == NULL )
+ {
+ msg_Err( p_vout, "XCreateImage() failed" );
+ free( p_data );
+ return( NULL );
+ }
+
+ return p_image;
+}
+
+#ifdef MODULE_NAME_IS_x11
+/*****************************************************************************
+ * SetPalette: sets an 8 bpp palette
+ *****************************************************************************
+ * This function sets the palette given as an argument. It does not return
+ * anything, but could later send information on which colors it was unable
+ * to set.
+ *****************************************************************************/
+static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
+{
+ int i;
+ XColor p_colors[255];
+
+ /* allocate palette */
+ for( i = 0; i < 255; i++ )
+ {
+ /* kludge: colors are indexed reversely because color 255 seems
+ * to be reserved for black even if we try to set it to white */
+ p_colors[ i ].pixel = 255 - i;
+ p_colors[ i ].pad = 0;
+ p_colors[ i ].flags = DoRed | DoGreen | DoBlue;
+ p_colors[ i ].red = red[ 255 - i ];
+ p_colors[ i ].blue = blue[ 255 - i ];
+ p_colors[ i ].green = green[ 255 - i ];
+ }
+
+ XStoreColors( p_vout->p_sys->p_display,
+ p_vout->p_sys->colormap, p_colors, 255 );
+}
+#endif
--- /dev/null
+/*****************************************************************************
+ * xcommon.h: Defines common to the X11 and XVideo plugins
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: xcommon.h,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * David Kennedy <dkennedy@tinytoad.com>
+ * Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Defines
+ *****************************************************************************/
+#ifdef MODULE_NAME_IS_xvideo
+# define IMAGE_TYPE XvImage
+# define EXTRA_ARGS int i_xvport, int i_chroma
+# define EXTRA_ARGS_SHM int i_xvport, int i_chroma, XShmSegmentInfo *p_shm
+# define DATA_SIZE(p) (p)->data_size
+# define IMAGE_FREE XFree /* There is nothing like XvDestroyImage */
+#else
+# define IMAGE_TYPE XImage
+# define EXTRA_ARGS Visual *p_visual, int i_depth, int i_bytes_per_pixel
+# define EXTRA_ARGS_SHM Visual *p_visual, int i_depth, XShmSegmentInfo *p_shm
+# define DATA_SIZE(p) ((p)->bytes_per_line * (p)->height)
+# define IMAGE_FREE XDestroyImage
+#endif
+
+VLC_DECLARE_STRUCT(x11_window_t)
+
+/*****************************************************************************
+ * x11_window_t: X11 window descriptor
+ *****************************************************************************
+ * This structure contains all the data necessary to describe an X11 window.
+ *****************************************************************************/
+struct x11_window_t
+{
+ Window base_window; /* base window */
+ Window video_window; /* sub-window for displaying video */
+ GC gc; /* graphic context instance handler */
+ int i_width; /* width of main window */
+ int i_height; /* height of main window */
+ Atom wm_protocols;
+ Atom wm_delete_window;
+};
+
+/*****************************************************************************
+ * vout_sys_t: video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the X11 and XVideo specific properties of an output thread.
+ *****************************************************************************/
+struct vout_sys_t
+{
+ /* Internal settings and properties */
+ Display * p_display; /* display pointer */
+
+ Visual * p_visual; /* visual pointer */
+ int i_screen; /* screen number */
+
+ /* Our current window */
+ x11_window_t * p_win;
+
+ /* Our two windows */
+ x11_window_t original_window;
+ x11_window_t fullscreen_window;
+
+ /* X11 generic properties */
+ vlc_bool_t b_altfullscreen; /* which fullscreen method */
+ vlc_bool_t b_createwindow; /* are we the base window's owner ? */
+#ifdef HAVE_SYS_SHM_H
+ vlc_bool_t b_shm; /* shared memory extension flag */
+#endif
+
+#ifdef MODULE_NAME_IS_xvideo
+ int i_xvport;
+#else
+ Colormap colormap; /* colormap used (8bpp only) */
+
+ int i_screen_depth;
+ int i_bytes_per_pixel;
+ int i_bytes_per_line;
+#endif
+
+ /* Screen saver properties */
+ int i_ss_timeout; /* timeout */
+ int i_ss_interval; /* interval between changes */
+ int i_ss_blanking; /* blanking mode */
+ int i_ss_exposure; /* exposure mode */
+#ifdef DPMSINFO_IN_DPMS_H
+ BOOL b_ss_dpms; /* DPMS mode */
+#endif
+
+ /* Mouse pointer properties */
+ vlc_bool_t b_mouse_pointer_visible;
+ mtime_t i_time_mouse_last_moved; /* used to auto-hide pointer*/
+ Cursor blank_cursor; /* the hidden cursor */
+ mtime_t i_time_button_last_pressed; /* to track dbl-clicks */
+ Pixmap cursor_pixmap;
+};
+
+/*****************************************************************************
+ * picture_sys_t: direct buffer method descriptor
+ *****************************************************************************
+ * This structure is part of the picture descriptor, it describes the
+ * XVideo specific properties of a direct buffer.
+ *****************************************************************************/
+struct picture_sys_t
+{
+ IMAGE_TYPE * p_image;
+
+#ifdef HAVE_SYS_SHM_H
+ XShmSegmentInfo shminfo; /* shared memory zone information */
+#endif
+};
+
+/*****************************************************************************
+ * mwmhints_t: window manager hints
+ *****************************************************************************
+ * Fullscreen needs to be able to hide the wm decorations so we provide
+ * this structure to make it easier.
+ *****************************************************************************/
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define PROP_MWM_HINTS_ELEMENTS 5
+typedef struct mwmhints_t
+{
+ u32 flags;
+ u32 functions;
+ u32 decorations;
+ s32 input_mode;
+ u32 status;
+} mwmhints_t;
+
+/*****************************************************************************
+ * Chroma defines
+ *****************************************************************************/
+#ifdef MODULE_NAME_IS_xvideo
+# define MAX_DIRECTBUFFERS 10
+#else
+# define MAX_DIRECTBUFFERS 2
+#endif
+
--- /dev/null
+/*****************************************************************************
+ * xvideo.c : Xvideo plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: xvideo.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Shane Harper <shanegh@optusnet.com.au>
+ * Vincent Seguin <seguin@via.ecp.fr>
+ * Samuel Hocevar <sam@zoy.org>
+ * David Kennedy <dkennedy@tinytoad.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+extern int E_(Activate) ( vlc_object_t * );
+extern void E_(Deactivate) ( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define ADAPTOR_TEXT N_("XVideo adaptor number")
+#define ADAPTOR_LONGTEXT N_( \
+ "If you graphics card provides several adaptors, this option allows you " \
+ "to choose which one will be used (you shouldn't have to change this).")
+
+#define ALT_FS_TEXT N_("alternate fullscreen method")
+#define ALT_FS_LONGTEXT N_( \
+ "There are two ways to make a fullscreen window, unfortunately each one " \
+ "has its drawbacks.\n" \
+ "1) Let the window manager handle your fullscreen window (default). But " \
+ "things like taskbars will likely show on top of the video.\n" \
+ "2) Completly bypass the window manager, but then nothing will be able " \
+ "to show on top of the video.")
+
+#define DISPLAY_TEXT N_("X11 display name")
+#define DISPLAY_LONGTEXT N_( \
+ "Specify the X11 hardware display you want to use. By default vlc will " \
+ "use the value of the DISPLAY environment variable.")
+
+#define CHROMA_TEXT N_("XVimage chroma format")
+#define CHROMA_LONGTEXT N_( \
+ "Force the XVideo renderer to use a specific chroma format instead of " \
+ "trying to improve performances by using the most efficient one.")
+
+#define DRAWABLE_TEXT N_("X11 drawable")
+#define DRAWABLE_LONGTEXT N_( \
+ "Specify a X11 drawable to use instead of opening a new window. This " \
+ "option is DANGEROUS, use with care.")
+
+#define SHM_TEXT N_("use shared memory")
+#define SHM_LONGTEXT N_( \
+ "Use shared memory to communicate between vlc and the X server.")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_string( "xvideo-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT );
+ add_integer( "xvideo-adaptor", -1, NULL, ADAPTOR_TEXT, ADAPTOR_LONGTEXT );
+ add_bool( "xvideo-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT );
+ add_string( "xvideo-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT );
+ add_integer( "xvideo-drawable", -1, NULL, DRAWABLE_TEXT, DRAWABLE_LONGTEXT );
+#ifdef HAVE_SYS_SHM_H
+ add_bool( "xvideo-shm", 1, NULL, SHM_TEXT, SHM_LONGTEXT );
+#endif
+ set_description( _("XVideo extension module") );
+ set_capability( "video output", 150 );
+ set_callbacks( E_(Activate), E_(Deactivate) );
+vlc_module_end();
+
+/* following functions are local */
+
+#if 0
+/*****************************************************************************
+ * XVideoSetAttribute
+ *****************************************************************************
+ * This function can be used to set attributes, e.g. XV_BRIGHTNESS and
+ * XV_CONTRAST. "f_value" should be in the range of 0 to 1.
+ *****************************************************************************/
+static void XVideoSetAttribute( vout_thread_t *p_vout,
+ char *attr_name, float f_value )
+{
+ int i_attrib;
+ XvAttribute *p_attrib;
+ Display *p_display = p_vout->p_sys->p_display;
+ int i_xvport = p_vout->p_sys->i_xvport;
+
+ p_attrib = XvQueryPortAttributes( p_display, i_xvport, &i_attrib );
+
+ do
+ {
+ i_attrib--;
+
+ if( i_attrib >= 0 && !strcmp( p_attrib[ i_attrib ].name, attr_name ) )
+ {
+ int i_sv = f_value * ( p_attrib[ i_attrib ].max_value
+ - p_attrib[ i_attrib ].min_value + 1 )
+ + p_attrib[ i_attrib ].min_value;
+
+ XvSetPortAttribute( p_display, i_xvport,
+ XInternAtom( p_display, attr_name, False ), i_sv );
+ break;
+ }
+
+ } while( i_attrib > 0 );
+
+ if( p_attrib )
+ XFree( p_attrib );
+}
+#endif
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+scope_SOURCES = scope.c
--- /dev/null
+/*****************************************************************************
+ * scope.c : Scope effect module
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: scope.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strdup() */
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/vout.h>
+
+#define SCOPE_WIDTH 320
+#define SCOPE_HEIGHT 240
+#define SCOPE_ASPECT (VOUT_ASPECT_FACTOR*SCOPE_WIDTH/SCOPE_HEIGHT)
+
+/*****************************************************************************
+ * aout_sys_t: scope audio output method descriptor
+ *****************************************************************************
+ * This structure is part of the audio output thread descriptor.
+ * It describes some scope specific variables.
+ *****************************************************************************/
+struct aout_sys_t
+{
+ aout_fifo_t *p_aout_fifo;
+
+ aout_thread_t *p_aout;
+ vout_thread_t *p_vout;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static int SetFormat ( aout_thread_t * );
+static int GetBufInfo ( aout_thread_t *, int );
+static void Play ( aout_thread_t *, byte_t *, int );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("scope effect") );
+ set_capability( "audio output", 0 );
+ set_callbacks( Open, Close );
+ add_shortcut( "scope" );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: open a scope effect plugin
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+ char *psz_method;
+
+ /* Allocate structure */
+ p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
+ if( p_aout->p_sys == NULL )
+ {
+ msg_Err( p_aout, "out of memory" );
+ return -1;
+ }
+
+ psz_method = config_GetPsz( p_aout, "aout" );
+ if( psz_method )
+ {
+ if( !*psz_method )
+ {
+ free( psz_method );
+ return -1;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+
+ /* Open video output */
+ p_aout->p_sys->p_vout =
+ vout_CreateThread( p_aout, SCOPE_WIDTH, SCOPE_HEIGHT,
+ VLC_FOURCC('I','4','2','0'), SCOPE_ASPECT );
+
+ if( p_aout->p_sys->p_vout == NULL )
+ {
+ msg_Err( p_aout, "no suitable vout module" );
+ free( p_aout->p_sys );
+ return -1;
+ }
+
+ /* Open audio output */
+ p_aout->p_sys->p_aout = vlc_object_create( p_aout, VLC_OBJECT_AOUT );
+
+ p_aout->p_sys->p_aout->i_format = p_aout->i_format;
+ p_aout->p_sys->p_aout->i_rate = p_aout->i_rate;
+ p_aout->p_sys->p_aout->i_channels = p_aout->i_channels;
+
+ p_aout->p_sys->p_aout->p_module =
+ module_Need( p_aout->p_sys->p_aout, "audio output", "" );
+ if( p_aout->p_sys->p_aout->p_module == NULL )
+ {
+ msg_Err( p_aout, "no suitable aout module" );
+ vlc_object_destroy( p_aout->p_sys->p_aout );
+ vout_DestroyThread( p_aout->p_sys->p_vout );
+ free( p_aout->p_sys );
+ return -1;
+ }
+
+ vlc_object_attach( p_aout->p_sys->p_aout, p_aout );
+
+ p_aout->pf_setformat = SetFormat;
+ p_aout->pf_getbufinfo = GetBufInfo;
+ p_aout->pf_play = Play;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * SetFormat: set the output format
+ *****************************************************************************/
+static int SetFormat( aout_thread_t *p_aout )
+{
+ int i_ret;
+
+ /* Force the output method */
+ p_aout->p_sys->p_aout->i_format = p_aout->i_format;
+ p_aout->p_sys->p_aout->i_channels = p_aout->i_channels;
+ p_aout->p_sys->p_aout->i_rate = p_aout->i_rate;
+
+ /*
+ * Initialize audio device
+ */
+ i_ret = p_aout->p_sys->p_aout->pf_setformat( p_aout->p_sys->p_aout );
+
+ if( i_ret )
+ {
+ return i_ret;
+ }
+
+ if( p_aout->p_sys->p_aout->i_format != p_aout->i_format
+ || p_aout->p_sys->p_aout->i_channels != p_aout->i_channels )
+ {
+ msg_Err( p_aout, "plugin is not very cooperative" );
+ return 0;
+ }
+
+ p_aout->i_channels = p_aout->p_sys->p_aout->i_channels;
+ p_aout->i_format = p_aout->p_sys->p_aout->i_format;
+ p_aout->i_rate = p_aout->p_sys->p_aout->i_rate;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * GetBufInfo: buffer status query
+ *****************************************************************************/
+static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
+{
+ return p_aout->p_sys->p_aout->pf_getbufinfo( p_aout->p_sys->p_aout,
+ i_buffer_limit );
+}
+
+/*****************************************************************************
+ * Play: play a sound samples buffer
+ *****************************************************************************
+ * This function writes a buffer of i_length bytes in the socket
+ *****************************************************************************/
+static void Play( aout_thread_t *p_aout, byte_t *p_buffer, int i_size )
+{
+ picture_t *p_outpic;
+ int i_index, i_image;
+ u8 *ppp_area[2][3];
+ u16 *p_sample;
+
+ /* Play the real sound */
+ p_aout->p_sys->p_aout->pf_play( p_aout->p_sys->p_aout, p_buffer, i_size );
+
+ for( i_image = 0; (i_image + 1) * SCOPE_WIDTH * 8 < i_size ; i_image++ )
+ {
+ /* Don't stay here forever */
+ if( mdate() >= p_aout->date - 10000 )
+ {
+ break;
+ }
+
+ /* This is a new frame. Get a structure from the video_output. */
+ while( ( p_outpic = vout_CreatePicture( p_aout->p_sys->p_vout, 0, 0, 0 ) )
+ == NULL )
+ {
+ if( p_aout->b_die )
+ {
+ return;
+ }
+ msleep( VOUT_OUTMEM_SLEEP );
+ }
+
+ /* Blank the picture */
+ for( i_index = 0 ; i_index < p_outpic->i_planes ; i_index++ )
+ {
+ memset( p_outpic->p[i_index].p_pixels, i_index ? 0x80 : 0x00,
+ p_outpic->p[i_index].i_lines * p_outpic->p[i_index].i_pitch );
+ }
+
+ /* We only support 2 channels for now */
+ for( i_index = 0 ; i_index < 2 ; i_index++ )
+ {
+ int j;
+ for( j = 0 ; j < 3 ; j++ )
+ {
+ ppp_area[i_index][j] =
+ p_outpic->p[j].p_pixels + i_index * p_outpic->p[j].i_lines
+ / p_aout->i_channels * p_outpic->p[j].i_pitch;
+ }
+ }
+
+ for( i_index = 0, p_sample = (u16*)p_buffer;
+ i_index < SCOPE_WIDTH;
+ i_index++ )
+ {
+ int i;
+ u8 i_value;
+
+ for( i = 0 ; i < 2 ; i++ )
+ {
+ /* Left channel */
+ i_value = *p_sample++ / 256 + 128;
+ *(ppp_area[0][0]
+ + p_outpic->p[0].i_pitch * i_index / SCOPE_WIDTH
+ + p_outpic->p[0].i_lines * i_value / 512
+ * p_outpic->p[0].i_pitch) = 0xbf;
+ *(ppp_area[0][1]
+ + p_outpic->p[1].i_pitch * i_index / SCOPE_WIDTH
+ + p_outpic->p[1].i_lines * i_value / 512
+ * p_outpic->p[1].i_pitch) = 0xff;
+
+ /* Right channel */
+ i_value = *p_sample++ / 256 + 128;
+ *(ppp_area[1][0]
+ + p_outpic->p[0].i_pitch * i_index / SCOPE_WIDTH
+ + p_outpic->p[0].i_lines * i_value / 512
+ * p_outpic->p[0].i_pitch) = 0x9f;
+ *(ppp_area[1][2]
+ + p_outpic->p[2].i_pitch * i_index / SCOPE_WIDTH
+ + p_outpic->p[2].i_lines * i_value / 512
+ * p_outpic->p[2].i_pitch) = 0xdd;
+ }
+ }
+
+ /* Display the picture - FIXME: find a better date :-) */
+ vout_DatePicture( p_aout->p_sys->p_vout, p_outpic,
+ p_aout->date + i_image * 20000 );
+ vout_DisplayPicture( p_aout->p_sys->p_vout, p_outpic );
+
+ p_buffer += SCOPE_WIDTH * 4;
+ }
+}
+
+/*****************************************************************************
+ * Close: close the plugin
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ aout_thread_t *p_aout = (aout_thread_t *)p_this;
+
+ /* Kill audio output */
+ module_Unneed( p_aout->p_sys->p_aout, p_aout->p_sys->p_aout->p_module );
+ vlc_object_detach_all( p_aout->p_sys->p_aout );
+ vlc_object_destroy( p_aout->p_sys->p_aout );
+
+ /* Kill video output */
+ vout_DestroyThread( p_aout->p_sys->p_vout );
+
+ free( p_aout->p_sys );
+}
+
--- /dev/null
+.dep
+*.lo
+*.o.*
+*.lo.*
--- /dev/null
+xosd_SOURCES = xosd.c
--- /dev/null
+/*****************************************************************************
+ * xosd.c : X On Screen Display interface
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: xosd.c,v 1.1 2002/08/04 17:23:44 sam Exp $
+ *
+ * Authors: Loïc Minier <lool@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <xosd.h>
+
+#include <vlc/intf.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+/*****************************************************************************
+ * intf_sys_t: description and status of rc interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ input_thread_t * p_input; /* associated input thread */
+ xosd * p_osd; /* libxosd handle */
+ char * psz_source; /* current file || NULL */
+};
+
+#define MAX_LINE_LENGTH 256
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static void Run ( intf_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define POSITION_TEXT N_("flip vertical position")
+#define POSITION_LONGTEXT N_("Display xosd output on the bottom of the " \
+ "screen instead of the top")
+
+#define TXT_OFS_TEXT N_("vertical offset")
+#define TXT_OFS_LONGTEXT N_("Vertical offset in pixels of the displayed text")
+
+#define SHD_OFS_TEXT N_("shadow offset")
+#define SHD_OFS_LONGTEXT N_("Offset in pixels of the shadow")
+
+#define FONT_TEXT N_("font")
+#define FONT_LONGTEXT N_("Font used to display text in the xosd output")
+
+vlc_module_begin();
+ add_category_hint( N_("Miscellaneous"), NULL );
+ add_bool( "xosd-position", 1, NULL, POSITION_TEXT, POSITION_LONGTEXT );
+ add_integer( "xosd-text-offset", 0, NULL, TXT_OFS_TEXT, TXT_OFS_LONGTEXT );
+ add_integer( "xosd-shadow-offset", 1, NULL,
+ SHD_OFS_TEXT, SHD_OFS_LONGTEXT );
+ add_string( "xosd-font", "-misc-fixed-medium-r-*-*-*-300-*-*-*-*-*-*",
+ NULL, FONT_TEXT, FONT_LONGTEXT );
+ set_description( _("xosd interface module") );
+ set_capability( "interface", 40 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open: initialize and create stuff
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return( 1 );
+ }
+
+ /* Initialize library */
+ p_intf->p_sys->p_osd =
+ xosd_init( "fixed", "LawnGreen", 3, XOSD_top, 0, 1 );
+
+ /* Initialize to NULL */
+ p_intf->p_sys->psz_source = NULL;
+
+ xosd_display( p_intf->p_sys->p_osd,
+ 0,
+ XOSD_string,
+ "xosd interface initialized" );
+
+ p_intf->pf_run = Run;
+
+ return( 0 );
+}
+
+/*****************************************************************************
+ * Close: destroy interface stuff
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ if( p_intf->p_sys->psz_source ) free( p_intf->p_sys->psz_source );
+
+ /* Uninitialize library */
+ xosd_uninit( p_intf->p_sys->p_osd );
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * Run: xosd thread
+ *****************************************************************************
+ * This part of the interface runs in a separate thread
+ *****************************************************************************/
+static void Run( intf_thread_t *p_intf )
+{
+ p_intf->p_sys->p_input = NULL;
+
+ while( !p_intf->b_die )
+ {
+ /* Manage the input part */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+ else /* We have a valid input */
+ {
+ /* Did source change? */
+ if ( (p_intf->p_sys->psz_source == NULL)
+ || (strcmp( p_intf->p_sys->psz_source,
+ p_intf->p_sys->p_input->psz_source ) != 0)
+ )
+ {
+ if( p_intf->p_sys->psz_source )
+ free( p_intf->p_sys->psz_source );
+
+ p_intf->p_sys->psz_source =
+ strdup( p_intf->p_sys->p_input->psz_source );
+
+ /* Set user preferences */
+ xosd_set_font( p_intf->p_sys->p_osd,
+ config_GetPsz( p_intf, "xosd-font" ) );
+ xosd_set_offset( p_intf->p_sys->p_osd,
+ config_GetInt( p_intf, "xosd-text-offset" ) );
+ xosd_set_shadow_offset( p_intf->p_sys->p_osd,
+ config_GetInt( p_intf, "xosd-shadow-offset" ));
+ xosd_set_pos( p_intf->p_sys->p_osd,
+ config_GetInt( p_intf, "xosd-position" ) ? XOSD_bottom
+ : XOSD_top );
+
+ /* Display */
+ xosd_display( p_intf->p_sys->p_osd,
+ 0, /* first line */
+ XOSD_string,
+ p_intf->p_sys->psz_source );
+ }
+ }
+
+ msleep( INTF_IDLE_SLEEP );
+ }
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+}
+
/*****************************************************************************
- * aout_spdif.c: AC3 passthrough output
+ * aout_spdif.c: A52 passthrough output
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: aout_spdif.c,v 1.29 2002/06/01 12:32:01 sam Exp $
+ * $Id: aout_spdif.c,v 1.30 2002/08/04 17:23:44 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Stéphane Borel <stef@via.ecp.fr>
*****************************************************************************
* This output thread is quite specific as it can only handle one fifo now.
*
- * Note: spdif can demux up to 8 ac3 streams, and can even take
- * care of time stamps (cf ac3 spec) but I'm not sure all decoders
+ * Note: spdif can demux up to 8 A52 streams, and can even take
+ * care of time stamps (cf A52 spec) but I'm not sure all decoders
* implement it.
*****************************************************************************/
void aout_SpdifThread( aout_thread_t * p_aout )
(p_aout->fifo[i_fifo].i_start_frame + 1 )
& AOUT_FIFO_SIZE;
- /* Compute the theorical duration of an ac3 frame */
- m_frame_time = 1000000 * AC3_FRAME_SIZE
+ /* Compute the theorical duration of an A52 frame */
+ m_frame_time = 1000000 * A52_FRAME_SIZE
/ p_aout->fifo[i_fifo].i_rate;
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/*****************************************************************************
- * aout_spdif.h: AC3 passthrough output
+ * aout_spdif.h: A52 passthrough output
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: aout_spdif.h,v 1.1 2002/02/24 22:12:45 sam Exp $
+ * $Id: aout_spdif.h,v 1.2 2002/08/04 17:23:44 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Stéphane Borel <stef@via.ecp.fr>
* audio_output.c : audio output thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: audio_output.c,v 1.87 2002/07/31 20:56:52 sam Exp $
+ * $Id: audio_output.c,v 1.88 2002/08/04 17:23:44 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
i_bytes = 2 * p_aout->i_units * p_aout->i_channels;
break;
- case AOUT_FMT_AC3:
+ case AOUT_FMT_A52:
pf_aout_thread = aout_SpdifThread;
- psz_format = "ac3 pass-through";
+ psz_format = "A52 pass-through";
i_bytes = SPDIF_FRAME_SIZE;
break;
* mpeg_system.c: TS, PS and PES management
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
- * $Id: mpeg_system.c,v 1.100 2002/07/23 00:39:17 sam Exp $
+ * $Id: mpeg_system.c,v 1.101 2002/08/04 17:23:44 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr>
if( p_es->i_fourcc == VLC_FOURCC('a','5','2',' ') )
{
- /* With ac3 audio, we need to skip first 3 bytes */
+ /* With A52 audio, we need to skip first 3 bytes */
i_pes_header_size += 3;
}
p_es->i_fourcc = VLC_FOURCC('m','p','g','a');
p_es->i_cat = AUDIO_ES;
break;
- case AC3_AUDIO_ES:
+ case A52_AUDIO_ES:
p_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
p_es->i_cat = AUDIO_ES;
break;
}
else if( (i_id & 0xF0FF) == 0x80BD )
{
- /* AC3 audio (0x80->0x8F) */
+ /* A52 audio (0x80->0x8F) */
p_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
p_es->i_cat = AUDIO_ES;
#ifdef AUTO_SPAWN
switch( config_GetInt( p_input, "audio-type" ) )
{
case -1:
- case REQUESTED_AC3:
+ case REQUESTED_A52:
input_SelectES( p_input, p_es );
}
#endif
* libvlc.h: main libvlc header
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
- * $Id: libvlc.h,v 1.9 2002/07/31 20:56:52 sam Exp $
+ * $Id: libvlc.h,v 1.10 2002/08/04 17:23:44 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
"4 -> 8 bits signed\n" \
"5 -> 16 bits unsigned little endian\n" \
"6 -> 16 bits unsigned big endian\n" \
- "7 -> mpeg2 audio (unsupported)\n" \
- "8 -> ac3 pass-through")
+ "7 -> MPEG2 audio (unsupported)\n" \
+ "8 -> A52 pass-through")
#define RATE_TEXT N_("audio output frequency (Hz)")
#define RATE_LONGTEXT N_( \
#define CODEC_TEXT N_("choose preferred codec list")
#define CODEC_LONGTEXT N_( \
"This allows you to select the order in which vlc will choose its " \
- "codecs. For instance, 'a52,ac3,any' will try the a52 codec before " \
- "the ac3 one. Please be aware that vlc does not make any difference " \
- "between audio or video codecs, so you should always specify 'any' at " \
- "the end of the list to make sure there is a fallback for all types.")
+ "codecs. For instance, 'a52old,a52,any' will try the old a52 codec " \
+ "before the new one. Please be aware that vlc does not make any " \
+ "difference between audio or video codecs, so you should always specify " \
+ "'any' at the end of the list to make sure there is a fallback for the " \
+ "types you didn't specify.")
#define MMX_TEXT N_("enable CPU MMX support")
#define MMX_LONGTEXT N_( \
* modules.c : Builtin and plugin modules management functions
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: modules.c,v 1.76 2002/08/04 12:18:41 sam Exp $
+ * $Id: modules.c,v 1.77 2002/08/04 17:23:44 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Ethan C. Baldridge <BaldridgeE@cadmus.com>
static void AllocateAllPlugins( vlc_object_t *p_this )
{
/* Yes, there are two NULLs because we replace one with "plugin-path". */
- char * path[] = { "plugins", PLUGIN_PATH, NULL, NULL };
+ char * path[] = { "modules", PLUGIN_PATH, NULL, NULL };
char ** ppsz_path = path;
char * psz_fullpath;