]> git.sesse.net Git - vlc/commitdiff
* ./modules/*: moved plugins to the new tree. Yet untested builds include
authorSam Hocevar <sam@videolan.org>
Sun, 4 Aug 2002 17:23:44 +0000 (17:23 +0000)
committerSam Hocevar <sam@videolan.org>
Sun, 4 Aug 2002 17:23:44 +0000 (17:23 +0000)
    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.

459 files changed:
Makefile
Makefile.modules
Makefile.opts.in
configure
configure.in
doc/mad/API [new file with mode: 0644]
doc/mad/BUGS [new file with mode: 0644]
doc/mad/DESIGN [new file with mode: 0644]
doc/mad/TODO [new file with mode: 0644]
doc/mad/joe_drew.txt [new file with mode: 0644]
doc/mad/rob_leslie.txt [new file with mode: 0644]
include/audio_output.h
include/input_ext-dec.h
include/input_ext-intf.h
modules/access/.cvsignore [new file with mode: 0644]
modules/access/Makefile [new file with mode: 0644]
modules/access/dvd/.cvsignore [new file with mode: 0644]
modules/access/dvd/Makefile [new file with mode: 0644]
modules/access/dvd/access.c [new file with mode: 0644]
modules/access/dvd/demux.c [new file with mode: 0644]
modules/access/dvd/dvd.c [new file with mode: 0644]
modules/access/dvd/dvd.h [new file with mode: 0644]
modules/access/dvd/dvdcss.h [new file with mode: 0644]
modules/access/dvd/es.c [new file with mode: 0644]
modules/access/dvd/es.h [new file with mode: 0644]
modules/access/dvd/ifo.c [new file with mode: 0644]
modules/access/dvd/ifo.h [new file with mode: 0644]
modules/access/dvd/seek.c [new file with mode: 0644]
modules/access/dvd/seek.h [new file with mode: 0644]
modules/access/dvd/summary.c [new file with mode: 0644]
modules/access/dvd/summary.h [new file with mode: 0644]
modules/access/dvd/udf.c [new file with mode: 0644]
modules/access/dvd/udf.h [new file with mode: 0644]
modules/access/dvdplay/.cvsignore [new file with mode: 0644]
modules/access/dvdplay/Makefile [new file with mode: 0644]
modules/access/dvdplay/access.c [new file with mode: 0644]
modules/access/dvdplay/access.h [new file with mode: 0644]
modules/access/dvdplay/demux.c [new file with mode: 0644]
modules/access/dvdplay/demux.h [new file with mode: 0644]
modules/access/dvdplay/dvd.c [new file with mode: 0644]
modules/access/dvdplay/dvd.h [new file with mode: 0644]
modules/access/dvdplay/es.c [new file with mode: 0644]
modules/access/dvdplay/es.h [new file with mode: 0644]
modules/access/dvdplay/intf.c [new file with mode: 0644]
modules/access/dvdplay/intf.h [new file with mode: 0644]
modules/access/dvdplay/tools.c [new file with mode: 0644]
modules/access/dvdplay/tools.h [new file with mode: 0644]
modules/access/dvdread/.cvsignore [new file with mode: 0644]
modules/access/dvdread/Makefile [new file with mode: 0644]
modules/access/dvdread/dvdread.c [new file with mode: 0644]
modules/access/dvdread/input.c [new file with mode: 0644]
modules/access/dvdread/input.h [new file with mode: 0644]
modules/access/file.c [new file with mode: 0644]
modules/access/http.c [new file with mode: 0644]
modules/access/satellite/.cvsignore [new file with mode: 0644]
modules/access/satellite/Makefile [new file with mode: 0644]
modules/access/satellite/access.c [new file with mode: 0644]
modules/access/satellite/dvb.c [new file with mode: 0644]
modules/access/satellite/dvb.h [new file with mode: 0644]
modules/access/satellite/satellite.c [new file with mode: 0644]
modules/access/udp.c [new file with mode: 0644]
modules/access/vcd/.cvsignore [new file with mode: 0644]
modules/access/vcd/Makefile [new file with mode: 0644]
modules/access/vcd/cdrom.c [new file with mode: 0644]
modules/access/vcd/cdrom.h [new file with mode: 0644]
modules/access/vcd/vcd.c [new file with mode: 0644]
modules/access/vcd/vcd.h [new file with mode: 0644]
modules/audio_output/alsa/.cvsignore [new file with mode: 0644]
modules/audio_output/alsa/Makefile [new file with mode: 0644]
modules/audio_output/alsa/alsa.c [new file with mode: 0644]
modules/audio_output/arts/.cvsignore [new file with mode: 0644]
modules/audio_output/arts/Makefile [new file with mode: 0644]
modules/audio_output/arts/arts.c [new file with mode: 0644]
modules/audio_output/dsp/.cvsignore [new file with mode: 0644]
modules/audio_output/dsp/Makefile [new file with mode: 0644]
modules/audio_output/dsp/dsp.c [new file with mode: 0644]
modules/audio_output/esd/.cvsignore [new file with mode: 0644]
modules/audio_output/esd/Makefile [new file with mode: 0644]
modules/audio_output/esd/esd.c [new file with mode: 0644]
modules/audio_output/waveout/.cvsignore [new file with mode: 0644]
modules/audio_output/waveout/Makefile [new file with mode: 0644]
modules/audio_output/waveout/waveout.c [new file with mode: 0644]
modules/codec/a52/.cvsignore [new file with mode: 0644]
modules/codec/a52/Makefile [new file with mode: 0644]
modules/codec/a52/a52.c [new file with mode: 0644]
modules/codec/a52/a52.h [new file with mode: 0644]
modules/codec/a52old/.cvsignore [new file with mode: 0644]
modules/codec/a52old/Makefile [new file with mode: 0644]
modules/codec/a52old/a52old.c [new file with mode: 0644]
modules/codec/a52old/adec.h [new file with mode: 0644]
modules/codec/a52old/bit_allocate.c [new file with mode: 0644]
modules/codec/a52old/decoder.c [new file with mode: 0644]
modules/codec/a52old/decoder.h [new file with mode: 0644]
modules/codec/a52old/downmix.h [moved from include/ac3_downmix.h with 94% similarity]
modules/codec/a52old/downmix/.cvsignore [new file with mode: 0644]
modules/codec/a52old/downmix/Makefile [new file with mode: 0644]
modules/codec/a52old/downmix/downmix.c [new file with mode: 0644]
modules/codec/a52old/downmix/downmix_3dn.c [new file with mode: 0644]
modules/codec/a52old/downmix/downmix_c.c [new file with mode: 0644]
modules/codec/a52old/downmix/downmix_common.h [new file with mode: 0644]
modules/codec/a52old/downmix/downmix_sse.c [new file with mode: 0644]
modules/codec/a52old/exponent.c [new file with mode: 0644]
modules/codec/a52old/exponent.h [new file with mode: 0644]
modules/codec/a52old/imdct.c [new file with mode: 0644]
modules/codec/a52old/imdct.h [moved from include/ac3_imdct.h with 97% similarity]
modules/codec/a52old/imdct/.cvsignore [new file with mode: 0644]
modules/codec/a52old/imdct/Makefile [new file with mode: 0644]
modules/codec/a52old/imdct/imdct.c [new file with mode: 0644]
modules/codec/a52old/imdct/imdct_3dn.c [new file with mode: 0644]
modules/codec/a52old/imdct/imdct_c.c [new file with mode: 0644]
modules/codec/a52old/imdct/imdct_common.c [new file with mode: 0644]
modules/codec/a52old/imdct/imdct_common.h [new file with mode: 0644]
modules/codec/a52old/imdct/imdct_sse.c [new file with mode: 0644]
modules/codec/a52old/imdct/retables.h [new file with mode: 0644]
modules/codec/a52old/imdct/srfft.h [new file with mode: 0644]
modules/codec/a52old/imdct/srfft_3dn.c [new file with mode: 0644]
modules/codec/a52old/imdct/srfft_c.c [new file with mode: 0644]
modules/codec/a52old/imdct/srfft_sse.c [new file with mode: 0644]
modules/codec/a52old/internal.h [new file with mode: 0644]
modules/codec/a52old/mantissa.c [new file with mode: 0644]
modules/codec/a52old/mantissa.h [new file with mode: 0644]
modules/codec/a52old/parse.c [new file with mode: 0644]
modules/codec/a52old/rematrix.c [new file with mode: 0644]
modules/codec/cinepak/.cvsignore [new file with mode: 0644]
modules/codec/cinepak/Makefile [new file with mode: 0644]
modules/codec/cinepak/cinepak.c [new file with mode: 0644]
modules/codec/cinepak/cinepak.h [new file with mode: 0644]
modules/codec/ffmpeg/.cvsignore [new file with mode: 0644]
modules/codec/ffmpeg/Makefile [new file with mode: 0644]
modules/codec/ffmpeg/ffmpeg.c [new file with mode: 0644]
modules/codec/ffmpeg/ffmpeg.h [new file with mode: 0644]
modules/codec/lpcm/.cvsignore [new file with mode: 0644]
modules/codec/lpcm/Makefile [new file with mode: 0644]
modules/codec/lpcm/lpcm.c [new file with mode: 0644]
modules/codec/lpcm/lpcm.h [new file with mode: 0644]
modules/codec/mad/.cvsignore [new file with mode: 0644]
modules/codec/mad/Makefile [new file with mode: 0644]
modules/codec/mad/decoder.c [new file with mode: 0644]
modules/codec/mad/decoder.h [new file with mode: 0644]
modules/codec/mad/libmad.c [new file with mode: 0644]
modules/codec/mad/libmad.h [new file with mode: 0644]
modules/codec/mpeg_audio/.cvsignore [new file with mode: 0644]
modules/codec/mpeg_audio/Makefile [new file with mode: 0644]
modules/codec/mpeg_audio/decoder.c [new file with mode: 0644]
modules/codec/mpeg_audio/decoder.h [new file with mode: 0644]
modules/codec/mpeg_audio/generic.c [new file with mode: 0644]
modules/codec/mpeg_audio/generic.h [new file with mode: 0644]
modules/codec/mpeg_audio/layer1.c [new file with mode: 0644]
modules/codec/mpeg_audio/layer1.h [new file with mode: 0644]
modules/codec/mpeg_audio/layer2.c [new file with mode: 0644]
modules/codec/mpeg_audio/layer2.h [new file with mode: 0644]
modules/codec/mpeg_audio/math.c [new file with mode: 0644]
modules/codec/mpeg_audio/math.h [new file with mode: 0644]
modules/codec/mpeg_audio/test.c [new file with mode: 0644]
modules/codec/mpeg_video/.cvsignore [new file with mode: 0644]
modules/codec/mpeg_video/Makefile [new file with mode: 0644]
modules/codec/mpeg_video/blocks.c [new file with mode: 0644]
modules/codec/mpeg_video/blocks.h [new file with mode: 0644]
modules/codec/mpeg_video/decoder.c [new file with mode: 0644]
modules/codec/mpeg_video/decoder.h [new file with mode: 0644]
modules/codec/mpeg_video/headers.c [new file with mode: 0644]
modules/codec/mpeg_video/idct/.cvsignore [new file with mode: 0644]
modules/codec/mpeg_video/idct/Makefile [new file with mode: 0644]
modules/codec/mpeg_video/idct/block_c.h [new file with mode: 0644]
modules/codec/mpeg_video/idct/block_mmx.h [new file with mode: 0644]
modules/codec/mpeg_video/idct/idct.c [new file with mode: 0644]
modules/codec/mpeg_video/idct/idct.h [new file with mode: 0644]
modules/codec/mpeg_video/idct/idct_decl.h [new file with mode: 0644]
modules/codec/mpeg_video/idct/idct_sparse.h [new file with mode: 0644]
modules/codec/mpeg_video/idct/idctaltivec.c [new file with mode: 0644]
modules/codec/mpeg_video/idct/idctclassic.c [new file with mode: 0644]
modules/codec/mpeg_video/idct/idctmmx.c [new file with mode: 0644]
modules/codec/mpeg_video/idct/idctmmxext.c [new file with mode: 0644]
modules/codec/mpeg_video/motion/.cvsignore [new file with mode: 0644]
modules/codec/mpeg_video/motion/Makefile [new file with mode: 0644]
modules/codec/mpeg_video/motion/motion.c [new file with mode: 0644]
modules/codec/mpeg_video/motion/motion3dnow.c [new file with mode: 0644]
modules/codec/mpeg_video/motion/motionaltivec.c [new file with mode: 0644]
modules/codec/mpeg_video/motion/motionmmx.c [new file with mode: 0644]
modules/codec/mpeg_video/motion/motionmmxext.c [new file with mode: 0644]
modules/codec/mpeg_video/parser.c [new file with mode: 0644]
modules/codec/mpeg_video/parser.h [new file with mode: 0644]
modules/codec/mpeg_video/pool.c [new file with mode: 0644]
modules/codec/mpeg_video/pool.h [new file with mode: 0644]
modules/codec/mpeg_video/synchro.c [new file with mode: 0644]
modules/codec/spdif/.cvsignore [new file with mode: 0644]
modules/codec/spdif/Makefile [new file with mode: 0644]
modules/codec/spdif/spdif.c [new file with mode: 0644]
modules/codec/spdif/spdif.h [new file with mode: 0644]
modules/codec/spudec/.cvsignore [new file with mode: 0644]
modules/codec/spudec/Makefile [new file with mode: 0644]
modules/codec/spudec/spudec.c [new file with mode: 0644]
modules/codec/spudec/spudec.h [new file with mode: 0644]
modules/control/lirc/.cvsignore [new file with mode: 0644]
modules/control/lirc/Makefile [new file with mode: 0644]
modules/control/lirc/lirc.c [new file with mode: 0644]
modules/control/rc/.cvsignore [new file with mode: 0644]
modules/control/rc/Makefile [new file with mode: 0644]
modules/control/rc/rc.c [new file with mode: 0644]
modules/demux/a52/.cvsignore [new file with mode: 0644]
modules/demux/a52/Makefile [new file with mode: 0644]
modules/demux/a52/demux.c [new file with mode: 0644]
modules/demux/avi/.cvsignore [new file with mode: 0644]
modules/demux/avi/Makefile [new file with mode: 0644]
modules/demux/avi/avi.c [new file with mode: 0644]
modules/demux/avi/avi.h [new file with mode: 0644]
modules/demux/avi/libioRIFF.c [new file with mode: 0644]
modules/demux/avi/libioRIFF.h [new file with mode: 0644]
modules/demux/mp4/.cvsignore [new file with mode: 0644]
modules/demux/mp4/Makefile [new file with mode: 0644]
modules/demux/mp4/libmp4.c [new file with mode: 0644]
modules/demux/mp4/libmp4.h [new file with mode: 0644]
modules/demux/mp4/mp4.c [new file with mode: 0644]
modules/demux/mp4/mp4.h [new file with mode: 0644]
modules/demux/mpeg/.cvsignore [new file with mode: 0644]
modules/demux/mpeg/Makefile [new file with mode: 0644]
modules/demux/mpeg/audio.c [new file with mode: 0644]
modules/demux/mpeg/es.c [new file with mode: 0644]
modules/demux/mpeg/ps.c [new file with mode: 0644]
modules/demux/mpeg/ts.c [new file with mode: 0644]
modules/gui/beos/.cvsignore [new file with mode: 0644]
modules/gui/beos/AudioOutput.cpp [new file with mode: 0644]
modules/gui/beos/BeOS.cpp [new file with mode: 0644]
modules/gui/beos/Bitmaps.h [new file with mode: 0644]
modules/gui/beos/DrawingTidbits.cpp [new file with mode: 0644]
modules/gui/beos/DrawingTidbits.h [new file with mode: 0644]
modules/gui/beos/Interface.cpp [new file with mode: 0644]
modules/gui/beos/InterfaceWindow.cpp [new file with mode: 0644]
modules/gui/beos/InterfaceWindow.h [new file with mode: 0644]
modules/gui/beos/Makefile [new file with mode: 0644]
modules/gui/beos/MediaControlView.cpp [new file with mode: 0644]
modules/gui/beos/MediaControlView.h [new file with mode: 0644]
modules/gui/beos/MsgVals.h [new file with mode: 0644]
modules/gui/beos/PlayListWindow.cpp [new file with mode: 0644]
modules/gui/beos/PlayListWindow.h [new file with mode: 0644]
modules/gui/beos/TransportButton.cpp [new file with mode: 0644]
modules/gui/beos/TransportButton.h [new file with mode: 0644]
modules/gui/beos/VideoOutput.cpp [new file with mode: 0644]
modules/gui/beos/VideoWindow.h [new file with mode: 0644]
modules/gui/beos/VlcWrapper.cpp [new file with mode: 0644]
modules/gui/beos/VlcWrapper.h [new file with mode: 0644]
modules/gui/familiar/.cvsignore [new file with mode: 0644]
modules/gui/familiar/Makefile [new file with mode: 0644]
modules/gui/familiar/callbacks.c [new file with mode: 0644]
modules/gui/familiar/callbacks.h [new file with mode: 0644]
modules/gui/familiar/familiar.c [new file with mode: 0644]
modules/gui/familiar/familiar.glade [new file with mode: 0644]
modules/gui/familiar/familiar.h [new file with mode: 0644]
modules/gui/familiar/interface.c [new file with mode: 0644]
modules/gui/familiar/interface.h [new file with mode: 0644]
modules/gui/familiar/support.c [new file with mode: 0644]
modules/gui/familiar/support.h [new file with mode: 0644]
modules/gui/gtk/.cvsignore [new file with mode: 0644]
modules/gui/gtk/Makefile [new file with mode: 0644]
modules/gui/gtk/common.h [new file with mode: 0644]
modules/gui/gtk/control.c [new file with mode: 0644]
modules/gui/gtk/control.h [new file with mode: 0644]
modules/gui/gtk/display.c [new file with mode: 0644]
modules/gui/gtk/display.h [new file with mode: 0644]
modules/gui/gtk/gnome.c [new file with mode: 0644]
modules/gui/gtk/gnome.glade [new file with mode: 0644]
modules/gui/gtk/gnome_callbacks.c [new file with mode: 0644]
modules/gui/gtk/gnome_callbacks.h [new file with mode: 0644]
modules/gui/gtk/gnome_interface.c [new file with mode: 0644]
modules/gui/gtk/gnome_interface.h [new file with mode: 0644]
modules/gui/gtk/gnome_support.c [new file with mode: 0644]
modules/gui/gtk/gnome_support.h [new file with mode: 0644]
modules/gui/gtk/gtk.c [new file with mode: 0644]
modules/gui/gtk/gtk.glade [new file with mode: 0644]
modules/gui/gtk/gtk_callbacks.c [new file with mode: 0644]
modules/gui/gtk/gtk_callbacks.h [new file with mode: 0644]
modules/gui/gtk/gtk_interface.c [new file with mode: 0644]
modules/gui/gtk/gtk_interface.h [new file with mode: 0644]
modules/gui/gtk/gtk_support.c [new file with mode: 0644]
modules/gui/gtk/gtk_support.h [new file with mode: 0644]
modules/gui/gtk/menu.c [new file with mode: 0644]
modules/gui/gtk/menu.h [new file with mode: 0644]
modules/gui/gtk/modules.c [new file with mode: 0644]
modules/gui/gtk/modules.h [new file with mode: 0644]
modules/gui/gtk/open.c [new file with mode: 0644]
modules/gui/gtk/open.h [new file with mode: 0644]
modules/gui/gtk/playlist.c [new file with mode: 0644]
modules/gui/gtk/playlist.h [new file with mode: 0644]
modules/gui/gtk/preferences.c [new file with mode: 0644]
modules/gui/gtk/preferences.h [new file with mode: 0644]
modules/gui/kde/.cvsignore [new file with mode: 0644]
modules/gui/kde/Makefile [new file with mode: 0644]
modules/gui/kde/QConfigItem.cpp [new file with mode: 0644]
modules/gui/kde/QConfigItem.h [new file with mode: 0644]
modules/gui/kde/common.h [new file with mode: 0644]
modules/gui/kde/disc.cpp [new file with mode: 0644]
modules/gui/kde/disc.h [new file with mode: 0644]
modules/gui/kde/interface.cpp [new file with mode: 0644]
modules/gui/kde/interface.h [new file with mode: 0644]
modules/gui/kde/kde.cpp [new file with mode: 0644]
modules/gui/kde/menu.cpp [new file with mode: 0644]
modules/gui/kde/menu.h [new file with mode: 0644]
modules/gui/kde/net.cpp [new file with mode: 0644]
modules/gui/kde/net.h [new file with mode: 0644]
modules/gui/kde/pluginsbox.cpp [new file with mode: 0644]
modules/gui/kde/pluginsbox.h [new file with mode: 0644]
modules/gui/kde/preferences.cpp [new file with mode: 0644]
modules/gui/kde/preferences.h [new file with mode: 0644]
modules/gui/kde/slider.cpp [new file with mode: 0644]
modules/gui/kde/slider.h [new file with mode: 0644]
modules/gui/kde/ui.rc [new file with mode: 0644]
modules/gui/macosx/.cvsignore [new file with mode: 0644]
modules/gui/macosx/Makefile [new file with mode: 0644]
modules/gui/macosx/aout.m [new file with mode: 0644]
modules/gui/macosx/controls.m [new file with mode: 0644]
modules/gui/macosx/intf.h [new file with mode: 0644]
modules/gui/macosx/intf.m [new file with mode: 0644]
modules/gui/macosx/macosx.m [new file with mode: 0644]
modules/gui/macosx/open.h [new file with mode: 0644]
modules/gui/macosx/open.m [new file with mode: 0644]
modules/gui/macosx/playlist.h [new file with mode: 0644]
modules/gui/macosx/playlist.m [new file with mode: 0644]
modules/gui/macosx/vout.h [new file with mode: 0644]
modules/gui/macosx/vout.m [new file with mode: 0644]
modules/gui/ncurses/.cvsignore [new file with mode: 0644]
modules/gui/ncurses/Makefile [new file with mode: 0644]
modules/gui/ncurses/ncurses.c [new file with mode: 0644]
modules/gui/qnx/.cvsignore [new file with mode: 0644]
modules/gui/qnx/Makefile [new file with mode: 0644]
modules/gui/qnx/aout.c [new file with mode: 0644]
modules/gui/qnx/qnx.c [new file with mode: 0644]
modules/gui/qnx/vout.c [new file with mode: 0644]
modules/gui/qt/.cvsignore [new file with mode: 0644]
modules/gui/qt/Makefile [new file with mode: 0644]
modules/gui/qt/intf.cpp [new file with mode: 0644]
modules/gui/qt/qt.cpp [new file with mode: 0644]
modules/gui/win32/.cvsignore [new file with mode: 0644]
modules/gui/win32/Makefile [new file with mode: 0644]
modules/gui/win32/about.cpp [new file with mode: 0644]
modules/gui/win32/about.dfm [new file with mode: 0644]
modules/gui/win32/about.h [new file with mode: 0644]
modules/gui/win32/control.cpp [new file with mode: 0644]
modules/gui/win32/control.h [new file with mode: 0644]
modules/gui/win32/disc.cpp [new file with mode: 0644]
modules/gui/win32/disc.dfm [new file with mode: 0644]
modules/gui/win32/disc.h [new file with mode: 0644]
modules/gui/win32/intfwin.bpf [new file with mode: 0644]
modules/gui/win32/intfwin.cpp [new file with mode: 0644]
modules/gui/win32/mainframe.cpp [new file with mode: 0644]
modules/gui/win32/mainframe.dfm [new file with mode: 0644]
modules/gui/win32/mainframe.h [new file with mode: 0644]
modules/gui/win32/menu.cpp [new file with mode: 0644]
modules/gui/win32/menu.h [new file with mode: 0644]
modules/gui/win32/messages.cpp [new file with mode: 0644]
modules/gui/win32/messages.dfm [new file with mode: 0644]
modules/gui/win32/messages.h [new file with mode: 0644]
modules/gui/win32/network.cpp [new file with mode: 0644]
modules/gui/win32/network.dfm [new file with mode: 0644]
modules/gui/win32/network.h [new file with mode: 0644]
modules/gui/win32/playlist.cpp [new file with mode: 0644]
modules/gui/win32/playlist.dfm [new file with mode: 0644]
modules/gui/win32/playlist.h [new file with mode: 0644]
modules/gui/win32/preferences.cpp [new file with mode: 0644]
modules/gui/win32/preferences.dfm [new file with mode: 0644]
modules/gui/win32/preferences.h [new file with mode: 0644]
modules/gui/win32/win32.bpr [new file with mode: 0644]
modules/gui/win32/win32.cpp [new file with mode: 0644]
modules/gui/win32/win32.h [new file with mode: 0644]
modules/gui/win32/win32_common.h [new file with mode: 0644]
modules/misc/dummy/.cvsignore [new file with mode: 0644]
modules/misc/dummy/Makefile [new file with mode: 0644]
modules/misc/dummy/aout.c [new file with mode: 0644]
modules/misc/dummy/decoder.c [new file with mode: 0644]
modules/misc/dummy/dummy.c [new file with mode: 0644]
modules/misc/dummy/dummy.h [new file with mode: 0644]
modules/misc/dummy/input.c [new file with mode: 0644]
modules/misc/dummy/interface.c [new file with mode: 0644]
modules/misc/dummy/vout.c [new file with mode: 0644]
modules/misc/logger/.cvsignore [new file with mode: 0644]
modules/misc/logger/Makefile [new file with mode: 0644]
modules/misc/logger/logger.c [new file with mode: 0644]
modules/misc/memcpy/.cvsignore [new file with mode: 0644]
modules/misc/memcpy/Makefile [new file with mode: 0644]
modules/misc/memcpy/fastmemcpy.h [new file with mode: 0644]
modules/misc/memcpy/memcpy.c [new file with mode: 0644]
modules/misc/memcpy/memcpyaltivec.c [new file with mode: 0644]
modules/misc/network/.cvsignore [new file with mode: 0644]
modules/misc/network/Makefile [new file with mode: 0644]
modules/misc/network/ipv4.c [new file with mode: 0644]
modules/misc/network/ipv6.c [new file with mode: 0644]
modules/misc/null/.cvsignore [new file with mode: 0644]
modules/misc/null/Makefile [new file with mode: 0644]
modules/misc/null/null.c [new file with mode: 0644]
modules/video_chroma/.cvsignore [new file with mode: 0644]
modules/video_chroma/Makefile [new file with mode: 0644]
modules/video_chroma/i420_rgb.c [new file with mode: 0644]
modules/video_chroma/i420_rgb.h [new file with mode: 0644]
modules/video_chroma/i420_rgb16.c [new file with mode: 0644]
modules/video_chroma/i420_rgb8.c [new file with mode: 0644]
modules/video_chroma/i420_rgb_c.h [new file with mode: 0644]
modules/video_chroma/i420_rgb_mmx.h [new file with mode: 0644]
modules/video_chroma/i420_ymga.c [new file with mode: 0644]
modules/video_chroma/i420_yuy2.c [new file with mode: 0644]
modules/video_chroma/i420_yuy2.h [new file with mode: 0644]
modules/video_chroma/i422_yuy2.c [new file with mode: 0644]
modules/video_chroma/i422_yuy2.h [new file with mode: 0644]
modules/video_filter/.cvsignore [new file with mode: 0644]
modules/video_filter/Makefile [new file with mode: 0644]
modules/video_filter/clone.c [new file with mode: 0644]
modules/video_filter/crop.c [new file with mode: 0644]
modules/video_filter/deinterlace/.cvsignore [new file with mode: 0644]
modules/video_filter/deinterlace/Makefile [new file with mode: 0644]
modules/video_filter/deinterlace/deinterlace.c [new file with mode: 0644]
modules/video_filter/distort.c [new file with mode: 0644]
modules/video_filter/filter_common.h [new file with mode: 0644]
modules/video_filter/invert.c [new file with mode: 0644]
modules/video_filter/transform.c [new file with mode: 0644]
modules/video_filter/wall.c [new file with mode: 0644]
modules/video_output/aa/.cvsignore [new file with mode: 0644]
modules/video_output/aa/Makefile [new file with mode: 0644]
modules/video_output/aa/aa.c [new file with mode: 0644]
modules/video_output/directx/.cvsignore [new file with mode: 0644]
modules/video_output/directx/Makefile [new file with mode: 0644]
modules/video_output/directx/aout.c [new file with mode: 0644]
modules/video_output/directx/directx.c [new file with mode: 0644]
modules/video_output/directx/events.c [new file with mode: 0644]
modules/video_output/directx/vout.c [new file with mode: 0644]
modules/video_output/directx/vout.h [new file with mode: 0644]
modules/video_output/fb/.cvsignore [new file with mode: 0644]
modules/video_output/fb/Makefile [new file with mode: 0644]
modules/video_output/fb/fb.c [new file with mode: 0644]
modules/video_output/ggi/.cvsignore [new file with mode: 0644]
modules/video_output/ggi/Makefile [new file with mode: 0644]
modules/video_output/ggi/ggi.c [new file with mode: 0644]
modules/video_output/glide/.cvsignore [new file with mode: 0644]
modules/video_output/glide/Makefile [new file with mode: 0644]
modules/video_output/glide/glide.c [new file with mode: 0644]
modules/video_output/mga/.cvsignore [new file with mode: 0644]
modules/video_output/mga/Makefile [new file with mode: 0644]
modules/video_output/mga/mga.c [new file with mode: 0644]
modules/video_output/mga/xmga.c [new file with mode: 0644]
modules/video_output/sdl/.cvsignore [new file with mode: 0644]
modules/video_output/sdl/Makefile [new file with mode: 0644]
modules/video_output/sdl/aout.c [new file with mode: 0644]
modules/video_output/sdl/sdl.c [new file with mode: 0644]
modules/video_output/sdl/vout.c [new file with mode: 0644]
modules/video_output/x11/.cvsignore [new file with mode: 0644]
modules/video_output/x11/Makefile [new file with mode: 0644]
modules/video_output/x11/x11.c [new file with mode: 0644]
modules/video_output/x11/xcommon.c [new file with mode: 0644]
modules/video_output/x11/xcommon.h [new file with mode: 0644]
modules/video_output/x11/xvideo.c [new file with mode: 0644]
modules/visualization/scope/.cvsignore [new file with mode: 0644]
modules/visualization/scope/Makefile [new file with mode: 0644]
modules/visualization/scope/scope.c [new file with mode: 0644]
modules/visualization/xosd/.cvsignore [new file with mode: 0644]
modules/visualization/xosd/Makefile [new file with mode: 0644]
modules/visualization/xosd/xosd.c [new file with mode: 0644]
src/audio_output/aout_spdif.c
src/audio_output/aout_spdif.h
src/audio_output/audio_output.c
src/input/mpeg_system.c
src/libvlc.h
src/misc/modules.c

index ea4b1f7a8512d37b6807477834c3667859251c05..4798c7dbb51ab73aff2df9b9df191e08043d1361 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,165 +13,6 @@ endif
 # Objects and files
 ###############################################################################
 
 # 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
 # 
 #
 # C Objects
 # 
@@ -238,10 +79,10 @@ CPP_DEP := $(CPP_OBJ:%.o=.dep/%.dpp)
 # Translate plugin names
 #
 ifneq (,$(PLUGINS))
 # 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))
 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
 
 #
 endif
 
 #
@@ -295,9 +136,9 @@ po-clean:
 
 plugins-clean:
        for dir in $(PLUGINS_DIR) ; do \
 
 plugins-clean:
        for dir in $(PLUGINS_DIR) ; do \
-               ( cd plugins/$${dir} \
+               ( cd modules/$${dir} \
                        && $(MAKE) -f ../../Makefile.modules clean ) ; done
                        && $(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)
 
 vlc-clean:
        rm -f $(C_OBJ) $(CPP_OBJ)
@@ -348,7 +189,7 @@ endif
 plugins-install:
        mkdir -p $(DESTDIR)$(libdir)/vlc
 ifneq (,$(PLUGINS))
 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:
 endif
 
 plugins-uninstall:
@@ -357,7 +198,7 @@ plugins-uninstall:
 builtins-install:
        mkdir -p $(DESTDIR)$(libdir)/vlc
 ifneq (,$(BUILTINS))
 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:
 endif
 
 builtins-uninstall:
@@ -410,13 +251,13 @@ dist:
        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 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 $$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
        # 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
                do cp $$i tmp/vlc/$$i ; done
        # Copy extra programs and documentation
        cp -a extras/* tmp/vlc/extras
@@ -472,12 +313,12 @@ package-win32:
        for file in AUTHORS COPYING ChangeLog README FAQ TODO ; \
                        do cp $$file tmp/$${file}.txt ; \
                        unix2dos tmp/$${file}.txt ; done
        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
        # 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))
 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 ; \
 endif
        mkdir tmp/share
        for file in default8x16.psf default8x9.psf ; \
@@ -504,9 +345,9 @@ package-beos:
        cp AUTHORS COPYING ChangeLog README FAQ TODO tmp/vlc/
        for file in default8x16.psf default8x9.psf ; \
                do cp share/$$file tmp/vlc/share/ ; done
        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} | \
        # Create package 
        mv tmp/vlc tmp/vlc-${VERSION}
        (cd tmp ; find vlc-${VERSION} | \
@@ -546,10 +387,10 @@ ifneq (,$(findstring darwin,$(SYS)))
        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
        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) 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
 endif
        $(INSTALL) -m 644 share/*.psf vlc.app/Contents/MacOS/share
 endif
@@ -564,7 +405,7 @@ src/misc/modules_builtin.h: Makefile.opts Makefile Makefile.config
        @rm -f $@ && cp $@.in $@
 ifneq (,$(BUILTINS))
        @for i in $(BUILTINS) ; do \
        @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
        done
        @echo "" >> $@ ;
 endif
@@ -573,7 +414,7 @@ endif
        @echo "    { \\" >> $@ ;
 ifneq (,$(BUILTINS))
        @for i in $(BUILTINS) ; do \
        @echo "    { \\" >> $@ ;
 ifneq (,$(BUILTINS))
        @for i in $(BUILTINS) ; do \
-               echo "        ALLOCATE_BUILTIN("$$i"); \\" >> $@ ; \
+               echo "        ALLOCATE_BUILTIN("`basename $$i`"); \\" >> $@ ; \
        done
 endif
        @echo "    } while( 0 );" >> $@ ;
        done
 endif
        @echo "    } while( 0 );" >> $@ ;
@@ -634,19 +475,11 @@ lib/libvlc.a: Makefile.opts Makefile.dep Makefile $(LIBVLC_OBJ)
 #lib/libvlc.so: Makefile.opts Makefile.dep Makefile $(LIBVLC_OBJ)
 #      $(CC) -shared $(LIBVLC_OBJ) $(LDFLAGS) $(vlc_LDFLAGS) -o $@
 
 #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)
 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
 
 #
 # Mozilla plugin target
index 5a04c8df2b44dabd051e932144d41110306e7d2a..3d9f603ec7b7465ddb48c2df777e9a7e83bd4fc2 100644 (file)
@@ -13,7 +13,7 @@ include Makefile
 #
 # Analyze the target we are asked to build
 #
 #
 # 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)
 
 #
 suff := $(shell echo $(MAKECMDGOALS) | sed 's@.*\.@@' | tr so/a lo/o)
 
 #
@@ -23,6 +23,9 @@ SRC_C := $(filter %.c,$($(module_name)_SOURCES))
 SRC_CPP := $(filter %.cpp,$($(module_name)_SOURCES))
 SRC_M := $(filter %.m,$($(module_name)_SOURCES))
 
 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) \
 ifeq (lo,$(suff))
 extra_CFLAGS := $(plugins_CFLAGS) $($(module_name)_CFLAGS) \
                 -DMODULE_NAME=$(module_name) -DMODULE_NAME_IS_$(module_name) \
@@ -57,17 +60,17 @@ clean:
 
 FORCE:
 
 
 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
 
 $(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
 
 $(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
 
 $(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
 
 $(SRC_C:%.c=%.$(suff).$(module_name)): %.$(suff).$(module_name): .dep/%.d
 $(SRC_C:%.c=%.$(suff).$(module_name)): %.$(suff).$(module_name): %.c
@@ -83,10 +86,10 @@ $(SRC_M:%.m=%.$(suff).$(module_name)): %.$(suff).$(module_name): %.m
 
 # foo_CUSTOM lets us override all target rules for foo.so and foo.a
 ifeq (,$($(module_name)_CUSTOM))
 
 # 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 $@
 
        $(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) $@
        rm -f $@
        ar rc $@ $(OBJ_ALL)
        $(RANLIB) $@
index f9d6de878c9a4df9b970d02444b58b6996b184ef..768ed80be8c0ae360fc1a95ea87ef61712c7fb60 100644 (file)
@@ -60,7 +60,7 @@ mozilla_CFLAGS = @mozilla_CFLAGS@
 
 a52_CFLAGS = @a52_CFLAGS@
 arts_CFLAGS = @arts_CFLAGS@
 
 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@
 directx_CFLAGS = @directx_CFLAGS@
 dvd_CFLAGS = @dvd_CFLAGS@
 dvdread_CFLAGS = @dvdread_CFLAGS@
@@ -76,7 +76,7 @@ kde_CFLAGS = @kde_CFLAGS@
 mad_CFLAGS = @mad_CFLAGS@
 memcpyaltivec_CFLAGS = @memcpyaltivec_CFLAGS@
 motionaltivec_CFLAGS = @motionaltivec_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@
 qt_CFLAGS = @qt_CFLAGS@
 sdl_CFLAGS = @sdl_CFLAGS@
 x11_CFLAGS = @x11_CFLAGS@
@@ -95,7 +95,7 @@ aa_LDFLAGS = @aa_LDFLAGS@
 alsa_LDFLAGS = @alsa_LDFLAGS@
 arts_LDFLAGS = @arts_LDFLAGS@
 beos_LDFLAGS = @beos_LDFLAGS@
 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@
 directx_LDFLAGS = @directx_LDFLAGS@
 dsp_LDFLAGS = @dsp_LDFLAGS@
 dvd_LDFLAGS = @dvd_LDFLAGS@
@@ -103,7 +103,7 @@ dvdread_LDFLAGS = @dvdread_LDFLAGS@
 dvdplay_LDFLAGS = @dvdplay_LDFLAGS@
 esd_LDFLAGS = @esd_LDFLAGS@
 familiar_LDFLAGS = @familiar_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@
 ffmpeg_LDFLAGS = @ffmpeg_LDFLAGS@
 mp4_LDFLAGS = @mp4_LDFLAGS@
 ggi_LDFLAGS = @ggi_LDFLAGS@
@@ -123,7 +123,7 @@ macosx_LDFLAGS = @macosx_LDFLAGS@
 mad_LDFLAGS = @mad_LDFLAGS@
 memcpyaltivec_LDFLAGS = @memcpyaltivec_LDFLAGS@
 motionaltivec_LDFLAGS = @motionaltivec_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@
 ncurses_LDFLAGS = @ncurses_LDFLAGS@
 qnx_LDFLAGS = @qnx_LDFLAGS@
 qt_LDFLAGS = @qt_LDFLAGS@
@@ -250,16 +250,10 @@ endif
 endif
 endif
 
 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
 #
 #
 # 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
 
 #
 # Debugging and profiling support
index 782b5c1680c1bd12fdaf9f7a5eb96e62ab87bf10..d3ee7331b25161675737dbdef01f10612a2d3bc7 100755 (executable)
--- a/configure
+++ b/configure
@@ -5386,7 +5386,7 @@ echo "$ac_t""$ac_cv_c_omit_frame_pointer" 1>&6
 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!
 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
 fi
 
 echo $ac_n "checking if \$CC accepts -bundle -undefined error -lcc_dynamic""... $ac_c" 1>&6
@@ -5532,29 +5532,35 @@ case "x${target_cpu}" in
 esac
 
 BUILTINS="${BUILTINS}"
 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 $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
 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
 #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
   rm -rf conftest*
   ac_cv_mmx_inline=yes
 else
@@ -5572,20 +5578,20 @@ if test "x${ac_cv_mmx_inline}" != "xno"; then
 fi
 
 echo $ac_n "checking if \$CC groks MMX EXT inline assembly""... $ac_c" 1>&6
 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
 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
 #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
   rm -rf conftest*
   ac_cv_mmxext_inline=yes
 else
@@ -5603,20 +5609,20 @@ if test "x${ac_cv_mmxext_inline}" != "xno"; then
 fi
 
 echo $ac_n "checking if \$CC groks 3D Now! inline assembly""... $ac_c" 1>&6
 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
 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
 #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
   rm -rf conftest*
   ac_cv_3dnow_inline=yes
 else
@@ -5638,20 +5644,20 @@ EOF
 fi
 
 echo $ac_n "checking if \$CC groks SSE inline assembly""... $ac_c" 1>&6
 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
 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
 #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
   rm -rf conftest*
   ac_cv_sse_inline=yes
 else
@@ -5676,20 +5682,20 @@ fi
 # 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
 # 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
 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
 #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*
   ac_cv_altivec_inline=yes
 else
@@ -5698,14 +5704,14 @@ else
   rm -rf conftest*
   CFLAGS="${save_CFLAGS} -Wa,-m7400"
           cat > conftest.$ac_ext <<EOF
   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
 #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
   rm -rf conftest*
   ac_cv_altivec_inline="-Wa,-m7400"
 else
@@ -5736,21 +5742,21 @@ EOF
 fi
 
 echo $ac_n "checking if \$CC groks AltiVec C extensions""... $ac_c" 1>&6
 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
 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
 #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
   rm -rf conftest*
   ac_cv_c_altivec=-faltivec
 else
@@ -5761,14 +5767,14 @@ else
         # Linux/PPC test
         CFLAGS="${save_CFLAGS} ${idctaltivec_CFLAGS} -fvec"
         cat > conftest.$ac_ext <<EOF
         # 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
 #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
   rm -rf conftest*
   ac_cv_c_altivec="-fvec"
 else
@@ -5798,20 +5804,20 @@ EOF
 fi
 
 echo $ac_n "checking if linker needs -framework vecLib""... $ac_c" 1>&6
 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
 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
 #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
   rm -rf conftest*
   ac_cv_ld_altivec=yes
 else
@@ -5943,17 +5949,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -5973,7 +5979,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
   cat >> confdefs.h <<EOF
 #define $ac_tr_hdr 1
 EOF
   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
           dvd_LDFLAGS="${dvd_LDFLAGS} -ldvdcss" 
 else
   echo "$ac_t""no" 1>&6
@@ -5984,7 +5990,7 @@ done
 
     else
       echo $ac_n "checking for libdvdcss.a in ${with_dvdcss_tree}""... $ac_c" 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
       real_dvdcss_tree="`cd ${with_dvdcss_tree} 2>/dev/null && pwd`"
       if test "x${real_dvdcss_tree}" = "x"
       then
@@ -5994,7 +6000,7 @@ echo "configure:5988: checking for libdvdcss.a in ${with_dvdcss_tree}" >&5
       if test -f "${real_dvdcss_tree}/src/.libs/libdvdcss.a"
       then
                 echo "$ac_t""${real_dvdcss_tree}/src/.libs/libdvdcss.a" 1>&6
       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
         dvd_LDFLAGS="${dvd_LDFLAGS} ${real_dvdcss_tree}/src/.libs/libdvdcss.a"
         dvd_CFLAGS="${dvd_CFLAGS} -I${real_dvdcss_tree}/src"
       else
@@ -6004,17 +6010,17 @@ echo "configure:5988: checking for libdvdcss.a in ${with_dvdcss_tree}" >&5
     fi
   ;;
   xno)
     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
     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
     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
       dvd_LDFLAGS="${dvd_LDFLAGS} -L${with_dvdcss}/lib -ldvdcss"
       dvd_CFLAGS="${dvd_CFLAGS} -I${with_dvdcss}/include"
     else
@@ -6052,17 +6058,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6084,17 +6090,17 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 EOF
  
      cat > conftest.$ac_ext <<EOF
 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
 #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*
   
   rm -rf conftest*
   
-          PLUGINS="${PLUGINS} dvdread"
+          PLUGINS="${PLUGINS} access/dvdread/dvdread"
           dvdread_LDFLAGS="${dvdread_LDFLAGS} ${test_LDFLAGS} -ldvdread"
           dvdread_CFLAGS="${dvdread_CFLAGS} ${test_CFLAGS}"
         
           dvdread_LDFLAGS="${dvdread_LDFLAGS} ${test_LDFLAGS} -ldvdread"
           dvdread_CFLAGS="${dvdread_CFLAGS} ${test_CFLAGS}"
         
@@ -6156,17 +6162,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6187,7 +6193,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 #define $ac_tr_hdr 1
 EOF
  
 #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}"
     
       dvdplay_LDFLAGS="${dvdplay_LDFLAGS} ${test_LDFLAGS} -ldvdplay -ldvdread"
       dvdplay_CFLAGS="${dvdplay_CFLAGS} ${test_CFLAGS}"
     
@@ -6238,17 +6244,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6268,8 +6274,8 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
   cat >> confdefs.h <<EOF
 #define $ac_tr_hdr 1
 EOF
   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_t""no" 1>&6
 fi
@@ -6277,7 +6283,7 @@ done
 
     else
       echo $ac_n "checking for libdvbpsi.a in ${with_dvbpsi_tree}""... $ac_c" 1>&6
 
     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
       real_dvbpsi_tree="`cd ${with_dvbpsi_tree} 2>/dev/null && pwd`"
       if test "x${real_dvbpsi_tree}" = "x"
       then
@@ -6287,9 +6293,9 @@ echo "configure:6281: checking for libdvbpsi.a in ${with_dvbpsi_tree}" >&5
       if test -f "${real_dvbpsi_tree}/src/.libs/libdvbpsi.a"
       then
                 echo "$ac_t""${real_dvbpsi_tree}/src/.libs/libdvbpsi.a" 1>&6
       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; }
       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; }
@@ -6300,7 +6306,7 @@ echo "configure:6281: checking for libdvbpsi.a in ${with_dvbpsi_tree}" >&5
       ;;
   *)
     echo $ac_n "checking for dvbpsi headers in ${with_dvbpsi}""... $ac_c" 1>&6
       ;;
   *)
     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=""
     if test "x${with_dvbpsi}" = "x"
     then
       test_LDFLAGS=""
@@ -6312,17 +6318,17 @@ echo "configure:6304: checking for dvbpsi headers in ${with_dvbpsi}" >&5
     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
     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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6339,9 +6345,9 @@ fi
 if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   
 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
       
 else
   echo "$ac_t""no" 1>&6
@@ -6368,7 +6374,7 @@ fi
 if test "x${enable_vcd}" != "xno"
 then
   cat > conftest.$ac_ext <<EOF
 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
 #include "confdefs.h"
 #include <linux/cdrom.h>
 EOF
@@ -6376,14 +6382,14 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   egrep "cdrom_msf0" >/dev/null 2>&1; then
   rm -rf conftest*
   
   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
   
 fi
 rm -f conftest*
 
   
   cat > conftest.$ac_ext <<EOF
-#line 6387 "configure"
+#line 6393 "configure"
 #include "confdefs.h"
 #include <sys/cdio.h>
 EOF
 #include "confdefs.h"
 #include <sys/cdio.h>
 EOF
@@ -6391,7 +6397,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   egrep "ioc_toc_header " >/dev/null 2>&1; then
   rm -rf conftest*
   
   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
     cat >> confdefs.h <<\EOF
 #define HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H 1
 EOF
@@ -6403,7 +6409,7 @@ rm -f conftest*
   
   if test "x${SYS}" = "xbsdi"
   then
   
   if test "x${SYS}" = "xbsdi"
   then
-    PLUGINS="${PLUGINS} vcd"
+    PLUGINS="${PLUGINS} access/vcd/vcd"
   fi
 
   if test "x${SYS}" = "xdarwin"
   fi
 
   if test "x${SYS}" = "xdarwin"
@@ -6418,7 +6424,7 @@ if test "${enable_satellite+set}" = set; then
   enableval="$enable_satellite"
    if test "x${enable_satellite}" = "xyes"
     then
   enableval="$enable_satellite"
    if test "x${enable_satellite}" = "xyes"
     then
-      PLUGINS="${PLUGINS} satellite"
+      PLUGINS="${PLUGINS} access/satellite/satellite"
     fi
 fi
 
     fi
 fi
 
@@ -6427,12 +6433,12 @@ if test "x${SYS}" != "xnto" && test "x${SYS}" != "xmingw32"
 then
   have_ipv6=0
   echo $ac_n "checking for inet_pton""... $ac_c" 1>&6
 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
 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.  */
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char inet_pton(); below.  */
@@ -6455,7 +6461,7 @@ inet_pton();
 
 ; return 0; }
 EOF
 
 ; 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
   rm -rf conftest*
   eval "ac_cv_func_inet_pton=yes"
 else
@@ -6474,7 +6480,7 @@ else
   echo "$ac_t""no" 1>&6
 
     echo $ac_n "checking for inet_pton in -lresolv""... $ac_c" 1>&6
   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_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
@@ -6482,7 +6488,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lresolv  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -6493,7 +6499,7 @@ int main() {
 inet_pton()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6518,9 +6524,9 @@ fi
 fi
 
   echo $ac_n "checking for sockaddr_in6 in netinet/in.h""... $ac_c" 1>&6
 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
   cat > conftest.$ac_ext <<EOF
-#line 6524 "configure"
+#line 6530 "configure"
 #include "confdefs.h"
 #include <netinet/in.h>
 EOF
 #include "confdefs.h"
 #include <netinet/in.h>
 EOF
@@ -6535,15 +6541,15 @@ fi
 rm -f conftest*
 
   if test x$have_ipv6 = x1; then
 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
   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
   cat > conftest.$ac_ext <<EOF
-#line 6547 "configure"
+#line 6553 "configure"
 #include "confdefs.h"
 #include <ws2tcpip.h>
 EOF
 #include "confdefs.h"
 #include <ws2tcpip.h>
 EOF
@@ -6551,7 +6557,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   egrep "addrinfo" >/dev/null 2>&1; then
   rm -rf conftest*
   echo "$ac_t""yes" 1>&6
   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
 else
   rm -rf conftest*
   echo "$ac_t""no" 1>&6
@@ -6568,7 +6574,7 @@ fi
 
 if test "x${enable_avi}" != "xno"
 then
 
 if test "x${enable_avi}" != "xno"
 then
-  PLUGINS="${PLUGINS} avi"
+  PLUGINS="${PLUGINS} demux/avi/avi"
 fi
 
 
 fi
 
 
@@ -6614,7 +6620,7 @@ 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: 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
     if test -f ${real_mad_tree}/libmad/mad.h
     then
       echo "$ac_t""yes" 1>&6
@@ -6622,7 +6628,7 @@ echo "configure:6618: checking for mad.h in ${real_mad_tree}/libmad" >&5
       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
       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_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
@@ -6630,7 +6636,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lmad  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -6641,7 +6647,7 @@ int main() {
 mad_bit_init()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6657,7 +6663,7 @@ fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   
 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
         mad_LDFLAGS="${mad_LDFLAGS} -lmad"
         
 else
@@ -6678,17 +6684,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6716,7 +6722,7 @@ fi
 done
 
     echo $ac_n "checking for mad_bit_init in -lmad""... $ac_c" 1>&6
 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_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
@@ -6724,7 +6730,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lmad  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -6735,7 +6741,7 @@ int main() {
 mad_bit_init()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6751,7 +6757,7 @@ fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   
 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
       mad_LDFLAGS="${mad_LDFLAGS} -lmad" 
 else
   echo "$ac_t""no" 1>&6
@@ -6792,7 +6798,7 @@ fi
   if test "x${with_ffmpeg_tree}" != "x"
   then
     echo $ac_n "checking for libavcodec.a in ${with_ffmpeg_tree}""... $ac_c" 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
     real_ffmpeg_tree="`cd ${with_ffmpeg_tree} 2>/dev/null && pwd`"
     if test "x${real_ffmpeg_tree}" = x
     then
@@ -6802,7 +6808,7 @@ echo "configure:6796: checking for libavcodec.a in ${with_ffmpeg_tree}" >&5
     if test -f "${real_ffmpeg_tree}/libavcodec/libavcodec.a"
     then
             echo "$ac_t""${real_ffmpeg_tree}/libavcodec/libavcodec.a" 1>&6
     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
       ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} ${real_ffmpeg_tree}/libavcodec/libavcodec.a -lm"
       ffmpeg_CFLAGS="${ffmpeg_CFLAGS} -I${real_ffmpeg_tree}/libavcodec"
     else
@@ -6813,7 +6819,7 @@ echo "configure:6796: checking for libavcodec.a in ${with_ffmpeg_tree}" >&5
     CFLAGS="${save_CFLAGS} ${ffmpeg_CFLAGS}"
     LDFLAGS="${save_LDFLAGS} ${ffmpeg_LDFLAGS} -lm"
     echo $ac_n "checking for avcodec_init in -lavcodec""... $ac_c" 1>&6
     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_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
@@ -6821,7 +6827,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lavcodec  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -6832,7 +6838,7 @@ int main() {
 avcodec_init()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6848,7 +6854,7 @@ fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   
 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
       ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} -lavcodec -lm" 
 else
   echo "$ac_t""no" 1>&6
@@ -6870,17 +6876,17 @@ if test "x${enable_mp4}" = "xyes"
 then
     ac_safe=`echo "zlib.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for zlib.h""... $ac_c" 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -6897,7 +6903,7 @@ fi
 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
 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_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
@@ -6905,7 +6911,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lz  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -6916,7 +6922,7 @@ int main() {
 inflateEnd()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -6931,7 +6937,7 @@ LIBS="$ac_save_LIBS"
 fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
 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
               mp4_LDFLAGS="${mp4_LDFLAGS} -lz" 
 else
   echo "$ac_t""no" 1>&6
@@ -6947,7 +6953,7 @@ fi
 
 if test "x${SYS}" = "xbeos"
 then
 
 if test "x${SYS}" = "xbeos"
 then
-    PLUGINS="${PLUGINS} beos"
+    PLUGINS="${PLUGINS} gui/beos/beos"
 fi
 
 # Check whether --enable-a52 or --disable-a52 was given.
 fi
 
 # Check whether --enable-a52 or --disable-a52 was given.
@@ -6973,7 +6979,7 @@ fi
       { 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: 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
     if test -f ${real_a52_tree}/include/a52.h
     then
       echo "$ac_t""yes" 1>&6
@@ -6981,7 +6987,7 @@ echo "configure:6977: checking for a52.h in ${real_a52_tree}/include" >&5
       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
       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_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
@@ -6989,7 +6995,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-la52 -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -7000,7 +7006,7 @@ int main() {
 a52_free()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7016,7 +7022,7 @@ fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   
 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"
         
         a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
         a52_CFLAGS="${a52_CFLAGS} -DUSE_A52DEC_TREE"
         
@@ -7041,17 +7047,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7073,7 +7079,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 EOF
  
       echo $ac_n "checking for a52_free in -la52""... $ac_c" 1>&6
 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_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
@@ -7081,7 +7087,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-la52 -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -7092,7 +7098,7 @@ int main() {
 a52_free()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7108,7 +7114,7 @@ fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   
 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}"
       
         a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
         a52_CFLAGS="${a52_CFLAGS}"
       
@@ -7133,7 +7139,7 @@ fi
 
 if test "x${enable_cinepak}" != "xno"
 then
 
 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.
 fi
 
 # Check whether --enable-vorbis or --disable-vorbis was given.
@@ -7148,17 +7154,17 @@ then
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7179,7 +7185,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 #define $ac_tr_hdr 1
 EOF
  
 #define $ac_tr_hdr 1
 EOF
  
-        #PLUGINS="${PLUGINS} vorbis"
+        #PLUGINS="${PLUGINS} demux/ogg/ogg codec/vorbis/vorbis"
     vorbis_LDFLAGS="${vorbis_LDFLAGS} -lvorbis"
    
 else
     vorbis_LDFLAGS="${vorbis_LDFLAGS} -lvorbis"
    
 else
@@ -7210,17 +7216,17 @@ if test "x${enable_x11}" != "xno" &&
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7241,7 +7247,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 #define $ac_tr_hdr 1
 EOF
  
 #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}"
   
     x11_LDFLAGS="${x11_LDFLAGS} -L${x_libraries} -lX11 -lXext"
     x11_CFLAGS="${x11_CFLAGS} -I${x_includes}"
   
@@ -7266,17 +7272,17 @@ if test "x${enable_xvideo}" != "xno" &&
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7299,7 +7305,7 @@ EOF
  
     CFLAGS="${save_CFLAGS} -L${x_libraries} -lX11 -lXext"
     echo $ac_n "checking for XvPutImage in -lXv_pic""... $ac_c" 1>&6
  
     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_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
@@ -7307,7 +7313,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lXv_pic  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -7318,7 +7324,7 @@ int main() {
 XvPutImage()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7334,13 +7340,13 @@ fi
 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 !
 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
       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_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
@@ -7348,7 +7354,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lXv  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -7359,7 +7365,7 @@ int main() {
 XvPutImage()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7375,12 +7381,13 @@ fi
 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
 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.
         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
 
       
 fi
 
@@ -7418,7 +7425,7 @@ 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
   # 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
 if eval "test \"`echo '$''{'ac_cv_path_SDL12_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7458,7 +7465,7 @@ fi
     # 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
     # 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
 if eval "test \"`echo '$''{'ac_cv_path_SDL11_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7499,7 +7506,7 @@ fi
     # 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
     # 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
 if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7536,7 +7543,7 @@ fi
   fi
   if test "x${SDL_CONFIG}" != "xno"
   then
   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}"
     sdl_CFLAGS="${sdl_CFLAGS} `${SDL_CONFIG} --cflags`"
     sdl_LDFLAGS="${sdl_LDFLAGS} `${SDL_CONFIG} --libs | sed 's,-rdynamic,,'`"
     CPPFLAGS="${save_CPPFLAGS} ${sdl_CFLAGS}"
@@ -7544,17 +7551,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7624,17 +7631,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7654,7 +7661,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
   cat >> confdefs.h <<EOF
 #define $ac_tr_hdr 1
 EOF
   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
         directx_LDFLAGS="${directx_LDFLAGS} -lgdi32" 
 else
   echo "$ac_t""no" 1>&6
@@ -7663,10 +7670,10 @@ done
 
     else
       echo $ac_n "checking for directX headers in ${with_directx}""... $ac_c" 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
       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
         directx_LDFLAGS="${directx_LDFLAGS} -lgdi32"
         directx_CFLAGS="${directx_CFLAGS} -I${with_directx}"
         echo "$ac_t""yes" 1>&6
@@ -7690,17 +7697,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7721,7 +7728,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 #define $ac_tr_hdr 1
 EOF
  
 #define $ac_tr_hdr 1
 EOF
  
-        PLUGINS="${PLUGINS} fb"
+        PLUGINS="${PLUGINS} video_output/fb/fb"
       
 else
   echo "$ac_t""no" 1>&6
       
 else
   echo "$ac_t""no" 1>&6
@@ -7735,7 +7742,7 @@ if test "${enable_mga+set}" = set; then
   enableval="$enable_mga"
    if test "x${enable_mga}" = "xyes"
     then
   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
 
     fi 
 fi
 
@@ -7748,7 +7755,7 @@ fi
 
 if test "x${enable_ggi}" = "xyes"
 then
 
 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
   ggi_LDFLAGS="${ggi_LDFLAGS} -lggi"
   # Check whether --with-ggi or --without-ggi was given.
 if test "${with_ggi+set}" = set; then
@@ -7770,7 +7777,7 @@ fi
 
 if test "x${enable_glide}" = "xyes"
 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.
   glide_LDFLAGS="${glide_LDFLAGS} -lglide2x -lm"
   glide_CFLAGS="${glide_CFLAGS} -I/usr/include/glide"
   # Check whether --with-glide or --without-glide was given.
@@ -7795,17 +7802,17 @@ if test "x${enable_aa}" = "xyes"
 then
   ac_safe=`echo "aalib.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for aalib.h""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7829,7 +7836,7 @@ fi
 
   if test "x${have_aa}" = "xtrue"
   then
 
   if test "x${have_aa}" = "xtrue"
   then
-    PLUGINS="${PLUGINS} aa"
+    PLUGINS="${PLUGINS} video_output/aa/aa"
     aa_LDFLAGS="${aa_LDFLAGS} -laa"
   fi
 fi
     aa_LDFLAGS="${aa_LDFLAGS} -laa"
   fi
 fi
@@ -7856,17 +7863,17 @@ then
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7887,9 +7894,9 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 #define $ac_tr_hdr 1
 EOF
  
 #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 $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_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
@@ -7897,14 +7904,14 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lossaudio  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7940,7 +7947,7 @@ if test "${enable_esd+set}" = set; then
      # 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
      # 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 eval "test \"`echo '$''{'ac_cv_path_ESD_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7975,7 +7982,7 @@ fi
 
      if test "x${ESD_CONFIG}" != "xno"
      then
 
      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
        esd_CFLAGS="${esd_CFLAGS} `${ESD_CONFIG} --cflags`"
        esd_LDFLAGS="${esd_LDFLAGS} `${ESD_CONFIG} --libs`"
      fi
@@ -7991,7 +7998,7 @@ if test "${enable_arts+set}" = set; then
      # 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
      # 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 eval "test \"`echo '$''{'ac_cv_path_ARTS_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8026,7 +8033,7 @@ fi
 
      if test "x${ARTS_CONFIG}" != "xno"
      then
 
      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
        arts_CFLAGS="${arts_CFLAGS} `${ARTS_CONFIG} --cflags`"
        arts_LDFLAGS="${arts_LDFLAGS} `${ARTS_CONFIG} --libs `"
      fi
@@ -8041,17 +8048,17 @@ if test "${enable_alsa+set}" = set; then
    then
      ac_safe=`echo "alsa/asoundlib.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for alsa/asoundlib.h""... $ac_c" 1>&6
    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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8068,7 +8075,7 @@ fi
 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
 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_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
@@ -8076,14 +8083,14 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lasound  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8111,7 +8118,7 @@ fi
 
      if test "x${have_alsa}" = "xtrue"
      then
 
      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
        alsa_LDFLAGS="${alsa_LDFLAGS} -lasound -lm -ldl"
      fi
    fi
@@ -8126,7 +8133,7 @@ fi
 
 if test "x${enable_waveout}" != "xno" -a "x${SYS}" = "xmingw32"
   then
 
 if test "x${enable_waveout}" != "xno" -a "x${SYS}" = "xmingw32"
   then
-    PLUGINS="${PLUGINS} waveout"
+    PLUGINS="${PLUGINS} audio_output/waveout/waveout"
     waveout_LDFLAGS="-lwinmm"
 fi
 
     waveout_LDFLAGS="-lwinmm"
 fi
 
@@ -8160,7 +8167,7 @@ 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
   # 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
 if eval "test \"`echo '$''{'ac_cv_path_GTK12_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8199,7 +8206,7 @@ fi
     # 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
     # 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
 if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8248,17 +8255,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8289,7 +8296,7 @@ done
 
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
 
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
-      PLUGINS="${PLUGINS} gtk"
+      PLUGINS="${PLUGINS} gui/gtk/gtk"
       ALIASES="${ALIASES} gvlc"
     fi
     CPPFLAGS="${save_CPPFLAGS}"
       ALIASES="${ALIASES} gvlc"
     fi
     CPPFLAGS="${save_CPPFLAGS}"
@@ -8318,7 +8325,7 @@ 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
   # 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
 if eval "test \"`echo '$''{'ac_cv_path_GTK12_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8357,7 +8364,7 @@ fi
     # 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
     # 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
 if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8406,17 +8413,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8447,7 +8454,7 @@ done
 
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
 
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
-      PLUGINS="${PLUGINS} familiar"
+      PLUGINS="${PLUGINS} gui/familiar/familiar"
     fi
     CPPFLAGS="${save_CPPFLAGS}"
   fi
     fi
     CPPFLAGS="${save_CPPFLAGS}"
   fi
@@ -8461,7 +8468,7 @@ if test "${enable_gnome+set}" = set; then
     # 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
     # 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
 if eval "test \"`echo '$''{'ac_cv_path_GNOME_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8505,17 +8512,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8536,7 +8543,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 #define $ac_tr_hdr 1
 EOF
  
 #define $ac_tr_hdr 1
 EOF
  
-      PLUGINS="${PLUGINS} gnome"
+      PLUGINS="${PLUGINS} gui/gtk/gnome"
       ALIASES="${ALIASES} gnome-vlc"
      
 else
       ALIASES="${ALIASES} gnome-vlc"
      
 else
@@ -8556,7 +8563,7 @@ fi
 if test "${enable_qt+set}" = set; then
   enableval="$enable_qt"
   if test "x${enable_qt}" = "xyes"; then
 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"
      ALIASES="${ALIASES} qvlc"
      qt_LDFLAGS="${qt_LDFLAGS} -lqt -L${QTDIR}/lib"
      qt_CFLAGS="${qt_CFLAGS} -I/usr/include/qt -I${QTDIR}/include"
@@ -8574,7 +8581,7 @@ fi
 if test "${enable_kde+set}" = set; then
   enableval="$enable_kde"
   if test "x${enable_kde}" = "xyes"; then
 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"
      ALIASES="${ALIASES} kvlc"
      kde_LDFLAGS="${kde_LDFLAGS} -L${KDEDIR}/lib -lkfile"
      kde_CFLAGS="${kde_CFLAGS} -I/usr/include/kde -I/usr/include/qt"
@@ -8594,7 +8601,7 @@ if test "${enable_macosx+set}" = set; then
   enableval="$enable_macosx"
   if test "x${enable_macosx}" = "xyes"
    then
   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
      macosx_LDFLAGS="${macosx_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework IOKit -framework Cocoa -framework Carbon -framework AGL -framework QuickTime -lobjc -ObjC"
    fi
 else
@@ -8602,17 +8609,17 @@ else
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8632,7 +8639,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
   cat >> confdefs.h <<EOF
 #define $ac_tr_hdr 1
 EOF
   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
      macosx_LDFLAGS="${macosx_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework IOKit -framework Cocoa -framework Carbon -framework AGL -framework QuickTime -lobjc -ObjC"
    
 else
@@ -8655,17 +8662,17 @@ fi
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8686,7 +8693,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
 #define $ac_tr_hdr 1
 EOF
  
 #define $ac_tr_hdr 1
 EOF
  
-        PLUGINS="${PLUGINS} qnx"
+        PLUGINS="${PLUGINS} gui/qnx/qnx"
         qnx_LDFLAGS="${qnx_LDFLAGS} -lasound -lph"
       
 else
         qnx_LDFLAGS="${qnx_LDFLAGS} -lasound -lph"
       
 else
@@ -8711,7 +8718,7 @@ fi
     then
       BCBUILDER="${with_bcbuilder}"
     fi
     then
       BCBUILDER="${with_bcbuilder}"
     fi
-    PLUGINS="${PLUGINS} intfwin"
+    PLUGINS="${PLUGINS} gui/win32/win32"
   fi 
 fi
 
   fi 
 fi
 
@@ -8720,7 +8727,7 @@ fi
 if test "${enable_ncurses+set}" = set; then
   enableval="$enable_ncurses"
   if test "x${enable_ncurses}" = "xyes"; then
 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
      ncurses_LDFLAGS="${ncurses_LDFLAGS} -lncurses"
    fi
 fi
@@ -8736,17 +8743,17 @@ if test "x${enable_xosd}" = "xyes"
 then
   ac_safe=`echo "xosd.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for xosd.h""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8770,7 +8777,7 @@ fi
 
   if test "x${have_xosd}" = "xtrue"
   then
 
   if test "x${have_xosd}" = "xtrue"
   then
-    PLUGINS="${PLUGINS} xosd"
+    PLUGINS="${PLUGINS} visualization/xosd/xosd"
     xosd_LDFLAGS="${xosd_LDFLAGS} -lxosd"
   fi
 fi
     xosd_LDFLAGS="${xosd_LDFLAGS} -lxosd"
   fi
 fi
@@ -8785,17 +8792,17 @@ if test "x${enable_lirc}" = "xyes"
 then
   ac_safe=`echo "lirc/lirc_client.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for lirc/lirc_client.h""... $ac_c" 1>&6
 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
 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"
 #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*
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8812,7 +8819,7 @@ fi
 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
 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_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
@@ -8820,7 +8827,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-llirc_client  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -8831,7 +8838,7 @@ int main() {
 lirc_init()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8859,7 +8866,7 @@ fi
 
   if test "x${have_lirc}" = "xtrue"
   then
 
   if test "x${have_lirc}" = "xtrue"
   then
-    PLUGINS="${PLUGINS} lirc"
+    PLUGINS="${PLUGINS} control/lirc/lirc"
     lirc_LDFLAGS="${lirc_LDFLAGS} -llirc_client"
   fi
 fi
     lirc_LDFLAGS="${lirc_LDFLAGS} -llirc_client"
   fi
 fi
@@ -8886,7 +8893,7 @@ fi
       ;;
     *)
                   echo $ac_n "checking whether the byte order is big-endian""... $ac_c" 1>&6
       ;;
     *)
                   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
 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8968,7 +8975,7 @@ if test "${enable_pth+set}" = set; then
   enableval="$enable_pth"
    if test "x${enable_pth}" = "xyes"; then
     echo $ac_n "checking for pth_init in -lpth""... $ac_c" 1>&6
   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_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
@@ -8976,7 +8983,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpth  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -8987,7 +8994,7 @@ int main() {
 pth_init()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -9015,7 +9022,7 @@ else
 fi
 
     cat > conftest.$ac_ext <<EOF
 fi
 
     cat > conftest.$ac_ext <<EOF
-#line 9019 "configure"
+#line 9026 "configure"
 #include "confdefs.h"
 #include <pth.h>
 EOF
 #include "confdefs.h"
 #include <pth.h>
 EOF
@@ -9041,7 +9048,7 @@ if test "${enable_st+set}" = set; then
   enableval="$enable_st"
    if test "x${enable_st}" = "xyes"; then
     echo $ac_n "checking for st_init in -lst""... $ac_c" 1>&6
   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_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
@@ -9049,7 +9056,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lst  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -9060,7 +9067,7 @@ int main() {
 st_init()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -9088,7 +9095,7 @@ else
 fi
 
     cat > conftest.$ac_ext <<EOF
 fi
 
     cat > conftest.$ac_ext <<EOF
-#line 9092 "configure"
+#line 9099 "configure"
 #include "confdefs.h"
 #include <st.h>
 EOF
 #include "confdefs.h"
 #include <st.h>
 EOF
@@ -9124,7 +9131,7 @@ then
   # 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
   # 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 eval "test \"`echo '$''{'ac_cv_path_MOZILLA_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9162,7 +9169,7 @@ fi
     if test "x${SYS}" != "xmingw32"; then
       LDFLAGS="${save_LDFLAGS} -L${x_libraries}"
       echo $ac_n "checking for XtStrings in -lXt""... $ac_c" 1>&6
     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_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
@@ -9170,7 +9177,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lXt  $LIBS"
 cat > conftest.$ac_ext <<EOF
   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
 #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
@@ -9181,7 +9188,7 @@ int main() {
 XtStrings()
 ; return 0; }
 EOF
 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
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -9589,11 +9596,11 @@ s%@builtins_CFLAGS@%$builtins_CFLAGS%g
 s%@mozilla_CFLAGS@%$mozilla_CFLAGS%g
 s%@a52_CFLAGS@%$a52_CFLAGS%g
 s%@arts_CFLAGS@%$arts_CFLAGS%g
 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%@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%@directx_CFLAGS@%$directx_CFLAGS%g
 s%@esd_CFLAGS@%$esd_CFLAGS%g
 s%@familiar_CFLAGS@%$familiar_CFLAGS%g
@@ -9620,16 +9627,16 @@ s%@aa_LDFLAGS@%$aa_LDFLAGS%g
 s%@alsa_LDFLAGS@%$alsa_LDFLAGS%g
 s%@arts_LDFLAGS@%$arts_LDFLAGS%g
 s%@beos_LDFLAGS@%$beos_LDFLAGS%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%@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%@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
 s%@ffmpeg_LDFLAGS@%$ffmpeg_LDFLAGS%g
 s%@mp4_LDFLAGS@%$mp4_LDFLAGS%g
 s%@ggi_LDFLAGS@%$ggi_LDFLAGS%g
index 88ee20577bbd3a4cabcf0612d744b10deb801c33..817f09bad6bee4d1aac3e49d293d7260505911d2 100644 (file)
@@ -367,7 +367,7 @@ AC_CACHE_CHECK([if \$CC accepts -fomit-frame-pointer],
 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!
 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
 fi
 
 dnl Check for Darwin plugin linking flags
@@ -434,16 +434,22 @@ dnl
 dnl  default modules
 dnl
 BUILTINS="${BUILTINS}"
 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
 
 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],
 
 AC_CACHE_CHECK([if \$CC groks MMX inline assembly],
     [ac_cv_mmx_inline],
@@ -627,7 +633,7 @@ then
     if test "x${with_dvdcss_tree}" = x
     then
       AC_CHECK_HEADERS(dvdcss/dvdcss.h,
     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]) ])
           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]) ])
@@ -644,7 +650,7 @@ then
       then
         dnl  Use a custom libdvdcss
         AC_MSG_RESULT(${real_dvdcss_tree}/src/.libs/libdvdcss.a)
       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
         dvd_LDFLAGS="${dvd_LDFLAGS} ${real_dvdcss_tree}/src/.libs/libdvdcss.a"
         dvd_CFLAGS="${dvd_CFLAGS} -I${real_dvdcss_tree}/src"
       else
@@ -656,7 +662,7 @@ then
   ;;
   xno)
     dnl  Compile without dvdcss (dlopen version, works only under Linux)
   ;;
   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"
   ;;
     dvd_CFLAGS="${dvd_CFLAGS} -DGOD_DAMN_DMCA"
     dvd_LDFLAGS="${dvd_LDFLAGS} -ldl"
   ;;
@@ -666,7 +672,7 @@ then
     then
       dnl  Use ${with_dvdcss}/include/dvdcss/dvdcss.h
       AC_MSG_RESULT(yes)
     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
       dvd_LDFLAGS="${dvd_LDFLAGS} -L${with_dvdcss}/lib -ldvdcss"
       dvd_CFLAGS="${dvd_CFLAGS} -I${with_dvdcss}/include"
     else
@@ -699,7 +705,7 @@ then
   AC_CHECK_HEADERS(dvdread/dvd_reader.h, [
      AC_TRY_COMPILE([#include <dvdread/dvd_reader.h>],
         [void foo() { int i=DVD_VIDEO_LB_LEN; }],[
   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}"
         ],[
           dvdread_LDFLAGS="${dvdread_LDFLAGS} ${test_LDFLAGS} -ldvdread"
           dvdread_CFLAGS="${dvdread_CFLAGS} ${test_CFLAGS}"
         ],[
@@ -741,7 +747,7 @@ then
   fi
   CPPFLAGS="$save_CPPFLAGS $test_CFLAGS"
   AC_CHECK_HEADERS(dvdplay/dvdplay.h, [
   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}"
     ],[
       dvdplay_LDFLAGS="${dvdplay_LDFLAGS} ${test_LDFLAGS} -ldvdplay -ldvdread"
       dvdplay_CFLAGS="${dvdplay_CFLAGS} ${test_CFLAGS}"
     ],[
@@ -775,8 +781,8 @@ then
     if test "x${with_dvbpsi_tree}" = "x"
     then
       AC_CHECK_HEADERS(dvbpsi/dr.h,
     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})
         [  AC_MSG_ERROR([cannot find libdvbpsi headers]) ])
     else
       AC_MSG_CHECKING(for libdvbpsi.a in ${with_dvbpsi_tree})
@@ -791,9 +797,9 @@ then
       then
         dnl  Use a custom libdvbpsi
         AC_MSG_RESULT(${real_dvbpsi_tree}/src/.libs/libdvbpsi.a)
       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)
       else
         dnl  The given libdvbpsi wasn't built
         AC_MSG_RESULT(no)
@@ -816,9 +822,9 @@ then
     fi
     CPPFLAGS="${save_CPPFLAGS} ${test_CFLAGS}"
     AC_CHECK_HEADER([dvbpsi/dr.h],[
     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_dvbpsi}" != "x"
       then
@@ -839,17 +845,17 @@ AC_ARG_ENABLE(vcd,
 if test "x${enable_vcd}" != "xno"
 then
   AC_EGREP_HEADER(cdrom_msf0,linux/cdrom.h,[
 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,[
   ])
   
   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
     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"
   fi
 
   if test "x${SYS}" = "xdarwin"
@@ -866,7 +872,7 @@ AC_ARG_ENABLE(satellite,
   [  --enable-satellite      satellite card support (default disabled)],
   [ if test "x${enable_satellite}" = "xyes"
     then
   [  --enable-satellite      satellite card support (default disabled)],
   [ if test "x${enable_satellite}" = "xyes"
     then
-      PLUGINS="${PLUGINS} satellite"
+      PLUGINS="${PLUGINS} access/satellite/satellite"
     fi])
 
 dnl
     fi])
 
 dnl
@@ -884,14 +890,14 @@ then
   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
   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)
   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
 fi
 
 dnl
@@ -901,7 +907,7 @@ AC_ARG_ENABLE(avi,
   [  --enable-avi            AVI demux module (default enabled)])
 if test "x${enable_avi}" != "xno"
 then
   [  --enable-avi            AVI demux module (default enabled)])
 if test "x${enable_avi}" != "xno"
 then
-  PLUGINS="${PLUGINS} avi"
+  PLUGINS="${PLUGINS} demux/avi/avi"
 fi
 
 dnl
 fi
 
 dnl
@@ -945,7 +951,7 @@ then
       mad_LDFLAGS="${mad_LDFLAGS} -L${real_mad_tree}/libmad/.libs"
       LDFLAGS="${save_LDFLAGS} ${mad_LDFLAGS}"
       AC_CHECK_LIB(mad, mad_bit_init, [
       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 ])
       ],[])
         mad_LDFLAGS="${mad_LDFLAGS} -lmad"
         ],[ AC_MSG_ERROR([the specified tree hasn't been compiled ])
       ],[])
@@ -960,7 +966,7 @@ then
     AC_CHECK_HEADERS(mad.h, ,
       [ AC_MSG_ERROR([Cannot find development headers for libmad...]) ])
     AC_CHECK_LIB(mad, mad_bit_init, [
     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}"
       mad_LDFLAGS="${mad_LDFLAGS} -lmad" ],
       [ AC_MSG_ERROR([Cannot find libmad library...]) ])
     CFLAGS="${save_CFLAGS}"
@@ -999,7 +1005,7 @@ then
     then
       dnl  Use a custom libffmpeg
       AC_MSG_RESULT(${real_ffmpeg_tree}/libavcodec/libavcodec.a)
     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
       ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} ${real_ffmpeg_tree}/libavcodec/libavcodec.a -lm"
       ffmpeg_CFLAGS="${ffmpeg_CFLAGS} -I${real_ffmpeg_tree}/libavcodec"
     else
@@ -1011,7 +1017,7 @@ then
     CFLAGS="${save_CFLAGS} ${ffmpeg_CFLAGS}"
     LDFLAGS="${save_LDFLAGS} ${ffmpeg_LDFLAGS} -lm"
     AC_CHECK_LIB(avcodec, avcodec_init, [
     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}"
       ffmpeg_LDFLAGS="${ffmpeg_LDFLAGS} -lavcodec -lm" ],
       [ AC_MSG_ERROR([Cannot find libavcodec library...]) ])
     LDFLAGS="${save_LDFLAGS}"
@@ -1028,7 +1034,7 @@ if test "x${enable_mp4}" = "xyes"
 then
     AC_CHECK_HEADER(zlib.h,
         AC_CHECK_LIB(z, inflateEnd,
 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...]) ])
               mp4_LDFLAGS="${mp4_LDFLAGS} -lz" ], 
             [ AC_MSG_ERROR([cannot find zlib library...]) ]),
         [  AC_MSG_ERROR([cannot find zlib header...]) ])
@@ -1037,7 +1043,7 @@ fi
 dnl special case for BeOS
 if test "x${SYS}" = "xbeos"
 then
 dnl special case for BeOS
 if test "x${SYS}" = "xbeos"
 then
-    PLUGINS="${PLUGINS} beos"
+    PLUGINS="${PLUGINS} gui/beos/beos"
 fi
 
 dnl
 fi
 
 dnl
@@ -1067,7 +1073,7 @@ then
       a52_LDFLAGS="${a52_LDFLAGS} -L${real_a52_tree}/liba52/.libs"
       LDFLAGS="${save_LDFLAGS} ${a52_LDFLAGS}"
       AC_CHECK_LIB(a52, a52_free, [
       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"
         ],[
         a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
         a52_CFLAGS="${a52_CFLAGS} -DUSE_A52DEC_TREE"
         ],[
@@ -1086,7 +1092,7 @@ then
   else dnl  no with args
     AC_CHECK_HEADERS(a52dec/a52.h, [
       AC_CHECK_LIB(a52, a52_free, [
   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])
         a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
         a52_CFLAGS="${a52_CFLAGS}"
       ],[],[-lm])
@@ -1101,7 +1107,7 @@ AC_ARG_ENABLE(cinepak,
   [  --enable-cinepak        Cinepak decoder (default enabled)])
 if test "x${enable_cinepak}" != "xno"
 then
   [  --enable-cinepak        Cinepak decoder (default enabled)])
 if test "x${enable_cinepak}" != "xno"
 then
-  PLUGINS="${PLUGINS} cinepak"
+  PLUGINS="${PLUGINS} codec/cinepak/cinepak"
 fi
 
 dnl
 fi
 
 dnl
@@ -1113,7 +1119,7 @@ if test "x${enable_vorbis}" != "xno"
 then
   AC_CHECK_HEADERS(ogg/ogg.h, [
     dnl disabled for the moment
 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
     vorbis_LDFLAGS="${vorbis_LDFLAGS} -lvorbis"
    ],[])
 fi
@@ -1134,7 +1140,7 @@ if test "x${enable_x11}" != "xno" &&
   (test "x${SYS}" != "xmingw32" || test "x${enable_x11}" = "xyes"); then
   CPPFLAGS="${save_CPPFLAGS} -I${x_includes}"
   AC_CHECK_HEADERS(X11/Xlib.h, [
   (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}"
   ])
     x11_LDFLAGS="${x11_LDFLAGS} -L${x_libraries} -lX11 -lXext"
     x11_CFLAGS="${x11_CFLAGS} -I${x_includes}"
   ])
@@ -1154,15 +1160,16 @@ if test "x${enable_xvideo}" != "xno" &&
     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 !
     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
       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.
         xvideo_LDFLAGS="${xvideo_LDFLAGS} -L${x_libraries} -lX11 -lXext -lXv"
         xvideo_CFLAGS="${xvideo_CFLAGS} -I${x_includes}",
         # Otherwise... well, do nothing.
+        :
       )
     )
     CFLAGS="${save_CFLAGS}"
       )
     )
     CFLAGS="${save_CFLAGS}"
@@ -1200,7 +1207,7 @@ then
   fi
   if test "x${SDL_CONFIG}" != "xno"
   then
   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}"
     sdl_CFLAGS="${sdl_CFLAGS} `${SDL_CONFIG} --cflags`"
     sdl_LDFLAGS="${sdl_LDFLAGS} `${SDL_CONFIG} --libs | sed 's,-rdynamic,,'`"
     CPPFLAGS="${save_CPPFLAGS} ${sdl_CFLAGS}"
@@ -1239,13 +1246,13 @@ then
     if test "x${with_directx}" = "x"
     then
       AC_CHECK_HEADERS(ddraw.h,
     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
         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)
         directx_LDFLAGS="${directx_LDFLAGS} -lgdi32"
         directx_CFLAGS="${directx_CFLAGS} -I${with_directx}"
         AC_MSG_RESULT(yes)
@@ -1265,7 +1272,7 @@ AC_ARG_ENABLE(fb,
     if test "x${enable_fb}" != "xno"
     then
       AC_CHECK_HEADERS(linux/fb.h, [
     if test "x${enable_fb}" != "xno"
     then
       AC_CHECK_HEADERS(linux/fb.h, [
-        PLUGINS="${PLUGINS} fb"
+        PLUGINS="${PLUGINS} video_output/fb/fb"
       ])
     fi
 
       ])
     fi
 
@@ -1276,7 +1283,7 @@ AC_ARG_ENABLE(mga,
   [  --enable-mga            Linux kernel Matrox support (default disabled)],
   [ if test "x${enable_mga}" = "xyes"
     then
   [  --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
     fi ])
 
 dnl
@@ -1286,7 +1293,7 @@ AC_ARG_ENABLE(ggi,
   [  --enable-ggi            GGI support (default disabled)])
 if test "x${enable_ggi}" = "xyes"
 then
   [  --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],
   ggi_LDFLAGS="${ggi_LDFLAGS} -lggi"
   AC_ARG_WITH(ggi,
     [    --with-ggi=PATH       path to libggi],
@@ -1304,7 +1311,7 @@ AC_ARG_ENABLE(glide,
   [  --enable-glide          Glide (3dfx) support (default disabled)])
 if test "x${enable_glide}" = "xyes"
 then
   [  --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,
   glide_LDFLAGS="${glide_LDFLAGS} -lglide2x -lm"
   glide_CFLAGS="${glide_CFLAGS} -I/usr/include/glide"
   AC_ARG_WITH(glide,
@@ -1326,7 +1333,7 @@ then
   AC_CHECK_HEADER(aalib.h,have_aa="true",have_aa="false")
   if test "x${have_aa}" = "xtrue"
   then
   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
     aa_LDFLAGS="${aa_LDFLAGS} -laa"
   fi
 fi
@@ -1347,7 +1354,7 @@ if test "x${enable_dsp}" != "xno" &&
   (test "x${SYS}" != "xmingw32" || test "x${enable_dsp}" = "xyes")
 then
   AC_CHECK_HEADERS(soundcard.h sys/soundcard.h machine/soundcard.h, [
   (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_CHECK_LIB(ossaudio,main,dsp_LDFLAGS="${dsp_LDFLAGS} -lossaudio")
   ])
 fi
@@ -1362,7 +1369,7 @@ AC_ARG_ENABLE(esd,
      AC_PATH_PROG(ESD_CONFIG, esd-config, no)
      if test "x${ESD_CONFIG}" != "xno"
      then
      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
        esd_CFLAGS="${esd_CFLAGS} `${ESD_CONFIG} --cflags`"
        esd_LDFLAGS="${esd_LDFLAGS} `${ESD_CONFIG} --libs`"
      fi
@@ -1378,7 +1385,7 @@ AC_ARG_ENABLE(arts,
      AC_PATH_PROG(ARTS_CONFIG, artsc-config, no)
      if test "x${ARTS_CONFIG}" != "xno"
      then
      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
        arts_CFLAGS="${arts_CFLAGS} `${ARTS_CONFIG} --cflags`"
        arts_LDFLAGS="${arts_LDFLAGS} `${ARTS_CONFIG} --libs `"
      fi
@@ -1394,7 +1401,7 @@ AC_ARG_ENABLE(alsa,
      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
      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])
        alsa_LDFLAGS="${alsa_LDFLAGS} -lasound -lm -ldl"
      fi
    fi])
@@ -1406,7 +1413,7 @@ AC_ARG_ENABLE(waveout,
   [  --enable-waveout        Win32 waveOut module (default enabled on Win32)])
 if test "x${enable_waveout}" != "xno" -a "x${SYS}" = "xmingw32"
   then
   [  --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
 
     waveout_LDFLAGS="-lwinmm"
 fi
 
@@ -1454,7 +1461,7 @@ then
     ])
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
     ])
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
-      PLUGINS="${PLUGINS} gtk"
+      PLUGINS="${PLUGINS} gui/gtk/gtk"
       ALIASES="${ALIASES} gvlc"
     fi
     CPPFLAGS="${save_CPPFLAGS}"
       ALIASES="${ALIASES} gvlc"
     fi
     CPPFLAGS="${save_CPPFLAGS}"
@@ -1499,7 +1506,7 @@ then
     ])
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
     ])
     if test "x${ac_cv_gtk_headers}" = "xyes"
     then
-      PLUGINS="${PLUGINS} familiar"
+      PLUGINS="${PLUGINS} gui/familiar/familiar"
     fi
     CPPFLAGS="${save_CPPFLAGS}"
   fi
     fi
     CPPFLAGS="${save_CPPFLAGS}"
   fi
@@ -1521,7 +1528,7 @@ AC_ARG_ENABLE(gnome,
     # now look for the gnome.h header
     CPPFLAGS="${save_CPPFLAGS} ${gnome_CFLAGS}"
     AC_CHECK_HEADERS(gnome.h, [
     # 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
       ALIASES="${ALIASES} gnome-vlc"
      ],[
       AC_MSG_ERROR([Can't find gnome headers. Please install the gnome
@@ -1536,7 +1543,7 @@ dnl
 AC_ARG_ENABLE(qt,
   [  --enable-qt             Qt interface support (default disabled)],
   [if test "x${enable_qt}" = "xyes"; then
 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"
      ALIASES="${ALIASES} qvlc"
      qt_LDFLAGS="${qt_LDFLAGS} -lqt -L${QTDIR}/lib"
      qt_CFLAGS="${qt_CFLAGS} -I/usr/include/qt -I${QTDIR}/include"
@@ -1554,7 +1561,7 @@ dnl
 AC_ARG_ENABLE(kde,
   [  --enable-kde            KDE interface support (default disabled)],
   [if test "x${enable_kde}" = "xyes"; then
 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"
      ALIASES="${ALIASES} kvlc"
      kde_LDFLAGS="${kde_LDFLAGS} -L${KDEDIR}/lib -lkfile"
      kde_CFLAGS="${kde_CFLAGS} -I/usr/include/kde -I/usr/include/qt"
@@ -1574,11 +1581,11 @@ AC_ARG_ENABLE(macosx,
   [  --enable-macosx         MacOS X support (default enabled on MacOS X)],
   [if test "x${enable_macosx}" = "xyes"
    then
   [  --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,
      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"
    )])
 
      macosx_LDFLAGS="${macosx_LDFLAGS} -framework CoreAudio -framework AudioToolbox -framework IOKit -framework Cocoa -framework Carbon -framework AGL -framework QuickTime -lobjc -ObjC"
    )])
 
@@ -1590,7 +1597,7 @@ AC_ARG_ENABLE(qnx,
     if test "x${enable_qnx}" != "xno"
     then
       AC_CHECK_HEADERS(Ph.h, [
     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
         qnx_LDFLAGS="${qnx_LDFLAGS} -lasound -lph"
       ])
     fi
@@ -1608,7 +1615,7 @@ AC_ARG_ENABLE(intfwin,
     then
       BCBUILDER="${with_bcbuilder}"
     fi
     then
       BCBUILDER="${with_bcbuilder}"
     fi
-    PLUGINS="${PLUGINS} intfwin"
+    PLUGINS="${PLUGINS} gui/win32/win32"
   fi ])
 
 dnl
   fi ])
 
 dnl
@@ -1617,7 +1624,7 @@ dnl
 AC_ARG_ENABLE(ncurses,
   [  --enable-ncurses        ncurses interface support (default disabled)],
   [if test "x${enable_ncurses}" = "xyes"; then
 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])
 
      ncurses_LDFLAGS="${ncurses_LDFLAGS} -lncurses"
    fi])
 
@@ -1631,7 +1638,7 @@ then
   AC_CHECK_HEADER(xosd.h, have_xosd="true", have_xosd="false")
   if test "x${have_xosd}" = "xtrue"
   then
   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
     xosd_LDFLAGS="${xosd_LDFLAGS} -lxosd"
   fi
 fi
@@ -1646,7 +1653,7 @@ then
   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
   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
     lirc_LDFLAGS="${lirc_LDFLAGS} -llirc_client"
   fi
 fi
@@ -1879,11 +1886,11 @@ AC_SUBST(mozilla_CFLAGS)
 
 AC_SUBST(a52_CFLAGS)
 AC_SUBST(arts_CFLAGS)
 
 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(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(directx_CFLAGS)
 AC_SUBST(esd_CFLAGS)
 AC_SUBST(familiar_CFLAGS)
@@ -1912,16 +1919,16 @@ AC_SUBST(aa_LDFLAGS)
 AC_SUBST(alsa_LDFLAGS)
 AC_SUBST(arts_LDFLAGS)
 AC_SUBST(beos_LDFLAGS)
 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(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(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)
 AC_SUBST(ffmpeg_LDFLAGS)
 AC_SUBST(mp4_LDFLAGS)
 AC_SUBST(ggi_LDFLAGS)
diff --git a/doc/mad/API b/doc/mad/API
new file mode 100644 (file)
index 0000000..83a8731
--- /dev/null
@@ -0,0 +1,262 @@
+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.)
+
+
+
+
diff --git a/doc/mad/BUGS b/doc/mad/BUGS
new file mode 100644 (file)
index 0000000..96c3931
--- /dev/null
@@ -0,0 +1,27 @@
+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.
diff --git a/doc/mad/DESIGN b/doc/mad/DESIGN
new file mode 100644 (file)
index 0000000..12035ba
--- /dev/null
@@ -0,0 +1,63 @@
+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.
+
+
diff --git a/doc/mad/TODO b/doc/mad/TODO
new file mode 100644 (file)
index 0000000..b19be0a
--- /dev/null
@@ -0,0 +1,40 @@
+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])
diff --git a/doc/mad/joe_drew.txt b/doc/mad/joe_drew.txt
new file mode 100644 (file)
index 0000000..97dbab9
--- /dev/null
@@ -0,0 +1,174 @@
+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.
diff --git a/doc/mad/rob_leslie.txt b/doc/mad/rob_leslie.txt
new file mode 100644 (file)
index 0000000..fbe49e4
--- /dev/null
@@ -0,0 +1,124 @@
+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
index 690053a7ac8eedecc9864347eea2a7994c283bc1..6257e4f16ed6a543d333389dca81b5c6469a7dfe 100644 (file)
@@ -2,7 +2,7 @@
  * audio_output.h : audio output thread interface
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
  * 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>
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Cyril Deguet <asmax@via.ecp.fr>
@@ -163,7 +163,7 @@ struct aout_thread_t
 #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_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
 
 #ifdef WORDS_BIGENDIAN
 #define AOUT_FMT_S16_NE      AOUT_FMT_S16_BE
@@ -171,8 +171,8 @@ struct aout_thread_t
 #define AOUT_FMT_S16_NE      AOUT_FMT_S16_LE
 #endif
 
 #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
 
 /* Size of a frame for spdif output */
 #define SPDIF_FRAME_SIZE    6144
index f5cdcd025f117d0b537861ea87dc5d5c13793a40..ff322913694410d0937807d36774715364b4cb5a 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-dec.h: structures exported to the VideoLAN decoders
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
  * 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>
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Kaempf <maxx@via.ecp.fr>
@@ -32,7 +32,7 @@
 #define MPEG2_VIDEO_ES      0x02
 #define MPEG1_AUDIO_ES      0x03
 #define MPEG2_AUDIO_ES      0x04
 #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
 /* These ones might violate the norm : */
 #define DVD_SPU_ES          0x82
 #define LPCM_AUDIO_ES       0x83
index f2d5b87f833ff528f90c8213cfa0b15f50ea077a..4b107b87198307ab6612539c2d28469cea827dbf 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
  * 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>
  *
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -31,7 +31,7 @@
  */
 /* FIXME ! */
 #define REQUESTED_MPEG         1
  */
 /* FIXME ! */
 #define REQUESTED_MPEG         1
-#define REQUESTED_AC3          2
+#define REQUESTED_A52          2
 #define REQUESTED_LPCM         3
 #define REQUESTED_NOAUDIO    255
 
 #define REQUESTED_LPCM         3
 #define REQUESTED_NOAUDIO    255
 
diff --git a/modules/access/.cvsignore b/modules/access/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/access/Makefile b/modules/access/Makefile
new file mode 100644 (file)
index 0000000..fda8268
--- /dev/null
@@ -0,0 +1,3 @@
+file_SOURCES = file.c
+udp_SOURCES = udp.c
+http_SOURCES = http.c
diff --git a/modules/access/dvd/.cvsignore b/modules/access/dvd/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/access/dvd/Makefile b/modules/access/dvd/Makefile
new file mode 100644 (file)
index 0000000..1a9f155
--- /dev/null
@@ -0,0 +1 @@
+dvd_SOURCES = dvd.c access.c demux.c seek.c es.c ifo.c udf.c summary.c
diff --git a/modules/access/dvd/access.c b/modules/access/dvd/access.c
new file mode 100644 (file)
index 0000000..267feba
--- /dev/null
@@ -0,0 +1,827 @@
+/* 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;
+} 
diff --git a/modules/access/dvd/demux.c b/modules/access/dvd/demux.c
new file mode 100644 (file)
index 0000000..b2c7bdc
--- /dev/null
@@ -0,0 +1,112 @@
+/* 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;
+}
diff --git a/modules/access/dvd/dvd.c b/modules/access/dvd/dvd.c
new file mode 100644 (file)
index 0000000..c229f70
--- /dev/null
@@ -0,0 +1,336 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/access/dvd/dvd.h b/modules/access/dvd/dvd.h
new file mode 100644 (file)
index 0000000..edd7efd
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * 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;
+
diff --git a/modules/access/dvd/dvdcss.h b/modules/access/dvd/dvdcss.h
new file mode 100644 (file)
index 0000000..3a27482
--- /dev/null
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ * 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 );
+
+
diff --git a/modules/access/dvd/es.c b/modules/access/dvd/es.c
new file mode 100644 (file)
index 0000000..baf7df9
--- /dev/null
@@ -0,0 +1,323 @@
+/* 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] );
+            }
+        }
+    }
+}
diff --git a/modules/access/dvd/es.h b/modules/access/dvd/es.h
new file mode 100644 (file)
index 0000000..f908b0a
--- /dev/null
@@ -0,0 +1,27 @@
+/* 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 * );
+
diff --git a/modules/access/dvd/ifo.c b/modules/access/dvd/ifo.c
new file mode 100644 (file)
index 0000000..9eea56e
--- /dev/null
@@ -0,0 +1,2183 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/access/dvd/ifo.h b/modules/access/dvd/ifo.h
new file mode 100644 (file)
index 0000000..e07a2de
--- /dev/null
@@ -0,0 +1,563 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/access/dvd/seek.c b/modules/access/dvd/seek.c
new file mode 100644 (file)
index 0000000..35524c2
--- /dev/null
@@ -0,0 +1,324 @@
+/* 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
diff --git a/modules/access/dvd/seek.h b/modules/access/dvd/seek.h
new file mode 100644 (file)
index 0000000..5b334a1
--- /dev/null
@@ -0,0 +1,37 @@
+/* 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 );
+
diff --git a/modules/access/dvd/summary.c b/modules/access/dvd/summary.c
new file mode 100644 (file)
index 0000000..f6837be
--- /dev/null
@@ -0,0 +1,178 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/access/dvd/summary.h b/modules/access/dvd/summary.h
new file mode 100644 (file)
index 0000000..9deda0e
--- /dev/null
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ * 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 );
+
+
diff --git a/modules/access/dvd/udf.c b/modules/access/dvd/udf.c
new file mode 100644 (file)
index 0000000..53e88db
--- /dev/null
@@ -0,0 +1,740 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/access/dvd/udf.h b/modules/access/dvd/udf.h
new file mode 100644 (file)
index 0000000..84b35f2
--- /dev/null
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/access/dvdplay/.cvsignore b/modules/access/dvdplay/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/access/dvdplay/Makefile b/modules/access/dvdplay/Makefile
new file mode 100644 (file)
index 0000000..2d87cf4
--- /dev/null
@@ -0,0 +1 @@
+dvdplay_SOURCES = dvd.c access.c demux.c intf.c es.c tools.c
diff --git a/modules/access/dvdplay/access.c b/modules/access/dvdplay/access.c
new file mode 100644 (file)
index 0000000..7161c83
--- /dev/null
@@ -0,0 +1,501 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/access/dvdplay/access.h b/modules/access/dvdplay/access.h
new file mode 100644 (file)
index 0000000..5fb5189
--- /dev/null
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * 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 * );
diff --git a/modules/access/dvdplay/demux.c b/modules/access/dvdplay/demux.c
new file mode 100644 (file)
index 0000000..021f5c7
--- /dev/null
@@ -0,0 +1,172 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/access/dvdplay/demux.h b/modules/access/dvdplay/demux.h
new file mode 100644 (file)
index 0000000..72a1205
--- /dev/null
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * 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 * );
diff --git a/modules/access/dvdplay/dvd.c b/modules/access/dvdplay/dvd.c
new file mode 100644 (file)
index 0000000..28aa113
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/access/dvdplay/dvd.h b/modules/access/dvdplay/dvd.h
new file mode 100644 (file)
index 0000000..b1418a6
--- /dev/null
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * 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;
+
diff --git a/modules/access/dvdplay/es.c b/modules/access/dvdplay/es.c
new file mode 100644 (file)
index 0000000..a09e133
--- /dev/null
@@ -0,0 +1,299 @@
+/*****************************************************************************
+ * 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 );
+}
+
+
diff --git a/modules/access/dvdplay/es.h b/modules/access/dvdplay/es.h
new file mode 100644 (file)
index 0000000..013305f
--- /dev/null
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * 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 * );
diff --git a/modules/access/dvdplay/intf.c b/modules/access/dvdplay/intf.c
new file mode 100644 (file)
index 0000000..7c10f20
--- /dev/null
@@ -0,0 +1,318 @@
+/*****************************************************************************
+ * 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;
+}
+
+
diff --git a/modules/access/dvdplay/intf.h b/modules/access/dvdplay/intf.h
new file mode 100644 (file)
index 0000000..f04a2d8
--- /dev/null
@@ -0,0 +1,24 @@
+/*****************************************************************************
+ * 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 );
diff --git a/modules/access/dvdplay/tools.c b/modules/access/dvdplay/tools.c
new file mode 100644 (file)
index 0000000..709fe72
--- /dev/null
@@ -0,0 +1,121 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/access/dvdplay/tools.h b/modules/access/dvdplay/tools.h
new file mode 100644 (file)
index 0000000..e0b612f
--- /dev/null
@@ -0,0 +1,24 @@
+/*****************************************************************************
+ * 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* );
diff --git a/modules/access/dvdread/.cvsignore b/modules/access/dvdread/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/access/dvdread/Makefile b/modules/access/dvdread/Makefile
new file mode 100644 (file)
index 0000000..6e7cf66
--- /dev/null
@@ -0,0 +1 @@
+dvdread_SOURCES = dvdread.c input.c
diff --git a/modules/access/dvdread/dvdread.c b/modules/access/dvdread/dvdread.c
new file mode 100644 (file)
index 0000000..6414f6f
--- /dev/null
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * 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();  
+
diff --git a/modules/access/dvdread/input.c b/modules/access/dvdread/input.c
new file mode 100644 (file)
index 0000000..82380ee
--- /dev/null
@@ -0,0 +1,1233 @@
+/*****************************************************************************
+ * 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] );
+        }
+    }
+}
diff --git a/modules/access/dvdread/input.h b/modules/access/dvdread/input.h
new file mode 100644 (file)
index 0000000..3d14a66
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * 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;
+
diff --git a/modules/access/file.c b/modules/access/file.c
new file mode 100644 (file)
index 0000000..cdda4d1
--- /dev/null
@@ -0,0 +1,151 @@
+/*****************************************************************************
+ * 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();
diff --git a/modules/access/http.c b/modules/access/http.c
new file mode 100644 (file)
index 0000000..c7badd1
--- /dev/null
@@ -0,0 +1,500 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/access/satellite/.cvsignore b/modules/access/satellite/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/access/satellite/Makefile b/modules/access/satellite/Makefile
new file mode 100644 (file)
index 0000000..dd4d0aa
--- /dev/null
@@ -0,0 +1 @@
+satellite_SOURCES = satellite.c access.c dvb.c
diff --git a/modules/access/satellite/access.c b/modules/access/satellite/access.c
new file mode 100644 (file)
index 0000000..1e828e0
--- /dev/null
@@ -0,0 +1,434 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/access/satellite/dvb.c b/modules/access/satellite/dvb.c
new file mode 100644 (file)
index 0000000..563b630
--- /dev/null
@@ -0,0 +1,235 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/access/satellite/dvb.h b/modules/access/satellite/dvb.h
new file mode 100644 (file)
index 0000000..ada0048
--- /dev/null
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * 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 );
diff --git a/modules/access/satellite/satellite.c b/modules/access/satellite/satellite.c
new file mode 100644 (file)
index 0000000..87c8496
--- /dev/null
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/access/udp.c b/modules/access/udp.c
new file mode 100644 (file)
index 0000000..3df44d2
--- /dev/null
@@ -0,0 +1,251 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/access/vcd/.cvsignore b/modules/access/vcd/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/access/vcd/Makefile b/modules/access/vcd/Makefile
new file mode 100644 (file)
index 0000000..3a17ed6
--- /dev/null
@@ -0,0 +1 @@
+vcd_SOURCES = vcd.c cdrom.c
diff --git a/modules/access/vcd/cdrom.c b/modules/access/vcd/cdrom.c
new file mode 100644 (file)
index 0000000..a0ff6ad
--- /dev/null
@@ -0,0 +1,486 @@
+/****************************************************************************
+ * 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
diff --git a/modules/access/vcd/cdrom.h b/modules/access/vcd/cdrom.h
new file mode 100644 (file)
index 0000000..945ec55
--- /dev/null
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * 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 * );
+
diff --git a/modules/access/vcd/vcd.c b/modules/access/vcd/vcd.c
new file mode 100644 (file)
index 0000000..4fa9125
--- /dev/null
@@ -0,0 +1,409 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/access/vcd/vcd.h b/modules/access/vcd/vcd.h
new file mode 100644 (file)
index 0000000..a15201b
--- /dev/null
@@ -0,0 +1,37 @@
+/*****************************************************************************
+ * 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;
+
diff --git a/modules/audio_output/alsa/.cvsignore b/modules/audio_output/alsa/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/audio_output/alsa/Makefile b/modules/audio_output/alsa/Makefile
new file mode 100644 (file)
index 0000000..bf4dfff
--- /dev/null
@@ -0,0 +1 @@
+alsa_SOURCES = alsa.c
diff --git a/modules/audio_output/alsa/alsa.c b/modules/audio_output/alsa/alsa.c
new file mode 100644 (file)
index 0000000..1b23d3d
--- /dev/null
@@ -0,0 +1,420 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/audio_output/arts/.cvsignore b/modules/audio_output/arts/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/audio_output/arts/Makefile b/modules/audio_output/arts/Makefile
new file mode 100644 (file)
index 0000000..ddd35a1
--- /dev/null
@@ -0,0 +1 @@
+arts_SOURCES = arts.c
diff --git a/modules/audio_output/arts/arts.c b/modules/audio_output/arts/arts.c
new file mode 100644 (file)
index 0000000..80e12b4
--- /dev/null
@@ -0,0 +1,150 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/audio_output/dsp/.cvsignore b/modules/audio_output/dsp/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/audio_output/dsp/Makefile b/modules/audio_output/dsp/Makefile
new file mode 100644 (file)
index 0000000..393faf0
--- /dev/null
@@ -0,0 +1 @@
+dsp_SOURCES = dsp.c
diff --git a/modules/audio_output/dsp/dsp.c b/modules/audio_output/dsp/dsp.c
new file mode 100644 (file)
index 0000000..069593d
--- /dev/null
@@ -0,0 +1,247 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/audio_output/esd/.cvsignore b/modules/audio_output/esd/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/audio_output/esd/Makefile b/modules/audio_output/esd/Makefile
new file mode 100644 (file)
index 0000000..b944324
--- /dev/null
@@ -0,0 +1 @@
+esd_SOURCES = esd.c
diff --git a/modules/audio_output/esd/esd.c b/modules/audio_output/esd/esd.c
new file mode 100644 (file)
index 0000000..fa8c008
--- /dev/null
@@ -0,0 +1,194 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/audio_output/waveout/.cvsignore b/modules/audio_output/waveout/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/audio_output/waveout/Makefile b/modules/audio_output/waveout/Makefile
new file mode 100644 (file)
index 0000000..ca29f24
--- /dev/null
@@ -0,0 +1 @@
+waveout_SOURCES = waveout.c
diff --git a/modules/audio_output/waveout/waveout.c b/modules/audio_output/waveout/waveout.c
new file mode 100644 (file)
index 0000000..5369675
--- /dev/null
@@ -0,0 +1,286 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/codec/a52/.cvsignore b/modules/codec/a52/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/a52/Makefile b/modules/codec/a52/Makefile
new file mode 100644 (file)
index 0000000..ba23988
--- /dev/null
@@ -0,0 +1 @@
+a52_SOURCES = a52.c
diff --git a/modules/codec/a52/a52.c b/modules/codec/a52/a52.c
new file mode 100644 (file)
index 0000000..dbb917b
--- /dev/null
@@ -0,0 +1,386 @@
+/*****************************************************************************
+ * 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; */
+    }
+}
diff --git a/modules/codec/a52/a52.h b/modules/codec/a52/a52.h
new file mode 100644 (file)
index 0000000..71bfaca
--- /dev/null
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * 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;
diff --git a/modules/codec/a52old/.cvsignore b/modules/codec/a52old/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/a52old/Makefile b/modules/codec/a52old/Makefile
new file mode 100644 (file)
index 0000000..f07f59d
--- /dev/null
@@ -0,0 +1 @@
+a52old_SOURCES = a52old.c decoder.c parse.c exponent.c bit_allocate.c mantissa.c rematrix.c imdct.c
diff --git a/modules/codec/a52old/a52old.c b/modules/codec/a52old/a52old.c
new file mode 100644 (file)
index 0000000..5d1c71c
--- /dev/null
@@ -0,0 +1,384 @@
+/*****************************************************************************
+ * 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; */
+    }
+}
+
diff --git a/modules/codec/a52old/adec.h b/modules/codec/a52old/adec.h
new file mode 100644 (file)
index 0000000..8789a3d
--- /dev/null
@@ -0,0 +1,409 @@
+/*****************************************************************************
+ * 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 */
+};
+
diff --git a/modules/codec/a52old/bit_allocate.c b/modules/codec/a52old/bit_allocate.c
new file mode 100644 (file)
index 0000000..200f27e
--- /dev/null
@@ -0,0 +1,452 @@
+/*****************************************************************************
+ * 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);
+}
diff --git a/modules/codec/a52old/decoder.c b/modules/codec/a52old/decoder.c
new file mode 100644 (file)
index 0000000..2892e5e
--- /dev/null
@@ -0,0 +1,129 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/a52old/decoder.h b/modules/codec/a52old/decoder.h
new file mode 100644 (file)
index 0000000..a41db75
--- /dev/null
@@ -0,0 +1,385 @@
+/*****************************************************************************
+ * 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;
+
+};
+
similarity index 94%
rename from include/ac3_downmix.h
rename to modules/codec/a52old/downmix.h
index 80737951cdaba597e2df1dfc08c1dfd167416902..0da10741555ab935559e40a6f963d4d8210206cb 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
 /*****************************************************************************
- * ac3_downmix.h : AC3 downmix types
+ * downmix.h : A52 downmix types
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
  *****************************************************************************
  * 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>
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Renaud Dartus <reno@videolan.org>
diff --git a/modules/codec/a52old/downmix/.cvsignore b/modules/codec/a52old/downmix/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/a52old/downmix/Makefile b/modules/codec/a52old/downmix/Makefile
new file mode 100644 (file)
index 0000000..accc86d
--- /dev/null
@@ -0,0 +1,3 @@
+downmix_SOURCES = downmix.c downmix_c.c
+downmixsse_SOURCES = downmix.c downmix_sse.c
+downmix3dn_SOURCES = downmix.c downmix_3dn.c
diff --git a/modules/codec/a52old/downmix/downmix.c b/modules/codec/a52old/downmix/downmix.c
new file mode 100644 (file)
index 0000000..56b5ffa
--- /dev/null
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/codec/a52old/downmix/downmix_3dn.c b/modules/codec/a52old/downmix/downmix_3dn.c
new file mode 100644 (file)
index 0000000..b86bc92
--- /dev/null
@@ -0,0 +1,307 @@
+/*****************************************************************************
+ * 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));
+    
+}
+
diff --git a/modules/codec/a52old/downmix/downmix_c.c b/modules/codec/a52old/downmix/downmix_c.c
new file mode 100644 (file)
index 0000000..2689687
--- /dev/null
@@ -0,0 +1,151 @@
+/*****************************************************************************
+ * 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;
+    }
+}
+
diff --git a/modules/codec/a52old/downmix/downmix_common.h b/modules/codec/a52old/downmix/downmix_common.h
new file mode 100644 (file)
index 0000000..f2e57f9
--- /dev/null
@@ -0,0 +1,32 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/codec/a52old/downmix/downmix_sse.c b/modules/codec/a52old/downmix/downmix_sse.c
new file mode 100644 (file)
index 0000000..c32ab4b
--- /dev/null
@@ -0,0 +1,312 @@
+/*****************************************************************************
+ * 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));
+    
+}
+
diff --git a/modules/codec/a52old/exponent.c b/modules/codec/a52old/exponent.c
new file mode 100644 (file)
index 0000000..1561565
--- /dev/null
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/a52old/exponent.h b/modules/codec/a52old/exponent.h
new file mode 100644 (file)
index 0000000..18f1978
--- /dev/null
@@ -0,0 +1,152 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/a52old/imdct.c b/modules/codec/a52old/imdct.c
new file mode 100644 (file)
index 0000000..f88e596
--- /dev/null
@@ -0,0 +1,262 @@
+/*****************************************************************************
+ * 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;
+        }
+    }
+}
similarity index 97%
rename from include/ac3_imdct.h
rename to modules/codec/a52old/imdct.h
index e6e101c859712a1057b86edd07c8946efb8209e0..37d27ebf13bbd54a446ab2b79b13c4fdff608c22 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
 /*****************************************************************************
- * ac3_imdct.h : AC3 IMDCT types
+ * imdct.h : A52 IMDCT types
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
  *****************************************************************************
  * 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>
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Renaud Dartus <reno@videolan.org>
diff --git a/modules/codec/a52old/imdct/.cvsignore b/modules/codec/a52old/imdct/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/a52old/imdct/Makefile b/modules/codec/a52old/imdct/Makefile
new file mode 100644 (file)
index 0000000..6e31fa1
--- /dev/null
@@ -0,0 +1,5 @@
+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)
diff --git a/modules/codec/a52old/imdct/imdct.c b/modules/codec/a52old/imdct/imdct.c
new file mode 100644 (file)
index 0000000..ea1653f
--- /dev/null
@@ -0,0 +1,71 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/codec/a52old/imdct/imdct_3dn.c b/modules/codec/a52old/imdct/imdct_3dn.c
new file mode 100644 (file)
index 0000000..cb2e0dd
--- /dev/null
@@ -0,0 +1,538 @@
+/*****************************************************************************
+ * 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));
+}
+
diff --git a/modules/codec/a52old/imdct/imdct_c.c b/modules/codec/a52old/imdct/imdct_c.c
new file mode 100644 (file)
index 0000000..a25e288
--- /dev/null
@@ -0,0 +1,196 @@
+/*****************************************************************************
+ * 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; 
+    }
+}
+
diff --git a/modules/codec/a52old/imdct/imdct_common.c b/modules/codec/a52old/imdct/imdct_common.c
new file mode 100644 (file)
index 0000000..774abcf
--- /dev/null
@@ -0,0 +1,196 @@
+/*****************************************************************************
+ * 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;
+    }
+}
diff --git a/modules/codec/a52old/imdct/imdct_common.h b/modules/codec/a52old/imdct/imdct_common.h
new file mode 100644 (file)
index 0000000..e5f19a2
--- /dev/null
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * 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[] );
diff --git a/modules/codec/a52old/imdct/imdct_sse.c b/modules/codec/a52old/imdct/imdct_sse.c
new file mode 100644 (file)
index 0000000..fd5405e
--- /dev/null
@@ -0,0 +1,582 @@
+/*****************************************************************************
+ * 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));
+
+}
diff --git a/modules/codec/a52old/imdct/retables.h b/modules/codec/a52old/imdct/retables.h
new file mode 100644 (file)
index 0000000..a9d496d
--- /dev/null
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * 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
+};
+
diff --git a/modules/codec/a52old/imdct/srfft.h b/modules/codec/a52old/imdct/srfft.h
new file mode 100644 (file)
index 0000000..fe91f8c
--- /dev/null
@@ -0,0 +1,292 @@
+/*****************************************************************************
+ * 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; \
+  }
+
diff --git a/modules/codec/a52old/imdct/srfft_3dn.c b/modules/codec/a52old/imdct/srfft_3dn.c
new file mode 100644 (file)
index 0000000..1416241
--- /dev/null
@@ -0,0 +1,335 @@
+/*****************************************************************************
+ * 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;
+  }
+}
diff --git a/modules/codec/a52old/imdct/srfft_c.c b/modules/codec/a52old/imdct/srfft_c.c
new file mode 100644 (file)
index 0000000..db7a181
--- /dev/null
@@ -0,0 +1,306 @@
+/*****************************************************************************
+ * 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]);
+}
+
diff --git a/modules/codec/a52old/imdct/srfft_sse.c b/modules/codec/a52old/imdct/srfft_sse.c
new file mode 100644 (file)
index 0000000..37f65e6
--- /dev/null
@@ -0,0 +1,360 @@
+/*****************************************************************************
+ * 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) );
+}
diff --git a/modules/codec/a52old/internal.h b/modules/codec/a52old/internal.h
new file mode 100644 (file)
index 0000000..b3086bb
--- /dev/null
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * 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 *);
+
diff --git a/modules/codec/a52old/mantissa.c b/modules/codec/a52old/mantissa.c
new file mode 100644 (file)
index 0000000..713d7a8
--- /dev/null
@@ -0,0 +1,81 @@
+/*****************************************************************************
+ * 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]);
+    }
+}
+
diff --git a/modules/codec/a52old/mantissa.h b/modules/codec/a52old/mantissa.h
new file mode 100644 (file)
index 0000000..7018a7d
--- /dev/null
@@ -0,0 +1,404 @@
+/*****************************************************************************
+ * 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++;
+        }
+    }
+}
+
diff --git a/modules/codec/a52old/parse.c b/modules/codec/a52old/parse.c
new file mode 100644 (file)
index 0000000..7d8919f
--- /dev/null
@@ -0,0 +1,862 @@
+/*****************************************************************************
+ * 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
+}
+
diff --git a/modules/codec/a52old/rematrix.c b/modules/codec/a52old/rematrix.c
new file mode 100644 (file)
index 0000000..af02d91
--- /dev/null
@@ -0,0 +1,79 @@
+/*****************************************************************************
+ * 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;
+        }
+    }
+}
+
diff --git a/modules/codec/cinepak/.cvsignore b/modules/codec/cinepak/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/cinepak/Makefile b/modules/codec/cinepak/Makefile
new file mode 100644 (file)
index 0000000..e47caa0
--- /dev/null
@@ -0,0 +1 @@
+cinepak_SOURCES = cinepak.c
diff --git a/modules/codec/cinepak/cinepak.c b/modules/codec/cinepak/cinepak.c
new file mode 100644 (file)
index 0000000..74ff13c
--- /dev/null
@@ -0,0 +1,966 @@
+/*****************************************************************************
+ * 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 );
+}
+
+
diff --git a/modules/codec/cinepak/cinepak.h b/modules/codec/cinepak/cinepak.h
new file mode 100644 (file)
index 0000000..df73d3c
--- /dev/null
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * 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;
diff --git a/modules/codec/ffmpeg/.cvsignore b/modules/codec/ffmpeg/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/ffmpeg/Makefile b/modules/codec/ffmpeg/Makefile
new file mode 100644 (file)
index 0000000..0630428
--- /dev/null
@@ -0,0 +1 @@
+ffmpeg_SOURCES = ffmpeg.c
diff --git a/modules/codec/ffmpeg/ffmpeg.c b/modules/codec/ffmpeg/ffmpeg.c
new file mode 100644 (file)
index 0000000..c303e2e
--- /dev/null
@@ -0,0 +1,869 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/codec/ffmpeg/ffmpeg.h b/modules/codec/ffmpeg/ffmpeg.h
new file mode 100644 (file)
index 0000000..09b3a7e
--- /dev/null
@@ -0,0 +1,220 @@
+/*****************************************************************************
+ * 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;
diff --git a/modules/codec/lpcm/.cvsignore b/modules/codec/lpcm/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/lpcm/Makefile b/modules/codec/lpcm/Makefile
new file mode 100644 (file)
index 0000000..aa3a240
--- /dev/null
@@ -0,0 +1 @@
+lpcm_SOURCES = lpcm.c
diff --git a/modules/codec/lpcm/lpcm.c b/modules/codec/lpcm/lpcm.c
new file mode 100644 (file)
index 0000000..9c08d8f
--- /dev/null
@@ -0,0 +1,227 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/codec/lpcm/lpcm.h b/modules/codec/lpcm/lpcm.h
new file mode 100644 (file)
index 0000000..9d37ac9
--- /dev/null
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * 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 );
diff --git a/modules/codec/mad/.cvsignore b/modules/codec/mad/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/mad/Makefile b/modules/codec/mad/Makefile
new file mode 100644 (file)
index 0000000..c569234
--- /dev/null
@@ -0,0 +1 @@
+mad_SOURCES = decoder.c libmad.c
diff --git a/modules/codec/mad/decoder.c b/modules/codec/mad/decoder.c
new file mode 100644 (file)
index 0000000..628e950
--- /dev/null
@@ -0,0 +1,239 @@
+/***************************************************************************
+              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 );
+}
+
diff --git a/modules/codec/mad/decoder.h b/modules/codec/mad/decoder.h
new file mode 100644 (file)
index 0000000..3112cc5
--- /dev/null
@@ -0,0 +1,63 @@
+/***************************************************************************
+             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
diff --git a/modules/codec/mad/libmad.c b/modules/codec/mad/libmad.c
new file mode 100644 (file)
index 0000000..fe397ed
--- /dev/null
@@ -0,0 +1,567 @@
+/***************************************************************************
+             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);
+}
diff --git a/modules/codec/mad/libmad.h b/modules/codec/mad/libmad.h
new file mode 100644 (file)
index 0000000..20dbca9
--- /dev/null
@@ -0,0 +1,51 @@
+/***************************************************************************
+           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
diff --git a/modules/codec/mpeg_audio/.cvsignore b/modules/codec/mpeg_audio/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/mpeg_audio/Makefile b/modules/codec/mpeg_audio/Makefile
new file mode 100644 (file)
index 0000000..6a1d52a
--- /dev/null
@@ -0,0 +1 @@
+mpeg_audio_SOURCES = decoder.c layer1.c layer2.c math.c generic.c
diff --git a/modules/codec/mpeg_audio/decoder.c b/modules/codec/mpeg_audio/decoder.c
new file mode 100644 (file)
index 0000000..627c681
--- /dev/null
@@ -0,0 +1,235 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/codec/mpeg_audio/decoder.h b/modules/codec/mpeg_audio/decoder.h
new file mode 100644 (file)
index 0000000..f7fb759
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/codec/mpeg_audio/generic.c b/modules/codec/mpeg_audio/generic.c
new file mode 100644 (file)
index 0000000..17592fb
--- /dev/null
@@ -0,0 +1,252 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_audio/generic.h b/modules/codec/mpeg_audio/generic.h
new file mode 100644 (file)
index 0000000..b6f5dc3
--- /dev/null
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * 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;
+
+
diff --git a/modules/codec/mpeg_audio/layer1.c b/modules/codec/mpeg_audio/layer1.c
new file mode 100644 (file)
index 0000000..18ebc77
--- /dev/null
@@ -0,0 +1,350 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_audio/layer1.h b/modules/codec/mpeg_audio/layer1.h
new file mode 100644 (file)
index 0000000..0e44630
--- /dev/null
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * 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);
+
diff --git a/modules/codec/mpeg_audio/layer2.c b/modules/codec/mpeg_audio/layer2.c
new file mode 100644 (file)
index 0000000..eb66972
--- /dev/null
@@ -0,0 +1,993 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_audio/layer2.h b/modules/codec/mpeg_audio/layer2.h
new file mode 100644 (file)
index 0000000..7df1c6b
--- /dev/null
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * 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 );
+
diff --git a/modules/codec/mpeg_audio/math.c b/modules/codec/mpeg_audio/math.c
new file mode 100644 (file)
index 0000000..553339a
--- /dev/null
@@ -0,0 +1,1044 @@
+/*****************************************************************************
+ * 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);
+}
diff --git a/modules/codec/mpeg_audio/math.h b/modules/codec/mpeg_audio/math.h
new file mode 100644 (file)
index 0000000..c8234c9
--- /dev/null
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * 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 );
+
diff --git a/modules/codec/mpeg_audio/test.c b/modules/codec/mpeg_audio/test.c
new file mode 100644 (file)
index 0000000..1e66cf1
--- /dev/null
@@ -0,0 +1,104 @@
+/*****************************************************************************
+ * 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;
+    }
+}
diff --git a/modules/codec/mpeg_video/.cvsignore b/modules/codec/mpeg_video/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/mpeg_video/Makefile b/modules/codec/mpeg_video/Makefile
new file mode 100644 (file)
index 0000000..b9e97b9
--- /dev/null
@@ -0,0 +1,5 @@
+ifeq ($(ARCH),hppa64)
+CFLAGS += -ffunction-sections
+endif
+
+mpeg_video_SOURCES = parser.c headers.c blocks.c synchro.c pool.c decoder.c
diff --git a/modules/codec/mpeg_video/blocks.c b/modules/codec/mpeg_video/blocks.c
new file mode 100644 (file)
index 0000000..c28dd7b
--- /dev/null
@@ -0,0 +1,2205 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/codec/mpeg_video/blocks.h b/modules/codec/mpeg_video/blocks.h
new file mode 100644 (file)
index 0000000..2aad2fd
--- /dev/null
@@ -0,0 +1,432 @@
+/*****************************************************************************
+ * 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}
+};
diff --git a/modules/codec/mpeg_video/decoder.c b/modules/codec/mpeg_video/decoder.c
new file mode 100644 (file)
index 0000000..3470596
--- /dev/null
@@ -0,0 +1,363 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/codec/mpeg_video/decoder.h b/modules/codec/mpeg_video/decoder.h
new file mode 100644 (file)
index 0000000..deceb75
--- /dev/null
@@ -0,0 +1,50 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/codec/mpeg_video/headers.c b/modules/codec/mpeg_video/headers.c
new file mode 100644 (file)
index 0000000..bebddda
--- /dev/null
@@ -0,0 +1,1204 @@
+/*****************************************************************************
+ * 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 ) );
+}
diff --git a/modules/codec/mpeg_video/idct/.cvsignore b/modules/codec/mpeg_video/idct/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/mpeg_video/idct/Makefile b/modules/codec/mpeg_video/idct/Makefile
new file mode 100644 (file)
index 0000000..f8c68d5
--- /dev/null
@@ -0,0 +1,5 @@
+idct_SOURCES = idct.c
+idctclassic_SOURCES = idctclassic.c
+idctmmx_SOURCES = idctmmx.c
+idctmmxext_SOURCES = idctmmxext.c
+idctaltivec_SOURCES = idctaltivec.c
diff --git a/modules/codec/mpeg_video/idct/block_c.h b/modules/codec/mpeg_video/idct/block_c.h
new file mode 100644 (file)
index 0000000..fc6a9b8
--- /dev/null
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/codec/mpeg_video/idct/block_mmx.h b/modules/codec/mpeg_video/idct/block_mmx.h
new file mode 100644 (file)
index 0000000..f58d78a
--- /dev/null
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * 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));
+}
+
diff --git a/modules/codec/mpeg_video/idct/idct.c b/modules/codec/mpeg_video/idct/idct.c
new file mode 100644 (file)
index 0000000..9dad3a9
--- /dev/null
@@ -0,0 +1,1243 @@
+/*****************************************************************************
+ * 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"
diff --git a/modules/codec/mpeg_video/idct/idct.h b/modules/codec/mpeg_video/idct/idct.h
new file mode 100644 (file)
index 0000000..adc9957
--- /dev/null
@@ -0,0 +1,142 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/codec/mpeg_video/idct/idct_decl.h b/modules/codec/mpeg_video/idct/idct_decl.h
new file mode 100644 (file)
index 0000000..82a94ca
--- /dev/null
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_video/idct/idct_sparse.h b/modules/codec/mpeg_video/idct/idct_sparse.h
new file mode 100644 (file)
index 0000000..1ff2a24
--- /dev/null
@@ -0,0 +1,120 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/codec/mpeg_video/idct/idctaltivec.c b/modules/codec/mpeg_video/idct/idctaltivec.c
new file mode 100644 (file)
index 0000000..ed49f0d
--- /dev/null
@@ -0,0 +1,719 @@
+/*****************************************************************************
+ * 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__ */
diff --git a/modules/codec/mpeg_video/idct/idctclassic.c b/modules/codec/mpeg_video/idct/idctclassic.c
new file mode 100644 (file)
index 0000000..8dac31d
--- /dev/null
@@ -0,0 +1,281 @@
+/*****************************************************************************
+ * 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"
diff --git a/modules/codec/mpeg_video/idct/idctmmx.c b/modules/codec/mpeg_video/idct/idctmmx.c
new file mode 100644 (file)
index 0000000..d5b4047
--- /dev/null
@@ -0,0 +1,406 @@
+/*****************************************************************************
+ * 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"
diff --git a/modules/codec/mpeg_video/idct/idctmmxext.c b/modules/codec/mpeg_video/idct/idctmmxext.c
new file mode 100644 (file)
index 0000000..229fc2c
--- /dev/null
@@ -0,0 +1,389 @@
+/*****************************************************************************
+ * 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"
diff --git a/modules/codec/mpeg_video/motion/.cvsignore b/modules/codec/mpeg_video/motion/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/mpeg_video/motion/Makefile b/modules/codec/mpeg_video/motion/Makefile
new file mode 100644 (file)
index 0000000..cf79eda
--- /dev/null
@@ -0,0 +1,5 @@
+motion_SOURCES = motion.c
+motionmmx_SOURCES = motionmmx.c
+motionmmxext_SOURCES = motionmmxext.c
+motion3dnow_SOURCES = motion3dnow.c
+motionaltivec_SOURCES = motionaltivec.c
diff --git a/modules/codec/mpeg_video/motion/motion.c b/modules/codec/mpeg_video/motion/motion.c
new file mode 100644 (file)
index 0000000..8d3603d
--- /dev/null
@@ -0,0 +1,145 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_video/motion/motion3dnow.c b/modules/codec/mpeg_video/motion/motion3dnow.c
new file mode 100644 (file)
index 0000000..c83b4a8
--- /dev/null
@@ -0,0 +1,576 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_video/motion/motionaltivec.c b/modules/codec/mpeg_video/motion/motionaltivec.c
new file mode 100644 (file)
index 0000000..1ea055e
--- /dev/null
@@ -0,0 +1,2074 @@
+/*****************************************************************************
+ * 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__ */
diff --git a/modules/codec/mpeg_video/motion/motionmmx.c b/modules/codec/mpeg_video/motion/motionmmx.c
new file mode 100644 (file)
index 0000000..097fa3e
--- /dev/null
@@ -0,0 +1,660 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_video/motion/motionmmxext.c b/modules/codec/mpeg_video/motion/motionmmxext.c
new file mode 100644 (file)
index 0000000..a33b63a
--- /dev/null
@@ -0,0 +1,551 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/mpeg_video/parser.c b/modules/codec/mpeg_video/parser.c
new file mode 100644 (file)
index 0000000..f129b41
--- /dev/null
@@ -0,0 +1,424 @@
+/*****************************************************************************
+ * 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;
+    }
+}
diff --git a/modules/codec/mpeg_video/parser.h b/modules/codec/mpeg_video/parser.h
new file mode 100644 (file)
index 0000000..f91da7e
--- /dev/null
@@ -0,0 +1,405 @@
+/*****************************************************************************
+ * 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;
+    }
+}
+
diff --git a/modules/codec/mpeg_video/pool.c b/modules/codec/mpeg_video/pool.c
new file mode 100644 (file)
index 0000000..7995217
--- /dev/null
@@ -0,0 +1,332 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/codec/mpeg_video/pool.h b/modules/codec/mpeg_video/pool.h
new file mode 100644 (file)
index 0000000..14347fd
--- /dev/null
@@ -0,0 +1,114 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/codec/mpeg_video/synchro.c b/modules/codec/mpeg_video/synchro.c
new file mode 100644 (file)
index 0000000..748c396
--- /dev/null
@@ -0,0 +1,586 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/codec/spdif/.cvsignore b/modules/codec/spdif/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/spdif/Makefile b/modules/codec/spdif/Makefile
new file mode 100644 (file)
index 0000000..d570604
--- /dev/null
@@ -0,0 +1 @@
+spdif_SOURCES = spdif.c
diff --git a/modules/codec/spdif/spdif.c b/modules/codec/spdif/spdif.c
new file mode 100644 (file)
index 0000000..353a7bc
--- /dev/null
@@ -0,0 +1,431 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/codec/spdif/spdif.h b/modules/codec/spdif/spdif.h
new file mode 100644 (file)
index 0000000..39b5019
--- /dev/null
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * 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;
+
diff --git a/modules/codec/spudec/.cvsignore b/modules/codec/spudec/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/codec/spudec/Makefile b/modules/codec/spudec/Makefile
new file mode 100644 (file)
index 0000000..51c3d30
--- /dev/null
@@ -0,0 +1 @@
+spudec_SOURCES = spudec.c
diff --git a/modules/codec/spudec/spudec.c b/modules/codec/spudec/spudec.c
new file mode 100644 (file)
index 0000000..a2712a5
--- /dev/null
@@ -0,0 +1,1210 @@
+/*****************************************************************************
+ * 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;
+    }
+}
diff --git a/modules/codec/spudec/spudec.h b/modules/codec/spudec/spudec.h
new file mode 100644 (file)
index 0000000..99d371e
--- /dev/null
@@ -0,0 +1,104 @@
+/*****************************************************************************
+ * 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 );
+
diff --git a/modules/control/lirc/.cvsignore b/modules/control/lirc/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/control/lirc/Makefile b/modules/control/lirc/Makefile
new file mode 100644 (file)
index 0000000..139372d
--- /dev/null
@@ -0,0 +1 @@
+lirc_SOURCES = lirc.c
diff --git a/modules/control/lirc/lirc.c b/modules/control/lirc/lirc.c
new file mode 100644 (file)
index 0000000..230e5d0
--- /dev/null
@@ -0,0 +1,252 @@
+/*****************************************************************************
+ * 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 );
+    }
+}
+
diff --git a/modules/control/rc/.cvsignore b/modules/control/rc/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/control/rc/Makefile b/modules/control/rc/Makefile
new file mode 100644 (file)
index 0000000..fbb6f2b
--- /dev/null
@@ -0,0 +1 @@
+rc_SOURCES = rc.c
diff --git a/modules/control/rc/rc.c b/modules/control/rc/rc.c
new file mode 100644 (file)
index 0000000..727dfcb
--- /dev/null
@@ -0,0 +1,331 @@
+/*****************************************************************************
+ * 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;
+    }
+}
+
diff --git a/modules/demux/a52/.cvsignore b/modules/demux/a52/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/demux/a52/Makefile b/modules/demux/a52/Makefile
new file mode 100644 (file)
index 0000000..2872efc
--- /dev/null
@@ -0,0 +1 @@
+a52_SOURCES = demux.c
diff --git a/modules/demux/a52/demux.c b/modules/demux/a52/demux.c
new file mode 100644 (file)
index 0000000..f38c073
--- /dev/null
@@ -0,0 +1,174 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/demux/avi/.cvsignore b/modules/demux/avi/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/demux/avi/Makefile b/modules/demux/avi/Makefile
new file mode 100644 (file)
index 0000000..1983576
--- /dev/null
@@ -0,0 +1 @@
+avi_SOURCES = avi.c libioRIFF.c
diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c
new file mode 100644 (file)
index 0000000..6c67e71
--- /dev/null
@@ -0,0 +1,2228 @@
+/*****************************************************************************
+ * 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 ) );
+    }
+}
+
+
+
diff --git a/modules/demux/avi/avi.h b/modules/demux/avi/avi.h
new file mode 100644 (file)
index 0000000..4f169c0
--- /dev/null
@@ -0,0 +1,263 @@
+/*****************************************************************************
+ * 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;
+
diff --git a/modules/demux/avi/libioRIFF.c b/modules/demux/avi/libioRIFF.c
new file mode 100644 (file)
index 0000000..bc23680
--- /dev/null
@@ -0,0 +1,442 @@
+/*****************************************************************************
+ * 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 );  
+}
diff --git a/modules/demux/avi/libioRIFF.h b/modules/demux/avi/libioRIFF.h
new file mode 100644 (file)
index 0000000..6f09667
--- /dev/null
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * 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 );
+
diff --git a/modules/demux/mp4/.cvsignore b/modules/demux/mp4/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/demux/mp4/Makefile b/modules/demux/mp4/Makefile
new file mode 100644 (file)
index 0000000..ed545ed
--- /dev/null
@@ -0,0 +1 @@
+mp4_SOURCES = mp4.c libmp4.c
diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
new file mode 100644 (file)
index 0000000..c77b0a6
--- /dev/null
@@ -0,0 +1,2307 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
new file mode 100644 (file)
index 0000000..e3e3f28
--- /dev/null
@@ -0,0 +1,804 @@
+/*****************************************************************************
+ * 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 );
+
+
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
new file mode 100644 (file)
index 0000000..b3fecc4
--- /dev/null
@@ -0,0 +1,1084 @@
+/*****************************************************************************
+ * 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 );
+}
+
+
+
diff --git a/modules/demux/mp4/mp4.h b/modules/demux/mp4/mp4.h
new file mode 100644 (file)
index 0000000..93cc8d7
--- /dev/null
@@ -0,0 +1,208 @@
+/*****************************************************************************
+ * 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 )
+          );
+}
diff --git a/modules/demux/mpeg/.cvsignore b/modules/demux/mpeg/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/demux/mpeg/Makefile b/modules/demux/mpeg/Makefile
new file mode 100644 (file)
index 0000000..1f968d8
--- /dev/null
@@ -0,0 +1,5 @@
+es_SOURCES = es.c
+ps_SOURCES = ps.c
+ts_SOURCES = ts.c
+ts_dvbpsi_SOURCES = ts.c
+audio_SOURCES = audio.c
diff --git a/modules/demux/mpeg/audio.c b/modules/demux/mpeg/audio.c
new file mode 100644 (file)
index 0000000..444a1e7
--- /dev/null
@@ -0,0 +1,662 @@
+/*****************************************************************************
+ * 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 );
+}
+
+
diff --git a/modules/demux/mpeg/es.c b/modules/demux/mpeg/es.c
new file mode 100644 (file)
index 0000000..af13465
--- /dev/null
@@ -0,0 +1,196 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/demux/mpeg/ps.c b/modules/demux/mpeg/ps.c
new file mode 100644 (file)
index 0000000..9e2d6f6
--- /dev/null
@@ -0,0 +1,278 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/demux/mpeg/ts.c b/modules/demux/mpeg/ts.c
new file mode 100644 (file)
index 0000000..2ecf45a
--- /dev/null
@@ -0,0 +1,912 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/beos/.cvsignore b/modules/gui/beos/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/gui/beos/AudioOutput.cpp b/modules/gui/beos/AudioOutput.cpp
new file mode 100644 (file)
index 0000000..d897165
--- /dev/null
@@ -0,0 +1,201 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/gui/beos/BeOS.cpp b/modules/gui/beos/BeOS.cpp
new file mode 100644 (file)
index 0000000..b453351
--- /dev/null
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/gui/beos/Bitmaps.h b/modules/gui/beos/Bitmaps.h
new file mode 100644 (file)
index 0000000..cbde243
--- /dev/null
@@ -0,0 +1,1749 @@
+/*****************************************************************************
+ * 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,
+};
+
diff --git a/modules/gui/beos/DrawingTidbits.cpp b/modules/gui/beos/DrawingTidbits.cpp
new file mode 100644 (file)
index 0000000..f62db43
--- /dev/null
@@ -0,0 +1,105 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/gui/beos/DrawingTidbits.h b/modules/gui/beos/DrawingTidbits.h
new file mode 100644 (file)
index 0000000..716fead
--- /dev/null
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/beos/Interface.cpp b/modules/gui/beos/Interface.cpp
new file mode 100644 (file)
index 0000000..9330575
--- /dev/null
@@ -0,0 +1,143 @@
+/*****************************************************************************
+ * 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 );
+    }
+    
+}
+
diff --git a/modules/gui/beos/InterfaceWindow.cpp b/modules/gui/beos/InterfaceWindow.cpp
new file mode 100644 (file)
index 0000000..8b92974
--- /dev/null
@@ -0,0 +1,591 @@
+/*****************************************************************************
+ * 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 );
+
+}
+
+
+
diff --git a/modules/gui/beos/InterfaceWindow.h b/modules/gui/beos/InterfaceWindow.h
new file mode 100644 (file)
index 0000000..5f993df
--- /dev/null
@@ -0,0 +1,77 @@
+/*****************************************************************************
+ * 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;
+};
+
diff --git a/modules/gui/beos/Makefile b/modules/gui/beos/Makefile
new file mode 100644 (file)
index 0000000..4045658
--- /dev/null
@@ -0,0 +1 @@
+beos_SOURCES = BeOS.cpp AudioOutput.cpp VideoOutput.cpp Interface.cpp InterfaceWindow.cpp DrawingTidbits.cpp TransportButton.cpp PlayListWindow.cpp MediaControlView.cpp VlcWrapper.cpp
diff --git a/modules/gui/beos/MediaControlView.cpp b/modules/gui/beos/MediaControlView.cpp
new file mode 100644 (file)
index 0000000..4132a9f
--- /dev/null
@@ -0,0 +1,287 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/gui/beos/MediaControlView.h b/modules/gui/beos/MediaControlView.h
new file mode 100644 (file)
index 0000000..7bb53ed
--- /dev/null
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ * 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;
+};
+
+
diff --git a/modules/gui/beos/MsgVals.h b/modules/gui/beos/MsgVals.h
new file mode 100644 (file)
index 0000000..297e74a
--- /dev/null
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * 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';
+
diff --git a/modules/gui/beos/PlayListWindow.cpp b/modules/gui/beos/PlayListWindow.cpp
new file mode 100644 (file)
index 0000000..02693c6
--- /dev/null
@@ -0,0 +1,170 @@
+/*****************************************************************************
+ * 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();
+}
diff --git a/modules/gui/beos/PlayListWindow.h b/modules/gui/beos/PlayListWindow.h
new file mode 100644 (file)
index 0000000..5b9dbad
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * 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;
+};
+
+
diff --git a/modules/gui/beos/TransportButton.cpp b/modules/gui/beos/TransportButton.cpp
new file mode 100644 (file)
index 0000000..0a82bb4
--- /dev/null
@@ -0,0 +1,622 @@
+/*****************************************************************************
+ * 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();
+}
+
+
diff --git a/modules/gui/beos/TransportButton.h b/modules/gui/beos/TransportButton.h
new file mode 100644 (file)
index 0000000..23bd1f8
--- /dev/null
@@ -0,0 +1,183 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/beos/VideoOutput.cpp b/modules/gui/beos/VideoOutput.cpp
new file mode 100644 (file)
index 0000000..9274891
--- /dev/null
@@ -0,0 +1,653 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/gui/beos/VideoWindow.h b/modules/gui/beos/VideoWindow.h
new file mode 100644 (file)
index 0000000..649b64d
--- /dev/null
@@ -0,0 +1,97 @@
+/*****************************************************************************
+ * 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;
+
+};
+
diff --git a/modules/gui/beos/VlcWrapper.cpp b/modules/gui/beos/VlcWrapper.cpp
new file mode 100644 (file)
index 0000000..f35c6ee
--- /dev/null
@@ -0,0 +1,459 @@
+/*****************************************************************************
+ * 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 */
+    
diff --git a/modules/gui/beos/VlcWrapper.h b/modules/gui/beos/VlcWrapper.h
new file mode 100644 (file)
index 0000000..79db5a6
--- /dev/null
@@ -0,0 +1,121 @@
+/*****************************************************************************
+ * 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;
+
+};
+
diff --git a/modules/gui/familiar/.cvsignore b/modules/gui/familiar/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/gui/familiar/Makefile b/modules/gui/familiar/Makefile
new file mode 100644 (file)
index 0000000..be8d597
--- /dev/null
@@ -0,0 +1 @@
+familiar_SOURCES = familiar.c interface.c support.c callbacks.c
diff --git a/modules/gui/familiar/callbacks.c b/modules/gui/familiar/callbacks.c
new file mode 100644 (file)
index 0000000..d699105
--- /dev/null
@@ -0,0 +1,235 @@
+/*****************************************************************************
+ * 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) );
+    }
+}
+
diff --git a/modules/gui/familiar/callbacks.h b/modules/gui/familiar/callbacks.h
new file mode 100644 (file)
index 0000000..4dca132
--- /dev/null
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * 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);
diff --git a/modules/gui/familiar/familiar.c b/modules/gui/familiar/familiar.c
new file mode 100644 (file)
index 0000000..403dabb
--- /dev/null
@@ -0,0 +1,203 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/gui/familiar/familiar.glade b/modules/gui/familiar/familiar.glade
new file mode 100644 (file)
index 0000000..1ed1cf5
--- /dev/null
@@ -0,0 +1,546 @@
+<?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>
diff --git a/modules/gui/familiar/familiar.h b/modules/gui/familiar/familiar.h
new file mode 100644 (file)
index 0000000..af44ab6
--- /dev/null
@@ -0,0 +1,50 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/gui/familiar/interface.c b/modules/gui/familiar/interface.c
new file mode 100644 (file)
index 0000000..ac2b6ad
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * 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;
+}
+
diff --git a/modules/gui/familiar/interface.h b/modules/gui/familiar/interface.h
new file mode 100644 (file)
index 0000000..27a3bcf
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+GtkWidget* create_familiar (void);
diff --git a/modules/gui/familiar/support.c b/modules/gui/familiar/support.c
new file mode 100644 (file)
index 0000000..4af2461
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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;
+}
+
diff --git a/modules/gui/familiar/support.h b/modules/gui/familiar/support.h
new file mode 100644 (file)
index 0000000..931bc5a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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);
+
diff --git a/modules/gui/gtk/.cvsignore b/modules/gui/gtk/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/gui/gtk/Makefile b/modules/gui/gtk/Makefile
new file mode 100644 (file)
index 0000000..cfab85e
--- /dev/null
@@ -0,0 +1,4 @@
+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)
diff --git a/modules/gui/gtk/common.h b/modules/gui/gtk/common.h
new file mode 100644 (file)
index 0000000..35ce290
--- /dev/null
@@ -0,0 +1,101 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/gui/gtk/control.c b/modules/gui/gtk/control.c
new file mode 100644 (file)
index 0000000..9f4273b
--- /dev/null
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/gui/gtk/control.h b/modules/gui/gtk/control.h
new file mode 100644 (file)
index 0000000..719908d
--- /dev/null
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ * 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 );
+
diff --git a/modules/gui/gtk/display.c b/modules/gui/gtk/display.c
new file mode 100644 (file)
index 0000000..dbcc8e9
--- /dev/null
@@ -0,0 +1,294 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/gtk/display.h b/modules/gui/gtk/display.h
new file mode 100644 (file)
index 0000000..e73d774
--- /dev/null
@@ -0,0 +1,33 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/gui/gtk/gnome.c b/modules/gui/gtk/gnome.c
new file mode 100644 (file)
index 0000000..8b58538
--- /dev/null
@@ -0,0 +1,512 @@
+/*****************************************************************************
+ * 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
+}
+
diff --git a/modules/gui/gtk/gnome.glade b/modules/gui/gtk/gnome.glade
new file mode 100644 (file)
index 0000000..1d101e1
--- /dev/null
@@ -0,0 +1,3507 @@
+<?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 &lt;videolan@videolan.org&gt;
+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>
diff --git a/modules/gui/gtk/gnome_callbacks.c b/modules/gui/gtk/gnome_callbacks.c
new file mode 100644 (file)
index 0000000..afc407c
--- /dev/null
@@ -0,0 +1,3 @@
+/*****************************************************************************
+ * This file is not used: everything is in gtk_callbacks.c
+ *****************************************************************************/
diff --git a/modules/gui/gtk/gnome_callbacks.h b/modules/gui/gtk/gnome_callbacks.h
new file mode 100644 (file)
index 0000000..3899961
--- /dev/null
@@ -0,0 +1,4 @@
+/*****************************************************************************
+ * This file is not needed: everything is in gtk_callbacks.h
+ *****************************************************************************/
+#include "gtk_callbacks.h"
diff --git a/modules/gui/gtk/gnome_interface.c b/modules/gui/gtk/gnome_interface.c
new file mode 100644 (file)
index 0000000..cb92d64
--- /dev/null
@@ -0,0 +1,2442 @@
+/* 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;
+}
+
diff --git a/modules/gui/gtk/gnome_interface.h b/modules/gui/gtk/gnome_interface.h
new file mode 100644 (file)
index 0000000..a6a2317
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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);
diff --git a/modules/gui/gtk/gnome_support.c b/modules/gui/gtk/gnome_support.c
new file mode 100644 (file)
index 0000000..d59198c
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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;
+}
+
diff --git a/modules/gui/gtk/gnome_support.h b/modules/gui/gtk/gnome_support.h
new file mode 100644 (file)
index 0000000..d9bb072
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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);
+
diff --git a/modules/gui/gtk/gtk.c b/modules/gui/gtk/gtk.c
new file mode 100644 (file)
index 0000000..7309aa3
--- /dev/null
@@ -0,0 +1,494 @@
+/*****************************************************************************
+ * 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
+}
diff --git a/modules/gui/gtk/gtk.glade b/modules/gui/gtk/gtk.glade
new file mode 100644 (file)
index 0000000..2e11ce7
--- /dev/null
@@ -0,0 +1,3545 @@
+<?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 &lt;videolan@videolan.org&gt;
+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>
diff --git a/modules/gui/gtk/gtk_callbacks.c b/modules/gui/gtk/gtk_callbacks.c
new file mode 100644 (file)
index 0000000..46ca900
--- /dev/null
@@ -0,0 +1,581 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/gui/gtk/gtk_callbacks.h b/modules/gui/gtk/gtk_callbacks.h
new file mode 100644 (file)
index 0000000..605c0ef
--- /dev/null
@@ -0,0 +1,151 @@
+/*****************************************************************************
+ * 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);
diff --git a/modules/gui/gtk/gtk_interface.c b/modules/gui/gtk/gtk_interface.c
new file mode 100644 (file)
index 0000000..09c162f
--- /dev/null
@@ -0,0 +1,2658 @@
+/* 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;
+}
+
diff --git a/modules/gui/gtk/gtk_interface.h b/modules/gui/gtk/gtk_interface.h
new file mode 100644 (file)
index 0000000..8dcbf9b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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);
diff --git a/modules/gui/gtk/gtk_support.c b/modules/gui/gtk/gtk_support.c
new file mode 100644 (file)
index 0000000..987d9a9
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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;
+}
+
diff --git a/modules/gui/gtk/gtk_support.h b/modules/gui/gtk/gtk_support.h
new file mode 100644 (file)
index 0000000..9439da3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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);
+
diff --git a/modules/gui/gtk/menu.c b/modules/gui/gtk/menu.c
new file mode 100644 (file)
index 0000000..9b8ec74
--- /dev/null
@@ -0,0 +1,1015 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/gui/gtk/menu.h b/modules/gui/gtk/menu.h
new file mode 100644 (file)
index 0000000..2903459
--- /dev/null
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * 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)) )
+
diff --git a/modules/gui/gtk/modules.c b/modules/gui/gtk/modules.c
new file mode 100644 (file)
index 0000000..8ebadb4
--- /dev/null
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/gui/gtk/modules.h b/modules/gui/gtk/modules.h
new file mode 100644 (file)
index 0000000..96eded9
--- /dev/null
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * 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 );
+
diff --git a/modules/gui/gtk/open.c b/modules/gui/gtk/open.c
new file mode 100644 (file)
index 0000000..022d8f4
--- /dev/null
@@ -0,0 +1,535 @@
+/*****************************************************************************
+ * 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;
+    }
+}
+
diff --git a/modules/gui/gtk/open.h b/modules/gui/gtk/open.h
new file mode 100644 (file)
index 0000000..aee469b
--- /dev/null
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * 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 );
+
diff --git a/modules/gui/gtk/playlist.c b/modules/gui/gtk/playlist.c
new file mode 100644 (file)
index 0000000..2e422aa
--- /dev/null
@@ -0,0 +1,741 @@
+/*****************************************************************************
+ * 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);
+}
+
diff --git a/modules/gui/gtk/playlist.h b/modules/gui/gtk/playlist.h
new file mode 100644 (file)
index 0000000..1ec460b
--- /dev/null
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/gui/gtk/preferences.c b/modules/gui/gtk/preferences.c
new file mode 100644 (file)
index 0000000..11e58a8
--- /dev/null
@@ -0,0 +1,947 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/gui/gtk/preferences.h b/modules/gui/gtk/preferences.h
new file mode 100644 (file)
index 0000000..8a03a33
--- /dev/null
@@ -0,0 +1,25 @@
+/*****************************************************************************
+ * 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 );
diff --git a/modules/gui/kde/.cvsignore b/modules/gui/kde/.cvsignore
new file mode 100644 (file)
index 0000000..e1108c6
--- /dev/null
@@ -0,0 +1,5 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
+*.moc.*
diff --git a/modules/gui/kde/Makefile b/modules/gui/kde/Makefile
new file mode 100644 (file)
index 0000000..701f9e2
--- /dev/null
@@ -0,0 +1,6 @@
+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 $@
diff --git a/modules/gui/kde/QConfigItem.cpp b/modules/gui/kde/QConfigItem.cpp
new file mode 100644 (file)
index 0000000..aad1f3c
--- /dev/null
@@ -0,0 +1,67 @@
+#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;
+}
diff --git a/modules/gui/kde/QConfigItem.h b/modules/gui/kde/QConfigItem.h
new file mode 100644 (file)
index 0000000..4a2e7fe
--- /dev/null
@@ -0,0 +1,34 @@
+#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
diff --git a/modules/gui/kde/common.h b/modules/gui/kde/common.h
new file mode 100644 (file)
index 0000000..67ec336
--- /dev/null
@@ -0,0 +1,20 @@
+/***************************************************************************
+                          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_ */
diff --git a/modules/gui/kde/disc.cpp b/modules/gui/kde/disc.cpp
new file mode 100644 (file)
index 0000000..dd89336
--- /dev/null
@@ -0,0 +1,80 @@
+/***************************************************************************
+                          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() );
+}
diff --git a/modules/gui/kde/disc.h b/modules/gui/kde/disc.h
new file mode 100644 (file)
index 0000000..86e6d96
--- /dev/null
@@ -0,0 +1,47 @@
+/***************************************************************************
+                          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
diff --git a/modules/gui/kde/interface.cpp b/modules/gui/kde/interface.cpp
new file mode 100644 (file)
index 0000000..12b9cf6
--- /dev/null
@@ -0,0 +1,466 @@
+/***************************************************************************
+                          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 );
+}
diff --git a/modules/gui/kde/interface.h b/modules/gui/kde/interface.h
new file mode 100644 (file)
index 0000000..9a7c7bf
--- /dev/null
@@ -0,0 +1,150 @@
+/***************************************************************************
+                          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_ */
diff --git a/modules/gui/kde/kde.cpp b/modules/gui/kde/kde.cpp
new file mode 100644 (file)
index 0000000..1dcc820
--- /dev/null
@@ -0,0 +1,174 @@
+/*****************************************************************************
+ * 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();
+}
+
diff --git a/modules/gui/kde/menu.cpp b/modules/gui/kde/menu.cpp
new file mode 100644 (file)
index 0000000..fbdbe4b
--- /dev/null
@@ -0,0 +1,82 @@
+/***************************************************************************
+                          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()
+{
+}
diff --git a/modules/gui/kde/menu.h b/modules/gui/kde/menu.h
new file mode 100644 (file)
index 0000000..480d882
--- /dev/null
@@ -0,0 +1,44 @@
+/***************************************************************************
+                          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_ */
diff --git a/modules/gui/kde/net.cpp b/modules/gui/kde/net.cpp
new file mode 100644 (file)
index 0000000..a214337
--- /dev/null
@@ -0,0 +1,77 @@
+/***************************************************************************
+                          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() );
+}
diff --git a/modules/gui/kde/net.h b/modules/gui/kde/net.h
new file mode 100644 (file)
index 0000000..3f99021
--- /dev/null
@@ -0,0 +1,45 @@
+/***************************************************************************
+                          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_ */
diff --git a/modules/gui/kde/pluginsbox.cpp b/modules/gui/kde/pluginsbox.cpp
new file mode 100644 (file)
index 0000000..e7a3309
--- /dev/null
@@ -0,0 +1,68 @@
+#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)));
+}
diff --git a/modules/gui/kde/pluginsbox.h b/modules/gui/kde/pluginsbox.h
new file mode 100644 (file)
index 0000000..168ecb5
--- /dev/null
@@ -0,0 +1,34 @@
+#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
diff --git a/modules/gui/kde/preferences.cpp b/modules/gui/kde/preferences.cpp
new file mode 100644 (file)
index 0000000..56ef098
--- /dev/null
@@ -0,0 +1,280 @@
+#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 );
+}
diff --git a/modules/gui/kde/preferences.h b/modules/gui/kde/preferences.h
new file mode 100644 (file)
index 0000000..f80880b
--- /dev/null
@@ -0,0 +1,24 @@
+#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
diff --git a/modules/gui/kde/slider.cpp b/modules/gui/kde/slider.cpp
new file mode 100644 (file)
index 0000000..9ef5a34
--- /dev/null
@@ -0,0 +1,52 @@
+/***************************************************************************
+                          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() );
+}
diff --git a/modules/gui/kde/slider.h b/modules/gui/kde/slider.h
new file mode 100644 (file)
index 0000000..13cc6e3
--- /dev/null
@@ -0,0 +1,45 @@
+/***************************************************************************
+                          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_ */
diff --git a/modules/gui/kde/ui.rc b/modules/gui/kde/ui.rc
new file mode 100644 (file)
index 0000000..8f0d817
--- /dev/null
@@ -0,0 +1,45 @@
+<!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>&amp;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>
diff --git a/modules/gui/macosx/.cvsignore b/modules/gui/macosx/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/gui/macosx/Makefile b/modules/gui/macosx/Makefile
new file mode 100644 (file)
index 0000000..8ade2c5
--- /dev/null
@@ -0,0 +1 @@
+macosx_SOURCES = macosx.m aout.m vout.m intf.m open.m playlist.m controls.m
diff --git a/modules/gui/macosx/aout.m b/modules/gui/macosx/aout.m
new file mode 100644 (file)
index 0000000..4f19283
--- /dev/null
@@ -0,0 +1,491 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/gui/macosx/controls.m b/modules/gui/macosx/controls.m
new file mode 100644 (file)
index 0000000..3e2a6b2
--- /dev/null
@@ -0,0 +1,518 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/macosx/intf.h b/modules/gui/macosx/intf.h
new file mode 100644 (file)
index 0000000..276ef92
--- /dev/null
@@ -0,0 +1,163 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m
new file mode 100644 (file)
index 0000000..774a5ac
--- /dev/null
@@ -0,0 +1,900 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/gui/macosx/macosx.m b/modules/gui/macosx/macosx.m
new file mode 100644 (file)
index 0000000..afb59a7
--- /dev/null
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/gui/macosx/open.h b/modules/gui/macosx/open.h
new file mode 100644 (file)
index 0000000..cb6df0d
--- /dev/null
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/macosx/open.m b/modules/gui/macosx/open.m
new file mode 100644 (file)
index 0000000..d8dd38d
--- /dev/null
@@ -0,0 +1,382 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/macosx/playlist.h b/modules/gui/macosx/playlist.h
new file mode 100644 (file)
index 0000000..adbf1f2
--- /dev/null
@@ -0,0 +1,47 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/gui/macosx/playlist.m b/modules/gui/macosx/playlist.m
new file mode 100644 (file)
index 0000000..d290a41
--- /dev/null
@@ -0,0 +1,246 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/gui/macosx/vout.h b/modules/gui/macosx/vout.h
new file mode 100644 (file)
index 0000000..2e072b6
--- /dev/null
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ * 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;
diff --git a/modules/gui/macosx/vout.m b/modules/gui/macosx/vout.m
new file mode 100644 (file)
index 0000000..e39ea9c
--- /dev/null
@@ -0,0 +1,800 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/gui/ncurses/.cvsignore b/modules/gui/ncurses/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/gui/ncurses/Makefile b/modules/gui/ncurses/Makefile
new file mode 100644 (file)
index 0000000..ec417ed
--- /dev/null
@@ -0,0 +1 @@
+ncurses_SOURCES = ncurses.c
diff --git a/modules/gui/ncurses/ncurses.c b/modules/gui/ncurses/ncurses.c
new file mode 100644 (file)
index 0000000..0e36259
--- /dev/null
@@ -0,0 +1,630 @@
+/*****************************************************************************
+ * 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 );
+    }
+}
+
diff --git a/modules/gui/qnx/.cvsignore b/modules/gui/qnx/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/gui/qnx/Makefile b/modules/gui/qnx/Makefile
new file mode 100644 (file)
index 0000000..be320aa
--- /dev/null
@@ -0,0 +1 @@
+qnx_SOURCES = qnx.c aout.c vout.c
diff --git a/modules/gui/qnx/aout.c b/modules/gui/qnx/aout.c
new file mode 100644 (file)
index 0000000..adbf84c
--- /dev/null
@@ -0,0 +1,243 @@
+/*****************************************************************************
+ * 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 );
+}
diff --git a/modules/gui/qnx/qnx.c b/modules/gui/qnx/qnx.c
new file mode 100644 (file)
index 0000000..32fbff1
--- /dev/null
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/gui/qnx/vout.c b/modules/gui/qnx/vout.c
new file mode 100644 (file)
index 0000000..b49d713
--- /dev/null
@@ -0,0 +1,1099 @@
+/*****************************************************************************
+ * 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 );
+    }
+}
diff --git a/modules/gui/qt/.cvsignore b/modules/gui/qt/.cvsignore
new file mode 100644 (file)
index 0000000..12c27ba
--- /dev/null
@@ -0,0 +1,5 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
+*.moc
diff --git a/modules/gui/qt/Makefile b/modules/gui/qt/Makefile
new file mode 100644 (file)
index 0000000..e0e4e8f
--- /dev/null
@@ -0,0 +1,8 @@
+qt_SOURCES = qt.cpp intf.cpp
+MOC_QT = intf.moc
+
+EXTRA_DEP = $(MOC_QT)
+
+$(MOC_QT): %.moc: %.cpp
+       $(MOC) -i $< -o $@
+
diff --git a/modules/gui/qt/intf.cpp b/modules/gui/qt/intf.cpp
new file mode 100644 (file)
index 0000000..cefbfdd
--- /dev/null
@@ -0,0 +1,596 @@
+/*****************************************************************************
+ * 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 */
+}
+
+
diff --git a/modules/gui/qt/qt.cpp b/modules/gui/qt/qt.cpp
new file mode 100644 (file)
index 0000000..62939a9
--- /dev/null
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/gui/win32/.cvsignore b/modules/gui/win32/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/gui/win32/Makefile b/modules/gui/win32/Makefile
new file mode 100644 (file)
index 0000000..62ef5e8
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# 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
+
+
diff --git a/modules/gui/win32/about.cpp b/modules/gui/win32/about.cpp
new file mode 100644 (file)
index 0000000..10c307e
--- /dev/null
@@ -0,0 +1,47 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/about.dfm b/modules/gui/win32/about.dfm
new file mode 100644 (file)
index 0000000..76cfa5a
--- /dev/null
@@ -0,0 +1,316 @@
+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
diff --git a/modules/gui/win32/about.h b/modules/gui/win32/about.h
new file mode 100644 (file)
index 0000000..d08caa9
--- /dev/null
@@ -0,0 +1,50 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/control.cpp b/modules/gui/win32/control.cpp
new file mode 100644 (file)
index 0000000..da70656
--- /dev/null
@@ -0,0 +1,120 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/control.h b/modules/gui/win32/control.h
new file mode 100644 (file)
index 0000000..0ee1ebd
--- /dev/null
@@ -0,0 +1,29 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/disc.cpp b/modules/gui/win32/disc.cpp
new file mode 100644 (file)
index 0000000..fff7ca3
--- /dev/null
@@ -0,0 +1,126 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/disc.dfm b/modules/gui/win32/disc.dfm
new file mode 100644 (file)
index 0000000..a86d530
--- /dev/null
@@ -0,0 +1,345 @@
+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
diff --git a/modules/gui/win32/disc.h b/modules/gui/win32/disc.h
new file mode 100644 (file)
index 0000000..1e2646d
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/intfwin.bpf b/modules/gui/win32/intfwin.bpf
new file mode 100644 (file)
index 0000000..24e5c00
--- /dev/null
@@ -0,0 +1,16 @@
+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
diff --git a/modules/gui/win32/intfwin.cpp b/modules/gui/win32/intfwin.cpp
new file mode 100644 (file)
index 0000000..267d765
--- /dev/null
@@ -0,0 +1,239 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/mainframe.cpp b/modules/gui/win32/mainframe.cpp
new file mode 100644 (file)
index 0000000..7a8f6a2
--- /dev/null
@@ -0,0 +1,736 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/mainframe.dfm b/modules/gui/win32/mainframe.dfm
new file mode 100644 (file)
index 0000000..e797238
--- /dev/null
@@ -0,0 +1,2438 @@
+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
diff --git a/modules/gui/win32/mainframe.h b/modules/gui/win32/mainframe.h
new file mode 100644 (file)
index 0000000..15b4111
--- /dev/null
@@ -0,0 +1,207 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/menu.cpp b/modules/gui/win32/menu.cpp
new file mode 100644 (file)
index 0000000..1de6140
--- /dev/null
@@ -0,0 +1,816 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/menu.h b/modules/gui/win32/menu.h
new file mode 100644 (file)
index 0000000..5c4ca32
--- /dev/null
@@ -0,0 +1,32 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/messages.cpp b/modules/gui/win32/messages.cpp
new file mode 100644 (file)
index 0000000..ef723ea
--- /dev/null
@@ -0,0 +1,113 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/messages.dfm b/modules/gui/win32/messages.dfm
new file mode 100644 (file)
index 0000000..dbe1734
--- /dev/null
@@ -0,0 +1,46 @@
+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
diff --git a/modules/gui/win32/messages.h b/modules/gui/win32/messages.h
new file mode 100644 (file)
index 0000000..74bbc9a
--- /dev/null
@@ -0,0 +1,47 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/network.cpp b/modules/gui/win32/network.cpp
new file mode 100644 (file)
index 0000000..eb499f6
--- /dev/null
@@ -0,0 +1,235 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/network.dfm b/modules/gui/win32/network.dfm
new file mode 100644 (file)
index 0000000..02f6cd6
--- /dev/null
@@ -0,0 +1,425 @@
+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
diff --git a/modules/gui/win32/network.h b/modules/gui/win32/network.h
new file mode 100644 (file)
index 0000000..45c5057
--- /dev/null
@@ -0,0 +1,75 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/playlist.cpp b/modules/gui/win32/playlist.cpp
new file mode 100644 (file)
index 0000000..a3a2c49
--- /dev/null
@@ -0,0 +1,387 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/playlist.dfm b/modules/gui/win32/playlist.dfm
new file mode 100644 (file)
index 0000000..0e8c535
--- /dev/null
@@ -0,0 +1,133 @@
+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
diff --git a/modules/gui/win32/playlist.h b/modules/gui/win32/playlist.h
new file mode 100644 (file)
index 0000000..d5fc114
--- /dev/null
@@ -0,0 +1,93 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/preferences.cpp b/modules/gui/win32/preferences.cpp
new file mode 100644 (file)
index 0000000..8cceece
--- /dev/null
@@ -0,0 +1,560 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/preferences.dfm b/modules/gui/win32/preferences.dfm
new file mode 100644 (file)
index 0000000..54dc0da
--- /dev/null
@@ -0,0 +1,294 @@
+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
diff --git a/modules/gui/win32/preferences.h b/modules/gui/win32/preferences.h
new file mode 100644 (file)
index 0000000..9dbb92d
--- /dev/null
@@ -0,0 +1,125 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/win32.bpr b/modules/gui/win32/win32.bpr
new file mode 100644 (file)
index 0000000..bcfb101
--- /dev/null
@@ -0,0 +1,110 @@
+<?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&quot;&quot; -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
diff --git a/modules/gui/win32/win32.cpp b/modules/gui/win32/win32.cpp
new file mode 100644 (file)
index 0000000..e3480b3
--- /dev/null
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/gui/win32/win32.h b/modules/gui/win32/win32.h
new file mode 100644 (file)
index 0000000..3724dbd
--- /dev/null
@@ -0,0 +1,27 @@
+/*****************************************************************************\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
diff --git a/modules/gui/win32/win32_common.h b/modules/gui/win32/win32_common.h
new file mode 100644 (file)
index 0000000..63f956c
--- /dev/null
@@ -0,0 +1,91 @@
+/*****************************************************************************\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
diff --git a/modules/misc/dummy/.cvsignore b/modules/misc/dummy/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/misc/dummy/Makefile b/modules/misc/dummy/Makefile
new file mode 100644 (file)
index 0000000..307e1c7
--- /dev/null
@@ -0,0 +1 @@
+dummy_SOURCES = dummy.c aout.c vout.c interface.c input.c decoder.c
diff --git a/modules/misc/dummy/aout.c b/modules/misc/dummy/aout.c
new file mode 100644 (file)
index 0000000..20c45aa
--- /dev/null
@@ -0,0 +1,76 @@
+/*****************************************************************************
+ * 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 )
+{
+    ;
+}
+
diff --git a/modules/misc/dummy/decoder.c b/modules/misc/dummy/decoder.c
new file mode 100644 (file)
index 0000000..444469f
--- /dev/null
@@ -0,0 +1,119 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/misc/dummy/dummy.c b/modules/misc/dummy/dummy.c
new file mode 100644 (file)
index 0000000..8ccd5d4
--- /dev/null
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/misc/dummy/dummy.h b/modules/misc/dummy/dummy.h
new file mode 100644 (file)
index 0000000..0cbd902
--- /dev/null
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * 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 * );
+
diff --git a/modules/misc/dummy/input.c b/modules/misc/dummy/input.c
new file mode 100644 (file)
index 0000000..7d6cfa8
--- /dev/null
@@ -0,0 +1,197 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/misc/dummy/interface.c b/modules/misc/dummy/interface.c
new file mode 100644 (file)
index 0000000..d6c8848
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * 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 );
+    }
+}
+
diff --git a/modules/misc/dummy/vout.c b/modules/misc/dummy/vout.c
new file mode 100644 (file)
index 0000000..000ebe5
--- /dev/null
@@ -0,0 +1,196 @@
+/*****************************************************************************
+ * 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 */
+}
+
diff --git a/modules/misc/logger/.cvsignore b/modules/misc/logger/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/misc/logger/Makefile b/modules/misc/logger/Makefile
new file mode 100644 (file)
index 0000000..35ed9d7
--- /dev/null
@@ -0,0 +1 @@
+logger_SOURCES = logger.c
diff --git a/modules/misc/logger/logger.c b/modules/misc/logger/logger.c
new file mode 100644 (file)
index 0000000..c17d6ac
--- /dev/null
@@ -0,0 +1,299 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/misc/memcpy/.cvsignore b/modules/misc/memcpy/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/misc/memcpy/Makefile b/modules/misc/memcpy/Makefile
new file mode 100644 (file)
index 0000000..ed9ee32
--- /dev/null
@@ -0,0 +1,5 @@
+memcpy_SOURCES = memcpy.c
+memcpymmx_SOURCES = memcpy.c
+memcpymmxext_SOURCES = memcpy.c
+memcpy3dn_SOURCES = memcpy.c
+memcpyaltivec_SOURCES = memcpyaltivec.c
diff --git a/modules/misc/memcpy/fastmemcpy.h b/modules/misc/memcpy/fastmemcpy.h
new file mode 100644 (file)
index 0000000..07068e9
--- /dev/null
@@ -0,0 +1,386 @@
+/*****************************************************************************
+ * 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 ) */
diff --git a/modules/misc/memcpy/memcpy.c b/modules/misc/memcpy/memcpy.c
new file mode 100644 (file)
index 0000000..b70b8c7
--- /dev/null
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/misc/memcpy/memcpyaltivec.c b/modules/misc/memcpy/memcpyaltivec.c
new file mode 100644 (file)
index 0000000..25d4ff2
--- /dev/null
@@ -0,0 +1,212 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/misc/network/.cvsignore b/modules/misc/network/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/misc/network/Makefile b/modules/misc/network/Makefile
new file mode 100644 (file)
index 0000000..6c75b41
--- /dev/null
@@ -0,0 +1,2 @@
+ipv4_SOURCES = ipv4.c
+ipv6_SOURCES = ipv6.c
diff --git a/modules/misc/network/ipv4.c b/modules/misc/network/ipv4.c
new file mode 100644 (file)
index 0000000..83ba7cd
--- /dev/null
@@ -0,0 +1,353 @@
+/*****************************************************************************
+ * 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 );
+    }
+}
diff --git a/modules/misc/network/ipv6.c b/modules/misc/network/ipv6.c
new file mode 100644 (file)
index 0000000..e2323bd
--- /dev/null
@@ -0,0 +1,422 @@
+/*****************************************************************************
+ * 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 );
+    }
+}
diff --git a/modules/misc/null/.cvsignore b/modules/misc/null/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/misc/null/Makefile b/modules/misc/null/Makefile
new file mode 100644 (file)
index 0000000..fbea829
--- /dev/null
@@ -0,0 +1 @@
+null_SOURCES = null.c
diff --git a/modules/misc/null/null.c b/modules/misc/null/null.c
new file mode 100644 (file)
index 0000000..434d999
--- /dev/null
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/video_chroma/.cvsignore b/modules/video_chroma/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_chroma/Makefile b/modules/video_chroma/Makefile
new file mode 100644 (file)
index 0000000..8a6a984
--- /dev/null
@@ -0,0 +1,8 @@
+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
diff --git a/modules/video_chroma/i420_rgb.c b/modules/video_chroma/i420_rgb.c
new file mode 100644 (file)
index 0000000..e2475e9
--- /dev/null
@@ -0,0 +1,419 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/video_chroma/i420_rgb.h b/modules/video_chroma/i420_rgb.h
new file mode 100644 (file)
index 0000000..dcd929d
--- /dev/null
@@ -0,0 +1,315 @@
+/*****************************************************************************
+ * 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;                                                                \
+    }                                                                         \
+
diff --git a/modules/video_chroma/i420_rgb16.c b/modules/video_chroma/i420_rgb16.c
new file mode 100644 (file)
index 0000000..070324d
--- /dev/null
@@ -0,0 +1,498 @@
+/*****************************************************************************
+ * 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;
+    }
+}
+
diff --git a/modules/video_chroma/i420_rgb8.c b/modules/video_chroma/i420_rgb8.c
new file mode 100644 (file)
index 0000000..6b643b4
--- /dev/null
@@ -0,0 +1,177 @@
+/*****************************************************************************
+ * 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;
+    }
+}
+
diff --git a/modules/video_chroma/i420_rgb_c.h b/modules/video_chroma/i420_rgb_c.h
new file mode 100644 (file)
index 0000000..1387fce
--- /dev/null
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * 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))
+
diff --git a/modules/video_chroma/i420_rgb_mmx.h b/modules/video_chroma/i420_rgb_mmx.h
new file mode 100644 (file)
index 0000000..252c47c
--- /dev/null
@@ -0,0 +1,284 @@
+/*****************************************************************************
+ * 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\
+"
+
diff --git a/modules/video_chroma/i420_ymga.c b/modules/video_chroma/i420_ymga.c
new file mode 100644 (file)
index 0000000..14341bf
--- /dev/null
@@ -0,0 +1,150 @@
+/*****************************************************************************
+ * 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
+    }
+}
+
diff --git a/modules/video_chroma/i420_yuy2.c b/modules/video_chroma/i420_yuy2.c
new file mode 100644 (file)
index 0000000..9aa3acb
--- /dev/null
@@ -0,0 +1,377 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/video_chroma/i420_yuy2.h b/modules/video_chroma/i420_yuy2.h
new file mode 100644 (file)
index 0000000..f56f6c5
--- /dev/null
@@ -0,0 +1,143 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/video_chroma/i422_yuy2.c b/modules/video_chroma/i422_yuy2.c
new file mode 100644 (file)
index 0000000..2b50b84
--- /dev/null
@@ -0,0 +1,318 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/video_chroma/i422_yuy2.h b/modules/video_chroma/i422_yuy2.h
new file mode 100644 (file)
index 0000000..1ce334e
--- /dev/null
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/video_filter/.cvsignore b/modules/video_filter/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_filter/Makefile b/modules/video_filter/Makefile
new file mode 100644 (file)
index 0000000..a49a479
--- /dev/null
@@ -0,0 +1,6 @@
+transform_SOURCES = transform.c
+invert_SOURCES = invert.c
+distort_SOURCES = distort.c
+wall_SOURCES = wall.c
+clone_SOURCES = clone.c
+crop_SOURCES = crop.c
diff --git a/modules/video_filter/clone.c b/modules/video_filter/clone.c
new file mode 100644 (file)
index 0000000..0607658
--- /dev/null
@@ -0,0 +1,257 @@
+/*****************************************************************************
+ * 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] );
+    }
+}
+
diff --git a/modules/video_filter/crop.c b/modules/video_filter/crop.c
new file mode 100644 (file)
index 0000000..8c9bc28
--- /dev/null
@@ -0,0 +1,461 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/video_filter/deinterlace/.cvsignore b/modules/video_filter/deinterlace/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_filter/deinterlace/Makefile b/modules/video_filter/deinterlace/Makefile
new file mode 100644 (file)
index 0000000..38beb06
--- /dev/null
@@ -0,0 +1 @@
+deinterlace_SOURCES = deinterlace.c
diff --git a/modules/video_filter/deinterlace/deinterlace.c b/modules/video_filter/deinterlace/deinterlace.c
new file mode 100644 (file)
index 0000000..3ea175e
--- /dev/null
@@ -0,0 +1,579 @@
+/*****************************************************************************
+ * 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;
+    }
+}
diff --git a/modules/video_filter/distort.c b/modules/video_filter/distort.c
new file mode 100644 (file)
index 0000000..c3ba5fa
--- /dev/null
@@ -0,0 +1,421 @@
+/*****************************************************************************
+ * 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;
+            }
+
+        }
+    }
+}
diff --git a/modules/video_filter/filter_common.h b/modules/video_filter/filter_common.h
new file mode 100644 (file)
index 0000000..bed8ed4
--- /dev/null
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * 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++;                                                   \
+    }                                                                         \
+
diff --git a/modules/video_filter/invert.c b/modules/video_filter/invert.c
new file mode 100644 (file)
index 0000000..1cbe350
--- /dev/null
@@ -0,0 +1,221 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/video_filter/transform.c b/modules/video_filter/transform.c
new file mode 100644 (file)
index 0000000..693d8c0
--- /dev/null
@@ -0,0 +1,386 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/video_filter/wall.c b/modules/video_filter/wall.c
new file mode 100644 (file)
index 0000000..b05f962
--- /dev/null
@@ -0,0 +1,421 @@
+/*****************************************************************************
+ * 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 );
+         }
+    }
+}
diff --git a/modules/video_output/aa/.cvsignore b/modules/video_output/aa/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/aa/Makefile b/modules/video_output/aa/Makefile
new file mode 100644 (file)
index 0000000..f4187c7
--- /dev/null
@@ -0,0 +1 @@
+aa_SOURCES = aa.c
diff --git a/modules/video_output/aa/aa.c b/modules/video_output/aa/aa.c
new file mode 100644 (file)
index 0000000..d125c52
--- /dev/null
@@ -0,0 +1,260 @@
+/*****************************************************************************
+ * 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 ] );
+    }
+}
+
diff --git a/modules/video_output/directx/.cvsignore b/modules/video_output/directx/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/directx/Makefile b/modules/video_output/directx/Makefile
new file mode 100644 (file)
index 0000000..4f6b1d3
--- /dev/null
@@ -0,0 +1 @@
+directx_SOURCES = directx.c vout.c events.c aout.c
diff --git a/modules/video_output/directx/aout.c b/modules/video_output/directx/aout.c
new file mode 100644 (file)
index 0000000..84cc2ab
--- /dev/null
@@ -0,0 +1,761 @@
+/*****************************************************************************
+ * 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" );
+
+}
diff --git a/modules/video_output/directx/directx.c b/modules/video_output/directx/directx.c
new file mode 100644 (file)
index 0000000..9196667
--- /dev/null
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/video_output/directx/events.c b/modules/video_output/directx/events.c
new file mode 100644 (file)
index 0000000..6e55e71
--- /dev/null
@@ -0,0 +1,580 @@
+/*****************************************************************************
+ * 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);
+}
diff --git a/modules/video_output/directx/vout.c b/modules/video_output/directx/vout.c
new file mode 100644 (file)
index 0000000..a0d566d
--- /dev/null
@@ -0,0 +1,1350 @@
+/*****************************************************************************
+ * 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;
+}
diff --git a/modules/video_output/directx/vout.h b/modules/video_output/directx/vout.h
new file mode 100644 (file)
index 0000000..6cfaed8
--- /dev/null
@@ -0,0 +1,112 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/video_output/fb/.cvsignore b/modules/video_output/fb/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/fb/Makefile b/modules/video_output/fb/Makefile
new file mode 100644 (file)
index 0000000..d993d4e
--- /dev/null
@@ -0,0 +1 @@
+fb_SOURCES = fb.c
diff --git a/modules/video_output/fb/fb.c b/modules/video_output/fb/fb.c
new file mode 100644 (file)
index 0000000..6709163
--- /dev/null
@@ -0,0 +1,695 @@
+/*****************************************************************************
+ * 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" );
+    }
+}
+
diff --git a/modules/video_output/ggi/.cvsignore b/modules/video_output/ggi/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/ggi/Makefile b/modules/video_output/ggi/Makefile
new file mode 100644 (file)
index 0000000..3be0c18
--- /dev/null
@@ -0,0 +1 @@
+ggi_SOURCES = ggi.c
diff --git a/modules/video_output/ggi/ggi.c b/modules/video_output/ggi/ggi.c
new file mode 100644 (file)
index 0000000..b737b55
--- /dev/null
@@ -0,0 +1,529 @@
+/*****************************************************************************
+ * 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" );
+    }
+}
+
diff --git a/modules/video_output/glide/.cvsignore b/modules/video_output/glide/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/glide/Makefile b/modules/video_output/glide/Makefile
new file mode 100644 (file)
index 0000000..9f3bd7a
--- /dev/null
@@ -0,0 +1 @@
+glide_SOURCES = glide.c
diff --git a/modules/video_output/glide/glide.c b/modules/video_output/glide/glide.c
new file mode 100644 (file)
index 0000000..cc484c9
--- /dev/null
@@ -0,0 +1,325 @@
+/*****************************************************************************
+ * 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();
+}
+
diff --git a/modules/video_output/mga/.cvsignore b/modules/video_output/mga/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/mga/Makefile b/modules/video_output/mga/Makefile
new file mode 100644 (file)
index 0000000..5f2c872
--- /dev/null
@@ -0,0 +1,2 @@
+mga_SOURCES = mga.c
+xmga_SOURCES = xmga.c
diff --git a/modules/video_output/mga/mga.c b/modules/video_output/mga/mga.c
new file mode 100644 (file)
index 0000000..82114c1
--- /dev/null
@@ -0,0 +1,343 @@
+/*****************************************************************************
+ * 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;
+}
+
diff --git a/modules/video_output/mga/xmga.c b/modules/video_output/mga/xmga.c
new file mode 100644 (file)
index 0000000..adac832
--- /dev/null
@@ -0,0 +1,1187 @@
+/*****************************************************************************
+ * 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;
+    }
+}
+
diff --git a/modules/video_output/sdl/.cvsignore b/modules/video_output/sdl/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/sdl/Makefile b/modules/video_output/sdl/Makefile
new file mode 100644 (file)
index 0000000..0a57b49
--- /dev/null
@@ -0,0 +1 @@
+sdl_SOURCES = sdl.c vout.c aout.c
diff --git a/modules/video_output/sdl/aout.c b/modules/video_output/sdl/aout.c
new file mode 100644 (file)
index 0000000..0c6f152
--- /dev/null
@@ -0,0 +1,280 @@
+/*****************************************************************************
+ * 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 );
+    }
+}
+
diff --git a/modules/video_output/sdl/sdl.c b/modules/video_output/sdl/sdl.c
new file mode 100644 (file)
index 0000000..fcecfb9
--- /dev/null
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/video_output/sdl/vout.c b/modules/video_output/sdl/vout.c
new file mode 100644 (file)
index 0000000..06d7fb4
--- /dev/null
@@ -0,0 +1,862 @@
+/*****************************************************************************
+ * 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" );
+    }
+}
+
diff --git a/modules/video_output/x11/.cvsignore b/modules/video_output/x11/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/video_output/x11/Makefile b/modules/video_output/x11/Makefile
new file mode 100644 (file)
index 0000000..a2e53c0
--- /dev/null
@@ -0,0 +1,2 @@
+x11_SOURCES = x11.c xcommon.c
+xvideo_SOURCES = xvideo.c xcommon.c
diff --git a/modules/video_output/x11/x11.c b/modules/video_output/x11/x11.c
new file mode 100644 (file)
index 0000000..044a312
--- /dev/null
@@ -0,0 +1,78 @@
+/*****************************************************************************
+ * 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();
+
diff --git a/modules/video_output/x11/xcommon.c b/modules/video_output/x11/xcommon.c
new file mode 100644 (file)
index 0000000..5bcee54
--- /dev/null
@@ -0,0 +1,2014 @@
+/*****************************************************************************
+ * 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
diff --git a/modules/video_output/x11/xcommon.h b/modules/video_output/x11/xcommon.h
new file mode 100644 (file)
index 0000000..179958d
--- /dev/null
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/video_output/x11/xvideo.c b/modules/video_output/x11/xvideo.c
new file mode 100644 (file)
index 0000000..0e6807a
--- /dev/null
@@ -0,0 +1,132 @@
+/*****************************************************************************
+ * 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
+
diff --git a/modules/visualization/scope/.cvsignore b/modules/visualization/scope/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/visualization/scope/Makefile b/modules/visualization/scope/Makefile
new file mode 100644 (file)
index 0000000..12eedae
--- /dev/null
@@ -0,0 +1 @@
+scope_SOURCES = scope.c
diff --git a/modules/visualization/scope/scope.c b/modules/visualization/scope/scope.c
new file mode 100644 (file)
index 0000000..9a79c3b
--- /dev/null
@@ -0,0 +1,299 @@
+/*****************************************************************************
+ * 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 );
+}
+
diff --git a/modules/visualization/xosd/.cvsignore b/modules/visualization/xosd/.cvsignore
new file mode 100644 (file)
index 0000000..435f39e
--- /dev/null
@@ -0,0 +1,4 @@
+.dep
+*.lo
+*.o.*
+*.lo.*
diff --git a/modules/visualization/xosd/Makefile b/modules/visualization/xosd/Makefile
new file mode 100644 (file)
index 0000000..07c0542
--- /dev/null
@@ -0,0 +1 @@
+xosd_SOURCES = xosd.c
diff --git a/modules/visualization/xosd/xosd.c b/modules/visualization/xosd/xosd.c
new file mode 100644 (file)
index 0000000..572b03b
--- /dev/null
@@ -0,0 +1,200 @@
+/*****************************************************************************
+ * 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;
+    }
+
+}
+
index 79c69a694f1088ed8749b84c4cda73e7f54a76d2..686d8d56d8b301d765c151ccbae873bad6f918f0 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
 /*****************************************************************************
- * aout_spdif.c: AC3 passthrough output
+ * aout_spdif.c: A52 passthrough output
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
  *****************************************************************************
  * 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>
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Stéphane Borel <stef@via.ecp.fr>
@@ -83,8 +83,8 @@ void iec958_build_burst( u8 * p_buf, aout_fifo_t * p_fifo )
  *****************************************************************************
  * This output thread is quite specific as it can only handle one fifo now.
  *
  *****************************************************************************
  * 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 )
  * implement it.
  *****************************************************************************/
 void aout_SpdifThread( aout_thread_t * p_aout )
@@ -124,8 +124,8 @@ void aout_SpdifThread( aout_thread_t * p_aout )
                     (p_aout->fifo[i_fifo].i_start_frame + 1 )
                     & AOUT_FIFO_SIZE;
 
                     (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 );
                                        / p_aout->fifo[i_fifo].i_rate;
 
                 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
index 3cb4ac96b95576e570337b91ce16abcc0fd731cb..ca123a841b7f682595bd7f60b5aa0bea9ebcb086 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
 /*****************************************************************************
- * aout_spdif.h: AC3 passthrough output
+ * aout_spdif.h: A52 passthrough output
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
  *****************************************************************************
  * 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>
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Stéphane Borel <stef@via.ecp.fr>
index f7ddbabd5e8eec930c533e82cce4bd1978f5a75b..4312e27c69212b4b93d2cad19b53fa7e6f8e7c34 100644 (file)
@@ -2,7 +2,7 @@
  * audio_output.c : audio output thread
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
  * 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>
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Cyril Deguet <asmax@via.ecp.fr>
@@ -181,9 +181,9 @@ static int aout_SpawnThread( aout_thread_t * p_aout )
             i_bytes = 2 * p_aout->i_units * p_aout->i_channels;
             break;
 
             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;
             pf_aout_thread = aout_SpdifThread;
-            psz_format = "ac3 pass-through";
+            psz_format = "A52 pass-through";
             i_bytes = SPDIF_FRAME_SIZE;
             break;
 
             i_bytes = SPDIF_FRAME_SIZE;
             break;
 
index 329b84e9fdc0ae7b3f0681fdaf0a8e592889b978..2ac3401b3731ec41fa8e94051c81e5cf47465636 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_system.c: TS, PS and PES management
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
  * 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>
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -339,7 +339,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
 
         if( p_es->i_fourcc == VLC_FOURCC('a','5','2',' ') )
         {
 
         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;
         }
 
             i_pes_header_size += 3;
         }
 
@@ -617,7 +617,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
                 p_es->i_fourcc = VLC_FOURCC('m','p','g','a');
                 p_es->i_cat = AUDIO_ES;
                 break;
                 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;
                 p_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
                 p_es->i_cat = AUDIO_ES;
                 break;
@@ -842,7 +842,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
                     }
                     else if( (i_id & 0xF0FF) == 0x80BD )
                     {
                     }
                     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
                         p_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
                         p_es->i_cat = AUDIO_ES;
 #ifdef AUTO_SPAWN
@@ -854,7 +854,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
                         switch( config_GetInt( p_input, "audio-type" ) )
                         {
                         case -1:
                         switch( config_GetInt( p_input, "audio-type" ) )
                         {
                         case -1:
-                        case REQUESTED_AC3:
+                        case REQUESTED_A52:
                             input_SelectES( p_input, p_es );
                         }
 #endif
                             input_SelectES( p_input, p_es );
                         }
 #endif
index 4b7ba85d50b3f1ff1ac59decbab19abb05453944..bae56bc089ae9d46cf7b65ddffb7e82b4f5dbf19 100644 (file)
@@ -2,7 +2,7 @@
  * libvlc.h: main libvlc header
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
  * 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>
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -89,8 +89,8 @@
     "4 ->  8 bits signed\n"                         \
     "5 -> 16 bits unsigned little endian\n"         \
     "6 -> 16 bits unsigned big endian\n"            \
     "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 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 " \
 #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_( \
 
 #define MMX_TEXT N_("enable CPU MMX support")
 #define MMX_LONGTEXT N_( \
index 41a6f29bc22540485f06a3812aed5c2d9743c388..fd08b1056dedb6224a81967559209649d2012eb8 100644 (file)
@@ -2,7 +2,7 @@
  * modules.c : Builtin and plugin modules management functions
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
  * 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>
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
@@ -569,7 +569,7 @@ void __module_Unneed( vlc_object_t * p_this, module_t * p_module )
 static void AllocateAllPlugins( vlc_object_t *p_this )
 {
     /* Yes, there are two NULLs because we replace one with "plugin-path". */
 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;
 
     char **         ppsz_path = path;
     char *          psz_fullpath;