changeset 19271:64d82a45a05d

introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author ben
date Mon, 31 Jul 2006 17:39:17 +0000
parents 7d39b911f0bd
children e53b30cd047f
files Copyright Gui/mplayer/common.c Gui/mplayer/gtk/fs.c Gui/mplayer/gtk/menu.c Gui/mplayer/mw.c Gui/mplayer/pb.c Gui/mplayer/play.c Gui/win32/dialogs.c Gui/win32/gui.c Gui/win32/interface.c Makefile TOOLS/Makefile TOOLS/netstream/Makefile TOOLS/netstream/netstream.c asxparser.c cfg-common.h libmenu/menu.c libmenu/menu_dvbin.c libmpcodecs/Makefile libmpdemux/Makefile libmpdemux/ai_alsa.c libmpdemux/ai_alsa1x.c libmpdemux/ai_oss.c libmpdemux/asf_mmst_streaming.c libmpdemux/asf_streaming.c libmpdemux/audio_in.c libmpdemux/audio_in.h libmpdemux/cache2.c libmpdemux/cdd.h libmpdemux/cdda.c libmpdemux/cddb.c libmpdemux/cdinfo.c libmpdemux/cookies.c libmpdemux/cookies.h libmpdemux/cue_read.c libmpdemux/cue_read.h libmpdemux/dvb_tune.c libmpdemux/dvbin.c libmpdemux/dvbin.h libmpdemux/dvdnav_stream.c libmpdemux/dvdnav_stream.h libmpdemux/freesdp/common.c libmpdemux/freesdp/common.h libmpdemux/freesdp/errorlist.c libmpdemux/freesdp/parser.c libmpdemux/freesdp/parser.h libmpdemux/freesdp/parserpriv.h libmpdemux/freesdp/priv.h libmpdemux/frequencies.c libmpdemux/frequencies.h libmpdemux/http.c libmpdemux/http.h libmpdemux/librtsp/rtsp.c libmpdemux/librtsp/rtsp.h libmpdemux/librtsp/rtsp_rtp.c libmpdemux/librtsp/rtsp_rtp.h libmpdemux/librtsp/rtsp_session.c libmpdemux/librtsp/rtsp_session.h libmpdemux/mf.c libmpdemux/mf.h libmpdemux/netstream.h libmpdemux/network.c libmpdemux/network.h libmpdemux/open.c libmpdemux/pnm.c libmpdemux/realrtsp/asmrp.c libmpdemux/realrtsp/asmrp.h libmpdemux/realrtsp/real.c libmpdemux/realrtsp/real.h libmpdemux/realrtsp/rmff.c libmpdemux/realrtsp/rmff.h libmpdemux/realrtsp/sdpplin.c libmpdemux/realrtsp/sdpplin.h libmpdemux/realrtsp/xbuffer.c libmpdemux/realrtsp/xbuffer.h libmpdemux/rtp.c libmpdemux/rtp.h libmpdemux/stream.c libmpdemux/stream.h libmpdemux/stream_dvd.c libmpdemux/stream_dvd.h libmpdemux/stream_file.c libmpdemux/stream_ftp.c libmpdemux/stream_livedotcom.c libmpdemux/stream_netstream.c libmpdemux/stream_null.c libmpdemux/stream_pvr.c libmpdemux/stream_rtsp.c libmpdemux/stream_smb.c libmpdemux/stream_vcd.c libmpdemux/stream_vstream.c libmpdemux/tv.c libmpdemux/tv.h libmpdemux/tvi_bsdbt848.c libmpdemux/tvi_def.h libmpdemux/tvi_dummy.c libmpdemux/tvi_v4l.c libmpdemux/tvi_v4l2.c libmpdemux/url.c libmpdemux/url.h libmpdemux/vcd_read.h libmpdemux/vcd_read_darwin.h libmpdemux/vcd_read_fbsd.h libmpdemux/vcd_read_nbsd.h m_option.c mencoder.c mplayer.c osdep/macosx_finder_args.c playtreeparser.c stream/Makefile stream/ai_alsa.c stream/ai_alsa1x.c stream/ai_oss.c stream/asf_mmst_streaming.c stream/asf_streaming.c stream/audio_in.c stream/audio_in.h stream/cache2.c stream/cdd.h stream/cdda.c stream/cddb.c stream/cdinfo.c stream/cookies.c stream/cookies.h stream/cue_read.c stream/cue_read.h stream/dvb_tune.c stream/dvbin.c stream/dvbin.h stream/dvdnav_stream.c stream/dvdnav_stream.h stream/freesdp/common.c stream/freesdp/common.h stream/freesdp/errorlist.c stream/freesdp/parser.c stream/freesdp/parser.h stream/freesdp/parserpriv.h stream/freesdp/priv.h stream/frequencies.c stream/frequencies.h stream/http.c stream/http.h stream/librtsp/rtsp.c stream/librtsp/rtsp.h stream/librtsp/rtsp_rtp.c stream/librtsp/rtsp_rtp.h stream/librtsp/rtsp_session.c stream/librtsp/rtsp_session.h stream/mf.c stream/mf.h stream/netstream.h stream/network.c stream/network.h stream/open.c stream/pnm.c stream/realrtsp/asmrp.c stream/realrtsp/asmrp.h stream/realrtsp/real.c stream/realrtsp/real.h stream/realrtsp/rmff.c stream/realrtsp/rmff.h stream/realrtsp/sdpplin.c stream/realrtsp/sdpplin.h stream/realrtsp/xbuffer.c stream/realrtsp/xbuffer.h stream/rtp.c stream/rtp.h stream/stream.c stream/stream.h stream/stream_dvd.c stream/stream_dvd.h stream/stream_file.c stream/stream_ftp.c stream/stream_livedotcom.c stream/stream_netstream.c stream/stream_null.c stream/stream_pvr.c stream/stream_rtsp.c stream/stream_smb.c stream/stream_vcd.c stream/stream_vstream.c stream/tv.c stream/tv.h stream/tvi_bsdbt848.c stream/tvi_def.h stream/tvi_dummy.c stream/tvi_v4l.c stream/tvi_v4l2.c stream/url.c stream/url.h stream/vcd_read.h stream/vcd_read_darwin.h stream/vcd_read_fbsd.h stream/vcd_read_nbsd.h subreader.c
diffstat 195 files changed, 32369 insertions(+), 32315 deletions(-) [+]
line wrap: on
line diff
--- a/Copyright	Mon Jul 31 12:35:04 2006 +0000
+++ b/Copyright	Mon Jul 31 17:39:17 2006 +0000
@@ -71,13 +71,13 @@
 Name:       dvbstream
 Version:    0.4.3-pre3 (cvs checkout)
 Homepage:   http://www.linuxstb.org/dvbstream/
-Directory:  libmpdemux
+Directory:  stream
 License:    GNU General Public License
 
 Name:       realrtsp
 Version:    xine CVS 2003/04/17 + patches
 Homepage:   http://www.xinehq.de
-Directory:  libmpdemux/realrtsp/
+Directory:  stream/realrtsp/
 License:    GNU General Public License
 
 Name:       id3edit
@@ -107,5 +107,5 @@
 Name:       FreeSDP
 Version:    0.4.1
 Homepage:   https://savannah.nongnu.org/projects/freesdp/
-Directory:  libmpdemux/freesdp/
+Directory:  stream/freesdp/
 License:    GNU General Public License
--- a/Gui/mplayer/common.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/mplayer/common.c	Mon Jul 31 17:39:17 2006 +0000
@@ -17,7 +17,7 @@
 #include "../libvo/x11_common.h"
 #include "../libvo/fastmemcpy.h"
 
-#include "../libmpdemux/stream.h"
+#include "../stream/stream.h"
 #include "../mixer.h"
 #include "../libvo/sub.h"
 #include "../mplayer.h"
--- a/Gui/mplayer/gtk/fs.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/mplayer/gtk/fs.c	Mon Jul 31 17:39:17 2006 +0000
@@ -16,7 +16,7 @@
 #include "../interface.h"
 #include "../../config.h"
 #include "../../help_mp.h"
-#include "../../libmpdemux/stream.h"
+#include "../../stream/stream.h"
 
 #include "../widgets.h"
 #include "fs.h"
--- a/Gui/mplayer/gtk/menu.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/mplayer/gtk/menu.c	Mon Jul 31 17:39:17 2006 +0000
@@ -14,7 +14,7 @@
 #include "../widgets.h"
 #include "app.h"
 
-#include "../../libmpdemux/stream.h"
+#include "../../stream/stream.h"
 #include "../../libmpdemux/demuxer.h"
 
 #include "../pixmaps/ab.xpm"
--- a/Gui/mplayer/mw.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/mplayer/mw.c	Mon Jul 31 17:39:17 2006 +0000
@@ -17,7 +17,7 @@
 #include "../libvo/x11_common.h"
 #include "../libvo/fastmemcpy.h"
 
-#include "../libmpdemux/stream.h"
+#include "../stream/stream.h"
 #include "../mixer.h"
 #include "../libvo/sub.h"
 #include "../mplayer.h"
--- a/Gui/mplayer/pb.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/mplayer/pb.c	Mon Jul 31 17:39:17 2006 +0000
@@ -17,7 +17,7 @@
 #include "../libvo/x11_common.h"
 #include "../libvo/fastmemcpy.h"
 
-#include "../libmpdemux/stream.h"
+#include "../stream/stream.h"
 #include "../mixer.h"
 #include "../libvo/sub.h"
 #include "../mplayer.h"
--- a/Gui/mplayer/play.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/mplayer/play.c	Mon Jul 31 17:39:17 2006 +0000
@@ -28,7 +28,7 @@
 #include "skin/skin.h"
 #include "skin/font.h"
 
-#include "libmpdemux/stream.h"
+#include "stream/stream.h"
 
 extern float rel_seek_secs;
 extern int abs_seek_pos;
--- a/Gui/win32/dialogs.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/win32/dialogs.c	Mon Jul 31 17:39:17 2006 +0000
@@ -24,7 +24,7 @@
 #include <interface.h>
 #include <mp_msg.h>
 #include <help_mp.h>
-#include <libmpdemux/stream.h>
+#include <stream/stream.h>
 #include <libmpdemux/demuxer.h>
 #include <libmpdemux/stheader.h>
 #include "gui.h"
--- a/Gui/win32/gui.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/win32/gui.c	Mon Jul 31 17:39:17 2006 +0000
@@ -34,7 +34,7 @@
 #include <input/input.h>
 #include <input/mouse.h>
 #include <osdep/keycodes.h>
-#include <libmpdemux/stream.h>
+#include <stream/stream.h>
 #include <libvo/video_out.h>
 #include <interface.h>
 #include "gui.h"
--- a/Gui/win32/interface.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/Gui/win32/interface.c	Mon Jul 31 17:39:17 2006 +0000
@@ -26,11 +26,11 @@
 #include <mp_msg.h>
 #include <help_mp.h>
 #include <codec-cfg.h>
-#include <libmpdemux/stream.h>
+#include <stream/stream.h>
 #include <libmpdemux/demuxer.h>
 #include <libmpdemux/stheader.h>
 #ifdef USE_DVDREAD
-#include <libmpdemux/stream_dvd.h>
+#include <stream/stream_dvd.h>
 #endif
 #include <input/input.h>
 #include <libvo/video_out.h>
--- a/Makefile	Mon Jul 31 12:35:04 2006 +0000
+++ b/Makefile	Mon Jul 31 17:39:17 2006 +0000
@@ -105,6 +105,7 @@
               $(W32_LIB) \
               libaf/libaf.a \
               libmpdemux/libmpdemux.a \
+              stream/stream.a \
               libswscale/libswscale.a \
               osdep/libosdep.a \
               $(DVDREAD_LIB) \
@@ -139,6 +140,7 @@
 endif
 
 PARTS = libmpdemux \
+        stream \
         libmpcodecs \
         libavutil \
         libavcodec \
@@ -195,6 +197,7 @@
 COMMON_DEPS = $(W32_DEP) \
               $(AV_DEP) \
               libmpdemux/libmpdemux.a \
+              stream/stream.a \
               libmpcodecs/libmpcodecs.a \
               libao2/libao2.a \
               osdep/libosdep.a \
@@ -274,6 +277,9 @@
 libmpdemux/libmpdemux.a:
 	$(MAKE) -C libmpdemux
 
+stream/stream.a:
+	$(MAKE) -C stream
+
 libmpcodecs/libmpcodecs.a:
 	$(MAKE) -C libmpcodecs
 
@@ -546,6 +552,7 @@
 libmpdvdkit2/libmpdvdkit.a: $(wildcard libmpdvdkit2/*.[ch])
 
 libmpdemux/libmpdemux.a: $(wildcard libmpdemux/*.[ch] libmpdemux/*/*.[ch])
+stream/stream.a: $(wildcard stream/*.[ch] stream/*/*.[ch])
 libmpcodecs/libmpcodecs.a: $(wildcard libmpcodecs/*.[ch]) $(wildcard libmpcodecs/native/*.[ch])
 libmpcodecs/libmpencoders.a: $(wildcard libmpcodecs/*.[ch])
 
--- a/TOOLS/Makefile	Mon Jul 31 12:35:04 2006 +0000
+++ b/TOOLS/Makefile	Mon Jul 31 17:39:17 2006 +0000
@@ -31,7 +31,7 @@
           ../libswscale/yuv2rgb.o ../libmpcodecs/img_format.o -lm
 
 vivodump: vivodump.c
-	$(CC) $(CFLAGS) -o $@ $< ../mp_msg.o ../libmpdemux/libmpdemux.a
+	$(CC) $(CFLAGS) -o $@ $< ../mp_msg.o ../libmpdemux/libmpdemux.a ../stream/stream.a
 
 fastmemcpybench: fastmemcpybench.c
 	$(CC) $(CFLAGS) -g $< -o fastmem-mmx  ../libvo/aclib.o -DNAME=\"mmx\"      -DHAVE_MMX
--- a/TOOLS/netstream/Makefile	Mon Jul 31 12:35:04 2006 +0000
+++ b/TOOLS/netstream/Makefile	Mon Jul 31 17:39:17 2006 +0000
@@ -19,6 +19,7 @@
 # FIXME: linking is a mess that should be fixed properly some day
 # it does not work with either GUI, live.com or libavformat enabled
 DEPS = $(MPROOT)/libmpdemux/libmpdemux.a \
+	$(MPROOT)/stream/stream.a \
 	$(MPROOT)/libmpdvdkit2/libmpdvdkit.a \
 	$(MPROOT)/libmpcodecs/native/minilzo.o \
 	$(MPROOT)/libvo/aclib.o \
@@ -45,7 +46,7 @@
 DEPS += $(MPROOT)/osdep/glob-win.o $(WIN32_LIB) -lwsock32
 endif
 
-netstream: $(MPROOT)/libmpdemux/libmpdemux.a netstream.o
+netstream: $(MPROOT)/libmpdemux/libmpdemux.a $(MPROOT)/libmpdemux/stream.a netstream.o
 
 	$(CC) $(CFLAGS) netstream.o -o netstream $(DEPS)
 
--- a/TOOLS/netstream/netstream.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/TOOLS/netstream/netstream.c	Mon Jul 31 17:39:17 2006 +0000
@@ -41,13 +41,13 @@
 #include <ws2tcpip.h>
 #endif
 
-#include <libmpdemux/stream.h>
+#include <stream/stream.h>
 #include <libmpdemux/demuxer.h>
 #include <mp_msg.h>
 #include <bswap.h>
 
 /// Netstream packets def and some helpers
-#include <libmpdemux/netstream.h>
+#include <stream/netstream.h>
 
 
 //Set some standard variables
--- a/asxparser.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/asxparser.c	Mon Jul 31 17:39:17 2006 +0000
@@ -8,7 +8,7 @@
 
 #include "playtree.h"
 #include "playtreeparser.h"
-#include "libmpdemux/stream.h"
+#include "stream/stream.h"
 #include "libmpdemux/demuxer.h"
 #include "asxparser.h"
 #include "mp_msg.h"
--- a/cfg-common.h	Mon Jul 31 12:35:04 2006 +0000
+++ b/cfg-common.h	Mon Jul 31 17:39:17 2006 +0000
@@ -366,7 +366,7 @@
 extern int ts_keep_broken;
 extern off_t ts_probe;
 
-#include "libmpdemux/tv.h"
+#include "stream/tv.h"
 
 extern char* edl_filename;
 extern char* edl_output_filename;
@@ -444,7 +444,7 @@
 #endif
 
 #ifdef HAS_DVBIN_SUPPORT
-#include "libmpdemux/dvbin.h"
+#include "stream/dvbin.h"
 extern m_config_t dvbin_opts_conf[];
 #endif
 
--- a/libmenu/menu.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/libmenu/menu.c	Mon Jul 31 17:39:17 2006 +0000
@@ -13,7 +13,7 @@
 #include "libvo/font_load.h"
 #include "osdep/keycodes.h"
 #include "asxparser.h"
-#include "libmpdemux/stream.h"
+#include "stream/stream.h"
 
 #include "img_format.h"
 #include "mp_image.h"
--- a/libmenu/menu_dvbin.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/libmenu/menu_dvbin.c	Mon Jul 31 17:39:17 2006 +0000
@@ -24,7 +24,7 @@
 #include "input/input.h"
 #include "osdep/keycodes.h"
 
-#include "libmpdemux/dvbin.h"
+#include "stream/dvbin.h"
 
 
 
--- a/libmpcodecs/Makefile	Mon Jul 31 12:35:04 2006 +0000
+++ b/libmpcodecs/Makefile	Mon Jul 31 17:39:17 2006 +0000
@@ -321,6 +321,7 @@
           -I. -I.. \
           -Inative \
           -I../libmpdemux \
+          -I../stream \
           -I../loader \
           $(LIBAV_INC) \
           -D_GNU_SOURCE \
--- a/libmpdemux/Makefile	Mon Jul 31 12:35:04 2006 +0000
+++ b/libmpdemux/Makefile	Mon Jul 31 17:39:17 2006 +0000
@@ -12,89 +12,15 @@
 
 # Core
 SRCS += extension.c \
-        mf.c \
-        open.c \
-        url.c \
         video.c \
 
-ifeq ($(STREAM_CACHE),yes)
-SRCS += cache2.c
-endif
-
 # Miscellaneous
-SRCS += cdinfo.c \
-        cue_read.c \
-        parse_es.c \
+SRCS += parse_es.c \
         parse_mp4.c \
         mpeg_packetizer.c \
         yuv4mpeg.c \
         yuv4mpeg_ratio.c \
 
-ifeq ($(CDDA),yes)
-SRCS += cdda.c
-  ifeq ($(MPLAYER_NETWORK),yes)
-  SRCS += cddb.c
-  endif
-endif
-
-# Stream readers/writers
-SRCS += stream.c \
-        stream_file.c \
-        stream_null.c \
-
-ifeq ($(HAVE_DVD),yes)
-SRCS += stream_dvd.c
-endif
-ifeq ($(DVDNAV),yes)
-SRCS += dvdnav_stream.c
-endif
-ifeq ($(VCD),yes)
-SRCS += stream_vcd.c
-endif
-ifeq ($(FTP),yes)
-SRCS += stream_ftp.c
-endif
-ifeq ($(LIBSMBCLIENT),yes)
-SRCS += stream_smb.c
-endif
-ifeq ($(MPLAYER_NETWORK),yes)
-  SRCS += stream_netstream.c
-  ifeq ($(STREAMING_LIVE555),yes)
-  SRCS += stream_livedotcom.c
-  endif
-endif
-ifeq ($(VSTREAM),yes)
-SRCS += stream_vstream.c
-endif
-
-# TV in
-ifeq ($(TV),yes)
-SRCS += tv.c frequencies.c tvi_dummy.c
-  ifeq ($(TV_BSDBT848),yes)
-  SRCS += tvi_bsdbt848.c
-  endif
-  ifeq ($(TV_V4L2),yes)
-  SRCS += tvi_v4l2.c audio_in.c
-    ifeq ($(PVR),yes)
-    SRCS += stream_pvr.c
-    endif
-  endif
-  ifeq ($(TV_V4L1),yes)
-  SRCS += tvi_v4l.c audio_in.c
-  endif
-  ifeq ($(TV_V4L),yes)
-    ifeq ($(ALSA1X),yes)
-     SRCS += ai_alsa1x.c
-    endif
-    ifeq ($(ALSA9),yes)
-     SRCS += ai_alsa.c
-    endif
-    ifeq ($(OSS),yes)
-     SRCS += ai_oss.c
-    endif
-  endif
-endif
-
 # Demuxers
 SRCS += demuxer.c \
         demux_aac.c \
@@ -166,48 +92,18 @@
 MUXERS += muxer_lavf.c
 endif
 
-ifeq ($(MPLAYER_NETWORK),yes)
-SRCS += asf_streaming.c \
-        http.c \
-        network.c \
-        cookies.c \
-        asf_mmst_streaming.c \
-        pnm.c \
-        rtp.c \
-        stream_rtsp.c \
-
-SRCS += realrtsp/asmrp.c \
-        realrtsp/real.c \
-        realrtsp/rmff.c \
-        realrtsp/sdpplin.c \
-        realrtsp/xbuffer.c \
-
-SRCS += librtsp/rtsp.c \
-        librtsp/rtsp_rtp.c \
-        librtsp/rtsp_session.c \
-
-SRCS += freesdp/common.c \
-        freesdp/errorlist.c \
-        freesdp/parser.c \
+ifeq ($(MENCODER),yes)
+SRCS += $(MUXERS)
+endif
 
 ifeq ($(STREAMING_LIVE555),yes)
 CPLUSPLUSSRCS = demux_rtp.cpp demux_rtp_codec.cpp
 CPLUSPLUSINCLUDE = $(LIVE_INCLUDES)
 endif
-endif
-
-ifeq ($(DVBIN),yes)
-SRCS += dvbin.c
-SRCS += dvb_tune.c
-endif
-
-ifeq ($(MENCODER),yes)
-SRCS += $(MUXERS)
-endif
 
 OBJS	= $(SRCS:.c=.o)
 OBJS   += $(CPLUSPLUSSRCS:.cpp=.o)
-INCLUDE = -I.. -I../loader $(LIBAV_INC)
+INCLUDE = -I.. -I../stream -I../loader $(LIBAV_INC)
 CFLAGS  = $(OPTFLAGS) $(INCLUDE) $(XMMS_CFLAGS)
 CPLUSPLUSFLAGS  = $(CFLAGS) $(CPLUSPLUSINCLUDE) -D__STDC_LIMIT_MACROS
 CPLUSPLUS = $(CC)
@@ -229,16 +125,14 @@
 
 test:	$(LIBNAME) test.c
 	$(CC) $(CFLAGS) test.c ../mp_msg.c ../osdep/shmem.c -o test \
-	  ./libmpdemux.a ../libmpdvdkit2/libmpdvdkit.a ../libvo/aclib.o \
+	  ./libmpdemux.a ../stream/stream.a \
+	  ../libmpdvdkit2/libmpdvdkit.a ../libvo/aclib.o \
 	  ../libmpcodecs/img_format.o ../libao2/afmt.o ../sub_cc.o \
 	  ../m_option.o ../subreader.o \
 	  $(ALSA_LIB) $(VORBIS_LIB) $(CDPARANOIA_LIB) -lz -lpthread
 
 clean:
-	rm -f *.o *.a *~ \
-	realrtsp/*.o realrtsp/*.a realrtsp/*~ \
-	librtsp/*.o librtsp/*.a librtsp/*~ \
-	freesdp/*.o freesdp/*.a freesdp/*~
+	rm -f *.o *.a *~
 
 distclean: clean
 	rm -f .depend test
--- a/libmpdemux/ai_alsa.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-
-#include "config.h"
-
-#include <alsa/asoundlib.h>
-#include "audio_in.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-int ai_alsa_setup(audio_in_t *ai)
-{
-    snd_pcm_hw_params_t *params;
-    snd_pcm_sw_params_t *swparams;
-    int buffer_size;
-    int err;
-    unsigned int rate;
-
-    snd_pcm_hw_params_alloca(&params);
-    snd_pcm_sw_params_alloca(&swparams);
-
-    err = snd_pcm_hw_params_any(ai->alsa.handle, params);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig);
-	return -1;
-    }
-    err = snd_pcm_hw_params_set_access(ai->alsa.handle, params,
-				       SND_PCM_ACCESS_RW_INTERLEAVED);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableAccessType);
-	return -1;
-    }
-    err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt);
-	return -1;
-    }
-    err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels);
-    if (err < 0) {
-	ai->channels = snd_pcm_hw_params_get_channels(params);
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableChanCount,
-	       ai->channels);
-    } else {
-	ai->channels = ai->req_channels;
-    }
-
-    err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, ai->req_samplerate, 0);
-    assert(err >= 0);
-    rate = err;
-    ai->samplerate = rate;
-
-    ai->alsa.buffer_time = 1000000;
-    ai->alsa.buffer_time = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params,
-							       ai->alsa.buffer_time, 0);
-    assert(ai->alsa.buffer_time >= 0);
-    ai->alsa.period_time = ai->alsa.buffer_time / 4;
-    ai->alsa.period_time = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params,
-							       ai->alsa.period_time, 0);
-    assert(ai->alsa.period_time >= 0);
-    err = snd_pcm_hw_params(ai->alsa.handle, params);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams);
-	snd_pcm_hw_params_dump(params, ai->alsa.log);
-	return -1;
-    }
-    ai->alsa.chunk_size = snd_pcm_hw_params_get_period_size(params, 0);
-    buffer_size = snd_pcm_hw_params_get_buffer_size(params);
-    if (ai->alsa.chunk_size == buffer_size) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize, ai->alsa.chunk_size, (long)buffer_size);
-	return -1;
-    }
-    snd_pcm_sw_params_current(ai->alsa.handle, swparams);
-    err = snd_pcm_sw_params_set_sleep_min(ai->alsa.handle, swparams,0);
-    assert(err >= 0);
-    err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size);
-    assert(err >= 0);
-
-    err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0);
-    assert(err >= 0);
-    err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size);
-    assert(err >= 0);
-
-    assert(err >= 0);
-    if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams);
-	snd_pcm_sw_params_dump(swparams, ai->alsa.log);
-	return -1;
-    }
-
-    if (mp_msg_test(MSGT_TV, MSGL_V)) {
-	snd_pcm_dump(ai->alsa.handle, ai->alsa.log);
-    }
-
-    ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
-    ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels;
-    ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8;
-    ai->samplesize = ai->alsa.bits_per_sample;
-    ai->bytes_per_sample = ai->alsa.bits_per_sample/8;
-
-    return 0;
-}
-
-int ai_alsa_init(audio_in_t *ai)
-{
-    int err;
-    
-    err = snd_pcm_open(&ai->alsa.handle, ai->alsa.device, SND_PCM_STREAM_CAPTURE, 0);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_ErrorOpeningAudio, snd_strerror(err));
-	return -1;
-    }
-    
-    err = snd_output_stdio_attach(&ai->alsa.log, stderr, 0);
-    
-    if (err < 0) {
-	return -1;
-    }
-    
-    err = ai_alsa_setup(ai);
-
-    return err;
-}
-
-#ifndef timersub
-#define	timersub(a, b, result) \
-do { \
-	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
-	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
-	if ((result)->tv_usec < 0) { \
-		--(result)->tv_sec; \
-		(result)->tv_usec += 1000000; \
-	} \
-} while (0)
-#endif
-
-int ai_alsa_xrun(audio_in_t *ai)
-{
-    snd_pcm_status_t *status;
-    int res;
-	
-    snd_pcm_status_alloca(&status);
-    if ((res = snd_pcm_status(ai->alsa.handle, status))<0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatusError, snd_strerror(res));
-	return -1;
-    }
-    if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
-	struct timeval now, diff, tstamp;
-	gettimeofday(&now, 0);
-	snd_pcm_status_get_trigger_tstamp(status, &tstamp);
-	timersub(&now, &tstamp, &diff);
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUN,
-	       diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
-	if (mp_msg_test(MSGT_TV, MSGL_V)) {
-	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatus);
-	    snd_pcm_status_dump(status, ai->alsa.log);
-	}
-	if ((res = snd_pcm_prepare(ai->alsa.handle))<0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError, snd_strerror(res));
-	    return -1;
-	}
-	return 0;		/* ok, data should be accepted again */
-    }
-    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError);
-    return -1;
-}
--- a/libmpdemux/ai_alsa1x.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-
-#include "config.h"
-
-#include <alsa/asoundlib.h>
-#include "audio_in.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-int ai_alsa_setup(audio_in_t *ai)
-{
-    snd_pcm_hw_params_t *params;
-    snd_pcm_sw_params_t *swparams;
-    snd_pcm_uframes_t buffer_size, period_size;
-    int err;
-    int dir;
-    unsigned int rate;
-
-    snd_pcm_hw_params_alloca(&params);
-    snd_pcm_sw_params_alloca(&swparams);
-
-    err = snd_pcm_hw_params_any(ai->alsa.handle, params);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig);
-	return -1;
-    }
-
-    err = snd_pcm_hw_params_set_access(ai->alsa.handle, params,
-				       SND_PCM_ACCESS_RW_INTERLEAVED);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableAccessType);
-	return -1;
-    }
-
-    err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt);
-	return -1;
-    }
-
-    err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels);
-    if (err < 0) {
-	snd_pcm_hw_params_get_channels(params, &ai->channels);
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableChanCount,
-	       ai->channels);
-    } else {
-	ai->channels = ai->req_channels;
-    }
-
-    dir = 0;
-    rate = ai->req_samplerate;
-    err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, &rate, &dir);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetSamplerate);
-    }
-    ai->samplerate = rate;
-
-    dir = 0;
-    ai->alsa.buffer_time = 1000000;
-    err = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params,
-						 &ai->alsa.buffer_time, &dir);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetBufferTime);
-    }
-
-    dir = 0;
-    ai->alsa.period_time = ai->alsa.buffer_time / 4;
-    err = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params,
-						 &ai->alsa.period_time, &dir);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetPeriodTime);
-    }
-
-    err = snd_pcm_hw_params(ai->alsa.handle, params);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams, snd_strerror(err));
-	snd_pcm_hw_params_dump(params, ai->alsa.log);
-	return -1;
-    }
-
-    dir = -1;
-    snd_pcm_hw_params_get_period_size(params, &period_size, &dir);
-    snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
-    ai->alsa.chunk_size = period_size;
-    if (period_size == buffer_size) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize, ai->alsa.chunk_size, (long)buffer_size);
-	return -1;
-    }
-
-    snd_pcm_sw_params_current(ai->alsa.handle, swparams);
-    err = snd_pcm_sw_params_set_sleep_min(ai->alsa.handle, swparams,0);
-    assert(err >= 0);
-    err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size);
-    assert(err >= 0);
-
-    err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0);
-    assert(err >= 0);
-    err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size);
-    assert(err >= 0);
-
-    assert(err >= 0);
-    if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams);
-	snd_pcm_sw_params_dump(swparams, ai->alsa.log);
-	return -1;
-    }
-
-    if (mp_msg_test(MSGT_TV, MSGL_V)) {
-	snd_pcm_dump(ai->alsa.handle, ai->alsa.log);
-    }
-
-    ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
-    ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels;
-    ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8;
-    ai->samplesize = ai->alsa.bits_per_sample;
-    ai->bytes_per_sample = ai->alsa.bits_per_sample/8;
-
-    return 0;
-}
-
-int ai_alsa_init(audio_in_t *ai)
-{
-    int err;
-    
-    err = snd_pcm_open(&ai->alsa.handle, ai->alsa.device, SND_PCM_STREAM_CAPTURE, 0);
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_ErrorOpeningAudio, snd_strerror(err));
-	return -1;
-    }
-    
-    err = snd_output_stdio_attach(&ai->alsa.log, stderr, 0);
-    
-    if (err < 0) {
-	return -1;
-    }
-    
-    err = ai_alsa_setup(ai);
-
-    return err;
-}
-
-#ifndef timersub
-#define	timersub(a, b, result) \
-do { \
-	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
-	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
-	if ((result)->tv_usec < 0) { \
-		--(result)->tv_sec; \
-		(result)->tv_usec += 1000000; \
-	} \
-} while (0)
-#endif
-
-int ai_alsa_xrun(audio_in_t *ai)
-{
-    snd_pcm_status_t *status;
-    int res;
-	
-    snd_pcm_status_alloca(&status);
-    if ((res = snd_pcm_status(ai->alsa.handle, status))<0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatusError, snd_strerror(res));
-	return -1;
-    }
-    if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
-	struct timeval now, diff, tstamp;
-	gettimeofday(&now, 0);
-	snd_pcm_status_get_trigger_tstamp(status, &tstamp);
-	timersub(&now, &tstamp, &diff);
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUN,
-	       diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
-	if (mp_msg_test(MSGT_TV, MSGL_V)) {
-	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatus);
-	    snd_pcm_status_dump(status, ai->alsa.log);
-	}
-	if ((res = snd_pcm_prepare(ai->alsa.handle))<0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError, snd_strerror(res));
-	    return -1;
-	}
-	return 0;		/* ok, data should be accepted again */
-    }
-    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError);
-    return -1;
-}
--- a/libmpdemux/ai_oss.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "config.h"
-
-#include <string.h> /* strerror */
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#ifdef HAVE_SYS_SOUNDCARD_H
-#include <sys/soundcard.h>
-#else
-#ifdef HAVE_SOUNDCARD_H
-#include <soundcard.h>
-#else
-#include <linux/soundcard.h>
-#endif
-#endif
-
-#include "audio_in.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-int ai_oss_set_samplerate(audio_in_t *ai)
-{
-    int tmp = ai->req_samplerate;
-    if (ioctl(ai->oss.audio_fd, SNDCTL_DSP_SPEED, &tmp) == -1) return -1;
-    ai->samplerate = tmp;
-    return 0;
-}
-
-int ai_oss_set_channels(audio_in_t *ai)
-{
-    int err;
-    int ioctl_param;
-
-    if (ai->req_channels > 2)
-    {
-	ioctl_param = ai->req_channels;
-	mp_msg(MSGT_TV, MSGL_V, "ioctl dsp channels: %d\n",
-	       err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_CHANNELS, &ioctl_param));
-	if (err < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetChanCount,
-		   ai->req_channels);
-	    return -1;
-	}
-	ai->channels = ioctl_param;
-    }
-    else
-    {
-	ioctl_param = (ai->req_channels == 2);
-	mp_msg(MSGT_TV, MSGL_V, "ioctl dsp stereo: %d (req: %d)\n",
-	       err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_STEREO, &ioctl_param),
-	       ioctl_param);
-	if (err < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetStereo,
-		   ai->req_channels == 2);
-	    return -1;
-	}
-	ai->channels = ioctl_param ? 2 : 1;
-    }
-    return 0;
-}
-
-int ai_oss_init(audio_in_t *ai)
-{
-    int err;
-    int ioctl_param;
-
-    ai->oss.audio_fd = open(ai->oss.device, O_RDONLY);
-    if (ai->oss.audio_fd < 0)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2Open,
-	       ai->oss.device, strerror(errno));
-	return -1;
-    }
-	
-    ioctl_param = 0 ;
-    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp getfmt: %d\n",
-	   ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETFMTS, &ioctl_param));
-	
-    mp_msg(MSGT_TV, MSGL_V, "Supported formats: %x\n", ioctl_param);
-    if (!(ioctl_param & AFMT_S16_LE))
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_UnsupportedFmt);
-
-    ioctl_param = AFMT_S16_LE;
-    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp setfmt: %d\n",
-	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SETFMT, &ioctl_param));
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetAudioFmt);
-	return -1;
-    }
-
-    if (ai_oss_set_channels(ai) < 0) return -1;
-	
-    ioctl_param = ai->req_samplerate;
-    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp speed: %d\n",
-	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SPEED, &ioctl_param));
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetSamplerate,
-	       ai->req_samplerate);
-	return -1;
-    }
-    ai->samplerate = ioctl_param;
-
-    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp trigger: %d\n",
-	   ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETTRIGGER, &ioctl_param));
-    mp_msg(MSGT_TV, MSGL_V, "trigger: %x\n", ioctl_param);
-    ioctl_param = PCM_ENABLE_INPUT;
-    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp trigger: %d\n",
-	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SETTRIGGER, &ioctl_param));
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetTrigger,
-	       PCM_ENABLE_INPUT);
-    }
-
-    ai->blocksize = 0;
-    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp getblocksize: %d\n",
-	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETBLKSIZE, &ai->blocksize));
-    if (err < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2GetBlockSize);
-    }
-    mp_msg(MSGT_TV, MSGL_V, "blocksize: %d\n", ai->blocksize);
-
-    // correct the blocksize to a reasonable value
-    if (ai->blocksize <= 0) {
-	ai->blocksize = 4096*ai->channels*2;
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_AudioBlockSizeZero, ai->blocksize);
-    } else if (ai->blocksize < 4096*ai->channels*2) {
-	ai->blocksize *= 4096*ai->channels*2/ai->blocksize;
-	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_AudioBlockSize2Low, ai->blocksize);
-    }
-
-    ai->samplesize = 16;
-    ai->bytes_per_sample = 2;
-
-    return 0;
-}
--- a/libmpdemux/asf_mmst_streaming.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,665 +0,0 @@
-// mmst implementation taken from the xine-mms plugin made by majormms (http://geocities.com/majormms/)
-// 
-// ported to mplayer by Abhijeet Phatak <abhijeetphatak@yahoo.com>
-// date : 16 April 2002
-//
-// information about the mms protocol can be find at http://get.to/sdp
-//
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <inttypes.h>
-
-#include "config.h"
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#else
-#include <winsock2.h>
-#endif
-
-#ifndef USE_SETLOCALE
-#undef USE_ICONV
-#endif
-
-#ifdef USE_ICONV
-#include <iconv.h>
-#ifdef USE_LANGINFO
-#include <langinfo.h>
-#endif
-#endif
-
-#include "url.h"
-#include "asf.h"
-
-#include "stream.h"
-
-#include "network.h"
-
-#define BUF_SIZE 102400
-#define HDR_BUF_SIZE 8192
-#define MAX_STREAMS 20
-
-typedef struct 
-{
-  uint8_t buf[BUF_SIZE];
-  int     num_bytes;
-
-} command_t;
-
-static int seq_num;
-static int num_stream_ids;
-static int stream_ids[MAX_STREAMS];
-
-static int get_data (int s, char *buf, size_t count);
-
-static void put_32 (command_t *cmd, uint32_t value) 
-{
-  cmd->buf[cmd->num_bytes  ] = value % 256;
-  value = value >> 8;
-  cmd->buf[cmd->num_bytes+1] = value % 256 ;
-  value = value >> 8;
-  cmd->buf[cmd->num_bytes+2] = value % 256 ;
-  value = value >> 8;
-  cmd->buf[cmd->num_bytes+3] = value % 256 ;
-
-  cmd->num_bytes += 4;
-}
-
-static uint32_t get_32 (unsigned char *cmd, int offset) 
-{
-  uint32_t ret;
-
-  ret = cmd[offset] ;
-  ret |= cmd[offset+1]<<8 ;
-  ret |= cmd[offset+2]<<16 ;
-  ret |= cmd[offset+3]<<24 ;
-
-  return ret;
-}
-
-static void send_command (int s, int command, uint32_t switches, 
-			  uint32_t extra, int length,
-			  char *data) 
-{
-  command_t  cmd;
-  int        len8;
-
-  len8 = (length + 7) / 8;
-
-  cmd.num_bytes = 0;
-
-  put_32 (&cmd, 0x00000001); /* start sequence */
-  put_32 (&cmd, 0xB00BFACE); /* #-)) */
-  put_32 (&cmd, len8*8 + 32);
-  put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */
-  put_32 (&cmd, len8 + 4);
-  put_32 (&cmd, seq_num);
-  seq_num++;
-  put_32 (&cmd, 0x0);        /* unknown */
-  put_32 (&cmd, 0x0);
-  put_32 (&cmd, len8+2);
-  put_32 (&cmd, 0x00030000 | command); /* dir | command */
-  put_32 (&cmd, switches);
-  put_32 (&cmd, extra);
-
-  memcpy (&cmd.buf[48], data, length);
-  if (length & 7)
-    memset(&cmd.buf[48 + length], 0, 8 - (length & 7));
-
-  if (send (s, cmd.buf, len8*8+48, 0) != (len8*8+48)) {
-    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_WriteError);
-  }
-}
-
-#ifdef USE_ICONV
-static iconv_t url_conv;
-#endif
-
-static void string_utf16(char *dest, char *src, int len) {
-    int i;
-#ifdef USE_ICONV
-    size_t len1, len2;
-    char *ip, *op;
-
-    if (url_conv != (iconv_t)(-1))
-    {
-    memset(dest, 0, 1000);
-    len1 = len; len2 = 1000;
-    ip = src; op = dest;
-
-    iconv(url_conv, &ip, &len1, &op, &len2);
-    }
-    else
-    {
-#endif
-	if (len > 499) len = 499;
-	for (i=0; i<len; i++) {
-	    dest[i*2] = src[i];
-	    dest[i*2+1] = 0;
-        }
-	/* trailing zeroes */
-	dest[i*2] = 0;
-	dest[i*2+1] = 0;
-#ifdef USE_ICONV
-    }
-#endif
-}
-
-static void get_answer (int s) 
-{
-  char  data[BUF_SIZE];
-  int   command = 0x1b;
-
-  while (command == 0x1b) {
-    int len;
-
-    len = recv (s, data, BUF_SIZE, 0) ;
-    if (!len) {
-      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_EOFAlert);
-      return;
-    }
-
-    command = get_32 (data, 36) & 0xFFFF;
-
-    if (command == 0x1b) 
-      send_command (s, 0x1b, 0, 0, 0, data);
-  }
-}
-
-static int get_data (int s, char *buf, size_t count) 
-{
-  ssize_t  len;
-  size_t total = 0;
-
-  while (total < count) {
-
-    len = recv (s, &buf[total], count-total, 0);
-
-    if (len<=0) {
-      perror ("read error:");
-      return 0;
-    }
-
-    total += len;
-
-    if (len != 0) {
-//      mp_msg(MSGT_NETWORK,MSGL_INFO,"[%d/%d]", total, count);
-      fflush (stdout);
-    }
-
-  }
-
-  return 1;
-
-}
-
-static int get_header (int s, uint8_t *header, streaming_ctrl_t *streaming_ctrl) 
-{
-  unsigned char  pre_header[8];
-  int            header_len;
-
-  header_len = 0;
-
-  while (1) {
-    if (!get_data (s, pre_header, 8)) {
-      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_PreHeaderReadFailed);
-      return 0;
-    }
-    if (pre_header[4] == 0x02) {
-      
-      int packet_len;
-      
-      packet_len = (pre_header[7] << 8 | pre_header[6]) - 8;
-
-//      mp_msg(MSGT_NETWORK,MSGL_INFO,"asf header packet detected, len=%d\n", packet_len);
-
-      if (packet_len < 0 || packet_len > HDR_BUF_SIZE - header_len) {
-        mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_MMST_InvalidHeaderSize);
-        return 0;
-      }
-
-      if (!get_data (s, &header[header_len], packet_len)) {
-	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_HeaderDataReadFailed);
-	return 0;
-      }
-
-      header_len += packet_len;
-
-      if ( (header[header_len-1] == 1) && (header[header_len-2]==1)) {
-	
-
-     if( streaming_bufferize( streaming_ctrl, header, header_len )<0 ) {
-				return -1;
- 	 }
-
-     //	mp_msg(MSGT_NETWORK,MSGL_INFO,"get header packet finished\n");
-
-	return (header_len);
-
-      } 
-
-    } else {
-
-      int32_t packet_len;
-      int command;
-      char data[BUF_SIZE];
-
-      if (!get_data (s, (char*)&packet_len, 4)) {
-	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_packet_lenReadFailed);
-	return 0;
-      }
-      
-      packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4;
-      
-//      mp_msg(MSGT_NETWORK,MSGL_INFO,"command packet detected, len=%d\n", packet_len);
-
-      if (packet_len < 0 || packet_len > BUF_SIZE) {
-        mp_msg(MSGT_NETWORK, MSGL_FATAL,
-                MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize);
-        return 0;
-      }
-      
-      if (!get_data (s, data, packet_len)) {
-	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_CmdDataReadFailed);
-	return 0;
-      }
-      
-      command = get_32 (data, 24) & 0xFFFF;
-      
-//      mp_msg(MSGT_NETWORK,MSGL_INFO,"command: %02x\n", command);
-      
-      if (command == 0x1b) 
-	send_command (s, 0x1b, 0, 0, 0, data);
-      
-    }
-
-//    mp_msg(MSGT_NETWORK,MSGL_INFO,"get header packet succ\n");
-  }
-}
-
-static int interp_header (uint8_t *header, int header_len) 
-{
-  int i;
-  int packet_length=-1;
-
-  /*
-   * parse header
-   */
-
-  i = 30;
-  while (i<header_len) {
-    
-    uint64_t  guid_1, guid_2, length;
-
-    guid_2 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) 
-      | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24)
-      | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40)
-      | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56);
-    i += 8;
-
-    guid_1 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) 
-      | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24)
-      | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40)
-      | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56);
-    i += 8;
-    
-//    mp_msg(MSGT_NETWORK,MSGL_INFO,"guid found: %016llx%016llx\n", guid_1, guid_2);
-
-    length = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) 
-      | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24)
-      | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40)
-      | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56);
-
-    i += 8;
-
-    if ( (guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22630ULL) ) {
-      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_HeaderObject);
-    } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) {
-      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_DataObject);
-    } else if ((guid_1 == 0x6553200cc000e48eULL) && (guid_2 == 0x11cfa9478cabdca1ULL)) {
-
-      packet_length = get_32(header, i+92-24);
-
-      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_FileObjectPacketLen,
-	      packet_length, get_32(header, i+96-24));
-
-
-    } else if ((guid_1 == 0x6553200cc000e68eULL) && (guid_2 == 0x11cfa9b7b7dc0791ULL)) {
-
-      int stream_id = header[i+48] | header[i+49] << 8;
-
-      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_StreamObjectStreamID, stream_id);
-
-      if (num_stream_ids < MAX_STREAMS) {
-      stream_ids[num_stream_ids] = stream_id;
-      num_stream_ids++;
-      } else {
-        mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_2ManyStreamID);
-      }
-      
-    } else {
-#if 0
-      int b = i;
-      printf ("unknown object (guid: %016llx, %016llx, len: %lld)\n", guid_1, guid_2, length);
-      for (; b < length; b++)
-      {
-        if (isascii(header[b]) || isalpha(header[b]))
-	    printf("%c ", header[b]);
-	else
-    	    printf("%x ", header[b]);
-      }
-      printf("\n");
-#else
-      mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_MMST_UnknownObject);
-#endif
-    }
-
-//    mp_msg(MSGT_NETWORK,MSGL_INFO,"length    : %lld\n", length);
-
-    i += length-24;
-
-  }
-
-  return packet_length;
-
-}
-
-
-static int get_media_packet (int s, int padding, streaming_ctrl_t *stream_ctrl) {
-  unsigned char  pre_header[8];
-  char           data[BUF_SIZE];
-
-  if (!get_data (s, pre_header, 8)) {
-    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_PreHeaderReadFailed);
-    return 0;
-  }
-
-//  for (i=0; i<8; i++)
-//    mp_msg(MSGT_NETWORK,MSGL_INFO,"pre_header[%d] = %02x (%d)\n",
-//	    i, pre_header[i], pre_header[i]);
-
-  if (pre_header[4] == 0x04) {
-
-    int packet_len;
-
-    packet_len = (pre_header[7] << 8 | pre_header[6]) - 8;
-
-//    mp_msg(MSGT_NETWORK,MSGL_INFO,"asf media packet detected, len=%d\n", packet_len);
-
-    if (packet_len < 0 || packet_len > BUF_SIZE) {
-      mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize);
-      return 0;
-    }
-      
-    if (!get_data (s, data, packet_len)) {
-      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_MediaDataReadFailed);
-      return 0;
-    }
-
-    streaming_bufferize(stream_ctrl, data, padding);
-
-  } else {
-
-    int32_t packet_len;
-    int command;
-
-    if (!get_data (s, (char*)&packet_len, 4)) {
-      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_packet_lenReadFailed);
-      return 0;
-    }
-
-    packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4;
-
-    if (packet_len < 0 || packet_len > BUF_SIZE) {
-      mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize);
-      return 0;
-    }
-
-    if (!get_data (s, data, packet_len)) {
-      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_CmdDataReadFailed);
-      return 0;
-    }
-
-    if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b)
-	 || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) {
-
-      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_MissingSignature);
-      return -1;
-    }
-
-    command = get_32 (data, 24) & 0xFFFF;
-
-//    mp_msg(MSGT_NETWORK,MSGL_INFO,"\ncommand packet detected, len=%d  cmd=0x%X\n", packet_len, command);
-
-    if (command == 0x1b) 
-      send_command (s, 0x1b, 0, 0, 0, data);
-    else if (command == 0x1e) {
-      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_PatentedTechnologyJoke);
-      return 0;
-    }
-    else if (command == 0x21 ) {
-	// Looks like it's new in WMS9
-	// Unknown command, but ignoring it seems to work.
-	return 0;
-    }
-    else if (command != 0x05) {
-      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_UnknownCmd,command);
-      return -1;
-    }
-  }
-
-//  mp_msg(MSGT_NETWORK,MSGL_INFO,"get media packet succ\n");
-
-  return 1;
-}
-
-
-static int packet_length1;
-
-static int asf_mmst_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) 
-{
-  int len;
-  
-  while( stream_ctrl->buffer_size==0 ) {
-          // buffer is empty - fill it!
-	  int ret = get_media_packet( fd, packet_length1, stream_ctrl);
-	  if( ret<0 ) {
-		  mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_GetMediaPacketErr,strerror(errno));
-		  return -1;
-	  } else if (ret==0) //EOF?
-		  return ret;
-  }
-  
-	  len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos;
-	  if(len>size) len=size;
-	  memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len );
-	  stream_ctrl->buffer_pos += len;
-	  if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) {
-		  free( stream_ctrl->buffer );
-		  stream_ctrl->buffer = NULL;
-		  stream_ctrl->buffer_size = 0;
-		  stream_ctrl->buffer_pos = 0;
-	  }
-	  return len;
-
-}
-
-static int asf_mmst_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) 
-{
-	return -1;
-	// Shut up gcc warning
-	fd++;
-	pos++;
-	streaming_ctrl=NULL;
-}
-
-int asf_mmst_streaming_start(stream_t *stream)
-{
-  char                 str[1024];
-  char                 data[BUF_SIZE];
-  uint8_t              asf_header[HDR_BUF_SIZE];
-  int                  asf_header_len;
-  int                  len, i, packet_length;
-  char                *path, *unescpath;
-  URL_t *url1 = stream->streaming_ctrl->url;
-  int s = stream->fd;
-
-  if( s>0 ) {
-	  closesocket( stream->fd );
-	  stream->fd = -1;
-  }
-  
-  /* parse url */
-  path = strchr(url1->file,'/') + 1;
-
-  /* mmst filename are not url_escaped by MS MediaPlayer and are expected as
-   * "plain text" by the server, so need to decode it here
-   */
-  unescpath=malloc(strlen(path)+1);
-  if (!unescpath) {
-	mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-	return -1; 
-  }
-  url_unescape_string(unescpath,path);
-  path=unescpath;
-  
-
-  if( url1->port==0 ) {
-	url1->port=1755;
-  }
-  s = connect2Server( url1->hostname, url1->port, 1);
-  if( s<0 ) {
-	  free(path);
-	  return s;
-  }
-  mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_Connected);
-  
-  seq_num=0;
-
-  /*
-  * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. 
-  * This command is sent at the very start of protocol initiation. It sends local information to the serve 
-  * cmd 1 0x01 
-  * */
-
-  /* prepare for the url encoding conversion */
-#ifdef USE_ICONV
-#ifdef USE_LANGINFO
-  url_conv = iconv_open("UTF-16LE",nl_langinfo(CODESET));
-#else
-  url_conv = iconv_open("UTF-16LE", NULL);
-#endif
-#endif
-
-  snprintf (str, 1023, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", url1->hostname);
-  string_utf16 (data, str, strlen(str));
-// send_command(s, commandno ....)
-  send_command (s, 1, 0, 0x0004000b, strlen(str)*2+2, data);
-
-  len = recv (s, data, BUF_SIZE, 0) ;
-
-  /*This sends details of the local machine IP address to a Funnel system at the server. 
-  * Also, the TCP or UDP transport selection is sent.
-  *
-  * here 192.168.0.1 is local ip address TCP/UDP states the tronsport we r using
-  * and 1037 is the  local TCP or UDP socket number
-  * cmd 2 0x02
-  *  */
-
-  string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037", 24);
-  memset (data, 0, 8);
-  send_command (s, 2, 0, 0, 24*2+10, data);
-
-  len = recv (s, data, BUF_SIZE, 0) ;
-
-  /* This command sends file path (at server) and file name request to the server.
-  * 0x5 */
-
-  string_utf16 (&data[8], path, strlen(path));
-  memset (data, 0, 8);
-  send_command (s, 5, 0, 0, strlen(path)*2+10, data);
-  free(path);
-
-  get_answer (s);
-
-  /* The ASF header chunk request. Includes ?session' variable for pre header value. 
-  * After this command is sent, 
-  * the server replies with 0x11 command and then the header chunk with header data follows.
-  * 0x15 */
-
-  memset (data, 0, 40);
-  data[32] = 2;
-
-  send_command (s, 0x15, 1, 0, 40, data);
-
-  num_stream_ids = 0;
-  /* get_headers(s, asf_header);  */
-
-  asf_header_len = get_header (s, asf_header, stream->streaming_ctrl);
-//  mp_msg(MSGT_NETWORK,MSGL_INFO,"---------------------------------- asf_header %d\n",asf_header);
-  if (asf_header_len==0) return -1; //error reading header
-  packet_length = interp_header (asf_header, asf_header_len);
-
-
-  /* 
-  * This command is the media stream MBR selector. Switches are always 6 bytes in length.  
-  * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. 
-  * Where:  
-  * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. 
-  * It is not yet understood what all this means. 
-  * And the last [02] byte is probably the header ?session' value. 
-  *  
-  *  0x33 */
-
-  memset (data, 0, 40);
-
-  for (i=1; i<num_stream_ids; i++) {
-    data [ (i-1) * 6 + 2 ] = 0xFF;
-    data [ (i-1) * 6 + 3 ] = 0xFF;
-    data [ (i-1) * 6 + 4 ] = stream_ids[i];
-    data [ (i-1) * 6 + 5 ] = 0x00;
-  }
-
-  send_command (s, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data);
-
-  get_answer (s);
-
-  /* Start sending file from packet xx. 
-  * This command is also used for resume downloads or requesting a lost packet. 
-  * Also used for seeking by sending a play point value which seeks to the media time point. 
-  * Includes ?session' value in pre header and the maximum media stream time. 
-  * 0x07 */
-
-  memset (data, 0, 40);
-
-  for (i=8; i<16; i++)
-    data[i] = 0xFF;
-
-  data[20] = 0x04;
-
-  send_command (s, 0x07, 1, 0xFFFF | stream_ids[0] << 16, 24, data);
-
-  stream->fd = s;
-  stream->streaming_ctrl->streaming_read = asf_mmst_streaming_read;
-  stream->streaming_ctrl->streaming_seek = asf_mmst_streaming_seek;
-  stream->streaming_ctrl->buffering = 1;
-  stream->streaming_ctrl->status = streaming_playing_e;
-
-  packet_length1 = packet_length;
-  mp_msg(MSGT_NETWORK,MSGL_INFO,"mmst packet_length = %d\n", packet_length);
-
-#ifdef USE_ICONV
-  if (url_conv != (iconv_t)(-1))
-    iconv_close(url_conv);
-#endif
-
-  return 0;
-}
--- a/libmpdemux/asf_streaming.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,882 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#else
-#include <winsock2.h>
-#endif
-
-#include "url.h"
-#include "http.h"
-#include "asf.h"
-
-#include "stream.h"
-#include "demuxer.h"
-
-#include "network.h"
-
-#ifdef ARCH_X86
-#define	ASF_LOAD_GUID_PREFIX(guid)	(*(uint32_t *)(guid))
-#else
-#define	ASF_LOAD_GUID_PREFIX(guid)	\
-	((guid)[3] << 24 | (guid)[2] << 16 | (guid)[1] << 8 | (guid)[0])
-#endif
-
-extern int network_bandwidth;
-
-int asf_mmst_streaming_start( stream_t *stream );
-static int asf_http_streaming_start(stream_t *stream, int *demuxer_type);
-
-// We can try several protocol for asf streaming
-// * first the UDP protcol, if there is a firewall, UDP
-//   packets will not come back, so the mmsu will fail.
-// * Then we can try TCP, but if there is a proxy for
-//   internet connection, the TCP connection will not get
-//   through
-// * Then we can try HTTP.
-// 
-// Note: Using 	WMP sequence  MMSU then MMST and then HTTP.
-
-static int asf_streaming_start( stream_t *stream, int *demuxer_type) {
-    char *proto = stream->streaming_ctrl->url->protocol;
-    int fd = -1;
-    int port = stream->streaming_ctrl->url->port;
-
-    // Is protocol mms or mmsu?
-    if (!strcasecmp(proto, "mmsu") || !strcasecmp(proto, "mms"))
-    {
-		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/UDP...\n");
-		//fd = asf_mmsu_streaming_start( stream );
-		if( fd>-1 ) return fd; //mmsu support is not implemented yet - using this code
-		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/UDP failed\n");
-		if( fd==-2 ) return -1;
-	}
-
-    //Is protocol mms or mmst?
-    if (!strcasecmp(proto, "mmst") || !strcasecmp(proto, "mms"))
-    {
-		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/TCP...\n");
-		fd = asf_mmst_streaming_start( stream );
-		stream->streaming_ctrl->url->port = port;
-		if( fd>-1 ) return fd;
-		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/TCP failed\n");
-		if( fd==-2 ) return -1;
-	}
-
-    //Is protocol http, http_proxy, or mms? 
-    if (!strcasecmp(proto, "http_proxy") || !strcasecmp(proto, "http") ||
-	!strcasecmp(proto, "mms") || !strcasecmp(proto, "mmshttp"))
-    {
-		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/HTTP...\n");
-		fd = asf_http_streaming_start( stream, demuxer_type );
-		stream->streaming_ctrl->url->port = port;
-		if( fd>-1 ) return fd;
-		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/HTTP failed\n");
-		if( fd==-2 ) return -1;
-	}
-
-    //everything failed
-	return -1;
-}
-
-static int asf_streaming(ASF_stream_chunck_t *stream_chunck, int *drop_packet ) {
-/*	
-printf("ASF stream chunck size=%d\n", stream_chunck->size);
-printf("length: %d\n", length );
-printf("0x%02X\n", stream_chunck->type );
-*/
-	if( drop_packet!=NULL ) *drop_packet = 0;
-
-	if( stream_chunck->size<8 ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_StreamChunkSize2Small, stream_chunck->size);
-		return -1;
-	}
-	if( stream_chunck->size!=stream_chunck->size_confirm ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_SizeConfirmMismatch, stream_chunck->size, stream_chunck->size_confirm);
-		return -1;
-	}
-/*	
-	printf("  type: 0x%02X\n", stream_chunck->type );
-	printf("  size: %d (0x%02X)\n", stream_chunck->size, stream_chunck->size );
-	printf("  sequence_number: 0x%04X\n", stream_chunck->sequence_number );
-	printf("  unknown: 0x%02X\n", stream_chunck->unknown );
-	printf("  size_confirm: 0x%02X\n", stream_chunck->size_confirm );
-*/
-	switch(stream_chunck->type) {
-		case ASF_STREAMING_CLEAR:	// $C	Clear ASF configuration
-			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Clearing ASF stream configuration!\n");
-			if( drop_packet!=NULL ) *drop_packet = 1;
-			return stream_chunck->size;
-			break;
-		case ASF_STREAMING_DATA:	// $D	Data follows
-//			printf("=====> Data follows\n");
-			break;
-		case ASF_STREAMING_END_TRANS:	// $E	Transfer complete
-			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Transfer complete\n");
-			if( drop_packet!=NULL ) *drop_packet = 1;
-			return stream_chunck->size;
-			break;
-		case ASF_STREAMING_HEADER:	// $H	ASF header chunk follows
-			mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF header chunk follows\n");
-			break;
-		default:
-			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Unknown stream type 0x%x\n", stream_chunck->type );
-	}
-	return stream_chunck->size+4;
-}
-
-extern int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len);
-extern const char asf_file_header_guid[];
-extern const char asf_stream_header_guid[];
-extern const char asf_stream_group_guid[];
-extern int audio_id;
-extern int video_id;
-
-static void close_s(stream_t *stream) {
-	close(stream->fd);
-	stream->fd=-1;
-}
-
-static int max_idx(int s_count, int *s_rates, int bound) {
-  int i, best = -1, rate = -1;
-  for (i = 0; i < s_count; i++) {
-    if (s_rates[i] > rate && s_rates[i] <= bound) {
-      rate = s_rates[i];
-      best = i;
-    }
-  }
-  return best;
-}
-
-static int asf_streaming_parse_header(int fd, streaming_ctrl_t* streaming_ctrl) {
-  ASF_header_t asfh;
-  ASF_stream_chunck_t chunk;
-  asf_http_streaming_ctrl_t* asf_ctrl = (asf_http_streaming_ctrl_t*) streaming_ctrl->data;
-  char* buffer=NULL, *chunk_buffer=NULL;
-  int i,r,size,pos = 0;
-  int start;
-  int buffer_size = 0;
-  int chunk_size2read = 0;
-  int bw = streaming_ctrl->bandwidth;
-  int *v_rates = NULL, *a_rates = NULL;
-  int v_rate = 0, a_rate = 0, a_idx = -1, v_idx = -1;
-  
-  if(asf_ctrl == NULL) return -1;
-
-	// The ASF header can be in several network chunks. For example if the content description
-	// is big, the ASF header will be split in 2 network chunk.
-	// So we need to retrieve all the chunk before starting to parse the header.
-  do {
-	  for( r=0; r < (int)sizeof(ASF_stream_chunck_t) ; ) {
-		i = nop_streaming_read(fd,((char*)&chunk)+r,sizeof(ASF_stream_chunck_t) - r,streaming_ctrl);
-		if(i <= 0) return -1;
-		r += i;
-	  }
-	  // Endian handling of the stream chunk
-	  le2me_ASF_stream_chunck_t(&chunk);
-	  size = asf_streaming( &chunk, &r) - sizeof(ASF_stream_chunck_t);
-	  if(r) mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_ASF_WarnDropHeader);
-	  if(size < 0){
-	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader);
-		return -1;
-	  }
-	  if (chunk.type != ASF_STREAMING_HEADER) {
-	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_NoHeaderAtFirstChunk);
-	    return -1;
-	  }
-	  
-	  // audit: do not overflow buffer_size
-	  if (size > SIZE_MAX - buffer_size) return -1;
-	  buffer = (char*) malloc(size+buffer_size);
-	  if(buffer == NULL) {
-	    mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MPDEMUX_ASF_BufferMallocFailed,size+buffer_size);
-	    return -1;
-	  }
-	  if( chunk_buffer!=NULL ) {
-	  	memcpy( buffer, chunk_buffer, buffer_size );
-		free( chunk_buffer );
-	  }
-	  chunk_buffer = buffer;
-	  buffer += buffer_size;
-	  buffer_size += size;
-	  
-	  for(r = 0; r < size;) {
-	    i = nop_streaming_read(fd,buffer+r,size-r,streaming_ctrl);
-	    if(i < 0) {
-		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingNetworkStream);
-		    return -1;
-	    }
-	    r += i;
-	  }  
-
-	  if( chunk_size2read==0 ) {
-		if(size < (int)sizeof(asfh)) {
-		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunk2Small);
-		    return -1;
-		} else mp_msg(MSGT_NETWORK,MSGL_DBG2,"Got chunk\n");
-	  	memcpy(&asfh,buffer,sizeof(asfh));
-	  	le2me_ASF_header_t(&asfh);
-		chunk_size2read = asfh.objh.size;
-		mp_msg(MSGT_NETWORK,MSGL_DBG2,"Size 2 read=%d\n", chunk_size2read);
-	  }
-  } while( buffer_size<chunk_size2read);
-  buffer = chunk_buffer;
-  size = buffer_size;
-	  
-  if(asfh.cno > 256) {
-    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrSubChunkNumberInvalid);
-    return -1;
-  }
-
-  start = sizeof(asfh);
-  
-  pos = find_asf_guid(buffer, asf_file_header_guid, start, size);
-  if (pos >= 0) {
-    ASF_file_header_t *fileh = (ASF_file_header_t *) &buffer[pos];
-    pos += sizeof(ASF_file_header_t);
-    if (pos > size) goto len_err_out;
-      le2me_ASF_file_header_t(fileh);
-/*
-      if(fileh.packetsize != fileh.packetsize2) {
-	printf("Error packetsize check don't match\n");
-	return -1;
-      }
-*/
-      asf_ctrl->packet_size = fileh->max_packet_size;
-      // before playing. 
-      // preroll: time in ms to bufferize before playing
-      streaming_ctrl->prebuffer_size = (unsigned int)(((double)fileh->preroll/1000.0)*((double)fileh->max_bitrate/8.0));
-  }
-
-  pos = start;
-  while ((pos = find_asf_guid(buffer, asf_stream_header_guid, pos, size)) >= 0)
-  {
-    ASF_stream_header_t *streamh = (ASF_stream_header_t *)&buffer[pos];
-    pos += sizeof(ASF_stream_header_t);
-    if (pos > size) goto len_err_out;
-      le2me_ASF_stream_header_t(streamh);
-      switch(ASF_LOAD_GUID_PREFIX(streamh->type)) {
-      case 0xF8699E40 : // audio stream
-	if(asf_ctrl->audio_streams == NULL){
-	  asf_ctrl->audio_streams = malloc(sizeof(int));
-	  asf_ctrl->n_audio = 1;
-	} else {
-	  asf_ctrl->n_audio++;
-	  asf_ctrl->audio_streams = (int*)realloc(asf_ctrl->audio_streams,
-						     asf_ctrl->n_audio*sizeof(int));
-	}
-	asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = streamh->stream_no;
-	break;
-      case 0xBC19EFC0 : // video stream
-	if(asf_ctrl->video_streams == NULL){
-	  asf_ctrl->video_streams = malloc(sizeof(int));
-	  asf_ctrl->n_video = 1;
-	} else {
-	  asf_ctrl->n_video++;
-	  asf_ctrl->video_streams = (int*)realloc(asf_ctrl->video_streams,
-						     asf_ctrl->n_video*sizeof(int));
-	}
-	asf_ctrl->video_streams[asf_ctrl->n_video-1] = streamh->stream_no;
-	break;
-      }
-  }
-
-  // always allocate to avoid lots of ifs later
-  v_rates = calloc(asf_ctrl->n_video, sizeof(int));
-  a_rates = calloc(asf_ctrl->n_audio, sizeof(int));
-
-  pos = find_asf_guid(buffer, asf_stream_group_guid, start, size);
-  if (pos >= 0) {
-    // stream bitrate properties object
-	int stream_count;
-	char *ptr = &buffer[pos];
-	
-	mp_msg(MSGT_NETWORK, MSGL_V, "Stream bitrate properties object\n");
-		stream_count = le2me_16(*(uint16_t*)ptr);
-		ptr += sizeof(uint16_t);
-		if (ptr > &buffer[size]) goto len_err_out;
-		mp_msg(MSGT_NETWORK, MSGL_V, " stream count=[0x%x][%u]\n",
-		        stream_count, stream_count );
-		for( i=0 ; i<stream_count ; i++ ) {
-			uint32_t rate;
-			int id;
-			int j;
-			id = le2me_16(*(uint16_t*)ptr);
-			ptr += sizeof(uint16_t);
-			if (ptr > &buffer[size]) goto len_err_out;
-			memcpy(&rate, ptr, sizeof(uint32_t));// workaround unaligment bug on sparc
-			ptr += sizeof(uint32_t);
-			if (ptr > &buffer[size]) goto len_err_out;
-			rate = le2me_32(rate);
-			mp_msg(MSGT_NETWORK, MSGL_V,
-                                "  stream id=[0x%x][%u]\n", id, id);
-			mp_msg(MSGT_NETWORK, MSGL_V,
-			        "  max bitrate=[0x%x][%u]\n", rate, rate);
-			for (j = 0; j < asf_ctrl->n_video; j++) {
-			  if (id == asf_ctrl->video_streams[j]) {
-			    mp_msg(MSGT_NETWORK, MSGL_V, "  is video stream\n");
-			    v_rates[j] = rate;
-			    break;
-			  }
-			}
-			for (j = 0; j < asf_ctrl->n_audio; j++) {
-			  if (id == asf_ctrl->audio_streams[j]) {
-			    mp_msg(MSGT_NETWORK, MSGL_V, "  is audio stream\n");
-			    a_rates[j] = rate;
-			    break;
-			  }
-			}
-		}
-  }
-  free(buffer);
-
-  // automatic stream selection based on bandwidth
-  if (bw == 0) bw = INT_MAX;
-  mp_msg(MSGT_NETWORK, MSGL_V, "Max bandwidth set to %d\n", bw);
-
-  if (asf_ctrl->n_audio) {
-    // find lowest-bitrate audio stream
-    a_rate = a_rates[0];
-    a_idx = 0;
-    for (i = 0; i < asf_ctrl->n_audio; i++) {
-      if (a_rates[i] < a_rate) {
-        a_rate = a_rates[i];
-        a_idx = i;
-      }
-    }
-    if (max_idx(asf_ctrl->n_video, v_rates, bw - a_rate) < 0) {
-      // both audio and video are not possible, try video only next
-      a_idx = -1;
-      a_rate = 0;
-    }
-  }
-  // find best video stream
-  v_idx = max_idx(asf_ctrl->n_video, v_rates, bw - a_rate);
-  if (v_idx >= 0)
-    v_rate = v_rates[v_idx];
-
-  // find best audio stream
-  a_idx = max_idx(asf_ctrl->n_audio, a_rates, bw - v_rate);
-    
-  free(v_rates);
-  free(a_rates);
-
-  if (a_idx < 0 && v_idx < 0) {
-    mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_Bandwidth2SmallCannotPlay);
-    return -1;
-  }
-
-  if (audio_id > 0)
-    // a audio stream was forced
-    asf_ctrl->audio_id = audio_id;
-  else if (a_idx >= 0)
-    asf_ctrl->audio_id = asf_ctrl->audio_streams[a_idx];
-  else if (asf_ctrl->n_audio) {
-    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedAudio);
-    audio_id = -2;
-  }
-
-  if (video_id > 0)
-    // a video stream was forced
-    asf_ctrl->video_id = video_id;
-  else if (v_idx >= 0)
-    asf_ctrl->video_id = asf_ctrl->video_streams[v_idx];
-  else if (asf_ctrl->n_video) {
-    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedVideo);
-    video_id = -2;
-  }
-
-  return 1;
-
-len_err_out:
-  mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_InvalidLenInHeader);
-  if (buffer) free(buffer);
-  if (v_rates) free(v_rates);
-  if (a_rates) free(a_rates);
-  return -1;
-}
-
-static int asf_http_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) {
-  static ASF_stream_chunck_t chunk;
-  int read,chunk_size = 0;
-  static int rest = 0, drop_chunk = 0, waiting = 0;
-  asf_http_streaming_ctrl_t *asf_http_ctrl = (asf_http_streaming_ctrl_t*)streaming_ctrl->data;
-
-  while(1) {
-    if (rest == 0 && waiting == 0) {
-      read = 0;
-      while(read < (int)sizeof(ASF_stream_chunck_t)){
-	int r = nop_streaming_read( fd, ((char*)&chunk) + read, 
-				    sizeof(ASF_stream_chunck_t)-read, 
-				    streaming_ctrl );
-	if(r <= 0){
-	  if( r < 0) 
-	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingChunkHeader);
-	  return -1;
-	}
-	read += r;
-      }
-      
-      // Endian handling of the stream chunk
-      le2me_ASF_stream_chunck_t(&chunk);
-      chunk_size = asf_streaming( &chunk, &drop_chunk );
-      if(chunk_size < 0) {
-	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader);
-	return -1;
-      }
-      chunk_size -= sizeof(ASF_stream_chunck_t);
-	
-      if(chunk.type != ASF_STREAMING_HEADER && (!drop_chunk)) {
-	if (asf_http_ctrl->packet_size < chunk_size) {
-	  mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunkBiggerThanPacket);
-	  return -1;
-	}
-	waiting = asf_http_ctrl->packet_size;
-      } else {
-	waiting = chunk_size;
-      }
-
-    } else if (rest){
-      chunk_size = rest;
-      rest = 0;
-    }
-
-    read = 0;
-    if ( waiting >= chunk_size) {
-      if (chunk_size > size){
-	rest = chunk_size - size;
-	chunk_size = size;
-      }
-      while(read < chunk_size) {
-	int got = nop_streaming_read( fd,buffer+read,chunk_size-read,streaming_ctrl );
-	if(got <= 0) {
-	  if(got < 0)
-	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingChunk);
-	  return -1;
-	}
-	read += got;
-      }
-      waiting -= read;
-      if (drop_chunk) continue;
-    }
-    if (rest == 0 && waiting > 0 && size-read > 0) {
-      int s = MIN(waiting,size-read);
-      memset(buffer+read,0,s);
-      waiting -= s;
-      read += s;
-    }
-    break;
-  }
-
-  return read;
-}
-
-static int asf_http_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) {
-	return -1;
-	// to shut up gcc warning
-	fd++;
-	pos++;
-	streaming_ctrl=NULL;
-}
-
-static int asf_header_check( HTTP_header_t *http_hdr ) {
-	ASF_obj_header_t *objh;
-	if( http_hdr==NULL ) return -1;
-	if( http_hdr->body==NULL || http_hdr->body_size<sizeof(ASF_obj_header_t) ) return -1;
-
-	objh = (ASF_obj_header_t*)http_hdr->body;
-	if( ASF_LOAD_GUID_PREFIX(objh->guid)==0x75B22630 ) return 0;
-	return -1;
-}
-
-static int asf_http_streaming_type(char *content_type, char *features, HTTP_header_t *http_hdr ) {
-	if( content_type==NULL ) return ASF_Unknown_e;
-	if( 	!strcasecmp(content_type, "application/octet-stream") ||
-		!strcasecmp(content_type, "application/vnd.ms.wms-hdr.asfv1") ||        // New in Corona, first request
-		!strcasecmp(content_type, "application/x-mms-framed") ||                // New in Corana, second request
-		!strcasecmp(content_type, "video/x-ms-asf")) {               
-
-		if( strstr(features, "broadcast") ) {
-			mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Live stream\n");
-			return ASF_Live_e;
-		} else {
-			mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Prerecorded\n");
-			return ASF_Prerecorded_e;
-		}
-	} else {
-		// Ok in a perfect world, web servers should be well configured
-		// so we could used mime type to know the stream type,
-		// but guess what? All of them are not well configured.
-		// So we have to check for an asf header :(, but it works :p
-		if( http_hdr->body_size>sizeof(ASF_obj_header_t) ) {
-			if( asf_header_check( http_hdr )==0 ) {
-				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Plain text\n");
-				return ASF_PlainText_e;
-			} else if( (!strcasecmp(content_type, "text/html")) ) {
-				mp_msg(MSGT_NETWORK,MSGL_V,"=====> HTML, MPlayer is not a browser...yet!\n");
-				return ASF_Unknown_e;
-			} else {
-				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Redirector\n");
-				return ASF_Redirector_e;
-			}
-		} else {
-			if(	(!strcasecmp(content_type, "audio/x-ms-wax")) ||
-				(!strcasecmp(content_type, "audio/x-ms-wma")) ||
-				(!strcasecmp(content_type, "video/x-ms-asf")) ||
-				(!strcasecmp(content_type, "video/x-ms-afs")) ||
-				(!strcasecmp(content_type, "video/x-ms-wvx")) ||
-				(!strcasecmp(content_type, "video/x-ms-wmv")) ||
-				(!strcasecmp(content_type, "video/x-ms-wma")) ) {
-				mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ASFRedirector);
-				return ASF_Redirector_e;
-			} else if( !strcasecmp(content_type, "text/plain") ) {
-				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Plain text\n");
-				return ASF_PlainText_e;
-			} else {
-				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF unknown content-type: %s\n", content_type );
-				return ASF_Unknown_e;
-			}
-		}
-	}
-	return ASF_Unknown_e;
-}
-
-static HTTP_header_t *asf_http_request(streaming_ctrl_t *streaming_ctrl) {
-	HTTP_header_t *http_hdr;
-	URL_t *url = NULL;
-	URL_t *server_url = NULL;
-	asf_http_streaming_ctrl_t *asf_http_ctrl;
-	char str[250];
-	char *ptr;
-	int i, enable;
-
-	int offset_hi=0, offset_lo=0, length=0;
-	int asf_nb_stream=0, stream_id;
-
-	// Sanity check
-	if( streaming_ctrl==NULL ) return NULL;
-	url = streaming_ctrl->url;
-	asf_http_ctrl = (asf_http_streaming_ctrl_t*)streaming_ctrl->data;
-	if( url==NULL || asf_http_ctrl==NULL ) return NULL;
-
-	// Common header for all requests.
-	http_hdr = http_new_header();
-	http_set_field( http_hdr, "Accept: */*" );
-	http_set_field( http_hdr, "User-Agent: NSPlayer/4.1.0.3856" );
-	http_add_basic_authentication( http_hdr, url->username, url->password );
-
-	// Check if we are using a proxy
-	if( !strcasecmp( url->protocol, "http_proxy" ) ) {
-		server_url = url_new( (url->file)+1 );
-		if( server_url==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_InvalidProxyURL);
-			http_free( http_hdr );
-			return NULL;
-		}
-		http_set_uri( http_hdr, server_url->url );
-		sprintf( str, "Host: %.220s:%d", server_url->hostname, server_url->port );
-		url_free( server_url );
-	} else {
-		http_set_uri( http_hdr, url->file );
-		sprintf( str, "Host: %.220s:%d", url->hostname, url->port );
-	}
-	
-	http_set_field( http_hdr, str );
-	http_set_field( http_hdr, "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}" );
-	sprintf(str, 
-		"Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=%u",
-		offset_hi, offset_lo, asf_http_ctrl->request, length );
-	http_set_field( http_hdr, str );
-
-	switch( asf_http_ctrl->streaming_type ) {
-		case ASF_Live_e:
-		case ASF_Prerecorded_e:
-			http_set_field( http_hdr, "Pragma: xPlayStrm=1" );
-			ptr = str;
-			ptr += sprintf( ptr, "Pragma: stream-switch-entry=");
-			if(asf_http_ctrl->n_audio > 0) {
-				for( i=0; i<asf_http_ctrl->n_audio ; i++ ) {
-					stream_id = asf_http_ctrl->audio_streams[i];
-					if(stream_id == asf_http_ctrl->audio_id) {
-						enable = 0;
-					} else {
-						enable = 2;
-						continue;
-					}
-					asf_nb_stream++;
-					ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable);
-				}
-			}
-			if(asf_http_ctrl->n_video > 0) {
-				for( i=0; i<asf_http_ctrl->n_video ; i++ ) {
-					stream_id = asf_http_ctrl->video_streams[i];
-					if(stream_id == asf_http_ctrl->video_id) {
-						enable = 0;
-					} else {
-						enable = 2;
-						continue;
-					}
-					asf_nb_stream++;
-					ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable);
-				}
-			}
-			http_set_field( http_hdr, str );
-			sprintf( str, "Pragma: stream-switch-count=%d", asf_nb_stream );
-			http_set_field( http_hdr, str );
-			break;
-		case ASF_Redirector_e:
-			break;
-		case ASF_Unknown_e:
-			// First request goes here.
-			break;
-		default:
-			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_UnknownASFStreamType);
-	}
-
-	http_set_field( http_hdr, "Connection: Close" );
-	http_build_request( http_hdr );
-
-	return http_hdr;
-}
-
-static int asf_http_parse_response(asf_http_streaming_ctrl_t *asf_http_ctrl, HTTP_header_t *http_hdr ) {
-	char *content_type, *pragma;
-	char features[64] = "\0";
-	size_t len;
-	if( http_response_parse(http_hdr)<0 ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_Failed2ParseHTTPResponse);
-		return -1;
-	}
-	switch( http_hdr->status_code ) {
-		case 200:
-			break;
-		case 401: // Authentication required
-			return ASF_Authenticate_e;
-		default:
-			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ServerReturn, http_hdr->status_code, http_hdr->reason_phrase);
-			return -1;
-	}
-
-	content_type = http_get_field( http_hdr, "Content-Type");
-//printf("Content-Type: [%s]\n", content_type);
-
-	pragma = http_get_field( http_hdr, "Pragma");
-	while( pragma!=NULL ) {
-		char *comma_ptr=NULL;
-		char *end;
-//printf("Pragma: [%s]\n", pragma );
-		// The pragma line can get severals attributes 
-		// separeted with a comma ','.
-		do {
-			if( !strncasecmp( pragma, "features=", 9) ) {
-				pragma += 9;
-				end = strstr( pragma, "," );
-				if( end==NULL ) {
-				  len = strlen(pragma);
-				} else { 
-				  len = (unsigned int)(end-pragma);
-				}
-				if(len > sizeof(features) - 1) {
-				  mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_ASF_ASFHTTPParseWarnCuttedPragma,pragma,len,sizeof(features) - 1);
-				  len = sizeof(features) - 1;
-				}
-				strncpy( features, pragma, len );
-				features[len]='\0';
-				break;
-			}
-			comma_ptr = strstr( pragma, "," );
-			if( comma_ptr!=NULL ) {
-				pragma = comma_ptr+1;
-				if( pragma[0]==' ' ) pragma++;
-			}
-		} while( comma_ptr!=NULL );
-		pragma = http_get_next_field( http_hdr );
-	}
-	asf_http_ctrl->streaming_type = asf_http_streaming_type( content_type, features, http_hdr );
-	return 0;
-}
-
-static int asf_http_streaming_start( stream_t *stream, int *demuxer_type ) {
-	HTTP_header_t *http_hdr=NULL;
-	URL_t *url = stream->streaming_ctrl->url;
-	asf_http_streaming_ctrl_t *asf_http_ctrl;
-	char buffer[BUFFER_SIZE];
-	int i, ret;
-	int fd = stream->fd;
-	int done;
-	int auth_retry = 0;
-
-	asf_http_ctrl = malloc(sizeof(asf_http_streaming_ctrl_t));
-	if( asf_http_ctrl==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-		return -1;
-	}
-	asf_http_ctrl->streaming_type = ASF_Unknown_e;
-	asf_http_ctrl->request = 1;
-	asf_http_ctrl->audio_streams = asf_http_ctrl->video_streams = NULL;
-	asf_http_ctrl->n_audio = asf_http_ctrl->n_video = 0;
-	stream->streaming_ctrl->data = (void*)asf_http_ctrl;
-
-	do {
-		done = 1;
-		if( fd>0 ) closesocket( fd );
-
-		if( !strcasecmp( url->protocol, "http_proxy" ) ) {
-			if( url->port==0 ) url->port = 8080;
-		} else {
-			if( url->port==0 ) url->port = 80;
-		}
-		fd = connect2Server( url->hostname, url->port, 1);
-		if( fd<0 ) return fd;
-
-		http_hdr = asf_http_request( stream->streaming_ctrl );
-		mp_msg(MSGT_NETWORK,MSGL_DBG2,"Request [%s]\n", http_hdr->buffer );
-		for(i=0; i < (int)http_hdr->buffer_size ; ) {
-			int r = send( fd, http_hdr->buffer+i, http_hdr->buffer_size-i, 0 );
-			if(r <0) {
-				mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_SocketWriteError,strerror(errno));
-				return -1;
-			}
-			i += r;
-		}       
-		http_free( http_hdr );
-		http_hdr = http_new_header();
-		do {
-			i = recv( fd, buffer, BUFFER_SIZE, 0 );
-//printf("read: %d\n", i );
-			if( i<=0 ) {
-				perror("read");
-				http_free( http_hdr );
-				return -1;
-			}
-			http_response_append( http_hdr, buffer, i );
-		} while( !http_is_header_entire( http_hdr ) );
-		if( mp_msg_test(MSGT_NETWORK,MSGL_V) ) {
-			http_hdr->buffer[http_hdr->buffer_size]='\0';
-			mp_msg(MSGT_NETWORK,MSGL_DBG2,"Response [%s]\n", http_hdr->buffer );
-		}
-		ret = asf_http_parse_response(asf_http_ctrl, http_hdr);
-		if( ret<0 ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_HeaderParseFailed);
-			http_free( http_hdr );
-			return -1;
-		}
-		switch( asf_http_ctrl->streaming_type ) {
-			case ASF_Live_e:
-			case ASF_Prerecorded_e:
-			case ASF_PlainText_e:
-				if( http_hdr->body_size>0 ) {
-					if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
-						http_free( http_hdr );
-						return -1;
-					}
-				}
-				if( asf_http_ctrl->request==1 ) {
-					if( asf_http_ctrl->streaming_type!=ASF_PlainText_e ) {
-						// First request, we only got the ASF header.
-						ret = asf_streaming_parse_header(fd,stream->streaming_ctrl);
-						if(ret < 0) return -1;
-						if(asf_http_ctrl->n_audio == 0 && asf_http_ctrl->n_video == 0) {
-							mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_NoStreamFound);
-							return -1;
-						}
-						asf_http_ctrl->request++;
-						done = 0;
-					} else {
-						done = 1;
-					}
-				}
-				break;
-			case ASF_Redirector_e:
-				if( http_hdr->body_size>0 ) {
-					if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
-						http_free( http_hdr );
-						return -1;
-					}
-				}
-				*demuxer_type = DEMUXER_TYPE_PLAYLIST;
-				done = 1;
-				break;
-			case ASF_Authenticate_e:
-				if( http_authenticate( http_hdr, url, &auth_retry)<0 ) return -1;
-				asf_http_ctrl->streaming_type = ASF_Unknown_e;
-				done = 0;
-				break;
-			case ASF_Unknown_e:
-			default:
-				mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_UnknownASFStreamingType);
-				closesocket(fd);
-				http_free( http_hdr );
-				return -1;
-		}
-	// Check if we got a redirect.	
-	} while(!done);
-
-	stream->fd = fd;
-	if( asf_http_ctrl->streaming_type==ASF_PlainText_e || asf_http_ctrl->streaming_type==ASF_Redirector_e ) {
-		stream->streaming_ctrl->streaming_read = nop_streaming_read;
-		stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
-	} else {
-		stream->streaming_ctrl->streaming_read = asf_http_streaming_read;
-		stream->streaming_ctrl->streaming_seek = asf_http_streaming_seek;
-		stream->streaming_ctrl->buffering = 1;
-	}
-	stream->streaming_ctrl->status = streaming_playing_e;
-	stream->close = close_s;
-
-	http_free( http_hdr );
-	return 0;
-}
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-	URL_t *url;
-
-	stream->streaming_ctrl = streaming_ctrl_new();
-	if( stream->streaming_ctrl==NULL ) {
-		return STREAM_ERROR;
-	}
-	stream->streaming_ctrl->bandwidth = network_bandwidth;
-	url = url_new(stream->url);
-	stream->streaming_ctrl->url = check4proxies(url);
-	url_free(url);
-	
-	mp_msg(MSGT_OPEN, MSGL_INFO, MSGTR_MPDEMUX_ASF_InfoStreamASFURL, stream->url);
-	if((!strncmp(stream->url, "http", 4)) && (*file_format!=DEMUXER_TYPE_ASF && *file_format!=DEMUXER_TYPE_UNKNOWN)) {
-		streaming_ctrl_free(stream->streaming_ctrl);
-		stream->streaming_ctrl = NULL;
-		return STREAM_UNSUPORTED;
-	}
-
-	if(asf_streaming_start(stream, file_format) < 0) {
-		mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_ASF_StreamingFailed);
-		streaming_ctrl_free(stream->streaming_ctrl);
-		stream->streaming_ctrl = NULL;
-		return STREAM_UNSUPORTED;
-	}
-	
-	*file_format = DEMUXER_TYPE_ASF;
-	stream->type = STREAMTYPE_STREAM;
-	fixup_network_stream_cache(stream);
-	return STREAM_OK;
-}
-
-stream_info_t stream_info_asf = {
-  "mms and mms over http streaming",
-  "null",
-  "Bertrand, Reimar Doeffinger, Albeu",
-  "originally based on work by Majormms (is that code still there?)",
-  open_s,
-  {"mms", "mmsu", "mmst", "http", "http_proxy", "mmshttp", NULL},
-  NULL,
-  0 // Urls are an option string
-};
-
--- a/libmpdemux/audio_in.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-
-#include "audio_in.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-#include <string.h>
-#include <errno.h>
-
-// sanitizes ai structure before calling other functions
-int audio_in_init(audio_in_t *ai, int type)
-{
-    ai->type = type;
-    ai->setup = 0;
-
-    ai->channels = -1;
-    ai->samplerate = -1;
-    ai->blocksize = -1;
-    ai->bytes_per_sample = -1;
-    ai->samplesize = -1;
-
-    switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    case AUDIO_IN_ALSA:
-	ai->alsa.handle = NULL;
-	ai->alsa.log = NULL;
-	ai->alsa.device = strdup("default");
-	return 0;
-#endif
-#ifdef USE_OSS_AUDIO
-    case AUDIO_IN_OSS:
-	ai->oss.audio_fd = -1;
-	ai->oss.device = strdup("/dev/dsp");
-	return 0;
-#endif
-    default:
-	return -1;
-    }
-}
-
-int audio_in_setup(audio_in_t *ai)
-{
-    
-    switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    case AUDIO_IN_ALSA:
-	if (ai_alsa_init(ai) < 0) return -1;
-	ai->setup = 1;
-	return 0;
-#endif
-#ifdef USE_OSS_AUDIO
-    case AUDIO_IN_OSS:
-	if (ai_oss_init(ai) < 0) return -1;
-	ai->setup = 1;
-	return 0;
-#endif
-    default:
-	return -1;
-    }
-}
-
-int audio_in_set_samplerate(audio_in_t *ai, int rate)
-{
-    switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    case AUDIO_IN_ALSA:
-	ai->req_samplerate = rate;
-	if (!ai->setup) return 0;
-	if (ai_alsa_setup(ai) < 0) return -1;
-	return ai->samplerate;
-#endif
-#ifdef USE_OSS_AUDIO
-    case AUDIO_IN_OSS:
-	ai->req_samplerate = rate;
-	if (!ai->setup) return 0;
-	if (ai_oss_set_samplerate(ai) < 0) return -1;
-	return ai->samplerate;
-#endif
-    default:
-	return -1;
-    }
-}
-
-int audio_in_set_channels(audio_in_t *ai, int channels)
-{
-    switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    case AUDIO_IN_ALSA:
-	ai->req_channels = channels;
-	if (!ai->setup) return 0;
-	if (ai_alsa_setup(ai) < 0) return -1;
-	return ai->channels;
-#endif
-#ifdef USE_OSS_AUDIO
-    case AUDIO_IN_OSS:
-	ai->req_channels = channels;
-	if (!ai->setup) return 0;
-	if (ai_oss_set_channels(ai) < 0) return -1;
-	return ai->channels;
-#endif
-    default:
-	return -1;
-    }
-}
-
-int audio_in_set_device(audio_in_t *ai, char *device)
-{
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    int i;
-#endif
-    if (ai->setup) return -1;
-    switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    case AUDIO_IN_ALSA:
-	if (ai->alsa.device) free(ai->alsa.device);
-	ai->alsa.device = strdup(device);
-	/* mplayer cannot handle colons in arguments */
-	for (i = 0; i < (int)strlen(ai->alsa.device); i++) {
-	    if (ai->alsa.device[i] == '.') ai->alsa.device[i] = ':';
-	}
-	return 0;
-#endif
-#ifdef USE_OSS_AUDIO
-    case AUDIO_IN_OSS:
-	if (ai->oss.device) free(ai->oss.device);
-	ai->oss.device = strdup(device);
-	return 0;
-#endif
-    default:
-	return -1;
-    }
-}
-
-int audio_in_uninit(audio_in_t *ai)
-{
-    if (ai->setup) {
-	switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-	case AUDIO_IN_ALSA:
-	    if (ai->alsa.log)
-		snd_output_close(ai->alsa.log);
-	    if (ai->alsa.handle) {
-		snd_pcm_close(ai->alsa.handle);
-	    }
-	    ai->setup = 0;
-	    return 0;
-#endif
-#ifdef USE_OSS_AUDIO
-	case AUDIO_IN_OSS:
-	    close(ai->oss.audio_fd);
-	    ai->setup = 0;
-	    return 0;
-#endif
-	}
-    }
-    return -1;
-}
-
-int audio_in_start_capture(audio_in_t *ai)
-{
-    switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    case AUDIO_IN_ALSA:
-	return snd_pcm_start(ai->alsa.handle);
-#endif
-#ifdef USE_OSS_AUDIO
-    case AUDIO_IN_OSS:
-	return 0;
-#endif
-    default:
-	return -1;
-    }
-}
-
-int audio_in_read_chunk(audio_in_t *ai, unsigned char *buffer)
-{
-    int ret;
-    
-    switch (ai->type) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    case AUDIO_IN_ALSA:
-	ret = snd_pcm_readi(ai->alsa.handle, buffer, ai->alsa.chunk_size);
-	if (ret != ai->alsa.chunk_size) {
-	    if (ret < 0) {
-		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio, snd_strerror(ret));
-		if (ret == -EPIPE) {
-		    if (ai_alsa_xrun(ai) == 0) {
-			mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_XRUNSomeFramesMayBeLeftOut);
-		    } else {
-			mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrFatalCannotRecover);
-		    }
-		}
-	    } else {
-		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples);
-	    }
-	    return -1;
-	}
-	return ret;
-#endif
-#ifdef USE_OSS_AUDIO
-    case AUDIO_IN_OSS:
-	ret = read(ai->oss.audio_fd, buffer, ai->blocksize);
-	if (ret != ai->blocksize) {
-	    if (ret < 0) {
-		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio, strerror(errno));
-	    } else {
-		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples);
-	    }
-	    return -1;
-	}
-	return ret;
-#endif
-    default:
-	return -1;
-    }
-}
--- a/libmpdemux/audio_in.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#ifndef _audio_in_h 
-#define _audio_in_h 
-
-#define AUDIO_IN_ALSA 1
-#define AUDIO_IN_OSS 2
-
-#include "config.h"
-
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-#include <alsa/asoundlib.h>
-
-typedef struct {
-    char *device;
-
-    snd_pcm_t *handle;
-    snd_output_t *log;
-    int buffer_time, period_time, chunk_size;
-    size_t bits_per_sample, bits_per_frame;
-} ai_alsa_t;
-#endif
-
-#ifdef USE_OSS_AUDIO
-typedef struct {
-    char *device;
-
-    int audio_fd;
-} ai_oss_t;
-#endif
-
-typedef struct 
-{
-    int type;
-    int setup;
-    
-    /* requested values */
-    int req_channels;
-    int req_samplerate;
-
-    /* real values read-only */
-    int channels;
-    int samplerate;
-    int blocksize;
-    int bytes_per_sample;
-    int samplesize;
-    
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-    ai_alsa_t alsa;
-#endif
-#ifdef USE_OSS_AUDIO
-    ai_oss_t oss;
-#endif
-} audio_in_t;
-
-int audio_in_init(audio_in_t *ai, int type);
-int audio_in_setup(audio_in_t *ai);
-int audio_in_set_device(audio_in_t *ai, char *device);
-int audio_in_set_samplerate(audio_in_t *ai, int rate);
-int audio_in_set_channels(audio_in_t *ai, int channels);
-int audio_in_uninit(audio_in_t *ai);
-int audio_in_start_capture(audio_in_t *ai);
-int audio_in_read_chunk(audio_in_t *ai, unsigned char *buffer);
-
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-int ai_alsa_setup(audio_in_t *ai);
-int ai_alsa_init(audio_in_t *ai);
-int ai_alsa_xrun(audio_in_t *ai);
-#endif
-
-#ifdef USE_OSS_AUDIO
-int ai_oss_set_samplerate(audio_in_t *ai);
-int ai_oss_set_channels(audio_in_t *ai);
-int ai_oss_init(audio_in_t *ai);
-#endif
-
-#endif /* _audio_in_h */
--- a/libmpdemux/cache2.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,367 +0,0 @@
-#include "config.h"
-
-// Initial draft of my new cache system...
-// Note it runs in 2 processes (using fork()), but doesn't requires locking!!
-// TODO: seeking, data consistency checking
-
-#define READ_USLEEP_TIME 10000
-#define FILL_USLEEP_TIME 50000
-#define PREFILL_SLEEP_TIME 200
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "osdep/timer.h"
-#ifndef WIN32
-#include <sys/wait.h>
-#include "osdep/shmem.h"
-#else
-#include <windows.h>
-static DWORD WINAPI ThreadProc(void* s);
-#endif
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#include "stream.h"
-
-int stream_fill_buffer(stream_t *s);
-int stream_seek_long(stream_t *s,off_t pos);
-
-extern int mp_input_check_interrupt(int time);
-
-typedef struct {
-  // constats:
-  unsigned char *buffer;      // base pointer of the alllocated buffer memory
-  int buffer_size; // size of the alllocated buffer memory
-  int sector_size; // size of a single sector (2048/2324)
-  int back_size;   // we should keep back_size amount of old bytes for backward seek
-  int fill_limit;  // we should fill buffer only if space>=fill_limit
-  int seek_limit;  // keep filling cache if distanse is less that seek limit
-  // filler's pointers:
-  int eof;
-  off_t min_filepos; // buffer contain only a part of the file, from min-max pos
-  off_t max_filepos;
-  off_t offset;      // filepos <-> bufferpos  offset value (filepos of the buffer's first byte)
-  // reader's pointers:
-  off_t read_filepos;
-  // commands/locking:
-//  int seek_lock;   // 1 if we will seek/reset buffer, 2 if we are ready for cmd
-//  int fifo_flag;  // 1 if we should use FIFO to notice cache about buffer reads.
-  // callback
-  stream_t* stream;
-} cache_vars_t;
-
-static int min_fill=0;
-
-int cache_fill_status=0;
-
-void cache_stats(cache_vars_t* s){
-  int newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
-  mp_msg(MSGT_CACHE,MSGL_INFO,"0x%06X  [0x%06X]  0x%06X   ",(int)s->min_filepos,(int)s->read_filepos,(int)s->max_filepos);
-  mp_msg(MSGT_CACHE,MSGL_INFO,"%3d %%  (%3d%%)\n",100*newb/s->buffer_size,100*min_fill/s->buffer_size);
-}
-
-int cache_read(cache_vars_t* s,unsigned char* buf,int size){
-  int total=0;
-  while(size>0){
-    int pos,newb,len;
-
-  //printf("CACHE2_READ: 0x%X <= 0x%X <= 0x%X  \n",s->min_filepos,s->read_filepos,s->max_filepos);
-    
-    if(s->read_filepos>=s->max_filepos || s->read_filepos<s->min_filepos){
-	// eof?
-	if(s->eof) break;
-	// waiting for buffer fill...
-	usec_sleep(READ_USLEEP_TIME); // 10ms
-	continue; // try again...
-    }
-
-    newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
-    if(newb<min_fill) min_fill=newb; // statistics...
-
-//    printf("*** newb: %d bytes ***\n",newb);
-
-    pos=s->read_filepos - s->offset;
-    if(pos<0) pos+=s->buffer_size; else
-    if(pos>=s->buffer_size) pos-=s->buffer_size;
-
-    if(newb>s->buffer_size-pos) newb=s->buffer_size-pos; // handle wrap...
-    if(newb>size) newb=size;
-    
-    // check:
-    if(s->read_filepos<s->min_filepos) mp_msg(MSGT_CACHE,MSGL_ERR,"Ehh. s->read_filepos<s->min_filepos !!! Report bug...\n");
-    
-    // len=write(mem,newb)
-    //printf("Buffer read: %d bytes\n",newb);
-    memcpy(buf,&s->buffer[pos],newb);
-    buf+=newb;
-    len=newb;
-    // ...
-    
-    s->read_filepos+=len;
-    size-=len;
-    total+=len;
-    
-  }
-  cache_fill_status=(s->max_filepos-s->read_filepos)/(s->buffer_size / 100);
-  return total;
-}
-
-int cache_fill(cache_vars_t* s){
-  int back,back2,newb,space,len,pos;
-  off_t read=s->read_filepos;
-  
-  if(read<s->min_filepos || read>s->max_filepos){
-      // seek...
-      mp_msg(MSGT_CACHE,MSGL_DBG2,"Out of boundaries... seeking to 0x%"PRIX64"  \n",(int64_t)read);
-      // streaming: drop cache contents only if seeking backward or too much fwd:
-      if(s->stream->type!=STREAMTYPE_STREAM ||
-          read<s->min_filepos || read>=s->max_filepos+s->seek_limit)
-      {
-        s->offset= // FIXME!?
-        s->min_filepos=s->max_filepos=read; // drop cache content :(
-        if(s->stream->eof) stream_reset(s->stream);
-        stream_seek(s->stream,read);
-        mp_msg(MSGT_CACHE,MSGL_DBG2,"Seek done. new pos: 0x%"PRIX64"  \n",(int64_t)stream_tell(s->stream));
-      }
-  }
-  
-  // calc number of back-bytes:
-  back=read - s->min_filepos;
-  if(back<0) back=0; // strange...
-  if(back>s->back_size) back=s->back_size;
-  
-  // calc number of new bytes:
-  newb=s->max_filepos - read;
-  if(newb<0) newb=0; // strange...
-
-  // calc free buffer space:
-  space=s->buffer_size - (newb+back);
-  
-  // calc bufferpos:
-  pos=s->max_filepos - s->offset;
-  if(pos>=s->buffer_size) pos-=s->buffer_size; // wrap-around
-  
-  if(space<s->fill_limit){
-//    printf("Buffer is full (%d bytes free, limit: %d)\n",space,s->fill_limit);
-    return 0; // no fill...
-  }
-
-//  printf("### read=0x%X  back=%d  newb=%d  space=%d  pos=%d\n",read,back,newb,space,pos);
-     
-  // reduce space if needed:
-  if(space>s->buffer_size-pos) space=s->buffer_size-pos;
-  
-//  if(space>32768) space=32768; // limit one-time block size
-  if(space>4*s->sector_size) space=4*s->sector_size;
-  
-//  if(s->seek_lock) return 0; // FIXME
-
-#if 1
-  // back+newb+space <= buffer_size
-  back2=s->buffer_size-(space+newb); // max back size
-  if(s->min_filepos<(read-back2)) s->min_filepos=read-back2;
-#else
-  s->min_filepos=read-back; // avoid seeking-back to temp area...
-#endif
-  
-  // ....
-  //printf("Buffer fill: %d bytes of %d\n",space,s->buffer_size);
-  //len=stream_fill_buffer(s->stream);
-  //memcpy(&s->buffer[pos],s->stream->buffer,len); // avoid this extra copy!
-  // ....
-  len=stream_read(s->stream,&s->buffer[pos],space);
-  if(!len) s->eof=1;
-  
-  s->max_filepos+=len;
-  if(pos+len>=s->buffer_size){
-      // wrap...
-      s->offset+=s->buffer_size;
-  }
-  
-  return len;
-  
-}
-
-cache_vars_t* cache_init(int size,int sector){
-  int num;
-#ifndef WIN32
-  cache_vars_t* s=shmem_alloc(sizeof(cache_vars_t));
-#else
-  cache_vars_t* s=malloc(sizeof(cache_vars_t));
-#endif
-  if(s==NULL) return NULL;
-  
-  memset(s,0,sizeof(cache_vars_t));
-  num=size/sector;
-  if(num < 16){
-     num = 16;
-  }//32kb min_size
-  s->buffer_size=num*sector;
-  s->sector_size=sector;
-#ifndef WIN32
-  s->buffer=shmem_alloc(s->buffer_size);
-#else
-  s->buffer=malloc(s->buffer_size);
-#endif
-
-  if(s->buffer == NULL){
-#ifndef WIN32
-    shmem_free(s,sizeof(cache_vars_t));
-#else
-    free(s);
-#endif
-    return NULL;
-  }
-
-  s->fill_limit=8*sector;
-  s->back_size=s->buffer_size/2;
-  return s;
-}
-
-void cache_uninit(stream_t *s) {
-  cache_vars_t* c = s->cache_data;
-  if(!s->cache_pid) return;
-#ifndef WIN32
-  kill(s->cache_pid,SIGKILL);
-  waitpid(s->cache_pid,NULL,0);
-#else
-  TerminateThread((HANDLE)s->cache_pid,0);
-  free(c->stream);
-#endif
-  if(!c) return;
-#ifndef WIN32
-  shmem_free(c->buffer,c->buffer_size);
-  shmem_free(s->cache_data,sizeof(cache_vars_t));
-#else
-  free(c->buffer);
-  free(s->cache_data);
-#endif
-}
-
-static void exit_sighandler(int x){
-  // close stream
-  exit(0);
-}
-
-int stream_enable_cache(stream_t *stream,int size,int min,int seek_limit){
-  int ss=(stream->type==STREAMTYPE_VCD)?VCD_SECTOR_DATA:STREAM_BUFFER_SIZE;
-  cache_vars_t* s;
-
-  if (stream->type==STREAMTYPE_STREAM && stream->fd < 0) {
-    // The stream has no 'fd' behind it, so is non-cacheable
-    mp_msg(MSGT_CACHE,MSGL_STATUS,"\rThis stream is non-cacheable\n");
-    return 1;
-  }
-
-  s=cache_init(size,ss);
-  if(s == NULL) return 0;
-  stream->cache_data=s;
-  s->stream=stream; // callback
-  s->seek_limit=seek_limit;
-
-
-  //make sure that we won't wait from cache_fill
-  //more data than it is alowed to fill
-  if (s->seek_limit > s->buffer_size - s->fill_limit ){
-     s->seek_limit = s->buffer_size - s->fill_limit;
-  }
-  if (min > s->buffer_size - s->fill_limit) {
-     min = s->buffer_size - s->fill_limit;
-  }
-  
-#ifndef WIN32  
-  if((stream->cache_pid=fork())){
-#else
-  {
-    DWORD threadId;
-    stream_t* stream2=malloc(sizeof(stream_t));
-    memcpy(stream2,s->stream,sizeof(stream_t));
-    s->stream=stream2;
-    stream->cache_pid = CreateThread(NULL,0,ThreadProc,s,0,&threadId);
-#endif
-    // wait until cache is filled at least prefill_init %
-    mp_msg(MSGT_CACHE,MSGL_V,"CACHE_PRE_INIT: %"PRId64" [%"PRId64"] %"PRId64"  pre:%d  eof:%d  \n",
-	(int64_t)s->min_filepos,(int64_t)s->read_filepos,(int64_t)s->max_filepos,min,s->eof);
-    while(s->read_filepos<s->min_filepos || s->max_filepos-s->read_filepos<min){
-	mp_msg(MSGT_CACHE,MSGL_STATUS,MSGTR_CacheFill,
-	    100.0*(float)(s->max_filepos-s->read_filepos)/(float)(s->buffer_size),
-	    (int64_t)s->max_filepos-s->read_filepos
-	);
-	if(s->eof) break; // file is smaller than prefill size
-	if(mp_input_check_interrupt(PREFILL_SLEEP_TIME))
-	  return 0;
-    }
-    mp_msg(MSGT_CACHE,MSGL_STATUS,"\n");
-    return 1; // parent exits
-  }
-  
-#ifdef WIN32
-}
-static DWORD WINAPI ThreadProc(void*s){
-#endif
-  
-// cache thread mainloop:
-  signal(SIGTERM,exit_sighandler); // kill
-  while(1){
-    if(!cache_fill((cache_vars_t*)s)){
-	 usec_sleep(FILL_USLEEP_TIME); // idle
-    }
-//	 cache_stats(s->cache_data);
-  }
-}
-
-int cache_stream_fill_buffer(stream_t *s){
-  int len;
-  if(s->eof){ s->buf_pos=s->buf_len=0; return 0; }
-  if(!s->cache_pid) return stream_fill_buffer(s);
-
-//  cache_stats(s->cache_data);
-
-  if(s->pos!=((cache_vars_t*)s->cache_data)->read_filepos) mp_msg(MSGT_CACHE,MSGL_ERR,"!!! read_filepos differs!!! report this bug...\n");
-
-  len=cache_read(s->cache_data,s->buffer, ((cache_vars_t*)s->cache_data)->sector_size);
-  //printf("cache_stream_fill_buffer->read -> %d\n",len);
-
-  if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
-  s->buf_pos=0;
-  s->buf_len=len;
-  s->pos+=len;
-//  printf("[%d]",len);fflush(stdout);
-  return len;
-
-}
-
-int cache_stream_seek_long(stream_t *stream,off_t pos){
-  cache_vars_t* s;
-  off_t newpos;
-  if(!stream->cache_pid) return stream_seek_long(stream,pos);
-  
-  s=stream->cache_data;
-//  s->seek_lock=1;
-  
-  mp_msg(MSGT_CACHE,MSGL_DBG2,"CACHE2_SEEK: 0x%"PRIX64" <= 0x%"PRIX64" (0x%"PRIX64") <= 0x%"PRIX64"  \n",s->min_filepos,pos,s->read_filepos,s->max_filepos);
-
-  newpos=pos/s->sector_size; newpos*=s->sector_size; // align
-  stream->pos=s->read_filepos=newpos;
-  s->eof=0; // !!!!!!!
-
-  cache_stream_fill_buffer(stream);
-
-  pos-=newpos;
-  if(pos>=0 && pos<=stream->buf_len){
-    stream->buf_pos=pos; // byte position in sector
-    return 1;
-  }
-
-//  stream->buf_pos=stream->buf_len=0;
-//  return 1;
-
-  mp_msg(MSGT_CACHE,MSGL_V,"cache_stream_seek: WARNING! Can't seek to 0x%"PRIX64" !\n",(int64_t)(pos+newpos));
-  return 0;
-}
--- a/libmpdemux/cdd.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-#ifndef __CDD_H__
-#define __CDD_H__
-
-#include "config.h"
-#ifndef HAVE_LIBCDIO
-#include <cdda_interface.h>
-#include <cdda_paranoia.h>
-#else
-#include <cdio/cdda.h>
-#include <cdio/paranoia.h>
-#endif
-
-typedef struct {
-	char cddb_hello[1024];	
-	unsigned long disc_id;
-	unsigned int tracks;
-	char *cache_dir;
-	char *freedb_server;
-	int freedb_proto_level;
-	int anonymous;
-	char category[100];
-	char *xmcd_file;
-	size_t xmcd_file_size;
-	void *user_data;
-} cddb_data_t;
-
-typedef struct {
-	unsigned int min, sec, frame;
-} cd_toc_t;
-
-typedef struct cd_track {
-	char *name;
-	unsigned int track_nb;
-	unsigned int min;
-	unsigned int sec;
-	unsigned int msec;
-	unsigned long frame_begin;
-	unsigned long frame_length;
-	struct cd_track *prev;
-	struct cd_track *next;
-} cd_track_t;
-
-typedef struct {
-	char *artist;
-	char *album;
-	char *genre;
-	unsigned int nb_tracks;
-	unsigned int min;
-	unsigned int sec;
-	unsigned msec;
-	cd_track_t *first;
-	cd_track_t *last;
-	cd_track_t *current;
-} cd_info_t;
-
-typedef struct {
-#ifndef HAVE_LIBCDIO
-	cdrom_drive* cd;
-	cdrom_paranoia* cdp;
-#else
-	cdrom_drive_t* cd;
-	cdrom_paranoia_t* cdp;
-#endif
-	int sector;
-	int start_sector;
-	int end_sector;
-	cd_info_t *cd_info;
-} cdda_priv;
-
-cd_info_t* 	cd_info_new();
-void		cd_info_free(cd_info_t *cd_info);
-cd_track_t*	cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length);
-cd_track_t*	cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb);
-
-void 		cd_info_debug(cd_info_t *cd_info);
-
-#endif // __CDD_H__
--- a/libmpdemux/cdda.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,391 +0,0 @@
-#include "config.h"
-
-#include "stream.h"
-#include "m_option.h"
-#include "m_struct.h"
-#include "bswap.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "demuxer.h"
-
-#include "cdd.h"
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#ifndef CD_FRAMESIZE_RAW
-#define CD_FRAMESIZE_RAW CDIO_CD_FRAMESIZE_RAW
-#endif
-
-
-extern char *cdrom_device;
-
-static struct cdda_params {
-  int speed;
-  int paranoia_mode;
-  char* generic_dev;
-  int sector_size;
-  int search_overlap;
-  int toc_bias;
-  int toc_offset;
-  int no_skip;
-  char* device;
-  m_span_t span;
-} cdda_dflts = {
-  -1,
-  0,
-  NULL,
-  0,
-  -1,
-  0,
-  0,
-  0,
-  NULL,
-  { 0, 0 }
-};
-
-#define ST_OFF(f) M_ST_OFF(struct cdda_params,f)
-m_option_t cdda_params_fields[] = {
-  { "speed", ST_OFF(speed), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
-  { "paranoia", ST_OFF(paranoia_mode), CONF_TYPE_INT,M_OPT_RANGE, 0, 2, NULL },
-  { "generic-dev", ST_OFF(generic_dev), CONF_TYPE_STRING, 0, 0, 0, NULL },
-  { "sector-size", ST_OFF(sector_size), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
-  { "overlap", ST_OFF(search_overlap), CONF_TYPE_INT, M_OPT_RANGE,0,75, NULL },
-  { "toc-bias", ST_OFF(toc_bias), CONF_TYPE_INT, 0, 0, 0, NULL },
-  { "toc-offset", ST_OFF(toc_offset), CONF_TYPE_INT, 0, 0, 0, NULL },
-  { "noskip", ST_OFF(no_skip), CONF_TYPE_FLAG, 0 , 0, 1, NULL },
-  { "skip", ST_OFF(no_skip), CONF_TYPE_FLAG, 0 , 1, 0, NULL },
-  { "device", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
-  { "span",  ST_OFF(span), CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
-  /// For url parsing
-  { "hostname", ST_OFF(span), CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
-  { "port", ST_OFF(speed), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
-  { "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
-  {NULL, NULL, 0, 0, 0, 0, NULL}
-};
-static struct m_struct_st stream_opts = {
-  "cdda",
-  sizeof(struct cdda_params),
-  &cdda_dflts,
-  cdda_params_fields
-};
-
-/// We keep these options but now they set the defaults
-m_option_t cdda_opts[] = {
-  { "speed", &cdda_dflts.speed, CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
-  { "paranoia", &cdda_dflts.paranoia_mode, CONF_TYPE_INT,M_OPT_RANGE, 0, 2, NULL },
-  { "generic-dev", &cdda_dflts.generic_dev, CONF_TYPE_STRING, 0, 0, 0, NULL },
-  { "sector-size", &cdda_dflts.sector_size, CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
-  { "overlap", &cdda_dflts.search_overlap, CONF_TYPE_INT, M_OPT_RANGE,0,75, NULL },
-  { "toc-bias", &cdda_dflts.toc_bias, CONF_TYPE_INT, 0, 0, 0, NULL },
-  { "toc-offset", &cdda_dflts.toc_offset, CONF_TYPE_INT, 0, 0, 0, NULL },
-  { "noskip", &cdda_dflts.no_skip, CONF_TYPE_FLAG, 0 , 0, 1, NULL },
-  { "skip", &cdda_dflts.no_skip, CONF_TYPE_FLAG, 0 , 1, 0, NULL },
-  { "device", &cdda_dflts.device, CONF_TYPE_STRING, 0, 0, 0, NULL },
-  { "span", &cdda_dflts.span, CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
-  {NULL, NULL, 0, 0, 0, 0, NULL}
-};
-
-extern int cdd_identify(const char *dev);
-extern int cddb_resolve(const char *dev, char **xmcd_file);
-extern cd_info_t* cddb_parse_xmcd(char *xmcd_file);
-
-static int seek(stream_t* s,off_t pos);
-static int fill_buffer(stream_t* s, char* buffer, int max_len);
-static void close_cdda(stream_t* s);
-
-static int open_cdda(stream_t *st,int m, void* opts, int* file_format) {
-  struct cdda_params* p = (struct cdda_params*)opts;
-  int mode = p->paranoia_mode;
-  int offset = p->toc_offset;
-#ifndef HAVE_LIBCDIO
-  cdrom_drive* cdd = NULL;
-#else
-  cdrom_drive_t* cdd = NULL;
-#endif
-  cdda_priv* priv;
-  cd_info_t *cd_info,*cddb_info = NULL;
-  unsigned int audiolen=0;
-  int last_track;
-  int i;
-  char *xmcd_file = NULL;
-
-  if(m != STREAM_READ) {
-    m_struct_free(&stream_opts,opts);
-    return STREAM_UNSUPORTED;
-  }
-
-  if(!p->device) {
-    if (cdrom_device)
-      p->device = strdup(cdrom_device);
-    else
-      p->device = strdup(DEFAULT_CDROM_DEVICE);
-  }
-
-#ifdef MPLAYER_NETWORK
-  // cdd_identify returns -1 if it cannot read the TOC,
-  // in which case there is no point in calling cddb_resolve
-  if(cdd_identify(p->device) >= 0 && strncmp(st->url,"cddb",4) == 0) {
-    i = cddb_resolve(p->device, &xmcd_file);
-    if(i == 0) {
-      cddb_info = cddb_parse_xmcd(xmcd_file);
-      free(xmcd_file);
-    }
-  }
-#endif
-  
-#ifndef HAVE_LIBCDIO
-  if(p->generic_dev)
-    cdd = cdda_identify_scsi(p->generic_dev,p->device,0,NULL);
-  else
-#endif
-#if defined(__NetBSD__)
-    cdd = cdda_identify_scsi(p->device,p->device,0,NULL);
-#else
-    cdd = cdda_identify(p->device,0,NULL);
-#endif
-
-  if(!cdd) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_MPDEMUX_CDDA_CantOpenCDDADevice);
-    m_struct_free(&stream_opts,opts);
-    free(cddb_info);
-    return STREAM_ERROR;
-  }
-
-  cdda_verbose_set(cdd, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
-
-  if(p->sector_size) {
-    cdd->nsectors = p->sector_size;
-#ifndef HAVE_LIBCDIO
-    cdd->bigbuff = p->sector_size * CD_FRAMESIZE_RAW;
-#endif
-  }
-
-  if(cdda_open(cdd) != 0) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_MPDEMUX_CDDA_CantOpenDisc);
-    cdda_close(cdd);
-    m_struct_free(&stream_opts,opts);
-    free(cddb_info);
-    return STREAM_ERROR;
-  }
-
-  cd_info = cd_info_new();
-  mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_MPDEMUX_CDDA_AudioCDFoundWithNTracks,cdda_tracks(cdd));
-  for(i=0;i<cdd->tracks;i++) {
-	  char track_name[80];
-	  long sec=cdda_track_firstsector(cdd,i+1);
-	  long off=cdda_track_lastsector(cdd,i+1)-sec+1;
-
-	  sprintf(track_name, "Track %d", i+1);
-	  cd_info_add_track(cd_info, track_name, i+1, (unsigned int)(off/(60*75)), (unsigned int)((off/75)%60), (unsigned int)(off%75), sec, off );
-	  audiolen += off;
-  }
-  cd_info->min  = (unsigned int)(audiolen/(60*75));
-  cd_info->sec  = (unsigned int)((audiolen/75)%60);
-  cd_info->msec = (unsigned int)(audiolen%75);
-
-  priv = malloc(sizeof(cdda_priv));
-  memset(priv, 0, sizeof(cdda_priv));
-  priv->cd = cdd;
-  priv->cd_info = cd_info;
-
-  if(p->toc_bias)
-    offset -= cdda_track_firstsector(cdd,1);
-
-  if(offset) {
-    int i;
-    for(i = 0 ; i < cdd->tracks + 1 ; i++)
-      cdd->disc_toc[i].dwStartSector += offset;
-  }
-
-  if(p->speed)
-    cdda_speed_set(cdd,p->speed);
-
-  last_track = cdda_tracks(cdd);
-  if (p->span.start > last_track) p->span.start = last_track;
-  if (p->span.end < p->span.start) p->span.end = p->span.start;
-  if (p->span.end > last_track) p->span.end = last_track;
-  if(p->span.start)
-    priv->start_sector = cdda_track_firstsector(cdd,p->span.start);
-  else
-    priv->start_sector = cdda_disc_firstsector(cdd);
-
-  if(p->span.end) {
-    priv->end_sector = cdda_track_lastsector(cdd,p->span.end);
-  } else
-    priv->end_sector = cdda_disc_lastsector(cdd);
-
-  priv->cdp = paranoia_init(cdd);
-  if(priv->cdp == NULL) {
-    cdda_close(cdd);
-    free(priv);
-    cd_info_free(cd_info);
-    m_struct_free(&stream_opts,opts);
-    free(cddb_info);
-    return STREAM_ERROR;
-  }
-
-  if(mode == 0)
-    mode = PARANOIA_MODE_DISABLE;
-  else if(mode == 1)
-    mode = PARANOIA_MODE_OVERLAP;
-  else
-    mode = PARANOIA_MODE_FULL;
-  
-  if(p->no_skip)
-    mode |= PARANOIA_MODE_NEVERSKIP;
-#ifndef HAVE_LIBCDIO
-  paranoia_modeset(cdd, mode);
-
-  if(p->search_overlap >= 0)
-    paranoia_overlapset(cdd,p->search_overlap);
-#else
-  paranoia_modeset(priv->cdp, mode);
-
-  if(p->search_overlap >= 0)
-    paranoia_overlapset(priv->cdp,p->search_overlap);
-#endif
-
-  paranoia_seek(priv->cdp,priv->start_sector,SEEK_SET);
-  priv->sector = priv->start_sector;
-
-#ifdef MPLAYER_NETWORK
-  if(cddb_info) {
-    cd_info_free(cd_info);
-    priv->cd_info = cddb_info;
-    cd_info_debug( cddb_info );
-  }
-#endif
-
-  st->priv = priv;
-  st->start_pos = priv->start_sector*CD_FRAMESIZE_RAW;
-  st->end_pos = priv->end_sector*CD_FRAMESIZE_RAW;
-  st->type = STREAMTYPE_CDDA;
-  st->sector_size = CD_FRAMESIZE_RAW;
-
-  st->fill_buffer = fill_buffer;
-  st->seek = seek;
-  st->close = close_cdda;
-
-  *file_format = DEMUXER_TYPE_RAWAUDIO;
-
-  m_struct_free(&stream_opts,opts);
-
-  return STREAM_OK;
-}
-
-#ifndef HAVE_LIBCDIO
-static void cdparanoia_callback(long inpos, int function) {
-#else
-static void cdparanoia_callback(long int inpos, paranoia_cb_mode_t function) {
-#endif
-}
-
-static int fill_buffer(stream_t* s, char* buffer, int max_len) {
-  cdda_priv* p = (cdda_priv*)s->priv;
-  cd_track_t *cd_track;
-  int16_t * buf;
-  int i;
-  
-  buf = paranoia_read(p->cdp,cdparanoia_callback);
-
-#ifdef WORDS_BIGENDIAN 
-  for(i=0;i<CD_FRAMESIZE_RAW/2;i++)
-          buf[i]=le2me_16(buf[i]);
-#endif
-
-  p->sector++;
-  s->pos = p->sector*CD_FRAMESIZE_RAW;
-  memcpy(buffer,buf,CD_FRAMESIZE_RAW);
-
-  if((p->sector < p->start_sector) || (p->sector >= p->end_sector)) {
-    s->eof = 1;
-    return 0;
-  }
-
-  for(i=0;i<p->cd->tracks;i++){
-	  if(p->cd->disc_toc[i].dwStartSector==p->sector-1) {
-		  cd_track = cd_info_get_track(p->cd_info, i+1);
-//printf("Track %d, sector=%d\n", i, p->sector-1);
-		  if( cd_track!=NULL ) {
-			mp_msg(MSGT_SEEK, MSGL_INFO, "\n%s\n", cd_track->name); 
-			mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDA_TRACK=%d\n", cd_track->track_nb);
-		  }
-		  break;
-	  }
-  }
-
-  
-  return CD_FRAMESIZE_RAW;
-}
-
-static int seek(stream_t* s,off_t newpos) {
-  cdda_priv* p = (cdda_priv*)s->priv;
-  cd_track_t *cd_track;
-  int sec;
-  int current_track=0, seeked_track=0;
-  int i;
-  
-  s->pos = newpos;
-  if(s->pos < 0) {
-    s->eof = 1;
-    return 0;
-  }
-
-  sec = s->pos/CD_FRAMESIZE_RAW;
-//printf("pos: %d, sec: %d ## %d\n", (int)s->pos, (int)sec, CD_FRAMESIZE_RAW);
-//printf("sector: %d  new: %d\n", p->sector, sec );
- 
-  for(i=0;i<p->cd->tracks;i++){
-//        printf("trk #%d: %d .. %d\n",i,p->cd->disc_toc[i].dwStartSector,p->cd->disc_toc[i+1].dwStartSector);
-	if( p->sector>=p->cd->disc_toc[i].dwStartSector && p->sector<p->cd->disc_toc[i+1].dwStartSector ) {
-		current_track = i;
-	}
-	if( sec>=p->cd->disc_toc[i].dwStartSector && sec<p->cd->disc_toc[i+1].dwStartSector ) {
-		seeked_track = i;
-	}
-  }
-//printf("current: %d, seeked: %d\n", current_track, seeked_track);
-	if( current_track!=seeked_track ) {
-//printf("Track %d, sector=%d\n", seeked_track, sec);
-		  cd_track = cd_info_get_track(p->cd_info, seeked_track+1);
-		  if( cd_track!=NULL ) {
-			  mp_msg(MSGT_SEEK, MSGL_INFO, "\n%s\n", cd_track->name);
-			  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDA_TRACK=%d\n", cd_track->track_nb);
-		  }
-
-	}
-#if 0
-  if(sec < p->start_sector)
-    sec = p->start_sector;
-  else if(sec > p->end_sector)
-    sec = p->end_sector;
-#endif
-
-  p->sector = sec;
-//  s->pos = sec*CD_FRAMESIZE_RAW;
-
-//printf("seek: %d, sec: %d\n", (int)s->pos, sec);
-  paranoia_seek(p->cdp,sec,SEEK_SET);
-  return 1;
-}
-
-static void close_cdda(stream_t* s) {
-  cdda_priv* p = (cdda_priv*)s->priv;
-  paranoia_free(p->cdp);
-  cdda_close(p->cd);
-  cd_info_free(p->cd_info);
-  free(p);
-}
-
-stream_info_t stream_info_cdda = {
-  "CDDA",
-  "cdda",
-  "Albeu",
-  "",
-  open_cdda,
-  { "cdda", "cddb", NULL },
-  &stream_opts,
-  1 // Urls are an option string
-};
--- a/libmpdemux/cddb.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,878 +0,0 @@
-/*
- * CDDB HTTP protocol 
- * by Bertrand Baudet <bertrand_baudet@yahoo.com>
- * (C) 2002, MPlayer team.
- *
- * Implementation follow the freedb.howto1.06.txt specification
- * from http://freedb.freedb.org
- * 
- * discid computation by Jeremy D. Zawodny
- *	 Copyright (c) 1998-2000 Jeremy D. Zawodny <Jeremy@Zawodny.com>
- *	 Code release under GPL
- *
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#ifdef WIN32
-#ifdef __MINGW32__
-#define mkdir(a,b) mkdir(a)
-#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2
-#include <winsock2.h>
-#endif
-#else
-#include <netdb.h>
-#include <sys/ioctl.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#if defined(__linux__)
-	#include <linux/cdrom.h>
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-	#include <sys/cdio.h>
-#elif defined(WIN32)
-        #include <ddk/ntddcdrm.h>
-#elif (__bsdi__)
-        #include <dvd.h>
-#endif
-
-#include "cdd.h"
-#include "version.h"
-#include "stream.h"
-#include "network.h"
-
-#define DEFAULT_FREEDB_SERVER	"freedb.freedb.org"
-#define DEFAULT_CACHE_DIR	"/.cddb/"
-
-stream_t* open_cdda(char *dev, char *track);
-
-static cd_toc_t cdtoc[100];
-static int cdtoc_last_track;
-
-#if defined(__linux__) || defined(__bsdi__)
-int 
-read_toc(const char *dev) {
-	int drive;
-	struct cdrom_tochdr tochdr;
-	struct cdrom_tocentry tocentry;
-	int i;
-
-	drive = open(dev, O_RDONLY | O_NONBLOCK);
-	if( drive<0 ) {
-		return drive;
-	}
-	
-	ioctl(drive, CDROMREADTOCHDR, &tochdr);
-	for (i = tochdr.cdth_trk0; i <= tochdr.cdth_trk1; i++) {
-		tocentry.cdte_track = i;
-		tocentry.cdte_format = CDROM_MSF;
-		ioctl(drive, CDROMREADTOCENTRY, &tocentry);
-		cdtoc[i-1].min = tocentry.cdte_addr.msf.minute;
-		cdtoc[i-1].sec = tocentry.cdte_addr.msf.second;
-		cdtoc[i-1].frame = tocentry.cdte_addr.msf.frame;
-		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
-		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
-	}
-	tocentry.cdte_track = 0xAA;
-	tocentry.cdte_format = CDROM_MSF;
-	ioctl(drive, CDROMREADTOCENTRY, &tocentry);
-	cdtoc[tochdr.cdth_trk1].min = tocentry.cdte_addr.msf.minute;
-	cdtoc[tochdr.cdth_trk1].sec = tocentry.cdte_addr.msf.second;
-	cdtoc[tochdr.cdth_trk1].frame = tocentry.cdte_addr.msf.frame;
-	cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].min*60*75;
-	cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].sec*75;
-	close(drive);
-	return tochdr.cdth_trk1;
-}
-
-#elif defined(WIN32)
-int
-read_toc(const char *dev) {
-        HANDLE drive;
-        DWORD r;
-        CDROM_TOC toc;
-        char device[10];
-        int i;
-
-        sprintf(device, "\\\\.\\%s", dev);
-        drive = CreateFile(device, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
-
-        if(!DeviceIoControl(drive, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(CDROM_TOC), &r, 0)) {
-                mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToReadTOC);
-                return 0;
-        }
-
-        for (i = toc.FirstTrack; i <= toc.LastTrack; i++) {
-                toc.FirstTrack = i;
-		cdtoc[i-1].min = toc.TrackData[i - 1].Address[1];
-		cdtoc[i-1].sec = toc.TrackData[i - 1].Address[2];
-		cdtoc[i-1].frame = toc.TrackData[i - 1].Address[3];
-		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
-		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
-        }
-        toc.FirstTrack = 0xAA;
-        cdtoc[toc.LastTrack].min = toc.TrackData[toc.LastTrack].Address[1];
-        cdtoc[toc.LastTrack].sec = toc.TrackData[toc.LastTrack].Address[2];
-        cdtoc[toc.LastTrack].frame = toc.TrackData[toc.LastTrack].Address[3];
-        cdtoc[toc.LastTrack].frame += cdtoc[toc.LastTrack].min*60*75;
-        cdtoc[toc.LastTrack].frame += cdtoc[toc.LastTrack].sec*75;
-        CloseHandle(drive);
-        return toc.LastTrack;
-}
-
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
-int 
-read_toc(const char *dev) {
-	int drive;
-	struct ioc_toc_header tochdr;
-	struct ioc_read_toc_single_entry tocentry;
-	int i;
-
-	drive = open(dev, O_RDONLY | O_NONBLOCK);
-	if( drive<0 ) {
-		return drive;
-	}
-
-	ioctl(drive, CDIOREADTOCHEADER, &tochdr);
-	for (i = tochdr.starting_track; i <= tochdr.ending_track; i++) {
-		tocentry.track = i;
-		tocentry.address_format = CD_MSF_FORMAT;
-		ioctl(drive, CDIOREADTOCENTRY, &tocentry);
-		cdtoc[i-1].min = tocentry.entry.addr.msf.minute;
-		cdtoc[i-1].sec = tocentry.entry.addr.msf.second;
-		cdtoc[i-1].frame = tocentry.entry.addr.msf.frame;
-		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
-		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
-	}
-	tocentry.track = 0xAA;
-	tocentry.address_format = CD_MSF_FORMAT;
-	ioctl(drive, CDIOREADTOCENTRY, &tocentry);
-	cdtoc[tochdr.ending_track].min = tocentry.entry.addr.msf.minute;
-	cdtoc[tochdr.ending_track].sec = tocentry.entry.addr.msf.second;
-	cdtoc[tochdr.ending_track].frame = tocentry.entry.addr.msf.frame;
-	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].min*60*75;
-	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].sec*75;
-	close(drive);
-	return tochdr.ending_track;
-}
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-int
-read_toc(const char *dev) {
-	int drive;
-	struct ioc_toc_header tochdr;
-	struct ioc_read_toc_entry tocentry;
-	int i;
-	struct cd_toc_entry toc_buffer;
-
-	drive = open(dev, O_RDONLY | O_NONBLOCK);
-	if( drive<0 ) {
-		return drive;
-	}
-
-	ioctl(drive, CDIOREADTOCHEADER, &tochdr);
-	for (i = tochdr.starting_track; i <= tochdr.ending_track; i++) {
-		tocentry.starting_track = i;
-		tocentry.address_format = CD_MSF_FORMAT;
-		tocentry.data = &toc_buffer;
-		tocentry.data_len = sizeof(toc_buffer);
-		ioctl(drive, CDIOREADTOCENTRYS, &tocentry);
-		cdtoc[i-1].min = toc_buffer.addr.msf.minute;
-		cdtoc[i-1].sec = toc_buffer.addr.msf.second;
-		cdtoc[i-1].frame = toc_buffer.addr.msf.frame;
-		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
-		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
-	}
-	tocentry.starting_track = 0xAA;
-	tocentry.address_format = CD_MSF_FORMAT;
-	ioctl(drive, CDIOREADTOCENTRYS, &tocentry);
-	cdtoc[tochdr.ending_track].min = toc_buffer.addr.msf.minute;
-	cdtoc[tochdr.ending_track].sec = toc_buffer.addr.msf.second;
-	cdtoc[tochdr.ending_track].frame = toc_buffer.addr.msf.frame;
-	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].min*60*75;
-	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].sec*75;
-	close(drive);
-	return tochdr.ending_track;
-}
-#endif
-
-/** 
-\brief Reads TOC from CD in the given device and prints the number of tracks
-       and the length of each track in minute:second:frame format.
-\param *dev the device to analyse
-\return if the command line -identify is given, returns the last track of
-        the TOC or -1 if the TOC can't be read,
-        otherwise just returns 0 and let cddb_resolve the TOC
-*/
-int cdd_identify(const char *dev)
-{
-	cdtoc_last_track = 0;
-	if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
-	{
-		int i, min, sec, frame;
-		cdtoc_last_track = read_toc(dev);
-		if (cdtoc_last_track < 0) {
-			mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToOpenDevice, dev);
-			return -1;
-		}
-		mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_CDDA_TRACKS=%d\n", cdtoc_last_track);
-		for (i = 1; i <= cdtoc_last_track; i++)
-		{
-			frame = cdtoc[i].frame - cdtoc[i-1].frame;
-			sec = frame / 75;
-			frame -= sec * 75;
-			min = sec / 60;
-			sec -= min * 60;
-			mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDA_TRACK_%d_MSF=%02d:%02d:%02d\n", i, min, sec, frame);
-		}
-	}
-	return cdtoc_last_track;
-}
-
-unsigned int 
-cddb_sum(int n) {
-	unsigned int ret;
-
-	ret = 0;
-	while (n > 0) {
-		ret += (n % 10);
-		n /= 10;
-	}
-	return ret;
-}
-
-unsigned long 
-cddb_discid(int tot_trks) {
-	unsigned int i, t = 0, n = 0;
-
-	i = 0;
-	while (i < (unsigned int)tot_trks) {
-		n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
-		i++;
-	}
-	t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) -
-		((cdtoc[0].min * 60) + cdtoc[0].sec);
-	return ((n % 0xff) << 24 | t << 8 | tot_trks);
-}
-
-
-
-int
-cddb_http_request(char *command, int (*reply_parser)(HTTP_header_t*,cddb_data_t*), cddb_data_t *cddb_data) {
-	char request[4096];
-	int fd, ret = 0;
-	URL_t *url;
-	HTTP_header_t *http_hdr;
-	
-	if( reply_parser==NULL || command==NULL || cddb_data==NULL ) return -1;
-	
-	sprintf( request, "http://%s/~cddb/cddb.cgi?cmd=%s%s&proto=%d", cddb_data->freedb_server, command, cddb_data->cddb_hello, cddb_data->freedb_proto_level );
-	mp_msg(MSGT_OPEN, MSGL_INFO,"Request[%s]\n", request );
-
-	url = url_new(request);
-	if( url==NULL ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NotAValidURL);
-		return -1;
-	}
-	
-	fd = http_send_request(url,0);
-	if( fd<0 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToSendHTTPRequest);
-		return -1;
-	}
-
-	http_hdr = http_read_response( fd );
-	if( http_hdr==NULL ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToReadHTTPResponse);
-		return -1;
-	}
-
-	http_debug_hdr(http_hdr);
-	mp_msg(MSGT_OPEN, MSGL_INFO,"body=[%s]\n", http_hdr->body );
-
-	switch(http_hdr->status_code) {
-		case 200:
-			ret = reply_parser(http_hdr, cddb_data);
-			break;
-		case 400:
-			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_HTTPErrorNOTFOUND);
-			break;
-		default:
-			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_HTTPErrorUnknown);
-	}
-
-	http_free( http_hdr );
-	url_free( url );
-	
-	return ret;
-}
-
-int
-cddb_read_cache(cddb_data_t *cddb_data) {
-	char file_name[100];
-	struct stat stats;
-	int file_fd, ret;
-	size_t file_size;
-
-	if( cddb_data==NULL || cddb_data->cache_dir==NULL ) return -1;
-	
-	sprintf( file_name, "%s%08lx", cddb_data->cache_dir, cddb_data->disc_id);
-	
-	file_fd = open(file_name, O_RDONLY
-#ifdef WIN32
-	| O_BINARY
-#endif
-	);
-	if( file_fd<0 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NoCacheFound);
-		return -1;
-	}
-
-	ret = fstat( file_fd, &stats );
-	if( ret<0 ) {
-		perror("fstat");
-		file_size = 4096;
-	} else {
-		file_size = stats.st_size;
-	}
-	
-	cddb_data->xmcd_file = malloc(file_size);
-	if( cddb_data->xmcd_file==NULL ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
-		close(file_fd);
-		return -1;
-	}
-	cddb_data->xmcd_file_size = read(file_fd, cddb_data->xmcd_file, file_size);
-	if( cddb_data->xmcd_file_size!=file_size ) {
-		mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenRead);
-		close(file_fd);
-		return -1;
-	}
-	
-	close(file_fd);
-	
-	return 0;
-}
-
-int
-cddb_write_cache(cddb_data_t *cddb_data) {
-	// We have the file, save it for cache.
-	struct stat file_stat;
-	char file_name[100];
-	int file_fd, ret;
-	int wrote=0;
-
-	if( cddb_data==NULL || cddb_data->cache_dir==NULL ) return -1;
-
-	// Check if the CDDB cache dir exist
-	ret = stat( cddb_data->cache_dir, &file_stat );
-	if( ret<0 ) {
-		// Directory not present, create it.
-		ret = mkdir( cddb_data->cache_dir, 0755 );
-#ifdef __MINGW32__
-		if( ret<0 && errno != EEXIST ) {
-#else
-		if( ret<0 ) {
-#endif
-			perror("mkdir");
-			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToCreateDirectory, cddb_data->cache_dir);
-			return -1;
-		}
-	}
-	
-	sprintf( file_name, "%s%08lx", cddb_data->cache_dir, cddb_data->disc_id );
-	
-	file_fd = creat(file_name, S_IREAD|S_IWRITE);
-	if( file_fd<0 ) {
-		perror("create");
-		return -1;
-	}
-	
-	wrote = write(file_fd, cddb_data->xmcd_file, cddb_data->xmcd_file_size);
-	if( wrote<0 ) {
-		perror("write");
-		close(file_fd);
-		return -1;
-	}
-	if( (unsigned int)wrote!=cddb_data->xmcd_file_size ) {
-		mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenWritten);
-		close(file_fd);
-		return -1;
-	}
-	
-	close(file_fd);
-
-	return 0;
-}
-
-int
-cddb_read_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
-	unsigned long disc_id;
-	char category[100];
-	char *ptr=NULL, *ptr2=NULL;
-	int ret, status;
-
-	if( http_hdr==NULL || cddb_data==NULL ) return -1;
-	
-	ret = sscanf( http_hdr->body, "%d ", &status);
-	if( ret!=1 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-		return -1;
-	}
-
-	switch(status) {
-		case 210:
-			ret = sscanf( http_hdr->body, "%d %s %08lx", &status, category, &disc_id);
-			if( ret!=3 ) {
-				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-				return -1;
-			}
-			// Check if it's a xmcd database file
-			ptr = strstr(http_hdr->body, "# xmcd");
-			if( ptr==NULL ) {
-				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_InvalidXMCDDatabaseReturned);
-				return -1;
-			}
-			// Ok found the beginning of the file
-			// look for the end
-			ptr2 = strstr(ptr, "\r\n.\r\n");
-			if( ptr2==NULL ) {
-				ptr2 = strstr(ptr, "\n.\n");
-				if( ptr2==NULL ) {
-					mp_msg(MSGT_DEMUX, MSGL_FIXME, "Unable to find '.'\n");
-					ptr2=ptr+strlen(ptr); //return -1;
-				}
-			}
-			// Ok found the end
-			// do a sanity check
-			if( http_hdr->body_size<(unsigned int)(ptr2-ptr) ) {
-				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_UnexpectedFIXME);
-				return -1;
-			}
-			cddb_data->xmcd_file = ptr;
-			cddb_data->xmcd_file_size = ptr2-ptr+2;
-			cddb_data->xmcd_file[cddb_data->xmcd_file_size] = '\0';
-			// Avoid the http_free function to free the xmcd file...save a mempcy...
-			http_hdr->body = NULL;
-			http_hdr->body_size = 0;
-			return cddb_write_cache(cddb_data);
-		default:
-			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);
-	}
-	return 0;
-}
-
-int
-cddb_request_titles(cddb_data_t *cddb_data) {
-	char command[1024];
-	sprintf( command, "cddb+read+%s+%08lx", cddb_data->category, cddb_data->disc_id);
-	return cddb_http_request(command, cddb_read_parse, cddb_data); 
-}
-
-int
-cddb_parse_matches_list(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
-	char album_title[100];
-	char *ptr = NULL;
-	int ret;
-	
-	ptr = strstr(http_hdr->body, "\n");
-	if( ptr==NULL ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_UnableToFindEOL);
-		return -1;
-	}
-	ptr++;
-	// We have a list of exact/inexact matches, so which one do we use?
-	// So let's take the first one.
-	ret = sscanf(ptr, "%s %08lx %s", cddb_data->category, &(cddb_data->disc_id), album_title);
-	if( ret!=3 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-		return -1;
-	}
-	ptr = strstr(http_hdr->body, album_title);
-	if( ptr!=NULL ) {
-		char *ptr2;
-		int len;
-		ptr2 = strstr(ptr, "\n");
-		if( ptr2==NULL ) {
-			len = (http_hdr->body_size)-(ptr-(http_hdr->body));
-		} else {
-			len = ptr2-ptr+1;
-		}
-		strncpy(album_title, ptr, len);
-		album_title[len-2]='\0';
-	}
-	mp_msg(MSGT_DEMUX, MSGL_STATUS, MSGTR_MPDEMUX_CDDB_ParseOKFoundAlbumTitle, album_title);
-	return 0;
-}
-
-int
-cddb_query_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
-	char album_title[100];
-	char *ptr = NULL;
-	int ret, status;
-	
-	ret = sscanf( http_hdr->body, "%d ", &status);
-	if( ret!=1 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-		return -1;
-	}
-
-	switch(status) {
-		case 200:
-			// Found exact match
-			ret = sscanf(http_hdr->body, "%d %s %08lx %s", &status, cddb_data->category, &(cddb_data->disc_id), album_title);
-			if( ret!=4 ) {
-				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-				return -1;
-			}
-			ptr = strstr(http_hdr->body, album_title);
-			if( ptr!=NULL ) {
-				char *ptr2;
-				int len;
-				ptr2 = strstr(ptr, "\n");
-				if( ptr2==NULL ) {
-					len = (http_hdr->body_size)-(ptr-(http_hdr->body));
-				} else {
-					len = ptr2-ptr+1;
-				}
-				strncpy(album_title, ptr, len);
-				album_title[len-2]='\0';
-			}
-			mp_msg(MSGT_DEMUX, MSGL_STATUS, MSGTR_MPDEMUX_CDDB_ParseOKFoundAlbumTitle, album_title);
-			return cddb_request_titles(cddb_data);
-		case 202:
-			// No match found
-			mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_CDDB_AlbumNotFound);
-			break;
-		case 210:
-			// Found exact matches, list follows
-			cddb_parse_matches_list(http_hdr, cddb_data);
-			return cddb_request_titles(cddb_data);
-/*
-body=[210 Found exact matches, list follows (until terminating `.')
-misc c711930d Santana / Supernatural
-rock c711930d Santana / Supernatural
-blues c711930d Santana / Supernatural
-.]
-*/	
-		case 211:
-			// Found inexact matches, list follows
-			cddb_parse_matches_list(http_hdr, cddb_data);
-			return cddb_request_titles(cddb_data);
-		case 500:
-			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_ServerReturnsCommandSyntaxErr);
-			break;
-		default:
-			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);	
-	}
-	return -1;
-}
-
-int
-cddb_proto_level_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
-	int max;
-	int ret, status;
-	char *ptr;
-	
-	ret = sscanf( http_hdr->body, "%d ", &status);
-	if( ret!=1 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);	
-		return -1;
-	}
-
-	switch(status) {
-		case 210:
-			ptr = strstr(http_hdr->body, "max proto:");
-			if( ptr==NULL ) {
-				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-				return -1;
-			}
-			ret = sscanf(ptr, "max proto: %d", &max);
-			if( ret!=1 ) {
-				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-				return -1;
-			}
-			cddb_data->freedb_proto_level = max;
-			return 0;
-		default:
-			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);	
-	}
-	return -1;
-}
-
-int
-cddb_get_proto_level(cddb_data_t *cddb_data) {
-	return cddb_http_request("stat", cddb_proto_level_parse, cddb_data);
-}
-
-int
-cddb_freedb_sites_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
-	int ret, status;
-
-	ret = sscanf( http_hdr->body, "%d ", &status);
-	if( ret!=1 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
-		return -1;
-	}
-
-	switch(status) {
-		case 210:
-			// TODO: Parse the sites
-			ret = cddb_data->anonymous;	// For gcc complaining about unused parameter.
-			return 0;
-		case 401:
-			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_NoSitesInfoAvailable);
-			break;
-		default:
-			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);
-	}
-	return -1;
-}
-
-int
-cddb_get_freedb_sites(cddb_data_t *cddb_data) {
-	return cddb_http_request("sites", cddb_freedb_sites_parse, cddb_data);
-}
-
-void
-cddb_create_hello(cddb_data_t *cddb_data) {
-	char host_name[51];
-	char *user_name;
-	
-	if( cddb_data->anonymous ) {	// Default is anonymous
-		/* Note from Eduardo Pérez Ureta <eperez@it.uc3m.es> : 
-		 * We don't send current user/host name in hello to prevent spam.
-		 * Software that sends this is considered spyware
-		 * that most people don't like.
-		 */
-		user_name = "anonymous";
-		strcpy(host_name, "localhost");
-	} else {
-		if( gethostname(host_name, 50)<0 ) {
-			strcpy(host_name, "localhost");
-		}
-		user_name = getenv("LOGNAME");
-	}
-	sprintf( cddb_data->cddb_hello, "&hello=%s+%s+%s+%s", user_name, host_name, "MPlayer", VERSION );
-}
-
-int 
-cddb_retrieve(cddb_data_t *cddb_data) {
-	char offsets[1024], command[1024];
-	char *ptr;
-	unsigned int i, time_len;
-	int ret;
-
-	ptr = offsets;
-	for( i=0; i<cddb_data->tracks ; i++ ) {
-		ptr += sprintf(ptr, "%d+", cdtoc[i].frame );
-		if (ptr-offsets > sizeof offsets - 40) break;
-	}
-	ptr[0]=0;
-	time_len = (cdtoc[cddb_data->tracks].frame)/75;
-	
-	cddb_data->freedb_server = DEFAULT_FREEDB_SERVER;
-	cddb_data->freedb_proto_level = 1;
-	cddb_data->xmcd_file = NULL;
-
-	cddb_create_hello(cddb_data);
-	if( cddb_get_proto_level(cddb_data)<0 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToGetProtocolLevel);
-		return -1;
-	}
-
-	//cddb_get_freedb_sites(&cddb_data);
-
-	sprintf(command, "cddb+query+%08lx+%d+%s%d", cddb_data->disc_id, cddb_data->tracks, offsets, time_len );
-	ret = cddb_http_request(command, cddb_query_parse, cddb_data);
-	if( ret<0 ) return -1;
-
-	if( cddb_data->cache_dir!=NULL ) {
-		free(cddb_data->cache_dir);
-	}
-	return 0;
-}
-
-int
-cddb_resolve(const char *dev, char **xmcd_file) {
-	char cddb_cache_dir[] = DEFAULT_CACHE_DIR;
-	char *home_dir = NULL;
-	cddb_data_t cddb_data;
-
-	if (cdtoc_last_track <= 0)
-	{
-	    cdtoc_last_track = read_toc(dev);
-	    if (cdtoc_last_track < 0) {
-		mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToOpenDevice, dev);
-		return -1;
-	    }
-	}
-	cddb_data.tracks = cdtoc_last_track;
-	cddb_data.disc_id = cddb_discid(cddb_data.tracks);
-	cddb_data.anonymous = 1;	// Don't send user info by default
-
-	// Check if there is a CD in the drive
-	// FIXME: That's not really a good way to check
-	if( cddb_data.disc_id==0 ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NoCDInDrive);
-		return -1;
-	}
-	
-	home_dir = getenv("HOME");
-#ifdef __MINGW32__
-	if( home_dir==NULL ) home_dir = getenv("USERPROFILE");
-	if( home_dir==NULL ) home_dir = getenv("HOMEPATH");
-	// Last resort, store the cddb cache in the mplayer directory
-	if( home_dir==NULL ) home_dir = (char *)get_path("");
-#endif
-	if( home_dir==NULL ) {
-		cddb_data.cache_dir = NULL;
-	} else {
-		cddb_data.cache_dir = malloc(strlen(home_dir)+strlen(cddb_cache_dir)+1);
-		if( cddb_data.cache_dir==NULL ) {
-			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
-			return -1;
-		}
-		sprintf(cddb_data.cache_dir, "%s%s", home_dir, cddb_cache_dir );
-	}
-
-	// Check for a cached file
-	if( cddb_read_cache(&cddb_data)<0 ) {
-		// No Cache found
-		if( cddb_retrieve(&cddb_data)<0 ) {
-			return -1;
-		}
-	}
-
-	if( cddb_data.xmcd_file!=NULL ) {
-//		printf("%s\n", cddb_data.xmcd_file );
-		*xmcd_file = cddb_data.xmcd_file;
-		return 0;
-	}
-	
-	return -1;
-}
-
-/*******************************************************************************************************************
- *
- * xmcd parser
- *
- *******************************************************************************************************************/
-char*
-xmcd_parse_dtitle(cd_info_t *cd_info, char *line) {
-	char *ptr, *album;
-	ptr = strstr(line, "DTITLE=");
-	if( ptr!=NULL ) {
-		ptr += 7;
-		album = strstr(ptr, "/");
-		if( album==NULL ) return NULL;
-		cd_info->album = malloc(strlen(album+2)+1);
-		if( cd_info->album==NULL ) {
-			return NULL;
-		}
-		strcpy( cd_info->album, album+2 );
-		album--;
-		album[0] = '\0';
-		cd_info->artist = malloc(strlen(ptr)+1);
-		if( cd_info->artist==NULL ) {
-			return NULL;
-		}
-		strcpy( cd_info->artist, ptr );
-	}
-	return ptr;
-}
-
-char*
-xmcd_parse_dgenre(cd_info_t *cd_info, char *line) {
-	char *ptr;
-	ptr = strstr(line, "DGENRE=");
-	if( ptr!=NULL ) {
-		ptr += 7;
-		cd_info->genre = malloc(strlen(ptr)+1);
-		if( cd_info->genre==NULL ) {
-			return NULL;
-		}
-		strcpy( cd_info->genre, ptr );
-	}
-	return ptr;
-}
-
-char*
-xmcd_parse_ttitle(cd_info_t *cd_info, char *line) {
-	unsigned int track_nb;
-	unsigned long sec, off;
-	char *ptr;
-	ptr = strstr(line, "TTITLE");
-	if( ptr!=NULL ) {
-		ptr += 6;
-		// Here we point to the track number
-		track_nb = atoi(ptr);
-		ptr = strstr(ptr, "=");
-		if( ptr==NULL ) return NULL;
-		ptr++;
-		
-		sec = cdtoc[track_nb].frame;
-		off = cdtoc[track_nb+1].frame-sec+1;
-
-		cd_info_add_track( cd_info, ptr, track_nb+1, (unsigned int)(off/(60*75)), (unsigned int)((off/75)%60), (unsigned int)(off%75), sec, off );
-	}
-	return ptr;
-}
-
-cd_info_t*
-cddb_parse_xmcd(char *xmcd_file) {
-	cd_info_t *cd_info = NULL;
-	int length, pos = 0;
-	char *ptr, *ptr2;
-	unsigned int audiolen;
-	if( xmcd_file==NULL ) return NULL;
-	
-	cd_info = cd_info_new();
-	if( cd_info==NULL ) {
-		return NULL;
-	}
-	
-	length = strlen(xmcd_file);
-	ptr = xmcd_file;
-	while( ptr!=NULL && pos<length ) {
-		// Read a line
-		ptr2 = ptr;
-		while( ptr2[0]!='\0' && ptr2[0]!='\r' && ptr2[0]!='\n' ) ptr2++;
-		if( ptr2[0]=='\0' ) {
-			break;
-		}
-		ptr2[0] = '\0';
-		// Ignore comments
-		if( ptr[0]!='#' ) {
-			// Search for the album title
-			if( xmcd_parse_dtitle(cd_info, ptr) );
-			// Search for the genre
-			else if( xmcd_parse_dgenre(cd_info, ptr) );
-			// Search for a track title
-			else if( xmcd_parse_ttitle(cd_info, ptr) ) audiolen++;	// <-- audiolen++ to shut up gcc warning
-		}
-		if( ptr2[1]=='\n' ) ptr2++;
-		pos = (ptr2+1)-ptr;
-		ptr = ptr2+1;
-	}
-
-	audiolen = cdtoc[cd_info->nb_tracks].frame-cdtoc[0].frame;	
-	cd_info->min  = (unsigned int)(audiolen/(60*75));
-	cd_info->sec  = (unsigned int)((audiolen/75)%60);
-	cd_info->msec = (unsigned int)(audiolen%75);
-	
-	return cd_info;
-}
--- a/libmpdemux/cdinfo.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * CD Info 
- * by Bertrand Baudet <bertrand_baudet@yahoo.com>
- * (C) 2002, MPlayer team.
-*/
-
-#include "config.h"
-
-#if defined(HAVE_CDDA) 
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "mp_msg.h"
-#include "help_mp.h"
-#include "cdd.h"
-
-/*******************************************************************************************************************
- *
- * xmcd parser, cd info list
- *
- *******************************************************************************************************************/
-
-cd_info_t*
-cd_info_new() {
-	cd_info_t *cd_info = NULL;
-	
-	cd_info = malloc(sizeof(cd_info_t));
-	if( cd_info==NULL ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
-		return NULL;
-	}
-	
-	memset(cd_info, 0, sizeof(cd_info_t));
-	
-	return cd_info;
-}
-
-void
-cd_info_free(cd_info_t *cd_info) {
-	cd_track_t *cd_track, *cd_track_next;
-	if( cd_info==NULL ) return;
-	if( cd_info->artist!=NULL ) free(cd_info->artist);
-	if( cd_info->album!=NULL ) free(cd_info->album);
-	if( cd_info->genre!=NULL ) free(cd_info->genre);
-
-	cd_track_next = cd_info->first;
-	while( cd_track_next!=NULL ) {
-		cd_track = cd_track_next;
-		cd_track_next = cd_track->next;
-		if( cd_track->name!=NULL ) free(cd_track->name);
-		free(cd_track);
-	}
-}
-
-cd_track_t*
-cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length) {
-	cd_track_t *cd_track;
-	
-	if( cd_info==NULL || track_name==NULL ) return NULL;
-	
-	cd_track = malloc(sizeof(cd_track_t));
-	if( cd_track==NULL ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
-		return NULL;
-	}
-	memset(cd_track, 0, sizeof(cd_track_t));
-	
-	cd_track->name = malloc(strlen(track_name)+1);
-	if( cd_track->name==NULL ) {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
-		free(cd_track);
-		return NULL;
-	}
-	strcpy(cd_track->name, track_name);
-	cd_track->track_nb = track_nb;
-	cd_track->min = min;
-	cd_track->sec = sec;
-	cd_track->msec = msec;
-	cd_track->frame_begin = frame_begin;
-	cd_track->frame_length = frame_length;
-
-	if( cd_info->first==NULL ) {
-		cd_info->first = cd_track;
-	}
-	if( cd_info->last!=NULL ) {
-		cd_info->last->next = cd_track;
-	}
-
-	cd_track->prev = cd_info->last;
-	
-	cd_info->last = cd_track;
-	cd_info->current = cd_track;
-
-	cd_info->nb_tracks++;
-	
-	return cd_track;
-}
-
-cd_track_t*
-cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb) {
-	cd_track_t *cd_track=NULL;
-
-	if( cd_info==NULL ) return NULL;
-
-	cd_track = cd_info->first;
-	while( cd_track!=NULL ) {
-		if( cd_track->track_nb==track_nb ) {
-			return cd_track;
-		}
-		cd_track = cd_track->next;
-	}
-	return NULL;
-}
-
-void
-cd_info_debug(cd_info_t *cd_info) {
-	cd_track_t *current_track;
-	printf("================ CD INFO === start =========\n");
-	if( cd_info==NULL ) {
-		printf("cd_info is NULL\n");
-		return;
-	}
-	printf(" artist=[%s]\n", cd_info->artist);
-	printf(" album=[%s]\n", cd_info->album);
-	printf(" genre=[%s]\n", cd_info->genre);
-	printf(" nb_tracks=%d\n", cd_info->nb_tracks);
-	printf(" length= %2d:%02d.%02d\n", cd_info->min, cd_info->sec, cd_info->msec);
-	current_track = cd_info->first;
-	while( current_track!=NULL ) {
-		printf("  #%2d %2d:%02d.%02d @ %7ld\t[%s] \n", current_track->track_nb, current_track->min, current_track->sec, current_track->msec, current_track->frame_begin, current_track->name);
-		current_track = current_track->next;
-	}
-	printf("================ CD INFO ===  end  =========\n");
-}
-
-#endif
--- a/libmpdemux/cookies.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-/*
- * HTTP Cookies
- * Reads Netscape and Mozilla cookies.txt files
- *
- * by Dave Lambley <mplayer@davel.me.uk>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <inttypes.h>
-
-#include "cookies.h"
-#include "http.h"
-#include "mp_msg.h"
-
-#define MAX_COOKIES 20
-
-char *cookies_file = NULL;
-
-typedef struct cookie_list_type {
-    char *name;
-    char *value;
-    char *domain;
-    char *path;
-
-    int secure;
-
-    struct cookie_list_type *next;
-} cookie_list_t;
-
-/* Pointer to the linked list of cookies */
-static struct cookie_list_type *cookie_list = NULL;
-
-
-/* Like strdup, but stops at anything <31. */
-static char *col_dup(const char *src)
-{
-    char *dst;
-    int length = 0;
-
-    while (src[length] > 31)
-	length++;
-
-    dst = malloc(length + 1);
-    strncpy(dst, src, length);
-    dst[length] = 0;
-
-    return dst;
-}
-
-static int right_hand_strcmp(const char *cookie_domain, const char *url_domain)
-{
-    int c_l;
-    int u_l;
-
-    c_l = strlen(cookie_domain);
-    u_l = strlen(url_domain);
-
-    if (c_l > u_l)
-	return -1;
-    return strcmp(cookie_domain, url_domain + u_l - c_l);
-}
-
-static int left_hand_strcmp(const char *cookie_path, const char *url_path)
-{
-    return strncmp(cookie_path, url_path, strlen(cookie_path));
-}
-
-/* Finds the start of all the columns */
-static int parse_line(char **ptr, char *cols[6])
-{
-    int col;
-    cols[0] = *ptr;
-
-    for (col = 1; col < 7; col++) {
-	for (; (**ptr) > 31; (*ptr)++);
-	if (**ptr == 0)
-	    return 0;
-	(*ptr)++;
-	if ((*ptr)[-1] != 9)
-	    return 0;
-	cols[col] = (*ptr);
-    }
-
-    return 1;
-}
-
-/* Loads a file into RAM */
-static char *load_file(const char *filename, off_t * length)
-{
-    int fd;
-    char *buffer;
-
-    mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
-
-    fd = open(filename, O_RDONLY);
-    if (fd < 0) {
-	mp_msg(MSGT_NETWORK, MSGL_V, "Could not open");
-	return NULL;
-    }
-
-    *length = lseek(fd, 0, SEEK_END);
-
-    if (*length < 0) {
-	mp_msg(MSGT_NETWORK, MSGL_V, "Could not find EOF");
-	return NULL;
-    }
-
-    if (*length > SIZE_MAX - 1) {
-	mp_msg(MSGT_NETWORK, MSGL_V, "File too big, could not malloc.");
-	return NULL;
-    }
-
-    lseek(fd, SEEK_SET, 0);
-
-    if (!(buffer = malloc(*length + 1))) {
-	mp_msg(MSGT_NETWORK, MSGL_V, "Could not malloc.");
-	return NULL;
-    }
-
-    if (read(fd, buffer, *length) != *length) {
-	mp_msg(MSGT_NETWORK, MSGL_V, "Read is behaving funny.");
-	return NULL;
-    }
-    close(fd);
-    buffer[*length] = 0;
-
-    return buffer;
-}
-
-/* Loads a cookies.txt file into a linked list. */
-static struct cookie_list_type *load_cookies_from(const char *filename,
-						  struct cookie_list_type
-						  *list)
-{
-    char *ptr;
-    off_t length;
-
-    mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
-
-    ptr = load_file(filename, &length);
-    if (!ptr)
-	return list;
-
-    while (*ptr > 0) {
-	char *cols[7];
-	if (parse_line(&ptr, cols)) {
-	    struct cookie_list_type *new;
-	    new = malloc(sizeof(cookie_list_t));
-	    new->name = col_dup(cols[5]);
-	    new->value = col_dup(cols[6]);
-	    new->path = col_dup(cols[2]);
-	    new->domain = col_dup(cols[0]);
-	    new->secure = (*(cols[3]) == 't') || (*(cols[3]) == 'T');
-	    new->next = list;
-	    list = new;
-	}
-    }
-    return list;
-}
-
-/* Attempt to load cookies.txt from various locations. Returns a pointer to the linked list contain the cookies. */
-static struct cookie_list_type *load_cookies(void)
-{
-    DIR *dir;
-    struct dirent *ent;
-    struct cookie_list_type *list = NULL;
-    char *buf;
-
-    char *homedir;
-
-    if (cookies_file)
-	return load_cookies_from(cookies_file, list);
-
-    homedir = getenv("HOME");
-    if (!homedir)
-	return list;
-
-
-    buf = malloc(strlen(homedir) + sizeof("/.mozilla/default") + 1);
-    sprintf(buf, "%s/.mozilla/default", homedir);
-    dir = opendir(buf);
-    free(buf);
-
-    if (dir) {
-	while ((ent = readdir(dir)) != NULL) {
-	    if ((ent->d_name)[0] != '.') {
-		buf = malloc(strlen(getenv("HOME")) + 
-                             sizeof("/.mozilla/default/") + 
-                             strlen(ent->d_name) + sizeof("cookies.txt") + 1);
-		sprintf(buf, "%s/.mozilla/default/%s/cookies.txt",
-			 getenv("HOME"), ent->d_name);
-		list = load_cookies_from(buf, list);
-		free(buf);
-	    }
-	}
-	closedir(dir);
-    }
-
-    buf = malloc(strlen(homedir) + sizeof("/.netscape/cookies.txt") + 1);
-    sprintf(buf, "%s/.netscape/cookies.txt", homedir);
-    list = load_cookies_from(buf, list);
-    free(buf);
-
-    return list;
-}
-
-/* Take an HTTP_header_t, and insert the correct headers. The cookie files are read if necessary. */
-void
-cookies_set(HTTP_header_t * http_hdr, const char *domain, const char *url)
-{
-    int found_cookies = 0;
-    struct cookie_list_type *cookies[MAX_COOKIES];
-    struct cookie_list_type *list, *start;
-    int i;
-    char *path;
-    char *buf;
-
-    path = strchr(url, '/');
-    if (!path)
-	path = "";
-
-    if (!cookie_list)
-	cookie_list = load_cookies();
-
-
-    list = start = cookie_list;
-
-    /* Find which cookies we want, removing duplicates. Cookies with the longest domain, then longest path take priority */
-    while (list) {
-	/* Check the cookie domain and path. Also, we never send "secure" cookies. These should only be sent over HTTPS. */
-	if ((right_hand_strcmp(list->domain, domain) == 0)
-	    && (left_hand_strcmp(list->path, path) == 0) && !list->secure) {
-	    int replacing = 0;
-	    for (i = 0; i < found_cookies; i++) {
-		if (strcmp(list->name, cookies[i]->name) == 0) {
-		    replacing = 0;
-		    if (strlen(list->domain) <= strlen(cookies[i]->domain)) {
-			cookies[i] = list;
-		    } else if (strlen(list->path) <= strlen(cookies[i]->path)) {
-			cookies[i] = list;
-		    }
-		}
-	    }
-	    if (found_cookies > MAX_COOKIES) {
-		/* Cookie jar overflow! */
-		break;
-	    }
-	    if (!replacing)
-		cookies[found_cookies++] = list;
-	}
-	list = list->next;
-    }
-
-
-    buf = strdup("Cookie:");
-
-    for (i = 0; i < found_cookies; i++) {
-	char *nbuf;
-
-	nbuf = malloc(strlen(buf) + strlen(" ") + strlen(cookies[i]->name) +
-		    strlen("=") + strlen(cookies[i]->value) + strlen(";") + 1);
-	sprintf(nbuf, "%s %s=%s;", buf, cookies[i]->name,
-		 cookies[i]->value);
-	free(buf);
-	buf = nbuf;
-    }
-
-    if (found_cookies)
-	http_set_field(http_hdr, buf);
-    else
-	free(buf);
-}
--- a/libmpdemux/cookies.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*
- * HTTP Cookies
- * Reads Netscape and Mozilla cookies.txt files
- * 
- * by Dave Lambley <mplayer@davel.me.uk>
- */
-
-#ifndef __COOKIES_H
-#define __COOKIES_H
-
-#include "http.h"
-
-extern void cookies_set(HTTP_header_t * http_hdr, const char *hostname,
-			const char *url);
-
-#endif
--- a/libmpdemux/cue_read.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,604 +0,0 @@
-//=================== VideoCD BinCue ==========================
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#include "stream.h"
-
-#include "cue_read.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-#define byte    unsigned char
-#define SIZERAW 2352
-#define SIZEISO_MODE1 2048
-#define SIZEISO_MODE2_RAW 2352
-#define SIZEISO_MODE2_FORM1 2048
-#define SIZEISO_MODE2_FORM2 2336
-#define AUDIO 0
-#define MODE1 1
-#define MODE2 2
-#define MODE1_2352 10
-#define MODE2_2352 20
-#define MODE1_2048 30
-#define MODE2_2336 40
-#define UNKNOWN -1
-
-static struct stream_priv_s {
-  char* filename;
-} stream_priv_dflts = {
-  NULL
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  { "string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-static struct m_struct_st stream_opts = {
-  "cue",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-static FILE* fd_cue;
-static int fd_bin = 0;
-
-static char bin_filename[256];
-
-static char cue_filename[256];
-static char bincue_path[256];
-
-
-typedef struct track
-{
-   unsigned short mode;
-   unsigned short minute;
-   unsigned short second;
-   unsigned short frame;
-
-   /* (min*60 + sec) * 75 + fps   */
-
-   unsigned long start_sector;
-
-   /* = the sizes in bytes off all tracks bevor this one */
-   /* its needed if there are mode1 tracks befor the mpeg tracks */
-   unsigned long start_offset;
-
-   /*   unsigned char num[3]; */
-} tTrack;
-
-/* max 99 tracks on a cd */
-static tTrack tracks[100];
-
-static struct cue_track_pos {
-  int track;
-  unsigned short mode;
-  unsigned short minute;
-  unsigned short second;
-  unsigned short frame;
-} cue_current_pos;
-
-/* number of tracks on the cd */
-static int nTracks = 0;
-
-/* presumes Line is preloaded with the "current" line of the file */
-static int cue_getTrackinfo(char *Line, tTrack *track)
-{
-  char inum[3];
-  char min;
-  char sec;
-  char fps;
-  int already_set = 0;
-
-  /* Get the 'mode' */
-  if (strncmp(&Line[2], "TRACK ", 6)==0)
-  {
-/*    strncpy(track->num, &Line[8], 2); track->num[2] = '\0'; */
-
-    track->mode = UNKNOWN;
-    if(strncmp(&Line[11], "AUDIO", 5)==0) track->mode = AUDIO;
-    if(strncmp(&Line[11], "MODE1/2352", 10)==0) track->mode = MODE1_2352;
-    if(strncmp(&Line[11], "MODE1/2048", 10)==0) track->mode = MODE1_2048;
-    if(strncmp(&Line[11], "MODE2/2352", 10)==0) track->mode = MODE2_2352;
-    if(strncmp(&Line[11], "MODE2/2336", 10)==0) track->mode = MODE2_2336;
-  }
-  else return(1);
-
-  /* Get the track indexes */
-  while(1) {
-    if(! fgets( Line, 256, fd_cue ) ) { break;}
-
-    if (strncmp(&Line[2], "TRACK ", 6)==0)
-    {
-      /* next track starting */
-      break;
-    }
-
-    /* Track 0 or 1, take the first an get fill the values*/
-    if (strncmp(&Line[4], "INDEX ", 6)==0)
-    {
-      /* check stuff here so if the answer is false the else stuff below won't be executed */
-      strncpy(inum, &Line[10], 2); inum[2] = '\0';
-      if ((already_set == 0) &&
-          ((strcmp(inum, "00")==0) || (strcmp(inum, "01")==0)))
-      {
-        already_set = 1;
-
-        min = ((Line[13]-'0')<<4) | (Line[14]-'0');
-        sec = ((Line[16]-'0')<<4) | (Line[17]-'0');
-        fps = ((Line[19]-'0')<<4) | (Line[20]-'0');
-
-        track->minute = (((min>>4)*10) + (min&0xf));
-        track->second = (((sec>>4)*10) + (sec&0xf));
-        track->frame  = (((fps>>4)*10) + (fps&0xf));
-      }
-    }
-    else if (strncmp(&Line[4], "PREGAP ", 7)==0) { ; /* ignore */ }
-    else if (strncmp(&Line[4], "FLAGS ", 6)==0)  { ; /* ignore */ }
-    else mp_msg (MSGT_OPEN,MSGL_INFO,
-                 MSGTR_MPDEMUX_CUEREAD_UnexpectedCuefileLine, Line);
-  }
-  return(0);
-}
-
-
-
-/* FIXME: the string operations ( strcpy,strcat ) below depend
- * on the arrays to have the same size, thus we need to make
- * sure the sizes are in sync.
- */
-static int cue_find_bin (char *firstline) {
-  int i,j;
-  char s[256];
-  char t[256];
-
-  /* get the filename out of that */
-  /*                      12345 6  */
-  mp_msg (MSGT_OPEN,MSGL_INFO, "[bincue] cue_find_bin(%s)\n", firstline);
-  if (strncmp(firstline, "FILE \"",6)==0)
-  {
-    i = 0;
-    j = 0;
-    while ( firstline[6 + i] != '"')
-    {
-      bin_filename[j] = firstline[6 + i];
-
-      /* if I found a path info, than delete all bevor it */
-      switch (bin_filename[j])
-      {
-        case '\\':
-          j = 0;
-          break;
-
-        case '/':
-          j = 0;
-          break;
-
-        default:
-          j++;
-      }
-      i++;
-    }
-    bin_filename[j+1] = '\0';
-
-  }
-
-  /* now try to open that file, without path */
-  fd_bin = open (bin_filename, O_RDONLY);
-  if (fd_bin == -1)
-  {
-    mp_msg(MSGT_OPEN,MSGL_STATUS, MSGTR_MPDEMUX_CUEREAD_BinFilenameTested,
-           bin_filename);
-
-    /* now try to find it with the path of the cue file */
-    snprintf(s,sizeof( s ),"%s/%s",bincue_path,bin_filename);
-    fd_bin = open (s, O_RDONLY);
-    if (fd_bin == -1)
-    {
-      mp_msg(MSGT_OPEN,MSGL_STATUS,
-             MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
-      /* now I would say the whole filename is shit, build our own */
-      strncpy(s, cue_filename, strlen(cue_filename) - 3 );
-      s[strlen(cue_filename) - 3] = '\0';
-      strcat(s, "bin");
-      fd_bin = open (s, O_RDONLY);
-      if (fd_bin == -1)
-      {
-        mp_msg(MSGT_OPEN,MSGL_STATUS,
-               MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
-
-        /* ok try it with path */
-        snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
-        fd_bin = open (t, O_RDONLY);
-        if (fd_bin == -1)
-        {
-          mp_msg(MSGT_OPEN,MSGL_STATUS,
-                 MSGTR_MPDEMUX_CUEREAD_BinFilenameTested,t);
-          /* now I would say the whole filename is shit, build our own */
-          strncpy(s, cue_filename, strlen(cue_filename) - 3 );
-          s[strlen(cue_filename) - 3] = '\0';
-          strcat(s, "img");
-          fd_bin = open (s, O_RDONLY);
-          if (fd_bin == -1)
-          {
-            mp_msg(MSGT_OPEN,MSGL_STATUS,
-                   MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
-            /* ok try it with path */
-            snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
-            fd_bin = open (t, O_RDONLY);
-            if (fd_bin == -1)
-            {
-              mp_msg(MSGT_OPEN,MSGL_STATUS,
-                     MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
-
-              /* I'll give up */
-              mp_msg(MSGT_OPEN,MSGL_ERR,
-                     MSGTR_MPDEMUX_CUEREAD_CannotFindBinFile);
-              return -1;
-            }
-          }
-        } else strcpy(bin_filename, t);
-
-      } else strcpy(bin_filename, s);
-
-    } else strcpy(bin_filename, s);
-
-  }
-
-  mp_msg(MSGT_OPEN,MSGL_INFO,
-         MSGTR_MPDEMUX_CUEREAD_UsingBinFile, bin_filename);
-  return 0;
-}
-
-static inline int cue_msf_2_sector(int minute, int second, int frame) {
- return frame + (second + minute * 60 ) * 75;
-}
-
-static inline int cue_get_msf(void) {
-  return cue_msf_2_sector (cue_current_pos.minute,
-                           cue_current_pos.second,
-                           cue_current_pos.frame);
-}
-
-static inline void cue_set_msf(unsigned int sect){
-  cue_current_pos.frame=sect%75;
-  sect=sect/75;
-  cue_current_pos.second=sect%60;
-  sect=sect/60;
-  cue_current_pos.minute=sect;
-}
-
-static inline int cue_mode_2_sector_size(int mode)
-{
-  switch (mode)
-  {
-    case AUDIO:      return AUDIO;
-    case MODE1_2352: return SIZERAW;
-    case MODE1_2048: return SIZEISO_MODE1;
-    case MODE2_2352: return SIZEISO_MODE2_RAW;
-    case MODE2_2336: return SIZEISO_MODE2_FORM2;
-
-    default:
-      mp_msg(MSGT_OPEN,MSGL_FATAL,
-             MSGTR_MPDEMUX_CUEREAD_UnknownModeForBinfile);
-      abort();
-  }
-
-}
-
-
-static int cue_read_cue (char *in_cue_filename)
-{
-  struct stat filestat;
-  char sLine[256];
-  unsigned int sect;
-  char *s,*t;
-  int i;
-
-  /* we have no tracks at the beginning */
-  nTracks = 0;
-
-  fd_bin = 0;
-
-  /* split the filename into a path and filename part */
-  s = strdup(in_cue_filename);
-  t = strrchr(s, '/');
-  if (t == (char *)NULL)
-     t = ".";
-  else {
-     *t = '\0';
-     t = s;
-     if (*t == '\0')
-       strcpy(t, "/");
-  }
-  
-  strlcpy(bincue_path,t,sizeof( bincue_path ));
-  mp_msg(MSGT_OPEN,MSGL_V,"dirname: %s, cuepath: %s\n", t, bincue_path);
-
-  /* no path at all? */
-  if (strcmp(bincue_path, ".") == 0) {
-    mp_msg(MSGT_OPEN,MSGL_V,"bincue_path: %s\n", bincue_path);
-    strlcpy(cue_filename,in_cue_filename,sizeof( cue_filename ));
-  } else {
-    strlcpy(cue_filename,in_cue_filename + strlen(bincue_path) + 1,
-            sizeof( cue_filename ));
-  }
-
-
-
-  /* open the cue file */
-  fd_cue = fopen (in_cue_filename, "r");
-  if (fd_cue == NULL)
-  {
-    mp_msg(MSGT_OPEN,MSGL_ERR,
-           MSGTR_MPDEMUX_CUEREAD_CannotOpenCueFile, in_cue_filename);
-    return -1;
-  }
-
-  /* read the first line and hand it to find_bin, which will
-     test more than one possible name of the file */
-
-  if(! fgets( sLine, 256, fd_cue ) )
-  {
-    mp_msg(MSGT_OPEN,MSGL_ERR,
-           MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
-    fclose (fd_cue);
-    return -1;
-  }
-
-  if (cue_find_bin(sLine)) {
-    fclose (fd_cue);
-    return -1;
-  }
-
-
-  /* now build the track list */
-  /* red the next line and call our track finder */
-  if(! fgets( sLine, 256, fd_cue ) )
-  {
-    mp_msg(MSGT_OPEN,MSGL_ERR,
-           MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
-    fclose (fd_cue);
-    return -1;
-  }
-
-  while(!feof(fd_cue))
-  {
-    if (cue_getTrackinfo(sLine, &tracks[nTracks++]) != 0)
-    {
-      mp_msg(MSGT_OPEN,MSGL_ERR,
-             MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
-      fclose (fd_cue);
-      return -1;
-    }
-  }
-
-  /* make a fake track with stands for the Lead out */
-  if (fstat (fd_bin, &filestat) == -1) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,
-           MSGTR_MPDEMUX_CUEREAD_ErrGettingBinFileSize);
-    fclose (fd_cue);
-    return -1;
-  }
-
-  sect = filestat.st_size / 2352;
-
-  tracks[nTracks].frame = sect%75;
-  sect=sect/75;
-  tracks[nTracks].second = sect%60;
-  sect=sect/60;
-  tracks[nTracks].minute = sect;
-
-
-  /* let's calculate the start sectors and offsets */
-  for(i = 0; i <= nTracks; i++)
-  {
-    tracks[i].start_sector = cue_msf_2_sector(tracks[i].minute,
-                                              tracks[nTracks].second,
-                                              tracks[nTracks].frame);
-
-    /* if we're the first track we don't need to offset of the one befor */
-    if (i == 0)
-    {
-      /* was always 0 on my svcds, but who knows */
-      tracks[0].start_offset = tracks[0].start_sector *
-        cue_mode_2_sector_size(tracks[0].mode);
-    } else
-    {
-      tracks[i].start_offset = tracks[i-1].start_offset +
-        (tracks[i].start_sector - tracks[i-1].start_sector) *
-        cue_mode_2_sector_size(tracks[i-1].mode);
-    }
-  }
-
-  fclose (fd_cue);
-
-  return fd_bin;
-}
-
-
-
-
-static int cue_read_toc_entry(void) {
-
-  int track = cue_current_pos.track - 1;
-
-  /* check if its a valid track, if not return -1 */
-  if (track >= nTracks)
-    return -1;
-
-
-  switch (tracks[track].mode)
-  {
-    case AUDIO:
-      cue_current_pos.mode = AUDIO;
-      break;
-    case MODE1_2352:
-      cue_current_pos.mode = MODE1;
-      break;
-    case MODE1_2048:
-      cue_current_pos.mode = MODE1;
-      break;
-    default: /* MODE2_2352 and MODE2_2336 */
-      cue_current_pos.mode = MODE2;
-  }
-  cue_current_pos.minute = tracks[track].minute;
-  cue_current_pos.second = tracks[track].second;
-  cue_current_pos.frame = tracks[track].frame;
-
-  return 0;
-}
-
-static int cue_vcd_seek_to_track (int track){
-  cue_current_pos.track  = track;
-
-  if (cue_read_toc_entry ())
-    return -1;
-
-  return VCD_SECTOR_DATA * cue_get_msf();
-}
-
-static int cue_vcd_get_track_end (int track){
-  cue_current_pos.frame = tracks[track].frame;
-  cue_current_pos.second = tracks[track].second;
-  cue_current_pos.minute = tracks[track].minute;
-
-  return VCD_SECTOR_DATA * cue_get_msf();
-}
-
-static void cue_vcd_read_toc(void){
-  int i;
-  for (i = 0; i < nTracks; ++i) {
-
-    mp_msg(MSGT_OPEN,MSGL_INFO,
-           MSGTR_MPDEMUX_CUEREAD_InfoTrackFormat,
-           i+1,
-           tracks[i].mode,
-           tracks[i].minute,
-           tracks[i].second,
-           tracks[i].frame
-           );
-  }
-}
-
-static int cue_vcd_read(stream_t *stream, char *mem, int size) {
-  unsigned long position;
-  int track = cue_current_pos.track - 1;
-
-  position = tracks[track].start_offset +
-             (cue_msf_2_sector(cue_current_pos.minute,
-                               cue_current_pos.second,
-                               cue_current_pos.frame) -
-              tracks[track].start_sector)
-             * cue_mode_2_sector_size(tracks[track].mode);
-
-  
-  if(position >= tracks[track+1].start_offset)
-    return 0;
-
-  if(lseek(fd_bin, position+VCD_SECTOR_OFFS, SEEK_SET) == -1) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_MPDEMUX_CUEREAD_UnexpectedBinFileEOF);
-    return 0;
-  }
-
-  if(read(fd_bin, mem, VCD_SECTOR_DATA) != VCD_SECTOR_DATA) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_MPDEMUX_CUEREAD_CannotReadNBytesOfPayload, VCD_SECTOR_DATA);
-    return 0;
-  }
-
-  cue_current_pos.frame++;
-  if (cue_current_pos.frame==75){
-    cue_current_pos.frame=0;
-    cue_current_pos.second++;
-    if (cue_current_pos.second==60){
-      cue_current_pos.second=0;
-      cue_current_pos.minute++;
-    }
-  }
-
-  return VCD_SECTOR_DATA;
-}
-
-static int seek(stream_t *s,off_t newpos) {
-  s->pos=newpos;
-  cue_set_msf(s->pos/VCD_SECTOR_DATA);
-  return 1;
-}
-
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-  int ret,ret2,f,track = 0;
-  char *filename = NULL, *colon = NULL;
-
-  if(mode != STREAM_READ || !p->filename) {
-    m_struct_free(&stream_opts,opts);
-    return STREAM_UNSUPORTED;
-  }
-  filename = strdup(p->filename);
-  if(!filename) {
-    m_struct_free(&stream_opts,opts);
-    return STREAM_UNSUPORTED;
-  }
-  colon = strstr(filename, ":");
-  if(colon) {
-    if(strlen(colon)>1)
-      track = atoi(colon+1);
-    *colon = 0;
-  }
-  if(!track)
-    track = 1;
-  
-  f = cue_read_cue(filename);
-  if(f < 0) {
-    m_struct_free(&stream_opts,opts);
-    return STREAM_UNSUPORTED;
-  }
-  cue_vcd_read_toc();
-  ret2=cue_vcd_get_track_end(track);
-  ret=cue_vcd_seek_to_track(track);
-  if(ret<0){ 
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");
-    return STREAM_UNSUPORTED;
-  }
-  mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_MPDEMUX_CUEREAD_CueStreamInfo_FilenameTrackTracksavail, filename, track, ret, ret2);
-
-  stream->fd = f;
-  stream->type = STREAMTYPE_VCDBINCUE;
-  stream->sector_size = VCD_SECTOR_DATA;
-  stream->flags = STREAM_READ | STREAM_SEEK_FW;
-  stream->start_pos = ret;
-  stream->end_pos = ret2;
-  stream->fill_buffer = cue_vcd_read;
-  stream->seek = seek;
-
-  free(filename);
-  m_struct_free(&stream_opts,opts);
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_cue = {
-  "CUE track",
-  "cue",
-  "Albeu",
-  "based on the code from ???",
-  open_s,
-  { "cue", NULL },
-  &stream_opts,
-  1 // Urls are an option string
-};
-
--- a/libmpdemux/cue_read.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-
-//int cue_read_cue (char *in_cue_filename);
-//int cue_vcd_seek_to_track (int track);
-//int cue_vcd_get_track_end (int track);
-//void cue_vcd_read_toc ();
-//int cue_vcd_read(char *mem);
-//inline void cue_set_msf(unsigned int sect);
--- a/libmpdemux/dvb_tune.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,791 +0,0 @@
-/* dvbtune - tune.c
-
-   Copyright (C) Dave Chapman 2001,2002
-
-   Modified for use with MPlayer, for details see the changelog at
-   http://svn.mplayerhq.hu/mplayer/trunk/
-   $Id$
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   as published by the Free Software Foundation; either version 2
-   of the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU 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.
-   Or, point your browser to http://www.gnu.org/copyleft/gpl.html
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <error.h>
-#include <time.h>
-#include <errno.h>
-#include "config.h"
-
-#ifdef HAVE_DVB_HEAD
-	#include <linux/dvb/dmx.h>
-	#include <linux/dvb/frontend.h>
-	char* dvb_frontenddev[4]={"/dev/dvb/adapter0/frontend0","/dev/dvb/adapter1/frontend0","/dev/dvb/adapter2/frontend0","/dev/dvb/adapter3/frontend0"};
-	char* dvb_dvrdev[4]={"/dev/dvb/adapter0/dvr0","/dev/dvb/adapter1/dvr0","/dev/dvb/adapter2/dvr0","/dev/dvb/adapter3/dvr0"};
-	char* dvb_demuxdev[4]={"/dev/dvb/adapter0/demux0","/dev/dvb/adapter1/demux0","/dev/dvb/adapter2/demux0","/dev/dvb/adapter3/demux0"};
-	static char* dvb_secdev[4]={"","","",""};	//UNUSED, ONLY FOR UNIFORMITY
-#else
-	#include <ost/dmx.h>
-	#include <ost/sec.h>
-	#include <ost/frontend.h>
-	char* dvb_frontenddev[4]={"/dev/ost/frontend0","/dev/ost/frontend1","/dev/ost/frontend2","/dev/ost/frontend3"};
-	char* dvb_dvrdev[4]={"/dev/ost/dvr0","/dev/ost/dvr1","/dev/ost/dvr2","/dev/ost/dvr3"};
-	static char* dvb_secdev[4]={"/dev/ost/sec0","/dev/ost/sec1","/dev/ost/sec2","/dev/ost/sec3"};
-	char* dvb_demuxdev[4]={"/dev/ost/demux0","/dev/ost/demux1","/dev/ost/demux2","/dev/ost/demux3"};
-#endif
-
-#include "dvbin.h"
-#include "mp_msg.h"
-
-
-
-int dvb_get_tuner_type(int fe_fd)
-{
-#ifdef HAVE_DVB_HEAD
-  struct dvb_frontend_info fe_info;
-#else
-  FrontendInfo fe_info;
-#endif
-
-  int res;
-
-  res = ioctl(fe_fd, FE_GET_INFO, &fe_info);
-  if(res < 0)
-  {
-  	mp_msg(MSGT_DEMUX, MSGL_ERR, "FE_GET_INFO error: %d, FD: %d\n\n", errno, fe_fd);
-	return 0;
-  }
-
-  switch(fe_info.type)
-  {
-	case FE_OFDM:
-      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-T\n");
-	  return TUNER_TER;
-
-	case FE_QPSK:
-      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-S\n");
-	  return TUNER_SAT;
-
-	case FE_QAM:
-      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-C\n");
-	  return TUNER_CBL;
-
-#ifdef DVB_ATSC
-	case FE_ATSC:
-      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-ATSC\n");
-	  return TUNER_ATSC;
-#endif
-	default:
-	  mp_msg(MSGT_DEMUX, MSGL_ERR, "UNKNOWN TUNER TYPE\n");
-	  return 0;
-  }
-
-}
-
-int dvb_set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype);
-
-int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt, int *pids)
-{
-	int i;
-	
-	priv->fe_fd = open(dvb_frontenddev[n], O_RDWR | O_NONBLOCK);
-	if(priv->fe_fd < 0)
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING FRONTEND DEVICE %s: ERRNO %d\n", dvb_frontenddev[n], errno);
-		return 0;
-	}
-#ifdef HAVE_DVB_HEAD
-    priv->sec_fd=0;
-#else
-	priv->sec_fd = open(dvb_secdev[n], O_RDWR);
-    if(priv->sec_fd < 0)
-    {
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING SEC DEVICE %s: ERRNO %d\n", dvb_secdev[n], errno);
-		close(priv->fe_fd);
-      	return 0;
-    }
-#endif
-	priv->demux_fds_cnt = 0;
-	mp_msg(MSGT_DEMUX, MSGL_V, "DVB_OPEN_DEVICES(%d)\n", demux_cnt);
-	for(i = 0; i < demux_cnt; i++)
-	{
-		priv->demux_fds[i] = open(dvb_demuxdev[n], O_RDWR | O_NONBLOCK);
-		if(priv->demux_fds[i] < 0)
-		{
-			mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING DEMUX 0: %d\n", errno);
-			return 0;
-		}
-		else
-		{
-			mp_msg(MSGT_DEMUX, MSGL_V, "OPEN(%d), file %s: FD=%d, CNT=%d\n", i, dvb_demuxdev[n], priv->demux_fds[i], priv->demux_fds_cnt);
-			priv->demux_fds_cnt++;
-		}
-	}
-
-
-	priv->dvr_fd = open(dvb_dvrdev[n], O_RDONLY| O_NONBLOCK);
-	if(priv->dvr_fd < 0)
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING DVR DEVICE %s: %d\n", dvb_dvrdev[n], errno);
-		return 0;
-	}
-
-    return 1;
-}
-
-
-int dvb_fix_demuxes(dvb_priv_t *priv, int cnt, int *pids)
-{
-	int i;
-	
-	mp_msg(MSGT_DEMUX, MSGL_V, "FIX %d -> %d\n", priv->demux_fds_cnt, cnt);
-	if(priv->demux_fds_cnt >= cnt)
-	{
-		for(i = priv->demux_fds_cnt-1; i >= cnt; i--)
-		{
-			mp_msg(MSGT_DEMUX, MSGL_V, "FIX, CLOSE fd(%d): %d\n", i, priv->demux_fds[i]);
-			close(priv->demux_fds[i]);
-		}
-		priv->demux_fds_cnt = cnt;
-	}
-	else if(priv->demux_fds_cnt < cnt)
-	{
-		for(i = priv->demux_fds_cnt; i < cnt; i++)
-		{
-			priv->demux_fds[i] = open(dvb_demuxdev[priv->card], O_RDWR | O_NONBLOCK);
-			mp_msg(MSGT_DEMUX, MSGL_V, "FIX, OPEN fd(%d): %d\n", i, priv->demux_fds[i]);
-			if(priv->demux_fds[i] < 0)
-			{
-				mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING DEMUX 0: %d\n", errno);
-				return 0;
-			}
-			else
-				priv->demux_fds_cnt++;
-		}	
-	}
-	
-	return 1;
-}
-
-int dvb_set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype)
-{
-	int i;
-	struct dmx_pes_filter_params pesFilterParams;
-
-	pesFilterParams.pid     = pid;
-	pesFilterParams.input   = DMX_IN_FRONTEND;
-	pesFilterParams.output  = DMX_OUT_TS_TAP;
-#ifdef HAVE_DVB_HEAD
-	pesFilterParams.pes_type = pestype;
-#else
-	pesFilterParams.pesType = pestype;
-#endif
-
-	pesFilterParams.flags   = DMX_IMMEDIATE_START;
-
-	errno = 0;
-	if ((i = ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams)) < 0)
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR IN SETTING DMX_FILTER %i for fd %d: ERRNO: %d", pid, fd, errno);
-		return 0;
-	}
-
-	mp_msg(MSGT_DEMUX, MSGL_V, "SET PES FILTER ON PID %d to fd %d, RESULT: %d, ERRNO: %d\n", pid, fd, i, errno);
-	return 1;
-}
-
-
-int dvb_demux_stop(int fd)
-{
-	int i;
-	i = ioctl(fd, DMX_STOP);
-
-	mp_msg(MSGT_DEMUX, MSGL_DBG2, "STOPPING FD: %d, RESULT: %d\n", fd, i);
-
-	return (i==0);
-}
-
-
-int dvb_demux_start(int fd)
-{
-	int i;
-	i = ioctl(fd, DMX_START);
-
-	mp_msg(MSGT_DEMUX, MSGL_DBG2, "STARTING FD: %d, RESULT: %d\n", fd, i);
-
-	return (i==0);
-}
-
-
-static int tune_it(int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone,
-	fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate,
-	fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth,
-	fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int tmout);
-
-
-int dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, int tone,
-		fe_spectral_inversion_t specInv, fe_modulation_t modulation, fe_guard_interval_t guardInterval,
-		fe_transmit_mode_t TransmissionMode, fe_bandwidth_t bandWidth, fe_code_rate_t HP_CodeRate,
-		fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout)
-{
-	int ris;
-
-	mp_msg(MSGT_DEMUX, MSGL_INFO, "dvb_tune Freq: %lu\n", (long unsigned int) freq);
-
-		ris = tune_it(priv->fe_fd, priv->sec_fd, freq, srate, pol, tone, specInv, diseqc, modulation, HP_CodeRate, TransmissionMode, guardInterval, bandWidth, LP_CodeRate, hier, timeout);
-
-	if(ris != 0)
-		mp_msg(MSGT_DEMUX, MSGL_INFO, "dvb_tune, TUNING FAILED\n");
-
-	return (ris == 0);
-}
-
-
-#ifndef HAVE_DVB_HEAD
-static int SecGetStatus (int fd, struct secStatus *state)
-{
-    if(ioctl(fd, SEC_GET_STATUS, state) < 0)
-    {
-        mp_msg(MSGT_DEMUX, MSGL_ERR, ("SEC GET STATUS: "));
-        return -1;
-    }
-
-    switch (state->busMode)
-    {
-	case SEC_BUS_IDLE:
-    	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  IDLE (%d)\n",state->busMode);
-    	    break;
-	case SEC_BUS_BUSY:
-    	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  BUSY (%d)\n",state->busMode);
-	    break;
-        case SEC_BUS_OFF:
-	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  OFF  (%d)\n",state->busMode);
-    	    break;
-        case SEC_BUS_OVERLOAD:
-	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  OVERLOAD (%d)\n",state->busMode);
-    	    break;
-	default:
-    	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  unknown  (%d)\n",state->busMode);
-            break;
-    }
-
-    switch (state->selVolt)
-    {
-	case SEC_VOLTAGE_OFF:
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  OFF (%d)\n",state->selVolt);
-		break;
-	case SEC_VOLTAGE_LT:
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  LT  (%d)\n",state->selVolt);
-		break;
-	case SEC_VOLTAGE_13:
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  13  (%d)\n",state->selVolt);
-		break;
-	case SEC_VOLTAGE_13_5:
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  13.5 (%d)\n",state->selVolt);
-		break;
-	case SEC_VOLTAGE_18:
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  18 (%d)\n",state->selVolt);
-		break;
-	case SEC_VOLTAGE_18_5:
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  18.5 (%d)\n",state->selVolt);
-		break;
-	default:
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  unknown (%d)\n",state->selVolt);
-		break;
-    }
-
- 	mp_msg(MSGT_DEMUX, MSGL_V, "SEC CONT TONE: %s\n", (state->contTone == SEC_TONE_ON ? "ON" : "OFF"));
-    return 0;
-}
-
-#endif
-
-static void print_status(fe_status_t festatus)
-{
-	mp_msg(MSGT_DEMUX, MSGL_V, "FE_STATUS:");
-	if (festatus & FE_HAS_SIGNAL) mp_msg(MSGT_DEMUX, MSGL_V," FE_HAS_SIGNAL");
-#ifdef HAVE_DVB_HEAD
-	if (festatus & FE_TIMEDOUT) mp_msg(MSGT_DEMUX, MSGL_V, " FE_TIMEDOUT");
-#else
-	if (festatus & FE_HAS_POWER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_POWER");
-	if (festatus & FE_SPECTRUM_INV) mp_msg(MSGT_DEMUX, MSGL_V, " FE_SPECTRUM_INV");
-	if (festatus & FE_TUNER_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_TUNER_HAS_LOCK");
-#endif
-	if (festatus & FE_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_LOCK");
-	if (festatus & FE_HAS_CARRIER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_CARRIER");
-	if (festatus & FE_HAS_VITERBI) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_VITERBI");
-	if (festatus & FE_HAS_SYNC) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_SYNC");
-	mp_msg(MSGT_DEMUX, MSGL_V, "\n");
-}
-
-
-#ifdef HAVE_DVB_HEAD
-static int check_status(int fd_frontend,struct dvb_frontend_parameters* feparams, int tuner_type, uint32_t base, int tmout)
-{
-	int32_t strength;
-	fe_status_t festatus;
-	struct pollfd pfd[1];
-	int ok=0, locks=0;
-	time_t tm1, tm2;
-
-	if (ioctl(fd_frontend,FE_SET_FRONTEND,feparams) < 0)
-	{
-	mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR tuning channel\n");
-	return -1;
-	}
-
-	pfd[0].fd = fd_frontend;
-	pfd[0].events = POLLPRI;
-
-	mp_msg(MSGT_DEMUX, MSGL_V, "Getting frontend status\n");
-	tm1 = tm2 = time((time_t*) NULL);
-	while(!ok)
-	{
-		festatus = 0;
-		if(poll(pfd,1,tmout*1000) > 0)
-		{
-			if (pfd[0].revents & POLLPRI)
-			{
-				if(ioctl(fd_frontend, FE_READ_STATUS, &festatus) >= 0)
-					if(festatus & FE_HAS_LOCK)
-						locks++;
-			}
-		}
-		usleep(10000);
-		tm2 = time((time_t*) NULL);
-		if((festatus & FE_TIMEDOUT) || (locks >= 2) || (tm2 - tm1 >= tmout))
-			ok = 1;
-	}
-
-	if(festatus & FE_HAS_LOCK)
-	{
-		if(ioctl(fd_frontend,FE_GET_FRONTEND,feparams) >= 0)
-		{
-		switch(tuner_type)
-		{
-			case FE_OFDM:
-			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",feparams->frequency);
-			break;
-			case FE_QPSK:
-			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",(unsigned int)((feparams->frequency)+base));
-			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",feparams->u.qpsk.symbol_rate);
-			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",feparams->u.qpsk.fec_inner);
-			mp_msg(MSGT_DEMUX, MSGL_V, "\n");
-			break;
-			case FE_QAM:
-			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",feparams->frequency);
-			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",feparams->u.qpsk.symbol_rate);
-			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",feparams->u.qpsk.fec_inner);
-			break;
-#ifdef DVB_ATSC
-			case FE_ATSC:
-			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",feparams->frequency);
-			mp_msg(MSGT_DEMUX, MSGL_V, "        Modulation: %d\n",feparams->u.vsb.modulation);
-			break;
-#endif
-			default:
-			break;
-		}
-		}
-
-		strength=0;
-		if(ioctl(fd_frontend,FE_READ_BER,&strength) >= 0)
-		mp_msg(MSGT_DEMUX, MSGL_V, "Bit error rate: %d\n",strength);
-
-		strength=0;
-		if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0)
-		mp_msg(MSGT_DEMUX, MSGL_V, "Signal strength: %d\n",strength);
-
-		strength=0;
-		if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0)
-		mp_msg(MSGT_DEMUX, MSGL_V, "SNR: %d\n",strength);
-
-		strength=0;
-		if(ioctl(fd_frontend,FE_READ_UNCORRECTED_BLOCKS,&strength) >= 0)
-		mp_msg(MSGT_DEMUX, MSGL_V, "UNC: %d\n",strength);
-		
-		print_status(festatus);
-	}
-	else
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "Not able to lock to the signal on the given frequency, timeout: %d\n", tmout);
-		return -1;
-	}
-	return 0;
-}
-
-#else
-
-static int check_status(int fd_frontend,FrontendParameters* feparams,int tuner_type,uint32_t base, int tmout)
-{
-	int i,res;
-	int32_t strength;
-	fe_status_t festatus;
-	FrontendEvent event;
-	
-	struct pollfd pfd[1];
-
-	while(1)
-	{
-	    if(ioctl(fd_frontend, FE_GET_EVENT, &event) == -1)
-	    break;
-	}
-
-	i = 0; res = -1;
-	while ((i < 3) && (res < 0))
-	{
-		if (ioctl(fd_frontend,FE_SET_FRONTEND,feparams) < 0)
-		{
-			mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR tuning channel\n");
-			return -1;
-		}
-
-		pfd[0].fd = fd_frontend;
-		pfd[0].events = POLLIN | POLLPRI;
-
-		if(poll(pfd,1,tmout*1000) > 0)
-		{
-			if (pfd[0].revents & POLLPRI)
-			{
-				mp_msg(MSGT_DEMUX, MSGL_V, "Getting frontend event\n");
-				if ( ioctl(fd_frontend, FE_GET_EVENT, &event) < 0)
-				{
-					mp_msg(MSGT_DEMUX, MSGL_ERR, "FE_GET_EVENT");
-					return -1;
-				}
-				mp_msg(MSGT_DEMUX, MSGL_V, "Received ");
-				switch(event.type)
-				{
-					case FE_UNEXPECTED_EV:
-					mp_msg(MSGT_DEMUX, MSGL_V, "unexpected event\n");
-					res = -1;
-					break;
-
-					case FE_FAILURE_EV:
-					mp_msg(MSGT_DEMUX, MSGL_V, "failure event\n");
-					res = -1;
-					break;
-
-					case FE_COMPLETION_EV:
-					mp_msg(MSGT_DEMUX, MSGL_V, "completion event\n");
-					res = 0;
-					break;
-				}
-			}
-			i++;
-		}
-	}
-
-	if (res > 0)
-	switch (event.type)
-	{
-		case FE_UNEXPECTED_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_UNEXPECTED_EV\n");
-			break;
-		case FE_COMPLETION_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_COMPLETION_EV\n");
-			break;
-		case FE_FAILURE_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_FAILURE_EV\n");
-			break;
-	}
-
-	if (event.type == FE_COMPLETION_EV)
-	{
-		switch(tuner_type)
-		{
-			case FE_OFDM:
-			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",event.u.completionEvent.Frequency);
-			break;
-
-			case FE_QPSK:
-			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",(unsigned int)((event.u.completionEvent.Frequency)+base));
-			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",event.u.completionEvent.u.qpsk.SymbolRate);
-			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",event.u.completionEvent.u.qpsk.FEC_inner);
-			mp_msg(MSGT_DEMUX, MSGL_V, "\n");
-			break;
-
-			case FE_QAM:
-			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",event.u.completionEvent.Frequency);
-			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",event.u.completionEvent.u.qpsk.SymbolRate);
-			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",event.u.completionEvent.u.qpsk.FEC_inner);
-			break;
-
-			default:
-			break;
-		}
-
-		strength=0;
-		if(ioctl(fd_frontend,FE_READ_BER,&strength) >= 0)
-		mp_msg(MSGT_DEMUX, MSGL_V, "Bit error rate: %d\n",strength);
-
-		strength=0;
-		if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0)
-		mp_msg(MSGT_DEMUX, MSGL_V, "Signal strength: %d\n",strength);
-
-		strength=0;
-		if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0)
-		mp_msg(MSGT_DEMUX, MSGL_V, "SNR: %d\n",strength);
-
-		festatus=0;
-		mp_msg(MSGT_DEMUX, MSGL_V, "FE_STATUS:");
-		
-		if(ioctl(fd_frontend,FE_READ_STATUS,&festatus) >= 0)
-		    print_status(festatus);
-		else
-		    mp_msg(MSGT_DEMUX, MSGL_ERR, " ERROR, UNABLE TO READ_STATUS");
-		    
-		mp_msg(MSGT_DEMUX, MSGL_V, "\n");
-	}
-	else
-	{
-		mp_msg(MSGT_DEMUX, MSGL_V, "Not able to lock to the signal on the given frequency\n");
-		return -1;
-	}
-	return 0;
-}
-#endif
-
-#ifdef HAVE_DVB_HEAD
-
-static struct diseqc_cmd {
-   struct dvb_diseqc_master_cmd cmd;
-   uint32_t wait;
-};
-
-static int diseqc_send_msg(int fd, fe_sec_voltage_t v, struct diseqc_cmd *cmd,
-		     fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b)
-{
-   if(ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1)
-    return -1;
-   if(ioctl(fd, FE_SET_VOLTAGE, v) == -1)
-    return -1;
-   usleep(15 * 1000);
-   if(ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd->cmd) == -1)
-    return -1;
-   usleep(cmd->wait * 1000);
-   usleep(15 * 1000);
-   if(ioctl(fd, FE_DISEQC_SEND_BURST, b) == -1)
-    return -1;
-   usleep(15 * 1000);
-   if(ioctl(fd, FE_SET_TONE, t) == -1)
-    return -1;
-
-    return 0;
-}
-
-/* digital satellite equipment control,
- * specification is available from http://www.eutelsat.com/
- */
-static int do_diseqc(int secfd, int sat_no, int polv, int hi_lo)
-{
-   struct diseqc_cmd cmd =  { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
-
-   /* param: high nibble: reset bits, low nibble set bits,
-    * bits are: option, position, polarizaion, band
-    */
-   cmd.cmd.msg[3] =
-       0xf0 | (((sat_no * 4) & 0x0f) | (hi_lo ? 1 : 0) | (polv ? 0 : 2));
-
-   return diseqc_send_msg(secfd, polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18,
-		   &cmd, hi_lo ? SEC_TONE_ON : SEC_TONE_OFF,
-		   (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A);
-}
-
-#else
-
-static int do_diseqc(int secfd, int sat_no, int polv, int hi_lo)
-{
-	struct secCommand scmd;
-        struct secCmdSequence scmds;
-
-        scmds.continuousTone = (hi_lo ? SEC_TONE_ON : SEC_TONE_OFF);
-        scmds.voltage = (polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
-        scmds.miniCommand = SEC_MINI_NONE;
-
-        scmd.type = SEC_CMDTYPE_DISEQC;
-        scmds.numCommands = 1;
-        scmds.commands = &scmd;
-
-        scmd.u.diseqc.addr = 0x10;
-        scmd.u.diseqc.cmd = 0x38;
-        scmd.u.diseqc.numParams = 1;
-        scmd.u.diseqc.params[0] = 0xf0 |
-                                  (((sat_no) << 2) & 0x0F) |
-				  (hi_lo ? 1 : 0) |
-                                  (polv ? 0 : 2); 
-
-        if (ioctl(secfd,SEC_SEND_SEQUENCE,&scmds) < 0)
-	{
-          mp_msg(MSGT_DEMUX, MSGL_ERR, "Error sending DisEqC");
-          return -1;
-        }
-	
-	return 0;
-}
-#endif
-
-static int tune_it(int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone,
-	fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate,
-	fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth,
-	fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout)
-{
-  int res, hi_lo, dfd;
-#ifdef HAVE_DVB_HEAD
-  struct dvb_frontend_parameters feparams;
-  struct dvb_frontend_info fe_info;
-#else
-  FrontendParameters feparams;
-  FrontendInfo fe_info;
-  struct secStatus sec_state;
-#endif
-
-
-  mp_msg(MSGT_DEMUX, MSGL_V,  "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, pol %c, tone %i, specInv, diseqc %u, fe_modulation_t modulation,fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth\n",
-	    fd_frontend, fd_sec, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc);
-
-
-  if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0))
-  {
-  	mp_msg(MSGT_DEMUX, MSGL_FATAL, "FE_GET_INFO FAILED\n");
-	return -1;
-  }
-
-
-#ifdef HAVE_DVB_HEAD
-  mp_msg(MSGT_DEMUX, MSGL_V, "Using DVB card \"%s\"\n", fe_info.name);
-#endif
-
-  switch(fe_info.type)
-  {
-    case FE_OFDM:
-#ifdef HAVE_DVB_HEAD
-      if (freq < 1000000) freq*=1000UL;
-      feparams.frequency=freq;
-      feparams.inversion=specInv;
-      feparams.u.ofdm.bandwidth=bandwidth;
-      feparams.u.ofdm.code_rate_HP=HP_CodeRate;
-      feparams.u.ofdm.code_rate_LP=LP_CodeRate;
-      feparams.u.ofdm.constellation=modulation;
-      feparams.u.ofdm.transmission_mode=TransmissionMode;
-      feparams.u.ofdm.guard_interval=guardInterval;
-      feparams.u.ofdm.hierarchy_information=hier;
-#else
-      if (freq < 1000000) freq*=1000UL;
-      feparams.Frequency=freq;
-      feparams.Inversion=specInv;
-      feparams.u.ofdm.bandWidth=bandwidth;
-      feparams.u.ofdm.HP_CodeRate=HP_CodeRate;
-      feparams.u.ofdm.LP_CodeRate=LP_CodeRate;
-      feparams.u.ofdm.Constellation=modulation;
-      feparams.u.ofdm.TransmissionMode=TransmissionMode;
-      feparams.u.ofdm.guardInterval=guardInterval;
-      feparams.u.ofdm.HierarchyInformation=hier;
-#endif
-      mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-T to %d Hz, bandwidth: %d\n",freq, bandwidth);
-      break;
-    case FE_QPSK:
-      if (freq > 2200000)
-      {
-        // this must be an absolute frequency
-        if (freq < SLOF)
-	{
-#ifdef HAVE_DVB_HEAD
-          freq = feparams.frequency=(freq-LOF1);
-#else
-          freq = feparams.Frequency=(freq-LOF1);
-#endif
-	    hi_lo = 0;
-        }
-	else
-	{
-#ifdef HAVE_DVB_HEAD
-          freq = feparams.frequency=(freq-LOF2);
-#else
-          freq = feparams.Frequency=(freq-LOF2);
-#endif
-	    hi_lo = 1;
-        }
-      }
-      else
-      {
-        // this is an L-Band frequency
-#ifdef HAVE_DVB_HEAD
-       feparams.frequency=freq;
-#else
-       feparams.Frequency=freq;
-#endif
-      }
-
-#ifdef HAVE_DVB_HEAD
-      feparams.inversion=specInv;
-      feparams.u.qpsk.symbol_rate=srate;
-      feparams.u.qpsk.fec_inner=HP_CodeRate;
-      dfd = fd_frontend;
-#else
-      feparams.Inversion=specInv;
-      feparams.u.qpsk.SymbolRate=srate;
-      feparams.u.qpsk.FEC_inner=HP_CodeRate;
-      dfd = fd_sec;
-#endif
-
-	mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-S to Freq: %u, Pol: %c Srate: %d, 22kHz: %s, LNB:  %d\n",freq,pol,srate,hi_lo ? "on" : "off", diseqc);
-
-   if(do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0)
-	mp_msg(MSGT_DEMUX, MSGL_V, "DISEQC SETTING SUCCEDED\n");
-   else
-   {
-	mp_msg(MSGT_DEMUX, MSGL_ERR, "DISEQC SETTING FAILED\n");
-	return -1;
-   }
-      break;
-    case FE_QAM:
-      mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-C to %d, srate=%d\n",freq,srate);
-#ifdef HAVE_DVB_HEAD
-      feparams.frequency=freq;
-      feparams.inversion=specInv;
-      feparams.u.qam.symbol_rate = srate;
-      feparams.u.qam.fec_inner = HP_CodeRate;
-      feparams.u.qam.modulation = modulation;
-#else
-      feparams.Frequency=freq;
-      feparams.Inversion=specInv;
-      feparams.u.qam.SymbolRate = srate;
-      feparams.u.qam.FEC_inner = HP_CodeRate;
-      feparams.u.qam.QAM = modulation;
-#endif
-      break;
-#ifdef DVB_ATSC
-    case FE_ATSC:
-      mp_msg(MSGT_DEMUX, MSGL_V, "tuning ATSC to %d, modulation=%d\n",freq,modulation);
-      feparams.frequency=freq;
-      feparams.u.vsb.modulation = modulation;
-      break;
-#endif
-    default:
-      mp_msg(MSGT_DEMUX, MSGL_V, "Unknown FE type. Aborting\n");
-      return 0;
-  }
-  usleep(100000);
-
-#ifndef HAVE_DVB_HEAD
-  if (fd_sec) SecGetStatus(fd_sec, &sec_state);
-#endif
-
-  return(check_status(fd_frontend,&feparams,fe_info.type, (hi_lo ? LOF2 : LOF1), timeout));
-}
--- a/libmpdemux/dvbin.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,870 +0,0 @@
-/*
-
-dvbstream
-(C) Dave Chapman <dave@dchapman.com> 2001, 2002.
-
-The latest version can be found at http://www.linuxstb.org/dvbstream
-
-Modified for use with MPlayer, for details see the changelog at
-http://svn.mplayerhq.hu/mplayer/trunk/
-$Id$
-
-Copyright notice:
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/poll.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "stream.h"
-#include "demuxer.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-#include "dvbin.h"
-
-
-#define MAX_CHANNELS 8
-#define CHANNEL_LINE_LEN 256
-#define min(a, b) ((a) <= (b) ? (a) : (b))
-
-
-//TODO: CAMBIARE list_ptr e da globale a per_priv
-
-
-static struct stream_priv_s
-{
-	char *prog;
-	int card;
-	char *type;
-	int vid, aid;
-	int timeout;
-	char *file;
-}
-stream_defaults =
-{
-	"", 1, "", 0, 0, 30, NULL
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s, f)
-
-/// URL definition
-static m_option_t stream_params[] = {
-	{"prog", ST_OFF(prog), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-	{"card", ST_OFF(card), CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL},
-	{"type", ST_OFF(type), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-	{"vid",  ST_OFF(vid),  CONF_TYPE_INT, 0, 0 ,0, NULL},
-	{"aid",  ST_OFF(aid),  CONF_TYPE_INT, 0, 0 ,0, NULL},
-	{"timeout",ST_OFF(timeout),  CONF_TYPE_INT, M_OPT_RANGE, 1, 30, NULL},
-	{"file", ST_OFF(file), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-
-	{"hostname", 	ST_OFF(prog), CONF_TYPE_STRING, 0, 0, 0, NULL },
-	{"username", 	ST_OFF(card), CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL},
-	{NULL, NULL, 0, 0, 0, 0, NULL}
-};
-
-static struct m_struct_st stream_opts = {
-	"dvbin",
-	sizeof(struct stream_priv_s),
-	&stream_defaults,
-	stream_params
-};
-
-
-
-m_option_t dvbin_opts_conf[] = {
-	{"prog", &stream_defaults.prog, CONF_TYPE_STRING, 0, 0 ,0, NULL},
-	{"card", &stream_defaults.card, CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL},
-	{"type", "DVB card type is autodetected and can't be overridden\n", CONF_TYPE_PRINT, CONF_NOCFG, 0 ,0, NULL},
-	{"vid",  &stream_defaults.vid,  CONF_TYPE_INT, 0, 0 ,0, NULL},
-	{"aid",  &stream_defaults.aid,  CONF_TYPE_INT, 0, 0 ,0, NULL},
-	{"timeout",  &stream_defaults.timeout,  CONF_TYPE_INT, M_OPT_RANGE, 1, 30, NULL},
-	{"file", &stream_defaults.file, CONF_TYPE_STRING, 0, 0 ,0, NULL},
-
-	{NULL, NULL, 0, 0, 0, 0, NULL}
-};
-
-
-
-
-extern int dvb_set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype);
-extern int dvb_demux_stop(int fd);
-extern int dvb_get_tuner_type(int fd);
-int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt, int *pids);
-int dvb_fix_demuxes(dvb_priv_t *priv, int cnt, int *pids);
-
-extern int dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, int tone,
-		fe_spectral_inversion_t specInv, fe_modulation_t modulation, fe_guard_interval_t guardInterval,
-		fe_transmit_mode_t TransmissionMode, fe_bandwidth_t bandWidth, fe_code_rate_t HP_CodeRate,
-		fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout);
-extern char *dvb_dvrdev[4], *dvb_demuxdev[4], *dvb_frontenddev[4];
-
-static dvb_config_t *dvb_config = NULL;
-
-
-static dvb_channels_list *dvb_get_channels(char *filename, int type)
-{
-	dvb_channels_list  *list;
-	FILE *f;
-	char line[CHANNEL_LINE_LEN], *colon;
-
-	int fields, cnt, pcnt, k;
-	dvb_channel_t *ptr, *tmp, chn;
-	char tmp_lcr[256], tmp_hier[256], inv[256], bw[256], cr[256], mod[256], transm[256], gi[256], vpid_str[256], apid_str[256];
-	const char *cbl_conf = "%d:%255[^:]:%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
-	const char *sat_conf = "%d:%c:%d:%d:%255[^:]:%255[^:]\n";
-	const char *ter_conf = "%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
-	const char *atsc_conf = "%d:%255[^:]:%255[^:]:%255[^:]\n";
-	
-	mp_msg(MSGT_DEMUX, MSGL_V, "CONFIG_READ FILE: %s, type: %d\n", filename, type);
-	if((f=fopen(filename, "r"))==NULL)
-	{
-		mp_msg(MSGT_DEMUX, MSGL_FATAL, "CAN'T READ CONFIG FILE %s\n", filename);
-		return NULL;
-	}
-
-	list = malloc(sizeof(dvb_channels_list));
-	if(list == NULL)
-	{
-		fclose(f);
-		mp_msg(MSGT_DEMUX, MSGL_V, "DVB_GET_CHANNELS: couldn't malloc enough memory\n");
-		return NULL;
-	}
-
-	ptr = &chn;
-	list->NUM_CHANNELS = 0;
-	list->channels = NULL;
-	while(! feof(f))
-	{
-		if( fgets(line, CHANNEL_LINE_LEN, f) == NULL )
-			continue;
-
-		if((line[0] == '#') || (strlen(line) == 0))
-			continue;
-
-		colon = index(line, ':');
-		if(colon)
-		{
-			k = colon - line;
-			if(!k)
-				continue;
-			ptr->name = (char*) malloc(k+1);
-			if(! ptr->name)
-				continue;
-			strncpy(ptr->name, line, k);
-			ptr->name[k] = 0;
-		}
-		else
-			continue;
-		k++;
-		apid_str[0] = vpid_str[0] = 0;
-		ptr->pids_cnt = 0;
-		ptr->freq = 0;
-		if(type == TUNER_TER)
-		{
-			fields = sscanf(&line[k], ter_conf,
-				&ptr->freq, inv, bw, cr, tmp_lcr, mod,
-				transm, gi, tmp_hier, vpid_str, apid_str);
-			mp_msg(MSGT_DEMUX, MSGL_V,
-				"TER, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d",
-				list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
-		}
-		else if(type == TUNER_CBL)
-		{
-			fields = sscanf(&line[k], cbl_conf,
-				&ptr->freq, inv, &ptr->srate,
-				cr, mod, vpid_str, apid_str);
-			mp_msg(MSGT_DEMUX, MSGL_V,
-				"CBL, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, SRATE: %d",
-				list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate);
-		}
-#ifdef DVB_ATSC
-		else if(type == TUNER_ATSC)
-		{
-			fields = sscanf(&line[k], atsc_conf,
-				 &ptr->freq, mod, vpid_str, apid_str);
-			mp_msg(MSGT_DEMUX, MSGL_V,
-				"ATSC, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d\n",
-				list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
-		}
-#endif
-		else //SATELLITE
-		{
-			fields = sscanf(&line[k], sat_conf,
-				&ptr->freq, &ptr->pol, &ptr->diseqc, &ptr->srate, vpid_str, apid_str);
-			ptr->pol = toupper(ptr->pol);
-			ptr->freq *=  1000UL;
-			ptr->srate *=  1000UL;
-			ptr->tone = -1;
-			ptr->inv = INVERSION_AUTO;
-			ptr->cr = FEC_AUTO;
-			if((ptr->diseqc > 4) || (ptr->diseqc < 0))
-			    continue;
-			if(ptr->diseqc > 0)
-			    ptr->diseqc--;
-			mp_msg(MSGT_DEMUX, MSGL_V,
-				"SAT, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, SRATE: %d, POL: %c, DISEQC: %d",
-				list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate, ptr->pol, ptr->diseqc);
-		}
-
-		if(vpid_str[0])
-		{
-			pcnt = sscanf(vpid_str, "%d+%d+%d+%d+%d+%d+%d", &ptr->pids[0], &ptr->pids[1], &ptr->pids[2], &ptr->pids[3],
-				&ptr->pids[4], &ptr->pids[5], &ptr->pids[6]);
-			if(pcnt > 0)
-			{
-				ptr->pids_cnt = pcnt;
-				fields++;
-			}
-		}
-		
-		if(apid_str[0])
-		{
-			cnt = ptr->pids_cnt;
-			pcnt = sscanf(apid_str, "%d+%d+%d+%d+%d+%d+%d+%d", &ptr->pids[cnt], &ptr->pids[cnt+1], &ptr->pids[cnt+2],
-				&ptr->pids[cnt+3], &ptr->pids[cnt+4], &ptr->pids[cnt+5], &ptr->pids[cnt+6], &ptr->pids[cnt+7]);
-			if(pcnt > 0)
-			{
-				ptr->pids_cnt += pcnt;
-				fields++;
-			}
-		}
-
-		if((fields < 2) || (ptr->pids_cnt <= 0) || (ptr->freq == 0) || (strlen(ptr->name) == 0))
-			continue;
-
-
-		ptr->pids[ptr->pids_cnt] = 0;	//PID 0 is the PAT
-		ptr->pids_cnt++;
-		mp_msg(MSGT_DEMUX, MSGL_V, " PIDS: ");
-		for(cnt = 0; cnt < ptr->pids_cnt; cnt++)
-			mp_msg(MSGT_DEMUX, MSGL_V, " %d ", ptr->pids[cnt]);
-		mp_msg(MSGT_DEMUX, MSGL_V, "\n");
-		
-		if((type == TUNER_TER) || (type == TUNER_CBL))
-		{
-			if(! strcmp(inv, "INVERSION_ON"))
-				ptr->inv = INVERSION_ON;
-			else if(! strcmp(inv, "INVERSION_OFF"))
-				ptr->inv = INVERSION_OFF;
-			else
-				ptr->inv = INVERSION_AUTO;
-
-
-			if(! strcmp(cr, "FEC_1_2"))
-				ptr->cr =FEC_1_2;
-			else if(! strcmp(cr, "FEC_2_3"))
-				ptr->cr =FEC_2_3;
-			else if(! strcmp(cr, "FEC_3_4"))
-				ptr->cr =FEC_3_4;
-#ifdef HAVE_DVB_HEAD
-			else if(! strcmp(cr, "FEC_4_5"))
-				ptr->cr =FEC_4_5;
-			else if(! strcmp(cr, "FEC_6_7"))
-				ptr->cr =FEC_6_7;
-			else if(! strcmp(cr, "FEC_8_9"))
-				ptr->cr =FEC_8_9;
-#endif
-			else if(! strcmp(cr, "FEC_5_6"))
-				ptr->cr =FEC_5_6;
-			else if(! strcmp(cr, "FEC_7_8"))
-				ptr->cr =FEC_7_8;
-			else if(! strcmp(cr, "FEC_NONE"))
-				ptr->cr =FEC_NONE;
-			else ptr->cr =FEC_AUTO;
-		}
-	
-
-		if((type == TUNER_TER) || (type == TUNER_CBL) || (type == TUNER_ATSC))
-		{
-			if(! strcmp(mod, "QAM_128"))
-				ptr->mod = QAM_128;
-			else if(! strcmp(mod, "QAM_256"))
-				ptr->mod = QAM_256;
-			else if(! strcmp(mod, "QAM_64"))
-				ptr->mod = QAM_64;
-			else if(! strcmp(mod, "QAM_32"))
-				ptr->mod = QAM_32;
-			else if(! strcmp(mod, "QAM_16"))
-				ptr->mod = QAM_16;
-#ifdef DVB_ATSC	
-			else if(! strcmp(mod, "VSB_8") || ! strcmp(mod, "8VSB"))
-				ptr->mod = VSB_8;
-			else if(! strcmp(mod, "VSB_16") || !strcmp(mod, "16VSB"))
-				ptr->mod = VSB_16;
-
-			ptr->inv = INVERSION_AUTO;
-#endif
-		}
-
-		if(type == TUNER_TER)
-		{
-			if(! strcmp(bw, "BANDWIDTH_6_MHZ"))
-				ptr->bw = BANDWIDTH_6_MHZ;
-			else if(! strcmp(bw, "BANDWIDTH_7_MHZ"))
-				ptr->bw = BANDWIDTH_7_MHZ;
-			else if(! strcmp(bw, "BANDWIDTH_8_MHZ"))
-				ptr->bw = BANDWIDTH_8_MHZ;
-
-
-			if(! strcmp(transm, "TRANSMISSION_MODE_2K"))
-				ptr->trans = TRANSMISSION_MODE_2K;
-			else if(! strcmp(transm, "TRANSMISSION_MODE_8K"))
-				ptr->trans = TRANSMISSION_MODE_8K;
-
-
-			if(! strcmp(gi, "GUARD_INTERVAL_1_32"))
-				ptr->gi = GUARD_INTERVAL_1_32;
-			else if(! strcmp(gi, "GUARD_INTERVAL_1_16"))
-				ptr->gi = GUARD_INTERVAL_1_16;
-			else if(! strcmp(gi, "GUARD_INTERVAL_1_8"))
-				ptr->gi = GUARD_INTERVAL_1_8;
-			else ptr->gi = GUARD_INTERVAL_1_4;
-			
-			if(! strcmp(tmp_lcr, "FEC_1_2"))
-				ptr->cr_lp =FEC_1_2;
-			else if(! strcmp(tmp_lcr, "FEC_2_3"))
-				ptr->cr_lp =FEC_2_3;
-			else if(! strcmp(tmp_lcr, "FEC_3_4"))
-				ptr->cr_lp =FEC_3_4;
-#ifdef HAVE_DVB_HEAD
-			else if(! strcmp(tmp_lcr, "FEC_4_5"))
-				ptr->cr_lp =FEC_4_5;
-			else if(! strcmp(tmp_lcr, "FEC_6_7"))
-				ptr->cr_lp =FEC_6_7;
-			else if(! strcmp(tmp_lcr, "FEC_8_9"))
-				ptr->cr_lp =FEC_8_9;
-#endif
-			else if(! strcmp(tmp_lcr, "FEC_5_6"))
-				ptr->cr_lp =FEC_5_6;
-			else if(! strcmp(tmp_lcr, "FEC_7_8"))
-				ptr->cr_lp =FEC_7_8;
-			else if(! strcmp(tmp_lcr, "FEC_NONE"))
-				ptr->cr_lp =FEC_NONE;
-			else ptr->cr_lp =FEC_AUTO;
-			
-			
-			if(! strcmp(tmp_hier, "HIERARCHY_1"))
-				ptr->hier = HIERARCHY_1;
-			else if(! strcmp(tmp_hier, "HIERARCHY_2"))
-				ptr->hier = HIERARCHY_2;
-			else if(! strcmp(tmp_hier, "HIERARCHY_4"))
-				ptr->hier = HIERARCHY_4;
-#ifdef HAVE_DVB_HEAD				
-			else if(! strcmp(tmp_hier, "HIERARCHY_AUTO"))
-				ptr->hier = HIERARCHY_AUTO;
-#endif
-			else	ptr->hier = HIERARCHY_NONE;
-		}
-
-		tmp = (dvb_channel_t*)realloc(list->channels, sizeof(dvb_channel_t) * (list->NUM_CHANNELS + 1));
-		if(tmp == NULL)
-			break;
-
-		list->channels = tmp;
-		memcpy(&(list->channels[list->NUM_CHANNELS]), ptr, sizeof(dvb_channel_t));
-		list->NUM_CHANNELS++;
-		if(sizeof(dvb_channel_t) * list->NUM_CHANNELS >= 1024*1024)
-		{
-			mp_msg(MSGT_DEMUX, MSGL_V, "dvbin.c, > 1MB allocated for channels struct, dropping the rest of the file\r\n");
-			break;
-		}
-	}
-
-	fclose(f);
-	if(list->NUM_CHANNELS == 0)
-	{
-		if(list->channels != NULL)
-			free(list->channels);
-		free(list);
-		return NULL;
-	}
-
-	list->current = 0;
-	return list;
-}
-
-
-
-static int dvb_streaming_read(stream_t *stream, char *buffer, int size)
-{
-	struct pollfd pfds[1];
-	int pos=0, tries, rk, fd;
-	dvb_priv_t *priv  = (dvb_priv_t *) stream->priv;
-
-	mp_msg(MSGT_DEMUX, MSGL_DBG3, "dvb_streaming_read(%d)\n", size);
-
-	tries = priv->retry + 1;
-	
-	fd = stream->fd;
-	while(pos < size)
-	{
-		pfds[0].fd = fd;
-		pfds[0].events = POLLIN | POLLPRI;
-
-		rk = size - pos;
-		if(poll(pfds, 1, 500) <= 0)
-		{
-			errno = 0;
-			mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_streaming_read, attempt N. %d failed with errno %d when reading %d bytes\n", tries, errno, size-pos);
-			if(--tries > 0)
-				continue;
-			else
-				break;
-		}
-		if((rk = read(fd, &buffer[pos], rk)) > 0)
-		{
-			pos += rk;
-			mp_msg(MSGT_DEMUX, MSGL_DBG3, "ret (%d) bytes\n", pos);
-		}
-	}
-		
-
-	if(! pos)
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_streaming_read, return %d bytes\n", pos);
-
-	return pos;
-}
-
-static void dvbin_close(stream_t *stream);
-
-int dvb_set_channel(dvb_priv_t *priv, int card, int n)
-{
-	dvb_channels_list *new_list;
-	dvb_channel_t *channel;
-	int do_tuning;
-	stream_t *stream  = (stream_t*) priv->stream;
-	char buf[4096];
-	dvb_config_t *conf = (dvb_config_t *) priv->config;
-	int devno;
-	int i;
-
-	if((card < 0) || (card > conf->count))
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_set_channel: INVALID CARD NUMBER: %d vs %d, abort\n", card, conf->count);
-		return 0;
-	}
-	
-	devno = conf->cards[card].devno;
-	new_list = conf->cards[card].list;
-	if((n > new_list->NUM_CHANNELS) || (n < 0))
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_set_channel: INVALID CHANNEL NUMBER: %d, for card %d, abort\n", n, card);
-		return 0;
-	}
-	channel = &(new_list->channels[n]);
-	
-	if(priv->is_on)	//the fds are already open and we have to stop the demuxers
-	{
-		for(i = 0; i < priv->demux_fds_cnt; i++)
-			dvb_demux_stop(priv->demux_fds[i]);
-			
-		priv->retry = 0;
-		while(dvb_streaming_read(stream, buf, 4096) > 0);	//empty both the stream's and driver's buffer
-		if(priv->card != card)
-		{
-			dvbin_close(stream);
-			if(! dvb_open_devices(priv, devno, channel->pids_cnt, channel->pids))
-			{
-				mp_msg(MSGT_DEMUX, MSGL_ERR, "DVB_SET_CHANNEL, COULDN'T OPEN DEVICES OF CARD: %d, EXIT\n", card);
-				return 0;
-			}
-			strcpy(priv->prev_tuning, "");
-		}
-		else	//close all demux_fds with pos > pids required for the new channel or open other demux_fds if we have too few
-		{	
-			if(! dvb_fix_demuxes(priv, channel->pids_cnt, channel->pids))
-				return 0;
-		}
-	}
-	else
-	{
-		if(! dvb_open_devices(priv, devno, channel->pids_cnt, channel->pids))
-		{
-			mp_msg(MSGT_DEMUX, MSGL_ERR, "DVB_SET_CHANNEL2, COULDN'T OPEN DEVICES OF CARD: %d, EXIT\n", card);
-			return 0;
-		}
-		strcpy(priv->prev_tuning, "");
-	}
-
-	dvb_config->priv = priv;
-	priv->card = card;
-	priv->list = new_list;
-	priv->retry = 5;
-	new_list->current = n;
-	stream->fd = priv->dvr_fd;
-	mp_msg(MSGT_DEMUX, MSGL_V, "DVB_SET_CHANNEL: new channel name=%s, card: %d, channel %d\n", channel->name, card, n);
-
-	switch(priv->tuner_type)
-	{
-		case TUNER_SAT:
-			sprintf(priv->new_tuning, "%d|%09d|%09d|%d|%c", priv->card, channel->freq, channel->srate, channel->diseqc, channel->pol);
-			break;
-
-		case TUNER_TER:
-			sprintf(priv->new_tuning, "%d|%09d|%d|%d|%d|%d|%d|%d", priv->card, channel->freq, channel->inv,
-				channel->bw, channel->cr, channel->mod, channel->trans, channel->gi);
-		  break;
-
-		case TUNER_CBL:
-			sprintf(priv->new_tuning, "%d|%09d|%d|%d|%d|%d", priv->card, channel->freq, channel->inv, channel->srate,
-				channel->cr, channel->mod);
-		break;
-#ifdef DVB_ATSC
-		case TUNER_ATSC:
-			sprintf(priv->new_tuning, "%d|%09d|%d", priv->card, channel->freq, channel->mod);
-		break;
-#endif
-	}
-
-
-
-	if(strcmp(priv->prev_tuning, priv->new_tuning))
-	{
-		mp_msg(MSGT_DEMUX, MSGL_V, "DIFFERENT TUNING THAN THE PREVIOUS: %s  -> %s\n", priv->prev_tuning, priv->new_tuning);
-		strcpy(priv->prev_tuning, priv->new_tuning);
-		do_tuning = 1;
-	}
-	else
-	{
-		mp_msg(MSGT_DEMUX, MSGL_V, "SAME TUNING PARAMETERS, NO TUNING\n");
-		do_tuning = 0;
-	}
-
-	stream->eof=1;
-	stream_reset(stream);
-
-
-	if(do_tuning)
-		if (! dvb_tune(priv, channel->freq, channel->pol, channel->srate, channel->diseqc, channel->tone,
-			channel->inv, channel->mod, channel->gi, channel->trans, channel->bw, channel->cr, channel->cr_lp, channel->hier, priv->timeout))
-			return 0;
-
-
-	priv->is_on = 1;
-
-	//sets demux filters and restart the stream
-	for(i = 0; i < channel->pids_cnt; i++)
-	{
-		if(! dvb_set_ts_filt(priv->demux_fds[i], channel->pids[i], DMX_PES_OTHER))
-			return 0;
-	}
-	
-	return 1;
-}
-
-
-
-int dvb_step_channel(dvb_priv_t *priv, int dir)
-{
-	int new_current;
-	dvb_channels_list *list;
-
-	mp_msg(MSGT_DEMUX, MSGL_V, "DVB_STEP_CHANNEL dir %d\n", dir);
-
-	if(priv == NULL)
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_step_channel: NULL priv_ptr, quit\n");
-		return 0;
-	}
-
-	list = priv->list;
-	if(list == NULL)
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_step_channel: NULL list_ptr, quit\n");
-		return 0;
-	}
-
-	new_current = (list->NUM_CHANNELS + list->current + (dir == DVB_CHANNEL_HIGHER ? 1 : -1)) % list->NUM_CHANNELS;
-
-	return dvb_set_channel(priv, priv->card, new_current);
-}
-
-
-
-
-extern char *get_path(const char *);
-
-static void dvbin_close(stream_t *stream)
-{
-	int i;
-	dvb_priv_t *priv  = (dvb_priv_t *) stream->priv;
-
-	for(i = priv->demux_fds_cnt-1; i >= 0; i--)
-	{
-		priv->demux_fds_cnt--;
-		mp_msg(MSGT_DEMUX, MSGL_V, "DVBIN_CLOSE, close(%d), fd=%d, COUNT=%d\n", i, priv->demux_fds[i], priv->demux_fds_cnt);
-		close(priv->demux_fds[i]);
-	}
-	close(priv->dvr_fd);
-
-	close(priv->fe_fd);
-#ifdef HAVE_DVB
-	close(priv->sec_fd);
-#endif
-
-	priv->is_on = 0;
-	dvb_config->priv = NULL;
-}
-
-
-static int dvb_streaming_start(dvb_priv_t *priv, struct stream_priv_s *opts, int tuner_type, char *progname)
-{
-	int i;
-	dvb_channel_t *channel = NULL;
-	stream_t *stream  = (stream_t*) priv->stream;
-
-	mp_msg(MSGT_DEMUX, MSGL_V, "\r\ndvb_streaming_start(PROG: %s, CARD: %d, VID: %d, AID: %d, TYPE: %s, FILE: %s)\r\n",
-	    opts->prog, opts->card, opts->vid, opts->aid,  opts->type, opts->file);
-
-	priv->is_on = 0;
-
-	i = 0;
-	while((channel == NULL) && i < priv->list->NUM_CHANNELS)
-	{
-		if(! strcmp(priv->list->channels[i].name, progname))
-			channel = &(priv->list->channels[i]);
-
-		i++;
-	}
-
-	if(channel != NULL)
-	{
-		priv->list->current = i-1;
-		mp_msg(MSGT_DEMUX, MSGL_V, "PROGRAM NUMBER %d: name=%s, freq=%u\n", i-1, channel->name, channel->freq);
-	}
-	else
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "\n\nDVBIN: no such channel \"%s\"\n\n", progname);
-		return 0;
-	}
-
-
-	strcpy(priv->prev_tuning, "");
-	if(!dvb_set_channel(priv, priv->card, priv->list->current))
-	{
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR, COULDN'T SET CHANNEL  %i: ", priv->list->current);
-		dvbin_close(stream);
-		return 0;
-	}
-
-	mp_msg(MSGT_DEMUX, MSGL_V,  "SUCCESSFUL EXIT from dvb_streaming_start\n");
-
-	return 1;
-}
-
-
-
-
-static int dvb_open(stream_t *stream, int mode, void *opts, int *file_format)
-{
-	// I don't force  the file format bacause, although it's almost always TS,
-	// there are some providers that stream an IP multicast with M$ Mpeg4 inside
-	struct stream_priv_s* p = (struct stream_priv_s*)opts;
-	dvb_priv_t *priv;
-	char *progname;
-	int tuner_type = 0;
-
-
-	if(mode != STREAM_READ)
-		return STREAM_UNSUPORTED;
-
-	stream->priv = (dvb_priv_t*) malloc(sizeof(dvb_priv_t));
-	if(stream->priv ==  NULL)
-		return STREAM_ERROR;
-
-	priv = (dvb_priv_t *)stream->priv;
-	priv->stream = stream;
-	dvb_config = dvb_get_config();
-	if(dvb_config == NULL)
-	{
-		free(priv);
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "DVB CONFIGURATION IS EMPTY, exit\n");
-		return STREAM_ERROR;
-	}
-	dvb_config->priv = priv;
-	priv->config = dvb_config;
-
-	if(p->card < 1 || p->card > priv->config->count)
- 	{
-		free(priv);
-		mp_msg(MSGT_DEMUX, MSGL_ERR, "NO CONFIGURATION FOUND FOR CARD N. %d, exit\n", p->card);
- 		return STREAM_ERROR;
- 	}
-	priv->card = p->card - 1;
-	priv->timeout = p->timeout;
-	
-	tuner_type = priv->config->cards[priv->card].type;
-
-	if(tuner_type == 0)
-	{
-		free(priv);
-		mp_msg(MSGT_DEMUX, MSGL_V, "OPEN_DVB: UNKNOWN OR UNDETECTABLE TUNER TYPE, EXIT\n");
-		return STREAM_ERROR;
-	}
-
-
-	priv->tuner_type = tuner_type;
-
-	mp_msg(MSGT_DEMUX, MSGL_V, "OPEN_DVB: prog=%s, card=%d, type=%d, vid=%d, aid=%d\n",
-		p->prog, priv->card+1, priv->tuner_type, p->vid, p->aid);
-
-	priv->list = priv->config->cards[priv->card].list;
-	
-	if((! strcmp(p->prog, "")) && (priv->list != NULL))
-		progname = priv->list->channels[0].name;
-	else
-		progname = p->prog;
-
-
-	if(! dvb_streaming_start(priv, p, tuner_type, progname))
-	{
-		free(stream->priv);
-		stream->priv = NULL;
-		return STREAM_ERROR;
-	}
-
-	stream->type = STREAMTYPE_DVB;
-	stream->fill_buffer = dvb_streaming_read;
-	stream->close = dvbin_close;
-	m_struct_free(&stream_opts, opts);
-	
-	*file_format = DEMUXER_TYPE_MPEG_TS;
-
-	return STREAM_OK;
-}
-
-#define MAX_CARDS 4
-dvb_config_t *dvb_get_config(void)
-{
-	int i, fd, type, size;
-	char filename[30], *conf_file, *name;
-	dvb_channels_list *list;
-	dvb_card_config_t *cards = NULL, *tmp;
-	dvb_config_t *conf = NULL;
-	
-	if(dvb_config != NULL)
-		return dvb_config;
-			
-	conf = (dvb_config_t*) malloc(sizeof(dvb_config_t));
-	if(conf == NULL)
-		return NULL;
-
-	conf->priv = NULL;	
-	conf->count = 0;
-	conf->cards = NULL;
-	for(i=0; i<MAX_CARDS; i++)
-	{
-		sprintf(filename, "/dev/dvb/adapter%d/frontend0", i);
-		fd = open(filename, O_RDWR | O_NONBLOCK);
-		if(fd < 0)
-		{
-			mp_msg(MSGT_DEMUX, MSGL_V, "DVB_CONFIG, can't open device %s, skipping\n", filename);
-			continue;
-		}
-			
-		type = dvb_get_tuner_type(fd);
-		close(fd);
-		if(type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL && type != TUNER_ATSC)
-		{
-			mp_msg(MSGT_DEMUX, MSGL_V, "DVB_CONFIG, can't detect tuner type of card %d, skipping\n", i);
-			continue;
-		}
-		
-		switch(type)
-		{
-			case TUNER_TER:
-			conf_file = get_path("channels.conf.ter");
-				break;
-			case TUNER_CBL:
-			conf_file = get_path("channels.conf.cbl");
-				break;
-			case TUNER_SAT:
-			conf_file = get_path("channels.conf.sat");
-				break;
-			case TUNER_ATSC:
-			conf_file = get_path("channels.conf.atsc");
-				break;
-		}
-		
-		if((access(conf_file, F_OK | R_OK) != 0))
-			conf_file = get_path("channels.conf");
-
-		list = dvb_get_channels(conf_file, type);
-		if(list == NULL)
-			continue;
-		
-		size = sizeof(dvb_card_config_t) * (conf->count + 1);
-		tmp = realloc(conf->cards, size);
-
-		if(tmp == NULL)
-		{
-			fprintf(stderr, "DVB_CONFIG, can't realloc %d bytes, skipping\n", size);
-			continue;
-		}
-		cards = tmp;
-
-		name = (char*) malloc(20);
-		if(name==NULL)
-		{
-			fprintf(stderr, "DVB_CONFIG, can't realloc 20 bytes, skipping\n");
-			continue;
-		}
-
-		conf->cards = cards;
-		conf->cards[conf->count].devno = i;
-		conf->cards[conf->count].list = list;
-		conf->cards[conf->count].type = type;
-		sprintf(name, "DVB-%c card n. %d", type==TUNER_TER ? 'T' : (type==TUNER_CBL ? 'C' : 'S'), conf->count+1);
-		conf->cards[conf->count].name = name;
-		conf->count++;
-	}
-
-	if(conf->count == 0)
-	{
-		free(conf);
-		conf = NULL;
-	}
-
-	dvb_config = conf;
-	return conf;
-}
-
-
-
-stream_info_t stream_info_dvb = {
-	"Dvb Input",
-	"dvbin",
-	"Nico",
-	"based on the code from ??? (probably Arpi)",
-	dvb_open, 			
-	{ "dvb", NULL },
-	&stream_opts,
-	1 				// Urls are an option string
-};
--- a/libmpdemux/dvbin.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/* Imported from the dvbstream project
- *
- * Modified for use with MPlayer, for details see the changelog at
- * http://svn.mplayerhq.hu/mplayer/trunk/
- * $Id$
- */
-
-#ifndef DVBIN_H
-#define DVBIN_H
-
-#include "stream.h"
-
-#define SLOF (11700*1000UL)
-#define LOF1 (9750*1000UL)
-#define LOF2 (10600*1000UL)
-
-#ifdef HAVE_DVB_HEAD
-	#include <linux/dvb/dmx.h>
-	#include <linux/dvb/frontend.h>
-	#include <linux/dvb/version.h>
-#else
-	#include <ost/dmx.h>
-	#include <ost/sec.h>
-	#include <ost/frontend.h>
-	#define fe_status_t FrontendStatus
-	#define fe_spectral_inversion_t SpectralInversion
-	#define fe_modulation_t Modulation
-	#define fe_code_rate_t CodeRate
-	#define fe_transmit_mode_t TransmitMode
-	#define fe_guard_interval_t GuardInterval
-	#define fe_bandwidth_t BandWidth
-	#define fe_hierarchy_t Hierarchy
-	#define fe_sec_voltage_t SecVoltage
-	#define dmx_pes_filter_params dmxPesFilterParams
-	#define dmx_sct_filter_params dmxSctFilterParams
-	#define dmx_pes_type_t dmxPesType_t
-#endif
-
-#undef DVB_ATSC
-#if defined(DVB_API_VERSION_MINOR)
-#if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR >= 1
-#define DVB_ATSC 1
-#endif
-#endif
-
-
-#define DVB_CHANNEL_LOWER -1
-#define DVB_CHANNEL_HIGHER 1
-
-#include "inttypes.h"
-
-#ifndef DMX_FILTER_SIZE
-#define DMX_FILTER_SIZE 16
-#endif
-
-typedef struct {
-	char 				*name;
-	int 				freq, srate, diseqc, tone;
-	char 				pol;
-	int 				tpid, dpid1, dpid2, progid, ca, pids[DMX_FILTER_SIZE], pids_cnt;
-	fe_spectral_inversion_t 	inv;
-	fe_modulation_t 		mod;
-	fe_transmit_mode_t 		trans;
-	fe_bandwidth_t 			bw;
-	fe_guard_interval_t 		gi;
-	fe_code_rate_t 			cr, cr_lp;
-	fe_hierarchy_t			hier;
-} dvb_channel_t;
-
-
-typedef struct {
-	uint16_t NUM_CHANNELS;
-	uint16_t current;
-	dvb_channel_t *channels;
-} dvb_channels_list;
-
-typedef struct {
-	int type;
-	dvb_channels_list *list;
-	char *name;
-	int devno;
-} dvb_card_config_t;
-
-typedef struct {
-	int count;
-	dvb_card_config_t *cards;
-	void *priv;
-} dvb_config_t;
-
-
-typedef struct {
-	int card;
-    int fe_fd;
-    int sec_fd;
-    int demux_fd[3], demux_fds[DMX_FILTER_SIZE], demux_fds_cnt;
-    int dvr_fd;
-
-    dvb_config_t *config;
-    dvb_channels_list *list;
-	int tuner_type;
-	int is_on;
-	stream_t *stream;
-	char new_tuning[256], prev_tuning[256];
-	int retry;
-	int timeout;
-} dvb_priv_t;
-
-
-#define TUNER_SAT	1
-#define TUNER_TER	2
-#define TUNER_CBL	3
-#define TUNER_ATSC	4
-
-extern int dvb_step_channel(dvb_priv_t *, int);
-extern int dvb_set_channel(dvb_priv_t *, int, int);
-extern dvb_config_t *dvb_get_config(void);
-
-#endif
--- a/libmpdemux/dvdnav_stream.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,396 +0,0 @@
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include "mp_msg.h"
-#include "osdep/timer.h"
-#include "input/input.h"
-#include "stream.h"
-#include "demuxer.h"
-#include "dvdnav_stream.h"
-#include "libvo/video_out.h"
-#include "spudec.h"
-#include "m_option.h"
-#include "m_struct.h"
-#include "help_mp.h"
-
-extern char *dvd_device;
-extern char *audio_lang, *dvdsub_lang;
-
-static struct stream_priv_s {
-  int track;
-  char* device;
-} stream_priv_dflts = {
-  1,
-  NULL
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  {"filename", 	ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
-  {"hostname", 	ST_OFF(track), CONF_TYPE_INT, 0, 0, 0, NULL},
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-static struct m_struct_st stream_opts = {
-  "dvd",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-int dvd_nav_skip_opening=0;     /* skip opening stalls? */
-int osd_show_dvd_nav_delay=0;   /* count down for dvd nav text on OSD */
-char dvd_nav_text[50];          /* for reporting stuff to OSD */
-int osd_show_dvd_nav_highlight; /* show highlight area */
-int osd_show_dvd_nav_sx;        /* start x .... */
-int osd_show_dvd_nav_ex;
-int osd_show_dvd_nav_sy;
-int osd_show_dvd_nav_ey;
-int dvd_nav_still=0;            /* are we on a still picture? */
-
-dvdnav_priv_t * new_dvdnav_stream(char * filename) {
-  char * title_str;
-  dvdnav_priv_t *dvdnav_priv;
-
-  if (!filename)
-    return NULL;
-
-  if (!(dvdnav_priv=calloc(1,sizeof(*dvdnav_priv))))
-    return NULL;
-
-  if (!(dvdnav_priv->filename=strdup(filename))) {
-    free(dvdnav_priv);
-    return NULL;
-  }
-
-  if(dvdnav_open(&(dvdnav_priv->dvdnav),dvdnav_priv->filename)!=DVDNAV_STATUS_OK)
-  {
-    free(dvdnav_priv->filename);
-    free(dvdnav_priv);
-    return NULL;
-  }
-
-  if (!dvdnav_priv->dvdnav) {
-    free(dvdnav_priv);
-    return NULL;
-  }
-
-  if(1)	//from vlc: if not used dvdnav from cvs will fail
-  {
-    int len, event;
-    char buf[2048];
-    
-    dvdnav_get_next_block(dvdnav_priv->dvdnav,buf,&event,&len);
-  }
-  
-  /* turn on dvdnav caching */
-  dvdnav_set_readahead_flag(dvdnav_priv->dvdnav, 0);
-  if(dvdnav_set_PGC_positioning_flag(dvdnav_priv->dvdnav, 1) != DVDNAV_STATUS_OK)
-    mp_msg(MSGT_OPEN,MSGL_ERR,"stream_dvdnav, failed to set PGC positioning\n");
-#if 1
-  /* report the title?! */
-  if (dvdnav_get_title_string(dvdnav_priv->dvdnav,&title_str)==DVDNAV_STATUS_OK) {
-    mp_msg(MSGT_IDENTIFY, MSGL_INFO,"Title: '%s'\n",title_str);
-  }
-#endif
-
-  //dvdnav_event_clear(dvdnav_priv);
-
-  return dvdnav_priv;
-}
-
-int dvdnav_stream_reset(dvdnav_priv_t * dvdnav_priv) {
-  if (!dvdnav_priv) return 0;
-
-//  if (dvdnav_reset(dvdnav_priv->dvdnav)!=DVDNAV_STATUS_OK)
-    return 0;
-
-  dvdnav_priv->started=0;
-
-  return 1;
-}
-
-int dvdnav_stream_sleeping(dvdnav_priv_t * dvdnav_priv) {
-    unsigned int now;
-
-    if (!dvdnav_priv) return 0;
-
-    if(dvdnav_priv->sleeping)
-    {
-      now=GetTimer();
-      while(dvdnav_priv->sleeping>1 || now<dvdnav_priv->sleep_until) {
-//        printf("%s %u<%u\n",__FUNCTION__,now,dvdnav_priv->sleep_until);
-//        usec_sleep(1000); /* 1ms granularity */
-        return 1; 
-      }
-      dvdnav_still_skip(dvdnav_priv->dvdnav); // continue past...
-      dvdnav_priv->sleeping=0;
-      mp_msg(MSGT_OPEN,MSGL_V, "%s: woke up!\n",__FUNCTION__);
-    }
-    dvd_nav_still=0;
-    mp_msg(MSGT_OPEN,MSGL_V, "%s: active\n",__FUNCTION__);
-    return 0;
-}
-
-void dvdnav_stream_sleep(dvdnav_priv_t * dvdnav_priv, int seconds) {
-    if (!dvdnav_priv) return;
-
-    if (!dvdnav_priv->started) return;
-
-    dvdnav_priv->sleeping=0;
-    switch (seconds) {
-    case 0:
-            return;
-    case 0xff:
-            mp_msg(MSGT_OPEN,MSGL_V, "Sleeping indefinately\n" );
-            dvdnav_priv->sleeping=2;
-            break;
-    default:
-            mp_msg(MSGT_OPEN,MSGL_V, "Sleeping %d sec(s)\n", seconds );
-            dvdnav_priv->sleep_until = GetTimer();// + seconds*1000000;
-            dvdnav_priv->sleeping=1;
-            break;
-    }
-    //if (dvdnav_priv->started) dvd_nav_still=1;
-}
-
-void dvdnav_stream_add_event(dvdnav_priv_t* dvdnav_priv, int event, unsigned char *buf, int len) {
-  //printf("%s: %d\n",__FUNCTION__,event);
-
-  dvdnav_event_t * dvdnav_event;
-  mp_cmd_t * cmd;
-
-  if (!dvdnav_priv->started) return;
-
-  if (!(dvdnav_event=calloc(1,sizeof(*dvdnav_event)))) {
-    mp_msg(MSGT_OPEN,MSGL_V, "%s: dvdnav_event: out of memory!\n",__FUNCTION__);
-    return;
-  }
-  dvdnav_event->event=event;
-  dvdnav_event->details=calloc(1,len);
-  memcpy(dvdnav_event->details,buf,len);
-  dvdnav_event->len=len;
-
-  if (!(cmd = calloc(1,sizeof(*cmd)))) {
-    mp_msg(MSGT_OPEN,MSGL_V, "%s: mp_cmd_t: out of memory!\n",__FUNCTION__);
-    free(dvdnav_event->details);
-    free(dvdnav_event);
-    return;
-  }
-  cmd->id=MP_CMD_DVDNAV_EVENT; // S+event;
-  cmd->name=strdup("dvdnav_event"); // FIXME: do I really need a 'name'?
-  cmd->nargs=1;
-  cmd->args[0].v.v=dvdnav_event;
-}
-
-int dvdnav_stream_read(dvdnav_priv_t * dvdnav_priv, unsigned char *buf, int *len) {
-  int event = DVDNAV_NOP;
-
-  if (!len) return -1;
-  *len=-1;
-  if (!dvdnav_priv) return -1;
-  if (!buf) return -1;
-
-  if (dvd_nav_still) {
-    mp_msg(MSGT_OPEN,MSGL_V, "%s: got a stream_read while I should be asleep!\n",__FUNCTION__);
-    *len=0;
-    return -1;
-  }
-
-  if (dvdnav_get_next_block(dvdnav_priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) {
-    mp_msg(MSGT_OPEN,MSGL_V, "Error getting next block from DVD %d (%s)\n",event, dvdnav_err_to_string(dvdnav_priv->dvdnav) );
-    *len=-1;
-  }
-  else if (event!=DVDNAV_BLOCK_OK) {
-
-    // need to handle certain events internally (like skipping stills)
-    switch (event) {
-    case DVDNAV_STILL_FRAME: {
-      dvdnav_still_event_t *still_event = (dvdnav_still_event_t*)(buf);
-      //if (dvdnav_priv->started) dvd_nav_still=1;
-      //else
-        dvdnav_still_skip(dvdnav_priv->dvdnav); // don't let dvdnav stall on this image
-
-      break;
-    case DVDNAV_WAIT:
-        dvdnav_wait_skip(dvdnav_priv->dvdnav);
-        break;
-    }
-    }
-
-    // got an event, repeat the read
-    dvdnav_stream_add_event(dvdnav_priv,event,buf,*len);
-    *len=0;
-  }
-//  printf("%s: got %d\n",__FUNCTION__,*len);
-  return event;
-}
-
-void dvdnav_stream_fullstart(dvdnav_priv_t * dvdnav_priv) {
-  if (dvdnav_priv && !dvdnav_priv->started) {
-    dvdnav_stream_reset(dvdnav_priv);
-    dvdnav_priv->started=1;
-  }
-}
-
-unsigned int * dvdnav_stream_get_palette(dvdnav_priv_t * dvdnav_priv) {
-  if (!dvdnav_priv) {
-    mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv\n",__FUNCTION__);
-    return NULL;
-  }
-  if (!dvdnav_priv->dvdnav) {
-    mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv->dvdnav\n",__FUNCTION__);
-    return NULL;
-  }
-  #if 0
-  if (!dvdnav_priv->dvdnav->vm) {
-    mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv->dvdnav->vm\n",__FUNCTION__);
-    return NULL;
-  }
-  if (!dvdnav_priv->dvdnav->vm->state.pgc) {
-    printf("%s: NULL dvdnav_priv->dvdnav->vm->state.pgc\n",__FUNCTION__);
-    return NULL;
-  }
-  return dvdnav_priv->dvdnav->vm->state.pgc->palette;
-  #endif
-}
-
-static void update_title_len(stream_t *stream) {
-  dvdnav_priv_t *priv = stream->priv;
-  dvdnav_status_t status;
-  uint32_t pos = 0, len = 0;
-
-  status = dvdnav_get_position(priv->dvdnav, &pos, &len);
-  if(status == DVDNAV_STATUS_OK && len)
-    stream->end_pos = (off_t) len * 2048;
-}
-  
-
-static int seek(stream_t *s, off_t newpos) {
-uint32_t pos = 0, len = 0, sector = 0;
-dvdnav_priv_t *priv = s->priv;
-
-  if(newpos==0) {
-    if(dvdnav_stream_reset(priv->dvdnav))
-      s->pos=0;
-  }
-  else {
-    if(s->end_pos && newpos > s->end_pos) 
-       newpos = s->end_pos;
-    sector = newpos / 2048ULL;
-    if(dvdnav_sector_search(priv->dvdnav, (uint64_t) sector, SEEK_SET) != DVDNAV_STATUS_OK)
-      goto fail;
-
-    s->pos = newpos;
-  }
-  
-  return 1;
-  
-fail:
-    mp_msg(MSGT_STREAM,MSGL_INFO,"dvdnav_stream, seeking to %"PRIu64" failed: %s\n", newpos, dvdnav_err_to_string(priv->dvdnav));
-
-  return 1;
-}
-
-static void stream_dvdnav_close(stream_t *s) {
-  dvdnav_priv_t *priv = s->priv;
-  dvdnav_close(priv->dvdnav);
-  priv->dvdnav = NULL;
-  free(priv);
-}
-
-
-static int fill_buffer(stream_t *s, char *but, int len)
-{
-    int event;
-    dvdnav_priv_t* dvdnav_priv=s->priv;
-    len=0;
-    if(!s->end_pos)
-      update_title_len(s);
-    while(!len) /* grab all event until DVDNAV_BLOCK_OK (len=2048), DVDNAV_STOP or DVDNAV_STILL_FRAME */
-    {
-        if(-1==(event=dvdnav_stream_read(dvdnav_priv, s->buffer, &len)) || len==-1)
-        {
-            mp_msg(MSGT_CPLAYER,MSGL_ERR, "DVDNAV stream read error!\n");
-            return 0;
-        }
-        switch (event) {
-            case DVDNAV_STOP: return len;
-	    case DVDNAV_BLOCK_OK: return len;
-#if 0
-            case DVDNAV_STILL_FRAME: {
-                if(!dvdnav_priv->stillok) dvdnav_priv->stillcounter++;
-                dvdnav_priv->lockstillcounter++;
-                return len;
-                break; 
-            }
-	    
-            case DVDNAV_WAIT: {
-                if(dvdnav_priv->waitcounter>=DVDNAV_MAX_WAIT_FRAME) return len;
-                break;
-            }
-#endif
-        }
-#if 0
-        if(dvdnav_priv->event.cell_really_change &&
-            dvdnav_priv->started &&
-	    !dvdnav_priv->vts_domain) 
-	        return len;
-#endif
-  }
-  mp_msg(MSGT_STREAM,MSGL_DBG2,"DVDNAV fill_buffer len: %d\n",len);
-  return len;
-}
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-  char *filename;
-  int event,len,tmplen=0;
-  uint32_t pos, l2;
-  dvdnav_priv_t *dvdnav_priv;
-  dvdnav_status_t status;
-
-  //mp_msg(MSGT_OPEN,MSGL_INFO,"URL: %s\n", filename);
-  
-  if(p->device) filename = p->device; 
-  else if(dvd_device) filename= dvd_device; 
-  else filename = DEFAULT_DVD_DEVICE;
-  if(!(dvdnav_priv=new_dvdnav_stream(filename))) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename);
-    return STREAM_UNSUPORTED;
-  }
-
-  if(dvdnav_title_play(dvdnav_priv->dvdnav, p->track) != DVDNAV_STATUS_OK) {
-    mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(dvdnav_priv->dvdnav));
-    return STREAM_UNSUPORTED;
-  }
-
-  stream->sector_size = 2048;
-  stream->flags = STREAM_READ | STREAM_SEEK;
-  stream->fill_buffer = fill_buffer;
-  stream->seek = seek;
-  stream->close = stream_dvdnav_close;
-  stream->type = STREAMTYPE_DVDNAV;
-  stream->priv=(void*)dvdnav_priv;
-  *file_format = DEMUXER_TYPE_MPEG_PS;
-
-  update_title_len(stream);
-  if(!stream->pos)
-    mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: %d, couldn't get init pos %s\r\n", status, dvdnav_err_to_string(dvdnav_priv->dvdnav));
-
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_dvdnav = {
-  "DVDNAV stream",
-  "null",
-  "",
-  "",
-  open_s,
-  { "dvdnav", NULL },
-  &stream_opts,
-  1 // Urls are an option string
-};
--- a/libmpdemux/dvdnav_stream.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#ifndef _MPLAYER_DVDNAV_STREAM_H
-#define _MPLAYER_DVDNAV_STREAM_H
-
-#include <dvdnav.h>
-
-typedef struct {
-  int event;             /* event number fromd dvdnav_events.h */
-  void * details;        /* event details */
-  int len;               /* bytes in details */
-} dvdnav_event_t;
-
-typedef struct {
-  dvdnav_t *       dvdnav;              /* handle to libdvdnav stuff */
-  char *           filename;            /* path */
-  int              ignore_timers;       /* should timers be skipped? */
-  int              sleeping;            /* are we sleeping? */
-  unsigned int     sleep_until;         /* timer */
-  int              started;             /* Has mplayer initialization finished? */
-  unsigned char    prebuf[STREAM_BUFFER_SIZE]; /* prefill buffer */
-  int              prelen;              /* length of prefill buffer */
-} dvdnav_priv_t;
-
-extern int dvd_nav_still;
-extern int dvd_nav_skip_opening;
-extern char dvd_nav_text[50];
-extern int osd_show_dvd_nav_delay;
-extern int osd_show_dvd_nav_highlight;
-extern int osd_show_dvd_nav_sx;
-extern int osd_show_dvd_nav_ex;
-extern int osd_show_dvd_nav_sy;
-extern int osd_show_dvd_nav_ey;
-
-dvdnav_priv_t * new_dvdnav_stream(char * filename);
-int dvdnav_stream_reset(dvdnav_priv_t * dvdnav_priv);
-void free_dvdnav_stream(dvdnav_priv_t * dvdnav_priv);
-
-void dvdnav_stream_ignore_timers(dvdnav_priv_t * dvdnav_priv, int ignore);
-int dvdnav_stream_read(dvdnav_priv_t * dvdnav_priv, unsigned char *buf, int *len);
-
-void dvdnav_stream_sleep(dvdnav_priv_t *dvdnav_priv, int seconds);
-int dvdnav_stream_sleeping(dvdnav_priv_t * dvdnav_priv);
-
-void dvdnav_stream_fullstart(dvdnav_priv_t *dvdnav_priv);
-unsigned int * dvdnav_stream_get_palette(dvdnav_priv_t * dvdnav_priv);
-
-#endif
--- a/libmpdemux/freesdp/common.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
-  This file is part of FreeSDP
-  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@suidzer0.org>
-
-  FreeSDP is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU 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
-*/
-
-/**
- * @file common.c
- *
- * @short Implementation of routines common to parse and formatting
- * modules .
- *
- * This file implements the routines that operate over data structures
- * that are used in both the parse and formatting modules.
- **/
-
-#include "priv.h"
-#include "common.h"
-
-static void
-safe_free (void *ptr)
-{
-  if (ptr)
-    free (ptr);
-}
-
-fsdp_description_t *
-fsdp_description_new (void)
-{
-  fsdp_description_t *result = malloc (sizeof (fsdp_description_t));
-
-  result->version = 0;
-  result->o_username = result->o_session_id =
-    result->o_announcement_version = NULL;
-  result->o_network_type = FSDP_NETWORK_TYPE_UNDEFINED;
-  result->o_address_type = FSDP_ADDRESS_TYPE_UNDEFINED;
-  result->o_address = NULL;
-  result->s_name = NULL;
-  result->i_information = NULL;
-  result->u_uri = NULL;
-  result->emails = NULL;
-  result->emails_count = 0;
-  result->phones = NULL;
-  result->phones_count = 0;
-  /* At first, there is no session-level definition for these
-     parameters */
-  result->c_network_type = FSDP_NETWORK_TYPE_UNDEFINED;
-  result->c_address_type = FSDP_ADDRESS_TYPE_UNDEFINED;
-  result->c_address.address = NULL;
-  /* there is no session-level definition for these parameters */
-  result->bw_modifiers = NULL;
-  result->bw_modifiers_count = 0;
-  result->time_periods = NULL;
-  result->time_periods_count = 0;
-  result->timezone_adj = NULL;
-  result->k_encryption_method = FSDP_ENCRYPTION_METHOD_UNDEFINED;
-  result->k_encryption_content = NULL;
-  /* Default/undefined values for attributes */
-  result->a_category = result->a_keywords = result->a_tool = NULL;
-  result->a_type = FSDP_SESSION_TYPE_UNDEFINED;
-  result->a_sendrecv_mode = FSDP_SENDRECV_UNDEFINED;
-  result->a_charset = NULL;
-  result->a_sdplangs = result->a_langs = NULL;
-  result->a_controls = NULL;
-  result->a_range = NULL;
-  result->a_rtpmaps = NULL;
-  result->a_rtpmaps_count = 0;
-  result->a_sdplangs_count = 0;
-  result->a_langs_count = 0;
-  result->a_controls_count = 0;
-  result->unidentified_attributes = NULL;
-  result->unidentified_attributes_count = 0;
-  result->media_announcements = NULL;
-  result->media_announcements_count = 0;
-
-  return result;
-}
-
-void
-fsdp_description_delete (fsdp_description_t * dsc)
-{
-  fsdp_description_recycle (dsc);
-  safe_free (dsc);
-}
-
-void
-fsdp_description_recycle (fsdp_description_t * dsc)
-{
-  /* Recursively free all strings and arrays */
-  unsigned int i, j;
-
-  if (!dsc)
-    return;
-
-  safe_free (dsc->o_username);
-  safe_free (dsc->o_session_id);
-  safe_free (dsc->o_announcement_version);
-  safe_free (dsc->o_address);
-  safe_free (dsc->s_name);
-  safe_free (dsc->i_information);
-  safe_free (dsc->u_uri);
-
-  for (i = 0; i < dsc->emails_count; i++)
-    safe_free ((char *) dsc->emails[i]);
-  safe_free (dsc->emails);
-
-  for (i = 0; i < dsc->phones_count; i++)
-    safe_free ((char *) dsc->phones[i]);
-  safe_free (dsc->phones);
-
-  safe_free (dsc->c_address.address);
-
-  for (i = 0; i < dsc->bw_modifiers_count; i++)
-    safe_free (dsc->bw_modifiers[i].b_unknown_bw_modt);
-  safe_free (dsc->bw_modifiers);
-
-  for (i = 0; i < dsc->time_periods_count; i++)
-  {
-    for (j = 0; j < dsc->time_periods[i]->repeats_count; j++)
-    {
-      safe_free (dsc->time_periods[i]->repeats[j]->offsets);
-      safe_free (dsc->time_periods[i]->repeats[j]);
-    }
-    safe_free (dsc->time_periods[i]->repeats);
-    safe_free (dsc->time_periods[i]);
-  }
-  safe_free (dsc->time_periods);
-
-  safe_free (dsc->timezone_adj);
-  safe_free (dsc->a_category);
-  safe_free (dsc->a_keywords);
-  safe_free (dsc->a_tool);
-
-  for (i = 0; i < dsc->a_rtpmaps_count; i++)
-    safe_free (dsc->a_rtpmaps[i]);
-  safe_free (dsc->a_rtpmaps);
-
-  safe_free (dsc->a_charset);
-
-  for (i = 0; i < dsc->a_sdplangs_count; i++)
-    safe_free (dsc->a_sdplangs[i]);
-  safe_free (dsc->a_sdplangs);
-
-  for (i = 0; i < dsc->a_langs_count; i++)
-    safe_free (dsc->a_langs[i]);
-  safe_free (dsc->a_langs);
-
-  for (i = 0; i < dsc->a_controls_count; i++)
-    safe_free (dsc->a_controls[i]);
-  safe_free (dsc->a_controls);
-
-  safe_free (dsc->a_range);
-
-  for (i = 0; i < dsc->media_announcements_count; i++)
-  {
-    for (j = 0; j < dsc->media_announcements[i]->formats_count; j++)
-      safe_free (dsc->media_announcements[i]->formats[j]);
-    safe_free (dsc->media_announcements[i]->formats);
-    safe_free (dsc->media_announcements[i]->i_title);
-
-    for (j = 0; j < dsc->media_announcements[i]->bw_modifiers_count; j++)
-    {
-      if (FSDP_BW_MOD_TYPE_UNKNOWN ==
-          dsc->media_announcements[i]->bw_modifiers[j].b_mod_type)
-        safe_free (dsc->media_announcements[i]->bw_modifiers[j].
-                   b_unknown_bw_modt);
-    }
-    safe_free (dsc->media_announcements[i]->bw_modifiers);
-
-    safe_free (dsc->media_announcements[i]->k_encryption_content);
-
-    for (j = 0; j < dsc->media_announcements[i]->a_rtpmaps_count; j++)
-    {
-      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->pt);
-      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->
-                 encoding_name);
-      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->parameters);
-      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]);
-    }
-    safe_free (dsc->media_announcements[i]->a_rtpmaps);
-
-    for (j = 0; j < dsc->media_announcements[i]->a_sdplangs_count; j++)
-      safe_free (dsc->media_announcements[i]->a_sdplangs[j]);
-    safe_free (dsc->media_announcements[i]->a_sdplangs);
-
-    for (j = 0; j < dsc->media_announcements[i]->a_langs_count; j++)
-      safe_free (dsc->media_announcements[i]->a_langs[j]);
-    safe_free (dsc->media_announcements[i]->a_langs);
-
-    for (j = 0; j < dsc->media_announcements[i]->a_controls_count; j++)
-      safe_free (dsc->media_announcements[i]->a_controls[j]);
-    safe_free (dsc->media_announcements[i]->a_controls);
-
-    for (j = 0; j < dsc->media_announcements[i]->a_fmtps_count; j++)
-      safe_free (dsc->media_announcements[i]->a_fmtps[j]);
-    safe_free (dsc->media_announcements[i]->a_fmtps);
-
-    for (j = 0;
-         j < dsc->media_announcements[i]->unidentified_attributes_count; j++)
-      safe_free (dsc->media_announcements[i]->unidentified_attributes[j]);
-    safe_free (dsc->media_announcements[i]->unidentified_attributes);
-    safe_free (dsc->media_announcements[i]);
-  }
-  safe_free (dsc->media_announcements);
-
-  /* This prevents the user to make the library crash when incorrectly
-     using recycled but not rebuilt descriptions */
-  dsc->emails_count = 0;
-  dsc->phones_count = 0;
-  dsc->bw_modifiers_count = 0;
-  dsc->time_periods_count = 0;
-  dsc->media_announcements_count = 0;
-}
--- a/libmpdemux/freesdp/common.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
-  This file is part of FreeSDP.
-  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
-
-  FreeSDP is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU 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
-*/
-
-/**
- * @file common.h
- * @ingroup common
- * @short Public header common for both parsing and formatting modules.
- **/
-
-#ifndef FSDP_COMMON_H
-#define FSDP_COMMON_H
-
-/* Macros to avoid name mangling when compiling with a C++ compiler */
-#ifdef __cplusplus
-#  define BEGIN_C_DECLS extern "C" {
-#  define END_C_DECLS   }
-#else /* !__cplusplus */
-#  define BEGIN_C_DECLS
-#  define END_C_DECLS
-#endif /* __cplusplus */
-
-#include <sys/time.h>
-#include <time.h>
-
-BEGIN_C_DECLS
-/**
- * @defgroup common FreeSDP Common Facilities
- *
- * Data types and routines common for both parsing and formatting
- * modules.
- **/
-/** @addtogroup common */
-/*@{*/
-/**
- * @enum fsdp_error_t freesdp/common.h
- * @short Error codes in the FreeSDP library.
- *
- * There is a FSDPE_MISSING_XXXX for each mandatory line, as
- * FSDPE_MISSING_OWNER. This kind of error is reported when a
- * mandatory description line, such as the owner line, is not found
- * where it should be in the SDP description. There are also several
- * error codes like FSDPE_INVALID_XXXX. These are returned when there
- * is a recognized line in the parsed description that violates the
- * SDP syntax or gives wrong parameters, for instance "c=foo bar",
- * which would cause a FSDPE_INVALID_CONNECTION error code to be
- * returned.
- **/
-typedef enum
-{
-  FSDPE_OK = 0,
-  FSDPE_ILLEGAL_CHARACTER,	 /**< Misplaced '\r', '\n' or '\0' */
-  FSDPE_MISSING_VERSION,	 /**< The first line is not like
-				    v=... */
-  FSDPE_INVALID_VERSION,	 /**< Parse error in version line,
-				    perhaps, the version specified in
-				    v=... is not valid for FreeSDP */
-  FSDPE_MISSING_OWNER,		 /**< No owner line found in its
-				    place */
-  FSDPE_INVALID_OWNER,		 /**< Parse error in owner line */
-  FSDPE_MISSING_NAME,		 /**< No session name found in its
-				    place */
-  FSDPE_EMPTY_NAME,		 /**< Empty session name line */
-
-  FSDPE_INVALID_CONNECTION,	 /**< Syntax error in connection
-				    line */
-
-  FSDPE_INVALID_CONNECTION_ADDRTYPE, /**< Unrecognized address type in
-					connection line */
-  FSDPE_INVALID_CONNECTION_NETTYPE,  /**< Unrecognized network type in
-					connection line */
-  FSDPE_INVALID_BANDWIDTH,	     /**< Parse error in bandwidth
-					line */
-  FSDPE_MISSING_TIME,		 /**< No time period has been given
-				    for the session */
-  FSDPE_INVALID_TIME,		 /**< Parse error in time line */
-  FSDPE_INVALID_REPEAT,		 /**< Parse error in repeat time
-				    line */
-  FSDPE_INVALID_TIMEZONE,	 /**< Parse error in timezone line */
-  FSDPE_INVALID_ENCRYPTION_METHOD, /**< Unknown encryption method */
-  FSDPE_INVALID_ATTRIBUTE,	 /**< Syntax error in an attribute
-				    line */
-
-  FSDPE_INVALID_ATTRIBUTE_RTPMAP,/**< Parse error in a=rtpmap:... line */
-  FSDPE_INVALID_SESSION_TYPE,	 /**< An unknown session type has been
-				    specified in a `type:'
-				    session-level attribute */
-
-  FSDPE_INVALID_MEDIA,		 /**< Parse error in media line */
-  FSDPE_UNKNOWN_MEDIA_TYPE,	 /**< Unknown media type in media
-				    line */
-
-  FSDPE_UNKNOWN_MEDIA_TRANSPORT, /**< A media transport has been
-				    specified that is unknown */
-
-  FSDPE_OVERFILLED,		 /**< extra unknown lines are at the
-				    end of the description */
-  FSDPE_INVALID_LINE,		 /**< a line unknown to FreeSDP has been
-				    found */
-  FSDPE_MISSING_CONNECTION_INFO, /**< No connection information has
-				     been provided for the whole
-				     session nor one or more media */
-  FSDPE_INVALID_INDEX,
-  /*  FSDPE_MAXSIZE, description does not fit requested maximun size */
-  FSDPE_INTERNAL_ERROR,
-
-  FSDPE_INVALID_PARAMETER,	 /**< Some parameter of the called
-				       FreeSDP routine has been given an
-				       invalid value. This includes
-				       cases such as NULL pointers. */
-  FSDPE_BUFFER_OVERFLOW
-} fsdp_error_t;
-
-/**
- * @short Type of network 
- *
- * Initially, SDP defines "Internet". New network types may be
- * registered with IANA. However, the number of types is expected to
- * be small and rarely extended. In addition, every new network type
- * requires at least one new address type.
- **/
-typedef enum
-{
-  FSDP_NETWORK_TYPE_UNDEFINED,		       /**< Not provided */
-  FSDP_NETWORK_TYPE_INET		       /**< Internet */
-} fsdp_network_type_t;
-
-/**
- * @short Type of address
- *
- * Initially, IPv4 and IPv6 are defined for the network type
- * Internet. New address types may be registered with IANA.
- **/
-typedef enum
-{
-  FSDP_ADDRESS_TYPE_UNDEFINED,		       /**< Not provided */
-  FSDP_ADDRESS_TYPE_IPV4,		      /**< IP version 4 */
-  FSDP_ADDRESS_TYPE_IPV6		      /**< IP version 6 */
-} fsdp_address_type_t;
-
-/**
- * @short Type of bandwith modifiers 
- *
- * Bandwidth modifiers specify the meaning of the bandwidth
- * value. Initially "Conference Total" and "Application Specific" are
- * defined. Both use kilobits as bandwidth unit. "Conference Total"
- * specifies that the bandwidth value is a proposed upper limit to the
- * session bandwidth. "Application Specific" specifies thath the
- * bandwidth value is the application concept of maximum bandwidth.
- **/
-typedef enum
-{
-  FSDP_BW_MOD_TYPE_UNDEFINED,		 /**< Not provided */
-  FSDP_BW_MOD_TYPE_UNKNOWN,		 /**< Unknown bandwidth
-						  modifier (FreeSDP
-						  ignores it) */
-  FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL,	 /**< "CT - Conference Total" */
-  FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC, /**< "AS - Application specific" */
-  FSDP_BW_MOD_TYPE_RTCP_SENDERS,	 /**< "RS - RTCP bandwidth for
-					    senders */
-  FSDP_BW_MOD_TYPE_RTCP_RECEIVERS,	 /**< "RR - RTCP bandwidth for
-					    receivers */
-} fsdp_bw_modifier_type_t;
-
-/**
- * @short encryption method
- *
- * The encryption method specifies the way to get the encryption key.
- **/
-typedef enum
-{
-  FSDP_ENCRYPTION_METHOD_UNDEFINED,    /**< Not provided */
-  FSDP_ENCRYPTION_METHOD_CLEAR,	       /**< The key field is the
-						 untransformed key */
-  FSDP_ENCRYPTION_METHOD_BASE64,       /**< The key is base64
-					  encoded */
-  FSDP_ENCRYPTION_METHOD_URI,	       /**< The key value provided is
-					  a URI pointing to the actual
-					  key */
-  FSDP_ENCRYPTION_METHOD_PROMPT	       /**< The key is not provided
-					  but should be got prompting
-					  the user */
-} fsdp_encryption_method_t;
-
-/**
- * @short Advised reception/transmission mode
- *
- * Depending on wheter sendrecv, recvonly, sendonly or inactive
- * attribute is given, the tools used to participate in the session
- * should be started in the corresponding transmission
- * mode. FSDP_SENDRECV_SENDRECV is the default for sessions which are
- * not of the conference type broadcast or H332.
- **/
-typedef enum
-{
-  FSDP_SENDRECV_UNDEFINED,		      /**< Not specified */
-  FSDP_SENDRECV_SENDRECV,		      /**< Send and receive */
-  FSDP_SENDRECV_RECVONLY,		      /**< Receive only */
-  FSDP_SENDRECV_SENDONLY,		      /**< Send only */
-  FSDP_SENDRECV_INACTIVE		      /**< Do not send nor receive */
-} fsdp_sendrecv_mode_t;
-
-/**
- * @short Values for `orient' media attribute.
- *
- * Normally used with whiteboard media, this attribute specifies the
- * orientation of the whiteboard.
- **/
-typedef enum
-{
-  FSDP_ORIENT_UNDEFINED,		     /**< Not specified */
-  FSDP_ORIENT_PORTRAIT,			     /**< Portrait */
-  FSDP_ORIENT_LANDSCAPE,		     /**< Landscape */
-  FSDP_ORIENT_SEASCAPE			     /**< Upside down landscape */
-} fsdp_orient_t;
-
-/**
- * @short Type of the conference
- *
- * The following types are initially defined: broadcast, meeting,
- * moderated, test and H332.
- **/
-typedef enum
-{
-  FSDP_SESSION_TYPE_UNDEFINED,		       /**< Not specified */
-  FSDP_SESSION_TYPE_BROADCAST,		       /**< Broadcast session */
-  FSDP_SESSION_TYPE_MEETING,		       /**< Meeting session */
-  FSDP_SESSION_TYPE_MODERATED,		       /**< Moderated session */
-  FSDP_SESSION_TYPE_TEST,		       /**< Test (do not display) */
-  FSDP_SESSION_TYPE_H332		       /**< H332 session */
-} fsdp_session_type_t;
-
-/**
- * @short Media type
- *
- * The following types are defined initially: audio, video,
- * application, data and control.
- **/
-typedef enum
-{
-  FSDP_MEDIA_UNDEFINED,		   /**< Not specified */
-  FSDP_MEDIA_VIDEO,		   /**< Video */
-  FSDP_MEDIA_AUDIO,		   /**< Audio */
-  FSDP_MEDIA_APPLICATION,	   /**< Application, such as whiteboard */
-  FSDP_MEDIA_DATA,		   /**< bulk data */
-  FSDP_MEDIA_CONTROL		   /**< Control channel */
-} fsdp_media_t;
-
-/**
- * @short Transport protocol
- *
- * The transport protocol used depends on the address type. Initially,
- * RTP over UDP Audio/Video Profile, and UDP are defined.
- *
- **/
-typedef enum
-{
-  FSDP_TP_UNDEFINED,		  /**< Not specified */
-  FSDP_TP_RTP_AVP,		  /**< RTP Audio/Video Profile */
-  FSDP_TP_UDP,			  /**< UDP */
-  FSDP_TP_TCP,			  /**< TCP */
-  FSDP_TP_UDPTL,		  /**< ITU-T T.38*/
-  FSDP_TP_VAT,			  /**< old vat protocol (historic)*/
-  FSDP_TP_OLD_RTP,		  /**< old rtp protocols (historic)*/
-  FSDP_TP_H320			  /**< TODO: add to the parser */
-} fsdp_transport_protocol_t;
-
-/**
- * Session-level attributes whose value is specified as a character
- * string in FreeSDP. These values are usually given to
- * fsdp_get_strn_att() in order to get the corresponding value.
- *
- **/
-typedef enum
-{
-  FSDP_SESSION_STR_ATT_CATEGORY,
-  FSDP_SESSION_STR_ATT_KEYWORDS,
-  FSDP_SESSION_STR_ATT_TOOL,
-  FSDP_SESSION_STR_ATT_CHARSET,
-} fsdp_session_str_att_t;
-
-/**
- * @short FreeSDP SDP description media object.
- *
- * Object for media specific information in SDP descriptions. Each SDP
- * description may include any number of media section. A
- * fsdp_media_description_t object encapsulates the information in a
- * media section, such as video, audio or whiteboard.
- **/
-typedef struct fsdp_media_description_t_s fsdp_media_description_t;
-
-/**
- * @short FreeSDP SDP session description object.
- *
- * Contains all the information extracted from a textual SDP
- * description, including all the media announcements.
- **/
-typedef struct fsdp_description_t_s fsdp_description_t;
-
-/**
- * Allocates memory and initializes values for a new
- * fsdp_description_t object. If you call this routine, do not forget
- * about <code>fsdp_description_delete()</code>
- *
- * @return new fsdp_description_t object
- **/
-fsdp_description_t *fsdp_description_new (void);
-
-/**
- * Destroys a fsdp_description_t object.
- *
- * @param dsc pointer to the fsdp_description_t object to delete.
- **/
-void fsdp_description_delete (fsdp_description_t * dsc);
-
-/**
- * Calling this function over a description is equivalent to calling
- * fsdp_description_delete and then fsdp_description_delete. This
- * function is however more suitable and efficient for description
- * processing loops.
- *
- * @param dsc pointer to the fsdp_description_t object to
- * renew/recycle.
- **/
-void fsdp_description_recycle (fsdp_description_t * dsc);
-
-/**
- *  * Returns a string correspondent to the error number.
- *   *
- *    * @param err_no error number.
- *     **/
-const char *fsdp_strerror (fsdp_error_t err_no);
-
-       /*@}*//* closes addtogroup common */
-
-END_C_DECLS
-#endif /* FSDP_COMMON_H */
--- a/libmpdemux/freesdp/errorlist.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
-  This file is part of FreeSDP
-  Copyright (C) 2001, 2002 Federico Montesino Pouzols <fedemp@suidzer0.org>
-
-  FreeSDP is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU 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
-*/
-
-/**
- * @file errorlist.c
- *
- * @short Translation table for error numbers
- *
- */
-
-#ifndef FSDP_ERRORLIST_C
-#define FSDP_ERRORLIST_C
-
-#include "common.h"
-
-const char *fsdp_error_t_s[] = {
-  "No error",/** FSDPE_OK **/
-  "Illegal character detected",/** FSDPE_ILLEGAL_CHARACTER **/
-  "Missing version item", /** FSDPE_MISSING_VERSION **/
-  "Invalid version item", /** FSDPE_INVALID_VERSION **/
-  "Owner item not present", /** FSDPE_MISSING_OWNER **/
-  "Parse error in owner item", /** FSDPE_INVALID_OWNER **/
-  "Session name not present", /** FSDPE_MISSING_NAME **/
-  "Empty session name item", /** FSDPE_EMPTY_NAME **/
-  "Syntax error in connection item", /** FSDPE_INVALID_CONNECTION **/
-  "Unrecognized address type in connection item", /** FSDPE_INVALID_CONNECTION_ADDRTYPE **/
-  "Unrecognized network type in connection item", /** FSDPE_INVALID_CONNECTION_NETTYPE **/
-  "Parse error in bandwith item", /** FSDPE_INVALID_BANDWIDTH **/
-  "No time period for the session", /** FSDPE_MISSING_TIME **/
-  "Parse error in time item", /** FSDPE_INVALID_TIME **/
-  "Parse error in repeat time item", /** FSDPE_INVALID_REPEAT **/
-  "Parse error in timezone item", /** FSDPE_INVALID_TIMEZONE **/
-  "Unknown encryption method", /** FSDPE_INVALID_ENCRYPTION_METHOD **/
-  "Syntax error in an attribute item", /** FSDPE_INVALID_ATTRIBUTE **/
-  "Syntax error in an rtpmap attribute item", /** FSDPE_INVALID_ATTRIBUTE_RTPMAP **/
-  "Unknown session type in a session-level attribute", /** FSDPE_INVALID_SESSION_TYPE **/
-  "Parse error in media item", /** FSDPE_INVALID_MEDIA **/
-  "Unknown media type in media item", /** FSDPE_UNKNOWN_MEDIA_TYPE **/
-  "Unknown media transport", /** FSDPE_UNKNOWN_MEDIA_TRANSPORT **/
-  "Unknown extra lines in description item", /** FSDPE_OVERFILLED **/
-  "Unknown line found",	/** FSDPE_INVALID_LINE **/
-  "No connection information provided",	/** FSDPE_MISSING_CONNECTION_INFO **/
-  "Description item does not fit in MAXSIZE", /** FSDPE_INVALID_INDEX **/
-  "Internal error", /** FSDPE_INTERNAL_ERROR **/
-  "Invalid function parameters", /** FSDPE_INVALID_PARAMETER **/
-  "Buffer overflow" /** FSDPE_BUFFER_OVERFLOW **/
-};
-
-
-const char *
-fsdp_strerror (fsdp_error_t err_no)
-{
-  return (fsdp_error_t_s[err_no]);
-}
-
-#endif
--- a/libmpdemux/freesdp/parser.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1958 +0,0 @@
-/*
-  This file is part of FreeSDP
-  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
-  
-  FreeSDP is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU 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
-
-  Benjamin Zores, (C) 2006
-    added support in parser for the a=control: lines.
-    added support in parser for the a=range: lines.
-*/
-
-/**
- * @file parser.c
- *
- * @short Parsing module implementation.
- *
- * This file implements the parsing routine <code>fsdp_parse</code>
- * and the <code>fsdp_get_xxxx</code> routines that allow to get the
- * session properties from a session description object build through
- * the application of <code>fsdp_parse</code> to a textual SDP session
- * description.
- **/
-
-#include "parserpriv.h"
-
-/**
- * Moves the <code>c<code> pointer up to the beginning of the next
- * line.
- *
- * @param c char pointer to pointer
- * @retval FSDPE_ILLEGAL_CHARACTER, when an illegal '\r' character
- * (not followed by a '\n') is found, returns
- */
-#define NEXT_LINE(c)                                                \
-({                                                                  \
- while ((*(c) != '\0') && (*(c) != '\r') && (*(c) != '\n')) {       \
-    (c)++;                                                          \
- }                                                                  \
- if (*(c) == '\n') {                                                \
-    (c)++;                                                          \
- } else if (*(c) == '\r') {                                         \
-    (c)++;                                                          \
-    if (*(c) == '\n') {                                             \
-       (c)++;                                                       \
-    } else {                                                        \
-       return FSDPE_ILLEGAL_CHARACTER;                              \
-   }                                                                \
- }                                                                  \
-})
-
-fsdp_error_t
-fsdp_parse (const char *text_description, fsdp_description_t * dsc)
-{
-  fsdp_error_t result;
-  const char *p = text_description, *p2;
-  unsigned int index, j;
-  /* temps for sscanf */
-  const unsigned int TEMPCHARS = 6;
-  char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
-  char longfsdp_buf[MAXLONGFIELDLEN];
-  const unsigned int TEMPINTS = 2;
-  unsigned long int wuint[TEMPINTS];
-
-  if ((NULL == text_description) || (NULL == dsc))
-    return FSDPE_INVALID_PARAMETER;
-
-  /***************************************************************************/
-  /* A) parse session-level description                                      */
-  /***************************************************************************/
-
-  /* `v=' line (protocol version) */
-  /* according to the RFC, only `v=0' is valid */
-  if (sscanf (p, "v=%1lu", &wuint[0]))
-  {
-    if (wuint[0] != 0)
-      return FSDPE_INVALID_VERSION;
-  }
-  else
-  {
-    return FSDPE_MISSING_VERSION;
-  }
-  NEXT_LINE (p);
-
-  /* `o=' line (owner/creator and session identifier) */
-  /* o=<username> <session id> <version> <network type> <address type>
-     <address> */
-  if (!strncmp (p, "o=", 2))
-  {
-    p += 2;
-    /* note that the following max lengths may vary in the future and
-       are quite arbitary */
-    if (sscanf
-        (p,
-         "%" MSFLENS "[\x21-\xFF] %" MSFLENS "[0-9] %" MSFLENS
-         "[0-9] %2s %3s %" MSFLENS "s", fsdp_buf[0], fsdp_buf[1],
-         fsdp_buf[2], fsdp_buf[3], fsdp_buf[4], fsdp_buf[5]) != 6)
-      return FSDPE_INVALID_OWNER;
-    dsc->o_username = strdup (fsdp_buf[0]);
-    dsc->o_session_id = strdup (fsdp_buf[1]);
-    dsc->o_announcement_version = strdup (fsdp_buf[2]);
-    if (!strncmp (fsdp_buf[3], "IN", 2))
-    {
-      dsc->o_network_type = FSDP_NETWORK_TYPE_INET;
-      if (!strncmp (fsdp_buf[4], "IP4", 3))
-        dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV4;
-      else if (!strncmp (fsdp_buf[4], "IP6", 3))
-        dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV6;
-      else
-        return FSDPE_INVALID_OWNER;
-    }
-    else
-    {
-      return FSDPE_INVALID_OWNER;
-    }
-    /* TODO? check valid unicast address/FQDN */
-    dsc->o_address = strdup (fsdp_buf[5]);
-  }
-  else
-  {
-    return FSDPE_MISSING_OWNER;
-  }
-  NEXT_LINE (p);
-
-  /* `s=' line (session name) -note that the name string cannot be empty */
-  /* s=<session name> */
-  if (!strncmp (p, "s=", 2))
-  {
-    if (sscanf (p, "s=%" MLFLENS "[^\r\n]", longfsdp_buf) < 1)
-      return FSDPE_EMPTY_NAME;
-    dsc->s_name = strdup (longfsdp_buf);
-  }
-  else
-  {
-    return FSDPE_MISSING_NAME;
-  }
-  NEXT_LINE (p);
-
-  /* `i=' line (session information) [optional] */
-  /* i=<session description> */
-  if (!strncmp (p, "i=", 2)
-      && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
-  {
-    dsc->i_information = strdup (longfsdp_buf);
-    NEXT_LINE (p);
-  }
-  else
-  {
-    /* (optional) information absent */
-  }
-
-  /* `u=' line (URI of description)  [optional] */
-  /* u=<URI> */
-  if (!strncmp (p, "u=", 2)
-      && sscanf (p, "u=%" MLFLENS "[^\r\n]", longfsdp_buf))
-  {
-    /* TODO? check valid uri */
-    dsc->u_uri = strdup (longfsdp_buf);
-    NEXT_LINE (p);
-  }
-  else
-  {
-    /* (optional) uri absent */
-  }
-
-  /* `e=' lines (email address) [zero or more] */
-  /* e=<email address> */
-  p2 = p;
-  j = 0;
-  while (!strncmp (p2, "e=", 2))
-  {
-    /* First, count how many emails are there */
-    j++;
-    NEXT_LINE (p2);
-  }
-  dsc->emails_count = j;
-  if (dsc->emails_count > 0)
-  {
-    /* Then, build the array of emails */
-    dsc->emails = calloc (j, sizeof (const char *));
-    for (j = 0; j < dsc->emails_count; j++)
-    {
-      sscanf (p, "e=%" MLFLENS "[^\r\n]", longfsdp_buf);
-      /* TODO? check valid email-address. */
-      dsc->emails[j] = strdup (longfsdp_buf);
-      NEXT_LINE (p);
-    }
-  }
-
-  /* `p=' lines (phone number) [zero or more] */
-  /*  p=<phone number> */
-  j = 0;
-  /* assert ( p2 == p ); */
-  while (!strncmp (p2, "p=", 2))
-  {
-    j++;
-    NEXT_LINE (p2);
-  }
-  dsc->phones_count = j;
-  if (dsc->phones_count > 0)
-  {
-    dsc->phones = calloc (j, sizeof (const char *));
-    for (j = 0; j < dsc->phones_count; j++)
-    {
-      sscanf (p, "p=%" MLFLENS "[^\r\n]", longfsdp_buf);
-      /* TODO? check valid phone-number. */
-      dsc->phones[j] = strdup (longfsdp_buf);
-      NEXT_LINE (p);
-    }
-  }
-
-  /* `c=' line (connection information - not required if included in all media) [optional] */
-  /* c=<network type> <address type> <connection address> */
-  result = fsdp_parse_c (&p, &(dsc->c_network_type), &(dsc->c_address_type),
-			 &(dsc->c_address));
-  if (FSDPE_OK != result)
-    return result;
-
-  /* `b=' lines (bandwidth information) [optional] */
-  /* b=<modifier>:<bandwidth-value> */
-  result =
-    fsdp_parse_b (&p, &(dsc->bw_modifiers), &(dsc->bw_modifiers_count));
-  if (FSDPE_OK != result)
-    return result;
-
-  /* A.1) Time descriptions: */
-
-  /* `t=' lines (time the session is active) [1 or more] */
-  /* t=<start time>  <stop time> */
-  j = 0;
-  p2 = p;
-  while (!strncmp (p2, "t=", 2))
-  {
-    j++;
-    NEXT_LINE (p2);
-    while (!strncmp (p2, "r=", 2))
-      NEXT_LINE (p2);
-  }
-  dsc->time_periods_count = j;
-  if (dsc->time_periods_count == 0)
-    return FSDPE_MISSING_TIME;
-  dsc->time_periods = calloc (dsc->time_periods_count,
-			      sizeof (fsdp_time_period_t *));
-  index = 0;
-  for (j = 0; j < dsc->time_periods_count; j++)
-  {
-    unsigned int h = 0;
-    if (sscanf (p, "t=%10lu %10lu", &wuint[0], &wuint[1]) != 2)
-    {
-      /* not all periods have been successfully parsed */
-      dsc->time_periods_count = j;
-      return FSDPE_INVALID_TIME;
-    }
-    dsc->time_periods[j] = calloc (1, sizeof (fsdp_time_period_t));
-
-    /* convert from NTP to time_t time */
-    if (wuint[0] != 0)
-      wuint[0] -= NTP_EPOCH_OFFSET;
-    if (wuint[1] != 0)
-      wuint[1] -= NTP_EPOCH_OFFSET;
-    dsc->time_periods[j]->start = wuint[0];
-    dsc->time_periods[j]->stop = wuint[1];
-    NEXT_LINE (p);
-
-    /* `r' lines [zero or more repeat times for each t=] */
-    /*r=<repeat interval> <active duration> <list of offsets from
-      start-time> */
-    p2 = p;
-    while (!strncmp (p2, "r=", 2))
-    {
-      h++;
-      NEXT_LINE (p2);
-    }
-    dsc->time_periods[j]->repeats_count = h;
-    if (h > 0)
-    {
-      unsigned int index2 = 0;
-      dsc->time_periods[j]->repeats =
-        calloc (h, sizeof (fsdp_repeat_t *));
-      for (h = 0; h < dsc->time_periods[j]->repeats_count; h++)
-      {
-        /*
-          get_repeat_values(p,&(dsc->time_periods[index].repeats[index2]));
-          fsdp_error_t get_repeat_values (const char *r, fsdp_repeat_t
-          *repeat);
-          */
-        if (sscanf (p, "r=%10s %10s %" MLFLENS "[^\r\n]",
-                    fsdp_buf[0], fsdp_buf[1], longfsdp_buf) == 3)
-        {
-          fsdp_repeat_t *repeat;
-          dsc->time_periods[j]->repeats[h] =
-            calloc (1, sizeof (fsdp_repeat_t));
-          repeat = dsc->time_periods[j]->repeats[h];
-          /* get interval, duration and list of offsets */
-          result =
-            fsdp_repeat_time_to_uint (fsdp_buf[0],
-                                      &(repeat->interval));
-          if (result == FSDPE_OK)
-          {
-            result =
-              fsdp_repeat_time_to_uint (fsdp_buf[1],
-                                        &(repeat->duration));
-            if (result == FSDPE_OK)
-            {
-              unsigned int k = 1;
-              const char *i = longfsdp_buf;
-              while (NULL != (i = strchr (i, ' ')))
-              {
-                k++;
-                if (NULL != i)
-                  i++;
-              }
-              repeat->offsets_count = k;
-              repeat->offsets = calloc (k, sizeof (time_t));
-              i = longfsdp_buf;
-              for (k = 0;
-                   (k < repeat->offsets_count)
-                     && (result == FSDPE_OK); k++)
-              {
-                result =
-                  fsdp_repeat_time_to_uint (i,
-                                            &(repeat->
-                                              offsets[k]));
-                i = strchr (i, ' ');
-                if (NULL != i)
-                  i++;
-              }
-              if (k < repeat->offsets_count)
-              {
-                /* there where invalid repeat offsets */
-                dsc->time_periods[j]->repeats_count = k;
-                return FSDPE_INVALID_REPEAT;
-              }
-            }
-          }
-          if (result != FSDPE_OK)
-          {
-            /* not all repeats have been succesfully parsed */
-            dsc->time_periods[j]->repeats_count = h;
-            return FSDPE_INVALID_REPEAT;
-          }
-          NEXT_LINE (p);
-        }
-        else
-        {
-          /* not all repeats have been succesfully parsed */
-          dsc->time_periods[j]->repeats_count = h;
-          return FSDPE_INVALID_REPEAT;
-        }
-        index2++;
-      }
-    }
-  }
-
-  /* `z=' line (time zone adjustments) [zero or more] */
-  /* z=<adjustment time> <offset> <adjustment time> <offset> .... */
-  if (!strncmp (p, "z=", 2))
-  {
-    if (sscanf (p, "z=%" MLFLENS "[^\r\n]", longfsdp_buf))
-    {
-      /* TODO: guess how many pairs are there and process them */
-      dsc->timezone_adj = strdup (longfsdp_buf);
-      NEXT_LINE (p);
-    }
-    else
-    {
-      return FSDPE_INVALID_TIMEZONE;
-    }
-  }
-
-  /* `k=' line (encryption key) [optional] */
-  /* k=<method> 
-     k=<method>:<encryption key> */
-  result = fsdp_parse_k (&p, &(dsc->k_encryption_method),
-			 &(dsc->k_encryption_content));
-  if (result != FSDPE_OK)
-    return result;
-
-  /* A.2) Attributes */
-  /* `a=' lines (session attribute) [0 or more] */
-  /* a=<attribute>
-     a=<attribute>:<value> */
-  while (!strncmp (p, "a=", 2))
-  {
-    /* The "9" lenght specifier of the first string is subject to
-       changes */
-    if (sscanf
-        (p, "a=%9[^:\r\n]:%" MSFLENS "[^\r\n]", fsdp_buf[0],
-         fsdp_buf[1]) == 2)
-    {
-      /* session-level value attributes */
-      if (!strncmp (fsdp_buf[0], "cat", 3))
-        dsc->a_category = strdup (fsdp_buf[1]);
-      else if (!strncmp (fsdp_buf[0], "keywds", 6))
-        dsc->a_keywords = strdup (fsdp_buf[1]);
-      else if (!strncmp (fsdp_buf[0], "tool", 4))
-        dsc->a_keywords = strdup (fsdp_buf[1]);
-      else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
-        fsdp_parse_rtpmap (&(dsc->a_rtpmaps),
-                           &(dsc->a_rtpmaps_count), fsdp_buf[1]);
-      else if (!strncmp (fsdp_buf[0], "type", 4))
-      {
-        if (!strncmp (fsdp_buf[1], "broadcast", 9))
-          dsc->a_type = FSDP_SESSION_TYPE_BROADCAST;
-        else if (!strncmp (fsdp_buf[1], "meeting", 7))
-          dsc->a_type = FSDP_SESSION_TYPE_MEETING;
-        else if (!strncmp (fsdp_buf[1], "moderated", 9))
-          dsc->a_type = FSDP_SESSION_TYPE_MODERATED;
-        else if (!strncmp (fsdp_buf[1], "test", 4))
-          dsc->a_type = FSDP_SESSION_TYPE_TEST;
-        else if (!strncmp (fsdp_buf[1], "H332", 4))
-          dsc->a_type = FSDP_SESSION_TYPE_H332;
-        else
-          return FSDPE_INVALID_SESSION_TYPE;
-      }
-      else if (!strncmp (fsdp_buf[0], "charset", 7))
-        dsc->a_charset = strdup (fsdp_buf[1]);
-      else if (!strncmp (fsdp_buf[0], "sdplang", 7))
-      {
-        if (NULL == dsc->a_sdplangs)
-        {
-          dsc->a_sdplangs_count = 0;
-          dsc->a_sdplangs =
-            calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
-        }
-        if (dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT)
-        {
-          dsc->a_sdplangs[dsc->a_sdplangs_count] =
-            strdup (fsdp_buf[1]);
-          dsc->a_sdplangs_count++;
-        }
-      }
-      else if (!strncmp (fsdp_buf[0], "lang", 4))
-      {
-        if (NULL == dsc->a_langs)
-        {
-          dsc->a_langs_count = 0;
-          dsc->a_langs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
-        }
-        if (dsc->a_langs_count < SDPLANGS_MAX_COUNT)
-        {
-          dsc->a_langs[dsc->a_langs_count] = strdup (fsdp_buf[1]);
-          dsc->a_langs_count++;
-        }
-      }
-      else if (!strncmp (fsdp_buf[0], "control", 7))
-      {
-        if (NULL == dsc->a_controls)
-        {
-          dsc->a_controls_count = 0;
-          dsc->a_controls =
-            calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
-        }
-        if (dsc->a_controls_count < SDPCONTROLS_MAX_COUNT)
-        {
-          dsc->a_controls[dsc->a_controls_count] =
-            strdup (fsdp_buf[1]);
-          dsc->a_controls_count++;
-        }
-      }
-      else if (!strncmp (fsdp_buf[0], "range", 5))
-      {
-        if (dsc->a_range)
-          free (dsc->a_range);
-        dsc->a_range = strdup (fsdp_buf[1]);
-      }
-      else
-      {
-        /* ignore unknown attributes, but provide access to them */
-        *longfsdp_buf = '\0';
-        strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN);
-        strncat (longfsdp_buf, ":", MAXLONGFIELDLEN);
-        strncat (longfsdp_buf, fsdp_buf[1], MAXLONGFIELDLEN);
-        if (NULL == dsc->unidentified_attributes)
-        {
-          dsc->unidentified_attributes_count = 0;
-          dsc->unidentified_attributes =
-            calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
-                    sizeof (char *));
-        }
-        if (dsc->unidentified_attributes_count <
-            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
-        {
-          dsc->unidentified_attributes
-            [dsc->unidentified_attributes_count] =
-            strdup (longfsdp_buf);
-          dsc->unidentified_attributes_count++;
-        }
-      }
-      NEXT_LINE (p);
-    }
-    else if (sscanf (p, "a=%20s", fsdp_buf[0]) == 1)
-    {
-      /* session-level property attributes */
-      if (!strncmp (fsdp_buf[0], "recvonly", 8))
-        dsc->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
-      else if (!strncmp (fsdp_buf[0], "sendonly", 8))
-        dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
-      else if (!strncmp (fsdp_buf[0], "inactive", 8))
-        dsc->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
-      else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
-        dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
-      else
-      {
-        /* ignore unknown attributes, but provide access to them */
-        *longfsdp_buf = '\0';
-        strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN);
-        if (NULL == dsc->unidentified_attributes)
-        {
-          dsc->unidentified_attributes_count = 0;
-          dsc->unidentified_attributes =
-            calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
-                    sizeof (char *));
-        }
-        if (dsc->unidentified_attributes_count <
-            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
-        {
-          dsc->unidentified_attributes
-            [dsc->unidentified_attributes_count] =
-            strdup (longfsdp_buf);
-          dsc->unidentified_attributes_count++;
-        }
-      }
-      NEXT_LINE (p);
-    }
-    else
-      return FSDPE_INVALID_ATTRIBUTE;
-  }
-
-  /***************************************************************************/
-  /* B) parse media-level descriptions                                       */
-  /***************************************************************************/
-  p2 = p;
-  j = 0;
-  while ((*p2 != '\0') && !strncmp (p2, "m=", 2))
-  {
-    char c;
-    j++;
-    NEXT_LINE (p2);
-    while (sscanf (p2, "%c=", &c) == 1)
-    {
-      if (c == 'i' || c == 'c' || c == 'b' || c == 'k' || c == 'a')
-      {
-        NEXT_LINE (p2);
-      }
-      else if (c == 'm')
-      {
-        break;
-      }
-      else
-      {
-        return FSDPE_INVALID_LINE;
-      }
-    }
-  }
-  dsc->media_announcements_count = j;
-  if (dsc->media_announcements_count == 0)
-  {
-    ;
-    /*return FSDPE_MISSING_MEDIA; */
-  }
-  else
-  {				/* dsc->media_announcements_count > 0 */
-    dsc->media_announcements =
-      calloc (j, sizeof (fsdp_media_announcement_t *));
-    for (j = 0; j < dsc->media_announcements_count; j++)
-    {
-      fsdp_media_announcement_t *media = NULL;
-      /* `m=' line (media name, transport address and format list) */
-      /* m=<media>  <port>  <transport> <fmt list> */
-      /* The max. string lengths are subject to change */
-      if (sscanf (p, "m=%11s %8s %7s %" MLFLENS "[^\r\n]",
-                  fsdp_buf[0], fsdp_buf[1], fsdp_buf[2],
-                  longfsdp_buf) != 4)
-      {
-        return FSDPE_INVALID_MEDIA;
-      }
-      else
-      {
-        dsc->media_announcements[j] =
-          calloc (1, sizeof (fsdp_media_announcement_t));
-        media = dsc->media_announcements[j];
-        if (!strncmp (fsdp_buf[0], "audio", 5))
-          media->media_type = FSDP_MEDIA_AUDIO;
-        else if (!strncmp (fsdp_buf[0], "video", 5))
-          media->media_type = FSDP_MEDIA_VIDEO;
-        else if (!strncmp (fsdp_buf[0], "application", 11))
-          media->media_type = FSDP_MEDIA_APPLICATION;
-        else if (!strncmp (fsdp_buf[0], "data", 4))
-          media->media_type = FSDP_MEDIA_DATA;
-        else if (!strncmp (fsdp_buf[0], "control", 7))
-          media->media_type = FSDP_MEDIA_CONTROL;
-        else
-          return FSDPE_UNKNOWN_MEDIA_TYPE;
-        {			/* try to get port specification as port/number */
-          char *slash;
-          if ((slash = strchr (fsdp_buf[1], '/')))
-          {
-            *slash = '\0';
-            slash++;
-            media->port = strtol (fsdp_buf[1], NULL, 10);
-            media->port_count = strtol (slash, NULL, 10);
-          }
-          else
-          {
-            media->port = strtol (fsdp_buf[1], NULL, 10);
-            media->port_count = 0;
-          }
-        }
-        if (!strncmp (fsdp_buf[2], "RTP/AVP", 7))
-          media->transport = FSDP_TP_RTP_AVP;
-        else if (!strncmp (fsdp_buf[2], "udp", 3))
-          media->transport = FSDP_TP_UDP;
-        else if (!strncmp (fsdp_buf[2], "TCP", 3))
-          media->transport = FSDP_TP_TCP;
-        else if (!strncmp (fsdp_buf[2], "UDPTL", 5))
-          media->transport = FSDP_TP_UDPTL;
-        else if (!strncmp (fsdp_buf[2], "vat", 3))
-          media->transport = FSDP_TP_VAT;
-        else if (!strncmp (fsdp_buf[2], "rtp", 3))
-          media->transport = FSDP_TP_OLD_RTP;
-        else
-          return FSDPE_UNKNOWN_MEDIA_TRANSPORT;
-        {
-          unsigned int k = 0;
-          char *s = longfsdp_buf;
-          while (NULL != (s = strchr (s, ' ')))
-          {
-            k++;
-            if (NULL != s)
-              s++;
-          }
-          k++;		/* when there is no space left, count the last format */
-          media->formats_count = k;
-          media->formats = calloc (k, sizeof (char *));
-          s = longfsdp_buf;
-          for (k = 0; k < media->formats_count; k++)
-          {
-            char *space = strchr (s, ' ');
-            if (NULL != space)
-              *space = '\0';
-            media->formats[k] = strdup (s);
-            s = space + 1;
-          }
-        }
-        NEXT_LINE (p);
-      }
-
-      /* `i=' line (media title) [optional] */
-      /* i=<media title> */
-      if (!strncmp (p, "i=", 2)
-          && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
-      {
-        media->i_title = strdup (longfsdp_buf);
-        NEXT_LINE (p);
-      }
-      else
-      {
-        /* (optional) information absent */
-      }
-
-      /* `c=' line (connection information - overrides session-level
-         line) [optional if provided at session-level] */
-      /* c=<network type> <address type> <connection address> */
-      result = fsdp_parse_c (&p, &(media->c_network_type),
-                             &(media->c_address_type),
-                             &(media->c_address));
-      if (result != FSDPE_OK)
-        return result;
-
-      /* `b=' lines (bandwidth information) [optional] */
-      /* b=<modifier>:<bandwidth-value> */
-      result = fsdp_parse_b (&p, &(media->bw_modifiers),
-                             &(media->bw_modifiers_count));
-      if (FSDPE_OK != result)
-        return result;
-
-      /* `k=' line (encryption key) [optional] */
-      /* k=<method> 
-         k=<method>:<encryption key> */
-      result = fsdp_parse_k (&p, &(media->k_encryption_method),
-                             &(media->k_encryption_content));
-      if (result != FSDPE_OK)
-        return result;
-
-      /* B.1) Attributes */
-
-      /* `a=' lines (zero or more media attribute lines) [optional] */
-      /* a=<attribute>
-         a=<attribute>:<value> */
-      while (!strncmp (p, "a=", 2))
-      {
-        if (sscanf
-            (p, "a=%9[^:\r\n]:%" MLFLENS "[^\r\n]", fsdp_buf[0],
-             longfsdp_buf) == 2)
-        {
-          /* media-level value attributes */
-          if (!strncmp (fsdp_buf[0], "ptime", 5))
-            media->a_ptime = strtoul (longfsdp_buf, NULL, 10);
-          else if (!strncmp (fsdp_buf[0], "maxptime", 8))
-            media->a_maxptime = strtoul (longfsdp_buf, NULL, 10);
-          else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
-            fsdp_parse_rtpmap (&(media->a_rtpmaps),
-                               &(media->a_rtpmaps_count),
-                               longfsdp_buf);
-          else if (!strncmp (fsdp_buf[0], "orient", 6))
-          {
-            if (!strncmp (longfsdp_buf, "portrait", 8))
-              media->a_orient = FSDP_ORIENT_PORTRAIT;
-            else if (!strncmp (longfsdp_buf, "landscape", 9))
-              media->a_orient = FSDP_ORIENT_LANDSCAPE;
-            else if (!strncmp (longfsdp_buf, "seascape", 9))
-              media->a_orient = FSDP_ORIENT_SEASCAPE;
-          }
-          else if (!strncmp (fsdp_buf[0], "sdplang", 7))
-          {
-            if (NULL == dsc->a_sdplangs)
-            {
-              media->a_sdplangs_count = 0;
-              media->a_sdplangs =
-                calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
-            }
-            if (media->a_sdplangs_count < SDPLANGS_MAX_COUNT)
-            {
-              media->a_sdplangs[dsc->a_sdplangs_count] =
-                strdup (longfsdp_buf);
-              media->a_sdplangs_count++;
-            }
-          }
-          else if (!strncmp (fsdp_buf[0], "lang", 4))
-          {
-            if (NULL == dsc->a_langs)
-            {
-              media->a_langs_count = 0;
-              media->a_langs =
-                calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
-            }
-            if (media->a_langs_count < SDPLANGS_MAX_COUNT)
-            {
-              media->a_langs[dsc->a_langs_count] =
-                strdup (longfsdp_buf);
-              media->a_langs_count++;
-            }
-          }
-          else if (!strncmp (fsdp_buf[0], "control", 7))
-          {
-            if (NULL == media->a_controls)
-            {
-              media->a_controls_count = 0;
-              media->a_controls =
-                calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
-            }
-            if (media->a_controls_count < SDPCONTROLS_MAX_COUNT)
-            {
-              media->a_controls[media->a_controls_count] =
-                strdup (longfsdp_buf);
-              media->a_controls_count++;
-            }
-          }
-          else if (!strncmp (fsdp_buf[0], "range", 5))
-          {
-            if (media->a_range)
-              free (media->a_range);
-            media->a_range = strdup (fsdp_buf[1]);
-          }
-          else if (!strncmp (fsdp_buf[0], "framerate", 9))
-            media->a_framerate = strtod (longfsdp_buf, NULL);
-          else if (!strncmp (fsdp_buf[0], "fmtp", 4))
-          {
-            if (NULL == media->a_fmtps)
-            {
-              media->a_fmtps_count = 0;
-              media->a_fmtps =
-                calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
-            }
-            if (media->a_fmtps_count < SDPLANGS_MAX_COUNT)
-            {
-              media->a_fmtps[media->a_fmtps_count] =
-                strdup (longfsdp_buf);
-              media->a_fmtps_count++;
-            }
-          }
-          else if (!strncmp (fsdp_buf[0], "rtcp", 4))
-          {
-            int opts = 0;
-            /* rtcp attribute: a=rtcp:<port> <nettype> <addrtype> <address> */
-            opts =
-              sscanf (longfsdp_buf, "%lu %2s %3s %" MSFLENS "s",
-                      &wuint[0], fsdp_buf[0], fsdp_buf[1],
-                      fsdp_buf[2]);
-            if (opts >= 1)
-            {
-              media->a_rtcp_port = wuint[0];
-              if (opts >= 2)
-              {
-                if (!strncmp (fsdp_buf[0], "IN", 2))
-                {
-                  media->a_rtcp_network_type =
-                    FSDP_NETWORK_TYPE_INET;
-                }	/* else
-                           ; TODO: define error code? */
-                if (opts >= 3)
-                {
-                  if (!strncmp (fsdp_buf[1], "IP4", 3))
-                    media->a_rtcp_address_type =
-                      FSDP_ADDRESS_TYPE_IPV4;
-                  else if (!strncmp (fsdp_buf[1], "IP6", 3))
-                    media->a_rtcp_address_type =
-                      FSDP_ADDRESS_TYPE_IPV6;
-                  else
-                    return FSDPE_INVALID_CONNECTION_NETTYPE;
-                  /*add specific code? */
-                  if (opts >= 4)
-                    media->a_rtcp_address =
-                      strdup (fsdp_buf[2]);
-                }
-              }
-            }
-          }
-          else
-          {
-            /* ignore unknown attributes, but provide access to them */
-            *fsdp_buf[1] = '\0';
-            strncat (fsdp_buf[1], fsdp_buf[0], MAXLONGFIELDLEN);
-            strncat (fsdp_buf[1], ":", MAXLONGFIELDLEN);
-            strncat (fsdp_buf[1], longfsdp_buf, MAXLONGFIELDLEN);
-            if (NULL == media->unidentified_attributes)
-            {
-              media->unidentified_attributes_count = 0;
-              media->unidentified_attributes =
-                calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
-                        sizeof (char *));
-            }
-            if (media->unidentified_attributes_count <
-                UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
-            {
-              media->unidentified_attributes
-                [media->unidentified_attributes_count] =
-                strdup (fsdp_buf[1]);
-              media->unidentified_attributes_count++;
-            }
-          }
-          NEXT_LINE (p);
-        }
-        else if (sscanf (p, "a=%8s", fsdp_buf[0]) == 1)
-        {
-          /* media-level property attributes */
-          if (!strncmp (fsdp_buf[0], "recvonly", 8))
-            media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
-          else if (!strncmp (fsdp_buf[0], "sendonly", 8))
-            media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
-          else if (!strncmp (fsdp_buf[0], "inactive", 8))
-            media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
-          else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
-            media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
-          else
-          {
-            /* ignore unknown attributes, but provide access to them */
-            *longfsdp_buf = '\0';
-            strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN);
-            if (NULL == media->unidentified_attributes)
-            {
-              media->unidentified_attributes_count = 0;
-              media->unidentified_attributes =
-                calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
-                        sizeof (char *));
-            }
-            if (media->unidentified_attributes_count <
-                UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
-            {
-              media->unidentified_attributes
-                [media->unidentified_attributes_count] =
-                strdup (longfsdp_buf);
-              media->unidentified_attributes_count++;
-            }
-          }
-          NEXT_LINE (p);
-        }
-        else
-          return FSDPE_INVALID_ATTRIBUTE;
-      }
-    }			/* end of for */
-  }
-
-  /* Check c= has been given at session level or at media level for
-     all media */
-  if (NULL == dsc->c_address.address)
-  {
-    unsigned int c;
-    for (c = 0; c < dsc->media_announcements_count; c++)
-      if (NULL == dsc->media_announcements[c]->c_address.address)
-        return FSDPE_MISSING_CONNECTION_INFO;
-  }
-
-  /* finish */
-  if (*p == '\0')
-    return FSDPE_OK;
-  else
-    return FSDPE_OVERFILLED;
-}
-
-static fsdp_error_t
-fsdp_parse_c (const char **p, fsdp_network_type_t * ntype,
-	      fsdp_address_type_t * atype,
-	      fsdp_connection_address_t * address)
-{
-  const unsigned int TEMPCHARS = 3;
-  char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
-
-  if (!strncmp (*p, "c=", 2))
-  {
-    if (sscanf (*p, "c=%2s %3s %" MSFLENS "s",
-                fsdp_buf[0], fsdp_buf[1], fsdp_buf[2]))
-    {
-      if (!strncmp (fsdp_buf[0], "IN", 2))
-      {
-        *ntype = FSDP_NETWORK_TYPE_INET;
-        if (!strncmp (fsdp_buf[1], "IP4", 3))
-          *atype = FSDP_ADDRESS_TYPE_IPV4;
-        else if (!strncmp (fsdp_buf[1], "IP6", 3))
-          *atype = FSDP_ADDRESS_TYPE_IPV6;
-        else
-          return FSDPE_INVALID_CONNECTION_NETTYPE;
-      }
-      else
-      {
-        return FSDPE_INVALID_CONNECTION_ADDRTYPE;
-      }
-      {
-        char *slash = strchr (fsdp_buf[2], '/');
-        if (NULL == slash)
-        {
-          address->address = strdup (fsdp_buf[2]);
-          address->address_ttl = 0;
-          address->address_count = 0;
-        }
-        else
-        {
-          /* address is IP4 multicast */
-          char *slash2;
-          *slash = '\0';
-          slash++;
-          address->address = strdup (fsdp_buf[2]);
-          slash2 = strchr (slash + 1, '/');
-          if (NULL == slash2)
-          {
-            address->address_ttl = strtol (slash, NULL, 10);
-            address->address_count = 0;
-          }
-          else
-          {
-            *slash2 = '\0';
-            slash2++;
-            address->address_ttl = strtol (slash, NULL, 10);
-            address->address_count = strtol (slash2, NULL, 10);
-          }
-        }
-      }
-      NEXT_LINE (*p);
-    }
-    else
-    {
-      return FSDPE_INVALID_CONNECTION;
-    }
-  }
-  return FSDPE_OK;
-}
-
-static fsdp_error_t
-fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers,
-	      unsigned int *bw_modifiers_count)
-{
-  char fsdp_buf[MAXSHORTFIELDLEN];
-  unsigned long int wuint;
-  unsigned int i = 0;
-  char *lp = (char *) *p;
-
-  /* count b= lines */
-  while (!strncmp (lp, "b=", 2))
-  {
-    NEXT_LINE (lp);
-    i++;
-  }
-  *bw_modifiers = calloc (i, sizeof (fsdp_bw_modifier_t));
-  *bw_modifiers_count = i;
-
-  while (i > 0)
-  {
-    unsigned int index = *bw_modifiers_count - i;
-    if (2 == sscanf (*p, "b=%20[^:\r\n]:%lu", fsdp_buf, &wuint))
-    {
-      if (!strncmp (fsdp_buf, "CT", 2))
-        (*bw_modifiers)[index].b_mod_type =
-          FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL;
-      else if (!strncmp (fsdp_buf, "AS", 2))
-        (*bw_modifiers)[index].b_mod_type =
-          FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC;
-      else if (!strncmp (fsdp_buf, "RS", 2))
-        (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS;
-      else if (!strncmp (fsdp_buf, "RR", 2))
-        (*bw_modifiers)[index].b_mod_type =
-          FSDP_BW_MOD_TYPE_RTCP_RECEIVERS;
-      else
-      {
-        (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN;
-        (*bw_modifiers)[index].b_unknown_bw_modt =
-          (char *) strdup (fsdp_buf);
-      }
-      (*bw_modifiers)[index].b_value = wuint;
-      NEXT_LINE (*p);
-    }
-    else
-    {
-      *bw_modifiers_count -= i;
-      return FSDPE_INVALID_BANDWIDTH;
-    }
-    i--;
-  }
-  return FSDPE_OK;
-}
-
-static fsdp_error_t
-fsdp_parse_k (const char **p, fsdp_encryption_method_t * method,
-	      char **content)
-{
-  char fsdp_buf[MAXSHORTFIELDLEN];
-  char longfsdp_buf[MAXLONGFIELDLEN];
-
-  if (!strncmp (*p, "k=", 2))
-  {
-    if (sscanf (*p, "k=prompt"))
-    {
-      *method = FSDP_ENCRYPTION_METHOD_PROMPT;
-      *content = NULL;
-      NEXT_LINE (*p);
-    }
-    else
-    {
-      if (sscanf
-          (*p, "k=%6[^:\r\n]:%" MLFLENS "s", fsdp_buf, longfsdp_buf))
-      {
-        if (!strncmp (fsdp_buf, "clear", 5))
-          *method = FSDP_ENCRYPTION_METHOD_CLEAR;
-        else if (!strncmp (fsdp_buf, "base64", 6))
-          *method = FSDP_ENCRYPTION_METHOD_BASE64;
-        else if (!strncmp (fsdp_buf, "uri", 3))
-          *method = FSDP_ENCRYPTION_METHOD_URI;
-        else
-          return FSDPE_INVALID_ENCRYPTION_METHOD;
-        *content = strdup (longfsdp_buf);
-        NEXT_LINE (*p);
-      }
-    }
-  }
-  return FSDPE_OK;
-}
-
-static fsdp_error_t
-fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter,
-		   const char *value)
-{
-  fsdp_error_t result = FSDPE_OK;
-
-  if (0 == *counter)
-  {
-    *counter = 0;
-    *rtpmap = calloc (MEDIA_RTPMAPS_MAX_COUNT, sizeof (fsdp_rtpmap_t *));
-  }
-  if (*counter < MEDIA_RTPMAPS_MAX_COUNT)
-  {
-    unsigned int c = *counter;
-    fsdp_rtpmap_t **map = *rtpmap;
-    char fsdp_buf[MAXSHORTFIELDLEN];
-    char longfsdp_buf[MAXLONGFIELDLEN];
-    map[c] = calloc (1, sizeof (fsdp_rtpmap_t));
-
-    /* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding
-       parameters]> */
-    if (2 == sscanf (value, "%s %s", fsdp_buf, longfsdp_buf))
-    {
-      char *slash1;
-      map[c]->pt = strdup (fsdp_buf);
-      /* parse <encoding name>/<clock rate>[/<encoding parameters>] */
-      slash1 = strchr (longfsdp_buf, '/');
-      if (NULL == slash1)
-      {
-        result = FSDPE_INVALID_ATTRIBUTE_RTPMAP;
-      }
-      else
-      {
-        char *slash2;
-        *slash1 = '\0';
-        slash1++;
-        map[c]->encoding_name = strdup (longfsdp_buf);
-        slash2 = strchr (slash1, '/');
-        if (NULL != slash2)
-        {
-          *slash2 = '\0';
-          slash2++;
-          map[c]->parameters = strdup (slash2);
-        }
-        map[c]->clock_rate = strtol (slash1, NULL, 10);
-      }
-      (*counter)++;
-    }
-  }
-  return result;
-}
-
-static fsdp_error_t
-fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds)
-{
-  const unsigned long SECONDS_PER_DAY = 86400;
-  const unsigned long SECONDS_PER_HOUR = 3600;
-  const unsigned long SECONDS_PER_MINUTE = 60;
-  char c;
-  unsigned long int wuint;
-
-  if (sscanf (time, "%lu%c", &wuint, &c) == 2)
-  {
-    /* time with unit specification character */
-    switch (c)
-    {
-    case 'd':
-      *seconds = wuint * SECONDS_PER_DAY;
-      break;
-    case 'h':
-      *seconds = wuint * SECONDS_PER_HOUR;
-      break;
-    case 'm':
-      *seconds = wuint * SECONDS_PER_MINUTE;
-      break;
-    case 's':
-      *seconds = wuint;
-      break;
-    default:
-      return FSDPE_INVALID_REPEAT;
-      break;
-    }
-  }
-  else if (sscanf (time, "%lu", &wuint) == 1)
-  {
-    /* time without unit specification character */
-    *seconds = wuint;
-  }
-  else
-  {
-    return FSDPE_INVALID_REPEAT;
-  }
-  return FSDPE_OK;
-}
-
-unsigned int
-fsdp_get_version (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->version;
-}
-
-const char *
-fsdp_get_owner_username (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->o_username;
-}
-
-const char *
-fsdp_get_session_id (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->o_session_id;
-}
-
-const char *
-fsdp_get_announcement_version (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->o_announcement_version;
-}
-
-fsdp_network_type_t
-fsdp_get_owner_network_type (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_NETWORK_TYPE_UNDEFINED;
-  return dsc->o_network_type;
-}
-
-fsdp_address_type_t
-fsdp_get_owner_address_type (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_ADDRESS_TYPE_UNDEFINED;
-  return dsc->o_address_type;
-}
-
-const char *
-fsdp_get_owner_address (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->o_address;
-}
-
-const char *
-fsdp_get_name (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->s_name;
-}
-
-const char *
-fsdp_get_information (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->i_information;
-}
-
-const char *
-fsdp_get_uri (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->u_uri;
-}
-
-unsigned int
-fsdp_get_emails_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->emails_count;
-}
-
-const char *
-fsdp_get_email (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->emails_count))
-    return NULL;
-  return dsc->emails[index];
-}
-
-unsigned int
-fsdp_get_phones_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->phones_count;
-}
-
-const char *
-fsdp_get_phone (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->phones_count))
-    return NULL;
-  return dsc->phones[index];
-}
-
-fsdp_network_type_t
-fsdp_get_global_conn_network_type (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_NETWORK_TYPE_UNDEFINED;
-  return dsc->c_network_type;
-}
-
-fsdp_address_type_t
-fsdp_get_global_conn_address_type (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_ADDRESS_TYPE_UNDEFINED;
-  return dsc->c_address_type;
-}
-
-const char *
-fsdp_get_global_conn_address (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->c_address.address;
-}
-
-unsigned int
-fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->c_address.address_ttl;
-}
-
-unsigned int
-fsdp_get_global_conn_address_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->c_address.address_count;
-}
-
-unsigned int
-fsdp_get_bw_modifier_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->bw_modifiers_count;
-}
-
-fsdp_bw_modifier_type_t
-fsdp_get_bw_modifier_type (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->bw_modifiers_count))
-    return FSDP_BW_MOD_TYPE_UNDEFINED;
-  return dsc->bw_modifiers[index].b_mod_type;
-}
-
-const char *
-fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc,
-				   unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->bw_modifiers_count) ||
-      (dsc->bw_modifiers[index].b_mod_type != FSDP_BW_MOD_TYPE_UNKNOWN))
-    return NULL;
-  return dsc->bw_modifiers[index].b_unknown_bw_modt;
-}
-
-unsigned long int
-fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->bw_modifiers_count))
-    return 0;
-  return dsc->bw_modifiers[index].b_value;
-}
-
-time_t
-fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->time_periods_count))
-    return 0;
-  return dsc->time_periods[index]->start;
-}
-
-time_t
-fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->time_periods_count))
-    return 0;
-  return dsc->time_periods[index]->stop;
-}
-
-unsigned int
-fsdp_get_period_repeats_count (const fsdp_description_t * dsc,
-			       unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->time_periods_count))
-    return 0;
-  return dsc->time_periods[index]->repeats_count;
-}
-
-unsigned long int
-fsdp_get_period_repeat_interval (const fsdp_description_t * dsc,
-				 unsigned int index, unsigned int rindex)
-{
-  if ((!dsc) || (index >= dsc->time_periods_count))
-    return 0;
-  return dsc->time_periods[index]->repeats[rindex]->interval;
-}
-
-unsigned long int
-fsdp_get_period_repeat_duration (const fsdp_description_t * dsc,
-				 unsigned int index, unsigned int rindex)
-{
-  if ((!dsc) || (index >= dsc->time_periods_count))
-    return 0;
-  return dsc->time_periods[index]->repeats[rindex]->duration;
-}
-
-const unsigned long int *
-fsdp_get_period_repeat_offsets (const fsdp_description_t * dsc,
-				unsigned int index, unsigned int rindex)
-{
-  if ((!dsc) || (index >= dsc->time_periods_count))
-    return NULL;
-  return dsc->time_periods[index]->repeats[rindex]->offsets;
-}
-
-const char *
-fsdp_get_timezone_adj (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->timezone_adj;
-}
-
-unsigned int
-fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->unidentified_attributes_count;
-}
-
-const char *
-fsdp_get_unidentified_attribute (const fsdp_description_t * dsc,
-				 unsigned int index)
-{
-  if (!dsc || (index < dsc->unidentified_attributes_count))
-    return NULL;
-  return dsc->unidentified_attributes[index];
-}
-
-fsdp_encryption_method_t
-fsdp_get_encryption_method (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_ENCRYPTION_METHOD_UNDEFINED;
-  return dsc->k_encryption_method;
-}
-
-const char *
-fsdp_get_encryption_content (const fsdp_description_t * dsc)
-{
-  if (!dsc || (dsc->k_encryption_method == FSDP_ENCRYPTION_METHOD_UNDEFINED))
-    return NULL;
-  return dsc->k_encryption_content;
-}
-
-unsigned int
-fsdp_get_rtpmap_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_rtpmaps_count;
-}
-
-const char *
-fsdp_get_rtpmap_payload_type (const fsdp_description_t * dsc,
-			      unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
-    return NULL;
-  return dsc->a_rtpmaps[index]->pt;
-}
-
-const char *
-fsdp_get_rtpmap_encoding_name (const fsdp_description_t * dsc,
-			       unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
-    return NULL;
-  return dsc->a_rtpmaps[index]->encoding_name;
-}
-
-unsigned int
-fsdp_get_rtpmap_clock_rate (const fsdp_description_t * dsc,
-			    unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
-    return 0;
-  return dsc->a_rtpmaps[index]->clock_rate;
-}
-
-const char *
-fsdp_get_rtpmap_encoding_parameters (const fsdp_description_t * dsc,
-				     unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
-    return NULL;
-  return dsc->a_rtpmaps[index]->parameters;
-}
-
-const char *
-fsdp_get_str_att (const fsdp_description_t * dsc, fsdp_session_str_att_t att)
-{
-  /*TODO: change these individual attributes with a table, thus
-    avoiding this slow switch */
-  char *result;
-
-  if (!dsc)
-    return NULL;
-
-  switch (att)
-  {
-  case FSDP_SESSION_STR_ATT_CATEGORY:
-    result = dsc->a_category;
-    break;
-  case FSDP_SESSION_STR_ATT_KEYWORDS:
-    result = dsc->a_keywords;
-    break;
-  case FSDP_SESSION_STR_ATT_TOOL:
-    result = dsc->a_tool;
-    break;
-  case FSDP_SESSION_STR_ATT_CHARSET:
-    result = dsc->a_charset;
-    break;
-  default:
-    result = NULL;
-  }
-  return result;
-}
-
-unsigned int
-fsdp_get_sdplang_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_sdplangs_count;
-}
-
-const char *
-fsdp_get_sdplang (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->a_sdplangs_count))
-    return NULL;
-  return dsc->a_sdplangs[index];
-}
-
-unsigned int
-fsdp_get_lang_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_langs_count;
-}
-
-const char *
-fsdp_get_lang (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->a_langs_count))
-    return NULL;
-  return dsc->a_langs[index];
-}
-
-unsigned int
-fsdp_get_control_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_controls_count;
-}
-
-const char *
-fsdp_get_control (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((!dsc) || (index >= dsc->a_controls_count))
-    return NULL;
-  return dsc->a_controls[index];
-}
-
-const char *
-fsdp_get_range (const fsdp_description_t * dsc)
-{
-  return dsc->a_range;
-}
-
-fsdp_sendrecv_mode_t
-fsdp_get_sendrecv_mode (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_SENDRECV_UNDEFINED;
-  return dsc->a_sendrecv_mode;
-}
-
-fsdp_session_type_t
-fsdp_get_session_type (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_SESSION_TYPE_UNDEFINED;
-  return dsc->a_type;
-}
-
-unsigned int
-fsdp_get_media_count (const fsdp_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->media_announcements_count;
-}
-
-const fsdp_media_description_t *
-fsdp_get_media (const fsdp_description_t * dsc, unsigned int index)
-{
-  if ((index >= dsc->media_announcements_count))
-    return NULL;
-  return dsc->media_announcements[index];
-}
-
-fsdp_media_t
-fsdp_get_media_type (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_MEDIA_UNDEFINED;
-  return dsc->media_type;
-}
-
-unsigned int
-fsdp_get_media_port (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->port;
-}
-
-unsigned int
-fsdp_get_media_port_count (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->port_count;
-}
-
-fsdp_transport_protocol_t
-fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_TP_UNDEFINED;
-  return dsc->transport;
-}
-
-unsigned int
-fsdp_get_media_formats_count (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->formats_count;
-}
-
-const char *
-fsdp_get_media_format (const fsdp_media_description_t * dsc,
-		       unsigned int index)
-{
-  if (!dsc && (index < dsc->formats_count))
-    return NULL;
-  return dsc->formats[index];
-}
-
-const char *
-fsdp_get_media_title (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->i_title;
-}
-
-fsdp_network_type_t
-fsdp_get_media_network_type (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_NETWORK_TYPE_UNDEFINED;
-  return dsc->c_network_type;
-}
-
-fsdp_address_type_t
-fsdp_get_media_address_type (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_ADDRESS_TYPE_UNDEFINED;
-  return dsc->c_address_type;
-}
-
-const char *
-fsdp_get_media_address (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->c_address.address;
-}
-
-unsigned int
-fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->c_address.address_ttl;
-}
-
-unsigned int
-fsdp_get_media_address_count (const fsdp_media_description_t * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->c_address.address_count;
-}
-
-fsdp_bw_modifier_type_t
-fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc,
-				 unsigned int index)
-{
-  if (!dsc || (index >= dsc->bw_modifiers_count))
-    return FSDP_BW_MOD_TYPE_UNDEFINED;
-  return dsc->bw_modifiers[index].b_mod_type;
-}
-
-const char *
-fsdp_get_media_bw_modifier_type_unknown (const fsdp_media_description_t * dsc,
-					 unsigned int index)
-{
-  if (!dsc || (index >= dsc->bw_modifiers_count) ||
-      (FSDP_BW_MOD_TYPE_UNKNOWN != dsc->bw_modifiers[index].b_mod_type))
-    return NULL;
-  return dsc->bw_modifiers[index].b_unknown_bw_modt;
-}
-
-unsigned long int
-fsdp_get_media_bw_value (const fsdp_media_description_t * dsc,
-			 unsigned int index)
-{
-  if (!dsc || (index >= dsc->bw_modifiers_count))
-    return 0;
-  return dsc->bw_modifiers[index].b_value;
-}
-
-fsdp_encryption_method_t
-fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_ENCRYPTION_METHOD_UNDEFINED;
-  return dsc->k_encryption_method;
-}
-
-const char *
-fsdp_get_media_encryption_content (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->k_encryption_content;
-}
-
-unsigned int
-fsdp_get_media_ptime (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_ptime;
-}
-
-unsigned int
-fsdp_get_media_maxptime (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_maxptime;
-}
-
-unsigned int
-fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->a_rtpmaps_count;
-}
-
-const char *
-fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t * mdsc,
-				    unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
-    return NULL;
-  return mdsc->a_rtpmaps[index]->pt;
-}
-
-const char *
-fsdp_get_media_rtpmap_encoding_name (const fsdp_media_description_t * mdsc,
-				     unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
-    return NULL;
-  return mdsc->a_rtpmaps[index]->encoding_name;
-}
-
-unsigned int
-fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc,
-				  unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
-    return 0;
-  return mdsc->a_rtpmaps[index]->clock_rate;
-}
-
-const char *
-fsdp_get_media_rtpmap_encoding_parameters (const fsdp_description_t * mdsc,
-					   unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
-    return NULL;
-  return mdsc->a_rtpmaps[index]->parameters;
-}
-
-unsigned int
-fsdp_get_media_sdplang_count (const fsdp_media_description_t * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->a_sdplangs_count;
-}
-
-const char *
-fsdp_get_media_sdplang (const fsdp_media_description_t * mdsc,
-			unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_sdplangs_count))
-    return NULL;
-  return mdsc->a_sdplangs[index];
-}
-
-unsigned int
-fsdp_get_media_lang_count (const fsdp_media_description_t * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->a_langs_count;
-}
-
-const char *
-fsdp_get_media_lang (const fsdp_media_description_t * mdsc,
-		     unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_langs_count))
-    return NULL;
-  return mdsc->a_langs[index];
-}
-
-unsigned int
-fsdp_get_media_control_count (const fsdp_media_description_t * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->a_controls_count;
-}
-
-char *
-fsdp_get_media_control (const fsdp_media_description_t * mdsc,
-			unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_controls_count))
-    return NULL;
-  return mdsc->a_controls[index];
-}
-
-char *
-fsdp_get_media_range (const fsdp_media_description_t * mdsc)
-{
-  return mdsc->a_range;
-}
-
-unsigned int
-fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->a_fmtps_count;
-}
-
-const char *
-fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc,
-		     unsigned int index)
-{
-  if (!mdsc || (index >= mdsc->a_fmtps_count))
-    return NULL;
-  return mdsc->a_fmtps[index];
-}
-
-fsdp_orient_t
-fsdp_get_media_orient (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_ORIENT_UNDEFINED;
-  return dsc->a_orient;
-}
-
-fsdp_sendrecv_mode_t
-fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_SENDRECV_UNDEFINED;
-  return dsc->a_sendrecv_mode;
-}
-
-float
-fsdp_get_media_framerate (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_framerate;
-}
-
-unsigned int
-fsdp_get_media_quality (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_quality;
-}
-
-unsigned int
-fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return 0;
-  return dsc->a_rtcp_port;
-}
-
-fsdp_network_type_t
-fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_NETWORK_TYPE_UNDEFINED;
-  return dsc->a_rtcp_network_type;
-}
-
-fsdp_address_type_t
-fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return FSDP_ADDRESS_TYPE_UNDEFINED;
-  return dsc->a_rtcp_address_type;
-}
-
-const char *
-fsdp_get_media_rtcp_address (const fsdp_media_description_t * dsc)
-{
-  if (!dsc)
-    return NULL;
-  return dsc->a_rtcp_address;
-}
-
-unsigned int
-fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t
-					     * mdsc)
-{
-  if (!mdsc)
-    return 0;
-  return mdsc->unidentified_attributes_count;
-}
-
-const char *
-fsdp_get_media_unidentified_attribute (const fsdp_media_description_t * mdsc,
-				       unsigned int index)
-{
-  if (!mdsc || (index < mdsc->unidentified_attributes_count))
-    return NULL;
-  return mdsc->unidentified_attributes[index];
-}
--- a/libmpdemux/freesdp/parser.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,728 +0,0 @@
-/*
-  This file is part of FreeSDP
-  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
-
-  FreeSDP is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU 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
-
-  Benjamin Zores, (C) 2006
-    added support in parser for the a=control: lines.
-    added support in parser for the a=range: lines.
-*/
-
-/**
- * @file parser.h
- * @ingroup parser
- * @short Specific public header for parsing module.
- **/
-
-#ifndef FSDP_PARSER_H
-#define FSDP_PARSER_H
-
-#include "common.h"
-
-BEGIN_C_DECLS
-/**
- * @defgroup parser FreeSDP Parsing Module
- *
- * SDP descriptions parsing routines.
- * @{
- **/
-/**
- * Parse a SDP description in <code>description</code>, extracting the
- * session properties into <code>dsc</code>. These properties can be
- * obtained individually later using the <code>fsdp_get_xxxx<code>
- * functions.
- *
- * @param description a multimedia session description formatted in
- * SDP.  
- * @param dsc pointer that is updated to point to a fsdp_description_t
- * object. This fsdp_description_t object should have been previously
- * allocated using <code>fsdp_description_new()</code>; to free it,
- * <code>fsdp_description_delete()</code> should be used.
- *
- * @return FSDPE_OK when parsing completes successfully. Otherwise,
- * another error code is returned.
- **/
-fsdp_error_t fsdp_parse (const char *description, fsdp_description_t * dsc);
-
-/**
- * Get the SDP protocol version of the description.
- *
- * @return SDP protocol version number. 
- **/
-unsigned int fsdp_get_version (const fsdp_description_t * dsc);
-
-/**
- * Get the username provided by the originator of the session. 
- *
- * @param dsc SDP description object.
- * @return username of the session owner
- **/
-const char *fsdp_get_owner_username (const fsdp_description_t * dsc);
-
-/**
- * Get the id for the session described in <code>dsc</code>. 
- *
- * @param dsc SDP description object.
- * @return id string for this session.
- **/
-const char *fsdp_get_session_id (const fsdp_description_t * dsc);
-
-/**
- * Get the announcement version for the session description in
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @return announcement version string for this description.
- **/
-const char *fsdp_get_announcement_version (const fsdp_description_t * dsc);
-
-/**
- * Get the the type of network the owner of the session described in
- * <code>dsc</code> is based on.
- *
- * @param dsc SDP description object.
- * @return network type for the owner of this session.
- **/
-fsdp_network_type_t
-fsdp_get_owner_network_type (const fsdp_description_t * dsc);
-
-/**
- * Get the the type of address the owner of the session described in
- * <code>dsc</code> is based on.
- *
- * @param dsc SDP description object.
- * @return network address type for the owner of this session.
- **/
-fsdp_address_type_t
-fsdp_get_owner_address_type (const fsdp_description_t * dsc);
-
-/**
- * Get the network address of the owner of the session described in
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @return network address for the owner this session.
- **/
-const char *fsdp_get_owner_address (const fsdp_description_t * dsc);
-
-/**
- * Get the name of the session described in <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @return name of this session.
- **/
-const char *fsdp_get_name (const fsdp_description_t * dsc);
-
-/**
- * Get the information about the session provided in the description
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @return information of this session.
- **/
-const char *fsdp_get_information (const fsdp_description_t * dsc);
-
-/**
- * Get an URI about the session provided in the description
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @return string containing an URI about the session. NULL if the
- * session uri is missing.
- **/
-const char *fsdp_get_uri (const fsdp_description_t * dsc);
-
-/**
- * Get the number of emails specified for the session in the description
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @return number of emails.
- **/
-unsigned int fsdp_get_emails_count (const fsdp_description_t * dsc);
-
-/**
- * Get the n-th email specified for the session in the description
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @param index number of URI. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_emails_count() - 1.
- * @return string containing an email about the session. NULL if there
- * is no such index.
- **/
-const char *fsdp_get_email (const fsdp_description_t * dsc,
-			    unsigned int index);
-
-/**
- * Get the number of phones specified for the session in the description
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @return number of emails.
- **/
-unsigned int fsdp_get_phones_count (const fsdp_description_t * dsc);
-
-/**
- * Get the n-th phone specified for the session in the description
- * <code>dsc</code>.
- *
- * @param dsc SDP description object.
- * @param index number of URI. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_phones_count() - 1.
- * @return string containing a phone about the session. NULL if there
- * is no such index.
- **/
-const char *fsdp_get_phone (const fsdp_description_t * dsc,
-			    unsigned int index);
-
-/**
- * Get the the global type of network of the multimedia session
- * connection.
- *
- * @param dsc SDP description object.
- * @return global network type for this
- * connection. FSDP_NETWORK_TYPE_UNDEFINED if no global network
- * address type is included in the description.
- **/
-fsdp_network_type_t
-fsdp_get_global_conn_network_type (const fsdp_description_t * dsc);
-
-/**
- * Get the the global type of network address of the multimedia
- * session connection.
- *
- * @param dsc SDP description object.
- * @return global network address type for this connection.
- * FSDP_ADDRESS_TYPE_UNDEFINED if no global network address type is
- * included in the description.
- **/
-fsdp_address_type_t
-fsdp_get_global_conn_address_type (const fsdp_description_t * dsc);
-
-/**
- * Get the the global address of the multimedia session connection.
- *
- * @param dsc SDP description object.
- * @return global address for this connection.
- **/
-const char *fsdp_get_global_conn_address (const fsdp_description_t * dsc);
-
-unsigned int
-fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc);
-
-unsigned int
-fsdp_get_global_conn_address_count (const fsdp_description_t * dsc);
-
-/**
- * Get the number of bandwidth modifiers specified for this session.
- *
- * @param dsc SDP description object.
- * @return number of bandwidth modifiers.
- **/
-unsigned int fsdp_get_bw_modifier_count (const fsdp_description_t * dsc);
-
-/**
- * Get the bandwidth modifier type for the session.
- *
- * @param dsc SDP description object.
- * @param index number of bandwidth modifier.
- *
- * @return global bandwidth modifier type.  
- * @retval FSDP_BW_MOD_TYPE_UNDEFINED if no global bandwith modifier
- * type is defined or invalid index.
- * @retval FSDP_BW_MOD_TYPE_UNKNOWN if an unknown bandwith modifier is
- * specified or an invalid index is provided. In this case
- * fsdp_get_bw_modifer_type_unknown() can be called to get the
- * modifier as a character string.
- **/
-fsdp_bw_modifier_type_t
-fsdp_get_bw_modifier_type (const fsdp_description_t * dsc,
-			   unsigned int index);
-
-/**
- * Get the textual bandwidth modifier type when it is unknown. 
- *
- * @param dsc SDP description object.
- * @param index number of bandwidth modifier.
- *
- * @return global bandwidth modifier type.
- * @retval empty string if the provided bandwidth type is not unknown,
- * the provided index is invalid or or there was a parse error.
- **/
-const char *fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc,
-					       unsigned int index);
-
-/**
- * Get the value for the bandwidth modifier. 
- *
- * @param dsc SDP description object.
- * @param index number of bandwidth modifier.
- * @return global bandwidth value.
- * @retval 0 if no bandwidth is specified for this session or an
- * invalid index has been provided.
- **/
-unsigned long int
-fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index);
-
-/**
- * Get the number of time periods specified for this session
- *
- * @param dsc SDP description object.
- * @return number of time periods
- **/
-unsigned long int fsdp_get_period_count (const fsdp_description_t * dsc);
-
-/**
- * Get the start time for the period selected by index.
- *
- * @param dsc SDP description object.
- * @param index number of time period. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_period_count() - 1.
- * @return start time
- * @retval 0 if an invalid index is provided.
- **/
-time_t
-fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index);
-
-/**
- * Get the stop time for the period selected by index.
- *
- * @param dsc SDP description object.
- * @param index number of time period. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_period_count() - 1.
- * @return stop time
- * @retval 0 if an invalid index is provided.
- **/
-time_t
-fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index);
-
-/**
- * Get the number of repeats for the period selected by index.
- *
- * @param dsc SDP description object.
- * @param index number of the period. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_period_count() - 1.
- * @return number of repeats
- * @retval 0 if an invalid index is provided.
- **/
-unsigned int
-fsdp_get_period_repeats_count (const fsdp_description_t * dsc,
-			       unsigned int index);
-
-/**
- * Get the interval time of the repeat selected by rindex for the
- * period selected by index.
- *
- * @param dsc SDP description object.
- * @param index number of time period. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_period_count() - 1.
- * @param rindex number of repeat
- * @return interval time
- * @retval 0 if an invalid index is provided.
- **/
-unsigned long int
-fsdp_get_period_repeat_interval (const fsdp_description_t * dsc,
-				 unsigned int index, unsigned int rindex);
-
-/**
- * Get the duration of the repeat selected by rindex for the period
- * selected by index.
- *
- * @param dsc SDP description object.
- * @param index number of time period. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_period_count() - 1.
- * @param rindex number of repeat
- * @return duration
- * @retval 0 if an invalid index is provided.
- **/
-unsigned long int
-fsdp_get_period_repeat_duration (const fsdp_description_t * dsc,
-				 unsigned int index, unsigned int rindex);
-
-/**
- * Get the offsets of the repeat selected by rindex for the period
- * selected by index.
- *
- * @param dsc SDP description object.
- * @param index number of time period. Note that this index follows the
- * traditional C convention: from 0 to fsdp_get_period_count() - 1.
- * @param rindex number of repeat
- * @return array of offsets
- * @retval NULL if an invalid index is provided.
- **/
-const unsigned long int *fsdp_get_period_repeat_offsets (const
-							 fsdp_description_t *
-							 dsc,
-							 unsigned int index,
-							 unsigned int rindex);
-
-/**
- * Get the encryption method defined for this session.
- *
- * @param dsc SDP description object.
- * @return encryption method. FSDP_ENCRYPTION_METHOD_UNDEFINED if no
- * encryption method is specified.
- **/
-fsdp_encryption_method_t
-fsdp_get_encryption_method (const fsdp_description_t * dsc);
-
-/**
- * Get the encryption key or a URI pointing to the encryption key for
- * this session.
- *
- * @param dsc SDP description object.
- * @return encryption key unless FSDP_ENCRYPTION_METHOD_URI is
- * specified, in which case a URI pointing to the key is returned. If
- * the global encryption method is undefined, NULL is returned.
- **/
-const char *fsdp_get_encryption_content (const fsdp_description_t * dsc);
-
-/**
- * Get timezone adjustments.
- *
- * @param dsc SDP description object.
- * @return string with list of timezone adjustments
- * @retval NULL if no timezone adjustment list was specified or there
- * was a parse error.
- **/
-const char *fsdp_get_timezone_adj (const fsdp_description_t * dsc);
-
-/**
- *
- **/
-unsigned int
-fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_unidentified_attribute (const fsdp_description_t * dsc,
-					     unsigned int index);
-
-/**
- *
- **/
-unsigned int
-fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t
-						* mdsc, unsigned int index);
-
-/**
- *
- **/
-const char *fsdp_get_media_rtpmap_encoding_name (const
-						 fsdp_media_description_t *
-						 mdsc, unsigned int index);
-
-/**
- *
- **/
-unsigned int
-fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc,
-				  unsigned int index);
-
-/**
- *
- **/
-const char *fsdp_get_media_rtpmap_encoding_parameters (const
-						       fsdp_description_t *
-						       mdsc,
-						       unsigned int index);
-
-/**
- * Get the value of the session attribute specified in
- * <code>att</code>. This function works for all the session
- * attributes whose value is a character string. These attributes are
- * defined in the session_string_attribute_t enumerated type.
- *
- * @param dsc SDP description object.
- * @param att attribute to get.
- *
- * @return value of the attribute <code>att</code>.
- * @retval NULL if the attribute was not specified or there was a
- * parse error or an invalid att is given.
- **/
-const char *fsdp_get_str_att (const fsdp_description_t * dsc,
-			      fsdp_session_str_att_t att);
-
-/**
- *
- **/
-unsigned int fsdp_get_sdplang_count (const fsdp_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_sdplang (const fsdp_description_t * dsc,
-			      unsigned int index);
-
-/** 
- * Get the mode of the conference, specified with attributes sendrecv,
- * sendonly, recvonly and inactive.
- *
- * @param dsc SDP description object.
- * @return send/rec conference mode.
- * @retval FSDP_SENDRECV_UNDEFINED if conference mode not provided.
- **/
-fsdp_sendrecv_mode_t fsdp_get_sendrecv_mode (const fsdp_description_t * dsc);
-
-/**
- * Get the type of conference, such as broadcast, meeting, moderated,
- * test or H332.
- *
- * @param dsc SDP description object.
- * @return conference type.
- * @retval FSDP_SESSION_TYPE_UNDEFINED if conference type not provided.
- **/
-fsdp_session_type_t fsdp_get_session_type (const fsdp_description_t * dsc);
-
-/**
- *
- **/
-unsigned int fsdp_get_media_count (const fsdp_description_t * dsc);
-
-/**
- *
- **/
-const fsdp_media_description_t *fsdp_get_media (const fsdp_description_t *
-						dsc, unsigned int index);
-
-/**
- *
- **/
-fsdp_media_t fsdp_get_media_type (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-unsigned int fsdp_get_media_port (const fsdp_media_description_t * dsc);
-
-unsigned int fsdp_get_media_port_count (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-fsdp_transport_protocol_t
-fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_formats (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-unsigned int
-fsdp_get_media_formats_count (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_format (const fsdp_media_description_t * dsc,
-				   unsigned int index);
-
-/**
- *
- **/
-const char *fsdp_get_media_title (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-fsdp_network_type_t
-fsdp_get_media_network_type (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-fsdp_address_type_t
-fsdp_get_media_address_type (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_address (const fsdp_media_description_t * dsc);
-
-unsigned int
-fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc);
-
-unsigned int
-fsdp_get_media_address_count (const fsdp_media_description_t * mdsc);
-
-/**
- *
- **/
-fsdp_bw_modifier_type_t
-fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc,
-				 unsigned int index);
-
-/**
- *
- **/
-const char *fsdp_get_media_bw_modifier_type_unknown (const
-						     fsdp_media_description_t
-						     * dsc,
-						     unsigned int index);
-
-/**
- *
- **/
-unsigned long int
-fsdp_get_media_bw_value (const fsdp_media_description_t * dsc,
-			 unsigned int index);
-
-/**
- *
- **/
-fsdp_encryption_method_t
-fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_encryption_content (const fsdp_media_description_t
-					       * dsc);
-
-/**
- *
- **/
-unsigned int fsdp_get_media_ptime (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-unsigned int fsdp_get_media_maxptime (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-unsigned int
-fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc,
-				 unsigned int index);
-
-/**
- *
- **/
-unsigned int
-fsdp_get_media_sdplang_count (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_sdplang (const fsdp_media_description_t * dsc,
-				    unsigned int index);
-
-/**
- *
- **/
-unsigned int fsdp_get_media_lang_count (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_lang (const fsdp_media_description_t * dsc,
-				 unsigned int index);
-
-
-unsigned int fsdp_get_control_count (const fsdp_description_t * dsc);
-
-const char *fsdp_get_control (const fsdp_description_t * dsc,
-			      unsigned int index);
-
-const char *fsdp_get_range (const fsdp_description_t * dsc);
-
-unsigned int
-fsdp_get_media_control_count (const fsdp_media_description_t * mdsc);
-
-char *fsdp_get_media_control (const fsdp_media_description_t * mdsc,
-			      unsigned int index);
-
-char *fsdp_get_media_range (const fsdp_media_description_t * mdsc);
-
-/**
- *
- **/
-fsdp_orient_t fsdp_get_media_orient (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-fsdp_sendrecv_mode_t
-fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-float fsdp_get_media_framerate (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-unsigned int fsdp_get_media_quality (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-unsigned int fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-fsdp_network_type_t
-fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-fsdp_address_type_t
-fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_rtcp_address (const fsdp_media_description_t *
-					 dsc);
-
-/**
- *
- **/
-unsigned int
-fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t
-					     * mdsc);
-
-/**
- *
- **/
-const char *fsdp_get_media_unidentified_attribute (const
-						   fsdp_media_description_t *
-						   mdsc, unsigned int index);
-
-
-	  /** @} *//* closes parser group */
-
-END_C_DECLS
-#endif /* FSDP_PARSER_H */
--- a/libmpdemux/freesdp/parserpriv.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
-  This file is part of FreeSDP
-  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@suidzer0.org>
-
-  FreeSDP is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU 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
-*/
-
-/**
- * @file parserpriv.h
- *
- * @short Private header for parser module.
- **/
-
-#ifndef FSDP_PARSERPRIV_H
-#define FSDP_PARSERPRIV_H
-
-#include "priv.h"
-#include "parser.h"
-
-/**
- * Parse a connection (c=<network type> <address type> <connection
- * address>) line. If the textual description in <code>p</code> begins
- * with a connection line, it is parsed. If not, nothing is done.
- * 
- * @param p fraction of textual SDP description.
- * @param ntype where to store the network type.
- * @param atype where to store the address type.
- * @param address where to store the connection address as a string.
- * 
- * @return parse error code.
- **/
-static fsdp_error_t
-fsdp_parse_c (const char **p, fsdp_network_type_t * ntype,
-	      fsdp_address_type_t * atype,
-	      fsdp_connection_address_t * address);
-
-/**
- * Parse b (b=<modifier>:<bandwidth-value>) consecutive lines. If the
- * textual description in <code>p</code> begins with a bandwidth line,
- * it is parsed as well as all b lines inmediately after it. If not,
- * nothing is done.
- * 
- * @param p fraction of textual SDP description.
- * @param bw_modifiers pointer to empty array of bandwidth modifiers to fill.
- * @param bw_modifiers_count where to set the number of bandwidth
- *        modifiers successfully parsed.
- *
- * @return parse error code.
- **/
-static fsdp_error_t
-fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers,
-	      unsigned int *bw_modifiers_count);
-
-/**
- * Parse a k (k=<method>) or (k=<method>:<encryption key>) line. If
- * the textual description in <code>p</code> begins with an encryption
- * line, it is parsed. If not, nothing is done.
- *
- * @param p fraction of textual SDP description.
- * @param method where to store the encryption method.
- * @param content where to store the encryption key if provided.
- *
- * @return parse error code.
- **/
-static fsdp_error_t
-fsdp_parse_k (const char **p, fsdp_encryption_method_t * method,
-	      char **content);
-
-
-/**
- * Parses a string whose first token (first characters before the
- * first space or end of string) is supposed to be a time in SDP
- * syntax. Some examples of SDP times are: 2d, 5h, 3444, 7778s,
- *
- * @param time time in SDP syntax as a string.
- * @param seconds where to store the value in seconds as an integer.
- *
- * @return parse error code.
- **/
-static fsdp_error_t
-fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds);
-
-static fsdp_error_t
-fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter,
-		   const char *value);
-
-/** 
- * Maximun default field len for "expected to be short" fields, like
- * username, session_id or inet addresses.
- *
- * MDFLENS value must be MAXSHORTFIELDLEN - 1 
- **/
-#define MAXSHORTFIELDLEN 96
-#define MSFLENS "95"
-
-/**
- * Maximun default field len for "maybe very long" fields, like
- * information, attribute values. This can also be used for lines
- * where there is only a string field, like phone and email.
- *
- * MLFLENS value must be MAXLONGFIELDLEN - 1
- **/
-#define MAXLONGFIELDLEN 1024
-#define MLFLENS "1023"
-
-#endif /* FSDP_PARSERPRIV_H */
--- a/libmpdemux/freesdp/priv.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/*
-  This file is part of FreeSDP
-  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
-
-  FreeSDP is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU 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
-
-  Benjamin Zores, (C) 2006
-    added support in parser for the a=control: lines.
-    added support in parser for the a=range: lines.
-*/
-
-/**
- * @file priv.h
- *
- * @short Common private header for both formatting and parsing modules.
- **/
-
-#ifndef FSDP_PRIV_H
-#define FSDP_PRIV_H
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "common.h"
-
-#define NTP_EPOCH_OFFSET 2208988800UL
-
-#define FSDP_MAX_LENGTH 2000
-
-/* Tags for doxygen documentation */
-
-/**
- * @mainpage FreeSDP Library Reference Manual
- * @section overview Overview (README)
- * @verbinclude ../../README
- *
- **/
-
-/**
- * @example formatdemo.c
- * 
- * A basic SDP descriptions formatter based on FreeSDP.
- **/
-
-/**
- * @example parsedemo.c
- * 
- * A basic SDP descriptions parser based on FreeSDP.
- **/
-
-/* Private routines declarations */
-
-BEGIN_C_DECLS
-/**
- * @short bandwidth modifier
- *
- * Holds type of modifier and value. Also holds the literal bandwidth
- * modifier if unknown.
- **/
-  typedef struct
-{
-  fsdp_bw_modifier_type_t b_mod_type;
-  unsigned long int b_value;
-  char *b_unknown_bw_modt;
-} fsdp_bw_modifier_t;
-
-/**
- * @short a=rtpmap: attribute
- *
- * Holds payload type, enconding name, RTP clock rate, and encofing
- * parameters.
- **/
-typedef struct
-{
-  char *pt;
-  char *encoding_name;
-  unsigned int clock_rate;
-  char *parameters;
-} fsdp_rtpmap_t;
-
-/**
- * @short Connection address specification
- *
- * Holds address (unicast or multicast) as well as TTL and number of
- * ports, when it is an IP4 multicast address.
- **/
-typedef struct fsdp_connection_address_t_s
-{
-  char *address;
-  unsigned int address_ttl;
-  unsigned int address_count;
-} fsdp_connection_address_t;
-
-/**
- * @short Struct for each media in a session description.
- **/
-struct fsdp_media_description_t_s
-{
-  /* from `m=<media>  <port>  <transport> <fmt list>' line */
-  fsdp_media_t media_type;
-  unsigned int port;
-  unsigned int port_count;
-  fsdp_transport_protocol_t transport;
-  char **formats;
-  unsigned int formats_count;
-  /* from i=<media title> */
-  char *i_title;
-  /* from `c=<network type> <address type> <connection address>' line
-     (optional) */
-  fsdp_network_type_t c_network_type;
-  fsdp_address_type_t c_address_type;
-  fsdp_connection_address_t c_address;
-  /* from `b=<modifier>:<bandwidth-value>' lines (optional) */
-  fsdp_bw_modifier_t *bw_modifiers;
-  unsigned int bw_modifiers_count;
-  /* from `k=<method>' or `k=<method>:<encryption key>' line
-     (optional) */
-  fsdp_encryption_method_t k_encryption_method;
-  char *k_encryption_content;
-  /* from `a=<attribute>' or `a=<attribute>:<value>' lines (opt) */
-  unsigned long int a_ptime;
-  unsigned long int a_maxptime;
-  /* rtpmap */
-  fsdp_rtpmap_t **a_rtpmaps;
-  unsigned int a_rtpmaps_count;
-  fsdp_orient_t a_orient;
-  fsdp_sendrecv_mode_t a_sendrecv_mode;
-
-  char **a_sdplangs;
-  unsigned int a_sdplangs_count;
-  char **a_langs;
-  unsigned int a_langs_count;
-
-  char **a_controls;
-  unsigned int a_controls_count;
-
-  char *a_range;
-
-  float a_framerate;
-  unsigned int a_quality;
-  char **a_fmtps;
-  unsigned int a_fmtps_count;
-  /* rtcp attribute */
-  unsigned int a_rtcp_port;
-  fsdp_network_type_t a_rtcp_network_type;
-  fsdp_address_type_t a_rtcp_address_type;
-  char *a_rtcp_address;
-  /* media attributes that are not directly supported */
-  char **unidentified_attributes;
-  unsigned int unidentified_attributes_count;
-};
-
-typedef struct fsdp_media_description_t_s fsdp_media_announcement_t;
-
-/**
- * @short Information for a repeat (struct for r= lines)
- **/
-typedef struct
-{
-  /* times in seconds */
-  unsigned long int interval;
-  unsigned long int duration;
-  unsigned long int *offsets;
-  unsigned int offsets_count;
-} fsdp_repeat_t;
-
-/**
- * @short Information about a time period
- *
- * The start and stop times as well as the information from the r=
- * lines for a t= line are stored in this structures.
- **/
-typedef struct
-{
-  time_t start;
-  time_t stop;
-  fsdp_repeat_t **repeats;
-  unsigned int repeats_count;
-} fsdp_time_period_t;
-
-/**
- * @short Struct for session descriptions.
- **/
-struct fsdp_description_t_s
-{
-  /* from v=... line */
-  unsigned int version;
-  /* from o=... line */
-  char *o_username;
-  char *o_session_id;
-  char *o_announcement_version;
-  fsdp_network_type_t o_network_type;
-  fsdp_address_type_t o_address_type;
-  char *o_address;
-  /* from s=... line */
-  char *s_name;
-  /* from i=... line (opt) */
-  char *i_information;
-  /* from u=... line (opt) */
-  char *u_uri;
-  /* from e=... lines (0 or more) */
-  const char **emails;
-  unsigned int emails_count;
-  /* from p=... lines (0 or more) */
-  const char **phones;
-  unsigned int phones_count;
-  /* from `c=<network type> <address type> <connection address>' line */
-  fsdp_network_type_t c_network_type;
-  fsdp_address_type_t c_address_type;
-  fsdp_connection_address_t c_address;
-  /* from `b=<modifier>:<bandwidth-value>' lines (optional) */
-  fsdp_bw_modifier_t *bw_modifiers;
-  unsigned int bw_modifiers_count;
-  /* from `t=<start time>  <stop time>' lines (1 or more) */
-  /* from `r=<repeat interval> <active duration> <list of offsets from
-     start-time>' */
-  fsdp_time_period_t **time_periods;
-  unsigned int time_periods_count;
-  /* from `z=<adjustment time> <offset> <adjustment time> <offset>
-     ....' lines */
-  char *timezone_adj;
-  /* from `k=<method>' or `k=<method>:<encryption key>' line (opt) */
-  fsdp_encryption_method_t k_encryption_method;
-  char *k_encryption_content;
-  /* from `a=<attribute>' or `a=<attribute>:<value>' lines (opt) */
-  char *a_category;
-  char *a_keywords;
-  char *a_tool;
-  char *a_range;
-  /* rtpmap */
-  fsdp_rtpmap_t **a_rtpmaps;
-  unsigned int a_rtpmaps_count;
-  fsdp_sendrecv_mode_t a_sendrecv_mode;
-  fsdp_session_type_t a_type;
-  char *a_charset;
-
-  char **a_sdplangs;
-  unsigned int a_sdplangs_count;
-  char **a_langs;
-  unsigned int a_langs_count;
-
-  char **a_controls;
-  unsigned int a_controls_count;
-  /* from `m=<media> <port>/<number of ports> <transport> <fmt list>'
-     lines [one or more] */
-  fsdp_media_announcement_t **media_announcements;
-  unsigned int media_announcements_count;
-  /* session attributes that are not directly supported */
-  char **unidentified_attributes;
-  unsigned int unidentified_attributes_count;
-};
-
-#define MEDIA_RTPMAPS_MAX_COUNT 5
-#define SDPLANGS_MAX_COUNT 5
-#define SDPCONTROLS_MAX_COUNT 10
-#define UNIDENTIFIED_ATTRIBUTES_MAX_COUNT 5
-
-END_C_DECLS
-#endif /* FSDP_PRIV_H */
--- a/libmpdemux/frequencies.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1169 +0,0 @@
-#include <stdlib.h>
-#include <sys/time.h>
-
-#include "frequencies.h"
-
-/* --------------------------------------------------------------------- */
-
-/* US broadcast */
-static const struct CHANLIST ntsc_bcast[] = {
-    { "2",	 55250 },
-    { "3",	 61250 },
-    { "4",	 67250 },
-    { "5",	 77250 },
-    { "6",	 83250 },
-    { "7",	175250 },
-    { "8",	181250 },
-    { "9",	187250 },
-    { "10",	193250 },
-    { "11",	199250 },
-    { "12",	205250 },
-    { "13",	211250 },
-    { "14",	471250 },
-    { "15",	477250 },
-    { "16",	483250 },
-    { "17",	489250 },
-    { "18",	495250 },
-    { "19",	501250 },
-    { "20",	507250 },
-    { "21",	513250 },
-    { "22",	519250 },
-    { "23",	525250 },
-    { "24",	531250 },
-    { "25",	537250 },
-    { "26",	543250 },
-    { "27",	549250 },
-    { "28",	555250 },
-    { "29",	561250 },
-    { "30",	567250 },
-    { "31",	573250 },
-    { "32",	579250 },
-    { "33",	585250 },
-    { "34",	591250 },
-    { "35",	597250 },
-    { "36",	603250 },
-    { "37",	609250 },
-    { "38",	615250 },
-    { "39",	621250 },
-    { "40",	627250 },
-    { "41",	633250 },
-    { "42",	639250 },
-    { "43",	645250 },
-    { "44",	651250 },
-    { "45",	657250 },
-    { "46",	663250 },
-    { "47",	669250 },
-    { "48",	675250 },
-    { "49",	681250 },
-    { "50",	687250 },
-    { "51",	693250 },
-    { "52",	699250 },
-    { "53",	705250 },
-    { "54",	711250 },
-    { "55",	717250 },
-    { "56",	723250 },
-    { "57",	729250 },
-    { "58",	735250 },
-    { "59",	741250 },
-    { "60",	747250 },
-    { "61",	753250 },
-    { "62",	759250 },
-    { "63",	765250 },
-    { "64",	771250 },
-    { "65",	777250 },
-    { "66",	783250 },
-    { "67",	789250 },
-    { "68",	795250 },
-    { "69",	801250 },
- 
-    { "70",	807250 },
-    { "71",	813250 },
-    { "72",	819250 },
-    { "73",	825250 },
-    { "74",	831250 },
-    { "75",	837250 },
-    { "76",	843250 },
-    { "77",	849250 },
-    { "78",	855250 },
-    { "79",	861250 },
-    { "80",	867250 },
-    { "81",	873250 },
-    { "82",	879250 },
-    { "83",	885250 },
-};
-
-/* US cable */
-static const struct CHANLIST ntsc_cable[] = {
-    { "1",	 73250 },
-    { "2",	 55250 },
-    { "3",	 61250 },
-    { "4",	 67250 },
-    { "5",	 77250 },
-    { "6",	 83250 },
-    { "7",	175250 },
-    { "8",	181250 },
-    { "9",	187250 },
-    { "10",	193250 },
-    { "11",	199250 },
-    { "12",	205250 },
-
-    { "13",	211250 },
-    { "14",	121250 },
-    { "15",	127250 },
-    { "16",	133250 },
-    { "17",	139250 },
-    { "18",	145250 },
-    { "19",	151250 },
-    { "20",	157250 },
- 
-    { "21",	163250 },
-    { "22",	169250 },
-    { "23",	217250 },
-    { "24",	223250 },
-    { "25",	229250 },
-    { "26",	235250 },
-    { "27",	241250 },
-    { "28",	247250 },
-    { "29",	253250 },
-    { "30",	259250 },
-    { "31",	265250 },
-    { "32",	271250 },
-    { "33",	277250 },
-    { "34",	283250 },
-    { "35",	289250 },
-    { "36",	295250 },
-    { "37",	301250 },
-    { "38",	307250 },
-    { "39",	313250 },
-    { "40",	319250 },
-    { "41",	325250 },
-    { "42",	331250 },
-    { "43",	337250 },
-    { "44",	343250 },
-    { "45",	349250 },
-    { "46",	355250 },
-    { "47",	361250 },
-    { "48",	367250 },
-    { "49",	373250 },
-    { "50",	379250 },
-    { "51",	385250 },
-    { "52",	391250 },
-    { "53",	397250 },
-    { "54",	403250 },
-    { "55",	409250 },
-    { "56",	415250 },
-    { "57",	421250 },
-    { "58",	427250 },
-    { "59",	433250 },
-    { "60",	439250 },
-    { "61",	445250 },
-    { "62",	451250 },
-    { "63",	457250 },
-    { "64",	463250 },
-    { "65",	469250 },
-    { "66",	475250 },
-    { "67",	481250 },
-    { "68",	487250 },
-    { "69",	493250 },
- 
-    { "70",	499250 },
-    { "71",	505250 },
-    { "72",	511250 },
-    { "73",	517250 },
-    { "74",	523250 },
-    { "75",	529250 },
-    { "76",	535250 },
-    { "77",	541250 },
-    { "78",	547250 },
-    { "79",	553250 },
-    { "80",	559250 },
-    { "81",	565250 },
-    { "82",	571250 },
-    { "83",	577250 },
-    { "84",	583250 },
-    { "85",	589250 },
-    { "86",	595250 },
-    { "87",	601250 },
-    { "88",	607250 },
-    { "89",	613250 },
-    { "90",	619250 },
-    { "91",	625250 },
-    { "92",	631250 },
-    { "93",	637250 },
-    { "94",	643250 },
-    { "95",	 91250 },
-    { "96",	 97250 },
-    { "97",	103250 },
-    { "98",	109250 },
-    { "99",	115250 },
-    { "100",	649250 },
-    { "101",	655250 },
-    { "102",	661250 },
-    { "103",	667250 },
-    { "104",	673250 },
-    { "105",	679250 },
-    { "106",	685250 },
-    { "107",	691250 },
-    { "108",	697250 },
-    { "109",	703250 },
-    { "110",	709250 },
-    { "111",	715250 },
-    { "112",	721250 },
-    { "113",	727250 },
-    { "114",	733250 },
-    { "115",	739250 },
-    { "116",	745250 },
-    { "117",	751250 },
-    { "118",	757250 },
-    { "119",	763250 },
-    { "120",	769250 },
-    { "121",	775250 },
-    { "122",	781250 },
-    { "123",	787250 },
-    { "124",	793250 },
-    { "125",	799250 },
- 
-    { "T7", 	  8250 },
-    { "T8",	 14250 },
-    { "T9",	 20250 },
-    { "T10",	 26250 },
-    { "T11",	 32250 },
-    { "T12",	 38250 },
-    { "T13",	 44250 },
-    { "T14",	 50250 }
-};
-
-/* US HRC */
-static const struct CHANLIST ntsc_hrc[] = {
-    { "1",	  72000 },
-    { "2",	  54000 }, 
-    { "3",	  60000 }, 
-    { "4",	  66000 }, 
-    { "5",	  78000 }, 
-    { "6",	  84000 }, 
-    { "7",	 174000 },
-    { "8",	 180000 },
-    { "9",	 186000 },
-    { "10",	 192000 },
-    { "11",	 198000 },
-    { "12",	 204000 },
-
-    { "13",	 210000 },
-    { "14",	 120000 },
-    { "15",	 126000 },
-    { "16",	 132000 },
-    { "17",	 138000 },
-    { "18",	 144000 },
-    { "19",	 150000 },
-    { "20",	 156000 },
- 
-    { "21",	 162000 },
-    { "22",	 168000 },
-    { "23",	 216000 },
-    { "24",	 222000 },
-    { "25",	 228000 },
-    { "26",	 234000 },
-    { "27",	 240000 },
-    { "28",	 246000 },
-    { "29",	 252000 },
-    { "30",	 258000 },
-    { "31",	 264000 },
-    { "32",	 270000 },
-    { "33",	 276000 },
-    { "34",	 282000 },
-    { "35",	 288000 },
-    { "36",	 294000 },
-    { "37",	 300000 },
-    { "38",	 306000 },
-    { "39",	 312000 },
-    { "40",	 318000 },
-    { "41",	 324000 },
-    { "42",	 330000 },
-    { "43",	 336000 },
-    { "44",	 342000 },
-    { "45",	 348000 },
-    { "46",	 354000 },
-    { "47",	 360000 },
-    { "48",	 366000 },
-    { "49",	 372000 },
-    { "50",	 378000 },
-    { "51",	 384000 },
-    { "52",	 390000 },
-    { "53",	 396000 },
-    { "54",	 402000 },
-    { "55",	 408000 },
-    { "56",	 414000 },
-    { "57",	 420000 },
-    { "58",	 426000 },
-    { "59",	 432000 },
-    { "60",	 438000 },
-    { "61",	 444000 },
-    { "62",	 450000 },
-    { "63",	 456000 },
-    { "64",	 462000 },
-    { "65",	 468000 },
-    { "66",	 474000 },
-    { "67",	 480000 },
-    { "68",	 486000 },
-    { "69",	 492000 },
- 
-    { "70",	 498000 },
-    { "71",	 504000 },
-    { "72",	 510000 },
-    { "73",	 516000 },
-    { "74",	 522000 },
-    { "75",	 528000 },
-    { "76",	 534000 },
-    { "77",	 540000 },
-    { "78",	 546000 },
-    { "79",	 552000 },
-    { "80",	 558000 },
-    { "81",	 564000 },
-    { "82",	 570000 },
-    { "83",	 576000 },
-    { "84",	 582000 },
-    { "85",	 588000 },
-    { "86",	 594000 },
-    { "87",	 600000 },
-    { "88",	 606000 },
-    { "89",	 612000 },
-    { "90",	 618000 },
-    { "91",	 624000 },
-    { "92",	 630000 },
-    { "93",	 636000 },
-    { "94",	 642000 },
-    { "95",	 900000 },
-    { "96",	 960000 },
-    { "97",	 102000 },
-    { "98",	 108000 },
-    { "99",	 114000 },
-    { "100",	 648000 },
-    { "101",	 654000 },
-    { "102",	 660000 },
-    { "103",	 666000 },
-    { "104",	 672000 },
-    { "105",	 678000 },
-    { "106",	 684000 },
-    { "107",	 690000 },
-    { "108",	 696000 },
-    { "109",	 702000 },
-    { "110",	 708000 },
-    { "111",	 714000 },
-    { "112",	 720000 },
-    { "113",	 726000 },
-    { "114",	 732000 },
-    { "115",	 738000 },
-    { "116",	 744000 },
-    { "117",	 750000 },
-    { "118",	 756000 },
-    { "119",	 762000 },
-    { "120",	 768000 },
-    { "121",	 774000 },
-    { "122",	 780000 },
-    { "123",	 786000 },
-    { "124",	 792000 },
-    { "125",	 798000 },
- 
-    { "T7",	   7000 },  
-    { "T8",	  13000 }, 
-    { "T9",	  19000 }, 
-    { "T10",	  25000 }, 
-    { "T11",	  31000 }, 
-    { "T12",	  37000 }, 
-    { "T13",	  43000 }, 
-    { "T14",	  49000 }, 
-};
-
-/* --------------------------------------------------------------------- */
-
-/* JP broadcast */
-static const struct CHANLIST ntsc_bcast_jp[] = {
-    { "1",   91250 },
-    { "2",   97250 },
-    { "3",  103250 },
-    { "4",  171250 },
-    { "5",  177250 },
-    { "6",  183250 },
-    { "7",  189250 },
-    { "8",  193250 },
-    { "9",  199250 },
-    { "10", 205250 },
-    { "11", 211250 },
-    { "12", 217250 },
-
-    { "13", 471250 },
-    { "14", 477250 },
-    { "15", 483250 },
-    { "16", 489250 },
-    { "17", 495250 },
-    { "18", 501250 },
-    { "19", 507250 },
-    { "20", 513250 },
-    { "21", 519250 },
-    { "22", 525250 },
-    { "23", 531250 },
-    { "24", 537250 },
-    { "25", 543250 },
-    { "26", 549250 },
-    { "27", 555250 },
-    { "28", 561250 },
-    { "29", 567250 },
-    { "30", 573250 },
-    { "31", 579250 },
-    { "32", 585250 },
-    { "33", 591250 },
-    { "34", 597250 },
-    { "35", 603250 },
-    { "36", 609250 },
-    { "37", 615250 },
-    { "38", 621250 },
-    { "39", 627250 },
-    { "40", 633250 },
-    { "41", 639250 },
-    { "42", 645250 },
-    { "43", 651250 },
-    { "44", 657250 },
-
-    { "45", 663250 },
-    { "46", 669250 },
-    { "47", 675250 },
-    { "48", 681250 },
-    { "49", 687250 },
-    { "50", 693250 },
-    { "51", 699250 },
-    { "52", 705250 },
-    { "53", 711250 },
-    { "54", 717250 },
-    { "55", 723250 },
-    { "56", 729250 },
-    { "57", 735250 },
-    { "58", 741250 },
-    { "59", 747250 },
-    { "60", 753250 },
-    { "61", 759250 },
-    { "62", 765250 },
-};
-
-/* JP cable */
-static const struct CHANLIST ntsc_cable_jp[] = {
-    { "13",	109250 },
-    { "14",	115250 },
-    { "15",	121250 },
-    { "16",	127250 },
-    { "17",	133250 },
-    { "18",	139250 },
-    { "19",	145250 },
-    { "20",	151250 },
- 
-    { "21",	157250 },
-    { "22",	165250 },
-    { "23",	223250 },
-    { "24",	231250 },
-    { "25",	237250 },
-    { "26",	243250 },
-    { "27",	249250 },
-    { "28",	253250 },
-    { "29",	259250 },
-    { "30",	265250 },
-    { "31",	271250 },
-    { "32",	277250 },
-    { "33",	283250 },
-    { "34",	289250 },
-    { "35",	295250 },
-    { "36",	301250 },
-    { "37",	307250 },
-    { "38",	313250 },
-    { "39",	319250 },
-    { "40",	325250 },
-    { "41",	331250 },
-    { "42",	337250 },
-    { "43",	343250 },
-    { "44",	349250 },
-    { "45", 	355250 },
-    { "46", 	361250 },
-    { "47", 	367250 },
-    { "48", 	373250 },
-    { "49", 	379250 },
-    { "50", 	385250 },
-    { "51", 	391250 },
-    { "52", 	397250 },
-    { "53", 	403250 },
-    { "54", 	409250 },
-    { "55", 	415250 },
-    { "56", 	421250 },
-    { "57", 	427250 },
-    { "58", 	433250 },
-    { "59", 	439250 },
-    { "60", 	445250 },
-    { "61", 	451250 },
-    { "62", 	457250 },
-    { "63",	463250 },
-};
-
-/* --------------------------------------------------------------------- */
-
-/* australia */
-static const struct CHANLIST pal_australia[] = {
-    { "0",	 46250 },
-    { "1",	 57250 },
-    { "2",	 64250 },
-    { "3",	 86250 },
-    { "4",  	 95250 },
-    { "5",  	102250 },
-    { "5A",  	138250 },
-    { "6",  	175250 },
-    { "7",  	182250 },
-    { "8",  	189250 },
-    { "9",  	196250 },
-    { "10", 	209250 },
-    { "11",	216250 },
-    { "28",	527250 },
-    { "29",	534250 },
-    { "30",	541250 },
-    { "31",	548250 },
-    { "32",	555250 },
-    { "33",	562250 },
-    { "34",	569250 },
-    { "35",	576250 },
-    { "36",     591250 },
-    { "39",	604250 },
-    { "40",	611250 },
-    { "41",	618250 },
-    { "42",	625250 },
-    { "43",	632250 },
-    { "44",	639250 },
-    { "45",	646250 },
-    { "46",	653250 },
-    { "47",	660250 },
-    { "48",	667250 },
-    { "49",	674250 },
-    { "50",	681250 },
-    { "51",	688250 },
-    { "52",	695250 },
-    { "53",	702250 },
-    { "54",	709250 },
-    { "55",	716250 },
-    { "56",	723250 },
-    { "57",	730250 },
-    { "58",	737250 },
-    { "59",	744250 },
-    { "60",	751250 },
-    { "61",	758250 },
-    { "62",	765250 },
-    { "63",	772250 },
-    { "64",	779250 },
-    { "65",	786250 },
-    { "66",	793250 },
-    { "67",	800250 },
-    { "68",	807250 },
-    { "69",	814250 },
-};
-
-/* --------------------------------------------------------------------- */
-/* europe                                                                */
-
-/* CCIR frequencies */
-
-#define FREQ_CCIR_I_III		\
-    { "E2",	  48250 },	\
-    { "E3",	  55250 },	\
-    { "E4",	  62250 },	\
-				\
-    { "S01",	  69250 },	\
-    { "S02",	  76250 },	\
-    { "S03",	  83250 },	\
-				\
-    { "E5",	 175250 },	\
-    { "E6",	 182250 },	\
-    { "E7",	 189250 },	\
-    { "E8",	 196250 },	\
-    { "E9",	 203250 },	\
-    { "E10",	 210250 },	\
-    { "E11",	 217250 },	\
-    { "E12",	 224250 }
-
-#define FREQ_CCIR_SL_SH		\
-    { "SE1",	 105250 },	\
-    { "SE2",	 112250 },	\
-    { "SE3",	 119250 },	\
-    { "SE4",	 126250 },	\
-    { "SE5",	 133250 },	\
-    { "SE6",	 140250 },	\
-    { "SE7",	 147250 },	\
-    { "SE8",	 154250 },	\
-    { "SE9",	 161250 },	\
-    { "SE10",    168250 },	\
-				\
-    { "SE11",    231250 },	\
-    { "SE12",    238250 },	\
-    { "SE13",    245250 },	\
-    { "SE14",    252250 },	\
-    { "SE15",    259250 },	\
-    { "SE16",    266250 },	\
-    { "SE17",    273250 },	\
-    { "SE18",    280250 },	\
-    { "SE19",    287250 },	\
-    { "SE20",    294250 }
-
-#define FREQ_CCIR_H	\
-    { "S21", 303250 },	\
-    { "S22", 311250 },	\
-    { "S23", 319250 },	\
-    { "S24", 327250 },	\
-    { "S25", 335250 },	\
-    { "S26", 343250 },	\
-    { "S27", 351250 },	\
-    { "S28", 359250 },	\
-    { "S29", 367250 },	\
-    { "S30", 375250 },	\
-    { "S31", 383250 },	\
-    { "S32", 391250 },	\
-    { "S33", 399250 },	\
-    { "S34", 407250 },	\
-    { "S35", 415250 },	\
-    { "S36", 423250 },	\
-    { "S37", 431250 },	\
-    { "S38", 439250 },	\
-    { "S39", 447250 },	\
-    { "S40", 455250 },	\
-    { "S41", 463250 }
-
-/* OIRT frequencies */
-
-#define FREQ_OIRT_I_III		\
-    { "R1",       49750 },	\
-    { "R2",       59250 },	\
-				\
-    { "R3",       77250 },	\
-    { "R4",       85250 },	\
-    { "R5",       93250 },	\
-				\
-    { "R6",	 175250 },	\
-    { "R7",	 183250 },	\
-    { "R8",	 191250 },	\
-    { "R9",	 199250 },	\
-    { "R10",	 207250 },	\
-    { "R11",	 215250 },	\
-    { "R12",	 223250 }
-
-#define FREQ_OIRT_SL_SH		\
-    { "SR1",	 111250 },	\
-    { "SR2",	 119250 },	\
-    { "SR3",	 127250 },	\
-    { "SR4",	 135250 },	\
-    { "SR5",	 143250 },	\
-    { "SR6",	 151250 },	\
-    { "SR7",	 159250 },	\
-    { "SR8",	 167250 },	\
-				\
-    { "SR11",    231250 },	\
-    { "SR12",    239250 },	\
-    { "SR13",    247250 },	\
-    { "SR14",    255250 },	\
-    { "SR15",    263250 },	\
-    { "SR16",    271250 },	\
-    { "SR17",    279250 },	\
-    { "SR18",    287250 },	\
-    { "SR19",    295250 }
-
-#define FREQ_UHF	\
-    { "21",  471250 },	\
-    { "22",  479250 },	\
-    { "23",  487250 },	\
-    { "24",  495250 },	\
-    { "25",  503250 },	\
-    { "26",  511250 },	\
-    { "27",  519250 },	\
-    { "28",  527250 },	\
-    { "29",  535250 },	\
-    { "30",  543250 },	\
-    { "31",  551250 },	\
-    { "32",  559250 },	\
-    { "33",  567250 },	\
-    { "34",  575250 },	\
-    { "35",  583250 },	\
-    { "36",  591250 },	\
-    { "37",  599250 },	\
-    { "38",  607250 },	\
-    { "39",  615250 },	\
-    { "40",  623250 },	\
-    { "41",  631250 },	\
-    { "42",  639250 },	\
-    { "43",  647250 },	\
-    { "44",  655250 },	\
-    { "45",  663250 },	\
-    { "46",  671250 },	\
-    { "47",  679250 },	\
-    { "48",  687250 },	\
-    { "49",  695250 },	\
-    { "50",  703250 },	\
-    { "51",  711250 },	\
-    { "52",  719250 },	\
-    { "53",  727250 },	\
-    { "54",  735250 },	\
-    { "55",  743250 },	\
-    { "56",  751250 },	\
-    { "57",  759250 },	\
-    { "58",  767250 },	\
-    { "59",  775250 },	\
-    { "60",  783250 },	\
-    { "61",  791250 },	\
-    { "62",  799250 },	\
-    { "63",  807250 },	\
-    { "64",  815250 },	\
-    { "65",  823250 },	\
-    { "66",  831250 },	\
-    { "67",  839250 },	\
-    { "68",  847250 },	\
-    { "69",  855250 }
-
-static const struct CHANLIST europe_west[] = {
-    FREQ_CCIR_I_III,
-    FREQ_CCIR_SL_SH,
-    FREQ_CCIR_H,
-    FREQ_UHF
-};
-
-static const struct CHANLIST europe_east[] = {
-    FREQ_OIRT_I_III,
-    FREQ_OIRT_SL_SH,
-    FREQ_CCIR_I_III,
-    FREQ_CCIR_SL_SH,
-    FREQ_CCIR_H,
-    FREQ_UHF
-};
-
-static const struct CHANLIST pal_italy[] = {
-    { "A",	 53750 },
-    { "B",	 62250 },
-    { "C",	 82250 },
-    { "D",	175250 },
-    { "E",	183750 },
-    { "F",	192250 },
-    { "G",	201250 },
-    { "H",	210250 },
-    { "H1",	217250 },
-    { "H2",	224250 },
-    FREQ_UHF
-};
-
-static const struct CHANLIST pal_ireland[] = {
-    { "0",    45750 },
-    { "1",    53750 },
-    { "2",    61750 },
-    { "3",   175250 },
-    { "4",   183250 },
-    { "5",   191250 },
-    { "6",   199250 },
-    { "7",   207250 },
-    { "8",   215250 },
-    FREQ_UHF,
-};
-
-static const struct CHANLIST secam_france[] = {
-    { "K01",    47750 },
-    { "K02",    55750 },
-    { "K03",    60500 },
-    { "K04",    63750 },
-    { "K05",   176000 },
-    { "K06",   184000 },
-    { "K07",   192000 },
-    { "K08",   200000 },
-    { "K09",   208000 },
-    { "K10",   216000 },
-    { "KB",    116750 },
-    { "KC",    128750 },
-    { "KD",    140750 },
-    { "KE",    159750 },
-    { "KF",    164750 },
-    { "KG",    176750 },
-    { "KH",    188750 },
-    { "KI",    200750 },
-    { "KJ",    212750 },
-    { "KK",    224750 },
-    { "KL",    236750 },
-    { "KM",    248750 },
-    { "KN",    260750 },
-    { "KO",    272750 },
-    { "KP",    284750 },
-    { "KQ",    296750 },
-    { "H01",   303250 },
-    { "H02",   311250 },
-    { "H03",   319250 },
-    { "H04",   327250 },
-    { "H05",   335250 },
-    { "H06",   343250 },
-    { "H07",   351250 },
-    { "H08",   359250 },
-    { "H09",   367250 },
-    { "H10",   375250 },
-    { "H11",   383250 },
-    { "H12",   391250 },
-    { "H13",   399250 },
-    { "H14",   407250 },
-    { "H15",   415250 },
-    { "H16",   423250 },
-    { "H17",   431250 },
-    { "H18",   439250 },
-    { "H19",   447250 },
-    FREQ_UHF,
-};
-
-/* --------------------------------------------------------------------- */
-
-static const struct CHANLIST pal_newzealand[] = {
-    { "1", 	  45250 }, 
-    { "2",	  55250 }, 
-    { "3",	  62250 },
-    { "4",	 175250 },
-    { "5",	 182250 },
-    { "6",	 189250 },
-    { "7",	 196250 },
-    { "8",	 203250 },
-    { "9",	 210250 },
-    { "10",	 217250 },
-    { "11",	 224250 },
-    FREQ_UHF,
-};
-
-/* --------------------------------------------------------------------- */
-
-/* China broadcast */
-static const struct CHANLIST pal_bcast_cn[] = {
-    { "1",	49750 },
-    { "2",	57750 },
-    { "3",	65750 },
-    { "4",	77250 },
-    { "5",	85250 },
-    { "6",	112250 },
-    { "7",	120250 },
-    { "8",	128250 },
-    { "9",	136250 },
-    { "10",	144250 },
-    { "11",	152250 },
-    { "12",	160250 },
-    { "13",	168250 },
-    { "14",	176250 },
-    { "15",	184250 },
-    { "16",	192250 },
-    { "17",	200250 },
-    { "18",	208250 },
-    { "19",	216250 },
-    { "20",	224250 },
-    { "21",	232250 },
-    { "22",	240250 },
-    { "23",	248250 },
-    { "24",	256250 },
-    { "25",	264250 },
-    { "26",	272250 },
-    { "27",	280250 },
-    { "28",	288250 },
-    { "29",	296250 },
-    { "30",	304250 },
-    { "31",	312250 },
-    { "32",	320250 },
-    { "33",	328250 },
-    { "34",	336250 },
-    { "35",	344250 },
-    { "36",	352250 },
-    { "37",	360250 },
-    { "38",	368250 },
-    { "39",	376250 },
-    { "40",	384250 },
-    { "41",	392250 },
-    { "42",	400250 },
-    { "43",	408250 },
-    { "44",	416250 },
-    { "45",	424250 },
-    { "46",	432250 },
-    { "47",	440250 },
-    { "48",	448250 },
-    { "49",	456250 },
-    { "50",	463250 },
-    { "51",	471250 },
-    { "52",	479250 },
-    { "53",	487250 },
-    { "54",	495250 },
-    { "55",	503250 },
-    { "56",	511250 },
-    { "57",	519250 },
-    { "58",	527250 },
-    { "59",	535250 },
-    { "60",	543250 },
-    { "61",	551250 },
-    { "62",	559250 },
-    { "63",	607250 },
-    { "64",	615250 },
-    { "65",	623250 },
-    { "66",	631250 },
-    { "67",	639250 },
-    { "68",	647250 },
-    { "69",	655250 },
-    { "70",	663250 },
-    { "71",	671250 },
-    { "72",	679250 },
-    { "73",	687250 },
-    { "74",	695250 },
-    { "75",	703250 },
-    { "76",	711250 },
-    { "77",	719250 },
-    { "78",	727250 },
-    { "79",	735250 },
-    { "80",	743250 },
-    { "81",	751250 },
-    { "82",	759250 },
-    { "83",	767250 },
-    { "84",	775250 },
-    { "85",	783250 },
-    { "86",	791250 },
-    { "87",	799250 },
-    { "88",	807250 },
-    { "89",	815250 },
-    { "90",	823250 },
-    { "91",	831250 },
-    { "92",	839250 },
-    { "93",	847250 },
-    { "94",	855250 },
-};
-
-/* --------------------------------------------------------------------- */
-/* South Africa Broadcast */
-
-static const struct CHANLIST pal_bcast_za[] ={
-    { "1", 175250 },
-    { "2", 183250 },
-    { "3", 191250 },
-    { "4", 199250 },
-    { "5", 207250 },
-    { "6", 215250 },
-    { "7", 223250 },
-    { "8", 231250 },
-    FREQ_UHF
-};
-
-/* --------------------------------------------------------------------- */
-
-static const struct CHANLIST argentina[] = {
-    { "001",   56250 },
-    { "002",   62250 },
-    { "003",   68250 },
-    { "004",   78250 },
-    { "005",   84250 },
-    { "006",  176250 },
-    { "007",  182250 },
-    { "008",  188250 },
-    { "009",  194250 },
-    { "010",  200250 },
-    { "011",  206250 },
-    { "012",  212250 },
-    { "013",  122250 },
-    { "014",  128250 },
-    { "015",  134250 },
-    { "016",  140250 },
-    { "017",  146250 },
-    { "018",  152250 },
-    { "019",  158250 },
-    { "020",  164250 },
-    { "021",  170250 },
-    { "022",  218250 },
-    { "023",  224250 },
-    { "024",  230250 },
-    { "025",  236250 },
-    { "026",  242250 },
-    { "027",  248250 },
-    { "028",  254250 },
-    { "029",  260250 },
-    { "030",  266250 },
-    { "031",  272250 },
-    { "032",  278250 },
-    { "033",  284250 },
-    { "034",  290250 },
-    { "035",  296250 },
-    { "036",  302250 },
-    { "037",  308250 },
-    { "038",  314250 },
-    { "039",  320250 },
-    { "040",  326250 },
-    { "041",  332250 },
-    { "042",  338250 },
-    { "043",  344250 },
-    { "044",  350250 },
-    { "045",  356250 },
-    { "046",  362250 },
-    { "047",  368250 },
-    { "048",  374250 },
-    { "049",  380250 },
-    { "050",  386250 },
-    { "051",  392250 },
-    { "052",  398250 },
-    { "053",  404250 },
-    { "054",  410250 },
-    { "055",  416250 },
-    { "056",  422250 },
-    { "057",  428250 },
-    { "058",  434250 },
-    { "059",  440250 },
-    { "060",  446250 },
-    { "061",  452250 },
-    { "062",  458250 },
-    { "063",  464250 },
-    { "064",  470250 },
-    { "065",  476250 },
-    { "066",  482250 },
-    { "067",  488250 },
-    { "068",  494250 },
-    { "069",  500250 },
-    { "070",  506250 },
-    { "071",  512250 },
-    { "072",  518250 },
-    { "073",  524250 },
-    { "074",  530250 },
-    { "075",  536250 },
-    { "076",  542250 },
-    { "077",  548250 },
-    { "078",  554250 },
-    { "079",  560250 },
-    { "080",  566250 },
-    { "081",  572250 },
-    { "082",  578250 },
-    { "083",  584250 },
-    { "084",  590250 },
-    { "085",  596250 },
-    { "086",  602250 },
-    { "087",  608250 },
-    { "088",  614250 },
-    { "089",  620250 },
-    { "090",  626250 },
-    { "091",  632250 },
-    { "092",  638250 },
-    { "093",  644250 },
-};
-
-/* --------------------------------------------------------------------- */
-
-static const struct CHANLIST russia[] = {
-    {"1",     49750 },
-    {"2",     59250 },
-    {"3",     77250 },
-    {"4",     85250 },
-    {"5",     93250 },
-    {"SK1",   111250 },
-    {"SK2",   119250 },
-    {"SK3",   127250 },
-    {"SK4",   135250 },
-    {"SK5",   143250 },
-    {"SK6",   151250 },
-    {"SK7",   159250 },
-    {"SK8",   167250 },
-    {"6",     175250 },
-    {"7",     183250 },
-    {"8",     191250 },
-    {"9",     199250 },
-    {"10",    207250 },
-    {"11",    215250 },
-    {"12",    223250 },
-    {"SK11",  231250 },
-    {"SK12",  239250 },
-    {"SK13",  247250 },
-    {"SK14",  255250 },
-    {"SK15",  263250 },
-    {"SK16",  271250 },
-    {"SK17",  279250 },
-    {"SK18",  287250 },
-    {"S19",   295250 },
-    {"S20",   303250 },
-    {"S21",   311250 },
-    {"S22",   319250 },
-    {"S23",   327250 },
-    {"S24",   335250 },
-    {"S25",   343250 },
-    {"S26",   351250 },
-    {"S27",   359250 },
-    {"S28",   367250 },
-    {"S29",   375250 },
-    {"S30",   383250 },
-    {"S31",   391250 },
-    {"S32",   399250 },
-    {"S33",   407250 },
-    {"S34",   415250 },
-    {"S35",   423250 },
-    {"S36",   431250 },
-    {"S37",   439250 },
-    {"S38",   447250 },
-    {"S39",   455250 },
-    {"S40",   463250 },
-    {"21",    471250 },
-    {"22",    479250 },
-    {"23",    487250 },
-    {"24",    495250 },
-    {"25",    503250 },
-    {"26",    511250 },
-    {"27",    519250 },
-    {"28",    527250 },
-    {"29",    535250 },
-    {"30",    543250 },
-    {"31",    551250 },
-    {"32",    559250 },
-    {"33",    567250 },
-    {"34",    575250 },
-    {"35",    583250 },
-    {"36",    591250 },
-    {"37",    599250 },
-    {"38",    607250 },
-    {"39",    615250 },
-    {"40",    623250 },
-    {"41",    631250 },
-    {"42",    639250 },
-    {"43",    647250 },
-    {"44",    655250 },
-    {"45",    663250 },
-    {"46",    671250 },
-    {"47",    679250 },
-    {"48",    687250 },
-    {"49",    695250 },
-    {"50",    703250 },
-    {"51",    711250 },
-    {"52",    719250 },
-    {"53",    727250 },
-    {"54",    735250 },
-    {"55",    743250 },
-    {"56",    751250 },
-    {"57",    759250 },
-    {"58",    767250 },
-    {"59",    775250 },
-    {"60",    783250 },
-    {"61",    791250 },
-    {"62",    799250 },
-    {"63",    807250 },
-    {"64",    815250 },
-    {"65",    523250 },
-    {"66",    831250 },
-    {"67",    839250 },
-    {"68",    847250 },
-    {"69",    855250 },
-};
-/* --------------------------------------------------------------------- */
-
-const struct CHANLISTS chanlists[] = {
-    { "us-bcast",         ntsc_bcast,        CHAN_COUNT(ntsc_bcast)        },
-    { "us-cable",         ntsc_cable,        CHAN_COUNT(ntsc_cable)        },
-    { "us-cable-hrc",     ntsc_hrc,          CHAN_COUNT(ntsc_hrc)          },
-    { "japan-bcast",      ntsc_bcast_jp,     CHAN_COUNT(ntsc_bcast_jp)     },
-    { "japan-cable",      ntsc_cable_jp,     CHAN_COUNT(ntsc_cable_jp)     },
-    { "europe-west",      europe_west,       CHAN_COUNT(europe_west)       },
-    { "europe-east",      europe_east,       CHAN_COUNT(europe_east)       },
-    { "italy",	          pal_italy,         CHAN_COUNT(pal_italy)         },
-    { "newzealand",       pal_newzealand,    CHAN_COUNT(pal_newzealand)    },
-    { "australia",        pal_australia,     CHAN_COUNT(pal_australia)     },
-    { "ireland",          pal_ireland,       CHAN_COUNT(pal_ireland)       },
-    { "france",           secam_france,      CHAN_COUNT(secam_france)      },
-    { "china-bcast",      pal_bcast_cn,      CHAN_COUNT(pal_bcast_cn)      },
-    { "southafrica",      pal_bcast_za,      CHAN_COUNT(pal_bcast_za)      },
-    { "argentina",        argentina,         CHAN_COUNT(argentina)         },
-    { "russia",           russia,            CHAN_COUNT(russia)            },
-    { NULL, NULL, 0 } /* EOF */
-};
-
-int                chantab   = 5;
-const struct CHANLIST *chanlist  = europe_west;
-int                chancount = CHAN_COUNT(europe_west);
--- a/libmpdemux/frequencies.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Worldwide channel/frequency list
- *
- * Nathan Laredo (laredo@broked.net)
- *
- * Frequencies are given in kHz 
- */
-#define NTSC_AUDIO_CARRIER	4500
-#define PAL_AUDIO_CARRIER_I	6000
-#define PAL_AUDIO_CARRIER_BGHN	5500
-#define PAL_AUDIO_CARRIER_MN	4500
-#define PAL_AUDIO_CARRIER_D	6500
-#define SEACAM_AUDIO_DKK1L	6500
-#define SEACAM_AUDIO_BG		5500
-/* NICAM 728 32-kHz, 14-bit digital stereo audio is transmitted in 1ms frames
-   containing 8 bits frame sync, 5 bits control, 11 bits additional data, and
-   704 bits audio data.  The bit rate is reduced by transmitting only 10 bits
-   plus parity of each 14 bit sample, the largest sample in a frame determines
-   which 10 bits are transmitted.  The parity bits for audio samples also 
-   specify the scaling factor used for that channel during that frame.  The
-   companeded audio data is interleaved to reduce the influence of dropouts
-   and the whole frame except for sync bits is scrambled for spectrum shaping.
-   Data is modulated using QPSK, at below following subcarrier freqs */
-#define NICAM728_PAL_BGH	5850
-#define NICAM728_PAL_I		6552
-
-/* COMPREHENSIVE LIST OF FORMAT BY COUNTRY
-   (M) NTSC used in:
-	Antigua, Aruba, Bahamas, Barbados, Belize, Bermuda, Bolivia, Burma,
-	Canada, Chile, Colombia, Costa Rica, Cuba, Curacao, Dominican Republic,
-	Ecuador, El Salvador, Guam Guatemala, Honduras, Jamaica, Japan,
-	South Korea, Mexico, Montserrat, Myanmar, Nicaragua, Panama, Peru,
-	Philippines, Puerto Rico, St Christopher and Nevis, Samoa, Suriname,
-	Taiwan, Trinidad/Tobago, United States, Venezuela, Virgin Islands
-   (B) PAL used in:
-	Albania, Algeria, Australia, Austria, Bahrain, Bangladesh, Belgium,
-	Bosnia-Herzegovinia, Brunei Darussalam, Cambodia, Cameroon, Croatia,
-	Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, Finland, Germany,
-	Ghana, Gibraltar, Greenland, Iceland, India, Indonesia, Israel, Italy,
-	Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysa, Maldives,
-	Malta, Nepal, Netherlands, New Zeland, Nigeria, Norway, Oman, Pakistan,
-	Papua New Guinea, Portugal, Qatar, Sao Tome and Principe, Saudi Arabia,
-	Seychelles, Sierra Leone, Singapore, Slovenia, Somali, Spain,
-	Sri Lanka, Sudan, Swaziland, Sweden, Switzeland, Syria, Thailand,
-	Tunisia, Turkey, Uganda, United Arab Emirates, Yemen
-   (N) PAL used in: (Combination N = 4.5MHz audio carrier, 3.58MHz burst)
-	Argentina (Combination N), Paraguay, Uruguay
-   (M) PAL (525/60, 3.57MHz burst) used in:
-	Brazil
-   (G) PAL used in:
-	Albania, Algeria, Austria, Bahrain, Bosnia/Herzegovinia, Cambodia,
-	Cameroon, Croatia, Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea,
-	Finland, Germany, Gibraltar, Greenland, Iceland, Israel, Italy, Jordan,
-	Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysia, Monaco,
-	Mozambique, Netherlands, New Zealand, Norway, Oman, Pakistan,
-	Papa New Guinea, Portugal, Qatar, Romania, Sierra Leone, Singapore,
-	Slovenia, Somalia, Spain, Sri Lanka, Sudan, Swaziland, Sweeden,
-	Switzerland, Syria, Thailand, Tunisia, Turkey, United Arab Emirates,
-	Yemen, Zambia, Zimbabwe
-   (D) PAL used in:
-	China, North Korea, Romania, Czech Republic
-   (H) PAL used in:
-	Belgium
-   (I) PAL used in:
-	Angola, Botswana, Gambia, Guinea-Bissau, Hong Kong, Ireland, Lesotho,
-	Malawi, Nambia, Nigeria, South Africa, Tanzania, United Kingdom,
-	Zanzibar
-   (B) SECAM used in:
-	Djibouti, Greece, Iran, Iraq, Lebanon, Mali, Mauritania, Mauritus,
-	Morocco
-   (D) SECAM used in:
-	Afghanistan, Armenia, Azerbaijan, Belarus, Bulgaria,
-	Estonia, Georgia, Hungary, Zazakhstan, Lithuania, Mongolia, Moldova,
-	Russia, Slovak Republic, Ukraine, Vietnam
-   (G) SECAM used in:
-	Greecem Iran, Iraq, Mali, Mauritus, Morocco, Saudi Arabia
-   (K) SECAM used in:
-	Armenia, Azerbaijan, Bulgaria, Estonia, Georgia,
-	Hungary, Kazakhstan, Lithuania, Madagascar, Moldova, Poland, Russia,
-	Slovak Republic, Ukraine, Vietnam
-   (K1) SECAM used in:
-	Benin, Burkina Faso, Burundi, Chad, Cape Verde, Central African
-	Republic, Comoros, Congo, Gabon, Madagascar, Niger, Rwanda, Senegal,
-	Togo, Zaire
-   (L) SECAM used in:
-	France
-*/
-
-/* --------------------------------------------------------------------- */
-
-struct CHANLIST {
-    char  name[8];
-    int   freq;
-};
-
-struct CHANLISTS {
-    const char             *name;
-    const struct CHANLIST  *list;
-    int                    count;
-};
-
-#define CHAN_COUNT(x) (sizeof(x)/sizeof(struct CHANLIST))
-
-/* --------------------------------------------------------------------- */
-
-extern const struct CHANLISTS   chanlists[];
-//extern struct STRTAB chanlist_names[];
-
-extern int                chantab;
-extern const struct CHANLIST *chanlist;
-extern int                chancount;
--- a/libmpdemux/http.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,948 +0,0 @@
-/* 
- * HTTP Helper
- * by Bertrand Baudet <bertrand_baudet@yahoo.com>
- * (C) 2001, MPlayer team.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-
-#include "http.h"
-#include "url.h"
-#include "mp_msg.h"
-
-#include "stream.h"
-#include "demuxer.h"
-#include "network.h"
-#include "help_mp.h"
-
-
-extern mime_struct_t mime_type_table[];
-extern int stream_cache_size;
-extern int network_bandwidth;
-
-extern int http_seek(stream_t *stream, off_t pos);
-
-typedef struct {
-  unsigned metaint;
-  unsigned metapos;
-  int is_ultravox;
-} scast_data_t;
-
-/**
- * \brief first read any data from sc->buffer then from fd
- * \param fd file descriptor to read data from
- * \param buffer buffer to read into
- * \param len how many bytes to read
- * \param sc streaming control containing buffer to read from first
- * \return len unless there is a read error or eof
- */
-static unsigned my_read(int fd, char *buffer, int len, streaming_ctrl_t *sc) {
-  unsigned pos = 0;
-  unsigned cp_len = sc->buffer_size - sc->buffer_pos;
-  if (cp_len > len)
-    cp_len = len;
-  memcpy(buffer, &sc->buffer[sc->buffer_pos], cp_len);
-  sc->buffer_pos += cp_len;
-  pos += cp_len;
-  while (pos < len) {
-    int ret = recv(fd, &buffer[pos], len - pos, 0);
-    if (ret <= 0)
-      break;
-    pos += ret;
-  }
-  return pos;
-}
-
-/**
- * \brief read and process (i.e. discard *g*) a block of ultravox metadata
- * \param fd file descriptor to read from
- * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd
- * \return number of real data before next metadata block starts or 0 on error
- */
-static unsigned uvox_meta_read(int fd, streaming_ctrl_t *sc) {
-  unsigned metaint;
-  unsigned char info[6] = {0, 0, 0, 0, 0, 0};
-  int info_read;
-  do {
-    info_read = my_read(fd, info, 1, sc);
-    if (info[0] == 0x00)
-      info_read = my_read(fd, info, 6, sc);
-    else
-      info_read += my_read(fd, &info[1], 5, sc);
-    if (info_read != 6) // read error or eof
-      return 0;
-    // sync byte and reserved flags
-    if (info[0] != 0x5a || (info[1] & 0xfc) != 0x00) {
-      mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid or unknown uvox metadata\n");
-      return 0;
-    }
-    if (info[1] & 0x01)
-      mp_msg(MSGT_DEMUXER, MSGL_WARN, "Encrypted ultravox data\n");
-    metaint = info[4] << 8 | info[5];
-    if ((info[3] & 0xf) < 0x07) { // discard any metadata nonsense
-      char *metabuf = malloc(metaint);
-      my_read(fd, metabuf, metaint, sc);
-      free(metabuf);
-    }
-  } while ((info[3] & 0xf) < 0x07);
-  return metaint;
-}
-
-/**
- * \brief read one scast meta data entry and print it
- * \param fd file descriptor to read from
- * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd
- */
-static void scast_meta_read(int fd, streaming_ctrl_t *sc) {
-  unsigned char tmp = 0;
-  unsigned metalen;
-  my_read(fd, &tmp, 1, sc);
-  metalen = tmp * 16;
-  if (metalen > 0) {
-    char *info = malloc(metalen + 1);
-    unsigned nlen = my_read(fd, info, metalen, sc);
-    info[nlen] = 0;
-    mp_msg(MSGT_DEMUXER, MSGL_INFO, "\nICY Info: %s\n", info);
-    free(info);
-  }
-}
-
-/**
- * \brief read data from scast/ultravox stream without any metadata
- * \param fd file descriptor to read from
- * \param buffer buffer to read data into
- * \param size number of bytes to read
- * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd
- */
-static int scast_streaming_read(int fd, char *buffer, int size,
-                                streaming_ctrl_t *sc) {
-  scast_data_t *sd = (scast_data_t *)sc->data;
-  unsigned block, ret;
-  unsigned done = 0;
-
-  // first read remaining data up to next metadata
-  block = sd->metaint - sd->metapos;
-  if (block > size)
-    block = size;
-  ret = my_read(fd, buffer, block, sc);
-  sd->metapos += ret;
-  done += ret;
-  if (ret != block) // read problems or eof
-    size = done;
-
-  while (done < size) { // now comes the metadata
-    if (sd->is_ultravox)
-    {
-      sd->metaint = uvox_meta_read(fd, sc);
-      if (!sd->metaint)
-        size = done;
-    }
-    else
-      scast_meta_read(fd, sc); // read and display metadata
-    sd->metapos = 0;
-    block = size - done;
-    if (block > sd->metaint)
-      block = sd->metaint;
-    ret = my_read(fd, &buffer[done], block, sc);
-    sd->metapos += ret;
-    done += ret;
-    if (ret != block) // read problems or eof
-      size = done;
-  }
-  return done;
-}
-
-static int scast_streaming_start(stream_t *stream) {
-  int metaint;
-  scast_data_t *scast_data;
-  HTTP_header_t *http_hdr = stream->streaming_ctrl->data;
-  int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0;
-  if (!stream || stream->fd < 0 || !http_hdr)
-    return -1;
-  if (is_ultravox)
-    metaint = 0;
-  else {
-    metaint = atoi(http_get_field(http_hdr, "Icy-MetaInt"));
-    if (metaint <= 0)
-      return -1;
-  }
-  stream->streaming_ctrl->buffer = malloc(http_hdr->body_size);
-  stream->streaming_ctrl->buffer_size = http_hdr->body_size;
-  stream->streaming_ctrl->buffer_pos = 0;
-  memcpy(stream->streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size);
-  scast_data = malloc(sizeof(scast_data_t));
-  scast_data->metaint = metaint;
-  scast_data->metapos = 0;
-  scast_data->is_ultravox = is_ultravox;
-  http_free(http_hdr);
-  stream->streaming_ctrl->data = scast_data;
-  stream->streaming_ctrl->streaming_read = scast_streaming_read;
-  stream->streaming_ctrl->streaming_seek = NULL;
-  stream->streaming_ctrl->prebuffer_size = 64 * 1024; // 64 KBytes
-  stream->streaming_ctrl->buffering = 1;
-  stream->streaming_ctrl->status = streaming_playing_e;
-  return 0;
-}
-
-static int nop_streaming_start( stream_t *stream ) {
-	HTTP_header_t *http_hdr = NULL;
-	char *next_url=NULL;
-	URL_t *rd_url=NULL;
-	int fd,ret;
-	if( stream==NULL ) return -1;
-
-	fd = stream->fd;
-	if( fd<0 ) {
-		fd = http_send_request( stream->streaming_ctrl->url, 0 ); 
-		if( fd<0 ) return -1;
-		http_hdr = http_read_response( fd );
-		if( http_hdr==NULL ) return -1;
-
-		switch( http_hdr->status_code ) {
-			case 200: // OK
-				mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") );
-				mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") );
-				if( http_hdr->body_size>0 ) {
-					if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
-						http_free( http_hdr );
-						return -1;
-					}
-				}
-				break;
-			// Redirect
-			case 301: // Permanently
-			case 302: // Temporarily
-				ret=-1;
-				next_url = http_get_field( http_hdr, "Location" );
-
-				if (next_url != NULL)
-					rd_url=url_new(next_url);
-
-				if (next_url != NULL && rd_url != NULL) {
-					mp_msg(MSGT_NETWORK,MSGL_STATUS,"Redirected: Using this url instead %s\n",next_url);
-							stream->streaming_ctrl->url=check4proxies(rd_url);
-					ret=nop_streaming_start(stream); //recursively get streaming started 
-				} else {
-					mp_msg(MSGT_NETWORK,MSGL_ERR,"Redirection failed\n");
-					closesocket( fd );
-					fd = -1;
-				}
-				return ret;
-				break;
-			case 401: //Authorization required
-			case 403: //Forbidden
-			case 404: //Not found
-			case 500: //Server Error
-			default:
-				mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned code %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase );
-				closesocket( fd );
-				fd = -1;
-				return -1;
-				break;
-		}
-		stream->fd = fd;
-	} else {
-		http_hdr = (HTTP_header_t*)stream->streaming_ctrl->data;
-		if( http_hdr->body_size>0 ) {
-			if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
-				http_free( http_hdr );
-				stream->streaming_ctrl->data = NULL;
-				return -1;
-			}
-		}
-	}
-
-	if( http_hdr ) {
-		http_free( http_hdr );
-		stream->streaming_ctrl->data = NULL;
-	}
-
-	stream->streaming_ctrl->streaming_read = nop_streaming_read;
-	stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
-	stream->streaming_ctrl->prebuffer_size = 64*1024; // 64 KBytes
-	stream->streaming_ctrl->buffering = 1;
-	stream->streaming_ctrl->status = streaming_playing_e;
-	return 0;
-}
-
-HTTP_header_t *
-http_new_header(void) {
-	HTTP_header_t *http_hdr;
-
-	http_hdr = malloc(sizeof(HTTP_header_t));
-	if( http_hdr==NULL ) return NULL;
-	memset( http_hdr, 0, sizeof(HTTP_header_t) );
-
-	return http_hdr;
-}
-
-void
-http_free( HTTP_header_t *http_hdr ) {
-	HTTP_field_t *field, *field2free;
-	if( http_hdr==NULL ) return;
-	if( http_hdr->protocol!=NULL ) free( http_hdr->protocol );
-	if( http_hdr->uri!=NULL ) free( http_hdr->uri );
-	if( http_hdr->reason_phrase!=NULL ) free( http_hdr->reason_phrase );
-	if( http_hdr->field_search!=NULL ) free( http_hdr->field_search );
-	if( http_hdr->method!=NULL ) free( http_hdr->method );
-	if( http_hdr->buffer!=NULL ) free( http_hdr->buffer );
-	field = http_hdr->first_field;
-	while( field!=NULL ) {
-		field2free = field;
-		if (field->field_name)
-		  free(field->field_name);
-		field = field->next;
-		free( field2free );
-	}
-	free( http_hdr );
-	http_hdr = NULL;
-}
-
-int
-http_response_append( HTTP_header_t *http_hdr, char *response, int length ) {
-	if( http_hdr==NULL || response==NULL || length<0 ) return -1;
-
-	if( (unsigned)length > SIZE_MAX - http_hdr->buffer_size - 1) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Bad size in memory (re)allocation\n");
-		return -1;
-	}
-	http_hdr->buffer = (char*)realloc( http_hdr->buffer, http_hdr->buffer_size+length+1 );
-	if( http_hdr->buffer==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory (re)allocation failed\n");
-		return -1;
-	}
-	memcpy( http_hdr->buffer+http_hdr->buffer_size, response, length );
-	http_hdr->buffer_size += length;
-	http_hdr->buffer[http_hdr->buffer_size]=0; // close the string!
-	return http_hdr->buffer_size;
-}
-
-int
-http_is_header_entire( HTTP_header_t *http_hdr ) {
-	if( http_hdr==NULL ) return -1;
-	if( http_hdr->buffer==NULL ) return 0; // empty
-	
-	if( strstr(http_hdr->buffer, "\r\n\r\n")==NULL &&
-	    strstr(http_hdr->buffer, "\n\n")==NULL ) return 0;
-	return 1;
-}
-
-int
-http_response_parse( HTTP_header_t *http_hdr ) {
-	char *hdr_ptr, *ptr;
-	char *field=NULL;
-	int pos_hdr_sep, hdr_sep_len;
-	size_t len;
-	if( http_hdr==NULL ) return -1;
-	if( http_hdr->is_parsed ) return 0;
-
-	// Get the protocol
-	hdr_ptr = strstr( http_hdr->buffer, " " );
-	if( hdr_ptr==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. No space separator found.\n");
-		return -1;
-	}
-	len = hdr_ptr-http_hdr->buffer;
-	http_hdr->protocol = malloc(len+1);
-	if( http_hdr->protocol==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		return -1;
-	}
-	strncpy( http_hdr->protocol, http_hdr->buffer, len );
-	http_hdr->protocol[len]='\0';
-	if( !strncasecmp( http_hdr->protocol, "HTTP", 4) ) {
-		if( sscanf( http_hdr->protocol+5,"1.%d", &(http_hdr->http_minor_version) )!=1 ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get HTTP minor version.\n");
-			return -1;
-		}
-	}
-
-	// Get the status code
-	if( sscanf( ++hdr_ptr, "%d", &(http_hdr->status_code) )!=1 ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get status code.\n");
-		return -1;
-	}
-	hdr_ptr += 4;
-
-	// Get the reason phrase
-	ptr = strstr( hdr_ptr, "\n" );
-	if( hdr_ptr==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get the reason phrase.\n");
-		return -1;
-	}
-	len = ptr-hdr_ptr;
-	http_hdr->reason_phrase = malloc(len+1);
-	if( http_hdr->reason_phrase==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		return -1;
-	}
-	strncpy( http_hdr->reason_phrase, hdr_ptr, len );
-	if( http_hdr->reason_phrase[len-1]=='\r' ) {
-		len--;
-	}
-	http_hdr->reason_phrase[len]='\0';
-
-	// Set the position of the header separator: \r\n\r\n
-	hdr_sep_len = 4;
-	ptr = strstr( http_hdr->buffer, "\r\n\r\n" );
-	if( ptr==NULL ) {
-		ptr = strstr( http_hdr->buffer, "\n\n" );
-		if( ptr==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"Header may be incomplete. No CRLF CRLF found.\n");
-			return -1;
-		}
-		hdr_sep_len = 2;
-	}
-	pos_hdr_sep = ptr-http_hdr->buffer;
-
-	// Point to the first line after the method line.
-	hdr_ptr = strstr( http_hdr->buffer, "\n" )+1;
-	do {
-		ptr = hdr_ptr;
-		while( *ptr!='\r' && *ptr!='\n' ) ptr++;
-		len = ptr-hdr_ptr;
-		if( len==0 ) break;
-		field = (char*)realloc(field, len+1);
-		if( field==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n");
-			return -1;
-		}
-		strncpy( field, hdr_ptr, len );
-		field[len]='\0';
-		http_set_field( http_hdr, field );
-		hdr_ptr = ptr+((*ptr=='\r')?2:1);
-	} while( hdr_ptr<(http_hdr->buffer+pos_hdr_sep) );
-	
-	if( field!=NULL ) free( field );
-
-	if( pos_hdr_sep+hdr_sep_len<http_hdr->buffer_size ) {
-		// Response has data!
-		http_hdr->body = http_hdr->buffer+pos_hdr_sep+hdr_sep_len;
-		http_hdr->body_size = http_hdr->buffer_size-(pos_hdr_sep+hdr_sep_len);
-	}
-
-	http_hdr->is_parsed = 1;
-	return 0;
-}
-
-char *
-http_build_request( HTTP_header_t *http_hdr ) {
-	char *ptr, *uri=NULL;
-	int len;
-	HTTP_field_t *field;
-	if( http_hdr==NULL ) return NULL;
-
-	if( http_hdr->method==NULL ) http_set_method( http_hdr, "GET");
-	if( http_hdr->uri==NULL ) http_set_uri( http_hdr, "/");
-	else {
-		uri = malloc(strlen(http_hdr->uri) + 1);
-		if( uri==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n");
-			return NULL;
-		}
-		strcpy(uri,http_hdr->uri);
-	}
-
-	//**** Compute the request length
-	// Add the Method line
-	len = strlen(http_hdr->method)+strlen(uri)+12;
-	// Add the fields
-	field = http_hdr->first_field; 
-	while( field!=NULL ) {
-		len += strlen(field->field_name)+2;
-		field = field->next;
-	}
-	// Add the CRLF
-	len += 2;
-	// Add the body
-	if( http_hdr->body!=NULL ) {
-		len += http_hdr->body_size;
-	}
-	// Free the buffer if it was previously used
-	if( http_hdr->buffer!=NULL ) {
-		free( http_hdr->buffer );
-		http_hdr->buffer = NULL;
-	}
-	http_hdr->buffer = malloc(len+1);
-	if( http_hdr->buffer==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n");
-		return NULL;
-	}
-	http_hdr->buffer_size = len;
-
-	//*** Building the request
-	ptr = http_hdr->buffer;
-	// Add the method line
-	ptr += sprintf( ptr, "%s %s HTTP/1.%d\r\n", http_hdr->method, uri, http_hdr->http_minor_version );
-	field = http_hdr->first_field;
-	// Add the field
-	while( field!=NULL ) {
-		ptr += sprintf( ptr, "%s\r\n", field->field_name );
-		field = field->next;
-	}
-	ptr += sprintf( ptr, "\r\n" );
-	// Add the body
-	if( http_hdr->body!=NULL ) {
-		memcpy( ptr, http_hdr->body, http_hdr->body_size );
-	}
-
-	if( uri ) free( uri );
-	return http_hdr->buffer;	
-}
-
-char *
-http_get_field( HTTP_header_t *http_hdr, const char *field_name ) {
-	if( http_hdr==NULL || field_name==NULL ) return NULL;
-	http_hdr->field_search_pos = http_hdr->first_field;
-	http_hdr->field_search = (char*)realloc( http_hdr->field_search, strlen(field_name)+1 );
-	if( http_hdr->field_search==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		return NULL;
-	}
-	strcpy( http_hdr->field_search, field_name );
-	return http_get_next_field( http_hdr );
-}
-
-char *
-http_get_next_field( HTTP_header_t *http_hdr ) {
-	char *ptr;
-	HTTP_field_t *field;
-	if( http_hdr==NULL ) return NULL;
-
-	field = http_hdr->field_search_pos;
-	while( field!=NULL ) { 
-		ptr = strstr( field->field_name, ":" );
-		if( ptr==NULL ) return NULL;
-		if( !strncasecmp( field->field_name, http_hdr->field_search, ptr-(field->field_name) ) ) {
-			ptr++;	// Skip the column
-			while( ptr[0]==' ' ) ptr++; // Skip the spaces if there is some
-			http_hdr->field_search_pos = field->next;
-			return ptr;	// return the value without the field name
-		}
-		field = field->next;
-	}
-	return NULL;
-}
-
-void
-http_set_field( HTTP_header_t *http_hdr, const char *field_name ) {
-	HTTP_field_t *new_field;
-	if( http_hdr==NULL || field_name==NULL ) return;
-
-	new_field = malloc(sizeof(HTTP_field_t));
-	if( new_field==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		return;
-	}
-	new_field->next = NULL;
-	new_field->field_name = malloc(strlen(field_name)+1);
-	if( new_field->field_name==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		return;
-	}
-	strcpy( new_field->field_name, field_name );
-
-	if( http_hdr->last_field==NULL ) {
-		http_hdr->first_field = new_field;
-	} else {
-		http_hdr->last_field->next = new_field;
-	}
-	http_hdr->last_field = new_field;
-	http_hdr->field_nb++;
-}
-
-void
-http_set_method( HTTP_header_t *http_hdr, const char *method ) {
-	if( http_hdr==NULL || method==NULL ) return;
-
-	http_hdr->method = malloc(strlen(method)+1);
-	if( http_hdr->method==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		return;
-	}
-	strcpy( http_hdr->method, method );
-}
-
-void
-http_set_uri( HTTP_header_t *http_hdr, const char *uri ) {
-	if( http_hdr==NULL || uri==NULL ) return;
-
-	http_hdr->uri = malloc(strlen(uri)+1);
-	if( http_hdr->uri==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		return;
-	}
-	strcpy( http_hdr->uri, uri );
-}
-
-int
-http_add_basic_authentication( HTTP_header_t *http_hdr, const char *username, const char *password ) {
-	char *auth = NULL, *usr_pass = NULL, *b64_usr_pass = NULL;
-	int encoded_len, pass_len=0, out_len;
-	int res = -1;
-	if( http_hdr==NULL || username==NULL ) return -1;
-
-	if( password!=NULL ) {
-		pass_len = strlen(password);
-	}
-	
-	usr_pass = malloc(strlen(username)+pass_len+2);
-	if( usr_pass==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		goto out;
-	}
-
-	sprintf( usr_pass, "%s:%s", username, (password==NULL)?"":password );
-
-	// Base 64 encode with at least 33% more data than the original size
-	encoded_len = strlen(usr_pass)*2;
-	b64_usr_pass = malloc(encoded_len);
-	if( b64_usr_pass==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		goto out;
-	}
-
-	out_len = base64_encode( usr_pass, strlen(usr_pass), b64_usr_pass, encoded_len);
-	if( out_len<0 ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Base64 out overflow\n");
-		goto out;
-	}
-
-	b64_usr_pass[out_len]='\0';
-	
-	auth = malloc(encoded_len+22);
-	if( auth==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
-		goto out;
-	}
-	
-	sprintf( auth, "Authorization: Basic %s", b64_usr_pass);
-	http_set_field( http_hdr, auth );
-	res = 0;
-	
-out:
-	free( usr_pass );
-	free( b64_usr_pass );
-	free( auth );
-	
-	return res;
-}
-
-void
-http_debug_hdr( HTTP_header_t *http_hdr ) {
-	HTTP_field_t *field;
-	int i = 0;
-	if( http_hdr==NULL ) return;
-
-	mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- START ---\n");
-	mp_msg(MSGT_NETWORK,MSGL_V,"protocol:           [%s]\n", http_hdr->protocol );
-	mp_msg(MSGT_NETWORK,MSGL_V,"http minor version: [%d]\n", http_hdr->http_minor_version );
-	mp_msg(MSGT_NETWORK,MSGL_V,"uri:                [%s]\n", http_hdr->uri );
-	mp_msg(MSGT_NETWORK,MSGL_V,"method:             [%s]\n", http_hdr->method );
-	mp_msg(MSGT_NETWORK,MSGL_V,"status code:        [%d]\n", http_hdr->status_code );
-	mp_msg(MSGT_NETWORK,MSGL_V,"reason phrase:      [%s]\n", http_hdr->reason_phrase );
-	mp_msg(MSGT_NETWORK,MSGL_V,"body size:          [%d]\n", http_hdr->body_size );
-
-	mp_msg(MSGT_NETWORK,MSGL_V,"Fields:\n");
-	field = http_hdr->first_field;
-	while( field!=NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_V," %d - %s\n", i++, field->field_name );
-		field = field->next;
-	}
-	mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- END ---\n");
-}
-
-int 
-base64_encode(const void *enc, int encLen, char *out, int outMax) {
-	static const char	b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-	unsigned char		*encBuf;
-	int			outLen;
-	unsigned int		bits;
-	unsigned int		shift;
-
-	encBuf = (unsigned char*)enc;
-	outLen = 0;
-	bits = 0;
-	shift = 0;
-	outMax &= ~3;
-
-	while( outLen<outMax ) {
-		if( encLen>0 ) {
-			// Shift in byte
-			bits <<= 8;
-			bits |= *encBuf;
-			shift += 8;
-			// Next byte
-			encBuf++;
-			encLen--;
-		} else if( shift>0 ) {
-			// Pad last bits to 6 bits - will end next loop
-			bits <<= 6 - shift;
-			shift = 6;
-		} else {
-			// As per RFC 2045, section 6.8,
-			// pad output as necessary: 0 to 2 '=' chars.
-			while( outLen & 3 ){
-				*out++ = '=';
-				outLen++;
-			}
-
-			return outLen;
-		}
-
-		// Encode 6 bit segments
-		while( shift>=6 ) {
-			shift -= 6;
-			*out = b64[ (bits >> shift) & 0x3F ];
-			out++;
-			outLen++;
-		}
-	}
-
-	// Output overflow
-	return -1;
-}
-
-static int http_streaming_start(stream_t *stream, int* file_format) {
-	HTTP_header_t *http_hdr;
-	unsigned int i;
-	int fd=-1;
-	int redirect = 0;
-	int auth_retry=0;
-	int seekable=0;
-	char *content_type;
-	char *next_url;
-	URL_t *url = stream->streaming_ctrl->url;
-
-	do
-	{
-		fd = http_send_request( url, 0 );
-		if( fd<0 ) {
-			return -1;
-		}
-
-		http_hdr = http_read_response( fd );
-		if( http_hdr==NULL ) {
-			closesocket( fd );
-			http_free( http_hdr );
-			return -1;
-		}
-
-		stream->fd=fd;
-		if( mp_msg_test(MSGT_NETWORK,MSGL_V) ) {
-			http_debug_hdr( http_hdr );
-		}
-		
-		stream->streaming_ctrl->data = (void*)http_hdr;
-
-		// Check if we can make partial content requests and thus seek in http-streams
-		if( http_hdr!=NULL && http_hdr->status_code==200 ) {
-		    char *accept_ranges;
-		    if( (accept_ranges = http_get_field(http_hdr,"Accept-Ranges")) != NULL )
-			seekable = strncmp(accept_ranges,"bytes",5)==0;
-		}
-
-		// Check if the response is an ICY status_code reason_phrase
-		if( !strcasecmp(http_hdr->protocol, "ICY") ) {
-			switch( http_hdr->status_code ) {
-				case 200: { // OK
-					char *field_data = NULL;
-					// note: I skip icy-notice1 and 2, as they contain html <BR>
-					// and are IMHO useless info ::atmos
-					if( (field_data = http_get_field(http_hdr, "icy-name")) != NULL )
-						mp_msg(MSGT_NETWORK,MSGL_INFO,"Name   : %s\n", field_data); field_data = NULL;
-					if( (field_data = http_get_field(http_hdr, "icy-genre")) != NULL )
-						mp_msg(MSGT_NETWORK,MSGL_INFO,"Genre  : %s\n", field_data); field_data = NULL;
-					if( (field_data = http_get_field(http_hdr, "icy-url")) != NULL )
-						mp_msg(MSGT_NETWORK,MSGL_INFO,"Website: %s\n", field_data); field_data = NULL;
-					// XXX: does this really mean public server? ::atmos
-					if( (field_data = http_get_field(http_hdr, "icy-pub")) != NULL )
-						mp_msg(MSGT_NETWORK,MSGL_INFO,"Public : %s\n", atoi(field_data)?"yes":"no"); field_data = NULL;
-					if( (field_data = http_get_field(http_hdr, "icy-br")) != NULL )
-						mp_msg(MSGT_NETWORK,MSGL_INFO,"Bitrate: %skbit/s\n", field_data); field_data = NULL;
-					
-					// If content-type == video/nsv we most likely have a winamp video stream 
-					// otherwise it should be mp3. if there are more types consider adding mime type 
-					// handling like later
-					if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "video/nsv") || !strcmp(field_data, "misc/ultravox")))
-						*file_format = DEMUXER_TYPE_NSV;
-					else if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "audio/aacp") || !strcmp(field_data, "audio/aac")))
-						*file_format = DEMUXER_TYPE_AAC;
-					else
-						*file_format = DEMUXER_TYPE_AUDIO;
-					return 0;
-				}
-				case 400: // Server Full
-					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server is full, skipping!\n");
-					return -1;
-				case 401: // Service Unavailable
-					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return service unavailable, skipping!\n");
-					return -1;
-				case 403: // Service Forbidden
-					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return 'Service Forbidden'\n");
-					return -1;
-				case 404: // Resource Not Found
-					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server couldn't find requested stream, skipping!\n");
-					return -1;
-				default:
-					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: unhandled ICY-Errorcode, contact MPlayer developers!\n");
-					return -1;
-			}
-		}
-
-		// Assume standard http if not ICY			
-		switch( http_hdr->status_code ) {
-			case 200: // OK
-				// Look if we can use the Content-Type
-				content_type = http_get_field( http_hdr, "Content-Type" );
-				if( content_type!=NULL ) {
-					char *content_length = NULL;
-					mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", content_type );
-					if( (content_length = http_get_field(http_hdr, "Content-Length")) != NULL)
-						mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length"));
-					// Check in the mime type table for a demuxer type
-					i = 0;
-					while(mime_type_table[i].mime_type != NULL) {
-						if( !strcasecmp( content_type, mime_type_table[i].mime_type ) ) {
-							*file_format = mime_type_table[i].demuxer_type;
-							return seekable;
-						}
-						i++;
-					}
-				}
-				// Not found in the mime type table, don't fail,
-				// we should try raw HTTP
-				return seekable;
-			// Redirect
-			case 301: // Permanently
-			case 302: // Temporarily
-				// TODO: RFC 2616, recommand to detect infinite redirection loops
-				next_url = http_get_field( http_hdr, "Location" );
-				if( next_url!=NULL ) {
-					closesocket( fd );
-					url_free( url );
-					stream->streaming_ctrl->url = url = url_new( next_url );
-					http_free( http_hdr );
-					redirect = 1;	
-				}
-				break;
-			case 401: // Authentication required
-				if( http_authenticate(http_hdr, url, &auth_retry)<0 ) return STREAM_UNSUPORTED;
-				redirect = 1;
-				break;
-			default:
-				mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase );
-				return -1;
-		}
-	} while( redirect );
-
-	return -1;
-}
-
-static int fixup_open(stream_t *stream,int seekable) {
-	HTTP_header_t *http_hdr = stream->streaming_ctrl->data;
-	int is_icy = http_hdr && http_get_field(http_hdr, "Icy-MetaInt");
-	int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0;
-
-	stream->type = STREAMTYPE_STREAM;
-	if(!is_icy && !is_ultravox && seekable)
-	{
-		stream->flags |= STREAM_SEEK;
-		stream->seek = http_seek;
-	}
-	stream->streaming_ctrl->bandwidth = network_bandwidth;
-	if ((!is_icy && !is_ultravox) || scast_streaming_start(stream))
-	if(nop_streaming_start( stream )) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_start failed\n");
-		streaming_ctrl_free(stream->streaming_ctrl);
-		stream->streaming_ctrl = NULL;
-		return STREAM_UNSUPORTED;
-	}
-
-	fixup_network_stream_cache(stream);
-	return STREAM_OK;
-}
-
-static int open_s1(stream_t *stream,int mode, void* opts, int* file_format) {
-	int seekable=0;
-	URL_t *url;
-
-	stream->streaming_ctrl = streaming_ctrl_new();
-	if( stream->streaming_ctrl==NULL ) {
-		return STREAM_ERROR;
-	}
-	stream->streaming_ctrl->bandwidth = network_bandwidth;
-	url = url_new(stream->url);
-	stream->streaming_ctrl->url = check4proxies(url);
-	url_free(url);
-	
-	mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_HTTP(1), URL: %s\n", stream->url);
-	seekable = http_streaming_start(stream, file_format);
-	if((seekable < 0) || (*file_format == DEMUXER_TYPE_ASF)) {
-		streaming_ctrl_free(stream->streaming_ctrl);
-		stream->streaming_ctrl = NULL;
-		return STREAM_UNSUPORTED;
-	}
-
-	return fixup_open(stream, seekable);
-}
-
-static int open_s2(stream_t *stream,int mode, void* opts, int* file_format) {
-	int seekable=0;
-	URL_t *url;
-
-	stream->streaming_ctrl = streaming_ctrl_new();
-	if( stream->streaming_ctrl==NULL ) {
-		return STREAM_ERROR;
-	}
-	stream->streaming_ctrl->bandwidth = network_bandwidth;
-	url = url_new(stream->url);
-	stream->streaming_ctrl->url = check4proxies(url);
-	url_free(url);
-	
-	mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_HTTP(2), URL: %s\n", stream->url);
-	seekable = http_streaming_start(stream, file_format);
-	if(seekable < 0) {
-		streaming_ctrl_free(stream->streaming_ctrl);
-		stream->streaming_ctrl = NULL;
-		return STREAM_UNSUPORTED;
-	}
-
-	return fixup_open(stream, seekable);
-}
-
-
-stream_info_t stream_info_http1 = {
-  "http streaming",
-  "null",
-  "Bertrand, Albeau, Reimar Doeffinger, Arpi?",
-  "plain http",
-  open_s1,
-  {"http", "http_proxy", "unsv", NULL},
-  NULL,
-  0 // Urls are an option string
-};
-
-stream_info_t stream_info_http2 = {
-  "http streaming",
-  "null",
-  "Bertrand, Albeu, Arpi? who?",
-  "plain http, also used as fallback for many other protocols",
-  open_s2,
-  {"http", "http_proxy", "pnm", "mms", "mmsu", "mmst", "rtsp", NULL},	//all the others as fallback
-  NULL,
-  0 // Urls are an option string
-};
--- a/libmpdemux/http.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* 
- * HTTP Helper
- * by Bertrand Baudet <bertrand_baudet@yahoo.com>
- * (C) 2001, MPlayer team.
- */
-
-#ifndef __HTTP_H
-#define __HTTP_H
-
-typedef struct HTTP_field_type {
-	char *field_name;
-	struct HTTP_field_type *next;
-} HTTP_field_t;
-
-typedef struct {
-	char *protocol;
-	char *method;
-	char *uri;
-	unsigned int status_code;
-	char *reason_phrase;
-	unsigned int http_minor_version;
-	// Field variables
-	HTTP_field_t *first_field;
-	HTTP_field_t *last_field;
-	unsigned int field_nb;
-	char *field_search;
-	HTTP_field_t *field_search_pos;
-	// Body variables
-	char *body;
-	size_t body_size;
-	char *buffer;
-	size_t buffer_size;
-	unsigned int is_parsed;
-} HTTP_header_t;
-
-HTTP_header_t*	http_new_header(void);
-void		http_free( HTTP_header_t *http_hdr );
-int		http_response_append( HTTP_header_t *http_hdr, char *data, int length );
-int		http_response_parse( HTTP_header_t *http_hdr );
-int		http_is_header_entire( HTTP_header_t *http_hdr );
-char* 		http_build_request( HTTP_header_t *http_hdr );
-char* 		http_get_field( HTTP_header_t *http_hdr, const char *field_name );
-char*		http_get_next_field( HTTP_header_t *http_hdr );
-void		http_set_field( HTTP_header_t *http_hdr, const char *field_name );
-void		http_set_method( HTTP_header_t *http_hdr, const char *method );
-void		http_set_uri( HTTP_header_t *http_hdr, const char *uri );
-int		http_add_basic_authentication( HTTP_header_t *http_hdr, const char *username, const char *password );
-
-void		http_debug_hdr( HTTP_header_t *http_hdr );
-
-int 		base64_encode(const void *enc, int encLen, char *out, int outMax);
-#endif // __HTTP_H
--- a/libmpdemux/librtsp/rtsp.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,804 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp.c,v 1.9 2003/04/10 02:30:48
- */
-
-/*
- * Copyright (C) 2000-2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * a minimalistic implementation of rtsp protocol,
- * *not* RFC 2326 compilant yet.
- *
- *    2006, Benjamin Zores and Vincent Mussard
- *      fixed a lot of RFC compliance issues.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <assert.h>
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#include <winsock2.h>
-#endif
-#include <string.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <inttypes.h>
-
-#include "mp_msg.h"
-#include "rtsp.h"
-#include "rtsp_session.h"
-#include "osdep/timer.h"
-
-/*
-#define LOG
-*/
-
-#define BUF_SIZE 4096
-#define HEADER_SIZE 1024
-#define MAX_FIELDS 256
-
-struct rtsp_s {
-
-  int           s;
-
-  char         *host;
-  int           port;
-  char         *path;
-  char         *param;
-  char         *mrl;
-  char         *user_agent;
-
-  char         *server;
-  unsigned int  server_state;
-  uint32_t      server_caps;
-  
-  unsigned int  cseq;
-  char         *session;
-
-  char        *answers[MAX_FIELDS];   /* data of last message */
-  char        *scheduled[MAX_FIELDS]; /* will be sent with next message */
-};
-
-/*
- * constants
- */
-
-#define RTSP_PROTOCOL_VERSION "RTSP/1.0"
-
-/* server states */
-#define RTSP_CONNECTED 1
-#define RTSP_INIT      2
-#define RTSP_READY     4
-#define RTSP_PLAYING   8
-#define RTSP_RECORDING 16
-
-/* server capabilities */
-#define RTSP_OPTIONS       0x001
-#define RTSP_DESCRIBE      0x002
-#define RTSP_ANNOUNCE      0x004
-#define RTSP_SETUP         0x008
-#define RTSP_GET_PARAMETER 0x010
-#define RTSP_SET_PARAMETER 0x020
-#define RTSP_TEARDOWN      0x040
-#define RTSP_PLAY          0x080
-#define RTSP_RECORD        0x100
-
-/*
- * network utilities
- */
- 
-static int write_stream(int s, const char *buf, int len) {
-  int total, timeout;
-
-  total = 0; timeout = 30;
-  while (total < len){ 
-    int n;
-
-    n = send (s, &buf[total], len - total, 0);
-
-    if (n > 0)
-      total += n;
-    else if (n < 0) {
-#ifndef HAVE_WINSOCK2
-      if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) {
-#else
-      if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) {
-#endif
-        usec_sleep (1000000); timeout--;
-      } else
-        return -1;
-    }
-  }
-
-  return total;
-}
-
-static ssize_t read_stream(int fd, void *buf, size_t count) {
-  
-  ssize_t ret, total;
-
-  total = 0;
-
-  while (total < count) {
-  
-    ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0);
-
-    if (ret<0) {
-      if(errno == EAGAIN) {
-        fd_set rset;
-        struct timeval timeout;
-    
-        FD_ZERO (&rset);
-        FD_SET  (fd, &rset);
-        
-        timeout.tv_sec  = 30;
-        timeout.tv_usec = 0;
-        
-        if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) {
-          return -1;
-        }
-        continue;
-      }
-      
-      mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: read error.\n");
-      return ret;
-    } else
-      total += ret;
-    
-    /* end of stream */
-    if (!ret) break;
-  }
-
-  return total;
-}
-
-/*
- * rtsp_get gets a line from stream
- * and returns a null terminated string.
- */
- 
-static char *rtsp_get(rtsp_t *s) {
-
-  int n=1;
-  char *buffer = malloc(BUF_SIZE);
-  char *string = NULL;
-
-  read_stream(s->s, buffer, 1);
-  while (n<BUF_SIZE) {
-    read_stream(s->s, &(buffer[n]), 1);
-    if ((buffer[n-1]==0x0d)&&(buffer[n]==0x0a)) break;
-    n++;
-  }
-
-  if (n>=BUF_SIZE) {
-    mp_msg(MSGT_OPEN, MSGL_FATAL, "librtsp: buffer overflow in rtsp_get\n");
-    exit(1);
-  }
-  string=malloc(n);
-  memcpy(string,buffer,n-1);
-  string[n-1]=0;
-
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << '%s'\n", string);
-#endif
-  
-
-  free(buffer);
-  return string;
-}
-
-/*
- * rtsp_put puts a line on stream
- */
- 
-static void rtsp_put(rtsp_t *s, const char *string) {
-
-  int len=strlen(string);
-  char *buf=malloc(len+2);
-
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: >> '%s'", string);
-#endif
-
-  memcpy(buf,string,len);
-  buf[len]=0x0d;
-  buf[len+1]=0x0a;
-
-  write_stream(s->s, buf, len+2);
-  
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, " done.\n");
-#endif
-
-  free(buf);
-}
-
-/*
- * extract server status code
- */
-
-static int rtsp_get_code(const char *string) {
-
-  char buf[4];
-  int code=0;
- 
-  if (!strncmp(string, RTSP_PROTOCOL_VERSION, strlen(RTSP_PROTOCOL_VERSION)))
-  {
-    memcpy(buf, string+strlen(RTSP_PROTOCOL_VERSION)+1, 3);
-    buf[3]=0;
-    code=atoi(buf);
-  } else if (!strncmp(string, RTSP_METHOD_SET_PARAMETER,8))
-  {
-    return RTSP_STATUS_SET_PARAMETER;
-  }
-
-  if(code != RTSP_STATUS_OK) mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: server responds: '%s'\n",string);
-
-  return code;
-}
-
-/*
- * send a request
- */
-
-static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) {
-
-  char **payload=s->scheduled;
-  char *buf;
-  
-  buf = malloc(strlen(type)+strlen(what)+strlen(RTSP_PROTOCOL_VERSION)+3);
-  
-  sprintf(buf,"%s %s %s",type, what, RTSP_PROTOCOL_VERSION);
-  rtsp_put(s,buf);
-  free(buf);
-  if (payload)
-    while (*payload) {
-      rtsp_put(s,*payload);
-      payload++;
-    }
-  rtsp_put(s,"");
-  rtsp_unschedule_all(s);
-}
-
-/*
- * schedule standard fields
- */
-
-static void rtsp_schedule_standard(rtsp_t *s) {
-
-  char tmp[17];
-  
-  snprintf(tmp, 17, "CSeq: %u", s->cseq);
-  rtsp_schedule_field(s, tmp);
-  
-  if (s->session) {
-    char *buf;
-    buf = malloc(strlen(s->session)+15);
-    sprintf(buf, "Session: %s", s->session);
-    rtsp_schedule_field(s, buf);
-    free(buf);
-  }
-}
-/*
- * get the answers, if server responses with something != 200, return NULL
- */
- 
-static int rtsp_get_answers(rtsp_t *s) {
-
-  char *answer=NULL;
-  unsigned int answer_seq;
-  char **answer_ptr=s->answers;
-  int code;
-  int ans_count = 0;
-  
-  answer=rtsp_get(s);
-  if (!answer)
-    return 0;
-  code=rtsp_get_code(answer);
-  free(answer);
-
-  rtsp_free_answers(s);
-  
-  do { /* while we get answer lines */
-  
-    answer=rtsp_get(s);
-    if (!answer)
-      return 0;
-    
-    if (!strncasecmp(answer,"CSeq:",5)) {
-      sscanf(answer,"%*s %u",&answer_seq);
-      if (s->cseq != answer_seq) {
-#ifdef LOG
-        mp_msg(MSGT_OPEN, MSGL_WARN, "librtsp: warning: CSeq mismatch. got %u, assumed %u", answer_seq, s->cseq);
-#endif
-        s->cseq=answer_seq;
-      }
-    }
-    if (!strncasecmp(answer,"Server:",7)) {
-      char *buf = malloc(strlen(answer));
-      sscanf(answer,"%*s %s",buf);
-      if (s->server) free(s->server);
-      s->server=strdup(buf);
-      free(buf);
-    }
-    if (!strncasecmp(answer,"Session:",8)) {
-      char *buf = calloc(1, strlen(answer));
-      sscanf(answer,"%*s %s",buf);
-      if (s->session) {
-        if (strcmp(buf, s->session)) {
-          mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: setting NEW session: %s\n", buf);
-          free(s->session);
-          s->session=strdup(buf);
-        }
-      } else
-      {
-#ifdef LOG
-        mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: setting session id to: %s\n", buf);
-#endif
-        s->session=strdup(buf);
-      }
-      free(buf);
-    }
-    *answer_ptr=answer;
-    answer_ptr++;
-  } while ((strlen(answer)!=0) && (++ans_count < MAX_FIELDS));
-  
-  s->cseq++;
-  
-  *answer_ptr=NULL;
-  rtsp_schedule_standard(s);
-    
-  return code;
-}
-
-/*
- * send an ok message
- */
-
-int rtsp_send_ok(rtsp_t *s) {
-  char cseq[16];
-  
-  rtsp_put(s, "RTSP/1.0 200 OK");
-  sprintf(cseq,"CSeq: %u", s->cseq);
-  rtsp_put(s, cseq);
-  rtsp_put(s, "");
-  return 0;
-}
-
-/*
- * implementation of must-have rtsp requests; functions return
- * server status code.
- */
-
-int rtsp_request_options(rtsp_t *s, const char *what) {
-
-  char *buf;
-
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(strlen(s->host)+16);
-    sprintf(buf,"rtsp://%s:%i", s->host, s->port);
-  }
-  rtsp_send_request(s,RTSP_METHOD_OPTIONS,buf);
-  free(buf);
-
-  return rtsp_get_answers(s);
-}
-
-int rtsp_request_describe(rtsp_t *s, const char *what) {
-
-  char *buf;
-
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(strlen(s->host)+strlen(s->path)+16);
-    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request(s,RTSP_METHOD_DESCRIBE,buf);
-  free(buf);
-  
-  return rtsp_get_answers(s);
-}
-
-int rtsp_request_setup(rtsp_t *s, const char *what, char *control) {
-
-  char *buf = NULL;
-
-  if (what)
-    buf = strdup (what);
-  else
-  {
-    int len = strlen (s->host) + strlen (s->path) + 16;
-    if (control)
-      len += strlen (control) + 1;
-    
-    buf = malloc (len);
-    sprintf (buf, "rtsp://%s:%i/%s%s%s", s->host, s->port, s->path,
-             control ? "/" : "", control ? control : "");
-  }
-  
-  rtsp_send_request (s, RTSP_METHOD_SETUP, buf);
-  free (buf);
-  return rtsp_get_answers (s);
-}
-
-int rtsp_request_setparameter(rtsp_t *s, const char *what) {
-
-  char *buf;
-
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(strlen(s->host)+strlen(s->path)+16);
-    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request(s,RTSP_METHOD_SET_PARAMETER,buf);
-  free(buf);
-  
-  return rtsp_get_answers(s);
-}
-
-int rtsp_request_play(rtsp_t *s, const char *what) {
-
-  char *buf;
-  int ret;
-  
-  if (what) {
-    buf=strdup(what);
-  } else
-  {
-    buf=malloc(strlen(s->host)+strlen(s->path)+16);
-    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request(s,RTSP_METHOD_PLAY,buf);
-  free(buf);
-  
-  ret = rtsp_get_answers (s);
-  if (ret == RTSP_STATUS_OK)
-    s->server_state = RTSP_PLAYING;
-
-  return ret;
-}
-
-int rtsp_request_teardown(rtsp_t *s, const char *what) {
-
-  char *buf;
-  
-  if (what)
-    buf = strdup (what);
-  else
-  {
-    buf =
-      malloc (strlen (s->host) + strlen (s->path) + 16);
-    sprintf (buf, "rtsp://%s:%i/%s", s->host, s->port, s->path);
-  }
-  rtsp_send_request (s, RTSP_METHOD_TEARDOWN, buf);
-  free (buf);
-
-  /* after teardown we're done with RTSP streaming, no need to get answer as
-     reading more will only result to garbage and buffer overflow */
-  return RTSP_STATUS_OK;
-}
-
-/*
- * read opaque data from stream
- */
-
-int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) {
-
-  int i,seq;
-
-  if (size>=4) {
-    i=read_stream(s->s, buffer, 4);
-    if (i<4) return i;
-    if (((buffer[0]=='S')&&(buffer[1]=='E')&&(buffer[2]=='T')&&(buffer[3]=='_')) ||
-        ((buffer[0]=='O')&&(buffer[1]=='P')&&(buffer[2]=='T')&&(buffer[3]=='I'))) // OPTIONS
-    {
-      char *rest=rtsp_get(s);
-      if (!rest)
-        return -1;      
-
-      seq=-1;
-      do {
-        free(rest);
-        rest=rtsp_get(s);
-        if (!rest)
-          return -1;
-        if (!strncasecmp(rest,"CSeq:",5))
-          sscanf(rest,"%*s %u",&seq);
-      } while (strlen(rest)!=0);
-      free(rest);
-      if (seq<0) {
-#ifdef LOG
-        mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: CSeq not recognized!\n");
-#endif
-        seq=1;
-      }
-      /* let's make the server happy */
-      rtsp_put(s, "RTSP/1.0 451 Parameter Not Understood");
-      rest=malloc(17);
-      sprintf(rest,"CSeq: %u", seq);
-      rtsp_put(s, rest);
-      free(rest);
-      rtsp_put(s, "");
-      i=read_stream(s->s, buffer, size);
-    } else
-    {
-      i=read_stream(s->s, buffer+4, size-4);
-      i+=4;
-    }
-  } else
-    i=read_stream(s->s, buffer, size);
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << %d of %d bytes\n", i, size);
-#endif
-
-  return i;
-}
-
-/*
- * connect to a rtsp server
- */
-
-//rtsp_t *rtsp_connect(const char *mrl, const char *user_agent) {
-rtsp_t *rtsp_connect(int fd, char* mrl, char *path, char *host, int port, char *user_agent) {
-
-  rtsp_t *s=malloc(sizeof(rtsp_t));
-  int i;
-  
-  for (i=0; i<MAX_FIELDS; i++) {
-    s->answers[i]=NULL;
-    s->scheduled[i]=NULL;
-  }
-
-  s->server=NULL;
-  s->server_state=0;
-  s->server_caps=0;
-  
-  s->cseq=0;
-  s->session=NULL;
-  
-  if (user_agent)
-    s->user_agent=strdup(user_agent);
-  else
-    s->user_agent=strdup("User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)");
-
-  s->mrl = strdup(mrl);
-  s->host = strdup(host);
-  s->port = port;
-  s->path = strdup(path);
-  while (*path == '/')
-    path++;
-  if ((s->param = strchr(s->path, '?')) != NULL)
-    s->param++;
-  //mp_msg(MSGT_OPEN, MSGL_INFO, "path=%s\n", s->path);
-  //mp_msg(MSGT_OPEN, MSGL_INFO, "param=%s\n", s->param ? s->param : "NULL");
-  s->s = fd;
-
-  if (s->s < 0) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: failed to connect to '%s'\n", s->host);
-    rtsp_close(s);
-    return NULL;
-  }
-
-  s->server_state=RTSP_CONNECTED;
-
-  /* now let's send an options request. */
-  rtsp_schedule_field(s, "CSeq: 1");
-  rtsp_schedule_field(s, s->user_agent);
-  rtsp_schedule_field(s, "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7");
-  rtsp_schedule_field(s, "PlayerStarttime: [28/03/2003:22:50:23 00:00]");
-  rtsp_schedule_field(s, "CompanyID: KnKV4M4I/B2FjJ1TToLycw==");
-  rtsp_schedule_field(s, "GUID: 00000000-0000-0000-0000-000000000000");
-  rtsp_schedule_field(s, "RegionData: 0");
-  rtsp_schedule_field(s, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
-  /*rtsp_schedule_field(s, "Pragma: initiate-session");*/
-  rtsp_request_options(s, NULL);
-
-  return s;
-}
-
-
-/*
- * closes an rtsp connection 
- */
-
-void rtsp_close(rtsp_t *s) {
-
-  if (s->server_state)
-  {
-    if (s->server_state == RTSP_PLAYING)
-      rtsp_request_teardown (s, NULL);
-    closesocket (s->s);
-  }
-
-  if (s->path) free(s->path);
-  if (s->host) free(s->host);
-  if (s->mrl) free(s->mrl);
-  if (s->session) free(s->session);
-  if (s->user_agent) free(s->user_agent);
-  rtsp_free_answers(s);
-  rtsp_unschedule_all(s);
-  free(s);  
-}
-
-/*
- * search in answers for tags. returns a pointer to the content
- * after the first matched tag. returns NULL if no match found.
- */
-
-char *rtsp_search_answers(rtsp_t *s, const char *tag) {
-
-  char **answer;
-  char *ptr;
-  
-  if (!s->answers) return NULL;
-  answer=s->answers;
-
-  while (*answer) {
-    if (!strncasecmp(*answer,tag,strlen(tag))) {
-      ptr=strchr(*answer,':');
-      if (!ptr) return NULL;
-      ptr++;
-      while(*ptr==' ') ptr++;
-      return ptr;
-    }
-    answer++;
-  }
-
-  return NULL;
-}
-
-/*
- * session id management
- */
-
-void rtsp_set_session(rtsp_t *s, const char *id) {
-
-  if (s->session) free(s->session);
-
-  s->session=strdup(id);
-
-}
-
-char *rtsp_get_session(rtsp_t *s) {
-
-  return s->session;
-
-}
-
-char *rtsp_get_mrl(rtsp_t *s) {
-
-  return s->mrl;
-
-}
-
-char *rtsp_get_param(rtsp_t *s, const char *p) {
-  int len;
-  char *param;
-  if (!s->param)
-    return NULL;
-  if (!p)
-    return strdup(s->param);
-  len = strlen(p);
-  param = s->param;
-  while (param && *param) {
-    char *nparam = strchr(param, '&');
-    if (strncmp(param, p, len) == 0 && param[len] == '=') {
-      param += len + 1;
-      len = nparam ? nparam - param : strlen(param);
-      nparam = malloc(len + 1);
-      memcpy(nparam, param, len);
-      nparam[len] = 0;
-      return nparam;
-    }
-    param = nparam ? nparam + 1 : NULL;
-  }
-  return NULL;
-}
-  
-/*
- * schedules a field for transmission
- */
-
-void rtsp_schedule_field(rtsp_t *s, const char *string) {
-
-  int i=0;
-  
-  if (!string) return;
-
-  while(s->scheduled[i]) {
-    i++;
-  }
-  s->scheduled[i]=strdup(string);
-}
-
-/*
- * removes the first scheduled field which prefix matches string. 
- */
-
-void rtsp_unschedule_field(rtsp_t *s, const char *string) {
-
-  char **ptr=s->scheduled;
-  
-  if (!string) return;
-
-  while(*ptr) {
-    if (!strncmp(*ptr, string, strlen(string)))
-      break;
-    else
-      ptr++;
-  }
-  if (*ptr) free(*ptr);
-  ptr++;
-  do {
-    *(ptr-1)=*ptr;
-  } while(*ptr);
-}
-
-/*
- * unschedule all fields
- */
-
-void rtsp_unschedule_all(rtsp_t *s) {
-
-  char **ptr;
-  
-  if (!s->scheduled) return;
-  ptr=s->scheduled;
-
-  while (*ptr) {
-    free(*ptr);
-    *ptr=NULL;
-    ptr++;
-  }
-}
-/*
- * free answers
- */
-
-void rtsp_free_answers(rtsp_t *s) {
-
-  char **answer;
-  
-  if (!s->answers) return;
-  answer=s->answers;
-
-  while (*answer) {
-    free(*answer);
-    *answer=NULL;
-    answer++;
-  }
-}
--- a/libmpdemux/librtsp/rtsp.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp.h,v 1.2 2002/12/16 21:50:55
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * a minimalistic implementation of rtsp protocol,
- * *not* RFC 2326 compilant yet.
- *
- *    2006, Benjamin Zores and Vincent Mussard
- *      fixed a lot of RFC compliance issues.
- */
- 
-#ifndef HAVE_RTSP_H
-#define HAVE_RTSP_H
-
-
-/* some codes returned by rtsp_request_* functions */
-
-#define RTSP_STATUS_SET_PARAMETER  10
-#define RTSP_STATUS_OK            200
-
-#define RTSP_METHOD_OPTIONS "OPTIONS"
-#define RTSP_METHOD_DESCRIBE "DESCRIBE"
-#define RTSP_METHOD_SETUP "SETUP"
-#define RTSP_METHOD_PLAY "PLAY"
-#define RTSP_METHOD_TEARDOWN "TEARDOWN"
-#define RTSP_METHOD_SET_PARAMETER "SET_PARAMETER"
-
-typedef struct rtsp_s rtsp_t;
-
-rtsp_t*  rtsp_connect (int fd, char *mrl, char *path, char *host, int port, char *user_agent);
-
-int rtsp_request_options(rtsp_t *s, const char *what);
-int rtsp_request_describe(rtsp_t *s, const char *what);
-int rtsp_request_setup(rtsp_t *s, const char *what, char *control);
-int rtsp_request_setparameter(rtsp_t *s, const char *what);
-int rtsp_request_play(rtsp_t *s, const char *what);
-int rtsp_request_teardown(rtsp_t *s, const char *what);
-
-int rtsp_send_ok(rtsp_t *s);
-
-int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size);
-
-char* rtsp_search_answers(rtsp_t *s, const char *tag);
-void rtsp_add_to_payload(char **payload, const char *string);
-
-void rtsp_free_answers(rtsp_t *this);
-
-int      rtsp_read (rtsp_t *this, char *data, int len);
-void     rtsp_close (rtsp_t *this);
-
-void  rtsp_set_session(rtsp_t *s, const char *id);
-char *rtsp_get_session(rtsp_t *s);
-
-char *rtsp_get_mrl(rtsp_t *s);
-char *rtsp_get_param(rtsp_t *s, const char *param);
-
-/*int      rtsp_peek_header (rtsp_t *this, char *data); */
-
-void rtsp_schedule_field(rtsp_t *s, const char *string);
-void rtsp_unschedule_field(rtsp_t *s, const char *string);
-void rtsp_unschedule_all(rtsp_t *s);
-
-#endif
-
--- a/libmpdemux/librtsp/rtsp_rtp.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,700 +0,0 @@
-/*
- *  Copyright (C) 2006 Benjamin Zores
- *   based on the Freebox patch for xine by Vincent Mussard
- *   but with many enhancements for better RTSP RFC compliance.
- *
- *   This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software Foundation,
- *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <inttypes.h>
-
-#include "config.h"
-
-#ifndef HAVE_WINSOCK2
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-
-#include "mp_msg.h"
-#include "rtsp.h"
-#include "rtsp_rtp.h"
-#include "rtsp_session.h"
-#include "../freesdp/common.h"
-#include "../freesdp/parser.h"
-
-#define RTSP_DEFAULT_PORT 31336
-#define MAX_LENGTH 256
-
-#define RTSP_ACCEPT_SDP "Accept: application/sdp"
-#define RTSP_CONTENT_LENGTH "Content-length"
-#define RTSP_CONTENT_TYPE "Content-Type"
-#define RTSP_APPLICATION_SDP "application/sdp"
-#define RTSP_RANGE "Range: "
-#define RTSP_NPT_NOW "npt=now-"
-#define RTSP_MEDIA_CONTAINER_MPEG_TS "33"
-#define RTSP_TRANSPORT_REQUEST "Transport: RTP/AVP;%s;%s%i-%i;mode=\"PLAY\""
-  
-#define RTSP_TRANSPORT_MULTICAST "multicast"
-#define RTSP_TRANSPORT_UNICAST "unicast"
-
-#define RTSP_MULTICAST_PORT "port="
-#define RTSP_UNICAST_CLIENT_PORT "client_port="
-#define RTSP_UNICAST_SERVER_PORT "server_port="
-#define RTSP_SETUP_DESTINATION "destination="
-
-#define RTSP_SESSION "Session"
-#define RTSP_TRANSPORT "Transport"
-
-/* hardcoded RTCP RR - this is _NOT_ RFC compliant */
-#define RTCP_RR_SIZE 32
-#define RTCP_RR "\201\311\0\7(.JD\31+\306\343\0\0\0\0\0\0/E\0\0\2&\0\0\0\0\0\0\0\0\201"
-#define RTCP_SEND_FREQUENCY 1024
-
-int rtsp_port = 0;
-char *rtsp_destination = NULL;
-
-void
-rtcp_send_rr (rtsp_t *s, struct rtp_rtsp_session_t *st)
-{
-  if (st->rtcp_socket == -1)
-    return;
-  
-  /* send RTCP RR every RTCP_SEND_FREQUENCY packets
-   * FIXME : NOT CORRECT, HARDCODED, BUT MAKES SOME SERVERS HAPPY
-   * not rfc compliant
-   * http://www.faqs.org/rfcs/rfc1889.html chapter 6 for RTCP
-   */
-
-  if (st->count == RTCP_SEND_FREQUENCY)
-  {
-    char rtcp_content[RTCP_RR_SIZE];
-    strcpy (rtcp_content, RTCP_RR);
-    send (st->rtcp_socket, rtcp_content, RTCP_RR_SIZE, 0);
-
-    /* ping RTSP server to keep connection alive.
-       we use OPTIONS instead of PING as not all servers support it */
-    rtsp_request_options (s, "*");
-    st->count = 0;
-  }
-  else
-    st->count++;
-}
-
-static struct rtp_rtsp_session_t *
-rtp_session_new (void)
-{
-  struct rtp_rtsp_session_t *st = NULL;
-  
-  st = malloc (sizeof (struct rtp_rtsp_session_t));
-  
-  st->rtp_socket = -1;
-  st->rtcp_socket = -1;
-  st->control_url = NULL;
-  st->count = 0;
-  
-  return st;
-}
-
-void
-rtp_session_free (struct rtp_rtsp_session_t *st)
-{
-  if (!st)
-    return;
-
-  if (st->rtp_socket != -1)
-    close (st->rtp_socket);
-  if (st->rtcp_socket != -1)
-    close (st->rtcp_socket);
-
-  if (st->control_url)
-    free (st->control_url);
-  free (st);
-}
-
-static void
-rtp_session_set_fd (struct rtp_rtsp_session_t *st,
-                    int rtp_sock, int rtcp_sock)
-{
-  if (!st)
-    return;
-
-  st->rtp_socket = rtp_sock;
-  st->rtcp_socket = rtcp_sock;
-}
-
-static int
-parse_port (const char *line, const char *param,
-            int *rtp_port, int *rtcp_port)
-{
-  char *parse1;
-  char *parse2;
-  char *parse3;
-  
-  char *line_copy = strdup (line);
-
-  parse1 = strstr (line_copy, param);
-
-  if (parse1)
-  {
-    parse2 = strstr (parse1, "-");
-    
-    if (parse2)
-    {
-      parse3 = strstr (parse2, ";");
-      
-      if (parse3)
-	parse3[0] = 0;
-      
-      parse2[0] = 0;
-    }
-    else
-    {
-      free (line_copy);
-      return 0;
-    }
-  }
-  else
-  {
-    free (line_copy);
-    return 0;
-  }
-  
-  *rtp_port = atoi (parse1 + strlen (param));
-  *rtcp_port = atoi (parse2 + 1);
-
-  free (line_copy);
-  
-  return 1;
-}
-
-static char *
-parse_destination (const char *line)
-{
-  char *parse1;
-  char *parse2;
-
-  char *dest = NULL;
-  char *line_copy = strdup (line);
-  int len;
-  
-  parse1 = strstr (line_copy, RTSP_SETUP_DESTINATION);
-  if (!parse1)
-  {
-    free (line_copy);
-    return NULL;
-  }
-  
-  parse2 = strstr (parse1, ";");
-  if (!parse2)
-  {
-    free (line_copy);
-    return NULL;
-  }
- 
-  len = strlen (parse1) - strlen (parse2)
-    - strlen (RTSP_SETUP_DESTINATION) + 1;
-  dest = (char *) malloc (len + 1);
-  snprintf (dest, len, parse1 + strlen (RTSP_SETUP_DESTINATION));
-  free (line_copy);
-
-  return dest;
-}
-
-static int
-rtcp_connect (int client_port, int server_port, const char* server_hostname)
-{
-  struct sockaddr_in sin;
-  struct hostent *hp;
-  int s;
-  
-  if (client_port <= 1023)
-    return -1;
-
-  s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-  if (s == -1)
-    return -1;
-
-  hp = gethostbyname (server_hostname);
-  if (!hp)
-  {
-    close (s);
-    return -1;
-  }
-
-  sin.sin_family = AF_INET;
-  sin.sin_addr.s_addr = INADDR_ANY;
-  sin.sin_port = htons (client_port);
-  
-  if (bind (s, (struct sockaddr *) &sin, sizeof (sin)))
-  {
-#ifndef HAVE_WINSOCK2
-    if (errno != EINPROGRESS)
-#else
-    if (WSAGetLastError() != WSAEINPROGRESS)
-#endif
-    {
-      close (s);
-      return -1;
-    }
-  }
-  
-  sin.sin_family = AF_INET;
-  memcpy (&(sin.sin_addr.s_addr), hp->h_addr, sizeof (hp->h_addr));
-  sin.sin_port = htons (server_port);
-
-  /* datagram socket */
-  if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) < 0)
-  {
-    close (s);
-    return -1;
-  }
-
-  return s;
-}
-
-static int
-rtp_connect (char *hostname, int port)
-{
-  struct sockaddr_in sin;
-  struct timeval tv;
-  int err, err_len;
-  int rxsockbufsz;
-  int s;
-  fd_set set;
-
-  if (port <= 1023)
-    return -1;
-
-  s = socket (PF_INET, SOCK_DGRAM, 0);
-  if (s == -1)
-    return -1;
-
-  sin.sin_family = AF_INET;
-  if (!hostname || !strcmp (hostname, "0.0.0.0"))
-    sin.sin_addr.s_addr = htonl (INADDR_ANY);
-  else
-#ifndef HAVE_WINSOCK2
-#ifdef USE_ATON
-    inet_aton (hostname, &sin.sin_addr);
-#else
-    inet_pton (AF_INET, hostname, &sin.sin_addr);
-#endif
-#else
-    sin.sin_addr.s_addr = htonl (INADDR_ANY);
-#endif
-  sin.sin_port = htons (port);
-
-  /* Increase the socket rx buffer size to maximum -- this is UDP */
-  rxsockbufsz = 240 * 1024;
-  if (setsockopt (s, SOL_SOCKET, SO_RCVBUF,
-                  &rxsockbufsz, sizeof (rxsockbufsz)))
-    mp_msg (MSGT_OPEN, MSGL_ERR, "Couldn't set receive socket buffer size\n");
-
-  /* if multicast address, add membership */
-  if ((ntohl (sin.sin_addr.s_addr) >> 28) == 0xe)
-  {
-    struct ip_mreq mcast;
-    mcast.imr_multiaddr.s_addr = sin.sin_addr.s_addr;
-    mcast.imr_interface.s_addr = 0;
-
-    if (setsockopt (s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof (mcast)))
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR, "IP_ADD_MEMBERSHIP failed\n");
-      close (s);
-      return -1;
-    }
-  }
-  
-  /* datagram socket */
-  if (bind (s, (struct sockaddr *) &sin, sizeof (sin)))
-  {
-#ifndef HAVE_WINSOCK2
-    if (errno != EINPROGRESS)
-#else
-    if (WSAGetLastError() != WSAEINPROGRESS)
-#endif
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR, "bind: %s\n", strerror (errno));
-      close (s);
-      return -1;
-    }
-  }
-
-  tv.tv_sec = 0;
-  tv.tv_usec = (1 * 1000000); /* 1 second timeout */
-  
-  FD_ZERO (&set);
-  FD_SET (s, &set);
-  
-  err = select (s + 1, &set, NULL, NULL, &tv);
-  if (err < 0)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR, "Select failed: %s\n", strerror (errno));
-    close (s);
-    return -1;
-  }
-  else if (err == 0)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR, "Timeout! No data from host %s\n", hostname);
-    close (s);
-    return -1;
-  }
-  
-  err_len = sizeof (err);
-  getsockopt (s, SOL_SOCKET, SO_ERROR, &err, (socklen_t *) &err_len);
-  if (err)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR, "Socket error: %d\n", err);
-    close (s);
-    return -1;
-  }
-  
-  return s;
-}
-
-static int
-is_multicast_address (char *addr)
-{
-  struct sockaddr_in sin;
-
-  if (!addr)
-    return -1;
-  
-  sin.sin_family = AF_INET;
-
-#ifndef HAVE_WINSOCK2
-#ifdef USE_ATON
-    inet_aton (addr, &sin.sin_addr);
-#else
-    inet_pton (AF_INET, addr, &sin.sin_addr);
-#endif
-#else
-    sin.sin_addr.s_addr = htonl (INADDR_ANY);
-#endif
-  
-  if ((ntohl (sin.sin_addr.s_addr) >> 28) == 0xe)
-    return 1;
-
-  return 0;
-}
-
-struct rtp_rtsp_session_t *
-rtp_setup_and_play (rtsp_t *rtsp_session)
-{
-  struct rtp_rtsp_session_t* rtp_session = NULL;
-  const fsdp_media_description_t *med_dsc = NULL;
-  char temp_buf[MAX_LENGTH + 1];
-  char npt[256];
-
-  char* answer;
-  char* sdp;
-  char *server_addr = NULL;
-  char *destination = NULL;
-
-  int statut;
-  int content_length = 0;
-  int is_multicast = 0;
-  
-  fsdp_description_t *dsc = NULL;
-  fsdp_error_t result;
-
-  int client_rtp_port = -1;
-  int client_rtcp_port = -1;
-  int server_rtp_port = -1;
-  int server_rtcp_port = -1;
-  int rtp_sock = -1;
-  int rtcp_sock = -1;
-
-  /* 1. send a RTSP DESCRIBE request to server */
-  rtsp_schedule_field (rtsp_session, RTSP_ACCEPT_SDP);
-  statut = rtsp_request_describe (rtsp_session, NULL);
-  if (statut < 200 || statut > 299)
-    return NULL;
-
-  answer = rtsp_search_answers (rtsp_session, RTSP_CONTENT_LENGTH);
-  if (answer)
-    content_length = atoi (answer);
-  else
-    return NULL;
-
-  answer = rtsp_search_answers (rtsp_session, RTSP_CONTENT_TYPE);
-  if (!answer || !strstr (answer, RTSP_APPLICATION_SDP))
-    return NULL;
-
-  /* 2. read SDP message from server */
-  sdp = (char *) malloc (content_length + 1);
-  if (rtsp_read_data (rtsp_session, sdp, content_length) <= 0)
-  {
-    free (sdp);
-    return NULL;
-  }
-  sdp[content_length] = 0;
-  
-  /* 3. parse SDP message */
-  dsc = fsdp_description_new ();
-  result = fsdp_parse (sdp, dsc);
-  if (result != FSDPE_OK)
-  {
-    free (sdp);
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-  mp_msg (MSGT_OPEN, MSGL_V, "SDP:\n%s\n", sdp);
-  free (sdp);
-
-  /* 4. check for number of media streams: only one is supported */
-  if (fsdp_get_media_count (dsc) != 1)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "A single media stream only is supported atm.\n");
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-
-  /* 5. set the Normal Play Time parameter
-   *    use range provided by server in SDP or start now if empty */
-  sprintf (npt, RTSP_RANGE);
-  if (fsdp_get_range (dsc))
-    strcat (npt, fsdp_get_range (dsc));
-  else
-    strcat (npt, RTSP_NPT_NOW);
-
-  /* 5. check for a valid media stream */
-  med_dsc = fsdp_get_media (dsc, 0);
-  if (!med_dsc)
-  {
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-
-  /* 6. parse the `m=<media>  <port>  <transport> <fmt list>' line */
- 
-  /* check for an A/V media */
-  if (fsdp_get_media_type (med_dsc) != FSDP_MEDIA_VIDEO &&
-      fsdp_get_media_type (med_dsc) != FSDP_MEDIA_AUDIO)
-  {
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-  
-  /* only RTP/AVP transport method is supported right now */
-  if (fsdp_get_media_transport_protocol (med_dsc) != FSDP_TP_RTP_AVP)
-  {
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-
-  /* only MPEG-TS is supported at the moment */
-  if (!strstr (fsdp_get_media_format (med_dsc, 0),
-               RTSP_MEDIA_CONTAINER_MPEG_TS))
-  {
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-
-  /* get client port (if any) advised by server */
-  client_rtp_port = fsdp_get_media_port (med_dsc);
-  if (client_rtp_port == -1)
-  {
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-
-  /* if client_rtp_port = 0 => let client randomly pick one */
-  if (client_rtp_port == 0)
-  {
-    /* TODO: we should check if the port is in use first */
-    if (rtsp_port)
-      client_rtp_port = rtsp_port;
-    else
-      client_rtp_port = RTSP_DEFAULT_PORT;
-  }
-
-  /* RTCP port generally is RTP port + 1 */
-  client_rtcp_port = client_rtp_port + 1;
-  
-  mp_msg (MSGT_OPEN, MSGL_V,
-          "RTP Port from SDP appears to be: %d\n", client_rtp_port);
-  mp_msg (MSGT_OPEN, MSGL_V,
-          "RTCP Port from SDP appears to be: %d\n", client_rtcp_port);
-
-  /* 7. parse the `c=<network type> <addr type> <connection address>' line */
-
-  /* check for a valid media network type (inet) */
-  if (fsdp_get_media_network_type (med_dsc) != FSDP_NETWORK_TYPE_INET)
-  {
-    /* no control for media: try global one instead */
-    if (fsdp_get_global_conn_network_type (dsc) != FSDP_NETWORK_TYPE_INET)
-    {
-      fsdp_description_delete (dsc);
-      return NULL;
-    }
-  }
-
-  /* only IPv4 is supported atm. */
-  if (fsdp_get_media_address_type (med_dsc) != FSDP_ADDRESS_TYPE_IPV4)
-  {
-    /* no control for media: try global one instead */
-    if (fsdp_get_global_conn_address_type (dsc) != FSDP_ADDRESS_TYPE_IPV4)
-    {
-      fsdp_description_delete (dsc);
-      return NULL;
-    }
-  }
-
-  /* get the media server address to connect to */
-  if (fsdp_get_media_address (med_dsc))
-    server_addr = strdup (fsdp_get_media_address (med_dsc));
-  else if (fsdp_get_global_conn_address (dsc))
-  {
-    /* no control for media: try global one instead */
-    server_addr = strdup (fsdp_get_global_conn_address (dsc));
-  }
-    
-  if (!server_addr)
-  {
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-
-  /* check for a UNICAST or MULTICAST address to connect to */
-  is_multicast = is_multicast_address (server_addr);
-
-  /* 8. initiate an RTP session */
-  rtp_session = rtp_session_new ();
-  if (!rtp_session)
-  {
-    free (server_addr);
-    fsdp_description_delete (dsc);
-    return NULL;
-  }
-
-  /* get the media control URL */
-  if (fsdp_get_media_control (med_dsc, 0))
-    rtp_session->control_url = strdup (fsdp_get_media_control (med_dsc, 0));
-  fsdp_description_delete (dsc);
-  if (!rtp_session->control_url)
-  {
-    free (server_addr);
-    rtp_session_free (rtp_session);
-    return NULL;
-  }
-
-  /* 9. create the payload for RTSP SETUP request */
-  memset (temp_buf, '\0', MAX_LENGTH);
-  snprintf (temp_buf, MAX_LENGTH,
-            RTSP_TRANSPORT_REQUEST,
-            is_multicast ? RTSP_TRANSPORT_MULTICAST : RTSP_TRANSPORT_UNICAST,
-            is_multicast ? RTSP_MULTICAST_PORT : RTSP_UNICAST_CLIENT_PORT,
-            client_rtp_port, client_rtcp_port);
-  mp_msg (MSGT_OPEN, MSGL_V, "RTSP Transport: %s\n", temp_buf);
-  
-  rtsp_unschedule_field (rtsp_session, RTSP_SESSION);
-  rtsp_schedule_field (rtsp_session, temp_buf);
-
-  /* 10. check for the media control URL type and initiate RTSP SETUP */
-  if (!strncmp (rtp_session->control_url, "rtsp://", 7)) /* absolute URL */
-    statut = rtsp_request_setup (rtsp_session,
-                                 rtp_session->control_url, NULL);
-  else /* relative URL */
-    statut = rtsp_request_setup (rtsp_session,
-                                 NULL, rtp_session->control_url);
-    
-  if (statut < 200 || statut > 299)
-  {
-    free (server_addr);
-    rtp_session_free (rtp_session);
-    return NULL;
-  }
-
-  /* 11. parse RTSP SETUP response: we need it to actually determine
-   *     the real address and port to connect to */
-  answer = rtsp_search_answers (rtsp_session, RTSP_TRANSPORT);
-  if (!answer)
-  {
-    free (server_addr);
-    rtp_session_free (rtp_session);
-    return NULL;
-  }
-
-  /* check for RTP and RTCP ports to bind according to how request was done */
-  is_multicast = 0;
-  if (strstr (answer, RTSP_TRANSPORT_MULTICAST))
-    is_multicast = 1;
-
-  if (is_multicast)
-    parse_port (answer, RTSP_MULTICAST_PORT,
-                &client_rtp_port, &client_rtcp_port);
-  else
-  {
-    parse_port (answer, RTSP_UNICAST_CLIENT_PORT,
-                &client_rtp_port, &client_rtcp_port);
-    parse_port (answer, RTSP_UNICAST_SERVER_PORT,
-                &server_rtp_port, &server_rtcp_port);
-  }
-
-  /* now check network settings as determined by server */
-  if (rtsp_destination)
-    destination = strdup (rtsp_destination);
-  else
-    destination = parse_destination (answer);
-  if (!destination)
-    destination = strdup (server_addr);
-  free (server_addr);
-
-  mp_msg (MSGT_OPEN, MSGL_V, "RTSP Destination: %s\n", destination);
-  mp_msg (MSGT_OPEN, MSGL_V, "Client RTP port : %d\n", client_rtp_port);
-  mp_msg (MSGT_OPEN, MSGL_V, "Client RTCP port : %d\n", client_rtcp_port);
-  mp_msg (MSGT_OPEN, MSGL_V, "Server RTP port : %d\n", server_rtp_port);
-  mp_msg (MSGT_OPEN, MSGL_V, "Server RTCP port : %d\n", server_rtcp_port);
-
-  /* 12. performs RTSP PLAY request */
-  rtsp_schedule_field (rtsp_session, npt);
-  statut = rtsp_request_play (rtsp_session, NULL);
-  if (statut < 200 || statut > 299)
-  {
-    free (destination);
-    rtp_session_free (rtp_session);
-    return NULL;
-  }
-
-  /* 13. create RTP and RTCP connections */
-  rtp_sock = rtp_connect (destination, client_rtp_port);
-  rtcp_sock = rtcp_connect (client_rtcp_port, server_rtcp_port, destination);
-  rtp_session_set_fd (rtp_session, rtp_sock, rtcp_sock);
-  free (destination);
-
-  mp_msg (MSGT_OPEN, MSGL_V, "RTP Sock : %d\nRTCP Sock : %d\n",
-          rtp_session->rtp_socket, rtp_session->rtcp_socket);
-
-  if (rtp_session->rtp_socket == -1)
-  {
-    rtp_session_free (rtp_session);
-    return NULL;
-  }
-
-  return rtp_session;
-}
--- a/libmpdemux/librtsp/rtsp_rtp.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- *  Copyright (C) 2006 Benjamin Zores
- *   heavily base on the Freebox patch for xine by Vincent Mussard
- *   but with many enhancements for better RTSP RFC compliance.
- *
- *   This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software Foundation,
- *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _HAVE_RTSP_RTP_H_
-#define _HAVE_RTSP_RTP_H_
-
-#include "rtsp.h"
-
-#define MAX_PREVIEW_SIZE 4096
-
-struct rtp_rtsp_session_t {
-  int rtp_socket;
-  int rtcp_socket;
-  char *control_url;
-  int count;
-};
-
-struct rtp_rtsp_session_t *rtp_setup_and_play (rtsp_t* rtsp_session);
-off_t rtp_read (struct rtp_rtsp_session_t* st, char *buf, off_t length);
-void rtp_session_free (struct rtp_rtsp_session_t *st);
-void rtcp_send_rr (rtsp_t *s, struct rtp_rtsp_session_t *st);
-
-#endif /* _HAVE_RTSP_RTP_H_ */
-
--- a/libmpdemux/librtsp/rtsp_session.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,269 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp_session.c,v 1.9 2003/02/11 16:20:40
- */
-
-/*
- * Copyright (C) 2000-2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * high level interface to rtsp servers.
- *
- *    2006, Benjamin Zores and Vincent Mussard
- *      Support for MPEG-TS streaming through RFC compliant RTSP servers
- */
-
-#include <sys/types.h>
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#include <winsock2.h>
-#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
-#include "mp_msg.h"
-#include "../rtp.h"
-#include "rtsp.h"
-#include "rtsp_rtp.h"
-#include "rtsp_session.h"
-#include "../realrtsp/real.h"
-#include "../realrtsp/rmff.h"
-#include "../realrtsp/asmrp.h"
-#include "../realrtsp/xbuffer.h"
-
-/*
-#define LOG
-*/
-
-#define RTSP_OPTIONS_PUBLIC "Public"
-#define RTSP_OPTIONS_SERVER "Server"
-#define RTSP_OPTIONS_LOCATION "Location"
-#define RTSP_OPTIONS_REAL "RealChallenge1"
-#define RTSP_SERVER_TYPE_REAL "Real"
-#define RTSP_SERVER_TYPE_HELIX "Helix"
-#define RTSP_SERVER_TYPE_UNKNOWN "unknown"
-
-struct rtsp_session_s {
-  rtsp_t       *s;
-  struct real_rtsp_session_t* real_session;
-  struct rtp_rtsp_session_t* rtp_session;
-};
-
-//rtsp_session_t *rtsp_session_start(char *mrl) {
-rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth) {
-
-  rtsp_session_t *rtsp_session = NULL;
-  char *server;
-  char *mrl_line = NULL;
-  rmff_header_t *h;
-
-  rtsp_session = malloc (sizeof (rtsp_session_t));
-  rtsp_session->s = NULL;
-  rtsp_session->real_session = NULL;
-  rtsp_session->rtp_session = NULL;
- 
-//connect:
-  *redir = 0;
-
-  /* connect to server */
-  rtsp_session->s=rtsp_connect(fd,*mrl,path,host,port,NULL);
-  if (!rtsp_session->s)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: failed to connect to server %s\n", path);
-    free(rtsp_session);
-    return NULL;
-  }
-
-  /* looking for server type */
-  if (rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_SERVER))
-    server=strdup(rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_SERVER));
-  else {
-    if (rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_REAL))
-      server=strdup(RTSP_SERVER_TYPE_REAL);
-    else
-      server=strdup(RTSP_SERVER_TYPE_UNKNOWN);
-  }
-  if (strstr(server,RTSP_SERVER_TYPE_REAL) || strstr(server,RTSP_SERVER_TYPE_HELIX))
-  {
-    /* we are talking to a real server ... */
-
-    h=real_setup_and_get_header(rtsp_session->s, bandwidth);
-    if (!h) {
-      /* got an redirect? */
-      if (rtsp_search_answers(rtsp_session->s, RTSP_OPTIONS_LOCATION))
-      {
-        free(mrl_line);
-	mrl_line=strdup(rtsp_search_answers(rtsp_session->s, RTSP_OPTIONS_LOCATION));
-        mp_msg (MSGT_OPEN, MSGL_INFO,"rtsp_session: redirected to %s\n", mrl_line);
-	rtsp_close(rtsp_session->s);
-	free(server);
-        free(*mrl);
-        free(rtsp_session);
-        /* tell the caller to redirect, return url to redirect to in mrl */
-        *mrl = mrl_line;
-        *redir = 1;
-        return NULL;
-//	goto connect; /* *shudder* i made a design mistake somewhere */
-      } else
-      {
-        mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: session can not be established.\n");
-        rtsp_close(rtsp_session->s);
-        free (server);
-        free(rtsp_session);
-        return NULL;
-      }
-    }
-	
-    rtsp_session->real_session = init_real_rtsp_session ();
-    rtsp_session->real_session->header_len =
-      rmff_dump_header (h, (char *) rtsp_session->real_session->header, 1024);
-
-    rtsp_session->real_session->recv =
-      xbuffer_copyin (rtsp_session->real_session->recv, 0,
-                      rtsp_session->real_session->header,
-                      rtsp_session->real_session->header_len);
-
-    rtsp_session->real_session->recv_size =
-      rtsp_session->real_session->header_len;
-    rtsp_session->real_session->recv_read = 0;
-  } else /* not a Real server : try RTP instead */
-  {
-    char *public = NULL;
-
-    /* look for the Public: field in response to RTSP OPTIONS */
-    public = strdup (rtsp_search_answers (rtsp_session->s,
-                                          RTSP_OPTIONS_PUBLIC));
-    if (!public)
-    {
-      rtsp_close (rtsp_session->s);
-      free (server);
-      free (mrl_line);
-      free (rtsp_session);
-      return NULL;
-    }
-
-    /* check for minimalistic RTSP RFC compliance */
-    if (!strstr (public, RTSP_METHOD_DESCRIBE)
-        || !strstr (public, RTSP_METHOD_SETUP)
-        || !strstr (public, RTSP_METHOD_PLAY)
-        || !strstr (public, RTSP_METHOD_TEARDOWN))
-    {
-      free (public);
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "Remote server does not meet minimal RTSP 1.0 compliance.\n");
-      rtsp_close (rtsp_session->s);
-      free (server);
-      free (mrl_line);
-      free (rtsp_session);
-      return NULL;
-    }
-
-    free (public);
-    rtsp_session->rtp_session = rtp_setup_and_play (rtsp_session->s);
-
-    /* neither a Real or an RTP server */
-    if (!rtsp_session->rtp_session)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR, "rtsp_session: unsupported RTSP server. ");
-      mp_msg (MSGT_OPEN, MSGL_ERR, "Server type is '%s'.\n", server);
-      rtsp_close (rtsp_session->s);
-      free (server);
-      free (mrl_line);
-      free (rtsp_session);
-      return NULL;
-    }
-  }
-  free(server);
-  
-  return rtsp_session;
-}
-
-int rtsp_session_read (rtsp_session_t *this, char *data, int len) {
-  
-  if (this->real_session) {
-  int to_copy=len;
-  char *dest=data;
-  char *source =
-    (char *) (this->real_session->recv + this->real_session->recv_read);
-  int fill = this->real_session->recv_size - this->real_session->recv_read;
-
-  if (len < 0) return 0;
-  while (to_copy > fill) {
-    
-    memcpy(dest, source, fill);
-    to_copy -= fill;
-    dest += fill;
-    this->real_session->recv_read = 0;
-    this->real_session->recv_size =
-      real_get_rdt_chunk (this->s, (char **)&(this->real_session->recv));
-    if (this->real_session->recv_size < 0)
-      return -1;
-    source = (char *) this->real_session->recv;
-    fill = this->real_session->recv_size;
-
-    if (this->real_session->recv_size == 0) {
-#ifdef LOG
-      mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d of %d bytes provided\n", len-to_copy, len);
-#endif
-      return len-to_copy;
-    }
-  }
-  
-  memcpy(dest, source, to_copy);
-  this->real_session->recv_read += to_copy;
-
-#ifdef LOG
-  mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d bytes provided\n", len);
-#endif
-
-  return len;
-  }
-  else if (this->rtp_session)
-  {
-    int l = 0;
-
-    l = read_rtp_from_server (this->rtp_session->rtp_socket, data, len);
-    /* send RTSP and RTCP keepalive  */
-    rtcp_send_rr (this->s, this->rtp_session);
-
-    if (l == 0)
-      rtsp_session_end (this);
-    
-    return l;
-  }
-
-  return 0;
-}
-
-void rtsp_session_end(rtsp_session_t *session) {
-
-  rtsp_close(session->s);
-  if (session->real_session)
-    free_real_rtsp_session (session->real_session);
-  if (session->rtp_session)
-    rtp_session_free (session->rtp_session);
-  free(session);
-}
--- a/libmpdemux/librtsp/rtsp_session.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rtsp_session.h,v 1.4 2003/01/31 14:06:18
- */
-
-/*
- * Copyright (C) 2000-2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * high level interface to rtsp servers.
- *
- *    2006, Benjamin Zores and Vincent Mussard
- *      Support for MPEG-TS streaming through RFC compliant RTSP servers
- */
-
-#ifndef HAVE_RTSP_SESSION_H
-#define HAVE_RTSP_SESSION_H
-
-typedef struct rtsp_session_s rtsp_session_t;
-
-rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth);
-
-int rtsp_session_read(rtsp_session_t *session, char *data, int len);
-
-void rtsp_session_end(rtsp_session_t *session);
-
-#endif
--- a/libmpdemux/mf.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "config.h"
-
-#ifdef HAVE_GLOB
-#include <glob.h>
-#else
-#include "osdep/glob.h"
-#endif
-
-#include "mp_msg.h"
-#include "help_mp.h"
-#include "stream.h"
-
-#include "mf.h"
-
-int    mf_w = 0; //352; // let codecs to detect it
-int    mf_h = 0; //288;
-float  mf_fps = 25.0;
-char * mf_type = NULL; //"jpg";
-
-mf_t* open_mf(char * filename){
-#if defined(HAVE_GLOB) || defined(__MINGW32__)
- glob_t        gg;
- struct stat   fs;
- int           i;
- char        * fname;
- mf_t        * mf;
- int           error_count = 0;
- int	       count = 0;
-
- mf=calloc( 1,sizeof( mf_t ) );
-
- if( filename[0] == '@' )
-  { 
-   FILE *lst_f=fopen(filename + 1,"r");
-   if ( lst_f ) 
-    {
-     fname=malloc( 255 );
-     while ( fgets( fname,255,lst_f ) ) 
-      {
-       /* remove spaces from end of fname */
-       char *t=fname + strlen( fname ) - 1;
-       while ( t > fname && isspace( *t ) ) *(t--)=0;
-       if ( stat( fname,&fs ) ) 
-        {
-         mp_msg( MSGT_STREAM,MSGL_V,"[mf] file not found: '%s'\n",fname );
-        }
-        else
-        {
-         mf->names=realloc( mf->names,( mf->nr_of_files + 1 ) * sizeof( char* ) );
-         mf->names[mf->nr_of_files]=strdup( fname );
-         mf->nr_of_files++;
-        }
-      }
-      fclose( lst_f );
-	     
-      mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d\n",mf->nr_of_files );
-      goto exit_mf;
-    }
-    mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] %s is not indirect filelist\n",filename+1 );
-  }
-
- if( strchr( filename,',') )
-  { 
-   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] filelist: %s\n",filename );
- 
-   while ( ( fname=strsep( &filename,"," ) ) )
-    {
-     if ( stat( fname,&fs ) ) 
-      {
-       mp_msg( MSGT_STREAM,MSGL_V,"[mf] file not found: '%s'\n",fname );
-      }
-      else
-      {
-       mf->names=realloc( mf->names,( mf->nr_of_files + 1 ) * sizeof( char* ) );
-       mf->names[mf->nr_of_files]=strdup( fname );
-//       mp_msg( MSGT_STREAM,MSGL_V,"[mf] added file %d.: %s\n",mf->nr_of_files,mf->names[mf->nr_of_files] );
-       mf->nr_of_files++;
-      }
-    }
-   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d\n",mf->nr_of_files );
- 
-   goto exit_mf;
-  } 
-
- fname=malloc( strlen( filename ) + 32 );
-
- if ( !strchr( filename,'%' ) )
-  {
-   strcpy( fname,filename ); 
-   if ( !strchr( filename,'*' ) ) strcat( fname,"*" );
-
-   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] search expr: %s\n",fname );
-
-   if ( glob( fname,0,NULL,&gg ) )
-    { free( mf ); free( fname ); return NULL; }
-
-   mf->nr_of_files=gg.gl_pathc;
-   mf->names=calloc( gg.gl_pathc, sizeof( char* ) );
-
-   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d (%d)\n",mf->nr_of_files, gg.gl_pathc * sizeof( char* ) );
-
-   for( i=0;i < gg.gl_pathc;i++ )
-    {
-     stat( gg.gl_pathv[i],&fs );
-     if( S_ISDIR( fs.st_mode ) ) continue;
-     mf->names[i]=strdup( gg.gl_pathv[i] );
-//     mp_msg( MSGT_STREAM,MSGL_DBG2,"[mf] added file %d.: %s\n",i,mf->names[i] );
-    }
-   globfree( &gg );
-   goto exit_mf;
-  }
-
- mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] search expr: %s\n",filename );
- 
- while ( error_count < 5 )
-  {
-   sprintf( fname,filename,count++ );
-   if ( stat( fname,&fs ) ) 
-    {
-     error_count++;
-     mp_msg( MSGT_STREAM,MSGL_V,"[mf] file not found: '%s'\n",fname );
-    }
-    else
-    {
-     mf->names=realloc( mf->names,( mf->nr_of_files + 1 ) * sizeof( char* ) );
-     mf->names[mf->nr_of_files]=strdup( fname );
-//     mp_msg( MSGT_STREAM,MSGL_V,"[mf] added file %d.: %s\n",mf->nr_of_files,mf->names[mf->nr_of_files] );
-     mf->nr_of_files++;
-    }
-  }
-
- mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d\n",mf->nr_of_files );
-
-exit_mf:
- free( fname );
- return mf;
-#else
- mp_msg(MSGT_STREAM,MSGL_FATAL,"[mf] mf support is disabled on your os\n");
- return 0;
-#endif
-}
-
--- a/libmpdemux/mf.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-
-#ifndef _MF_H
-#define _MF_H
-
-extern int    mf_w;
-extern int    mf_h;
-extern float  mf_fps;
-extern char * mf_type;
-
-typedef struct
-{
- int curr_frame;
- int nr_of_files;
- char ** names;
-} mf_t;
-
-mf_t* open_mf(char * filename);
-
-#endif
--- a/libmpdemux/netstream.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-
-/*
- * Common stuff for netstream
- * Packets and so on are defined here along with a few helpers
- * wich are used by both the client and the server
- *
- * Data is always low endian
- */
-
-typedef struct mp_net_stream_packet_st {
-  uint16_t len;
-  uint8_t cmd;
-  char data[0];
-} __attribute__ ((packed))  mp_net_stream_packet_t;
-
-#define PACKET_MAX_SIZE 4096
-
-// Commands sent by the client
-#define NET_STREAM_OPEN 0
-// data is the url
-#define NET_STREAM_FILL_BUFFER 1
-// data is an uint16 wich is the max len of the data to return
-#define NET_STREAM_SEEK 3
-// data is an uint64 wich the pos where to seek
-#define NET_STREAM_CLOSE 4
-// no data
-#define NET_STREAM_RESET 5
-// no data
-
-// Server response
-#define NET_STREAM_OK 128
-// Data returned if open is successful
-typedef struct mp_net_stream_opened_st {
-  uint32_t file_format;
-  uint32_t flags;
-  uint32_t sector_size;
-  uint64_t start_pos;
-  uint64_t end_pos;
-}  __attribute__ ((packed))  mp_net_stream_opened_t;
-// FILL_BUFFER return the data
-// CLOSE return nothing
-#define NET_STREAM_ERROR 129
-// Data is the error message (if any ;)
-
-static int net_read(int fd, char* buf, int len) {
-  int r = 0;
-  while(len) {
-    r = recv(fd,buf,len,0);
-    if(r <= 0) {
-      if(errno == EINTR) continue;
-      if(r < 0)
-	mp_msg(MSGT_NETST,MSGL_ERR,"Read failed: %s\n",strerror(errno));
-      return 0;
-    }
-    len -= r;
-    buf += r;
-  }
-  return 1;
-}
-
-static mp_net_stream_packet_t* read_packet(int fd) {
-  uint16_t len;
-  mp_net_stream_packet_t* pack = 
-    (mp_net_stream_packet_t*)malloc(sizeof(mp_net_stream_packet_t));
-  
-  if(!net_read(fd,(char*)pack,sizeof(mp_net_stream_packet_t))) {
-    free(pack);
-    return NULL;
-  }
-  pack->len = le2me_16(pack->len);
-
-  if(pack->len < sizeof(mp_net_stream_packet_t)) {
-    mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid packet (too small: %d)\n",pack->len);
-    free(pack);
-    return NULL;
-  }
-  if(pack->len > PACKET_MAX_SIZE) {
-    mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid packet (too big: %d)\n",pack->len);
-    free(pack);
-    return NULL;
-  }
-  len = pack->len;
-  if(len > sizeof(mp_net_stream_packet_t)) {
-    pack = realloc(pack,len);
-    if(!pack) {
-      mp_msg(MSGT_NETST,MSGL_ERR,"Failed to get memory for the packet (%d bytes)\n",len);
-      return NULL;
-    }
-    if(!net_read(fd,pack->data,len - sizeof(mp_net_stream_packet_t)))
-      return NULL;
-  }
-  //  printf ("Read packet %d %d %d\n",fd,pack->cmd,pack->len);
-  return pack;
-}
-
-static int net_write(int fd, char* buf, int len) {
-  int w;
-  while(len) {
-    w = send(fd,buf,len,0);
-    if(w <= 0) {
-      if(errno == EINTR) continue;
-      if(w < 0)
-	mp_msg(MSGT_NETST,MSGL_ERR,"Write failed: %s\n",strerror(errno));
-      return 0;
-    }
-    len -= w;
-    buf += w;
-  }
-  return 1;
-}
-
-static int write_packet(int fd, uint8_t cmd,char* data,int len) {
-  mp_net_stream_packet_t* pack = malloc(len + sizeof(mp_net_stream_packet_t));
-  
-  if(len > 0 && data)
-    memcpy(pack->data,data,len);
-  pack->len = len + sizeof(mp_net_stream_packet_t);
-  pack->cmd = cmd;
-  
-  //  printf("Write packet %d %d (%p) %d\n",fd,cmd,data,len);
-  pack->len = le2me_16(pack->len);
-  if(net_write(fd,(char*)pack,pack->len)) {
-    free(pack);
-    return 1;
-  }
-  free(pack);
-  return 0;
-}
-
-static void net_stream_opened_2_me(mp_net_stream_opened_t* o) {
-  o->file_format = le2me_32(o->file_format);
-  o->flags = le2me_32(o->flags);
-  o->sector_size = le2me_32(o->sector_size);
-  o->start_pos = le2me_64(o->start_pos);
-  o->end_pos = le2me_64(o->end_pos);
-}
--- a/libmpdemux/network.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,657 +0,0 @@
-/*
- * Network layer for MPlayer
- * by Bertrand BAUDET <bertrand_baudet@yahoo.com>
- * (C) 2001, MPlayer team.
- */
-
-//#define DUMP2FILE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <errno.h>
-#include <ctype.h>
-
-#include "config.h"
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-
-#include "stream.h"
-#include "demuxer.h"
-#include "m_config.h"
-
-#include "network.h"
-#include "http.h"
-#include "cookies.h"
-#include "url.h"
-
-#include "version.h"
-
-extern int stream_cache_size;
-
-extern int mp_input_check_interrupt(int time);
-
-/* Variables for the command line option -user, -passwd, -bandwidth,
-   -user-agent and -nocookies */
-
-char *network_username=NULL;
-char *network_password=NULL;
-int   network_bandwidth=0;
-int   network_cookies_enabled = 0;
-char *network_useragent=NULL;
-
-/* IPv6 options */
-int   network_prefer_ipv4 = 0;
-int   network_ipv4_only_proxy = 0;
-
-
-mime_struct_t mime_type_table[] = {
-	// MP3 streaming, some MP3 streaming server answer with audio/mpeg
-	{ "audio/mpeg", DEMUXER_TYPE_AUDIO },
-	// MPEG streaming
-	{ "video/mpeg", DEMUXER_TYPE_UNKNOWN },
-	{ "video/x-mpeg", DEMUXER_TYPE_UNKNOWN },
-	{ "video/x-mpeg2", DEMUXER_TYPE_UNKNOWN },
-	// AVI ??? => video/x-msvideo
-	{ "video/x-msvideo", DEMUXER_TYPE_AVI },
-	// MOV => video/quicktime
-	{ "video/quicktime", DEMUXER_TYPE_MOV },
-	// ASF
-        { "audio/x-ms-wax", DEMUXER_TYPE_ASF },
-	{ "audio/x-ms-wma", DEMUXER_TYPE_ASF },
-	{ "video/x-ms-asf", DEMUXER_TYPE_ASF },
-	{ "video/x-ms-afs", DEMUXER_TYPE_ASF },
-	{ "video/x-ms-wvx", DEMUXER_TYPE_ASF },
-	{ "video/x-ms-wmv", DEMUXER_TYPE_ASF },
-	{ "video/x-ms-wma", DEMUXER_TYPE_ASF },
-	{ "application/x-mms-framed", DEMUXER_TYPE_ASF },
-	{ "application/vnd.ms.wms-hdr.asfv1", DEMUXER_TYPE_ASF },
-	{ "application/octet-stream", DEMUXER_TYPE_ASF },
-	// Playlists
-	{ "video/x-ms-wmx", DEMUXER_TYPE_PLAYLIST },
-	{ "audio/x-scpls", DEMUXER_TYPE_PLAYLIST },
-	{ "audio/x-mpegurl", DEMUXER_TYPE_PLAYLIST },
-	{ "audio/x-pls", DEMUXER_TYPE_PLAYLIST },
-	// Real Media
-//	{ "audio/x-pn-realaudio", DEMUXER_TYPE_REAL },
-	// OGG Streaming
-	{ "application/x-ogg", DEMUXER_TYPE_OGG },
-	// NullSoft Streaming Video
-	{ "video/nsv", DEMUXER_TYPE_NSV},
-	{ "misc/ultravox", DEMUXER_TYPE_NSV},
-	{ NULL, DEMUXER_TYPE_UNKNOWN},
-};
-
-
-streaming_ctrl_t *
-streaming_ctrl_new(void) {
-	streaming_ctrl_t *streaming_ctrl;
-	streaming_ctrl = malloc(sizeof(streaming_ctrl_t));
-	if( streaming_ctrl==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-		return NULL;
-	}
-	memset( streaming_ctrl, 0, sizeof(streaming_ctrl_t) );
-	return streaming_ctrl;
-}
-
-void
-streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl ) {
-	if( streaming_ctrl==NULL ) return;
-	if( streaming_ctrl->url ) url_free( streaming_ctrl->url );
-	if( streaming_ctrl->buffer ) free( streaming_ctrl->buffer );
-	if( streaming_ctrl->data ) free( streaming_ctrl->data );
-	free( streaming_ctrl );
-}
-
-
-// Converts an address family constant to a string
-
-const char *af2String(int af) {
-	switch (af) {
-		case AF_INET:	return "AF_INET";
-		
-#ifdef HAVE_AF_INET6
-		case AF_INET6:	return "AF_INET6";
-#endif
-		default:	return "Unknown address family!";
-	}
-}
-
-
-
-// Connect to a server using a TCP connection, with specified address family
-// return -2 for fatal error, like unable to resolve name, connection timeout...
-// return -1 is unable to connect to a particular port
-
-int
-connect2Server_with_af(char *host, int port, int af,int verb) {
-	int socket_server_fd;
-	int err, err_len;
-	int ret,count = 0;
-	fd_set set;
-	struct timeval tv;
-	union {
-		struct sockaddr_in four;
-#ifdef HAVE_AF_INET6
-		struct sockaddr_in6 six;
-#endif
-	} server_address;
-	size_t server_address_size;
-	void *our_s_addr;	// Pointer to sin_addr or sin6_addr
-	struct hostent *hp=NULL;
-	char buf[255];
-	
-#ifdef HAVE_WINSOCK2
-	u_long val;
-#endif
-	
-	socket_server_fd = socket(af, SOCK_STREAM, 0);
-	
-	
-	if( socket_server_fd==-1 ) {
-//		mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af));
-		return -2;
-	}
-
-	switch (af) {
-		case AF_INET:  our_s_addr = (void *) &server_address.four.sin_addr; break;
-#ifdef HAVE_AF_INET6
-		case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break;
-#endif
-		default:
-			mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af);
-			return -2;
-	}
-	
-	
-	memset(&server_address, 0, sizeof(server_address));
-	
-#ifndef HAVE_WINSOCK2
-#ifdef USE_ATON
-	if (inet_aton(host, our_s_addr)!=1)
-#else
-	if (inet_pton(af, host, our_s_addr)!=1)
-#endif
-#else
-	if ( inet_addr(host)==INADDR_NONE )
-#endif
-	{
-		if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af));
-		
-#ifdef HAVE_GETHOSTBYNAME2
-		hp=(struct hostent*)gethostbyname2( host, af );
-#else
-		hp=(struct hostent*)gethostbyname( host );
-#endif
-		if( hp==NULL ) {
-			if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host);
-			return -2;
-		}
-		
-		memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length );
-	}
-#ifdef HAVE_WINSOCK2
-	else {
-		unsigned long addr = inet_addr(host);
-		memcpy( our_s_addr, (void*)&addr, sizeof(addr) );
-	}
-#endif
-	
-	switch (af) {
-		case AF_INET:
-			server_address.four.sin_family=af;
-			server_address.four.sin_port=htons(port);			
-			server_address_size = sizeof(server_address.four);
-			break;
-#ifdef HAVE_AF_INET6		
-		case AF_INET6:
-			server_address.six.sin6_family=af;
-			server_address.six.sin6_port=htons(port);
-			server_address_size = sizeof(server_address.six);
-			break;
-#endif
-		default:
-			mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af);
-			return -2;
-	}
-
-#if defined(USE_ATON) || defined(HAVE_WINSOCK2)
-	strncpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255);
-#else
-	inet_ntop(af, our_s_addr, buf, 255);
-#endif
-	if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port );
-
-	// Turn the socket as non blocking so we can timeout on the connection
-#ifndef HAVE_WINSOCK2
-	fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK );
-#else
-	val = 1;
-	ioctlsocket( socket_server_fd, FIONBIO, &val );
-#endif
-	if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) {
-#ifndef HAVE_WINSOCK2
-		if( errno!=EINPROGRESS ) {
-#else
-		if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) {
-#endif
-			if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af));
-			closesocket(socket_server_fd);
-			return -1;
-		}
-	}
-	tv.tv_sec = 0;
-	tv.tv_usec = 500000;
-	FD_ZERO( &set );
-	FD_SET( socket_server_fd, &set );
-	// When the connection will be made, we will have a writable fd
-	while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) {
-	      if( ret<0 ) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed);
-	      else if(ret > 0) break;
-	      else if(count > 30 || mp_input_check_interrupt(500)) {
-		if(count > 30)
-		  mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout);
-		else
-		  mp_msg(MSGT_NETWORK,MSGL_V,"Connection interuppted by user\n");
-		return -3;
-	      }
-	      count++;
-	      FD_ZERO( &set );
-	      FD_SET( socket_server_fd, &set );
-	      tv.tv_sec = 0;
-	      tv.tv_usec = 500000;
-	}
-
-	// Turn back the socket as blocking
-#ifndef HAVE_WINSOCK2
-	fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK );
-#else
-	val = 0;
-	ioctlsocket( socket_server_fd, FIONBIO, &val );
-#endif
-	// Check if there were any error
-	err_len = sizeof(int);
-	ret =  getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len);
-	if(ret < 0) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno));
-		return -2;
-	}
-	if(err > 0) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err));
-		return -1;
-	}
-	
-	return socket_server_fd;
-}
-
-// Connect to a server using a TCP connection
-// return -2 for fatal error, like unable to resolve name, connection timeout...
-// return -1 is unable to connect to a particular port
-
-
-int
-connect2Server(char *host, int  port, int verb) {
-#ifdef HAVE_AF_INET6
-	int r;
-	int s = -2;
-
-	r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6,verb);	
-	if (r > -1) return r;
-
-	s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET,verb);
-	if (s == -2) return r;
-	return s;
-#else	
-	return connect2Server_with_af(host, port, AF_INET,verb);
-#endif
-
-	
-}
-
-URL_t*
-check4proxies( URL_t *url ) {
-	URL_t *url_out = NULL;
-	if( url==NULL ) return NULL;
-	url_out = url_new( url->url );
-	if( !strcasecmp(url->protocol, "http_proxy") ) {
-		mp_msg(MSGT_NETWORK,MSGL_V,"Using HTTP proxy: http://%s:%d\n", url->hostname, url->port );
-		return url_out;
-	}
-	// Check if the http_proxy environment variable is set.
-	if( !strcasecmp(url->protocol, "http") ) {
-		char *proxy;
-		proxy = getenv("http_proxy");
-		if( proxy!=NULL ) {
-			// We got a proxy, build the URL to use it
-			int len;
-			char *new_url;
-			URL_t *tmp_url;
-			URL_t *proxy_url = url_new( proxy );
-
-			if( proxy_url==NULL ) {
-				mp_msg(MSGT_NETWORK,MSGL_WARN,
-					MSGTR_MPDEMUX_NW_InvalidProxySettingTryingWithout);
-				return url_out;
-			}
-			
-#ifdef HAVE_AF_INET6
-			if (network_ipv4_only_proxy && (gethostbyname(url->hostname)==NULL)) {
-				mp_msg(MSGT_NETWORK,MSGL_WARN,
-					MSGTR_MPDEMUX_NW_CantResolvTryingWithoutProxy);
-				url_free(proxy_url);
-				return url_out;
-			}
-#endif
-
-			mp_msg(MSGT_NETWORK,MSGL_V,"Using HTTP proxy: %s\n", proxy_url->url );
-			len = strlen( proxy_url->hostname ) + strlen( url->url ) + 20;	// 20 = http_proxy:// + port
-			new_url = malloc( len+1 );
-			if( new_url==NULL ) {
-				mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-				url_free(proxy_url);
-				return url_out;
-			}
-			sprintf(new_url, "http_proxy://%s:%d/%s", proxy_url->hostname, proxy_url->port, url->url );
-			tmp_url = url_new( new_url );
-			if( tmp_url==NULL ) {
-				free( new_url );
-				url_free( proxy_url );
-				return url_out;
-			}
-			url_free( url_out );
-			url_out = tmp_url;
-			free( new_url );
-			url_free( proxy_url );
-		}
-	}
-	return url_out;
-}
-
-int
-http_send_request( URL_t *url, off_t pos ) {
-	HTTP_header_t *http_hdr;
-	URL_t *server_url;
-	char str[256];
-	int fd;
-	int ret;
-	int proxy = 0;		// Boolean
-
-	http_hdr = http_new_header();
-
-	if( !strcasecmp(url->protocol, "http_proxy") ) {
-		proxy = 1;
-		server_url = url_new( (url->file)+1 );
-		http_set_uri( http_hdr, server_url->url );
-	} else {
-		server_url = url;
-		http_set_uri( http_hdr, server_url->file );
-	}
-	if (server_url->port && server_url->port != 80)
-	    snprintf(str, 256, "Host: %s:%d", server_url->hostname, server_url->port );
-	else
-	    snprintf(str, 256, "Host: %s", server_url->hostname );
-	http_set_field( http_hdr, str);
-	if (network_useragent)
-	{
-	    snprintf(str, 256, "User-Agent: %s", network_useragent);
-	    http_set_field(http_hdr, str);
-	}
-	else
-	    http_set_field( http_hdr, "User-Agent: MPlayer/"VERSION);
-
-	http_set_field(http_hdr, "Icy-MetaData: 1");
-
-	if(pos>0) { 
-	// Extend http_send_request with possibility to do partial content retrieval
-	    snprintf(str, 256, "Range: bytes=%"PRId64"-", (int64_t)pos);
-	    http_set_field(http_hdr, str);
-	}
-	    
-	if (network_cookies_enabled) cookies_set( http_hdr, server_url->hostname, server_url->url );
-	
-	http_set_field( http_hdr, "Connection: close");
-	http_add_basic_authentication( http_hdr, url->username, url->password );
-	if( http_build_request( http_hdr )==NULL ) {
-		goto err_out;
-	}
-
-	if( proxy ) {
-		if( url->port==0 ) url->port = 8080;			// Default port for the proxy server
-		fd = connect2Server( url->hostname, url->port,1 );
-		url_free( server_url );
-		server_url = NULL;
-	} else {
-		if( server_url->port==0 ) server_url->port = 80;	// Default port for the web server
-		fd = connect2Server( server_url->hostname, server_url->port,1 );
-	}
-	if( fd<0 ) {
-		goto err_out;
-	}
-	mp_msg(MSGT_NETWORK,MSGL_DBG2,"Request: [%s]\n", http_hdr->buffer );
-	
-	ret = send( fd, http_hdr->buffer, http_hdr->buffer_size, 0 );
-	if( ret!=(int)http_hdr->buffer_size ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ErrSendingHTTPRequest);
-		goto err_out;
-	}
-	
-	http_free( http_hdr );
-
-	return fd;
-err_out:
-	http_free(http_hdr);
-	if (proxy && server_url)
-		url_free(server_url);
-	return -1;
-}
-
-HTTP_header_t *
-http_read_response( int fd ) {
-	HTTP_header_t *http_hdr;
-	char response[BUFFER_SIZE];
-	int i;
-
-	http_hdr = http_new_header();
-	if( http_hdr==NULL ) {
-		return NULL;
-	}
-
-	do {
-		i = recv( fd, response, BUFFER_SIZE, 0 ); 
-		if( i<0 ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ReadFailed);
-			http_free( http_hdr );
-			return NULL;
-		}
-		if( i==0 ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_Read0CouldBeEOF);
-			http_free( http_hdr );
-			return NULL;
-		}
-		http_response_append( http_hdr, response, i );
-	} while( !http_is_header_entire( http_hdr ) ); 
-	http_response_parse( http_hdr );
-	return http_hdr;
-}
-
-int
-http_authenticate(HTTP_header_t *http_hdr, URL_t *url, int *auth_retry) {
-	char *aut;
-
-	if( *auth_retry==1 ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_AuthFailed);
-		return -1;
-	}
-	if( *auth_retry>0 ) {
-		if( url->username ) {
-			free( url->username );
-			url->username = NULL;
-		}
-		if( url->password ) {
-			free( url->password );
-			url->password = NULL;
-		}
-	}
-
-	aut = http_get_field(http_hdr, "WWW-Authenticate");
-	if( aut!=NULL ) {
-		char *aut_space;
-		aut_space = strstr(aut, "realm=");
-		if( aut_space!=NULL ) aut_space += 6;
-		mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_AuthRequiredFor, aut_space);
-	} else {
-		mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_AuthRequired);
-	}
-	if( network_username ) {
-		url->username = strdup(network_username);
-		if( url->username==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-			return -1;
-		}
-	} else {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_AuthFailed);
-		return -1;
-	}
-	if( network_password ) {
-		url->password = strdup(network_password);
-		if( url->password==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-			return -1;
-		}
-	} else {
-		mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_NoPasswdProvidedTryingBlank);
-	}
-	(*auth_retry)++;
-	return 0;
-}
-
-int
-http_seek( stream_t *stream, off_t pos ) {
-	HTTP_header_t *http_hdr = NULL;
-	int fd;
-	if( stream==NULL ) return 0;
-
-	if( stream->fd>0 ) closesocket(stream->fd); // need to reconnect to seek in http-stream
-	fd = http_send_request( stream->streaming_ctrl->url, pos ); 
-	if( fd<0 ) return 0;
-
-	http_hdr = http_read_response( fd );
-
-	if( http_hdr==NULL ) return 0;
-
-	switch( http_hdr->status_code ) {
-		case 200:
-		case 206: // OK
-			mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") );
-			mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") );
-			if( http_hdr->body_size>0 ) {
-				if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
-					http_free( http_hdr );
-					return -1;
-				}
-			}
-			break;
-		default:
-			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ErrServerReturned, http_hdr->status_code, http_hdr->reason_phrase );
-			close( fd );
-			fd = -1;
-	}
-	stream->fd = fd;
-
-	if( http_hdr ) {
-		http_free( http_hdr );
-		stream->streaming_ctrl->data = NULL;
-	}
-
-	stream->pos=pos;
-
-	return 1;
-}
-
-
-int
-streaming_bufferize( streaming_ctrl_t *streaming_ctrl, char *buffer, int size) {
-//printf("streaming_bufferize\n");
-	streaming_ctrl->buffer = malloc(size);
-	if( streaming_ctrl->buffer==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-		return -1;
-	}
-	memcpy( streaming_ctrl->buffer, buffer, size );
-	streaming_ctrl->buffer_size = size;
-	return size;
-}
-
-int
-nop_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) {
-	int len=0;
-//printf("nop_streaming_read\n");
-	if( stream_ctrl->buffer_size!=0 ) {
-		int buffer_len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos;
-//printf("%d bytes in buffer\n", stream_ctrl->buffer_size);
-		len = (size<buffer_len)?size:buffer_len;
-		memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len );
-		stream_ctrl->buffer_pos += len;
-//printf("buffer_pos = %d\n", stream_ctrl->buffer_pos );
-		if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) {
-			free( stream_ctrl->buffer );
-			stream_ctrl->buffer = NULL;
-			stream_ctrl->buffer_size = 0;
-			stream_ctrl->buffer_pos = 0;
-//printf("buffer cleaned\n");
-		}
-//printf("read %d bytes from buffer\n", len );
-	}
-
-	if( len<size ) {
-		int ret;
-		ret = recv( fd, buffer+len, size-len, 0 );
-		if( ret<0 ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_read error : %s\n",strerror(errno));
-		}
-		len += ret;
-//printf("read %d bytes from network\n", len );
-	}
-	
-	return len;
-}
-
-int
-nop_streaming_seek( int fd, off_t pos, streaming_ctrl_t *stream_ctrl ) {
-	return -1;
-	// To shut up gcc warning
-	fd++;
-	pos++;
-	stream_ctrl=NULL;
-}
-
-
-void fixup_network_stream_cache(stream_t *stream) {
-  if(stream->streaming_ctrl->buffering) {
-    if(stream_cache_size<0) {
-      // cache option not set, will use our computed value.
-      // buffer in KBytes, *5 because the prefill is 20% of the buffer.
-      stream_cache_size = (stream->streaming_ctrl->prebuffer_size/1024)*5;
-      if( stream_cache_size<64 ) stream_cache_size = 64;	// 16KBytes min buffer
-    }
-    mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_CacheSizeSetTo, stream_cache_size);
-  }
-}
-
-
-int
-streaming_stop( stream_t *stream ) {
-	stream->streaming_ctrl->status = streaming_stopped_e;
-	return 0;
-}
--- a/libmpdemux/network.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Network layer for MPlayer
- * by Bertrand BAUDET <bertrand_baudet@yahoo.com>
- * (C) 2001, MPlayer team.
- */
-
-#ifndef __NETWORK_H
-#define __NETWORK_H
-
-#include <fcntl.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#endif
-
-#include "url.h"
-#include "http.h"
-#include "stream.h"
-
-#define BUFFER_SIZE		2048
-
-typedef struct {
-	const char *mime_type;
-	int demuxer_type;
-} mime_struct_t;
-
-typedef enum {
-	streaming_stopped_e,
-	streaming_playing_e
-} streaming_status;
-
-typedef struct streaming_control {
-	URL_t *url;
-	streaming_status status;
-	int buffering;	// boolean
-	unsigned int prebuffer_size;
-	char *buffer;
-	unsigned int buffer_size;
-	unsigned int buffer_pos;
-	unsigned int bandwidth;	// The downstream available
-	int (*streaming_read)( int fd, char *buffer, int buffer_size, struct streaming_control *stream_ctrl );
-	int (*streaming_seek)( int fd, off_t pos, struct streaming_control *stream_ctrl );
-	void *data;
-} streaming_ctrl_t;
-
-//int streaming_start( stream_t *stream, int *demuxer_type, URL_t *url );
-streaming_ctrl_t *streaming_ctrl_new(void);
-int streaming_bufferize( streaming_ctrl_t *streaming_ctrl, char *buffer, int size);
-
-int nop_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl );
-int nop_streaming_seek( int fd, off_t pos, streaming_ctrl_t *stream_ctrl );
-void streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl );
-
-int connect2Server(char *host, int port,int verb);
-
-int http_send_request(URL_t *url, off_t pos);
-HTTP_header_t *http_read_response(int fd);
-
-int http_authenticate(HTTP_header_t *http_hdr, URL_t *url, int *auth_retry);
-URL_t* check4proxies(URL_t *url);
-
-#endif
--- a/libmpdemux/open.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#ifdef __FreeBSD__
-#include <sys/cdrio.h>
-#endif
-
-#include "m_option.h"
-#include "stream.h"
-#include "demuxer.h"
-#include "mf.h"
-
-
-/// We keep these 2 for the gui atm, but they will be removed.
-int vcd_track=0;
-char* cdrom_device=NULL;
-int dvd_chapter=1;
-int dvd_last_chapter=0;
-char* dvd_device=NULL;
-int dvd_title=0;
-
-// Open a new stream  (stdin/file/vcd/url)
-
-stream_t* open_stream(char* filename,char** options, int* file_format){
-  // Check if playlist or unknown 
-  if (*file_format != DEMUXER_TYPE_PLAYLIST){
-    *file_format=DEMUXER_TYPE_UNKNOWN;
-  }
-
-if(!filename) {
-   mp_msg(MSGT_OPEN,MSGL_ERR,"NULL filename, report this bug\n");
-   return NULL;
-}
-
-//============ Open STDIN or plain FILE ============
-
-  return open_stream_full(filename,STREAM_READ,options,file_format);
-}
-
--- a/libmpdemux/pnm.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,921 +0,0 @@
-/*
- * Copyright (C) 2000-2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- * $Id$
- *
- * pnm protocol implementation 
- * based upon code from joschka
- */
-
-#include "config.h"
-
-#include <unistd.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <inttypes.h>
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#include <sys/socket.h>
-//#include <netinet/in.h>
-//#include <netdb.h>
-#else
-#include <winsock2.h>
-#endif
-
-#include "stream.h"
-#include "demuxer.h"
-#include "help_mp.h"
-#include "osdep/timer.h"
-
-#include "pnm.h"
-//#include "libreal/rmff.h"
-
-extern int network_bandwidth;
-
-#define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
-        (((long)(unsigned char)(ch3)       ) | \
-        ( (long)(unsigned char)(ch2) << 8  ) | \
-        ( (long)(unsigned char)(ch1) << 16 ) | \
-        ( (long)(unsigned char)(ch0) << 24 ) )
-
-
-#define RMF_TAG   FOURCC_TAG('.', 'R', 'M', 'F')
-#define PROP_TAG  FOURCC_TAG('P', 'R', 'O', 'P')
-#define MDPR_TAG  FOURCC_TAG('M', 'D', 'P', 'R')
-#define CONT_TAG  FOURCC_TAG('C', 'O', 'N', 'T')
-#define DATA_TAG  FOURCC_TAG('D', 'A', 'T', 'A')
-#define INDX_TAG  FOURCC_TAG('I', 'N', 'D', 'X')
-#define PNA_TAG   FOURCC_TAG('P', 'N', 'A',  0 )
-
-/*
-#define LOG
-*/
-
-#define BUF_SIZE 4096
-#define HEADER_SIZE 4096
-
-struct pnm_s {
-
-  int           s;
-
-//  char         *host;
-//  int           port;
-  char         *path;
-//  char         *url;
-
-  char          buffer[BUF_SIZE]; /* scratch buffer */
-
-  /* receive buffer */
-  uint8_t       recv[BUF_SIZE];
-  int           recv_size;
-  int           recv_read;
-
-  uint8_t       header[HEADER_SIZE];
-  int           header_len;
-  int           header_read;
-  unsigned int  seq_num[4];     /* two streams with two indices   */
-  unsigned int  seq_current[2]; /* seqs of last stream chunk read */
-  uint32_t      ts_current;     /* timestamp of current chunk     */
-  uint32_t      ts_last[2];     /* timestamps of last chunks      */
-  unsigned int  packet;         /* number of last recieved packet */
-};
-
-/*
- * utility macros
- */
-
-#define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
-#define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
-                   (((uint8_t*)(x))[1] << 16) | \
-                   (((uint8_t*)(x))[2] << 8) | \
-                    ((uint8_t*)(x))[3])
-
-/* D means direct (no pointer) */
-#define BE_16D(x) ((x & 0xff00) >> 8)|((x & 0x00ff) << 8)
-
-/* sizes */
-#define PREAMBLE_SIZE 8
-#define CHECKSUM_SIZE 3
-
-
-/* header of rm files */
-#define RM_HEADER_SIZE 0x12
-static const unsigned char rm_header[]={
-        0x2e, 0x52, 0x4d, 0x46, /* object_id      ".RMF" */
-        0x00, 0x00, 0x00, 0x12, /* header_size    0x12   */
-        0x00, 0x00,             /* object_version 0x00   */
-        0x00, 0x00, 0x00, 0x00, /* file_version   0x00   */
-        0x00, 0x00, 0x00, 0x06  /* num_headers    0x06   */
-};
-
-/* data chunk header */
-#define PNM_DATA_HEADER_SIZE 18
-static const unsigned char pnm_data_header[]={
-        'D','A','T','A',
-         0,0,0,0,       /* data chunk size  */
-         0,0,           /* object version   */
-         0,0,0,0,       /* num packets      */
-         0,0,0,0};      /* next data header */
-
-/* pnm request chunk ids */
-
-#define PNA_CLIENT_CAPS      0x03
-#define PNA_CLIENT_CHALLANGE 0x04
-#define PNA_BANDWIDTH        0x05
-#define PNA_GUID             0x13
-#define PNA_TIMESTAMP        0x17
-#define PNA_TWENTYFOUR       0x18
-
-#define PNA_CLIENT_STRING    0x63
-#define PNA_PATH_REQUEST     0x52
-
-static const unsigned char pnm_challenge[] = "0990f6b4508b51e801bd6da011ad7b56";
-static const unsigned char pnm_timestamp[] = "[15/06/1999:22:22:49 00:00]";
-static const unsigned char pnm_guid[]      = "3eac2411-83d5-11d2-f3ea-d7c3a51aa8b0";
-static const unsigned char pnm_response[]  = "97715a899cbe41cee00dd434851535bf";
-static const unsigned char client_string[] = "WinNT_9.0_6.0.6.45_plus32_MP60_en-US_686l";
-
-#define PNM_HEADER_SIZE 11
-static const unsigned char pnm_header[] = {
-        'P','N','A',
-        0x00, 0x0a,
-        0x00, 0x14,
-        0x00, 0x02,
-        0x00, 0x01 };
-
-#define PNM_CLIENT_CAPS_SIZE 126
-static const unsigned char pnm_client_caps[] = {
-    0x07, 0x8a, 'p','n','r','v', 
-       0, 0x90, 'p','n','r','v', 
-       0, 0x64, 'd','n','e','t', 
-       0, 0x46, 'p','n','r','v', 
-       0, 0x32, 'd','n','e','t', 
-       0, 0x2b, 'p','n','r','v', 
-       0, 0x28, 'd','n','e','t', 
-       0, 0x24, 'p','n','r','v', 
-       0, 0x19, 'd','n','e','t', 
-       0, 0x18, 'p','n','r','v', 
-       0, 0x14, 's','i','p','r', 
-       0, 0x14, 'd','n','e','t', 
-       0, 0x24, '2','8','_','8', 
-       0, 0x12, 'p','n','r','v', 
-       0, 0x0f, 'd','n','e','t', 
-       0, 0x0a, 's','i','p','r', 
-       0, 0x0a, 'd','n','e','t', 
-       0, 0x08, 's','i','p','r', 
-       0, 0x06, 's','i','p','r', 
-       0, 0x12, 'l','p','c','J', 
-       0, 0x07, '0','5','_','6' };
-
-static const uint32_t pnm_default_bandwidth=10485800;
-static const uint32_t pnm_available_bandwidths[]={14400,19200,28800,33600,34430,57600,
-                                  115200,262200,393216,524300,1544000,10485800};
-
-#define PNM_TWENTYFOUR_SIZE 16
-static unsigned char pnm_twentyfour[]={
-    0xd5, 0x42, 0xa3, 0x1b, 0xef, 0x1f, 0x70, 0x24,
-    0x85, 0x29, 0xb3, 0x8d, 0xba, 0x11, 0xf3, 0xd6 };
-
-/* now other data follows. marked with 0x0000 at the beginning */
-static int after_chunks_length=6;
-static unsigned char after_chunks[]={
-    0x00, 0x00, /* mark */
-    
-    0x50, 0x84, /* seems to be fixated */
-    0x1f, 0x3a  /* varies on each request (checksum ?)*/
-    };
-
-static void hexdump (char *buf, int length);
-
-static int rm_write(int s, const char *buf, int len) {
-  int total, timeout;
-
-  total = 0; timeout = 30;
-  while (total < len){ 
-    int n;
-
-    n = send (s, &buf[total], len - total, 0);
-
-    if (n > 0)
-      total += n;
-    else if (n < 0) {
-#ifndef HAVE_WINSOCK2
-      if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) {
-#else
-      if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) {
-#endif
-        usec_sleep (1000000); timeout--;
-      } else
-        return -1;
-    }
-  }
-
-  return total;
-}
-
-static ssize_t rm_read(int fd, void *buf, size_t count) {
-  
-  ssize_t ret, total;
-
-  total = 0;
-
-  while (total < count) {
-  
-    fd_set rset;
-    struct timeval timeout;
-
-    FD_ZERO (&rset);
-    FD_SET  (fd, &rset);
-    
-    timeout.tv_sec  = 3;
-    timeout.tv_usec = 0;
-    
-    if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) {
-      return -1;
-    }
-    
-    ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0);
-
-    if (ret<=0) {
-      mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: read error.\n");
-      return ret;
-    } else
-      total += ret;
-  }
-
-  return total;
-}
-
-/*
- * debugging utilities
- */
- 
-static void hexdump (char *buf, int length) {
-
-  int i;
-
-  mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: ascii>");
-  for (i = 0; i < length; i++) {
-    unsigned char c = buf[i];
-
-    if ((c >= 32) && (c <= 128))
-      mp_msg(MSGT_OPEN, MSGL_INFO, "%c", c);
-    else
-      mp_msg(MSGT_OPEN, MSGL_INFO, ".");
-  }
-  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
-
-  mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: hexdump> ");
-  for (i = 0; i < length; i++) {
-    unsigned char c = buf[i];
-
-    mp_msg(MSGT_OPEN, MSGL_INFO, "%02x", c);
-
-    if ((i % 16) == 15)
-      mp_msg(MSGT_OPEN, MSGL_INFO, "\npnm:         ");
-
-    if ((i % 2) == 1)
-      mp_msg(MSGT_OPEN, MSGL_INFO, " ");
-
-  }
-  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
-}
-
-/*
- * pnm_get_chunk gets a chunk from stream
- * and returns number of bytes read 
- */
-
-static int pnm_get_chunk(pnm_t *p, 
-                         unsigned int max,
-                         unsigned int *chunk_type,
-                         char *data, int *need_response) {
-
-  unsigned int chunk_size;
-  unsigned int n;
-  char *ptr;
- 
-  if (max < PREAMBLE_SIZE)
-    return -1;
-
-  /* get first PREAMBLE_SIZE bytes and ignore checksum */
-  rm_read (p->s, data, CHECKSUM_SIZE);
-  if (data[0] == 0x72)
-    rm_read (p->s, data, PREAMBLE_SIZE);
-  else
-    rm_read (p->s, data+CHECKSUM_SIZE, PREAMBLE_SIZE-CHECKSUM_SIZE);
-  
-  max -= PREAMBLE_SIZE;
-
-  *chunk_type = BE_32(data);
-  chunk_size = BE_32(data+4);
-
-  switch (*chunk_type) {
-    case PNA_TAG:
-      *need_response=0;
-      ptr=data+PREAMBLE_SIZE;
-      if (max < 1)
-	return -1;
-      rm_read (p->s, ptr++, 1);
-      max -= 1;
-
-      while(1) {
-	/* expecting following chunk format: 0x4f <chunk size> <data...> */
-
-        if (max < 2)
-          return -1;
-        rm_read (p->s, ptr, 2);
-        max -= 2;
-	if (*ptr == 'X') /* checking for server message */
-	{
-	  mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: got a message from server:\n");
-	  if (max < 1)
-	    return -1;
-	  rm_read (p->s, ptr+2, 1);
-	  max = -1;
-	  n=BE_16(ptr+1);
-	  if (max < n)
-	    return -1;
-	  rm_read (p->s, ptr+3, n);
-	  max -= n;
-	  ptr[3+n]=0;
-	  mp_msg(MSGT_OPEN, MSGL_WARN, "%s\n",ptr+3);
-	  return -1;
-	}
-	
-	if (*ptr == 'F') /* checking for server error */
-	{
-	  mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: server error.\n");
-	  return -1;
-	}
-	if (*ptr == 'i')
-	{
-	  ptr+=2;
-	  *need_response=1;
-	  continue;
-	}
-	if (*ptr != 0x4f) break;
-	n=ptr[1];
-	if (max < n)
-	  return -1;
-	rm_read (p->s, ptr+2, n);
-	max -= n;
-	ptr+=(n+2);
-      }
-      /* the checksum of the next chunk is ignored here */
-      if (max < 1)
-        return -1;
-      rm_read (p->s, ptr+2, 1);
-      ptr+=3;
-      chunk_size=ptr-data;
-      break;
-    case RMF_TAG:
-    case DATA_TAG:
-    case PROP_TAG:
-    case MDPR_TAG:
-    case CONT_TAG:
-      if (chunk_size > max || chunk_size < PREAMBLE_SIZE) {
-        mp_msg(MSGT_OPEN, MSGL_ERR, "error: max chunk size exceded (max was 0x%04x)\n", max);
-#ifdef LOG
-        n=rm_read (p->s, &data[PREAMBLE_SIZE], 0x100 - PREAMBLE_SIZE);
-        hexdump(data,n+PREAMBLE_SIZE);
-#endif
-        return -1;
-      }
-      rm_read (p->s, &data[PREAMBLE_SIZE], chunk_size-PREAMBLE_SIZE);
-      break;
-    default:
-      *chunk_type = 0;
-      chunk_size  = PREAMBLE_SIZE; 
-      break;
-  }
-
-  return chunk_size;
-}
-
-/*
- * writes a chunk to a buffer, returns number of bytes written
- */
-
-static int pnm_write_chunk(uint16_t chunk_id, uint16_t length, 
-    const char *chunk, char *data) {
-
-  data[0]=(chunk_id>>8)%0xff;
-  data[1]=chunk_id%0xff;
-  data[2]=(length>>8)%0xff;
-  data[3]=length%0xff;
-  memcpy(&data[4],chunk,length);
-  
-  return length+4;
-}
-
-/*
- * constructs a request and sends it
- */
-
-static void pnm_send_request(pnm_t *p, uint32_t bandwidth) {
-
-  uint16_t i16;
-  int c=PNM_HEADER_SIZE;
-  char fixme[]={0,1};
-
-  memcpy(p->buffer,pnm_header,PNM_HEADER_SIZE);
-  c+=pnm_write_chunk(PNA_CLIENT_CHALLANGE,strlen(pnm_challenge),
-          pnm_challenge,&p->buffer[c]);
-  c+=pnm_write_chunk(PNA_CLIENT_CAPS,PNM_CLIENT_CAPS_SIZE,
-          pnm_client_caps,&p->buffer[c]);
-  c+=pnm_write_chunk(0x0a,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x0c,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x0d,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x16,2,fixme,&p->buffer[c]);
-  c+=pnm_write_chunk(PNA_TIMESTAMP,strlen(pnm_timestamp),
-          pnm_timestamp,&p->buffer[c]);
-  c+=pnm_write_chunk(PNA_BANDWIDTH,4,
-          (const char *)&pnm_default_bandwidth,&p->buffer[c]);
-  c+=pnm_write_chunk(0x08,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x0e,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x0f,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x11,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x10,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x15,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(0x12,0,NULL,&p->buffer[c]);
-  c+=pnm_write_chunk(PNA_GUID,strlen(pnm_guid),
-          pnm_guid,&p->buffer[c]);
-  c+=pnm_write_chunk(PNA_TWENTYFOUR,PNM_TWENTYFOUR_SIZE,
-          pnm_twentyfour,&p->buffer[c]);
-  
-  /* data after chunks */
-  memcpy(&p->buffer[c],after_chunks,after_chunks_length);
-  c+=after_chunks_length;
-
-  /* client id string */
-  p->buffer[c]=PNA_CLIENT_STRING;
-  i16=BE_16D((strlen(client_string)-1)); /* don't know why do we have -1 here */
-  memcpy(&p->buffer[c+1],&i16,2);
-  memcpy(&p->buffer[c+3],client_string,strlen(client_string)+1);
-  c=c+3+strlen(client_string)+1;
-
-  /* file path */
-  p->buffer[c]=0;
-  p->buffer[c+1]=PNA_PATH_REQUEST;
-  i16=BE_16D(strlen(p->path));
-  memcpy(&p->buffer[c+2],&i16,2);
-  memcpy(&p->buffer[c+4],p->path,strlen(p->path));
-  c=c+4+strlen(p->path);
-
-  /* some trailing bytes */
-  p->buffer[c]='y';
-  p->buffer[c+1]='B';
-  
-  rm_write(p->s,p->buffer,c+2);
-}
-
-/*
- * pnm_send_response sends a response of a challenge
- */
-
-static void pnm_send_response(pnm_t *p, const char *response) {
-
-  int size=strlen(response);
-
-  p->buffer[0]=0x23;
-  p->buffer[1]=0;
-  p->buffer[2]=(unsigned char) size;
-
-  memcpy(&p->buffer[3], response, size);
-
-  rm_write (p->s, p->buffer, size+3);
-
-}
-
-/*
- * get headers and challenge and fix headers
- * write headers to p->header
- * write challenge to p->buffer
- *
- * return 0 on error.  != 0 on success
- */
-
-static int pnm_get_headers(pnm_t *p, int *need_response) {
-
-  uint32_t chunk_type;
-  uint8_t  *ptr=p->header;
-  uint8_t  *prop_hdr=NULL;
-  int      chunk_size,size=0;
-  int      nr;
-/*  rmff_header_t *h; */
-
-  *need_response=0;
-
-  while(1) {
-    if (HEADER_SIZE-size<=0)
-    {
-      mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: header buffer overflow. exiting\n");
-      return 0;
-    }
-    chunk_size=pnm_get_chunk(p,HEADER_SIZE-size,&chunk_type,ptr,&nr);
-    if (chunk_size < 0) return 0;
-    if (chunk_type == 0) break;
-    if (chunk_type == PNA_TAG)
-    {
-      memcpy(ptr, rm_header, RM_HEADER_SIZE);
-      chunk_size=RM_HEADER_SIZE;
-      *need_response=nr;
-    }
-    if (chunk_type == DATA_TAG)
-      chunk_size=0;
-    if (chunk_type == RMF_TAG)
-      chunk_size=0;
-    if (chunk_type == PROP_TAG)
-        prop_hdr=ptr;
-    size+=chunk_size;
-    ptr+=chunk_size;
-  }
-  
-  if (!prop_hdr) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: error while parsing headers.\n");
-    return 0;
-  }
-  
-  /* set data offset */
-  size--;
-  prop_hdr[42]=(size>>24)%0xff;
-  prop_hdr[43]=(size>>16)%0xff;
-  prop_hdr[44]=(size>>8)%0xff;
-  prop_hdr[45]=(size)%0xff;
-  size++;
-
-  /* read challenge */
-  memcpy (p->buffer, ptr, PREAMBLE_SIZE);
-  rm_read (p->s, &p->buffer[PREAMBLE_SIZE], 64);
-
-  /* now write a data header */
-  memcpy(ptr, pnm_data_header, PNM_DATA_HEADER_SIZE);
-  size+=PNM_DATA_HEADER_SIZE;
-/*  
-  h=rmff_scan_header(p->header);
-  rmff_fix_header(h);
-  p->header_len=rmff_get_header_size(h);
-  rmff_dump_header(h, p->header, HEADER_SIZE);
-*/
-  p->header_len=size;
-  
-  return 1;
-}
-
-/* 
- * determine correct stream number by looking at indices
- */
-
-static int pnm_calc_stream(pnm_t *p) {
-
-  char str0=0,str1=0;
-
-  /* looking at the first index to
-   * find possible stream types
-   */
-  if (p->seq_current[0]==p->seq_num[0]) str0=1;
-  if (p->seq_current[0]==p->seq_num[2]) str1=1;
-
-  switch (str0+str1) {
-    case 1: /* one is possible, good. */
-      if (str0)
-      {
-        p->seq_num[0]++;
-        p->seq_num[1]=p->seq_current[1]+1;
-        return 0;
-      } else
-      {
-        p->seq_num[2]++;
-        p->seq_num[3]=p->seq_current[1]+1;
-        return 1;
-      }
-      break;
-    case 0:
-    case 2: /* both types or none possible, not so good */
-      /* try to figure out by second index */
-      if (  (p->seq_current[1] == p->seq_num[1])
-          &&(p->seq_current[1] != p->seq_num[3]))
-      {
-        /* ok, only stream0 matches */
-        p->seq_num[0]=p->seq_current[0]+1;
-        p->seq_num[1]++;
-        return 0;
-      }
-      if (  (p->seq_current[1] == p->seq_num[3])
-          &&(p->seq_current[1] != p->seq_num[1]))
-      {
-        /* ok, only stream1 matches */
-        p->seq_num[2]=p->seq_current[0]+1;
-        p->seq_num[3]++;
-        return 1;
-      }
-      /* wow, both streams match, or not.   */
-      /* now we try to decide by timestamps */
-      if (p->ts_current < p->ts_last[1])
-        return 0;
-      if (p->ts_current < p->ts_last[0])
-        return 1;
-      /* does not help, we guess type 0     */
-#ifdef LOG
-      mp_msg(MSGT_OPEN, MSGL_INFO, "guessing stream# 0\n");
-#endif
-      p->seq_num[0]=p->seq_current[0]+1;
-      p->seq_num[1]=p->seq_current[1]+1;
-      return 0;
-      break;
-  }
-  mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: wow, something very nasty happened in pnm_calc_stream\n");
-  return 2;
-}
-
-/*
- * gets a stream chunk and writes it to a recieve buffer
- */
-
-static int pnm_get_stream_chunk(pnm_t *p) {
-
-  int  n;
-  char keepalive='!';
-  unsigned int fof1, fof2, stream;
-
-  /* send a keepalive                               */
-  /* realplayer seems to do that every 43th package */
-  if ((p->packet%43) == 42)  
-  {
-    rm_write(p->s,&keepalive,1);
-  }
-
-  /* data chunks begin with: 'Z' <o> <o> <i1> 'Z' <i2>
-   * where <o> is the offset to next stream chunk,
-   * <i1> is a 16 bit index
-   * <i2> is a 8 bit index which counts from 0x10 to somewhere
-   */
-  
-  n = rm_read (p->s, p->buffer, 8);
-  if (n<0) return -1;
-  if (n<8) return 0;
-  
-  /* skip 8 bytes if 0x62 is read */
-  if (p->buffer[0] == 0x62)
-  {
-    n = rm_read (p->s, p->buffer, 8);
-    if (n<8) return 0;
-#ifdef LOG
-    mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: had to seek 8 bytes on 0x62\n");
-#endif
-  }
-  
-  /* a server message */
-  if (p->buffer[0] == 'X')
-  {
-    int size=BE_16(&p->buffer[1]);
-
-    rm_read (p->s, &p->buffer[8], size-5);
-    p->buffer[size+3]=0;
-    mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: got message from server while reading stream:\n%s\n", &p->buffer[3]);
-    return -1;
-  }
-  if (p->buffer[0] == 'F')
-  {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: server error.\n");
-    return -1;
-  }
-
-  /* skip bytewise to next chunk.
-   * seems, that we don't need that, if we send enough
-   * keepalives
-   */
-  n=0;
-  while (p->buffer[0] != 0x5a) {
-    int i;
-    for (i=1; i<8; i++) {
-      p->buffer[i-1]=p->buffer[i];
-    }
-    rm_read (p->s, &p->buffer[7], 1);
-    n++;
-  }
-
-#ifdef LOG
-  if (n) mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: had to seek %i bytes to next chunk\n", n);
-#endif
-
-  /* check for 'Z's */
-  if ((p->buffer[0] != 0x5a)||(p->buffer[7] != 0x5a))
-  {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: bad boundaries\n");
-    hexdump(p->buffer, 8);
-    return 0;
-  }
-
-  /* check offsets */
-  fof1=BE_16(&p->buffer[1]);
-  fof2=BE_16(&p->buffer[3]);
-  if (fof1 != fof2)
-  {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: frame offsets are different: 0x%04x 0x%04x\n",fof1,fof2);
-    return 0;
-  }
-
-  /* get first index */
-  p->seq_current[0]=BE_16(&p->buffer[5]);
-  
-  /* now read the rest of stream chunk */
-  n = rm_read (p->s, &p->recv[5], fof1-5);
-  if (n<(fof1-5)) return 0;
-
-  /* get second index */
-  p->seq_current[1]=p->recv[5];
-
-  /* get timestamp */
-  p->ts_current=BE_32(&p->recv[6]);
-  
-  /* get stream number */
-  stream=pnm_calc_stream(p);
-
-  /* saving timestamp */
-  p->ts_last[stream]=p->ts_current;
-  
-  /* constructing a data packet header */
-  
-  p->recv[0]=0;        /* object version */
-  p->recv[1]=0;
-
-  fof2=BE_16(&fof2);
-  memcpy(&p->recv[2], &fof2, 2);
-  /*p->recv[2]=(fof2>>8)%0xff;*/   /* length */
-  /*p->recv[3]=(fof2)%0xff;*/
-
-  p->recv[4]=0;         /* stream number */
-  p->recv[5]=stream;
-  
-  p->recv[10]=p->recv[10] & 0xfe; /* streambox seems to do that... */
-
-  p->packet++;
-
-  p->recv_size=fof1;
-
-  return fof1;
-}
-
-// pnm_t *pnm_connect(const char *mrl) {
-static pnm_t *pnm_connect(int fd, char *path) {
-  
-  pnm_t *p=malloc(sizeof(pnm_t));
-  int need_response=0;
-  
-  p->path=strdup(path);
-  p->s=fd;
-
-  pnm_send_request(p,pnm_available_bandwidths[10]);
-  if (!pnm_get_headers(p, &need_response)) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: failed to set up stream\n");
-    free(p->path);
-    free(p);
-    return NULL;
-  }
-  if (need_response)
-    pnm_send_response(p, pnm_response);
-  p->ts_last[0]=0;
-  p->ts_last[1]=0;
-  
-  /* copy header to recv */
-
-  memcpy(p->recv, p->header, p->header_len);
-  p->recv_size = p->header_len;
-  p->recv_read = 0;
-
-  return p;
-}
-
-static int pnm_read (pnm_t *this, char *data, int len) {
-  
-  int to_copy=len;
-  char *dest=data;
-  char *source=this->recv + this->recv_read;
-  int fill=this->recv_size - this->recv_read;
-  int retval;
-  
-  if (len < 0) return 0;
-  while (to_copy > fill) {
-    
-    memcpy(dest, source, fill);
-    to_copy -= fill;
-    dest += fill;
-    this->recv_read=0;
-
-    if ((retval = pnm_get_stream_chunk (this)) <= 0) {
-#ifdef LOG
-      mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: %d of %d bytes provided\n", len-to_copy, len);
-#endif
-      if (retval < 0)
-        return retval;
-      else
-      return len-to_copy;
-    }
-    source = this->recv;
-    fill = this->recv_size - this->recv_read;
-  }
-
-  memcpy(dest, source, to_copy);
-  this->recv_read += to_copy;
-
-#ifdef LOG
-  mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: %d bytes provided\n", len);
-#endif
-
-  return len;
-}
-
-static int pnm_peek_header (pnm_t *this, char *data) {
-
-  memcpy (data, this->header, this->header_len);
-  return this->header_len;
-}
-
-static void pnm_close(pnm_t *p) {
-
-  if (p->s >= 0) closesocket(p->s);
-  free(p->path);
-  free(p);
-}
-
-static int pnm_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) {
-	return pnm_read(stream_ctrl->data, buffer, size);
-}
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  int fd;
-  pnm_t *pnm;
-  URL_t *url;
-
-  mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_PNM, URL: %s\n", stream->url);
-  stream->streaming_ctrl = streaming_ctrl_new();
-  if(stream->streaming_ctrl==NULL) {
-    return STREAM_ERROR;
-  }
-  stream->streaming_ctrl->bandwidth = network_bandwidth;
-  url = url_new(stream->url);
-  stream->streaming_ctrl->url = check4proxies(url);
-  //url_free(url);
-
-  fd = connect2Server( stream->streaming_ctrl->url->hostname,
-    stream->streaming_ctrl->url->port ? stream->streaming_ctrl->url->port : 7070,1 );
-  
-  if(fd<0)
-    goto fail;
-
-  pnm = pnm_connect(fd,stream->streaming_ctrl->url->file);
-  if(!pnm) 
-    goto fail;
-  stream->type = STREAMTYPE_STREAM;
-  stream->fd=fd;
-  stream->streaming_ctrl->data=pnm;
-  stream->streaming_ctrl->streaming_read = pnm_streaming_read;
-  //stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
-  stream->streaming_ctrl->prebuffer_size = 8*1024;  // 8 KBytes
-  stream->streaming_ctrl->buffering = 1;
-  stream->streaming_ctrl->status = streaming_playing_e;
-  *file_format = DEMUXER_TYPE_REAL;
-  fixup_network_stream_cache(stream);
-  return STREAM_OK;
-
-fail:
-  streaming_ctrl_free(stream->streaming_ctrl);
-  stream->streaming_ctrl = NULL;
-  return STREAM_UNSUPORTED;
-}
-
-
-stream_info_t stream_info_pnm = {
-  "RealNetworks pnm",
-  "pnm",
-  "Arpi, xine team",
-  "ported from xine",
-  open_s,
-  {"pnm", NULL},	//pnm as fallback
-  NULL,
-  0 // Urls are an option string
-};
--- a/libmpdemux/realrtsp/asmrp.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,677 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS asmrp.c,v 1.2 2002/12/17 16:49:48
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- * 
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * a parser for real's asm rules
- *
- * grammar for these rules:
- *
-
-   rule_book  = { rule }
-   rule       = ( '#' condition { ',' assignment } | [ assignment {',' assignment} ]) ';'
-   assignment = id '=' const
-   const      = ( number | string )
-   condition  = comp_expr { ( '&&' | '||' ) comp_expr }
-   comp_expr  = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand }
-   operand    = ( '$' id | num | '(' condition ')' )
-
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-/*
-#define LOG
-*/
-
-#define ASMRP_SYM_NONE         0
-#define ASMRP_SYM_EOF          1
-
-#define ASMRP_SYM_NUM          2
-#define ASMRP_SYM_ID           3
-#define ASMRP_SYM_STRING       4
-
-#define ASMRP_SYM_HASH         10
-#define ASMRP_SYM_SEMICOLON    11
-#define ASMRP_SYM_COMMA        12
-#define ASMRP_SYM_EQUALS       13
-#define ASMRP_SYM_AND          14
-#define ASMRP_SYM_OR           15
-#define ASMRP_SYM_LESS         16
-#define ASMRP_SYM_LEQ          17
-#define ASMRP_SYM_GEQ          18
-#define ASMRP_SYM_GREATER      19
-#define ASMRP_SYM_DOLLAR       20
-#define ASMRP_SYM_LPAREN       21
-#define ASMRP_SYM_RPAREN       22
-
-#define ASMRP_MAX_ID         1024
-
-#define ASMRP_MAX_SYMTAB       10
-
-typedef struct {
-  char *id;
-  int   v;
-} asmrp_sym_t;
-
-typedef struct {
-
-  /* public part */
-
-  int         sym;
-  int         num;
-  
-  char        str[ASMRP_MAX_ID];
-
-  /* private part */
-
-  char       *buf;
-  int         pos;
-  char        ch;
-
-  asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB];
-  int         sym_tab_num;
-
-} asmrp_t;
-
-static asmrp_t *asmrp_new (void) {
-
-  asmrp_t *p;
-
-  p = malloc (sizeof (asmrp_t));
-
-  p->sym_tab_num = 0;
-  p->sym         = ASMRP_SYM_NONE;
-
-  return p;
-}
-
-static void asmrp_dispose (asmrp_t *p) {
-
-  int i;
-
-  for (i=0; i<p->sym_tab_num; i++) 
-    free (p->sym_tab[i].id);
-
-  free (p);
-}
-
-static void asmrp_getch (asmrp_t *p) {
-  p->ch = p->buf[p->pos];
-  p->pos++;
-
-#ifdef LOG
-  printf ("%c\n", p->ch);
-#endif
-
-}
-
-static void asmrp_init (asmrp_t *p, const char *str) {
-
-  p->buf = strdup (str);
-  p->pos = 0;
-  
-  asmrp_getch (p);
-}
-
-static void asmrp_number (asmrp_t *p) {
-
-  int num;
-
-  num = 0;
-  while ( (p->ch>='0') && (p->ch<='9') ) {
-
-    num = num*10 + (p->ch - '0');
-
-    asmrp_getch (p);
-  }
-
-  p->sym = ASMRP_SYM_NUM;
-  p->num = num;
-}
-
-static void asmrp_string (asmrp_t *p) {
-
-  int l;
-
-  l = 0;
-
-  while ( (p->ch!='"') && (p->ch>=32) ) {
-
-    p->str[l] = p->ch;
-
-    l++;
-    asmrp_getch (p);
-  }
-  p->str[l]=0;
-  
-  if (p->ch=='"')
-    asmrp_getch (p);
-  
-  p->sym = ASMRP_SYM_STRING;
-}
-
-static void asmrp_identifier (asmrp_t *p) {
-
-  int l;
-
-  l = 0;
-
-  while ( ((p->ch>='A') && (p->ch<='z'))
-	  || ((p->ch>='0') && (p->ch<='9'))) {
-
-    p->str[l] = p->ch;
-
-    l++;
-    asmrp_getch (p);
-  }
-  p->str[l]=0;
-  
-  p->sym = ASMRP_SYM_ID;
-}
-
-#ifdef LOG
-static void asmrp_print_sym (asmrp_t *p) {
-
-  printf ("symbol: ");
-
-  switch (p->sym) {
-
-  case ASMRP_SYM_NONE:
-    printf ("NONE\n");
-    break;
-
-  case ASMRP_SYM_EOF:
-    printf ("EOF\n");
-    break;
-
-  case ASMRP_SYM_NUM:
-    printf ("NUM %d\n", p->num);
-    break;
-
-  case ASMRP_SYM_ID:
-    printf ("ID '%s'\n", p->str);
-    break;
-
-  case ASMRP_SYM_STRING:
-    printf ("STRING \"%s\"\n", p->str);
-    break;
-
-  case ASMRP_SYM_HASH:
-    printf ("#\n");
-    break;
-
-  case ASMRP_SYM_SEMICOLON:
-    printf (";\n");
-    break;
-  case ASMRP_SYM_COMMA:
-    printf (",\n");
-    break;
-  case ASMRP_SYM_EQUALS:
-    printf ("==\n");
-    break;
-  case ASMRP_SYM_AND:
-    printf ("&&\n");
-    break;
-  case ASMRP_SYM_OR:
-    printf ("||\n");
-    break;
-  case ASMRP_SYM_LESS:
-    printf ("<\n");
-    break;
-  case ASMRP_SYM_LEQ:
-    printf ("<=\n");
-    break;
-  case ASMRP_SYM_GEQ:
-    printf (">=\n");
-    break;
-  case ASMRP_SYM_GREATER:
-    printf (">\n");
-    break;
-  case ASMRP_SYM_DOLLAR:
-    printf ("$\n");
-    break;
-  case ASMRP_SYM_LPAREN:
-    printf ("(\n");
-    break;
-  case ASMRP_SYM_RPAREN:
-    printf (")\n");
-    break;
-
-  default:
-    printf ("unknown symbol %d\n", p->sym);
-  }
-}
-#endif
-
-static void asmrp_get_sym (asmrp_t *p) {
-
-  while (p->ch <= 32) {
-    if (p->ch == 0) {
-      p->sym = ASMRP_SYM_EOF;
-      return;
-    }
-
-    asmrp_getch (p);
-  }
-
-  if (p->ch == '\\')
-    asmrp_getch (p);
-
-  switch (p->ch) {
-
-  case '#':
-    p->sym = ASMRP_SYM_HASH;
-    asmrp_getch (p);
-    break;
-  case ';':
-    p->sym = ASMRP_SYM_SEMICOLON;
-    asmrp_getch (p);
-    break;
-  case ',':
-    p->sym = ASMRP_SYM_COMMA;
-    asmrp_getch (p);
-    break;
-  case '=':
-    p->sym = ASMRP_SYM_EQUALS;
-    asmrp_getch (p);
-    if (p->ch=='=')
-      asmrp_getch (p);
-    break;
-  case '&':
-    p->sym = ASMRP_SYM_AND;
-    asmrp_getch (p);
-    if (p->ch=='&')
-      asmrp_getch (p);
-    break;
-  case '|':
-    p->sym = ASMRP_SYM_OR;
-    asmrp_getch (p);
-    if (p->ch=='|')
-      asmrp_getch (p);
-    break;
-  case '<':
-    p->sym = ASMRP_SYM_LESS;
-    asmrp_getch (p);
-    if (p->ch=='=') {
-      p->sym = ASMRP_SYM_LEQ;
-      asmrp_getch (p);
-    }
-    break;
-  case '>':
-    p->sym = ASMRP_SYM_GREATER;
-    asmrp_getch (p);
-    if (p->ch=='=') {
-      p->sym = ASMRP_SYM_GEQ;
-      asmrp_getch (p);
-    }
-    break;
-  case '$':
-    p->sym = ASMRP_SYM_DOLLAR;
-    asmrp_getch (p);
-    break;
-  case '(':
-    p->sym = ASMRP_SYM_LPAREN;
-    asmrp_getch (p);
-    break;
-  case ')':
-    p->sym = ASMRP_SYM_RPAREN;
-    asmrp_getch (p);
-    break;
-
-  case '"':
-    asmrp_getch (p);
-    asmrp_string (p);
-    break;
-
-  case '0': case '1': case '2': case '3': case '4':
-  case '5': case '6': case '7': case '8': case '9':
-    asmrp_number (p);
-    break;
-
-  default:
-    asmrp_identifier (p);
-  }
-
-#ifdef LOG
-  asmrp_print_sym (p);
-#endif
-
-}
-
-static int asmrp_find_id (asmrp_t *p, char *s) {
-
-  int i;
-
-  for (i=0; i<p->sym_tab_num; i++) {
-    if (!strcmp (s, p->sym_tab[i].id))
-      return i;
-  }
-
-  return -1;
-}
-
-static int asmrp_set_id (asmrp_t *p, char *s, int v) {
-
-  int i;
-
-  i = asmrp_find_id (p, s);
-
-  if (i<0) {
-    i = p->sym_tab_num;
-    p->sym_tab_num++;
-    p->sym_tab[i].id = strdup (s);
-
-#ifdef LOG
-    printf ("new symbol '%s'\n", s);
-#endif
-
-  }    
-
-  p->sym_tab[i].v = v;
- 
-#ifdef LOG
-  printf ("symbol '%s' assigned %d\n", s, v);
-#endif
-
-  return i;
-}
-
-static int asmrp_condition (asmrp_t *p) ;
-
-static int asmrp_operand (asmrp_t *p) {
-
-  int i, ret;
-  
-#ifdef LOG
-  printf ("operand\n");
-#endif
-
-  ret = 0;
-
-  switch (p->sym) {
-
-  case ASMRP_SYM_DOLLAR:
-
-    asmrp_get_sym (p);
-    
-    if (p->sym != ASMRP_SYM_ID) {
-      printf ("error: identifier expected.\n");
-      abort();
-    }
-
-    i = asmrp_find_id (p, p->str);
-    if (i<0) {
-      printf ("error: unknown identifier %s\n", p->str);
-    }
-    ret = p->sym_tab[i].v;
-
-    asmrp_get_sym (p);
-    break;
-
-  case ASMRP_SYM_NUM:
-    ret = p->num;
-
-    asmrp_get_sym (p);
-    break;
-
-  case ASMRP_SYM_LPAREN:
-    asmrp_get_sym (p);
-
-    ret = asmrp_condition (p);
-
-    if (p->sym != ASMRP_SYM_RPAREN) {
-      printf ("error: ) expected.\n");
-      abort();
-    }
-
-    asmrp_get_sym (p);
-    break;
-
-  default:
-    printf ("syntax error, $ number or ( expected\n");
-    abort();
-  }
-
-#ifdef LOG
-  printf ("operand done, =%d\n", ret);
-#endif
-  
-  return ret;
-}
-
-static int asmrp_comp_expression (asmrp_t *p) {
-
-  int a;
-
-#ifdef LOG
-  printf ("comp_expression\n");
-#endif
-
-  a = asmrp_operand (p);
-
-  while ( (p->sym == ASMRP_SYM_LESS)
-	  || (p->sym == ASMRP_SYM_LEQ)
-	  || (p->sym == ASMRP_SYM_EQUALS)
-	  || (p->sym == ASMRP_SYM_GEQ)
-	  || (p->sym == ASMRP_SYM_GREATER) ) {
-    int op = p->sym;
-    int b;
-
-    asmrp_get_sym (p);
-
-    b = asmrp_operand (p);
-
-    switch (op) {
-    case ASMRP_SYM_LESS:
-      a = a<b;
-      break;
-    case ASMRP_SYM_LEQ:
-      a = a<=b;
-      break;
-    case ASMRP_SYM_EQUALS:
-      a = a==b;
-      break;
-    case ASMRP_SYM_GEQ:
-      a = a>=b;
-      break;
-    case ASMRP_SYM_GREATER:
-      a = a>b;
-      break;
-    }
-
-  }
-
-#ifdef LOG
-  printf ("comp_expression done = %d\n", a);
-#endif
-  return a;
-}
-
-static int asmrp_condition (asmrp_t *p) {
-  
-  int a;
-
-#ifdef LOG
-  printf ("condition\n");
-#endif
-
-  a = asmrp_comp_expression (p);
-
-  while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) {
-    int op, b;
-
-    op = p->sym;
-
-    asmrp_get_sym (p);
-
-    b = asmrp_comp_expression (p);
-
-    switch (op) {
-    case ASMRP_SYM_AND:
-      a = a & b;
-      break;
-    case ASMRP_SYM_OR:
-      a = a | b;
-      break;
-    }
-  }
-
-#ifdef LOG
-  printf ("condition done = %d\n", a);
-#endif
-  return a;
-}
-
-static void asmrp_assignment (asmrp_t *p) {
-
-#ifdef LOG
-  printf ("assignment\n");
-#endif
-
-  if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) {
-#ifdef LOG
-    printf ("empty assignment\n");
-#endif
-    return;
-  }
-
-  if (p->sym != ASMRP_SYM_ID) {
-    printf ("error: identifier expected\n");
-    abort ();
-  }
-  asmrp_get_sym (p);
-
-  if (p->sym != ASMRP_SYM_EQUALS) {
-    printf ("error: = expected\n");
-    abort ();
-  }
-  asmrp_get_sym (p);
-
-  if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) 
-       && (p->sym != ASMRP_SYM_ID)) {
-    printf ("error: number or string expected\n");
-    abort ();
-  }
-  asmrp_get_sym (p);
-
-#ifdef LOG
-  printf ("assignment done\n");
-#endif
-}
-
-static int asmrp_rule (asmrp_t *p) {
-  
-  int ret;
-
-#ifdef LOG
-  printf ("rule\n");
-#endif
-
-  ret = 1;
-  
-  if (p->sym == ASMRP_SYM_HASH) {
-
-    asmrp_get_sym (p);
-    ret = asmrp_condition (p);
-
-    while (p->sym == ASMRP_SYM_COMMA) {
-      
-      asmrp_get_sym (p);
-      
-      asmrp_assignment (p);
-    }
-
-  } else if (p->sym != ASMRP_SYM_SEMICOLON) {
-
-    asmrp_assignment (p);
-
-    while (p->sym == ASMRP_SYM_COMMA) {
-
-      asmrp_get_sym (p);
-      asmrp_assignment (p);
-    }
-  }
-
-#ifdef LOG
-  printf ("rule done = %d\n", ret);
-#endif
-
-  if (p->sym != ASMRP_SYM_SEMICOLON) {
-    printf ("semicolon expected.\n");
-    abort ();
-  }
-
-  asmrp_get_sym (p);
-
-  return ret;
-}
-
-static int asmrp_eval (asmrp_t *p, int *matches) {
-
-  int rule_num, num_matches;
-
-#ifdef LOG
-  printf ("eval\n");
-#endif
-
-  asmrp_get_sym (p);
-
-  rule_num = 0; num_matches = 0;
-  while (p->sym != ASMRP_SYM_EOF) {
-
-    if (asmrp_rule (p)) {
-#ifdef LOG
-      printf ("rule #%d is true\n", rule_num);
-#endif
-      matches[num_matches] = rule_num;
-      num_matches++;
-    }
-
-    rule_num++;
-  }
-
-  matches[num_matches] = -1;
-  return num_matches;
-}
-
-int asmrp_match (const char *rules, int bandwidth, int *matches) {
-
-  asmrp_t *p;
-  int      num_matches;
-
-  p = asmrp_new ();
-
-  asmrp_init (p, rules);
-
-  asmrp_set_id (p, "Bandwidth", bandwidth);
-  asmrp_set_id (p, "OldPNMPlayer", 0);
-
-  num_matches = asmrp_eval (p, matches);
-
-  asmrp_dispose (p);
-
-  return num_matches;
-}
-
--- a/libmpdemux/realrtsp/asmrp.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS asmrp.h,v 1.1 2002/12/12 22:14:54
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * a parser for real's asm rules
- *
- * grammar for these rules:
- *
-
-   rule_book  = { '#' rule ';'}
-   rule       = condition {',' assignment}
-   assignment = id '=' const
-   const      = ( number | string )
-   condition  = comp_expr { ( '&&' | '||' ) comp_expr }
-   comp_expr  = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand }
-   operand    = ( '$' id | num | '(' condition ')' )
-
- */
-
-#ifndef HAVE_ASMRP_H
-#define HAVE_ASMRP_H
-
-int asmrp_match (const char *rules, int bandwidth, int *matches) ;
-
-#endif
--- a/libmpdemux/realrtsp/real.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,612 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS real.c,v 1.8 2003/03/30 17:11:50
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * special functions for real streams.
- * adopted from joschkas real tools.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "../config.h"
-#include "../bswap.h"
-#include "real.h"
-#include "asmrp.h"
-#include "sdpplin.h"
-#include "xbuffer.h"
-#if USE_LIBAVUTIL_SO
-#include "ffmpeg/md5.h"
-#else
-#include "libavutil/md5.h"
-#endif
-
-/*
-#define LOG
-*/
-
-static const unsigned char xor_table[] = {
-    0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
-    0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
-    0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
-    0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
-    0x10, 0x57, 0x05, 0x18, 0x54, 0x00, 0x00, 0x00 };
-
-
-#define BE_32C(x,y) (*((uint32_t*)(x))=be2me_32(y))
-
-#define BE_16(x)  be2me_16(*(uint16_t*)(x))
-
-#define BE_32(x)  be2me_32(*(uint32_t*)(x))
-
-#ifndef MAX
-#define MAX(x,y) ((x>y) ? x : y)
-#endif
-
-#define BUF_SIZE 4096
-
-#ifdef LOG
-static void hexdump (const char *buf, int length) {
-
-  int i;
-
-  printf (" hexdump> ");
-  for (i = 0; i < length; i++) {
-    unsigned char c = buf[i];
-
-    printf ("%02x", c);
-
-    if ((i % 16) == 15)
-      printf ("\n         ");
-
-    if ((i % 2) == 1)
-      printf (" ");
-
-  }
-  printf ("\n");
-}
-#endif
-
-
-static void calc_response_string (char *result, char *challenge) {
- 
-  char zres[16];
-  int  i;
-      
-  av_md5_sum(zres, challenge, 64);
- 
-  /* convert zres to ascii string */
-  for (i=0; i<16; i++ ) {
-    char a, b;
-    
-    a = (zres[i] >> 4) & 15;
-    b = zres[i] & 15;
-
-    result[i*2]   = ((a<10) ? (a+48) : (a+87)) & 255;
-    result[i*2+1] = ((b<10) ? (b+48) : (b+87)) & 255;
-  }
-}
-
-static void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) {
-
-  int   ch_len, table_len, resp_len;
-  int   i;
-  char *ptr;
-  char  buf[128];
-
-  /* initialize return values */
-  memset(response, 0, 64);
-  memset(chksum, 0, 34);
-
-  /* initialize buffer */
-  memset(buf, 0, 128);
-  ptr=buf;
-  BE_32C(ptr, 0xa1e9149d);
-  ptr+=4;
-  BE_32C(ptr, 0x0e6b3b59);
-  ptr+=4;
-
-  /* some (length) checks */
-  if (challenge != NULL)
-  {
-    ch_len = strlen (challenge);
-
-    if (ch_len == 40) /* what a hack... */
-    {
-      challenge[32]=0;
-      ch_len=32;
-    }
-    if ( ch_len > 56 ) ch_len=56;
-    
-    /* copy challenge to buf */
-    memcpy(ptr, challenge, ch_len);
-  }
-  
-    table_len = strlen(xor_table);
-
-    if (table_len > 56) table_len=56;
-
-    /* xor challenge bytewise with xor_table */
-    for (i=0; i<table_len; i++)
-      ptr[i] = ptr[i] ^ xor_table[i];
-
-  calc_response_string (response, buf);
-
-  /* add tail */
-  resp_len = strlen (response);
-  strcpy (&response[resp_len], "01d0a8e3");
-
-  /* calculate checksum */
-  for (i=0; i<resp_len/4; i++)
-    chksum[i] = response[i*4];
-}
-
-
-/*
- * takes a MLTI-Chunk and a rule number got from match_asm_rule,
- * returns a pointer to selected data and number of bytes in that.
- */
-
-static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out) {
-
-  int numrules, codec, size;
-  int i;
-  
-  /* MLTI chunk should begin with MLTI */
-
-  if ((mlti_chunk[0] != 'M')
-      ||(mlti_chunk[1] != 'L')
-      ||(mlti_chunk[2] != 'T')
-      ||(mlti_chunk[3] != 'I'))
-  {
-#ifdef LOG
-    printf("libreal: MLTI tag not detected, copying data\n");
-#endif
-    *out = xbuffer_copyin(*out, 0, mlti_chunk, mlti_size);
-    return mlti_size;
-  }
-
-  mlti_chunk+=4;
-
-  /* next 16 bits are the number of rules */
-  numrules=BE_16(mlti_chunk);
-  if (selection >= numrules) return 0;
-
-  /* now <numrules> indices of codecs follows */
-  /* we skip to selection                     */
-  mlti_chunk+=(selection+1)*2;
-
-  /* get our index */
-  codec=BE_16(mlti_chunk);
-
-  /* skip to number of codecs */
-  mlti_chunk+=(numrules-selection)*2;
-
-  /* get number of codecs */
-  numrules=BE_16(mlti_chunk);
-
-  if (codec >= numrules) {
-    printf("codec index >= number of codecs. %i %i\n", codec, numrules);
-    return 0;
-  }
-
-  mlti_chunk+=2;
- 
-  /* now seek to selected codec */
-  for (i=0; i<codec; i++) {
-    size=BE_32(mlti_chunk);
-    mlti_chunk+=size+4;
-  }
-  
-  size=BE_32(mlti_chunk);
-
-#ifdef LOG
-  hexdump(mlti_chunk+4, size);
-#endif
-  *out = xbuffer_copyin(*out, 0, mlti_chunk+4, size);
-  return size;
-}
-
-/*
- * looking at stream description.
- */
-
-static rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {
-
-  sdpplin_t *desc;
-  rmff_header_t *header;
-  char *buf;
-  int len, i;
-  int max_bit_rate=0;
-  int avg_bit_rate=0;
-  int max_packet_size=0;
-  int avg_packet_size=0;
-  int duration=0;
-  
-
-  if (!data) return NULL;
-
-  desc=sdpplin_parse(data);
-
-  if (!desc) return NULL;
-  
-  buf = xbuffer_init(2048);
-  header=calloc(1,sizeof(rmff_header_t));
-
-  header->fileheader=rmff_new_fileheader(4+desc->stream_count);
-  header->cont=rmff_new_cont(
-      desc->title,
-      desc->author,
-      desc->copyright,
-      desc->abstract);
-  header->data=rmff_new_dataheader(0,0);
-  header->streams=calloc(1,sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
-#ifdef LOG
-    printf("number of streams: %u\n", desc->stream_count);
-#endif
-
-  for (i=0; i<desc->stream_count; i++) {
-
-    int j=0;
-    int n;
-    char b[64];
-    int rulematches[16];
-
-#ifdef LOG
-    printf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
-#endif
-    n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
-    for (j=0; j<n; j++) {
-#ifdef LOG
-      printf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
-#endif
-      sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
-      *stream_rules = xbuffer_strcat(*stream_rules, b);
-    }
-
-    if (!desc->stream[i]->mlti_data) {
-	len = 0;
-	buf = NULL;
-    } else
-    len=select_mlti_data(desc->stream[i]->mlti_data, desc->stream[i]->mlti_data_size, rulematches[0], &buf);
-    
-    header->streams[i]=rmff_new_mdpr(
-	desc->stream[i]->stream_id,
-        desc->stream[i]->max_bit_rate,
-        desc->stream[i]->avg_bit_rate,
-        desc->stream[i]->max_packet_size,
-        desc->stream[i]->avg_packet_size,
-        desc->stream[i]->start_time,
-        desc->stream[i]->preroll,
-        desc->stream[i]->duration,
-        desc->stream[i]->stream_name,
-        desc->stream[i]->mime_type,
-	len,
-	buf);
-
-    duration=MAX(duration,desc->stream[i]->duration);
-    max_bit_rate+=desc->stream[i]->max_bit_rate;
-    avg_bit_rate+=desc->stream[i]->avg_bit_rate;
-    max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size);
-    if (avg_packet_size)
-      avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2;
-    else
-      avg_packet_size=desc->stream[i]->avg_packet_size;
-  }
-  
-  if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
-    (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
-
-  header->prop=rmff_new_prop(
-      max_bit_rate,
-      avg_bit_rate,
-      max_packet_size,
-      avg_packet_size,
-      0,
-      duration,
-      0,
-      0,
-      0,
-      desc->stream_count,
-      desc->flags);
-
-  rmff_fix_header(header);
-  buf = xbuffer_free(buf);
-
-  return header;
-}
-
-int real_get_rdt_chunk(rtsp_t *rtsp_session, char **buffer) {
-
-  int n=1;
-  uint8_t header[8];
-  rmff_pheader_t ph;
-  int size;
-  int flags1, flags2;
-  int unknown1;
-  uint32_t ts;
-  static uint32_t prev_ts = -1;
-  static int prev_stream_number = -1;
-
-  n=rtsp_read_data(rtsp_session, header, 8);
-  if (n<8) return 0;
-  if (header[0] != 0x24)
-  {
-    printf("rdt chunk not recognized: got 0x%02x\n", header[0]);
-    return 0;
-  }
-  size=(header[1]<<16)+(header[2]<<8)+(header[3]);
-  flags1=header[4];
-  if ((flags1!=0x40)&&(flags1!=0x42))
-  {
-#ifdef LOG
-    printf("got flags1: 0x%02x\n",flags1);
-#endif
-    if(header[6] == 0x06) {
-      printf("Stream EOF detected\n");
-      return -1;
-    }
-    header[0]=header[5];
-    header[1]=header[6];
-    header[2]=header[7];
-    n=rtsp_read_data(rtsp_session, header+3, 5);
-    if (n<5) return 0;
-#ifdef LOG
-    printf("ignoring bytes:\n");
-    hexdump(header, 8);
-#endif
-    n=rtsp_read_data(rtsp_session, header+4, 4);
-    if (n<4) return 0;
-    flags1=header[4];
-    size-=9;
-  }
-  flags2=header[7];
-  // header[5..6] == frame number in stream
-  unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
-  n=rtsp_read_data(rtsp_session, header, 6);
-  if (n<6) return 0;
-  ts=BE_32(header);
-  
-#ifdef LOG
-  printf("ts: %u, size: %u, flags: 0x%02x, unknown values: 0x%06x 0x%02x 0x%02x\n", 
-          ts, size, flags1, unknown1, header[4], header[5]);
-#endif
-  size+=2;
-  
-  ph.object_version=0;
-  ph.length=size;
-  ph.stream_number=(flags1>>1)&1;
-  ph.timestamp=ts;
-  ph.reserved=0;
-  if ((flags2&1) == 0 && (prev_ts != ts || prev_stream_number != ph.stream_number))
-  {
-    prev_ts = ts;
-    prev_stream_number = ph.stream_number;
-    ph.flags=2;
-  }
-  else
-    ph.flags=0;
-  *buffer = xbuffer_ensure_size(*buffer, 12+size);
-  rmff_dump_pheader(&ph, *buffer);
-  size-=12;
-  n=rtsp_read_data(rtsp_session, (*buffer)+12, size);
-  
-  return (n <= 0) ? 0 : n+12;
-}
-
-static int convert_timestamp(char *str, int *sec, int *msec) {
-  int hh, mm, ss, ms = 0;
-  if (sscanf(str, "%d:%d:%d.%d", &hh, &mm, &ss, &ms) < 3) {
-    hh = 0;
-    if (sscanf(str, "%d:%d.%d", &mm, &ss, &ms) < 2) {
-      mm = 0;
-      if (sscanf(str, "%d.%d", &ss, &ms) < 1) {
-	ss = 0;
-	ms = 0;
-      }
-    }
-  }
-  if (sec)
-    *sec = hh * 3600 + mm * 60 + ss;
-  if (msec)
-    *msec = ms;
-  return 1;
-}
-
-//! maximum size of the rtsp description, must be < INT_MAX
-#define MAX_DESC_BUF (20 * 1024 * 1024)
-rmff_header_t  *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth) {
-
-  char *description=NULL;
-  char *session_id=NULL;
-  rmff_header_t *h;
-  char *challenge1;
-  char challenge2[64];
-  char checksum[34];
-  char *subscribe;
-  char *buf = xbuffer_init(256);
-  char *mrl=rtsp_get_mrl(rtsp_session);
-  unsigned int size;
-  int status;
-  uint32_t maxbandwidth = bandwidth;
-  
-  /* get challenge */
-  challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
-#ifdef LOG
-  printf("real: Challenge1: %s\n", challenge1);
-#endif
-
-  /* set a reasonable default to get the best stream, unless bandwidth given */
-  if (!bandwidth)
-      bandwidth = 10485800;
-  
-  /* request stream description */
-  rtsp_schedule_field(rtsp_session, "Accept: application/sdp");
-  sprintf(buf, "Bandwidth: %u", bandwidth);
-  rtsp_schedule_field(rtsp_session, buf);
-  rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000");
-  rtsp_schedule_field(rtsp_session, "RegionData: 0");
-  rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
-  rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
-  rtsp_schedule_field(rtsp_session, "Language: en-US");
-  rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
-  status=rtsp_request_describe(rtsp_session,NULL);
-
-  if ( status<200 || status>299 )
-  {
-    char *alert=rtsp_search_answers(rtsp_session,"Alert");
-    if (alert) {
-      printf("real: got message from server:\n%s\n", alert);
-    }
-    rtsp_send_ok(rtsp_session);
-    buf = xbuffer_free(buf);
-    return NULL;
-  }
-
-  /* receive description */
-  size=0;
-  if (!rtsp_search_answers(rtsp_session,"Content-length"))
-    printf("real: got no Content-length!\n");
-  else
-    size=atoi(rtsp_search_answers(rtsp_session,"Content-length"));
-
-  // as size is unsigned this also catches the case (size < 0)
-  if (size > MAX_DESC_BUF) {
-    printf("real: Content-length for description too big (> %uMB)!\n",
-            MAX_DESC_BUF/(1024*1024) );
-    xbuffer_free(buf);
-    return NULL;
-  }
-
-  if (!rtsp_search_answers(rtsp_session,"ETag"))
-    printf("real: got no ETag!\n");
-  else
-    session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
-    
-#ifdef LOG
-  printf("real: Stream description size: %u\n", size);
-#endif
-
-  description=malloc(size+1);
-
-  if( rtsp_read_data(rtsp_session, description, size) <= 0) {
-    buf = xbuffer_free(buf);
-    return NULL;
-  }
-  description[size]=0;
-
-  /* parse sdp (sdpplin) and create a header and a subscribe string */
-  subscribe = xbuffer_init(256);
-  strcpy(subscribe, "Subscribe: ");
-  h=real_parse_sdp(description, &subscribe, bandwidth);
-  if (!h) {
-    subscribe = xbuffer_free(subscribe);
-    buf = xbuffer_free(buf);
-    return NULL;
-  }
-  rmff_fix_header(h);
-
-#ifdef LOG
-  printf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
-    h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
-#endif
-  
-  /* setup our streams */
-  real_calc_response_and_checksum (challenge2, checksum, challenge1);
-  buf = xbuffer_ensure_size(buf, strlen(challenge2) + strlen(checksum) + 32);
-  sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum);
-  rtsp_schedule_field(rtsp_session, buf);
-  buf = xbuffer_ensure_size(buf, strlen(session_id) + 32);
-  sprintf(buf, "If-Match: %s", session_id);
-  rtsp_schedule_field(rtsp_session, buf);
-  rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
-  buf = xbuffer_ensure_size(buf, strlen(mrl) + 32);
-  sprintf(buf, "%s/streamid=0", mrl);
-  rtsp_request_setup(rtsp_session,buf,NULL);
-
-  if (h->prop->num_streams > 1) {
-    rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
-    buf = xbuffer_ensure_size(buf, strlen(session_id) + 32);
-    sprintf(buf, "If-Match: %s", session_id);
-    rtsp_schedule_field(rtsp_session, buf);
-
-    buf = xbuffer_ensure_size(buf, strlen(mrl) + 32);
-    sprintf(buf, "%s/streamid=1", mrl);
-    rtsp_request_setup(rtsp_session,buf,NULL);
-  }
-  /* set stream parameter (bandwidth) with our subscribe string */
-  rtsp_schedule_field(rtsp_session, subscribe);
-  rtsp_request_setparameter(rtsp_session,NULL);
-
-  /* set delivery bandwidth */
-  if (maxbandwidth) {
-      sprintf(buf, "SetDeliveryBandwidth: Bandwidth=%u;BackOff=0", maxbandwidth);
-      rtsp_schedule_field(rtsp_session, buf);
-      rtsp_request_setparameter(rtsp_session,NULL);
-  }
-
-  {
-    int s_ss = 0, s_ms = 0, e_ss = 0, e_ms = 0;
-    char *str;
-    if ((str = rtsp_get_param(rtsp_session, "start"))) {
-      convert_timestamp(str, &s_ss, &s_ms);
-      free(str);
-    }
-    if ((str = rtsp_get_param(rtsp_session, "end"))) {
-      convert_timestamp(str, &e_ss, &e_ms);
-      free(str);
-    }
-    str = buf + sprintf(buf, s_ms ? "%s%d.%d-" : "%s%d-", "Range: npt=", s_ss, s_ms);
-    if (e_ss || e_ms)
-      sprintf(str, e_ms ? "%d.%d" : "%d", e_ss, e_ms);
-  }
-  rtsp_schedule_field(rtsp_session, buf);
-  /* and finally send a play request */
-  rtsp_request_play(rtsp_session,NULL);
-
-  subscribe = xbuffer_free(subscribe);
-  buf = xbuffer_free(buf);
-  return h;
-}
-
-struct real_rtsp_session_t *
-init_real_rtsp_session (void)
-{
-  struct real_rtsp_session_t *real_rtsp_session = NULL;
-
-  real_rtsp_session = malloc (sizeof (struct real_rtsp_session_t));
-  real_rtsp_session->recv = xbuffer_init (BUF_SIZE);
-
-  return real_rtsp_session;
-}
-
-void
-free_real_rtsp_session (struct real_rtsp_session_t* real_session)
-{
-  if (!real_session)
-    return;
-  
-  xbuffer_free (real_session->recv);
-  free (real_session);
-}
--- a/libmpdemux/realrtsp/real.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS real.h,v 1.2 2002/12/24 01:30:22
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * special functions for real streams.
- * adopted from joschkas real tools.
- *
- */
- 
-#ifndef HAVE_REAL_H
-#define HAVE_REAL_H
-
-#include "rmff.h"
-#include "../librtsp/rtsp.h"
-
-#define HEADER_SIZE 4096
-
-struct real_rtsp_session_t {
-  /* receive buffer */
-  uint8_t *recv;
-  int recv_size;
-  int recv_read;
-
-  /* header buffer */
-  uint8_t header[HEADER_SIZE];
-  int header_len;
-  int header_read;
-};
-
-int real_get_rdt_chunk(rtsp_t *rtsp_session, char **buffer);
-rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth);
-struct real_rtsp_session_t *init_real_rtsp_session (void);
-void free_real_rtsp_session (struct real_rtsp_session_t* real_session);
-
-#endif
-
--- a/libmpdemux/realrtsp/rmff.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,907 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rmff.c,v 1.3 2002/12/24 01:30:22
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * functions for real media file format
- * adopted from joschkas real tools
- */
-
-#include "rmff.h"
-#include "xbuffer.h"
-
-/*
-#define LOG
-*/
-
-#define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
-#define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
-                   (((uint8_t*)(x))[1] << 16) | \
-                   (((uint8_t*)(x))[2] << 8) | \
-                    ((uint8_t*)(x))[3])
-
-static void hexdump (const char *buf, int length) {
-
-  int i;
-
-  printf ("rmff: ascii>");
-  for (i = 0; i < length; i++) {
-    unsigned char c = buf[i];
-
-    if ((c >= 32) && (c <= 128))
-      printf ("%c", c);
-    else
-      printf (".");
-  }
-  printf ("\n");
-
-  printf ("rmff: hexdump> ");
-  for (i = 0; i < length; i++) {
-    unsigned char c = buf[i];
-
-    printf ("%02x", c);
-
-    if ((i % 16) == 15)
-      printf ("\nrmff:         ");
-
-    if ((i % 2) == 1)
-      printf (" ");
-
-  }
-  printf ("\n");
-}
-
-/*
- * writes header data to a buffer
- */
-
-static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) {
-
-  if (!fileheader) return;
-  fileheader->object_id=BE_32(&fileheader->object_id);
-  fileheader->size=BE_32(&fileheader->size);
-  fileheader->object_version=BE_16(&fileheader->object_version);
-  fileheader->file_version=BE_32(&fileheader->file_version);
-  fileheader->num_headers=BE_32(&fileheader->num_headers);
-  
-  memcpy(buffer, fileheader, 8);
-  memcpy(&buffer[8], &fileheader->object_version, 2);
-  memcpy(&buffer[10], &fileheader->file_version, 8);
-
-  fileheader->size=BE_32(&fileheader->size);
-  fileheader->object_version=BE_16(&fileheader->object_version);
-  fileheader->file_version=BE_32(&fileheader->file_version);
-  fileheader->num_headers=BE_32(&fileheader->num_headers);
-  fileheader->object_id=BE_32(&fileheader->object_id);
-}
-
-static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) {
-
-  if (!prop) return;
-  prop->object_id=BE_32(&prop->object_id);
-  prop->size=BE_32(&prop->size);
-  prop->object_version=BE_16(&prop->object_version);
-  prop->max_bit_rate=BE_32(&prop->max_bit_rate);
-  prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
-  prop->max_packet_size=BE_32(&prop->max_packet_size);
-  prop->avg_packet_size=BE_32(&prop->avg_packet_size);
-  prop->num_packets=BE_32(&prop->num_packets);
-  prop->duration=BE_32(&prop->duration);
-  prop->preroll=BE_32(&prop->preroll);
-  prop->index_offset=BE_32(&prop->index_offset);
-  prop->data_offset=BE_32(&prop->data_offset);
-  prop->num_streams=BE_16(&prop->num_streams);
-  prop->flags=BE_16(&prop->flags);
-
-  memcpy(buffer, prop, 8);
-  memcpy(&buffer[8], &prop->object_version, 2);
-  memcpy(&buffer[10], &prop->max_bit_rate, 36);
-  memcpy(&buffer[46], &prop->num_streams, 2);
-  memcpy(&buffer[48], &prop->flags, 2);
-  
-  prop->size=BE_32(&prop->size);
-  prop->object_version=BE_16(&prop->object_version);
-  prop->max_bit_rate=BE_32(&prop->max_bit_rate);
-  prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
-  prop->max_packet_size=BE_32(&prop->max_packet_size);
-  prop->avg_packet_size=BE_32(&prop->avg_packet_size);
-  prop->num_packets=BE_32(&prop->num_packets);
-  prop->duration=BE_32(&prop->duration);
-  prop->preroll=BE_32(&prop->preroll);
-  prop->index_offset=BE_32(&prop->index_offset);
-  prop->data_offset=BE_32(&prop->data_offset);
-  prop->num_streams=BE_16(&prop->num_streams);
-  prop->flags=BE_16(&prop->flags);
-  prop->object_id=BE_32(&prop->object_id);
-}
-
-static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) {
-
-  int s1, s2, s3;
-
-  if (!mdpr) return;
-  mdpr->object_id=BE_32(&mdpr->object_id);
-  mdpr->size=BE_32(&mdpr->size);
-  mdpr->object_version=BE_16(&mdpr->object_version);
-  mdpr->stream_number=BE_16(&mdpr->stream_number);
-  mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
-  mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
-  mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
-  mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
-  mdpr->start_time=BE_32(&mdpr->start_time);
-  mdpr->preroll=BE_32(&mdpr->preroll);
-  mdpr->duration=BE_32(&mdpr->duration);
-
-  memcpy(buffer, mdpr, 8);
-  memcpy(&buffer[8], &mdpr->object_version, 2);
-  memcpy(&buffer[10], &mdpr->stream_number, 2);
-  memcpy(&buffer[12], &mdpr->max_bit_rate, 28);
-  memcpy(&buffer[40], &mdpr->stream_name_size, 1);
-  s1=mdpr->stream_name_size;
-  memcpy(&buffer[41], mdpr->stream_name, s1);
-
-  memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1);
-  s2=mdpr->mime_type_size;
-  memcpy(&buffer[42+s1], mdpr->mime_type, s2);
-  
-  mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
-  memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4);
-  mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
-  s3=mdpr->type_specific_len;
-  memcpy(&buffer[46+s1+s2], mdpr->type_specific_data, s3);
-
-  mdpr->size=BE_32(&mdpr->size);
-  mdpr->stream_number=BE_16(&mdpr->stream_number);
-  mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
-  mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
-  mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
-  mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
-  mdpr->start_time=BE_32(&mdpr->start_time);
-  mdpr->preroll=BE_32(&mdpr->preroll);
-  mdpr->duration=BE_32(&mdpr->duration);
-  mdpr->object_id=BE_32(&mdpr->object_id);
-
-}
-
-static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) {
-
-  int p;
-
-  if (!cont) return;
-  cont->object_id=BE_32(&cont->object_id);
-  cont->size=BE_32(&cont->size);
-  cont->object_version=BE_16(&cont->object_version);
-
-  memcpy(buffer, cont, 8);
-  memcpy(&buffer[8], &cont->object_version, 2);
-  
-  cont->title_len=BE_16(&cont->title_len);
-  memcpy(&buffer[10], &cont->title_len, 2);
-  cont->title_len=BE_16(&cont->title_len);
-  memcpy(&buffer[12], cont->title, cont->title_len);
-  p=12+cont->title_len;
-
-  cont->author_len=BE_16(&cont->author_len);
-  memcpy(&buffer[p], &cont->author_len, 2);
-  cont->author_len=BE_16(&cont->author_len);
-  memcpy(&buffer[p+2], cont->author, cont->author_len);
-  p+=2+cont->author_len;
-
-  cont->copyright_len=BE_16(&cont->copyright_len);
-  memcpy(&buffer[p], &cont->copyright_len, 2);
-  cont->copyright_len=BE_16(&cont->copyright_len);
-  memcpy(&buffer[p+2], cont->copyright, cont->copyright_len);
-  p+=2+cont->copyright_len;
-
-  cont->comment_len=BE_16(&cont->comment_len);
-  memcpy(&buffer[p], &cont->comment_len, 2);
-  cont->comment_len=BE_16(&cont->comment_len);
-  memcpy(&buffer[p+2], cont->comment, cont->comment_len);
-
-  cont->size=BE_32(&cont->size);
-  cont->object_version=BE_16(&cont->object_version);
-  cont->object_id=BE_32(&cont->object_id);
-}
-
-static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) {
-
-  if (!data) return;
-  data->object_id=BE_32(&data->object_id);
-  data->size=BE_32(&data->size);
-  data->object_version=BE_16(&data->object_version);
-  data->num_packets=BE_32(&data->num_packets);
-  data->next_data_header=BE_32(&data->next_data_header);
-
-  memcpy(buffer, data, 8);
-  memcpy(&buffer[8], &data->object_version, 2);
-  memcpy(&buffer[10], &data->num_packets, 8);
-  
-  data->num_packets=BE_32(&data->num_packets);
-  data->next_data_header=BE_32(&data->next_data_header);
-  data->size=BE_32(&data->size);
-  data->object_version=BE_16(&data->object_version);
-  data->object_id=BE_32(&data->object_id);
-}
-
-int rmff_dump_header(rmff_header_t *h, char *buffer, int max) {
-
-  int written=0;
-  rmff_mdpr_t **stream=h->streams;
-
-  rmff_dump_fileheader(h->fileheader, &buffer[written]);
-  written+=h->fileheader->size;
-  rmff_dump_prop(h->prop, &buffer[written]);
-  written+=h->prop->size;
-  rmff_dump_cont(h->cont, &buffer[written]);
-  written+=h->cont->size;
-  if (stream)
-  {
-    while(*stream)
-    {
-      rmff_dump_mdpr(*stream, &buffer[written]);
-      written+=(*stream)->size;
-      stream++;
-    }
-  }
-    
-  rmff_dump_dataheader(h->data, &buffer[written]);
-  written+=18;
-
-  return written;
-}
-
-void rmff_dump_pheader(rmff_pheader_t *h, char *data) {
-
-  data[0]=(h->object_version>>8) & 0xff;
-  data[1]=h->object_version & 0xff;
-  data[2]=(h->length>>8) & 0xff;
-  data[3]=h->length & 0xff;
-  data[4]=(h->stream_number>>8) & 0xff;
-  data[5]=h->stream_number & 0xff;
-  data[6]=(h->timestamp>>24) & 0xff;
-  data[7]=(h->timestamp>>16) & 0xff;
-  data[8]=(h->timestamp>>8) & 0xff;
-  data[9]=h->timestamp & 0xff;
-  data[10]=h->reserved;
-  data[11]=h->flags;
-}
-
-static rmff_fileheader_t *rmff_scan_fileheader(const char *data) {
-
-  rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t));
-
-  fileheader->object_id=BE_32(data);
-  fileheader->size=BE_32(&data[4]);
-  fileheader->object_version=BE_16(&data[8]);
-  if (fileheader->object_version != 0)
-  {
-    printf("warning: unknown object version in .RMF: 0x%04x\n",
-      fileheader->object_version);
-  }
-  fileheader->file_version=BE_32(&data[10]);
-  fileheader->num_headers=BE_32(&data[14]);
-
-  return fileheader;
-}
-
-static rmff_prop_t *rmff_scan_prop(const char *data) {
-
-  rmff_prop_t *prop=malloc(sizeof(rmff_prop_t));
-
-  prop->object_id=BE_32(data);
-  prop->size=BE_32(&data[4]);
-  prop->object_version=BE_16(&data[8]);
-  if (prop->object_version != 0)
-  {
-    printf("warning: unknown object version in PROP: 0x%04x\n",
-      prop->object_version);
-  }
-  prop->max_bit_rate=BE_32(&data[10]);
-  prop->avg_bit_rate=BE_32(&data[14]);
-  prop->max_packet_size=BE_32(&data[18]);
-  prop->avg_packet_size=BE_32(&data[22]);
-  prop->num_packets=BE_32(&data[26]);
-  prop->duration=BE_32(&data[30]);
-  prop->preroll=BE_32(&data[34]);
-  prop->index_offset=BE_32(&data[38]);
-  prop->data_offset=BE_32(&data[42]);
-  prop->num_streams=BE_16(&data[46]);
-  prop->flags=BE_16(&data[48]);
-
-  return prop;
-}
-
-static rmff_mdpr_t *rmff_scan_mdpr(const char *data) {
-
-  rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t));
-
-  mdpr->object_id=BE_32(data);
-  mdpr->size=BE_32(&data[4]);
-  mdpr->object_version=BE_16(&data[8]);
-  if (mdpr->object_version != 0)
-  {
-    printf("warning: unknown object version in MDPR: 0x%04x\n",
-      mdpr->object_version);
-  }
-  mdpr->stream_number=BE_16(&data[10]);
-  mdpr->max_bit_rate=BE_32(&data[12]);
-  mdpr->avg_bit_rate=BE_32(&data[16]);
-  mdpr->max_packet_size=BE_32(&data[20]);
-  mdpr->avg_packet_size=BE_32(&data[24]);
-  mdpr->start_time=BE_32(&data[28]);
-  mdpr->preroll=BE_32(&data[32]);
-  mdpr->duration=BE_32(&data[36]);
-  
-  mdpr->stream_name_size=data[40];
-  mdpr->stream_name=malloc(mdpr->stream_name_size+1);
-  memcpy(mdpr->stream_name, &data[41], mdpr->stream_name_size);
-  mdpr->stream_name[mdpr->stream_name_size]=0;
-  
-  mdpr->mime_type_size=data[41+mdpr->stream_name_size];
-  mdpr->mime_type=malloc(mdpr->mime_type_size+1);
-  memcpy(mdpr->mime_type, &data[42+mdpr->stream_name_size], mdpr->mime_type_size);
-  mdpr->mime_type[mdpr->mime_type_size]=0;
-  
-  mdpr->type_specific_len=BE_32(&data[42+mdpr->stream_name_size+mdpr->mime_type_size]);
-  mdpr->type_specific_data=malloc(mdpr->type_specific_len);
-  memcpy(mdpr->type_specific_data, 
-      &data[46+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len);
-  
-  return mdpr;
-}
-
-static rmff_cont_t *rmff_scan_cont(const char *data) {
-
-  rmff_cont_t *cont=malloc(sizeof(rmff_cont_t));
-  int pos;
-
-  cont->object_id=BE_32(data);
-  cont->size=BE_32(&data[4]);
-  cont->object_version=BE_16(&data[8]);
-  if (cont->object_version != 0)
-  {
-    printf("warning: unknown object version in CONT: 0x%04x\n",
-      cont->object_version);
-  }
-  cont->title_len=BE_16(&data[10]);
-  cont->title=malloc(cont->title_len+1);
-  memcpy(cont->title, &data[12], cont->title_len);
-  cont->title[cont->title_len]=0;
-  pos=cont->title_len+12;
-  cont->author_len=BE_16(&data[pos]);
-  cont->author=malloc(cont->author_len+1);
-  memcpy(cont->author, &data[pos+2], cont->author_len);
-  cont->author[cont->author_len]=0;
-  pos=pos+2+cont->author_len;
-  cont->copyright_len=BE_16(&data[pos]);
-  cont->copyright=malloc(cont->copyright_len+1);
-  memcpy(cont->copyright, &data[pos+2], cont->copyright_len);
-  cont->copyright[cont->copyright_len]=0;
-  pos=pos+2+cont->copyright_len;
-  cont->comment_len=BE_16(&data[pos]);
-  cont->comment=malloc(cont->comment_len+1);
-  memcpy(cont->comment, &data[pos+2], cont->comment_len);
-  cont->comment[cont->comment_len]=0;
-
-  return cont;
-}
-
-static rmff_data_t *rmff_scan_dataheader(const char *data) {
-
-  rmff_data_t *dh=malloc(sizeof(rmff_data_t));
-
-  dh->object_id=BE_32(data);
-  dh->size=BE_32(&data[4]);
-  dh->object_version=BE_16(&data[8]);
-  if (dh->object_version != 0)
-  {
-    printf("warning: unknown object version in DATA: 0x%04x\n",
-      dh->object_version);
-  }
-  dh->num_packets=BE_32(&data[10]);
-  dh->next_data_header=BE_32(&data[14]);
-
-  return dh;
-}
- 
-rmff_header_t *rmff_scan_header(const char *data) {
-
-	rmff_header_t *header=malloc(sizeof(rmff_header_t));
-	rmff_mdpr_t   *mdpr=NULL;
-	int           chunk_size;
-	uint32_t      chunk_type;
-  const char    *ptr=data;
-  int           i;
-
-  header->fileheader=NULL;
-	header->prop=NULL;
-	header->cont=NULL;
-	header->data=NULL;
-
-  chunk_type = BE_32(ptr);
-  if (chunk_type != RMF_TAG)
-  {
-    printf("rmff: not an real media file header (.RMF tag not found).\n");
-    free(header);
-    return NULL;
-  }
-  header->fileheader=rmff_scan_fileheader(ptr);
-  ptr += header->fileheader->size;
-	
-	header->streams=malloc(sizeof(rmff_mdpr_t*)*(header->fileheader->num_headers));
-  for (i=0; i<header->fileheader->num_headers; i++) {
-    header->streams[i]=NULL;
-  }
-  
-  for (i=1; i<header->fileheader->num_headers; i++) {
-    chunk_type = BE_32(ptr);
-  
-    if (ptr[0] == 0)
-    {
-      printf("rmff: warning: only %d of %d header found.\n", i, header->fileheader->num_headers);
-      break;
-    }
-    
-    chunk_size=1;
-    switch (chunk_type) {
-    case PROP_TAG:
-      header->prop=rmff_scan_prop(ptr);
-      chunk_size=header->prop->size;
-      break;
-    case MDPR_TAG:
-      mdpr=rmff_scan_mdpr(ptr);
-      chunk_size=mdpr->size;
-      header->streams[mdpr->stream_number]=mdpr;
-      break;
-    case CONT_TAG:
-      header->cont=rmff_scan_cont(ptr);
-      chunk_size=header->cont->size;
-      break;
-    case DATA_TAG:
-      header->data=rmff_scan_dataheader(ptr);
-      chunk_size=34;     /* hard coded header size */
-      break;
-    default:
-      printf("unknown chunk\n");
-      hexdump(ptr,10);
-      chunk_size=1;
-      break;
-    }
-    ptr+=chunk_size;
-  }
-
-	return header;
-}
-
-rmff_header_t *rmff_scan_header_stream(int fd) {
-
-  rmff_header_t *header;
-  char *buf=xbuffer_init(1024);
-  int index=0;
-  uint32_t chunk_type;
-  uint32_t chunk_size;
-
-  do {
-    buf = xbuffer_ensure_size(buf, index+8);
-    recv(fd, buf+index, 8, 0);
-    chunk_type=BE_32(buf+index); index+=4;
-    chunk_size=BE_32(buf+index); index+=4;
-
-    switch (chunk_type) {
-      case DATA_TAG:
-        chunk_size=18;
-      case MDPR_TAG:
-      case CONT_TAG:
-      case RMF_TAG:
-      case PROP_TAG:
-        buf = xbuffer_ensure_size(buf, index+chunk_size-8);
-        recv(fd, buf+index, (chunk_size-8), 0);
-	index+=(chunk_size-8);
-        break;
-      default:
-        printf("rmff_scan_header_stream: unknown chunk");
-        hexdump(buf+index-8, 8);
-        chunk_type=DATA_TAG;
-    }
-  } while (chunk_type != DATA_TAG);
-
-  header = rmff_scan_header(buf);
-
-  xbuffer_free(buf);
-
-  return header;
-}
-
-void rmff_scan_pheader(rmff_pheader_t *h, char *data) {
-
-  h->object_version=BE_16(data);
-  h->length=BE_16(data+2);
-  h->stream_number=BE_16(data+4);
-  h->timestamp=BE_32(data+6);
-  h->reserved=(uint8_t)data[10];
-  h->flags=(uint8_t)data[11];
-}
-
-rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) {
-
-  rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t));
-
-  fileheader->object_id=RMF_TAG;
-  fileheader->size=18;
-  fileheader->object_version=0;
-  fileheader->file_version=0;
-  fileheader->num_headers=num_headers;
-
-  return fileheader;
-}
-
-rmff_prop_t *rmff_new_prop (
-    uint32_t max_bit_rate,
-    uint32_t avg_bit_rate,
-    uint32_t max_packet_size,
-    uint32_t avg_packet_size,
-    uint32_t num_packets,
-    uint32_t duration,
-    uint32_t preroll,
-    uint32_t index_offset,
-    uint32_t data_offset,
-    uint16_t num_streams,
-    uint16_t flags ) {
-
-  rmff_prop_t *prop=malloc(sizeof(rmff_prop_t));
-
-  prop->object_id=PROP_TAG;
-  prop->size=50;
-  prop->object_version=0;
-
-  prop->max_bit_rate=max_bit_rate;
-  prop->avg_bit_rate=avg_bit_rate;
-  prop->max_packet_size=max_packet_size;
-  prop->avg_packet_size=avg_packet_size;
-  prop->num_packets=num_packets;
-  prop->duration=duration;
-  prop->preroll=preroll;
-  prop->index_offset=index_offset;
-  prop->data_offset=data_offset;
-  prop->num_streams=num_streams;
-  prop->flags=flags;
-   
-  return prop;
-}
-
-rmff_mdpr_t *rmff_new_mdpr(
-      uint16_t   stream_number,
-      uint32_t   max_bit_rate,
-      uint32_t   avg_bit_rate,
-      uint32_t   max_packet_size,
-      uint32_t   avg_packet_size,
-      uint32_t   start_time,
-      uint32_t   preroll,
-      uint32_t   duration,
-      const char *stream_name,
-      const char *mime_type,
-      uint32_t   type_specific_len,
-      const char *type_specific_data ) {
-
-  rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t));
-  
-  mdpr->object_id=MDPR_TAG;
-  mdpr->object_version=0;
-
-  mdpr->stream_number=stream_number;
-  mdpr->max_bit_rate=max_bit_rate;
-  mdpr->avg_bit_rate=avg_bit_rate;
-  mdpr->max_packet_size=max_packet_size;
-  mdpr->avg_packet_size=avg_packet_size;
-  mdpr->start_time=start_time;
-  mdpr->preroll=preroll;
-  mdpr->duration=duration;
-  mdpr->stream_name_size=0;
-  if (stream_name) {
-    mdpr->stream_name=strdup(stream_name);
-    mdpr->stream_name_size=strlen(stream_name);
-  }
-  mdpr->mime_type_size=0;
-  if (mime_type) {
-    mdpr->mime_type=strdup(mime_type);
-    mdpr->mime_type_size=strlen(mime_type);
-  }
-  mdpr->type_specific_len=type_specific_len;
-  mdpr->type_specific_data=malloc(type_specific_len);
-  memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len);
-  mdpr->mlti_data=NULL;
-  
-  mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46;
-
-  return mdpr;
-}
-
-rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment) {
-
-  rmff_cont_t *cont=malloc(sizeof(rmff_cont_t));
-
-  cont->object_id=CONT_TAG;
-  cont->object_version=0;
-
-  cont->title=NULL;
-  cont->author=NULL;
-  cont->copyright=NULL;
-  cont->comment=NULL;
-  
-  cont->title_len=0;
-  cont->author_len=0;
-  cont->copyright_len=0;
-  cont->comment_len=0;
-
-  if (title) {
-    cont->title_len=strlen(title);
-    cont->title=strdup(title);
-  }
-  if (author) {
-    cont->author_len=strlen(author);
-    cont->author=strdup(author);
-  }
-  if (copyright) {
-    cont->copyright_len=strlen(copyright);
-    cont->copyright=strdup(copyright);
-  }
-  if (comment) {
-    cont->comment_len=strlen(comment);
-    cont->comment=strdup(comment);
-  }
-  cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18;
-
-  return cont;
-}
-
-rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header) {
-
-  rmff_data_t *data=malloc(sizeof(rmff_data_t));
-
-  data->object_id=DATA_TAG;
-  data->size=18;
-  data->object_version=0;
-  data->num_packets=num_packets;
-  data->next_data_header=next_data_header;
-
-  return data;
-}
-  
-void rmff_print_header(rmff_header_t *h) {
-
-  rmff_mdpr_t **stream;
-  
-  if(!h) {
-    printf("rmff_print_header: NULL given\n");
-    return;
-  }
-  if(h->fileheader)
-  {
-    printf("\nFILE:\n");
-    printf("file version      : %d\n", h->fileheader->file_version);
-    printf("number of headers : %d\n", h->fileheader->num_headers);
-  }
-  if(h->cont)
-  {
-    printf("\nCONTENT:\n");
-    printf("title     : %s\n", h->cont->title);
-    printf("author    : %s\n", h->cont->author);
-    printf("copyright : %s\n", h->cont->copyright);
-    printf("comment   : %s\n", h->cont->comment);
-  }
-  if(h->prop)
-  {
-    printf("\nSTREAM PROPERTIES:\n");
-    printf("bit rate (max/avg)    : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate);
-    printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size);
-    printf("packets       : %i\n", h->prop->num_packets);
-    printf("duration      : %i ms\n", h->prop->duration);
-    printf("pre-buffer    : %i ms\n", h->prop->preroll);
-    printf("index offset  : %i bytes\n", h->prop->index_offset);
-    printf("data offset   : %i bytes\n", h->prop->data_offset);
-    printf("media streams : %i\n", h->prop->num_streams);
-    printf("flags         : ");
-    if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled ");
-    if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled ");
-    if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast ");
-    printf("\n");
-  }
-  stream=h->streams;
-  if(stream)
-  {
-    while (*stream)
-    {
-      printf("\nSTREAM %i:\n", (*stream)->stream_number);
-      printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type);
-      printf("bit rate (max/avg)      : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate);
-      printf("packet size (max/avg)   : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size);
-      printf("start time : %i\n", (*stream)->start_time);
-      printf("pre-buffer : %i ms\n", (*stream)->preroll);
-      printf("duration   : %i ms\n", (*stream)->duration);
-      printf("type specific data:\n");
-      hexdump((*stream)->type_specific_data, (*stream)->type_specific_len);
-      stream++;
-    }
-  }
-  if(h->data)
-  {
-    printf("\nDATA:\n");
-    printf("size      : %i\n", h->data->size);
-    printf("packets   : %i\n", h->data->num_packets);
-    printf("next DATA : 0x%08x\n", h->data->next_data_header);
-  } 
-}
-
-void rmff_fix_header(rmff_header_t *h) {
-
-  int num_headers=0;
-  int header_size=0;
-  rmff_mdpr_t **streams;
-  int num_streams=0;
-
-  if (!h) {
-    printf("rmff_fix_header: fatal: no header given.\n");
-    return;
-  }
-
-  if (!h->streams) {
-    printf("rmff_fix_header: warning: no MDPR chunks\n");
-  } else
-  {
-    streams=h->streams;
-    while (*streams)
-    {
-      num_streams++;
-      num_headers++;
-      header_size+=(*streams)->size;
-      streams++;
-    }
-  }
-  
-  if (h->prop) {
-    if (h->prop->size != 50)
-    {
-#ifdef LOG
-      printf("rmff_fix_header: correcting prop.size from %i to %i\n", h->prop->size, 50);
-#endif
-      h->prop->size=50;
-    }
-    if (h->prop->num_streams != num_streams)
-    {
-#ifdef LOG
-      printf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h->prop->num_streams, num_streams);
-#endif
-      h->prop->num_streams=num_streams;
-    }
-    num_headers++;
-    header_size+=50;
-  } else
-    printf("rmff_fix_header: warning: no PROP chunk.\n");
-
-  if (h->cont) {
-    num_headers++;
-    header_size+=h->cont->size;
-  } else
-    printf("rmff_fix_header: warning: no CONT chunk.\n");
-
-  if (!h->data) {
-#ifdef LOG
-    printf("rmff_fix_header: no DATA chunk, creating one\n");
-#endif
-    h->data=malloc(sizeof(rmff_data_t));
-    h->data->object_id=DATA_TAG;
-    h->data->object_version=0;
-    h->data->size=34;
-    h->data->num_packets=0;
-    h->data->next_data_header=0;
-  }
-  num_headers++;
-
-  
-  if (!h->fileheader) {
-#ifdef LOG
-    printf("rmff_fix_header: no fileheader, creating one");
-#endif
-    h->fileheader=malloc(sizeof(rmff_fileheader_t));
-    h->fileheader->object_id=RMF_TAG;
-    h->fileheader->size=34;
-    h->fileheader->object_version=0;
-    h->fileheader->file_version=0;
-    h->fileheader->num_headers=num_headers+1;
-  }
-  header_size+=h->fileheader->size;
-  num_headers++;
-
-  if(h->fileheader->num_headers != num_headers) {
-#ifdef LOG
-    printf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers); 
-#endif
-    h->fileheader->num_headers=num_headers;
-  }
-
-  if(h->prop) {
-    if (h->prop->data_offset != header_size) {
-#ifdef LOG
-      printf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size); 
-#endif
-      h->prop->data_offset=header_size;
-    }
-    if (h->prop->num_packets == 0) {
-      int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size);
-#ifdef LOG
-      printf("rmff_fix_header: assuming prop.num_packets=%i\n", p); 
-#endif
-      h->prop->num_packets=p;
-    }
-    if (h->data->num_packets == 0) {
-#ifdef LOG
-      printf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets); 
-#endif
-      h->data->num_packets=h->prop->num_packets;
-    }
-    
-#ifdef LOG
-    printf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size); 
-#endif
-    h->data->size=h->prop->num_packets*h->prop->avg_packet_size;
-  }
-}
-
-int rmff_get_header_size(rmff_header_t *h) {
-
-  if (!h) return 0;
-  if (!h->prop) return -1;
-
-  return h->prop->data_offset+18;
-  
-}
-
-void rmff_free_header(rmff_header_t *h) {
-
-  if (!h) return;
-
-  if (h->fileheader) free(h->fileheader);
-  if (h->prop) free(h->prop);
-  if (h->data) free(h->data);
-  if (h->cont)
-  {
-    free(h->cont->title);
-    free(h->cont->author);
-    free(h->cont->copyright);
-    free(h->cont->comment);
-    free(h->cont);
-  }
-  if (h->streams)
-  {
-    rmff_mdpr_t **s=h->streams;
-
-    while(*s) {
-      free((*s)->stream_name);
-      free((*s)->mime_type);
-      free((*s)->type_specific_data);
-      free(*s);
-      s++;
-    }
-    free(h->streams);
-  }
-  free(h);
-}
--- a/libmpdemux/realrtsp/rmff.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS rmff.h,v 1.3 2003/02/10 22:11:10
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * some functions for real media file headers
- * adopted from joschkas real tools
- */
-
-#include <sys/types.h>
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#include <winsock2.h>
-#endif
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
-
-#ifndef HAVE_RMFF_H
-#define HAVE_RMFF_H
-
-
-#define RMFF_HEADER_SIZE 0x12
-
-#define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
-        (((long)(unsigned char)(ch3)       ) | \
-        ( (long)(unsigned char)(ch2) << 8  ) | \
-        ( (long)(unsigned char)(ch1) << 16 ) | \
-        ( (long)(unsigned char)(ch0) << 24 ) )
-
-
-#define RMF_TAG   FOURCC_TAG('.', 'R', 'M', 'F')
-#define PROP_TAG  FOURCC_TAG('P', 'R', 'O', 'P')
-#define MDPR_TAG  FOURCC_TAG('M', 'D', 'P', 'R')
-#define CONT_TAG  FOURCC_TAG('C', 'O', 'N', 'T')
-#define DATA_TAG  FOURCC_TAG('D', 'A', 'T', 'A')
-#define INDX_TAG  FOURCC_TAG('I', 'N', 'D', 'X')
-#define PNA_TAG   FOURCC_TAG('P', 'N', 'A',  0 )
-
-#define MLTI_TAG  FOURCC_TAG('M', 'L', 'T', 'I')
-
-/* prop flags */
-#define PN_SAVE_ENABLED         0x01
-#define PN_PERFECT_PLAY_ENABLED 0x02
-#define PN_LIVE_BROADCAST       0x04
-
-/*
- * rm header data structs
- */
-
-typedef struct {
-
-  uint32_t object_id;
-  uint32_t size;
-  uint16_t object_version;
-
-  uint32_t file_version;
-  uint32_t num_headers;
-} rmff_fileheader_t;
-
-typedef struct {
-
-  uint32_t object_id;
-  uint32_t size;
-  uint16_t object_version;
-
-  uint32_t max_bit_rate;
-  uint32_t avg_bit_rate;
-  uint32_t max_packet_size;
-  uint32_t avg_packet_size;
-  uint32_t num_packets;
-  uint32_t duration;
-  uint32_t preroll;
-  uint32_t index_offset;
-  uint32_t data_offset;
-  uint16_t num_streams;
-  uint16_t flags;
-    
-} rmff_prop_t;
-
-typedef struct {
-
-  uint32_t  object_id;
-  uint32_t  size;
-  uint16_t  object_version;
-
-  uint16_t  stream_number;
-  uint32_t  max_bit_rate;
-  uint32_t  avg_bit_rate;
-  uint32_t  max_packet_size;
-  uint32_t  avg_packet_size;
-  uint32_t  start_time;
-  uint32_t  preroll;
-  uint32_t  duration;
-  uint8_t   stream_name_size;
-  char      *stream_name;
-  uint8_t   mime_type_size;
-  char      *mime_type;
-  uint32_t  type_specific_len;
-  char      *type_specific_data;
-
-  int       mlti_data_size;
-  char      *mlti_data;
-
-} rmff_mdpr_t;
-
-typedef struct {
-
-  uint32_t  object_id;
-  uint32_t  size;
-  uint16_t  object_version;
-
-  uint16_t  title_len;
-  char      *title;
-  uint16_t  author_len;
-  char      *author;
-  uint16_t  copyright_len;
-  char      *copyright;
-  uint16_t  comment_len;
-  char      *comment;
-  
-} rmff_cont_t;
-
-typedef struct {
-  
-  uint32_t object_id;
-  uint32_t size;
-  uint16_t object_version;
-
-  uint32_t num_packets;
-  uint32_t next_data_header; /* rarely used */
-} rmff_data_t;
-
-typedef struct {
-
-  rmff_fileheader_t *fileheader;
-  rmff_prop_t *prop;
-  rmff_mdpr_t **streams;
-  rmff_cont_t *cont;
-  rmff_data_t *data;
-} rmff_header_t;
-
-typedef struct {
-
-  uint16_t object_version;
-
-  uint16_t length;
-  uint16_t stream_number;
-  uint32_t timestamp;
-  uint8_t reserved;
-  uint8_t flags;
-
-} rmff_pheader_t;
-
-/*
- * constructors for header structs
- */
- 
-rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers);
-
-rmff_prop_t *rmff_new_prop (
-    uint32_t max_bit_rate,
-    uint32_t avg_bit_rate,
-    uint32_t max_packet_size,
-    uint32_t avg_packet_size,
-    uint32_t num_packets,
-    uint32_t duration,
-    uint32_t preroll,
-    uint32_t index_offset,
-    uint32_t data_offset,
-    uint16_t num_streams,
-    uint16_t flags );
-
-rmff_mdpr_t *rmff_new_mdpr(
-    uint16_t   stream_number,
-    uint32_t   max_bit_rate,
-    uint32_t   avg_bit_rate,
-    uint32_t   max_packet_size,
-    uint32_t   avg_packet_size,
-    uint32_t   start_time,
-    uint32_t   preroll,
-    uint32_t   duration,
-    const char *stream_name,
-    const char *mime_type,
-    uint32_t   type_specific_len,
-    const char *type_specific_data );
-
-rmff_cont_t *rmff_new_cont(
-    const char *title,
-    const char *author,
-    const char *copyright,
-    const char *comment);
-
-rmff_data_t *rmff_new_dataheader(
-    uint32_t num_packets, uint32_t next_data_header);
-
-/*
- * reads header infos from data and returns a newly allocated header struct
- */
-rmff_header_t *rmff_scan_header(const char *data);
-
-/*
- * scans a data packet header. Notice, that this function does not allocate
- * the header struct itself.
- */
-void rmff_scan_pheader(rmff_pheader_t *h, char *data);
-
-/*
- * reads header infos from stream and returns a newly allocated header struct
- */
-rmff_header_t *rmff_scan_header_stream(int fd);
-
-/*
- * prints header information in human readible form to stdout
- */
-void rmff_print_header(rmff_header_t *h);
-
-/*
- * does some checks and fixes header if possible
- */
-void rmff_fix_header(rmff_header_t *h);
-
-/*
- * returns the size of the header (incl. first data-header)
- */
-int rmff_get_header_size(rmff_header_t *h);
- 
-/*
- * dumps the header <h> to <buffer>. <max> is the size of <buffer>
- */
-int rmff_dump_header(rmff_header_t *h, char *buffer, int max);
-
-/*
- * dumps a packet header
- */
-void rmff_dump_pheader(rmff_pheader_t *h, char *data);
-
-/*
- * frees a header struct
- */
-void rmff_free_header(rmff_header_t *h);
-
-#endif
--- a/libmpdemux/realrtsp/sdpplin.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,366 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS sdpplin.c,v 1.1 2002/12/24 01:30:22
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * sdp/sdpplin parser.
- *
- */
- 
-#include "config.h"
-#include "../librtsp/rtsp.h"
-#include "sdpplin.h"
-#include "xbuffer.h"
-#include "mp_msg.h"
-
-/*
-#define LOG
-*/
-
-/*
- * Decodes base64 strings (based upon b64 package)
- */
-
-static char *b64_decode(const char *in, char *out, int *size)
-{
-  char dtable[256];              /* Encode / decode table */
-  int i,j,k;
-
-  for (i = 0; i < 255; i++) {
-    dtable[i] = 0x80;
-  }
-  for (i = 'A'; i <= 'Z'; i++) {
-    dtable[i] = 0 + (i - 'A');
-  }
-  for (i = 'a'; i <= 'z'; i++) {
-    dtable[i] = 26 + (i - 'a');
-  }
-  for (i = '0'; i <= '9'; i++) {
-    dtable[i] = 52 + (i - '0');
-  }
-  dtable['+'] = 62;
-  dtable['/'] = 63;
-  dtable['='] = 0;
-
-  k=0;
-  
-  /*CONSTANTCONDITION*/
-  for (j=0; j<strlen(in); j+=4)
-  {
-    char a[4], b[4];
-
-    for (i = 0; i < 4; i++) {
-      int c = in[i+j];
-
-      if (dtable[c] & 0x80) {
-        printf("Illegal character '%c' in input.\n", c);
-//        exit(1);
-        return NULL;
-      }
-      a[i] = (char) c;
-      b[i] = (char) dtable[c];
-    }
-    out = xbuffer_ensure_size(out, k+4);
-    out[k++] = (b[0] << 2) | (b[1] >> 4);
-    out[k++] = (b[1] << 4) | (b[2] >> 2);
-    out[k++] = (b[2] << 6) | b[3];
-    i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
-    if (i < 3) {
-      out[k]=0;
-      *size=k;
-      return out;
-    }
-  }
-  out[k]=0;
-  *size=k;
-  return out;
-}
-
-static char *nl(char *data) {
-
-  char *nlptr = (data) ? strchr(data,'\n') : NULL;
-  return (nlptr) ? nlptr + 1 : NULL;
-}
-
-static int filter(const char *in, const char *filter, char **out) {
-
-  int flen=strlen(filter);
-  int len;
-
-  if (!in)
-    return 0;
-
-  len = (strchr(in,'\n')) ? strchr(in,'\n')-in : strlen(in);
-
-  if (!strncmp(in,filter,flen))
-  {
-    if(in[flen]=='"') flen++;
-    if(in[len-1]==13) len--;
-    if(in[len-1]=='"') len--;
-    *out = xbuffer_copyin(*out, 0, in+flen, len-flen+1);
-    (*out)[len-flen]=0;
-
-    return len-flen;
-  }
-  
-  return 0;
-}
-static sdpplin_stream_t *sdpplin_parse_stream(char **data) {
-
-  sdpplin_stream_t *desc=calloc(1,sizeof(sdpplin_stream_t));
-  char      *buf=xbuffer_init(32);
-  char      *decoded=xbuffer_init(32);
-  int       handled;
-  int       got_mimetype;
-    
-  if (filter(*data, "m=", &buf)) {
-    desc->id = strdup(buf);
-  } else
-  {
-    printf("sdpplin: no m= found.\n");
-    free(desc);
-    xbuffer_free(buf);
-    return NULL;
-  }
-  *data=nl(*data);
-
-  got_mimetype = 0;
-
-  while (*data && **data && *data[0]!='m') {
-#ifdef LOG
-    {
-      int len=strchr(*data,'\n')-(*data);
-      buf = xbuffer_copyin(buf, 0, *data, len+1);
-      buf[len]=0;
-      printf("libreal: sdpplin_stream: '%s'\n", buf);
-    }
-#endif
-
-    handled=0;
-    
-    if(filter(*data,"a=control:streamid=",&buf)) {
-      desc->stream_id=atoi(buf);
-      handled=1;
-      *data=nl(*data);
-    }
-
-    if(filter(*data,"a=MaxBitRate:integer;",&buf)) {
-      desc->max_bit_rate=atoi(buf);
-      if (!desc->avg_bit_rate)
-        desc->avg_bit_rate=desc->max_bit_rate;
-      handled=1;
-      *data=nl(*data);
-    }
-
-    if(filter(*data,"a=MaxPacketSize:integer;",&buf)) {
-      desc->max_packet_size=atoi(buf);
-      if (!desc->avg_packet_size)
-        desc->avg_packet_size=desc->max_packet_size;
-      handled=1;
-      *data=nl(*data);
-    }
-    
-    if(filter(*data,"a=StartTime:integer;",&buf)) {
-      desc->start_time=atoi(buf);
-      handled=1;
-      *data=nl(*data);
-    }
-
-    if(filter(*data,"a=Preroll:integer;",&buf)) {
-      desc->preroll=atoi(buf);
-      handled=1;
-      *data=nl(*data);
-    }
-
-    if(filter(*data,"a=length:npt=",&buf)) {
-      desc->duration=(uint32_t)(atof(buf)*1000);
-      handled=1;
-      *data=nl(*data);
-    }
-
-    if(filter(*data,"a=StreamName:string;",&buf)) {
-      desc->stream_name=strdup(buf);
-      desc->stream_name_size=strlen(desc->stream_name);
-      handled=1;
-      *data=nl(*data);
-    }
-
-    if(filter(*data,"a=mimetype:string;",&buf)) {
-      desc->mime_type=strdup(buf);
-      desc->mime_type_size=strlen(desc->mime_type);
-      handled=1;
-      got_mimetype = 1;
-      *data=nl(*data);
-    }
-
-    if(filter(*data,"a=OpaqueData:buffer;",&buf)) {
-      decoded = b64_decode(buf, decoded, &(desc->mlti_data_size));
-      desc->mlti_data=malloc(desc->mlti_data_size);
-      memcpy(desc->mlti_data, decoded, desc->mlti_data_size);
-      handled=1;
-      *data=nl(*data);
-#ifdef LOG
-      printf("mlti_data_size: %i\n", desc->mlti_data_size);
-#endif
-    }
-    
-    if(filter(*data,"a=ASMRuleBook:string;",&buf)) {
-      desc->asm_rule_book=strdup(buf);
-      handled=1;
-      *data=nl(*data);
-    }
-
-    if(!handled) {
-#ifdef LOG
-      int len=strchr(*data,'\n')-(*data);
-      buf = xbuffer_copyin(buf, 0, *data, len+1);
-      buf[len]=0;
-      printf("libreal: sdpplin_stream: not handled: '%s'\n", buf);
-#endif
-      *data=nl(*data);
-    }
-  }
-
-  if (!got_mimetype) {
-    mp_msg(MSGT_OPEN, MSGL_V, "libreal: sdpplin_stream: no mimetype\n");
-    desc->mime_type = strdup("audio/x-pn-realaudio");
-    desc->mime_type_size = strlen(desc->mime_type);
-    if (desc->stream_id)
-      mp_msg(MSGT_OPEN, MSGL_WARN, "libreal: sdpplin_stream: implicit mimetype for stream_id != 0, weird.\n");
-  }
-
-  xbuffer_free(buf);
-  xbuffer_free(decoded);
-  
-  return desc;
-}
-
-sdpplin_t *sdpplin_parse(char *data) {
-
-  sdpplin_t        *desc=calloc(1,sizeof(sdpplin_t));
-  char             *buf=xbuffer_init(32);
-  char             *decoded=xbuffer_init(32);
-  int              handled;
-  int              len;
-
-  while (data && *data) {
-#ifdef LOG
-    {
-      int len=strchr(data,'\n')-(data);
-      buf = xbuffer_copyin(buf, 0, data, len+1);
-      buf[len]=0;
-      printf("libreal: sdpplin: '%s'\n", buf);
-    }
-#endif
-
-    handled=0;
-    
-    if (filter(data, "m=", &buf)) {
-      sdpplin_stream_t *stream=sdpplin_parse_stream(&data);
-#ifdef LOG
-      printf("got data for stream id %u\n", stream->stream_id);
-#endif
-      if (desc->stream && (stream->stream_id >= 0) && (stream->stream_id < desc->stream_count))
-      desc->stream[stream->stream_id]=stream;
-      else if (desc->stream)
-      {
-      mp_msg(MSGT_OPEN, MSGL_ERR, "sdpplin: bad stream_id %d (must be >= 0, < %d). Broken sdp?\n",
-        stream->stream_id, desc->stream_count);
-      free(stream);
-      } else {
-        mp_msg(MSGT_OPEN, MSGL_V, "sdpplin: got 'm=', but 'a=StreamCount' is still unknown.\n");
-        if (stream->stream_id == 0) {
-          desc->stream_count=1;
-          desc->stream=malloc(sizeof(sdpplin_stream_t*));
-          desc->stream[0]=stream;
-        } else {
-          mp_msg(MSGT_OPEN, MSGL_ERR, "sdpplin: got 'm=', but 'a=StreamCount' is still unknown and stream_id != 0. Broken sdp?\n");
-          free(stream);
-        }
-      }
-      continue;
-    }
-
-    if(filter(data,"a=Title:buffer;",&buf)) {
-      decoded=b64_decode(buf, decoded, &len);
-      desc->title=strdup(decoded);
-      handled=1;
-      data=nl(data);
-    }
-    
-    if(filter(data,"a=Author:buffer;",&buf)) {
-      decoded=b64_decode(buf, decoded, &len);
-      desc->author=strdup(decoded);
-      handled=1;
-      data=nl(data);
-    }
-    
-    if(filter(data,"a=Copyright:buffer;",&buf)) {
-      decoded=b64_decode(buf, decoded, &len);
-      desc->copyright=strdup(decoded);
-      handled=1;
-      data=nl(data);
-    }
-    
-    if(filter(data,"a=Abstract:buffer;",&buf)) {
-      decoded=b64_decode(buf, decoded, &len);
-      desc->abstract=strdup(decoded);
-      handled=1;
-      data=nl(data);
-    }
-    
-    if(filter(data,"a=StreamCount:integer;",&buf)) {
-      desc->stream_count=(unsigned int)atoi(buf);
-      desc->stream=malloc(sizeof(sdpplin_stream_t*)*desc->stream_count);
-      handled=1;
-      data=nl(data);
-    }
-
-    if(filter(data,"a=Flags:integer;",&buf)) {
-      desc->flags=atoi(buf);
-      handled=1;
-      data=nl(data);
-    }
-
-    if(!handled) {
-#ifdef LOG
-      int len=strchr(data,'\n')-data;
-      buf = xbuffer_copyin(buf, 0, data, len+1);
-      buf[len]=0;
-      printf("libreal: sdpplin: not handled: '%s'\n", buf);
-#endif
-      data=nl(data);
-    }
-  }
-
-  xbuffer_free(buf);
-  xbuffer_free(decoded);
-  
-  return desc;
-}
-
-void sdpplin_free(sdpplin_t *description) {
-
-  /* TODO: free strings */
-  free(description);
-}
-
--- a/libmpdemux/realrtsp/sdpplin.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * This file was ported to MPlayer from xine CVS sdpplin.h,v 1.1 2002/12/24 01:30:22
- */
-
-/*
- * Copyright (C) 2002 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU 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
- *
- *
- * sdp/sdpplin parser.
- *
- */
- 
-#ifndef HAVE_SDPPLIN_H
-#define HAVE_SDPPLIN_H
-
-#include "rmff.h"
-#include "../librtsp/rtsp.h"
-
-typedef struct {
-
-  char *id;
-  char *bandwidth;
-
-  int stream_id;
-  char *range;
-  char *length;
-  char *rtpmap;
-  char *mimetype;
-  int min_switch_overlap;
-  int start_time;
-  int end_one_rule_end_all;
-  int avg_bit_rate;
-  int max_bit_rate;
-  int avg_packet_size;
-  int max_packet_size;
-  int end_time;
-  int seek_greater_on_switch;
-  int preroll;
-
-  int duration;
-  char *stream_name;
-  int stream_name_size;
-  char *mime_type;
-  int mime_type_size;
-  char *mlti_data;
-  int mlti_data_size;
-  int  rmff_flags_length;
-  char *rmff_flags;
-  int  asm_rule_book_length;
-  char *asm_rule_book;
-
-} sdpplin_stream_t;
-
-typedef struct {
-
-  int sdp_version, sdpplin_version;
-  char *owner;
-  char *session_name;
-  char *session_info;
-  char *uri;
-  char *email;
-  char *phone;
-  char *connection;
-  char *bandwidth;
-
-  int flags;
-  int is_real_data_type;
-  int stream_count;
-  char *title;
-  char *author;
-  char *copyright;
-  char *keywords;
-  int  asm_rule_book_length;
-  char *asm_rule_book;
-  char *abstract;
-  char *range;
-  int avg_bit_rate;
-  int max_bit_rate;
-  int avg_packet_size;
-  int max_packet_size;
-  int preroll;
-  int duration;
-
-  sdpplin_stream_t **stream;
-  
-} sdpplin_t;
-
-sdpplin_t *sdpplin_parse(char *data);
-
-void sdpplin_free(sdpplin_t *description);
-
-#endif
-
--- a/libmpdemux/realrtsp/xbuffer.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/* 
- * xbuffer code
- *
- * Includes a minimalistic replacement for xine_buffer functions used in
- * Real streaming code. Only function needed by this code are implemented.
- *
- * Most code comes from xine_buffer.c Copyright (C) 2002 the xine project
- *
- * WARNING: do not mix original xine_buffer functions with this code!
- * xbuffers behave like xine_buffers, but are not byte-compatible with them.
- * You must take care of pointers returned by xbuffers functions (no macro to
- * do it automatically)
- *
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-#include "xbuffer.h"
-
-
-typedef struct {
-  uint32_t size;
-  uint32_t chunk_size;
-} xbuffer_header_t;
-
-#define XBUFFER_HEADER_SIZE sizeof (xbuffer_header_t)
-
-
-
-void *xbuffer_init(int chunk_size) {  
-  uint8_t *data=calloc(1,chunk_size+XBUFFER_HEADER_SIZE);
-
-  xbuffer_header_t *header=(xbuffer_header_t*)data;
-
-  header->size=chunk_size;
-  header->chunk_size=chunk_size;
-
-  return data+XBUFFER_HEADER_SIZE;
-}
-
-
-
-void *xbuffer_free(void *buf) {
-  if (!buf) {
-    return NULL;
-  }
-
-  free(((uint8_t*)buf)-XBUFFER_HEADER_SIZE);
-
-  return NULL;
-}
-
-
-
-void *xbuffer_copyin(void *buf, int index, const void *data, int len) {
-    if (!buf || !data) {
-    return NULL;
-  }
-
-  buf = xbuffer_ensure_size(buf, index+len);
-  memcpy(((uint8_t*)buf)+index, data, len);
-
-  return buf;
-}
-
-
-
-void *xbuffer_ensure_size(void *buf, int size) {
-  xbuffer_header_t *xbuf;
-  int new_size;
-
-  if (!buf) {
-    return 0;
-  }
-
-  xbuf = ((xbuffer_header_t*)(((uint8_t*)buf)-XBUFFER_HEADER_SIZE));
-  
-  if (xbuf->size < size) {
-    new_size = size + xbuf->chunk_size - (size % xbuf->chunk_size);
-    xbuf->size = new_size;
-    buf = ((uint8_t*)realloc(((uint8_t*)buf)-XBUFFER_HEADER_SIZE,
-          new_size+XBUFFER_HEADER_SIZE)) + XBUFFER_HEADER_SIZE;
-  }
-
-  return buf;
-}
-
-
-
-void *xbuffer_strcat(void *buf, char *data) {
-
-  if (!buf || !data) {
-    return NULL;
-  }
-
-  buf = xbuffer_ensure_size(buf, strlen(buf)+strlen(data)+1);
-
-  strcat(buf, data);
-
-  return buf;
-}
--- a/libmpdemux/realrtsp/xbuffer.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/* 
- * xbuffer code
- *
- * Includes a minimalistic replacement for xine_buffer functions used in
- * Real streaming code. Only function needed by this code are implemented.
- *
- * Most code comes from xine_buffer.c Copyright (C) 2002 the xine project
- *
- * WARNING: do not mix original xine_buffer functions with this code!
- * xbuffers behave like xine_buffers, but are not byte-compatible with them.
- * You must take care of pointers returned by xbuffers functions (no macro to
- * do it automatically)
- *
- */
-
-
-#ifndef _XCL_H_
-#define _XCL_H_
-
-void *xbuffer_init(int chunk_size);
-void *xbuffer_free(void *buf);
-void *xbuffer_copyin(void *buf, int index, const void *data, int len);
-void *xbuffer_ensure_size(void *buf, int size);
-void *xbuffer_strcat(void *buf, char *data);
-
-#endif
--- a/libmpdemux/rtp.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,434 +0,0 @@
-/* Imported from the dvbstream-0.2 project
- *
- * Modified for use with MPlayer, for details see the changelog at
- * http://svn.mplayerhq.hu/mplayer/trunk/
- * $Id$
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#define closesocket close
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-#include <errno.h>
-#include "stream.h"
-
-/* MPEG-2 TS RTP stack */
-
-#define DEBUG        1
-#include "rtp.h"
-
-extern int network_bandwidth;
-
-
-#define DEBUG        1
-#include "../mp_msg.h"
-#include "rtp.h"
-
-// RTP reorder routines
-// Also handling of repeated UDP packets (a bug of ExtremeNetworks switches firmware)
-// rtpreord procedures
-// write rtp packets in cache
-// get rtp packets reordered
-
-#define MAXRTPPACKETSIN 32   // The number of max packets being reordered
-
-struct rtpbuffer
-{
-	unsigned char  data[MAXRTPPACKETSIN][STREAM_BUFFER_SIZE];
-	unsigned short  seq[MAXRTPPACKETSIN];
-	unsigned short  len[MAXRTPPACKETSIN];
-	unsigned short first;
-};
-static struct rtpbuffer rtpbuf;
-
-// RTP Reordering functions
-// Algorithm works as follows:
-// If next packet is in sequence just copy it to buffer
-// Otherwise copy it in cache according to its sequence number
-// Cache is a circular array where "rtpbuf.first" points to next sequence slot
-// and keeps track of expected sequence
-
-// Initialize rtp cache
-static void rtp_cache_reset(unsigned short seq)
-{
-	int i;
-	
-	rtpbuf.first = 0;
-	rtpbuf.seq[0] = ++seq;
-	
-	for (i=0; i<MAXRTPPACKETSIN; i++) {
-		rtpbuf.len[i] = 0;
-	}
-}
-
-// Write in a cache the rtp packet in right rtp sequence order
-static int rtp_cache(int fd, char *buffer, int length)
-{
-	struct rtpheader rh;
-	int newseq;
-	char *data;
-	unsigned short seq;
-	static int is_first = 1;
-	
-	getrtp2(fd, &rh, &data, &length);
-	if(!length)
-		return 0;
-	seq = rh.b.sequence;
-	
-	newseq = seq - rtpbuf.seq[rtpbuf.first];
-	
-	if ((newseq == 0) || is_first)
-	{
-		is_first = 0;
-		
-		//mp_msg(MSGT_NETWORK, MSGL_DBG4, "RTP (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
-		rtpbuf.first = ( 1 + rtpbuf.first ) % MAXRTPPACKETSIN;
-		rtpbuf.seq[rtpbuf.first] = ++seq;
-		goto feed;
-	}
-	
-	if (newseq > MAXRTPPACKETSIN)
-	{
-		mp_msg(MSGT_NETWORK, MSGL_DBG2, "Overrun(seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
-		rtp_cache_reset(seq);
-		goto feed;
-	}
-	
-	if (newseq < 0)
-	{
-		int i;
-		
-		// Is it a stray packet re-sent to network?
-		for (i=0; i<MAXRTPPACKETSIN; i++) {
-			if (rtpbuf.seq[i] == seq) {
-				mp_msg(MSGT_NETWORK, MSGL_ERR, "Stray packet (seq[%d]=%d seq=%d, newseq=%d found at %d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq, i);
-				return  0; // Yes, it is!
-			}
-		}
-		// Some heuristic to decide when to drop packet or to restart everything
-		if (newseq > -(3 * MAXRTPPACKETSIN)) {
-			mp_msg(MSGT_NETWORK, MSGL_ERR, "Too Old packet (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
-			return  0; // Yes, it is!
-		}
-		
-		mp_msg(MSGT_NETWORK, MSGL_ERR,  "Underrun(seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
-		
-		rtp_cache_reset(seq);
-		goto feed;
-	}
-	
-	mp_msg(MSGT_NETWORK, MSGL_DBG4, "Out of Seq (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
-	newseq = ( newseq + rtpbuf.first ) % MAXRTPPACKETSIN;
-	memcpy (rtpbuf.data[newseq], data, length);
-	rtpbuf.len[newseq] = length;
-	rtpbuf.seq[newseq] = seq;
-	
-	return 0;
-
-feed:
-	memcpy (buffer, data, length);
-	return length;
-}
-
-// Get next packet in cache
-// Look in cache to get first packet in sequence
-static int rtp_get_next(int fd, char *buffer, int length)
-{
-	int i;
-	unsigned short nextseq;
-
-	// If we have empty buffer we loop to fill it
-	for (i=0; i < MAXRTPPACKETSIN -3; i++) {
-		if (rtpbuf.len[rtpbuf.first] != 0) break;
-		
-		length = rtp_cache(fd, buffer, length) ;
-		
-		// returns on first packet in sequence 
-		if (length > 0) {
-			//mp_msg(MSGT_NETWORK, MSGL_DBG4, "Getting rtp [%d] %hu\n", i, rtpbuf.first);
-			return length;
-		} else if (length < 0) break;
-		
-		// Only if length == 0 loop continues!
-	}
-	
-	i = rtpbuf.first;
-	while (rtpbuf.len[i] == 0) {
-		mp_msg(MSGT_NETWORK, MSGL_ERR,  "Lost packet %hu\n", rtpbuf.seq[i]);
-		i = ( 1 + i ) % MAXRTPPACKETSIN;
-		if (rtpbuf.first == i) break;
-	}
-	rtpbuf.first = i;
-	
-	// Copy next non empty packet from cache
-	mp_msg(MSGT_NETWORK, MSGL_DBG4, "Getting rtp from cache [%d] %hu\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first]);
-	memcpy (buffer, rtpbuf.data[rtpbuf.first], rtpbuf.len[rtpbuf.first]);
-	length = rtpbuf.len[rtpbuf.first]; // can be zero?
-	
-	// Reset fisrt slot and go next in cache
-	rtpbuf.len[rtpbuf.first] = 0;
-	nextseq = rtpbuf.seq[rtpbuf.first];
-	rtpbuf.first = ( 1 + rtpbuf.first ) % MAXRTPPACKETSIN;
-	rtpbuf.seq[rtpbuf.first] = nextseq + 1;
-	
-	return length;
-}
-
-
-// Read next rtp packet using cache 
-int read_rtp_from_server(int fd, char *buffer, int length) {
-	// Following test is ASSERT (i.e. uneuseful if code is correct)
-	if(buffer==NULL || length<STREAM_BUFFER_SIZE) {
-		mp_msg(MSGT_NETWORK, MSGL_ERR, "RTP buffer invalid; no data return from network\n");
-		return 0;
-	}
-	
-	// loop just to skip empty packets
-	while ((length = rtp_get_next(fd, buffer, length)) == 0) {
-		mp_msg(MSGT_NETWORK, MSGL_ERR, "Got empty packet from RTP cache!?\n");
-	}
-	
-	return(length);
-}
-
-// Start listening on a UDP port. If multicast, join the group.
-static int rtp_open_socket( URL_t *url ) {
-	int socket_server_fd, rxsockbufsz;
-	int err, err_len;
-	fd_set set;
-	struct sockaddr_in server_address;
-	struct ip_mreq mcast;
-        struct timeval tv;
-	struct hostent *hp;
-
-	mp_msg(MSGT_NETWORK,MSGL_V,"Listening for traffic on %s:%d ...\n", url->hostname, url->port );
-
-	socket_server_fd = socket(AF_INET, SOCK_DGRAM, 0);
-//	fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK );
-	if( socket_server_fd==-1 ) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create socket\n");
-		return -1;
-	}
-
-	if( isalpha(url->hostname[0]) ) {
-#ifndef HAVE_WINSOCK2
-		hp =(struct hostent*)gethostbyname( url->hostname );
-		if( hp==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname);
-			goto err_out;
-		}
-		memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr_list[0], hp->h_length );
-#else
-		server_address.sin_addr.s_addr = htonl(INADDR_ANY);
-#endif
-	} else {
-#ifndef HAVE_WINSOCK2
-#ifdef USE_ATON
-		inet_aton(url->hostname, &server_address.sin_addr);
-#else
-		inet_pton(AF_INET, url->hostname, &server_address.sin_addr);
-#endif
-#else
-		server_address.sin_addr.s_addr = htonl(INADDR_ANY);
-#endif
-	}
-	server_address.sin_family=AF_INET;
-	server_address.sin_port=htons(url->port);
-
-	if( bind( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) {
-#ifndef HAVE_WINSOCK2
-		if( errno!=EINPROGRESS ) {
-#else
-		if( WSAGetLastError() != WSAEINPROGRESS ) {
-#endif
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to connect to server\n");
-			goto err_out;
-		}
-	}
-	
-#ifdef HAVE_WINSOCK2
-	if (isalpha(url->hostname[0])) {
-		hp =(struct hostent*)gethostbyname( url->hostname );
-		if( hp==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname);
-			goto err_out;
-		}
-		memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length );
-	} else {
-		unsigned int addr = inet_addr(url->hostname);
-		memcpy( (void*)&server_address.sin_addr, (void*)&addr, sizeof(addr) );
-	}
-#endif
-
-	// Increase the socket rx buffer size to maximum -- this is UDP
-	rxsockbufsz = 240 * 1024;
-	if( setsockopt( socket_server_fd, SOL_SOCKET, SO_RCVBUF, &rxsockbufsz, sizeof(rxsockbufsz))) {
-		mp_msg(MSGT_NETWORK,MSGL_ERR,"Couldn't set receive socket buffer size\n");
-	}
-
-	if((ntohl(server_address.sin_addr.s_addr) >> 28) == 0xe) {
-		mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr;
-		//mcast.imr_interface.s_addr = inet_addr("10.1.1.2");
-		mcast.imr_interface.s_addr = 0;
-		if( setsockopt( socket_server_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))) {
-			mp_msg(MSGT_NETWORK,MSGL_ERR,"IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n");
-			goto err_out;
-		}
-	}
-
-	tv.tv_sec = 0;
-	tv.tv_usec = (1 * 1000000);	// 1 second timeout
-	FD_ZERO( &set );
-	FD_SET( socket_server_fd, &set );
-	err = select(socket_server_fd+1, &set, NULL, NULL, &tv);
-	if (err < 0) {
-	  mp_msg(MSGT_NETWORK, MSGL_FATAL, "Select failed: %s\n", strerror(errno));
-	  goto err_out;
-	}
-	if (err == 0) {
-	  mp_msg(MSGT_NETWORK,MSGL_ERR,"Timeout! No data from host %s\n", url->hostname );
-	  goto err_out;
-	}
-		err_len = sizeof( err );
-		getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len );
-		if( err ) {
-			mp_msg(MSGT_NETWORK,MSGL_DBG2,"Socket error: %d\n", err );
-			goto err_out;
-		}
-	return socket_server_fd;
-
-err_out:
-  closesocket(socket_server_fd);
-  return -1;	
-}
-
-static int rtp_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) {
-	return read_rtp_from_server( fd, buffer, size );
-}
-
-static int rtp_streaming_start( stream_t *stream, int raw_udp ) {
-	streaming_ctrl_t *streaming_ctrl;
-	int fd;
-
-	if( stream==NULL ) return -1;
-	streaming_ctrl = stream->streaming_ctrl;
-	fd = stream->fd;
-	
-	if( fd<0 ) {
-		fd = rtp_open_socket( (streaming_ctrl->url) ); 
-		if( fd<0 ) return -1;
-		stream->fd = fd;
-	}
-
-	if(raw_udp)
-		streaming_ctrl->streaming_read = nop_streaming_read;
-	else
-		streaming_ctrl->streaming_read = rtp_streaming_read;
-	streaming_ctrl->streaming_seek = nop_streaming_seek;
-	streaming_ctrl->prebuffer_size = 64*1024;	// 64 KBytes	
-	streaming_ctrl->buffering = 0;
-	streaming_ctrl->status = streaming_playing_e;
-	return 0;
-}
-
-
-static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) {
-  static char buf[1600];
-  unsigned int intP;
-  char* charP = (char*) &intP;
-  int headerSize;
-  int lengthPacket;
-  lengthPacket=recv(fd,buf,1590,0);
-  if (lengthPacket<0)
-    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp: socket read error\n");
-  else if (lengthPacket<12)
-    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp: packet too small (%d) to be an rtp frame (>12bytes)\n", lengthPacket);
-  if(lengthPacket<12) {
-    *lengthData = 0;
-    return 0;
-  }
-  rh->b.v  = (unsigned int) ((buf[0]>>6)&0x03);
-  rh->b.p  = (unsigned int) ((buf[0]>>5)&0x01);
-  rh->b.x  = (unsigned int) ((buf[0]>>4)&0x01);
-  rh->b.cc = (unsigned int) ((buf[0]>>0)&0x0f);
-  rh->b.m  = (unsigned int) ((buf[1]>>7)&0x01);
-  rh->b.pt = (unsigned int) ((buf[1]>>0)&0x7f);
-  intP = 0;
-  memcpy(charP+2,&buf[2],2);
-  rh->b.sequence = ntohl(intP);
-  intP = 0;
-  memcpy(charP,&buf[4],4);
-  rh->timestamp = ntohl(intP);
-
-  headerSize = 12 + 4*rh->b.cc; /* in bytes */
-
-  *lengthData = lengthPacket - headerSize;
-  *data = (char*) buf + headerSize;
-
-  //  mp_msg(MSGT_NETWORK,MSGL_DBG2,"Reading rtp: v=%x p=%x x=%x cc=%x m=%x pt=%x seq=%x ts=%x lgth=%d\n",rh->b.v,rh->b.p,rh->b.x,rh->b.cc,rh->b.m,rh->b.pt,rh->b.sequence,rh->timestamp,lengthPacket);
-
-  return(0);
-}
-
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  URL_t *url;
-  int udp = 0;
-
-  mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_RTP, URL: %s\n", stream->url);
-  stream->streaming_ctrl = streaming_ctrl_new();
-  if( stream->streaming_ctrl==NULL ) {
-    return STREAM_ERROR;
-  }
-  stream->streaming_ctrl->bandwidth = network_bandwidth;
-  url = url_new(stream->url);
-  stream->streaming_ctrl->url = check4proxies(url);
-
-  if( url->port==0 ) {
-    mp_msg(MSGT_NETWORK,MSGL_ERR,"You must enter a port number for RTP and UDP streams!\n");
-    goto fail;
-  }
-  if(!strncmp(stream->url, "udp", 3))
-    udp = 1;
-
-  if(rtp_streaming_start(stream, udp) < 0) {
-    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp_streaming_start(rtp) failed\n");
-    goto fail;
-  }
-
-  stream->type = STREAMTYPE_STREAM;
-  fixup_network_stream_cache(stream);
-  return STREAM_OK;
-
-fail:
-  streaming_ctrl_free( stream->streaming_ctrl );
-  stream->streaming_ctrl = NULL;
-  return STREAM_UNSUPORTED;
-}
-
-
-stream_info_t stream_info_rtp_udp = {
-  "mpeg rtp and upd streaming",
-  "rtp and udp",
-  "Dave Chapman",
-  "native rtp support",
-  open_s,
-  {"rtp", "udp", NULL},
-  NULL,
-  0 // Urls are an option string
-};
-
-
--- a/libmpdemux/rtp.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/* Imported from the dvbstream project
- *
- * Modified for use with MPlayer, for details see the changelog at
- * http://svn.mplayerhq.hu/mplayer/trunk/
- * $Id$
- */
-
-#ifndef _RTP_H
-#define _RTP_H
-
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#include <sys/socket.h>
-#else
-#include <winsock2.h>
-#endif
-
-struct rtpbits {
-  unsigned int v:2;           /* version: 2 */
-  unsigned int p:1;           /* is there padding appended: 0 */
-  unsigned int x:1;           /* number of extension headers: 0 */
-  unsigned int cc:4;          /* number of CSRC identifiers: 0 */
-  unsigned int m:1;           /* marker: 0 */
-  unsigned int pt:7;          /* payload type: 33 for MPEG2 TS - RFC 1890 */
-  unsigned int sequence:16;   /* sequence number: random */
-};
-
-struct rtpheader {	/* in network byte order */
-  struct rtpbits b;
-  int timestamp;	/* start: random */
-  int ssrc;		/* random */
-};
-
-
-static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData);
-int read_rtp_from_server(int fd, char *buffer, int length);
-
-#endif
--- a/libmpdemux/stream.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,434 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifndef __MINGW32__
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#endif
-#include <fcntl.h>
-#include <signal.h>
-#include <strings.h>
-
-#include "config.h"
-
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#else
-#include <winsock2.h>
-#endif
-
-#include "mp_msg.h"
-#include "help_mp.h"
-#include "osdep/shmem.h"
-
-#include "stream.h"
-#include "demuxer.h"
-
-#include "m_option.h"
-#include "m_struct.h"
-
-
-void cache_uninit(stream_t *s); // defined in cache2.c
-
-//#include "vcd_read_bincue.h"
-
-#ifdef HAVE_VCD
-extern stream_info_t stream_info_vcd;
-#endif
-#ifdef HAVE_CDDA
-extern stream_info_t stream_info_cdda;
-#endif
-#ifdef MPLAYER_NETWORK
-extern stream_info_t stream_info_netstream;
-extern stream_info_t stream_info_pnm;
-extern stream_info_t stream_info_asf;
-extern stream_info_t stream_info_rtsp;
-extern stream_info_t stream_info_rtp_udp;
-extern stream_info_t stream_info_http1;
-extern stream_info_t stream_info_http2;
-#endif
-#ifdef HAS_DVBIN_SUPPORT
-extern stream_info_t stream_info_dvb;
-#endif
-#ifdef HAVE_PVR
-extern stream_info_t stream_info_pvr;
-#endif
-#ifdef HAVE_FTP
-extern stream_info_t stream_info_ftp;
-#endif
-#ifdef HAVE_VSTREAM
-extern stream_info_t stream_info_vstream;
-#endif
-#ifdef USE_DVDNAV
-extern stream_info_t stream_info_dvdnav;
-#endif
-#ifdef LIBSMBCLIENT
-extern stream_info_t stream_info_smb;
-#endif
-#ifdef STREAMING_LIVE555
-extern stream_info_t stream_info_sdp;
-extern stream_info_t stream_info_rtsp_sip;
-#endif
-
-extern stream_info_t stream_info_cue;
-extern stream_info_t stream_info_null;
-extern stream_info_t stream_info_file;
-#ifdef HAVE_DVD
-extern stream_info_t stream_info_dvd;
-#endif
-
-stream_info_t* auto_open_streams[] = {
-#ifdef HAVE_VCD
-  &stream_info_vcd,
-#endif
-#ifdef HAVE_CDDA
-  &stream_info_cdda,
-#endif
-#ifdef MPLAYER_NETWORK
-  &stream_info_netstream,
-  &stream_info_http1,
-  &stream_info_asf,
-  &stream_info_pnm,
-  &stream_info_rtsp,
-#ifdef STREAMING_LIVE555
-  &stream_info_sdp,
-  &stream_info_rtsp_sip,
-#endif
-  &stream_info_rtp_udp,
-  &stream_info_http2,
-#endif
-#ifdef HAS_DVBIN_SUPPORT
-  &stream_info_dvb,
-#endif
-#ifdef HAVE_PVR
-  &stream_info_pvr,
-#endif
-#ifdef HAVE_FTP
-  &stream_info_ftp,
-#endif
-#ifdef HAVE_VSTREAM
-  &stream_info_vstream,
-#endif
-#ifdef LIBSMBCLIENT
-  &stream_info_smb,
-#endif
-  &stream_info_cue,
-#ifdef HAVE_DVD
-  &stream_info_dvd,
-#endif
-#ifdef USE_DVDNAV
-  &stream_info_dvdnav,
-#endif
-
-  &stream_info_null,
-  &stream_info_file,
-  NULL
-};
-
-stream_t* open_stream_plugin(stream_info_t* sinfo,char* filename,int mode,
-			     char** options, int* file_format, int* ret) {
-  void* arg = NULL;
-  stream_t* s;
-  m_struct_t* desc = (m_struct_t*)sinfo->opts;
-
-  // Parse options
-  if(desc) {
-    arg = m_struct_alloc(desc);
-    if(sinfo->opts_url) {
-      m_option_t url_opt = 
-	{ "stream url", arg , CONF_TYPE_CUSTOM_URL, 0, 0 ,0, sinfo->opts };
-      if(m_option_parse(&url_opt,"stream url",filename,arg,M_CONFIG_FILE) < 0) {
-	mp_msg(MSGT_OPEN,MSGL_ERR, "URL parsing failed on url %s\n",filename);
-	m_struct_free(desc,arg);
-	return NULL;
-      }	
-    }
-    if(options) {
-      int i;
-      for(i = 0 ; options[i] != NULL ; i += 2) {
-	mp_msg(MSGT_OPEN,MSGL_DBG2, "Set stream arg %s=%s\n",
-	       options[i],options[i+1]);
-	if(!m_struct_set(desc,arg,options[i],options[i+1]))
-	  mp_msg(MSGT_OPEN,MSGL_WARN, "Failed to set stream option %s=%s\n",
-		 options[i],options[i+1]);
-      }
-    }
-  }
-  s = new_stream(-2,-2);
-  s->url=strdup(filename);
-  s->flags |= mode;
-  *ret = sinfo->open(s,mode,arg,file_format);
-  if((*ret) != STREAM_OK) {
-    free(s->url);
-    free(s);
-    return NULL;
-  }
-  if(s->type <= -2)
-    mp_msg(MSGT_OPEN,MSGL_WARN, "Warning streams need a type !!!!\n");
-  if(s->flags & STREAM_SEEK && !s->seek)
-    s->flags &= ~STREAM_SEEK;
-  if(s->seek && !(s->flags & STREAM_SEEK))
-    s->flags |= STREAM_SEEK;
-  
-
-  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: [%s] %s\n",sinfo->name,filename);
-  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Description: %s\n",sinfo->info);
-  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Author: %s\n", sinfo->author);
-  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Comment: %s\n", sinfo->comment);
-  
-  return s;
-}
-
-
-stream_t* open_stream_full(char* filename,int mode, char** options, int* file_format) {
-  int i,j,l,r;
-  stream_info_t* sinfo;
-  stream_t* s;
-
-  for(i = 0 ; auto_open_streams[i] ; i++) {
-    sinfo = auto_open_streams[i];
-    if(!sinfo->protocols) {
-      mp_msg(MSGT_OPEN,MSGL_WARN, "Stream type %s has protocols == NULL, it's a bug\n", sinfo->name);
-      continue;
-    }
-    for(j = 0 ; sinfo->protocols[j] ; j++) {
-      l = strlen(sinfo->protocols[j]);
-      // l == 0 => Don't do protocol matching (ie network and filenames)
-      if((l == 0) || ((strncmp(sinfo->protocols[j],filename,l) == 0) &&
-		      (strncmp("://",filename+l,3) == 0))) {
-	*file_format = DEMUXER_TYPE_UNKNOWN;
-	s = open_stream_plugin(sinfo,filename,mode,options,file_format,&r);
-	if(s) return s;
-	if(r != STREAM_UNSUPORTED) {
-	  mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_FailedToOpen,filename);
-	  return NULL;
-	}
-	break;
-      }
-    }
-  }
-
-  mp_msg(MSGT_OPEN,MSGL_ERR, "No stream found to handle url %s\n",filename);
-  return NULL;
-}
-
-//=================== STREAMER =========================
-
-int stream_fill_buffer(stream_t *s){
-  int len;
-  if (/*s->fd == NULL ||*/ s->eof) { s->buf_pos = s->buf_len = 0; return 0; }
-  switch(s->type){
-  case STREAMTYPE_STREAM:
-#ifdef MPLAYER_NETWORK
-    if( s->streaming_ctrl!=NULL ) {
-	    len=s->streaming_ctrl->streaming_read(s->fd,s->buffer,STREAM_BUFFER_SIZE, s->streaming_ctrl);break;
-    } else {
-      len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break;
-    }
-#else
-    len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break;
-#endif
-  case STREAMTYPE_DS:
-    len = demux_read_data((demux_stream_t*)s->priv,s->buffer,STREAM_BUFFER_SIZE);
-    break;
-  
-    
-  default: 
-    len= s->fill_buffer ? s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE) : 0;
-  }
-  if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
-  s->buf_pos=0;
-  s->buf_len=len;
-  s->pos+=len;
-//  printf("[%d]",len);fflush(stdout);
-  return len;
-}
-
-int stream_seek_long(stream_t *s,off_t pos){
-off_t newpos=0;
-
-//  if( mp_msg_test(MSGT_STREAM,MSGL_DBG3) ) printf("seek_long to 0x%X\n",(unsigned int)pos);
-
-  s->buf_pos=s->buf_len=0;
-
-  switch(s->type){
-  case STREAMTYPE_STREAM:
-#ifdef _LARGEFILE_SOURCE
-    newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break;
-#else
-    newpos=pos&(~(STREAM_BUFFER_SIZE-1));break;
-#endif
-  default:
-    // Round on sector size
-    if(s->sector_size)
-      newpos=(pos/s->sector_size)*s->sector_size;
-    else { // Otherwise on the buffer size
-#ifdef _LARGEFILE_SOURCE
-      newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break;
-#else
-      newpos=pos&(~(STREAM_BUFFER_SIZE-1));break;
-#endif
-    }
-    break;
-  }
-
-if( mp_msg_test(MSGT_STREAM,MSGL_DBG3) ){
-  mp_msg(MSGT_STREAM,MSGL_DBG3, "s->pos=%"PRIX64"  newpos=%"PRIX64"  new_bufpos=%"PRIX64"  buflen=%X  \n",
-    (int64_t)s->pos,(int64_t)newpos,(int64_t)pos,s->buf_len);
-}
-  pos-=newpos;
-
-if(newpos==0 || newpos!=s->pos){
-  switch(s->type){
-  case STREAMTYPE_STREAM:
-    //s->pos=newpos; // real seek
-    // Some streaming protocol allow to seek backward and forward
-    // A function call that return -1 can tell that the protocol
-    // doesn't support seeking.
-#ifdef MPLAYER_NETWORK
-    if(s->seek) { // new stream seek is much cleaner than streaming_ctrl one
-      if(!s->seek(s,newpos)) {
-      	mp_msg(MSGT_STREAM,MSGL_ERR, "Seek failed\n");
-      	return 0;
-      }
-      break;
-    }
-	
-    if( s->streaming_ctrl!=NULL && s->streaming_ctrl->streaming_seek ) {
-      if( s->streaming_ctrl->streaming_seek( s->fd, pos, s->streaming_ctrl )<0 ) {
-        mp_msg(MSGT_STREAM,MSGL_INFO,"Stream not seekable!\n");
-        return 1;
-      }
-    } 
-#else
-    if(newpos<s->pos){
-      mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n");
-      return 1;
-    }
-    while(s->pos<newpos){
-      if(stream_fill_buffer(s)<=0) break; // EOF
-    }
-#endif
-    break;
-  default:
-    // This should at the beginning as soon as all streams are converted
-    if(!s->seek)
-      return 0;
-    // Now seek
-    if(!s->seek(s,newpos)) {
-      mp_msg(MSGT_STREAM,MSGL_ERR, "Seek failed\n");
-      return 0;
-    }
-  }
-//   putchar('.');fflush(stdout);
-//} else {
-//   putchar('%');fflush(stdout);
-}
-
-while(stream_fill_buffer(s) > 0 && pos >= 0) {
-  if(pos<=s->buf_len){
-    s->buf_pos=pos; // byte position in sector
-    return 1;
-  }
-  pos -= s->buf_len;
-}
-  
-//  if(pos==s->buf_len) printf("XXX Seek to last byte of file -> EOF\n");
-  
-  mp_msg(MSGT_STREAM,MSGL_V,"stream_seek: WARNING! Can't seek to 0x%"PRIX64" !\n",(int64_t)(pos+newpos));
-  return 0;
-}
-
-
-void stream_reset(stream_t *s){
-  if(s->eof){
-    s->pos=0; //ftell(f);
-//    s->buf_pos=s->buf_len=0;
-    s->eof=0;
-  }
-  if(s->control) s->control(s,STREAM_CTRL_RESET,NULL);
-  //stream_seek(s,0);
-}
-
-int stream_control(stream_t *s, int cmd, void *arg){
-  if(!s->control) return STREAM_UNSUPORTED;
-  return s->control(s, cmd, arg);
-}
-
-stream_t* new_memory_stream(unsigned char* data,int len){
-  stream_t *s;
-
-  if(len < 0)
-    return NULL;
-  s=malloc(sizeof(stream_t)+len);
-  memset(s,0,sizeof(stream_t));
-  s->fd=-1;
-  s->type=STREAMTYPE_MEMORY;
-  s->buf_pos=0; s->buf_len=len;
-  s->start_pos=0; s->end_pos=len;
-  stream_reset(s);
-  s->pos=len;
-  memcpy(s->buffer,data,len);
-  return s;
-}
-
-stream_t* new_stream(int fd,int type){
-  stream_t *s=malloc(sizeof(stream_t));
-  if(s==NULL) return NULL;
-  memset(s,0,sizeof(stream_t));
-
-#ifdef HAVE_WINSOCK2
-  {
-    WSADATA wsdata;
-    int temp = WSAStartup(0x0202, &wsdata); // there might be a better place for this (-> later)
-    mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 init: %i\n", temp);
-  }
-#endif
-  
-  s->fd=fd;
-  s->type=type;
-  s->buf_pos=s->buf_len=0;
-  s->start_pos=s->end_pos=0;
-  s->priv=NULL;
-  s->url=NULL;
-  s->cache_pid=0;
-  stream_reset(s);
-  return s;
-}
-
-void free_stream(stream_t *s){
-//  printf("\n*** free_stream() called ***\n");
-#ifdef USE_STREAM_CACHE
-  if(s->cache_pid) {
-    cache_uninit(s);
-  }
-#endif
-  if(s->close) s->close(s);
-  if(s->fd>0){
-    /* on unix we define closesocket to close
-       on windows however we have to distinguish between
-       network socket and file */
-    if(s->url && strstr(s->url,"://"))
-      closesocket(s->fd);
-    else close(s->fd);
-  }
-#ifdef HAVE_WINSOCK2
-  mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 uninit\n");
-  WSACleanup(); // there might be a better place for this (-> later)
-#endif
-  // Disabled atm, i don't like that. s->priv can be anything after all
-  // streams should destroy their priv on close
-  //if(s->priv) free(s->priv);
-  if(s->url) free(s->url);
-  free(s);
-}
-
-stream_t* new_ds_stream(demux_stream_t *ds) {
-  stream_t* s = new_stream(-1,STREAMTYPE_DS);
-  s->priv = ds;
-  return s;
-}
--- a/libmpdemux/stream.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,301 +0,0 @@
-#ifndef __STREAM_H
-#define __STREAM_H
-
-#include "mp_msg.h"
-#include <string.h>
-#include <inttypes.h>
-#include <sys/types.h>
-
-#define STREAMTYPE_DUMMY -1    // for placeholders, when the actual reading is handled in the demuxer
-#define STREAMTYPE_FILE 0      // read from seekable file
-#define STREAMTYPE_VCD  1      // raw mode-2 CDROM reading, 2324 bytes/sector
-#define STREAMTYPE_STREAM 2    // same as FILE but no seeking (for net/stdin)
-#define STREAMTYPE_DVD  3      // libdvdread
-#define STREAMTYPE_MEMORY  4   // read data from memory area
-#define STREAMTYPE_PLAYLIST 6  // FIXME!!! same as STREAMTYPE_FILE now
-#define STREAMTYPE_DS   8      // read from a demuxer stream
-#define STREAMTYPE_DVDNAV 9    // we cannot safely "seek" in this...
-#define STREAMTYPE_CDDA 10     // raw audio CD reader
-#define STREAMTYPE_SMB 11      // smb:// url, using libsmbclient (samba)
-#define STREAMTYPE_VCDBINCUE 12      // vcd directly from bin/cue files
-#define STREAMTYPE_DVB 13
-#define STREAMTYPE_VSTREAM 14
-#define STREAMTYPE_SDP 15
-#define STREAMTYPE_PVR 16
-
-#define STREAM_BUFFER_SIZE 2048
-
-#define VCD_SECTOR_SIZE 2352
-#define VCD_SECTOR_OFFS 24
-#define VCD_SECTOR_DATA 2324
-
-/// atm it will always use mode == STREAM_READ
-/// streams that use the new api should check the mode at open
-#define STREAM_READ  0
-#define STREAM_WRITE 1
-/// Seek flags, if not mannualy set and s->seek isn't NULL
-/// STREAM_SEEK is automaticly set
-#define STREAM_SEEK_BW  2
-#define STREAM_SEEK_FW  4
-#define STREAM_SEEK  (STREAM_SEEK_BW|STREAM_SEEK_FW)
-
-//////////// Open return code
-/// This can't open the requested protocol (used by stream wich have a
-/// * protocol when they don't know the requested protocol)
-#define STREAM_UNSUPORTED -1
-#define STREAM_ERROR 0
-#define STREAM_OK    1
-
-#define MAX_STREAM_PROTOCOLS 10
-
-#define STREAM_CTRL_RESET 0
-#define STREAM_CTRL_GET_TIME_LENGTH 1
-
-#ifdef MPLAYER_NETWORK
-#include "network.h"
-#endif
-
-struct stream_st;
-typedef struct stream_info_st {
-  const char *info;
-  const char *name;
-  const char *author;
-  const char *comment;
-  /// mode isn't used atm (ie always READ) but it shouldn't be ignored
-  /// opts is at least in it's defaults settings and may have been
-  /// altered by url parsing if enabled and the options string parsing.
-  int (*open)(struct stream_st* st, int mode, void* opts, int* file_format);
-  char* protocols[MAX_STREAM_PROTOCOLS];
-  void* opts;
-  int opts_url; /* If this is 1 we will parse the url as an option string
-		 * too. Otherwise options are only parsed from the
-		 * options string given to open_stream_plugin */
-} stream_info_t;
-
-typedef struct stream_st {
-  // Read
-  int (*fill_buffer)(struct stream_st *s, char* buffer, int max_len);
-  // Write
-  int (*write_buffer)(struct stream_st *s, char* buffer, int len);
-  // Seek
-  int (*seek)(struct stream_st *s,off_t pos);
-  // Control
-  // Will be later used to let streams like dvd and cdda report
-  // their structure (ie tracks, chapters, etc)
-  int (*control)(struct stream_st *s,int cmd,void* arg);
-  // Close
-  void (*close)(struct stream_st *s);
-
-  int fd;   // file descriptor, see man open(2)
-  int type; // see STREAMTYPE_*
-  int flags;
-  int sector_size; // sector size (seek will be aligned on this size if non 0)
-  unsigned int buf_pos,buf_len;
-  off_t pos,start_pos,end_pos;
-  int eof;
-  unsigned int cache_pid;
-  void* cache_data;
-  void* priv; // used for DVD, TV, RTSP etc
-  char* url;  // strdup() of filename/url
-#ifdef MPLAYER_NETWORK
-  streaming_ctrl_t *streaming_ctrl;
-#endif
-  unsigned char buffer[STREAM_BUFFER_SIZE>VCD_SECTOR_SIZE?STREAM_BUFFER_SIZE:VCD_SECTOR_SIZE];
-} stream_t;
-
-#ifdef USE_STREAM_CACHE
-int stream_enable_cache(stream_t *stream,int size,int min,int prefill);
-int cache_stream_fill_buffer(stream_t *s);
-int cache_stream_seek_long(stream_t *s,off_t pos);
-#else
-// no cache, define wrappers:
-#define cache_stream_fill_buffer(x) stream_fill_buffer(x)
-#define cache_stream_seek_long(x,y) stream_seek_long(x,y)
-#define stream_enable_cache(x,y,z,w) 1
-#endif
-void fixup_network_stream_cache(stream_t *stream);
-
-inline static int stream_read_char(stream_t *s){
-  return (s->buf_pos<s->buf_len)?s->buffer[s->buf_pos++]:
-    (cache_stream_fill_buffer(s)?s->buffer[s->buf_pos++]:-256);
-//  if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++];
-//  stream_fill_buffer(s);
-//  if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++];
-//  return 0; // EOF
-}
-
-inline static unsigned int stream_read_word(stream_t *s){
-  int x,y;
-  x=stream_read_char(s);
-  y=stream_read_char(s);
-  return (x<<8)|y;
-}
-
-inline static unsigned int stream_read_dword(stream_t *s){
-  unsigned int y;
-  y=stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  return y;
-}
-
-#define stream_read_fourcc stream_read_dword_le
-
-inline static unsigned int stream_read_word_le(stream_t *s){
-  int x,y;
-  x=stream_read_char(s);
-  y=stream_read_char(s);
-  return (y<<8)|x;
-}
-
-inline static unsigned int stream_read_dword_le(stream_t *s){
-  unsigned int y;
-  y=stream_read_char(s);
-  y|=stream_read_char(s)<<8;
-  y|=stream_read_char(s)<<16;
-  y|=stream_read_char(s)<<24;
-  return y;
-}
-
-inline static uint64_t stream_read_qword(stream_t *s){
-  uint64_t y;
-  y = stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  return y;
-}
-
-inline static uint64_t stream_read_qword_le(stream_t *s){
-  uint64_t y;
-  y = stream_read_char(s);
-  y|=stream_read_char(s)<<8;
-  y|=stream_read_char(s)<<16;
-  y|=stream_read_char(s)<<24;
-  y|=(uint64_t)stream_read_char(s)<<32;
-  y|=(uint64_t)stream_read_char(s)<<40;
-  y|=(uint64_t)stream_read_char(s)<<48;
-  y|=(uint64_t)stream_read_char(s)<<56;
-  return y;
-}
-
-inline static unsigned int stream_read_int24(stream_t *s){
-  unsigned int y;
-  y = stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  y=(y<<8)|stream_read_char(s);
-  return y;
-}
-
-inline static int stream_read(stream_t *s,char* mem,int total){
-  int len=total;
-  while(len>0){
-    int x;
-    x=s->buf_len-s->buf_pos;
-    if(x==0){
-      if(!cache_stream_fill_buffer(s)) return total-len; // EOF
-      x=s->buf_len-s->buf_pos;
-    }
-    if(s->buf_pos>s->buf_len) mp_msg(MSGT_DEMUX, MSGL_WARN, "stream_read: WARNING! s->buf_pos>s->buf_len\n");
-    if(x>len) x=len;
-    memcpy(mem,&s->buffer[s->buf_pos],x);
-    s->buf_pos+=x; mem+=x; len-=x;
-  }
-  return total;
-}
-
-inline static unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max) {
-  int len;
-  unsigned char* end,*ptr = mem;;
-  do {
-    len = s->buf_len-s->buf_pos;
-    // try to fill the buffer
-    if(len <= 0 &&
-       (!cache_stream_fill_buffer(s) || 
-        (len = s->buf_len-s->buf_pos) <= 0)) break;
-    end = (unsigned char*) memchr((void*)(s->buffer+s->buf_pos),'\n',len);
-    if(end) len = end - (s->buffer+s->buf_pos) + 1;
-    if(len > 0 && max > 1) {
-      int l = len > max-1 ? max-1 : len;
-      memcpy(ptr,s->buffer+s->buf_pos,l);
-      max -= l;
-      ptr += l;
-    }
-    s->buf_pos += len;
-  } while(!end);
-  if(s->eof && ptr == mem) return NULL;
-  if(max > 0) ptr[0] = 0;
-  return mem;
-}
-
-
-inline static int stream_eof(stream_t *s){
-  return s->eof;
-}
-
-inline static off_t stream_tell(stream_t *s){
-  return s->pos+s->buf_pos-s->buf_len;
-}
-
-inline static int stream_seek(stream_t *s,off_t pos){
-
-  mp_dbg(MSGT_DEMUX, MSGL_DBG3, "seek to 0x%qX\n",(long long)pos);
-
-  if(pos<s->pos){
-    off_t x=pos-(s->pos-s->buf_len);
-    if(x>=0){
-      s->buf_pos=x;
-//      putchar('*');fflush(stdout);
-      return 1;
-    }
-  }
-  
-  return cache_stream_seek_long(s,pos);
-}
-
-inline static int stream_skip(stream_t *s,off_t len){
-  if( (len<0 && (s->flags & STREAM_SEEK_BW)) || (len>2*STREAM_BUFFER_SIZE && (s->flags & STREAM_SEEK_FW)) ) {
-    // negative or big skip!
-    return stream_seek(s,stream_tell(s)+len);
-  }
-  while(len>0){
-    int x=s->buf_len-s->buf_pos;
-    if(x==0){
-      if(!cache_stream_fill_buffer(s)) return 0; // EOF
-      x=s->buf_len-s->buf_pos;
-    }
-    if(x>len) x=len;
-    //memcpy(mem,&s->buf[s->buf_pos],x);
-    s->buf_pos+=x; len-=x;
-  }
-  return 1;
-}
-
-void stream_reset(stream_t *s);
-int stream_control(stream_t *s, int cmd, void *arg);
-stream_t* new_stream(int fd,int type);
-void free_stream(stream_t *s);
-stream_t* new_memory_stream(unsigned char* data,int len);
-stream_t* open_stream(char* filename,char** options,int* file_format);
-stream_t* open_stream_full(char* filename,int mode, char** options, int* file_format);
-
-extern int dvd_title;
-extern int dvd_chapter;
-extern int dvd_last_chapter;
-extern int dvd_angle;
-
-extern char * audio_stream;
-
-typedef struct {
- int id; // 0 - 31 mpeg; 128 - 159 ac3; 160 - 191 pcm
- int language; 
- int type;
- int channels;
-} stream_language_t;
-
-#endif // __STREAM_H
--- a/libmpdemux/stream_dvd.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,851 +0,0 @@
-
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#ifdef __FreeBSD__
-#include <sys/cdrio.h>
-#endif
-
-#define FIRST_AC3_AID 128
-#define FIRST_DTS_AID 136
-#define FIRST_MPG_AID 0
-#define FIRST_PCM_AID 160
-
-#include "stream.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-#include "stream_dvd.h"
-
-/// We keep these 2 for the gui atm, but they will be removed.
-extern int dvd_title;
-extern int dvd_chapter;
-extern int dvd_last_chapter;
-extern char* dvd_device;
-int dvd_angle=1;
-
-#ifdef USE_DVDREAD
-#define	LIBDVDREAD_VERSION(maj,min,micro)	((maj)*10000 + (min)*100 + (micro))
-/*
- * Try to autodetect the libdvd-0.9.0 library
- * (0.9.0 removed the <dvdread/dvd_udf.h> header, and moved the two defines
- * DVD_VIDEO_LB_LEN and MAX_UDF_FILE_NAME_LEN from it to
- * <dvdread/dvd_reader.h>)
- */
-#ifndef DVDREAD_VERSION
-#if defined(DVD_VIDEO_LB_LEN) && defined(MAX_UDF_FILE_NAME_LEN)
-#define	DVDREAD_VERSION	LIBDVDREAD_VERSION(0,9,0)
-#else
-#define	DVDREAD_VERSION	LIBDVDREAD_VERSION(0,8,0)
-#endif
-#endif
-
-char * dvd_audio_stream_types[8] = { "ac3","unknown","mpeg1","mpeg2ext","lpcm","unknown","dts" };
-char * dvd_audio_stream_channels[6] = { "mono", "stereo", "unknown", "unknown", "5.1/6.1", "5.1" };
-#endif /* #ifdef USE_DVDREAD */
-
-
-static struct stream_priv_s {
-  int title;
-} stream_priv_dflts = {
-  1
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  { "hostname", ST_OFF(title), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-static struct m_struct_st stream_opts = {
-  "dvd",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-int dvd_parse_chapter_range(m_option_t *conf, const char *range) {
-  const char *s;
-  char *t;
-  if (!range)
-    return M_OPT_MISSING_PARAM;
-  s = range;
-  dvd_chapter = 1;
-  dvd_last_chapter = 0;
-  if(*range && isdigit(*range)) {
-    dvd_chapter = strtol(range, &s, 10);
-    if(range == s) {
-      mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
-      return M_OPT_INVALID;
-    }
-  }
-  if(*s == 0)
-    return 0;
-  else if(*s != '-') {
-    mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
-    return M_OPT_INVALID;
-  }
-  ++s;
-  if(*s == 0)
-      return 0;
-  if(! isdigit(*s)) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
-    return M_OPT_INVALID;
-  }
-  dvd_last_chapter = strtol(s, &t, 10);
-  if (s == t || *t) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
-    return M_OPT_INVALID;
-  }
-  return 0;
-}
-
-#ifdef USE_DVDREAD
-int dvd_chapter_from_cell(dvd_priv_t* dvd,int title,int cell)
-{
-  pgc_t * cur_pgc;
-  ptt_info_t* ptt;
-  int chapter = cell;
-  int pgc_id,pgn;
-  if(title < 0 || cell < 0){
-    return 0;
-  }
-  /* for most DVD's chapter == cell */
-  /* but there are more complecated cases... */
-  if(chapter >= dvd->vmg_file->tt_srpt->title[title].nr_of_ptts) {
-    chapter = dvd->vmg_file->tt_srpt->title[title].nr_of_ptts-1;
-  }
-  title = dvd->tt_srpt->title[title].vts_ttn-1;
-  ptt = dvd->vts_file->vts_ptt_srpt->title[title].ptt;
-  while(chapter >= 0) {
-    pgc_id = ptt[chapter].pgcn;
-    pgn = ptt[chapter].pgn;
-    cur_pgc = dvd->vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-    if(cell >= cur_pgc->program_map[pgn-1]-1) {
-      return chapter;
-    }
-    --chapter;
-  }
-  /* didn't find a chapter ??? */
-  return chapter;
-}
-
-int dvd_aid_from_lang(stream_t *stream, unsigned char* lang) {
-  dvd_priv_t *d=stream->priv;
-  int code,i;
-  if(lang) {
-    while(strlen(lang)>=2) {
-      code=lang[1]|(lang[0]<<8);
-      for(i=0;i<d->nr_of_channels;i++) {
-        if(d->audio_streams[i].language==code) {
-          mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDaudioChannel,
-          d->audio_streams[i].id, lang[0],lang[1]);
-          return d->audio_streams[i].id;
-        }
-        //printf("%X != %X  (%c%c)\n",code,d->audio_streams[i].language,lang[0],lang[1]);
-      }
-      lang+=2; while (lang[0]==',' || lang[0]==' ') ++lang;
-    }
-    mp_msg(MSGT_OPEN,MSGL_WARN,MSGTR_DVDnoMatchingAudio);
-  }
-  return -1;
-}
-
-int dvd_number_of_subs(stream_t *stream) {
-  dvd_priv_t *d;
-  if (!stream) return -1;
-  d = stream->priv;
-  if (!d) return -1;
-  return d->nr_of_subtitles;
-}
-
-int dvd_lang_from_sid(stream_t *stream, int id) {
-  dvd_priv_t *d;
-  if (!stream) return 0;
-  d = stream->priv;
-  if (!d) return 0;
-  if (id >= d->nr_of_subtitles) return 0;
-  return d->subtitles[id].language;
-}
-
-int dvd_sid_from_lang(stream_t *stream, unsigned char* lang) {
-  dvd_priv_t *d=stream->priv;
-  int code,i;
-  while(lang && strlen(lang)>=2) {
-    code=lang[1]|(lang[0]<<8);
-    for(i=0;i<d->nr_of_subtitles;i++) {
-      if(d->subtitles[i].language==code) {
-        mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDsubtitleChannel, i, lang[0],lang[1]);
-        return i;
-      }
-    }
-    lang+=2; 
-    while (lang[0]==',' || lang[0]==' ') ++lang;
-  }
-  mp_msg(MSGT_OPEN,MSGL_WARN,MSGTR_DVDnoMatchingSubtitle);
-  return -1;
-}
-
-static int dvd_next_cell(dvd_priv_t *d) {
-  int next_cell=d->cur_cell;
-
-  mp_msg(MSGT_DVD,MSGL_DBG2, "dvd_next_cell: next1=0x%X  \n",next_cell);
-  if( d->cur_pgc->cell_playback[ next_cell ].block_type == BLOCK_TYPE_ANGLE_BLOCK ) {
-    while(next_cell<d->last_cell) {
-      if( d->cur_pgc->cell_playback[next_cell].block_mode == BLOCK_MODE_LAST_CELL )
-        break;
-      ++next_cell;
-    }
-  }
-  mp_msg(MSGT_DVD,MSGL_DBG2, "dvd_next_cell: next2=0x%X  \n",next_cell);
-
-  ++next_cell;
-  if(next_cell>=d->last_cell) 
-    return -1; // EOF
-  if(d->cur_pgc->cell_playback[next_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ) {
-    next_cell+=dvd_angle;
-    if(next_cell>=d->last_cell) 
-      return -1; // EOF
-  }
-  mp_msg(MSGT_DVD,MSGL_DBG2, "dvd_next_cell: next3=0x%X  \n",next_cell);
-  return next_cell;
-}
-
-int dvd_read_sector(dvd_priv_t *d,unsigned char* data) {
-  int len;
-
-  if(d->packs_left==0) {
-    /**
-     * 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.
-     *
-     * Otherwise, we set our next address past the end of this cell to
-     * force the code above to go to the next cell in the program.
-     */
-    if(d->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL) {
-       d->cur_pack= d->dsi_pack.dsi_gi.nv_pck_lbn + ( d->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
-       mp_msg(MSGT_DVD,MSGL_DBG2, "Navi  new pos=0x%X  \n",d->cur_pack);
-    } else {
-      // end of cell! find next cell!
-      mp_msg(MSGT_DVD,MSGL_V, "--- END OF CELL !!! ---\n");
-      d->cur_pack=d->cell_last_pack+1;
-    }
-  }
-
-read_next:
-  if(d->cur_pack>d->cell_last_pack) {
-    // end of cell!
-    int next=dvd_next_cell(d);
-    if(next>=0) {
-      d->cur_cell=next;
-      // if( d->cur_pgc->cell_playback[d->cur_cell].block_type 
-      // == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle;
-      d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
-      d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
-      mp_msg(MSGT_DVD,MSGL_V, "DVD next cell: %d  pack: 0x%X-0x%X  \n",d->cur_cell,d->cur_pack,d->cell_last_pack);
-    } else 
-        return -1; // EOF
-  }
-
-  len = DVDReadBlocks(d->title, d->cur_pack, 1, data);
-  if(!len) return -1; //error
-
-  if(data[38]==0 && data[39]==0 && data[40]==1 && data[41]==0xBF &&
-    data[1024]==0 && data[1025]==0 && data[1026]==1 && data[1027]==0xBF) {
-       // found a Navi packet!!!
-#if DVDREAD_VERSION >= LIBDVDREAD_VERSION(0,9,0)
-    navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ]));
-#else
-    navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t));
-#endif
-    if(d->cur_pack != d->dsi_pack.dsi_gi.nv_pck_lbn ) {
-      mp_msg(MSGT_DVD,MSGL_V, "Invalid NAVI packet! lba=0x%X  navi=0x%X  \n",
-        d->cur_pack,d->dsi_pack.dsi_gi.nv_pck_lbn);
-    } else {
-      // process!
-      d->packs_left = d->dsi_pack.dsi_gi.vobu_ea;
-      mp_msg(MSGT_DVD,MSGL_DBG2, "Found NAVI packet! lba=0x%X  len=%d  \n",d->cur_pack,d->packs_left);
-      //navPrint_DSI(&d->dsi_pack);
-      mp_msg(MSGT_DVD,MSGL_DBG3,"\r### CELL %d: Navi: %d/%d  IFO: %d/%d   \n",d->cur_cell,
-        d->dsi_pack.dsi_gi.vobu_c_idn,d->dsi_pack.dsi_gi.vobu_vob_idn,
-        d->cur_pgc->cell_position[d->cur_cell].cell_nr,
-        d->cur_pgc->cell_position[d->cur_cell].vob_id_nr);
-
-      if(d->angle_seek) {
-        int i,skip=0;
-#if defined(__GNUC__) && ( defined(__sparc__) || defined(hpux) )
-        // workaround for a bug in the sparc/hpux version of gcc 2.95.X ... 3.2,
-        // it generates incorrect code for unaligned access to a packed
-        // structure member, resulting in an mplayer crash with a SIGBUS
-        // signal.
-        //
-        // See also gcc problem report PR c/7847:
-        // http://gcc.gnu.org/cgi-bin/gnatsweb.pl?database=gcc&cmd=view+audit-trail&pr=7847
-        for(i=0;i<9;i++) {	// check if all values zero:
-          typeof(d->dsi_pack.sml_agli.data[i].address) tmp_addr;
-          memcpy(&tmp_addr,&d->dsi_pack.sml_agli.data[i].address,sizeof(tmp_addr));
-          if((skip=tmp_addr)!=0) break;
-        }
-#else
-        for(i=0;i<9;i++)	// check if all values zero:
-          if((skip=d->dsi_pack.sml_agli.data[i].address)!=0) break;
-#endif
-        if(skip) {
-          // sml_agli table has valid data (at least one non-zero):
-         d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+
-         d->dsi_pack.sml_agli.data[dvd_angle].address;
-         d->angle_seek=0;
-         mp_msg(MSGT_DVD,MSGL_V, "Angle-seek synced using sml_agli map!  new_lba=0x%X  \n",d->cur_pack);
-        } else {
-          // check if we're in the right cell, jump otherwise:
-          if( (d->dsi_pack.dsi_gi.vobu_c_idn==d->cur_pgc->cell_position[d->cur_cell].cell_nr) &&
-            (d->dsi_pack.dsi_gi.vobu_vob_idn==d->cur_pgc->cell_position[d->cur_cell].vob_id_nr) ){
-            d->angle_seek=0;
-            mp_msg(MSGT_DVD,MSGL_V, "Angle-seek synced by cell/vob IDN search!  \n");
-          } else {
-            // wrong angle, skip this vobu:
-            d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+
-            d->dsi_pack.dsi_gi.vobu_ea;
-            d->angle_seek=2; // DEBUG
-          }
-        }
-      }
-    }
-    ++d->cur_pack;
-    goto read_next;
-  }
-
-  ++d->cur_pack;
-  if(d->packs_left>=0) --d->packs_left;
-
-  if(d->angle_seek) {
-    if(d->angle_seek==2) mp_msg(MSGT_DVD,MSGL_V, "!!! warning! reading packet while angle_seek !!!\n");
-    goto read_next; // searching for Navi packet
-  }
-
-  return d->cur_pack-1;
-}
-
-void dvd_seek(dvd_priv_t *d,int pos) {
-  d->packs_left=-1;
-  d->cur_pack=pos;
-
-  // check if we stay in current cell (speedup things, and avoid angle skip)
-  if(d->cur_pack>d->cell_last_pack ||
-     d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector) {
-
-    // ok, cell change, find the right cell!
-    d->cur_cell=0;
-    if(d->cur_pgc->cell_playback[d->cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
-      d->cur_cell+=dvd_angle;
-
-    while(1) {
-      int next;
-      d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
-      if(d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector) {
-        d->cur_pack=d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
-        break;
-      }
-      if(d->cur_pack<=d->cell_last_pack) break; // ok, we find it! :)
-      next=dvd_next_cell(d);
-      if(next<0) {
-        //d->cur_pack=d->cell_last_pack+1;
-        break; // we're after the last cell
-      }
-      d->cur_cell=next;
-    }
-  }
-
-  mp_msg(MSGT_DVD,MSGL_V, "DVD Seek! lba=0x%X  cell=%d  packs: 0x%X-0x%X  \n",
-    d->cur_pack,d->cur_cell,d->cur_pgc->cell_playback[ d->cur_cell ].first_sector,d->cell_last_pack);
-
-  // if we're in interleaved multi-angle cell, find the right angle chain!
-  // (read Navi block, and use the seamless angle jump table)
-  d->angle_seek=1;
-}
-
-void dvd_close(dvd_priv_t *d) {
-  ifoClose(d->vts_file);
-  ifoClose(d->vmg_file);
-  DVDCloseFile(d->title);
-  DVDClose(d->dvd);
-  dvd_chapter = 1;
-  dvd_last_chapter = 0;
-}
-
-#endif /* #ifdef USE_DVDREAD */
-
-static int fill_buffer(stream_t *s, char *but, int len)
-{
-#ifdef USE_DVDREAD
-  if(s->type == STREAMTYPE_DVD) {
-    off_t pos=dvd_read_sector(s->priv,s->buffer);
-    if(pos>=0) {
-      len=2048; // full sector
-      s->pos=2048*pos-len;
-    } else len=-1; // error
-  }
-#endif
-  return len;
-}
-
-static int seek(stream_t *s, off_t newpos) {
-#ifdef USE_DVDREAD
-  s->pos=newpos; // real seek
-  dvd_seek(s->priv,s->pos/2048);
-#endif
-  return 1;
-}
-
-static void stream_dvd_close(stream_t *s) {
-#ifdef USE_DVDREAD
-  dvd_close(s->priv);
-#endif
-}
-
-/** 
-\brief Converts DVD time structure to milliseconds.
-\param *dev the DVD time structure to convert
-\return returns the time in milliseconds
-*/
-static int dvdtimetomsec(dvd_time_t *dt)
-{
-  static int framerates[4] = {0, 2500, 0, 2997};
-  int framerate = framerates[(dt->frame_u & 0xc0) >> 6];
-  int msec = (((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f)) * 3600000;
-  msec += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60000;
-  msec += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000;
-  if(framerate > 0)
-    msec += (((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f)) * 100000 / framerate;
-  return msec;
-}
-
-static int mp_get_titleset_length(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_no)
-{
-    int vts_ttn;  ///< title number within video title set
-    int pgc_no;   ///< program chain number
-    int msec;     ///< time length in milliseconds
-
-    msec=0;
-    if(!vts_file || !tt_srpt)
-        return 0;
-
-    if(vts_file->vtsi_mat && vts_file->vts_pgcit)
-    {
-            vts_ttn = tt_srpt->title[title_no].vts_ttn - 1;
-            pgc_no = vts_file->vts_ptt_srpt->title[vts_ttn].ptt[0].pgcn - 1;
-            msec = dvdtimetomsec(&vts_file->vts_pgcit->pgci_srp[pgc_no].pgc->playback_time);
-    }
-    return msec;
-}
-
-
-static int mp_describe_titleset(dvd_reader_t *dvd, tt_srpt_t *tt_srpt, int vts_no)
-{
-    ifo_handle_t *vts_file;
-    int title_no, msec=0;
-
-    vts_file = ifoOpen(dvd, vts_no);
-    if(!vts_file)
-        return 0;
-
-    if(!vts_file->vtsi_mat || !vts_file->vts_pgcit)
-    {
-        ifoClose(vts_file);
-        return 0;
-    }
-
-    for(title_no = 0; title_no < tt_srpt->nr_of_srpts; title_no++)
-    {
-        if (tt_srpt->title[title_no].title_set_nr != vts_no)
-            continue;
-        msec = mp_get_titleset_length(vts_file, tt_srpt, title_no);
-        mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_TITLE_%d_LENGTH=%d.%03d\n", title_no + 1, msec / 1000, msec % 1000);
-    }
-    ifoClose(vts_file);
-    return 1;
-}
-
-static int control(stream_t *stream,int cmd,void* arg) 
-{
-    switch(cmd) 
-    {
-        case STREAM_CTRL_GET_TIME_LENGTH:
-        {
-            dvd_priv_t *d = stream->priv;
-            *((unsigned int *)arg) = mp_get_titleset_length(d->vts_file, d->tt_srpt, d->cur_title-1);
-            return 1;
-        }
-    }
-    return STREAM_UNSUPORTED;
-}
-
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-  char *filename;
-
-  filename = strdup(stream->url);
-  mp_msg(MSGT_OPEN,MSGL_V,"URL: %s\n", filename);
-  dvd_title = p->title;
-#ifdef USE_DVDREAD
-  if(1){
-    //int ret,ret2;
-    dvd_priv_t *d;
-    int ttn,pgc_id,pgn;
-    dvd_reader_t *dvd;
-    dvd_file_t *title;
-    ifo_handle_t *vmg_file;
-    tt_srpt_t *tt_srpt;
-    ifo_handle_t *vts_file;
-    /**
-     * Open the disc.
-     */
-    if(!dvd_device) dvd_device=strdup(DEFAULT_DVD_DEVICE);
-#ifdef SYS_DARWIN
-    /* Dynamic DVD drive selection on Darwin */
-    if(!strcmp(dvd_device, "/dev/rdiskN")) {
-      int i;
-      char *temp_device = malloc(strlen(dvd_device)+1);
-
-      for (i = 1; i < 10; i++) {
-        sprintf(temp_device, "/dev/rdisk%d", i);
-        dvd = DVDOpen(temp_device);
-        if(!dvd) {
-          mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,temp_device);
-        } else {
-#if DVDREAD_VERSION <= LIBDVDREAD_VERSION(0,9,4)
-          int len;
-          if(!UDFFindFile(dvd,"/",&len)) {
-            mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,temp_device);
-            DVDClose(dvd);
-          } else
-#endif
-          {
-          free(temp_device);
-          break;
-          }
-        }
-      }
-
-      if(!dvd) {
-        m_struct_free(&stream_opts,opts);
-        return STREAM_UNSUPORTED;
-      }
-    } else
-#endif /* SYS_DARWIN */
-    {
-        dvd = DVDOpen(dvd_device);
-        if(!dvd) {
-          mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,dvd_device);
-          m_struct_free(&stream_opts,opts);
-          return STREAM_UNSUPORTED;
-        }
-    }
-
-    mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDwait);
-
-    /**
-     * Load the video manager to find out the information about the titles on
-     * this disc.
-     */
-    vmg_file = ifoOpen(dvd, 0);
-    if(!vmg_file) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVMG);
-      DVDClose( dvd );
-      m_struct_free(&stream_opts,opts);
-      return STREAM_UNSUPORTED;
-    }
-    tt_srpt = vmg_file->tt_srpt;
-    if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
-    {
-      int title_no; ///< title number
-      mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLES=%d\n", tt_srpt->nr_of_srpts);
-      for (title_no = 0; title_no < tt_srpt->nr_of_srpts; title_no++)
-      {
-        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_CHAPTERS=%d\n", title_no + 1, tt_srpt->title[title_no].nr_of_ptts);
-        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_ANGLES=%d\n", title_no + 1, tt_srpt->title[title_no].nr_of_angles);
-      }
-    }
-    if (mp_msg_test(MSGT_IDENTIFY, MSGL_V))
-    {
-      unsigned char discid [16]; ///< disk ID, a 128 bit MD5 sum
-      int vts_no;   ///< video title set number
-      for (vts_no = 1; vts_no <= vmg_file->vts_atrt->nr_of_vtss; vts_no++)
-        mp_describe_titleset(dvd, tt_srpt, vts_no);
-      if (DVDDiscID(dvd, discid) >= 0)
-      {
-        int i;
-        char buf[33];
-        for (i = 0; i < 16; i ++)
-          sprintf(buf+2*i, "%02X", discid[i]);
-        mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_DISC_ID=%s\n", buf);
-      }
-    }
-    /**
-     * Make sure our title number is valid.
-     */
-    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumTitles, tt_srpt->nr_of_srpts );
-    if(dvd_title < 1 || dvd_title > tt_srpt->nr_of_srpts) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidTitle, dvd_title);
-      ifoClose( vmg_file );
-      DVDClose( dvd );
-      m_struct_free(&stream_opts,opts);
-      return STREAM_UNSUPORTED;
-    }
-    --dvd_title; // remap 1.. -> 0..
-    /**
-     * Make sure the chapter number is valid for this title.
-     */
-    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumChapters, tt_srpt->title[dvd_title].nr_of_ptts);
-    if(dvd_chapter<1 || dvd_chapter>tt_srpt->title[dvd_title].nr_of_ptts) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidChapter, dvd_chapter);
-      ifoClose( vmg_file );
-      DVDClose( dvd );
-      m_struct_free(&stream_opts,opts);
-      return STREAM_UNSUPORTED;
-    }
-    if(dvd_last_chapter>0) {
-      if(dvd_last_chapter<dvd_chapter || dvd_last_chapter>tt_srpt->title[dvd_title].nr_of_ptts) {
-        mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidLastChapter, dvd_last_chapter);
-        ifoClose( vmg_file );
-        DVDClose( dvd );
-        m_struct_free(&stream_opts,opts);
-        return STREAM_UNSUPORTED;
-      }
-    }
-    --dvd_chapter; // remap 1.. -> 0..
-    /* XXX No need to remap dvd_last_chapter */
-    /**
-     * Make sure the angle number is valid for this title.
-     */
-    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumAngles, tt_srpt->title[dvd_title].nr_of_angles);
-    if(dvd_angle<1 || dvd_angle>tt_srpt->title[dvd_title].nr_of_angles) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidAngle, dvd_angle);
-      ifoClose( vmg_file );
-      DVDClose( dvd );
-      m_struct_free(&stream_opts,opts);
-      return STREAM_UNSUPORTED;
-    }
-    --dvd_angle; // remap 1.. -> 0..
-
-    ttn = tt_srpt->title[dvd_title].vts_ttn - 1;
-    /**
-     * Load the VTS information for the title set our title is in.
-     */
-    vts_file = ifoOpen( dvd, tt_srpt->title[dvd_title].title_set_nr );
-    if(!vts_file) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoIFO, tt_srpt->title[dvd_title].title_set_nr );
-      ifoClose( vmg_file );
-      DVDClose( dvd );
-      m_struct_free(&stream_opts,opts);
-      return STREAM_UNSUPORTED;
-    }
-    /**
-     * We've got enough info, time to open the title set data.
-     */
-    title = DVDOpenFile(dvd, tt_srpt->title[dvd_title].title_set_nr, DVD_READ_TITLE_VOBS);
-    if(!title) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVOBs, tt_srpt->title[dvd_title].title_set_nr);
-      ifoClose( vts_file );
-      ifoClose( vmg_file );
-      DVDClose( dvd );
-      m_struct_free(&stream_opts,opts);
-      return STREAM_UNSUPORTED;
-    }
-
-    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDopenOk);
-    // store data
-    d=malloc(sizeof(dvd_priv_t)); memset(d,0,sizeof(dvd_priv_t));
-    d->dvd=dvd;
-    d->title=title;
-    d->vmg_file=vmg_file;
-    d->tt_srpt=tt_srpt;
-    d->vts_file=vts_file;
-    d->cur_title = dvd_title+1;
-
-    /**
-     * Check number of audio channels and types
-     */
-    {
-      d->nr_of_channels=0;
-      if(vts_file->vts_pgcit) {
-        int i;
-        for(i=0;i<8;i++)
-#ifdef USE_MPDVDKIT
-          if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i].present) {
-#else
-          if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i] & 0x8000) {
-#endif
-            audio_attr_t * audio = &vts_file->vtsi_mat->vts_audio_attr[i];
-            int language = 0;
-            char tmp[] = "unknown";
-
-            if(audio->lang_type == 1) {
-              language=audio->lang_code;
-              tmp[0]=language>>8;
-              tmp[1]=language&0xff;
-              tmp[2]=0;
-            }
-
-            d->audio_streams[d->nr_of_channels].language=language;
-#ifdef USE_MPDVDKIT
-            d->audio_streams[d->nr_of_channels].id=vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i].s_audio;
-#else
-            d->audio_streams[d->nr_of_channels].id=vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i] >> 8 & 7;
-#endif
-            switch(audio->audio_format) {
-              case 0: // ac3
-                d->audio_streams[d->nr_of_channels].id+=FIRST_AC3_AID;
-                break;
-              case 6: // dts
-                d->audio_streams[d->nr_of_channels].id+=FIRST_DTS_AID;
-                break;
-              case 2: // mpeg layer 1/2/3
-              case 3: // mpeg2 ext
-                d->audio_streams[d->nr_of_channels].id+=FIRST_MPG_AID;
-                break;
-              case 4: // lpcm
-                d->audio_streams[d->nr_of_channels].id+=FIRST_PCM_AID;
-                break;
-           }
-
-           d->audio_streams[d->nr_of_channels].type=audio->audio_format;
-           // Pontscho: to my mind, tha channels:
-           //  1 - stereo
-           //  5 - 5.1
-           d->audio_streams[d->nr_of_channels].channels=audio->channels;
-           mp_msg(MSGT_OPEN,MSGL_V,"[open] audio stream: %d audio format: %s (%s) language: %s aid: %d\n",
-             d->nr_of_channels,
-             dvd_audio_stream_types[ audio->audio_format ],
-             dvd_audio_stream_channels[ audio->channels ],
-             tmp,
-             d->audio_streams[d->nr_of_channels].id
-           );
-           mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_ID=%d\n", d->audio_streams[d->nr_of_channels].id);
-           if(language && tmp[0])
-             mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", d->audio_streams[d->nr_of_channels].id, tmp);
-
-           d->nr_of_channels++;
-         }
-      }
-      mp_msg(MSGT_OPEN,MSGL_V,"[open] number of audio channels on disk: %d.\n",d->nr_of_channels );
-    }
-
-    /**
-     * Check number of subtitles and language
-     */
-    {
-      int i;
-
-      d->nr_of_subtitles=0;
-      for(i=0;i<32;i++)
-#ifdef USE_MPDVDKIT
-      if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i].present) {
-#else
-      if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i] & 0x80000000) {
-#endif
-        subp_attr_t * subtitle = &vts_file->vtsi_mat->vts_subp_attr[i];
-        video_attr_t *video = &vts_file->vtsi_mat->vts_video_attr;
-        int language = 0;
-        char tmp[] = "unknown";
-
-        if(subtitle->type == 1) {
-          language=subtitle->lang_code;
-          tmp[0]=language>>8;
-          tmp[1]=language&0xff;
-          tmp[2]=0;
-        }
-
-        d->subtitles[ d->nr_of_subtitles ].language=language;
-        d->subtitles[ d->nr_of_subtitles ].id=d->nr_of_subtitles;
-        if(video->display_aspect_ratio == 0) /* 4:3 */
-#ifdef USE_MPDVDKIT
-          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i].s_4p3;
-#else
-          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i] >> 24 & 31;
-#endif
-        else if(video->display_aspect_ratio == 3) /* 16:9 */
-#ifdef USE_MPDVDKIT
-          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i].s_lbox;
-#else
-          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i] >> 8 & 31;
-#endif
-
-        mp_msg(MSGT_OPEN,MSGL_V,"[open] subtitle ( sid ): %d language: %s\n", d->nr_of_subtitles, tmp);
-        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", d->subtitles[d->nr_of_subtitles].id);
-        if(language && tmp[0])
-          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", d->nr_of_subtitles, tmp);
-        d->nr_of_subtitles++;
-      }
-      mp_msg(MSGT_OPEN,MSGL_V,"[open] number of subtitles on disk: %d\n",d->nr_of_subtitles );
-    }
-
-    /**
-     * Determine which program chain we want to watch.  This is based on the
-     * chapter number.
-     */
-    pgc_id = vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_chapter].pgcn; // local
-    pgn  = vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_chapter].pgn;  // local
-    d->cur_pgc = vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-    d->cur_cell = d->cur_pgc->program_map[pgn-1] - 1; // start playback here
-    d->packs_left=-1;      // for Navi stuff
-    d->angle_seek=0;
-    /* XXX dvd_last_chapter is in the range 1..nr_of_ptts */
-    if(dvd_last_chapter > 0 && dvd_last_chapter < tt_srpt->title[dvd_title].nr_of_ptts) {
-      pgn=vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_last_chapter].pgn;
-      d->last_cell=d->cur_pgc->program_map[pgn-1] - 1;
-    } else
-      d->last_cell=d->cur_pgc->nr_of_cells;
-
-    if(d->cur_pgc->cell_playback[d->cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ) 
-      d->cur_cell+=dvd_angle;
-    d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
-    d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
-    mp_msg(MSGT_DVD,MSGL_V, "DVD start cell: %d  pack: 0x%X-0x%X  \n",d->cur_cell,d->cur_pack,d->cell_last_pack);
-
-    // ... (unimplemented)
-    //    return NULL;
-    stream->type = STREAMTYPE_DVD;
-    stream->sector_size = 2048;
-    stream->flags = STREAM_READ | STREAM_SEEK;
-    stream->fill_buffer = fill_buffer;
-    stream->seek = seek;
-    stream->control = control;
-    stream->close = stream_dvd_close;
-    stream->start_pos = (off_t)d->cur_pack*2048;
-    stream->end_pos = (off_t)(d->cur_pgc->cell_playback[d->last_cell-1].last_sector)*2048;
-    mp_msg(MSGT_DVD,MSGL_V,"DVD start=%d end=%d  \n",d->cur_pack,d->cur_pgc->cell_playback[d->last_cell-1].last_sector);
-    stream->priv = (void*)d;
-    return STREAM_OK;
-  }
-#endif /* #ifdef USE_DVDREAD */
-  mp_msg(MSGT_DVD,MSGL_ERR,MSGTR_NoDVDSupport);
-  m_struct_free(&stream_opts,opts);
-  return STREAM_UNSUPORTED;
-}
-
-
-stream_info_t stream_info_dvd = {
-  "DVD stream",
-  "null",
-  "",
-  "",
-  open_s,
-  { "dvd", NULL },
-  &stream_opts,
-  1 // Urls are an option string
-};
--- a/libmpdemux/stream_dvd.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-
-#ifdef USE_DVDREAD
-
-#ifdef USE_MPDVDKIT
-#include "libmpdvdkit2/dvd_reader.h"
-#include "libmpdvdkit2/ifo_types.h"
-#include "libmpdvdkit2/ifo_read.h"
-#include "libmpdvdkit2/nav_read.h"
-#else
-#include <dvdread/dvd_reader.h>
-#include <dvdread/ifo_types.h>
-#include <dvdread/ifo_read.h>
-#include <dvdread/nav_read.h>
-#endif
-
-typedef struct {
-  dvd_reader_t *dvd;
-  dvd_file_t *title;
-  ifo_handle_t *vmg_file;
-  tt_srpt_t *tt_srpt;
-  ifo_handle_t *vts_file;
-  vts_ptt_srpt_t *vts_ptt_srpt;
-  pgc_t *cur_pgc;
-//
-  int cur_title;
-  int cur_cell;
-  int last_cell;
-  int cur_pack;
-  int cell_last_pack;
-// Navi:
-  int packs_left;
-  dsi_t dsi_pack;
-  int angle_seek;
-// audio datas
-  int nr_of_channels;
-  stream_language_t audio_streams[32];
-// subtitles
-  int nr_of_subtitles;
-  stream_language_t subtitles[32];
-} dvd_priv_t;
-
-int dvd_number_of_subs(stream_t *stream);
-int dvd_lang_from_sid(stream_t *stream, int id);
-int dvd_aid_from_lang(stream_t *stream, unsigned char* lang);
-int dvd_sid_from_lang(stream_t *stream, unsigned char* lang);
-int dvd_chapter_from_cell(dvd_priv_t *dvd,int title,int cell);
-
-#endif
--- a/libmpdemux/stream_file.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "mp_msg.h"
-#include "stream.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-static struct stream_priv_s {
-  char* filename;
-  char *filename2;
-} stream_priv_dflts = {
-  NULL, NULL
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  {"string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  {"filename", ST_OFF(filename2), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-static struct m_struct_st stream_opts = {
-  "file",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};  
-
-static int fill_buffer(stream_t *s, char* buffer, int max_len){
-  int r = read(s->fd,buffer,max_len);
-  return (r <= 0) ? -1 : r;
-}
-
-static int write_buffer(stream_t *s, char* buffer, int len) {
-  int r = write(s->fd,buffer,len);
-  return (r <= 0) ? -1 : r;
-}
-
-static int seek(stream_t *s,off_t newpos) {
-  s->pos = newpos;
-  if(lseek(s->fd,s->pos,SEEK_SET)<0) {
-    s->eof=1;
-    return 0;
-  }
-  return 1;
-}
-
-static int seek_forward(stream_t *s,off_t newpos) {
-  if(newpos<s->pos){
-    mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n");
-    return 0;
-  }
-  while(s->pos<newpos){
-    int len=s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE);
-    if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; break; } // EOF
-    s->buf_pos=0;
-    s->buf_len=len;
-    s->pos+=len;
-  }
-  return 1;
-}
-
-static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
-  int f;
-  mode_t m = 0;
-  off_t len;
-  unsigned char *filename;
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-
-  if(mode == STREAM_READ)
-    m = O_RDONLY;
-  else if(mode == STREAM_WRITE)
-    m = O_WRONLY;
-  else {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[file] Unknown open mode %d\n",mode);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_UNSUPORTED;
-  }
-
-  if(p->filename)
-    filename = p->filename;
-  else if(p->filename2)
-    filename = p->filename2;
-  else
-    filename = NULL;
-  if(!filename) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[file] No filename\n");
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-
-#if defined(__CYGWIN__)|| defined(__MINGW32__)
-  m |= O_BINARY;
-#endif    
-
-  if(!strcmp(filename,"-")){
-    if(mode == STREAM_READ) {
-      // read from stdin
-      mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ReadSTDIN);
-      f=0; // 0=stdin
-#ifdef __MINGW32__
-	  setmode(fileno(stdin),O_BINARY);
-#endif
-    } else {
-      mp_msg(MSGT_OPEN,MSGL_INFO,"Writing to stdout\n");
-      f=1;
-#ifdef __MINGW32__
-	  setmode(fileno(stdout),O_BINARY);
-#endif
-    }
-  } else {
-    f=open(filename,m);
-    if(f<0) {
-      mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,filename);
-      m_struct_free(&stream_opts,opts);
-      return STREAM_ERROR;
-    }
-  }
-
-  len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET);
-#ifdef __MINGW32__
-  if(f==0 || len == -1) {
-#else
-  if(len == -1) {
-#endif
-    stream->seek = seek_forward;
-    stream->type = STREAMTYPE_STREAM; // Must be move to STREAMTYPE_FILE
-    stream->flags |= STREAM_SEEK_FW;
-  } else if(len >= 0) {
-    stream->seek = seek;
-    stream->end_pos = len;
-    stream->type = STREAMTYPE_FILE;
-  }
-
-  mp_msg(MSGT_OPEN,MSGL_V,"[file] File size is %"PRId64" bytes\n", (int64_t)len);
-
-  stream->fd = f;
-  stream->fill_buffer = fill_buffer;
-  stream->write_buffer = write_buffer;
-
-  m_struct_free(&stream_opts,opts);
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_file = {
-  "File",
-  "file",
-  "Albeu",
-  "based on the code from ??? (probably Arpi)",
-  open_f,
-  { "file", "", NULL },
-  &stream_opts,
-  1 // Urls are an option string
-};
--- a/libmpdemux/stream_ftp.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,469 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#ifndef HAVE_WINSOCK2
-#include <sys/socket.h>
-#define closesocket close
-#else
-#include <winsock2.h>
-#endif
-
-#include "mp_msg.h"
-#include "stream.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-static struct stream_priv_s {
-  char* user;
-  char* pass;
-  char* host;
-  int port;
-  char* filename;
-
-  char *cput,*cget;
-  int handle;
-  int cavail,cleft;
-  char *buf;
-} stream_priv_dflts = {
-  "anonymous","no@spam",
-  NULL,
-  21,
-  NULL,
-  NULL,
-  NULL,
-
-  0,
-  0,0,
-  NULL
-};
-
-#define BUFSIZE 2048
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  {"username", ST_OFF(user), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  {"password", ST_OFF(pass), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  {"hostname", ST_OFF(host), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  {"port", ST_OFF(port), CONF_TYPE_INT, 0, 0 ,65635, NULL},
-  {"filename", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-static struct m_struct_st stream_opts = {
-  "ftp",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-#define TELNET_IAC      255             /* interpret as command: */
-#define TELNET_IP       244             /* interrupt process--permanently */
-#define TELNET_SYNCH    242             /* for telfunc calls */
-
-// Check if there is something to read on a fd. This avoid hanging
-// forever if the network stop responding.
-static int fd_can_read(int fd,int timeout) {
-  fd_set fds;
-  struct timeval tv;
-
-  FD_ZERO(&fds);
-  FD_SET(fd,&fds);
-  tv.tv_sec = timeout;
-  tv.tv_usec = 0;
-  
-  return (select(fd+1, &fds, NULL, NULL, &tv) > 0);
-}
-
-/*
- * read a line of text
- *
- * return -1 on error or bytecount
- */
-static int readline(char *buf,int max,struct stream_priv_s *ctl)
-{
-    int x,retval = 0;
-    char *end,*bp=buf;
-    int eof = 0;
- 
-    do {
-      if (ctl->cavail > 0) {
-	x = (max >= ctl->cavail) ? ctl->cavail : max-1;
-	end = memccpy(bp,ctl->cget,'\n',x);
-	if (end != NULL)
-	  x = end - bp;
-	retval += x;
-	bp += x;
-	*bp = '\0';
-	max -= x;
-	ctl->cget += x;
-	ctl->cavail -= x;
-	if (end != NULL) {
-	  bp -= 2;
-	  if (strcmp(bp,"\r\n") == 0) {
-	    *bp++ = '\n';
-	    *bp++ = '\0';
-	    --retval;
-	  }
-	  break;
-	}
-      }
-      if (max == 1) {
-	*buf = '\0';
-	break;
-      }
-      if (ctl->cput == ctl->cget) {
-	ctl->cput = ctl->cget = ctl->buf;
-	ctl->cavail = 0;
-	ctl->cleft = BUFSIZE;
-      }
-      if(eof) {
-	if (retval == 0)
-	  retval = -1;
-	break;
-      }
-
-      if(!fd_can_read(ctl->handle, 15)) {
-        mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] read timed out\n");
-        retval = -1;
-        break;
-      }
-
-      if ((x = recv(ctl->handle,ctl->cput,ctl->cleft,0)) == -1) {
-	mp_msg(MSGT_STREAM,MSGL_ERR, "[ftp] read error: %s\n",strerror(errno));
-	retval = -1;
-	break;
-      }
-      if (x == 0)
-	eof = 1;
-      ctl->cleft -= x;
-      ctl->cavail += x;
-      ctl->cput += x;
-    } while (1);
-    
-    return retval;
-}
-
-/*
- * read a response from the server
- *
- * return 0 if first char doesn't match
- * return 1 if first char matches
- */
-static int readresp(struct stream_priv_s* ctl,char* rsp)
-{
-    static char response[256];
-    char match[5];
-    int r;
-
-    if (readline(response,256,ctl) == -1)
-      return 0;
- 
-    r = atoi(response)/100;
-    if(rsp) strcpy(rsp,response);
-
-    mp_msg(MSGT_STREAM,MSGL_V, "[ftp] < %s",response);
-
-    if (response[3] == '-') {
-      strncpy(match,response,3);
-      match[3] = ' ';
-      match[4] = '\0';
-      do {
-	if (readline(response,256,ctl) == -1) {
-	  mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Control socket read failed\n");
-	  return 0;
-	}
-	mp_msg(MSGT_OPEN,MSGL_V, "[ftp] < %s",response);
-      }	while (strncmp(response,match,4));
-    }
-    return r;
-}
-
-
-static int FtpSendCmd(const char *cmd, struct stream_priv_s *nControl,char* rsp)
-{
-  int l = strlen(cmd);
-  int hascrlf = cmd[l - 2] == '\r' && cmd[l - 1] == '\n';
-
-  if(hascrlf && l == 2) mp_msg(MSGT_STREAM,MSGL_V, "\n");
-  else mp_msg(MSGT_STREAM,MSGL_V, "[ftp] > %s",cmd);
-  while(l > 0) {
-    int s = send(nControl->handle,cmd,l,0);
-
-    if(s <= 0) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] write error: %s\n",strerror(errno));
-      return 0;
-    }
-    
-    cmd += s;
-    l -= s;
-  }
-    
-  if (hascrlf)  
-    return readresp(nControl,rsp);
-  else
-    return FtpSendCmd("\r\n", nControl, rsp);
-}
-
-static int FtpOpenPort(struct stream_priv_s* p) {
-  int resp,fd;
-  char rsp_txt[256];
-  char* par,str[128];
-  int num[6];
-
-  resp = FtpSendCmd("PASV",p,rsp_txt);
-  if(resp != 2) {
-    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'PASV' failed: %s\n",rsp_txt);
-    return 0;
-  }
-  
-  par = strchr(rsp_txt,'(');
-  
-  if(!par || !par[0] || !par[1]) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] invalid server response: %s ??\n",rsp_txt);
-    return 0;
-  }
-
-  sscanf(par+1,"%u,%u,%u,%u,%u,%u",&num[0],&num[1],&num[2],
-	 &num[3],&num[4],&num[5]);
-  snprintf(str,127,"%d.%d.%d.%d",num[0],num[1],num[2],num[3]);
-  fd = connect2Server(str,(num[4]<<8)+num[5],0);
-
-  if(fd < 0)
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] failed to create data connection\n");
-
-  return fd;
-}
-
-static int FtpOpenData(stream_t* s,size_t newpos) {
-  struct stream_priv_s* p = s->priv;
-  int resp;
-  char str[256],rsp_txt[256];
-
-  // Open a new connection
-  s->fd = FtpOpenPort(p);
-
-  if(s->fd < 0) return 0;
-
-  if(newpos > 0) {
-    snprintf(str,255,"REST %"PRId64, (int64_t)newpos);
-
-    resp = FtpSendCmd(str,p,rsp_txt);
-    if(resp != 3) {
-      mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
-      newpos = 0;
-    }
-  }
-
-  // Get the file
-  snprintf(str,255,"RETR %s",p->filename);
-  resp = FtpSendCmd(str,p,rsp_txt);
-
-  if(resp != 1) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
-    return 0;
-  }
-
-  s->pos = newpos;
-  return 1;
-}
-
-static int fill_buffer(stream_t *s, char* buffer, int max_len){
-  int r;
-
-  if(s->fd < 0 && !FtpOpenData(s,s->pos))
-    return -1;
-  
-  if(!fd_can_read(s->fd, 15)) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] read timed out\n");
-    return -1;
-  }
-
-  r = recv(s->fd,buffer,max_len,0);
-  return (r <= 0) ? -1 : r;
-}
-
-static int seek(stream_t *s,off_t newpos) {
-  struct stream_priv_s* p = s->priv;
-  int resp;
-  char rsp_txt[256];
-
-  if(s->pos > s->end_pos) {
-    s->eof=1;
-    return 0;
-  }
-
-  // Check to see if the server doesn't alredy terminated the transfert
-  if(fd_can_read(p->handle, 0)) {
-    if(readresp(p,rsp_txt) != 2)
-      mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] Warning the server didn't finished the transfert correctly: %s\n",rsp_txt);
-    closesocket(s->fd);
-    s->fd = -1;
-  }
-
-  // Close current download
-  if(s->fd >= 0) {
-    static const char pre_cmd[]={TELNET_IAC,TELNET_IP,TELNET_IAC,TELNET_SYNCH};
-    //int fl;
-    
-    // First close the fd
-    closesocket(s->fd);
-    s->fd = 0;
-    
-    // Send send the telnet sequence needed to make the server react
-    
-    // Dunno if this is really needed, lftp have it. I let
-    // it here in case it turn out to be needed on some other OS
-    //fl=fcntl(p->handle,F_GETFL);
-    //fcntl(p->handle,F_SETFL,fl&~O_NONBLOCK);
-
-    // send only first byte as OOB due to OOB braindamage in many unices
-    send(p->handle,pre_cmd,1,MSG_OOB);
-    send(p->handle,pre_cmd+1,sizeof(pre_cmd)-1,0);
-    
-    //fcntl(p->handle,F_SETFL,fl);
-
-    // Get the 426 Transfer aborted
-    // Or the 226 Transfer complete
-    resp = readresp(p,rsp_txt);
-    if(resp != 4 && resp != 2) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Server didn't abort correctly: %s\n",rsp_txt);
-      s->eof = 1;
-      return 0;
-    }
-    // Send the ABOR command
-    // Ignore the return code as sometimes it fail with "nothing to abort"
-    FtpSendCmd("ABOR",p,rsp_txt);
-  }
-  return FtpOpenData(s,newpos);
-}
-
-
-static void close_f(stream_t *s) {
-  struct stream_priv_s* p = s->priv;
-
-  if(!p) return;
-
-  if(s->fd > 0) {
-    closesocket(s->fd);
-    s->fd = 0;
-  }
-
-  FtpSendCmd("QUIT",p,NULL);
-
-  if(p->handle) closesocket(p->handle);
-  if(p->buf) free(p->buf);
-
-  m_struct_free(&stream_opts,p);
-}
-
-
-
-static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
-  int len = 0,resp;
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-  char str[256],rsp_txt[256];
-
-  if(mode != STREAM_READ) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Unknown open mode %d\n",mode);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_UNSUPORTED;
-  }
-
-  if(!p->filename || !p->host) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Bad url\n");
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-
-  // Open the control connection
-  p->handle = connect2Server(p->host,p->port,1);
-  
-  if(p->handle < 0) {
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-
-  // We got a connection, let's start serious things
-  stream->fd = -1;
-  stream->priv = p;
-  p->buf = malloc(BUFSIZE);
-
-  if (readresp(p, NULL) == 0) {
-    close_f(stream);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-
-  // Login
-  snprintf(str,255,"USER %s",p->user);
-  resp = FtpSendCmd(str,p,rsp_txt);
-
-  // password needed
-  if(resp == 3) {
-    snprintf(str,255,"PASS %s",p->pass);
-    resp = FtpSendCmd(str,p,rsp_txt);
-    if(resp != 2) {
-      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
-      close_f(stream);
-      return STREAM_ERROR;
-    }
-  } else if(resp != 2) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
-    close_f(stream);
-    return STREAM_ERROR;
-  }
-    
-  // Set the transfert type
-  resp = FtpSendCmd("TYPE I",p,rsp_txt);
-  if(resp != 2) {
-    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'TYPE I' failed: %s\n",rsp_txt);
-    close_f(stream);
-    return STREAM_ERROR;
-  }
-
-  // Get the filesize
-  snprintf(str,255,"SIZE %s",p->filename);
-  resp = FtpSendCmd(str,p,rsp_txt);
-  if(resp != 2) {
-    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
-  } else {
-    int dummy;
-    sscanf(rsp_txt,"%d %d",&dummy,&len);
-  }
-
-  if(len > 0) {
-    stream->seek = seek;
-    stream->end_pos = len;
-  }
-
-  // The data connection is really opened only at the first
-  // read/seek. This must be done when the cache is used
-  // because the connection would stay open in the main process,
-  // preventing correct abort with many servers.
-  stream->fd = -1;
-  stream->priv = p;
-  stream->fill_buffer = fill_buffer;
-  stream->close = close_f;
-
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_ftp = {
-  "File Transfer Protocol",
-  "ftp",
-  "Albeu",
-  "reuse a bit of code from ftplib written by Thomas Pfau",
-  open_f,
-  { "ftp", NULL },
-  &stream_opts,
-  1 // Urls are an option string
-};
--- a/libmpdemux/stream_livedotcom.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-
-#include "config.h"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "stream.h"
-#include "network.h"
-#include "demuxer.h"
-#include "help_mp.h"
-
-extern int network_bandwidth;
-
-static int _rtsp_streaming_seek(int fd, off_t pos, streaming_ctrl_t* streaming_ctrl) {
-  return -1; // For now, we don't handle RTSP stream seeking
-}
-
-static int rtsp_streaming_start(stream_t* stream) {
-  stream->streaming_ctrl->streaming_seek = _rtsp_streaming_seek;
-  return 0;
-}
-
-
-static int open_live_rtsp_sip(stream_t *stream,int mode, void* opts, int* file_format) {
-  URL_t *url;
-
-  stream->streaming_ctrl = streaming_ctrl_new();
-  if( stream->streaming_ctrl==NULL ) {
-    return STREAM_ERROR;
-  }
-  stream->streaming_ctrl->bandwidth = network_bandwidth;
-  url = url_new(stream->url);
-  stream->streaming_ctrl->url = check4proxies(url);
-  //url_free(url);
-
-  mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_LIVE555, URL: %s\n", stream->url);
-
-  if(rtsp_streaming_start(stream) < 0) {
-    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtsp_streaming_start failed\n");
-    goto fail;
-  }
-
-  *file_format = DEMUXER_TYPE_RTP;
-  stream->type = STREAMTYPE_STREAM;
-  return STREAM_OK;
-
-fail:
-  streaming_ctrl_free( stream->streaming_ctrl );
-  stream->streaming_ctrl = NULL;
-  return STREAM_ERROR;
-}
-
-static int open_live_sdp(stream_t *stream,int mode, void* opts, int* file_format) {
-  int f;
-  char *filename = stream->url;
-  off_t len;
-  char* sdpDescription;
-  ssize_t numBytesRead;
-
-  if(strncmp("sdp://",filename,6) == 0) {
-    filename += 6;
-#if defined(__CYGWIN__) || defined(__MINGW32__)
-    f = open(filename,O_RDONLY|O_BINARY);
-#else
-    f = open(filename,O_RDONLY);
-#endif
-    if(f < 0) {
-      mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,filename);
-      return STREAM_ERROR;
-    }
-
-    len=lseek(f,0,SEEK_END); 
-    lseek(f,0,SEEK_SET);
-    if(len == -1)
-      return STREAM_ERROR;
-    if(len > SIZE_MAX - 1)
-      return STREAM_ERROR;
-
-    sdpDescription = malloc(len+1);
-    if(sdpDescription == NULL) return STREAM_ERROR;
-    numBytesRead = read(f, sdpDescription, len);
-    if(numBytesRead != len) {
-      free(sdpDescription);
-      return STREAM_ERROR;
-    }
-    sdpDescription[len] = '\0'; // to be safe
-    stream->priv = sdpDescription;
-
-    stream->type = STREAMTYPE_SDP;
-    *file_format = DEMUXER_TYPE_RTP;
-    return STREAM_OK;
-  }
-  return STREAM_UNSUPORTED;
-}
-
-
-stream_info_t stream_info_rtsp_sip = {
-  "standard RTSP and SIP",
-  "RTSP and SIP",
-  "Ross Finlayson",
-  "Uses LIVE555 Streaming Media library.",
-  open_live_rtsp_sip,
-  {"rtsp", "sip", NULL },
-  NULL,
-  0 // Urls are an option string
-};
-
-stream_info_t stream_info_sdp = {
-  "SDP stream descriptor",
-  "SDP",
-  "Ross Finlayson",
-  "Uses LIVE555 Streaming Media library.",
-  open_live_sdp,
-  {"sdp", NULL },
-  NULL,
-  0 // Urls are an option string
-};
--- a/libmpdemux/stream_netstream.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,308 +0,0 @@
-/*
- *  stream_netstream.c
- *
- *	Copyright (C) Alban Bedel - 04/2003
- *
- *  This file is part of MPlayer, a free movie player.
- *	
- *  MPlayer is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
- *  any later version.
- *   
- *  MPlayer is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *   
- *  You should have received a copy of the GNU General Public License
- *  along with GNU Make; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- *
- */
-
-/*
- *  Net stream allow you to access MPlayer stream accross a tcp
- *  connection.
- *  Note that at least mf and tv use a dummy stream (they are
- *  implemented at the demuxer level) so you won't be able to
- *  access those :(( but dvd, vcd and so on should work perfectly
- *  (if you have the bandwidth ;)
- *   A simple server is in TOOLS/netstream.
- *
- */
-
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <inttypes.h>
-#include <errno.h>
-
-#ifndef HAVE_WINSOCK2
-#define closesocket close
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#else
-#include <winsock2.h>
-#endif
-
-#include "mp_msg.h"
-#include "stream.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-#include "bswap.h"
-
-#include "netstream.h"
-
-static struct stream_priv_s {
-  char* host;
-  int port;
-  char* url;
-} stream_priv_dflts = {
-  NULL,
-  10000,
-  NULL
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  {"hostname", ST_OFF(host), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  {"port", ST_OFF(port), CONF_TYPE_INT, M_OPT_MIN, 1 ,0, NULL},
-  {"filename", ST_OFF(url), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-static struct m_struct_st stream_opts = {
-  "netstream",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-//// When the cache is running we need a lock as
-//// fill_buffer is called from another proccess
-static int lock_fd(int fd) {
-#ifndef HAVE_WINSOCK2
-  struct flock lock;
-
-  memset(&lock,0,sizeof(struct flock));
-  lock.l_type = F_WRLCK;
-
-  mp_msg(MSGT_STREAM,MSGL_DBG2, "Lock (%d)\n",getpid());
-  do {    
-    if(fcntl(fd,F_SETLKW,&lock)) {
-      if(errno == EAGAIN) continue;
-      mp_msg(MSGT_STREAM,MSGL_ERR, "Failed to get the lock: %s\n",
-	     strerror(errno));
-      return 0;
-    }
-  } while(0);
-  mp_msg(MSGT_STREAM,MSGL_DBG2, "Locked (%d)\n",getpid());
-#else
-printf("FIXME? should lock here\n");
-#endif
-  return 1;
-}
-
-static int unlock_fd(int fd) {
-#ifndef HAVE_WINSOCK2
-  struct flock lock;
-
-  memset(&lock,0,sizeof(struct flock));
-  lock.l_type = F_UNLCK;
-
-  mp_msg(MSGT_STREAM,MSGL_DBG2, "Unlock (%d)\n",getpid());
-  if(fcntl(fd,F_SETLK,&lock)) {
-    mp_msg(MSGT_STREAM,MSGL_ERR, "Failed to release the lock: %s\n",
-	   strerror(errno));
-    return 0;
-  }
-#else
-printf("FIXME? should unlock here\n");
-#endif
-  return 1;
-}
-
-static mp_net_stream_packet_t* send_net_stream_cmd(stream_t *s,uint16_t cmd,char* data,int len) {
-  mp_net_stream_packet_t* pack;
-
-  // Cache is enabled : lock
-  if(s->cache_data && !lock_fd(s->fd))
-    return NULL;
-  // Send a command
-  if(!write_packet(s->fd,cmd,data,len)) {
-    if(s->cache_data) unlock_fd(s->fd);
-    return 0;
-  }
-  // Read the response
-  pack = read_packet(s->fd);
-  // Now we can unlock
-  if(s->cache_data) unlock_fd(s->fd);
-
-  if(!pack)
-    return NULL;
-
-  switch(pack->cmd) {
-  case NET_STREAM_OK:
-    return pack;
-  case NET_STREAM_ERROR:
-    if(pack->len > sizeof(mp_net_stream_packet_t))
-      mp_msg(MSGT_STREAM,MSGL_ERR, "Fill buffer failed: %s\n",pack->data);
-    else
-      mp_msg(MSGT_STREAM,MSGL_ERR, "Fill buffer failed\n");
-    free(pack);
-    return NULL;
-  }
-  
-  mp_msg(MSGT_STREAM,MSGL_ERR, "Unknown response to %d: %d\n",cmd,pack->cmd);
-  free(pack);
-  return NULL;
-}
-
-static int fill_buffer(stream_t *s, char* buffer, int max_len){
-  uint16_t len = le2me_16(max_len);
-  mp_net_stream_packet_t* pack;
-
-  pack = send_net_stream_cmd(s,NET_STREAM_FILL_BUFFER,(char*)&len,2);
-  if(!pack) {
-    return -1;
-  }
-  len = pack->len - sizeof(mp_net_stream_packet_t);
-  if(len > max_len) {
-    mp_msg(MSGT_STREAM,MSGL_ERR, "Got a too big a packet %d / %d\n",len,max_len);
-    free(pack);
-    return 0;
-  }
-  if(len > 0)
-    memcpy(buffer,pack->data,len);
-  free(pack);
-  return len;
-}
-
-
-static int seek(stream_t *s,off_t newpos) {
-  uint64_t pos = le2me_64((uint64_t)newpos);
-  mp_net_stream_packet_t* pack;
-  
-  pack = send_net_stream_cmd(s,NET_STREAM_SEEK,(char*)&pos,8);
-  if(!pack) {    
-    return 0;
-  }
-  s->pos = newpos;
-  free(pack);
-  return 1;
-}
-
-static int net_stream_reset(struct stream_st *s) {
-  mp_net_stream_packet_t* pack;
-  
-  pack = send_net_stream_cmd(s,NET_STREAM_RESET,NULL,0);  
-  if(!pack) {
-    return 0;
-  }
-  free(pack);
-  return 1;
-}
- 
-static int control(struct stream_st *s,int cmd,void* arg) {
-  switch(cmd) {
-  case STREAM_CTRL_RESET:
-    return net_stream_reset(s);
-  }
-  return STREAM_UNSUPORTED;
-}
-
-static void close_s(struct stream_st *s) {
-  mp_net_stream_packet_t* pack;
-  
-  pack = send_net_stream_cmd(s,NET_STREAM_CLOSE,NULL,0);
-  if(pack)
-    free(pack);
-}
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  int f;
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-  mp_net_stream_packet_t* pack;
-  mp_net_stream_opened_t* opened;
-
-  if(mode != STREAM_READ)
-    return STREAM_UNSUPORTED;
-
-  if(!p->host) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "We need an host name (ex: mpst://server.net/cdda://5)\n");
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-  if(!p->url || strlen(p->url) == 0) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "We need a remote url (ex: mpst://server.net/cdda://5)\n");
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-
-  f = connect2Server(p->host,p->port,1);
-  if(f < 0) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "Connection to %s:%d failed\n",p->host,p->port);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-  stream->fd = f;
-  /// Now send an open command
-  pack = send_net_stream_cmd(stream,NET_STREAM_OPEN,p->url,strlen(p->url) + 1);
-  if(!pack) {
-    goto error;
-  }
-  
-  if(pack->len != sizeof(mp_net_stream_packet_t) + 
-     sizeof(mp_net_stream_opened_t)) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "Invalid open response packet len (%d bytes)\n",pack->len);
-    free(pack);
-    goto error;
-  }
-  
-  opened = (mp_net_stream_opened_t*)pack->data;
-  net_stream_opened_2_me(opened);
-
-  *file_format = opened->file_format;
-  stream->flags = opened->flags;
-  stream->sector_size = opened->sector_size;
-  stream->start_pos = opened->start_pos;
-  stream->end_pos = opened->end_pos;
-
-  stream->fill_buffer = fill_buffer;
-  stream->control = control;
-  if(stream->flags & STREAM_SEEK)
-    stream->seek = seek;
-  stream->close = close_s;
-
-  free(pack);
-  m_struct_free(&stream_opts,opts);
-
-  return STREAM_OK;
-
-  error:
-  closesocket(f);
-  m_struct_free(&stream_opts,opts);
-  return STREAM_ERROR;
-}
-
-stream_info_t stream_info_netstream = {
-  "Net stream",
-  "netstream",
-  "Albeu",
-  "",
-  open_s,
-  { "mpst",NULL },
-  &stream_opts,
-  1 // Url is an option string
-};
--- a/libmpdemux/stream_null.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "stream.h"
-#include "demuxer.h"
-
-#ifdef USE_TV
-extern char* tv_param_channel;
-#endif
-
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  stream->type = STREAMTYPE_DUMMY;
-
-  if(strncmp("mf://",stream->url,5) == 0) {
-    *file_format =  DEMUXER_TYPE_MF;
-  } 
-#ifdef USE_TV
-  else if (strncmp("tv://",stream->url,5) == 0) {
-    *file_format =  DEMUXER_TYPE_TV;
-    if(stream->url[5] != '\0')
-      tv_param_channel = strdup(stream->url + 5);
-  }
-#endif
-  return 1;
-}
-
-
-stream_info_t stream_info_null = {
-  "Null stream",
-  "null",
-  "Albeu",
-  "",
-  open_s,
-  { 
-#ifdef USE_TV
-"tv", 
-#endif
-"mf", "null", NULL },
-  NULL,
-  0 // Urls are an option string
-};
--- a/libmpdemux/stream_pvr.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1026 +0,0 @@
-/*
- *  Copyright (C) 2006 Benjamin Zores
- *   Stream layer for WinTV PVR-150/250/350 (a.k.a IVTV) PVR cards.
- *   See http://ivtvdriver.org/index.php/Main_Page for more details on the
- *    cards supported by the ivtv driver.
- *
- *   This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software Foundation,
- *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/fcntl.h>
-#include <inttypes.h>
-#include <sys/poll.h>
-#include <linux/videodev2.h>
-#include <linux/ivtv.h>
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#include "stream.h"
-#include "tv.h"
-
-#define PVR_DEFAULT_DEVICE "/dev/video0"
-
-/* logging mechanisms */
-#define LOG_LEVEL_PVR  "[pvr]"
-#define LOG_LEVEL_V4L2 "[v4l2]"
-#define LOG_LEVEL_IVTV "[ivtv]"
-
-/* IVTV driver settings (see http://ivtvdriver.org/index.php/Ivtvctl ) */
-
-/* codec aspect ratio (1:1, 4:3, 16:9, 2.21:1) */
-#define PVR_ASPECT_RATIO_1_1                                   1
-#define PVR_ASPECT_RATIO_4_3                                   2
-#define PVR_ASPECT_RATIO_16_9                                  3
-#define PVR_ASPECT_RATIO_2_21_1                                4
-
-/* audio codec sample rate (32KHz, CD 44.1 KHz, AC97 48 KHz) */
-#define PVR_AUDIO_SAMPLE_RATE_44_1_KHZ                         0x0000
-#define PVR_AUDIO_SAMPLE_RATE_48_KHZ                           0x0001
-#define PVR_AUDIO_SAMPLE_RATE_32_KHZ                           0x0002
-
-/* audio codec layer (1 or 2) */
-#define PVR_AUDIO_LAYER_1                                      0x0004
-#define PVR_AUDIO_LAYER_2                                      0x0008
-
-/* audio codec bitrate */
-#define PVR_AUDIO_BITRATE_32                                   0x0010
-#define PVR_AUDIO_BITRATE_L1_64                                0x0020
-#define PVR_AUDIO_BITRATE_L1_96                                0x0030
-#define PVR_AUDIO_BITRATE_L1_128                               0x0040
-#define PVR_AUDIO_BITRATE_L1_160                               0x0050
-#define PVR_AUDIO_BITRATE_L1_192                               0x0060
-#define PVR_AUDIO_BITRATE_L1_224                               0x0070
-#define PVR_AUDIO_BITRATE_L1_256                               0x0080
-#define PVR_AUDIO_BITRATE_L1_288                               0x0090
-#define PVR_AUDIO_BITRATE_L1_320                               0x00A0
-#define PVR_AUDIO_BITRATE_L1_352                               0x00B0
-#define PVR_AUDIO_BITRATE_L1_384                               0x00C0
-#define PVR_AUDIO_BITRATE_L1_416                               0x00D0
-#define PVR_AUDIO_BITRATE_L1_448                               0x00E0
-#define PVR_AUDIO_BITRATE_L2_48                                0x0020
-#define PVR_AUDIO_BITRATE_L2_56                                0x0030
-#define PVR_AUDIO_BITRATE_L2_64                                0x0040
-#define PVR_AUDIO_BITRATE_L2_80                                0x0050
-#define PVR_AUDIO_BITRATE_L2_96                                0x0060
-#define PVR_AUDIO_BITRATE_L2_112                               0x0070
-#define PVR_AUDIO_BITRATE_L2_128                               0x0080
-#define PVR_AUDIO_BITRATE_L2_160                               0x0090
-#define PVR_AUDIO_BITRATE_L2_192                               0x00A0
-#define PVR_AUDIO_BITRATE_L2_224                               0x00B0
-#define PVR_AUDIO_BITRATE_L2_256                               0x00C0
-#define PVR_AUDIO_BITRATE_L2_320                               0x00D0
-#define PVR_AUDIO_BITRATE_L2_384                               0x00E0
-
-/* audio codec mode */
-#define PVR_AUDIO_MODE_ARG_STEREO                              "stereo"
-#define PVR_AUDIO_MODE_ARG_JOINT_STEREO                        "joint_stereo"
-#define PVR_AUDIO_MODE_ARG_DUAL                                "dual"
-#define PVR_AUDIO_MODE_ARG_MONO                                "mono"
-#define PVR_AUDIO_MODE_STEREO                                  0x0000
-#define PVR_AUDIO_MODE_JOINT_STEREO                            0x0100
-#define PVR_AUDIO_MODE_DUAL                                    0x0200
-#define PVR_AUDIO_MODE_MONO                                    0x0300
-
-/* video codec bitrate mode */
-#define PVR_VIDEO_BITRATE_MODE_ARG_VBR                         "vbr"
-#define PVR_VIDEO_BITRATE_MODE_ARG_CBR                         "cbr"
-#define PVR_VIDEO_BITRATE_MODE_VBR                             0
-#define PVR_VIDEO_BITRATE_MODE_CBR                             1
-
-/* video codec stream type */
-#define PVR_VIDEO_STREAM_TYPE_PS                               "ps"
-#define PVR_VIDEO_STREAM_TYPE_TS                               "ts"
-#define PVR_VIDEO_STREAM_TYPE_MPEG1                            "mpeg1"
-#define PVR_VIDEO_STREAM_TYPE_DVD                              "dvd"
-#define PVR_VIDEO_STREAM_TYPE_VCD                              "vcd"
-#define PVR_VIDEO_STREAM_TYPE_SVCD                             "svcd"
-#define PVR_VIDEO_STREAM_TYPE_DVD_S1                           "dvds1"
-#define PVR_VIDEO_STREAM_TYPE_DVD_S2                           "dvds2"
-
-/* command line arguments */
-int pvr_param_aspect_ratio = 0;
-int pvr_param_sample_rate = 0;
-int pvr_param_audio_layer = 0;
-int pvr_param_audio_bitrate = 0;
-char *pvr_param_audio_mode = NULL;
-int pvr_param_bitrate = 0;
-char *pvr_param_bitrate_mode = NULL;
-int pvr_param_bitrate_peak = 0;
-char *pvr_param_stream_type = NULL;
-
-struct pvr_t {
-  int dev_fd;
-  char *video_dev;
-
-  /* v4l2 params */
-  int mute;
-  int input;
-  int normid;
-  int brightness;
-  int contrast;
-  int hue;
-  int saturation;
-  int width;
-  int height;
-  char *freq;
-
-  /* ivtv params */
-  int aspect;
-  int samplerate;
-  int layer;
-  int audio_rate;
-  int audio_mode;
-  int bitrate;
-  int bitrate_mode;
-  int bitrate_peak;
-  int stream_type;
-};
-
-static struct pvr_t *
-pvr_init (void)
-{
-  struct pvr_t *pvr = NULL;
-
-  pvr = malloc (sizeof (struct pvr_t)); 
-  pvr->dev_fd = -1;
-  pvr->video_dev = strdup (PVR_DEFAULT_DEVICE);
-
-  /* v4l2 params */
-  pvr->mute = 0;
-  pvr->input = 0;
-  pvr->normid = -1;
-  pvr->brightness = 0;
-  pvr->contrast = 0;
-  pvr->hue = 0;
-  pvr->saturation = 0;
-  pvr->width = -1;
-  pvr->height = -1;
-  pvr->freq = NULL;
-
-  /* ivtv params */
-  pvr->aspect = -1;
-  pvr->samplerate = -1;
-  pvr->layer = -1;
-  pvr->audio_rate = -1;
-  pvr->audio_mode = -1;
-  pvr->bitrate = -1;
-  pvr->bitrate_mode = -1;
-  pvr->bitrate_peak = -1;
-  pvr->stream_type = -1;
-  
-  return pvr;
-}
-
-static void
-pvr_uninit (struct pvr_t *pvr)
-{
-  if (!pvr)
-    return;
-
-  /* close device */
-  if (pvr->dev_fd)
-    close (pvr->dev_fd);
-  
-  if (pvr->video_dev)
-    free (pvr->video_dev);
-  if (pvr->freq)
-    free (pvr->freq);
-  free (pvr);
-}
-
-/* IVTV layer */
-
-static void
-parse_ivtv_options (struct pvr_t *pvr)
-{
-  if (!pvr)
-    return;
-
-  /* -pvr aspect=digit */
-  if (pvr_param_aspect_ratio >= 1 && pvr_param_aspect_ratio <= 4)
-    pvr->aspect = pvr_param_aspect_ratio;
-
-  /* -pvr arate=x */
-  if (pvr_param_sample_rate != 0)
-  {
-    switch (pvr_param_sample_rate)
-    {
-    case 32000:
-      pvr->samplerate = PVR_AUDIO_SAMPLE_RATE_32_KHZ;
-      break;
-    case 44100:
-      pvr->samplerate = PVR_AUDIO_SAMPLE_RATE_44_1_KHZ;
-      break;
-    case 48000:
-      pvr->samplerate = PVR_AUDIO_SAMPLE_RATE_48_KHZ;
-      break;
-    default:
-      break;
-    }
-  }
-
-  /* -pvr alayer=x */
-  if (pvr_param_audio_layer == 1)
-    pvr->layer = PVR_AUDIO_LAYER_1;
-  else if (pvr_param_audio_layer == 2)
-    pvr->layer = PVR_AUDIO_LAYER_2;
-
-  /* -pvr abitrate=x */
-  if (pvr_param_audio_bitrate != 0)
-  {
-    /* set according to layer or use layer 1 by default if not specified */
-    switch (pvr_param_audio_bitrate)
-    {
-    case 32:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_32;
-      break;
-    case 48:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_48;
-      break;
-    case 56:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_56;
-      break;
-    case 64:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_64 : PVR_AUDIO_BITRATE_L1_64;
-      break;
-    case 80:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_80;
-      break;
-    case 96:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_96 : PVR_AUDIO_BITRATE_L1_96;
-      break;
-    case 112:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_112;
-      break;
-    case 128:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_128 : PVR_AUDIO_BITRATE_L1_128;
-      break;
-    case 160:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_160 : PVR_AUDIO_BITRATE_L1_160;
-      break;
-    case 192:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_192 : PVR_AUDIO_BITRATE_L1_192;
-      break;
-    case 224:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_224 : PVR_AUDIO_BITRATE_L1_224;
-      break;
-    case 256:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_256 : PVR_AUDIO_BITRATE_L1_256;
-      break;
-    case 288:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_288;
-      break;
-    case 320:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_320 : PVR_AUDIO_BITRATE_L1_320;
-      break;
-    case 352:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_352;
-      break;
-    case 384:
-      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
-        PVR_AUDIO_BITRATE_L2_384 : PVR_AUDIO_BITRATE_L1_384;
-      break;
-    case 416:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_416;
-      break;
-    case 448:
-      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_448;
-      break;
-    default:
-      break;
-    }
-  }
-  
-  /* -pvr amode=x */
-  if (pvr_param_audio_mode)
-  {
-    if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_STEREO))
-      pvr->audio_mode = PVR_AUDIO_MODE_STEREO;
-    else if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_JOINT_STEREO))
-      pvr->audio_mode = PVR_AUDIO_MODE_JOINT_STEREO;
-    else if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_DUAL))
-      pvr->audio_mode = PVR_AUDIO_MODE_DUAL;
-    else if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_MONO))
-      pvr->audio_mode = PVR_AUDIO_MODE_MONO;
-    else /* for anything else, set to stereo */
-      pvr->audio_mode = PVR_AUDIO_MODE_STEREO;
-  }
-
-  /* -pvr vbitrate=x */
-  if (pvr_param_bitrate)
-    pvr->bitrate = pvr_param_bitrate;
-
-  /* -pvr vmode=x */
-  if (pvr_param_bitrate_mode)
-  {
-    if (!strcmp (pvr_param_bitrate_mode, PVR_VIDEO_BITRATE_MODE_ARG_VBR))
-      pvr->bitrate_mode = PVR_VIDEO_BITRATE_MODE_VBR;
-    else if (!strcmp (pvr_param_bitrate_mode, PVR_VIDEO_BITRATE_MODE_ARG_CBR))
-      pvr->bitrate_mode = PVR_VIDEO_BITRATE_MODE_CBR;
-    else /* for anything else, set to VBR */
-      pvr->bitrate_mode = PVR_VIDEO_BITRATE_MODE_VBR;
-  }
-
-  /* -pvr vpeak=x */
-  if (pvr_param_bitrate_peak)
-    pvr->bitrate_peak = pvr_param_bitrate_peak;
-
-  /* -pvr fmt=x */
-  if (pvr_param_stream_type)
-  {
-    if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_PS))
-      pvr->stream_type = IVTV_STREAM_PS;
-    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_TS))
-      pvr->stream_type = IVTV_STREAM_TS;
-    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_MPEG1))
-      pvr->stream_type = IVTV_STREAM_MPEG1;
-    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_DVD))
-      pvr->stream_type = IVTV_STREAM_DVD;
-    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_VCD))
-      pvr->stream_type = IVTV_STREAM_VCD;
-    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_SVCD))
-      pvr->stream_type = IVTV_STREAM_SVCD;
-    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_DVD_S1))
-      pvr->stream_type = IVTV_STREAM_DVD_S1;
-    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_DVD_S2))
-      pvr->stream_type = IVTV_STREAM_DVD_S2;
-    else /* for anything else, set to MPEG PS */
-      pvr->stream_type = IVTV_STREAM_PS;
-  }
-}
-
-static int
-set_ivtv_settings (struct pvr_t *pvr)
-{
-  struct ivtv_ioctl_codec codec;
-
-  if (!pvr)
-    return -1;
-  
-  if (pvr->dev_fd < 0)
-    return -1;
-
-  /* get current settings */
-  if (ioctl (pvr->dev_fd, IVTV_IOC_G_CODEC, &codec) < 0)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't get codec (%s).\n", LOG_LEVEL_IVTV, strerror (errno));
-    return -1;
-  }
-  
-  /* set default encoding settings
-   * may be overlapped by user parameters
-   * Use VBR MPEG_PS encoding at 6 Mbps (peak at 9.6 Mbps)
-   * with 48 KHz L2 384 kbps audio.
-   */
-  codec.aspect = PVR_ASPECT_RATIO_4_3;
-  codec.bitrate_mode = PVR_VIDEO_BITRATE_MODE_VBR;
-  codec.bitrate = 6000000;
-  codec.bitrate_peak = 9600000;
-  codec.stream_type = IVTV_STREAM_PS;
-  codec.audio_bitmask = PVR_AUDIO_LAYER_2
-    | PVR_AUDIO_BITRATE_L2_384 | PVR_AUDIO_SAMPLE_RATE_48_KHZ;
-
-  /* set aspect ratio */
-  if (pvr->aspect != -1)
-    codec.aspect = pvr->aspect;
-
-  /* if user value is given, we need to reset audio bitmask */
-  if ((pvr->samplerate != -1) || (pvr->layer != -1)
-      || (pvr->audio_rate != -1) || (pvr->audio_mode != -1))
-    codec.audio_bitmask = 0;
-  
-  /* set audio samplerate */
-  if (pvr->samplerate != -1)
-    codec.audio_bitmask |= pvr->samplerate;
-
-  /* set audio layer */
-  if (pvr->layer != -1)
-    codec.audio_bitmask |= pvr->layer;
-
-  /* set audio bitrate */
-  if (pvr->audio_rate != -1)
-    codec.audio_bitmask |= pvr->audio_rate;
-
-  /* set audio mode */
-  if (pvr->audio_mode != -1)
-    codec.audio_bitmask |= pvr->audio_mode;
-
-  /* set video bitrate */
-  if (pvr->bitrate != -1)
-    codec.bitrate = pvr->bitrate;
-
-  /* set video bitrate mode */
-  if (pvr->bitrate_mode != -1)
-    codec.bitrate_mode = pvr->bitrate_mode;
-
-  /* set video bitrate peak */
-  if (pvr->bitrate != -1)
-    codec.bitrate_peak = pvr->bitrate_peak;
-
-  /* set video stream type */
-  if (pvr->stream_type != -1)
-    codec.stream_type = pvr->stream_type;
-
-  /* set new encoding settings */
-  if (ioctl (pvr->dev_fd, IVTV_IOC_S_CODEC, &codec) < 0)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't set codec (%s).\n", LOG_LEVEL_IVTV, strerror (errno));
-    return -1;
-  }
-
-  return 0;
-}
-
-/* V4L2 layer */
-
-static void
-parse_v4l2_tv_options (struct pvr_t *pvr)
-{
-  if (!pvr)
-    return;
-  
-  if (tv_param_device)
-  {
-    if (pvr->video_dev)
-      free (pvr->video_dev);
-    pvr->video_dev = strdup (tv_param_device);
-  }
-  
-  if (tv_param_noaudio)
-    pvr->mute = tv_param_noaudio;
-
-  if (tv_param_input)
-    pvr->input = tv_param_input;
-  
-  if (tv_param_normid)
-    pvr->normid = tv_param_normid;
-  
-  if (tv_param_brightness)
-    pvr->brightness = tv_param_brightness;
-  
-  if (tv_param_contrast)
-    pvr->contrast = tv_param_contrast;
-  
-  if (tv_param_hue)
-    pvr->hue = tv_param_hue;
-  
-  if (tv_param_saturation)
-    pvr->saturation = tv_param_saturation;
-
-  if (tv_param_width)
-    pvr->width = tv_param_width;
-
-  if (tv_param_height)
-    pvr->height = tv_param_height;
-
-  if (tv_param_freq)
-    pvr->freq = strdup (tv_param_freq);
-}
-
-static int
-set_v4l2_settings (struct pvr_t *pvr)
-{
-  if (!pvr)
-    return -1;
-  
-  if (pvr->dev_fd < 0)
-    return -1;
-
-  /* -tv noaudio */
-  if (pvr->mute)
-  {
-    struct v4l2_control ctrl;
-    ctrl.id = V4L2_CID_AUDIO_MUTE;
-    ctrl.value = 1;
-    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't mute (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
-      return -1;
-    }
-  }
-
-  /* -tv input=x */
-  if (pvr->input != 0)
-  {
-    if (ioctl (pvr->dev_fd, VIDIOC_S_INPUT, &pvr->input) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set input (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
-      return -1;
-    }
-  }
-  
-  /* -tv normid=x */
-  if (pvr->normid != -1)
-  {
-    struct v4l2_standard std;
-    std.index = pvr->normid;
-
-    if (ioctl (pvr->dev_fd, VIDIOC_ENUMSTD, &std) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set norm (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
-      return -1;
-    }
-
-    mp_msg (MSGT_OPEN, MSGL_V,
-            "%s set norm to %s\n", LOG_LEVEL_V4L2, std.name);
-
-    if (ioctl (pvr->dev_fd, VIDIOC_S_STD, &std.id) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set norm (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
-      return -1;
-    }
-  }
-  
-  /* -tv brightness=x */
-  if (pvr->brightness != 0)
-  {
-    struct v4l2_control ctrl;
-    ctrl.id = V4L2_CID_BRIGHTNESS;
-    ctrl.value = pvr->brightness;
-
-    if (ctrl.value < 0)
-      ctrl.value = 0;
-    if (ctrl.value > 255)
-      ctrl.value = 255;
-    
-    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set brightness to %d (%s).\n",
-              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
-      return -1;
-    }
-  }
-
-  /* -tv contrast=x */
-  if (pvr->contrast != 0)
-  {
-    struct v4l2_control ctrl;
-    ctrl.id = V4L2_CID_CONTRAST;
-    ctrl.value = pvr->contrast;
-
-    if (ctrl.value < 0)
-      ctrl.value = 0;
-    if (ctrl.value > 127)
-      ctrl.value = 127;
-    
-    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set contrast to %d (%s).\n",
-              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
-      return -1;
-    }
-  }
-
-  /* -tv hue=x */
-  if (pvr->hue != 0)
-  {
-    struct v4l2_control ctrl;
-    ctrl.id = V4L2_CID_HUE;
-    ctrl.value = pvr->hue;
-
-    if (ctrl.value < -128)
-      ctrl.value = -128;
-    if (ctrl.value > 127)
-      ctrl.value = 127;
-    
-    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set hue to %d (%s).\n",
-              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
-      return -1;
-    }
-  }
-  
-  /* -tv saturation=x */
-  if (pvr->saturation != 0)
-  {
-    struct v4l2_control ctrl;
-    ctrl.id = V4L2_CID_SATURATION;
-    ctrl.value = pvr->saturation;
-
-    if (ctrl.value < 0)
-      ctrl.value = 0;
-    if (ctrl.value > 127)
-      ctrl.value = 127;
-    
-    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set saturation to %d (%s).\n",
-              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
-      return -1;
-    }
-  }
-  
-  /* -tv width=x:height=y */
-  if (pvr->width && pvr->height)
-  {
-    struct v4l2_format vfmt;
-    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    vfmt.fmt.pix.width = pvr->width;
-    vfmt.fmt.pix.height = pvr->height;
-
-    if (ioctl (pvr->dev_fd, VIDIOC_S_FMT, &vfmt) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't set resolution to %dx%d (%s).\n",
-              LOG_LEVEL_V4L2, pvr->width, pvr->height, strerror (errno));
-      return -1;
-    }
-  }
-
-  /* -tv freq=x */
-  if (pvr->freq)
-  {
-    struct v4l2_frequency vf;
-    vf.tuner = 0;
-    vf.type = 0;
-    vf.frequency = strtol (pvr->freq, 0L, 0);
-    mp_msg (MSGT_OPEN, MSGL_INFO,
-            "%s setting frequency to %d\n", LOG_LEVEL_V4L2, vf.frequency);
-    
-    if (ioctl (pvr->dev_fd, VIDIOC_S_FREQUENCY, &vf) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR, "%s can't set frequency (%s).\n",
-              LOG_LEVEL_V4L2, strerror (errno));
-      return -1;
-    }
-  }
-
-  return 0;
-}
-
-static int
-v4l2_list_capabilities (struct pvr_t *pvr)
-{
-  struct v4l2_audio vaudio;
-  struct v4l2_standard vs;
-  struct v4l2_input vin;
-  int err = 0;
-  
-  if (!pvr)
-    return -1;
-
-  if (pvr->dev_fd < 0)
-    return -1;
-  
-  /* list available video inputs */
-  vin.index = 0;
-  err = 1;
-  mp_msg (MSGT_OPEN, MSGL_INFO,
-          "%s Available video inputs: ", LOG_LEVEL_V4L2);
-  while (ioctl (pvr->dev_fd, VIDIOC_ENUMINPUT, &vin) >= 0)
-  {
-    err = 0;
-    mp_msg (MSGT_OPEN, MSGL_INFO, "'#%d, %s' ", vin.index, vin.name);
-    vin.index++;
-  }
-  if (err)
-  {
-    mp_msg (MSGT_OPEN, MSGL_INFO, "none\n");
-    return -1;
-  }
-  else
-    mp_msg (MSGT_OPEN, MSGL_INFO, "\n");
-
-  /* list available audio inputs */
-  vaudio.index = 0;
-  err = 1;
-  mp_msg (MSGT_OPEN, MSGL_INFO,
-          "%s Available audio inputs: ", LOG_LEVEL_V4L2);
-  while (ioctl (pvr->dev_fd, VIDIOC_ENUMAUDIO, &vaudio) >= 0)
-  {
-    err = 0;
-    mp_msg (MSGT_OPEN, MSGL_INFO, "'#%d, %s' ", vaudio.index, vaudio.name);
-    vaudio.index++;
-  }
-  if (err)
-  {
-    mp_msg (MSGT_OPEN, MSGL_INFO, "none\n");
-    return -1;
-  }
-  else
-    mp_msg (MSGT_OPEN, MSGL_INFO, "\n");
-
-  /* list available norms */
-  vs.index = 0;
-  mp_msg (MSGT_OPEN, MSGL_INFO, "%s Available norms: ", LOG_LEVEL_V4L2);
-  while (ioctl (pvr->dev_fd, VIDIOC_ENUMSTD, &vs) >= 0)
-  {
-    err = 0;
-    mp_msg (MSGT_OPEN, MSGL_INFO, "'#%d, %s' ", vs.index, vs.name);
-    vs.index++;
-  }
-  if (err)
-  {
-    mp_msg (MSGT_OPEN, MSGL_INFO, "none\n");
-    return -1;
-  }
-  else
-    mp_msg (MSGT_OPEN, MSGL_INFO, "\n");
-
-  return 0;
-}
-
-static int
-v4l2_display_settings (struct pvr_t *pvr)
-{
-  struct v4l2_audio vaudio;
-  struct v4l2_standard vs;
-  struct v4l2_input vin;
-  v4l2_std_id std;
-  int input;
-  
-  if (!pvr)
-    return -1;
-
-  if (pvr->dev_fd < 0)
-    return -1;
-
-  /* get current video input */
-  if (ioctl (pvr->dev_fd, VIDIOC_G_INPUT, &input) == 0)
-  {
-    vin.index = input;
-    if (ioctl (pvr->dev_fd, VIDIOC_ENUMINPUT, &vin) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
-      return -1;
-    }
-    else
-      mp_msg (MSGT_OPEN, MSGL_INFO,
-              "%s Video input: %s\n", LOG_LEVEL_V4L2, vin.name);
-  }
-  else
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
-    return -1;
-  }
-
-  /* get current audio input */
-  if (ioctl (pvr->dev_fd, VIDIOC_G_AUDIO, &vaudio) == 0)
-  {
-    vaudio.index = input;
-    if (ioctl (pvr->dev_fd, VIDIOC_ENUMAUDIO, &vaudio) < 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
-      return -1;
-    }
-    else
-      mp_msg (MSGT_OPEN, MSGL_INFO,
-              "%s Audio input: %s\n", LOG_LEVEL_V4L2, vaudio.name);
-  }
-  else
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
-    return -1;
-  }
-
-  /* get current video format */
-  if (ioctl (pvr->dev_fd, VIDIOC_G_STD, &std) == 0)
-  {
-    vs.index = 0;
-
-    while (ioctl (pvr->dev_fd, VIDIOC_ENUMSTD, &vs) >= 0)
-    {
-      if (vs.id == std)
-      {
-        mp_msg (MSGT_OPEN, MSGL_INFO,
-                "%s Norm: %s.\n", LOG_LEVEL_V4L2, vs.name);
-        break;
-      }
-      vs.index++;
-    }
-  }
-  else
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't get norm (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
-    return -1;
-  }
-
-  return 0;
-}
-
-/* stream layer */
-
-static void
-pvr_stream_close (stream_t *stream)
-{
-  struct pvr_t *pvr;
-
-  if (!stream)
-    return;
-  
-  pvr = (struct pvr_t *) stream->priv;
-  pvr_uninit (pvr);
-}
-
-static int
-pvr_stream_read (stream_t *stream, char *buffer, int size)
-{
-  struct pollfd pfds[1];
-  struct pvr_t *pvr;
-  int rk, fd, pos;
-
-  if (!stream || !buffer)
-    return 0;
-  
-  pvr = (struct pvr_t *) stream->priv;
-  fd = pvr->dev_fd;
-  pos = 0;
-
-  if (fd < 0)
-    return 0;
-  
-  while (pos < size)
-  {
-    pfds[0].fd = fd;
-    pfds[0].events = POLLIN | POLLPRI;
-
-    rk = size - pos;
-
-    if (poll (pfds, 1, 500) <= 0)
-    {
-      mp_msg (MSGT_OPEN, MSGL_ERR,
-              "%s failed with errno %d when reading %d bytes\n",
-              LOG_LEVEL_PVR, errno, size-pos);
-      break;
-    }
-
-    rk = read (fd, &buffer[pos], rk);
-    if (rk > 0)
-    {
-      pos += rk;
-      mp_msg (MSGT_OPEN, MSGL_DBG3,
-              "%s read (%d) bytes\n", LOG_LEVEL_PVR, pos);
-    }
-  }
-		
-  if (!pos)
-    mp_msg (MSGT_OPEN, MSGL_ERR, "%s read %d bytes\n", LOG_LEVEL_PVR, pos);
-
-  return pos;
-}
-
-static int
-pvr_stream_open (stream_t *stream, int mode, void *opts, int *file_format)
-{
-  struct ivtv_ioctl_codec codec;
-  struct ivtv_driver_info info;
-  struct v4l2_capability vcap;
-  struct pvr_t *pvr = NULL;
-  
-  if (mode != STREAM_READ)
-    return STREAM_UNSUPORTED;
-  
-  pvr = pvr_init ();
-
-  parse_v4l2_tv_options (pvr);
-  parse_ivtv_options (pvr);
-  
-  /* open device */
-  pvr->dev_fd = open (pvr->video_dev, O_RDWR);
-  mp_msg (MSGT_OPEN, MSGL_INFO,
-          "%s Using device %s\n", LOG_LEVEL_PVR, pvr->video_dev);
-  if (pvr->dev_fd == -1)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s error opening device %s\n", LOG_LEVEL_PVR, pvr->video_dev);
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-  
-  /* query capabilities (i.e test V4L2 support) */
-  if (ioctl (pvr->dev_fd, VIDIOC_QUERYCAP, &vcap) < 0)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s device is not V4L2 compliant (%s).\n",
-            LOG_LEVEL_PVR, strerror (errno));
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-  else
-    mp_msg (MSGT_OPEN, MSGL_INFO,
-            "%s Detected %s\n", LOG_LEVEL_PVR, vcap.card);
-
-  /* get codec and initialize card (i.e test IVTV support) */
-  if (ioctl (pvr->dev_fd, IVTV_IOC_G_CODEC, &codec) < 0)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s device is not IVTV compliant (%s).\n",
-            LOG_LEVEL_PVR, strerror (errno));
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-  
-  /* get ivtv driver info */
-  if (ioctl (pvr->dev_fd, IVTV_IOC_G_DRIVER_INFO, &info) < 0)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s device is not IVTV compliant (%s).\n",
-            LOG_LEVEL_PVR, strerror (errno));
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-  else
-    mp_msg (MSGT_OPEN, MSGL_INFO,
-            "%s Detected ivtv driver: %s\n", LOG_LEVEL_PVR, info.comment);
-
-  /* list V4L2 capabilities */
-  if (v4l2_list_capabilities (pvr) == -1)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't get v4l2 capabilities\n", LOG_LEVEL_PVR);
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-  
-  /* apply V4L2 settings */
-  if (set_v4l2_settings (pvr) == -1)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't set v4l2 settings\n", LOG_LEVEL_PVR);
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-
-  /* apply IVTV settings */
-  if (set_ivtv_settings (pvr) == -1)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't set ivtv settings\n", LOG_LEVEL_PVR);
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-  
-  /* display current V4L2 settings */
-  if (v4l2_display_settings (pvr) == -1)
-  {
-    mp_msg (MSGT_OPEN, MSGL_ERR,
-            "%s can't get v4l2 settings\n", LOG_LEVEL_PVR);
-    pvr_uninit (pvr);
-    return STREAM_ERROR;
-  }
-
-  stream->priv = pvr;
-  stream->type = STREAMTYPE_PVR;
-  stream->fill_buffer = pvr_stream_read;
-  stream->close = pvr_stream_close;
-  
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_pvr = {
-  "PVR (V4L2/IVTV) Input",
-  "pvr",
-  "Benjamin Zores",
-  "",
-  pvr_stream_open, 			
-  { "pvr", NULL },
-  NULL,
-  1
-};
--- a/libmpdemux/stream_rtsp.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- *  Copyright (C) 2006 Benjamin Zores
- *   based on previous Real RTSP support from Roberto Togni and xine team.
- *
- *   This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software Foundation,
- *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include "config.h"
-#ifndef HAVE_WINSOCK2
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#define closesocket close
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-#include <errno.h>
-
-#include "stream.h"
-#include "librtsp/rtsp.h"
-#include "librtsp/rtsp_session.h"
-
-#define RTSP_DEFAULT_PORT 554
-
-extern int network_bandwidth;
-
-static int
-rtsp_streaming_read (int fd, char *buffer,
-                     int size, streaming_ctrl_t *stream_ctrl)
-{
-  return rtsp_session_read (stream_ctrl->data, buffer, size);
-}
-
-static int
-rtsp_streaming_start (stream_t *stream)
-{
-  int fd;
-  rtsp_session_t *rtsp;
-  char *mrl;
-  char *file;
-  int port;
-  int redirected, temp;
-
-  if (!stream)
-    return -1;
-
-  /* counter so we don't get caught in infinite redirections */
-  temp = 5;
-
-  do {
-    redirected = 0;
-
-    fd = connect2Server (stream->streaming_ctrl->url->hostname,
-                         port = (stream->streaming_ctrl->url->port ?
-                                 stream->streaming_ctrl->url->port :
-                                 RTSP_DEFAULT_PORT), 1);
-    
-    if (fd < 0 && !stream->streaming_ctrl->url->port)
-      fd = connect2Server (stream->streaming_ctrl->url->hostname,
-                           port = 7070, 1);
-
-    if (fd < 0)
-      return -1;
-    
-    file = stream->streaming_ctrl->url->file;
-    if (file[0] == '/')
-      file++;
-
-    mrl = malloc (strlen (stream->streaming_ctrl->url->hostname)
-                  + strlen (file) + 16);
-    
-    sprintf (mrl, "rtsp://%s:%i/%s",
-             stream->streaming_ctrl->url->hostname, port, file);
-
-    rtsp = rtsp_session_start (fd, &mrl, file,
-                               stream->streaming_ctrl->url->hostname,
-                               port, &redirected,
-                               stream->streaming_ctrl->bandwidth);
-
-    if (redirected == 1)
-    {
-      url_free (stream->streaming_ctrl->url);
-      stream->streaming_ctrl->url = url_new (mrl);
-      closesocket (fd);
-    }
-
-    free (mrl);
-    temp--;
-  } while ((redirected != 0) && (temp > 0));    
-
-  if (!rtsp)
-    return -1;
-
-  stream->fd = fd;
-  stream->streaming_ctrl->data = rtsp;
-  
-  stream->streaming_ctrl->streaming_read = rtsp_streaming_read;
-  stream->streaming_ctrl->streaming_seek = NULL;
-  stream->streaming_ctrl->prebuffer_size = 128*1024;  // 640 KBytes
-  stream->streaming_ctrl->buffering = 1;
-  stream->streaming_ctrl->status = streaming_playing_e;
-  
-  return 0;
-}
-
-static void
-rtsp_streaming_close (struct stream_st *s)
-{
-  rtsp_session_t *rtsp = NULL;
-  
-  rtsp = (rtsp_session_t *) s->streaming_ctrl->data;
-  if (rtsp)
-    rtsp_session_end (rtsp);
-}
-
-static int
-rtsp_streaming_open (stream_t *stream, int mode, void *opts, int *file_format)
-{
-  URL_t *url;
-  extern int index_mode;
-  
-  mp_msg (MSGT_OPEN, MSGL_INFO, "STREAM_RTSP, URL: %s\n", stream->url);
-  stream->streaming_ctrl = streaming_ctrl_new ();
-  if (!stream->streaming_ctrl)
-    return STREAM_ERROR;
-
-  stream->streaming_ctrl->bandwidth = network_bandwidth;
-  url = url_new (stream->url);
-  stream->streaming_ctrl->url = check4proxies (url);
-
-  stream->fd = -1;
-  index_mode = -1; /* prevent most RTSP streams from locking due to -idx */
-  if (rtsp_streaming_start (stream) < 0)
-  {
-    streaming_ctrl_free (stream->streaming_ctrl);
-    stream->streaming_ctrl = NULL;
-    return STREAM_UNSUPORTED;
-  }
-
-  fixup_network_stream_cache (stream);
-  stream->type = STREAMTYPE_STREAM;
-  stream->close = rtsp_streaming_close;
-
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_rtsp = {
-  "RTSP streaming",
-  "rtsp",
-  "Benjamin Zores, Roberto Togni",
-  "ported from xine",
-  rtsp_streaming_open,
-  {"rtsp", NULL},
-  NULL,
-  0 /* Urls are an option string */
-};
--- a/libmpdemux/stream_smb.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-
-#include "config.h"
-
-#include <libsmbclient.h>
-#include <unistd.h>
-
-#include "mp_msg.h"
-#include "stream.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-static struct stream_priv_s {
-} stream_priv_dflts = {
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-// URL definition
-static m_option_t stream_opts_fields[] = {
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-
-static struct m_struct_st stream_opts = {
-  "smb",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-static char smb_password[15];
-static char smb_username[15];
-
-static void smb_auth_fn(const char *server, const char *share,
-             char *workgroup, int wgmaxlen, char *username, int unmaxlen,
-	     char *password, int pwmaxlen)
-{
-  char temp[128];
-  
-  strcpy(temp, "LAN");				  
-  if (temp[strlen(temp) - 1] == 0x0a)
-    temp[strlen(temp) - 1] = 0x00;
-  
-  if (temp[0]) strncpy(workgroup, temp, wgmaxlen - 1);
-  
-  strcpy(temp, smb_username); 
-  if (temp[strlen(temp) - 1] == 0x0a)
-    temp[strlen(temp) - 1] = 0x00;
-  
-  if (temp[0]) strncpy(username, temp, unmaxlen - 1);
-						      
-  strcpy(temp, smb_password); 
-  if (temp[strlen(temp) - 1] == 0x0a)
-    temp[strlen(temp) - 1] = 0x00;
-								
-   if (temp[0]) strncpy(password, temp, pwmaxlen - 1);
-}
-
-static int seek(stream_t *s,off_t newpos) {
-  s->pos = newpos;
-  if(smbc_lseek(s->fd,s->pos,SEEK_SET)<0) {
-    s->eof=1;
-    return 0;
-  }
-  return 1;
-}
-
-static int fill_buffer(stream_t *s, char* buffer, int max_len){
-  int r = smbc_read(s->fd,buffer,max_len);
-  return (r <= 0) ? -1 : r;
-}
-
-static int write_buffer(stream_t *s, char* buffer, int len) {
-  int r = smbc_write(s->fd,buffer,len);
-  return (r <= 0) ? -1 : r;
-}
-
-static void close_f(stream_t *s){
-  smbc_close(s->fd);
-}
-
-static int open_f (stream_t *stream, int mode, void *opts, int* file_format) {
-  struct stream_priv_s *p = (struct stream_priv_s*)opts;
-  char *filename;
-  mode_t m = 0;
-  off_t len;
-  int fd, err;
-  
-  filename = stream->url;
-  
-  if(mode == STREAM_READ)
-    m = O_RDONLY;
-  else if (mode == STREAM_WRITE) //who's gonna do that ?
-    m = O_WRONLY;
-  else {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "[smb] Unknown open mode %d\n", mode);
-    m_struct_free (&stream_opts, opts);
-    return STREAM_UNSUPORTED;
-  }
-  
-  if(!filename) {
-    mp_msg(MSGT_OPEN,MSGL_ERR, "[smb] Bad url\n");
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-  
-  err = smbc_init(smb_auth_fn, 1);
-  if (err < 0) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_SMBInitError,err);
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-  
-  fd = smbc_open(filename, m,0644);
-  if (fd < 0) {	
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_SMBFileNotFound, filename);
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-  
-  len = smbc_lseek(fd,0,SEEK_END);
-  smbc_lseek (fd, 0, SEEK_SET);
-  if (len <= 0)
-    stream->flags = 0;
-  else {
-    stream->flags = STREAM_READ | STREAM_SEEK;
-    stream->end_pos = len;
-    stream->seek = seek;
-  }
-  stream->type = STREAMTYPE_SMB;
-  stream->fd = fd;
-  stream->fill_buffer = fill_buffer;
-  stream->write_buffer = write_buffer;
-  stream->close = close_f;
-  
-  m_struct_free(&stream_opts, opts);
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_smb = {
-  "Server Message Block",
-  "smb",
-  "M. Tourne",
-  "based on the code from 'a bulgarian' (one says)",
-  open_f,
-  {"smb", NULL},
-  &stream_opts,
-  0 //Url is an option string
-};
--- a/libmpdemux/stream_vcd.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-
-#include "config.h"
-
-#include "mp_msg.h"
-#include "stream.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-#include <sys/cdrio.h>
-#include "vcd_read_fbsd.h" 
-#elif defined(__NetBSD__) || defined (__OpenBSD__)
-#include "vcd_read_nbsd.h"
-#elif defined(SYS_DARWIN)
-#include "vcd_read_darwin.h" 
-#else
-#include "vcd_read.h"
-#endif
-
-extern char *cdrom_device;
-
-static struct stream_priv_s {
-  int track;
-  char* device;
-} stream_priv_dflts = {
-  1,
-  NULL
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  { "track", ST_OFF(track), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
-  { "device", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  /// For url parsing
-  { "hostname", ST_OFF(track), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
-  { "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-static struct m_struct_st stream_opts = {
-  "vcd",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-static int fill_buffer(stream_t *s, char* buffer, int max_len){
-  if(s->pos > s->end_pos) /// don't past end of current track
-    return 0;
-  return vcd_read(s->priv,buffer);
-}
-
-static int seek(stream_t *s,off_t newpos) {
-  s->pos = newpos;
-  vcd_set_msf(s->priv,s->pos/VCD_SECTOR_DATA);
-  return 1;
-}
-
-static void close_s(stream_t *stream) {
-  free(stream->priv);
-}
-
-static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-  int ret,ret2,f;
-  mp_vcd_priv_t* vcd;
-#ifdef __FreeBSD__
-  int bsize = VCD_SECTOR_SIZE;
-#endif
-
-  if(mode != STREAM_READ) {
-    m_struct_free(&stream_opts,opts);
-    return STREAM_UNSUPORTED;
-  }
-
-  if (!p->device) {
-    if(cdrom_device)
-      p->device = strdup(cdrom_device);
-    else
-      p->device = strdup(DEFAULT_CDROM_DEVICE);
-  }
-
-  f=open(p->device,O_RDONLY);
-  if(f<0){ 
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CdDevNotfound,p->device);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-
-  vcd = vcd_read_toc(f);
-  if(!vcd) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,"Failed to get cd toc\n");
-    close(f);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-  ret2=vcd_get_track_end(vcd,p->track);
-  if(ret2<0){
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (get)\n");
-    close(f);
-    free(vcd);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-  ret=vcd_seek_to_track(vcd,p->track);
-  if(ret<0){
-    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");
-    close(f);
-    free(vcd);
-    m_struct_free(&stream_opts,opts);
-    return STREAM_ERROR;
-  }
-  mp_msg(MSGT_OPEN,MSGL_V,"VCD start byte position: 0x%X  end: 0x%X\n",ret,ret2);
-
-#ifdef __FreeBSD__
-  if (ioctl (f, CDRIOCSETBLOCKSIZE, &bsize) == -1) {
-    mp_msg(MSGT_OPEN,MSGL_WARN,"Error in CDRIOCSETBLOCKSIZE");
-  }
-#endif
-
-  stream->fd = f;
-  stream->type = STREAMTYPE_VCD;
-  stream->sector_size = VCD_SECTOR_DATA;
-  stream->start_pos=ret;
-  stream->end_pos=ret2;
-  stream->priv = vcd;
-
-  stream->fill_buffer = fill_buffer;
-  stream->seek = seek;
-  stream->close = close_s;
-
-  m_struct_free(&stream_opts,opts);
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_vcd = {
-  "Video CD",
-  "vcd",
-  "Albeu",
-  "based on the code from ???",
-  open_s,
-  { "vcd", NULL },
-  &stream_opts,
-  1 // Urls are an option string
-};
--- a/libmpdemux/stream_vstream.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- *  stream_vstream.c
- *
- *	Copyright (C) Joey Parrish
- *
- *  This file is part of MPlayer, a free movie player.
- *	
- *  MPlayer is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
- *  any later version.
- *   
- *  MPlayer is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *   
- *  You should have received a copy of the GNU General Public License
- *  along with GNU Make; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- *
- */
-
-/*
- *   If you have a tivo with the vstream server installed, (and most tivo
- *   hackers do,) then you can connect to it and stream ty files using
- *   this module.  The url syntax is tivo://host/fsid or tivo://host/list
- *   to list the available recordings and their fsid's.
- *   This module depends on libvstream-client, which is available from
- *   http://armory.nicewarrior.org/projects/vstream-client .
- *
- */
-
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdarg.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <inttypes.h>
-#include <errno.h>
-
-#include "mp_msg.h"
-#include "stream.h"
-#include "help_mp.h"
-#include "m_option.h"
-#include "m_struct.h"
-
-#include <vstream-client.h>
-
-void vstream_error(const char *format, ...) {
-    char buf[1024];
-    va_list va;
-    va_start(va, format);
-    vsnprintf(buf, 1024, format, va);
-    va_end(va);
-    mp_msg(MSGT_STREAM, MSGL_ERR, buf);
-}
-
-static struct stream_priv_s {
-  char* host;
-  char* fsid;
-} stream_priv_dflts = {
-  NULL,
-  NULL
-};
-
-#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
-/// URL definition
-static m_option_t stream_opts_fields[] = {
-  {"hostname", ST_OFF(host), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  {"filename", ST_OFF(fsid), CONF_TYPE_STRING, 0, 0 ,0, NULL},
-  { NULL, NULL, 0, 0, 0, 0,  NULL }
-};
-
-static struct m_struct_st stream_opts = {
-  "vstream",
-  sizeof(struct stream_priv_s),
-  &stream_priv_dflts,
-  stream_opts_fields
-};
-
-static int fill_buffer(stream_t *s, char* buffer, int max_len){
-  struct stream_priv_s* p = (struct stream_priv_s*)s->priv;
-  int len = vstream_load_chunk(p->fsid, buffer, max_len, s->pos);
-  if (len <= 0) return 0;
-  return len;
-}
-
-static int seek(stream_t *s,off_t newpos) {
-  s->pos = newpos;
-  return 1;
-}
-
-static int control(struct stream_st *s,int cmd,void* arg) {
-  return STREAM_UNSUPORTED;
-}
-
-static void close_s(struct stream_st *s) {
-}
-
-static int open_s(stream_t *stream, int mode, void* opts, int* file_format) {
-  int f;
-  struct stream_priv_s* p = (struct stream_priv_s*)opts;
-
-  if(mode != STREAM_READ)
-    return STREAM_UNSUPORTED;
-
-  if(!p->host) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "We need a host name (ex: tivo://hostname/fsid)\n");
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-
-  if(!p->fsid || strlen(p->fsid) == 0) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "We need an fsid (ex: tivo://hostname/fsid)\n");
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-
-  f = connect2Server(p->host, VSERVER_PORT, 1);
-
-  if(f < 0) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "Connection to %s failed\n", p->host);
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-  stream->fd = f;
-
-  vstream_set_socket_fd(f);
-
-  if (!strcmp(p->fsid, "list")) {
-    vstream_list_streams(0);
-    return STREAM_ERROR;
-  } else if (!strcmp(p->fsid, "llist")) {
-    vstream_list_streams(1);
-    return STREAM_ERROR;
-  }
-
-  if (vstream_start()) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "Cryptic internal error #1\n");
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-  if (vstream_startstream(p->fsid)) {
-    mp_msg(MSGT_OPEN, MSGL_ERR, "Cryptic internal error #2\n");
-    m_struct_free(&stream_opts, opts);
-    return STREAM_ERROR;
-  }
-  
-  stream->start_pos = 0;
-  stream->end_pos = vstream_streamsize();
-  mp_msg(MSGT_OPEN, MSGL_DBG2, "Tivo stream size is %d\n", stream->end_pos);
-
-  stream->priv = p;
-  stream->fill_buffer = fill_buffer;
-  stream->control = control;
-  stream->seek = seek;
-  stream->close = close_s;
-  stream->type = STREAMTYPE_VSTREAM;
-
-  return STREAM_OK;
-}
-
-stream_info_t stream_info_vstream = {
-  "vstream client",
-  "vstream",
-  "Joey",
-  "",
-  open_s,
-  { "tivo", NULL },
-  &stream_opts,
-  1 // Url is an option string
-};
--- a/libmpdemux/tv.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,919 +0,0 @@
-/*
- TV Interface for MPlayer
- 
- (C) Alex Beregszaszi
- 
- API idea based on libvo2
-
- Feb 19, 2002: Significant rewrites by Charles R. Henrich (henrich@msu.edu)
-				to add support for audio, and bktr *BSD support.
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/time.h>
-
-#include "config.h"
-
-int tv_param_on = 0;
-
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#include "stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-#include "libaf/af_format.h"
-#include "libvo/img_format.h"
-#include "libvo/fastmemcpy.h"
-
-#include "tv.h"
-
-#include "frequencies.h"
-
-/* some default values */
-int tv_param_audiorate = 44100;
-int tv_param_noaudio = 0;
-int tv_param_immediate = 0;
-char *tv_param_freq = NULL;
-char *tv_param_channel = NULL;
-char *tv_param_norm = "pal";
-#ifdef HAVE_TV_V4L2
-int tv_param_normid = -1;
-#endif
-char *tv_param_chanlist = "europe-east";
-char *tv_param_device = NULL;
-char *tv_param_driver = "dummy";
-int tv_param_width = -1;
-int tv_param_height = -1;
-int tv_param_input = 0; /* used in v4l and bttv */
-int tv_param_outfmt = -1;
-float tv_param_fps = -1.0;
-char **tv_param_channels = NULL;
-int tv_param_audio_id = 0;
-#if defined(HAVE_TV_V4L)
-int tv_param_amode = -1;
-int tv_param_volume = -1;
-int tv_param_bass = -1;
-int tv_param_treble = -1;
-int tv_param_balance = -1;
-int tv_param_forcechan = -1;
-int tv_param_force_audio = 0;
-int tv_param_buffer_size = -1;
-int tv_param_mjpeg = 0;
-int tv_param_decimation = 2;
-int tv_param_quality = 90;
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-int tv_param_alsa = 0;
-#endif
-char* tv_param_adevice = NULL;
-#endif
-int tv_param_brightness = 0;
-int tv_param_contrast = 0;
-int tv_param_hue = 0;
-int tv_param_saturation = 0;
-tv_channels_t *tv_channel_list;
-tv_channels_t *tv_channel_current, *tv_channel_last;
-char *tv_channel_last_real;
-
-/* ================== DEMUX_TV ===================== */
-/*
-  Return value:
-    0 = EOF(?) or no stream
-    1 = successfully read a packet
-*/
-/* fill demux->video and demux->audio */
-
-static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
-{
-    tvi_handle_t *tvh=(tvi_handle_t*)(demux->priv);
-    demux_packet_t* dp;
-    unsigned int len=0;
-
-    /* ================== ADD AUDIO PACKET =================== */
-
-    if (ds==demux->audio && tv_param_noaudio == 0 && 
-        tvh->functions->control(tvh->priv, 
-                                TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
-        {
-        len = tvh->functions->get_audio_framesize(tvh->priv);
-
-        dp=new_demux_packet(len);
-        dp->flags|=1; /* Keyframe */
-        dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len);
-        ds_add_packet(demux->audio,dp);
-        }
-
-    /* ================== ADD VIDEO PACKET =================== */
-
-    if (ds==demux->video && tvh->functions->control(tvh->priv, 
-                            TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE)
-        {
-		len = tvh->functions->get_video_framesize(tvh->priv);
-       	dp=new_demux_packet(len);
-		dp->flags|=1; /* Keyframe */
-  		dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len);
-   		ds_add_packet(demux->video,dp);
-	 }
-
-    return 1;
-}
-
-static int norm_from_string(tvi_handle_t *tvh, char* norm)
-{
-#ifdef HAVE_TV_V4L2
-    if (strcmp(tv_param_driver, "v4l2") != 0) {
-#endif
-    if (!strcasecmp(norm, "pal"))
-	return TV_NORM_PAL;
-    else if (!strcasecmp(norm, "ntsc"))
-	return TV_NORM_NTSC;
-    else if (!strcasecmp(norm, "secam"))
-	return TV_NORM_SECAM;
-    else if (!strcasecmp(norm, "palnc"))
-	return TV_NORM_PALNC;
-    else if (!strcasecmp(norm, "palm"))
-	return TV_NORM_PALM;
-    else if (!strcasecmp(norm, "paln"))
-	return TV_NORM_PALN;
-    else if (!strcasecmp(norm, "ntscjp"))
-	return TV_NORM_NTSCJP;
-    else {
-	mp_msg(MSGT_TV, MSGL_V, "tv.c: norm_from_string(%s): Bogus norm parameter, setting PAL.\n", norm);
-	return TV_NORM_PAL;
-    }
-#ifdef HAVE_TV_V4L2
-    } else {
-	tvi_functions_t *funcs = tvh->functions;
-	char str[8];
-	strncpy(str, norm, sizeof(str)-1);
-	str[sizeof(str)-1] = '\0';
-        if (funcs->control(tvh->priv, TVI_CONTROL_SPC_GET_NORMID, str) != TVI_CONTROL_TRUE)
-	    return 0;
-	return *(int *)str;
-    }
-#endif
-}
-
-static int open_tv(tvi_handle_t *tvh)
-{
-    int i;
-    tvi_functions_t *funcs = tvh->functions;
-    int tv_fmt_list[] = {
-      IMGFMT_YV12,
-      IMGFMT_I420,
-      IMGFMT_UYVY,
-      IMGFMT_YUY2,
-      IMGFMT_RGB32,
-      IMGFMT_RGB24,
-      IMGFMT_RGB16,
-      IMGFMT_RGB15
-    };
-
-    if (funcs->control(tvh->priv, TVI_CONTROL_IS_VIDEO, 0) != TVI_CONTROL_TRUE)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "Error: No video input present!\n");
-	return 0;
-    }
-
-    if (tv_param_outfmt == -1)
-      for (i = 0; i < sizeof (tv_fmt_list) / sizeof (*tv_fmt_list); i++)
-        {
-          tv_param_outfmt = tv_fmt_list[i];
-          if (funcs->control (tvh->priv, TVI_CONTROL_VID_SET_FORMAT,
-                              &tv_param_outfmt) == TVI_CONTROL_TRUE)
-            break;
-        }
-    else
-    {
-    switch(tv_param_outfmt)
-    {
-	case IMGFMT_YV12:
-	case IMGFMT_I420:
-	case IMGFMT_UYVY:
-	case IMGFMT_YUY2:
-	case IMGFMT_RGB32:
-	case IMGFMT_RGB24:
-	case IMGFMT_BGR32:
-	case IMGFMT_BGR24:
-	case IMGFMT_BGR16:
-	case IMGFMT_BGR15:
-	    break;
-	default:
-	    mp_msg(MSGT_TV, MSGL_ERR, "==================================================================\n");
-	    mp_msg(MSGT_TV, MSGL_ERR, " WARNING: UNTESTED OR UNKNOWN OUTPUT IMAGE FORMAT REQUESTED (0x%x)\n", tv_param_outfmt);
-	    mp_msg(MSGT_TV, MSGL_ERR, " This may cause buggy playback or program crash! Bug reports will\n");
-	    mp_msg(MSGT_TV, MSGL_ERR, " be ignored! You should try again with YV12 (which is the default\n");
-	    mp_msg(MSGT_TV, MSGL_ERR, " colorspace) and read the documentation!\n");
-	    mp_msg(MSGT_TV, MSGL_ERR, "==================================================================\n");
-    }
-    funcs->control(tvh->priv, TVI_CONTROL_VID_SET_FORMAT, &tv_param_outfmt);
-    }
-
-    /* set some params got from cmdline */
-    funcs->control(tvh->priv, TVI_CONTROL_SPC_SET_INPUT, &tv_param_input);
-
-#ifdef HAVE_TV_V4L2
-    if (!strcmp(tv_param_driver, "v4l2") && tv_param_normid >= 0) {
-	mp_msg(MSGT_TV, MSGL_V, "Selected norm id: %d\n", tv_param_normid);
-	if (funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tv_param_normid) != TVI_CONTROL_TRUE) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
-	}
-    } else {
-#endif
-    /* select video norm */
-    tvh->norm = norm_from_string(tvh, tv_param_norm);
-
-    mp_msg(MSGT_TV, MSGL_V, "Selected norm: %s\n", tv_param_norm);
-    if (funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->norm) != TVI_CONTROL_TRUE) {
-	mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
-    }
-#ifdef HAVE_TV_V4L2
-    }
-#endif
-
-#ifdef HAVE_TV_V4L1
-    if ( tv_param_mjpeg )
-    {
-      /* set width to expected value */
-      if (tv_param_width == -1)
-        {
-          tv_param_width = 704/tv_param_decimation;
-        }
-      if (tv_param_height == -1)
-        {
-	  if ( tvh->norm != TV_NORM_NTSC )
-            tv_param_height = 576/tv_param_decimation; 
-	  else
-            tv_param_height = 480/tv_param_decimation; 
-        }
-      mp_msg(MSGT_TV, MSGL_INFO, 
-	       "  MJP: width %d height %d\n", tv_param_width, tv_param_height);
-    }
-#endif
-
-    /* limits on w&h are norm-dependent -- JM */
-    /* set width */
-    if (tv_param_width != -1)
-    {
-	if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_WIDTH, &tv_param_width) == TVI_CONTROL_TRUE)
-	    funcs->control(tvh->priv, TVI_CONTROL_VID_SET_WIDTH, &tv_param_width);
-	else
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "Unable to set requested width: %d\n", tv_param_width);
-	    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &tv_param_width);
-	}    
-    }
-
-    /* set height */
-    if (tv_param_height != -1)
-    {
-	if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_HEIGHT, &tv_param_height) == TVI_CONTROL_TRUE)
-	    funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HEIGHT, &tv_param_height);
-	else
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "Unable to set requested height: %d\n", tv_param_height);
-	    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &tv_param_height);
-	}    
-    }
-
-    if (funcs->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE)
-    {
-	mp_msg(MSGT_TV, MSGL_WARN, "Selected input hasn't got a tuner!\n");	
-	goto done;
-    }
-
-    /* select channel list */
-    for (i = 0; chanlists[i].name != NULL; i++)
-    {
-	if (!strcasecmp(chanlists[i].name, tv_param_chanlist))
-	{
-	    tvh->chanlist = i;
-	    tvh->chanlist_s = chanlists[i].list;
-	    break;
-	}
-    }
-
-    if (tvh->chanlist == -1)
-	mp_msg(MSGT_TV, MSGL_WARN, "Unable to find selected channel list! (%s)\n",
-	    tv_param_chanlist);
-    else
-	mp_msg(MSGT_TV, MSGL_V, "Selected channel list: %s (including %d channels)\n",
-	    chanlists[tvh->chanlist].name, chanlists[tvh->chanlist].count);
-
-    if (tv_param_freq && tv_param_channel)
-    {
-	mp_msg(MSGT_TV, MSGL_WARN, "You can't set frequency and channel simultaneously!\n");
-	goto done;
-    }
-
-    /* Handle channel names */
-    if (tv_param_channels) {
-	char** channels = tv_param_channels;
-	mp_msg(MSGT_TV, MSGL_INFO, "TV channel names detected.\n");
-	tv_channel_list = malloc(sizeof(tv_channels_t));
-	tv_channel_list->index=1;
-	tv_channel_list->next=NULL;
-	tv_channel_list->prev=NULL;
-	tv_channel_current = tv_channel_list;
-
-	while (*channels) {
-		char* tmp = *(channels++);
-		char* sep = strchr(tmp,'-');
-		int i;
-		struct CHANLIST cl;
-
-		if (!sep) continue; // Wrong syntax, but mplayer should not crash
-
-		strlcpy(tv_channel_current->name, sep + 1,
-		        sizeof(tv_channel_current->name));
-		sep[0] = '\0';
-		strncpy(tv_channel_current->number, tmp, 5);
-
-		while ((sep=strchr(tv_channel_current->name, '_')))
-		    sep[0] = ' ';
-
-		tv_channel_current->freq = 0;
-		for (i = 0; i < chanlists[tvh->chanlist].count; i++) {
-		    cl = tvh->chanlist_s[i];
-		    if (!strcasecmp(cl.name, tv_channel_current->number)) {
-			tv_channel_current->freq=cl.freq;
-			break;
-		    }
-		}
-	        if (tv_channel_current->freq == 0)
-		    mp_msg(MSGT_TV, MSGL_ERR, "Couldn't find frequency for channel %s (%s)\n",
-				    tv_channel_current->number, tv_channel_current->name);
-		else {
-		  sep = strchr(tv_channel_current->name, '-');
-		  if ( !sep ) sep = strchr(tv_channel_current->name, '+');
-
-		  if ( sep ) {
-		    i = atoi (sep+1);
-		    if ( sep[0] == '+' ) tv_channel_current->freq += i * 100;
-		    if ( sep[0] == '-' ) tv_channel_current->freq -= i * 100;
-		    sep[0] = '\0';
-		  }
-		}
-
-		/*mp_msg(MSGT_TV, MSGL_INFO, "-- Detected channel %s - %s (%5.3f)\n",
-				tv_channel_current->number, tv_channel_current->name,
-				(float)tv_channel_current->freq/1000);*/
-
-		tv_channel_current->next = malloc(sizeof(tv_channels_t));
-		tv_channel_current->next->index = tv_channel_current->index + 1;
-		tv_channel_current->next->prev = tv_channel_current;
-		tv_channel_current->next->next = NULL;
-		tv_channel_current = tv_channel_current->next;
-	}
-	if (tv_channel_current->prev)
-  	  tv_channel_current->prev->next = NULL;
-	free(tv_channel_current);
-    } else 
-	    tv_channel_last_real = malloc(5);
-
-    if (tv_channel_list) {
-	int i;
-	int channel = 0;
-	if (tv_param_channel)
-	 {
-	   if (isdigit(*tv_param_channel))
-		/* if tv_param_channel begins with a digit interpret it as a number */
-		channel = atoi(tv_param_channel);
-	   else
-	      {
-		/* if tv_param_channel does not begin with a digit 
-		   set the first channel that contains tv_param_channel in its name */
-
-		tv_channel_current = tv_channel_list;
-		while ( tv_channel_current ) {
-			if ( strstr(tv_channel_current->name, tv_param_channel) )
-			  break;
-			tv_channel_current = tv_channel_current->next;
-			}
-		if ( !tv_channel_current ) tv_channel_current = tv_channel_list;
-	      }
-	 }
-	else
-		channel = 1;
-
-	if ( channel ) {
-	tv_channel_current = tv_channel_list;
-	for (i = 1; i < channel; i++)
-		if (tv_channel_current->next)
-			tv_channel_current = tv_channel_current->next;
-	}
-
-	mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
-			tv_channel_current->name, (float)tv_channel_current->freq/1000);
-	tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
-	tv_channel_last = tv_channel_current;
-    } else {
-    /* we need to set frequency */
-    if (tv_param_freq)
-    {
-	unsigned long freq = atof(tv_param_freq)*16;
-
-        /* set freq in MHz */
-	funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_FREQ, &freq);
-
-	funcs->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, &freq);
-	mp_msg(MSGT_TV, MSGL_V, "Selected frequency: %lu (%.3f)\n",
-	    freq, (float)freq/16);
-    }
-
-	    if (tv_param_channel) {
-	struct CHANLIST cl;
-
-	mp_msg(MSGT_TV, MSGL_V, "Requested channel: %s\n", tv_param_channel);
-	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
-	{
-	    cl = tvh->chanlist_s[i];
-		    //  printf("count%d: name: %s, freq: %d\n",
-		    //	i, cl.name, cl.freq);
-	    if (!strcasecmp(cl.name, tv_param_channel))
-	    {
-			strcpy(tv_channel_last_real, cl.name);
-		tvh->channel = i;
-		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
-		    cl.name, (float)cl.freq/1000);
-		tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
-		break;
-	    }
-	}
-    }
-    }
-    
-    /* grep frequency in chanlist */
-    {
-	unsigned long i2;
-	int freq;
-	
-	tv_get_freq(tvh, &i2);
-	
-	freq = (int) (((float)(i2/16))*1000)+250;
-	
-	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
-	{
-	    if (tvh->chanlist_s[i].freq == freq)
-	    {
-		tvh->channel = i+1;
-		break;
-	    }
-	}
-    }
-
-done:    
-    /* also start device! */
-	return 1;
-}
-
-static demuxer_t* demux_open_tv(demuxer_t *demuxer)
-{
-    tvi_handle_t *tvh;
-    sh_video_t *sh_video;
-    sh_audio_t *sh_audio = NULL;
-    tvi_functions_t *funcs;
-    
-    if(!(tvh=tv_begin())) return NULL;
-    if (!tv_init(tvh)) return NULL;
-    if (!open_tv(tvh)){
-	tv_uninit(tvh);
-	return NULL;
-    }
-    funcs = tvh->functions;
-    demuxer->priv=tvh;
-    
-    sh_video = new_sh_video(demuxer, 0);
-
-    /* get IMAGE FORMAT */
-    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &sh_video->format);
-//    if (IMGFMT_IS_RGB(sh_video->format) || IMGFMT_IS_BGR(sh_video->format))
-//	sh_video->format = 0x0;
-
-    /* set FPS and FRAMETIME */
-
-    if(!sh_video->fps)
-    {
-        float tmp;
-        if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &tmp) != TVI_CONTROL_TRUE)
-             sh_video->fps = 25.0f; /* on PAL */
-        else sh_video->fps = tmp;
-    }
-
-    if (tv_param_fps != -1.0f)
-        sh_video->fps = tv_param_fps;
-
-    sh_video->frametime = 1.0f/sh_video->fps;
-
-    /* If playback only mode, go to immediate mode, fail silently */
-    if(tv_param_immediate == 1)
-        {
-        funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0);
-        tv_param_noaudio = 1; 
-        }
-
-    /* disable TV audio if -nosound is present */
-    if (!demuxer->audio || demuxer->audio->id == -2) {
-        tv_param_noaudio = 1; 
-    }
-
-    /* set width */
-    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w);
-
-    /* set height */
-    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h);
-
-    demuxer->video->sh = sh_video;
-    sh_video->ds = demuxer->video;
-    demuxer->video->id = 0;
-    demuxer->seekable = 0;
-
-    /* here comes audio init */
-    if (tv_param_noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
-    {
-	int audio_format;
-	int sh_audio_format;
-	char buf[128];
-
-	/* yeah, audio is present */
-
-	funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE, 
-				  &tv_param_audiorate);
-
-	if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE)
-	    goto no_audio;
-
-	switch(audio_format)
-	{
-	    case AF_FORMAT_U8:
-	    case AF_FORMAT_S8:
-	    case AF_FORMAT_U16_LE:
-	    case AF_FORMAT_U16_BE:
-	    case AF_FORMAT_S16_LE:
-	    case AF_FORMAT_S16_BE:
-	    case AF_FORMAT_S32_LE:
-	    case AF_FORMAT_S32_BE:
-		sh_audio_format = 0x1; /* PCM */
-		break;
-	    case AF_FORMAT_IMA_ADPCM:
-	    case AF_FORMAT_MU_LAW:
-	    case AF_FORMAT_A_LAW:
-	    case AF_FORMAT_MPEG2:
-	    case AF_FORMAT_AC3:
-	    default:
-		mp_msg(MSGT_TV, MSGL_ERR, "Audio type '%s (%x)' unsupported!\n",
-		    af_fmt2str(audio_format, buf, 128), audio_format);
-		goto no_audio;
-	}
-	
-	sh_audio = new_sh_audio(demuxer, 0);
-
-	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, 
-                   &sh_audio->samplerate);
-	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE, 
-                   &sh_audio->samplesize);
-	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, 
-                   &sh_audio->channels);
-
-	sh_audio->format = sh_audio_format;
-	sh_audio->sample_format = audio_format;
-
-	sh_audio->i_bps = sh_audio->o_bps =
-	    sh_audio->samplerate * sh_audio->samplesize * 
-	    sh_audio->channels;
-
-	// emulate WF for win32 codecs:
-	sh_audio->wf = malloc(sizeof(WAVEFORMATEX));
-	sh_audio->wf->wFormatTag = sh_audio->format;
-	sh_audio->wf->nChannels = sh_audio->channels;
-	sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8;
-	sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
-	sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels;
-	sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps;
-
-	mp_msg(MSGT_DECVIDEO, MSGL_V, "  TV audio: %d channels, %d bits, %d Hz\n",
-          sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
-          sh_audio->wf->nSamplesPerSec);
-
-	demuxer->audio->sh = sh_audio;
-	sh_audio->ds = demuxer->audio;
-	demuxer->audio->id = 0;
-    }
-no_audio:
-
-    if(!(funcs->start(tvh->priv))){
-	// start failed :(
-	tv_uninit(tvh);
-	return NULL;
-    }
-
-    /* set color eq */
-    tv_set_color_options(tvh, TV_COLOR_BRIGHTNESS, tv_param_brightness);
-    tv_set_color_options(tvh, TV_COLOR_HUE, tv_param_hue);
-    tv_set_color_options(tvh, TV_COLOR_SATURATION, tv_param_saturation);
-    tv_set_color_options(tvh, TV_COLOR_CONTRAST, tv_param_contrast);
-
-    return demuxer;
-}
-
-static void demux_close_tv(demuxer_t *demuxer)
-{
-    tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv);
-    tvh->functions->uninit(tvh->priv);
-}
-
-/* ================== STREAM_TV ===================== */
-tvi_handle_t *tvi_init_dummy(char *device);
-tvi_handle_t *tvi_init_v4l(char *device, char *adevice);
-tvi_handle_t *tvi_init_v4l2(char *device, char *adevice);
-tvi_handle_t *tvi_init_bsdbt848(char *device);
-
-tvi_handle_t *tv_begin(void)
-{
-    if (!strcmp(tv_param_driver, "dummy"))
-	return tvi_init_dummy(tv_param_device);
-#ifdef HAVE_TV_V4L1
-    if (!strcmp(tv_param_driver, "v4l"))
-	return tvi_init_v4l(tv_param_device, tv_param_adevice);
-#endif
-#ifdef HAVE_TV_V4L2
-    if (!strcmp(tv_param_driver, "v4l2"))
-	return tvi_init_v4l2(tv_param_device, tv_param_adevice);
-#endif
-#ifdef HAVE_TV_BSDBT848
-    if (!strcmp(tv_param_driver, "bsdbt848"))
-	return tvi_init_bsdbt848(tv_param_device);
-#endif
-
-    mp_msg(MSGT_TV, MSGL_ERR, "No such driver: %s\n", tv_param_driver); 
-    return(NULL);
-}
-
-int tv_init(tvi_handle_t *tvh)
-{
-    mp_msg(MSGT_TV, MSGL_INFO, "Selected driver: %s\n", tvh->info->short_name);
-    mp_msg(MSGT_TV, MSGL_INFO, " name: %s\n", tvh->info->name);
-    mp_msg(MSGT_TV, MSGL_INFO, " author: %s\n", tvh->info->author);
-    if (tvh->info->comment)
-	mp_msg(MSGT_TV, MSGL_INFO, " comment: %s\n", tvh->info->comment);
-
-    return(tvh->functions->init(tvh->priv));
-}
-
-int tv_uninit(tvi_handle_t *tvh)
-{
-    return(tvh->functions->uninit(tvh->priv));
-}
-
-/* utilities for mplayer (not mencoder!!) */
-int tv_set_color_options(tvi_handle_t *tvh, int opt, int value)
-{
-    tvi_functions_t *funcs = tvh->functions;
-
-    switch(opt)
-    {
-	case TV_COLOR_BRIGHTNESS:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_BRIGHTNESS, &value);
-	case TV_COLOR_HUE:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HUE, &value);
-	case TV_COLOR_SATURATION:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_SATURATION, &value);
-	case TV_COLOR_CONTRAST:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_CONTRAST, &value);
-	default:
-	    mp_msg(MSGT_TV, MSGL_WARN, "Unknown color option (%d) specified!\n", opt);
-    }
-    
-    return(TVI_CONTROL_UNKNOWN);
-}
-
-int tv_get_color_options(tvi_handle_t *tvh, int opt, int* value)
-{
-    tvi_functions_t *funcs = tvh->functions;
-
-    switch(opt)
-    {
-	case TV_COLOR_BRIGHTNESS:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_BRIGHTNESS, value);
-	case TV_COLOR_HUE:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HUE, value);
-	case TV_COLOR_SATURATION:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_SATURATION, value);
-	case TV_COLOR_CONTRAST:
-	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_CONTRAST, value);
-	default:
-	    mp_msg(MSGT_TV, MSGL_WARN, "Unknown color option (%d) specified!\n", opt);
-    }
-    
-    return(TVI_CONTROL_UNKNOWN);
-}
-
-int tv_get_freq(tvi_handle_t *tvh, unsigned long *freq)
-{
-    if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) == TVI_CONTROL_TRUE)
-    {
-	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, freq);
-	mp_msg(MSGT_TV, MSGL_V, "Current frequency: %lu (%.3f)\n",
-	    *freq, (float)*freq/16);
-    }
-    return(1);
-}
-
-int tv_set_freq(tvi_handle_t *tvh, unsigned long freq)
-{
-    if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) == TVI_CONTROL_TRUE)
-    {
-//	unsigned long freq = atof(tv_param_freq)*16;
-
-        /* set freq in MHz */
-	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_FREQ, &freq);
-
-	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, &freq);
-	mp_msg(MSGT_TV, MSGL_V, "Current frequency: %lu (%.3f)\n",
-	    freq, (float)freq/16);
-    }
-    return(1);
-}
-
-int tv_step_channel_real(tvi_handle_t *tvh, int direction)
-{
-    struct CHANLIST cl;
-
-    if (direction == TV_CHANNEL_LOWER)
-    {
-	if (tvh->channel-1 >= 0)
-	{
-	    strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
-	    cl = tvh->chanlist_s[--tvh->channel];
-	    mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
-		cl.name, (float)cl.freq/1000);
-	    tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
-	}	
-    }
-
-    if (direction == TV_CHANNEL_HIGHER)
-    {
-	if (tvh->channel+1 < chanlists[tvh->chanlist].count)
-	{
-	    strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
-	    cl = tvh->chanlist_s[++tvh->channel];
-	    mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
-		cl.name, (float)cl.freq/1000);
-	    tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
-	}	
-    }
-    return(1);
-}
-
-int tv_step_channel(tvi_handle_t *tvh, int direction) {
-	if (tv_channel_list) {
-		if (direction == TV_CHANNEL_HIGHER) {
-			tv_channel_last = tv_channel_current;
-			if (tv_channel_current->next)
-				tv_channel_current = tv_channel_current->next;
-			else
-				tv_channel_current = tv_channel_list;
-				tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
-				mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n",
-			tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
-		}
-		if (direction == TV_CHANNEL_LOWER) {
-			tv_channel_last = tv_channel_current;
-			if (tv_channel_current->prev)
-				tv_channel_current = tv_channel_current->prev;
-			else
-				while (tv_channel_current->next)
-					tv_channel_current = tv_channel_current->next;
-				tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
-				mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n",
-			tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
-		}
-	} else tv_step_channel_real(tvh, direction);
-	return(1);
-}
-
-int tv_set_channel_real(tvi_handle_t *tvh, char *channel) {
-	int i;
-	struct CHANLIST cl;
-
-        strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
-	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
-	{
-	    cl = tvh->chanlist_s[i];
-//	    printf("count%d: name: %s, freq: %d\n",
-//		i, cl.name, cl.freq);
-	    if (!strcasecmp(cl.name, channel))
-	    {
-		tvh->channel = i;
-		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
-		    cl.name, (float)cl.freq/1000);
-		tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
-		break;
-	    }
-	}
-	return(1);
-}
-
-int tv_set_channel(tvi_handle_t *tvh, char *channel) {
-	int i, channel_int;
-
-	if (tv_channel_list) {
-		tv_channel_last = tv_channel_current;
-		channel_int = atoi(channel);
-		tv_channel_current = tv_channel_list;
-		for (i = 1; i < channel_int; i++)
-			if (tv_channel_current->next)
-				tv_channel_current = tv_channel_current->next;
-		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
-				tv_channel_current->name, (float)tv_channel_current->freq/1000);
-		tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
-	} else tv_set_channel_real(tvh, channel);
-	return(1);
-}
-
-int tv_last_channel(tvi_handle_t *tvh) {
-
-	if (tv_channel_list) {
-		tv_channels_t *tmp;
-
-		tmp = tv_channel_last;
-		tv_channel_last = tv_channel_current;
-		tv_channel_current = tmp;
-
-		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
-				tv_channel_current->name, (float)tv_channel_current->freq/1000);
-		tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
-	} else {
-		int i;
-		struct CHANLIST cl;
-
-		for (i = 0; i < chanlists[tvh->chanlist].count; i++)
-		{
-		    cl = tvh->chanlist_s[i];
-		    if (!strcasecmp(cl.name, tv_channel_last_real))
-		    {
-			strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
-			tvh->channel = i;
-			mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
-			    cl.name, (float)cl.freq/1000);
-			tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
-			break;
-		    }
-		}
-	}
-	return(1);
-}
-
-int tv_step_norm(tvi_handle_t *tvh)
-{
-  tvh->norm++;
-  if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM,
-                              &tvh->norm) != TVI_CONTROL_TRUE) {
-    tvh->norm = 0;
-    if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM,
-                                &tvh->norm) != TVI_CONTROL_TRUE) {
-      mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
-      return 0;
-    }
-  }
-    return(1);
-}
-
-int tv_step_chanlist(tvi_handle_t *tvh)
-{
-    return(1);
-}
-
-int tv_set_norm(tvi_handle_t *tvh, char* norm)
-{
-    tvh->norm = norm_from_string(tvh, norm);
-
-    mp_msg(MSGT_TV, MSGL_V, "Selected norm: %s\n", tv_param_norm);
-    if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->norm) != TVI_CONTROL_TRUE) {
-	mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
-	return 0;
-    }
-    return(1);
-}
-
-demuxer_desc_t demuxer_desc_tv = {
-  "Tv card demuxer",
-  "tv",
-  "TV",
-  "Alex Beregszaszi, Charles R. Henrich",
-  "?",
-  DEMUXER_TYPE_TV,
-  0, // no autodetect
-  NULL,
-  demux_tv_fill_buffer,
-  demux_open_tv,
-  demux_close_tv,
-  NULL,
-  NULL
-};
--- a/libmpdemux/tv.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-#ifndef TV_H
-#define TV_H
-
-extern int tv_param_on;
-
-#ifdef USE_TV
-//#include "libao2/afmt.h"
-//#include "libvo/img_format.h"
-//#include "libvo/fastmemcpy.h"
-//#include "mp_msg.h"
-
-extern char *tv_param_freq;
-extern char *tv_param_channel;
-extern char *tv_param_chanlist;
-extern char *tv_param_norm;
-#ifdef HAVE_TV_V4L2
-extern int tv_param_normid;
-#endif
-extern char *tv_param_device;
-extern char *tv_param_driver;
-extern int tv_param_width;
-extern int tv_param_height;
-extern int tv_param_input;
-extern int tv_param_outfmt;
-extern float tv_param_fps;
-extern char **tv_param_channels;
-extern int tv_param_noaudio;
-extern int tv_param_immediate;
-extern int tv_param_audiorate;
-extern int tv_param_audio_id;
-#if defined(HAVE_TV_V4L)
-extern int tv_param_amode;
-extern int tv_param_volume;
-extern int tv_param_bass;
-extern int tv_param_treble;
-extern int tv_param_balance;
-extern int tv_param_forcechan;
-extern int tv_param_force_audio;
-extern int tv_param_buffer_size;
-extern int tv_param_mjpeg;
-extern int tv_param_decimation;
-extern int tv_param_quality;
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-extern int tv_param_alsa;
-#endif
-extern char* tv_param_adevice;
-#endif
-extern int tv_param_brightness;
-extern int tv_param_contrast;
-extern int tv_param_hue;
-extern int tv_param_saturation;
-
-typedef struct tvi_info_s
-{
-    const char *name;
-    const char *short_name;
-    const char *author;
-    const char *comment;
-} tvi_info_t;
-
-typedef struct tvi_functions_s
-{
-    int (*init)();
-    int (*uninit)();
-    int (*control)();
-    int (*start)();
-    double (*grab_video_frame)();
-#ifdef HAVE_TV_BSDBT848
-    double (*grabimmediate_video_frame)();
-#endif
-    int (*get_video_framesize)();
-    double (*grab_audio_frame)();
-    int (*get_audio_framesize)();
-} tvi_functions_t;
-
-typedef struct tvi_handle_s {
-    tvi_info_t		*info;
-    tvi_functions_t	*functions;
-    void		*priv;
-    int 		seq;
-
-    /* specific */
-    int			norm;
-    int			chanlist;
-    const struct CHANLIST *chanlist_s;
-    int			channel;
-} tvi_handle_t;
-
-typedef struct tv_channels_s {
-    int index;
-    char number[5];
-    char name[20];
-    int   freq;
-    struct tv_channels_s *next;
-    struct tv_channels_s *prev;
-} tv_channels_t;
-
-extern tv_channels_t *tv_channel_list;
-extern tv_channels_t *tv_channel_current, *tv_channel_last;
-extern char *tv_channel_last_real;
-
-#define TVI_CONTROL_FALSE		0
-#define TVI_CONTROL_TRUE		1
-#define TVI_CONTROL_NA			-1
-#define TVI_CONTROL_UNKNOWN		-2
-
-/* ======================== CONTROLS =========================== */
-
-/* GENERIC controls */
-#define TVI_CONTROL_IS_AUDIO		0x1
-#define TVI_CONTROL_IS_VIDEO		0x2
-#define TVI_CONTROL_IS_TUNER		0x3
-#define TVI_CONTROL_IMMEDIATE           0x4
-
-/* VIDEO controls */
-#define TVI_CONTROL_VID_GET_FPS		0x101
-#define TVI_CONTROL_VID_GET_PLANES	0x102
-#define TVI_CONTROL_VID_GET_BITS	0x103
-#define TVI_CONTROL_VID_CHK_BITS	0x104
-#define TVI_CONTROL_VID_SET_BITS	0x105
-#define TVI_CONTROL_VID_GET_FORMAT	0x106
-#define TVI_CONTROL_VID_CHK_FORMAT	0x107
-#define TVI_CONTROL_VID_SET_FORMAT	0x108
-#define TVI_CONTROL_VID_GET_WIDTH	0x109
-#define TVI_CONTROL_VID_CHK_WIDTH	0x110
-#define TVI_CONTROL_VID_SET_WIDTH	0x111
-#define TVI_CONTROL_VID_GET_HEIGHT	0x112
-#define TVI_CONTROL_VID_CHK_HEIGHT	0x113
-#define TVI_CONTROL_VID_SET_HEIGHT	0x114
-#define TVI_CONTROL_VID_GET_BRIGHTNESS	0x115
-#define TVI_CONTROL_VID_SET_BRIGHTNESS	0x116
-#define TVI_CONTROL_VID_GET_HUE		0x117
-#define TVI_CONTROL_VID_SET_HUE		0x118
-#define TVI_CONTROL_VID_GET_SATURATION	0x119
-#define TVI_CONTROL_VID_SET_SATURATION	0x11a
-#define TVI_CONTROL_VID_GET_CONTRAST	0x11b
-#define TVI_CONTROL_VID_SET_CONTRAST	0x11c
-#define TVI_CONTROL_VID_GET_PICTURE	0x11d
-#define TVI_CONTROL_VID_SET_PICTURE	0x11e
-
-/* TUNER controls */
-#define TVI_CONTROL_TUN_GET_FREQ	0x201
-#define TVI_CONTROL_TUN_SET_FREQ	0x202
-#define TVI_CONTROL_TUN_GET_TUNER	0x203	/* update priv->tuner struct for used input */
-#define TVI_CONTROL_TUN_SET_TUNER	0x204	/* update priv->tuner struct for used input */
-#define TVI_CONTROL_TUN_GET_NORM	0x205
-#define TVI_CONTROL_TUN_SET_NORM	0x206
-
-/* AUDIO controls */
-#define TVI_CONTROL_AUD_GET_FORMAT	0x301
-#define TVI_CONTROL_AUD_GET_SAMPLERATE	0x302
-#define TVI_CONTROL_AUD_GET_SAMPLESIZE	0x303
-#define TVI_CONTROL_AUD_GET_CHANNELS	0x304
-#define TVI_CONTROL_AUD_SET_SAMPLERATE	0x305
-
-/* SPECIFIC controls */
-#define TVI_CONTROL_SPC_GET_INPUT	0x401	/* set input channel (tv,s-video,composite..) */
-#define TVI_CONTROL_SPC_SET_INPUT	0x402	/* set input channel (tv,s-video,composite..) */
-#define TVI_CONTROL_SPC_GET_NORMID	0x403	/* get normid from norm name */
-
-extern tvi_handle_t *tv_begin(void);
-extern int tv_init(tvi_handle_t *tvh);
-extern int tv_uninit(tvi_handle_t *tvh);
-
-int tv_set_color_options(tvi_handle_t *tvh, int opt, int val);
-int tv_get_color_options(tvi_handle_t *tvh, int opt, int* val);
-#define TV_COLOR_BRIGHTNESS	1
-#define TV_COLOR_HUE		2
-#define TV_COLOR_SATURATION	3
-#define TV_COLOR_CONTRAST	4
-
-int tv_step_channel_real(tvi_handle_t *tvh, int direction);
-int tv_step_channel(tvi_handle_t *tvh, int direction);
-#define TV_CHANNEL_LOWER	1
-#define TV_CHANNEL_HIGHER	2
-
-int tv_last_channel(tvi_handle_t *tvh);
-
-int tv_set_channel_real(tvi_handle_t *tvh, char *channel);
-int tv_set_channel(tvi_handle_t *tvh, char *channel);
-
-int tv_step_norm(tvi_handle_t *tvh);
-int tv_step_chanlist(tvi_handle_t *tvh);
-
-int tv_set_freq(tvi_handle_t *tvh, unsigned long freq);
-int tv_get_freq(tvi_handle_t *tvh, unsigned long *freq);
-
-int tv_set_norm(tvi_handle_t *tvh, char* norm);
-
-#define TV_NORM_PAL		1
-#define TV_NORM_NTSC		2
-#define TV_NORM_SECAM		3
-#define TV_NORM_PALNC		4
-#define TV_NORM_PALM		5
-#define TV_NORM_PALN		6
-#define TV_NORM_NTSCJP		7
-
-#endif /* USE_TV */
-
-#endif /* TV_H */
--- a/libmpdemux/tvi_bsdbt848.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,846 +0,0 @@
-/*
-    (C)2002 Charles R. Henrich (henrich@msu.edu)
-    *BSD (hopefully, requires working driver!) BrookTree capture support.
-
-    Still in (active) development!
-
-	v1.1	Mar 13 2002   Fully functional, need to move ring buffer to
-						  the kernel driver. 
-    v1.0    Feb 19 2002   First Release, need to add support for changing
-                            audio parameters.
-*/
-
-#include "config.h"
-
-#define RINGSIZE 8
-#define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */
-
-#define TRUE  (1==1)
-#define FALSE (1==0)
-
-#define PAL_WIDTH  768
-#define PAL_HEIGHT 576
-#define PAL_FPS    25
-
-#define NTSC_WIDTH  640
-#define NTSC_HEIGHT 480
-#define NTSC_FPS    29.97
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/filio.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <string.h>
-
-#include <sys/param.h>
-#ifdef __NetBSD__
-#include <dev/ic/bt8xx.h>
-#include <sys/audioio.h>
-#elif defined(__DragonFly__)
-#include <dev/video/meteor/ioctl_meteor.h>
-#include <dev/video/bktr/ioctl_bt848.h>
-#elif __FreeBSD_version >= 502100
-#include <dev/bktr/ioctl_meteor.h>
-#include <dev/bktr/ioctl_bt848.h>
-#else
-#include <machine/ioctl_meteor.h>
-#include <machine/ioctl_bt848.h>
-#endif
-
-#ifdef HAVE_SYS_SOUNDCARD_H
-#include <sys/soundcard.h>
-#else
-#ifdef HAVE_SOUNDCARD_H
-#include <soundcard.h>
-#else
-#include <machine/soundcard.h>
-#endif
-#endif
-
-#include "libaf/af_format.h"
-#include "libvo/img_format.h"
-#include "tv.h"
-
-/* information about this file */
-static tvi_info_t info = {
-    "Brooktree848 Support",
-    "bsdbt848",
-    "Charles Henrich",
-    "in development"
-};
-
-typedef struct {
-    int dirty;
-    double timestamp;
-    char *buf;
-} RBFRAME;
-
-/* private data's */
-typedef struct {
-
-/* Audio */
-    char *dspdev;
-    int dspready;
-    int dspfd;
-    int dspsamplesize;
-    int dspstereo;
-    int dspspeed;
-    int dspfmt;
-    int dspframesize;
-    int dsprate;
-    long long dspbytesread;
-
-/* Video */
-    char *btdev;
-    int videoready;
-    int btfd;
-    int source;
-    float maxfps;
-    float fps;
-    int iformat;
-    int maxheight;
-    int maxwidth;
-    struct meteor_geomet geom;
-    struct meteor_capframe capframe;
-
-/* Frame Buffer */
-
-    int framebufsize;
-    float timestamp;
-    int curpaintframe;
-    int curbufframe;
-    unsigned char *livebuf;
-    RBFRAME framebuf[RINGSIZE];
-
-/* Inputs */
-
-    int input;
-
-/* Tuner */
-
-    char *tunerdev;
-    int tunerfd;
-    int tunerready;
-    u_long tunerfreq;
-    struct bktr_chnlset cset;
-
-/* Other */
-
-    int immediatemode;
-    double starttime;
-
-} priv_t;
-
-#include "tvi_def.h"
-
-static priv_t *G_private=NULL;
-
-static int getinput(int innumber);
-
-static void processframe(int signal)
-{
-struct timeval curtime;
-
-if(G_private->immediatemode == TRUE) return;
-
-gettimeofday(&curtime, NULL);
-
-if(G_private->framebuf[G_private->curpaintframe].dirty == TRUE)
-    {
-    memcpy(G_private->framebuf[G_private->curpaintframe].buf, 
-            G_private->livebuf, G_private->framebufsize);
-
-    G_private->framebuf[G_private->curpaintframe].dirty = FALSE;
-
-    G_private->framebuf[G_private->curpaintframe].timestamp = 
-            curtime.tv_sec + curtime.tv_usec*.000001;
-
-    G_private->curpaintframe++;
-
-    if(G_private->curpaintframe >= RINGSIZE) G_private->curpaintframe = 0;
-    }
-
-return;
-}
-
-/* handler creator - entry point ! */
-tvi_handle_t *tvi_init_bsdbt848(char *device)
-{
-    return(new_handle());
-}
-
-static int control(priv_t *priv, int cmd, void *arg)
-{
-    switch(cmd)
-    {
-
-/* Tuner Controls */
-
-    case TVI_CONTROL_IS_TUNER:
-        if(priv->tunerready == FALSE) return TVI_CONTROL_FALSE;
-        return(TVI_CONTROL_TRUE);
-
-    case TVI_CONTROL_TUN_GET_FREQ:
-        {
-        if(ioctl(priv->tunerfd, TVTUNER_GETFREQ, &priv->tunerfreq) < 0)
-            {
-            perror("GETFREQ:ioctl");
-            return(TVI_CONTROL_FALSE);
-            }
-
-        (int)*(void **)arg = priv->tunerfreq;
-        return(TVI_CONTROL_TRUE);
-        }
-    
-    case TVI_CONTROL_TUN_SET_FREQ:
-        {
-        priv->tunerfreq = (int)*(void **)arg;
-
-        if(ioctl(priv->tunerfd, TVTUNER_SETFREQ, &priv->tunerfreq) < 0) 
-            {
-            perror("SETFREQ:ioctl");
-            return(0);
-            }
-
-        return(TVI_CONTROL_TRUE);        
-        }
-
-    case TVI_CONTROL_TUN_GET_TUNER:
-    case TVI_CONTROL_TUN_SET_TUNER:
-
-/* Inputs */
-
-    case TVI_CONTROL_SPC_GET_INPUT:
-        {
-        if(ioctl(priv->btfd, METEORGINPUT, &priv->input) < 0)
-            {
-            perror("GINPUT:ioctl");
-            return(TVI_CONTROL_FALSE);
-            }
-
-        (int)*(void **)arg = priv->input;
-        return(TVI_CONTROL_TRUE);
-        }
-    
-    case TVI_CONTROL_SPC_SET_INPUT:
-        {
-        priv->input = getinput((int)*(void **)arg);
-
-        if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0) 
-            {
-            perror("tunerfreq:ioctl");
-            return(0);
-            }
-
-        return(TVI_CONTROL_TRUE);        
-        }
-
-/* Audio Controls */
-
-    case TVI_CONTROL_IS_AUDIO:
-        if(priv->dspready == FALSE) return TVI_CONTROL_FALSE;
-        return(TVI_CONTROL_TRUE);
-
-    case TVI_CONTROL_AUD_GET_FORMAT:
-        {
-        (int)*(void **)arg = AF_FORMAT_S16_LE;
-        return(TVI_CONTROL_TRUE);
-        }
-    case TVI_CONTROL_AUD_GET_CHANNELS:
-        {
-        (int)*(void **)arg = 2;
-        return(TVI_CONTROL_TRUE);
-        }
-    case TVI_CONTROL_AUD_SET_SAMPLERATE:
-        {
-        int dspspeed = (int)*(void **)arg;
-
-           if(ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &dspspeed) == -1) 
-            {
-            perror("invalidaudiorate");
-            return(TVI_CONTROL_FALSE);
-            }
-
-        priv->dspspeed = dspspeed;
-
-        priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
-                                priv->fps * (priv->dspstereo+1);
-        priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*
-                                (priv->dspstereo+1);
-
-        return(TVI_CONTROL_TRUE);
-        }
-    case TVI_CONTROL_AUD_GET_SAMPLERATE:
-        {
-        (int)*(void **)arg = priv->dspspeed;
-        return(TVI_CONTROL_TRUE);
-        }
-    case TVI_CONTROL_AUD_GET_SAMPLESIZE:
-        {
-        (int)*(void **)arg = priv->dspsamplesize/8;
-        return(TVI_CONTROL_TRUE);
-        }
-
-/* Video Controls */
-
-    case TVI_CONTROL_IS_VIDEO:
-        if(priv->videoready == FALSE) return TVI_CONTROL_FALSE;
-        return(TVI_CONTROL_TRUE);
-
-    case TVI_CONTROL_TUN_SET_NORM:
-        {
-        int req_mode = (int)*(void **)arg;
-	u_short tmp_fps;
-
-        priv->iformat = METEOR_FMT_AUTOMODE;
-
-        if(req_mode == TV_NORM_PAL) 
-            {
-            priv->iformat = METEOR_FMT_PAL;
-            priv->maxheight = PAL_HEIGHT;
-            priv->maxwidth = PAL_WIDTH;
-            priv->maxfps = PAL_FPS;
-            priv->fps = PAL_FPS;
-
-            if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
-
-            if(priv->geom.rows > priv->maxheight) 
-                {
-                priv->geom.rows = priv->maxheight;
-                }
-
-            if(priv->geom.columns > priv->maxwidth) 
-                {
-                priv->geom.columns = priv->maxwidth;
-                }
-            }
-
-        if(req_mode == TV_NORM_NTSC) 
-            {
-            priv->iformat = METEOR_FMT_NTSC;
-            priv->maxheight = NTSC_HEIGHT;
-            priv->maxwidth = NTSC_WIDTH;
-            priv->maxfps = NTSC_FPS;
-            priv->fps = NTSC_FPS;
-
-            priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
-                                 priv->fps * (priv->dspstereo+1);
-            priv->dsprate = priv->dspspeed * priv->dspsamplesize/8 *
-                                (priv->dspstereo+1);
-
-            if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
-
-            if(priv->geom.rows > priv->maxheight) 
-                {
-                priv->geom.rows = priv->maxheight;
-                }
-
-            if(priv->geom.columns > priv->maxwidth) 
-                {
-                priv->geom.columns = priv->maxwidth;
-                }
-            }
-
-        if(req_mode == TV_NORM_SECAM) priv->iformat = METEOR_FMT_SECAM;
-
-        if(ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) 
-            {
-            perror("format:ioctl");
-            return(TVI_CONTROL_FALSE);
-            }
-    
-        if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
-            {
-            perror("geo:ioctl");
-            return(0);
-            }
-
-	tmp_fps = priv->fps;
-        if(ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0) 
-            {
-            perror("fps:ioctl");
-            return(0);
-            }
-
-#ifdef BT848_SAUDIO
-	if(priv->tunerready == TRUE &&
-	    ioctl(priv->tunerfd, BT848_SAUDIO, &tv_param_audio_id) < 0)
-	    {
-	    perror("audioid:ioctl");
-	    }
-#endif
-
-        return(TVI_CONTROL_TRUE);
-        }
-    
-    case TVI_CONTROL_VID_GET_FORMAT:
-        (int)*(void **)arg = IMGFMT_UYVY;
-        return(TVI_CONTROL_TRUE);
-
-    case TVI_CONTROL_VID_SET_FORMAT:
-        {
-        int req_fmt = (int)*(void **)arg;
-
-        if(req_fmt != IMGFMT_UYVY) return(TVI_CONTROL_FALSE);
-
-        return(TVI_CONTROL_TRUE);
-        }
-    case TVI_CONTROL_VID_SET_WIDTH:
-        priv->geom.columns = (int)*(void **)arg;
-
-        if(priv->geom.columns > priv->maxwidth) 
-            {
-            priv->geom.columns = priv->maxwidth;
-            }
-
-        if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
-            {
-            perror("width:ioctl");
-            return(0);
-            }
-
-        return(TVI_CONTROL_TRUE);
-
-    case TVI_CONTROL_VID_GET_WIDTH:
-        (int)*(void **)arg = priv->geom.columns;
-        return(TVI_CONTROL_TRUE);
-
-    case TVI_CONTROL_VID_SET_HEIGHT:
-        priv->geom.rows = (int)*(void **)arg;
-
-        if(priv->geom.rows > priv->maxheight) 
-            {
-            priv->geom.rows = priv->maxheight;
-            }
-
-        if(priv->geom.rows <= priv->maxheight / 2)
-            {
-            priv->geom.oformat |= METEOR_GEO_EVEN_ONLY;
-            }  
-
-        if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
-            {
-            perror("height:ioctl");
-            return(0);
-            }
-
-        return(TVI_CONTROL_TRUE);        
-
-    case TVI_CONTROL_VID_GET_HEIGHT:
-        (int)*(void **)arg = priv->geom.rows;
-        return(TVI_CONTROL_TRUE);        
-
-    case TVI_CONTROL_VID_GET_FPS:
-        *(float *)arg = priv->fps;
-        return(TVI_CONTROL_TRUE);        
-
-/*
-    case TVI_CONTROL_VID_SET_FPS:
-        priv->fps = (int)*(void **)arg;
-
-        if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
-
-        if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) 
-            {
-            perror("fps:ioctl");
-            return(0);
-            }
-
-        return(TVI_CONTROL_TRUE);        
-*/
-
-    case TVI_CONTROL_VID_CHK_WIDTH:
-    case TVI_CONTROL_VID_CHK_HEIGHT:
-        return(TVI_CONTROL_TRUE);
-
-    case TVI_CONTROL_IMMEDIATE:
-        priv->immediatemode = TRUE;
-        return(TVI_CONTROL_TRUE);
-    }
-
-    return(TVI_CONTROL_UNKNOWN);
-}
-
-static int init(priv_t *priv)
-{
-int marg;
-int count;
-u_short tmp_fps;
-
-G_private = priv; /* Oooh, sick */
-
-/* Video Configuration */
-
-priv->videoready = TRUE;
-priv->btdev = strdup("/dev/bktr0");
-priv->immediatemode = FALSE;
-priv->iformat = METEOR_FMT_PAL;
-priv->maxheight = PAL_HEIGHT;
-priv->maxwidth = PAL_WIDTH;
-priv->maxfps = PAL_FPS;
-priv->source = METEOR_INPUT_DEV0;
-priv->fps = priv->maxfps;
-
-priv->starttime=0;
-priv->curpaintframe=0;
-priv->curbufframe=0;
-
-priv->geom.columns = priv->maxwidth;
-priv->geom.rows = priv->maxheight;
-priv->geom.frames = 1;
-priv->geom.oformat = METEOR_GEO_YUV_PACKED;
-
-priv->btfd = open(priv->btdev, O_RDONLY);
-
-if(priv->btfd < 0)
-    {
-    perror("bktr open");
-    priv->videoready = FALSE;
-    }
-
-if(priv->videoready == TRUE && 
-   ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) 
-    {
-    perror("FMT:ioctl");
-    }
-
-if(priv->videoready == TRUE &&
-   ioctl(priv->btfd, METEORSINPUT, &priv->source) < 0) 
-    {
-    perror("SINPUT:ioctl");
-    }
-
-tmp_fps = priv->fps;
-if(priv->videoready == TRUE &&
-   ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0) 
-    {
-    perror("SFPS:ioctl");
-    }
-
-if(priv->videoready == TRUE &&
-   ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
-    {
-    perror("SGEO:ioctl");
-    }
-
-if(priv->videoready == TRUE)
-    {
-    priv->framebufsize = (priv->geom.columns * priv->geom.rows * 2);
-
-    priv->livebuf = (u_char *)mmap((caddr_t)0, priv->framebufsize, PROT_READ,
-                                MAP_SHARED, priv->btfd, (off_t)0);
-
-    if(priv->livebuf == (u_char *) MAP_FAILED)
-        {
-        perror("mmap");
-        priv->videoready = FALSE;
-        }
-
-    for(count=0;count<RINGSIZE;count++)
-        {
-        priv->framebuf[count].buf = malloc(priv->framebufsize);
-
-        if(priv->framebuf[count].buf == NULL)
-            {
-            perror("framebufmalloc");
-            priv->videoready = FALSE;
-            break;
-            }
-
-        priv->framebuf[count].dirty = TRUE;
-        priv->framebuf[count].timestamp = 0;
-        }
-    }
-
-/* Tuner Configuration */
-
-priv->tunerdev = strdup("/dev/tuner0");
-priv->tunerready = TRUE;
-
-priv->tunerfd = open(priv->tunerdev, O_RDONLY);
-
-if(priv->tunerfd < 0)
-    {
-    perror("tune open");
-    priv->tunerready = FALSE;
-    }
-
-/* Audio Configuration */
-
-priv->dspready = TRUE;
-#ifdef __NetBSD__
-priv->dspdev = strdup("/dev/sound");
-#else
-priv->dspdev = strdup("/dev/dsp");
-#endif
-priv->dspsamplesize = 16;
-priv->dspstereo = 1;
-priv->dspspeed = 44100;
-priv->dspfmt = AFMT_S16_LE;
-priv->dspbytesread = 0;
-priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*(priv->dspstereo+1);
-priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/priv->fps * 
-                     (priv->dspstereo+1);
-
-if((priv->dspfd = open (priv->dspdev, O_RDONLY, 0)) < 0)
-    {
-    perror("dsp open");
-    priv->dspready = FALSE;
-    } 
-
-marg = (256 << 16) | 12;
-
-if (ioctl(priv->dspfd, SNDCTL_DSP_SETFRAGMENT, &marg ) < 0 ) 
-    {
-    perror("setfrag");
-    priv->dspready = FALSE;
-    }
-
-if((priv->dspready == TRUE) &&
-   ((ioctl(priv->dspfd, SNDCTL_DSP_SAMPLESIZE, &priv->dspsamplesize) == -1) ||
-   (ioctl(priv->dspfd, SNDCTL_DSP_STEREO, &priv->dspstereo) == -1) ||
-   (ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &priv->dspspeed) == -1) ||
-   (ioctl(priv->dspfd, SNDCTL_DSP_SETFMT, &priv->dspfmt) == -1)))
-    {
-    perror ("configuration of dsp failed");
-    close(priv->dspfd);
-    priv->dspready = FALSE;
-    }
-
-return(1);
-}
-
-/* that's the real start, we'got the format parameters (checked with control) */
-static int start(priv_t *priv)
-{
-int tmp;
-struct timeval curtime;
-int marg;
-
-fprintf(stderr,"START\n");
-if(priv->videoready == FALSE) return(0);
-
-signal(SIGUSR1, processframe);
-signal(SIGALRM, processframe);
-
-marg = SIGUSR1;
-
-if(ioctl(priv->btfd, METEORSSIGNAL, &marg) < 0) 
-    {
-    perror("METEORSSIGNAL failed");
-    return(0);
-    }
-
-read(priv->dspfd, &tmp, 2);
-
-gettimeofday(&curtime, NULL);
-
-priv->starttime = curtime.tv_sec + (curtime.tv_usec *.000001);
-
-marg = METEOR_CAP_CONTINOUS;
-
-if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0) 
-    {
-    perror("METEORCAPTUR failed");
-    return(0);
-    }
-
-return(1);
-}
-
-static int uninit(priv_t *priv)
-{
-int marg;
-
-if(priv->videoready == FALSE) return(0);
-
-marg = METEOR_SIG_MODE_MASK;
-
-if(ioctl( priv->btfd, METEORSSIGNAL, &marg) < 0 ) 
-    {
-    perror("METEORSSIGNAL");
-    return(0);
-    }
-
-marg = METEOR_CAP_STOP_CONT;
-
-if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0 ) 
-    {
-    perror("METEORCAPTUR STOP");
-    return(0);
-    }
-
-close(priv->btfd);
-close(priv->dspfd);
-
-priv->dspfd = -1;
-priv->btfd = -1;
-
-priv->dspready = priv->videoready = FALSE;
-
-return(1);
-}
-
-
-static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
-{
-struct timeval curtime;
-sigset_t sa_mask;
-
-if(priv->videoready == FALSE) return(0);
-
-alarm(1);
-sigfillset(&sa_mask);
-sigdelset(&sa_mask,SIGINT);
-sigdelset(&sa_mask,SIGUSR1);
-sigdelset(&sa_mask,SIGALRM);
-sigsuspend(&sa_mask);
-alarm(0);
-
-memcpy(buffer, priv->livebuf, len);
-
-/* PTS = 0, show the frame NOW, this routine is only used in playback mode
-    without audio capture .. */
-
-return(0); 
-}
-
-static double grab_video_frame(priv_t *priv, char *buffer, int len)
-{
-struct timeval curtime;
-double timestamp=0;
-sigset_t sa_mask;
-
-if(priv->videoready == FALSE) return(0);
-
-if(priv->immediatemode == TRUE) 
-    {
-    return grabimmediate_video_frame(priv, buffer, len);
-    }
-
-while(priv->framebuf[priv->curbufframe].dirty == TRUE)
-    {
-    alarm(1);
-    sigemptyset(&sa_mask);
-    sigsuspend(&sa_mask);
-    alarm(0);
-    }
-
-memcpy(buffer, priv->framebuf[priv->curbufframe].buf, len);
-timestamp = priv->framebuf[priv->curbufframe].timestamp;
-priv->framebuf[priv->curbufframe].dirty = TRUE;
-
-priv->curbufframe++;
-if(priv->curbufframe >= RINGSIZE) priv->curbufframe = 0;
-
-return(timestamp-priv->starttime);
-}
-
-static int get_video_framesize(priv_t *priv)
-{
-return(priv->geom.columns*priv->geom.rows*16/8);
-}
-
-static double grab_audio_frame(priv_t *priv, char *buffer, int len)
-{
-struct timeval curtime;
-double curpts;
-double timeskew;
-int bytesavail;
-int bytesread;
-int ret;
-
-if(priv->dspready == FALSE) return 0;
-
-gettimeofday(&curtime, NULL);
-
-/* Get exactly one frame of audio, which forces video sync to audio.. */
-
-bytesread=read(priv->dspfd, buffer, len); 
-
-while(bytesread < len)
-    {
-    ret=read(priv->dspfd, &buffer[bytesread], len-bytesread);
-
-    if(ret == -1)
-        {
-        perror("Audio read failed!");
-        return 0;
-        }
-
-    bytesread+=ret;
-    }
-
-priv->dspbytesread += bytesread;
-
-curpts = curtime.tv_sec + curtime.tv_usec * .000001;
-
-timeskew = priv->dspbytesread * 1.0 / priv->dsprate - (curpts-priv->starttime);
-
-if(timeskew > .125/priv->fps) 
-    {
-    priv->starttime -= timeskew;
-    }
-else
-    {
-    if(timeskew < -.125/priv->fps) 
-        {
-        priv->starttime -= timeskew;
-        }
-    }
-
-return(priv->dspbytesread * 1.0 / priv->dsprate);
-}
-
-static int get_audio_framesize(priv_t *priv)
-{
-int bytesavail;
-#ifdef __NetBSD__
-struct audio_info auinf;
-#endif
-
-if(priv->dspready == FALSE) return 0;
-
-#ifdef __NetBSD__
-if(ioctl(priv->dspfd, AUDIO_GETINFO, &auinf) < 0) 
-    {
-    perror("AUDIO_GETINFO");
-    return(TVI_CONTROL_FALSE);
-    }
-else
-    bytesavail = auinf.record.seek; /* *priv->dspsamplesize; */
-#else
-if(ioctl(priv->dspfd, FIONREAD, &bytesavail) < 0) 
-    {
-    perror("FIONREAD");
-    return(TVI_CONTROL_FALSE);
-    }
-#endif
-
-/* When mencoder wants audio data, it wants data..
-   it won't go do anything else until it gets it :( */
-
-if(bytesavail == 0) return FRAGSIZE;
-
-return(bytesavail);
-}
-
-static int getinput(int innumber)
-{
-switch(innumber)
-    {
-    case 0: return METEOR_INPUT_DEV0;     /* RCA   */
-    case 1: return METEOR_INPUT_DEV1;     /* Tuner */
-    case 2: return METEOR_INPUT_DEV2;     /* In 1  */
-    case 3: return METEOR_INPUT_DEV3;     /* In 2  */
-    case 4: return METEOR_INPUT_DEV_RGB;     /* RGB   */
-    case 5: return METEOR_INPUT_DEV_SVIDEO; /* SVid  */
-    }
-
-return 0;
-}
--- a/libmpdemux/tvi_def.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-#include <stdlib.h> /* malloc */
-#include <string.h> /* memset */
-
-static int init(priv_t *priv);
-static int uninit(priv_t *priv);
-static int control(priv_t *priv, int cmd, void *arg);
-static int start(priv_t *priv);
-static double grab_video_frame(priv_t *priv, char *buffer, int len);
-#ifdef HAVE_TV_BSDBT848
-static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len);
-#endif
-static int get_video_framesize(priv_t *priv);
-static double grab_audio_frame(priv_t *priv, char *buffer, int len);
-static int get_audio_framesize(priv_t *priv);
-
-static tvi_functions_t functions =
-{
-    init,
-    uninit,
-    control,
-    start,
-    grab_video_frame,
-#ifdef HAVE_TV_BSDBT848
-    grabimmediate_video_frame,
-#endif
-    get_video_framesize,
-    grab_audio_frame,
-    get_audio_framesize
-};
-
-static tvi_handle_t *new_handle(void)
-{
-    tvi_handle_t *h = (tvi_handle_t *)malloc(sizeof(tvi_handle_t));
-
-    if (!h)
-	return(NULL);
-    h->priv = (priv_t *)malloc(sizeof(priv_t));
-    if (!h->priv)
-    {
-	free(h);
-	return(NULL);
-    }
-    memset(h->priv, 0, sizeof(priv_t));
-    h->info = &info;
-    h->functions = &functions;
-    h->seq = 0;
-    h->chanlist = -1;
-    h->chanlist_s = NULL;
-    h->norm = -1;
-    h->channel = -1;
-    return(h);
-}
-
-static void free_handle(tvi_handle_t *h)
-{
-    if (h) {
-	if (h->priv)
-	    free(h->priv);
-	free(h);
-    }
-}
--- a/libmpdemux/tvi_dummy.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
-    Only a sample!
-*/
-
-#include "config.h"
-
-#include <stdio.h>
-#include "libvo/img_format.h"
-#include "tv.h"
-
-/* information about this file */
-static tvi_info_t info = {
-	"NULL-TV",
-	"dummy",
-	"alex",
-	NULL
-};
-
-/* private data's */
-typedef struct {
-    int width;
-    int height;
-} priv_t;
-
-#include "tvi_def.h"
-
-/* handler creator - entry point ! */
-tvi_handle_t *tvi_init_dummy(char *device)
-{
-    return(new_handle());
-}
-
-/* initialisation */
-static int init(priv_t *priv)
-{
-    priv->width = 320;
-    priv->height = 200;
-    return(1);
-}
-
-/* that's the real start, we'got the format parameters (checked with control) */
-static int start(priv_t *priv)
-{
-    return(1);
-}
-
-static int uninit(priv_t *priv)
-{
-    return(1);
-}
-
-static int control(priv_t *priv, int cmd, void *arg)
-{
-    switch(cmd)
-    {
-	case TVI_CONTROL_IS_VIDEO:
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_GET_FORMAT:
-//	    *(int *)arg = IMGFMT_YV12;
-	    *(int *)arg = IMGFMT_YV12;
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_SET_FORMAT:
-	{
-//	    int req_fmt = *(int *)arg;
-	    int req_fmt = *(int *)arg;
-	    if (req_fmt != IMGFMT_YV12)
-		return(TVI_CONTROL_FALSE);
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_VID_SET_WIDTH:
-	    priv->width = *(int *)arg;
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_GET_WIDTH:
-	    *(int *)arg = priv->width;
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_SET_HEIGHT:
-	    priv->height = *(int *)arg;
-	    return(TVI_CONTROL_TRUE);	    
-	case TVI_CONTROL_VID_GET_HEIGHT:
-	    *(int *)arg = priv->height;
-	    return(TVI_CONTROL_TRUE);	    
-	case TVI_CONTROL_VID_CHK_WIDTH:
-	case TVI_CONTROL_VID_CHK_HEIGHT:
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_TUN_SET_NORM:
-	    return(TVI_CONTROL_TRUE);
-    }
-    return(TVI_CONTROL_UNKNOWN);
-}
-
-#ifdef HAVE_TV_BSDBT848
-static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
-{
-    memset(buffer, 0xCC, len);
-    return(1);
-}
-#endif
-
-static double grab_video_frame(priv_t *priv, char *buffer, int len)
-{
-    memset(buffer, 0x42, len);
-    return(1);
-}
-
-static int get_video_framesize(priv_t *priv)
-{
-    /* YV12 */
-    return(priv->width*priv->height*12/8);
-}
-
-static double grab_audio_frame(priv_t *priv, char *buffer, int len)
-{
-    memset(buffer, 0x42, len);
-    return(1);
-}
-
-static int get_audio_framesize(priv_t *priv)
-{
-    return(1);
-}
--- a/libmpdemux/tvi_v4l.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1759 +0,0 @@
-/*
-  Video 4 Linux input
-
-  (C) Alex Beregszaszi
-  
-  Some ideas are based on xawtv/libng's grab-v4l.c written by
-    Gerd Knorr <kraxel@bytesex.org>
-
-  Multithreading, a/v sync and native ALSA support by
-    Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
-
-  Mjpeg hardware encoding support by 
-    Iván Szántó <szivan@freemail.hu>
-
-  CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!
-*/
-
-#include "config.h"
-
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/time.h>
-
-/* Necessary to prevent collisions between <linux/time.h> and <sys/time.h> when V4L2 is installed. */
-#define _LINUX_TIME_H
-
-#include <linux/videodev.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#ifdef HAVE_SYS_SYSINFO_H
-#include <sys/sysinfo.h>
-#endif
-
-#include "mp_msg.h"
-#include "libaf/af_format.h"
-#include "libvo/img_format.h"
-#include "libvo/fastmemcpy.h"
-#include "libvo/videodev_mjpeg.h"
-
-#include "tv.h"
-
-#include "audio_in.h"
-
-static tvi_info_t info = {
-	"Video 4 Linux input",
-	"v4l",
-	"Alex Beregszaszi",
-	"under development"
-};
-
-#define PAL_WIDTH  768
-#define PAL_HEIGHT 576
-#define PAL_FPS    25
-
-#define NTSC_WIDTH  640
-#define NTSC_HEIGHT 480
-#define NTSC_FPS    (30000.0/1001.0)
-
-#define MAX_AUDIO_CHANNELS	10
-
-#define VID_BUF_SIZE_IMMEDIATE 2
-#define VIDEO_AVG_BUFFER_SIZE 600
-
-typedef struct {
-    /* general */
-    char			*video_device;
-    int                         video_fd;
-    struct video_capability	capability;
-    struct video_channel	*channels;
-    int				act_channel;
-    struct video_tuner		tuner;
-
-    /* video */
-    struct video_picture	picture;
-    int				format;		/* output format */
-    int				width;
-    int				height;
-    int				bytesperline;
-    float			fps;
-
-    struct video_mbuf		mbuf;
-    unsigned char               *mmap;
-    struct video_mmap		*buf;
-    int				nbuf;
-
-    /* audio */
-    char			*audio_device;
-    audio_in_t                  audio_in;
-
-    int				audio_id;
-    struct video_audio		audio[MAX_AUDIO_CHANNELS];
-    int				audio_channels[MAX_AUDIO_CHANNELS];
-
-    /* buffering stuff */
-    int                         immediate_mode;
-
-    int                         audio_buffer_size;
-    int                         aud_skew_cnt;
-    unsigned char		*audio_ringbuffer;
-    long long			*audio_skew_buffer;
-    volatile int		audio_head;
-    volatile int		audio_tail;
-    volatile int		audio_cnt;
-    volatile long long          audio_skew;
-    volatile double             audio_skew_factor;
-    volatile long long          audio_skew_measure_time;
-    volatile int                audio_drop;
-
-    int                         first;
-    int                         video_buffer_size_max;
-    volatile int                video_buffer_size_current;
-    unsigned char		**video_ringbuffer;
-    long long                   *video_timebuffer;
-    long long                   *video_avg_buffer;
-    int		                video_avg_ptr;
-    int		                video_interval_sum;
-    volatile int		video_head;
-    volatile int		video_tail;
-    volatile int		video_cnt;
-
-    volatile int                shutdown;
-
-    pthread_t			audio_grabber_thread;
-    pthread_t			video_grabber_thread;
-    pthread_mutex_t             audio_starter;
-    pthread_mutex_t             skew_mutex;
-    pthread_mutex_t             video_buffer_mutex;
-
-    long long                   starttime;
-    double                      audio_secs_per_block;
-    long long                   audio_skew_total;
-    long			audio_recv_blocks_total;
-    long			audio_sent_blocks_total;
-    long                        mjpeg_bufsize;
-    
-} priv_t;
-
-#include "tvi_def.h"
-
-static const char *device_cap2name[] = {
-    "capture", "tuner", "teletext", "overlay", "chromakey", "clipping",
-    "frameram", "scales", "monochrome", "subcapture", "mpeg-decoder",
-    "mpeg-encoder", "mjpeg-decoder", "mjpeg-encoder", NULL
-};
-
-static const char *device_palette2name[] = {
-    "-", "grey", "hi240", "rgb16", "rgb24", "rgb32", "rgb15", "yuv422",
-    "yuyv", "uyvy", "yuv420", "yuv411", "raw", "yuv422p", "yuv411p",
-    "yuv420p", "yuv410p"
-};
-#define PALETTE(x) ((x < sizeof(device_palette2name)/sizeof(char*)) ? device_palette2name[x] : "UNKNOWN")
-
-static const char *norm2name(int mode)
-{
-    switch (mode) {
-    case VIDEO_MODE_PAL:
-	return "pal";
-    case VIDEO_MODE_SECAM:
-	return "secam";
-    case VIDEO_MODE_NTSC:
-	return "ntsc";
-    case VIDEO_MODE_AUTO:
-	return "auto";
-    default:
-	return "unknown";
-    }
-};
-
-static const char *audio_mode2name(int mode)
-{
-    switch (mode) {
-    case VIDEO_SOUND_MONO:
-	return "mono";
-    case VIDEO_SOUND_STEREO:
-	return "stereo";
-    case VIDEO_SOUND_LANG1:
-	return "language1";
-    case VIDEO_SOUND_LANG2:
-	return "language2";
-    default:
-	return "unknown";
-    }
-};
-
-static void *audio_grabber(void *data);
-static void *video_grabber(void *data);
-
-static int palette2depth(int palette)
-{
-    switch(palette)
-    {
-	/* component */
-	case VIDEO_PALETTE_RGB555:
-	    return(15);
-	case VIDEO_PALETTE_RGB565:
-	    return(16);
-	case VIDEO_PALETTE_RGB24:
-	    return(24);
-	case VIDEO_PALETTE_RGB32:
-	    return(32);
-	/* planar */
-	case VIDEO_PALETTE_YUV411P:
-	case VIDEO_PALETTE_YUV420P:
-	case VIDEO_PALETTE_YUV410P:
-	    return(12);
-	/* packed */
-	case VIDEO_PALETTE_YUV422P:
-	case VIDEO_PALETTE_YUV422:
-	case VIDEO_PALETTE_YUYV:
-	case VIDEO_PALETTE_UYVY:
-	case VIDEO_PALETTE_YUV420:
-	case VIDEO_PALETTE_YUV411:
-	    return(16);
-    }
-    return(-1);
-}
-
-static int format2palette(int format)
-{
-    switch(format)
-    {
-	case IMGFMT_BGR15:
-	    return(VIDEO_PALETTE_RGB555);
-	case IMGFMT_BGR16:
-	    return(VIDEO_PALETTE_RGB565);
-	case IMGFMT_BGR24:
-	    return(VIDEO_PALETTE_RGB24);
-	case IMGFMT_BGR32:
-	    return(VIDEO_PALETTE_RGB32);
-	case IMGFMT_YV12:
-	case IMGFMT_I420:
-	    return(VIDEO_PALETTE_YUV420P);
-	case IMGFMT_YUY2:
-	    return(VIDEO_PALETTE_YUV422);
-    case IMGFMT_UYVY:
-       return(VIDEO_PALETTE_UYVY);
-    }
-    return(-1);
-}
-
-// sets and sanitizes audio buffer/block sizes
-static void setup_audio_buffer_sizes(priv_t *priv)
-{
-    int bytes_per_sample = priv->audio_in.bytes_per_sample;
-
-    // make the audio buffer at least 5 seconds long
-    priv->audio_buffer_size = 1 + 5*priv->audio_in.samplerate
-	*priv->audio_in.channels
-	*bytes_per_sample/priv->audio_in.blocksize;
-    if (priv->audio_buffer_size < 256) priv->audio_buffer_size = 256;
-
-    // make the skew buffer at least 1 second long
-    priv->aud_skew_cnt = 1 + 1*priv->audio_in.samplerate
-	*priv->audio_in.channels
-	*bytes_per_sample/priv->audio_in.blocksize;
-    if (priv->aud_skew_cnt < 16) priv->aud_skew_cnt = 16;
-
-    mp_msg(MSGT_TV, MSGL_V, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
-	   priv->audio_buffer_size, priv->audio_in.blocksize, priv->aud_skew_cnt);
-}
-
-tvi_handle_t *tvi_init_v4l(char *device, char *adevice)
-{
-    tvi_handle_t *h;
-    priv_t *priv;
-    
-    h = new_handle();
-    if (!h)
-	return(NULL);
-
-    priv = h->priv;
-
-    /* set video device name */
-    if (!device)
-	priv->video_device = strdup("/dev/video0");
-    else
-	priv->video_device = strdup(device);
-
-    /* set video device name */
-    if (!adevice)
-	priv->audio_device = NULL;
-    else {
-	priv->audio_device = strdup(adevice);
-    }
-    
-    /* allocation failed */
-    if (!priv->video_device) {
-	free_handle(h);
-	return(NULL);
-    }
-
-    return(h);
-}
-
-/* retrieves info about audio channels from the BTTV */
-static void init_v4l_audio(priv_t *priv)
-{
-    int i;
-    int reqmode;
-
-    if (!priv->capability.audios) return;
-
-    /* audio chanlist */
-
-    mp_msg(MSGT_TV, MSGL_V, " Audio devices: %d\n", priv->capability.audios);
-
-    mp_msg(MSGT_TV, MSGL_V, "Video capture card reports the audio setup as follows:\n");
-    for (i = 0; i < priv->capability.audios; i++)
-    {
-	if (i >= MAX_AUDIO_CHANNELS)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "no space for more audio channels (increase in source!) (%d > %d)\n",
-		   i, MAX_AUDIO_CHANNELS);
-	    i = priv->capability.audios;
-	    break;
-	}
-
-	priv->audio[i].audio = i;
-	if (ioctl(priv->video_fd, VIDIOCGAUDIO, &priv->audio[i]) == -1)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get audio failed: %s\n", strerror(errno));
-	    break;
-	}
-
-	/* mute all channels */
-	priv->audio[i].flags |= VIDEO_AUDIO_MUTE;
-	reqmode = -1;
-	if (tv_param_amode >= 0) {
-	    switch (tv_param_amode) {
-	    case 0:
-		reqmode = VIDEO_SOUND_MONO;
-		break;
-	    case 1:
-		reqmode = VIDEO_SOUND_STEREO;
-		break;
-	    case 2:
-		reqmode = VIDEO_SOUND_LANG1;
-		break;
-	    case 3:
-		reqmode = VIDEO_SOUND_LANG2;
-		break;
-	    default:
-		mp_msg(MSGT_TV, MSGL_ERR, "Unknown audio mode requested.\n");
-		break;
-	    }
-	    if (reqmode >= 0) priv->audio[i].mode = reqmode;
-	}
-	ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[i]);
-	
-	// get the parameters back
-	if (ioctl(priv->video_fd, VIDIOCGAUDIO, &priv->audio[i]) == -1)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get audio failed: %s\n", strerror(errno));
-	    break;
-	}
-	    
-	switch(priv->audio[i].mode)
-	{
-	case VIDEO_SOUND_MONO:
-	case VIDEO_SOUND_LANG1:
-	case VIDEO_SOUND_LANG2:
-	    priv->audio_channels[i] = 1;
-	    break;
-	case VIDEO_SOUND_STEREO:
-	    priv->audio_channels[i] = 2;
-	    break;
-	default:
-	    mp_msg(MSGT_TV, MSGL_ERR, "Card reports an unknown audio mode !\n");
-	    mp_msg(MSGT_TV, MSGL_ERR, "Trying two channel audio. Use forcechan to override.\n");
-	    priv->audio_channels[i] = 2;
-	    break;
-	}
-
-	if (reqmode >= 0 && priv->audio[i].mode != reqmode) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "Audio mode setup warning!\n");
-	    mp_msg(MSGT_TV, MSGL_ERR, "Requested mode was %s, but v4l still reports %s.\n",
-		   audio_mode2name(reqmode), audio_mode2name(priv->audio[i].mode));
-	    mp_msg(MSGT_TV, MSGL_ERR, "You may need \"forcechan\" option to force stereo/mono audio recording.\n");
-	}
-
-	/* display stuff */
-	mp_msg(MSGT_TV, MSGL_V, "  %d: %s: ", priv->audio[i].audio,
-	       priv->audio[i].name);
-	if (priv->audio[i].flags & VIDEO_AUDIO_MUTABLE) {
-	    mp_msg(MSGT_TV, MSGL_V, "muted=%s ",
-		   (priv->audio[i].flags & VIDEO_AUDIO_MUTE) ? "yes" : "no");
-	}
-	mp_msg(MSGT_TV, MSGL_V, "vol=%d bass=%d treble=%d balance=%d mode=%s",
-	       priv->audio[i].volume, priv->audio[i].bass, priv->audio[i].treble,
-	       priv->audio[i].balance, audio_mode2name(priv->audio[i].mode));
-	mp_msg(MSGT_TV, MSGL_V, " chan=%d\n", priv->audio_channels[i]);
-
-	if (tv_param_forcechan >= 0)
-	    priv->audio_channels[i] = tv_param_forcechan;
-
-	// we'll call VIDIOCSAUDIO again when starting capture
-	// let's set audio mode to requested mode again for the case
-	// when VIDIOCGAUDIO just cannot report the mode correctly
-	if (reqmode >= 0) priv->audio[i].mode = reqmode;
-    }
-}
-
-#if !defined(__LINUX_VIDEODEV2_H) && !defined(VIDIOC_QUERYCAP)
-struct v4l2_capability
-{
-        __u8    driver[16];     /* i.e. "bttv" */
-        __u8    card[32];       /* i.e. "Hauppauge WinTV" */
-        __u8    bus_info[32];   /* "PCI:" + pci_dev->slot_name */
-        __u32   version;        /* should use KERNEL_VERSION() */
-        __u32   capabilities;   /* Device capabilities */
-        __u32   reserved[4];
-};
-
-#define VIDIOC_QUERYCAP         _IOR  ('V',  0, struct v4l2_capability)
-#endif
-
-static int init(priv_t *priv)
-{
-    int i;
-
-    if (tv_param_immediate == 1)
-	tv_param_noaudio = 1;
-    
-    priv->video_ringbuffer = NULL;
-    priv->video_timebuffer = NULL;
-    priv->video_avg_buffer = NULL;
-    priv->audio_ringbuffer = NULL;
-    priv->audio_skew_buffer = NULL;
-
-    priv->video_fd = open(priv->video_device, O_RDWR);
-    mp_msg(MSGT_TV, MSGL_DBG2, "Video fd: %d, %p\n", priv->video_fd,
-	priv->video_device);
-    if (priv->video_fd == -1)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "unable to open '%s': %s\n",
-	    priv->video_device, strerror(errno));
-	goto err;
-    }
-    
-    /* check for v4l2 */
-    if (ioctl(priv->video_fd, VIDIOC_QUERYCAP, &priv->capability) == 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "=================================================================\n");
-	mp_msg(MSGT_TV, MSGL_ERR, " WARNING: YOU ARE USING V4L DEMUXER WITH V4L2 DRIVERS!!!\n");
-	mp_msg(MSGT_TV, MSGL_ERR, " As the V4L1 compatibility layer is broken, this may not work.\n");
-	mp_msg(MSGT_TV, MSGL_ERR, " If you encounter any problems, use driver=v4l2 instead.\n");
-	mp_msg(MSGT_TV, MSGL_ERR, " Bugreports on driver=v4l with v4l2 drivers will be ignored.\n");
-	mp_msg(MSGT_TV, MSGL_ERR, "=================================================================\n");
-    }
-    
-    /* get capabilities (priv->capability is needed!) */
-    if (ioctl(priv->video_fd, VIDIOCGCAP, &priv->capability) == -1)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "ioctl get capabilites failed: %s\n", strerror(errno));
-	goto err;
-    }
-
-    fcntl(priv->video_fd, F_SETFD, FD_CLOEXEC);
-
-    mp_msg(MSGT_TV, MSGL_INFO, "Selected device: %s\n", priv->capability.name);
-    mp_msg(MSGT_TV, MSGL_INFO, " Capabilites: ");
-    for (i = 0; device_cap2name[i] != NULL; i++)
-	if (priv->capability.type & (1 << i))
-	    mp_msg(MSGT_TV, MSGL_INFO, "%s ", device_cap2name[i]);
-    mp_msg(MSGT_TV, MSGL_INFO, "\n");
-    mp_msg(MSGT_TV, MSGL_INFO, " Device type: %d\n", priv->capability.type);
-    mp_msg(MSGT_TV, MSGL_INFO, " Supported sizes: %dx%d => %dx%d\n",
-	priv->capability.minwidth, priv->capability.minheight,
-	priv->capability.maxwidth, priv->capability.maxheight);
-    priv->width = priv->capability.minwidth;
-    priv->height = priv->capability.minheight;
-
-    /* somewhere here could disable tv_param_mjpeg, if it is not a capability */
-
-    /* initialize if necessary */
-    if ( tv_param_mjpeg )
-      {
-        struct mjpeg_params bparm;
-        struct mjpeg_requestbuffers breq;          /* buffer requests */
-
-        if (ioctl(priv->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)
-        {
-           mp_msg(MSGT_TV, MSGL_ERR, 
-              "  MJP: Error getting video parameters: %s\n", strerror(errno));
-           goto err;
-        }
-
-        mp_msg(MSGT_TV, MSGL_INFO, 
-	       "  MJP: previous params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n",
-	           bparm.img_x, bparm.img_y, bparm.img_width, bparm.img_height,          
-		   bparm.decimation, bparm.field_per_buff);
-
-        mp_msg(MSGT_TV, MSGL_INFO, 
-	       "  MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n",
-	           bparm.HorDcm, bparm.VerDcm, bparm.TmpDcm);
-
-        bparm.input = tv_param_input; /* tv */
-        if (!strcasecmp(tv_param_norm, "pal"))
-	  bparm.norm =  0; /* PAL */
-        else if (!strcasecmp(tv_param_norm, "ntsc"))
-	  bparm.norm =  1; /* NTSC */
-        else if (!strcasecmp(tv_param_norm, "secam"))
-	  bparm.norm =  2; /* SECAM */
-        bparm.quality = tv_param_quality;
-        bparm.decimation = tv_param_decimation;
-
-        mp_msg(MSGT_TV, MSGL_INFO, "  MJP: setting params to decimation: %d, quality: %d\n", 
-	                                 bparm.decimation, bparm.quality);
-
-        if (ioctl(priv->video_fd, MJPIOC_S_PARAMS, &bparm) < 0)
-         {
-            mp_msg(MSGT_TV, MSGL_ERR,
-               "  MJP: Error setting video parameters: %s\n", strerror(errno));
-            goto err;
-         }
-
-        if (ioctl(priv->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)
-        {
-           mp_msg(MSGT_TV, MSGL_ERR, 
-              "  MJP: Error getting video parameters: %s\n", strerror(errno));
-           goto err;
-        }
-
-        mp_msg(MSGT_TV, MSGL_INFO, 
-	       "  MJP: current params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n",
-	           bparm.img_x, bparm.img_y, bparm.img_width, bparm.img_height,          
-		   bparm.decimation, bparm.field_per_buff);
-
-        mp_msg(MSGT_TV, MSGL_INFO, 
-	       "  MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n",
-	           bparm.HorDcm, bparm.VerDcm, bparm.TmpDcm);
-
-
-        breq.count = 64;
-	priv -> nbuf = breq.count;
-        priv->mbuf.frames = priv -> nbuf;
-        priv->mjpeg_bufsize = 256*1024;
-        if (tv_param_buffer_size >= 0) {
-          priv->mjpeg_bufsize = tv_param_buffer_size*1024;
-	  }
-        breq.size  = priv -> mjpeg_bufsize;
-        if (ioctl(priv->video_fd, MJPIOC_REQBUFS,&(breq)) < 0)
-        {
-           mp_msg (MSGT_TV, MSGL_ERR,
-              "  MJP: Error requesting video buffers: %s\n", strerror(errno));
-           goto err;
-        }
-        mp_msg(MSGT_TV, MSGL_INFO,
-           "  MJP: Got %ld buffers of size %ld KB\n", 
-                    breq.count, breq.size/1024);
-
-        priv -> mmap = mmap(0, breq.count * breq.size, 
-           PROT_READ|PROT_WRITE, MAP_SHARED, priv->video_fd, 0);
-        if (priv -> mmap == MAP_FAILED)
-        {
-           mp_msg(MSGT_TV, MSGL_INFO,
-              "  MJP: Error mapping video buffers: %s\n", strerror(errno));
-           goto err;
-        }
-      }
-
-    mp_msg(MSGT_TV, MSGL_INFO, " Inputs: %d\n", priv->capability.channels);
-    priv->channels = calloc(priv->capability.channels, sizeof(struct video_channel));
-    if (!priv->channels)
-	goto malloc_failed;
-    memset(priv->channels, 0, sizeof(struct video_channel)*priv->capability.channels);
-    for (i = 0; i < priv->capability.channels; i++)
-    {
-	priv->channels[i].channel = i;
-	if (ioctl(priv->video_fd, VIDIOCGCHAN, &priv->channels[i]) == -1)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get channel failed: %s\n", strerror(errno));
-	    break;
-	}
-	mp_msg(MSGT_TV, MSGL_INFO, "  %d: %s: %s%s%s%s (tuner:%d, norm:%s)\n", i,
-	    priv->channels[i].name,
-	    (priv->channels[i].flags & VIDEO_VC_TUNER) ? "tuner " : "",
-	    (priv->channels[i].flags & VIDEO_VC_AUDIO) ? "audio " : "",
-	    (priv->channels[i].flags & VIDEO_TYPE_TV) ? "tv " : "",
-	    (priv->channels[i].flags & VIDEO_TYPE_CAMERA) ? "camera " : "",
-	    priv->channels[i].tuners,
-	    norm2name(priv->channels[i].norm));
-    }
-    priv->act_channel = 0;
-
-    if (!(priv->capability.type & VID_TYPE_CAPTURE))
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "Only grabbing supported (for overlay use another program)\n");
-	goto err;
-    }
-    
-    if ( !tv_param_mjpeg )
-    {
-    /* map grab buffer */
-    if (ioctl(priv->video_fd, VIDIOCGMBUF, &priv->mbuf) == -1)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "ioctl get mbuf failed: %s\n", strerror(errno));
-	goto err;
-    }
-
-    mp_msg(MSGT_TV, MSGL_V, "mbuf: size=%d, frames=%d\n",
-	priv->mbuf.size, priv->mbuf.frames);
-    priv->mmap = mmap(0, priv->mbuf.size, PROT_READ|PROT_WRITE,
-		MAP_SHARED, priv->video_fd, 0);
-    if (priv->mmap == (unsigned char *)-1)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "Unable to map memory for buffers: %s\n", strerror(errno));
-	goto err;
-    }
-    mp_msg(MSGT_TV, MSGL_DBG2, "our buffer: %p\n", priv->mmap);
-
-    /* num of buffers */
-    priv->nbuf = priv->mbuf.frames;
-    
-    /* video buffers */
-    priv->buf = calloc(priv->nbuf, sizeof(struct video_mmap));
-    if (!priv->buf)
-	goto malloc_failed;
-    memset(priv->buf, 0, priv->nbuf * sizeof(struct video_mmap));
-    }
-    
-    /* init v4l audio even when we don't capture */
-    init_v4l_audio(priv);
-
-    if (!priv->capability.audios && !tv_param_force_audio) tv_param_noaudio = 1;
-
-    /* audio init */
-    if (!tv_param_noaudio) {
-	
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-	if (tv_param_alsa)
-	    audio_in_init(&priv->audio_in, AUDIO_IN_ALSA);
-	else
-	    audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
-#else
-	audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
-#endif
-
-	if (priv->audio_device) {
-	    audio_in_set_device(&priv->audio_in, priv->audio_device);
-	}
-
-	if (tv_param_audio_id < priv->capability.audios)
-	    priv->audio_id = tv_param_audio_id;
-	else
-	    priv->audio_id = 0;
-	audio_in_set_samplerate(&priv->audio_in, 44100);
-	if (priv->capability.audios) {
-	    audio_in_set_channels(&priv->audio_in, priv->audio_channels[priv->audio_id]);
-	} else {
-	    if (tv_param_forcechan >= 0) {
-		audio_in_set_channels(&priv->audio_in, tv_param_forcechan);
-	    } else {
-		audio_in_set_channels(&priv->audio_in, 2);
-	    }
-	}
-	if (audio_in_setup(&priv->audio_in) < 0) return 0;
-	setup_audio_buffer_sizes(priv);
-    }
-
-    return(1);
-
-malloc_failed:
-    if (priv->channels)
-	free(priv->channels);
-    if (priv->buf)
-	free(priv->buf);
-err:
-    if (priv->video_fd != -1)
-	close(priv->video_fd);
-    return(0);
-}
-
-static int uninit(priv_t *priv)
-{
-    unsigned long num;
-    priv->shutdown = 1;
-
-    mp_msg(MSGT_TV, MSGL_V, "Waiting for threads to finish... ");
-    if (!tv_param_noaudio) {
-	pthread_join(priv->audio_grabber_thread, NULL);
-	pthread_mutex_destroy(&priv->audio_starter);
-	pthread_mutex_destroy(&priv->skew_mutex);
-    }
-    pthread_mutex_destroy(&priv->video_buffer_mutex);
-    pthread_join(priv->video_grabber_thread, NULL);
-    mp_msg(MSGT_TV, MSGL_V, "done\n");
-
-    if (priv->capability.audios) {
-	priv->audio[priv->audio_id].flags |= VIDEO_AUDIO_MUTE;
-	ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
-    }
-    
-    if ( tv_param_mjpeg )
-      {
-	num = -1;
-        if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)
-          {
-            mp_msg(MSGT_TV, MSGL_ERR, "\n  MJP: ioctl MJPIOC_QBUF_CAPT failed: %s\n", strerror(errno));
-          }
-      }
-    else
-      {
-	// We need to munmap as close don't close mem mappings
-	if(munmap(priv->mmap,priv->mbuf.size))
-	  mp_msg(MSGT_TV, MSGL_ERR, "Munmap failed: %s\n",strerror(errno));
-      }
-
-    if(close(priv->video_fd))
-      mp_msg(MSGT_TV, MSGL_ERR, "Close tv failed: %s\n",strerror(errno));
-
-    audio_in_uninit(&priv->audio_in);
-
-    if (priv->video_ringbuffer) {
-	int i;
-	for (i = 0; i < priv->video_buffer_size_current; i++) {
-	    free(priv->video_ringbuffer[i]);
-	}
-	free(priv->video_ringbuffer);
-    }
-    
-    if (priv->video_timebuffer)
-	free(priv->video_timebuffer);
-    if (priv->video_avg_buffer)
-	free(priv->video_avg_buffer);
-    if (!tv_param_noaudio) {
-	if (priv->audio_ringbuffer)
-	    free(priv->audio_ringbuffer);
-	if (priv->audio_skew_buffer)
-	    free(priv->audio_skew_buffer);
-    }
-
-    return(1);
-}
-
-static int get_capture_buffer_size(priv_t *priv)
-{
-    int bufsize, cnt;
-
-    if (tv_param_buffer_size >= 0) {
-	bufsize = tv_param_buffer_size*1024*1024;
-    } else {
-#ifdef HAVE_SYS_SYSINFO_H
-	struct sysinfo si;
-	
-	sysinfo(&si);
-	if (si.totalram<2*1024*1024) {
-	    bufsize = 1024*1024;
-	} else {
-	    bufsize = si.totalram/2;
-	}
-#else
-	bufsize = 16*1024*1024;
-#endif
-    }
-    
-    cnt = bufsize/(priv->height*priv->bytesperline);
-    if (cnt < 2) cnt = 2;
-    
-    return cnt;
-}
-
-static int start(priv_t *priv)
-{
-    int i;
-    int bytes_per_sample;
-    
-    if (ioctl(priv->video_fd, VIDIOCGPICT, &priv->picture) == -1)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "ioctl get picture failed: %s\n", strerror(errno));
-	return(0);
-    }
-
-    priv->picture.palette = format2palette(priv->format);
-    priv->picture.depth = palette2depth(priv->picture.palette);
-
-    if (priv->format != IMGFMT_BGR15) {
-	priv->bytesperline = priv->width * priv->picture.depth / 8;
-    } else {
-	priv->bytesperline = priv->width * 2;
-    }
-
-    mp_msg(MSGT_TV, MSGL_V, "Picture values:\n");
-    mp_msg(MSGT_TV, MSGL_V, " Depth: %d, Palette: %s (Format: %s)\n", priv->picture.depth,
-	PALETTE(priv->picture.palette), vo_format_name(priv->format));
-    mp_msg(MSGT_TV, MSGL_V, " Brightness: %d, Hue: %d, Colour: %d, Contrast: %d\n",
-	priv->picture.brightness, priv->picture.hue,
-	priv->picture.colour, priv->picture.contrast);
-    
-
-    if (ioctl(priv->video_fd, VIDIOCSPICT, &priv->picture) == -1)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "ioctl set picture failed: %s\n", strerror(errno));
-    }
-
-    if ( !tv_param_mjpeg )
-    {
-    priv->nbuf = priv->mbuf.frames;
-    for (i=0; i < priv->nbuf; i++)
-    {
-	priv->buf[i].format = priv->picture.palette;
-	priv->buf[i].frame = i;
-	priv->buf[i].width = priv->width;
-	priv->buf[i].height = priv->height;
-	mp_msg(MSGT_TV, MSGL_DBG2, "buffer: %d => %p\n", i, &priv->buf[i]);
-    } 
-    } 
-
-#if 0
-    {
-	struct video_play_mode pmode;
-	
-	pmode.mode = VID_PLAY_NORMAL;
-	pmode.p1 = 1;
-	pmode.p2 = 0;
-	if (ioctl(priv->video_fd, VIDIOCSPLAYMODE, &pmode) == -1)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl set play mode failed: %s\n", strerror(errno));
-//	    return(0);
-	}
-    }
-#endif
-
-#if 0
-    {
-	struct video_window win;
-
-	win.x = 0;
-	win.y = 0;
-	win.width = priv->width;
-	win.height = priv->height;
-	win.chromakey = -1;
-	win.flags = 0;
-	//win.clipcount = 0;
-	
-	ioctl(priv->video_fd, VIDIOCSWIN, &win);
-    }
-
-    // initialize video capture
-    if (ioctl(priv->video_fd, VIDIOCCAPTURE, &one) == -1)
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "FATAL: ioctl ccapture failed: %s\n", strerror(errno));
-	return(0);
-    }
-#endif
-
-    /* setup audio parameters */
-    if (!tv_param_noaudio) {
-	setup_audio_buffer_sizes(priv);
-	bytes_per_sample = priv->audio_in.bytes_per_sample;
-	priv->audio_skew_buffer = calloc(priv->aud_skew_cnt, sizeof(long long));
-	if (!priv->audio_skew_buffer) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
-	    return 0;
-	}
-
-	priv->audio_ringbuffer = calloc(priv->audio_in.blocksize, priv->audio_buffer_size);
-	if (!priv->audio_ringbuffer) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate audio buffer: %s\n", strerror(errno));
-	    return 0;
-	}
-
-	priv->audio_secs_per_block = (double)priv->audio_in.blocksize/(priv->audio_in.samplerate
-								    *priv->audio_in.channels
-								    *bytes_per_sample);
-	priv->audio_head = 0;
-	priv->audio_tail = 0;
-	priv->audio_cnt = 0;
-	priv->audio_drop = 0;
-	priv->audio_skew = 0;
-	priv->audio_skew_total = 0;
-	priv->audio_recv_blocks_total = 0;
-	priv->audio_sent_blocks_total = 0;
-    }
-
-    /* setup video parameters */
-    if (priv->immediate_mode) {
-	priv->video_buffer_size_max = VID_BUF_SIZE_IMMEDIATE;
-    } else {
-	priv->video_buffer_size_max = get_capture_buffer_size(priv);
-    }
-    priv->video_buffer_size_current = 0;
-
-    if (!tv_param_noaudio) {
-	if (priv->video_buffer_size_max < 3.0*priv->fps*priv->audio_secs_per_block) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "Video buffer shorter than 3 times audio frame duration.\n"
-		   "You will probably experience heavy framedrops.\n");
-	}
-    }
-
-    mp_msg(MSGT_TV, MSGL_V, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
-	   priv->video_buffer_size_max,
-	   priv->video_buffer_size_max*priv->height*priv->bytesperline/(1024*1024));
-
-    priv->video_ringbuffer = calloc(priv->video_buffer_size_max, sizeof(unsigned char*));
-    if (!priv->video_ringbuffer) {
-	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate video buffer: %s\n", strerror(errno));
-	return 0;
-    }
-    for (i = 0; i < priv->video_buffer_size_max; i++)
-	priv->video_ringbuffer[i] = NULL;
-    
-    priv->video_timebuffer = calloc(priv->video_buffer_size_max, sizeof(long long));
-    if (!priv->video_timebuffer) {
-	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate time buffer: %s\n", strerror(errno));
-	return 0;
-    }
-    priv->video_avg_buffer = malloc(sizeof(long long) * VIDEO_AVG_BUFFER_SIZE);
-    if (!priv->video_avg_buffer) {
-	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate period buffer: %s\n", strerror(errno));
-	return 0;
-    }
-    priv->video_interval_sum = (1e6/priv->fps)*VIDEO_AVG_BUFFER_SIZE;
-    for (i = 0; i < VIDEO_AVG_BUFFER_SIZE; i++) {
-	priv->video_avg_buffer[i] = 1e6/priv->fps;
-    }
-
-    priv->video_avg_ptr = 0;
-    
-    priv->video_head = 0;
-    priv->video_tail = 0;
-    priv->video_cnt = 0;
-    priv->first = 1;
-
-    if (priv->capability.audios) {
-	/* enable audio */
-	if (tv_param_volume >= 0)
-	    priv->audio[priv->audio_id].volume = tv_param_volume;
-	if (tv_param_bass >= 0)
-	    priv->audio[priv->audio_id].bass = tv_param_bass;
-	if (tv_param_treble >= 0)
-	    priv->audio[priv->audio_id].treble = tv_param_treble;
-	if (tv_param_balance >= 0)
-	    priv->audio[priv->audio_id].balance = tv_param_balance;
-	priv->audio[priv->audio_id].flags &= ~VIDEO_AUDIO_MUTE;
-	mp_msg(MSGT_TV, MSGL_V, "Enabling tv audio. Requested setup is:\n");
-	mp_msg(MSGT_TV, MSGL_V, "id=%d vol=%d bass=%d treble=%d balance=%d mode=%s",
-	       priv->audio_id,
-	       priv->audio[priv->audio_id].volume, priv->audio[priv->audio_id].bass, priv->audio[priv->audio_id].treble,
-	       priv->audio[priv->audio_id].balance, audio_mode2name(priv->audio[priv->audio_id].mode));
-	mp_msg(MSGT_TV, MSGL_V, " chan=%d\n", priv->audio_channels[priv->audio_id]);
-	ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
-    }
-    
-    /* launch capture threads */
-    priv->shutdown = 0;
-    if (!tv_param_noaudio) {
-	pthread_mutex_init(&priv->audio_starter, NULL);
-	pthread_mutex_init(&priv->skew_mutex, NULL);
-	pthread_mutex_lock(&priv->audio_starter);
-	pthread_create(&priv->audio_grabber_thread, NULL, audio_grabber, priv);
-    }
-    pthread_mutex_init(&priv->video_buffer_mutex, NULL);
-    /* we'll launch the video capture later, when a first request for a frame arrives */
-
-    return(1);
-}
-
-
-static int control(priv_t *priv, int cmd, void *arg)
-{
-    mp_msg(MSGT_TV, MSGL_DBG2, "\ndebug: control(priv=%p, cmd=%d, arg=%p)\n",
-	priv, cmd, arg);
-    switch(cmd)
-    {
-	/* ========== GENERIC controls =========== */
-	case TVI_CONTROL_IS_VIDEO:
-	{
-	    if (priv->capability.type & VID_TYPE_CAPTURE)
-		return(TVI_CONTROL_TRUE);
-	    return(TVI_CONTROL_FALSE);
-	}
-	case TVI_CONTROL_IS_AUDIO:
-	    if (tv_param_force_audio) return(TVI_CONTROL_TRUE);
-	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_AUDIO)
-	    {
-		return(TVI_CONTROL_TRUE);
-	    }
-	    return(TVI_CONTROL_FALSE);
-	case TVI_CONTROL_IS_TUNER:
-	{
-//	    if (priv->capability.type & VID_TYPE_TUNER)
-	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_TUNER)
-		return(TVI_CONTROL_TRUE);
-	    return(TVI_CONTROL_FALSE);
-	}
-
-	/* ========== VIDEO controls =========== */
-	case TVI_CONTROL_VID_GET_FORMAT:
-	{
-	    int output_fmt = -1;
-
-	    output_fmt = priv->format;
-            if ( tv_param_mjpeg )
-	    {
-              mp_msg(MSGT_TV, MSGL_INFO, "  MJP: setting sh_video->format to mjpg\n");
-	      output_fmt = 0x47504a4d;
-	      output_fmt = 0x67706a6d;
-	      *(int *)arg = output_fmt;
-	      mp_msg(MSGT_TV, MSGL_V, "Output format: %s\n", "mjpg");
-	    }
-	    else
-	    {
-	    *(int *)arg = output_fmt;
-	    mp_msg(MSGT_TV, MSGL_V, "Output format: %s\n", vo_format_name(output_fmt));
-	    }
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_VID_SET_FORMAT:
-	    priv->format = *(int *)arg;
-	    // !HACK! v4l uses BGR format instead of RGB
-	    // and we have to correct this. Fortunately,
-	    // tv.c reads later the format back so we
-	    // can persuade it to use what we want.
-	    if (IMGFMT_IS_RGB(priv->format)) {
-		priv->format &= ~IMGFMT_RGB_MASK;
-		priv->format |= IMGFMT_BGR;
-	    }
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_GET_PLANES:
-	    *(int *)arg = 1; /* FIXME, also not needed at this time */
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_GET_BITS:
-	    *(int *)arg = palette2depth(format2palette(priv->format));
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_GET_WIDTH:
-	    *(int *)arg = priv->width;
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_CHK_WIDTH:
-	{
-	    int req_width = *(int *)arg;
-	    
-	    mp_msg(MSGT_TV, MSGL_V, "Requested width: %d\n", req_width);
-	    if ((req_width >= priv->capability.minwidth) &&
-		(req_width <= priv->capability.maxwidth))
-		return(TVI_CONTROL_TRUE);
-	    return(TVI_CONTROL_FALSE);
-	}
-	case TVI_CONTROL_VID_SET_WIDTH:
-	    priv->width = *(int *)arg;
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_GET_HEIGHT:
-	    *(int *)arg = priv->height;
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_CHK_HEIGHT:
-	{
-	    int req_height = *(int *)arg;
-	    
-	    mp_msg(MSGT_TV, MSGL_V, "Requested height: %d\n", req_height);
-	    if ((req_height >= priv->capability.minheight) &&
-		(req_height <= priv->capability.maxheight))
-		return(TVI_CONTROL_TRUE);
-	    return(TVI_CONTROL_FALSE);
-	}
-	case TVI_CONTROL_VID_SET_HEIGHT:
-	    priv->height = *(int *)arg;
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_GET_PICTURE:
-	    if (ioctl(priv->video_fd, VIDIOCGPICT, &priv->picture) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get picture failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_SET_PICTURE:
-	    if (ioctl(priv->video_fd, VIDIOCSPICT, &priv->picture) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get picture failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_VID_SET_BRIGHTNESS:
-	    priv->picture.brightness = (327*(*(int *)arg+100)) + 68;
-	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
-	case TVI_CONTROL_VID_SET_HUE:
-	    priv->picture.hue = (327*(*(int *)arg+100)) + 68;
-	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
-	case TVI_CONTROL_VID_SET_SATURATION:
-	    priv->picture.colour = (327*(*(int *)arg+100)) + 68;
-	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
-	case TVI_CONTROL_VID_SET_CONTRAST:
-	    priv->picture.contrast = (327*(*(int *)arg+100)) + 68;
-	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
-	case TVI_CONTROL_VID_GET_BRIGHTNESS:
-	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
-	    *(int*)arg = ((int)priv->picture.brightness-68)/327-100;
-	    return 1;
-	case TVI_CONTROL_VID_GET_HUE:
-	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
-	    *(int*)arg = ((int)priv->picture.hue-68)/327-100;
-	    return 1;
-	case TVI_CONTROL_VID_GET_SATURATION:
-	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
-	    *(int*)arg = ((int)priv->picture.colour-68)/327-100;
-	    return 1;
-	case TVI_CONTROL_VID_GET_CONTRAST:
-	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
-	    *(int*)arg = ((int)priv->picture.contrast-68)/327-100;
-	    return 1;
-	case TVI_CONTROL_VID_GET_FPS:
-	    *(float *)arg=priv->fps;
-	    return(TVI_CONTROL_TRUE);
-
-	/* ========== TUNER controls =========== */
-	case TVI_CONTROL_TUN_GET_FREQ:
-	{
-	    unsigned long freq;
-	    
-	    if (ioctl(priv->video_fd, VIDIOCGFREQ, &freq) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get freq failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    
-	    /* tuner uses khz not mhz ! */
-//	    if (priv->tuner.flags & VIDEO_TUNER_LOW)
-//	        freq /= 1000;
-	    *(unsigned long *)arg = freq;
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_TUN_SET_FREQ:
-	{
-	    /* argument is in MHz ! */
-	    unsigned long freq = *(unsigned long *)arg;
-	    
-	    if (priv->capability.audios) {
-		priv->audio[priv->audio_id].flags |= VIDEO_AUDIO_MUTE;
-		ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
-	    }
-
-	    mp_msg(MSGT_TV, MSGL_V, "requested frequency: %.3f\n", (float)freq/16);
-	    
-	    /* tuner uses khz not mhz ! */
-//	    if (priv->tuner.flags & VIDEO_TUNER_LOW)
-//	        freq *= 1000;
-//	    mp_msg(MSGT_TV, MSGL_V, " requesting from driver: freq=%.3f\n", (float)freq/16);
-	    if (ioctl(priv->video_fd, VIDIOCSFREQ, &freq) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set freq failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    usleep(100000); // wait to suppress noise during switching
-
-	    if (priv->capability.audios) {
-		priv->audio[priv->audio_id].flags &= ~VIDEO_AUDIO_MUTE;
-		ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
-	    }
-
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_TUN_GET_TUNER:
-	{
-	    if (ioctl(priv->video_fd, VIDIOCGTUNER, &priv->tuner) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get tuner failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    
-	    mp_msg(MSGT_TV, MSGL_V, "Tuner (%s) range: %lu -> %lu\n", priv->tuner.name,
-		priv->tuner.rangelow, priv->tuner.rangehigh);
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_TUN_SET_TUNER:
-	{
-	    if (ioctl(priv->video_fd, VIDIOCSTUNER, &priv->tuner) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set tuner failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_TUN_SET_NORM:
-	{
-	    int req_mode = *(int *)arg;
-
-	    if ((req_mode != TV_NORM_PAL) && (req_mode != TV_NORM_NTSC) && (req_mode != TV_NORM_SECAM)
-		&& (req_mode != TV_NORM_PALNC) && (req_mode != TV_NORM_PALM) && (req_mode != TV_NORM_PALN)
-		&& (req_mode != TV_NORM_NTSCJP)) {
-		mp_msg(MSGT_TV, MSGL_ERR, "Unknown norm!\n");
-		return(TVI_CONTROL_FALSE);
-	    }
-
-	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_TUNER) {
-		int prev_mode;
-		
-		control(priv, TVI_CONTROL_TUN_GET_TUNER, 0);
-		if (((req_mode == TV_NORM_PAL
-		      || req_mode == TV_NORM_PALNC
-		      || req_mode == TV_NORM_PALN) && !(priv->tuner.flags & VIDEO_TUNER_PAL)) ||
-		    ((req_mode == TV_NORM_NTSC
-		      || req_mode == TV_NORM_NTSCJP
-		      || req_mode == TV_NORM_PALM) && !(priv->tuner.flags & VIDEO_TUNER_NTSC)) ||
-		    ((req_mode == TV_NORM_SECAM) && !(priv->tuner.flags & VIDEO_TUNER_SECAM)))
-		{
-		    mp_msg(MSGT_TV, MSGL_ERR, "Tuner isn't capable to set norm!\n");
-		    return(TVI_CONTROL_FALSE);
-		}
-
-		prev_mode = priv->tuner.mode;
-
-		switch(req_mode) {
-		case TV_NORM_PAL:
-		case TV_NORM_PALNC:
-		case TV_NORM_PALN:
-		    priv->tuner.mode = VIDEO_MODE_PAL;
-		    break;
-		case TV_NORM_NTSC:
-		case TV_NORM_NTSCJP:
-		case TV_NORM_PALM:
-		    priv->tuner.mode = VIDEO_MODE_NTSC;
-		    break;
-		case TV_NORM_SECAM:
-		    priv->tuner.mode = VIDEO_MODE_SECAM;
-		    break;
-		}
-	    
-		if (control(priv, TVI_CONTROL_TUN_SET_TUNER, &priv->tuner) != TVI_CONTROL_TRUE) {
-		    // norm setting failed, but maybe it's only because it's fixed
-		    if (priv->tuner.mode != prev_mode) return(TVI_CONTROL_FALSE); // no it really failed
-		}
-
-	    }
-
-	    switch(req_mode) {
-	    case TV_NORM_PAL:
-		priv->channels[priv->act_channel].norm = VIDEO_MODE_PAL;
-		break;
-	    case TV_NORM_NTSC:
-		priv->channels[priv->act_channel].norm = VIDEO_MODE_NTSC;
-		break;
-	    case TV_NORM_SECAM:
-		priv->channels[priv->act_channel].norm = VIDEO_MODE_SECAM;
-		break;
-	    case TV_NORM_PALNC:
-		priv->channels[priv->act_channel].norm = 3;
-		break;
-	    case TV_NORM_PALM:
-		priv->channels[priv->act_channel].norm = 4;
-		break;
-	    case TV_NORM_PALN:
-		priv->channels[priv->act_channel].norm = 5;
-		break;
-	    case TV_NORM_NTSCJP:
-		priv->channels[priv->act_channel].norm = 6;
-		break;
-	    }
-	    if (ioctl(priv->video_fd, VIDIOCSCHAN, &priv->channels[priv->act_channel]) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set chan failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-
-	    if (ioctl(priv->video_fd, VIDIOCGCAP, &priv->capability) == -1) {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get capabilites failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-
-	    if(req_mode == TV_NORM_PAL || req_mode == TV_NORM_SECAM || req_mode == TV_NORM_PALN || req_mode == TV_NORM_PALNC) {
-		priv->fps = PAL_FPS;
-            }
-
-	    if(req_mode == TV_NORM_NTSC || req_mode == TV_NORM_NTSCJP || req_mode == TV_NORM_PALM) {
-		priv->fps = NTSC_FPS;
-            }
-
-	    if(priv->height > priv->capability.maxheight) {
-		priv->height = priv->capability.maxheight;
-	    }
-
-	    if(priv->width > priv->capability.maxwidth) {
-		priv->width = priv->capability.maxwidth;
-	    }
-	    
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_TUN_GET_NORM:
-	{
-	    *(int *)arg = priv->tuner.mode;
-
-	    return(TVI_CONTROL_TRUE);
-	}
-	
-	/* ========== AUDIO controls =========== */
-	case TVI_CONTROL_AUD_GET_FORMAT:
-	{
-	    *(int *)arg = AF_FORMAT_S16_LE;
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_AUD_GET_CHANNELS:
-	{
-	    *(int *)arg = priv->audio_in.channels;
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_AUD_GET_SAMPLERATE:
-	{
-	    *(int *)arg = priv->audio_in.samplerate;
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_AUD_GET_SAMPLESIZE:
-	{
-	    *(int *)arg = priv->audio_in.bytes_per_sample;
-	    return(TVI_CONTROL_TRUE);
-	}
-	case TVI_CONTROL_AUD_SET_SAMPLERATE:
-	{
-	    if (audio_in_set_samplerate(&priv->audio_in, *(int *)arg) < 0) return TVI_CONTROL_FALSE;
-	    setup_audio_buffer_sizes(priv);
-	    return(TVI_CONTROL_TRUE);
-	}
-	/* ========== SPECIFIC controls =========== */
-	case TVI_CONTROL_SPC_GET_INPUT:
-	{
-	    int req_chan = *(int *)arg;
-	    int i;
-
-	    for (i = 0; i < priv->capability.channels; i++)
-	    {
-		if (priv->channels[i].channel == req_chan)
-		    break;
-	    }
-	    
-	    priv->act_channel = i;
-
-	    if (ioctl(priv->video_fd, VIDIOCGCHAN, &priv->channels[i]) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get channel failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    return(TVI_CONTROL_TRUE);
-	}
-
-	case TVI_CONTROL_SPC_SET_INPUT:
-	{
-	    struct video_channel chan;
-	    int req_chan = *(int *)arg;
-	    int i;
-	    
-	    if (req_chan >= priv->capability.channels)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "Invalid input requested: %d, valid: 0-%d\n",
-		    req_chan, priv->capability.channels - 1);
-		return(TVI_CONTROL_FALSE);
-	    }
-
-	    for (i = 0; i < priv->capability.channels; i++)
-	    {
-		if (priv->channels[i].channel == req_chan)
-		    chan = priv->channels[i];
-	    }
-
-	    if (ioctl(priv->video_fd, VIDIOCSCHAN, &chan) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set chan failed: %s\n", strerror(errno));
-		return(TVI_CONTROL_FALSE);
-	    }
-	    mp_msg(MSGT_TV, MSGL_INFO, "Using input '%s'\n", chan.name);
-
-	    priv->act_channel = i;
-
-	    /* update tuner state */
-//	    if (priv->capability.type & VID_TYPE_TUNER)
-	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_TUNER)
-		control(priv, TVI_CONTROL_TUN_GET_TUNER, 0);
-
-	    /* update local channel list */	
-	    control(priv, TVI_CONTROL_SPC_GET_INPUT, &req_chan);
-	    return(TVI_CONTROL_TRUE);
-	case TVI_CONTROL_IMMEDIATE:
-	    priv->immediate_mode = 1;
-	    return(TVI_CONTROL_TRUE);
-	}
-    }
-
-    return(TVI_CONTROL_UNKNOWN);
-}
-
-// copies a video frame
-// for RGB (i.e. BGR in mplayer) flips the image upside down
-// for YV12 swaps the 2nd and 3rd plane
-static inline void copy_frame(priv_t *priv, unsigned char *dest, unsigned char *source)
-{
-    int i;
-    unsigned char *sptr;
-
-    // YV12 uses VIDEO_PALETTE_YUV420P, but the planes are swapped
-    if (priv->format == IMGFMT_YV12) {
-	memcpy(dest, source, priv->width * priv->height);
-	memcpy(dest+priv->width * priv->height*5/4, source+priv->width * priv->height, priv->width * priv->height/4);
-	memcpy(dest+priv->width * priv->height, source+priv->width * priv->height*5/4, priv->width * priv->height/4);
-	return;
-    }
-
-    switch (priv->picture.palette) {
-    case VIDEO_PALETTE_RGB24:
-    case VIDEO_PALETTE_RGB32:
-    case VIDEO_PALETTE_RGB555:
-    case VIDEO_PALETTE_RGB565:
-	sptr = source + (priv->height-1)*priv->bytesperline;
-	for (i = 0; i < priv->height; i++) {
-	    memcpy(dest, sptr, priv->bytesperline);
-	    dest += priv->bytesperline;
-	    sptr -= priv->bytesperline;
-	}
-	break;
-    case VIDEO_PALETTE_UYVY:
-    case VIDEO_PALETTE_YUV420P:
-    default:
-	memcpy(dest, source, priv->bytesperline * priv->height);
-    }
-    
-}
-
-// maximum skew change, in frames
-#define MAX_SKEW_DELTA 0.6
-static void *video_grabber(void *data)
-{
-#define MAXTOL (priv->nbuf)
-    priv_t *priv = (priv_t*)data;
-    struct timeval curtime;
-    long long skew, prev_skew, xskew, interval, prev_interval;
-    int frame;
-    int i;
-    int framecount;
-    int tolerance;
-    unsigned long num;
-
-    /* start the capture process */
-
-    if ( tv_param_mjpeg )
-      {
-        mp_msg(MSGT_TV, MSGL_INFO, "  MJP: gonna capture ! \n");
-        for (i=0; i < priv->nbuf; i++) {
-	num = i;
-        if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)
-          {
-            mp_msg(MSGT_TV, MSGL_ERR, 
-	           "\n  MJP: ioctl MJPIOC_QBUF_CAPT b failed: %s\n", strerror(errno));
-          }
-	  }
-      }
-    else
-      {
-    for (i=0; i < priv->nbuf; i++) {
-	if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[i]) == -1)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno));
-	}
-      }
-    }
-
-    gettimeofday(&curtime, NULL);
-    priv->starttime = (long long)1e6*curtime.tv_sec + curtime.tv_usec;
-    priv->audio_skew_measure_time = 0;
-    pthread_mutex_unlock(&priv->audio_starter);
-    xskew = 0;
-    skew = 0;
-    interval = 0;
-
-    prev_interval = 0;
-    prev_skew = 0;
-
-    tolerance = MAXTOL;
-
-    for (framecount = 0; !priv->shutdown;)
-    {
-	for (i = 0; i < priv->nbuf && !priv->shutdown; i++, framecount++) {
-
-	    if (priv->immediate_mode) {
-		while (priv->video_cnt == priv->video_buffer_size_max) {
-		    usleep(10000);
-                    if (priv->shutdown) {
-                      return NULL;
-                    }
-		}
-	    }
-		
-	    frame = i;
-
-	    if ( tv_param_mjpeg )
-	    {
-	    while (ioctl(priv->video_fd, MJPIOC_SYNC, &priv->buf[frame].frame) < 0 &&
-		   (errno == EAGAIN || errno == EINTR));
-
-	    }
-	    else
-	    {
-	    while (ioctl(priv->video_fd, VIDIOCSYNC, &priv->buf[frame].frame) < 0 &&
-		   (errno == EAGAIN || errno == EINTR));
-	    }
-	    mp_dbg(MSGT_TV, MSGL_DBG3, "\npicture sync failed\n");
-
-	    gettimeofday(&curtime, NULL);
-	    if (!priv->immediate_mode) {
-		interval = (long long)1e6*curtime.tv_sec + curtime.tv_usec - priv->starttime;
-	    } else {
-		interval = (long long)1e6*framecount/priv->fps;
-	    }
-
-	    if (!priv->immediate_mode) {
-		long long period, orig_interval;
-
-		if (tolerance == 0) {
-		    if (interval - prev_interval == 0) {
-			mp_msg(MSGT_TV, MSGL_V, "\nvideo capture thread: frame delta = 0\n");
-		    } else if ((interval - prev_interval < (long long)0.85e6/priv->fps)
-			       || (interval - prev_interval > (long long)1.15e6/priv->fps) ) {
-			mp_msg(MSGT_TV, MSGL_V, "\nvideo capture thread: frame delta ~ %.1lf fps\n",
-			       (double)1e6/(interval - prev_interval));
-		    }
-		}
-
-		// correct the rate fluctuations on a small scale
-		orig_interval = interval;
-		period = priv->video_interval_sum/VIDEO_AVG_BUFFER_SIZE;
-		if (interval - prev_interval > 105*period/100) {
-		    if (tolerance > 0) {
-			mp_msg(MSGT_TV, MSGL_DBG3, "correcting timestamp\n");
-			interval = prev_interval + priv->video_interval_sum/VIDEO_AVG_BUFFER_SIZE;
-			tolerance--;
-		    } else {
-			mp_msg(MSGT_TV, MSGL_DBG3, "bad - frames were dropped\n");
-			tolerance = MAXTOL;
-		    }
-		} else {
-		    if (tolerance < MAXTOL) {
-			mp_msg(MSGT_TV, MSGL_DBG3, "fluctuation overcome\n");
-		    }
-		    tolerance = MAXTOL;
-		}
-		    
-		priv->video_interval_sum -= priv->video_avg_buffer[priv->video_avg_ptr];
-		priv->video_avg_buffer[priv->video_avg_ptr++] = orig_interval-prev_interval;
-		priv->video_interval_sum += orig_interval-prev_interval;
-		if (priv->video_avg_ptr >= VIDEO_AVG_BUFFER_SIZE) priv->video_avg_ptr = 0;
-
-//		fprintf(stderr, "fps: %lf\n", (double)1e6*VIDEO_AVG_BUFFER_SIZE/priv->video_interval_sum);
-		
-		// interpolate the skew in time
-		pthread_mutex_lock(&priv->skew_mutex);
-		xskew = priv->audio_skew + (interval - priv->audio_skew_measure_time)*priv->audio_skew_factor;
-		pthread_mutex_unlock(&priv->skew_mutex);
-		// correct extreme skew changes to avoid (especially) moving backwards in time
-		if (xskew - prev_skew > (interval - prev_interval)*MAX_SKEW_DELTA) {
-		    skew = prev_skew + (interval - prev_interval)*MAX_SKEW_DELTA;
-		} else if (xskew - prev_skew < -(interval - prev_interval)*MAX_SKEW_DELTA) {
-		    skew = prev_skew - (interval - prev_interval)*MAX_SKEW_DELTA;
-		} else {
-		    skew = xskew;
-		}
-	    }
-
-	    mp_msg(MSGT_TV, MSGL_DBG3, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
-		   (interval != prev_interval) ? (double)1e6/(interval - prev_interval) : -1,
-		   (double)1e-6*interval, (double)1e-6*xskew, (double)1e-6*skew);
-	    mp_msg(MSGT_TV, MSGL_DBG3, "vcnt = %d, acnt = %d\n", priv->video_cnt, priv->audio_cnt);
-
-	    prev_skew = skew;
-	    prev_interval = interval;
-
-	    /* allocate a new buffer, if needed */
-	    pthread_mutex_lock(&priv->video_buffer_mutex);
-	    if (priv->video_buffer_size_current < priv->video_buffer_size_max) {
-		if (priv->video_cnt == priv->video_buffer_size_current) {
-		    unsigned char *newbuf = calloc(priv->bytesperline, priv->height);
-		    if (newbuf) {
-			memmove(priv->video_ringbuffer+priv->video_tail+1, priv->video_ringbuffer+priv->video_tail,
-			       (priv->video_buffer_size_current-priv->video_tail)*sizeof(unsigned char *));
-			memmove(priv->video_timebuffer+priv->video_tail+1, priv->video_timebuffer+priv->video_tail,
-			       (priv->video_buffer_size_current-priv->video_tail)*sizeof(long long));
-			priv->video_ringbuffer[priv->video_tail] = newbuf;
-			if ((priv->video_head >= priv->video_tail) && (priv->video_cnt > 0)) priv->video_head++;
-			priv->video_buffer_size_current++;
-		    }
-		}
-	    }
-	    pthread_mutex_unlock(&priv->video_buffer_mutex);
-
-	    if (priv->video_cnt == priv->video_buffer_size_current) {
-		if (!priv->immediate_mode) {
-		    mp_msg(MSGT_TV, MSGL_ERR, "\nvideo buffer full - dropping frame\n");
-		}
-	    } else {
-		if (priv->immediate_mode) {
-		    priv->video_timebuffer[priv->video_tail] = interval;
-		} else {
-		    // compensate for audio skew
-		    // negative skew => there are more audio samples, increase interval
-		    // positive skew => less samples, shorten the interval
-		    priv->video_timebuffer[priv->video_tail] = interval - skew;
-		}
-		
-                if ( tv_param_mjpeg )
-		copy_frame(priv, priv->video_ringbuffer[priv->video_tail], 
-		           priv->mmap+(priv->mjpeg_bufsize)*i);
-		else
-		copy_frame(priv, priv->video_ringbuffer[priv->video_tail], priv->mmap+priv->mbuf.offsets[frame]);
-		priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current;
-		priv->video_cnt++;
-	    }
-
-            if ( tv_param_mjpeg )
-            {
-	      num = frame;
-              if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)
-                {
-                  mp_msg(MSGT_TV, MSGL_ERR, "\n  MJP: ioctl MJPIOC_QBUF_CAPT end failed: %s\n", 
-		                                    strerror(errno));
-		  continue;
-                }
-	    }
-	    else
-	    {
-	    if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[frame]) == -1)
-	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno));
-		continue;
-	    }
-	    }
-
-	}
-
-    }
-    mp_msg(MSGT_TV, MSGL_INFO, "  MJP: returning! \n");
-    return NULL;
-}
-
-static double grab_video_frame(priv_t *priv, char *buffer, int len)
-{
-    double interval;
-
-    if (priv->first) {
-	pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);
-	priv->first = 0;
-    }
-
-    while (priv->video_cnt == 0) {
-	usleep(10000);
-    }
-
-    pthread_mutex_lock(&priv->video_buffer_mutex);
-    interval = (double)priv->video_timebuffer[priv->video_head]*1e-6;
-    memcpy(buffer, priv->video_ringbuffer[priv->video_head], len);
-    priv->video_cnt--;
-    priv->video_head = (priv->video_head+1)%priv->video_buffer_size_current;
-    pthread_mutex_unlock(&priv->video_buffer_mutex);
-
-    return interval;
-}
-
-static int get_video_framesize(priv_t *priv)
-{
-    return(priv->bytesperline * priv->height);
-}
-
-static void *audio_grabber(void *data)
-{
-    priv_t *priv = (priv_t*)data;
-    struct timeval tv;
-    int i, audio_skew_ptr = 0;
-    long long current_time, prev_skew = 0;
-
-    pthread_mutex_lock(&priv->audio_starter);
-
-    audio_in_start_capture(&priv->audio_in);
-    for (i = 0; i < priv->aud_skew_cnt; i++)
-	priv->audio_skew_buffer[i] = 0;
-
-    for (; !priv->shutdown;)
-    {
-	if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0)
-	    continue;
-
-	gettimeofday(&tv, NULL);
-
-	priv->audio_recv_blocks_total++;
-	current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->starttime;
-
-	priv->audio_skew_total -= priv->audio_skew_buffer[audio_skew_ptr];
-	priv->audio_skew_buffer[audio_skew_ptr] = current_time
-	    - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total;
-	priv->audio_skew_total += priv->audio_skew_buffer[audio_skew_ptr];
-	audio_skew_ptr = (audio_skew_ptr+1) % priv->aud_skew_cnt;
-
-	pthread_mutex_lock(&priv->skew_mutex);
-	// linear interpolation - here we interpolate current skew value
-	// from the moving average, which we expect to be in the middle
-	// of the interval
-	if (priv->audio_recv_blocks_total > priv->aud_skew_cnt) {
-	    priv->audio_skew = priv->audio_skew_total/priv->aud_skew_cnt;
-	    priv->audio_skew += (priv->audio_skew*priv->aud_skew_cnt)/(2*priv->audio_recv_blocks_total-priv->aud_skew_cnt);
-	} else {
-	    // this smoothes the evolution of audio_skew at startup a bit
-	    priv->audio_skew = ((priv->aud_skew_cnt+priv->audio_recv_blocks_total)*priv->audio_skew_total)/(priv->aud_skew_cnt*priv->audio_recv_blocks_total);
-	}
-	// current skew factor (assuming linearity)
-	// used for further interpolation in video_grabber
-	// probably overkill but seems to be necessary for
-	// stress testing by dropping half of the audio frames ;)
-	// especially when using ALSA with large block sizes
-	// where audio_skew remains a long while behind
-	if ((priv->audio_skew_measure_time != 0) && (current_time - priv->audio_skew_measure_time != 0)) {
-	    priv->audio_skew_factor = (double)(priv->audio_skew-prev_skew)/(current_time - priv->audio_skew_measure_time);
-	} else {
-	    priv->audio_skew_factor = 0.0;
-	}
-	
-	priv->audio_skew_measure_time = current_time;
-	prev_skew = priv->audio_skew;
-	pthread_mutex_unlock(&priv->skew_mutex);
-	
-	if ((priv->audio_tail+1) % priv->audio_buffer_size == priv->audio_head) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "\ntoo bad - dropping audio frame !\n");
-	    priv->audio_drop++;
-	} else {
-	    priv->audio_tail = (priv->audio_tail+1) % priv->audio_buffer_size;
-	    priv->audio_cnt++;
-	}
-    }
-    return NULL;
-}
-
-static double grab_audio_frame(priv_t *priv, char *buffer, int len)
-{
-    mp_dbg(MSGT_TV, MSGL_DBG2, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
-	priv, buffer, len);
-
-    if (priv->first) {
-	pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);
-	priv->first = 0;
-    }
-
-    // compensate for dropped audio frames
-    if (priv->audio_drop && (priv->audio_head == priv->audio_tail)) {
-	priv->audio_drop--;
-	priv->audio_sent_blocks_total++;
-	memset(buffer, 0, len);
-	return (double)priv->audio_sent_blocks_total*priv->audio_secs_per_block;
-    }
-
-    while (priv->audio_head == priv->audio_tail) {
-	usleep(10000);
-    }
-    memcpy(buffer, priv->audio_ringbuffer+priv->audio_head*priv->audio_in.blocksize, len);
-    priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
-    priv->audio_cnt--;
-    priv->audio_sent_blocks_total++;
-    return (double)priv->audio_sent_blocks_total*priv->audio_secs_per_block;
-}
-
-static int get_audio_framesize(priv_t *priv)
-{
-    return(priv->audio_in.blocksize);
-}
--- a/libmpdemux/tvi_v4l2.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1746 +0,0 @@
-/*
-**  Video 4 Linux 2 input
-**
-**  This file is part of MPlayer, see http://mplayerhq.hu/ for info.  
-**
-**  (c) 2003 Martin Olschewski <olschewski@zpr.uni-koeln.de>
-**  (c) 2003 Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
-**  
-**  File licensed under the GPL, see http://www.fsf.org/ for more info.
-**
-**  Some ideas are based on works from
-**    Alex Beregszaszi <alex@fsn.hu>
-**    Gerd Knorr <kraxel@bytesex.org>
-**
-**  CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!
-*/
-
-/*
-
-known issues:
-- norm setting isn't consistent with tvi_v4l
-- the same for volume/bass/treble/balance
-
-*/
-
-#include "config.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#ifdef HAVE_SYS_SYSINFO_H
-#include <sys/sysinfo.h>
-#endif
-#include <linux/types.h>
-#include <linux/videodev2.h>
-#include "mp_msg.h"
-#include "libvo/img_format.h"
-#include "libaf/af_format.h"
-#include "tv.h"
-#include "audio_in.h"
-
-/* information about this file */
-static tvi_info_t info = {
-    "Video 4 Linux 2 input",
-    "v4l2",
-    "Martin Olschewski <olschewski@zpr.uni-koeln.de>",
-    "first try, more to come ;-)"
-};
-
-struct map {
-    struct v4l2_buffer buf;
-    void   *addr;
-    size_t len;
-};
-
-#define BUFFER_COUNT 6
-
-/* private data */
-typedef struct {
-    /* video */
-    char			*video_dev;
-    int				video_fd;
-    int                         mp_format;
-    struct v4l2_capability	capability;
-    struct v4l2_input           input;
-    struct v4l2_format		format;
-    struct v4l2_standard	standard;
-    struct v4l2_tuner		tuner;
-    struct map			*map;
-    int				mapcount;
-    int				frames;
-    volatile long long          first_frame;
-    long long                   curr_frame;
-    /* audio video interleaving ;-) */
-    volatile int		streamon;
-    pthread_t			audio_grabber_thread;
-    pthread_mutex_t		skew_mutex;
-
-    /* 2nd level video buffers */
-    int                         first;
-    int                         immediate_mode;
-
-    int                         video_buffer_size_max;
-    volatile int                video_buffer_size_current;
-    unsigned char		**video_ringbuffer;
-    long long                   *video_timebuffer;
-    volatile int		video_head;
-    volatile int		video_tail;
-    volatile int		video_cnt;
-    pthread_t			video_grabber_thread;
-    pthread_mutex_t             video_buffer_mutex;
-
-    /* audio */
-    char			*audio_dev;
-    audio_in_t                  audio_in;
-
-    long long                   audio_start_time;
-    int                         audio_buffer_size;
-    int                         aud_skew_cnt;
-    unsigned char		*audio_ringbuffer;
-    long long			*audio_skew_buffer;
-    long long			*audio_skew_delta_buffer;
-    volatile int		audio_head;
-    volatile int		audio_tail;
-    volatile int		audio_cnt;
-    volatile long long          audio_skew;
-    volatile double             audio_skew_factor;
-    volatile long long          audio_skew_measure_time;
-    volatile int                audio_drop;
-    volatile int                shutdown;
-
-    int                         audio_inited;
-    double                      audio_secs_per_block;
-    long long                   audio_usecs_per_block;
-    long long                   audio_skew_total;
-    long long                   audio_skew_delta_total;
-    long			audio_recv_blocks_total;
-    long			audio_sent_blocks_total;
-    pthread_mutex_t             audio_mutex;
-    int                         audio_insert_null_samples;
-    volatile long               audio_null_blocks_inserted;
-    volatile long long          dropped_frames_timeshift;
-    long long                   dropped_frames_compensated;
-} priv_t;
-
-#include "tvi_def.h"
-
-static void *audio_grabber(void *data);
-static void *video_grabber(void *data);
-
-/**********************************************************************\
-
-    Only few of the fourccs are the same in v4l2 and mplayer:
-
-    IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410
-    IMGFMT_YV12 == V4L2_PIX_FMT_YVU420
-    IMGFMT_NV12 == V4L2_PIX_FMT_NV12
-    IMGFMT_422P == V4L2_PIX_FMT_YUV422P
-    IMGFMT_411P == V4L2_PIX_FMT_YUV411P
-    IMGFMT_UYVY == V4L2_PIX_FMT_UYVY
-    IMGFMT_Y41P == V4L2_PIX_FMT_Y41P
-
-    This may be an useful translation table for some others:
-
-    IMGFMT_RGB8  == V4L2_PIX_FMT_RGB332
-    IMGFMT_BGR15 == V4L2_PIX_FMT_RGB555
-    IMGFMT_BGR16 == V4L2_PIX_FMT_RGB565
-    IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24
-    IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32
-    IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24
-    IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32
-    IMGFMT_Y800  == V4L2_PIX_FMT_GREY
-    IMGFMT_IF09  == V4L2_PIX_FMT_YUV410
-    IMGFMT_I420  == V4L2_PIX_FMT_YUV420
-    IMGFMT_YUY2  == V4L2_PIX_FMT_YUYV
-
-\**********************************************************************/
-
-/*
-** Translate a mplayer fourcc to a video4linux2 pixel format.
-*/
-static int fcc_mp2vl(int fcc)
-{
-    switch (fcc) {
-    case IMGFMT_RGB8:	return V4L2_PIX_FMT_RGB332;
-    case IMGFMT_BGR15:	return V4L2_PIX_FMT_RGB555;
-    case IMGFMT_BGR16:	return V4L2_PIX_FMT_RGB565;
-    case IMGFMT_RGB24:	return V4L2_PIX_FMT_RGB24;
-    case IMGFMT_RGB32:	return V4L2_PIX_FMT_RGB32;
-    case IMGFMT_BGR24:	return V4L2_PIX_FMT_BGR24;
-    case IMGFMT_BGR32:	return V4L2_PIX_FMT_BGR32;
-    case IMGFMT_Y800:	return V4L2_PIX_FMT_GREY;
-    case IMGFMT_IF09:	return V4L2_PIX_FMT_YUV410;
-    case IMGFMT_I420:	return V4L2_PIX_FMT_YUV420;
-    case IMGFMT_YUY2:	return V4L2_PIX_FMT_YUYV;
-    case IMGFMT_YV12:	return V4L2_PIX_FMT_YVU420;
-    case IMGFMT_UYVY:   return V4L2_PIX_FMT_UYVY;
-    }
-    return fcc;
-}
-
-/*
-** Translate a video4linux2 fourcc aka pixel format to mplayer.
-*/
-static int fcc_vl2mp(int fcc)
-{
-    switch (fcc) {
-    case V4L2_PIX_FMT_RGB332:	return IMGFMT_RGB8;
-    case V4L2_PIX_FMT_RGB555:	return IMGFMT_BGR15;
-    case V4L2_PIX_FMT_RGB565:	return IMGFMT_BGR16;
-    case V4L2_PIX_FMT_RGB24:	return IMGFMT_RGB24;
-    case V4L2_PIX_FMT_RGB32:	return IMGFMT_RGB32;
-    case V4L2_PIX_FMT_BGR24:	return IMGFMT_BGR24;
-    case V4L2_PIX_FMT_BGR32:	return IMGFMT_BGR32;
-    case V4L2_PIX_FMT_GREY:		return IMGFMT_Y800;
-    case V4L2_PIX_FMT_YUV410:	return IMGFMT_IF09;
-    case V4L2_PIX_FMT_YUV420:	return IMGFMT_I420;
-    case V4L2_PIX_FMT_YVU420:	return IMGFMT_YV12;
-    case V4L2_PIX_FMT_YUYV:		return IMGFMT_YUY2;
-    case V4L2_PIX_FMT_UYVY:     return IMGFMT_UYVY;
-    }
-    return fcc;
-}
-
-/*
-** Translate a video4linux2 fourcc aka pixel format
-** to a human readable string.
-*/
-static const char *pixfmt2name(int pixfmt)
-{
-    static char unknown[24];
-
-    switch (pixfmt) {
-    case V4L2_PIX_FMT_RGB332:	return "RGB332";
-    case V4L2_PIX_FMT_RGB555:	return "RGB555";
-    case V4L2_PIX_FMT_RGB565:	return "RGB565";
-    case V4L2_PIX_FMT_RGB555X:	return "RGB555X";
-    case V4L2_PIX_FMT_RGB565X:	return "RGB565X";
-    case V4L2_PIX_FMT_BGR24:	return "BGR24";
-    case V4L2_PIX_FMT_RGB24:	return "RGB24";
-    case V4L2_PIX_FMT_BGR32:	return "BGR32";
-    case V4L2_PIX_FMT_RGB32:	return "RGB32";
-    case V4L2_PIX_FMT_GREY:		return "GREY";
-    case V4L2_PIX_FMT_YVU410:	return "YVU410";
-    case V4L2_PIX_FMT_YVU420:	return "YVU420";
-    case V4L2_PIX_FMT_YUYV:		return "YUYV";
-    case V4L2_PIX_FMT_UYVY:		return "UYVY";
-/*	case V4L2_PIX_FMT_YVU422P:	return "YVU422P"; */
-/*	case V4L2_PIX_FMT_YVU411P:	return "YVU411P"; */
-    case V4L2_PIX_FMT_YUV422P:	return "YUV422P";
-    case V4L2_PIX_FMT_YUV411P:	return "YUV411P";
-    case V4L2_PIX_FMT_Y41P:		return "Y41P";
-    case V4L2_PIX_FMT_NV12:		return "NV12";
-    case V4L2_PIX_FMT_NV21:		return "NV21";
-    case V4L2_PIX_FMT_YUV410:	return "YUV410";
-    case V4L2_PIX_FMT_YUV420:	return "YUV420";
-    case V4L2_PIX_FMT_YYUV:		return "YYUV";
-    case V4L2_PIX_FMT_HI240:	return "HI240";
-    case V4L2_PIX_FMT_WNVA:		return "WNVA";
-    }
-    sprintf(unknown, "unknown (0x%x)", pixfmt);
-    return unknown;
-}
-
-
-/*
-** Gives the depth of a video4linux2 fourcc aka pixel format in bits.
-*/
-static int pixfmt2depth(int pixfmt)
-{
-    switch (pixfmt) {
-    case V4L2_PIX_FMT_RGB332:
-	return 8;
-    case V4L2_PIX_FMT_RGB555:
-    case V4L2_PIX_FMT_RGB565:
-    case V4L2_PIX_FMT_RGB555X:
-    case V4L2_PIX_FMT_RGB565X:
-	return 16;
-    case V4L2_PIX_FMT_BGR24:
-    case V4L2_PIX_FMT_RGB24:
-	return 24;
-    case V4L2_PIX_FMT_BGR32:
-    case V4L2_PIX_FMT_RGB32:
-	return 32;
-    case V4L2_PIX_FMT_GREY:
-	return 8;
-    case V4L2_PIX_FMT_YVU410:
-	return 9;
-    case V4L2_PIX_FMT_YVU420:
-	return 12;
-    case V4L2_PIX_FMT_YUYV:
-    case V4L2_PIX_FMT_UYVY:
-    case V4L2_PIX_FMT_YUV422P:
-    case V4L2_PIX_FMT_YUV411P:
-	return 16;
-    case V4L2_PIX_FMT_Y41P:
-    case V4L2_PIX_FMT_NV12:
-    case V4L2_PIX_FMT_NV21:
-	return 12;
-    case V4L2_PIX_FMT_YUV410:
-	return 9;
-    case V4L2_PIX_FMT_YUV420:
-	return 12;
-    case V4L2_PIX_FMT_YYUV:
-	return 16;
-    case V4L2_PIX_FMT_HI240:
-	return 8;
-
-    }
-    return 0;
-}
-
-static int amode2v4l(int amode) 
-{
-    switch (amode) {
-    case 0:
-	return V4L2_TUNER_MODE_MONO;
-    case 1:
-	return V4L2_TUNER_MODE_STEREO;
-    case 2:
-	return V4L2_TUNER_MODE_LANG1;
-    case 3:
-	return V4L2_TUNER_MODE_LANG2;
-    default:
-	return -1;
-    }
-}
-
-
-// sets and sanitizes audio buffer/block sizes
-static void setup_audio_buffer_sizes(priv_t *priv)
-{
-    int bytes_per_sample = priv->audio_in.bytes_per_sample;
-    double fps = (double)priv->standard.frameperiod.denominator /
-	priv->standard.frameperiod.numerator;
-    int seconds = priv->video_buffer_size_max/fps;
-
-    if (seconds < 5) seconds = 5;
-    if (seconds > 500) seconds = 500;
-
-    // make the audio buffer at least as the video buffer capacity (or 5 seconds) long
-    priv->audio_buffer_size = 1 + seconds*priv->audio_in.samplerate
-	*priv->audio_in.channels
-	*bytes_per_sample/priv->audio_in.blocksize;
-    if (priv->audio_buffer_size < 256) priv->audio_buffer_size = 256;
-
-    // make the skew buffer at least 1 second long
-    priv->aud_skew_cnt = 1 + 1*priv->audio_in.samplerate
-	*priv->audio_in.channels
-	*bytes_per_sample/priv->audio_in.blocksize;
-    if (priv->aud_skew_cnt < 16) priv->aud_skew_cnt = 16;
-
-    mp_msg(MSGT_TV, MSGL_V, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
-	   priv->audio_buffer_size, priv->audio_in.blocksize, priv->aud_skew_cnt);
-}
-
-static void init_audio(priv_t *priv)
-{
-    if (priv->audio_inited) return;
-
-    if (!tv_param_noaudio) {
-#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
-	if (tv_param_alsa)
-	    audio_in_init(&priv->audio_in, AUDIO_IN_ALSA);
-	else
-	    audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
-#else
-	audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
-#endif
-
-	if (priv->audio_dev) {
-	    audio_in_set_device(&priv->audio_in, priv->audio_dev);
-	}
-
-	audio_in_set_samplerate(&priv->audio_in, 44100);
-	if (priv->capability.capabilities & V4L2_CAP_TUNER) {
-	    if (priv->tuner.audmode == V4L2_TUNER_MODE_STEREO) {
-		audio_in_set_channels(&priv->audio_in, 2);
-	    } else {
-		audio_in_set_channels(&priv->audio_in, 1);
-	    }
-	} else {
-	    if (tv_param_forcechan >= 0) {
-		audio_in_set_channels(&priv->audio_in, tv_param_forcechan);
-	    } else {
-		audio_in_set_channels(&priv->audio_in, 2);
-	    }
-	}
-
-	if (audio_in_setup(&priv->audio_in) < 0) return;
-
-	priv->audio_inited = 1;
-    }
-}
-
-#if 0
-/*
-** the number of milliseconds elapsed between time0 and time1
-*/
-static size_t difftv(struct timeval time1, struct timeval time0)
-{
-    return	(time1.tv_sec  - time0.tv_sec)  * 1000 +
-	(time1.tv_usec - time0.tv_usec) / 1000;
-}
-#endif
-
-/*
-** Get current video capture format.
-*/
-static int getfmt(priv_t *priv)
-{
-    int i;
-
-    priv->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if ((i = ioctl(priv->video_fd, VIDIOC_G_FMT, &priv->format)) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get format failed: %s\n",
-	       info.short_name, strerror(errno));
-    }
-    return i;
-}
-
-
-/*
-** Get current video capture standard.
-*/
-static int getstd(priv_t *priv)
-{
-    v4l2_std_id id;
-    int i=0;
-
-    if (ioctl(priv->video_fd, VIDIOC_G_STD, &id) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get standard failed: %s\n",
-	       info.short_name, strerror(errno));
-	return -1;
-    }
-    do {
-	priv->standard.index = i++;
-	if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) {
-	    return -1;
-	}
-    } while (priv->standard.id != id);
-    return 0;
-}
-
-/***********************************************************************\
- *									*
- *									*
- *	Interface to mplayer						*
- *									*
- *									*
-\***********************************************************************/
-
-static int set_mute(priv_t *priv, int value) 
-{
-    struct v4l2_control control;
-    control.id = V4L2_CID_AUDIO_MUTE;
-    control.value = value;
-    if (ioctl(priv->video_fd, VIDIOC_S_CTRL, &control) < 0) {
-	mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set mute failed: %s\n",
-	       info.short_name, strerror(errno));
-	return 0;
-    }
-    return 1;
-}
-
-/*
-** MPlayer uses values from -100 up to 100 for controls.
-** Here they are scaled to what the tv card needs and applied.
-*/
-static int set_control(priv_t *priv, struct v4l2_control *control, int val_signed) {
-    struct v4l2_queryctrl	qctrl;
-
-    qctrl.id = control->id;
-    if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n",
-	 info.short_name, strerror(errno));
-	return TVI_CONTROL_FALSE;
-    }
-
-    if (val_signed) {
-	if (control->value < 0) {
-	    control->value = qctrl.default_value + control->value *
-		(qctrl.default_value - qctrl.minimum) / 100;
-	} else {
-	    control->value = qctrl.default_value + control->value *
-		(qctrl.maximum - qctrl.default_value) / 100;
-	}
-    } else {
-	if (control->value < 50) {
-	    control->value = qctrl.default_value + (control->value-50) *
-		(qctrl.default_value - qctrl.minimum) / 50;
-	} else {
-	    control->value = qctrl.default_value + (control->value-50) *
-		(qctrl.maximum - qctrl.default_value) / 50;
-	}
-    }
-    
-
-    if (ioctl(priv->video_fd, VIDIOC_S_CTRL, control) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl set %s %d failed: %s\n",
-	 info.short_name, qctrl.name, control->value, strerror(errno));
-	return TVI_CONTROL_FALSE;
-    }
-    mp_msg(MSGT_TV, MSGL_V, "%s: set %s: %d [%d, %d]\n", info.short_name,
-     qctrl.name, control->value, qctrl.minimum, qctrl.maximum);
-
-    return TVI_CONTROL_TRUE;
-}
-
-
-/*
-** Scale the control values back to what mplayer needs.
-*/
-static int get_control(priv_t *priv, struct v4l2_control *control, int val_signed) {
-    struct v4l2_queryctrl	qctrl;
-
-    qctrl.id = control->id;
-    if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n",
-	 info.short_name, strerror(errno));
-	return TVI_CONTROL_FALSE;
-    }
-
-    if (ioctl(priv->video_fd, VIDIOC_G_CTRL, control) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl get %s failed: %s\n",
-	 info.short_name, qctrl.name, strerror(errno));
-	return TVI_CONTROL_FALSE;
-    }
-    mp_msg(MSGT_TV, MSGL_V, "%s: get %s: %d [%d, %d]\n", info.short_name,
-     qctrl.name, control->value, qctrl.minimum, qctrl.maximum);
-
-    if (val_signed) {
-	if (control->value < qctrl.default_value) {
-	    control->value = (control->value - qctrl.default_value) * 100 /
-		(qctrl.default_value - qctrl.minimum);
-	} else {
-	    control->value = (control->value - qctrl.default_value) * 100 /
-		(qctrl.maximum - qctrl.default_value);
-	}
-    } else {
-	if (control->value < qctrl.default_value) {
-	    control->value = (control->value - qctrl.default_value) * 50 /
-		(qctrl.default_value - qctrl.minimum) + 50;
-	} else {
-	    control->value = (control->value - qctrl.default_value) * 50 /
-		(qctrl.maximum - qctrl.default_value) + 50;
-	}
-    }
-
-    return TVI_CONTROL_TRUE;
-}
-
-static int control(priv_t *priv, int cmd, void *arg)
-{
-    struct v4l2_control control;
-    struct v4l2_frequency frequency;
-
-    switch(cmd) {
-    case TVI_CONTROL_IS_VIDEO:
-	return priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE?
-	    TVI_CONTROL_TRUE: TVI_CONTROL_FALSE;
-    case TVI_CONTROL_IS_AUDIO:
-	if (tv_param_force_audio) return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_IS_TUNER:
-	return priv->capability.capabilities & V4L2_CAP_TUNER?
-	    TVI_CONTROL_TRUE: TVI_CONTROL_FALSE;
-    case TVI_CONTROL_IMMEDIATE:
-	priv->immediate_mode = 1;
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_GET_FPS:
-	*(float *)arg = (float)priv->standard.frameperiod.denominator /
-	    priv->standard.frameperiod.numerator;
-	mp_msg(MSGT_TV, MSGL_V, "%s: get fps: %f\n", info.short_name,
-	       *(float *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_GET_BITS:
-	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
-	*(int *)arg = pixfmt2depth(priv->format.fmt.pix.pixelformat);
-	mp_msg(MSGT_TV, MSGL_V, "%s: get depth: %d\n", info.short_name,
-	       *(int *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_GET_FORMAT:
-	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
-	*(int *)arg = fcc_vl2mp(priv->format.fmt.pix.pixelformat);
-	mp_msg(MSGT_TV, MSGL_V, "%s: get format: %s\n", info.short_name,
-	       pixfmt2name(priv->format.fmt.pix.pixelformat));
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_SET_FORMAT:
-	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
-	priv->format.fmt.pix.pixelformat = fcc_mp2vl(*(int *)arg);
-	priv->format.fmt.pix.field = V4L2_FIELD_ANY;
-	    
-	priv->mp_format = *(int *)arg;
-	mp_msg(MSGT_TV, MSGL_V, "%s: set format: %s\n", info.short_name,
-	       pixfmt2name(priv->format.fmt.pix.pixelformat));
-	if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set format failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	/* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers
-	  might even always return the default parameters -> update the format here*/
-	priv->mp_format = fcc_vl2mp(priv->format.fmt.pix.pixelformat);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_GET_WIDTH:
-	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
-	*(int *)arg = priv->format.fmt.pix.width;
-	mp_msg(MSGT_TV, MSGL_V, "%s: get width: %d\n", info.short_name,
-	       *(int *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_CHK_WIDTH:
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_SET_WIDTH:
-	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
-	priv->format.fmt.pix.width = *(int *)arg;
-	mp_msg(MSGT_TV, MSGL_V, "%s: set width: %d\n", info.short_name,
-	       *(int *)arg);
-	if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set width failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_GET_HEIGHT:
-	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
-	*(int *)arg = priv->format.fmt.pix.height;
-	mp_msg(MSGT_TV, MSGL_V, "%s: get height: %d\n", info.short_name,
-	       *(int *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_CHK_HEIGHT:
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_VID_SET_HEIGHT:
-	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
-	priv->format.fmt.pix.height = *(int *)arg;
-	priv->format.fmt.pix.field = V4L2_FIELD_ANY;
-	mp_msg(MSGT_TV, MSGL_V, "%s: set height: %d\n", info.short_name,
-	       *(int *)arg);
-	if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set height failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	return TVI_CONTROL_TRUE;
-	case TVI_CONTROL_VID_GET_BRIGHTNESS:
-	    control.id = V4L2_CID_BRIGHTNESS;
-	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
-		*(int *)arg = control.value;
-		return TVI_CONTROL_TRUE;
-	    }
-	    return TVI_CONTROL_FALSE;
-	case TVI_CONTROL_VID_SET_BRIGHTNESS:
-	    control.id = V4L2_CID_BRIGHTNESS;
-	    control.value = *(int *)arg;
-	    return set_control(priv, &control, 1);
-	case TVI_CONTROL_VID_GET_HUE:
-	    control.id = V4L2_CID_HUE;
-	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
-		*(int *)arg = control.value;
-		return TVI_CONTROL_TRUE;
-	    }
-	    return TVI_CONTROL_FALSE;
-	case TVI_CONTROL_VID_SET_HUE:
-	    control.id = V4L2_CID_HUE;
-	    control.value = *(int *)arg;
-	    return set_control(priv, &control, 1);
-	case TVI_CONTROL_VID_GET_SATURATION:
-	    control.id = V4L2_CID_SATURATION;
-	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
-		*(int *)arg = control.value;
-		return TVI_CONTROL_TRUE;
-	    }
-	    return TVI_CONTROL_FALSE;
-	case TVI_CONTROL_VID_SET_SATURATION:
-	    control.id = V4L2_CID_SATURATION;
-	    control.value = *(int *)arg;
-	    return set_control(priv, &control, 1);
-	case TVI_CONTROL_VID_GET_CONTRAST:
-	    control.id = V4L2_CID_CONTRAST;
-	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
-		*(int *)arg = control.value;
-		return TVI_CONTROL_TRUE;
-	    }
-	    return TVI_CONTROL_FALSE;
-	case TVI_CONTROL_VID_SET_CONTRAST:
-	    control.id = V4L2_CID_CONTRAST;
-	    control.value = *(int *)arg;
-	    return set_control(priv, &control, 1);
-    case TVI_CONTROL_TUN_GET_FREQ:
-	frequency.tuner = 0;
-	frequency.type  = V4L2_TUNER_ANALOG_TV;
-	if (ioctl(priv->video_fd, VIDIOC_G_FREQUENCY, &frequency) < 0) {
-	    mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl get frequency failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	*(int *)arg = frequency.frequency;
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_TUN_SET_FREQ:
-#if 0
-	set_mute(priv, 1);
-	usleep(100000); // wait to suppress noise during switching
-#endif
-	frequency.tuner = 0;
-	frequency.type  = V4L2_TUNER_ANALOG_TV;
-	frequency.frequency = *(int *)arg;
-	if (ioctl(priv->video_fd, VIDIOC_S_FREQUENCY, &frequency) < 0) {
-	    mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set frequency failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-#if 0
-	usleep(100000); // wait to suppress noise during switching
-	set_mute(priv, 0);
-#endif
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_TUN_GET_TUNER:
-	mp_msg(MSGT_TV, MSGL_V, "%s: get tuner\n",info.short_name);
-	if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_TUN_SET_TUNER:
-	mp_msg(MSGT_TV, MSGL_V, "%s: set tuner\n",info.short_name);
-	if (ioctl(priv->video_fd, VIDIOC_S_TUNER, &priv->tuner) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set tuner failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_TUN_GET_NORM:
-	*(int *)arg = priv->standard.index;
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_TUN_SET_NORM:
-	priv->standard.index = *(int *)arg;
-	if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum norm failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	mp_msg(MSGT_TV, MSGL_V, "%s: set norm: %s\n", info.short_name, priv->standard.name);
-	if (ioctl(priv->video_fd, VIDIOC_S_STD, &priv->standard.id) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set norm failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_SPC_GET_NORMID:
-	{
-	    int i;
-	    for (i = 0;; i++) {
-		struct v4l2_standard standard;
-		memset(&standard, 0, sizeof(standard));
-		standard.index = i;
-		if (-1 == ioctl(priv->video_fd, VIDIOC_ENUMSTD, &standard))
-		    return TVI_CONTROL_FALSE;
-		if (!strcasecmp(standard.name, (char *)arg)) {
-		    *(int *)arg = i;
-		    return TVI_CONTROL_TRUE;
-		}
-	    }
-	    return TVI_CONTROL_FALSE;
-	}
-    case TVI_CONTROL_SPC_GET_INPUT:
-	if (ioctl(priv->video_fd, VIDIOC_G_INPUT, (int *)arg) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get input failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_SPC_SET_INPUT:
-	mp_msg(MSGT_TV, MSGL_V, "%s: set input: %d\n", info.short_name, *(int *)arg);
-	priv->input.index = *(int *)arg;
-	if (ioctl(priv->video_fd, VIDIOC_ENUMINPUT, &priv->input) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum input failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	if (ioctl(priv->video_fd, VIDIOC_S_INPUT, (int *)arg) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set input failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return TVI_CONTROL_FALSE;
-	}
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_AUD_GET_FORMAT:
-	init_audio(priv);
-	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
-	*(int *)arg = AF_FORMAT_S16_LE;
-	mp_msg(MSGT_TV, MSGL_V, "%s: get audio format: %d\n",
-	       info.short_name, *(int *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_AUD_GET_SAMPLERATE:
-	init_audio(priv);
-	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
-	*(int *)arg = priv->audio_in.samplerate;
-	mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplerate: %d\n",
-	       info.short_name, *(int *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_AUD_GET_SAMPLESIZE:
-	init_audio(priv);
-	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
-	*(int *)arg = priv->audio_in.bytes_per_sample;
-	mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplesize: %d\n",
-	       info.short_name, *(int *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_AUD_GET_CHANNELS:
-	init_audio(priv);
-	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
-	*(int *)arg = priv->audio_in.channels;
-	mp_msg(MSGT_TV, MSGL_V, "%s: get audio channels: %d\n",
-	       info.short_name, *(int *)arg);
-	return TVI_CONTROL_TRUE;
-    case TVI_CONTROL_AUD_SET_SAMPLERATE:
-	init_audio(priv);
-	mp_msg(MSGT_TV, MSGL_V, "%s: set audio samplerate: %d\n",
-	       info.short_name, *(int *)arg);
-	if (audio_in_set_samplerate(&priv->audio_in, *(int*)arg) < 0) return TVI_CONTROL_FALSE;
-//	setup_audio_buffer_sizes(priv);
-	return TVI_CONTROL_TRUE;
-    }
-    mp_msg(MSGT_TV, MSGL_V, "%s: unknown control: %d\n", info.short_name, cmd);
-    return(TVI_CONTROL_UNKNOWN);
-}
-
-
-#define PRIV ((priv_t *) (tvi_handle->priv))
-
-/* handler creator - entry point ! */
-tvi_handle_t *tvi_init_v4l2(char *video_dev, char *audio_dev)
-{
-    tvi_handle_t *tvi_handle;
-
-    /* new_handle initializes priv with memset 0 */
-    tvi_handle = new_handle();
-    if (!tvi_handle) {
-	return NULL;
-    }
-    PRIV->video_fd = -1;
-
-    PRIV->video_dev = strdup(video_dev? video_dev: "/dev/video0");
-    if (!PRIV->video_dev) {
-	free_handle(tvi_handle);
-	return NULL;
-    }
-
-    if (audio_dev) {
-	PRIV->audio_dev = strdup(audio_dev);
-	if (!PRIV->audio_dev) {
-	    free(PRIV->video_dev);
-	    free_handle(tvi_handle);
-	    return NULL;
-	}
-    }
-
-    return tvi_handle;
-}
-
-#undef PRIV
-
-
-static int uninit(priv_t *priv)
-{
-    int i, frames, dropped = 0;
-
-    priv->shutdown = 1;
-    if(priv->video_grabber_thread)
-	pthread_join(priv->video_grabber_thread, NULL);
-    pthread_mutex_destroy(&priv->video_buffer_mutex);
-
-    if (priv->streamon) {
-	struct v4l2_buffer buf;
-
-	/* get performance */
-	frames = 1 + (priv->curr_frame - priv->first_frame +
-		      priv->standard.frameperiod.numerator * 500000 /
-		      priv->standard.frameperiod.denominator) *
-	    priv->standard.frameperiod.denominator /
-	    priv->standard.frameperiod.numerator / 1000000;
-	dropped = frames - priv->frames;
-
-	/* turn off streaming */
-	if (ioctl(priv->video_fd, VIDIOC_STREAMOFF, &(priv->map[0].buf.type)) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl streamoff failed: %s\n",
-		   info.short_name, strerror(errno));
-	}
-	priv->streamon = 0;
-
-	/* unqueue all remaining buffers */
-	memset(&buf,0,sizeof(buf));
-	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	while (!ioctl(priv->video_fd, VIDIOC_DQBUF, &buf));
-    }
-
-    /* unmap all buffers */
-    for (i = 0; i < priv->mapcount; i++) {
-	if (munmap(priv->map[i].addr, priv->map[i].len) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: munmap capture buffer failed: %s\n",
-		   info.short_name, strerror(errno));
-	}
-    }
-
-    /* stop audio thread */
-    if (!tv_param_noaudio && priv->audio_grabber_thread) {
-	pthread_join(priv->audio_grabber_thread, NULL);
-	pthread_mutex_destroy(&priv->skew_mutex);
-	pthread_mutex_destroy(&priv->audio_mutex);
-    }
-
-    set_mute(priv, 1);
-
-    /* free memory and close device */
-    free(priv->map);		priv->map = NULL;
-    priv->mapcount = 0;
-    if(priv->video_fd!=-1)close(priv->video_fd);	priv->video_fd  = -1;
-    free(priv->video_dev);	priv->video_dev = NULL;
-
-    if (priv->video_ringbuffer) {
-	int i;
-	for (i = 0; i < priv->video_buffer_size_current; i++) {
-	    free(priv->video_ringbuffer[i]);
-	}
-	free(priv->video_ringbuffer);
-    }
-    if (priv->video_timebuffer)
-	free(priv->video_timebuffer);
-    if (!tv_param_noaudio) {
-	if (priv->audio_ringbuffer)
-	    free(priv->audio_ringbuffer);
-	if (priv->audio_skew_buffer)
-	    free(priv->audio_skew_buffer);
-	if (priv->audio_skew_delta_buffer)
-	    free(priv->audio_skew_delta_buffer);
-    }
-
-    /* show some nice statistics ;-) */
-    mp_msg(MSGT_TV, MSGL_INFO,
-	   "%s: %d frames successfully processed, %d frames dropped.\n",
-	   info.short_name, priv->frames, dropped);
-    mp_msg(MSGT_TV, MSGL_V, "%s: up to %u video frames buffered.\n",
-	   info.short_name, priv->video_buffer_size_current);
-    return 1;
-}
-
-
-/* initialisation */
-static int init(priv_t *priv)
-{
-    int i;
-
-    priv->audio_ringbuffer = NULL;
-    priv->audio_skew_buffer = NULL;
-    priv->audio_skew_delta_buffer = NULL;
-
-    priv->audio_inited = 0;
-
-    /* Open the video device. */
-    priv->video_fd = open(priv->video_dev, O_RDWR);
-    if (priv->video_fd < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: unable to open '%s': %s\n",
-	       info.short_name, priv->video_dev, strerror(errno));
-	uninit(priv);
-	return 0;
-    }
-    mp_msg(MSGT_TV, MSGL_DBG2, "%s: video fd: %s: %d\n",
-	   info.short_name, priv->video_dev, priv->video_fd);
-
-    /*
-    ** Query the video capabilities and current settings
-    ** for further control calls.
-    */
-    if (ioctl(priv->video_fd, VIDIOC_QUERYCAP, &priv->capability) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query capabilities failed: %s\n",
-	       info.short_name, strerror(errno));
-	uninit(priv);
-	return 0;
-    }
-
-    if (!(priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE))
-    {
-	mp_msg(MSGT_TV, MSGL_ERR, "Device %s is not a video capture device.\n",
-	       priv->video_dev);
-	return 0;
-    }
-
-    if (getfmt(priv) < 0) {
-	uninit(priv);
-	return 0;
-    }
-    getstd(priv);
-    /*
-    ** if this device has got a tuner query it's settings
-    ** otherwise set some nice defaults
-    */
-    if (priv->capability.capabilities & V4L2_CAP_TUNER) {
-	if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n",
-		   info.short_name, strerror(errno));
-	    uninit(priv);
-	    return 0;
-	}
-    }
-    mp_msg(MSGT_TV, MSGL_INFO, "Selected device: %s\n", priv->capability.card);
-    if (priv->capability.capabilities & V4L2_CAP_TUNER) {
-	mp_msg(MSGT_TV, MSGL_INFO, " Tuner cap:%s%s%s\n",
-		(priv->tuner.capability & V4L2_TUNER_CAP_STEREO) ? " STEREO" : "",
-		(priv->tuner.capability & V4L2_TUNER_CAP_LANG1)  ? " LANG1"  : "",
-		(priv->tuner.capability & V4L2_TUNER_CAP_LANG2)  ? " LANG2"  : "");
-	mp_msg(MSGT_TV, MSGL_INFO, " Tuner rxs:%s%s%s%s\n",
-		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_MONO)   ? " MONO"   : "",
-		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_STEREO) ? " STEREO" : "",
-		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_LANG1)  ? " LANG1"  : "",
-		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_LANG2)  ? " LANG2"  : "");
-    }
-    mp_msg(MSGT_TV, MSGL_INFO, " Capabilites:%s%s%s%s%s%s%s%s%s%s%s\n",
-	   priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE?
-	   "  video capture": "",
-	   priv->capability.capabilities & V4L2_CAP_VIDEO_OUTPUT?
-	   "  video output": "",
-	   priv->capability.capabilities & V4L2_CAP_VIDEO_OVERLAY?
-	   "  video overlay": "",
-	   priv->capability.capabilities & V4L2_CAP_VBI_CAPTURE?
-	   "  VBI capture device": "",
-	   priv->capability.capabilities & V4L2_CAP_VBI_OUTPUT?
-	   "  VBI output": "",
-	   priv->capability.capabilities & V4L2_CAP_RDS_CAPTURE?
-	   "  RDS data capture": "",
-	   priv->capability.capabilities & V4L2_CAP_TUNER?
-	   "  tuner": "",
-	   priv->capability.capabilities & V4L2_CAP_AUDIO?
-	   "  audio": "",
-	   priv->capability.capabilities & V4L2_CAP_READWRITE?
-	   "  read/write": "",
-	   priv->capability.capabilities & V4L2_CAP_ASYNCIO?
-	   "  async i/o": "",
-	   priv->capability.capabilities & V4L2_CAP_STREAMING?
-	   "  streaming": "");
-    mp_msg(MSGT_TV, MSGL_INFO, " supported norms:");
-    for (i = 0;; i++) {
-	struct v4l2_standard standard;
-	memset(&standard, 0, sizeof(standard));
-	standard.index = i;
-	if (-1 == ioctl(priv->video_fd, VIDIOC_ENUMSTD, &standard))
-	    break;
-	mp_msg(MSGT_TV, MSGL_INFO, " %d = %s;", i, standard.name);
-    }
-    mp_msg(MSGT_TV, MSGL_INFO, "\n inputs:");
-    for (i = 0; 1; i++) {
-	struct v4l2_input input;
-
-	input.index = i;
-	if (ioctl(priv->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
-	    break;
-	}
-	mp_msg(MSGT_TV, MSGL_INFO, " %d = %s;", i, input.name);
-    }
-    if (ioctl(priv->video_fd, VIDIOC_G_INPUT, &i) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get input failed: %s\n",
-	       info.short_name, strerror(errno));
-    }
-    mp_msg(MSGT_TV, MSGL_INFO, "\n Current input: %d\n", i);
-    for (i = 0; ; i++) {
-	struct v4l2_fmtdesc fmtdesc;
-
-	fmtdesc.index = i;
-	fmtdesc.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	if (ioctl(priv->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0) {
-	    break;
-	}
-	mp_msg(MSGT_TV, MSGL_V, " Format %-6s (%2d bits, %s): %s\n",
-	       pixfmt2name(fmtdesc.pixelformat), pixfmt2depth(fmtdesc.pixelformat),
-	       fmtdesc.description, vo_format_name(fcc_vl2mp(fmtdesc.pixelformat)));
-    }
-    mp_msg(MSGT_TV, MSGL_INFO, " Current format: %s\n",
-	   pixfmt2name(priv->format.fmt.pix.pixelformat));
-
-    /* set some nice defaults */
-    if (getfmt(priv) < 0) return 0;
-    priv->format.fmt.pix.width  = 640;
-    priv->format.fmt.pix.height = 480;
-    if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set format failed: %s\n",
-	       info.short_name, strerror(errno));
-	uninit(priv);
-	return 0;
-    }
-
-//    if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !tv_param_force_audio) tv_param_noaudio = 1;
-
-    if (priv->capability.capabilities & V4L2_CAP_TUNER) {
-	struct v4l2_control control;
-	if (tv_param_amode >= 0) {
-	    mp_msg(MSGT_TV, MSGL_V, "%s: setting audio mode\n", info.short_name);
-	    priv->tuner.audmode = amode2v4l(tv_param_amode);
-	    if (ioctl(priv->video_fd, VIDIOC_S_TUNER, &priv->tuner) < 0) {
-		mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set tuner failed: %s\n",
-		       info.short_name, strerror(errno));
-		return TVI_CONTROL_FALSE;
-	    }
-	}
-	mp_msg(MSGT_TV, MSGL_INFO, "%s: current audio mode is :%s%s%s%s\n", info.short_name,
-		(priv->tuner.audmode == V4L2_TUNER_MODE_MONO)   ? " MONO"   : "",
-		(priv->tuner.audmode == V4L2_TUNER_MODE_STEREO) ? " STEREO" : "",
-		(priv->tuner.audmode == V4L2_TUNER_MODE_LANG1)  ? " LANG1"  : "",
-		(priv->tuner.audmode == V4L2_TUNER_MODE_LANG2)  ? " LANG2"  : "");
-
-	if (tv_param_volume >= 0) {
-	    control.id = V4L2_CID_AUDIO_VOLUME;
-	    control.value = tv_param_volume;
-	    set_control(priv, &control, 0);
-	}
-	if (tv_param_bass >= 0) {
-	    control.id = V4L2_CID_AUDIO_BASS;
-	    control.value = tv_param_bass;
-	    set_control(priv, &control, 0);
-	}
-	if (tv_param_treble >= 0) {
-	    control.id = V4L2_CID_AUDIO_TREBLE;
-	    control.value = tv_param_treble;
-	    set_control(priv, &control, 0);
-	}
-	if (tv_param_balance >= 0) {
-	    control.id = V4L2_CID_AUDIO_BALANCE;
-	    control.value = tv_param_balance;
-	    set_control(priv, &control, 0);
-	}
-    }
-
-    return 1;
-}
-
-static int get_capture_buffer_size(priv_t *priv)
-{
-    int bufsize, cnt;
-    int w = priv->format.fmt.pix.width;
-    int h = priv->format.fmt.pix.height;
-    int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
-    int bytesperline = w*d/8;
-
-    if (tv_param_buffer_size >= 0) {
-	bufsize = tv_param_buffer_size*1024*1024;
-    } else {
-#ifdef HAVE_SYS_SYSINFO_H
-	struct sysinfo si;
-	
-	sysinfo(&si);
-	if (si.totalram<2*1024*1024) {
-	    bufsize = 1024*1024;
-	} else {
-	    bufsize = si.totalram/2;
-	}
-#else
-	bufsize = 16*1024*1024;
-#endif
-    }
-    
-    cnt = bufsize/(h*bytesperline);
-    if (cnt < 2) cnt = 2;
-    
-    return cnt;
-}
-
-/* that's the real start, we'got the format parameters (checked with control) */
-static int start(priv_t *priv)
-{
-    struct v4l2_requestbuffers request;
-    int i;
-
-    /* setup audio parameters */
-
-    init_audio(priv);
-    if (!tv_param_noaudio && !priv->audio_inited) return 0;
-
-    /* we need this to size the audio buffer properly */
-    if (priv->immediate_mode) {
-	priv->video_buffer_size_max = 2;
-    } else {
-	priv->video_buffer_size_max = get_capture_buffer_size(priv);
-    }
-    
-    if (!tv_param_noaudio) {
-	setup_audio_buffer_sizes(priv);
-	priv->audio_skew_buffer = calloc(priv->aud_skew_cnt, sizeof(long long));
-	if (!priv->audio_skew_buffer) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
-	    return 0;
-	}
-	priv->audio_skew_delta_buffer = calloc(priv->aud_skew_cnt, sizeof(long long));
-	if (!priv->audio_skew_delta_buffer) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
-	    return 0;
-	}
-
-	priv->audio_ringbuffer = calloc(priv->audio_in.blocksize, priv->audio_buffer_size);
-	if (!priv->audio_ringbuffer) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate audio buffer: %s\n", strerror(errno));
-	    return 0;
-	}
-
-	priv->audio_secs_per_block = (double)priv->audio_in.blocksize/(priv->audio_in.samplerate
-								    *priv->audio_in.channels
-								    *priv->audio_in.bytes_per_sample);
-	priv->audio_usecs_per_block = 1e6*priv->audio_secs_per_block;
-	priv->audio_head = 0;
-	priv->audio_tail = 0;
-	priv->audio_cnt = 0;
-	priv->audio_drop = 0;
-	priv->audio_skew = 0;
-	priv->audio_skew_total = 0;
-	priv->audio_skew_delta_total = 0;
-	priv->audio_recv_blocks_total = 0;
-	priv->audio_sent_blocks_total = 0;
-	priv->audio_null_blocks_inserted = 0;
-	priv->audio_insert_null_samples = 0;
-	priv->dropped_frames_timeshift = 0;
-	priv->dropped_frames_compensated = 0;
-
-	pthread_mutex_init(&priv->skew_mutex, NULL);
-	pthread_mutex_init(&priv->audio_mutex, NULL);
-    }
-
-    /* setup video parameters */
-    if (!tv_param_noaudio) {
-	if (priv->video_buffer_size_max < (3*priv->standard.frameperiod.denominator) /
-					       priv->standard.frameperiod.numerator
-	    *priv->audio_secs_per_block) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "Video buffer shorter than 3 times audio frame duration.\n"
-		   "You will probably experience heavy framedrops.\n");
-	}
-    }
-    
-    {
-	int bytesperline = priv->format.fmt.pix.width*pixfmt2depth(priv->format.fmt.pix.pixelformat)/8;
-	
-	mp_msg(MSGT_TV, MSGL_V, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
-	       priv->video_buffer_size_max,
-	       priv->video_buffer_size_max*priv->format.fmt.pix.height*bytesperline/(1024*1024));
-    }
-
-    priv->video_ringbuffer = calloc(priv->video_buffer_size_max, sizeof(unsigned char*));
-    if (!priv->video_ringbuffer) {
-	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate video buffer: %s\n", strerror(errno));
-	return 0;
-    }
-    for (i = 0; i < priv->video_buffer_size_max; i++)
-	priv->video_ringbuffer[i] = NULL;
-    priv->video_timebuffer = calloc(priv->video_buffer_size_max, sizeof(long long));
-    if (!priv->video_timebuffer) {
-	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate time buffer: %s\n", strerror(errno));
-	return 0;
-    }
-
-    pthread_mutex_init(&priv->video_buffer_mutex, NULL);
-
-    priv->video_head = 0;
-    priv->video_tail = 0;
-    priv->video_cnt = 0;
-    
-    /* request buffers */
-    if (priv->immediate_mode) {
-	request.count = 2;
-    } else {
-	request.count = BUFFER_COUNT;
-    }
-    
-    request.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    request.memory = V4L2_MEMORY_MMAP;
-    if (ioctl(priv->video_fd, VIDIOC_REQBUFS, &request) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl request buffers failed: %s\n",
-	       info.short_name, strerror(errno));
-	return 0;
-    }
-
-    /* query buffers */
-    if (!(priv->map = calloc(request.count, sizeof(struct map)))) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: malloc capture buffers failed: %s\n",
-	       info.short_name, strerror(errno));
-	return 0;
-    }
-
-    /* map and queue buffers */
-    for (i = 0; i < request.count; i++) {
-	memset(&priv->map[i].buf,0,sizeof(priv->map[i].buf));
-	priv->map[i].buf.index = i;
-	priv->map[i].buf.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	priv->map[i].buf.memory  = V4L2_MEMORY_MMAP;
-	if (ioctl(priv->video_fd, VIDIOC_QUERYBUF, &(priv->map[i].buf)) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query buffer failed: %s\n",
-		   info.short_name, strerror(errno));
-	    free(priv->map);
-	    priv->map = NULL;
-	    return 0;
-	}
-	priv->map[i].addr = mmap (0, priv->map[i].buf.length, PROT_READ |
-				  PROT_WRITE, MAP_SHARED, priv->video_fd, priv->map[i].buf.m.offset);
-	if (priv->map[i].addr == MAP_FAILED) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: mmap capture buffer failed: %s\n",
-		   info.short_name, strerror(errno));
-	    priv->map[i].len = 0;
-	    return 0;
-	}
-	priv->map[i].len = priv->map[i].buf.length;
-	/* count up to make sure this is correct everytime */
-	priv->mapcount++;
-
-	if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return 0;
-	}
-    }
-
-    /* start audio thread */
-    priv->shutdown = 0;
-    priv->audio_skew_measure_time = 0;
-    priv->first_frame = 0;
-    priv->audio_skew = 0;
-    priv->first = 1;
-
-    set_mute(priv, 0);
-    
-    return 1;
-}
-
-
-#ifdef HAVE_TV_BSDBT848
-static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
-{
-    memset(buffer, 0xCC, len);
-    return(1);
-}
-#endif /* HAVE_TV_BSDBT848 */
-
-// copies a video frame
-static inline void copy_frame(priv_t *priv, unsigned char *dest, unsigned char *source)
-{
-    int w = priv->format.fmt.pix.width;
-    int h = priv->format.fmt.pix.height;
-    int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
-    int bytesperline = w*d/8;
-
-    memcpy(dest, source, bytesperline * h);
-}
-
-// maximum skew change, in frames
-#define MAX_SKEW_DELTA 0.6
-static void *video_grabber(void *data)
-{
-    priv_t *priv = (priv_t*)data;
-    long long skew, prev_skew, xskew, interval, prev_interval, delta;
-    int i;
-    int framesize = priv->format.fmt.pix.height*priv->format.fmt.pix.width*
-	pixfmt2depth(priv->format.fmt.pix.pixelformat)/8;
-    fd_set rdset;
-    struct timeval timeout;
-    struct v4l2_buffer buf;
-
-    xskew = 0;
-    skew = 0;
-    interval = 0;
-    prev_interval = 0;
-    prev_skew = 0;
-
-    mp_msg(MSGT_TV, MSGL_V, "%s: going to capture\n", info.short_name);
-    if (ioctl(priv->video_fd, VIDIOC_STREAMON, &(priv->format.type)) < 0) {
-	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl streamon failed: %s\n",
-	       info.short_name, strerror(errno));
-	return 0;
-    }
-    priv->streamon = 1;
-
-    if (!tv_param_noaudio) {
-	pthread_create(&priv->audio_grabber_thread, NULL, audio_grabber, priv);
-    }
-
-    for (priv->frames = 0; !priv->shutdown;)
-    {
-	int ret;
-	
-	if (priv->immediate_mode) {
-	    while (priv->video_cnt == priv->video_buffer_size_max) {
-		usleep(10000);
-		if (priv->shutdown) {
-		    return NULL;
-		}
-	    }
-	}
-		
-	FD_ZERO (&rdset);
-	FD_SET (priv->video_fd, &rdset);
-
-	timeout.tv_sec = 1;
-	timeout.tv_usec = 0;
-
-	i = select(priv->video_fd + 1, &rdset, NULL, NULL, &timeout);
-	if (i < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: select failed: %s\n",
-		   info.short_name, strerror(errno));
-	    continue;
-	}
-	else if (i == 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: select timeout\n", info.short_name);
-	    continue;
-	}
-	else if (!FD_ISSET(priv->video_fd, &rdset)) {
-	    continue;
-	}
-
-	memset(&buf,0,sizeof(buf));
-	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ret = ioctl(priv->video_fd, VIDIOC_DQBUF, &buf);
-
-	if (ret < 0) {
-	    /*
-	      if there's no signal, the buffer might me dequeued
-	      so we query all the buffers to see which one we should
-	      put back to queue
-
-	      observed with saa7134 0.2.8
-	      don't know if is it a bug or (mis)feature
-	     */
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
-		   info.short_name, strerror(errno), buf.index);
-	    for (i = 0; i < priv->mapcount; i++) {
-		memset(&buf,0,sizeof(buf));
-		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		buf.index = i;
-		ret = ioctl(priv->video_fd, VIDIOC_QUERYBUF, &buf);
-		if (ret < 0) {
-		    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query buffer failed: %s, idx = %d\n",
-			   info.short_name, strerror(errno), buf.index);
-		    return 0;
-		}
-		if ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE)) == V4L2_BUF_FLAG_MAPPED) {
-		    if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) {
-			mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
-			       info.short_name, strerror(errno));
-			return 0;
-		    }		
-		}
-	    }
-	    continue;
-	}
-
-	/* store the timestamp of the very first frame as reference */
-	if (!priv->frames++) {
-	    if (!tv_param_noaudio) pthread_mutex_lock(&priv->skew_mutex);
-	    priv->first_frame = (long long)1e6*buf.timestamp.tv_sec + buf.timestamp.tv_usec;
-	    if (!tv_param_noaudio) pthread_mutex_unlock(&priv->skew_mutex);
-	}
-	priv->curr_frame = (long long)buf.timestamp.tv_sec*1e6+buf.timestamp.tv_usec;
-//	fprintf(stderr, "idx = %d, ts = %lf\n", buf.index, (double)(priv->curr_frame) / 1e6);
-
-	interval = priv->curr_frame - priv->first_frame;
-	delta = interval - prev_interval;
-
-	if (!priv->immediate_mode) {
-	    // interpolate the skew in time
-	    if (!tv_param_noaudio) pthread_mutex_lock(&priv->skew_mutex);
-	    xskew = priv->audio_skew + (interval - priv->audio_skew_measure_time)*priv->audio_skew_factor;
-	    if (!tv_param_noaudio) pthread_mutex_unlock(&priv->skew_mutex);
- 	    // correct extreme skew changes to avoid (especially) moving backwards in time
-	    if (xskew - prev_skew > delta*MAX_SKEW_DELTA) {
-		skew = prev_skew + delta*MAX_SKEW_DELTA;
-	    } else if (xskew - prev_skew < -delta*MAX_SKEW_DELTA) {
-		skew = prev_skew - delta*MAX_SKEW_DELTA;
-	    } else {
-		skew = xskew;
-	    }
-	}
-
-	mp_msg(MSGT_TV, MSGL_DBG3, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
-	       delta ? (double)1e6/delta : -1,
-	       (double)1e-6*interval, (double)1e-6*xskew, (double)1e-6*skew);
-	mp_msg(MSGT_TV, MSGL_DBG3, "vcnt = %d, acnt = %d\n", priv->video_cnt, priv->audio_cnt);
-
-	prev_skew = skew;
-	prev_interval = interval;
-
-	/* allocate a new buffer, if needed */
-	pthread_mutex_lock(&priv->video_buffer_mutex);
-	if (priv->video_buffer_size_current < priv->video_buffer_size_max) {
-	    if (priv->video_cnt == priv->video_buffer_size_current) {
-		unsigned char *newbuf = malloc(framesize);
-		if (newbuf) {
-		    memmove(priv->video_ringbuffer+priv->video_tail+1, priv->video_ringbuffer+priv->video_tail,
-			    (priv->video_buffer_size_current-priv->video_tail)*sizeof(unsigned char *));
-		    memmove(priv->video_timebuffer+priv->video_tail+1, priv->video_timebuffer+priv->video_tail,
-			    (priv->video_buffer_size_current-priv->video_tail)*sizeof(long long));
-		    priv->video_ringbuffer[priv->video_tail] = newbuf;
-		    if ((priv->video_head >= priv->video_tail) && (priv->video_cnt > 0)) priv->video_head++;
-		    priv->video_buffer_size_current++;
-		}
-	    }
-	}
-	pthread_mutex_unlock(&priv->video_buffer_mutex);
-
-	if (priv->video_cnt == priv->video_buffer_size_current) {
-	    if (!priv->immediate_mode) {
-		mp_msg(MSGT_TV, MSGL_ERR, "\nvideo buffer full - dropping frame\n");
-		if (priv->audio_insert_null_samples) {
-		    pthread_mutex_lock(&priv->audio_mutex);
-		    priv->dropped_frames_timeshift += delta;
-		    pthread_mutex_unlock(&priv->audio_mutex);
-		}
-	    }
-	} else {
-	    if (priv->immediate_mode) {
-		priv->video_timebuffer[priv->video_tail] = 0;
-	    } else {
-		// compensate for audio skew
-		// negative skew => there are more audio samples, increase interval
-		// positive skew => less samples, shorten the interval
-		priv->video_timebuffer[priv->video_tail] = interval - skew;
-		if (priv->audio_insert_null_samples && priv->video_timebuffer[priv->video_tail] > 0) {
-		    pthread_mutex_lock(&priv->audio_mutex);
-		    priv->video_timebuffer[priv->video_tail] += 
-			(priv->audio_null_blocks_inserted
-			 - priv->dropped_frames_timeshift/priv->audio_usecs_per_block)
-			*priv->audio_usecs_per_block;
-		    pthread_mutex_unlock(&priv->audio_mutex);
-		}
-	    }
-
-	    copy_frame(priv, priv->video_ringbuffer[priv->video_tail], priv->map[buf.index].addr);
-	    priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current;
-	    priv->video_cnt++;
-	}
-	if (ioctl(priv->video_fd, VIDIOC_QBUF, &buf) < 0) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
-		   info.short_name, strerror(errno));
-	    return 0;
-	}
-    }
-    return NULL;
-}
-
-#define MAX_LOOP 50
-static double grab_video_frame(priv_t *priv, char *buffer, int len)
-{
-    double interval;
-    int loop_cnt = 0;
-
-    if (priv->first) {
-	pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);
-	priv->first = 0;
-    }
-
-    while (priv->video_cnt == 0) {
-	usleep(10000);
-	if (loop_cnt++ > MAX_LOOP) return 0;
-    }
-
-    pthread_mutex_lock(&priv->video_buffer_mutex);
-    interval = (double)priv->video_timebuffer[priv->video_head]*1e-6;
-    memcpy(buffer, priv->video_ringbuffer[priv->video_head], len);
-    priv->video_cnt--;
-    priv->video_head = (priv->video_head+1)%priv->video_buffer_size_current;
-    pthread_mutex_unlock(&priv->video_buffer_mutex);
-
-    return interval;
-}
-
-static int get_video_framesize(priv_t *priv)
-{
-    return priv->format.fmt.pix.sizeimage;
-}
-
-//#define DOUBLESPEED
-#ifdef DOUBLESPEED
-// for testing purposes only
-static void read_doublespeed(priv_t *priv)
-{
-    char *bufx = calloc(priv->audio_in.blocksize, 2);
-    short *s;
-    short *d;
-    int i;
-    
-    audio_in_read_chunk(&priv->audio_in, bufx);
-    audio_in_read_chunk(&priv->audio_in, bufx+priv->audio_in.blocksize);
-
-    s = bufx;
-    d = priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize;
-    for (i = 0; i < priv->audio_in.blocksize/2; i++) {
-	*d++ = *s++;
-	*s++;
-    }
-    
-}
-#endif
-
-static void *audio_grabber(void *data)
-{
-    priv_t *priv = (priv_t*)data;
-    struct timeval tv;
-    int i, audio_skew_ptr = 0;
-    long long current_time, prev_skew = 0, prev_skew_uncorr = 0;
-    long long start_time_avg;
-
-    gettimeofday(&tv, NULL);
-    start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
-    audio_in_start_capture(&priv->audio_in);
-    for (i = 0; i < priv->aud_skew_cnt; i++)
-	priv->audio_skew_buffer[i] = 0;
-    for (i = 0; i < priv->aud_skew_cnt; i++)
-	priv->audio_skew_delta_buffer[i] = 0;
-
-    for (; !priv->shutdown;)
-    {
-#ifdef DOUBLESPEED
-	read_doublespeed(priv);
-#else
-	if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0)
-	    continue;
-#endif
-	pthread_mutex_lock(&priv->skew_mutex);
-	if (priv->first_frame == 0) {
-	    // there is no first frame yet (unlikely to happen)
-	    gettimeofday(&tv, NULL);
-	    start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
-//	    fprintf(stderr, "warning - first frame not yet available!\n");
-	    pthread_mutex_unlock(&priv->skew_mutex);
-	    continue;
-	}
-	pthread_mutex_unlock(&priv->skew_mutex);
-
-	gettimeofday(&tv, NULL);
-
-	priv->audio_recv_blocks_total++;
-	current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_start_time;
-
-	if (priv->audio_recv_blocks_total < priv->aud_skew_cnt*2) {
-	    start_time_avg += (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
-	    priv->audio_start_time = start_time_avg/(priv->audio_recv_blocks_total+1);
-	}
-
-//	fprintf(stderr, "spb = %lf, bs = %d, skew = %lf\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
-//		(double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
-
-	// put the current skew into the ring buffer
-	priv->audio_skew_total -= priv->audio_skew_buffer[audio_skew_ptr];
-	priv->audio_skew_buffer[audio_skew_ptr] = current_time
-	    - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
-	priv->audio_skew_total += priv->audio_skew_buffer[audio_skew_ptr];
-
-	pthread_mutex_lock(&priv->skew_mutex);
-
-	// skew calculation
-
-	// compute the sliding average of the skews
-	if (priv->audio_recv_blocks_total > priv->aud_skew_cnt) {
-	    priv->audio_skew = priv->audio_skew_total/priv->aud_skew_cnt;
-	} else {
-	    priv->audio_skew = priv->audio_skew_total/priv->audio_recv_blocks_total;
-	}
-
-	// put the current skew change (skew-prev_skew) into the ring buffer
-	priv->audio_skew_delta_total -= priv->audio_skew_delta_buffer[audio_skew_ptr];
-	priv->audio_skew_delta_buffer[audio_skew_ptr] = priv->audio_skew - prev_skew_uncorr;
-	priv->audio_skew_delta_total += priv->audio_skew_delta_buffer[audio_skew_ptr];
-	prev_skew_uncorr = priv->audio_skew; // remember the _uncorrected_ average value
-
-	audio_skew_ptr = (audio_skew_ptr+1) % priv->aud_skew_cnt; // rotate the buffer pointer
-
-	// sliding average approximates the value in the middle of the interval
-	// so interpolate the skew value further to the current time
-	priv->audio_skew += priv->audio_skew_delta_total/2;
-
-	// now finally, priv->audio_skew contains fairly good approximation
-	// of the current value 
-
-	// current skew factor (assuming linearity)
-	// used for further interpolation in video_grabber
-	// probably overkill but seems to be necessary for
-	// stress testing by dropping half of the audio frames ;)
-	// especially when using ALSA with large block sizes
-	// where audio_skew remains a long while behind
-	if ((priv->audio_skew_measure_time != 0) && (current_time - priv->audio_skew_measure_time != 0)) {
-	    priv->audio_skew_factor = (double)(priv->audio_skew-prev_skew)/(current_time - priv->audio_skew_measure_time);
-	} else {
-	    priv->audio_skew_factor = 0.0;
-	}
-
-	priv->audio_skew_measure_time = current_time;
-	prev_skew = priv->audio_skew;
-	priv->audio_skew += priv->audio_start_time - priv->first_frame;
-	pthread_mutex_unlock(&priv->skew_mutex);
-	
-//	fprintf(stderr, "audio_skew = %lf, delta = %lf\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
-
-	pthread_mutex_lock(&priv->audio_mutex);
-	if ((priv->audio_tail+1) % priv->audio_buffer_size == priv->audio_head) {
-	    mp_msg(MSGT_TV, MSGL_ERR, "\ntoo bad - dropping audio frame !\n");
-	    priv->audio_drop++;
-	} else {
-	    priv->audio_tail = (priv->audio_tail+1) % priv->audio_buffer_size;
-	    priv->audio_cnt++;
-	}
-	pthread_mutex_unlock(&priv->audio_mutex);
-    }
-    return NULL;
-}
-
-static double grab_audio_frame(priv_t *priv, char *buffer, int len)
-{
-    mp_dbg(MSGT_TV, MSGL_DBG2, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
-	priv, buffer, len);
-
-    // hack: if grab_audio_frame is called first, it means we are used by mplayer
-    // => switch to the mode which outputs audio immediately, even if
-    // it should be silence
-    if (priv->first) priv->audio_insert_null_samples = 1;
-
-    pthread_mutex_lock(&priv->audio_mutex);
-    while (priv->audio_insert_null_samples
-	   && priv->dropped_frames_timeshift - priv->dropped_frames_compensated >= priv->audio_usecs_per_block) {
-	// some frames were dropped - drop the corresponding number of audio blocks
-	if (priv->audio_drop) {
-	    priv->audio_drop--;
-	} else {
-	    if (priv->audio_head == priv->audio_tail) break;
-	    priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
-	}
-	priv->dropped_frames_compensated += priv->audio_usecs_per_block;
-    }
-
-    // compensate for dropped audio frames
-    if (priv->audio_drop && (priv->audio_head == priv->audio_tail)) {
-	priv->audio_drop--;
-	memset(buffer, 0, len);
-	goto out;
-    }
-
-    if (priv->audio_insert_null_samples && (priv->audio_head == priv->audio_tail)) {
-	// return silence to avoid desync and stuttering
-	memset(buffer, 0, len);
-	priv->audio_null_blocks_inserted++;
-	goto out;
-    }
-
-    pthread_mutex_unlock(&priv->audio_mutex);
-    while (priv->audio_head == priv->audio_tail) {
-	// this is mencoder => just wait until some audio is available
-	usleep(10000);
-    }
-    pthread_mutex_lock(&priv->audio_mutex);
-    memcpy(buffer, priv->audio_ringbuffer+priv->audio_head*priv->audio_in.blocksize, len);
-    priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
-    priv->audio_cnt--;
-out:
-    pthread_mutex_unlock(&priv->audio_mutex);
-    priv->audio_sent_blocks_total++;
-    return (double)priv->audio_sent_blocks_total*priv->audio_secs_per_block;
-}
-
-static int get_audio_framesize(priv_t *priv)
-{
-    return(priv->audio_in.blocksize);
-}
--- a/libmpdemux/url.c	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,373 +0,0 @@
-/*
- * URL Helper
- * by Bertrand Baudet <bertrand_baudet@yahoo.com>
- * (C) 2001, MPlayer team.
- *
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <inttypes.h>
-
-#include "url.h"
-#include "mp_msg.h"
-#include "help_mp.h"
-
-#ifndef SIZE_MAX
-#define SIZE_MAX ((size_t)-1)
-#endif
-
-URL_t*
-url_new(const char* url) {
-	int pos1, pos2,v6addr = 0;
-	URL_t* Curl = NULL;
-        char *escfilename=NULL;
-	char *ptr1=NULL, *ptr2=NULL, *ptr3=NULL, *ptr4=NULL;
-	int jumpSize = 3;
-
-	if( url==NULL ) return NULL;
-	
-        if (strlen(url) > (SIZE_MAX / 3 - 1)) {
-                mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-                goto err_out;
-        }
-        escfilename=malloc(strlen(url)*3+1);
-        if (!escfilename ) {
-                mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-                goto err_out;
-        }
-
-	// Create the URL container
-	Curl = malloc(sizeof(URL_t));
-	if( Curl==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-		goto err_out;
-	}
-
-	// Initialisation of the URL container members
-	memset( Curl, 0, sizeof(URL_t) );
-
-	url_escape_string(escfilename,url);
-
-	// Copy the url in the URL container
-	Curl->url = strdup(escfilename);
-	if( Curl->url==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-		goto err_out;
-	}
-        mp_msg(MSGT_OPEN,MSGL_V,"Filename for url is now %s\n",escfilename);
-
-	// extract the protocol
-	ptr1 = strstr(escfilename, "://");
-	if( ptr1==NULL ) {
-	        // Check for a special case: "sip:" (without "//"):
-	        if (strstr(escfilename, "sip:") == escfilename) {
-		        ptr1 = (char *)&url[3]; // points to ':'
-			jumpSize = 1;
-		} else {
-		        mp_msg(MSGT_NETWORK,MSGL_V,"Not an URL!\n");
-			goto err_out;
-		}
-	}
-	pos1 = ptr1-escfilename;
-	Curl->protocol = malloc(pos1+1);
-	if( Curl->protocol==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-		goto err_out;
-	}
-	strncpy(Curl->protocol, escfilename, pos1);
-	Curl->protocol[pos1] = '\0';
-
-	// jump the "://"
-	ptr1 += jumpSize;
-	pos1 += jumpSize;
-
-	// check if a username:password is given
-	ptr2 = strstr(ptr1, "@");
-	ptr3 = strstr(ptr1, "/");
-	if( ptr3!=NULL && ptr3<ptr2 ) {
-		// it isn't really a username but rather a part of the path
-		ptr2 = NULL;
-	}
-	if( ptr2!=NULL ) {
-		// We got something, at least a username...
-		int len = ptr2-ptr1;
-		Curl->username = malloc(len+1);
-		if( Curl->username==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-			goto err_out;
-		}
-		strncpy(Curl->username, ptr1, len);
-		Curl->username[len] = '\0';
-
-		ptr3 = strstr(ptr1, ":");
-		if( ptr3!=NULL && ptr3<ptr2 ) {
-			// We also have a password
-			int len2 = ptr2-ptr3-1;
-			Curl->username[ptr3-ptr1]='\0';
-			Curl->password = malloc(len2+1);
-			if( Curl->password==NULL ) {
-				mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-				goto err_out;
-			}
-			strncpy( Curl->password, ptr3+1, len2);
-			Curl->password[len2]='\0';
-		}
-		ptr1 = ptr2+1;
-		pos1 = ptr1-escfilename;
-	}
-
-	// before looking for a port number check if we have an IPv6 type numeric address
-	// in IPv6 URL the numeric address should be inside square braces.
-	ptr2 = strstr(ptr1, "[");
-	ptr3 = strstr(ptr1, "]");
-	ptr4 = strstr(ptr1, "/");
-	if( ptr2!=NULL && ptr3!=NULL && ptr2 < ptr3 && (!ptr4 || ptr4 > ptr3)) {
-		// we have an IPv6 numeric address
-		ptr1++;
-		pos1++;
-		ptr2 = ptr3;
-		v6addr = 1;
-	} else {
-		ptr2 = ptr1;
-
-	}
-	
-	// look if the port is given
-	ptr2 = strstr(ptr2, ":");
-	// If the : is after the first / it isn't the port
-	ptr3 = strstr(ptr1, "/");
-	if(ptr3 && ptr3 - ptr2 < 0) ptr2 = NULL;
-	if( ptr2==NULL ) {
-		// No port is given
-		// Look if a path is given
-		if( ptr3==NULL ) {
-			// No path/filename
-			// So we have an URL like http://www.hostname.com
-			pos2 = strlen(escfilename);
-		} else {
-			// We have an URL like http://www.hostname.com/file.txt
-                        pos2 = ptr3-escfilename;
-		}
-	} else {
-		// We have an URL beginning like http://www.hostname.com:1212
-		// Get the port number
-		Curl->port = atoi(ptr2+1);
-		pos2 = ptr2-escfilename;
-	}
-	if( v6addr ) pos2--;
-	// copy the hostname in the URL container
-	Curl->hostname = malloc(pos2-pos1+1);
-	if( Curl->hostname==NULL ) {
-		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-		goto err_out;
-	}
-	strncpy(Curl->hostname, ptr1, pos2-pos1);
-	Curl->hostname[pos2-pos1] = '\0';
-
-	// Look if a path is given
-	ptr2 = strstr(ptr1, "/");
-	if( ptr2!=NULL ) {
-		// A path/filename is given
-		// check if it's not a trailing '/'
-		if( strlen(ptr2)>1 ) {
-			// copy the path/filename in the URL container
-			Curl->file = strdup(ptr2);
-			if( Curl->file==NULL ) {
-				mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-				goto err_out;
-			}
-		}
-	} 
-	// Check if a filename was given or set, else set it with '/'
-	if( Curl->file==NULL ) {
-		Curl->file = malloc(2);
-		if( Curl->file==NULL ) {
-			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
-			goto err_out;
-		}
-		strcpy(Curl->file, "/");
-	}
-	
-        free(escfilename);
-	return Curl;
-err_out:
-	if (escfilename) free(escfilename);
-	if (Curl) url_free(Curl);
-	return NULL;
-}
-
-void
-url_free(URL_t* url) {
-	if(!url) return;
-	if(url->url) free(url->url);
-	if(url->protocol) free(url->protocol);
-	if(url->hostname) free(url->hostname);
-	if(url->file) free(url->file);
-	if(url->username) free(url->username);
-	if(url->password) free(url->password);
-	free(url);
-}
-
-
-/* Replace escape sequences in an URL (or a part of an URL) */
-/* works like strcpy(), but without return argument */
-void
-url_unescape_string(char *outbuf, const char *inbuf)
-{
-	unsigned char c,c1,c2;
-        int i,len=strlen(inbuf);
-        for (i=0;i<len;i++){
-		c = inbuf[i];
-		if (c == '%' && i<len-2) { //must have 2 more chars
-			c1 = toupper(inbuf[i+1]); // we need uppercase characters
-			c2 = toupper(inbuf[i+2]);
-			if (	((c1>='0' && c1<='9') || (c1>='A' && c1<='F')) &&
-				((c2>='0' && c2<='9') || (c2>='A' && c2<='F')) ) {
-				if (c1>='0' && c1<='9') c1-='0';
-				else c1-='A'-10;
-				if (c2>='0' && c2<='9') c2-='0';
-				else c2-='A'-10;
-				c = (c1<<4) + c2;
-                                i=i+2; //only skip next 2 chars if valid esc
-			}
-		}
-		*outbuf++ = c;
-	} 
-        *outbuf++='\0'; //add nullterm to string
-}
-
-static void
-url_escape_string_part(char *outbuf, const char *inbuf) {
-	unsigned char c,c1,c2;
-        int i,len=strlen(inbuf);
-
-	for  (i=0;i<len;i++) {
-		c = inbuf[i];
-                if ((c=='%') && i<len-2 ) { //need 2 more characters
-                    c1=toupper(inbuf[i+1]); c2=toupper(inbuf[i+2]); // need uppercase chars
-                   } else {
-                    c1=129; c2=129; //not escape chars
-                   }
-
-		if(	(c >= 'A' && c <= 'Z') ||
-			(c >= 'a' && c <= 'z') ||
-			(c >= '0' && c <= '9') ||
-			(c >= 0x7f)) {
-			*outbuf++ = c;
-                } else if ( c=='%' && ((c1 >= '0' && c1 <= '9') || (c1 >= 'A' && c1 <= 'F')) &&
-                           ((c2 >= '0' && c2 <= '9') || (c2 >= 'A' && c2 <= 'F'))) {
-                                                              // check if part of an escape sequence
-                            *outbuf++=c;                      // already
-			      
-                                                              // dont escape again
-                            mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_URL_StringAlreadyEscaped,c,c1,c2);
-                                                              // error as this should not happen against RFC 2396
-                                                              // to escape a string twice
-		} else {
-			/* all others will be escaped */
-			c1 = ((c & 0xf0) >> 4);
-			c2 = (c & 0x0f);
-			if (c1 < 10) c1+='0';
-			else c1+='A'-10;
-			if (c2 < 10) c2+='0';
-			else c2+='A'-10;
-			*outbuf++ = '%';
-			*outbuf++ = c1;
-			*outbuf++ = c2;
-		}
-	}
-        *outbuf++='\0';
-}
-
-/* Replace specific characters in the URL string by an escape sequence */
-/* works like strcpy(), but without return argument */
-void
-url_escape_string(char *outbuf, const char *inbuf) {
-	unsigned char c;
-        int i = 0,j,len = strlen(inbuf);
-	char* tmp,*unesc = NULL, *in;
-	
-	// Look if we have an ip6 address, if so skip it there is
-	// no need to escape anything in there.
-	tmp = strstr(inbuf,"://[");
-	if(tmp) {
-		tmp = strchr(tmp+4,']');
-		if(tmp && (tmp[1] == '/' || tmp[1] == ':' ||
-			   tmp[1] == '\0')) {
-			i = tmp+1-inbuf;
-			strncpy(outbuf,inbuf,i);
-			outbuf += i;
-			tmp = NULL;
-		}
-	}
-	
-	while(i < len) {
-		// look for the next char that must be kept
-		for  (j=i;j<len;j++) {
-			c = inbuf[j];
-			if(c=='-' || c=='_' || c=='.' || c=='!' || c=='~' ||	/* mark characters */
-			   c=='*' || c=='\'' || c=='(' || c==')' || 	 	/* do not touch escape character */
-			   c==';' || c=='/' || c=='?' || c==':' || c=='@' || 	/* reserved characters */
-			   c=='&' || c=='=' || c=='+' || c=='$' || c==',') 	/* see RFC 2396 */
-				break;
-		}
-		// we are on a reserved char, write it out
-		if(j == i) {
-			*outbuf++ = c;
-			i++;
-			continue;
-		}
-		// we found one, take that part of the string
-		if(j < len) {
-			if(!tmp) tmp = malloc(len+1);
-			strncpy(tmp,inbuf+i,j-i);
-			tmp[j-i] = '\0';
-			in = tmp;
-		} else // take the rest of the string
-			in = (char*)inbuf+i;
-		
-		if(!unesc) unesc = malloc(len+1);
-		// unescape first to avoid escaping escape
-		url_unescape_string(unesc,in);
-		// then escape, including mark and other reserved chars
-		// that can come from escape sequences
-		url_escape_string_part(outbuf,unesc);
-		outbuf += strlen(outbuf);
-		i += strlen(in);
-	}
-	*outbuf = '\0';
-	if(tmp) free(tmp);
-	if(unesc) free(unesc);
-}
-
-#ifdef __URL_DEBUG
-void
-url_debug(const URL_t *url) {
-	if( url==NULL ) {
-		printf("URL pointer NULL\n");
-		return;
-	}
-	if( url->url!=NULL ) {
-		printf("url=%s\n", url->url );
-	}
-	if( url->protocol!=NULL ) {
-		printf("protocol=%s\n", url->protocol );
-	}
-	if( url->hostname!=NULL ) {
-		printf("hostname=%s\n", url->hostname );
-	}
-	printf("port=%d\n", url->port );
-	if( url->file!=NULL ) {
-		printf("file=%s\n", url->file );
-	}
-	if( url->username!=NULL ) {
-		printf("username=%s\n", url->username );
-	}
-	if( url->password!=NULL ) {
-		printf("password=%s\n", url->password );
-	}
-}
-#endif //__URL_DEBUG
--- a/libmpdemux/url.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* 
- * URL Helper
- * by Bertrand Baudet <bertrand_baudet@yahoo.com>
- * (C) 2001, MPlayer team.
- */
-
-#ifndef __URL_H
-#define __URL_H
-
-//#define __URL_DEBUG
-
-typedef struct {
-	char *url;
-	char *protocol;
-	char *hostname;
-	char *file;
-	unsigned int port;
-	char *username;
-	char *password;
-} URL_t;
-
-URL_t* url_new(const char* url);
-void   url_free(URL_t* url);
-
-void url_unescape_string(char *outbuf, const char *inbuf);
-void url_escape_string(char *outbuf, const char *inbuf);
-
-#ifdef __URL_DEBUG
-void url_debug(const URL_t* url);
-#endif // __URL_DEBUG
-
-#endif // __URL_H
--- a/libmpdemux/vcd_read.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-//=================== VideoCD ==========================
-#if	defined(linux) || defined(sun) || defined(__bsdi__)
-
-typedef struct mp_vcd_priv_st mp_vcd_priv_t;
-
-#if	defined(linux)
-#include <linux/cdrom.h>
-#elif	defined(sun)
-#include <sys/cdio.h>
-static int sun_vcd_read(mp_vcd_priv_t*, int*);
-#elif	defined(__bsdi__)
-#include <dvd.h>
-#endif
-
-struct mp_vcd_priv_st {
-  int fd;
-  struct cdrom_tocentry entry;
-  char buf[VCD_SECTOR_SIZE];
-};
-
-static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect){
-  vcd->entry.cdte_addr.msf.frame=sect%75;
-  sect=sect/75;
-  vcd->entry.cdte_addr.msf.second=sect%60;
-  sect=sect/60;
-  vcd->entry.cdte_addr.msf.minute=sect;
-}
-
-static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd){
-  return vcd->entry.cdte_addr.msf.frame +
-        (vcd->entry.cdte_addr.msf.second+
-         vcd->entry.cdte_addr.msf.minute*60)*75;
-}
-
-int vcd_seek_to_track(mp_vcd_priv_t* vcd,int track){
-  vcd->entry.cdte_format = CDROM_MSF;
-  vcd->entry.cdte_track  = track;
-  if (ioctl(vcd->fd, CDROMREADTOCENTRY, &vcd->entry)) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
-    return -1;
-  }
-  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
-}
-
-int vcd_get_track_end(mp_vcd_priv_t* vcd,int track){
-  struct cdrom_tochdr tochdr;
-  if (ioctl(vcd->fd,CDROMREADTOCHDR,&tochdr)==-1) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-    return -1;
-  }
-  vcd->entry.cdte_format = CDROM_MSF;
-  vcd->entry.cdte_track  = track<tochdr.cdth_trk1?(track+1):CDROM_LEADOUT;
-  if (ioctl(vcd->fd, CDROMREADTOCENTRY, &vcd->entry)) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
-    return -1;
-  }
-  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
-}
-
-mp_vcd_priv_t* vcd_read_toc(int fd){
-  struct cdrom_tochdr tochdr;
-  mp_vcd_priv_t* vcd;
-  int i, min = 0, sec = 0, frame = 0;
-  if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-    return NULL;
-  }
-  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", tochdr.cdth_trk0);
-  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", tochdr.cdth_trk1);
-  for (i=tochdr.cdth_trk0 ; i<=tochdr.cdth_trk1 + 1; i++){
-      struct cdrom_tocentry tocentry;
-
-      tocentry.cdte_track  = i<=tochdr.cdth_trk1 ? i : CDROM_LEADOUT;
-      tocentry.cdte_format = CDROM_MSF;
-
-      if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)==-1) {
-	mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
-	return NULL;
-      }
-        
-      if (i<=tochdr.cdth_trk1)
-      mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d  mode: %d\n",
-          (int)tocentry.cdte_track,
-          (int)tocentry.cdte_adr,
-          (int)tocentry.cdte_ctrl,
-          (int)tocentry.cdte_format,
-          (int)tocentry.cdte_addr.msf.minute,
-          (int)tocentry.cdte_addr.msf.second,
-          (int)tocentry.cdte_addr.msf.frame,
-          (int)tocentry.cdte_datamode
-      );
-
-      if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
-      {
-        if (i > tochdr.cdth_trk0)
-        {
-          min = tocentry.cdte_addr.msf.minute - min;
-          sec = tocentry.cdte_addr.msf.second - sec;
-          frame = tocentry.cdte_addr.msf.frame - frame;
-          if ( frame < 0 )
-          {
-            frame += 75;
-            sec --;
-          }
-          if ( sec < 0 )
-          {
-            sec += 60;
-            min --;
-          }
-          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
-        }
-        min = tocentry.cdte_addr.msf.minute;
-        sec = tocentry.cdte_addr.msf.second;
-        frame = tocentry.cdte_addr.msf.frame;
-      }
-    }
-  vcd = malloc(sizeof(mp_vcd_priv_t));
-  vcd->fd = fd;
-  return vcd;
-}
-
-static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
-#if	defined(linux) || defined(__bsdi__)
-  memcpy(vcd->buf,&vcd->entry.cdte_addr.msf,sizeof(struct cdrom_msf));
-  if(ioctl(vcd->fd,CDROMREADRAW,vcd->buf)==-1) return 0; // EOF?
-  memcpy(mem,&vcd->buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA);
-#elif	defined(sun)
-  {
-    int offset;
-    if (sun_vcd_read(vcd->fd, &offset) <= 0) return 0;
-    memcpy(mem,&vcd->buf[offset],VCD_SECTOR_DATA);
-  }
-#endif
-
-  vcd->entry.cdte_addr.msf.frame++;
-  if (vcd->entry.cdte_addr.msf.frame==75){
-    vcd->entry.cdte_addr.msf.frame=0;
-    vcd->entry.cdte_addr.msf.second++;
-    if (vcd->entry.cdte_addr.msf.second==60){
-      vcd->entry.cdte_addr.msf.second=0;
-      vcd->entry.cdte_addr.msf.minute++;
-    }
-  }
-    
-  return VCD_SECTOR_DATA;
-}
-
-
-#ifdef	sun
-#include <sys/scsi/generic/commands.h>
-#include <sys/scsi/impl/uscsi.h>
-
-#define	SUN_XAREAD	1	/*fails on atapi drives*/
-#define	SUN_MODE2READ	2	/*fails on atapi drives*/
-#define	SUN_SCSIREAD	3
-#define	SUN_VCDREAD	SUN_SCSIREAD
-
-static int sun_vcd_read(mp_vcd_priv_t* vcd, int *offset)
-{
-#if SUN_VCDREAD == SUN_XAREAD
-  struct cdrom_cdxa cdxa;
-  cdxa.cdxa_addr = vcd_get_msf(vcd);
-  cdxa.cdxa_length = 1;
-  cdxa.cdxa_data = vcd->buf;
-  cdxa.cdxa_format = CDROM_XA_SECTOR_DATA;
-  
-  if(ioctl(vcd->fd,CDROMCDXA,&cdxa)==-1) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"CDROMCDXA: %s\n",strerror(errno));
-    return 0;
-  }
-  *offset = 0;
-#elif SUN_VCDREAD == SUN_MODE2READ
-  struct cdrom_read cdread;
-  cdread.cdread_lba = 4*vcd_get_msf(vcd);
-  cdread.cdread_bufaddr = vcd->buf;
-  cdread.cdread_buflen = 2336;
-
-  if(ioctl(vcd->fd,CDROMREADMODE2,&cdread)==-1) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"CDROMREADMODE2: %s\n",strerror(errno));
-    return 0;
-  }
-  *offset = 8;
-#elif SUN_VCDREAD == SUN_SCSIREAD
-  struct uscsi_cmd sc;
-  union scsi_cdb cdb;
-  int lba = vcd_get_msf(vcd);
-  int blocks = 1;
-  int sector_type;
-  int sync, header_code, user_data, edc_ecc, error_field;
-  int sub_channel;
-
-  /* sector_type = 3; *//* mode2 */
-  sector_type = 5;	/* mode2/form2 */
-  sync = 0;
-  header_code = 0;
-  user_data = 1;
-  edc_ecc = 0;
-  error_field = 0;
-  sub_channel = 0;
-
-  memset(&cdb, 0, sizeof(cdb));
-  memset(&sc, 0, sizeof(sc));
-  cdb.scc_cmd = 0xBE;
-  cdb.cdb_opaque[1] = (sector_type) << 2;
-  cdb.cdb_opaque[2] = (lba >> 24) & 0xff;
-  cdb.cdb_opaque[3] = (lba >> 16) & 0xff;
-  cdb.cdb_opaque[4] = (lba >>  8) & 0xff;
-  cdb.cdb_opaque[5] =  lba & 0xff;
-  cdb.cdb_opaque[6] = (blocks >> 16) & 0xff;
-  cdb.cdb_opaque[7] = (blocks >>  8) & 0xff;
-  cdb.cdb_opaque[8] =  blocks & 0xff;
-  cdb.cdb_opaque[9] = (sync << 7) |
-		      (header_code << 5) |
-		      (user_data << 4) |
-		      (edc_ecc << 3) |
-		      (error_field << 1);
-  cdb.cdb_opaque[10] = sub_channel;
-
-  sc.uscsi_cdb = (caddr_t)&cdb;
-  sc.uscsi_cdblen = 12;
-  sc.uscsi_bufaddr = vcd->buf;
-  sc.uscsi_buflen = 2336;
-  sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ;
-  sc.uscsi_timeout = 20;
-  if (ioctl(vcd->fd, USCSICMD, &sc)) {
-      mp_msg(MSGT_STREAM,MSGL_ERR,"USCSICMD: READ CD: %s\n",strerror(errno));
-      return -1;
-  }
-  if (sc.uscsi_status) {
-      mp_msg(MSGT_STREAM,MSGL_ERR,"scsi command failed with status %d\n", sc.uscsi_status);
-      return -1;
-  }
-  *offset = 0;
-  return 1;
-#else
-#error SUN_VCDREAD
-#endif
-}
-#endif	/*sun*/
-
-#else /* linux || sun || __bsdi__ */
-
-#error vcd is not yet supported on this arch...
-
-#endif
--- a/libmpdemux/vcd_read_darwin.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-#include <sys/types.h>
-#include <CoreFoundation/CFBase.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/storage/IOCDTypes.h>
-#include <IOKit/storage/IOCDMedia.h>
-#include <IOKit/storage/IOCDMediaBSDClient.h>
-
-//=================== VideoCD ==========================
-#define	CDROM_LEADOUT	0xAA
-
-typedef struct
-{
-	uint8_t sync            [12];
-	uint8_t header          [4];
-	uint8_t subheader       [8];
-	uint8_t data            [2324];
-	uint8_t spare           [4];
-} cdsector_t;
-
-typedef struct mp_vcd_priv_st
-{
-	int fd;
-	dk_cd_read_track_info_t entry;
-	CDMSF msf;
-	cdsector_t buf;
-} mp_vcd_priv_t;
-
-static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect)
-{
-  vcd->msf.frame=sect%75;
-  sect=sect/75;
-  vcd->msf.second=sect%60;
-  sect=sect/60;
-  vcd->msf.minute=sect;
-}
-
-static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd)
-{
-  return vcd->msf.frame +
-        (vcd->msf.second+
-         vcd->msf.minute*60)*75;
-
-return 0;
-}
-
-int vcd_seek_to_track(mp_vcd_priv_t* vcd, int track)
-{
-	dk_cd_read_track_info_t tocentry;
-	struct CDTrackInfo entry;
-
-	memset( &vcd->entry, 0, sizeof(vcd->entry));
-	vcd->entry.addressType = kCDTrackInfoAddressTypeTrackNumber;
-	vcd->entry.address = track;
-	vcd->entry.bufferLength = sizeof(entry);
-	vcd->entry.buffer = &entry;
-  
-	if (ioctl(vcd->fd, DKIOCCDREADTRACKINFO, &vcd->entry))
-	{
-		mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
-		return -1;
-	}
-	return VCD_SECTOR_DATA*vcd_get_msf(vcd);
-  
-return -1;
-}
-
-int vcd_get_track_end(mp_vcd_priv_t* vcd, int track)
-{
-	dk_cd_read_disc_info_t tochdr;
-	struct CDDiscInfo hdr;
-	
-	dk_cd_read_track_info_t tocentry;
-	struct CDTrackInfo entry;
-	
-	//read toc header
-    memset(&tochdr, 0, sizeof(tochdr));
-    tochdr.buffer = &hdr;
-    tochdr.bufferLength = sizeof(hdr);
-  
-    if (ioctl(vcd->fd, DKIOCCDREADDISCINFO, &tochdr) < 0)
-	{
-		mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-		return NULL;
-    }
-	
-	//read track info
-	memset( &vcd->entry, 0, sizeof(vcd->entry));
-	vcd->entry.addressType = kCDTrackInfoAddressTypeTrackNumber;
-	vcd->entry.address = track<(hdr.lastTrackNumberInLastSessionLSB+1)?(track):CDROM_LEADOUT;
-	vcd->entry.bufferLength = sizeof(entry);
-	vcd->entry.buffer = &entry;
-  
-	if (ioctl(vcd->fd, DKIOCCDREADTRACKINFO, &vcd->entry))
-	{
-		mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
-		return -1;
-	}
-	return VCD_SECTOR_DATA*vcd_get_msf(vcd);
-
-return -1;
-}
-
-mp_vcd_priv_t* vcd_read_toc(int fd)
-{
-	dk_cd_read_disc_info_t tochdr;
-	struct CDDiscInfo hdr;
-	
-	dk_cd_read_track_info_t tocentry;
-	struct CDTrackInfo entry;
-	CDMSF trackMSF;
-	
-	mp_vcd_priv_t* vcd;
-	int i, min = 0, sec = 0, frame = 0;
-  
-	//read toc header
-    memset(&tochdr, 0, sizeof(tochdr));
-    tochdr.buffer = &hdr;
-    tochdr.bufferLength = sizeof(hdr);
-  
-    if (ioctl(fd, DKIOCCDREADDISCINFO, &tochdr) < 0)
-	{
-		mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-		return NULL;
-    }
-	
-	//print all track info
-	mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", hdr.firstTrackNumberInLastSessionLSB);
-	mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", hdr.lastTrackNumberInLastSessionLSB);
-	for (i=hdr.firstTrackNumberInLastSessionLSB ; i<=hdr.lastTrackNumberInLastSessionLSB + 1; i++)
-	{
-		memset( &tocentry, 0, sizeof(tocentry));
-		tocentry.addressType = kCDTrackInfoAddressTypeTrackNumber;
-		tocentry.address = i<=hdr.lastTrackNumberInLastSessionLSB ? i : CDROM_LEADOUT;
-		tocentry.bufferLength = sizeof(entry);
-		tocentry.buffer = &entry;
-
-		if (ioctl(fd,DKIOCCDREADTRACKINFO,&tocentry)==-1)
-		{
-			mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
-			return NULL;
-		}
-		
-		trackMSF = CDConvertLBAToMSF(entry.trackStartAddress);
-        
-		//mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
-		if (i<=hdr.lastTrackNumberInLastSessionLSB)
-		mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d: format=%d  %02d:%02d:%02d\n",
-          (int)tocentry.address,
-          //(int)tocentry.entry.addr_type,
-          //(int)tocentry.entry.control,
-          (int)tocentry.addressType,
-          (int)trackMSF.minute,
-          (int)trackMSF.second,
-          (int)trackMSF.frame
-		);
-
-		if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
-		{
-		  if (i > hdr.firstTrackNumberInLastSessionLSB)
-		  {
-		    min = trackMSF.minute - min;
-		    sec = trackMSF.second - sec;
-		    frame = trackMSF.frame - frame;
-		    if ( frame < 0 )
-		    {
-		      frame += 75;
-		      sec --;
-		    }
-		    if ( sec < 0 )
-		    {
-		      sec += 60;
-		      min --;
-		    }
-		    mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
-		  }
-		  min = trackMSF.minute;
-		  sec = trackMSF.second;
-		  frame = trackMSF.frame;
-		}
-	}
- 
-	vcd = malloc(sizeof(mp_vcd_priv_t));
-	vcd->fd = fd;
-	vcd->msf = trackMSF;
-	return vcd;
-
-	return NULL;
-}
-
-static int vcd_read(mp_vcd_priv_t* vcd,char *mem)
-{
-	if (pread(vcd->fd,&vcd->buf,VCD_SECTOR_SIZE,vcd_get_msf(vcd)*VCD_SECTOR_SIZE) != VCD_SECTOR_SIZE)
-		return 0;  // EOF?
-
-	vcd->msf.frame++;
-	if (vcd->msf.frame==75)
-	{
-		vcd->msf.frame=0;
-		vcd->msf.second++;
-        
-		if (vcd->msf.second==60)
-		{
-			vcd->msf.second=0;
-			vcd->msf.minute++;
-        }
-      }
-	  
-      memcpy(mem,vcd->buf.data,VCD_SECTOR_DATA);
-      return VCD_SECTOR_DATA;
-return 0;
-}
-
--- a/libmpdemux/vcd_read_fbsd.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-#include <sys/cdio.h>
-#include <sys/cdrio.h>
-
-//=================== VideoCD ==========================
-#define	CDROM_LEADOUT	0xAA
-
-typedef struct {
-	uint8_t sync            [12];
-	uint8_t header          [4];
-	uint8_t subheader       [8];
-	uint8_t data            [2324];
-	uint8_t spare           [4];
-} cdsector_t;
-
-typedef struct mp_vcd_priv_st {
-  int fd;
-  struct ioc_read_toc_single_entry entry;
-  cdsector_t buf;
-} mp_vcd_priv_t;
-
-static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect){
-  vcd->entry.entry.addr.msf.frame=sect%75;
-  sect=sect/75;
-  vcd->entry.entry.addr.msf.second=sect%60;
-  sect=sect/60;
-  vcd->entry.entry.addr.msf.minute=sect;
-}
-
-static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd){
-  return vcd->entry.entry.addr.msf.frame +
-        (vcd->entry.entry.addr.msf.second+
-         vcd->entry.entry.addr.msf.minute*60)*75;
-}
-
-int vcd_seek_to_track(mp_vcd_priv_t* vcd, int track){
-  vcd->entry.address_format = CD_MSF_FORMAT;
-  vcd->entry.track  = track;
-  if (ioctl(vcd->fd, CDIOREADTOCENTRY, &vcd->entry)) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
-    return -1;
-  }
-  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
-}
-
-int vcd_get_track_end(mp_vcd_priv_t* vcd, int track){
-  struct ioc_toc_header tochdr;
-  if (ioctl(vcd->fd,CDIOREADTOCHEADER,&tochdr)==-1) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-    return -1;
-  }
-  vcd->entry.address_format = CD_MSF_FORMAT;
-  vcd->entry.track  = track<tochdr.ending_track?(track+1):CDROM_LEADOUT;
-  if (ioctl(vcd->fd, CDIOREADTOCENTRY, &vcd->entry)) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
-    return -1;
-  }
-  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
-}
-
-mp_vcd_priv_t* vcd_read_toc(int fd){
-  struct ioc_toc_header tochdr;
-  mp_vcd_priv_t* vcd;
-  int i, min = 0, sec = 0, frame = 0;
-  if (ioctl(fd,CDIOREADTOCHEADER,&tochdr)==-1) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-    return NULL;
-  }
-  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", tochdr.starting_track);
-  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", tochdr.ending_track);
-  for (i=tochdr.starting_track ; i<=tochdr.ending_track + 1; i++){
-      struct ioc_read_toc_single_entry tocentry;
-
-      tocentry.track  = i<=tochdr.ending_track ? i : CDROM_LEADOUT;
-      tocentry.address_format = CD_MSF_FORMAT;
-
-      if (ioctl(fd,CDIOREADTOCENTRY,&tocentry)==-1) {
-	mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
-	return NULL;
-      }
-        
-      if (i<=tochdr.ending_track)
-      mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
-          (int)tocentry.track,
-          (int)tocentry.entry.addr_type,
-          (int)tocentry.entry.control,
-          (int)tocentry.address_format,
-          (int)tocentry.entry.addr.msf.minute,
-          (int)tocentry.entry.addr.msf.second,
-          (int)tocentry.entry.addr.msf.frame
-      );
-
-      if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
-      {
-        if (i > tochdr.starting_track)
-        {
-          min = tocentry.entry.addr.msf.minute - min;
-          sec = tocentry.entry.addr.msf.second - sec;
-          frame = tocentry.entry.addr.msf.frame - frame;
-          if ( frame < 0 )
-          {
-            frame += 75;
-            sec --;
-          }
-          if ( sec < 0 )
-          {
-            sec += 60;
-            min --;
-          }
-          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
-        }
-        min = tocentry.entry.addr.msf.minute;
-        sec = tocentry.entry.addr.msf.second;
-        frame = tocentry.entry.addr.msf.frame;
-      }
-    }
-  vcd = malloc(sizeof(mp_vcd_priv_t));
-  vcd->fd = fd;
-  return vcd;  
-}
-
-static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
-
-      if (pread(vcd->fd,&vcd->buf,VCD_SECTOR_SIZE,vcd_get_msf(vcd)*VCD_SECTOR_SIZE)
-	 != VCD_SECTOR_SIZE) return 0;  // EOF?
-
-      vcd->entry.entry.addr.msf.frame++;
-      if (vcd->entry.entry.addr.msf.frame==75){
-        vcd->entry.entry.addr.msf.frame=0;
-        vcd->entry.entry.addr.msf.second++;
-        if (vcd->entry.entry.addr.msf.second==60){
-          vcd->entry.entry.addr.msf.second=0;
-          vcd->entry.entry.addr.msf.minute++;
-        }
-      }
-      memcpy(mem,vcd->buf.data,VCD_SECTOR_DATA);
-      return VCD_SECTOR_DATA;
-}
-
--- a/libmpdemux/vcd_read_nbsd.h	Mon Jul 31 12:35:04 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-
-#include <sys/types.h>
-#ifdef __NetBSD__
-#include <sys/inttypes.h>
-#endif
-#include <sys/cdio.h>
-#include <sys/scsiio.h>
-
-#define	CDROM_LEADOUT	0xAA
-
-typedef struct mp_vcd_priv_st {
-  int fd;
-  struct ioc_read_toc_entry entry;
-  struct cd_toc_entry entry_data;
-} mp_vcd_priv_t;
-
-static inline void 
-vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect)
-{
-  vcd->entry_data.addr.msf.frame = sect % 75;
-  sect = sect / 75;
-  vcd->entry_data.addr.msf.second = sect % 60;
-  sect = sect / 60;
-  vcd->entry_data.addr.msf.minute = sect;
-}
-
-static inline void
-vcd_inc_msf(mp_vcd_priv_t* vcd)
-{
-  vcd->entry_data.addr.msf.frame++;
-  if (vcd->entry_data.addr.msf.frame==75){
-    vcd->entry_data.addr.msf.frame=0;
-    vcd->entry_data.addr.msf.second++;
-    if (vcd->entry_data.addr.msf.second==60){
-      vcd->entry_data.addr.msf.second=0;
-      vcd->entry_data.addr.msf.minute++;
-    }
-  }
-}
-
-static inline unsigned int 
-vcd_get_msf(mp_vcd_priv_t* vcd)
-{
-  return vcd->entry_data.addr.msf.frame +
-  (vcd->entry_data.addr.msf.second +
-   vcd->entry_data.addr.msf.minute * 60) * 75;
-}
-
-int 
-vcd_seek_to_track(mp_vcd_priv_t* vcd, int track)
-{
-  vcd->entry.address_format = CD_MSF_FORMAT;
-  vcd->entry.starting_track = track;
-  vcd->entry.data_len = sizeof(struct cd_toc_entry);
-  vcd->entry.data = &vcd->entry_data;
-  if (ioctl(vcd->fd, CDIOREADTOCENTRIES, &vcd->entry)) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
-    return -1;
-  }
-  return VCD_SECTOR_DATA * vcd_get_msf(vcd);
-}
-
-int 
-vcd_get_track_end(mp_vcd_priv_t* vcd, int track)
-{
-  struct ioc_toc_header tochdr;
-  if (ioctl(vcd->fd, CDIOREADTOCHEADER, &tochdr) == -1) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-    return -1;
-  }
-  vcd->entry.address_format = CD_MSF_FORMAT;
-  vcd->entry.starting_track = track < tochdr.ending_track ? (track + 1) : CDROM_LEADOUT;
-  vcd->entry.data_len = sizeof(struct cd_toc_entry);
-  vcd->entry.data = &vcd->entry_data;
-  if (ioctl(vcd->fd, CDIOREADTOCENTRYS, &vcd->entry)) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
-    return -1;
-  }
-  return VCD_SECTOR_DATA * vcd_get_msf(vcd);
-}
-
-mp_vcd_priv_t*
-vcd_read_toc(int fd)
-{
-  struct ioc_toc_header tochdr;
-  mp_vcd_priv_t* vcd;
-  int i, min = 0, sec = 0, frame = 0;
-  if (ioctl(fd, CDIOREADTOCHEADER, &tochdr) == -1) {
-    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
-    return;
-  }
-  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", tochdr.starting_track);
-  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", tochdr.ending_track);
-  for (i = tochdr.starting_track; i <= tochdr.ending_track + 1; i++) {
-    struct ioc_read_toc_entry tocentry;
-    struct cd_toc_entry tocentry_data;
-
-    tocentry.starting_track = i<=tochdr.ending_track ? i : CDROM_LEADOUT;
-    tocentry.address_format = CD_MSF_FORMAT;
-    tocentry.data_len = sizeof(struct cd_toc_entry);
-    tocentry.data = &tocentry_data;
-
-    if (ioctl(fd, CDIOREADTOCENTRYS, &tocentry) == -1) {
-      mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
-      return NULL;
-    }
-    if (i <= tochdr.ending_track)
-    mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
-	   (int) tocentry.starting_track,
-	   (int) tocentry.data->addr_type,
-	   (int) tocentry.data->control,
-	   (int) tocentry.address_format,
-	   (int) tocentry.data->addr.msf.minute,
-	   (int) tocentry.data->addr.msf.second,
-	   (int) tocentry.data->addr.msf.frame
-      );
-
-    if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
-    {
-      if (i > tochdr.starting_track)
-      {
-        min = tocentry.data->addr.msf.minute - min;
-        sec = tocentry.data->addr.msf.second - sec;
-        frame = tocentry.data->addr.msf.frame - frame;
-        if ( frame < 0 )
-        {
-          frame += 75;
-          sec --;
-        }
-        if ( sec < 0 )
-        {
-          sec += 60;
-          min --;
-        }
-        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
-      }
-      min = tocentry.data->addr.msf.minute;
-      sec = tocentry.data->addr.msf.second;
-      frame = tocentry.data->addr.msf.frame;
-    }
-  }
-  vcd = malloc(sizeof(mp_vcd_priv_t));
-  vcd->fd = fd;
-  return vcd;
-}
-
-static int 
-vcd_read(mp_vcd_priv_t* vcd, char *mem)
-{
-  struct scsireq  sc;
-  int             lba = vcd_get_msf(vcd);
-  int             blocks;
-  int             sector_type;
-  int             sync, header_code, user_data, edc_ecc, error_field;
-  int             sub_channel;
-  int             rc;
-
-  blocks = 1;
-  sector_type = 5;		/* mode2/form2 */
-  sync = 0;
-  header_code = 0;
-  user_data = 1;
-  edc_ecc = 0;
-  error_field = 0;
-  sub_channel = 0;
-
-  memset(&sc, 0, sizeof(sc));
-  sc.cmd[0] = 0xBE;
-  sc.cmd[1] = (sector_type) << 2;
-  sc.cmd[2] = (lba >> 24) & 0xff;
-  sc.cmd[3] = (lba >> 16) & 0xff;
-  sc.cmd[4] = (lba >> 8) & 0xff;
-  sc.cmd[5] = lba & 0xff;
-  sc.cmd[6] = (blocks >> 16) & 0xff;
-  sc.cmd[7] = (blocks >> 8) & 0xff;
-  sc.cmd[8] = blocks & 0xff;
-  sc.cmd[9] = (sync << 7) | (header_code << 5) | (user_data << 4) |
-    (edc_ecc << 3) | (error_field << 1);
-  sc.cmd[10] = sub_channel;
-  sc.cmdlen = 12;
-  sc.databuf = (caddr_t) mem;
-  sc.datalen = 2328;
-  sc.senselen = sizeof(sc.sense);
-  sc.flags = SCCMD_READ;
-  sc.timeout = 10000;
-  rc = ioctl(vcd->fd, SCIOCCOMMAND, &sc);
-  if (rc == -1) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"SCIOCCOMMAND: %s\n",strerror(errno));
-    return -1;
-  }
-  if (sc.retsts || sc.error) {
-    mp_msg(MSGT_STREAM,MSGL_ERR,"scsi command failed: status %d error %d\n",
-	   sc.retsts,sc.error);
-    return -1;
-  }
-  vcd_inc_msf(vcd);
-  return VCD_SECTOR_DATA;
-}
-
--- a/m_option.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/m_option.c	Mon Jul 31 17:39:17 2006 +0000
@@ -15,7 +15,7 @@
 #include "m_option.h"
 //#include "m_config.h"
 #include "mp_msg.h"
-#include "libmpdemux/url.h"
+#include "stream/url.h"
 
 // Don't free for 'production' atm
 #ifndef MP_DEBUG
--- a/mencoder.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/mencoder.c	Mon Jul 31 17:39:17 2006 +0000
@@ -48,7 +48,7 @@
 #include "m_config.h"
 #include "parser-mecmd.h"
 
-#include "libmpdemux/stream.h"
+#include "stream/stream.h"
 #include "libmpdemux/demuxer.h"
 #include "libmpdemux/stheader.h"
 #include "libmpdemux/mp3_hdr.h"
@@ -76,7 +76,7 @@
 #include "get_path.c"
 
 #ifdef USE_DVDREAD
-#include "libmpdemux/stream_dvd.h"
+#include "stream/stream_dvd.h"
 #endif
 
 #ifdef USE_LIBAVCODEC
--- a/mplayer.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/mplayer.c	Mon Jul 31 17:39:17 2006 +0000
@@ -106,11 +106,11 @@
 #endif /* HAVE_RTC */
 
 #ifdef USE_TV
-#include "libmpdemux/tv.h"
+#include "stream/tv.h"
 #endif
 
 #ifdef HAS_DVBIN_SUPPORT
-#include "libmpdemux/dvbin.h"
+#include "stream/dvbin.h"
 static int last_dvb_step = 1;
 static int dvbin_reopen = 0;
 extern void cache_uninit(stream_t *s);
@@ -175,14 +175,14 @@
 
 static int max_framesize=0;
 
-#include "libmpdemux/stream.h"
+#include "stream/stream.h"
 #include "libmpdemux/demuxer.h"
 #include "libmpdemux/stheader.h"
 //#include "parse_es.h"
 #include "libmpdemux/matroska.h"
 
 #ifdef USE_DVDREAD
-#include "libmpdemux/stream_dvd.h"
+#include "stream/stream_dvd.h"
 #endif
 
 #include "libmpcodecs/dec_audio.h"
--- a/osdep/macosx_finder_args.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/osdep/macosx_finder_args.c	Mon Jul 31 17:39:17 2006 +0000
@@ -1,6 +1,6 @@
 #include <Carbon/Carbon.h>
 #include <ApplicationServices/ApplicationServices.h>
-#include "libmpdemux/url.h"
+#include "stream/url.h"
 #include "mp_msg.h"
 #include "m_option.h"
 #include "m_config.h"
--- a/playtreeparser.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/playtreeparser.c	Mon Jul 31 17:39:17 2006 +0000
@@ -18,7 +18,7 @@
 #include "m_config.h"
 #include "playtree.h"
 #include "playtreeparser.h"
-#include "libmpdemux/stream.h"
+#include "stream/stream.h"
 #include "libmpdemux/demuxer.h"
 #include "mp_msg.h"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/Makefile	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,151 @@
+
+LIBNAME = stream.a
+
+include ../config.mak
+
+# Core
+SRCS += mf.c \
+        open.c \
+        url.c \
+
+ifeq ($(STREAM_CACHE),yes)
+SRCS += cache2.c
+endif
+
+# Miscellaneous
+SRCS += cdinfo.c \
+        cue_read.c \
+
+ifeq ($(CDDA),yes)
+SRCS += cdda.c
+  ifeq ($(MPLAYER_NETWORK),yes)
+  SRCS += cddb.c
+  endif
+endif
+
+# Stream readers/writers
+SRCS += stream.c \
+        stream_file.c \
+        stream_null.c \
+
+ifeq ($(HAVE_DVD),yes)
+SRCS += stream_dvd.c
+endif
+ifeq ($(DVDNAV),yes)
+SRCS += dvdnav_stream.c
+endif
+ifeq ($(VCD),yes)
+SRCS += stream_vcd.c
+endif
+ifeq ($(FTP),yes)
+SRCS += stream_ftp.c
+endif
+ifeq ($(LIBSMBCLIENT),yes)
+SRCS += stream_smb.c
+endif
+ifeq ($(MPLAYER_NETWORK),yes)
+  SRCS += stream_netstream.c
+  ifeq ($(STREAMING_LIVE555),yes)
+  SRCS += stream_livedotcom.c
+  endif
+endif
+ifeq ($(VSTREAM),yes)
+SRCS += stream_vstream.c
+endif
+
+# TV in
+ifeq ($(TV),yes)
+SRCS += tv.c frequencies.c tvi_dummy.c
+  ifeq ($(TV_BSDBT848),yes)
+  SRCS += tvi_bsdbt848.c
+  endif
+  ifeq ($(TV_V4L2),yes)
+  SRCS += tvi_v4l2.c audio_in.c
+    ifeq ($(PVR),yes)
+    SRCS += stream_pvr.c
+    endif
+  endif
+  ifeq ($(TV_V4L1),yes)
+  SRCS += tvi_v4l.c audio_in.c
+  endif
+  ifeq ($(TV_V4L),yes)
+    ifeq ($(ALSA1X),yes)
+     SRCS += ai_alsa1x.c
+    endif
+    ifeq ($(ALSA9),yes)
+     SRCS += ai_alsa.c
+    endif
+    ifeq ($(OSS),yes)
+     SRCS += ai_oss.c
+    endif
+  endif
+endif
+
+ifeq ($(MPLAYER_NETWORK),yes)
+SRCS += asf_streaming.c \
+        http.c \
+        network.c \
+        cookies.c \
+        asf_mmst_streaming.c \
+        pnm.c \
+        rtp.c \
+        stream_rtsp.c \
+
+SRCS += realrtsp/asmrp.c \
+        realrtsp/real.c \
+        realrtsp/rmff.c \
+        realrtsp/sdpplin.c \
+        realrtsp/xbuffer.c \
+
+SRCS += librtsp/rtsp.c \
+        librtsp/rtsp_rtp.c \
+        librtsp/rtsp_session.c \
+
+SRCS += freesdp/common.c \
+        freesdp/errorlist.c \
+        freesdp/parser.c \
+
+endif
+
+ifeq ($(DVBIN),yes)
+SRCS += dvbin.c
+SRCS += dvb_tune.c
+endif
+
+OBJS	= $(SRCS:.c=.o)
+INCLUDE = -I.. -I../libmpdemux -I../loader $(LIBAV_INC)
+CFLAGS  = $(OPTFLAGS) $(INCLUDE) $(XMMS_CFLAGS)
+
+.SUFFIXES: .c .o
+
+# .PHONY: all clean
+
+all:	$(LIBNAME)
+
+.c.o:
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+$(LIBNAME):	$(OBJS)
+	$(AR) r $(LIBNAME) $(OBJS)
+	$(RANLIB) $(LIBNAME)
+
+clean:
+	rm -f *.o *.a *~ \
+	realrtsp/*.o realrtsp/*.a realrtsp/*~ \
+	librtsp/*.o librtsp/*.a librtsp/*~ \
+	freesdp/*.o freesdp/*.a freesdp/*~
+
+distclean: clean
+	rm -f .depend test
+
+dep:    depend
+
+depend:
+	$(CC) -MM $(CFLAGS) test.c $(SRCS) 1>.depend
+
+#
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/ai_alsa.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,166 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "config.h"
+
+#include <alsa/asoundlib.h>
+#include "audio_in.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+int ai_alsa_setup(audio_in_t *ai)
+{
+    snd_pcm_hw_params_t *params;
+    snd_pcm_sw_params_t *swparams;
+    int buffer_size;
+    int err;
+    unsigned int rate;
+
+    snd_pcm_hw_params_alloca(&params);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    err = snd_pcm_hw_params_any(ai->alsa.handle, params);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig);
+	return -1;
+    }
+    err = snd_pcm_hw_params_set_access(ai->alsa.handle, params,
+				       SND_PCM_ACCESS_RW_INTERLEAVED);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableAccessType);
+	return -1;
+    }
+    err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt);
+	return -1;
+    }
+    err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels);
+    if (err < 0) {
+	ai->channels = snd_pcm_hw_params_get_channels(params);
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableChanCount,
+	       ai->channels);
+    } else {
+	ai->channels = ai->req_channels;
+    }
+
+    err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, ai->req_samplerate, 0);
+    assert(err >= 0);
+    rate = err;
+    ai->samplerate = rate;
+
+    ai->alsa.buffer_time = 1000000;
+    ai->alsa.buffer_time = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params,
+							       ai->alsa.buffer_time, 0);
+    assert(ai->alsa.buffer_time >= 0);
+    ai->alsa.period_time = ai->alsa.buffer_time / 4;
+    ai->alsa.period_time = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params,
+							       ai->alsa.period_time, 0);
+    assert(ai->alsa.period_time >= 0);
+    err = snd_pcm_hw_params(ai->alsa.handle, params);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams);
+	snd_pcm_hw_params_dump(params, ai->alsa.log);
+	return -1;
+    }
+    ai->alsa.chunk_size = snd_pcm_hw_params_get_period_size(params, 0);
+    buffer_size = snd_pcm_hw_params_get_buffer_size(params);
+    if (ai->alsa.chunk_size == buffer_size) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize, ai->alsa.chunk_size, (long)buffer_size);
+	return -1;
+    }
+    snd_pcm_sw_params_current(ai->alsa.handle, swparams);
+    err = snd_pcm_sw_params_set_sleep_min(ai->alsa.handle, swparams,0);
+    assert(err >= 0);
+    err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size);
+    assert(err >= 0);
+
+    err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0);
+    assert(err >= 0);
+    err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size);
+    assert(err >= 0);
+
+    assert(err >= 0);
+    if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams);
+	snd_pcm_sw_params_dump(swparams, ai->alsa.log);
+	return -1;
+    }
+
+    if (mp_msg_test(MSGT_TV, MSGL_V)) {
+	snd_pcm_dump(ai->alsa.handle, ai->alsa.log);
+    }
+
+    ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
+    ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels;
+    ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8;
+    ai->samplesize = ai->alsa.bits_per_sample;
+    ai->bytes_per_sample = ai->alsa.bits_per_sample/8;
+
+    return 0;
+}
+
+int ai_alsa_init(audio_in_t *ai)
+{
+    int err;
+    
+    err = snd_pcm_open(&ai->alsa.handle, ai->alsa.device, SND_PCM_STREAM_CAPTURE, 0);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_ErrorOpeningAudio, snd_strerror(err));
+	return -1;
+    }
+    
+    err = snd_output_stdio_attach(&ai->alsa.log, stderr, 0);
+    
+    if (err < 0) {
+	return -1;
+    }
+    
+    err = ai_alsa_setup(ai);
+
+    return err;
+}
+
+#ifndef timersub
+#define	timersub(a, b, result) \
+do { \
+	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+	if ((result)->tv_usec < 0) { \
+		--(result)->tv_sec; \
+		(result)->tv_usec += 1000000; \
+	} \
+} while (0)
+#endif
+
+int ai_alsa_xrun(audio_in_t *ai)
+{
+    snd_pcm_status_t *status;
+    int res;
+	
+    snd_pcm_status_alloca(&status);
+    if ((res = snd_pcm_status(ai->alsa.handle, status))<0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatusError, snd_strerror(res));
+	return -1;
+    }
+    if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
+	struct timeval now, diff, tstamp;
+	gettimeofday(&now, 0);
+	snd_pcm_status_get_trigger_tstamp(status, &tstamp);
+	timersub(&now, &tstamp, &diff);
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUN,
+	       diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+	if (mp_msg_test(MSGT_TV, MSGL_V)) {
+	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatus);
+	    snd_pcm_status_dump(status, ai->alsa.log);
+	}
+	if ((res = snd_pcm_prepare(ai->alsa.handle))<0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError, snd_strerror(res));
+	    return -1;
+	}
+	return 0;		/* ok, data should be accepted again */
+    }
+    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError);
+    return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/ai_alsa1x.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,185 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "config.h"
+
+#include <alsa/asoundlib.h>
+#include "audio_in.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+int ai_alsa_setup(audio_in_t *ai)
+{
+    snd_pcm_hw_params_t *params;
+    snd_pcm_sw_params_t *swparams;
+    snd_pcm_uframes_t buffer_size, period_size;
+    int err;
+    int dir;
+    unsigned int rate;
+
+    snd_pcm_hw_params_alloca(&params);
+    snd_pcm_sw_params_alloca(&swparams);
+
+    err = snd_pcm_hw_params_any(ai->alsa.handle, params);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PcmBrokenConfig);
+	return -1;
+    }
+
+    err = snd_pcm_hw_params_set_access(ai->alsa.handle, params,
+				       SND_PCM_ACCESS_RW_INTERLEAVED);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableAccessType);
+	return -1;
+    }
+
+    err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableSampleFmt);
+	return -1;
+    }
+
+    err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels);
+    if (err < 0) {
+	snd_pcm_hw_params_get_channels(params, &ai->channels);
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_UnavailableChanCount,
+	       ai->channels);
+    } else {
+	ai->channels = ai->req_channels;
+    }
+
+    dir = 0;
+    rate = ai->req_samplerate;
+    err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, &rate, &dir);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetSamplerate);
+    }
+    ai->samplerate = rate;
+
+    dir = 0;
+    ai->alsa.buffer_time = 1000000;
+    err = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params,
+						 &ai->alsa.buffer_time, &dir);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetBufferTime);
+    }
+
+    dir = 0;
+    ai->alsa.period_time = ai->alsa.buffer_time / 4;
+    err = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params,
+						 &ai->alsa.period_time, &dir);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA1X_CannotSetPeriodTime);
+    }
+
+    err = snd_pcm_hw_params(ai->alsa.handle, params);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallHWParams, snd_strerror(err));
+	snd_pcm_hw_params_dump(params, ai->alsa.log);
+	return -1;
+    }
+
+    dir = -1;
+    snd_pcm_hw_params_get_period_size(params, &period_size, &dir);
+    snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
+    ai->alsa.chunk_size = period_size;
+    if (period_size == buffer_size) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_PeriodEqualsBufferSize, ai->alsa.chunk_size, (long)buffer_size);
+	return -1;
+    }
+
+    snd_pcm_sw_params_current(ai->alsa.handle, swparams);
+    err = snd_pcm_sw_params_set_sleep_min(ai->alsa.handle, swparams,0);
+    assert(err >= 0);
+    err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size);
+    assert(err >= 0);
+
+    err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0);
+    assert(err >= 0);
+    err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size);
+    assert(err >= 0);
+
+    assert(err >= 0);
+    if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_CannotInstallSWParams);
+	snd_pcm_sw_params_dump(swparams, ai->alsa.log);
+	return -1;
+    }
+
+    if (mp_msg_test(MSGT_TV, MSGL_V)) {
+	snd_pcm_dump(ai->alsa.handle, ai->alsa.log);
+    }
+
+    ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
+    ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels;
+    ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8;
+    ai->samplesize = ai->alsa.bits_per_sample;
+    ai->bytes_per_sample = ai->alsa.bits_per_sample/8;
+
+    return 0;
+}
+
+int ai_alsa_init(audio_in_t *ai)
+{
+    int err;
+    
+    err = snd_pcm_open(&ai->alsa.handle, ai->alsa.device, SND_PCM_STREAM_CAPTURE, 0);
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_ErrorOpeningAudio, snd_strerror(err));
+	return -1;
+    }
+    
+    err = snd_output_stdio_attach(&ai->alsa.log, stderr, 0);
+    
+    if (err < 0) {
+	return -1;
+    }
+    
+    err = ai_alsa_setup(ai);
+
+    return err;
+}
+
+#ifndef timersub
+#define	timersub(a, b, result) \
+do { \
+	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+	if ((result)->tv_usec < 0) { \
+		--(result)->tv_sec; \
+		(result)->tv_usec += 1000000; \
+	} \
+} while (0)
+#endif
+
+int ai_alsa_xrun(audio_in_t *ai)
+{
+    snd_pcm_status_t *status;
+    int res;
+	
+    snd_pcm_status_alloca(&status);
+    if ((res = snd_pcm_status(ai->alsa.handle, status))<0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatusError, snd_strerror(res));
+	return -1;
+    }
+    if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
+	struct timeval now, diff, tstamp;
+	gettimeofday(&now, 0);
+	snd_pcm_status_get_trigger_tstamp(status, &tstamp);
+	timersub(&now, &tstamp, &diff);
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUN,
+	       diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+	if (mp_msg_test(MSGT_TV, MSGL_V)) {
+	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaStatus);
+	    snd_pcm_status_dump(status, ai->alsa.log);
+	}
+	if ((res = snd_pcm_prepare(ai->alsa.handle))<0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaXRUNPrepareError, snd_strerror(res));
+	    return -1;
+	}
+	return 0;		/* ok, data should be accepted again */
+    }
+    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIALSA_AlsaReadWriteError);
+    return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/ai_oss.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,139 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+
+#include <string.h> /* strerror */
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#else
+#ifdef HAVE_SOUNDCARD_H
+#include <soundcard.h>
+#else
+#include <linux/soundcard.h>
+#endif
+#endif
+
+#include "audio_in.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+int ai_oss_set_samplerate(audio_in_t *ai)
+{
+    int tmp = ai->req_samplerate;
+    if (ioctl(ai->oss.audio_fd, SNDCTL_DSP_SPEED, &tmp) == -1) return -1;
+    ai->samplerate = tmp;
+    return 0;
+}
+
+int ai_oss_set_channels(audio_in_t *ai)
+{
+    int err;
+    int ioctl_param;
+
+    if (ai->req_channels > 2)
+    {
+	ioctl_param = ai->req_channels;
+	mp_msg(MSGT_TV, MSGL_V, "ioctl dsp channels: %d\n",
+	       err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_CHANNELS, &ioctl_param));
+	if (err < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetChanCount,
+		   ai->req_channels);
+	    return -1;
+	}
+	ai->channels = ioctl_param;
+    }
+    else
+    {
+	ioctl_param = (ai->req_channels == 2);
+	mp_msg(MSGT_TV, MSGL_V, "ioctl dsp stereo: %d (req: %d)\n",
+	       err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_STEREO, &ioctl_param),
+	       ioctl_param);
+	if (err < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetStereo,
+		   ai->req_channels == 2);
+	    return -1;
+	}
+	ai->channels = ioctl_param ? 2 : 1;
+    }
+    return 0;
+}
+
+int ai_oss_init(audio_in_t *ai)
+{
+    int err;
+    int ioctl_param;
+
+    ai->oss.audio_fd = open(ai->oss.device, O_RDONLY);
+    if (ai->oss.audio_fd < 0)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2Open,
+	       ai->oss.device, strerror(errno));
+	return -1;
+    }
+	
+    ioctl_param = 0 ;
+    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp getfmt: %d\n",
+	   ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETFMTS, &ioctl_param));
+	
+    mp_msg(MSGT_TV, MSGL_V, "Supported formats: %x\n", ioctl_param);
+    if (!(ioctl_param & AFMT_S16_LE))
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_UnsupportedFmt);
+
+    ioctl_param = AFMT_S16_LE;
+    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp setfmt: %d\n",
+	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SETFMT, &ioctl_param));
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetAudioFmt);
+	return -1;
+    }
+
+    if (ai_oss_set_channels(ai) < 0) return -1;
+	
+    ioctl_param = ai->req_samplerate;
+    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp speed: %d\n",
+	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SPEED, &ioctl_param));
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetSamplerate,
+	       ai->req_samplerate);
+	return -1;
+    }
+    ai->samplerate = ioctl_param;
+
+    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp trigger: %d\n",
+	   ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETTRIGGER, &ioctl_param));
+    mp_msg(MSGT_TV, MSGL_V, "trigger: %x\n", ioctl_param);
+    ioctl_param = PCM_ENABLE_INPUT;
+    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp trigger: %d\n",
+	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SETTRIGGER, &ioctl_param));
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2SetTrigger,
+	       PCM_ENABLE_INPUT);
+    }
+
+    ai->blocksize = 0;
+    mp_msg(MSGT_TV, MSGL_V, "ioctl dsp getblocksize: %d\n",
+	   err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETBLKSIZE, &ai->blocksize));
+    if (err < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_Unable2GetBlockSize);
+    }
+    mp_msg(MSGT_TV, MSGL_V, "blocksize: %d\n", ai->blocksize);
+
+    // correct the blocksize to a reasonable value
+    if (ai->blocksize <= 0) {
+	ai->blocksize = 4096*ai->channels*2;
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_AudioBlockSizeZero, ai->blocksize);
+    } else if (ai->blocksize < 4096*ai->channels*2) {
+	ai->blocksize *= 4096*ai->channels*2/ai->blocksize;
+	mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AIOSS_AudioBlockSize2Low, ai->blocksize);
+    }
+
+    ai->samplesize = 16;
+    ai->bytes_per_sample = 2;
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/asf_mmst_streaming.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,665 @@
+// mmst implementation taken from the xine-mms plugin made by majormms (http://geocities.com/majormms/)
+// 
+// ported to mplayer by Abhijeet Phatak <abhijeetphatak@yahoo.com>
+// date : 16 April 2002
+//
+// information about the mms protocol can be find at http://get.to/sdp
+//
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#else
+#include <winsock2.h>
+#endif
+
+#ifndef USE_SETLOCALE
+#undef USE_ICONV
+#endif
+
+#ifdef USE_ICONV
+#include <iconv.h>
+#ifdef USE_LANGINFO
+#include <langinfo.h>
+#endif
+#endif
+
+#include "url.h"
+#include "asf.h"
+
+#include "stream.h"
+
+#include "network.h"
+
+#define BUF_SIZE 102400
+#define HDR_BUF_SIZE 8192
+#define MAX_STREAMS 20
+
+typedef struct 
+{
+  uint8_t buf[BUF_SIZE];
+  int     num_bytes;
+
+} command_t;
+
+static int seq_num;
+static int num_stream_ids;
+static int stream_ids[MAX_STREAMS];
+
+static int get_data (int s, char *buf, size_t count);
+
+static void put_32 (command_t *cmd, uint32_t value) 
+{
+  cmd->buf[cmd->num_bytes  ] = value % 256;
+  value = value >> 8;
+  cmd->buf[cmd->num_bytes+1] = value % 256 ;
+  value = value >> 8;
+  cmd->buf[cmd->num_bytes+2] = value % 256 ;
+  value = value >> 8;
+  cmd->buf[cmd->num_bytes+3] = value % 256 ;
+
+  cmd->num_bytes += 4;
+}
+
+static uint32_t get_32 (unsigned char *cmd, int offset) 
+{
+  uint32_t ret;
+
+  ret = cmd[offset] ;
+  ret |= cmd[offset+1]<<8 ;
+  ret |= cmd[offset+2]<<16 ;
+  ret |= cmd[offset+3]<<24 ;
+
+  return ret;
+}
+
+static void send_command (int s, int command, uint32_t switches, 
+			  uint32_t extra, int length,
+			  char *data) 
+{
+  command_t  cmd;
+  int        len8;
+
+  len8 = (length + 7) / 8;
+
+  cmd.num_bytes = 0;
+
+  put_32 (&cmd, 0x00000001); /* start sequence */
+  put_32 (&cmd, 0xB00BFACE); /* #-)) */
+  put_32 (&cmd, len8*8 + 32);
+  put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */
+  put_32 (&cmd, len8 + 4);
+  put_32 (&cmd, seq_num);
+  seq_num++;
+  put_32 (&cmd, 0x0);        /* unknown */
+  put_32 (&cmd, 0x0);
+  put_32 (&cmd, len8+2);
+  put_32 (&cmd, 0x00030000 | command); /* dir | command */
+  put_32 (&cmd, switches);
+  put_32 (&cmd, extra);
+
+  memcpy (&cmd.buf[48], data, length);
+  if (length & 7)
+    memset(&cmd.buf[48 + length], 0, 8 - (length & 7));
+
+  if (send (s, cmd.buf, len8*8+48, 0) != (len8*8+48)) {
+    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_WriteError);
+  }
+}
+
+#ifdef USE_ICONV
+static iconv_t url_conv;
+#endif
+
+static void string_utf16(char *dest, char *src, int len) {
+    int i;
+#ifdef USE_ICONV
+    size_t len1, len2;
+    char *ip, *op;
+
+    if (url_conv != (iconv_t)(-1))
+    {
+    memset(dest, 0, 1000);
+    len1 = len; len2 = 1000;
+    ip = src; op = dest;
+
+    iconv(url_conv, &ip, &len1, &op, &len2);
+    }
+    else
+    {
+#endif
+	if (len > 499) len = 499;
+	for (i=0; i<len; i++) {
+	    dest[i*2] = src[i];
+	    dest[i*2+1] = 0;
+        }
+	/* trailing zeroes */
+	dest[i*2] = 0;
+	dest[i*2+1] = 0;
+#ifdef USE_ICONV
+    }
+#endif
+}
+
+static void get_answer (int s) 
+{
+  char  data[BUF_SIZE];
+  int   command = 0x1b;
+
+  while (command == 0x1b) {
+    int len;
+
+    len = recv (s, data, BUF_SIZE, 0) ;
+    if (!len) {
+      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_EOFAlert);
+      return;
+    }
+
+    command = get_32 (data, 36) & 0xFFFF;
+
+    if (command == 0x1b) 
+      send_command (s, 0x1b, 0, 0, 0, data);
+  }
+}
+
+static int get_data (int s, char *buf, size_t count) 
+{
+  ssize_t  len;
+  size_t total = 0;
+
+  while (total < count) {
+
+    len = recv (s, &buf[total], count-total, 0);
+
+    if (len<=0) {
+      perror ("read error:");
+      return 0;
+    }
+
+    total += len;
+
+    if (len != 0) {
+//      mp_msg(MSGT_NETWORK,MSGL_INFO,"[%d/%d]", total, count);
+      fflush (stdout);
+    }
+
+  }
+
+  return 1;
+
+}
+
+static int get_header (int s, uint8_t *header, streaming_ctrl_t *streaming_ctrl) 
+{
+  unsigned char  pre_header[8];
+  int            header_len;
+
+  header_len = 0;
+
+  while (1) {
+    if (!get_data (s, pre_header, 8)) {
+      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_PreHeaderReadFailed);
+      return 0;
+    }
+    if (pre_header[4] == 0x02) {
+      
+      int packet_len;
+      
+      packet_len = (pre_header[7] << 8 | pre_header[6]) - 8;
+
+//      mp_msg(MSGT_NETWORK,MSGL_INFO,"asf header packet detected, len=%d\n", packet_len);
+
+      if (packet_len < 0 || packet_len > HDR_BUF_SIZE - header_len) {
+        mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_MMST_InvalidHeaderSize);
+        return 0;
+      }
+
+      if (!get_data (s, &header[header_len], packet_len)) {
+	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_HeaderDataReadFailed);
+	return 0;
+      }
+
+      header_len += packet_len;
+
+      if ( (header[header_len-1] == 1) && (header[header_len-2]==1)) {
+	
+
+     if( streaming_bufferize( streaming_ctrl, header, header_len )<0 ) {
+				return -1;
+ 	 }
+
+     //	mp_msg(MSGT_NETWORK,MSGL_INFO,"get header packet finished\n");
+
+	return (header_len);
+
+      } 
+
+    } else {
+
+      int32_t packet_len;
+      int command;
+      char data[BUF_SIZE];
+
+      if (!get_data (s, (char*)&packet_len, 4)) {
+	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_packet_lenReadFailed);
+	return 0;
+      }
+      
+      packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4;
+      
+//      mp_msg(MSGT_NETWORK,MSGL_INFO,"command packet detected, len=%d\n", packet_len);
+
+      if (packet_len < 0 || packet_len > BUF_SIZE) {
+        mp_msg(MSGT_NETWORK, MSGL_FATAL,
+                MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize);
+        return 0;
+      }
+      
+      if (!get_data (s, data, packet_len)) {
+	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_CmdDataReadFailed);
+	return 0;
+      }
+      
+      command = get_32 (data, 24) & 0xFFFF;
+      
+//      mp_msg(MSGT_NETWORK,MSGL_INFO,"command: %02x\n", command);
+      
+      if (command == 0x1b) 
+	send_command (s, 0x1b, 0, 0, 0, data);
+      
+    }
+
+//    mp_msg(MSGT_NETWORK,MSGL_INFO,"get header packet succ\n");
+  }
+}
+
+static int interp_header (uint8_t *header, int header_len) 
+{
+  int i;
+  int packet_length=-1;
+
+  /*
+   * parse header
+   */
+
+  i = 30;
+  while (i<header_len) {
+    
+    uint64_t  guid_1, guid_2, length;
+
+    guid_2 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) 
+      | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24)
+      | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40)
+      | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56);
+    i += 8;
+
+    guid_1 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) 
+      | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24)
+      | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40)
+      | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56);
+    i += 8;
+    
+//    mp_msg(MSGT_NETWORK,MSGL_INFO,"guid found: %016llx%016llx\n", guid_1, guid_2);
+
+    length = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) 
+      | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24)
+      | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40)
+      | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56);
+
+    i += 8;
+
+    if ( (guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22630ULL) ) {
+      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_HeaderObject);
+    } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) {
+      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_DataObject);
+    } else if ((guid_1 == 0x6553200cc000e48eULL) && (guid_2 == 0x11cfa9478cabdca1ULL)) {
+
+      packet_length = get_32(header, i+92-24);
+
+      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_FileObjectPacketLen,
+	      packet_length, get_32(header, i+96-24));
+
+
+    } else if ((guid_1 == 0x6553200cc000e68eULL) && (guid_2 == 0x11cfa9b7b7dc0791ULL)) {
+
+      int stream_id = header[i+48] | header[i+49] << 8;
+
+      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_StreamObjectStreamID, stream_id);
+
+      if (num_stream_ids < MAX_STREAMS) {
+      stream_ids[num_stream_ids] = stream_id;
+      num_stream_ids++;
+      } else {
+        mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_2ManyStreamID);
+      }
+      
+    } else {
+#if 0
+      int b = i;
+      printf ("unknown object (guid: %016llx, %016llx, len: %lld)\n", guid_1, guid_2, length);
+      for (; b < length; b++)
+      {
+        if (isascii(header[b]) || isalpha(header[b]))
+	    printf("%c ", header[b]);
+	else
+    	    printf("%x ", header[b]);
+      }
+      printf("\n");
+#else
+      mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_MMST_UnknownObject);
+#endif
+    }
+
+//    mp_msg(MSGT_NETWORK,MSGL_INFO,"length    : %lld\n", length);
+
+    i += length-24;
+
+  }
+
+  return packet_length;
+
+}
+
+
+static int get_media_packet (int s, int padding, streaming_ctrl_t *stream_ctrl) {
+  unsigned char  pre_header[8];
+  char           data[BUF_SIZE];
+
+  if (!get_data (s, pre_header, 8)) {
+    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_PreHeaderReadFailed);
+    return 0;
+  }
+
+//  for (i=0; i<8; i++)
+//    mp_msg(MSGT_NETWORK,MSGL_INFO,"pre_header[%d] = %02x (%d)\n",
+//	    i, pre_header[i], pre_header[i]);
+
+  if (pre_header[4] == 0x04) {
+
+    int packet_len;
+
+    packet_len = (pre_header[7] << 8 | pre_header[6]) - 8;
+
+//    mp_msg(MSGT_NETWORK,MSGL_INFO,"asf media packet detected, len=%d\n", packet_len);
+
+    if (packet_len < 0 || packet_len > BUF_SIZE) {
+      mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize);
+      return 0;
+    }
+      
+    if (!get_data (s, data, packet_len)) {
+      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_MediaDataReadFailed);
+      return 0;
+    }
+
+    streaming_bufferize(stream_ctrl, data, padding);
+
+  } else {
+
+    int32_t packet_len;
+    int command;
+
+    if (!get_data (s, (char*)&packet_len, 4)) {
+      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_packet_lenReadFailed);
+      return 0;
+    }
+
+    packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4;
+
+    if (packet_len < 0 || packet_len > BUF_SIZE) {
+      mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MPDEMUX_MMST_InvalidRTSPPacketSize);
+      return 0;
+    }
+
+    if (!get_data (s, data, packet_len)) {
+      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_CmdDataReadFailed);
+      return 0;
+    }
+
+    if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b)
+	 || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) {
+
+      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_MissingSignature);
+      return -1;
+    }
+
+    command = get_32 (data, 24) & 0xFFFF;
+
+//    mp_msg(MSGT_NETWORK,MSGL_INFO,"\ncommand packet detected, len=%d  cmd=0x%X\n", packet_len, command);
+
+    if (command == 0x1b) 
+      send_command (s, 0x1b, 0, 0, 0, data);
+    else if (command == 0x1e) {
+      mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_PatentedTechnologyJoke);
+      return 0;
+    }
+    else if (command == 0x21 ) {
+	// Looks like it's new in WMS9
+	// Unknown command, but ignoring it seems to work.
+	return 0;
+    }
+    else if (command != 0x05) {
+      mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_UnknownCmd,command);
+      return -1;
+    }
+  }
+
+//  mp_msg(MSGT_NETWORK,MSGL_INFO,"get media packet succ\n");
+
+  return 1;
+}
+
+
+static int packet_length1;
+
+static int asf_mmst_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) 
+{
+  int len;
+  
+  while( stream_ctrl->buffer_size==0 ) {
+          // buffer is empty - fill it!
+	  int ret = get_media_packet( fd, packet_length1, stream_ctrl);
+	  if( ret<0 ) {
+		  mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_MMST_GetMediaPacketErr,strerror(errno));
+		  return -1;
+	  } else if (ret==0) //EOF?
+		  return ret;
+  }
+  
+	  len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos;
+	  if(len>size) len=size;
+	  memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len );
+	  stream_ctrl->buffer_pos += len;
+	  if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) {
+		  free( stream_ctrl->buffer );
+		  stream_ctrl->buffer = NULL;
+		  stream_ctrl->buffer_size = 0;
+		  stream_ctrl->buffer_pos = 0;
+	  }
+	  return len;
+
+}
+
+static int asf_mmst_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) 
+{
+	return -1;
+	// Shut up gcc warning
+	fd++;
+	pos++;
+	streaming_ctrl=NULL;
+}
+
+int asf_mmst_streaming_start(stream_t *stream)
+{
+  char                 str[1024];
+  char                 data[BUF_SIZE];
+  uint8_t              asf_header[HDR_BUF_SIZE];
+  int                  asf_header_len;
+  int                  len, i, packet_length;
+  char                *path, *unescpath;
+  URL_t *url1 = stream->streaming_ctrl->url;
+  int s = stream->fd;
+
+  if( s>0 ) {
+	  closesocket( stream->fd );
+	  stream->fd = -1;
+  }
+  
+  /* parse url */
+  path = strchr(url1->file,'/') + 1;
+
+  /* mmst filename are not url_escaped by MS MediaPlayer and are expected as
+   * "plain text" by the server, so need to decode it here
+   */
+  unescpath=malloc(strlen(path)+1);
+  if (!unescpath) {
+	mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+	return -1; 
+  }
+  url_unescape_string(unescpath,path);
+  path=unescpath;
+  
+
+  if( url1->port==0 ) {
+	url1->port=1755;
+  }
+  s = connect2Server( url1->hostname, url1->port, 1);
+  if( s<0 ) {
+	  free(path);
+	  return s;
+  }
+  mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_MMST_Connected);
+  
+  seq_num=0;
+
+  /*
+  * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. 
+  * This command is sent at the very start of protocol initiation. It sends local information to the serve 
+  * cmd 1 0x01 
+  * */
+
+  /* prepare for the url encoding conversion */
+#ifdef USE_ICONV
+#ifdef USE_LANGINFO
+  url_conv = iconv_open("UTF-16LE",nl_langinfo(CODESET));
+#else
+  url_conv = iconv_open("UTF-16LE", NULL);
+#endif
+#endif
+
+  snprintf (str, 1023, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", url1->hostname);
+  string_utf16 (data, str, strlen(str));
+// send_command(s, commandno ....)
+  send_command (s, 1, 0, 0x0004000b, strlen(str)*2+2, data);
+
+  len = recv (s, data, BUF_SIZE, 0) ;
+
+  /*This sends details of the local machine IP address to a Funnel system at the server. 
+  * Also, the TCP or UDP transport selection is sent.
+  *
+  * here 192.168.0.1 is local ip address TCP/UDP states the tronsport we r using
+  * and 1037 is the  local TCP or UDP socket number
+  * cmd 2 0x02
+  *  */
+
+  string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037", 24);
+  memset (data, 0, 8);
+  send_command (s, 2, 0, 0, 24*2+10, data);
+
+  len = recv (s, data, BUF_SIZE, 0) ;
+
+  /* This command sends file path (at server) and file name request to the server.
+  * 0x5 */
+
+  string_utf16 (&data[8], path, strlen(path));
+  memset (data, 0, 8);
+  send_command (s, 5, 0, 0, strlen(path)*2+10, data);
+  free(path);
+
+  get_answer (s);
+
+  /* The ASF header chunk request. Includes ?session' variable for pre header value. 
+  * After this command is sent, 
+  * the server replies with 0x11 command and then the header chunk with header data follows.
+  * 0x15 */
+
+  memset (data, 0, 40);
+  data[32] = 2;
+
+  send_command (s, 0x15, 1, 0, 40, data);
+
+  num_stream_ids = 0;
+  /* get_headers(s, asf_header);  */
+
+  asf_header_len = get_header (s, asf_header, stream->streaming_ctrl);
+//  mp_msg(MSGT_NETWORK,MSGL_INFO,"---------------------------------- asf_header %d\n",asf_header);
+  if (asf_header_len==0) return -1; //error reading header
+  packet_length = interp_header (asf_header, asf_header_len);
+
+
+  /* 
+  * This command is the media stream MBR selector. Switches are always 6 bytes in length.  
+  * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. 
+  * Where:  
+  * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. 
+  * It is not yet understood what all this means. 
+  * And the last [02] byte is probably the header ?session' value. 
+  *  
+  *  0x33 */
+
+  memset (data, 0, 40);
+
+  for (i=1; i<num_stream_ids; i++) {
+    data [ (i-1) * 6 + 2 ] = 0xFF;
+    data [ (i-1) * 6 + 3 ] = 0xFF;
+    data [ (i-1) * 6 + 4 ] = stream_ids[i];
+    data [ (i-1) * 6 + 5 ] = 0x00;
+  }
+
+  send_command (s, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data);
+
+  get_answer (s);
+
+  /* Start sending file from packet xx. 
+  * This command is also used for resume downloads or requesting a lost packet. 
+  * Also used for seeking by sending a play point value which seeks to the media time point. 
+  * Includes ?session' value in pre header and the maximum media stream time. 
+  * 0x07 */
+
+  memset (data, 0, 40);
+
+  for (i=8; i<16; i++)
+    data[i] = 0xFF;
+
+  data[20] = 0x04;
+
+  send_command (s, 0x07, 1, 0xFFFF | stream_ids[0] << 16, 24, data);
+
+  stream->fd = s;
+  stream->streaming_ctrl->streaming_read = asf_mmst_streaming_read;
+  stream->streaming_ctrl->streaming_seek = asf_mmst_streaming_seek;
+  stream->streaming_ctrl->buffering = 1;
+  stream->streaming_ctrl->status = streaming_playing_e;
+
+  packet_length1 = packet_length;
+  mp_msg(MSGT_NETWORK,MSGL_INFO,"mmst packet_length = %d\n", packet_length);
+
+#ifdef USE_ICONV
+  if (url_conv != (iconv_t)(-1))
+    iconv_close(url_conv);
+#endif
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/asf_streaming.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,882 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#else
+#include <winsock2.h>
+#endif
+
+#include "url.h"
+#include "http.h"
+#include "asf.h"
+
+#include "stream.h"
+#include "demuxer.h"
+
+#include "network.h"
+
+#ifdef ARCH_X86
+#define	ASF_LOAD_GUID_PREFIX(guid)	(*(uint32_t *)(guid))
+#else
+#define	ASF_LOAD_GUID_PREFIX(guid)	\
+	((guid)[3] << 24 | (guid)[2] << 16 | (guid)[1] << 8 | (guid)[0])
+#endif
+
+extern int network_bandwidth;
+
+int asf_mmst_streaming_start( stream_t *stream );
+static int asf_http_streaming_start(stream_t *stream, int *demuxer_type);
+
+// We can try several protocol for asf streaming
+// * first the UDP protcol, if there is a firewall, UDP
+//   packets will not come back, so the mmsu will fail.
+// * Then we can try TCP, but if there is a proxy for
+//   internet connection, the TCP connection will not get
+//   through
+// * Then we can try HTTP.
+// 
+// Note: Using 	WMP sequence  MMSU then MMST and then HTTP.
+
+static int asf_streaming_start( stream_t *stream, int *demuxer_type) {
+    char *proto = stream->streaming_ctrl->url->protocol;
+    int fd = -1;
+    int port = stream->streaming_ctrl->url->port;
+
+    // Is protocol mms or mmsu?
+    if (!strcasecmp(proto, "mmsu") || !strcasecmp(proto, "mms"))
+    {
+		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/UDP...\n");
+		//fd = asf_mmsu_streaming_start( stream );
+		if( fd>-1 ) return fd; //mmsu support is not implemented yet - using this code
+		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/UDP failed\n");
+		if( fd==-2 ) return -1;
+	}
+
+    //Is protocol mms or mmst?
+    if (!strcasecmp(proto, "mmst") || !strcasecmp(proto, "mms"))
+    {
+		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/TCP...\n");
+		fd = asf_mmst_streaming_start( stream );
+		stream->streaming_ctrl->url->port = port;
+		if( fd>-1 ) return fd;
+		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/TCP failed\n");
+		if( fd==-2 ) return -1;
+	}
+
+    //Is protocol http, http_proxy, or mms? 
+    if (!strcasecmp(proto, "http_proxy") || !strcasecmp(proto, "http") ||
+	!strcasecmp(proto, "mms") || !strcasecmp(proto, "mmshttp"))
+    {
+		mp_msg(MSGT_NETWORK,MSGL_V,"Trying ASF/HTTP...\n");
+		fd = asf_http_streaming_start( stream, demuxer_type );
+		stream->streaming_ctrl->url->port = port;
+		if( fd>-1 ) return fd;
+		mp_msg(MSGT_NETWORK,MSGL_V,"  ===> ASF/HTTP failed\n");
+		if( fd==-2 ) return -1;
+	}
+
+    //everything failed
+	return -1;
+}
+
+static int asf_streaming(ASF_stream_chunck_t *stream_chunck, int *drop_packet ) {
+/*	
+printf("ASF stream chunck size=%d\n", stream_chunck->size);
+printf("length: %d\n", length );
+printf("0x%02X\n", stream_chunck->type );
+*/
+	if( drop_packet!=NULL ) *drop_packet = 0;
+
+	if( stream_chunck->size<8 ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_StreamChunkSize2Small, stream_chunck->size);
+		return -1;
+	}
+	if( stream_chunck->size!=stream_chunck->size_confirm ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_SizeConfirmMismatch, stream_chunck->size, stream_chunck->size_confirm);
+		return -1;
+	}
+/*	
+	printf("  type: 0x%02X\n", stream_chunck->type );
+	printf("  size: %d (0x%02X)\n", stream_chunck->size, stream_chunck->size );
+	printf("  sequence_number: 0x%04X\n", stream_chunck->sequence_number );
+	printf("  unknown: 0x%02X\n", stream_chunck->unknown );
+	printf("  size_confirm: 0x%02X\n", stream_chunck->size_confirm );
+*/
+	switch(stream_chunck->type) {
+		case ASF_STREAMING_CLEAR:	// $C	Clear ASF configuration
+			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Clearing ASF stream configuration!\n");
+			if( drop_packet!=NULL ) *drop_packet = 1;
+			return stream_chunck->size;
+			break;
+		case ASF_STREAMING_DATA:	// $D	Data follows
+//			printf("=====> Data follows\n");
+			break;
+		case ASF_STREAMING_END_TRANS:	// $E	Transfer complete
+			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Transfer complete\n");
+			if( drop_packet!=NULL ) *drop_packet = 1;
+			return stream_chunck->size;
+			break;
+		case ASF_STREAMING_HEADER:	// $H	ASF header chunk follows
+			mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF header chunk follows\n");
+			break;
+		default:
+			mp_msg(MSGT_NETWORK,MSGL_V,"=====> Unknown stream type 0x%x\n", stream_chunck->type );
+	}
+	return stream_chunck->size+4;
+}
+
+extern int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len);
+extern const char asf_file_header_guid[];
+extern const char asf_stream_header_guid[];
+extern const char asf_stream_group_guid[];
+extern int audio_id;
+extern int video_id;
+
+static void close_s(stream_t *stream) {
+	close(stream->fd);
+	stream->fd=-1;
+}
+
+static int max_idx(int s_count, int *s_rates, int bound) {
+  int i, best = -1, rate = -1;
+  for (i = 0; i < s_count; i++) {
+    if (s_rates[i] > rate && s_rates[i] <= bound) {
+      rate = s_rates[i];
+      best = i;
+    }
+  }
+  return best;
+}
+
+static int asf_streaming_parse_header(int fd, streaming_ctrl_t* streaming_ctrl) {
+  ASF_header_t asfh;
+  ASF_stream_chunck_t chunk;
+  asf_http_streaming_ctrl_t* asf_ctrl = (asf_http_streaming_ctrl_t*) streaming_ctrl->data;
+  char* buffer=NULL, *chunk_buffer=NULL;
+  int i,r,size,pos = 0;
+  int start;
+  int buffer_size = 0;
+  int chunk_size2read = 0;
+  int bw = streaming_ctrl->bandwidth;
+  int *v_rates = NULL, *a_rates = NULL;
+  int v_rate = 0, a_rate = 0, a_idx = -1, v_idx = -1;
+  
+  if(asf_ctrl == NULL) return -1;
+
+	// The ASF header can be in several network chunks. For example if the content description
+	// is big, the ASF header will be split in 2 network chunk.
+	// So we need to retrieve all the chunk before starting to parse the header.
+  do {
+	  for( r=0; r < (int)sizeof(ASF_stream_chunck_t) ; ) {
+		i = nop_streaming_read(fd,((char*)&chunk)+r,sizeof(ASF_stream_chunck_t) - r,streaming_ctrl);
+		if(i <= 0) return -1;
+		r += i;
+	  }
+	  // Endian handling of the stream chunk
+	  le2me_ASF_stream_chunck_t(&chunk);
+	  size = asf_streaming( &chunk, &r) - sizeof(ASF_stream_chunck_t);
+	  if(r) mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_ASF_WarnDropHeader);
+	  if(size < 0){
+	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader);
+		return -1;
+	  }
+	  if (chunk.type != ASF_STREAMING_HEADER) {
+	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_NoHeaderAtFirstChunk);
+	    return -1;
+	  }
+	  
+	  // audit: do not overflow buffer_size
+	  if (size > SIZE_MAX - buffer_size) return -1;
+	  buffer = (char*) malloc(size+buffer_size);
+	  if(buffer == NULL) {
+	    mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MPDEMUX_ASF_BufferMallocFailed,size+buffer_size);
+	    return -1;
+	  }
+	  if( chunk_buffer!=NULL ) {
+	  	memcpy( buffer, chunk_buffer, buffer_size );
+		free( chunk_buffer );
+	  }
+	  chunk_buffer = buffer;
+	  buffer += buffer_size;
+	  buffer_size += size;
+	  
+	  for(r = 0; r < size;) {
+	    i = nop_streaming_read(fd,buffer+r,size-r,streaming_ctrl);
+	    if(i < 0) {
+		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingNetworkStream);
+		    return -1;
+	    }
+	    r += i;
+	  }  
+
+	  if( chunk_size2read==0 ) {
+		if(size < (int)sizeof(asfh)) {
+		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunk2Small);
+		    return -1;
+		} else mp_msg(MSGT_NETWORK,MSGL_DBG2,"Got chunk\n");
+	  	memcpy(&asfh,buffer,sizeof(asfh));
+	  	le2me_ASF_header_t(&asfh);
+		chunk_size2read = asfh.objh.size;
+		mp_msg(MSGT_NETWORK,MSGL_DBG2,"Size 2 read=%d\n", chunk_size2read);
+	  }
+  } while( buffer_size<chunk_size2read);
+  buffer = chunk_buffer;
+  size = buffer_size;
+	  
+  if(asfh.cno > 256) {
+    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrSubChunkNumberInvalid);
+    return -1;
+  }
+
+  start = sizeof(asfh);
+  
+  pos = find_asf_guid(buffer, asf_file_header_guid, start, size);
+  if (pos >= 0) {
+    ASF_file_header_t *fileh = (ASF_file_header_t *) &buffer[pos];
+    pos += sizeof(ASF_file_header_t);
+    if (pos > size) goto len_err_out;
+      le2me_ASF_file_header_t(fileh);
+/*
+      if(fileh.packetsize != fileh.packetsize2) {
+	printf("Error packetsize check don't match\n");
+	return -1;
+      }
+*/
+      asf_ctrl->packet_size = fileh->max_packet_size;
+      // before playing. 
+      // preroll: time in ms to bufferize before playing
+      streaming_ctrl->prebuffer_size = (unsigned int)(((double)fileh->preroll/1000.0)*((double)fileh->max_bitrate/8.0));
+  }
+
+  pos = start;
+  while ((pos = find_asf_guid(buffer, asf_stream_header_guid, pos, size)) >= 0)
+  {
+    ASF_stream_header_t *streamh = (ASF_stream_header_t *)&buffer[pos];
+    pos += sizeof(ASF_stream_header_t);
+    if (pos > size) goto len_err_out;
+      le2me_ASF_stream_header_t(streamh);
+      switch(ASF_LOAD_GUID_PREFIX(streamh->type)) {
+      case 0xF8699E40 : // audio stream
+	if(asf_ctrl->audio_streams == NULL){
+	  asf_ctrl->audio_streams = malloc(sizeof(int));
+	  asf_ctrl->n_audio = 1;
+	} else {
+	  asf_ctrl->n_audio++;
+	  asf_ctrl->audio_streams = (int*)realloc(asf_ctrl->audio_streams,
+						     asf_ctrl->n_audio*sizeof(int));
+	}
+	asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = streamh->stream_no;
+	break;
+      case 0xBC19EFC0 : // video stream
+	if(asf_ctrl->video_streams == NULL){
+	  asf_ctrl->video_streams = malloc(sizeof(int));
+	  asf_ctrl->n_video = 1;
+	} else {
+	  asf_ctrl->n_video++;
+	  asf_ctrl->video_streams = (int*)realloc(asf_ctrl->video_streams,
+						     asf_ctrl->n_video*sizeof(int));
+	}
+	asf_ctrl->video_streams[asf_ctrl->n_video-1] = streamh->stream_no;
+	break;
+      }
+  }
+
+  // always allocate to avoid lots of ifs later
+  v_rates = calloc(asf_ctrl->n_video, sizeof(int));
+  a_rates = calloc(asf_ctrl->n_audio, sizeof(int));
+
+  pos = find_asf_guid(buffer, asf_stream_group_guid, start, size);
+  if (pos >= 0) {
+    // stream bitrate properties object
+	int stream_count;
+	char *ptr = &buffer[pos];
+	
+	mp_msg(MSGT_NETWORK, MSGL_V, "Stream bitrate properties object\n");
+		stream_count = le2me_16(*(uint16_t*)ptr);
+		ptr += sizeof(uint16_t);
+		if (ptr > &buffer[size]) goto len_err_out;
+		mp_msg(MSGT_NETWORK, MSGL_V, " stream count=[0x%x][%u]\n",
+		        stream_count, stream_count );
+		for( i=0 ; i<stream_count ; i++ ) {
+			uint32_t rate;
+			int id;
+			int j;
+			id = le2me_16(*(uint16_t*)ptr);
+			ptr += sizeof(uint16_t);
+			if (ptr > &buffer[size]) goto len_err_out;
+			memcpy(&rate, ptr, sizeof(uint32_t));// workaround unaligment bug on sparc
+			ptr += sizeof(uint32_t);
+			if (ptr > &buffer[size]) goto len_err_out;
+			rate = le2me_32(rate);
+			mp_msg(MSGT_NETWORK, MSGL_V,
+                                "  stream id=[0x%x][%u]\n", id, id);
+			mp_msg(MSGT_NETWORK, MSGL_V,
+			        "  max bitrate=[0x%x][%u]\n", rate, rate);
+			for (j = 0; j < asf_ctrl->n_video; j++) {
+			  if (id == asf_ctrl->video_streams[j]) {
+			    mp_msg(MSGT_NETWORK, MSGL_V, "  is video stream\n");
+			    v_rates[j] = rate;
+			    break;
+			  }
+			}
+			for (j = 0; j < asf_ctrl->n_audio; j++) {
+			  if (id == asf_ctrl->audio_streams[j]) {
+			    mp_msg(MSGT_NETWORK, MSGL_V, "  is audio stream\n");
+			    a_rates[j] = rate;
+			    break;
+			  }
+			}
+		}
+  }
+  free(buffer);
+
+  // automatic stream selection based on bandwidth
+  if (bw == 0) bw = INT_MAX;
+  mp_msg(MSGT_NETWORK, MSGL_V, "Max bandwidth set to %d\n", bw);
+
+  if (asf_ctrl->n_audio) {
+    // find lowest-bitrate audio stream
+    a_rate = a_rates[0];
+    a_idx = 0;
+    for (i = 0; i < asf_ctrl->n_audio; i++) {
+      if (a_rates[i] < a_rate) {
+        a_rate = a_rates[i];
+        a_idx = i;
+      }
+    }
+    if (max_idx(asf_ctrl->n_video, v_rates, bw - a_rate) < 0) {
+      // both audio and video are not possible, try video only next
+      a_idx = -1;
+      a_rate = 0;
+    }
+  }
+  // find best video stream
+  v_idx = max_idx(asf_ctrl->n_video, v_rates, bw - a_rate);
+  if (v_idx >= 0)
+    v_rate = v_rates[v_idx];
+
+  // find best audio stream
+  a_idx = max_idx(asf_ctrl->n_audio, a_rates, bw - v_rate);
+    
+  free(v_rates);
+  free(a_rates);
+
+  if (a_idx < 0 && v_idx < 0) {
+    mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_Bandwidth2SmallCannotPlay);
+    return -1;
+  }
+
+  if (audio_id > 0)
+    // a audio stream was forced
+    asf_ctrl->audio_id = audio_id;
+  else if (a_idx >= 0)
+    asf_ctrl->audio_id = asf_ctrl->audio_streams[a_idx];
+  else if (asf_ctrl->n_audio) {
+    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedAudio);
+    audio_id = -2;
+  }
+
+  if (video_id > 0)
+    // a video stream was forced
+    asf_ctrl->video_id = video_id;
+  else if (v_idx >= 0)
+    asf_ctrl->video_id = asf_ctrl->video_streams[v_idx];
+  else if (asf_ctrl->n_video) {
+    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedVideo);
+    video_id = -2;
+  }
+
+  return 1;
+
+len_err_out:
+  mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_InvalidLenInHeader);
+  if (buffer) free(buffer);
+  if (v_rates) free(v_rates);
+  if (a_rates) free(a_rates);
+  return -1;
+}
+
+static int asf_http_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) {
+  static ASF_stream_chunck_t chunk;
+  int read,chunk_size = 0;
+  static int rest = 0, drop_chunk = 0, waiting = 0;
+  asf_http_streaming_ctrl_t *asf_http_ctrl = (asf_http_streaming_ctrl_t*)streaming_ctrl->data;
+
+  while(1) {
+    if (rest == 0 && waiting == 0) {
+      read = 0;
+      while(read < (int)sizeof(ASF_stream_chunck_t)){
+	int r = nop_streaming_read( fd, ((char*)&chunk) + read, 
+				    sizeof(ASF_stream_chunck_t)-read, 
+				    streaming_ctrl );
+	if(r <= 0){
+	  if( r < 0) 
+	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingChunkHeader);
+	  return -1;
+	}
+	read += r;
+      }
+      
+      // Endian handling of the stream chunk
+      le2me_ASF_stream_chunck_t(&chunk);
+      chunk_size = asf_streaming( &chunk, &drop_chunk );
+      if(chunk_size < 0) {
+	mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader);
+	return -1;
+      }
+      chunk_size -= sizeof(ASF_stream_chunck_t);
+	
+      if(chunk.type != ASF_STREAMING_HEADER && (!drop_chunk)) {
+	if (asf_http_ctrl->packet_size < chunk_size) {
+	  mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunkBiggerThanPacket);
+	  return -1;
+	}
+	waiting = asf_http_ctrl->packet_size;
+      } else {
+	waiting = chunk_size;
+      }
+
+    } else if (rest){
+      chunk_size = rest;
+      rest = 0;
+    }
+
+    read = 0;
+    if ( waiting >= chunk_size) {
+      if (chunk_size > size){
+	rest = chunk_size - size;
+	chunk_size = size;
+      }
+      while(read < chunk_size) {
+	int got = nop_streaming_read( fd,buffer+read,chunk_size-read,streaming_ctrl );
+	if(got <= 0) {
+	  if(got < 0)
+	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrReadingChunk);
+	  return -1;
+	}
+	read += got;
+      }
+      waiting -= read;
+      if (drop_chunk) continue;
+    }
+    if (rest == 0 && waiting > 0 && size-read > 0) {
+      int s = MIN(waiting,size-read);
+      memset(buffer+read,0,s);
+      waiting -= s;
+      read += s;
+    }
+    break;
+  }
+
+  return read;
+}
+
+static int asf_http_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) {
+	return -1;
+	// to shut up gcc warning
+	fd++;
+	pos++;
+	streaming_ctrl=NULL;
+}
+
+static int asf_header_check( HTTP_header_t *http_hdr ) {
+	ASF_obj_header_t *objh;
+	if( http_hdr==NULL ) return -1;
+	if( http_hdr->body==NULL || http_hdr->body_size<sizeof(ASF_obj_header_t) ) return -1;
+
+	objh = (ASF_obj_header_t*)http_hdr->body;
+	if( ASF_LOAD_GUID_PREFIX(objh->guid)==0x75B22630 ) return 0;
+	return -1;
+}
+
+static int asf_http_streaming_type(char *content_type, char *features, HTTP_header_t *http_hdr ) {
+	if( content_type==NULL ) return ASF_Unknown_e;
+	if( 	!strcasecmp(content_type, "application/octet-stream") ||
+		!strcasecmp(content_type, "application/vnd.ms.wms-hdr.asfv1") ||        // New in Corona, first request
+		!strcasecmp(content_type, "application/x-mms-framed") ||                // New in Corana, second request
+		!strcasecmp(content_type, "video/x-ms-asf")) {               
+
+		if( strstr(features, "broadcast") ) {
+			mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Live stream\n");
+			return ASF_Live_e;
+		} else {
+			mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Prerecorded\n");
+			return ASF_Prerecorded_e;
+		}
+	} else {
+		// Ok in a perfect world, web servers should be well configured
+		// so we could used mime type to know the stream type,
+		// but guess what? All of them are not well configured.
+		// So we have to check for an asf header :(, but it works :p
+		if( http_hdr->body_size>sizeof(ASF_obj_header_t) ) {
+			if( asf_header_check( http_hdr )==0 ) {
+				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Plain text\n");
+				return ASF_PlainText_e;
+			} else if( (!strcasecmp(content_type, "text/html")) ) {
+				mp_msg(MSGT_NETWORK,MSGL_V,"=====> HTML, MPlayer is not a browser...yet!\n");
+				return ASF_Unknown_e;
+			} else {
+				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Redirector\n");
+				return ASF_Redirector_e;
+			}
+		} else {
+			if(	(!strcasecmp(content_type, "audio/x-ms-wax")) ||
+				(!strcasecmp(content_type, "audio/x-ms-wma")) ||
+				(!strcasecmp(content_type, "video/x-ms-asf")) ||
+				(!strcasecmp(content_type, "video/x-ms-afs")) ||
+				(!strcasecmp(content_type, "video/x-ms-wvx")) ||
+				(!strcasecmp(content_type, "video/x-ms-wmv")) ||
+				(!strcasecmp(content_type, "video/x-ms-wma")) ) {
+				mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ASFRedirector);
+				return ASF_Redirector_e;
+			} else if( !strcasecmp(content_type, "text/plain") ) {
+				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF Plain text\n");
+				return ASF_PlainText_e;
+			} else {
+				mp_msg(MSGT_NETWORK,MSGL_V,"=====> ASF unknown content-type: %s\n", content_type );
+				return ASF_Unknown_e;
+			}
+		}
+	}
+	return ASF_Unknown_e;
+}
+
+static HTTP_header_t *asf_http_request(streaming_ctrl_t *streaming_ctrl) {
+	HTTP_header_t *http_hdr;
+	URL_t *url = NULL;
+	URL_t *server_url = NULL;
+	asf_http_streaming_ctrl_t *asf_http_ctrl;
+	char str[250];
+	char *ptr;
+	int i, enable;
+
+	int offset_hi=0, offset_lo=0, length=0;
+	int asf_nb_stream=0, stream_id;
+
+	// Sanity check
+	if( streaming_ctrl==NULL ) return NULL;
+	url = streaming_ctrl->url;
+	asf_http_ctrl = (asf_http_streaming_ctrl_t*)streaming_ctrl->data;
+	if( url==NULL || asf_http_ctrl==NULL ) return NULL;
+
+	// Common header for all requests.
+	http_hdr = http_new_header();
+	http_set_field( http_hdr, "Accept: */*" );
+	http_set_field( http_hdr, "User-Agent: NSPlayer/4.1.0.3856" );
+	http_add_basic_authentication( http_hdr, url->username, url->password );
+
+	// Check if we are using a proxy
+	if( !strcasecmp( url->protocol, "http_proxy" ) ) {
+		server_url = url_new( (url->file)+1 );
+		if( server_url==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_InvalidProxyURL);
+			http_free( http_hdr );
+			return NULL;
+		}
+		http_set_uri( http_hdr, server_url->url );
+		sprintf( str, "Host: %.220s:%d", server_url->hostname, server_url->port );
+		url_free( server_url );
+	} else {
+		http_set_uri( http_hdr, url->file );
+		sprintf( str, "Host: %.220s:%d", url->hostname, url->port );
+	}
+	
+	http_set_field( http_hdr, str );
+	http_set_field( http_hdr, "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}" );
+	sprintf(str, 
+		"Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=%u",
+		offset_hi, offset_lo, asf_http_ctrl->request, length );
+	http_set_field( http_hdr, str );
+
+	switch( asf_http_ctrl->streaming_type ) {
+		case ASF_Live_e:
+		case ASF_Prerecorded_e:
+			http_set_field( http_hdr, "Pragma: xPlayStrm=1" );
+			ptr = str;
+			ptr += sprintf( ptr, "Pragma: stream-switch-entry=");
+			if(asf_http_ctrl->n_audio > 0) {
+				for( i=0; i<asf_http_ctrl->n_audio ; i++ ) {
+					stream_id = asf_http_ctrl->audio_streams[i];
+					if(stream_id == asf_http_ctrl->audio_id) {
+						enable = 0;
+					} else {
+						enable = 2;
+						continue;
+					}
+					asf_nb_stream++;
+					ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable);
+				}
+			}
+			if(asf_http_ctrl->n_video > 0) {
+				for( i=0; i<asf_http_ctrl->n_video ; i++ ) {
+					stream_id = asf_http_ctrl->video_streams[i];
+					if(stream_id == asf_http_ctrl->video_id) {
+						enable = 0;
+					} else {
+						enable = 2;
+						continue;
+					}
+					asf_nb_stream++;
+					ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable);
+				}
+			}
+			http_set_field( http_hdr, str );
+			sprintf( str, "Pragma: stream-switch-count=%d", asf_nb_stream );
+			http_set_field( http_hdr, str );
+			break;
+		case ASF_Redirector_e:
+			break;
+		case ASF_Unknown_e:
+			// First request goes here.
+			break;
+		default:
+			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_UnknownASFStreamType);
+	}
+
+	http_set_field( http_hdr, "Connection: Close" );
+	http_build_request( http_hdr );
+
+	return http_hdr;
+}
+
+static int asf_http_parse_response(asf_http_streaming_ctrl_t *asf_http_ctrl, HTTP_header_t *http_hdr ) {
+	char *content_type, *pragma;
+	char features[64] = "\0";
+	size_t len;
+	if( http_response_parse(http_hdr)<0 ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_Failed2ParseHTTPResponse);
+		return -1;
+	}
+	switch( http_hdr->status_code ) {
+		case 200:
+			break;
+		case 401: // Authentication required
+			return ASF_Authenticate_e;
+		default:
+			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ServerReturn, http_hdr->status_code, http_hdr->reason_phrase);
+			return -1;
+	}
+
+	content_type = http_get_field( http_hdr, "Content-Type");
+//printf("Content-Type: [%s]\n", content_type);
+
+	pragma = http_get_field( http_hdr, "Pragma");
+	while( pragma!=NULL ) {
+		char *comma_ptr=NULL;
+		char *end;
+//printf("Pragma: [%s]\n", pragma );
+		// The pragma line can get severals attributes 
+		// separeted with a comma ','.
+		do {
+			if( !strncasecmp( pragma, "features=", 9) ) {
+				pragma += 9;
+				end = strstr( pragma, "," );
+				if( end==NULL ) {
+				  len = strlen(pragma);
+				} else { 
+				  len = (unsigned int)(end-pragma);
+				}
+				if(len > sizeof(features) - 1) {
+				  mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_ASF_ASFHTTPParseWarnCuttedPragma,pragma,len,sizeof(features) - 1);
+				  len = sizeof(features) - 1;
+				}
+				strncpy( features, pragma, len );
+				features[len]='\0';
+				break;
+			}
+			comma_ptr = strstr( pragma, "," );
+			if( comma_ptr!=NULL ) {
+				pragma = comma_ptr+1;
+				if( pragma[0]==' ' ) pragma++;
+			}
+		} while( comma_ptr!=NULL );
+		pragma = http_get_next_field( http_hdr );
+	}
+	asf_http_ctrl->streaming_type = asf_http_streaming_type( content_type, features, http_hdr );
+	return 0;
+}
+
+static int asf_http_streaming_start( stream_t *stream, int *demuxer_type ) {
+	HTTP_header_t *http_hdr=NULL;
+	URL_t *url = stream->streaming_ctrl->url;
+	asf_http_streaming_ctrl_t *asf_http_ctrl;
+	char buffer[BUFFER_SIZE];
+	int i, ret;
+	int fd = stream->fd;
+	int done;
+	int auth_retry = 0;
+
+	asf_http_ctrl = malloc(sizeof(asf_http_streaming_ctrl_t));
+	if( asf_http_ctrl==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+		return -1;
+	}
+	asf_http_ctrl->streaming_type = ASF_Unknown_e;
+	asf_http_ctrl->request = 1;
+	asf_http_ctrl->audio_streams = asf_http_ctrl->video_streams = NULL;
+	asf_http_ctrl->n_audio = asf_http_ctrl->n_video = 0;
+	stream->streaming_ctrl->data = (void*)asf_http_ctrl;
+
+	do {
+		done = 1;
+		if( fd>0 ) closesocket( fd );
+
+		if( !strcasecmp( url->protocol, "http_proxy" ) ) {
+			if( url->port==0 ) url->port = 8080;
+		} else {
+			if( url->port==0 ) url->port = 80;
+		}
+		fd = connect2Server( url->hostname, url->port, 1);
+		if( fd<0 ) return fd;
+
+		http_hdr = asf_http_request( stream->streaming_ctrl );
+		mp_msg(MSGT_NETWORK,MSGL_DBG2,"Request [%s]\n", http_hdr->buffer );
+		for(i=0; i < (int)http_hdr->buffer_size ; ) {
+			int r = send( fd, http_hdr->buffer+i, http_hdr->buffer_size-i, 0 );
+			if(r <0) {
+				mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_SocketWriteError,strerror(errno));
+				return -1;
+			}
+			i += r;
+		}       
+		http_free( http_hdr );
+		http_hdr = http_new_header();
+		do {
+			i = recv( fd, buffer, BUFFER_SIZE, 0 );
+//printf("read: %d\n", i );
+			if( i<=0 ) {
+				perror("read");
+				http_free( http_hdr );
+				return -1;
+			}
+			http_response_append( http_hdr, buffer, i );
+		} while( !http_is_header_entire( http_hdr ) );
+		if( mp_msg_test(MSGT_NETWORK,MSGL_V) ) {
+			http_hdr->buffer[http_hdr->buffer_size]='\0';
+			mp_msg(MSGT_NETWORK,MSGL_DBG2,"Response [%s]\n", http_hdr->buffer );
+		}
+		ret = asf_http_parse_response(asf_http_ctrl, http_hdr);
+		if( ret<0 ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_HeaderParseFailed);
+			http_free( http_hdr );
+			return -1;
+		}
+		switch( asf_http_ctrl->streaming_type ) {
+			case ASF_Live_e:
+			case ASF_Prerecorded_e:
+			case ASF_PlainText_e:
+				if( http_hdr->body_size>0 ) {
+					if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
+						http_free( http_hdr );
+						return -1;
+					}
+				}
+				if( asf_http_ctrl->request==1 ) {
+					if( asf_http_ctrl->streaming_type!=ASF_PlainText_e ) {
+						// First request, we only got the ASF header.
+						ret = asf_streaming_parse_header(fd,stream->streaming_ctrl);
+						if(ret < 0) return -1;
+						if(asf_http_ctrl->n_audio == 0 && asf_http_ctrl->n_video == 0) {
+							mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_NoStreamFound);
+							return -1;
+						}
+						asf_http_ctrl->request++;
+						done = 0;
+					} else {
+						done = 1;
+					}
+				}
+				break;
+			case ASF_Redirector_e:
+				if( http_hdr->body_size>0 ) {
+					if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
+						http_free( http_hdr );
+						return -1;
+					}
+				}
+				*demuxer_type = DEMUXER_TYPE_PLAYLIST;
+				done = 1;
+				break;
+			case ASF_Authenticate_e:
+				if( http_authenticate( http_hdr, url, &auth_retry)<0 ) return -1;
+				asf_http_ctrl->streaming_type = ASF_Unknown_e;
+				done = 0;
+				break;
+			case ASF_Unknown_e:
+			default:
+				mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_UnknownASFStreamingType);
+				closesocket(fd);
+				http_free( http_hdr );
+				return -1;
+		}
+	// Check if we got a redirect.	
+	} while(!done);
+
+	stream->fd = fd;
+	if( asf_http_ctrl->streaming_type==ASF_PlainText_e || asf_http_ctrl->streaming_type==ASF_Redirector_e ) {
+		stream->streaming_ctrl->streaming_read = nop_streaming_read;
+		stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
+	} else {
+		stream->streaming_ctrl->streaming_read = asf_http_streaming_read;
+		stream->streaming_ctrl->streaming_seek = asf_http_streaming_seek;
+		stream->streaming_ctrl->buffering = 1;
+	}
+	stream->streaming_ctrl->status = streaming_playing_e;
+	stream->close = close_s;
+
+	http_free( http_hdr );
+	return 0;
+}
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+	URL_t *url;
+
+	stream->streaming_ctrl = streaming_ctrl_new();
+	if( stream->streaming_ctrl==NULL ) {
+		return STREAM_ERROR;
+	}
+	stream->streaming_ctrl->bandwidth = network_bandwidth;
+	url = url_new(stream->url);
+	stream->streaming_ctrl->url = check4proxies(url);
+	url_free(url);
+	
+	mp_msg(MSGT_OPEN, MSGL_INFO, MSGTR_MPDEMUX_ASF_InfoStreamASFURL, stream->url);
+	if((!strncmp(stream->url, "http", 4)) && (*file_format!=DEMUXER_TYPE_ASF && *file_format!=DEMUXER_TYPE_UNKNOWN)) {
+		streaming_ctrl_free(stream->streaming_ctrl);
+		stream->streaming_ctrl = NULL;
+		return STREAM_UNSUPORTED;
+	}
+
+	if(asf_streaming_start(stream, file_format) < 0) {
+		mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_ASF_StreamingFailed);
+		streaming_ctrl_free(stream->streaming_ctrl);
+		stream->streaming_ctrl = NULL;
+		return STREAM_UNSUPORTED;
+	}
+	
+	*file_format = DEMUXER_TYPE_ASF;
+	stream->type = STREAMTYPE_STREAM;
+	fixup_network_stream_cache(stream);
+	return STREAM_OK;
+}
+
+stream_info_t stream_info_asf = {
+  "mms and mms over http streaming",
+  "null",
+  "Bertrand, Reimar Doeffinger, Albeu",
+  "originally based on work by Majormms (is that code still there?)",
+  open_s,
+  {"mms", "mmsu", "mmst", "http", "http_proxy", "mmshttp", NULL},
+  NULL,
+  0 // Urls are an option string
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/audio_in.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,219 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#include "audio_in.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+#include <string.h>
+#include <errno.h>
+
+// sanitizes ai structure before calling other functions
+int audio_in_init(audio_in_t *ai, int type)
+{
+    ai->type = type;
+    ai->setup = 0;
+
+    ai->channels = -1;
+    ai->samplerate = -1;
+    ai->blocksize = -1;
+    ai->bytes_per_sample = -1;
+    ai->samplesize = -1;
+
+    switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    case AUDIO_IN_ALSA:
+	ai->alsa.handle = NULL;
+	ai->alsa.log = NULL;
+	ai->alsa.device = strdup("default");
+	return 0;
+#endif
+#ifdef USE_OSS_AUDIO
+    case AUDIO_IN_OSS:
+	ai->oss.audio_fd = -1;
+	ai->oss.device = strdup("/dev/dsp");
+	return 0;
+#endif
+    default:
+	return -1;
+    }
+}
+
+int audio_in_setup(audio_in_t *ai)
+{
+    
+    switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    case AUDIO_IN_ALSA:
+	if (ai_alsa_init(ai) < 0) return -1;
+	ai->setup = 1;
+	return 0;
+#endif
+#ifdef USE_OSS_AUDIO
+    case AUDIO_IN_OSS:
+	if (ai_oss_init(ai) < 0) return -1;
+	ai->setup = 1;
+	return 0;
+#endif
+    default:
+	return -1;
+    }
+}
+
+int audio_in_set_samplerate(audio_in_t *ai, int rate)
+{
+    switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    case AUDIO_IN_ALSA:
+	ai->req_samplerate = rate;
+	if (!ai->setup) return 0;
+	if (ai_alsa_setup(ai) < 0) return -1;
+	return ai->samplerate;
+#endif
+#ifdef USE_OSS_AUDIO
+    case AUDIO_IN_OSS:
+	ai->req_samplerate = rate;
+	if (!ai->setup) return 0;
+	if (ai_oss_set_samplerate(ai) < 0) return -1;
+	return ai->samplerate;
+#endif
+    default:
+	return -1;
+    }
+}
+
+int audio_in_set_channels(audio_in_t *ai, int channels)
+{
+    switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    case AUDIO_IN_ALSA:
+	ai->req_channels = channels;
+	if (!ai->setup) return 0;
+	if (ai_alsa_setup(ai) < 0) return -1;
+	return ai->channels;
+#endif
+#ifdef USE_OSS_AUDIO
+    case AUDIO_IN_OSS:
+	ai->req_channels = channels;
+	if (!ai->setup) return 0;
+	if (ai_oss_set_channels(ai) < 0) return -1;
+	return ai->channels;
+#endif
+    default:
+	return -1;
+    }
+}
+
+int audio_in_set_device(audio_in_t *ai, char *device)
+{
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    int i;
+#endif
+    if (ai->setup) return -1;
+    switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    case AUDIO_IN_ALSA:
+	if (ai->alsa.device) free(ai->alsa.device);
+	ai->alsa.device = strdup(device);
+	/* mplayer cannot handle colons in arguments */
+	for (i = 0; i < (int)strlen(ai->alsa.device); i++) {
+	    if (ai->alsa.device[i] == '.') ai->alsa.device[i] = ':';
+	}
+	return 0;
+#endif
+#ifdef USE_OSS_AUDIO
+    case AUDIO_IN_OSS:
+	if (ai->oss.device) free(ai->oss.device);
+	ai->oss.device = strdup(device);
+	return 0;
+#endif
+    default:
+	return -1;
+    }
+}
+
+int audio_in_uninit(audio_in_t *ai)
+{
+    if (ai->setup) {
+	switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+	case AUDIO_IN_ALSA:
+	    if (ai->alsa.log)
+		snd_output_close(ai->alsa.log);
+	    if (ai->alsa.handle) {
+		snd_pcm_close(ai->alsa.handle);
+	    }
+	    ai->setup = 0;
+	    return 0;
+#endif
+#ifdef USE_OSS_AUDIO
+	case AUDIO_IN_OSS:
+	    close(ai->oss.audio_fd);
+	    ai->setup = 0;
+	    return 0;
+#endif
+	}
+    }
+    return -1;
+}
+
+int audio_in_start_capture(audio_in_t *ai)
+{
+    switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    case AUDIO_IN_ALSA:
+	return snd_pcm_start(ai->alsa.handle);
+#endif
+#ifdef USE_OSS_AUDIO
+    case AUDIO_IN_OSS:
+	return 0;
+#endif
+    default:
+	return -1;
+    }
+}
+
+int audio_in_read_chunk(audio_in_t *ai, unsigned char *buffer)
+{
+    int ret;
+    
+    switch (ai->type) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    case AUDIO_IN_ALSA:
+	ret = snd_pcm_readi(ai->alsa.handle, buffer, ai->alsa.chunk_size);
+	if (ret != ai->alsa.chunk_size) {
+	    if (ret < 0) {
+		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio, snd_strerror(ret));
+		if (ret == -EPIPE) {
+		    if (ai_alsa_xrun(ai) == 0) {
+			mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_XRUNSomeFramesMayBeLeftOut);
+		    } else {
+			mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrFatalCannotRecover);
+		    }
+		}
+	    } else {
+		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples);
+	    }
+	    return -1;
+	}
+	return ret;
+#endif
+#ifdef USE_OSS_AUDIO
+    case AUDIO_IN_OSS:
+	ret = read(ai->oss.audio_fd, buffer, ai->blocksize);
+	if (ret != ai->blocksize) {
+	    if (ret < 0) {
+		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio, strerror(errno));
+	    } else {
+		mp_msg(MSGT_TV, MSGL_ERR, MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples);
+	    }
+	    return -1;
+	}
+	return ret;
+#endif
+    default:
+	return -1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/audio_in.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,75 @@
+#ifndef _audio_in_h 
+#define _audio_in_h 
+
+#define AUDIO_IN_ALSA 1
+#define AUDIO_IN_OSS 2
+
+#include "config.h"
+
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+#include <alsa/asoundlib.h>
+
+typedef struct {
+    char *device;
+
+    snd_pcm_t *handle;
+    snd_output_t *log;
+    int buffer_time, period_time, chunk_size;
+    size_t bits_per_sample, bits_per_frame;
+} ai_alsa_t;
+#endif
+
+#ifdef USE_OSS_AUDIO
+typedef struct {
+    char *device;
+
+    int audio_fd;
+} ai_oss_t;
+#endif
+
+typedef struct 
+{
+    int type;
+    int setup;
+    
+    /* requested values */
+    int req_channels;
+    int req_samplerate;
+
+    /* real values read-only */
+    int channels;
+    int samplerate;
+    int blocksize;
+    int bytes_per_sample;
+    int samplesize;
+    
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+    ai_alsa_t alsa;
+#endif
+#ifdef USE_OSS_AUDIO
+    ai_oss_t oss;
+#endif
+} audio_in_t;
+
+int audio_in_init(audio_in_t *ai, int type);
+int audio_in_setup(audio_in_t *ai);
+int audio_in_set_device(audio_in_t *ai, char *device);
+int audio_in_set_samplerate(audio_in_t *ai, int rate);
+int audio_in_set_channels(audio_in_t *ai, int channels);
+int audio_in_uninit(audio_in_t *ai);
+int audio_in_start_capture(audio_in_t *ai);
+int audio_in_read_chunk(audio_in_t *ai, unsigned char *buffer);
+
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+int ai_alsa_setup(audio_in_t *ai);
+int ai_alsa_init(audio_in_t *ai);
+int ai_alsa_xrun(audio_in_t *ai);
+#endif
+
+#ifdef USE_OSS_AUDIO
+int ai_oss_set_samplerate(audio_in_t *ai);
+int ai_oss_set_channels(audio_in_t *ai);
+int ai_oss_init(audio_in_t *ai);
+#endif
+
+#endif /* _audio_in_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cache2.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,367 @@
+#include "config.h"
+
+// Initial draft of my new cache system...
+// Note it runs in 2 processes (using fork()), but doesn't requires locking!!
+// TODO: seeking, data consistency checking
+
+#define READ_USLEEP_TIME 10000
+#define FILL_USLEEP_TIME 50000
+#define PREFILL_SLEEP_TIME 200
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "osdep/timer.h"
+#ifndef WIN32
+#include <sys/wait.h>
+#include "osdep/shmem.h"
+#else
+#include <windows.h>
+static DWORD WINAPI ThreadProc(void* s);
+#endif
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "stream.h"
+
+int stream_fill_buffer(stream_t *s);
+int stream_seek_long(stream_t *s,off_t pos);
+
+extern int mp_input_check_interrupt(int time);
+
+typedef struct {
+  // constats:
+  unsigned char *buffer;      // base pointer of the alllocated buffer memory
+  int buffer_size; // size of the alllocated buffer memory
+  int sector_size; // size of a single sector (2048/2324)
+  int back_size;   // we should keep back_size amount of old bytes for backward seek
+  int fill_limit;  // we should fill buffer only if space>=fill_limit
+  int seek_limit;  // keep filling cache if distanse is less that seek limit
+  // filler's pointers:
+  int eof;
+  off_t min_filepos; // buffer contain only a part of the file, from min-max pos
+  off_t max_filepos;
+  off_t offset;      // filepos <-> bufferpos  offset value (filepos of the buffer's first byte)
+  // reader's pointers:
+  off_t read_filepos;
+  // commands/locking:
+//  int seek_lock;   // 1 if we will seek/reset buffer, 2 if we are ready for cmd
+//  int fifo_flag;  // 1 if we should use FIFO to notice cache about buffer reads.
+  // callback
+  stream_t* stream;
+} cache_vars_t;
+
+static int min_fill=0;
+
+int cache_fill_status=0;
+
+void cache_stats(cache_vars_t* s){
+  int newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
+  mp_msg(MSGT_CACHE,MSGL_INFO,"0x%06X  [0x%06X]  0x%06X   ",(int)s->min_filepos,(int)s->read_filepos,(int)s->max_filepos);
+  mp_msg(MSGT_CACHE,MSGL_INFO,"%3d %%  (%3d%%)\n",100*newb/s->buffer_size,100*min_fill/s->buffer_size);
+}
+
+int cache_read(cache_vars_t* s,unsigned char* buf,int size){
+  int total=0;
+  while(size>0){
+    int pos,newb,len;
+
+  //printf("CACHE2_READ: 0x%X <= 0x%X <= 0x%X  \n",s->min_filepos,s->read_filepos,s->max_filepos);
+    
+    if(s->read_filepos>=s->max_filepos || s->read_filepos<s->min_filepos){
+	// eof?
+	if(s->eof) break;
+	// waiting for buffer fill...
+	usec_sleep(READ_USLEEP_TIME); // 10ms
+	continue; // try again...
+    }
+
+    newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
+    if(newb<min_fill) min_fill=newb; // statistics...
+
+//    printf("*** newb: %d bytes ***\n",newb);
+
+    pos=s->read_filepos - s->offset;
+    if(pos<0) pos+=s->buffer_size; else
+    if(pos>=s->buffer_size) pos-=s->buffer_size;
+
+    if(newb>s->buffer_size-pos) newb=s->buffer_size-pos; // handle wrap...
+    if(newb>size) newb=size;
+    
+    // check:
+    if(s->read_filepos<s->min_filepos) mp_msg(MSGT_CACHE,MSGL_ERR,"Ehh. s->read_filepos<s->min_filepos !!! Report bug...\n");
+    
+    // len=write(mem,newb)
+    //printf("Buffer read: %d bytes\n",newb);
+    memcpy(buf,&s->buffer[pos],newb);
+    buf+=newb;
+    len=newb;
+    // ...
+    
+    s->read_filepos+=len;
+    size-=len;
+    total+=len;
+    
+  }
+  cache_fill_status=(s->max_filepos-s->read_filepos)/(s->buffer_size / 100);
+  return total;
+}
+
+int cache_fill(cache_vars_t* s){
+  int back,back2,newb,space,len,pos;
+  off_t read=s->read_filepos;
+  
+  if(read<s->min_filepos || read>s->max_filepos){
+      // seek...
+      mp_msg(MSGT_CACHE,MSGL_DBG2,"Out of boundaries... seeking to 0x%"PRIX64"  \n",(int64_t)read);
+      // streaming: drop cache contents only if seeking backward or too much fwd:
+      if(s->stream->type!=STREAMTYPE_STREAM ||
+          read<s->min_filepos || read>=s->max_filepos+s->seek_limit)
+      {
+        s->offset= // FIXME!?
+        s->min_filepos=s->max_filepos=read; // drop cache content :(
+        if(s->stream->eof) stream_reset(s->stream);
+        stream_seek(s->stream,read);
+        mp_msg(MSGT_CACHE,MSGL_DBG2,"Seek done. new pos: 0x%"PRIX64"  \n",(int64_t)stream_tell(s->stream));
+      }
+  }
+  
+  // calc number of back-bytes:
+  back=read - s->min_filepos;
+  if(back<0) back=0; // strange...
+  if(back>s->back_size) back=s->back_size;
+  
+  // calc number of new bytes:
+  newb=s->max_filepos - read;
+  if(newb<0) newb=0; // strange...
+
+  // calc free buffer space:
+  space=s->buffer_size - (newb+back);
+  
+  // calc bufferpos:
+  pos=s->max_filepos - s->offset;
+  if(pos>=s->buffer_size) pos-=s->buffer_size; // wrap-around
+  
+  if(space<s->fill_limit){
+//    printf("Buffer is full (%d bytes free, limit: %d)\n",space,s->fill_limit);
+    return 0; // no fill...
+  }
+
+//  printf("### read=0x%X  back=%d  newb=%d  space=%d  pos=%d\n",read,back,newb,space,pos);
+     
+  // reduce space if needed:
+  if(space>s->buffer_size-pos) space=s->buffer_size-pos;
+  
+//  if(space>32768) space=32768; // limit one-time block size
+  if(space>4*s->sector_size) space=4*s->sector_size;
+  
+//  if(s->seek_lock) return 0; // FIXME
+
+#if 1
+  // back+newb+space <= buffer_size
+  back2=s->buffer_size-(space+newb); // max back size
+  if(s->min_filepos<(read-back2)) s->min_filepos=read-back2;
+#else
+  s->min_filepos=read-back; // avoid seeking-back to temp area...
+#endif
+  
+  // ....
+  //printf("Buffer fill: %d bytes of %d\n",space,s->buffer_size);
+  //len=stream_fill_buffer(s->stream);
+  //memcpy(&s->buffer[pos],s->stream->buffer,len); // avoid this extra copy!
+  // ....
+  len=stream_read(s->stream,&s->buffer[pos],space);
+  if(!len) s->eof=1;
+  
+  s->max_filepos+=len;
+  if(pos+len>=s->buffer_size){
+      // wrap...
+      s->offset+=s->buffer_size;
+  }
+  
+  return len;
+  
+}
+
+cache_vars_t* cache_init(int size,int sector){
+  int num;
+#ifndef WIN32
+  cache_vars_t* s=shmem_alloc(sizeof(cache_vars_t));
+#else
+  cache_vars_t* s=malloc(sizeof(cache_vars_t));
+#endif
+  if(s==NULL) return NULL;
+  
+  memset(s,0,sizeof(cache_vars_t));
+  num=size/sector;
+  if(num < 16){
+     num = 16;
+  }//32kb min_size
+  s->buffer_size=num*sector;
+  s->sector_size=sector;
+#ifndef WIN32
+  s->buffer=shmem_alloc(s->buffer_size);
+#else
+  s->buffer=malloc(s->buffer_size);
+#endif
+
+  if(s->buffer == NULL){
+#ifndef WIN32
+    shmem_free(s,sizeof(cache_vars_t));
+#else
+    free(s);
+#endif
+    return NULL;
+  }
+
+  s->fill_limit=8*sector;
+  s->back_size=s->buffer_size/2;
+  return s;
+}
+
+void cache_uninit(stream_t *s) {
+  cache_vars_t* c = s->cache_data;
+  if(!s->cache_pid) return;
+#ifndef WIN32
+  kill(s->cache_pid,SIGKILL);
+  waitpid(s->cache_pid,NULL,0);
+#else
+  TerminateThread((HANDLE)s->cache_pid,0);
+  free(c->stream);
+#endif
+  if(!c) return;
+#ifndef WIN32
+  shmem_free(c->buffer,c->buffer_size);
+  shmem_free(s->cache_data,sizeof(cache_vars_t));
+#else
+  free(c->buffer);
+  free(s->cache_data);
+#endif
+}
+
+static void exit_sighandler(int x){
+  // close stream
+  exit(0);
+}
+
+int stream_enable_cache(stream_t *stream,int size,int min,int seek_limit){
+  int ss=(stream->type==STREAMTYPE_VCD)?VCD_SECTOR_DATA:STREAM_BUFFER_SIZE;
+  cache_vars_t* s;
+
+  if (stream->type==STREAMTYPE_STREAM && stream->fd < 0) {
+    // The stream has no 'fd' behind it, so is non-cacheable
+    mp_msg(MSGT_CACHE,MSGL_STATUS,"\rThis stream is non-cacheable\n");
+    return 1;
+  }
+
+  s=cache_init(size,ss);
+  if(s == NULL) return 0;
+  stream->cache_data=s;
+  s->stream=stream; // callback
+  s->seek_limit=seek_limit;
+
+
+  //make sure that we won't wait from cache_fill
+  //more data than it is alowed to fill
+  if (s->seek_limit > s->buffer_size - s->fill_limit ){
+     s->seek_limit = s->buffer_size - s->fill_limit;
+  }
+  if (min > s->buffer_size - s->fill_limit) {
+     min = s->buffer_size - s->fill_limit;
+  }
+  
+#ifndef WIN32  
+  if((stream->cache_pid=fork())){
+#else
+  {
+    DWORD threadId;
+    stream_t* stream2=malloc(sizeof(stream_t));
+    memcpy(stream2,s->stream,sizeof(stream_t));
+    s->stream=stream2;
+    stream->cache_pid = CreateThread(NULL,0,ThreadProc,s,0,&threadId);
+#endif
+    // wait until cache is filled at least prefill_init %
+    mp_msg(MSGT_CACHE,MSGL_V,"CACHE_PRE_INIT: %"PRId64" [%"PRId64"] %"PRId64"  pre:%d  eof:%d  \n",
+	(int64_t)s->min_filepos,(int64_t)s->read_filepos,(int64_t)s->max_filepos,min,s->eof);
+    while(s->read_filepos<s->min_filepos || s->max_filepos-s->read_filepos<min){
+	mp_msg(MSGT_CACHE,MSGL_STATUS,MSGTR_CacheFill,
+	    100.0*(float)(s->max_filepos-s->read_filepos)/(float)(s->buffer_size),
+	    (int64_t)s->max_filepos-s->read_filepos
+	);
+	if(s->eof) break; // file is smaller than prefill size
+	if(mp_input_check_interrupt(PREFILL_SLEEP_TIME))
+	  return 0;
+    }
+    mp_msg(MSGT_CACHE,MSGL_STATUS,"\n");
+    return 1; // parent exits
+  }
+  
+#ifdef WIN32
+}
+static DWORD WINAPI ThreadProc(void*s){
+#endif
+  
+// cache thread mainloop:
+  signal(SIGTERM,exit_sighandler); // kill
+  while(1){
+    if(!cache_fill((cache_vars_t*)s)){
+	 usec_sleep(FILL_USLEEP_TIME); // idle
+    }
+//	 cache_stats(s->cache_data);
+  }
+}
+
+int cache_stream_fill_buffer(stream_t *s){
+  int len;
+  if(s->eof){ s->buf_pos=s->buf_len=0; return 0; }
+  if(!s->cache_pid) return stream_fill_buffer(s);
+
+//  cache_stats(s->cache_data);
+
+  if(s->pos!=((cache_vars_t*)s->cache_data)->read_filepos) mp_msg(MSGT_CACHE,MSGL_ERR,"!!! read_filepos differs!!! report this bug...\n");
+
+  len=cache_read(s->cache_data,s->buffer, ((cache_vars_t*)s->cache_data)->sector_size);
+  //printf("cache_stream_fill_buffer->read -> %d\n",len);
+
+  if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
+  s->buf_pos=0;
+  s->buf_len=len;
+  s->pos+=len;
+//  printf("[%d]",len);fflush(stdout);
+  return len;
+
+}
+
+int cache_stream_seek_long(stream_t *stream,off_t pos){
+  cache_vars_t* s;
+  off_t newpos;
+  if(!stream->cache_pid) return stream_seek_long(stream,pos);
+  
+  s=stream->cache_data;
+//  s->seek_lock=1;
+  
+  mp_msg(MSGT_CACHE,MSGL_DBG2,"CACHE2_SEEK: 0x%"PRIX64" <= 0x%"PRIX64" (0x%"PRIX64") <= 0x%"PRIX64"  \n",s->min_filepos,pos,s->read_filepos,s->max_filepos);
+
+  newpos=pos/s->sector_size; newpos*=s->sector_size; // align
+  stream->pos=s->read_filepos=newpos;
+  s->eof=0; // !!!!!!!
+
+  cache_stream_fill_buffer(stream);
+
+  pos-=newpos;
+  if(pos>=0 && pos<=stream->buf_len){
+    stream->buf_pos=pos; // byte position in sector
+    return 1;
+  }
+
+//  stream->buf_pos=stream->buf_len=0;
+//  return 1;
+
+  mp_msg(MSGT_CACHE,MSGL_V,"cache_stream_seek: WARNING! Can't seek to 0x%"PRIX64" !\n",(int64_t)(pos+newpos));
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cdd.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,77 @@
+#ifndef __CDD_H__
+#define __CDD_H__
+
+#include "config.h"
+#ifndef HAVE_LIBCDIO
+#include <cdda_interface.h>
+#include <cdda_paranoia.h>
+#else
+#include <cdio/cdda.h>
+#include <cdio/paranoia.h>
+#endif
+
+typedef struct {
+	char cddb_hello[1024];	
+	unsigned long disc_id;
+	unsigned int tracks;
+	char *cache_dir;
+	char *freedb_server;
+	int freedb_proto_level;
+	int anonymous;
+	char category[100];
+	char *xmcd_file;
+	size_t xmcd_file_size;
+	void *user_data;
+} cddb_data_t;
+
+typedef struct {
+	unsigned int min, sec, frame;
+} cd_toc_t;
+
+typedef struct cd_track {
+	char *name;
+	unsigned int track_nb;
+	unsigned int min;
+	unsigned int sec;
+	unsigned int msec;
+	unsigned long frame_begin;
+	unsigned long frame_length;
+	struct cd_track *prev;
+	struct cd_track *next;
+} cd_track_t;
+
+typedef struct {
+	char *artist;
+	char *album;
+	char *genre;
+	unsigned int nb_tracks;
+	unsigned int min;
+	unsigned int sec;
+	unsigned msec;
+	cd_track_t *first;
+	cd_track_t *last;
+	cd_track_t *current;
+} cd_info_t;
+
+typedef struct {
+#ifndef HAVE_LIBCDIO
+	cdrom_drive* cd;
+	cdrom_paranoia* cdp;
+#else
+	cdrom_drive_t* cd;
+	cdrom_paranoia_t* cdp;
+#endif
+	int sector;
+	int start_sector;
+	int end_sector;
+	cd_info_t *cd_info;
+} cdda_priv;
+
+cd_info_t* 	cd_info_new();
+void		cd_info_free(cd_info_t *cd_info);
+cd_track_t*	cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length);
+cd_track_t*	cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb);
+
+void 		cd_info_debug(cd_info_t *cd_info);
+
+#endif // __CDD_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cdda.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,391 @@
+#include "config.h"
+
+#include "stream.h"
+#include "m_option.h"
+#include "m_struct.h"
+#include "bswap.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "demuxer.h"
+
+#include "cdd.h"
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifndef CD_FRAMESIZE_RAW
+#define CD_FRAMESIZE_RAW CDIO_CD_FRAMESIZE_RAW
+#endif
+
+
+extern char *cdrom_device;
+
+static struct cdda_params {
+  int speed;
+  int paranoia_mode;
+  char* generic_dev;
+  int sector_size;
+  int search_overlap;
+  int toc_bias;
+  int toc_offset;
+  int no_skip;
+  char* device;
+  m_span_t span;
+} cdda_dflts = {
+  -1,
+  0,
+  NULL,
+  0,
+  -1,
+  0,
+  0,
+  0,
+  NULL,
+  { 0, 0 }
+};
+
+#define ST_OFF(f) M_ST_OFF(struct cdda_params,f)
+m_option_t cdda_params_fields[] = {
+  { "speed", ST_OFF(speed), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
+  { "paranoia", ST_OFF(paranoia_mode), CONF_TYPE_INT,M_OPT_RANGE, 0, 2, NULL },
+  { "generic-dev", ST_OFF(generic_dev), CONF_TYPE_STRING, 0, 0, 0, NULL },
+  { "sector-size", ST_OFF(sector_size), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
+  { "overlap", ST_OFF(search_overlap), CONF_TYPE_INT, M_OPT_RANGE,0,75, NULL },
+  { "toc-bias", ST_OFF(toc_bias), CONF_TYPE_INT, 0, 0, 0, NULL },
+  { "toc-offset", ST_OFF(toc_offset), CONF_TYPE_INT, 0, 0, 0, NULL },
+  { "noskip", ST_OFF(no_skip), CONF_TYPE_FLAG, 0 , 0, 1, NULL },
+  { "skip", ST_OFF(no_skip), CONF_TYPE_FLAG, 0 , 1, 0, NULL },
+  { "device", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
+  { "span",  ST_OFF(span), CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
+  /// For url parsing
+  { "hostname", ST_OFF(span), CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
+  { "port", ST_OFF(speed), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
+  { "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
+  {NULL, NULL, 0, 0, 0, 0, NULL}
+};
+static struct m_struct_st stream_opts = {
+  "cdda",
+  sizeof(struct cdda_params),
+  &cdda_dflts,
+  cdda_params_fields
+};
+
+/// We keep these options but now they set the defaults
+m_option_t cdda_opts[] = {
+  { "speed", &cdda_dflts.speed, CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
+  { "paranoia", &cdda_dflts.paranoia_mode, CONF_TYPE_INT,M_OPT_RANGE, 0, 2, NULL },
+  { "generic-dev", &cdda_dflts.generic_dev, CONF_TYPE_STRING, 0, 0, 0, NULL },
+  { "sector-size", &cdda_dflts.sector_size, CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
+  { "overlap", &cdda_dflts.search_overlap, CONF_TYPE_INT, M_OPT_RANGE,0,75, NULL },
+  { "toc-bias", &cdda_dflts.toc_bias, CONF_TYPE_INT, 0, 0, 0, NULL },
+  { "toc-offset", &cdda_dflts.toc_offset, CONF_TYPE_INT, 0, 0, 0, NULL },
+  { "noskip", &cdda_dflts.no_skip, CONF_TYPE_FLAG, 0 , 0, 1, NULL },
+  { "skip", &cdda_dflts.no_skip, CONF_TYPE_FLAG, 0 , 1, 0, NULL },
+  { "device", &cdda_dflts.device, CONF_TYPE_STRING, 0, 0, 0, NULL },
+  { "span", &cdda_dflts.span, CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
+  {NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+extern int cdd_identify(const char *dev);
+extern int cddb_resolve(const char *dev, char **xmcd_file);
+extern cd_info_t* cddb_parse_xmcd(char *xmcd_file);
+
+static int seek(stream_t* s,off_t pos);
+static int fill_buffer(stream_t* s, char* buffer, int max_len);
+static void close_cdda(stream_t* s);
+
+static int open_cdda(stream_t *st,int m, void* opts, int* file_format) {
+  struct cdda_params* p = (struct cdda_params*)opts;
+  int mode = p->paranoia_mode;
+  int offset = p->toc_offset;
+#ifndef HAVE_LIBCDIO
+  cdrom_drive* cdd = NULL;
+#else
+  cdrom_drive_t* cdd = NULL;
+#endif
+  cdda_priv* priv;
+  cd_info_t *cd_info,*cddb_info = NULL;
+  unsigned int audiolen=0;
+  int last_track;
+  int i;
+  char *xmcd_file = NULL;
+
+  if(m != STREAM_READ) {
+    m_struct_free(&stream_opts,opts);
+    return STREAM_UNSUPORTED;
+  }
+
+  if(!p->device) {
+    if (cdrom_device)
+      p->device = strdup(cdrom_device);
+    else
+      p->device = strdup(DEFAULT_CDROM_DEVICE);
+  }
+
+#ifdef MPLAYER_NETWORK
+  // cdd_identify returns -1 if it cannot read the TOC,
+  // in which case there is no point in calling cddb_resolve
+  if(cdd_identify(p->device) >= 0 && strncmp(st->url,"cddb",4) == 0) {
+    i = cddb_resolve(p->device, &xmcd_file);
+    if(i == 0) {
+      cddb_info = cddb_parse_xmcd(xmcd_file);
+      free(xmcd_file);
+    }
+  }
+#endif
+  
+#ifndef HAVE_LIBCDIO
+  if(p->generic_dev)
+    cdd = cdda_identify_scsi(p->generic_dev,p->device,0,NULL);
+  else
+#endif
+#if defined(__NetBSD__)
+    cdd = cdda_identify_scsi(p->device,p->device,0,NULL);
+#else
+    cdd = cdda_identify(p->device,0,NULL);
+#endif
+
+  if(!cdd) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_MPDEMUX_CDDA_CantOpenCDDADevice);
+    m_struct_free(&stream_opts,opts);
+    free(cddb_info);
+    return STREAM_ERROR;
+  }
+
+  cdda_verbose_set(cdd, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
+
+  if(p->sector_size) {
+    cdd->nsectors = p->sector_size;
+#ifndef HAVE_LIBCDIO
+    cdd->bigbuff = p->sector_size * CD_FRAMESIZE_RAW;
+#endif
+  }
+
+  if(cdda_open(cdd) != 0) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_MPDEMUX_CDDA_CantOpenDisc);
+    cdda_close(cdd);
+    m_struct_free(&stream_opts,opts);
+    free(cddb_info);
+    return STREAM_ERROR;
+  }
+
+  cd_info = cd_info_new();
+  mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_MPDEMUX_CDDA_AudioCDFoundWithNTracks,cdda_tracks(cdd));
+  for(i=0;i<cdd->tracks;i++) {
+	  char track_name[80];
+	  long sec=cdda_track_firstsector(cdd,i+1);
+	  long off=cdda_track_lastsector(cdd,i+1)-sec+1;
+
+	  sprintf(track_name, "Track %d", i+1);
+	  cd_info_add_track(cd_info, track_name, i+1, (unsigned int)(off/(60*75)), (unsigned int)((off/75)%60), (unsigned int)(off%75), sec, off );
+	  audiolen += off;
+  }
+  cd_info->min  = (unsigned int)(audiolen/(60*75));
+  cd_info->sec  = (unsigned int)((audiolen/75)%60);
+  cd_info->msec = (unsigned int)(audiolen%75);
+
+  priv = malloc(sizeof(cdda_priv));
+  memset(priv, 0, sizeof(cdda_priv));
+  priv->cd = cdd;
+  priv->cd_info = cd_info;
+
+  if(p->toc_bias)
+    offset -= cdda_track_firstsector(cdd,1);
+
+  if(offset) {
+    int i;
+    for(i = 0 ; i < cdd->tracks + 1 ; i++)
+      cdd->disc_toc[i].dwStartSector += offset;
+  }
+
+  if(p->speed)
+    cdda_speed_set(cdd,p->speed);
+
+  last_track = cdda_tracks(cdd);
+  if (p->span.start > last_track) p->span.start = last_track;
+  if (p->span.end < p->span.start) p->span.end = p->span.start;
+  if (p->span.end > last_track) p->span.end = last_track;
+  if(p->span.start)
+    priv->start_sector = cdda_track_firstsector(cdd,p->span.start);
+  else
+    priv->start_sector = cdda_disc_firstsector(cdd);
+
+  if(p->span.end) {
+    priv->end_sector = cdda_track_lastsector(cdd,p->span.end);
+  } else
+    priv->end_sector = cdda_disc_lastsector(cdd);
+
+  priv->cdp = paranoia_init(cdd);
+  if(priv->cdp == NULL) {
+    cdda_close(cdd);
+    free(priv);
+    cd_info_free(cd_info);
+    m_struct_free(&stream_opts,opts);
+    free(cddb_info);
+    return STREAM_ERROR;
+  }
+
+  if(mode == 0)
+    mode = PARANOIA_MODE_DISABLE;
+  else if(mode == 1)
+    mode = PARANOIA_MODE_OVERLAP;
+  else
+    mode = PARANOIA_MODE_FULL;
+  
+  if(p->no_skip)
+    mode |= PARANOIA_MODE_NEVERSKIP;
+#ifndef HAVE_LIBCDIO
+  paranoia_modeset(cdd, mode);
+
+  if(p->search_overlap >= 0)
+    paranoia_overlapset(cdd,p->search_overlap);
+#else
+  paranoia_modeset(priv->cdp, mode);
+
+  if(p->search_overlap >= 0)
+    paranoia_overlapset(priv->cdp,p->search_overlap);
+#endif
+
+  paranoia_seek(priv->cdp,priv->start_sector,SEEK_SET);
+  priv->sector = priv->start_sector;
+
+#ifdef MPLAYER_NETWORK
+  if(cddb_info) {
+    cd_info_free(cd_info);
+    priv->cd_info = cddb_info;
+    cd_info_debug( cddb_info );
+  }
+#endif
+
+  st->priv = priv;
+  st->start_pos = priv->start_sector*CD_FRAMESIZE_RAW;
+  st->end_pos = priv->end_sector*CD_FRAMESIZE_RAW;
+  st->type = STREAMTYPE_CDDA;
+  st->sector_size = CD_FRAMESIZE_RAW;
+
+  st->fill_buffer = fill_buffer;
+  st->seek = seek;
+  st->close = close_cdda;
+
+  *file_format = DEMUXER_TYPE_RAWAUDIO;
+
+  m_struct_free(&stream_opts,opts);
+
+  return STREAM_OK;
+}
+
+#ifndef HAVE_LIBCDIO
+static void cdparanoia_callback(long inpos, int function) {
+#else
+static void cdparanoia_callback(long int inpos, paranoia_cb_mode_t function) {
+#endif
+}
+
+static int fill_buffer(stream_t* s, char* buffer, int max_len) {
+  cdda_priv* p = (cdda_priv*)s->priv;
+  cd_track_t *cd_track;
+  int16_t * buf;
+  int i;
+  
+  buf = paranoia_read(p->cdp,cdparanoia_callback);
+
+#ifdef WORDS_BIGENDIAN 
+  for(i=0;i<CD_FRAMESIZE_RAW/2;i++)
+          buf[i]=le2me_16(buf[i]);
+#endif
+
+  p->sector++;
+  s->pos = p->sector*CD_FRAMESIZE_RAW;
+  memcpy(buffer,buf,CD_FRAMESIZE_RAW);
+
+  if((p->sector < p->start_sector) || (p->sector >= p->end_sector)) {
+    s->eof = 1;
+    return 0;
+  }
+
+  for(i=0;i<p->cd->tracks;i++){
+	  if(p->cd->disc_toc[i].dwStartSector==p->sector-1) {
+		  cd_track = cd_info_get_track(p->cd_info, i+1);
+//printf("Track %d, sector=%d\n", i, p->sector-1);
+		  if( cd_track!=NULL ) {
+			mp_msg(MSGT_SEEK, MSGL_INFO, "\n%s\n", cd_track->name); 
+			mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDA_TRACK=%d\n", cd_track->track_nb);
+		  }
+		  break;
+	  }
+  }
+
+  
+  return CD_FRAMESIZE_RAW;
+}
+
+static int seek(stream_t* s,off_t newpos) {
+  cdda_priv* p = (cdda_priv*)s->priv;
+  cd_track_t *cd_track;
+  int sec;
+  int current_track=0, seeked_track=0;
+  int i;
+  
+  s->pos = newpos;
+  if(s->pos < 0) {
+    s->eof = 1;
+    return 0;
+  }
+
+  sec = s->pos/CD_FRAMESIZE_RAW;
+//printf("pos: %d, sec: %d ## %d\n", (int)s->pos, (int)sec, CD_FRAMESIZE_RAW);
+//printf("sector: %d  new: %d\n", p->sector, sec );
+ 
+  for(i=0;i<p->cd->tracks;i++){
+//        printf("trk #%d: %d .. %d\n",i,p->cd->disc_toc[i].dwStartSector,p->cd->disc_toc[i+1].dwStartSector);
+	if( p->sector>=p->cd->disc_toc[i].dwStartSector && p->sector<p->cd->disc_toc[i+1].dwStartSector ) {
+		current_track = i;
+	}
+	if( sec>=p->cd->disc_toc[i].dwStartSector && sec<p->cd->disc_toc[i+1].dwStartSector ) {
+		seeked_track = i;
+	}
+  }
+//printf("current: %d, seeked: %d\n", current_track, seeked_track);
+	if( current_track!=seeked_track ) {
+//printf("Track %d, sector=%d\n", seeked_track, sec);
+		  cd_track = cd_info_get_track(p->cd_info, seeked_track+1);
+		  if( cd_track!=NULL ) {
+			  mp_msg(MSGT_SEEK, MSGL_INFO, "\n%s\n", cd_track->name);
+			  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDA_TRACK=%d\n", cd_track->track_nb);
+		  }
+
+	}
+#if 0
+  if(sec < p->start_sector)
+    sec = p->start_sector;
+  else if(sec > p->end_sector)
+    sec = p->end_sector;
+#endif
+
+  p->sector = sec;
+//  s->pos = sec*CD_FRAMESIZE_RAW;
+
+//printf("seek: %d, sec: %d\n", (int)s->pos, sec);
+  paranoia_seek(p->cdp,sec,SEEK_SET);
+  return 1;
+}
+
+static void close_cdda(stream_t* s) {
+  cdda_priv* p = (cdda_priv*)s->priv;
+  paranoia_free(p->cdp);
+  cdda_close(p->cd);
+  cd_info_free(p->cd_info);
+  free(p);
+}
+
+stream_info_t stream_info_cdda = {
+  "CDDA",
+  "cdda",
+  "Albeu",
+  "",
+  open_cdda,
+  { "cdda", "cddb", NULL },
+  &stream_opts,
+  1 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cddb.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,878 @@
+/*
+ * CDDB HTTP protocol 
+ * by Bertrand Baudet <bertrand_baudet@yahoo.com>
+ * (C) 2002, MPlayer team.
+ *
+ * Implementation follow the freedb.howto1.06.txt specification
+ * from http://freedb.freedb.org
+ * 
+ * discid computation by Jeremy D. Zawodny
+ *	 Copyright (c) 1998-2000 Jeremy D. Zawodny <Jeremy@Zawodny.com>
+ *	 Code release under GPL
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#ifdef WIN32
+#ifdef __MINGW32__
+#define mkdir(a,b) mkdir(a)
+#endif
+#include <windows.h>
+#ifdef HAVE_WINSOCK2
+#include <winsock2.h>
+#endif
+#else
+#include <netdb.h>
+#include <sys/ioctl.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#if defined(__linux__)
+	#include <linux/cdrom.h>
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+	#include <sys/cdio.h>
+#elif defined(WIN32)
+        #include <ddk/ntddcdrm.h>
+#elif (__bsdi__)
+        #include <dvd.h>
+#endif
+
+#include "cdd.h"
+#include "version.h"
+#include "stream.h"
+#include "network.h"
+
+#define DEFAULT_FREEDB_SERVER	"freedb.freedb.org"
+#define DEFAULT_CACHE_DIR	"/.cddb/"
+
+stream_t* open_cdda(char *dev, char *track);
+
+static cd_toc_t cdtoc[100];
+static int cdtoc_last_track;
+
+#if defined(__linux__) || defined(__bsdi__)
+int 
+read_toc(const char *dev) {
+	int drive;
+	struct cdrom_tochdr tochdr;
+	struct cdrom_tocentry tocentry;
+	int i;
+
+	drive = open(dev, O_RDONLY | O_NONBLOCK);
+	if( drive<0 ) {
+		return drive;
+	}
+	
+	ioctl(drive, CDROMREADTOCHDR, &tochdr);
+	for (i = tochdr.cdth_trk0; i <= tochdr.cdth_trk1; i++) {
+		tocentry.cdte_track = i;
+		tocentry.cdte_format = CDROM_MSF;
+		ioctl(drive, CDROMREADTOCENTRY, &tocentry);
+		cdtoc[i-1].min = tocentry.cdte_addr.msf.minute;
+		cdtoc[i-1].sec = tocentry.cdte_addr.msf.second;
+		cdtoc[i-1].frame = tocentry.cdte_addr.msf.frame;
+		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
+		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
+	}
+	tocentry.cdte_track = 0xAA;
+	tocentry.cdte_format = CDROM_MSF;
+	ioctl(drive, CDROMREADTOCENTRY, &tocentry);
+	cdtoc[tochdr.cdth_trk1].min = tocentry.cdte_addr.msf.minute;
+	cdtoc[tochdr.cdth_trk1].sec = tocentry.cdte_addr.msf.second;
+	cdtoc[tochdr.cdth_trk1].frame = tocentry.cdte_addr.msf.frame;
+	cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].min*60*75;
+	cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].sec*75;
+	close(drive);
+	return tochdr.cdth_trk1;
+}
+
+#elif defined(WIN32)
+int
+read_toc(const char *dev) {
+        HANDLE drive;
+        DWORD r;
+        CDROM_TOC toc;
+        char device[10];
+        int i;
+
+        sprintf(device, "\\\\.\\%s", dev);
+        drive = CreateFile(device, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+
+        if(!DeviceIoControl(drive, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(CDROM_TOC), &r, 0)) {
+                mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToReadTOC);
+                return 0;
+        }
+
+        for (i = toc.FirstTrack; i <= toc.LastTrack; i++) {
+                toc.FirstTrack = i;
+		cdtoc[i-1].min = toc.TrackData[i - 1].Address[1];
+		cdtoc[i-1].sec = toc.TrackData[i - 1].Address[2];
+		cdtoc[i-1].frame = toc.TrackData[i - 1].Address[3];
+		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
+		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
+        }
+        toc.FirstTrack = 0xAA;
+        cdtoc[toc.LastTrack].min = toc.TrackData[toc.LastTrack].Address[1];
+        cdtoc[toc.LastTrack].sec = toc.TrackData[toc.LastTrack].Address[2];
+        cdtoc[toc.LastTrack].frame = toc.TrackData[toc.LastTrack].Address[3];
+        cdtoc[toc.LastTrack].frame += cdtoc[toc.LastTrack].min*60*75;
+        cdtoc[toc.LastTrack].frame += cdtoc[toc.LastTrack].sec*75;
+        CloseHandle(drive);
+        return toc.LastTrack;
+}
+
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+int 
+read_toc(const char *dev) {
+	int drive;
+	struct ioc_toc_header tochdr;
+	struct ioc_read_toc_single_entry tocentry;
+	int i;
+
+	drive = open(dev, O_RDONLY | O_NONBLOCK);
+	if( drive<0 ) {
+		return drive;
+	}
+
+	ioctl(drive, CDIOREADTOCHEADER, &tochdr);
+	for (i = tochdr.starting_track; i <= tochdr.ending_track; i++) {
+		tocentry.track = i;
+		tocentry.address_format = CD_MSF_FORMAT;
+		ioctl(drive, CDIOREADTOCENTRY, &tocentry);
+		cdtoc[i-1].min = tocentry.entry.addr.msf.minute;
+		cdtoc[i-1].sec = tocentry.entry.addr.msf.second;
+		cdtoc[i-1].frame = tocentry.entry.addr.msf.frame;
+		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
+		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
+	}
+	tocentry.track = 0xAA;
+	tocentry.address_format = CD_MSF_FORMAT;
+	ioctl(drive, CDIOREADTOCENTRY, &tocentry);
+	cdtoc[tochdr.ending_track].min = tocentry.entry.addr.msf.minute;
+	cdtoc[tochdr.ending_track].sec = tocentry.entry.addr.msf.second;
+	cdtoc[tochdr.ending_track].frame = tocentry.entry.addr.msf.frame;
+	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].min*60*75;
+	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].sec*75;
+	close(drive);
+	return tochdr.ending_track;
+}
+
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+int
+read_toc(const char *dev) {
+	int drive;
+	struct ioc_toc_header tochdr;
+	struct ioc_read_toc_entry tocentry;
+	int i;
+	struct cd_toc_entry toc_buffer;
+
+	drive = open(dev, O_RDONLY | O_NONBLOCK);
+	if( drive<0 ) {
+		return drive;
+	}
+
+	ioctl(drive, CDIOREADTOCHEADER, &tochdr);
+	for (i = tochdr.starting_track; i <= tochdr.ending_track; i++) {
+		tocentry.starting_track = i;
+		tocentry.address_format = CD_MSF_FORMAT;
+		tocentry.data = &toc_buffer;
+		tocentry.data_len = sizeof(toc_buffer);
+		ioctl(drive, CDIOREADTOCENTRYS, &tocentry);
+		cdtoc[i-1].min = toc_buffer.addr.msf.minute;
+		cdtoc[i-1].sec = toc_buffer.addr.msf.second;
+		cdtoc[i-1].frame = toc_buffer.addr.msf.frame;
+		cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
+		cdtoc[i-1].frame += cdtoc[i-1].sec*75;
+	}
+	tocentry.starting_track = 0xAA;
+	tocentry.address_format = CD_MSF_FORMAT;
+	ioctl(drive, CDIOREADTOCENTRYS, &tocentry);
+	cdtoc[tochdr.ending_track].min = toc_buffer.addr.msf.minute;
+	cdtoc[tochdr.ending_track].sec = toc_buffer.addr.msf.second;
+	cdtoc[tochdr.ending_track].frame = toc_buffer.addr.msf.frame;
+	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].min*60*75;
+	cdtoc[tochdr.ending_track].frame += cdtoc[tochdr.ending_track].sec*75;
+	close(drive);
+	return tochdr.ending_track;
+}
+#endif
+
+/** 
+\brief Reads TOC from CD in the given device and prints the number of tracks
+       and the length of each track in minute:second:frame format.
+\param *dev the device to analyse
+\return if the command line -identify is given, returns the last track of
+        the TOC or -1 if the TOC can't be read,
+        otherwise just returns 0 and let cddb_resolve the TOC
+*/
+int cdd_identify(const char *dev)
+{
+	cdtoc_last_track = 0;
+	if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
+	{
+		int i, min, sec, frame;
+		cdtoc_last_track = read_toc(dev);
+		if (cdtoc_last_track < 0) {
+			mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToOpenDevice, dev);
+			return -1;
+		}
+		mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_CDDA_TRACKS=%d\n", cdtoc_last_track);
+		for (i = 1; i <= cdtoc_last_track; i++)
+		{
+			frame = cdtoc[i].frame - cdtoc[i-1].frame;
+			sec = frame / 75;
+			frame -= sec * 75;
+			min = sec / 60;
+			sec -= min * 60;
+			mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDA_TRACK_%d_MSF=%02d:%02d:%02d\n", i, min, sec, frame);
+		}
+	}
+	return cdtoc_last_track;
+}
+
+unsigned int 
+cddb_sum(int n) {
+	unsigned int ret;
+
+	ret = 0;
+	while (n > 0) {
+		ret += (n % 10);
+		n /= 10;
+	}
+	return ret;
+}
+
+unsigned long 
+cddb_discid(int tot_trks) {
+	unsigned int i, t = 0, n = 0;
+
+	i = 0;
+	while (i < (unsigned int)tot_trks) {
+		n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
+		i++;
+	}
+	t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) -
+		((cdtoc[0].min * 60) + cdtoc[0].sec);
+	return ((n % 0xff) << 24 | t << 8 | tot_trks);
+}
+
+
+
+int
+cddb_http_request(char *command, int (*reply_parser)(HTTP_header_t*,cddb_data_t*), cddb_data_t *cddb_data) {
+	char request[4096];
+	int fd, ret = 0;
+	URL_t *url;
+	HTTP_header_t *http_hdr;
+	
+	if( reply_parser==NULL || command==NULL || cddb_data==NULL ) return -1;
+	
+	sprintf( request, "http://%s/~cddb/cddb.cgi?cmd=%s%s&proto=%d", cddb_data->freedb_server, command, cddb_data->cddb_hello, cddb_data->freedb_proto_level );
+	mp_msg(MSGT_OPEN, MSGL_INFO,"Request[%s]\n", request );
+
+	url = url_new(request);
+	if( url==NULL ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NotAValidURL);
+		return -1;
+	}
+	
+	fd = http_send_request(url,0);
+	if( fd<0 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToSendHTTPRequest);
+		return -1;
+	}
+
+	http_hdr = http_read_response( fd );
+	if( http_hdr==NULL ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToReadHTTPResponse);
+		return -1;
+	}
+
+	http_debug_hdr(http_hdr);
+	mp_msg(MSGT_OPEN, MSGL_INFO,"body=[%s]\n", http_hdr->body );
+
+	switch(http_hdr->status_code) {
+		case 200:
+			ret = reply_parser(http_hdr, cddb_data);
+			break;
+		case 400:
+			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_HTTPErrorNOTFOUND);
+			break;
+		default:
+			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_HTTPErrorUnknown);
+	}
+
+	http_free( http_hdr );
+	url_free( url );
+	
+	return ret;
+}
+
+int
+cddb_read_cache(cddb_data_t *cddb_data) {
+	char file_name[100];
+	struct stat stats;
+	int file_fd, ret;
+	size_t file_size;
+
+	if( cddb_data==NULL || cddb_data->cache_dir==NULL ) return -1;
+	
+	sprintf( file_name, "%s%08lx", cddb_data->cache_dir, cddb_data->disc_id);
+	
+	file_fd = open(file_name, O_RDONLY
+#ifdef WIN32
+	| O_BINARY
+#endif
+	);
+	if( file_fd<0 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NoCacheFound);
+		return -1;
+	}
+
+	ret = fstat( file_fd, &stats );
+	if( ret<0 ) {
+		perror("fstat");
+		file_size = 4096;
+	} else {
+		file_size = stats.st_size;
+	}
+	
+	cddb_data->xmcd_file = malloc(file_size);
+	if( cddb_data->xmcd_file==NULL ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
+		close(file_fd);
+		return -1;
+	}
+	cddb_data->xmcd_file_size = read(file_fd, cddb_data->xmcd_file, file_size);
+	if( cddb_data->xmcd_file_size!=file_size ) {
+		mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenRead);
+		close(file_fd);
+		return -1;
+	}
+	
+	close(file_fd);
+	
+	return 0;
+}
+
+int
+cddb_write_cache(cddb_data_t *cddb_data) {
+	// We have the file, save it for cache.
+	struct stat file_stat;
+	char file_name[100];
+	int file_fd, ret;
+	int wrote=0;
+
+	if( cddb_data==NULL || cddb_data->cache_dir==NULL ) return -1;
+
+	// Check if the CDDB cache dir exist
+	ret = stat( cddb_data->cache_dir, &file_stat );
+	if( ret<0 ) {
+		// Directory not present, create it.
+		ret = mkdir( cddb_data->cache_dir, 0755 );
+#ifdef __MINGW32__
+		if( ret<0 && errno != EEXIST ) {
+#else
+		if( ret<0 ) {
+#endif
+			perror("mkdir");
+			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToCreateDirectory, cddb_data->cache_dir);
+			return -1;
+		}
+	}
+	
+	sprintf( file_name, "%s%08lx", cddb_data->cache_dir, cddb_data->disc_id );
+	
+	file_fd = creat(file_name, S_IREAD|S_IWRITE);
+	if( file_fd<0 ) {
+		perror("create");
+		return -1;
+	}
+	
+	wrote = write(file_fd, cddb_data->xmcd_file, cddb_data->xmcd_file_size);
+	if( wrote<0 ) {
+		perror("write");
+		close(file_fd);
+		return -1;
+	}
+	if( (unsigned int)wrote!=cddb_data->xmcd_file_size ) {
+		mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_CDDB_NotAllXMCDFileHasBeenWritten);
+		close(file_fd);
+		return -1;
+	}
+	
+	close(file_fd);
+
+	return 0;
+}
+
+int
+cddb_read_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
+	unsigned long disc_id;
+	char category[100];
+	char *ptr=NULL, *ptr2=NULL;
+	int ret, status;
+
+	if( http_hdr==NULL || cddb_data==NULL ) return -1;
+	
+	ret = sscanf( http_hdr->body, "%d ", &status);
+	if( ret!=1 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+		return -1;
+	}
+
+	switch(status) {
+		case 210:
+			ret = sscanf( http_hdr->body, "%d %s %08lx", &status, category, &disc_id);
+			if( ret!=3 ) {
+				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+				return -1;
+			}
+			// Check if it's a xmcd database file
+			ptr = strstr(http_hdr->body, "# xmcd");
+			if( ptr==NULL ) {
+				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_InvalidXMCDDatabaseReturned);
+				return -1;
+			}
+			// Ok found the beginning of the file
+			// look for the end
+			ptr2 = strstr(ptr, "\r\n.\r\n");
+			if( ptr2==NULL ) {
+				ptr2 = strstr(ptr, "\n.\n");
+				if( ptr2==NULL ) {
+					mp_msg(MSGT_DEMUX, MSGL_FIXME, "Unable to find '.'\n");
+					ptr2=ptr+strlen(ptr); //return -1;
+				}
+			}
+			// Ok found the end
+			// do a sanity check
+			if( http_hdr->body_size<(unsigned int)(ptr2-ptr) ) {
+				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_UnexpectedFIXME);
+				return -1;
+			}
+			cddb_data->xmcd_file = ptr;
+			cddb_data->xmcd_file_size = ptr2-ptr+2;
+			cddb_data->xmcd_file[cddb_data->xmcd_file_size] = '\0';
+			// Avoid the http_free function to free the xmcd file...save a mempcy...
+			http_hdr->body = NULL;
+			http_hdr->body_size = 0;
+			return cddb_write_cache(cddb_data);
+		default:
+			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);
+	}
+	return 0;
+}
+
+int
+cddb_request_titles(cddb_data_t *cddb_data) {
+	char command[1024];
+	sprintf( command, "cddb+read+%s+%08lx", cddb_data->category, cddb_data->disc_id);
+	return cddb_http_request(command, cddb_read_parse, cddb_data); 
+}
+
+int
+cddb_parse_matches_list(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
+	char album_title[100];
+	char *ptr = NULL;
+	int ret;
+	
+	ptr = strstr(http_hdr->body, "\n");
+	if( ptr==NULL ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_UnableToFindEOL);
+		return -1;
+	}
+	ptr++;
+	// We have a list of exact/inexact matches, so which one do we use?
+	// So let's take the first one.
+	ret = sscanf(ptr, "%s %08lx %s", cddb_data->category, &(cddb_data->disc_id), album_title);
+	if( ret!=3 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+		return -1;
+	}
+	ptr = strstr(http_hdr->body, album_title);
+	if( ptr!=NULL ) {
+		char *ptr2;
+		int len;
+		ptr2 = strstr(ptr, "\n");
+		if( ptr2==NULL ) {
+			len = (http_hdr->body_size)-(ptr-(http_hdr->body));
+		} else {
+			len = ptr2-ptr+1;
+		}
+		strncpy(album_title, ptr, len);
+		album_title[len-2]='\0';
+	}
+	mp_msg(MSGT_DEMUX, MSGL_STATUS, MSGTR_MPDEMUX_CDDB_ParseOKFoundAlbumTitle, album_title);
+	return 0;
+}
+
+int
+cddb_query_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
+	char album_title[100];
+	char *ptr = NULL;
+	int ret, status;
+	
+	ret = sscanf( http_hdr->body, "%d ", &status);
+	if( ret!=1 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+		return -1;
+	}
+
+	switch(status) {
+		case 200:
+			// Found exact match
+			ret = sscanf(http_hdr->body, "%d %s %08lx %s", &status, cddb_data->category, &(cddb_data->disc_id), album_title);
+			if( ret!=4 ) {
+				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+				return -1;
+			}
+			ptr = strstr(http_hdr->body, album_title);
+			if( ptr!=NULL ) {
+				char *ptr2;
+				int len;
+				ptr2 = strstr(ptr, "\n");
+				if( ptr2==NULL ) {
+					len = (http_hdr->body_size)-(ptr-(http_hdr->body));
+				} else {
+					len = ptr2-ptr+1;
+				}
+				strncpy(album_title, ptr, len);
+				album_title[len-2]='\0';
+			}
+			mp_msg(MSGT_DEMUX, MSGL_STATUS, MSGTR_MPDEMUX_CDDB_ParseOKFoundAlbumTitle, album_title);
+			return cddb_request_titles(cddb_data);
+		case 202:
+			// No match found
+			mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_CDDB_AlbumNotFound);
+			break;
+		case 210:
+			// Found exact matches, list follows
+			cddb_parse_matches_list(http_hdr, cddb_data);
+			return cddb_request_titles(cddb_data);
+/*
+body=[210 Found exact matches, list follows (until terminating `.')
+misc c711930d Santana / Supernatural
+rock c711930d Santana / Supernatural
+blues c711930d Santana / Supernatural
+.]
+*/	
+		case 211:
+			// Found inexact matches, list follows
+			cddb_parse_matches_list(http_hdr, cddb_data);
+			return cddb_request_titles(cddb_data);
+		case 500:
+			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_ServerReturnsCommandSyntaxErr);
+			break;
+		default:
+			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);	
+	}
+	return -1;
+}
+
+int
+cddb_proto_level_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
+	int max;
+	int ret, status;
+	char *ptr;
+	
+	ret = sscanf( http_hdr->body, "%d ", &status);
+	if( ret!=1 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);	
+		return -1;
+	}
+
+	switch(status) {
+		case 210:
+			ptr = strstr(http_hdr->body, "max proto:");
+			if( ptr==NULL ) {
+				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+				return -1;
+			}
+			ret = sscanf(ptr, "max proto: %d", &max);
+			if( ret!=1 ) {
+				mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+				return -1;
+			}
+			cddb_data->freedb_proto_level = max;
+			return 0;
+		default:
+			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);	
+	}
+	return -1;
+}
+
+int
+cddb_get_proto_level(cddb_data_t *cddb_data) {
+	return cddb_http_request("stat", cddb_proto_level_parse, cddb_data);
+}
+
+int
+cddb_freedb_sites_parse(HTTP_header_t *http_hdr, cddb_data_t *cddb_data) {
+	int ret, status;
+
+	ret = sscanf( http_hdr->body, "%d ", &status);
+	if( ret!=1 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_ParseError);
+		return -1;
+	}
+
+	switch(status) {
+		case 210:
+			// TODO: Parse the sites
+			ret = cddb_data->anonymous;	// For gcc complaining about unused parameter.
+			return 0;
+		case 401:
+			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_NoSitesInfoAvailable);
+			break;
+		default:
+			mp_msg(MSGT_DEMUX, MSGL_FIXME, MSGTR_MPDEMUX_CDDB_UnhandledCode);
+	}
+	return -1;
+}
+
+int
+cddb_get_freedb_sites(cddb_data_t *cddb_data) {
+	return cddb_http_request("sites", cddb_freedb_sites_parse, cddb_data);
+}
+
+void
+cddb_create_hello(cddb_data_t *cddb_data) {
+	char host_name[51];
+	char *user_name;
+	
+	if( cddb_data->anonymous ) {	// Default is anonymous
+		/* Note from Eduardo Pérez Ureta <eperez@it.uc3m.es> : 
+		 * We don't send current user/host name in hello to prevent spam.
+		 * Software that sends this is considered spyware
+		 * that most people don't like.
+		 */
+		user_name = "anonymous";
+		strcpy(host_name, "localhost");
+	} else {
+		if( gethostname(host_name, 50)<0 ) {
+			strcpy(host_name, "localhost");
+		}
+		user_name = getenv("LOGNAME");
+	}
+	sprintf( cddb_data->cddb_hello, "&hello=%s+%s+%s+%s", user_name, host_name, "MPlayer", VERSION );
+}
+
+int 
+cddb_retrieve(cddb_data_t *cddb_data) {
+	char offsets[1024], command[1024];
+	char *ptr;
+	unsigned int i, time_len;
+	int ret;
+
+	ptr = offsets;
+	for( i=0; i<cddb_data->tracks ; i++ ) {
+		ptr += sprintf(ptr, "%d+", cdtoc[i].frame );
+		if (ptr-offsets > sizeof offsets - 40) break;
+	}
+	ptr[0]=0;
+	time_len = (cdtoc[cddb_data->tracks].frame)/75;
+	
+	cddb_data->freedb_server = DEFAULT_FREEDB_SERVER;
+	cddb_data->freedb_proto_level = 1;
+	cddb_data->xmcd_file = NULL;
+
+	cddb_create_hello(cddb_data);
+	if( cddb_get_proto_level(cddb_data)<0 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToGetProtocolLevel);
+		return -1;
+	}
+
+	//cddb_get_freedb_sites(&cddb_data);
+
+	sprintf(command, "cddb+query+%08lx+%d+%s%d", cddb_data->disc_id, cddb_data->tracks, offsets, time_len );
+	ret = cddb_http_request(command, cddb_query_parse, cddb_data);
+	if( ret<0 ) return -1;
+
+	if( cddb_data->cache_dir!=NULL ) {
+		free(cddb_data->cache_dir);
+	}
+	return 0;
+}
+
+int
+cddb_resolve(const char *dev, char **xmcd_file) {
+	char cddb_cache_dir[] = DEFAULT_CACHE_DIR;
+	char *home_dir = NULL;
+	cddb_data_t cddb_data;
+
+	if (cdtoc_last_track <= 0)
+	{
+	    cdtoc_last_track = read_toc(dev);
+	    if (cdtoc_last_track < 0) {
+		mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToOpenDevice, dev);
+		return -1;
+	    }
+	}
+	cddb_data.tracks = cdtoc_last_track;
+	cddb_data.disc_id = cddb_discid(cddb_data.tracks);
+	cddb_data.anonymous = 1;	// Don't send user info by default
+
+	// Check if there is a CD in the drive
+	// FIXME: That's not really a good way to check
+	if( cddb_data.disc_id==0 ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NoCDInDrive);
+		return -1;
+	}
+	
+	home_dir = getenv("HOME");
+#ifdef __MINGW32__
+	if( home_dir==NULL ) home_dir = getenv("USERPROFILE");
+	if( home_dir==NULL ) home_dir = getenv("HOMEPATH");
+	// Last resort, store the cddb cache in the mplayer directory
+	if( home_dir==NULL ) home_dir = (char *)get_path("");
+#endif
+	if( home_dir==NULL ) {
+		cddb_data.cache_dir = NULL;
+	} else {
+		cddb_data.cache_dir = malloc(strlen(home_dir)+strlen(cddb_cache_dir)+1);
+		if( cddb_data.cache_dir==NULL ) {
+			mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
+			return -1;
+		}
+		sprintf(cddb_data.cache_dir, "%s%s", home_dir, cddb_cache_dir );
+	}
+
+	// Check for a cached file
+	if( cddb_read_cache(&cddb_data)<0 ) {
+		// No Cache found
+		if( cddb_retrieve(&cddb_data)<0 ) {
+			return -1;
+		}
+	}
+
+	if( cddb_data.xmcd_file!=NULL ) {
+//		printf("%s\n", cddb_data.xmcd_file );
+		*xmcd_file = cddb_data.xmcd_file;
+		return 0;
+	}
+	
+	return -1;
+}
+
+/*******************************************************************************************************************
+ *
+ * xmcd parser
+ *
+ *******************************************************************************************************************/
+char*
+xmcd_parse_dtitle(cd_info_t *cd_info, char *line) {
+	char *ptr, *album;
+	ptr = strstr(line, "DTITLE=");
+	if( ptr!=NULL ) {
+		ptr += 7;
+		album = strstr(ptr, "/");
+		if( album==NULL ) return NULL;
+		cd_info->album = malloc(strlen(album+2)+1);
+		if( cd_info->album==NULL ) {
+			return NULL;
+		}
+		strcpy( cd_info->album, album+2 );
+		album--;
+		album[0] = '\0';
+		cd_info->artist = malloc(strlen(ptr)+1);
+		if( cd_info->artist==NULL ) {
+			return NULL;
+		}
+		strcpy( cd_info->artist, ptr );
+	}
+	return ptr;
+}
+
+char*
+xmcd_parse_dgenre(cd_info_t *cd_info, char *line) {
+	char *ptr;
+	ptr = strstr(line, "DGENRE=");
+	if( ptr!=NULL ) {
+		ptr += 7;
+		cd_info->genre = malloc(strlen(ptr)+1);
+		if( cd_info->genre==NULL ) {
+			return NULL;
+		}
+		strcpy( cd_info->genre, ptr );
+	}
+	return ptr;
+}
+
+char*
+xmcd_parse_ttitle(cd_info_t *cd_info, char *line) {
+	unsigned int track_nb;
+	unsigned long sec, off;
+	char *ptr;
+	ptr = strstr(line, "TTITLE");
+	if( ptr!=NULL ) {
+		ptr += 6;
+		// Here we point to the track number
+		track_nb = atoi(ptr);
+		ptr = strstr(ptr, "=");
+		if( ptr==NULL ) return NULL;
+		ptr++;
+		
+		sec = cdtoc[track_nb].frame;
+		off = cdtoc[track_nb+1].frame-sec+1;
+
+		cd_info_add_track( cd_info, ptr, track_nb+1, (unsigned int)(off/(60*75)), (unsigned int)((off/75)%60), (unsigned int)(off%75), sec, off );
+	}
+	return ptr;
+}
+
+cd_info_t*
+cddb_parse_xmcd(char *xmcd_file) {
+	cd_info_t *cd_info = NULL;
+	int length, pos = 0;
+	char *ptr, *ptr2;
+	unsigned int audiolen;
+	if( xmcd_file==NULL ) return NULL;
+	
+	cd_info = cd_info_new();
+	if( cd_info==NULL ) {
+		return NULL;
+	}
+	
+	length = strlen(xmcd_file);
+	ptr = xmcd_file;
+	while( ptr!=NULL && pos<length ) {
+		// Read a line
+		ptr2 = ptr;
+		while( ptr2[0]!='\0' && ptr2[0]!='\r' && ptr2[0]!='\n' ) ptr2++;
+		if( ptr2[0]=='\0' ) {
+			break;
+		}
+		ptr2[0] = '\0';
+		// Ignore comments
+		if( ptr[0]!='#' ) {
+			// Search for the album title
+			if( xmcd_parse_dtitle(cd_info, ptr) );
+			// Search for the genre
+			else if( xmcd_parse_dgenre(cd_info, ptr) );
+			// Search for a track title
+			else if( xmcd_parse_ttitle(cd_info, ptr) ) audiolen++;	// <-- audiolen++ to shut up gcc warning
+		}
+		if( ptr2[1]=='\n' ) ptr2++;
+		pos = (ptr2+1)-ptr;
+		ptr = ptr2+1;
+	}
+
+	audiolen = cdtoc[cd_info->nb_tracks].frame-cdtoc[0].frame;	
+	cd_info->min  = (unsigned int)(audiolen/(60*75));
+	cd_info->sec  = (unsigned int)((audiolen/75)%60);
+	cd_info->msec = (unsigned int)(audiolen%75);
+	
+	return cd_info;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cdinfo.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,137 @@
+/*
+ * CD Info 
+ * by Bertrand Baudet <bertrand_baudet@yahoo.com>
+ * (C) 2002, MPlayer team.
+*/
+
+#include "config.h"
+
+#if defined(HAVE_CDDA) 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mp_msg.h"
+#include "help_mp.h"
+#include "cdd.h"
+
+/*******************************************************************************************************************
+ *
+ * xmcd parser, cd info list
+ *
+ *******************************************************************************************************************/
+
+cd_info_t*
+cd_info_new() {
+	cd_info_t *cd_info = NULL;
+	
+	cd_info = malloc(sizeof(cd_info_t));
+	if( cd_info==NULL ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
+		return NULL;
+	}
+	
+	memset(cd_info, 0, sizeof(cd_info_t));
+	
+	return cd_info;
+}
+
+void
+cd_info_free(cd_info_t *cd_info) {
+	cd_track_t *cd_track, *cd_track_next;
+	if( cd_info==NULL ) return;
+	if( cd_info->artist!=NULL ) free(cd_info->artist);
+	if( cd_info->album!=NULL ) free(cd_info->album);
+	if( cd_info->genre!=NULL ) free(cd_info->genre);
+
+	cd_track_next = cd_info->first;
+	while( cd_track_next!=NULL ) {
+		cd_track = cd_track_next;
+		cd_track_next = cd_track->next;
+		if( cd_track->name!=NULL ) free(cd_track->name);
+		free(cd_track);
+	}
+}
+
+cd_track_t*
+cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length) {
+	cd_track_t *cd_track;
+	
+	if( cd_info==NULL || track_name==NULL ) return NULL;
+	
+	cd_track = malloc(sizeof(cd_track_t));
+	if( cd_track==NULL ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
+		return NULL;
+	}
+	memset(cd_track, 0, sizeof(cd_track_t));
+	
+	cd_track->name = malloc(strlen(track_name)+1);
+	if( cd_track->name==NULL ) {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed);
+		free(cd_track);
+		return NULL;
+	}
+	strcpy(cd_track->name, track_name);
+	cd_track->track_nb = track_nb;
+	cd_track->min = min;
+	cd_track->sec = sec;
+	cd_track->msec = msec;
+	cd_track->frame_begin = frame_begin;
+	cd_track->frame_length = frame_length;
+
+	if( cd_info->first==NULL ) {
+		cd_info->first = cd_track;
+	}
+	if( cd_info->last!=NULL ) {
+		cd_info->last->next = cd_track;
+	}
+
+	cd_track->prev = cd_info->last;
+	
+	cd_info->last = cd_track;
+	cd_info->current = cd_track;
+
+	cd_info->nb_tracks++;
+	
+	return cd_track;
+}
+
+cd_track_t*
+cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb) {
+	cd_track_t *cd_track=NULL;
+
+	if( cd_info==NULL ) return NULL;
+
+	cd_track = cd_info->first;
+	while( cd_track!=NULL ) {
+		if( cd_track->track_nb==track_nb ) {
+			return cd_track;
+		}
+		cd_track = cd_track->next;
+	}
+	return NULL;
+}
+
+void
+cd_info_debug(cd_info_t *cd_info) {
+	cd_track_t *current_track;
+	printf("================ CD INFO === start =========\n");
+	if( cd_info==NULL ) {
+		printf("cd_info is NULL\n");
+		return;
+	}
+	printf(" artist=[%s]\n", cd_info->artist);
+	printf(" album=[%s]\n", cd_info->album);
+	printf(" genre=[%s]\n", cd_info->genre);
+	printf(" nb_tracks=%d\n", cd_info->nb_tracks);
+	printf(" length= %2d:%02d.%02d\n", cd_info->min, cd_info->sec, cd_info->msec);
+	current_track = cd_info->first;
+	while( current_track!=NULL ) {
+		printf("  #%2d %2d:%02d.%02d @ %7ld\t[%s] \n", current_track->track_nb, current_track->min, current_track->sec, current_track->msec, current_track->frame_begin, current_track->name);
+		current_track = current_track->next;
+	}
+	printf("================ CD INFO ===  end  =========\n");
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cookies.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,278 @@
+/*
+ * HTTP Cookies
+ * Reads Netscape and Mozilla cookies.txt files
+ *
+ * by Dave Lambley <mplayer@davel.me.uk>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <inttypes.h>
+
+#include "cookies.h"
+#include "http.h"
+#include "mp_msg.h"
+
+#define MAX_COOKIES 20
+
+char *cookies_file = NULL;
+
+typedef struct cookie_list_type {
+    char *name;
+    char *value;
+    char *domain;
+    char *path;
+
+    int secure;
+
+    struct cookie_list_type *next;
+} cookie_list_t;
+
+/* Pointer to the linked list of cookies */
+static struct cookie_list_type *cookie_list = NULL;
+
+
+/* Like strdup, but stops at anything <31. */
+static char *col_dup(const char *src)
+{
+    char *dst;
+    int length = 0;
+
+    while (src[length] > 31)
+	length++;
+
+    dst = malloc(length + 1);
+    strncpy(dst, src, length);
+    dst[length] = 0;
+
+    return dst;
+}
+
+static int right_hand_strcmp(const char *cookie_domain, const char *url_domain)
+{
+    int c_l;
+    int u_l;
+
+    c_l = strlen(cookie_domain);
+    u_l = strlen(url_domain);
+
+    if (c_l > u_l)
+	return -1;
+    return strcmp(cookie_domain, url_domain + u_l - c_l);
+}
+
+static int left_hand_strcmp(const char *cookie_path, const char *url_path)
+{
+    return strncmp(cookie_path, url_path, strlen(cookie_path));
+}
+
+/* Finds the start of all the columns */
+static int parse_line(char **ptr, char *cols[6])
+{
+    int col;
+    cols[0] = *ptr;
+
+    for (col = 1; col < 7; col++) {
+	for (; (**ptr) > 31; (*ptr)++);
+	if (**ptr == 0)
+	    return 0;
+	(*ptr)++;
+	if ((*ptr)[-1] != 9)
+	    return 0;
+	cols[col] = (*ptr);
+    }
+
+    return 1;
+}
+
+/* Loads a file into RAM */
+static char *load_file(const char *filename, off_t * length)
+{
+    int fd;
+    char *buffer;
+
+    mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
+
+    fd = open(filename, O_RDONLY);
+    if (fd < 0) {
+	mp_msg(MSGT_NETWORK, MSGL_V, "Could not open");
+	return NULL;
+    }
+
+    *length = lseek(fd, 0, SEEK_END);
+
+    if (*length < 0) {
+	mp_msg(MSGT_NETWORK, MSGL_V, "Could not find EOF");
+	return NULL;
+    }
+
+    if (*length > SIZE_MAX - 1) {
+	mp_msg(MSGT_NETWORK, MSGL_V, "File too big, could not malloc.");
+	return NULL;
+    }
+
+    lseek(fd, SEEK_SET, 0);
+
+    if (!(buffer = malloc(*length + 1))) {
+	mp_msg(MSGT_NETWORK, MSGL_V, "Could not malloc.");
+	return NULL;
+    }
+
+    if (read(fd, buffer, *length) != *length) {
+	mp_msg(MSGT_NETWORK, MSGL_V, "Read is behaving funny.");
+	return NULL;
+    }
+    close(fd);
+    buffer[*length] = 0;
+
+    return buffer;
+}
+
+/* Loads a cookies.txt file into a linked list. */
+static struct cookie_list_type *load_cookies_from(const char *filename,
+						  struct cookie_list_type
+						  *list)
+{
+    char *ptr;
+    off_t length;
+
+    mp_msg(MSGT_NETWORK, MSGL_V, "Loading cookie file: %s\n", filename);
+
+    ptr = load_file(filename, &length);
+    if (!ptr)
+	return list;
+
+    while (*ptr > 0) {
+	char *cols[7];
+	if (parse_line(&ptr, cols)) {
+	    struct cookie_list_type *new;
+	    new = malloc(sizeof(cookie_list_t));
+	    new->name = col_dup(cols[5]);
+	    new->value = col_dup(cols[6]);
+	    new->path = col_dup(cols[2]);
+	    new->domain = col_dup(cols[0]);
+	    new->secure = (*(cols[3]) == 't') || (*(cols[3]) == 'T');
+	    new->next = list;
+	    list = new;
+	}
+    }
+    return list;
+}
+
+/* Attempt to load cookies.txt from various locations. Returns a pointer to the linked list contain the cookies. */
+static struct cookie_list_type *load_cookies(void)
+{
+    DIR *dir;
+    struct dirent *ent;
+    struct cookie_list_type *list = NULL;
+    char *buf;
+
+    char *homedir;
+
+    if (cookies_file)
+	return load_cookies_from(cookies_file, list);
+
+    homedir = getenv("HOME");
+    if (!homedir)
+	return list;
+
+
+    buf = malloc(strlen(homedir) + sizeof("/.mozilla/default") + 1);
+    sprintf(buf, "%s/.mozilla/default", homedir);
+    dir = opendir(buf);
+    free(buf);
+
+    if (dir) {
+	while ((ent = readdir(dir)) != NULL) {
+	    if ((ent->d_name)[0] != '.') {
+		buf = malloc(strlen(getenv("HOME")) + 
+                             sizeof("/.mozilla/default/") + 
+                             strlen(ent->d_name) + sizeof("cookies.txt") + 1);
+		sprintf(buf, "%s/.mozilla/default/%s/cookies.txt",
+			 getenv("HOME"), ent->d_name);
+		list = load_cookies_from(buf, list);
+		free(buf);
+	    }
+	}
+	closedir(dir);
+    }
+
+    buf = malloc(strlen(homedir) + sizeof("/.netscape/cookies.txt") + 1);
+    sprintf(buf, "%s/.netscape/cookies.txt", homedir);
+    list = load_cookies_from(buf, list);
+    free(buf);
+
+    return list;
+}
+
+/* Take an HTTP_header_t, and insert the correct headers. The cookie files are read if necessary. */
+void
+cookies_set(HTTP_header_t * http_hdr, const char *domain, const char *url)
+{
+    int found_cookies = 0;
+    struct cookie_list_type *cookies[MAX_COOKIES];
+    struct cookie_list_type *list, *start;
+    int i;
+    char *path;
+    char *buf;
+
+    path = strchr(url, '/');
+    if (!path)
+	path = "";
+
+    if (!cookie_list)
+	cookie_list = load_cookies();
+
+
+    list = start = cookie_list;
+
+    /* Find which cookies we want, removing duplicates. Cookies with the longest domain, then longest path take priority */
+    while (list) {
+	/* Check the cookie domain and path. Also, we never send "secure" cookies. These should only be sent over HTTPS. */
+	if ((right_hand_strcmp(list->domain, domain) == 0)
+	    && (left_hand_strcmp(list->path, path) == 0) && !list->secure) {
+	    int replacing = 0;
+	    for (i = 0; i < found_cookies; i++) {
+		if (strcmp(list->name, cookies[i]->name) == 0) {
+		    replacing = 0;
+		    if (strlen(list->domain) <= strlen(cookies[i]->domain)) {
+			cookies[i] = list;
+		    } else if (strlen(list->path) <= strlen(cookies[i]->path)) {
+			cookies[i] = list;
+		    }
+		}
+	    }
+	    if (found_cookies > MAX_COOKIES) {
+		/* Cookie jar overflow! */
+		break;
+	    }
+	    if (!replacing)
+		cookies[found_cookies++] = list;
+	}
+	list = list->next;
+    }
+
+
+    buf = strdup("Cookie:");
+
+    for (i = 0; i < found_cookies; i++) {
+	char *nbuf;
+
+	nbuf = malloc(strlen(buf) + strlen(" ") + strlen(cookies[i]->name) +
+		    strlen("=") + strlen(cookies[i]->value) + strlen(";") + 1);
+	sprintf(nbuf, "%s %s=%s;", buf, cookies[i]->name,
+		 cookies[i]->value);
+	free(buf);
+	buf = nbuf;
+    }
+
+    if (found_cookies)
+	http_set_field(http_hdr, buf);
+    else
+	free(buf);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cookies.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,16 @@
+/*
+ * HTTP Cookies
+ * Reads Netscape and Mozilla cookies.txt files
+ * 
+ * by Dave Lambley <mplayer@davel.me.uk>
+ */
+
+#ifndef __COOKIES_H
+#define __COOKIES_H
+
+#include "http.h"
+
+extern void cookies_set(HTTP_header_t * http_hdr, const char *hostname,
+			const char *url);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cue_read.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,604 @@
+//=================== VideoCD BinCue ==========================
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "stream.h"
+
+#include "cue_read.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+#define byte    unsigned char
+#define SIZERAW 2352
+#define SIZEISO_MODE1 2048
+#define SIZEISO_MODE2_RAW 2352
+#define SIZEISO_MODE2_FORM1 2048
+#define SIZEISO_MODE2_FORM2 2336
+#define AUDIO 0
+#define MODE1 1
+#define MODE2 2
+#define MODE1_2352 10
+#define MODE2_2352 20
+#define MODE1_2048 30
+#define MODE2_2336 40
+#define UNKNOWN -1
+
+static struct stream_priv_s {
+  char* filename;
+} stream_priv_dflts = {
+  NULL
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  { "string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "cue",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+static FILE* fd_cue;
+static int fd_bin = 0;
+
+static char bin_filename[256];
+
+static char cue_filename[256];
+static char bincue_path[256];
+
+
+typedef struct track
+{
+   unsigned short mode;
+   unsigned short minute;
+   unsigned short second;
+   unsigned short frame;
+
+   /* (min*60 + sec) * 75 + fps   */
+
+   unsigned long start_sector;
+
+   /* = the sizes in bytes off all tracks bevor this one */
+   /* its needed if there are mode1 tracks befor the mpeg tracks */
+   unsigned long start_offset;
+
+   /*   unsigned char num[3]; */
+} tTrack;
+
+/* max 99 tracks on a cd */
+static tTrack tracks[100];
+
+static struct cue_track_pos {
+  int track;
+  unsigned short mode;
+  unsigned short minute;
+  unsigned short second;
+  unsigned short frame;
+} cue_current_pos;
+
+/* number of tracks on the cd */
+static int nTracks = 0;
+
+/* presumes Line is preloaded with the "current" line of the file */
+static int cue_getTrackinfo(char *Line, tTrack *track)
+{
+  char inum[3];
+  char min;
+  char sec;
+  char fps;
+  int already_set = 0;
+
+  /* Get the 'mode' */
+  if (strncmp(&Line[2], "TRACK ", 6)==0)
+  {
+/*    strncpy(track->num, &Line[8], 2); track->num[2] = '\0'; */
+
+    track->mode = UNKNOWN;
+    if(strncmp(&Line[11], "AUDIO", 5)==0) track->mode = AUDIO;
+    if(strncmp(&Line[11], "MODE1/2352", 10)==0) track->mode = MODE1_2352;
+    if(strncmp(&Line[11], "MODE1/2048", 10)==0) track->mode = MODE1_2048;
+    if(strncmp(&Line[11], "MODE2/2352", 10)==0) track->mode = MODE2_2352;
+    if(strncmp(&Line[11], "MODE2/2336", 10)==0) track->mode = MODE2_2336;
+  }
+  else return(1);
+
+  /* Get the track indexes */
+  while(1) {
+    if(! fgets( Line, 256, fd_cue ) ) { break;}
+
+    if (strncmp(&Line[2], "TRACK ", 6)==0)
+    {
+      /* next track starting */
+      break;
+    }
+
+    /* Track 0 or 1, take the first an get fill the values*/
+    if (strncmp(&Line[4], "INDEX ", 6)==0)
+    {
+      /* check stuff here so if the answer is false the else stuff below won't be executed */
+      strncpy(inum, &Line[10], 2); inum[2] = '\0';
+      if ((already_set == 0) &&
+          ((strcmp(inum, "00")==0) || (strcmp(inum, "01")==0)))
+      {
+        already_set = 1;
+
+        min = ((Line[13]-'0')<<4) | (Line[14]-'0');
+        sec = ((Line[16]-'0')<<4) | (Line[17]-'0');
+        fps = ((Line[19]-'0')<<4) | (Line[20]-'0');
+
+        track->minute = (((min>>4)*10) + (min&0xf));
+        track->second = (((sec>>4)*10) + (sec&0xf));
+        track->frame  = (((fps>>4)*10) + (fps&0xf));
+      }
+    }
+    else if (strncmp(&Line[4], "PREGAP ", 7)==0) { ; /* ignore */ }
+    else if (strncmp(&Line[4], "FLAGS ", 6)==0)  { ; /* ignore */ }
+    else mp_msg (MSGT_OPEN,MSGL_INFO,
+                 MSGTR_MPDEMUX_CUEREAD_UnexpectedCuefileLine, Line);
+  }
+  return(0);
+}
+
+
+
+/* FIXME: the string operations ( strcpy,strcat ) below depend
+ * on the arrays to have the same size, thus we need to make
+ * sure the sizes are in sync.
+ */
+static int cue_find_bin (char *firstline) {
+  int i,j;
+  char s[256];
+  char t[256];
+
+  /* get the filename out of that */
+  /*                      12345 6  */
+  mp_msg (MSGT_OPEN,MSGL_INFO, "[bincue] cue_find_bin(%s)\n", firstline);
+  if (strncmp(firstline, "FILE \"",6)==0)
+  {
+    i = 0;
+    j = 0;
+    while ( firstline[6 + i] != '"')
+    {
+      bin_filename[j] = firstline[6 + i];
+
+      /* if I found a path info, than delete all bevor it */
+      switch (bin_filename[j])
+      {
+        case '\\':
+          j = 0;
+          break;
+
+        case '/':
+          j = 0;
+          break;
+
+        default:
+          j++;
+      }
+      i++;
+    }
+    bin_filename[j+1] = '\0';
+
+  }
+
+  /* now try to open that file, without path */
+  fd_bin = open (bin_filename, O_RDONLY);
+  if (fd_bin == -1)
+  {
+    mp_msg(MSGT_OPEN,MSGL_STATUS, MSGTR_MPDEMUX_CUEREAD_BinFilenameTested,
+           bin_filename);
+
+    /* now try to find it with the path of the cue file */
+    snprintf(s,sizeof( s ),"%s/%s",bincue_path,bin_filename);
+    fd_bin = open (s, O_RDONLY);
+    if (fd_bin == -1)
+    {
+      mp_msg(MSGT_OPEN,MSGL_STATUS,
+             MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
+      /* now I would say the whole filename is shit, build our own */
+      strncpy(s, cue_filename, strlen(cue_filename) - 3 );
+      s[strlen(cue_filename) - 3] = '\0';
+      strcat(s, "bin");
+      fd_bin = open (s, O_RDONLY);
+      if (fd_bin == -1)
+      {
+        mp_msg(MSGT_OPEN,MSGL_STATUS,
+               MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
+
+        /* ok try it with path */
+        snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
+        fd_bin = open (t, O_RDONLY);
+        if (fd_bin == -1)
+        {
+          mp_msg(MSGT_OPEN,MSGL_STATUS,
+                 MSGTR_MPDEMUX_CUEREAD_BinFilenameTested,t);
+          /* now I would say the whole filename is shit, build our own */
+          strncpy(s, cue_filename, strlen(cue_filename) - 3 );
+          s[strlen(cue_filename) - 3] = '\0';
+          strcat(s, "img");
+          fd_bin = open (s, O_RDONLY);
+          if (fd_bin == -1)
+          {
+            mp_msg(MSGT_OPEN,MSGL_STATUS,
+                   MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
+            /* ok try it with path */
+            snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
+            fd_bin = open (t, O_RDONLY);
+            if (fd_bin == -1)
+            {
+              mp_msg(MSGT_OPEN,MSGL_STATUS,
+                     MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
+
+              /* I'll give up */
+              mp_msg(MSGT_OPEN,MSGL_ERR,
+                     MSGTR_MPDEMUX_CUEREAD_CannotFindBinFile);
+              return -1;
+            }
+          }
+        } else strcpy(bin_filename, t);
+
+      } else strcpy(bin_filename, s);
+
+    } else strcpy(bin_filename, s);
+
+  }
+
+  mp_msg(MSGT_OPEN,MSGL_INFO,
+         MSGTR_MPDEMUX_CUEREAD_UsingBinFile, bin_filename);
+  return 0;
+}
+
+static inline int cue_msf_2_sector(int minute, int second, int frame) {
+ return frame + (second + minute * 60 ) * 75;
+}
+
+static inline int cue_get_msf(void) {
+  return cue_msf_2_sector (cue_current_pos.minute,
+                           cue_current_pos.second,
+                           cue_current_pos.frame);
+}
+
+static inline void cue_set_msf(unsigned int sect){
+  cue_current_pos.frame=sect%75;
+  sect=sect/75;
+  cue_current_pos.second=sect%60;
+  sect=sect/60;
+  cue_current_pos.minute=sect;
+}
+
+static inline int cue_mode_2_sector_size(int mode)
+{
+  switch (mode)
+  {
+    case AUDIO:      return AUDIO;
+    case MODE1_2352: return SIZERAW;
+    case MODE1_2048: return SIZEISO_MODE1;
+    case MODE2_2352: return SIZEISO_MODE2_RAW;
+    case MODE2_2336: return SIZEISO_MODE2_FORM2;
+
+    default:
+      mp_msg(MSGT_OPEN,MSGL_FATAL,
+             MSGTR_MPDEMUX_CUEREAD_UnknownModeForBinfile);
+      abort();
+  }
+
+}
+
+
+static int cue_read_cue (char *in_cue_filename)
+{
+  struct stat filestat;
+  char sLine[256];
+  unsigned int sect;
+  char *s,*t;
+  int i;
+
+  /* we have no tracks at the beginning */
+  nTracks = 0;
+
+  fd_bin = 0;
+
+  /* split the filename into a path and filename part */
+  s = strdup(in_cue_filename);
+  t = strrchr(s, '/');
+  if (t == (char *)NULL)
+     t = ".";
+  else {
+     *t = '\0';
+     t = s;
+     if (*t == '\0')
+       strcpy(t, "/");
+  }
+  
+  strlcpy(bincue_path,t,sizeof( bincue_path ));
+  mp_msg(MSGT_OPEN,MSGL_V,"dirname: %s, cuepath: %s\n", t, bincue_path);
+
+  /* no path at all? */
+  if (strcmp(bincue_path, ".") == 0) {
+    mp_msg(MSGT_OPEN,MSGL_V,"bincue_path: %s\n", bincue_path);
+    strlcpy(cue_filename,in_cue_filename,sizeof( cue_filename ));
+  } else {
+    strlcpy(cue_filename,in_cue_filename + strlen(bincue_path) + 1,
+            sizeof( cue_filename ));
+  }
+
+
+
+  /* open the cue file */
+  fd_cue = fopen (in_cue_filename, "r");
+  if (fd_cue == NULL)
+  {
+    mp_msg(MSGT_OPEN,MSGL_ERR,
+           MSGTR_MPDEMUX_CUEREAD_CannotOpenCueFile, in_cue_filename);
+    return -1;
+  }
+
+  /* read the first line and hand it to find_bin, which will
+     test more than one possible name of the file */
+
+  if(! fgets( sLine, 256, fd_cue ) )
+  {
+    mp_msg(MSGT_OPEN,MSGL_ERR,
+           MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
+    fclose (fd_cue);
+    return -1;
+  }
+
+  if (cue_find_bin(sLine)) {
+    fclose (fd_cue);
+    return -1;
+  }
+
+
+  /* now build the track list */
+  /* red the next line and call our track finder */
+  if(! fgets( sLine, 256, fd_cue ) )
+  {
+    mp_msg(MSGT_OPEN,MSGL_ERR,
+           MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
+    fclose (fd_cue);
+    return -1;
+  }
+
+  while(!feof(fd_cue))
+  {
+    if (cue_getTrackinfo(sLine, &tracks[nTracks++]) != 0)
+    {
+      mp_msg(MSGT_OPEN,MSGL_ERR,
+             MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
+      fclose (fd_cue);
+      return -1;
+    }
+  }
+
+  /* make a fake track with stands for the Lead out */
+  if (fstat (fd_bin, &filestat) == -1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,
+           MSGTR_MPDEMUX_CUEREAD_ErrGettingBinFileSize);
+    fclose (fd_cue);
+    return -1;
+  }
+
+  sect = filestat.st_size / 2352;
+
+  tracks[nTracks].frame = sect%75;
+  sect=sect/75;
+  tracks[nTracks].second = sect%60;
+  sect=sect/60;
+  tracks[nTracks].minute = sect;
+
+
+  /* let's calculate the start sectors and offsets */
+  for(i = 0; i <= nTracks; i++)
+  {
+    tracks[i].start_sector = cue_msf_2_sector(tracks[i].minute,
+                                              tracks[nTracks].second,
+                                              tracks[nTracks].frame);
+
+    /* if we're the first track we don't need to offset of the one befor */
+    if (i == 0)
+    {
+      /* was always 0 on my svcds, but who knows */
+      tracks[0].start_offset = tracks[0].start_sector *
+        cue_mode_2_sector_size(tracks[0].mode);
+    } else
+    {
+      tracks[i].start_offset = tracks[i-1].start_offset +
+        (tracks[i].start_sector - tracks[i-1].start_sector) *
+        cue_mode_2_sector_size(tracks[i-1].mode);
+    }
+  }
+
+  fclose (fd_cue);
+
+  return fd_bin;
+}
+
+
+
+
+static int cue_read_toc_entry(void) {
+
+  int track = cue_current_pos.track - 1;
+
+  /* check if its a valid track, if not return -1 */
+  if (track >= nTracks)
+    return -1;
+
+
+  switch (tracks[track].mode)
+  {
+    case AUDIO:
+      cue_current_pos.mode = AUDIO;
+      break;
+    case MODE1_2352:
+      cue_current_pos.mode = MODE1;
+      break;
+    case MODE1_2048:
+      cue_current_pos.mode = MODE1;
+      break;
+    default: /* MODE2_2352 and MODE2_2336 */
+      cue_current_pos.mode = MODE2;
+  }
+  cue_current_pos.minute = tracks[track].minute;
+  cue_current_pos.second = tracks[track].second;
+  cue_current_pos.frame = tracks[track].frame;
+
+  return 0;
+}
+
+static int cue_vcd_seek_to_track (int track){
+  cue_current_pos.track  = track;
+
+  if (cue_read_toc_entry ())
+    return -1;
+
+  return VCD_SECTOR_DATA * cue_get_msf();
+}
+
+static int cue_vcd_get_track_end (int track){
+  cue_current_pos.frame = tracks[track].frame;
+  cue_current_pos.second = tracks[track].second;
+  cue_current_pos.minute = tracks[track].minute;
+
+  return VCD_SECTOR_DATA * cue_get_msf();
+}
+
+static void cue_vcd_read_toc(void){
+  int i;
+  for (i = 0; i < nTracks; ++i) {
+
+    mp_msg(MSGT_OPEN,MSGL_INFO,
+           MSGTR_MPDEMUX_CUEREAD_InfoTrackFormat,
+           i+1,
+           tracks[i].mode,
+           tracks[i].minute,
+           tracks[i].second,
+           tracks[i].frame
+           );
+  }
+}
+
+static int cue_vcd_read(stream_t *stream, char *mem, int size) {
+  unsigned long position;
+  int track = cue_current_pos.track - 1;
+
+  position = tracks[track].start_offset +
+             (cue_msf_2_sector(cue_current_pos.minute,
+                               cue_current_pos.second,
+                               cue_current_pos.frame) -
+              tracks[track].start_sector)
+             * cue_mode_2_sector_size(tracks[track].mode);
+
+  
+  if(position >= tracks[track+1].start_offset)
+    return 0;
+
+  if(lseek(fd_bin, position+VCD_SECTOR_OFFS, SEEK_SET) == -1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_MPDEMUX_CUEREAD_UnexpectedBinFileEOF);
+    return 0;
+  }
+
+  if(read(fd_bin, mem, VCD_SECTOR_DATA) != VCD_SECTOR_DATA) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_MPDEMUX_CUEREAD_CannotReadNBytesOfPayload, VCD_SECTOR_DATA);
+    return 0;
+  }
+
+  cue_current_pos.frame++;
+  if (cue_current_pos.frame==75){
+    cue_current_pos.frame=0;
+    cue_current_pos.second++;
+    if (cue_current_pos.second==60){
+      cue_current_pos.second=0;
+      cue_current_pos.minute++;
+    }
+  }
+
+  return VCD_SECTOR_DATA;
+}
+
+static int seek(stream_t *s,off_t newpos) {
+  s->pos=newpos;
+  cue_set_msf(s->pos/VCD_SECTOR_DATA);
+  return 1;
+}
+
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+  int ret,ret2,f,track = 0;
+  char *filename = NULL, *colon = NULL;
+
+  if(mode != STREAM_READ || !p->filename) {
+    m_struct_free(&stream_opts,opts);
+    return STREAM_UNSUPORTED;
+  }
+  filename = strdup(p->filename);
+  if(!filename) {
+    m_struct_free(&stream_opts,opts);
+    return STREAM_UNSUPORTED;
+  }
+  colon = strstr(filename, ":");
+  if(colon) {
+    if(strlen(colon)>1)
+      track = atoi(colon+1);
+    *colon = 0;
+  }
+  if(!track)
+    track = 1;
+  
+  f = cue_read_cue(filename);
+  if(f < 0) {
+    m_struct_free(&stream_opts,opts);
+    return STREAM_UNSUPORTED;
+  }
+  cue_vcd_read_toc();
+  ret2=cue_vcd_get_track_end(track);
+  ret=cue_vcd_seek_to_track(track);
+  if(ret<0){ 
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");
+    return STREAM_UNSUPORTED;
+  }
+  mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_MPDEMUX_CUEREAD_CueStreamInfo_FilenameTrackTracksavail, filename, track, ret, ret2);
+
+  stream->fd = f;
+  stream->type = STREAMTYPE_VCDBINCUE;
+  stream->sector_size = VCD_SECTOR_DATA;
+  stream->flags = STREAM_READ | STREAM_SEEK_FW;
+  stream->start_pos = ret;
+  stream->end_pos = ret2;
+  stream->fill_buffer = cue_vcd_read;
+  stream->seek = seek;
+
+  free(filename);
+  m_struct_free(&stream_opts,opts);
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_cue = {
+  "CUE track",
+  "cue",
+  "Albeu",
+  "based on the code from ???",
+  open_s,
+  { "cue", NULL },
+  &stream_opts,
+  1 // Urls are an option string
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/cue_read.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,7 @@
+
+//int cue_read_cue (char *in_cue_filename);
+//int cue_vcd_seek_to_track (int track);
+//int cue_vcd_get_track_end (int track);
+//void cue_vcd_read_toc ();
+//int cue_vcd_read(char *mem);
+//inline void cue_set_msf(unsigned int sect);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/dvb_tune.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,791 @@
+/* dvbtune - tune.c
+
+   Copyright (C) Dave Chapman 2001,2002
+
+   Modified for use with MPlayer, for details see the changelog at
+   http://svn.mplayerhq.hu/mplayer/trunk/
+   $Id$
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU 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.
+   Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <error.h>
+#include <time.h>
+#include <errno.h>
+#include "config.h"
+
+#ifdef HAVE_DVB_HEAD
+	#include <linux/dvb/dmx.h>
+	#include <linux/dvb/frontend.h>
+	char* dvb_frontenddev[4]={"/dev/dvb/adapter0/frontend0","/dev/dvb/adapter1/frontend0","/dev/dvb/adapter2/frontend0","/dev/dvb/adapter3/frontend0"};
+	char* dvb_dvrdev[4]={"/dev/dvb/adapter0/dvr0","/dev/dvb/adapter1/dvr0","/dev/dvb/adapter2/dvr0","/dev/dvb/adapter3/dvr0"};
+	char* dvb_demuxdev[4]={"/dev/dvb/adapter0/demux0","/dev/dvb/adapter1/demux0","/dev/dvb/adapter2/demux0","/dev/dvb/adapter3/demux0"};
+	static char* dvb_secdev[4]={"","","",""};	//UNUSED, ONLY FOR UNIFORMITY
+#else
+	#include <ost/dmx.h>
+	#include <ost/sec.h>
+	#include <ost/frontend.h>
+	char* dvb_frontenddev[4]={"/dev/ost/frontend0","/dev/ost/frontend1","/dev/ost/frontend2","/dev/ost/frontend3"};
+	char* dvb_dvrdev[4]={"/dev/ost/dvr0","/dev/ost/dvr1","/dev/ost/dvr2","/dev/ost/dvr3"};
+	static char* dvb_secdev[4]={"/dev/ost/sec0","/dev/ost/sec1","/dev/ost/sec2","/dev/ost/sec3"};
+	char* dvb_demuxdev[4]={"/dev/ost/demux0","/dev/ost/demux1","/dev/ost/demux2","/dev/ost/demux3"};
+#endif
+
+#include "dvbin.h"
+#include "mp_msg.h"
+
+
+
+int dvb_get_tuner_type(int fe_fd)
+{
+#ifdef HAVE_DVB_HEAD
+  struct dvb_frontend_info fe_info;
+#else
+  FrontendInfo fe_info;
+#endif
+
+  int res;
+
+  res = ioctl(fe_fd, FE_GET_INFO, &fe_info);
+  if(res < 0)
+  {
+  	mp_msg(MSGT_DEMUX, MSGL_ERR, "FE_GET_INFO error: %d, FD: %d\n\n", errno, fe_fd);
+	return 0;
+  }
+
+  switch(fe_info.type)
+  {
+	case FE_OFDM:
+      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-T\n");
+	  return TUNER_TER;
+
+	case FE_QPSK:
+      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-S\n");
+	  return TUNER_SAT;
+
+	case FE_QAM:
+      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-C\n");
+	  return TUNER_CBL;
+
+#ifdef DVB_ATSC
+	case FE_ATSC:
+      mp_msg(MSGT_DEMUX, MSGL_V, "TUNER TYPE SEEMS TO BE DVB-ATSC\n");
+	  return TUNER_ATSC;
+#endif
+	default:
+	  mp_msg(MSGT_DEMUX, MSGL_ERR, "UNKNOWN TUNER TYPE\n");
+	  return 0;
+  }
+
+}
+
+int dvb_set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype);
+
+int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt, int *pids)
+{
+	int i;
+	
+	priv->fe_fd = open(dvb_frontenddev[n], O_RDWR | O_NONBLOCK);
+	if(priv->fe_fd < 0)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING FRONTEND DEVICE %s: ERRNO %d\n", dvb_frontenddev[n], errno);
+		return 0;
+	}
+#ifdef HAVE_DVB_HEAD
+    priv->sec_fd=0;
+#else
+	priv->sec_fd = open(dvb_secdev[n], O_RDWR);
+    if(priv->sec_fd < 0)
+    {
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING SEC DEVICE %s: ERRNO %d\n", dvb_secdev[n], errno);
+		close(priv->fe_fd);
+      	return 0;
+    }
+#endif
+	priv->demux_fds_cnt = 0;
+	mp_msg(MSGT_DEMUX, MSGL_V, "DVB_OPEN_DEVICES(%d)\n", demux_cnt);
+	for(i = 0; i < demux_cnt; i++)
+	{
+		priv->demux_fds[i] = open(dvb_demuxdev[n], O_RDWR | O_NONBLOCK);
+		if(priv->demux_fds[i] < 0)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING DEMUX 0: %d\n", errno);
+			return 0;
+		}
+		else
+		{
+			mp_msg(MSGT_DEMUX, MSGL_V, "OPEN(%d), file %s: FD=%d, CNT=%d\n", i, dvb_demuxdev[n], priv->demux_fds[i], priv->demux_fds_cnt);
+			priv->demux_fds_cnt++;
+		}
+	}
+
+
+	priv->dvr_fd = open(dvb_dvrdev[n], O_RDONLY| O_NONBLOCK);
+	if(priv->dvr_fd < 0)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING DVR DEVICE %s: %d\n", dvb_dvrdev[n], errno);
+		return 0;
+	}
+
+    return 1;
+}
+
+
+int dvb_fix_demuxes(dvb_priv_t *priv, int cnt, int *pids)
+{
+	int i;
+	
+	mp_msg(MSGT_DEMUX, MSGL_V, "FIX %d -> %d\n", priv->demux_fds_cnt, cnt);
+	if(priv->demux_fds_cnt >= cnt)
+	{
+		for(i = priv->demux_fds_cnt-1; i >= cnt; i--)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_V, "FIX, CLOSE fd(%d): %d\n", i, priv->demux_fds[i]);
+			close(priv->demux_fds[i]);
+		}
+		priv->demux_fds_cnt = cnt;
+	}
+	else if(priv->demux_fds_cnt < cnt)
+	{
+		for(i = priv->demux_fds_cnt; i < cnt; i++)
+		{
+			priv->demux_fds[i] = open(dvb_demuxdev[priv->card], O_RDWR | O_NONBLOCK);
+			mp_msg(MSGT_DEMUX, MSGL_V, "FIX, OPEN fd(%d): %d\n", i, priv->demux_fds[i]);
+			if(priv->demux_fds[i] < 0)
+			{
+				mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING DEMUX 0: %d\n", errno);
+				return 0;
+			}
+			else
+				priv->demux_fds_cnt++;
+		}	
+	}
+	
+	return 1;
+}
+
+int dvb_set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype)
+{
+	int i;
+	struct dmx_pes_filter_params pesFilterParams;
+
+	pesFilterParams.pid     = pid;
+	pesFilterParams.input   = DMX_IN_FRONTEND;
+	pesFilterParams.output  = DMX_OUT_TS_TAP;
+#ifdef HAVE_DVB_HEAD
+	pesFilterParams.pes_type = pestype;
+#else
+	pesFilterParams.pesType = pestype;
+#endif
+
+	pesFilterParams.flags   = DMX_IMMEDIATE_START;
+
+	errno = 0;
+	if ((i = ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams)) < 0)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR IN SETTING DMX_FILTER %i for fd %d: ERRNO: %d", pid, fd, errno);
+		return 0;
+	}
+
+	mp_msg(MSGT_DEMUX, MSGL_V, "SET PES FILTER ON PID %d to fd %d, RESULT: %d, ERRNO: %d\n", pid, fd, i, errno);
+	return 1;
+}
+
+
+int dvb_demux_stop(int fd)
+{
+	int i;
+	i = ioctl(fd, DMX_STOP);
+
+	mp_msg(MSGT_DEMUX, MSGL_DBG2, "STOPPING FD: %d, RESULT: %d\n", fd, i);
+
+	return (i==0);
+}
+
+
+int dvb_demux_start(int fd)
+{
+	int i;
+	i = ioctl(fd, DMX_START);
+
+	mp_msg(MSGT_DEMUX, MSGL_DBG2, "STARTING FD: %d, RESULT: %d\n", fd, i);
+
+	return (i==0);
+}
+
+
+static int tune_it(int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone,
+	fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate,
+	fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth,
+	fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int tmout);
+
+
+int dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, int tone,
+		fe_spectral_inversion_t specInv, fe_modulation_t modulation, fe_guard_interval_t guardInterval,
+		fe_transmit_mode_t TransmissionMode, fe_bandwidth_t bandWidth, fe_code_rate_t HP_CodeRate,
+		fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout)
+{
+	int ris;
+
+	mp_msg(MSGT_DEMUX, MSGL_INFO, "dvb_tune Freq: %lu\n", (long unsigned int) freq);
+
+		ris = tune_it(priv->fe_fd, priv->sec_fd, freq, srate, pol, tone, specInv, diseqc, modulation, HP_CodeRate, TransmissionMode, guardInterval, bandWidth, LP_CodeRate, hier, timeout);
+
+	if(ris != 0)
+		mp_msg(MSGT_DEMUX, MSGL_INFO, "dvb_tune, TUNING FAILED\n");
+
+	return (ris == 0);
+}
+
+
+#ifndef HAVE_DVB_HEAD
+static int SecGetStatus (int fd, struct secStatus *state)
+{
+    if(ioctl(fd, SEC_GET_STATUS, state) < 0)
+    {
+        mp_msg(MSGT_DEMUX, MSGL_ERR, ("SEC GET STATUS: "));
+        return -1;
+    }
+
+    switch (state->busMode)
+    {
+	case SEC_BUS_IDLE:
+    	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  IDLE (%d)\n",state->busMode);
+    	    break;
+	case SEC_BUS_BUSY:
+    	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  BUSY (%d)\n",state->busMode);
+	    break;
+        case SEC_BUS_OFF:
+	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  OFF  (%d)\n",state->busMode);
+    	    break;
+        case SEC_BUS_OVERLOAD:
+	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  OVERLOAD (%d)\n",state->busMode);
+    	    break;
+	default:
+    	    mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE:  unknown  (%d)\n",state->busMode);
+            break;
+    }
+
+    switch (state->selVolt)
+    {
+	case SEC_VOLTAGE_OFF:
+		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  OFF (%d)\n",state->selVolt);
+		break;
+	case SEC_VOLTAGE_LT:
+		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  LT  (%d)\n",state->selVolt);
+		break;
+	case SEC_VOLTAGE_13:
+		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  13  (%d)\n",state->selVolt);
+		break;
+	case SEC_VOLTAGE_13_5:
+		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  13.5 (%d)\n",state->selVolt);
+		break;
+	case SEC_VOLTAGE_18:
+		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  18 (%d)\n",state->selVolt);
+		break;
+	case SEC_VOLTAGE_18_5:
+		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  18.5 (%d)\n",state->selVolt);
+		break;
+	default:
+		mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE:  unknown (%d)\n",state->selVolt);
+		break;
+    }
+
+ 	mp_msg(MSGT_DEMUX, MSGL_V, "SEC CONT TONE: %s\n", (state->contTone == SEC_TONE_ON ? "ON" : "OFF"));
+    return 0;
+}
+
+#endif
+
+static void print_status(fe_status_t festatus)
+{
+	mp_msg(MSGT_DEMUX, MSGL_V, "FE_STATUS:");
+	if (festatus & FE_HAS_SIGNAL) mp_msg(MSGT_DEMUX, MSGL_V," FE_HAS_SIGNAL");
+#ifdef HAVE_DVB_HEAD
+	if (festatus & FE_TIMEDOUT) mp_msg(MSGT_DEMUX, MSGL_V, " FE_TIMEDOUT");
+#else
+	if (festatus & FE_HAS_POWER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_POWER");
+	if (festatus & FE_SPECTRUM_INV) mp_msg(MSGT_DEMUX, MSGL_V, " FE_SPECTRUM_INV");
+	if (festatus & FE_TUNER_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_TUNER_HAS_LOCK");
+#endif
+	if (festatus & FE_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_LOCK");
+	if (festatus & FE_HAS_CARRIER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_CARRIER");
+	if (festatus & FE_HAS_VITERBI) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_VITERBI");
+	if (festatus & FE_HAS_SYNC) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_SYNC");
+	mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+}
+
+
+#ifdef HAVE_DVB_HEAD
+static int check_status(int fd_frontend,struct dvb_frontend_parameters* feparams, int tuner_type, uint32_t base, int tmout)
+{
+	int32_t strength;
+	fe_status_t festatus;
+	struct pollfd pfd[1];
+	int ok=0, locks=0;
+	time_t tm1, tm2;
+
+	if (ioctl(fd_frontend,FE_SET_FRONTEND,feparams) < 0)
+	{
+	mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR tuning channel\n");
+	return -1;
+	}
+
+	pfd[0].fd = fd_frontend;
+	pfd[0].events = POLLPRI;
+
+	mp_msg(MSGT_DEMUX, MSGL_V, "Getting frontend status\n");
+	tm1 = tm2 = time((time_t*) NULL);
+	while(!ok)
+	{
+		festatus = 0;
+		if(poll(pfd,1,tmout*1000) > 0)
+		{
+			if (pfd[0].revents & POLLPRI)
+			{
+				if(ioctl(fd_frontend, FE_READ_STATUS, &festatus) >= 0)
+					if(festatus & FE_HAS_LOCK)
+						locks++;
+			}
+		}
+		usleep(10000);
+		tm2 = time((time_t*) NULL);
+		if((festatus & FE_TIMEDOUT) || (locks >= 2) || (tm2 - tm1 >= tmout))
+			ok = 1;
+	}
+
+	if(festatus & FE_HAS_LOCK)
+	{
+		if(ioctl(fd_frontend,FE_GET_FRONTEND,feparams) >= 0)
+		{
+		switch(tuner_type)
+		{
+			case FE_OFDM:
+			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",feparams->frequency);
+			break;
+			case FE_QPSK:
+			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",(unsigned int)((feparams->frequency)+base));
+			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",feparams->u.qpsk.symbol_rate);
+			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",feparams->u.qpsk.fec_inner);
+			mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+			break;
+			case FE_QAM:
+			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",feparams->frequency);
+			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",feparams->u.qpsk.symbol_rate);
+			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",feparams->u.qpsk.fec_inner);
+			break;
+#ifdef DVB_ATSC
+			case FE_ATSC:
+			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",feparams->frequency);
+			mp_msg(MSGT_DEMUX, MSGL_V, "        Modulation: %d\n",feparams->u.vsb.modulation);
+			break;
+#endif
+			default:
+			break;
+		}
+		}
+
+		strength=0;
+		if(ioctl(fd_frontend,FE_READ_BER,&strength) >= 0)
+		mp_msg(MSGT_DEMUX, MSGL_V, "Bit error rate: %d\n",strength);
+
+		strength=0;
+		if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0)
+		mp_msg(MSGT_DEMUX, MSGL_V, "Signal strength: %d\n",strength);
+
+		strength=0;
+		if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0)
+		mp_msg(MSGT_DEMUX, MSGL_V, "SNR: %d\n",strength);
+
+		strength=0;
+		if(ioctl(fd_frontend,FE_READ_UNCORRECTED_BLOCKS,&strength) >= 0)
+		mp_msg(MSGT_DEMUX, MSGL_V, "UNC: %d\n",strength);
+		
+		print_status(festatus);
+	}
+	else
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "Not able to lock to the signal on the given frequency, timeout: %d\n", tmout);
+		return -1;
+	}
+	return 0;
+}
+
+#else
+
+static int check_status(int fd_frontend,FrontendParameters* feparams,int tuner_type,uint32_t base, int tmout)
+{
+	int i,res;
+	int32_t strength;
+	fe_status_t festatus;
+	FrontendEvent event;
+	
+	struct pollfd pfd[1];
+
+	while(1)
+	{
+	    if(ioctl(fd_frontend, FE_GET_EVENT, &event) == -1)
+	    break;
+	}
+
+	i = 0; res = -1;
+	while ((i < 3) && (res < 0))
+	{
+		if (ioctl(fd_frontend,FE_SET_FRONTEND,feparams) < 0)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR tuning channel\n");
+			return -1;
+		}
+
+		pfd[0].fd = fd_frontend;
+		pfd[0].events = POLLIN | POLLPRI;
+
+		if(poll(pfd,1,tmout*1000) > 0)
+		{
+			if (pfd[0].revents & POLLPRI)
+			{
+				mp_msg(MSGT_DEMUX, MSGL_V, "Getting frontend event\n");
+				if ( ioctl(fd_frontend, FE_GET_EVENT, &event) < 0)
+				{
+					mp_msg(MSGT_DEMUX, MSGL_ERR, "FE_GET_EVENT");
+					return -1;
+				}
+				mp_msg(MSGT_DEMUX, MSGL_V, "Received ");
+				switch(event.type)
+				{
+					case FE_UNEXPECTED_EV:
+					mp_msg(MSGT_DEMUX, MSGL_V, "unexpected event\n");
+					res = -1;
+					break;
+
+					case FE_FAILURE_EV:
+					mp_msg(MSGT_DEMUX, MSGL_V, "failure event\n");
+					res = -1;
+					break;
+
+					case FE_COMPLETION_EV:
+					mp_msg(MSGT_DEMUX, MSGL_V, "completion event\n");
+					res = 0;
+					break;
+				}
+			}
+			i++;
+		}
+	}
+
+	if (res > 0)
+	switch (event.type)
+	{
+		case FE_UNEXPECTED_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_UNEXPECTED_EV\n");
+			break;
+		case FE_COMPLETION_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_COMPLETION_EV\n");
+			break;
+		case FE_FAILURE_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_FAILURE_EV\n");
+			break;
+	}
+
+	if (event.type == FE_COMPLETION_EV)
+	{
+		switch(tuner_type)
+		{
+			case FE_OFDM:
+			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",event.u.completionEvent.Frequency);
+			break;
+
+			case FE_QPSK:
+			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",(unsigned int)((event.u.completionEvent.Frequency)+base));
+			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",event.u.completionEvent.u.qpsk.SymbolRate);
+			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",event.u.completionEvent.u.qpsk.FEC_inner);
+			mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+			break;
+
+			case FE_QAM:
+			mp_msg(MSGT_DEMUX, MSGL_V, "Event:  Frequency: %d\n",event.u.completionEvent.Frequency);
+			mp_msg(MSGT_DEMUX, MSGL_V, "        SymbolRate: %d\n",event.u.completionEvent.u.qpsk.SymbolRate);
+			mp_msg(MSGT_DEMUX, MSGL_V, "        FEC_inner:  %d\n",event.u.completionEvent.u.qpsk.FEC_inner);
+			break;
+
+			default:
+			break;
+		}
+
+		strength=0;
+		if(ioctl(fd_frontend,FE_READ_BER,&strength) >= 0)
+		mp_msg(MSGT_DEMUX, MSGL_V, "Bit error rate: %d\n",strength);
+
+		strength=0;
+		if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0)
+		mp_msg(MSGT_DEMUX, MSGL_V, "Signal strength: %d\n",strength);
+
+		strength=0;
+		if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0)
+		mp_msg(MSGT_DEMUX, MSGL_V, "SNR: %d\n",strength);
+
+		festatus=0;
+		mp_msg(MSGT_DEMUX, MSGL_V, "FE_STATUS:");
+		
+		if(ioctl(fd_frontend,FE_READ_STATUS,&festatus) >= 0)
+		    print_status(festatus);
+		else
+		    mp_msg(MSGT_DEMUX, MSGL_ERR, " ERROR, UNABLE TO READ_STATUS");
+		    
+		mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+	}
+	else
+	{
+		mp_msg(MSGT_DEMUX, MSGL_V, "Not able to lock to the signal on the given frequency\n");
+		return -1;
+	}
+	return 0;
+}
+#endif
+
+#ifdef HAVE_DVB_HEAD
+
+static struct diseqc_cmd {
+   struct dvb_diseqc_master_cmd cmd;
+   uint32_t wait;
+};
+
+static int diseqc_send_msg(int fd, fe_sec_voltage_t v, struct diseqc_cmd *cmd,
+		     fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b)
+{
+   if(ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1)
+    return -1;
+   if(ioctl(fd, FE_SET_VOLTAGE, v) == -1)
+    return -1;
+   usleep(15 * 1000);
+   if(ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd->cmd) == -1)
+    return -1;
+   usleep(cmd->wait * 1000);
+   usleep(15 * 1000);
+   if(ioctl(fd, FE_DISEQC_SEND_BURST, b) == -1)
+    return -1;
+   usleep(15 * 1000);
+   if(ioctl(fd, FE_SET_TONE, t) == -1)
+    return -1;
+
+    return 0;
+}
+
+/* digital satellite equipment control,
+ * specification is available from http://www.eutelsat.com/
+ */
+static int do_diseqc(int secfd, int sat_no, int polv, int hi_lo)
+{
+   struct diseqc_cmd cmd =  { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
+
+   /* param: high nibble: reset bits, low nibble set bits,
+    * bits are: option, position, polarizaion, band
+    */
+   cmd.cmd.msg[3] =
+       0xf0 | (((sat_no * 4) & 0x0f) | (hi_lo ? 1 : 0) | (polv ? 0 : 2));
+
+   return diseqc_send_msg(secfd, polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18,
+		   &cmd, hi_lo ? SEC_TONE_ON : SEC_TONE_OFF,
+		   (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A);
+}
+
+#else
+
+static int do_diseqc(int secfd, int sat_no, int polv, int hi_lo)
+{
+	struct secCommand scmd;
+        struct secCmdSequence scmds;
+
+        scmds.continuousTone = (hi_lo ? SEC_TONE_ON : SEC_TONE_OFF);
+        scmds.voltage = (polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+        scmds.miniCommand = SEC_MINI_NONE;
+
+        scmd.type = SEC_CMDTYPE_DISEQC;
+        scmds.numCommands = 1;
+        scmds.commands = &scmd;
+
+        scmd.u.diseqc.addr = 0x10;
+        scmd.u.diseqc.cmd = 0x38;
+        scmd.u.diseqc.numParams = 1;
+        scmd.u.diseqc.params[0] = 0xf0 |
+                                  (((sat_no) << 2) & 0x0F) |
+				  (hi_lo ? 1 : 0) |
+                                  (polv ? 0 : 2); 
+
+        if (ioctl(secfd,SEC_SEND_SEQUENCE,&scmds) < 0)
+	{
+          mp_msg(MSGT_DEMUX, MSGL_ERR, "Error sending DisEqC");
+          return -1;
+        }
+	
+	return 0;
+}
+#endif
+
+static int tune_it(int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone,
+	fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate,
+	fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth,
+	fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout)
+{
+  int res, hi_lo, dfd;
+#ifdef HAVE_DVB_HEAD
+  struct dvb_frontend_parameters feparams;
+  struct dvb_frontend_info fe_info;
+#else
+  FrontendParameters feparams;
+  FrontendInfo fe_info;
+  struct secStatus sec_state;
+#endif
+
+
+  mp_msg(MSGT_DEMUX, MSGL_V,  "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, pol %c, tone %i, specInv, diseqc %u, fe_modulation_t modulation,fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth\n",
+	    fd_frontend, fd_sec, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc);
+
+
+  if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0))
+  {
+  	mp_msg(MSGT_DEMUX, MSGL_FATAL, "FE_GET_INFO FAILED\n");
+	return -1;
+  }
+
+
+#ifdef HAVE_DVB_HEAD
+  mp_msg(MSGT_DEMUX, MSGL_V, "Using DVB card \"%s\"\n", fe_info.name);
+#endif
+
+  switch(fe_info.type)
+  {
+    case FE_OFDM:
+#ifdef HAVE_DVB_HEAD
+      if (freq < 1000000) freq*=1000UL;
+      feparams.frequency=freq;
+      feparams.inversion=specInv;
+      feparams.u.ofdm.bandwidth=bandwidth;
+      feparams.u.ofdm.code_rate_HP=HP_CodeRate;
+      feparams.u.ofdm.code_rate_LP=LP_CodeRate;
+      feparams.u.ofdm.constellation=modulation;
+      feparams.u.ofdm.transmission_mode=TransmissionMode;
+      feparams.u.ofdm.guard_interval=guardInterval;
+      feparams.u.ofdm.hierarchy_information=hier;
+#else
+      if (freq < 1000000) freq*=1000UL;
+      feparams.Frequency=freq;
+      feparams.Inversion=specInv;
+      feparams.u.ofdm.bandWidth=bandwidth;
+      feparams.u.ofdm.HP_CodeRate=HP_CodeRate;
+      feparams.u.ofdm.LP_CodeRate=LP_CodeRate;
+      feparams.u.ofdm.Constellation=modulation;
+      feparams.u.ofdm.TransmissionMode=TransmissionMode;
+      feparams.u.ofdm.guardInterval=guardInterval;
+      feparams.u.ofdm.HierarchyInformation=hier;
+#endif
+      mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-T to %d Hz, bandwidth: %d\n",freq, bandwidth);
+      break;
+    case FE_QPSK:
+      if (freq > 2200000)
+      {
+        // this must be an absolute frequency
+        if (freq < SLOF)
+	{
+#ifdef HAVE_DVB_HEAD
+          freq = feparams.frequency=(freq-LOF1);
+#else
+          freq = feparams.Frequency=(freq-LOF1);
+#endif
+	    hi_lo = 0;
+        }
+	else
+	{
+#ifdef HAVE_DVB_HEAD
+          freq = feparams.frequency=(freq-LOF2);
+#else
+          freq = feparams.Frequency=(freq-LOF2);
+#endif
+	    hi_lo = 1;
+        }
+      }
+      else
+      {
+        // this is an L-Band frequency
+#ifdef HAVE_DVB_HEAD
+       feparams.frequency=freq;
+#else
+       feparams.Frequency=freq;
+#endif
+      }
+
+#ifdef HAVE_DVB_HEAD
+      feparams.inversion=specInv;
+      feparams.u.qpsk.symbol_rate=srate;
+      feparams.u.qpsk.fec_inner=HP_CodeRate;
+      dfd = fd_frontend;
+#else
+      feparams.Inversion=specInv;
+      feparams.u.qpsk.SymbolRate=srate;
+      feparams.u.qpsk.FEC_inner=HP_CodeRate;
+      dfd = fd_sec;
+#endif
+
+	mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-S to Freq: %u, Pol: %c Srate: %d, 22kHz: %s, LNB:  %d\n",freq,pol,srate,hi_lo ? "on" : "off", diseqc);
+
+   if(do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0)
+	mp_msg(MSGT_DEMUX, MSGL_V, "DISEQC SETTING SUCCEDED\n");
+   else
+   {
+	mp_msg(MSGT_DEMUX, MSGL_ERR, "DISEQC SETTING FAILED\n");
+	return -1;
+   }
+      break;
+    case FE_QAM:
+      mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-C to %d, srate=%d\n",freq,srate);
+#ifdef HAVE_DVB_HEAD
+      feparams.frequency=freq;
+      feparams.inversion=specInv;
+      feparams.u.qam.symbol_rate = srate;
+      feparams.u.qam.fec_inner = HP_CodeRate;
+      feparams.u.qam.modulation = modulation;
+#else
+      feparams.Frequency=freq;
+      feparams.Inversion=specInv;
+      feparams.u.qam.SymbolRate = srate;
+      feparams.u.qam.FEC_inner = HP_CodeRate;
+      feparams.u.qam.QAM = modulation;
+#endif
+      break;
+#ifdef DVB_ATSC
+    case FE_ATSC:
+      mp_msg(MSGT_DEMUX, MSGL_V, "tuning ATSC to %d, modulation=%d\n",freq,modulation);
+      feparams.frequency=freq;
+      feparams.u.vsb.modulation = modulation;
+      break;
+#endif
+    default:
+      mp_msg(MSGT_DEMUX, MSGL_V, "Unknown FE type. Aborting\n");
+      return 0;
+  }
+  usleep(100000);
+
+#ifndef HAVE_DVB_HEAD
+  if (fd_sec) SecGetStatus(fd_sec, &sec_state);
+#endif
+
+  return(check_status(fd_frontend,&feparams,fe_info.type, (hi_lo ? LOF2 : LOF1), timeout));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/dvbin.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,870 @@
+/*
+
+dvbstream
+(C) Dave Chapman <dave@dchapman.com> 2001, 2002.
+
+The latest version can be found at http://www.linuxstb.org/dvbstream
+
+Modified for use with MPlayer, for details see the changelog at
+http://svn.mplayerhq.hu/mplayer/trunk/
+$Id$
+
+Copyright notice:
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "stream.h"
+#include "demuxer.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+#include "dvbin.h"
+
+
+#define MAX_CHANNELS 8
+#define CHANNEL_LINE_LEN 256
+#define min(a, b) ((a) <= (b) ? (a) : (b))
+
+
+//TODO: CAMBIARE list_ptr e da globale a per_priv
+
+
+static struct stream_priv_s
+{
+	char *prog;
+	int card;
+	char *type;
+	int vid, aid;
+	int timeout;
+	char *file;
+}
+stream_defaults =
+{
+	"", 1, "", 0, 0, 30, NULL
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s, f)
+
+/// URL definition
+static m_option_t stream_params[] = {
+	{"prog", ST_OFF(prog), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+	{"card", ST_OFF(card), CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL},
+	{"type", ST_OFF(type), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+	{"vid",  ST_OFF(vid),  CONF_TYPE_INT, 0, 0 ,0, NULL},
+	{"aid",  ST_OFF(aid),  CONF_TYPE_INT, 0, 0 ,0, NULL},
+	{"timeout",ST_OFF(timeout),  CONF_TYPE_INT, M_OPT_RANGE, 1, 30, NULL},
+	{"file", ST_OFF(file), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+
+	{"hostname", 	ST_OFF(prog), CONF_TYPE_STRING, 0, 0, 0, NULL },
+	{"username", 	ST_OFF(card), CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL},
+	{NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+static struct m_struct_st stream_opts = {
+	"dvbin",
+	sizeof(struct stream_priv_s),
+	&stream_defaults,
+	stream_params
+};
+
+
+
+m_option_t dvbin_opts_conf[] = {
+	{"prog", &stream_defaults.prog, CONF_TYPE_STRING, 0, 0 ,0, NULL},
+	{"card", &stream_defaults.card, CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL},
+	{"type", "DVB card type is autodetected and can't be overridden\n", CONF_TYPE_PRINT, CONF_NOCFG, 0 ,0, NULL},
+	{"vid",  &stream_defaults.vid,  CONF_TYPE_INT, 0, 0 ,0, NULL},
+	{"aid",  &stream_defaults.aid,  CONF_TYPE_INT, 0, 0 ,0, NULL},
+	{"timeout",  &stream_defaults.timeout,  CONF_TYPE_INT, M_OPT_RANGE, 1, 30, NULL},
+	{"file", &stream_defaults.file, CONF_TYPE_STRING, 0, 0 ,0, NULL},
+
+	{NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+
+
+
+extern int dvb_set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype);
+extern int dvb_demux_stop(int fd);
+extern int dvb_get_tuner_type(int fd);
+int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt, int *pids);
+int dvb_fix_demuxes(dvb_priv_t *priv, int cnt, int *pids);
+
+extern int dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, int tone,
+		fe_spectral_inversion_t specInv, fe_modulation_t modulation, fe_guard_interval_t guardInterval,
+		fe_transmit_mode_t TransmissionMode, fe_bandwidth_t bandWidth, fe_code_rate_t HP_CodeRate,
+		fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout);
+extern char *dvb_dvrdev[4], *dvb_demuxdev[4], *dvb_frontenddev[4];
+
+static dvb_config_t *dvb_config = NULL;
+
+
+static dvb_channels_list *dvb_get_channels(char *filename, int type)
+{
+	dvb_channels_list  *list;
+	FILE *f;
+	char line[CHANNEL_LINE_LEN], *colon;
+
+	int fields, cnt, pcnt, k;
+	dvb_channel_t *ptr, *tmp, chn;
+	char tmp_lcr[256], tmp_hier[256], inv[256], bw[256], cr[256], mod[256], transm[256], gi[256], vpid_str[256], apid_str[256];
+	const char *cbl_conf = "%d:%255[^:]:%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
+	const char *sat_conf = "%d:%c:%d:%d:%255[^:]:%255[^:]\n";
+	const char *ter_conf = "%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
+	const char *atsc_conf = "%d:%255[^:]:%255[^:]:%255[^:]\n";
+	
+	mp_msg(MSGT_DEMUX, MSGL_V, "CONFIG_READ FILE: %s, type: %d\n", filename, type);
+	if((f=fopen(filename, "r"))==NULL)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_FATAL, "CAN'T READ CONFIG FILE %s\n", filename);
+		return NULL;
+	}
+
+	list = malloc(sizeof(dvb_channels_list));
+	if(list == NULL)
+	{
+		fclose(f);
+		mp_msg(MSGT_DEMUX, MSGL_V, "DVB_GET_CHANNELS: couldn't malloc enough memory\n");
+		return NULL;
+	}
+
+	ptr = &chn;
+	list->NUM_CHANNELS = 0;
+	list->channels = NULL;
+	while(! feof(f))
+	{
+		if( fgets(line, CHANNEL_LINE_LEN, f) == NULL )
+			continue;
+
+		if((line[0] == '#') || (strlen(line) == 0))
+			continue;
+
+		colon = index(line, ':');
+		if(colon)
+		{
+			k = colon - line;
+			if(!k)
+				continue;
+			ptr->name = (char*) malloc(k+1);
+			if(! ptr->name)
+				continue;
+			strncpy(ptr->name, line, k);
+			ptr->name[k] = 0;
+		}
+		else
+			continue;
+		k++;
+		apid_str[0] = vpid_str[0] = 0;
+		ptr->pids_cnt = 0;
+		ptr->freq = 0;
+		if(type == TUNER_TER)
+		{
+			fields = sscanf(&line[k], ter_conf,
+				&ptr->freq, inv, bw, cr, tmp_lcr, mod,
+				transm, gi, tmp_hier, vpid_str, apid_str);
+			mp_msg(MSGT_DEMUX, MSGL_V,
+				"TER, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d",
+				list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
+		}
+		else if(type == TUNER_CBL)
+		{
+			fields = sscanf(&line[k], cbl_conf,
+				&ptr->freq, inv, &ptr->srate,
+				cr, mod, vpid_str, apid_str);
+			mp_msg(MSGT_DEMUX, MSGL_V,
+				"CBL, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, SRATE: %d",
+				list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate);
+		}
+#ifdef DVB_ATSC
+		else if(type == TUNER_ATSC)
+		{
+			fields = sscanf(&line[k], atsc_conf,
+				 &ptr->freq, mod, vpid_str, apid_str);
+			mp_msg(MSGT_DEMUX, MSGL_V,
+				"ATSC, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d\n",
+				list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
+		}
+#endif
+		else //SATELLITE
+		{
+			fields = sscanf(&line[k], sat_conf,
+				&ptr->freq, &ptr->pol, &ptr->diseqc, &ptr->srate, vpid_str, apid_str);
+			ptr->pol = toupper(ptr->pol);
+			ptr->freq *=  1000UL;
+			ptr->srate *=  1000UL;
+			ptr->tone = -1;
+			ptr->inv = INVERSION_AUTO;
+			ptr->cr = FEC_AUTO;
+			if((ptr->diseqc > 4) || (ptr->diseqc < 0))
+			    continue;
+			if(ptr->diseqc > 0)
+			    ptr->diseqc--;
+			mp_msg(MSGT_DEMUX, MSGL_V,
+				"SAT, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, SRATE: %d, POL: %c, DISEQC: %d",
+				list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate, ptr->pol, ptr->diseqc);
+		}
+
+		if(vpid_str[0])
+		{
+			pcnt = sscanf(vpid_str, "%d+%d+%d+%d+%d+%d+%d", &ptr->pids[0], &ptr->pids[1], &ptr->pids[2], &ptr->pids[3],
+				&ptr->pids[4], &ptr->pids[5], &ptr->pids[6]);
+			if(pcnt > 0)
+			{
+				ptr->pids_cnt = pcnt;
+				fields++;
+			}
+		}
+		
+		if(apid_str[0])
+		{
+			cnt = ptr->pids_cnt;
+			pcnt = sscanf(apid_str, "%d+%d+%d+%d+%d+%d+%d+%d", &ptr->pids[cnt], &ptr->pids[cnt+1], &ptr->pids[cnt+2],
+				&ptr->pids[cnt+3], &ptr->pids[cnt+4], &ptr->pids[cnt+5], &ptr->pids[cnt+6], &ptr->pids[cnt+7]);
+			if(pcnt > 0)
+			{
+				ptr->pids_cnt += pcnt;
+				fields++;
+			}
+		}
+
+		if((fields < 2) || (ptr->pids_cnt <= 0) || (ptr->freq == 0) || (strlen(ptr->name) == 0))
+			continue;
+
+
+		ptr->pids[ptr->pids_cnt] = 0;	//PID 0 is the PAT
+		ptr->pids_cnt++;
+		mp_msg(MSGT_DEMUX, MSGL_V, " PIDS: ");
+		for(cnt = 0; cnt < ptr->pids_cnt; cnt++)
+			mp_msg(MSGT_DEMUX, MSGL_V, " %d ", ptr->pids[cnt]);
+		mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+		
+		if((type == TUNER_TER) || (type == TUNER_CBL))
+		{
+			if(! strcmp(inv, "INVERSION_ON"))
+				ptr->inv = INVERSION_ON;
+			else if(! strcmp(inv, "INVERSION_OFF"))
+				ptr->inv = INVERSION_OFF;
+			else
+				ptr->inv = INVERSION_AUTO;
+
+
+			if(! strcmp(cr, "FEC_1_2"))
+				ptr->cr =FEC_1_2;
+			else if(! strcmp(cr, "FEC_2_3"))
+				ptr->cr =FEC_2_3;
+			else if(! strcmp(cr, "FEC_3_4"))
+				ptr->cr =FEC_3_4;
+#ifdef HAVE_DVB_HEAD
+			else if(! strcmp(cr, "FEC_4_5"))
+				ptr->cr =FEC_4_5;
+			else if(! strcmp(cr, "FEC_6_7"))
+				ptr->cr =FEC_6_7;
+			else if(! strcmp(cr, "FEC_8_9"))
+				ptr->cr =FEC_8_9;
+#endif
+			else if(! strcmp(cr, "FEC_5_6"))
+				ptr->cr =FEC_5_6;
+			else if(! strcmp(cr, "FEC_7_8"))
+				ptr->cr =FEC_7_8;
+			else if(! strcmp(cr, "FEC_NONE"))
+				ptr->cr =FEC_NONE;
+			else ptr->cr =FEC_AUTO;
+		}
+	
+
+		if((type == TUNER_TER) || (type == TUNER_CBL) || (type == TUNER_ATSC))
+		{
+			if(! strcmp(mod, "QAM_128"))
+				ptr->mod = QAM_128;
+			else if(! strcmp(mod, "QAM_256"))
+				ptr->mod = QAM_256;
+			else if(! strcmp(mod, "QAM_64"))
+				ptr->mod = QAM_64;
+			else if(! strcmp(mod, "QAM_32"))
+				ptr->mod = QAM_32;
+			else if(! strcmp(mod, "QAM_16"))
+				ptr->mod = QAM_16;
+#ifdef DVB_ATSC	
+			else if(! strcmp(mod, "VSB_8") || ! strcmp(mod, "8VSB"))
+				ptr->mod = VSB_8;
+			else if(! strcmp(mod, "VSB_16") || !strcmp(mod, "16VSB"))
+				ptr->mod = VSB_16;
+
+			ptr->inv = INVERSION_AUTO;
+#endif
+		}
+
+		if(type == TUNER_TER)
+		{
+			if(! strcmp(bw, "BANDWIDTH_6_MHZ"))
+				ptr->bw = BANDWIDTH_6_MHZ;
+			else if(! strcmp(bw, "BANDWIDTH_7_MHZ"))
+				ptr->bw = BANDWIDTH_7_MHZ;
+			else if(! strcmp(bw, "BANDWIDTH_8_MHZ"))
+				ptr->bw = BANDWIDTH_8_MHZ;
+
+
+			if(! strcmp(transm, "TRANSMISSION_MODE_2K"))
+				ptr->trans = TRANSMISSION_MODE_2K;
+			else if(! strcmp(transm, "TRANSMISSION_MODE_8K"))
+				ptr->trans = TRANSMISSION_MODE_8K;
+
+
+			if(! strcmp(gi, "GUARD_INTERVAL_1_32"))
+				ptr->gi = GUARD_INTERVAL_1_32;
+			else if(! strcmp(gi, "GUARD_INTERVAL_1_16"))
+				ptr->gi = GUARD_INTERVAL_1_16;
+			else if(! strcmp(gi, "GUARD_INTERVAL_1_8"))
+				ptr->gi = GUARD_INTERVAL_1_8;
+			else ptr->gi = GUARD_INTERVAL_1_4;
+			
+			if(! strcmp(tmp_lcr, "FEC_1_2"))
+				ptr->cr_lp =FEC_1_2;
+			else if(! strcmp(tmp_lcr, "FEC_2_3"))
+				ptr->cr_lp =FEC_2_3;
+			else if(! strcmp(tmp_lcr, "FEC_3_4"))
+				ptr->cr_lp =FEC_3_4;
+#ifdef HAVE_DVB_HEAD
+			else if(! strcmp(tmp_lcr, "FEC_4_5"))
+				ptr->cr_lp =FEC_4_5;
+			else if(! strcmp(tmp_lcr, "FEC_6_7"))
+				ptr->cr_lp =FEC_6_7;
+			else if(! strcmp(tmp_lcr, "FEC_8_9"))
+				ptr->cr_lp =FEC_8_9;
+#endif
+			else if(! strcmp(tmp_lcr, "FEC_5_6"))
+				ptr->cr_lp =FEC_5_6;
+			else if(! strcmp(tmp_lcr, "FEC_7_8"))
+				ptr->cr_lp =FEC_7_8;
+			else if(! strcmp(tmp_lcr, "FEC_NONE"))
+				ptr->cr_lp =FEC_NONE;
+			else ptr->cr_lp =FEC_AUTO;
+			
+			
+			if(! strcmp(tmp_hier, "HIERARCHY_1"))
+				ptr->hier = HIERARCHY_1;
+			else if(! strcmp(tmp_hier, "HIERARCHY_2"))
+				ptr->hier = HIERARCHY_2;
+			else if(! strcmp(tmp_hier, "HIERARCHY_4"))
+				ptr->hier = HIERARCHY_4;
+#ifdef HAVE_DVB_HEAD				
+			else if(! strcmp(tmp_hier, "HIERARCHY_AUTO"))
+				ptr->hier = HIERARCHY_AUTO;
+#endif
+			else	ptr->hier = HIERARCHY_NONE;
+		}
+
+		tmp = (dvb_channel_t*)realloc(list->channels, sizeof(dvb_channel_t) * (list->NUM_CHANNELS + 1));
+		if(tmp == NULL)
+			break;
+
+		list->channels = tmp;
+		memcpy(&(list->channels[list->NUM_CHANNELS]), ptr, sizeof(dvb_channel_t));
+		list->NUM_CHANNELS++;
+		if(sizeof(dvb_channel_t) * list->NUM_CHANNELS >= 1024*1024)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_V, "dvbin.c, > 1MB allocated for channels struct, dropping the rest of the file\r\n");
+			break;
+		}
+	}
+
+	fclose(f);
+	if(list->NUM_CHANNELS == 0)
+	{
+		if(list->channels != NULL)
+			free(list->channels);
+		free(list);
+		return NULL;
+	}
+
+	list->current = 0;
+	return list;
+}
+
+
+
+static int dvb_streaming_read(stream_t *stream, char *buffer, int size)
+{
+	struct pollfd pfds[1];
+	int pos=0, tries, rk, fd;
+	dvb_priv_t *priv  = (dvb_priv_t *) stream->priv;
+
+	mp_msg(MSGT_DEMUX, MSGL_DBG3, "dvb_streaming_read(%d)\n", size);
+
+	tries = priv->retry + 1;
+	
+	fd = stream->fd;
+	while(pos < size)
+	{
+		pfds[0].fd = fd;
+		pfds[0].events = POLLIN | POLLPRI;
+
+		rk = size - pos;
+		if(poll(pfds, 1, 500) <= 0)
+		{
+			errno = 0;
+			mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_streaming_read, attempt N. %d failed with errno %d when reading %d bytes\n", tries, errno, size-pos);
+			if(--tries > 0)
+				continue;
+			else
+				break;
+		}
+		if((rk = read(fd, &buffer[pos], rk)) > 0)
+		{
+			pos += rk;
+			mp_msg(MSGT_DEMUX, MSGL_DBG3, "ret (%d) bytes\n", pos);
+		}
+	}
+		
+
+	if(! pos)
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_streaming_read, return %d bytes\n", pos);
+
+	return pos;
+}
+
+static void dvbin_close(stream_t *stream);
+
+int dvb_set_channel(dvb_priv_t *priv, int card, int n)
+{
+	dvb_channels_list *new_list;
+	dvb_channel_t *channel;
+	int do_tuning;
+	stream_t *stream  = (stream_t*) priv->stream;
+	char buf[4096];
+	dvb_config_t *conf = (dvb_config_t *) priv->config;
+	int devno;
+	int i;
+
+	if((card < 0) || (card > conf->count))
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_set_channel: INVALID CARD NUMBER: %d vs %d, abort\n", card, conf->count);
+		return 0;
+	}
+	
+	devno = conf->cards[card].devno;
+	new_list = conf->cards[card].list;
+	if((n > new_list->NUM_CHANNELS) || (n < 0))
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_set_channel: INVALID CHANNEL NUMBER: %d, for card %d, abort\n", n, card);
+		return 0;
+	}
+	channel = &(new_list->channels[n]);
+	
+	if(priv->is_on)	//the fds are already open and we have to stop the demuxers
+	{
+		for(i = 0; i < priv->demux_fds_cnt; i++)
+			dvb_demux_stop(priv->demux_fds[i]);
+			
+		priv->retry = 0;
+		while(dvb_streaming_read(stream, buf, 4096) > 0);	//empty both the stream's and driver's buffer
+		if(priv->card != card)
+		{
+			dvbin_close(stream);
+			if(! dvb_open_devices(priv, devno, channel->pids_cnt, channel->pids))
+			{
+				mp_msg(MSGT_DEMUX, MSGL_ERR, "DVB_SET_CHANNEL, COULDN'T OPEN DEVICES OF CARD: %d, EXIT\n", card);
+				return 0;
+			}
+			strcpy(priv->prev_tuning, "");
+		}
+		else	//close all demux_fds with pos > pids required for the new channel or open other demux_fds if we have too few
+		{	
+			if(! dvb_fix_demuxes(priv, channel->pids_cnt, channel->pids))
+				return 0;
+		}
+	}
+	else
+	{
+		if(! dvb_open_devices(priv, devno, channel->pids_cnt, channel->pids))
+		{
+			mp_msg(MSGT_DEMUX, MSGL_ERR, "DVB_SET_CHANNEL2, COULDN'T OPEN DEVICES OF CARD: %d, EXIT\n", card);
+			return 0;
+		}
+		strcpy(priv->prev_tuning, "");
+	}
+
+	dvb_config->priv = priv;
+	priv->card = card;
+	priv->list = new_list;
+	priv->retry = 5;
+	new_list->current = n;
+	stream->fd = priv->dvr_fd;
+	mp_msg(MSGT_DEMUX, MSGL_V, "DVB_SET_CHANNEL: new channel name=%s, card: %d, channel %d\n", channel->name, card, n);
+
+	switch(priv->tuner_type)
+	{
+		case TUNER_SAT:
+			sprintf(priv->new_tuning, "%d|%09d|%09d|%d|%c", priv->card, channel->freq, channel->srate, channel->diseqc, channel->pol);
+			break;
+
+		case TUNER_TER:
+			sprintf(priv->new_tuning, "%d|%09d|%d|%d|%d|%d|%d|%d", priv->card, channel->freq, channel->inv,
+				channel->bw, channel->cr, channel->mod, channel->trans, channel->gi);
+		  break;
+
+		case TUNER_CBL:
+			sprintf(priv->new_tuning, "%d|%09d|%d|%d|%d|%d", priv->card, channel->freq, channel->inv, channel->srate,
+				channel->cr, channel->mod);
+		break;
+#ifdef DVB_ATSC
+		case TUNER_ATSC:
+			sprintf(priv->new_tuning, "%d|%09d|%d", priv->card, channel->freq, channel->mod);
+		break;
+#endif
+	}
+
+
+
+	if(strcmp(priv->prev_tuning, priv->new_tuning))
+	{
+		mp_msg(MSGT_DEMUX, MSGL_V, "DIFFERENT TUNING THAN THE PREVIOUS: %s  -> %s\n", priv->prev_tuning, priv->new_tuning);
+		strcpy(priv->prev_tuning, priv->new_tuning);
+		do_tuning = 1;
+	}
+	else
+	{
+		mp_msg(MSGT_DEMUX, MSGL_V, "SAME TUNING PARAMETERS, NO TUNING\n");
+		do_tuning = 0;
+	}
+
+	stream->eof=1;
+	stream_reset(stream);
+
+
+	if(do_tuning)
+		if (! dvb_tune(priv, channel->freq, channel->pol, channel->srate, channel->diseqc, channel->tone,
+			channel->inv, channel->mod, channel->gi, channel->trans, channel->bw, channel->cr, channel->cr_lp, channel->hier, priv->timeout))
+			return 0;
+
+
+	priv->is_on = 1;
+
+	//sets demux filters and restart the stream
+	for(i = 0; i < channel->pids_cnt; i++)
+	{
+		if(! dvb_set_ts_filt(priv->demux_fds[i], channel->pids[i], DMX_PES_OTHER))
+			return 0;
+	}
+	
+	return 1;
+}
+
+
+
+int dvb_step_channel(dvb_priv_t *priv, int dir)
+{
+	int new_current;
+	dvb_channels_list *list;
+
+	mp_msg(MSGT_DEMUX, MSGL_V, "DVB_STEP_CHANNEL dir %d\n", dir);
+
+	if(priv == NULL)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_step_channel: NULL priv_ptr, quit\n");
+		return 0;
+	}
+
+	list = priv->list;
+	if(list == NULL)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_step_channel: NULL list_ptr, quit\n");
+		return 0;
+	}
+
+	new_current = (list->NUM_CHANNELS + list->current + (dir == DVB_CHANNEL_HIGHER ? 1 : -1)) % list->NUM_CHANNELS;
+
+	return dvb_set_channel(priv, priv->card, new_current);
+}
+
+
+
+
+extern char *get_path(const char *);
+
+static void dvbin_close(stream_t *stream)
+{
+	int i;
+	dvb_priv_t *priv  = (dvb_priv_t *) stream->priv;
+
+	for(i = priv->demux_fds_cnt-1; i >= 0; i--)
+	{
+		priv->demux_fds_cnt--;
+		mp_msg(MSGT_DEMUX, MSGL_V, "DVBIN_CLOSE, close(%d), fd=%d, COUNT=%d\n", i, priv->demux_fds[i], priv->demux_fds_cnt);
+		close(priv->demux_fds[i]);
+	}
+	close(priv->dvr_fd);
+
+	close(priv->fe_fd);
+#ifdef HAVE_DVB
+	close(priv->sec_fd);
+#endif
+
+	priv->is_on = 0;
+	dvb_config->priv = NULL;
+}
+
+
+static int dvb_streaming_start(dvb_priv_t *priv, struct stream_priv_s *opts, int tuner_type, char *progname)
+{
+	int i;
+	dvb_channel_t *channel = NULL;
+	stream_t *stream  = (stream_t*) priv->stream;
+
+	mp_msg(MSGT_DEMUX, MSGL_V, "\r\ndvb_streaming_start(PROG: %s, CARD: %d, VID: %d, AID: %d, TYPE: %s, FILE: %s)\r\n",
+	    opts->prog, opts->card, opts->vid, opts->aid,  opts->type, opts->file);
+
+	priv->is_on = 0;
+
+	i = 0;
+	while((channel == NULL) && i < priv->list->NUM_CHANNELS)
+	{
+		if(! strcmp(priv->list->channels[i].name, progname))
+			channel = &(priv->list->channels[i]);
+
+		i++;
+	}
+
+	if(channel != NULL)
+	{
+		priv->list->current = i-1;
+		mp_msg(MSGT_DEMUX, MSGL_V, "PROGRAM NUMBER %d: name=%s, freq=%u\n", i-1, channel->name, channel->freq);
+	}
+	else
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "\n\nDVBIN: no such channel \"%s\"\n\n", progname);
+		return 0;
+	}
+
+
+	strcpy(priv->prev_tuning, "");
+	if(!dvb_set_channel(priv, priv->card, priv->list->current))
+	{
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR, COULDN'T SET CHANNEL  %i: ", priv->list->current);
+		dvbin_close(stream);
+		return 0;
+	}
+
+	mp_msg(MSGT_DEMUX, MSGL_V,  "SUCCESSFUL EXIT from dvb_streaming_start\n");
+
+	return 1;
+}
+
+
+
+
+static int dvb_open(stream_t *stream, int mode, void *opts, int *file_format)
+{
+	// I don't force  the file format bacause, although it's almost always TS,
+	// there are some providers that stream an IP multicast with M$ Mpeg4 inside
+	struct stream_priv_s* p = (struct stream_priv_s*)opts;
+	dvb_priv_t *priv;
+	char *progname;
+	int tuner_type = 0;
+
+
+	if(mode != STREAM_READ)
+		return STREAM_UNSUPORTED;
+
+	stream->priv = (dvb_priv_t*) malloc(sizeof(dvb_priv_t));
+	if(stream->priv ==  NULL)
+		return STREAM_ERROR;
+
+	priv = (dvb_priv_t *)stream->priv;
+	priv->stream = stream;
+	dvb_config = dvb_get_config();
+	if(dvb_config == NULL)
+	{
+		free(priv);
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "DVB CONFIGURATION IS EMPTY, exit\n");
+		return STREAM_ERROR;
+	}
+	dvb_config->priv = priv;
+	priv->config = dvb_config;
+
+	if(p->card < 1 || p->card > priv->config->count)
+ 	{
+		free(priv);
+		mp_msg(MSGT_DEMUX, MSGL_ERR, "NO CONFIGURATION FOUND FOR CARD N. %d, exit\n", p->card);
+ 		return STREAM_ERROR;
+ 	}
+	priv->card = p->card - 1;
+	priv->timeout = p->timeout;
+	
+	tuner_type = priv->config->cards[priv->card].type;
+
+	if(tuner_type == 0)
+	{
+		free(priv);
+		mp_msg(MSGT_DEMUX, MSGL_V, "OPEN_DVB: UNKNOWN OR UNDETECTABLE TUNER TYPE, EXIT\n");
+		return STREAM_ERROR;
+	}
+
+
+	priv->tuner_type = tuner_type;
+
+	mp_msg(MSGT_DEMUX, MSGL_V, "OPEN_DVB: prog=%s, card=%d, type=%d, vid=%d, aid=%d\n",
+		p->prog, priv->card+1, priv->tuner_type, p->vid, p->aid);
+
+	priv->list = priv->config->cards[priv->card].list;
+	
+	if((! strcmp(p->prog, "")) && (priv->list != NULL))
+		progname = priv->list->channels[0].name;
+	else
+		progname = p->prog;
+
+
+	if(! dvb_streaming_start(priv, p, tuner_type, progname))
+	{
+		free(stream->priv);
+		stream->priv = NULL;
+		return STREAM_ERROR;
+	}
+
+	stream->type = STREAMTYPE_DVB;
+	stream->fill_buffer = dvb_streaming_read;
+	stream->close = dvbin_close;
+	m_struct_free(&stream_opts, opts);
+	
+	*file_format = DEMUXER_TYPE_MPEG_TS;
+
+	return STREAM_OK;
+}
+
+#define MAX_CARDS 4
+dvb_config_t *dvb_get_config(void)
+{
+	int i, fd, type, size;
+	char filename[30], *conf_file, *name;
+	dvb_channels_list *list;
+	dvb_card_config_t *cards = NULL, *tmp;
+	dvb_config_t *conf = NULL;
+	
+	if(dvb_config != NULL)
+		return dvb_config;
+			
+	conf = (dvb_config_t*) malloc(sizeof(dvb_config_t));
+	if(conf == NULL)
+		return NULL;
+
+	conf->priv = NULL;	
+	conf->count = 0;
+	conf->cards = NULL;
+	for(i=0; i<MAX_CARDS; i++)
+	{
+		sprintf(filename, "/dev/dvb/adapter%d/frontend0", i);
+		fd = open(filename, O_RDWR | O_NONBLOCK);
+		if(fd < 0)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_V, "DVB_CONFIG, can't open device %s, skipping\n", filename);
+			continue;
+		}
+			
+		type = dvb_get_tuner_type(fd);
+		close(fd);
+		if(type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL && type != TUNER_ATSC)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_V, "DVB_CONFIG, can't detect tuner type of card %d, skipping\n", i);
+			continue;
+		}
+		
+		switch(type)
+		{
+			case TUNER_TER:
+			conf_file = get_path("channels.conf.ter");
+				break;
+			case TUNER_CBL:
+			conf_file = get_path("channels.conf.cbl");
+				break;
+			case TUNER_SAT:
+			conf_file = get_path("channels.conf.sat");
+				break;
+			case TUNER_ATSC:
+			conf_file = get_path("channels.conf.atsc");
+				break;
+		}
+		
+		if((access(conf_file, F_OK | R_OK) != 0))
+			conf_file = get_path("channels.conf");
+
+		list = dvb_get_channels(conf_file, type);
+		if(list == NULL)
+			continue;
+		
+		size = sizeof(dvb_card_config_t) * (conf->count + 1);
+		tmp = realloc(conf->cards, size);
+
+		if(tmp == NULL)
+		{
+			fprintf(stderr, "DVB_CONFIG, can't realloc %d bytes, skipping\n", size);
+			continue;
+		}
+		cards = tmp;
+
+		name = (char*) malloc(20);
+		if(name==NULL)
+		{
+			fprintf(stderr, "DVB_CONFIG, can't realloc 20 bytes, skipping\n");
+			continue;
+		}
+
+		conf->cards = cards;
+		conf->cards[conf->count].devno = i;
+		conf->cards[conf->count].list = list;
+		conf->cards[conf->count].type = type;
+		sprintf(name, "DVB-%c card n. %d", type==TUNER_TER ? 'T' : (type==TUNER_CBL ? 'C' : 'S'), conf->count+1);
+		conf->cards[conf->count].name = name;
+		conf->count++;
+	}
+
+	if(conf->count == 0)
+	{
+		free(conf);
+		conf = NULL;
+	}
+
+	dvb_config = conf;
+	return conf;
+}
+
+
+
+stream_info_t stream_info_dvb = {
+	"Dvb Input",
+	"dvbin",
+	"Nico",
+	"based on the code from ??? (probably Arpi)",
+	dvb_open, 			
+	{ "dvb", NULL },
+	&stream_opts,
+	1 				// Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/dvbin.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,118 @@
+/* Imported from the dvbstream project
+ *
+ * Modified for use with MPlayer, for details see the changelog at
+ * http://svn.mplayerhq.hu/mplayer/trunk/
+ * $Id$
+ */
+
+#ifndef DVBIN_H
+#define DVBIN_H
+
+#include "stream.h"
+
+#define SLOF (11700*1000UL)
+#define LOF1 (9750*1000UL)
+#define LOF2 (10600*1000UL)
+
+#ifdef HAVE_DVB_HEAD
+	#include <linux/dvb/dmx.h>
+	#include <linux/dvb/frontend.h>
+	#include <linux/dvb/version.h>
+#else
+	#include <ost/dmx.h>
+	#include <ost/sec.h>
+	#include <ost/frontend.h>
+	#define fe_status_t FrontendStatus
+	#define fe_spectral_inversion_t SpectralInversion
+	#define fe_modulation_t Modulation
+	#define fe_code_rate_t CodeRate
+	#define fe_transmit_mode_t TransmitMode
+	#define fe_guard_interval_t GuardInterval
+	#define fe_bandwidth_t BandWidth
+	#define fe_hierarchy_t Hierarchy
+	#define fe_sec_voltage_t SecVoltage
+	#define dmx_pes_filter_params dmxPesFilterParams
+	#define dmx_sct_filter_params dmxSctFilterParams
+	#define dmx_pes_type_t dmxPesType_t
+#endif
+
+#undef DVB_ATSC
+#if defined(DVB_API_VERSION_MINOR)
+#if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR >= 1
+#define DVB_ATSC 1
+#endif
+#endif
+
+
+#define DVB_CHANNEL_LOWER -1
+#define DVB_CHANNEL_HIGHER 1
+
+#include "inttypes.h"
+
+#ifndef DMX_FILTER_SIZE
+#define DMX_FILTER_SIZE 16
+#endif
+
+typedef struct {
+	char 				*name;
+	int 				freq, srate, diseqc, tone;
+	char 				pol;
+	int 				tpid, dpid1, dpid2, progid, ca, pids[DMX_FILTER_SIZE], pids_cnt;
+	fe_spectral_inversion_t 	inv;
+	fe_modulation_t 		mod;
+	fe_transmit_mode_t 		trans;
+	fe_bandwidth_t 			bw;
+	fe_guard_interval_t 		gi;
+	fe_code_rate_t 			cr, cr_lp;
+	fe_hierarchy_t			hier;
+} dvb_channel_t;
+
+
+typedef struct {
+	uint16_t NUM_CHANNELS;
+	uint16_t current;
+	dvb_channel_t *channels;
+} dvb_channels_list;
+
+typedef struct {
+	int type;
+	dvb_channels_list *list;
+	char *name;
+	int devno;
+} dvb_card_config_t;
+
+typedef struct {
+	int count;
+	dvb_card_config_t *cards;
+	void *priv;
+} dvb_config_t;
+
+
+typedef struct {
+	int card;
+    int fe_fd;
+    int sec_fd;
+    int demux_fd[3], demux_fds[DMX_FILTER_SIZE], demux_fds_cnt;
+    int dvr_fd;
+
+    dvb_config_t *config;
+    dvb_channels_list *list;
+	int tuner_type;
+	int is_on;
+	stream_t *stream;
+	char new_tuning[256], prev_tuning[256];
+	int retry;
+	int timeout;
+} dvb_priv_t;
+
+
+#define TUNER_SAT	1
+#define TUNER_TER	2
+#define TUNER_CBL	3
+#define TUNER_ATSC	4
+
+extern int dvb_step_channel(dvb_priv_t *, int);
+extern int dvb_set_channel(dvb_priv_t *, int, int);
+extern dvb_config_t *dvb_get_config(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/dvdnav_stream.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,396 @@
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include "mp_msg.h"
+#include "osdep/timer.h"
+#include "input/input.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "dvdnav_stream.h"
+#include "libvo/video_out.h"
+#include "spudec.h"
+#include "m_option.h"
+#include "m_struct.h"
+#include "help_mp.h"
+
+extern char *dvd_device;
+extern char *audio_lang, *dvdsub_lang;
+
+static struct stream_priv_s {
+  int track;
+  char* device;
+} stream_priv_dflts = {
+  1,
+  NULL
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  {"filename", 	ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
+  {"hostname", 	ST_OFF(track), CONF_TYPE_INT, 0, 0, 0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "dvd",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+int dvd_nav_skip_opening=0;     /* skip opening stalls? */
+int osd_show_dvd_nav_delay=0;   /* count down for dvd nav text on OSD */
+char dvd_nav_text[50];          /* for reporting stuff to OSD */
+int osd_show_dvd_nav_highlight; /* show highlight area */
+int osd_show_dvd_nav_sx;        /* start x .... */
+int osd_show_dvd_nav_ex;
+int osd_show_dvd_nav_sy;
+int osd_show_dvd_nav_ey;
+int dvd_nav_still=0;            /* are we on a still picture? */
+
+dvdnav_priv_t * new_dvdnav_stream(char * filename) {
+  char * title_str;
+  dvdnav_priv_t *dvdnav_priv;
+
+  if (!filename)
+    return NULL;
+
+  if (!(dvdnav_priv=calloc(1,sizeof(*dvdnav_priv))))
+    return NULL;
+
+  if (!(dvdnav_priv->filename=strdup(filename))) {
+    free(dvdnav_priv);
+    return NULL;
+  }
+
+  if(dvdnav_open(&(dvdnav_priv->dvdnav),dvdnav_priv->filename)!=DVDNAV_STATUS_OK)
+  {
+    free(dvdnav_priv->filename);
+    free(dvdnav_priv);
+    return NULL;
+  }
+
+  if (!dvdnav_priv->dvdnav) {
+    free(dvdnav_priv);
+    return NULL;
+  }
+
+  if(1)	//from vlc: if not used dvdnav from cvs will fail
+  {
+    int len, event;
+    char buf[2048];
+    
+    dvdnav_get_next_block(dvdnav_priv->dvdnav,buf,&event,&len);
+  }
+  
+  /* turn on dvdnav caching */
+  dvdnav_set_readahead_flag(dvdnav_priv->dvdnav, 0);
+  if(dvdnav_set_PGC_positioning_flag(dvdnav_priv->dvdnav, 1) != DVDNAV_STATUS_OK)
+    mp_msg(MSGT_OPEN,MSGL_ERR,"stream_dvdnav, failed to set PGC positioning\n");
+#if 1
+  /* report the title?! */
+  if (dvdnav_get_title_string(dvdnav_priv->dvdnav,&title_str)==DVDNAV_STATUS_OK) {
+    mp_msg(MSGT_IDENTIFY, MSGL_INFO,"Title: '%s'\n",title_str);
+  }
+#endif
+
+  //dvdnav_event_clear(dvdnav_priv);
+
+  return dvdnav_priv;
+}
+
+int dvdnav_stream_reset(dvdnav_priv_t * dvdnav_priv) {
+  if (!dvdnav_priv) return 0;
+
+//  if (dvdnav_reset(dvdnav_priv->dvdnav)!=DVDNAV_STATUS_OK)
+    return 0;
+
+  dvdnav_priv->started=0;
+
+  return 1;
+}
+
+int dvdnav_stream_sleeping(dvdnav_priv_t * dvdnav_priv) {
+    unsigned int now;
+
+    if (!dvdnav_priv) return 0;
+
+    if(dvdnav_priv->sleeping)
+    {
+      now=GetTimer();
+      while(dvdnav_priv->sleeping>1 || now<dvdnav_priv->sleep_until) {
+//        printf("%s %u<%u\n",__FUNCTION__,now,dvdnav_priv->sleep_until);
+//        usec_sleep(1000); /* 1ms granularity */
+        return 1; 
+      }
+      dvdnav_still_skip(dvdnav_priv->dvdnav); // continue past...
+      dvdnav_priv->sleeping=0;
+      mp_msg(MSGT_OPEN,MSGL_V, "%s: woke up!\n",__FUNCTION__);
+    }
+    dvd_nav_still=0;
+    mp_msg(MSGT_OPEN,MSGL_V, "%s: active\n",__FUNCTION__);
+    return 0;
+}
+
+void dvdnav_stream_sleep(dvdnav_priv_t * dvdnav_priv, int seconds) {
+    if (!dvdnav_priv) return;
+
+    if (!dvdnav_priv->started) return;
+
+    dvdnav_priv->sleeping=0;
+    switch (seconds) {
+    case 0:
+            return;
+    case 0xff:
+            mp_msg(MSGT_OPEN,MSGL_V, "Sleeping indefinately\n" );
+            dvdnav_priv->sleeping=2;
+            break;
+    default:
+            mp_msg(MSGT_OPEN,MSGL_V, "Sleeping %d sec(s)\n", seconds );
+            dvdnav_priv->sleep_until = GetTimer();// + seconds*1000000;
+            dvdnav_priv->sleeping=1;
+            break;
+    }
+    //if (dvdnav_priv->started) dvd_nav_still=1;
+}
+
+void dvdnav_stream_add_event(dvdnav_priv_t* dvdnav_priv, int event, unsigned char *buf, int len) {
+  //printf("%s: %d\n",__FUNCTION__,event);
+
+  dvdnav_event_t * dvdnav_event;
+  mp_cmd_t * cmd;
+
+  if (!dvdnav_priv->started) return;
+
+  if (!(dvdnav_event=calloc(1,sizeof(*dvdnav_event)))) {
+    mp_msg(MSGT_OPEN,MSGL_V, "%s: dvdnav_event: out of memory!\n",__FUNCTION__);
+    return;
+  }
+  dvdnav_event->event=event;
+  dvdnav_event->details=calloc(1,len);
+  memcpy(dvdnav_event->details,buf,len);
+  dvdnav_event->len=len;
+
+  if (!(cmd = calloc(1,sizeof(*cmd)))) {
+    mp_msg(MSGT_OPEN,MSGL_V, "%s: mp_cmd_t: out of memory!\n",__FUNCTION__);
+    free(dvdnav_event->details);
+    free(dvdnav_event);
+    return;
+  }
+  cmd->id=MP_CMD_DVDNAV_EVENT; // S+event;
+  cmd->name=strdup("dvdnav_event"); // FIXME: do I really need a 'name'?
+  cmd->nargs=1;
+  cmd->args[0].v.v=dvdnav_event;
+}
+
+int dvdnav_stream_read(dvdnav_priv_t * dvdnav_priv, unsigned char *buf, int *len) {
+  int event = DVDNAV_NOP;
+
+  if (!len) return -1;
+  *len=-1;
+  if (!dvdnav_priv) return -1;
+  if (!buf) return -1;
+
+  if (dvd_nav_still) {
+    mp_msg(MSGT_OPEN,MSGL_V, "%s: got a stream_read while I should be asleep!\n",__FUNCTION__);
+    *len=0;
+    return -1;
+  }
+
+  if (dvdnav_get_next_block(dvdnav_priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) {
+    mp_msg(MSGT_OPEN,MSGL_V, "Error getting next block from DVD %d (%s)\n",event, dvdnav_err_to_string(dvdnav_priv->dvdnav) );
+    *len=-1;
+  }
+  else if (event!=DVDNAV_BLOCK_OK) {
+
+    // need to handle certain events internally (like skipping stills)
+    switch (event) {
+    case DVDNAV_STILL_FRAME: {
+      dvdnav_still_event_t *still_event = (dvdnav_still_event_t*)(buf);
+      //if (dvdnav_priv->started) dvd_nav_still=1;
+      //else
+        dvdnav_still_skip(dvdnav_priv->dvdnav); // don't let dvdnav stall on this image
+
+      break;
+    case DVDNAV_WAIT:
+        dvdnav_wait_skip(dvdnav_priv->dvdnav);
+        break;
+    }
+    }
+
+    // got an event, repeat the read
+    dvdnav_stream_add_event(dvdnav_priv,event,buf,*len);
+    *len=0;
+  }
+//  printf("%s: got %d\n",__FUNCTION__,*len);
+  return event;
+}
+
+void dvdnav_stream_fullstart(dvdnav_priv_t * dvdnav_priv) {
+  if (dvdnav_priv && !dvdnav_priv->started) {
+    dvdnav_stream_reset(dvdnav_priv);
+    dvdnav_priv->started=1;
+  }
+}
+
+unsigned int * dvdnav_stream_get_palette(dvdnav_priv_t * dvdnav_priv) {
+  if (!dvdnav_priv) {
+    mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv\n",__FUNCTION__);
+    return NULL;
+  }
+  if (!dvdnav_priv->dvdnav) {
+    mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv->dvdnav\n",__FUNCTION__);
+    return NULL;
+  }
+  #if 0
+  if (!dvdnav_priv->dvdnav->vm) {
+    mp_msg(MSGT_OPEN,MSGL_V, "%s: NULL dvdnav_priv->dvdnav->vm\n",__FUNCTION__);
+    return NULL;
+  }
+  if (!dvdnav_priv->dvdnav->vm->state.pgc) {
+    printf("%s: NULL dvdnav_priv->dvdnav->vm->state.pgc\n",__FUNCTION__);
+    return NULL;
+  }
+  return dvdnav_priv->dvdnav->vm->state.pgc->palette;
+  #endif
+}
+
+static void update_title_len(stream_t *stream) {
+  dvdnav_priv_t *priv = stream->priv;
+  dvdnav_status_t status;
+  uint32_t pos = 0, len = 0;
+
+  status = dvdnav_get_position(priv->dvdnav, &pos, &len);
+  if(status == DVDNAV_STATUS_OK && len)
+    stream->end_pos = (off_t) len * 2048;
+}
+  
+
+static int seek(stream_t *s, off_t newpos) {
+uint32_t pos = 0, len = 0, sector = 0;
+dvdnav_priv_t *priv = s->priv;
+
+  if(newpos==0) {
+    if(dvdnav_stream_reset(priv->dvdnav))
+      s->pos=0;
+  }
+  else {
+    if(s->end_pos && newpos > s->end_pos) 
+       newpos = s->end_pos;
+    sector = newpos / 2048ULL;
+    if(dvdnav_sector_search(priv->dvdnav, (uint64_t) sector, SEEK_SET) != DVDNAV_STATUS_OK)
+      goto fail;
+
+    s->pos = newpos;
+  }
+  
+  return 1;
+  
+fail:
+    mp_msg(MSGT_STREAM,MSGL_INFO,"dvdnav_stream, seeking to %"PRIu64" failed: %s\n", newpos, dvdnav_err_to_string(priv->dvdnav));
+
+  return 1;
+}
+
+static void stream_dvdnav_close(stream_t *s) {
+  dvdnav_priv_t *priv = s->priv;
+  dvdnav_close(priv->dvdnav);
+  priv->dvdnav = NULL;
+  free(priv);
+}
+
+
+static int fill_buffer(stream_t *s, char *but, int len)
+{
+    int event;
+    dvdnav_priv_t* dvdnav_priv=s->priv;
+    len=0;
+    if(!s->end_pos)
+      update_title_len(s);
+    while(!len) /* grab all event until DVDNAV_BLOCK_OK (len=2048), DVDNAV_STOP or DVDNAV_STILL_FRAME */
+    {
+        if(-1==(event=dvdnav_stream_read(dvdnav_priv, s->buffer, &len)) || len==-1)
+        {
+            mp_msg(MSGT_CPLAYER,MSGL_ERR, "DVDNAV stream read error!\n");
+            return 0;
+        }
+        switch (event) {
+            case DVDNAV_STOP: return len;
+	    case DVDNAV_BLOCK_OK: return len;
+#if 0
+            case DVDNAV_STILL_FRAME: {
+                if(!dvdnav_priv->stillok) dvdnav_priv->stillcounter++;
+                dvdnav_priv->lockstillcounter++;
+                return len;
+                break; 
+            }
+	    
+            case DVDNAV_WAIT: {
+                if(dvdnav_priv->waitcounter>=DVDNAV_MAX_WAIT_FRAME) return len;
+                break;
+            }
+#endif
+        }
+#if 0
+        if(dvdnav_priv->event.cell_really_change &&
+            dvdnav_priv->started &&
+	    !dvdnav_priv->vts_domain) 
+	        return len;
+#endif
+  }
+  mp_msg(MSGT_STREAM,MSGL_DBG2,"DVDNAV fill_buffer len: %d\n",len);
+  return len;
+}
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+  char *filename;
+  int event,len,tmplen=0;
+  uint32_t pos, l2;
+  dvdnav_priv_t *dvdnav_priv;
+  dvdnav_status_t status;
+
+  //mp_msg(MSGT_OPEN,MSGL_INFO,"URL: %s\n", filename);
+  
+  if(p->device) filename = p->device; 
+  else if(dvd_device) filename= dvd_device; 
+  else filename = DEFAULT_DVD_DEVICE;
+  if(!(dvdnav_priv=new_dvdnav_stream(filename))) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename);
+    return STREAM_UNSUPORTED;
+  }
+
+  if(dvdnav_title_play(dvdnav_priv->dvdnav, p->track) != DVDNAV_STATUS_OK) {
+    mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(dvdnav_priv->dvdnav));
+    return STREAM_UNSUPORTED;
+  }
+
+  stream->sector_size = 2048;
+  stream->flags = STREAM_READ | STREAM_SEEK;
+  stream->fill_buffer = fill_buffer;
+  stream->seek = seek;
+  stream->close = stream_dvdnav_close;
+  stream->type = STREAMTYPE_DVDNAV;
+  stream->priv=(void*)dvdnav_priv;
+  *file_format = DEMUXER_TYPE_MPEG_PS;
+
+  update_title_len(stream);
+  if(!stream->pos)
+    mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: %d, couldn't get init pos %s\r\n", status, dvdnav_err_to_string(dvdnav_priv->dvdnav));
+
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_dvdnav = {
+  "DVDNAV stream",
+  "null",
+  "",
+  "",
+  open_s,
+  { "dvdnav", NULL },
+  &stream_opts,
+  1 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/dvdnav_stream.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,46 @@
+#ifndef _MPLAYER_DVDNAV_STREAM_H
+#define _MPLAYER_DVDNAV_STREAM_H
+
+#include <dvdnav.h>
+
+typedef struct {
+  int event;             /* event number fromd dvdnav_events.h */
+  void * details;        /* event details */
+  int len;               /* bytes in details */
+} dvdnav_event_t;
+
+typedef struct {
+  dvdnav_t *       dvdnav;              /* handle to libdvdnav stuff */
+  char *           filename;            /* path */
+  int              ignore_timers;       /* should timers be skipped? */
+  int              sleeping;            /* are we sleeping? */
+  unsigned int     sleep_until;         /* timer */
+  int              started;             /* Has mplayer initialization finished? */
+  unsigned char    prebuf[STREAM_BUFFER_SIZE]; /* prefill buffer */
+  int              prelen;              /* length of prefill buffer */
+} dvdnav_priv_t;
+
+extern int dvd_nav_still;
+extern int dvd_nav_skip_opening;
+extern char dvd_nav_text[50];
+extern int osd_show_dvd_nav_delay;
+extern int osd_show_dvd_nav_highlight;
+extern int osd_show_dvd_nav_sx;
+extern int osd_show_dvd_nav_ex;
+extern int osd_show_dvd_nav_sy;
+extern int osd_show_dvd_nav_ey;
+
+dvdnav_priv_t * new_dvdnav_stream(char * filename);
+int dvdnav_stream_reset(dvdnav_priv_t * dvdnav_priv);
+void free_dvdnav_stream(dvdnav_priv_t * dvdnav_priv);
+
+void dvdnav_stream_ignore_timers(dvdnav_priv_t * dvdnav_priv, int ignore);
+int dvdnav_stream_read(dvdnav_priv_t * dvdnav_priv, unsigned char *buf, int *len);
+
+void dvdnav_stream_sleep(dvdnav_priv_t *dvdnav_priv, int seconds);
+int dvdnav_stream_sleeping(dvdnav_priv_t * dvdnav_priv);
+
+void dvdnav_stream_fullstart(dvdnav_priv_t *dvdnav_priv);
+unsigned int * dvdnav_stream_get_palette(dvdnav_priv_t * dvdnav_priv);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/freesdp/common.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,226 @@
+/*
+  This file is part of FreeSDP
+  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@suidzer0.org>
+
+  FreeSDP is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU 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
+*/
+
+/**
+ * @file common.c
+ *
+ * @short Implementation of routines common to parse and formatting
+ * modules .
+ *
+ * This file implements the routines that operate over data structures
+ * that are used in both the parse and formatting modules.
+ **/
+
+#include "priv.h"
+#include "common.h"
+
+static void
+safe_free (void *ptr)
+{
+  if (ptr)
+    free (ptr);
+}
+
+fsdp_description_t *
+fsdp_description_new (void)
+{
+  fsdp_description_t *result = malloc (sizeof (fsdp_description_t));
+
+  result->version = 0;
+  result->o_username = result->o_session_id =
+    result->o_announcement_version = NULL;
+  result->o_network_type = FSDP_NETWORK_TYPE_UNDEFINED;
+  result->o_address_type = FSDP_ADDRESS_TYPE_UNDEFINED;
+  result->o_address = NULL;
+  result->s_name = NULL;
+  result->i_information = NULL;
+  result->u_uri = NULL;
+  result->emails = NULL;
+  result->emails_count = 0;
+  result->phones = NULL;
+  result->phones_count = 0;
+  /* At first, there is no session-level definition for these
+     parameters */
+  result->c_network_type = FSDP_NETWORK_TYPE_UNDEFINED;
+  result->c_address_type = FSDP_ADDRESS_TYPE_UNDEFINED;
+  result->c_address.address = NULL;
+  /* there is no session-level definition for these parameters */
+  result->bw_modifiers = NULL;
+  result->bw_modifiers_count = 0;
+  result->time_periods = NULL;
+  result->time_periods_count = 0;
+  result->timezone_adj = NULL;
+  result->k_encryption_method = FSDP_ENCRYPTION_METHOD_UNDEFINED;
+  result->k_encryption_content = NULL;
+  /* Default/undefined values for attributes */
+  result->a_category = result->a_keywords = result->a_tool = NULL;
+  result->a_type = FSDP_SESSION_TYPE_UNDEFINED;
+  result->a_sendrecv_mode = FSDP_SENDRECV_UNDEFINED;
+  result->a_charset = NULL;
+  result->a_sdplangs = result->a_langs = NULL;
+  result->a_controls = NULL;
+  result->a_range = NULL;
+  result->a_rtpmaps = NULL;
+  result->a_rtpmaps_count = 0;
+  result->a_sdplangs_count = 0;
+  result->a_langs_count = 0;
+  result->a_controls_count = 0;
+  result->unidentified_attributes = NULL;
+  result->unidentified_attributes_count = 0;
+  result->media_announcements = NULL;
+  result->media_announcements_count = 0;
+
+  return result;
+}
+
+void
+fsdp_description_delete (fsdp_description_t * dsc)
+{
+  fsdp_description_recycle (dsc);
+  safe_free (dsc);
+}
+
+void
+fsdp_description_recycle (fsdp_description_t * dsc)
+{
+  /* Recursively free all strings and arrays */
+  unsigned int i, j;
+
+  if (!dsc)
+    return;
+
+  safe_free (dsc->o_username);
+  safe_free (dsc->o_session_id);
+  safe_free (dsc->o_announcement_version);
+  safe_free (dsc->o_address);
+  safe_free (dsc->s_name);
+  safe_free (dsc->i_information);
+  safe_free (dsc->u_uri);
+
+  for (i = 0; i < dsc->emails_count; i++)
+    safe_free ((char *) dsc->emails[i]);
+  safe_free (dsc->emails);
+
+  for (i = 0; i < dsc->phones_count; i++)
+    safe_free ((char *) dsc->phones[i]);
+  safe_free (dsc->phones);
+
+  safe_free (dsc->c_address.address);
+
+  for (i = 0; i < dsc->bw_modifiers_count; i++)
+    safe_free (dsc->bw_modifiers[i].b_unknown_bw_modt);
+  safe_free (dsc->bw_modifiers);
+
+  for (i = 0; i < dsc->time_periods_count; i++)
+  {
+    for (j = 0; j < dsc->time_periods[i]->repeats_count; j++)
+    {
+      safe_free (dsc->time_periods[i]->repeats[j]->offsets);
+      safe_free (dsc->time_periods[i]->repeats[j]);
+    }
+    safe_free (dsc->time_periods[i]->repeats);
+    safe_free (dsc->time_periods[i]);
+  }
+  safe_free (dsc->time_periods);
+
+  safe_free (dsc->timezone_adj);
+  safe_free (dsc->a_category);
+  safe_free (dsc->a_keywords);
+  safe_free (dsc->a_tool);
+
+  for (i = 0; i < dsc->a_rtpmaps_count; i++)
+    safe_free (dsc->a_rtpmaps[i]);
+  safe_free (dsc->a_rtpmaps);
+
+  safe_free (dsc->a_charset);
+
+  for (i = 0; i < dsc->a_sdplangs_count; i++)
+    safe_free (dsc->a_sdplangs[i]);
+  safe_free (dsc->a_sdplangs);
+
+  for (i = 0; i < dsc->a_langs_count; i++)
+    safe_free (dsc->a_langs[i]);
+  safe_free (dsc->a_langs);
+
+  for (i = 0; i < dsc->a_controls_count; i++)
+    safe_free (dsc->a_controls[i]);
+  safe_free (dsc->a_controls);
+
+  safe_free (dsc->a_range);
+
+  for (i = 0; i < dsc->media_announcements_count; i++)
+  {
+    for (j = 0; j < dsc->media_announcements[i]->formats_count; j++)
+      safe_free (dsc->media_announcements[i]->formats[j]);
+    safe_free (dsc->media_announcements[i]->formats);
+    safe_free (dsc->media_announcements[i]->i_title);
+
+    for (j = 0; j < dsc->media_announcements[i]->bw_modifiers_count; j++)
+    {
+      if (FSDP_BW_MOD_TYPE_UNKNOWN ==
+          dsc->media_announcements[i]->bw_modifiers[j].b_mod_type)
+        safe_free (dsc->media_announcements[i]->bw_modifiers[j].
+                   b_unknown_bw_modt);
+    }
+    safe_free (dsc->media_announcements[i]->bw_modifiers);
+
+    safe_free (dsc->media_announcements[i]->k_encryption_content);
+
+    for (j = 0; j < dsc->media_announcements[i]->a_rtpmaps_count; j++)
+    {
+      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->pt);
+      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->
+                 encoding_name);
+      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]->parameters);
+      safe_free (dsc->media_announcements[i]->a_rtpmaps[j]);
+    }
+    safe_free (dsc->media_announcements[i]->a_rtpmaps);
+
+    for (j = 0; j < dsc->media_announcements[i]->a_sdplangs_count; j++)
+      safe_free (dsc->media_announcements[i]->a_sdplangs[j]);
+    safe_free (dsc->media_announcements[i]->a_sdplangs);
+
+    for (j = 0; j < dsc->media_announcements[i]->a_langs_count; j++)
+      safe_free (dsc->media_announcements[i]->a_langs[j]);
+    safe_free (dsc->media_announcements[i]->a_langs);
+
+    for (j = 0; j < dsc->media_announcements[i]->a_controls_count; j++)
+      safe_free (dsc->media_announcements[i]->a_controls[j]);
+    safe_free (dsc->media_announcements[i]->a_controls);
+
+    for (j = 0; j < dsc->media_announcements[i]->a_fmtps_count; j++)
+      safe_free (dsc->media_announcements[i]->a_fmtps[j]);
+    safe_free (dsc->media_announcements[i]->a_fmtps);
+
+    for (j = 0;
+         j < dsc->media_announcements[i]->unidentified_attributes_count; j++)
+      safe_free (dsc->media_announcements[i]->unidentified_attributes[j]);
+    safe_free (dsc->media_announcements[i]->unidentified_attributes);
+    safe_free (dsc->media_announcements[i]);
+  }
+  safe_free (dsc->media_announcements);
+
+  /* This prevents the user to make the library crash when incorrectly
+     using recycled but not rebuilt descriptions */
+  dsc->emails_count = 0;
+  dsc->phones_count = 0;
+  dsc->bw_modifiers_count = 0;
+  dsc->time_periods_count = 0;
+  dsc->media_announcements_count = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/freesdp/common.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,352 @@
+/*
+  This file is part of FreeSDP.
+  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
+
+  FreeSDP is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU 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
+*/
+
+/**
+ * @file common.h
+ * @ingroup common
+ * @short Public header common for both parsing and formatting modules.
+ **/
+
+#ifndef FSDP_COMMON_H
+#define FSDP_COMMON_H
+
+/* Macros to avoid name mangling when compiling with a C++ compiler */
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+#include <sys/time.h>
+#include <time.h>
+
+BEGIN_C_DECLS
+/**
+ * @defgroup common FreeSDP Common Facilities
+ *
+ * Data types and routines common for both parsing and formatting
+ * modules.
+ **/
+/** @addtogroup common */
+/*@{*/
+/**
+ * @enum fsdp_error_t freesdp/common.h
+ * @short Error codes in the FreeSDP library.
+ *
+ * There is a FSDPE_MISSING_XXXX for each mandatory line, as
+ * FSDPE_MISSING_OWNER. This kind of error is reported when a
+ * mandatory description line, such as the owner line, is not found
+ * where it should be in the SDP description. There are also several
+ * error codes like FSDPE_INVALID_XXXX. These are returned when there
+ * is a recognized line in the parsed description that violates the
+ * SDP syntax or gives wrong parameters, for instance "c=foo bar",
+ * which would cause a FSDPE_INVALID_CONNECTION error code to be
+ * returned.
+ **/
+typedef enum
+{
+  FSDPE_OK = 0,
+  FSDPE_ILLEGAL_CHARACTER,	 /**< Misplaced '\r', '\n' or '\0' */
+  FSDPE_MISSING_VERSION,	 /**< The first line is not like
+				    v=... */
+  FSDPE_INVALID_VERSION,	 /**< Parse error in version line,
+				    perhaps, the version specified in
+				    v=... is not valid for FreeSDP */
+  FSDPE_MISSING_OWNER,		 /**< No owner line found in its
+				    place */
+  FSDPE_INVALID_OWNER,		 /**< Parse error in owner line */
+  FSDPE_MISSING_NAME,		 /**< No session name found in its
+				    place */
+  FSDPE_EMPTY_NAME,		 /**< Empty session name line */
+
+  FSDPE_INVALID_CONNECTION,	 /**< Syntax error in connection
+				    line */
+
+  FSDPE_INVALID_CONNECTION_ADDRTYPE, /**< Unrecognized address type in
+					connection line */
+  FSDPE_INVALID_CONNECTION_NETTYPE,  /**< Unrecognized network type in
+					connection line */
+  FSDPE_INVALID_BANDWIDTH,	     /**< Parse error in bandwidth
+					line */
+  FSDPE_MISSING_TIME,		 /**< No time period has been given
+				    for the session */
+  FSDPE_INVALID_TIME,		 /**< Parse error in time line */
+  FSDPE_INVALID_REPEAT,		 /**< Parse error in repeat time
+				    line */
+  FSDPE_INVALID_TIMEZONE,	 /**< Parse error in timezone line */
+  FSDPE_INVALID_ENCRYPTION_METHOD, /**< Unknown encryption method */
+  FSDPE_INVALID_ATTRIBUTE,	 /**< Syntax error in an attribute
+				    line */
+
+  FSDPE_INVALID_ATTRIBUTE_RTPMAP,/**< Parse error in a=rtpmap:... line */
+  FSDPE_INVALID_SESSION_TYPE,	 /**< An unknown session type has been
+				    specified in a `type:'
+				    session-level attribute */
+
+  FSDPE_INVALID_MEDIA,		 /**< Parse error in media line */
+  FSDPE_UNKNOWN_MEDIA_TYPE,	 /**< Unknown media type in media
+				    line */
+
+  FSDPE_UNKNOWN_MEDIA_TRANSPORT, /**< A media transport has been
+				    specified that is unknown */
+
+  FSDPE_OVERFILLED,		 /**< extra unknown lines are at the
+				    end of the description */
+  FSDPE_INVALID_LINE,		 /**< a line unknown to FreeSDP has been
+				    found */
+  FSDPE_MISSING_CONNECTION_INFO, /**< No connection information has
+				     been provided for the whole
+				     session nor one or more media */
+  FSDPE_INVALID_INDEX,
+  /*  FSDPE_MAXSIZE, description does not fit requested maximun size */
+  FSDPE_INTERNAL_ERROR,
+
+  FSDPE_INVALID_PARAMETER,	 /**< Some parameter of the called
+				       FreeSDP routine has been given an
+				       invalid value. This includes
+				       cases such as NULL pointers. */
+  FSDPE_BUFFER_OVERFLOW
+} fsdp_error_t;
+
+/**
+ * @short Type of network 
+ *
+ * Initially, SDP defines "Internet". New network types may be
+ * registered with IANA. However, the number of types is expected to
+ * be small and rarely extended. In addition, every new network type
+ * requires at least one new address type.
+ **/
+typedef enum
+{
+  FSDP_NETWORK_TYPE_UNDEFINED,		       /**< Not provided */
+  FSDP_NETWORK_TYPE_INET		       /**< Internet */
+} fsdp_network_type_t;
+
+/**
+ * @short Type of address
+ *
+ * Initially, IPv4 and IPv6 are defined for the network type
+ * Internet. New address types may be registered with IANA.
+ **/
+typedef enum
+{
+  FSDP_ADDRESS_TYPE_UNDEFINED,		       /**< Not provided */
+  FSDP_ADDRESS_TYPE_IPV4,		      /**< IP version 4 */
+  FSDP_ADDRESS_TYPE_IPV6		      /**< IP version 6 */
+} fsdp_address_type_t;
+
+/**
+ * @short Type of bandwith modifiers 
+ *
+ * Bandwidth modifiers specify the meaning of the bandwidth
+ * value. Initially "Conference Total" and "Application Specific" are
+ * defined. Both use kilobits as bandwidth unit. "Conference Total"
+ * specifies that the bandwidth value is a proposed upper limit to the
+ * session bandwidth. "Application Specific" specifies thath the
+ * bandwidth value is the application concept of maximum bandwidth.
+ **/
+typedef enum
+{
+  FSDP_BW_MOD_TYPE_UNDEFINED,		 /**< Not provided */
+  FSDP_BW_MOD_TYPE_UNKNOWN,		 /**< Unknown bandwidth
+						  modifier (FreeSDP
+						  ignores it) */
+  FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL,	 /**< "CT - Conference Total" */
+  FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC, /**< "AS - Application specific" */
+  FSDP_BW_MOD_TYPE_RTCP_SENDERS,	 /**< "RS - RTCP bandwidth for
+					    senders */
+  FSDP_BW_MOD_TYPE_RTCP_RECEIVERS,	 /**< "RR - RTCP bandwidth for
+					    receivers */
+} fsdp_bw_modifier_type_t;
+
+/**
+ * @short encryption method
+ *
+ * The encryption method specifies the way to get the encryption key.
+ **/
+typedef enum
+{
+  FSDP_ENCRYPTION_METHOD_UNDEFINED,    /**< Not provided */
+  FSDP_ENCRYPTION_METHOD_CLEAR,	       /**< The key field is the
+						 untransformed key */
+  FSDP_ENCRYPTION_METHOD_BASE64,       /**< The key is base64
+					  encoded */
+  FSDP_ENCRYPTION_METHOD_URI,	       /**< The key value provided is
+					  a URI pointing to the actual
+					  key */
+  FSDP_ENCRYPTION_METHOD_PROMPT	       /**< The key is not provided
+					  but should be got prompting
+					  the user */
+} fsdp_encryption_method_t;
+
+/**
+ * @short Advised reception/transmission mode
+ *
+ * Depending on wheter sendrecv, recvonly, sendonly or inactive
+ * attribute is given, the tools used to participate in the session
+ * should be started in the corresponding transmission
+ * mode. FSDP_SENDRECV_SENDRECV is the default for sessions which are
+ * not of the conference type broadcast or H332.
+ **/
+typedef enum
+{
+  FSDP_SENDRECV_UNDEFINED,		      /**< Not specified */
+  FSDP_SENDRECV_SENDRECV,		      /**< Send and receive */
+  FSDP_SENDRECV_RECVONLY,		      /**< Receive only */
+  FSDP_SENDRECV_SENDONLY,		      /**< Send only */
+  FSDP_SENDRECV_INACTIVE		      /**< Do not send nor receive */
+} fsdp_sendrecv_mode_t;
+
+/**
+ * @short Values for `orient' media attribute.
+ *
+ * Normally used with whiteboard media, this attribute specifies the
+ * orientation of the whiteboard.
+ **/
+typedef enum
+{
+  FSDP_ORIENT_UNDEFINED,		     /**< Not specified */
+  FSDP_ORIENT_PORTRAIT,			     /**< Portrait */
+  FSDP_ORIENT_LANDSCAPE,		     /**< Landscape */
+  FSDP_ORIENT_SEASCAPE			     /**< Upside down landscape */
+} fsdp_orient_t;
+
+/**
+ * @short Type of the conference
+ *
+ * The following types are initially defined: broadcast, meeting,
+ * moderated, test and H332.
+ **/
+typedef enum
+{
+  FSDP_SESSION_TYPE_UNDEFINED,		       /**< Not specified */
+  FSDP_SESSION_TYPE_BROADCAST,		       /**< Broadcast session */
+  FSDP_SESSION_TYPE_MEETING,		       /**< Meeting session */
+  FSDP_SESSION_TYPE_MODERATED,		       /**< Moderated session */
+  FSDP_SESSION_TYPE_TEST,		       /**< Test (do not display) */
+  FSDP_SESSION_TYPE_H332		       /**< H332 session */
+} fsdp_session_type_t;
+
+/**
+ * @short Media type
+ *
+ * The following types are defined initially: audio, video,
+ * application, data and control.
+ **/
+typedef enum
+{
+  FSDP_MEDIA_UNDEFINED,		   /**< Not specified */
+  FSDP_MEDIA_VIDEO,		   /**< Video */
+  FSDP_MEDIA_AUDIO,		   /**< Audio */
+  FSDP_MEDIA_APPLICATION,	   /**< Application, such as whiteboard */
+  FSDP_MEDIA_DATA,		   /**< bulk data */
+  FSDP_MEDIA_CONTROL		   /**< Control channel */
+} fsdp_media_t;
+
+/**
+ * @short Transport protocol
+ *
+ * The transport protocol used depends on the address type. Initially,
+ * RTP over UDP Audio/Video Profile, and UDP are defined.
+ *
+ **/
+typedef enum
+{
+  FSDP_TP_UNDEFINED,		  /**< Not specified */
+  FSDP_TP_RTP_AVP,		  /**< RTP Audio/Video Profile */
+  FSDP_TP_UDP,			  /**< UDP */
+  FSDP_TP_TCP,			  /**< TCP */
+  FSDP_TP_UDPTL,		  /**< ITU-T T.38*/
+  FSDP_TP_VAT,			  /**< old vat protocol (historic)*/
+  FSDP_TP_OLD_RTP,		  /**< old rtp protocols (historic)*/
+  FSDP_TP_H320			  /**< TODO: add to the parser */
+} fsdp_transport_protocol_t;
+
+/**
+ * Session-level attributes whose value is specified as a character
+ * string in FreeSDP. These values are usually given to
+ * fsdp_get_strn_att() in order to get the corresponding value.
+ *
+ **/
+typedef enum
+{
+  FSDP_SESSION_STR_ATT_CATEGORY,
+  FSDP_SESSION_STR_ATT_KEYWORDS,
+  FSDP_SESSION_STR_ATT_TOOL,
+  FSDP_SESSION_STR_ATT_CHARSET,
+} fsdp_session_str_att_t;
+
+/**
+ * @short FreeSDP SDP description media object.
+ *
+ * Object for media specific information in SDP descriptions. Each SDP
+ * description may include any number of media section. A
+ * fsdp_media_description_t object encapsulates the information in a
+ * media section, such as video, audio or whiteboard.
+ **/
+typedef struct fsdp_media_description_t_s fsdp_media_description_t;
+
+/**
+ * @short FreeSDP SDP session description object.
+ *
+ * Contains all the information extracted from a textual SDP
+ * description, including all the media announcements.
+ **/
+typedef struct fsdp_description_t_s fsdp_description_t;
+
+/**
+ * Allocates memory and initializes values for a new
+ * fsdp_description_t object. If you call this routine, do not forget
+ * about <code>fsdp_description_delete()</code>
+ *
+ * @return new fsdp_description_t object
+ **/
+fsdp_description_t *fsdp_description_new (void);
+
+/**
+ * Destroys a fsdp_description_t object.
+ *
+ * @param dsc pointer to the fsdp_description_t object to delete.
+ **/
+void fsdp_description_delete (fsdp_description_t * dsc);
+
+/**
+ * Calling this function over a description is equivalent to calling
+ * fsdp_description_delete and then fsdp_description_delete. This
+ * function is however more suitable and efficient for description
+ * processing loops.
+ *
+ * @param dsc pointer to the fsdp_description_t object to
+ * renew/recycle.
+ **/
+void fsdp_description_recycle (fsdp_description_t * dsc);
+
+/**
+ *  * Returns a string correspondent to the error number.
+ *   *
+ *    * @param err_no error number.
+ *     **/
+const char *fsdp_strerror (fsdp_error_t err_no);
+
+       /*@}*//* closes addtogroup common */
+
+END_C_DECLS
+#endif /* FSDP_COMMON_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/freesdp/errorlist.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,72 @@
+/*
+  This file is part of FreeSDP
+  Copyright (C) 2001, 2002 Federico Montesino Pouzols <fedemp@suidzer0.org>
+
+  FreeSDP is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU 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
+*/
+
+/**
+ * @file errorlist.c
+ *
+ * @short Translation table for error numbers
+ *
+ */
+
+#ifndef FSDP_ERRORLIST_C
+#define FSDP_ERRORLIST_C
+
+#include "common.h"
+
+const char *fsdp_error_t_s[] = {
+  "No error",/** FSDPE_OK **/
+  "Illegal character detected",/** FSDPE_ILLEGAL_CHARACTER **/
+  "Missing version item", /** FSDPE_MISSING_VERSION **/
+  "Invalid version item", /** FSDPE_INVALID_VERSION **/
+  "Owner item not present", /** FSDPE_MISSING_OWNER **/
+  "Parse error in owner item", /** FSDPE_INVALID_OWNER **/
+  "Session name not present", /** FSDPE_MISSING_NAME **/
+  "Empty session name item", /** FSDPE_EMPTY_NAME **/
+  "Syntax error in connection item", /** FSDPE_INVALID_CONNECTION **/
+  "Unrecognized address type in connection item", /** FSDPE_INVALID_CONNECTION_ADDRTYPE **/
+  "Unrecognized network type in connection item", /** FSDPE_INVALID_CONNECTION_NETTYPE **/
+  "Parse error in bandwith item", /** FSDPE_INVALID_BANDWIDTH **/
+  "No time period for the session", /** FSDPE_MISSING_TIME **/
+  "Parse error in time item", /** FSDPE_INVALID_TIME **/
+  "Parse error in repeat time item", /** FSDPE_INVALID_REPEAT **/
+  "Parse error in timezone item", /** FSDPE_INVALID_TIMEZONE **/
+  "Unknown encryption method", /** FSDPE_INVALID_ENCRYPTION_METHOD **/
+  "Syntax error in an attribute item", /** FSDPE_INVALID_ATTRIBUTE **/
+  "Syntax error in an rtpmap attribute item", /** FSDPE_INVALID_ATTRIBUTE_RTPMAP **/
+  "Unknown session type in a session-level attribute", /** FSDPE_INVALID_SESSION_TYPE **/
+  "Parse error in media item", /** FSDPE_INVALID_MEDIA **/
+  "Unknown media type in media item", /** FSDPE_UNKNOWN_MEDIA_TYPE **/
+  "Unknown media transport", /** FSDPE_UNKNOWN_MEDIA_TRANSPORT **/
+  "Unknown extra lines in description item", /** FSDPE_OVERFILLED **/
+  "Unknown line found",	/** FSDPE_INVALID_LINE **/
+  "No connection information provided",	/** FSDPE_MISSING_CONNECTION_INFO **/
+  "Description item does not fit in MAXSIZE", /** FSDPE_INVALID_INDEX **/
+  "Internal error", /** FSDPE_INTERNAL_ERROR **/
+  "Invalid function parameters", /** FSDPE_INVALID_PARAMETER **/
+  "Buffer overflow" /** FSDPE_BUFFER_OVERFLOW **/
+};
+
+
+const char *
+fsdp_strerror (fsdp_error_t err_no)
+{
+  return (fsdp_error_t_s[err_no]);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/freesdp/parser.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,1958 @@
+/*
+  This file is part of FreeSDP
+  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
+  
+  FreeSDP is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU 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
+
+  Benjamin Zores, (C) 2006
+    added support in parser for the a=control: lines.
+    added support in parser for the a=range: lines.
+*/
+
+/**
+ * @file parser.c
+ *
+ * @short Parsing module implementation.
+ *
+ * This file implements the parsing routine <code>fsdp_parse</code>
+ * and the <code>fsdp_get_xxxx</code> routines that allow to get the
+ * session properties from a session description object build through
+ * the application of <code>fsdp_parse</code> to a textual SDP session
+ * description.
+ **/
+
+#include "parserpriv.h"
+
+/**
+ * Moves the <code>c<code> pointer up to the beginning of the next
+ * line.
+ *
+ * @param c char pointer to pointer
+ * @retval FSDPE_ILLEGAL_CHARACTER, when an illegal '\r' character
+ * (not followed by a '\n') is found, returns
+ */
+#define NEXT_LINE(c)                                                \
+({                                                                  \
+ while ((*(c) != '\0') && (*(c) != '\r') && (*(c) != '\n')) {       \
+    (c)++;                                                          \
+ }                                                                  \
+ if (*(c) == '\n') {                                                \
+    (c)++;                                                          \
+ } else if (*(c) == '\r') {                                         \
+    (c)++;                                                          \
+    if (*(c) == '\n') {                                             \
+       (c)++;                                                       \
+    } else {                                                        \
+       return FSDPE_ILLEGAL_CHARACTER;                              \
+   }                                                                \
+ }                                                                  \
+})
+
+fsdp_error_t
+fsdp_parse (const char *text_description, fsdp_description_t * dsc)
+{
+  fsdp_error_t result;
+  const char *p = text_description, *p2;
+  unsigned int index, j;
+  /* temps for sscanf */
+  const unsigned int TEMPCHARS = 6;
+  char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
+  char longfsdp_buf[MAXLONGFIELDLEN];
+  const unsigned int TEMPINTS = 2;
+  unsigned long int wuint[TEMPINTS];
+
+  if ((NULL == text_description) || (NULL == dsc))
+    return FSDPE_INVALID_PARAMETER;
+
+  /***************************************************************************/
+  /* A) parse session-level description                                      */
+  /***************************************************************************/
+
+  /* `v=' line (protocol version) */
+  /* according to the RFC, only `v=0' is valid */
+  if (sscanf (p, "v=%1lu", &wuint[0]))
+  {
+    if (wuint[0] != 0)
+      return FSDPE_INVALID_VERSION;
+  }
+  else
+  {
+    return FSDPE_MISSING_VERSION;
+  }
+  NEXT_LINE (p);
+
+  /* `o=' line (owner/creator and session identifier) */
+  /* o=<username> <session id> <version> <network type> <address type>
+     <address> */
+  if (!strncmp (p, "o=", 2))
+  {
+    p += 2;
+    /* note that the following max lengths may vary in the future and
+       are quite arbitary */
+    if (sscanf
+        (p,
+         "%" MSFLENS "[\x21-\xFF] %" MSFLENS "[0-9] %" MSFLENS
+         "[0-9] %2s %3s %" MSFLENS "s", fsdp_buf[0], fsdp_buf[1],
+         fsdp_buf[2], fsdp_buf[3], fsdp_buf[4], fsdp_buf[5]) != 6)
+      return FSDPE_INVALID_OWNER;
+    dsc->o_username = strdup (fsdp_buf[0]);
+    dsc->o_session_id = strdup (fsdp_buf[1]);
+    dsc->o_announcement_version = strdup (fsdp_buf[2]);
+    if (!strncmp (fsdp_buf[3], "IN", 2))
+    {
+      dsc->o_network_type = FSDP_NETWORK_TYPE_INET;
+      if (!strncmp (fsdp_buf[4], "IP4", 3))
+        dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV4;
+      else if (!strncmp (fsdp_buf[4], "IP6", 3))
+        dsc->o_address_type = FSDP_ADDRESS_TYPE_IPV6;
+      else
+        return FSDPE_INVALID_OWNER;
+    }
+    else
+    {
+      return FSDPE_INVALID_OWNER;
+    }
+    /* TODO? check valid unicast address/FQDN */
+    dsc->o_address = strdup (fsdp_buf[5]);
+  }
+  else
+  {
+    return FSDPE_MISSING_OWNER;
+  }
+  NEXT_LINE (p);
+
+  /* `s=' line (session name) -note that the name string cannot be empty */
+  /* s=<session name> */
+  if (!strncmp (p, "s=", 2))
+  {
+    if (sscanf (p, "s=%" MLFLENS "[^\r\n]", longfsdp_buf) < 1)
+      return FSDPE_EMPTY_NAME;
+    dsc->s_name = strdup (longfsdp_buf);
+  }
+  else
+  {
+    return FSDPE_MISSING_NAME;
+  }
+  NEXT_LINE (p);
+
+  /* `i=' line (session information) [optional] */
+  /* i=<session description> */
+  if (!strncmp (p, "i=", 2)
+      && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
+  {
+    dsc->i_information = strdup (longfsdp_buf);
+    NEXT_LINE (p);
+  }
+  else
+  {
+    /* (optional) information absent */
+  }
+
+  /* `u=' line (URI of description)  [optional] */
+  /* u=<URI> */
+  if (!strncmp (p, "u=", 2)
+      && sscanf (p, "u=%" MLFLENS "[^\r\n]", longfsdp_buf))
+  {
+    /* TODO? check valid uri */
+    dsc->u_uri = strdup (longfsdp_buf);
+    NEXT_LINE (p);
+  }
+  else
+  {
+    /* (optional) uri absent */
+  }
+
+  /* `e=' lines (email address) [zero or more] */
+  /* e=<email address> */
+  p2 = p;
+  j = 0;
+  while (!strncmp (p2, "e=", 2))
+  {
+    /* First, count how many emails are there */
+    j++;
+    NEXT_LINE (p2);
+  }
+  dsc->emails_count = j;
+  if (dsc->emails_count > 0)
+  {
+    /* Then, build the array of emails */
+    dsc->emails = calloc (j, sizeof (const char *));
+    for (j = 0; j < dsc->emails_count; j++)
+    {
+      sscanf (p, "e=%" MLFLENS "[^\r\n]", longfsdp_buf);
+      /* TODO? check valid email-address. */
+      dsc->emails[j] = strdup (longfsdp_buf);
+      NEXT_LINE (p);
+    }
+  }
+
+  /* `p=' lines (phone number) [zero or more] */
+  /*  p=<phone number> */
+  j = 0;
+  /* assert ( p2 == p ); */
+  while (!strncmp (p2, "p=", 2))
+  {
+    j++;
+    NEXT_LINE (p2);
+  }
+  dsc->phones_count = j;
+  if (dsc->phones_count > 0)
+  {
+    dsc->phones = calloc (j, sizeof (const char *));
+    for (j = 0; j < dsc->phones_count; j++)
+    {
+      sscanf (p, "p=%" MLFLENS "[^\r\n]", longfsdp_buf);
+      /* TODO? check valid phone-number. */
+      dsc->phones[j] = strdup (longfsdp_buf);
+      NEXT_LINE (p);
+    }
+  }
+
+  /* `c=' line (connection information - not required if included in all media) [optional] */
+  /* c=<network type> <address type> <connection address> */
+  result = fsdp_parse_c (&p, &(dsc->c_network_type), &(dsc->c_address_type),
+			 &(dsc->c_address));
+  if (FSDPE_OK != result)
+    return result;
+
+  /* `b=' lines (bandwidth information) [optional] */
+  /* b=<modifier>:<bandwidth-value> */
+  result =
+    fsdp_parse_b (&p, &(dsc->bw_modifiers), &(dsc->bw_modifiers_count));
+  if (FSDPE_OK != result)
+    return result;
+
+  /* A.1) Time descriptions: */
+
+  /* `t=' lines (time the session is active) [1 or more] */
+  /* t=<start time>  <stop time> */
+  j = 0;
+  p2 = p;
+  while (!strncmp (p2, "t=", 2))
+  {
+    j++;
+    NEXT_LINE (p2);
+    while (!strncmp (p2, "r=", 2))
+      NEXT_LINE (p2);
+  }
+  dsc->time_periods_count = j;
+  if (dsc->time_periods_count == 0)
+    return FSDPE_MISSING_TIME;
+  dsc->time_periods = calloc (dsc->time_periods_count,
+			      sizeof (fsdp_time_period_t *));
+  index = 0;
+  for (j = 0; j < dsc->time_periods_count; j++)
+  {
+    unsigned int h = 0;
+    if (sscanf (p, "t=%10lu %10lu", &wuint[0], &wuint[1]) != 2)
+    {
+      /* not all periods have been successfully parsed */
+      dsc->time_periods_count = j;
+      return FSDPE_INVALID_TIME;
+    }
+    dsc->time_periods[j] = calloc (1, sizeof (fsdp_time_period_t));
+
+    /* convert from NTP to time_t time */
+    if (wuint[0] != 0)
+      wuint[0] -= NTP_EPOCH_OFFSET;
+    if (wuint[1] != 0)
+      wuint[1] -= NTP_EPOCH_OFFSET;
+    dsc->time_periods[j]->start = wuint[0];
+    dsc->time_periods[j]->stop = wuint[1];
+    NEXT_LINE (p);
+
+    /* `r' lines [zero or more repeat times for each t=] */
+    /*r=<repeat interval> <active duration> <list of offsets from
+      start-time> */
+    p2 = p;
+    while (!strncmp (p2, "r=", 2))
+    {
+      h++;
+      NEXT_LINE (p2);
+    }
+    dsc->time_periods[j]->repeats_count = h;
+    if (h > 0)
+    {
+      unsigned int index2 = 0;
+      dsc->time_periods[j]->repeats =
+        calloc (h, sizeof (fsdp_repeat_t *));
+      for (h = 0; h < dsc->time_periods[j]->repeats_count; h++)
+      {
+        /*
+          get_repeat_values(p,&(dsc->time_periods[index].repeats[index2]));
+          fsdp_error_t get_repeat_values (const char *r, fsdp_repeat_t
+          *repeat);
+          */
+        if (sscanf (p, "r=%10s %10s %" MLFLENS "[^\r\n]",
+                    fsdp_buf[0], fsdp_buf[1], longfsdp_buf) == 3)
+        {
+          fsdp_repeat_t *repeat;
+          dsc->time_periods[j]->repeats[h] =
+            calloc (1, sizeof (fsdp_repeat_t));
+          repeat = dsc->time_periods[j]->repeats[h];
+          /* get interval, duration and list of offsets */
+          result =
+            fsdp_repeat_time_to_uint (fsdp_buf[0],
+                                      &(repeat->interval));
+          if (result == FSDPE_OK)
+          {
+            result =
+              fsdp_repeat_time_to_uint (fsdp_buf[1],
+                                        &(repeat->duration));
+            if (result == FSDPE_OK)
+            {
+              unsigned int k = 1;
+              const char *i = longfsdp_buf;
+              while (NULL != (i = strchr (i, ' ')))
+              {
+                k++;
+                if (NULL != i)
+                  i++;
+              }
+              repeat->offsets_count = k;
+              repeat->offsets = calloc (k, sizeof (time_t));
+              i = longfsdp_buf;
+              for (k = 0;
+                   (k < repeat->offsets_count)
+                     && (result == FSDPE_OK); k++)
+              {
+                result =
+                  fsdp_repeat_time_to_uint (i,
+                                            &(repeat->
+                                              offsets[k]));
+                i = strchr (i, ' ');
+                if (NULL != i)
+                  i++;
+              }
+              if (k < repeat->offsets_count)
+              {
+                /* there where invalid repeat offsets */
+                dsc->time_periods[j]->repeats_count = k;
+                return FSDPE_INVALID_REPEAT;
+              }
+            }
+          }
+          if (result != FSDPE_OK)
+          {
+            /* not all repeats have been succesfully parsed */
+            dsc->time_periods[j]->repeats_count = h;
+            return FSDPE_INVALID_REPEAT;
+          }
+          NEXT_LINE (p);
+        }
+        else
+        {
+          /* not all repeats have been succesfully parsed */
+          dsc->time_periods[j]->repeats_count = h;
+          return FSDPE_INVALID_REPEAT;
+        }
+        index2++;
+      }
+    }
+  }
+
+  /* `z=' line (time zone adjustments) [zero or more] */
+  /* z=<adjustment time> <offset> <adjustment time> <offset> .... */
+  if (!strncmp (p, "z=", 2))
+  {
+    if (sscanf (p, "z=%" MLFLENS "[^\r\n]", longfsdp_buf))
+    {
+      /* TODO: guess how many pairs are there and process them */
+      dsc->timezone_adj = strdup (longfsdp_buf);
+      NEXT_LINE (p);
+    }
+    else
+    {
+      return FSDPE_INVALID_TIMEZONE;
+    }
+  }
+
+  /* `k=' line (encryption key) [optional] */
+  /* k=<method> 
+     k=<method>:<encryption key> */
+  result = fsdp_parse_k (&p, &(dsc->k_encryption_method),
+			 &(dsc->k_encryption_content));
+  if (result != FSDPE_OK)
+    return result;
+
+  /* A.2) Attributes */
+  /* `a=' lines (session attribute) [0 or more] */
+  /* a=<attribute>
+     a=<attribute>:<value> */
+  while (!strncmp (p, "a=", 2))
+  {
+    /* The "9" lenght specifier of the first string is subject to
+       changes */
+    if (sscanf
+        (p, "a=%9[^:\r\n]:%" MSFLENS "[^\r\n]", fsdp_buf[0],
+         fsdp_buf[1]) == 2)
+    {
+      /* session-level value attributes */
+      if (!strncmp (fsdp_buf[0], "cat", 3))
+        dsc->a_category = strdup (fsdp_buf[1]);
+      else if (!strncmp (fsdp_buf[0], "keywds", 6))
+        dsc->a_keywords = strdup (fsdp_buf[1]);
+      else if (!strncmp (fsdp_buf[0], "tool", 4))
+        dsc->a_keywords = strdup (fsdp_buf[1]);
+      else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
+        fsdp_parse_rtpmap (&(dsc->a_rtpmaps),
+                           &(dsc->a_rtpmaps_count), fsdp_buf[1]);
+      else if (!strncmp (fsdp_buf[0], "type", 4))
+      {
+        if (!strncmp (fsdp_buf[1], "broadcast", 9))
+          dsc->a_type = FSDP_SESSION_TYPE_BROADCAST;
+        else if (!strncmp (fsdp_buf[1], "meeting", 7))
+          dsc->a_type = FSDP_SESSION_TYPE_MEETING;
+        else if (!strncmp (fsdp_buf[1], "moderated", 9))
+          dsc->a_type = FSDP_SESSION_TYPE_MODERATED;
+        else if (!strncmp (fsdp_buf[1], "test", 4))
+          dsc->a_type = FSDP_SESSION_TYPE_TEST;
+        else if (!strncmp (fsdp_buf[1], "H332", 4))
+          dsc->a_type = FSDP_SESSION_TYPE_H332;
+        else
+          return FSDPE_INVALID_SESSION_TYPE;
+      }
+      else if (!strncmp (fsdp_buf[0], "charset", 7))
+        dsc->a_charset = strdup (fsdp_buf[1]);
+      else if (!strncmp (fsdp_buf[0], "sdplang", 7))
+      {
+        if (NULL == dsc->a_sdplangs)
+        {
+          dsc->a_sdplangs_count = 0;
+          dsc->a_sdplangs =
+            calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
+        }
+        if (dsc->a_sdplangs_count < SDPLANGS_MAX_COUNT)
+        {
+          dsc->a_sdplangs[dsc->a_sdplangs_count] =
+            strdup (fsdp_buf[1]);
+          dsc->a_sdplangs_count++;
+        }
+      }
+      else if (!strncmp (fsdp_buf[0], "lang", 4))
+      {
+        if (NULL == dsc->a_langs)
+        {
+          dsc->a_langs_count = 0;
+          dsc->a_langs = calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
+        }
+        if (dsc->a_langs_count < SDPLANGS_MAX_COUNT)
+        {
+          dsc->a_langs[dsc->a_langs_count] = strdup (fsdp_buf[1]);
+          dsc->a_langs_count++;
+        }
+      }
+      else if (!strncmp (fsdp_buf[0], "control", 7))
+      {
+        if (NULL == dsc->a_controls)
+        {
+          dsc->a_controls_count = 0;
+          dsc->a_controls =
+            calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
+        }
+        if (dsc->a_controls_count < SDPCONTROLS_MAX_COUNT)
+        {
+          dsc->a_controls[dsc->a_controls_count] =
+            strdup (fsdp_buf[1]);
+          dsc->a_controls_count++;
+        }
+      }
+      else if (!strncmp (fsdp_buf[0], "range", 5))
+      {
+        if (dsc->a_range)
+          free (dsc->a_range);
+        dsc->a_range = strdup (fsdp_buf[1]);
+      }
+      else
+      {
+        /* ignore unknown attributes, but provide access to them */
+        *longfsdp_buf = '\0';
+        strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN);
+        strncat (longfsdp_buf, ":", MAXLONGFIELDLEN);
+        strncat (longfsdp_buf, fsdp_buf[1], MAXLONGFIELDLEN);
+        if (NULL == dsc->unidentified_attributes)
+        {
+          dsc->unidentified_attributes_count = 0;
+          dsc->unidentified_attributes =
+            calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
+                    sizeof (char *));
+        }
+        if (dsc->unidentified_attributes_count <
+            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
+        {
+          dsc->unidentified_attributes
+            [dsc->unidentified_attributes_count] =
+            strdup (longfsdp_buf);
+          dsc->unidentified_attributes_count++;
+        }
+      }
+      NEXT_LINE (p);
+    }
+    else if (sscanf (p, "a=%20s", fsdp_buf[0]) == 1)
+    {
+      /* session-level property attributes */
+      if (!strncmp (fsdp_buf[0], "recvonly", 8))
+        dsc->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
+      else if (!strncmp (fsdp_buf[0], "sendonly", 8))
+        dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
+      else if (!strncmp (fsdp_buf[0], "inactive", 8))
+        dsc->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
+      else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
+        dsc->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
+      else
+      {
+        /* ignore unknown attributes, but provide access to them */
+        *longfsdp_buf = '\0';
+        strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN);
+        if (NULL == dsc->unidentified_attributes)
+        {
+          dsc->unidentified_attributes_count = 0;
+          dsc->unidentified_attributes =
+            calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
+                    sizeof (char *));
+        }
+        if (dsc->unidentified_attributes_count <
+            UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
+        {
+          dsc->unidentified_attributes
+            [dsc->unidentified_attributes_count] =
+            strdup (longfsdp_buf);
+          dsc->unidentified_attributes_count++;
+        }
+      }
+      NEXT_LINE (p);
+    }
+    else
+      return FSDPE_INVALID_ATTRIBUTE;
+  }
+
+  /***************************************************************************/
+  /* B) parse media-level descriptions                                       */
+  /***************************************************************************/
+  p2 = p;
+  j = 0;
+  while ((*p2 != '\0') && !strncmp (p2, "m=", 2))
+  {
+    char c;
+    j++;
+    NEXT_LINE (p2);
+    while (sscanf (p2, "%c=", &c) == 1)
+    {
+      if (c == 'i' || c == 'c' || c == 'b' || c == 'k' || c == 'a')
+      {
+        NEXT_LINE (p2);
+      }
+      else if (c == 'm')
+      {
+        break;
+      }
+      else
+      {
+        return FSDPE_INVALID_LINE;
+      }
+    }
+  }
+  dsc->media_announcements_count = j;
+  if (dsc->media_announcements_count == 0)
+  {
+    ;
+    /*return FSDPE_MISSING_MEDIA; */
+  }
+  else
+  {				/* dsc->media_announcements_count > 0 */
+    dsc->media_announcements =
+      calloc (j, sizeof (fsdp_media_announcement_t *));
+    for (j = 0; j < dsc->media_announcements_count; j++)
+    {
+      fsdp_media_announcement_t *media = NULL;
+      /* `m=' line (media name, transport address and format list) */
+      /* m=<media>  <port>  <transport> <fmt list> */
+      /* The max. string lengths are subject to change */
+      if (sscanf (p, "m=%11s %8s %7s %" MLFLENS "[^\r\n]",
+                  fsdp_buf[0], fsdp_buf[1], fsdp_buf[2],
+                  longfsdp_buf) != 4)
+      {
+        return FSDPE_INVALID_MEDIA;
+      }
+      else
+      {
+        dsc->media_announcements[j] =
+          calloc (1, sizeof (fsdp_media_announcement_t));
+        media = dsc->media_announcements[j];
+        if (!strncmp (fsdp_buf[0], "audio", 5))
+          media->media_type = FSDP_MEDIA_AUDIO;
+        else if (!strncmp (fsdp_buf[0], "video", 5))
+          media->media_type = FSDP_MEDIA_VIDEO;
+        else if (!strncmp (fsdp_buf[0], "application", 11))
+          media->media_type = FSDP_MEDIA_APPLICATION;
+        else if (!strncmp (fsdp_buf[0], "data", 4))
+          media->media_type = FSDP_MEDIA_DATA;
+        else if (!strncmp (fsdp_buf[0], "control", 7))
+          media->media_type = FSDP_MEDIA_CONTROL;
+        else
+          return FSDPE_UNKNOWN_MEDIA_TYPE;
+        {			/* try to get port specification as port/number */
+          char *slash;
+          if ((slash = strchr (fsdp_buf[1], '/')))
+          {
+            *slash = '\0';
+            slash++;
+            media->port = strtol (fsdp_buf[1], NULL, 10);
+            media->port_count = strtol (slash, NULL, 10);
+          }
+          else
+          {
+            media->port = strtol (fsdp_buf[1], NULL, 10);
+            media->port_count = 0;
+          }
+        }
+        if (!strncmp (fsdp_buf[2], "RTP/AVP", 7))
+          media->transport = FSDP_TP_RTP_AVP;
+        else if (!strncmp (fsdp_buf[2], "udp", 3))
+          media->transport = FSDP_TP_UDP;
+        else if (!strncmp (fsdp_buf[2], "TCP", 3))
+          media->transport = FSDP_TP_TCP;
+        else if (!strncmp (fsdp_buf[2], "UDPTL", 5))
+          media->transport = FSDP_TP_UDPTL;
+        else if (!strncmp (fsdp_buf[2], "vat", 3))
+          media->transport = FSDP_TP_VAT;
+        else if (!strncmp (fsdp_buf[2], "rtp", 3))
+          media->transport = FSDP_TP_OLD_RTP;
+        else
+          return FSDPE_UNKNOWN_MEDIA_TRANSPORT;
+        {
+          unsigned int k = 0;
+          char *s = longfsdp_buf;
+          while (NULL != (s = strchr (s, ' ')))
+          {
+            k++;
+            if (NULL != s)
+              s++;
+          }
+          k++;		/* when there is no space left, count the last format */
+          media->formats_count = k;
+          media->formats = calloc (k, sizeof (char *));
+          s = longfsdp_buf;
+          for (k = 0; k < media->formats_count; k++)
+          {
+            char *space = strchr (s, ' ');
+            if (NULL != space)
+              *space = '\0';
+            media->formats[k] = strdup (s);
+            s = space + 1;
+          }
+        }
+        NEXT_LINE (p);
+      }
+
+      /* `i=' line (media title) [optional] */
+      /* i=<media title> */
+      if (!strncmp (p, "i=", 2)
+          && sscanf (p, "i=%" MLFLENS "[^\r\n]", longfsdp_buf))
+      {
+        media->i_title = strdup (longfsdp_buf);
+        NEXT_LINE (p);
+      }
+      else
+      {
+        /* (optional) information absent */
+      }
+
+      /* `c=' line (connection information - overrides session-level
+         line) [optional if provided at session-level] */
+      /* c=<network type> <address type> <connection address> */
+      result = fsdp_parse_c (&p, &(media->c_network_type),
+                             &(media->c_address_type),
+                             &(media->c_address));
+      if (result != FSDPE_OK)
+        return result;
+
+      /* `b=' lines (bandwidth information) [optional] */
+      /* b=<modifier>:<bandwidth-value> */
+      result = fsdp_parse_b (&p, &(media->bw_modifiers),
+                             &(media->bw_modifiers_count));
+      if (FSDPE_OK != result)
+        return result;
+
+      /* `k=' line (encryption key) [optional] */
+      /* k=<method> 
+         k=<method>:<encryption key> */
+      result = fsdp_parse_k (&p, &(media->k_encryption_method),
+                             &(media->k_encryption_content));
+      if (result != FSDPE_OK)
+        return result;
+
+      /* B.1) Attributes */
+
+      /* `a=' lines (zero or more media attribute lines) [optional] */
+      /* a=<attribute>
+         a=<attribute>:<value> */
+      while (!strncmp (p, "a=", 2))
+      {
+        if (sscanf
+            (p, "a=%9[^:\r\n]:%" MLFLENS "[^\r\n]", fsdp_buf[0],
+             longfsdp_buf) == 2)
+        {
+          /* media-level value attributes */
+          if (!strncmp (fsdp_buf[0], "ptime", 5))
+            media->a_ptime = strtoul (longfsdp_buf, NULL, 10);
+          else if (!strncmp (fsdp_buf[0], "maxptime", 8))
+            media->a_maxptime = strtoul (longfsdp_buf, NULL, 10);
+          else if (!strncmp (fsdp_buf[0], "rtpmap", 6))
+            fsdp_parse_rtpmap (&(media->a_rtpmaps),
+                               &(media->a_rtpmaps_count),
+                               longfsdp_buf);
+          else if (!strncmp (fsdp_buf[0], "orient", 6))
+          {
+            if (!strncmp (longfsdp_buf, "portrait", 8))
+              media->a_orient = FSDP_ORIENT_PORTRAIT;
+            else if (!strncmp (longfsdp_buf, "landscape", 9))
+              media->a_orient = FSDP_ORIENT_LANDSCAPE;
+            else if (!strncmp (longfsdp_buf, "seascape", 9))
+              media->a_orient = FSDP_ORIENT_SEASCAPE;
+          }
+          else if (!strncmp (fsdp_buf[0], "sdplang", 7))
+          {
+            if (NULL == dsc->a_sdplangs)
+            {
+              media->a_sdplangs_count = 0;
+              media->a_sdplangs =
+                calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
+            }
+            if (media->a_sdplangs_count < SDPLANGS_MAX_COUNT)
+            {
+              media->a_sdplangs[dsc->a_sdplangs_count] =
+                strdup (longfsdp_buf);
+              media->a_sdplangs_count++;
+            }
+          }
+          else if (!strncmp (fsdp_buf[0], "lang", 4))
+          {
+            if (NULL == dsc->a_langs)
+            {
+              media->a_langs_count = 0;
+              media->a_langs =
+                calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
+            }
+            if (media->a_langs_count < SDPLANGS_MAX_COUNT)
+            {
+              media->a_langs[dsc->a_langs_count] =
+                strdup (longfsdp_buf);
+              media->a_langs_count++;
+            }
+          }
+          else if (!strncmp (fsdp_buf[0], "control", 7))
+          {
+            if (NULL == media->a_controls)
+            {
+              media->a_controls_count = 0;
+              media->a_controls =
+                calloc (SDPCONTROLS_MAX_COUNT, sizeof (char *));
+            }
+            if (media->a_controls_count < SDPCONTROLS_MAX_COUNT)
+            {
+              media->a_controls[media->a_controls_count] =
+                strdup (longfsdp_buf);
+              media->a_controls_count++;
+            }
+          }
+          else if (!strncmp (fsdp_buf[0], "range", 5))
+          {
+            if (media->a_range)
+              free (media->a_range);
+            media->a_range = strdup (fsdp_buf[1]);
+          }
+          else if (!strncmp (fsdp_buf[0], "framerate", 9))
+            media->a_framerate = strtod (longfsdp_buf, NULL);
+          else if (!strncmp (fsdp_buf[0], "fmtp", 4))
+          {
+            if (NULL == media->a_fmtps)
+            {
+              media->a_fmtps_count = 0;
+              media->a_fmtps =
+                calloc (SDPLANGS_MAX_COUNT, sizeof (char *));
+            }
+            if (media->a_fmtps_count < SDPLANGS_MAX_COUNT)
+            {
+              media->a_fmtps[media->a_fmtps_count] =
+                strdup (longfsdp_buf);
+              media->a_fmtps_count++;
+            }
+          }
+          else if (!strncmp (fsdp_buf[0], "rtcp", 4))
+          {
+            int opts = 0;
+            /* rtcp attribute: a=rtcp:<port> <nettype> <addrtype> <address> */
+            opts =
+              sscanf (longfsdp_buf, "%lu %2s %3s %" MSFLENS "s",
+                      &wuint[0], fsdp_buf[0], fsdp_buf[1],
+                      fsdp_buf[2]);
+            if (opts >= 1)
+            {
+              media->a_rtcp_port = wuint[0];
+              if (opts >= 2)
+              {
+                if (!strncmp (fsdp_buf[0], "IN", 2))
+                {
+                  media->a_rtcp_network_type =
+                    FSDP_NETWORK_TYPE_INET;
+                }	/* else
+                           ; TODO: define error code? */
+                if (opts >= 3)
+                {
+                  if (!strncmp (fsdp_buf[1], "IP4", 3))
+                    media->a_rtcp_address_type =
+                      FSDP_ADDRESS_TYPE_IPV4;
+                  else if (!strncmp (fsdp_buf[1], "IP6", 3))
+                    media->a_rtcp_address_type =
+                      FSDP_ADDRESS_TYPE_IPV6;
+                  else
+                    return FSDPE_INVALID_CONNECTION_NETTYPE;
+                  /*add specific code? */
+                  if (opts >= 4)
+                    media->a_rtcp_address =
+                      strdup (fsdp_buf[2]);
+                }
+              }
+            }
+          }
+          else
+          {
+            /* ignore unknown attributes, but provide access to them */
+            *fsdp_buf[1] = '\0';
+            strncat (fsdp_buf[1], fsdp_buf[0], MAXLONGFIELDLEN);
+            strncat (fsdp_buf[1], ":", MAXLONGFIELDLEN);
+            strncat (fsdp_buf[1], longfsdp_buf, MAXLONGFIELDLEN);
+            if (NULL == media->unidentified_attributes)
+            {
+              media->unidentified_attributes_count = 0;
+              media->unidentified_attributes =
+                calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
+                        sizeof (char *));
+            }
+            if (media->unidentified_attributes_count <
+                UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
+            {
+              media->unidentified_attributes
+                [media->unidentified_attributes_count] =
+                strdup (fsdp_buf[1]);
+              media->unidentified_attributes_count++;
+            }
+          }
+          NEXT_LINE (p);
+        }
+        else if (sscanf (p, "a=%8s", fsdp_buf[0]) == 1)
+        {
+          /* media-level property attributes */
+          if (!strncmp (fsdp_buf[0], "recvonly", 8))
+            media->a_sendrecv_mode = FSDP_SENDRECV_RECVONLY;
+          else if (!strncmp (fsdp_buf[0], "sendonly", 8))
+            media->a_sendrecv_mode = FSDP_SENDRECV_SENDONLY;
+          else if (!strncmp (fsdp_buf[0], "inactive", 8))
+            media->a_sendrecv_mode = FSDP_SENDRECV_INACTIVE;
+          else if (!strncmp (fsdp_buf[0], "sendrecv", 8))
+            media->a_sendrecv_mode = FSDP_SENDRECV_SENDRECV;
+          else
+          {
+            /* ignore unknown attributes, but provide access to them */
+            *longfsdp_buf = '\0';
+            strncat (longfsdp_buf, fsdp_buf[0], MAXLONGFIELDLEN);
+            if (NULL == media->unidentified_attributes)
+            {
+              media->unidentified_attributes_count = 0;
+              media->unidentified_attributes =
+                calloc (UNIDENTIFIED_ATTRIBUTES_MAX_COUNT,
+                        sizeof (char *));
+            }
+            if (media->unidentified_attributes_count <
+                UNIDENTIFIED_ATTRIBUTES_MAX_COUNT)
+            {
+              media->unidentified_attributes
+                [media->unidentified_attributes_count] =
+                strdup (longfsdp_buf);
+              media->unidentified_attributes_count++;
+            }
+          }
+          NEXT_LINE (p);
+        }
+        else
+          return FSDPE_INVALID_ATTRIBUTE;
+      }
+    }			/* end of for */
+  }
+
+  /* Check c= has been given at session level or at media level for
+     all media */
+  if (NULL == dsc->c_address.address)
+  {
+    unsigned int c;
+    for (c = 0; c < dsc->media_announcements_count; c++)
+      if (NULL == dsc->media_announcements[c]->c_address.address)
+        return FSDPE_MISSING_CONNECTION_INFO;
+  }
+
+  /* finish */
+  if (*p == '\0')
+    return FSDPE_OK;
+  else
+    return FSDPE_OVERFILLED;
+}
+
+static fsdp_error_t
+fsdp_parse_c (const char **p, fsdp_network_type_t * ntype,
+	      fsdp_address_type_t * atype,
+	      fsdp_connection_address_t * address)
+{
+  const unsigned int TEMPCHARS = 3;
+  char fsdp_buf[TEMPCHARS][MAXSHORTFIELDLEN];
+
+  if (!strncmp (*p, "c=", 2))
+  {
+    if (sscanf (*p, "c=%2s %3s %" MSFLENS "s",
+                fsdp_buf[0], fsdp_buf[1], fsdp_buf[2]))
+    {
+      if (!strncmp (fsdp_buf[0], "IN", 2))
+      {
+        *ntype = FSDP_NETWORK_TYPE_INET;
+        if (!strncmp (fsdp_buf[1], "IP4", 3))
+          *atype = FSDP_ADDRESS_TYPE_IPV4;
+        else if (!strncmp (fsdp_buf[1], "IP6", 3))
+          *atype = FSDP_ADDRESS_TYPE_IPV6;
+        else
+          return FSDPE_INVALID_CONNECTION_NETTYPE;
+      }
+      else
+      {
+        return FSDPE_INVALID_CONNECTION_ADDRTYPE;
+      }
+      {
+        char *slash = strchr (fsdp_buf[2], '/');
+        if (NULL == slash)
+        {
+          address->address = strdup (fsdp_buf[2]);
+          address->address_ttl = 0;
+          address->address_count = 0;
+        }
+        else
+        {
+          /* address is IP4 multicast */
+          char *slash2;
+          *slash = '\0';
+          slash++;
+          address->address = strdup (fsdp_buf[2]);
+          slash2 = strchr (slash + 1, '/');
+          if (NULL == slash2)
+          {
+            address->address_ttl = strtol (slash, NULL, 10);
+            address->address_count = 0;
+          }
+          else
+          {
+            *slash2 = '\0';
+            slash2++;
+            address->address_ttl = strtol (slash, NULL, 10);
+            address->address_count = strtol (slash2, NULL, 10);
+          }
+        }
+      }
+      NEXT_LINE (*p);
+    }
+    else
+    {
+      return FSDPE_INVALID_CONNECTION;
+    }
+  }
+  return FSDPE_OK;
+}
+
+static fsdp_error_t
+fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers,
+	      unsigned int *bw_modifiers_count)
+{
+  char fsdp_buf[MAXSHORTFIELDLEN];
+  unsigned long int wuint;
+  unsigned int i = 0;
+  char *lp = (char *) *p;
+
+  /* count b= lines */
+  while (!strncmp (lp, "b=", 2))
+  {
+    NEXT_LINE (lp);
+    i++;
+  }
+  *bw_modifiers = calloc (i, sizeof (fsdp_bw_modifier_t));
+  *bw_modifiers_count = i;
+
+  while (i > 0)
+  {
+    unsigned int index = *bw_modifiers_count - i;
+    if (2 == sscanf (*p, "b=%20[^:\r\n]:%lu", fsdp_buf, &wuint))
+    {
+      if (!strncmp (fsdp_buf, "CT", 2))
+        (*bw_modifiers)[index].b_mod_type =
+          FSDP_BW_MOD_TYPE_CONFERENCE_TOTAL;
+      else if (!strncmp (fsdp_buf, "AS", 2))
+        (*bw_modifiers)[index].b_mod_type =
+          FSDP_BW_MOD_TYPE_APPLICATION_SPECIFIC;
+      else if (!strncmp (fsdp_buf, "RS", 2))
+        (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_RTCP_SENDERS;
+      else if (!strncmp (fsdp_buf, "RR", 2))
+        (*bw_modifiers)[index].b_mod_type =
+          FSDP_BW_MOD_TYPE_RTCP_RECEIVERS;
+      else
+      {
+        (*bw_modifiers)[index].b_mod_type = FSDP_BW_MOD_TYPE_UNKNOWN;
+        (*bw_modifiers)[index].b_unknown_bw_modt =
+          (char *) strdup (fsdp_buf);
+      }
+      (*bw_modifiers)[index].b_value = wuint;
+      NEXT_LINE (*p);
+    }
+    else
+    {
+      *bw_modifiers_count -= i;
+      return FSDPE_INVALID_BANDWIDTH;
+    }
+    i--;
+  }
+  return FSDPE_OK;
+}
+
+static fsdp_error_t
+fsdp_parse_k (const char **p, fsdp_encryption_method_t * method,
+	      char **content)
+{
+  char fsdp_buf[MAXSHORTFIELDLEN];
+  char longfsdp_buf[MAXLONGFIELDLEN];
+
+  if (!strncmp (*p, "k=", 2))
+  {
+    if (sscanf (*p, "k=prompt"))
+    {
+      *method = FSDP_ENCRYPTION_METHOD_PROMPT;
+      *content = NULL;
+      NEXT_LINE (*p);
+    }
+    else
+    {
+      if (sscanf
+          (*p, "k=%6[^:\r\n]:%" MLFLENS "s", fsdp_buf, longfsdp_buf))
+      {
+        if (!strncmp (fsdp_buf, "clear", 5))
+          *method = FSDP_ENCRYPTION_METHOD_CLEAR;
+        else if (!strncmp (fsdp_buf, "base64", 6))
+          *method = FSDP_ENCRYPTION_METHOD_BASE64;
+        else if (!strncmp (fsdp_buf, "uri", 3))
+          *method = FSDP_ENCRYPTION_METHOD_URI;
+        else
+          return FSDPE_INVALID_ENCRYPTION_METHOD;
+        *content = strdup (longfsdp_buf);
+        NEXT_LINE (*p);
+      }
+    }
+  }
+  return FSDPE_OK;
+}
+
+static fsdp_error_t
+fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter,
+		   const char *value)
+{
+  fsdp_error_t result = FSDPE_OK;
+
+  if (0 == *counter)
+  {
+    *counter = 0;
+    *rtpmap = calloc (MEDIA_RTPMAPS_MAX_COUNT, sizeof (fsdp_rtpmap_t *));
+  }
+  if (*counter < MEDIA_RTPMAPS_MAX_COUNT)
+  {
+    unsigned int c = *counter;
+    fsdp_rtpmap_t **map = *rtpmap;
+    char fsdp_buf[MAXSHORTFIELDLEN];
+    char longfsdp_buf[MAXLONGFIELDLEN];
+    map[c] = calloc (1, sizeof (fsdp_rtpmap_t));
+
+    /* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding
+       parameters]> */
+    if (2 == sscanf (value, "%s %s", fsdp_buf, longfsdp_buf))
+    {
+      char *slash1;
+      map[c]->pt = strdup (fsdp_buf);
+      /* parse <encoding name>/<clock rate>[/<encoding parameters>] */
+      slash1 = strchr (longfsdp_buf, '/');
+      if (NULL == slash1)
+      {
+        result = FSDPE_INVALID_ATTRIBUTE_RTPMAP;
+      }
+      else
+      {
+        char *slash2;
+        *slash1 = '\0';
+        slash1++;
+        map[c]->encoding_name = strdup (longfsdp_buf);
+        slash2 = strchr (slash1, '/');
+        if (NULL != slash2)
+        {
+          *slash2 = '\0';
+          slash2++;
+          map[c]->parameters = strdup (slash2);
+        }
+        map[c]->clock_rate = strtol (slash1, NULL, 10);
+      }
+      (*counter)++;
+    }
+  }
+  return result;
+}
+
+static fsdp_error_t
+fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds)
+{
+  const unsigned long SECONDS_PER_DAY = 86400;
+  const unsigned long SECONDS_PER_HOUR = 3600;
+  const unsigned long SECONDS_PER_MINUTE = 60;
+  char c;
+  unsigned long int wuint;
+
+  if (sscanf (time, "%lu%c", &wuint, &c) == 2)
+  {
+    /* time with unit specification character */
+    switch (c)
+    {
+    case 'd':
+      *seconds = wuint * SECONDS_PER_DAY;
+      break;
+    case 'h':
+      *seconds = wuint * SECONDS_PER_HOUR;
+      break;
+    case 'm':
+      *seconds = wuint * SECONDS_PER_MINUTE;
+      break;
+    case 's':
+      *seconds = wuint;
+      break;
+    default:
+      return FSDPE_INVALID_REPEAT;
+      break;
+    }
+  }
+  else if (sscanf (time, "%lu", &wuint) == 1)
+  {
+    /* time without unit specification character */
+    *seconds = wuint;
+  }
+  else
+  {
+    return FSDPE_INVALID_REPEAT;
+  }
+  return FSDPE_OK;
+}
+
+unsigned int
+fsdp_get_version (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->version;
+}
+
+const char *
+fsdp_get_owner_username (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->o_username;
+}
+
+const char *
+fsdp_get_session_id (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->o_session_id;
+}
+
+const char *
+fsdp_get_announcement_version (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->o_announcement_version;
+}
+
+fsdp_network_type_t
+fsdp_get_owner_network_type (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_NETWORK_TYPE_UNDEFINED;
+  return dsc->o_network_type;
+}
+
+fsdp_address_type_t
+fsdp_get_owner_address_type (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_ADDRESS_TYPE_UNDEFINED;
+  return dsc->o_address_type;
+}
+
+const char *
+fsdp_get_owner_address (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->o_address;
+}
+
+const char *
+fsdp_get_name (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->s_name;
+}
+
+const char *
+fsdp_get_information (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->i_information;
+}
+
+const char *
+fsdp_get_uri (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->u_uri;
+}
+
+unsigned int
+fsdp_get_emails_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->emails_count;
+}
+
+const char *
+fsdp_get_email (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->emails_count))
+    return NULL;
+  return dsc->emails[index];
+}
+
+unsigned int
+fsdp_get_phones_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->phones_count;
+}
+
+const char *
+fsdp_get_phone (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->phones_count))
+    return NULL;
+  return dsc->phones[index];
+}
+
+fsdp_network_type_t
+fsdp_get_global_conn_network_type (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_NETWORK_TYPE_UNDEFINED;
+  return dsc->c_network_type;
+}
+
+fsdp_address_type_t
+fsdp_get_global_conn_address_type (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_ADDRESS_TYPE_UNDEFINED;
+  return dsc->c_address_type;
+}
+
+const char *
+fsdp_get_global_conn_address (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->c_address.address;
+}
+
+unsigned int
+fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->c_address.address_ttl;
+}
+
+unsigned int
+fsdp_get_global_conn_address_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->c_address.address_count;
+}
+
+unsigned int
+fsdp_get_bw_modifier_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->bw_modifiers_count;
+}
+
+fsdp_bw_modifier_type_t
+fsdp_get_bw_modifier_type (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->bw_modifiers_count))
+    return FSDP_BW_MOD_TYPE_UNDEFINED;
+  return dsc->bw_modifiers[index].b_mod_type;
+}
+
+const char *
+fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc,
+				   unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->bw_modifiers_count) ||
+      (dsc->bw_modifiers[index].b_mod_type != FSDP_BW_MOD_TYPE_UNKNOWN))
+    return NULL;
+  return dsc->bw_modifiers[index].b_unknown_bw_modt;
+}
+
+unsigned long int
+fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->bw_modifiers_count))
+    return 0;
+  return dsc->bw_modifiers[index].b_value;
+}
+
+time_t
+fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->time_periods_count))
+    return 0;
+  return dsc->time_periods[index]->start;
+}
+
+time_t
+fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->time_periods_count))
+    return 0;
+  return dsc->time_periods[index]->stop;
+}
+
+unsigned int
+fsdp_get_period_repeats_count (const fsdp_description_t * dsc,
+			       unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->time_periods_count))
+    return 0;
+  return dsc->time_periods[index]->repeats_count;
+}
+
+unsigned long int
+fsdp_get_period_repeat_interval (const fsdp_description_t * dsc,
+				 unsigned int index, unsigned int rindex)
+{
+  if ((!dsc) || (index >= dsc->time_periods_count))
+    return 0;
+  return dsc->time_periods[index]->repeats[rindex]->interval;
+}
+
+unsigned long int
+fsdp_get_period_repeat_duration (const fsdp_description_t * dsc,
+				 unsigned int index, unsigned int rindex)
+{
+  if ((!dsc) || (index >= dsc->time_periods_count))
+    return 0;
+  return dsc->time_periods[index]->repeats[rindex]->duration;
+}
+
+const unsigned long int *
+fsdp_get_period_repeat_offsets (const fsdp_description_t * dsc,
+				unsigned int index, unsigned int rindex)
+{
+  if ((!dsc) || (index >= dsc->time_periods_count))
+    return NULL;
+  return dsc->time_periods[index]->repeats[rindex]->offsets;
+}
+
+const char *
+fsdp_get_timezone_adj (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->timezone_adj;
+}
+
+unsigned int
+fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->unidentified_attributes_count;
+}
+
+const char *
+fsdp_get_unidentified_attribute (const fsdp_description_t * dsc,
+				 unsigned int index)
+{
+  if (!dsc || (index < dsc->unidentified_attributes_count))
+    return NULL;
+  return dsc->unidentified_attributes[index];
+}
+
+fsdp_encryption_method_t
+fsdp_get_encryption_method (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_ENCRYPTION_METHOD_UNDEFINED;
+  return dsc->k_encryption_method;
+}
+
+const char *
+fsdp_get_encryption_content (const fsdp_description_t * dsc)
+{
+  if (!dsc || (dsc->k_encryption_method == FSDP_ENCRYPTION_METHOD_UNDEFINED))
+    return NULL;
+  return dsc->k_encryption_content;
+}
+
+unsigned int
+fsdp_get_rtpmap_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_rtpmaps_count;
+}
+
+const char *
+fsdp_get_rtpmap_payload_type (const fsdp_description_t * dsc,
+			      unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
+    return NULL;
+  return dsc->a_rtpmaps[index]->pt;
+}
+
+const char *
+fsdp_get_rtpmap_encoding_name (const fsdp_description_t * dsc,
+			       unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
+    return NULL;
+  return dsc->a_rtpmaps[index]->encoding_name;
+}
+
+unsigned int
+fsdp_get_rtpmap_clock_rate (const fsdp_description_t * dsc,
+			    unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
+    return 0;
+  return dsc->a_rtpmaps[index]->clock_rate;
+}
+
+const char *
+fsdp_get_rtpmap_encoding_parameters (const fsdp_description_t * dsc,
+				     unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->a_rtpmaps_count))
+    return NULL;
+  return dsc->a_rtpmaps[index]->parameters;
+}
+
+const char *
+fsdp_get_str_att (const fsdp_description_t * dsc, fsdp_session_str_att_t att)
+{
+  /*TODO: change these individual attributes with a table, thus
+    avoiding this slow switch */
+  char *result;
+
+  if (!dsc)
+    return NULL;
+
+  switch (att)
+  {
+  case FSDP_SESSION_STR_ATT_CATEGORY:
+    result = dsc->a_category;
+    break;
+  case FSDP_SESSION_STR_ATT_KEYWORDS:
+    result = dsc->a_keywords;
+    break;
+  case FSDP_SESSION_STR_ATT_TOOL:
+    result = dsc->a_tool;
+    break;
+  case FSDP_SESSION_STR_ATT_CHARSET:
+    result = dsc->a_charset;
+    break;
+  default:
+    result = NULL;
+  }
+  return result;
+}
+
+unsigned int
+fsdp_get_sdplang_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_sdplangs_count;
+}
+
+const char *
+fsdp_get_sdplang (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->a_sdplangs_count))
+    return NULL;
+  return dsc->a_sdplangs[index];
+}
+
+unsigned int
+fsdp_get_lang_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_langs_count;
+}
+
+const char *
+fsdp_get_lang (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->a_langs_count))
+    return NULL;
+  return dsc->a_langs[index];
+}
+
+unsigned int
+fsdp_get_control_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_controls_count;
+}
+
+const char *
+fsdp_get_control (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((!dsc) || (index >= dsc->a_controls_count))
+    return NULL;
+  return dsc->a_controls[index];
+}
+
+const char *
+fsdp_get_range (const fsdp_description_t * dsc)
+{
+  return dsc->a_range;
+}
+
+fsdp_sendrecv_mode_t
+fsdp_get_sendrecv_mode (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_SENDRECV_UNDEFINED;
+  return dsc->a_sendrecv_mode;
+}
+
+fsdp_session_type_t
+fsdp_get_session_type (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_SESSION_TYPE_UNDEFINED;
+  return dsc->a_type;
+}
+
+unsigned int
+fsdp_get_media_count (const fsdp_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->media_announcements_count;
+}
+
+const fsdp_media_description_t *
+fsdp_get_media (const fsdp_description_t * dsc, unsigned int index)
+{
+  if ((index >= dsc->media_announcements_count))
+    return NULL;
+  return dsc->media_announcements[index];
+}
+
+fsdp_media_t
+fsdp_get_media_type (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_MEDIA_UNDEFINED;
+  return dsc->media_type;
+}
+
+unsigned int
+fsdp_get_media_port (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->port;
+}
+
+unsigned int
+fsdp_get_media_port_count (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->port_count;
+}
+
+fsdp_transport_protocol_t
+fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_TP_UNDEFINED;
+  return dsc->transport;
+}
+
+unsigned int
+fsdp_get_media_formats_count (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->formats_count;
+}
+
+const char *
+fsdp_get_media_format (const fsdp_media_description_t * dsc,
+		       unsigned int index)
+{
+  if (!dsc && (index < dsc->formats_count))
+    return NULL;
+  return dsc->formats[index];
+}
+
+const char *
+fsdp_get_media_title (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->i_title;
+}
+
+fsdp_network_type_t
+fsdp_get_media_network_type (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_NETWORK_TYPE_UNDEFINED;
+  return dsc->c_network_type;
+}
+
+fsdp_address_type_t
+fsdp_get_media_address_type (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_ADDRESS_TYPE_UNDEFINED;
+  return dsc->c_address_type;
+}
+
+const char *
+fsdp_get_media_address (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->c_address.address;
+}
+
+unsigned int
+fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->c_address.address_ttl;
+}
+
+unsigned int
+fsdp_get_media_address_count (const fsdp_media_description_t * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->c_address.address_count;
+}
+
+fsdp_bw_modifier_type_t
+fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc,
+				 unsigned int index)
+{
+  if (!dsc || (index >= dsc->bw_modifiers_count))
+    return FSDP_BW_MOD_TYPE_UNDEFINED;
+  return dsc->bw_modifiers[index].b_mod_type;
+}
+
+const char *
+fsdp_get_media_bw_modifier_type_unknown (const fsdp_media_description_t * dsc,
+					 unsigned int index)
+{
+  if (!dsc || (index >= dsc->bw_modifiers_count) ||
+      (FSDP_BW_MOD_TYPE_UNKNOWN != dsc->bw_modifiers[index].b_mod_type))
+    return NULL;
+  return dsc->bw_modifiers[index].b_unknown_bw_modt;
+}
+
+unsigned long int
+fsdp_get_media_bw_value (const fsdp_media_description_t * dsc,
+			 unsigned int index)
+{
+  if (!dsc || (index >= dsc->bw_modifiers_count))
+    return 0;
+  return dsc->bw_modifiers[index].b_value;
+}
+
+fsdp_encryption_method_t
+fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_ENCRYPTION_METHOD_UNDEFINED;
+  return dsc->k_encryption_method;
+}
+
+const char *
+fsdp_get_media_encryption_content (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->k_encryption_content;
+}
+
+unsigned int
+fsdp_get_media_ptime (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_ptime;
+}
+
+unsigned int
+fsdp_get_media_maxptime (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_maxptime;
+}
+
+unsigned int
+fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->a_rtpmaps_count;
+}
+
+const char *
+fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t * mdsc,
+				    unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
+    return NULL;
+  return mdsc->a_rtpmaps[index]->pt;
+}
+
+const char *
+fsdp_get_media_rtpmap_encoding_name (const fsdp_media_description_t * mdsc,
+				     unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
+    return NULL;
+  return mdsc->a_rtpmaps[index]->encoding_name;
+}
+
+unsigned int
+fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc,
+				  unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
+    return 0;
+  return mdsc->a_rtpmaps[index]->clock_rate;
+}
+
+const char *
+fsdp_get_media_rtpmap_encoding_parameters (const fsdp_description_t * mdsc,
+					   unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_rtpmaps_count))
+    return NULL;
+  return mdsc->a_rtpmaps[index]->parameters;
+}
+
+unsigned int
+fsdp_get_media_sdplang_count (const fsdp_media_description_t * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->a_sdplangs_count;
+}
+
+const char *
+fsdp_get_media_sdplang (const fsdp_media_description_t * mdsc,
+			unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_sdplangs_count))
+    return NULL;
+  return mdsc->a_sdplangs[index];
+}
+
+unsigned int
+fsdp_get_media_lang_count (const fsdp_media_description_t * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->a_langs_count;
+}
+
+const char *
+fsdp_get_media_lang (const fsdp_media_description_t * mdsc,
+		     unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_langs_count))
+    return NULL;
+  return mdsc->a_langs[index];
+}
+
+unsigned int
+fsdp_get_media_control_count (const fsdp_media_description_t * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->a_controls_count;
+}
+
+char *
+fsdp_get_media_control (const fsdp_media_description_t * mdsc,
+			unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_controls_count))
+    return NULL;
+  return mdsc->a_controls[index];
+}
+
+char *
+fsdp_get_media_range (const fsdp_media_description_t * mdsc)
+{
+  return mdsc->a_range;
+}
+
+unsigned int
+fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->a_fmtps_count;
+}
+
+const char *
+fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc,
+		     unsigned int index)
+{
+  if (!mdsc || (index >= mdsc->a_fmtps_count))
+    return NULL;
+  return mdsc->a_fmtps[index];
+}
+
+fsdp_orient_t
+fsdp_get_media_orient (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_ORIENT_UNDEFINED;
+  return dsc->a_orient;
+}
+
+fsdp_sendrecv_mode_t
+fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_SENDRECV_UNDEFINED;
+  return dsc->a_sendrecv_mode;
+}
+
+float
+fsdp_get_media_framerate (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_framerate;
+}
+
+unsigned int
+fsdp_get_media_quality (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_quality;
+}
+
+unsigned int
+fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return 0;
+  return dsc->a_rtcp_port;
+}
+
+fsdp_network_type_t
+fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_NETWORK_TYPE_UNDEFINED;
+  return dsc->a_rtcp_network_type;
+}
+
+fsdp_address_type_t
+fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return FSDP_ADDRESS_TYPE_UNDEFINED;
+  return dsc->a_rtcp_address_type;
+}
+
+const char *
+fsdp_get_media_rtcp_address (const fsdp_media_description_t * dsc)
+{
+  if (!dsc)
+    return NULL;
+  return dsc->a_rtcp_address;
+}
+
+unsigned int
+fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t
+					     * mdsc)
+{
+  if (!mdsc)
+    return 0;
+  return mdsc->unidentified_attributes_count;
+}
+
+const char *
+fsdp_get_media_unidentified_attribute (const fsdp_media_description_t * mdsc,
+				       unsigned int index)
+{
+  if (!mdsc || (index < mdsc->unidentified_attributes_count))
+    return NULL;
+  return mdsc->unidentified_attributes[index];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/freesdp/parser.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,728 @@
+/*
+  This file is part of FreeSDP
+  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
+
+  FreeSDP is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU 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
+
+  Benjamin Zores, (C) 2006
+    added support in parser for the a=control: lines.
+    added support in parser for the a=range: lines.
+*/
+
+/**
+ * @file parser.h
+ * @ingroup parser
+ * @short Specific public header for parsing module.
+ **/
+
+#ifndef FSDP_PARSER_H
+#define FSDP_PARSER_H
+
+#include "common.h"
+
+BEGIN_C_DECLS
+/**
+ * @defgroup parser FreeSDP Parsing Module
+ *
+ * SDP descriptions parsing routines.
+ * @{
+ **/
+/**
+ * Parse a SDP description in <code>description</code>, extracting the
+ * session properties into <code>dsc</code>. These properties can be
+ * obtained individually later using the <code>fsdp_get_xxxx<code>
+ * functions.
+ *
+ * @param description a multimedia session description formatted in
+ * SDP.  
+ * @param dsc pointer that is updated to point to a fsdp_description_t
+ * object. This fsdp_description_t object should have been previously
+ * allocated using <code>fsdp_description_new()</code>; to free it,
+ * <code>fsdp_description_delete()</code> should be used.
+ *
+ * @return FSDPE_OK when parsing completes successfully. Otherwise,
+ * another error code is returned.
+ **/
+fsdp_error_t fsdp_parse (const char *description, fsdp_description_t * dsc);
+
+/**
+ * Get the SDP protocol version of the description.
+ *
+ * @return SDP protocol version number. 
+ **/
+unsigned int fsdp_get_version (const fsdp_description_t * dsc);
+
+/**
+ * Get the username provided by the originator of the session. 
+ *
+ * @param dsc SDP description object.
+ * @return username of the session owner
+ **/
+const char *fsdp_get_owner_username (const fsdp_description_t * dsc);
+
+/**
+ * Get the id for the session described in <code>dsc</code>. 
+ *
+ * @param dsc SDP description object.
+ * @return id string for this session.
+ **/
+const char *fsdp_get_session_id (const fsdp_description_t * dsc);
+
+/**
+ * Get the announcement version for the session description in
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @return announcement version string for this description.
+ **/
+const char *fsdp_get_announcement_version (const fsdp_description_t * dsc);
+
+/**
+ * Get the the type of network the owner of the session described in
+ * <code>dsc</code> is based on.
+ *
+ * @param dsc SDP description object.
+ * @return network type for the owner of this session.
+ **/
+fsdp_network_type_t
+fsdp_get_owner_network_type (const fsdp_description_t * dsc);
+
+/**
+ * Get the the type of address the owner of the session described in
+ * <code>dsc</code> is based on.
+ *
+ * @param dsc SDP description object.
+ * @return network address type for the owner of this session.
+ **/
+fsdp_address_type_t
+fsdp_get_owner_address_type (const fsdp_description_t * dsc);
+
+/**
+ * Get the network address of the owner of the session described in
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @return network address for the owner this session.
+ **/
+const char *fsdp_get_owner_address (const fsdp_description_t * dsc);
+
+/**
+ * Get the name of the session described in <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @return name of this session.
+ **/
+const char *fsdp_get_name (const fsdp_description_t * dsc);
+
+/**
+ * Get the information about the session provided in the description
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @return information of this session.
+ **/
+const char *fsdp_get_information (const fsdp_description_t * dsc);
+
+/**
+ * Get an URI about the session provided in the description
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @return string containing an URI about the session. NULL if the
+ * session uri is missing.
+ **/
+const char *fsdp_get_uri (const fsdp_description_t * dsc);
+
+/**
+ * Get the number of emails specified for the session in the description
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @return number of emails.
+ **/
+unsigned int fsdp_get_emails_count (const fsdp_description_t * dsc);
+
+/**
+ * Get the n-th email specified for the session in the description
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @param index number of URI. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_emails_count() - 1.
+ * @return string containing an email about the session. NULL if there
+ * is no such index.
+ **/
+const char *fsdp_get_email (const fsdp_description_t * dsc,
+			    unsigned int index);
+
+/**
+ * Get the number of phones specified for the session in the description
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @return number of emails.
+ **/
+unsigned int fsdp_get_phones_count (const fsdp_description_t * dsc);
+
+/**
+ * Get the n-th phone specified for the session in the description
+ * <code>dsc</code>.
+ *
+ * @param dsc SDP description object.
+ * @param index number of URI. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_phones_count() - 1.
+ * @return string containing a phone about the session. NULL if there
+ * is no such index.
+ **/
+const char *fsdp_get_phone (const fsdp_description_t * dsc,
+			    unsigned int index);
+
+/**
+ * Get the the global type of network of the multimedia session
+ * connection.
+ *
+ * @param dsc SDP description object.
+ * @return global network type for this
+ * connection. FSDP_NETWORK_TYPE_UNDEFINED if no global network
+ * address type is included in the description.
+ **/
+fsdp_network_type_t
+fsdp_get_global_conn_network_type (const fsdp_description_t * dsc);
+
+/**
+ * Get the the global type of network address of the multimedia
+ * session connection.
+ *
+ * @param dsc SDP description object.
+ * @return global network address type for this connection.
+ * FSDP_ADDRESS_TYPE_UNDEFINED if no global network address type is
+ * included in the description.
+ **/
+fsdp_address_type_t
+fsdp_get_global_conn_address_type (const fsdp_description_t * dsc);
+
+/**
+ * Get the the global address of the multimedia session connection.
+ *
+ * @param dsc SDP description object.
+ * @return global address for this connection.
+ **/
+const char *fsdp_get_global_conn_address (const fsdp_description_t * dsc);
+
+unsigned int
+fsdp_get_global_conn_address_ttl (const fsdp_description_t * dsc);
+
+unsigned int
+fsdp_get_global_conn_address_count (const fsdp_description_t * dsc);
+
+/**
+ * Get the number of bandwidth modifiers specified for this session.
+ *
+ * @param dsc SDP description object.
+ * @return number of bandwidth modifiers.
+ **/
+unsigned int fsdp_get_bw_modifier_count (const fsdp_description_t * dsc);
+
+/**
+ * Get the bandwidth modifier type for the session.
+ *
+ * @param dsc SDP description object.
+ * @param index number of bandwidth modifier.
+ *
+ * @return global bandwidth modifier type.  
+ * @retval FSDP_BW_MOD_TYPE_UNDEFINED if no global bandwith modifier
+ * type is defined or invalid index.
+ * @retval FSDP_BW_MOD_TYPE_UNKNOWN if an unknown bandwith modifier is
+ * specified or an invalid index is provided. In this case
+ * fsdp_get_bw_modifer_type_unknown() can be called to get the
+ * modifier as a character string.
+ **/
+fsdp_bw_modifier_type_t
+fsdp_get_bw_modifier_type (const fsdp_description_t * dsc,
+			   unsigned int index);
+
+/**
+ * Get the textual bandwidth modifier type when it is unknown. 
+ *
+ * @param dsc SDP description object.
+ * @param index number of bandwidth modifier.
+ *
+ * @return global bandwidth modifier type.
+ * @retval empty string if the provided bandwidth type is not unknown,
+ * the provided index is invalid or or there was a parse error.
+ **/
+const char *fsdp_get_bw_modifier_type_unknown (const fsdp_description_t * dsc,
+					       unsigned int index);
+
+/**
+ * Get the value for the bandwidth modifier. 
+ *
+ * @param dsc SDP description object.
+ * @param index number of bandwidth modifier.
+ * @return global bandwidth value.
+ * @retval 0 if no bandwidth is specified for this session or an
+ * invalid index has been provided.
+ **/
+unsigned long int
+fsdp_get_bw_value (const fsdp_description_t * dsc, unsigned int index);
+
+/**
+ * Get the number of time periods specified for this session
+ *
+ * @param dsc SDP description object.
+ * @return number of time periods
+ **/
+unsigned long int fsdp_get_period_count (const fsdp_description_t * dsc);
+
+/**
+ * Get the start time for the period selected by index.
+ *
+ * @param dsc SDP description object.
+ * @param index number of time period. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_period_count() - 1.
+ * @return start time
+ * @retval 0 if an invalid index is provided.
+ **/
+time_t
+fsdp_get_period_start (const fsdp_description_t * dsc, unsigned int index);
+
+/**
+ * Get the stop time for the period selected by index.
+ *
+ * @param dsc SDP description object.
+ * @param index number of time period. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_period_count() - 1.
+ * @return stop time
+ * @retval 0 if an invalid index is provided.
+ **/
+time_t
+fsdp_get_period_stop (const fsdp_description_t * dsc, unsigned int index);
+
+/**
+ * Get the number of repeats for the period selected by index.
+ *
+ * @param dsc SDP description object.
+ * @param index number of the period. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_period_count() - 1.
+ * @return number of repeats
+ * @retval 0 if an invalid index is provided.
+ **/
+unsigned int
+fsdp_get_period_repeats_count (const fsdp_description_t * dsc,
+			       unsigned int index);
+
+/**
+ * Get the interval time of the repeat selected by rindex for the
+ * period selected by index.
+ *
+ * @param dsc SDP description object.
+ * @param index number of time period. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_period_count() - 1.
+ * @param rindex number of repeat
+ * @return interval time
+ * @retval 0 if an invalid index is provided.
+ **/
+unsigned long int
+fsdp_get_period_repeat_interval (const fsdp_description_t * dsc,
+				 unsigned int index, unsigned int rindex);
+
+/**
+ * Get the duration of the repeat selected by rindex for the period
+ * selected by index.
+ *
+ * @param dsc SDP description object.
+ * @param index number of time period. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_period_count() - 1.
+ * @param rindex number of repeat
+ * @return duration
+ * @retval 0 if an invalid index is provided.
+ **/
+unsigned long int
+fsdp_get_period_repeat_duration (const fsdp_description_t * dsc,
+				 unsigned int index, unsigned int rindex);
+
+/**
+ * Get the offsets of the repeat selected by rindex for the period
+ * selected by index.
+ *
+ * @param dsc SDP description object.
+ * @param index number of time period. Note that this index follows the
+ * traditional C convention: from 0 to fsdp_get_period_count() - 1.
+ * @param rindex number of repeat
+ * @return array of offsets
+ * @retval NULL if an invalid index is provided.
+ **/
+const unsigned long int *fsdp_get_period_repeat_offsets (const
+							 fsdp_description_t *
+							 dsc,
+							 unsigned int index,
+							 unsigned int rindex);
+
+/**
+ * Get the encryption method defined for this session.
+ *
+ * @param dsc SDP description object.
+ * @return encryption method. FSDP_ENCRYPTION_METHOD_UNDEFINED if no
+ * encryption method is specified.
+ **/
+fsdp_encryption_method_t
+fsdp_get_encryption_method (const fsdp_description_t * dsc);
+
+/**
+ * Get the encryption key or a URI pointing to the encryption key for
+ * this session.
+ *
+ * @param dsc SDP description object.
+ * @return encryption key unless FSDP_ENCRYPTION_METHOD_URI is
+ * specified, in which case a URI pointing to the key is returned. If
+ * the global encryption method is undefined, NULL is returned.
+ **/
+const char *fsdp_get_encryption_content (const fsdp_description_t * dsc);
+
+/**
+ * Get timezone adjustments.
+ *
+ * @param dsc SDP description object.
+ * @return string with list of timezone adjustments
+ * @retval NULL if no timezone adjustment list was specified or there
+ * was a parse error.
+ **/
+const char *fsdp_get_timezone_adj (const fsdp_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int
+fsdp_get_unidentified_attribute_count (const fsdp_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_unidentified_attribute (const fsdp_description_t * dsc,
+					     unsigned int index);
+
+/**
+ *
+ **/
+unsigned int
+fsdp_get_media_rtpmap_count (const fsdp_media_description_t * mdsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_rtpmap_payload_type (const fsdp_media_description_t
+						* mdsc, unsigned int index);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_rtpmap_encoding_name (const
+						 fsdp_media_description_t *
+						 mdsc, unsigned int index);
+
+/**
+ *
+ **/
+unsigned int
+fsdp_get_media_rtpmap_clock_rate (const fsdp_media_description_t * mdsc,
+				  unsigned int index);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_rtpmap_encoding_parameters (const
+						       fsdp_description_t *
+						       mdsc,
+						       unsigned int index);
+
+/**
+ * Get the value of the session attribute specified in
+ * <code>att</code>. This function works for all the session
+ * attributes whose value is a character string. These attributes are
+ * defined in the session_string_attribute_t enumerated type.
+ *
+ * @param dsc SDP description object.
+ * @param att attribute to get.
+ *
+ * @return value of the attribute <code>att</code>.
+ * @retval NULL if the attribute was not specified or there was a
+ * parse error or an invalid att is given.
+ **/
+const char *fsdp_get_str_att (const fsdp_description_t * dsc,
+			      fsdp_session_str_att_t att);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_sdplang_count (const fsdp_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_sdplang (const fsdp_description_t * dsc,
+			      unsigned int index);
+
+/** 
+ * Get the mode of the conference, specified with attributes sendrecv,
+ * sendonly, recvonly and inactive.
+ *
+ * @param dsc SDP description object.
+ * @return send/rec conference mode.
+ * @retval FSDP_SENDRECV_UNDEFINED if conference mode not provided.
+ **/
+fsdp_sendrecv_mode_t fsdp_get_sendrecv_mode (const fsdp_description_t * dsc);
+
+/**
+ * Get the type of conference, such as broadcast, meeting, moderated,
+ * test or H332.
+ *
+ * @param dsc SDP description object.
+ * @return conference type.
+ * @retval FSDP_SESSION_TYPE_UNDEFINED if conference type not provided.
+ **/
+fsdp_session_type_t fsdp_get_session_type (const fsdp_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_media_count (const fsdp_description_t * dsc);
+
+/**
+ *
+ **/
+const fsdp_media_description_t *fsdp_get_media (const fsdp_description_t *
+						dsc, unsigned int index);
+
+/**
+ *
+ **/
+fsdp_media_t fsdp_get_media_type (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_media_port (const fsdp_media_description_t * dsc);
+
+unsigned int fsdp_get_media_port_count (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+fsdp_transport_protocol_t
+fsdp_get_media_transport_protocol (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_formats (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int
+fsdp_get_media_formats_count (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_format (const fsdp_media_description_t * dsc,
+				   unsigned int index);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_title (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+fsdp_network_type_t
+fsdp_get_media_network_type (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+fsdp_address_type_t
+fsdp_get_media_address_type (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_address (const fsdp_media_description_t * dsc);
+
+unsigned int
+fsdp_get_media_address_ttl (const fsdp_media_description_t * mdsc);
+
+unsigned int
+fsdp_get_media_address_count (const fsdp_media_description_t * mdsc);
+
+/**
+ *
+ **/
+fsdp_bw_modifier_type_t
+fsdp_get_media_bw_modifier_type (const fsdp_media_description_t * dsc,
+				 unsigned int index);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_bw_modifier_type_unknown (const
+						     fsdp_media_description_t
+						     * dsc,
+						     unsigned int index);
+
+/**
+ *
+ **/
+unsigned long int
+fsdp_get_media_bw_value (const fsdp_media_description_t * dsc,
+			 unsigned int index);
+
+/**
+ *
+ **/
+fsdp_encryption_method_t
+fsdp_get_media_encryption_method (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_encryption_content (const fsdp_media_description_t
+					       * dsc);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_media_ptime (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_media_maxptime (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int
+fsdp_get_media_fmtp_count (const fsdp_media_description_t * mdsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_fmtp (const fsdp_media_description_t * mdsc,
+				 unsigned int index);
+
+/**
+ *
+ **/
+unsigned int
+fsdp_get_media_sdplang_count (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_sdplang (const fsdp_media_description_t * dsc,
+				    unsigned int index);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_media_lang_count (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_lang (const fsdp_media_description_t * dsc,
+				 unsigned int index);
+
+
+unsigned int fsdp_get_control_count (const fsdp_description_t * dsc);
+
+const char *fsdp_get_control (const fsdp_description_t * dsc,
+			      unsigned int index);
+
+const char *fsdp_get_range (const fsdp_description_t * dsc);
+
+unsigned int
+fsdp_get_media_control_count (const fsdp_media_description_t * mdsc);
+
+char *fsdp_get_media_control (const fsdp_media_description_t * mdsc,
+			      unsigned int index);
+
+char *fsdp_get_media_range (const fsdp_media_description_t * mdsc);
+
+/**
+ *
+ **/
+fsdp_orient_t fsdp_get_media_orient (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+fsdp_sendrecv_mode_t
+fsdp_get_media_sendrecv (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+float fsdp_get_media_framerate (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_media_quality (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+unsigned int fsdp_get_media_rtcp_port (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+fsdp_network_type_t
+fsdp_get_media_rtcp_network_type (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+fsdp_address_type_t
+fsdp_get_media_rtcp_address_type (const fsdp_media_description_t * dsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_rtcp_address (const fsdp_media_description_t *
+					 dsc);
+
+/**
+ *
+ **/
+unsigned int
+fsdp_get_media_unidentified_attribute_count (const fsdp_media_description_t
+					     * mdsc);
+
+/**
+ *
+ **/
+const char *fsdp_get_media_unidentified_attribute (const
+						   fsdp_media_description_t *
+						   mdsc, unsigned int index);
+
+
+	  /** @} *//* closes parser group */
+
+END_C_DECLS
+#endif /* FSDP_PARSER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/freesdp/parserpriv.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,118 @@
+/*
+  This file is part of FreeSDP
+  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@suidzer0.org>
+
+  FreeSDP is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU 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
+*/
+
+/**
+ * @file parserpriv.h
+ *
+ * @short Private header for parser module.
+ **/
+
+#ifndef FSDP_PARSERPRIV_H
+#define FSDP_PARSERPRIV_H
+
+#include "priv.h"
+#include "parser.h"
+
+/**
+ * Parse a connection (c=<network type> <address type> <connection
+ * address>) line. If the textual description in <code>p</code> begins
+ * with a connection line, it is parsed. If not, nothing is done.
+ * 
+ * @param p fraction of textual SDP description.
+ * @param ntype where to store the network type.
+ * @param atype where to store the address type.
+ * @param address where to store the connection address as a string.
+ * 
+ * @return parse error code.
+ **/
+static fsdp_error_t
+fsdp_parse_c (const char **p, fsdp_network_type_t * ntype,
+	      fsdp_address_type_t * atype,
+	      fsdp_connection_address_t * address);
+
+/**
+ * Parse b (b=<modifier>:<bandwidth-value>) consecutive lines. If the
+ * textual description in <code>p</code> begins with a bandwidth line,
+ * it is parsed as well as all b lines inmediately after it. If not,
+ * nothing is done.
+ * 
+ * @param p fraction of textual SDP description.
+ * @param bw_modifiers pointer to empty array of bandwidth modifiers to fill.
+ * @param bw_modifiers_count where to set the number of bandwidth
+ *        modifiers successfully parsed.
+ *
+ * @return parse error code.
+ **/
+static fsdp_error_t
+fsdp_parse_b (const char **p, fsdp_bw_modifier_t ** bw_modifiers,
+	      unsigned int *bw_modifiers_count);
+
+/**
+ * Parse a k (k=<method>) or (k=<method>:<encryption key>) line. If
+ * the textual description in <code>p</code> begins with an encryption
+ * line, it is parsed. If not, nothing is done.
+ *
+ * @param p fraction of textual SDP description.
+ * @param method where to store the encryption method.
+ * @param content where to store the encryption key if provided.
+ *
+ * @return parse error code.
+ **/
+static fsdp_error_t
+fsdp_parse_k (const char **p, fsdp_encryption_method_t * method,
+	      char **content);
+
+
+/**
+ * Parses a string whose first token (first characters before the
+ * first space or end of string) is supposed to be a time in SDP
+ * syntax. Some examples of SDP times are: 2d, 5h, 3444, 7778s,
+ *
+ * @param time time in SDP syntax as a string.
+ * @param seconds where to store the value in seconds as an integer.
+ *
+ * @return parse error code.
+ **/
+static fsdp_error_t
+fsdp_repeat_time_to_uint (const char *time, unsigned long int *seconds);
+
+static fsdp_error_t
+fsdp_parse_rtpmap (fsdp_rtpmap_t *** rtpmap, unsigned int *counter,
+		   const char *value);
+
+/** 
+ * Maximun default field len for "expected to be short" fields, like
+ * username, session_id or inet addresses.
+ *
+ * MDFLENS value must be MAXSHORTFIELDLEN - 1 
+ **/
+#define MAXSHORTFIELDLEN 96
+#define MSFLENS "95"
+
+/**
+ * Maximun default field len for "maybe very long" fields, like
+ * information, attribute values. This can also be used for lines
+ * where there is only a string field, like phone and email.
+ *
+ * MLFLENS value must be MAXLONGFIELDLEN - 1
+ **/
+#define MAXLONGFIELDLEN 1024
+#define MLFLENS "1023"
+
+#endif /* FSDP_PARSERPRIV_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/freesdp/priv.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,274 @@
+/*
+  This file is part of FreeSDP
+  Copyright (C) 2001,2002,2003 Federico Montesino Pouzols <fedemp@altern.org>
+
+  FreeSDP is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU 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
+
+  Benjamin Zores, (C) 2006
+    added support in parser for the a=control: lines.
+    added support in parser for the a=range: lines.
+*/
+
+/**
+ * @file priv.h
+ *
+ * @short Common private header for both formatting and parsing modules.
+ **/
+
+#ifndef FSDP_PRIV_H
+#define FSDP_PRIV_H
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+#define NTP_EPOCH_OFFSET 2208988800UL
+
+#define FSDP_MAX_LENGTH 2000
+
+/* Tags for doxygen documentation */
+
+/**
+ * @mainpage FreeSDP Library Reference Manual
+ * @section overview Overview (README)
+ * @verbinclude ../../README
+ *
+ **/
+
+/**
+ * @example formatdemo.c
+ * 
+ * A basic SDP descriptions formatter based on FreeSDP.
+ **/
+
+/**
+ * @example parsedemo.c
+ * 
+ * A basic SDP descriptions parser based on FreeSDP.
+ **/
+
+/* Private routines declarations */
+
+BEGIN_C_DECLS
+/**
+ * @short bandwidth modifier
+ *
+ * Holds type of modifier and value. Also holds the literal bandwidth
+ * modifier if unknown.
+ **/
+  typedef struct
+{
+  fsdp_bw_modifier_type_t b_mod_type;
+  unsigned long int b_value;
+  char *b_unknown_bw_modt;
+} fsdp_bw_modifier_t;
+
+/**
+ * @short a=rtpmap: attribute
+ *
+ * Holds payload type, enconding name, RTP clock rate, and encofing
+ * parameters.
+ **/
+typedef struct
+{
+  char *pt;
+  char *encoding_name;
+  unsigned int clock_rate;
+  char *parameters;
+} fsdp_rtpmap_t;
+
+/**
+ * @short Connection address specification
+ *
+ * Holds address (unicast or multicast) as well as TTL and number of
+ * ports, when it is an IP4 multicast address.
+ **/
+typedef struct fsdp_connection_address_t_s
+{
+  char *address;
+  unsigned int address_ttl;
+  unsigned int address_count;
+} fsdp_connection_address_t;
+
+/**
+ * @short Struct for each media in a session description.
+ **/
+struct fsdp_media_description_t_s
+{
+  /* from `m=<media>  <port>  <transport> <fmt list>' line */
+  fsdp_media_t media_type;
+  unsigned int port;
+  unsigned int port_count;
+  fsdp_transport_protocol_t transport;
+  char **formats;
+  unsigned int formats_count;
+  /* from i=<media title> */
+  char *i_title;
+  /* from `c=<network type> <address type> <connection address>' line
+     (optional) */
+  fsdp_network_type_t c_network_type;
+  fsdp_address_type_t c_address_type;
+  fsdp_connection_address_t c_address;
+  /* from `b=<modifier>:<bandwidth-value>' lines (optional) */
+  fsdp_bw_modifier_t *bw_modifiers;
+  unsigned int bw_modifiers_count;
+  /* from `k=<method>' or `k=<method>:<encryption key>' line
+     (optional) */
+  fsdp_encryption_method_t k_encryption_method;
+  char *k_encryption_content;
+  /* from `a=<attribute>' or `a=<attribute>:<value>' lines (opt) */
+  unsigned long int a_ptime;
+  unsigned long int a_maxptime;
+  /* rtpmap */
+  fsdp_rtpmap_t **a_rtpmaps;
+  unsigned int a_rtpmaps_count;
+  fsdp_orient_t a_orient;
+  fsdp_sendrecv_mode_t a_sendrecv_mode;
+
+  char **a_sdplangs;
+  unsigned int a_sdplangs_count;
+  char **a_langs;
+  unsigned int a_langs_count;
+
+  char **a_controls;
+  unsigned int a_controls_count;
+
+  char *a_range;
+
+  float a_framerate;
+  unsigned int a_quality;
+  char **a_fmtps;
+  unsigned int a_fmtps_count;
+  /* rtcp attribute */
+  unsigned int a_rtcp_port;
+  fsdp_network_type_t a_rtcp_network_type;
+  fsdp_address_type_t a_rtcp_address_type;
+  char *a_rtcp_address;
+  /* media attributes that are not directly supported */
+  char **unidentified_attributes;
+  unsigned int unidentified_attributes_count;
+};
+
+typedef struct fsdp_media_description_t_s fsdp_media_announcement_t;
+
+/**
+ * @short Information for a repeat (struct for r= lines)
+ **/
+typedef struct
+{
+  /* times in seconds */
+  unsigned long int interval;
+  unsigned long int duration;
+  unsigned long int *offsets;
+  unsigned int offsets_count;
+} fsdp_repeat_t;
+
+/**
+ * @short Information about a time period
+ *
+ * The start and stop times as well as the information from the r=
+ * lines for a t= line are stored in this structures.
+ **/
+typedef struct
+{
+  time_t start;
+  time_t stop;
+  fsdp_repeat_t **repeats;
+  unsigned int repeats_count;
+} fsdp_time_period_t;
+
+/**
+ * @short Struct for session descriptions.
+ **/
+struct fsdp_description_t_s
+{
+  /* from v=... line */
+  unsigned int version;
+  /* from o=... line */
+  char *o_username;
+  char *o_session_id;
+  char *o_announcement_version;
+  fsdp_network_type_t o_network_type;
+  fsdp_address_type_t o_address_type;
+  char *o_address;
+  /* from s=... line */
+  char *s_name;
+  /* from i=... line (opt) */
+  char *i_information;
+  /* from u=... line (opt) */
+  char *u_uri;
+  /* from e=... lines (0 or more) */
+  const char **emails;
+  unsigned int emails_count;
+  /* from p=... lines (0 or more) */
+  const char **phones;
+  unsigned int phones_count;
+  /* from `c=<network type> <address type> <connection address>' line */
+  fsdp_network_type_t c_network_type;
+  fsdp_address_type_t c_address_type;
+  fsdp_connection_address_t c_address;
+  /* from `b=<modifier>:<bandwidth-value>' lines (optional) */
+  fsdp_bw_modifier_t *bw_modifiers;
+  unsigned int bw_modifiers_count;
+  /* from `t=<start time>  <stop time>' lines (1 or more) */
+  /* from `r=<repeat interval> <active duration> <list of offsets from
+     start-time>' */
+  fsdp_time_period_t **time_periods;
+  unsigned int time_periods_count;
+  /* from `z=<adjustment time> <offset> <adjustment time> <offset>
+     ....' lines */
+  char *timezone_adj;
+  /* from `k=<method>' or `k=<method>:<encryption key>' line (opt) */
+  fsdp_encryption_method_t k_encryption_method;
+  char *k_encryption_content;
+  /* from `a=<attribute>' or `a=<attribute>:<value>' lines (opt) */
+  char *a_category;
+  char *a_keywords;
+  char *a_tool;
+  char *a_range;
+  /* rtpmap */
+  fsdp_rtpmap_t **a_rtpmaps;
+  unsigned int a_rtpmaps_count;
+  fsdp_sendrecv_mode_t a_sendrecv_mode;
+  fsdp_session_type_t a_type;
+  char *a_charset;
+
+  char **a_sdplangs;
+  unsigned int a_sdplangs_count;
+  char **a_langs;
+  unsigned int a_langs_count;
+
+  char **a_controls;
+  unsigned int a_controls_count;
+  /* from `m=<media> <port>/<number of ports> <transport> <fmt list>'
+     lines [one or more] */
+  fsdp_media_announcement_t **media_announcements;
+  unsigned int media_announcements_count;
+  /* session attributes that are not directly supported */
+  char **unidentified_attributes;
+  unsigned int unidentified_attributes_count;
+};
+
+#define MEDIA_RTPMAPS_MAX_COUNT 5
+#define SDPLANGS_MAX_COUNT 5
+#define SDPCONTROLS_MAX_COUNT 10
+#define UNIDENTIFIED_ATTRIBUTES_MAX_COUNT 5
+
+END_C_DECLS
+#endif /* FSDP_PRIV_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/frequencies.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,1169 @@
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "frequencies.h"
+
+/* --------------------------------------------------------------------- */
+
+/* US broadcast */
+static const struct CHANLIST ntsc_bcast[] = {
+    { "2",	 55250 },
+    { "3",	 61250 },
+    { "4",	 67250 },
+    { "5",	 77250 },
+    { "6",	 83250 },
+    { "7",	175250 },
+    { "8",	181250 },
+    { "9",	187250 },
+    { "10",	193250 },
+    { "11",	199250 },
+    { "12",	205250 },
+    { "13",	211250 },
+    { "14",	471250 },
+    { "15",	477250 },
+    { "16",	483250 },
+    { "17",	489250 },
+    { "18",	495250 },
+    { "19",	501250 },
+    { "20",	507250 },
+    { "21",	513250 },
+    { "22",	519250 },
+    { "23",	525250 },
+    { "24",	531250 },
+    { "25",	537250 },
+    { "26",	543250 },
+    { "27",	549250 },
+    { "28",	555250 },
+    { "29",	561250 },
+    { "30",	567250 },
+    { "31",	573250 },
+    { "32",	579250 },
+    { "33",	585250 },
+    { "34",	591250 },
+    { "35",	597250 },
+    { "36",	603250 },
+    { "37",	609250 },
+    { "38",	615250 },
+    { "39",	621250 },
+    { "40",	627250 },
+    { "41",	633250 },
+    { "42",	639250 },
+    { "43",	645250 },
+    { "44",	651250 },
+    { "45",	657250 },
+    { "46",	663250 },
+    { "47",	669250 },
+    { "48",	675250 },
+    { "49",	681250 },
+    { "50",	687250 },
+    { "51",	693250 },
+    { "52",	699250 },
+    { "53",	705250 },
+    { "54",	711250 },
+    { "55",	717250 },
+    { "56",	723250 },
+    { "57",	729250 },
+    { "58",	735250 },
+    { "59",	741250 },
+    { "60",	747250 },
+    { "61",	753250 },
+    { "62",	759250 },
+    { "63",	765250 },
+    { "64",	771250 },
+    { "65",	777250 },
+    { "66",	783250 },
+    { "67",	789250 },
+    { "68",	795250 },
+    { "69",	801250 },
+ 
+    { "70",	807250 },
+    { "71",	813250 },
+    { "72",	819250 },
+    { "73",	825250 },
+    { "74",	831250 },
+    { "75",	837250 },
+    { "76",	843250 },
+    { "77",	849250 },
+    { "78",	855250 },
+    { "79",	861250 },
+    { "80",	867250 },
+    { "81",	873250 },
+    { "82",	879250 },
+    { "83",	885250 },
+};
+
+/* US cable */
+static const struct CHANLIST ntsc_cable[] = {
+    { "1",	 73250 },
+    { "2",	 55250 },
+    { "3",	 61250 },
+    { "4",	 67250 },
+    { "5",	 77250 },
+    { "6",	 83250 },
+    { "7",	175250 },
+    { "8",	181250 },
+    { "9",	187250 },
+    { "10",	193250 },
+    { "11",	199250 },
+    { "12",	205250 },
+
+    { "13",	211250 },
+    { "14",	121250 },
+    { "15",	127250 },
+    { "16",	133250 },
+    { "17",	139250 },
+    { "18",	145250 },
+    { "19",	151250 },
+    { "20",	157250 },
+ 
+    { "21",	163250 },
+    { "22",	169250 },
+    { "23",	217250 },
+    { "24",	223250 },
+    { "25",	229250 },
+    { "26",	235250 },
+    { "27",	241250 },
+    { "28",	247250 },
+    { "29",	253250 },
+    { "30",	259250 },
+    { "31",	265250 },
+    { "32",	271250 },
+    { "33",	277250 },
+    { "34",	283250 },
+    { "35",	289250 },
+    { "36",	295250 },
+    { "37",	301250 },
+    { "38",	307250 },
+    { "39",	313250 },
+    { "40",	319250 },
+    { "41",	325250 },
+    { "42",	331250 },
+    { "43",	337250 },
+    { "44",	343250 },
+    { "45",	349250 },
+    { "46",	355250 },
+    { "47",	361250 },
+    { "48",	367250 },
+    { "49",	373250 },
+    { "50",	379250 },
+    { "51",	385250 },
+    { "52",	391250 },
+    { "53",	397250 },
+    { "54",	403250 },
+    { "55",	409250 },
+    { "56",	415250 },
+    { "57",	421250 },
+    { "58",	427250 },
+    { "59",	433250 },
+    { "60",	439250 },
+    { "61",	445250 },
+    { "62",	451250 },
+    { "63",	457250 },
+    { "64",	463250 },
+    { "65",	469250 },
+    { "66",	475250 },
+    { "67",	481250 },
+    { "68",	487250 },
+    { "69",	493250 },
+ 
+    { "70",	499250 },
+    { "71",	505250 },
+    { "72",	511250 },
+    { "73",	517250 },
+    { "74",	523250 },
+    { "75",	529250 },
+    { "76",	535250 },
+    { "77",	541250 },
+    { "78",	547250 },
+    { "79",	553250 },
+    { "80",	559250 },
+    { "81",	565250 },
+    { "82",	571250 },
+    { "83",	577250 },
+    { "84",	583250 },
+    { "85",	589250 },
+    { "86",	595250 },
+    { "87",	601250 },
+    { "88",	607250 },
+    { "89",	613250 },
+    { "90",	619250 },
+    { "91",	625250 },
+    { "92",	631250 },
+    { "93",	637250 },
+    { "94",	643250 },
+    { "95",	 91250 },
+    { "96",	 97250 },
+    { "97",	103250 },
+    { "98",	109250 },
+    { "99",	115250 },
+    { "100",	649250 },
+    { "101",	655250 },
+    { "102",	661250 },
+    { "103",	667250 },
+    { "104",	673250 },
+    { "105",	679250 },
+    { "106",	685250 },
+    { "107",	691250 },
+    { "108",	697250 },
+    { "109",	703250 },
+    { "110",	709250 },
+    { "111",	715250 },
+    { "112",	721250 },
+    { "113",	727250 },
+    { "114",	733250 },
+    { "115",	739250 },
+    { "116",	745250 },
+    { "117",	751250 },
+    { "118",	757250 },
+    { "119",	763250 },
+    { "120",	769250 },
+    { "121",	775250 },
+    { "122",	781250 },
+    { "123",	787250 },
+    { "124",	793250 },
+    { "125",	799250 },
+ 
+    { "T7", 	  8250 },
+    { "T8",	 14250 },
+    { "T9",	 20250 },
+    { "T10",	 26250 },
+    { "T11",	 32250 },
+    { "T12",	 38250 },
+    { "T13",	 44250 },
+    { "T14",	 50250 }
+};
+
+/* US HRC */
+static const struct CHANLIST ntsc_hrc[] = {
+    { "1",	  72000 },
+    { "2",	  54000 }, 
+    { "3",	  60000 }, 
+    { "4",	  66000 }, 
+    { "5",	  78000 }, 
+    { "6",	  84000 }, 
+    { "7",	 174000 },
+    { "8",	 180000 },
+    { "9",	 186000 },
+    { "10",	 192000 },
+    { "11",	 198000 },
+    { "12",	 204000 },
+
+    { "13",	 210000 },
+    { "14",	 120000 },
+    { "15",	 126000 },
+    { "16",	 132000 },
+    { "17",	 138000 },
+    { "18",	 144000 },
+    { "19",	 150000 },
+    { "20",	 156000 },
+ 
+    { "21",	 162000 },
+    { "22",	 168000 },
+    { "23",	 216000 },
+    { "24",	 222000 },
+    { "25",	 228000 },
+    { "26",	 234000 },
+    { "27",	 240000 },
+    { "28",	 246000 },
+    { "29",	 252000 },
+    { "30",	 258000 },
+    { "31",	 264000 },
+    { "32",	 270000 },
+    { "33",	 276000 },
+    { "34",	 282000 },
+    { "35",	 288000 },
+    { "36",	 294000 },
+    { "37",	 300000 },
+    { "38",	 306000 },
+    { "39",	 312000 },
+    { "40",	 318000 },
+    { "41",	 324000 },
+    { "42",	 330000 },
+    { "43",	 336000 },
+    { "44",	 342000 },
+    { "45",	 348000 },
+    { "46",	 354000 },
+    { "47",	 360000 },
+    { "48",	 366000 },
+    { "49",	 372000 },
+    { "50",	 378000 },
+    { "51",	 384000 },
+    { "52",	 390000 },
+    { "53",	 396000 },
+    { "54",	 402000 },
+    { "55",	 408000 },
+    { "56",	 414000 },
+    { "57",	 420000 },
+    { "58",	 426000 },
+    { "59",	 432000 },
+    { "60",	 438000 },
+    { "61",	 444000 },
+    { "62",	 450000 },
+    { "63",	 456000 },
+    { "64",	 462000 },
+    { "65",	 468000 },
+    { "66",	 474000 },
+    { "67",	 480000 },
+    { "68",	 486000 },
+    { "69",	 492000 },
+ 
+    { "70",	 498000 },
+    { "71",	 504000 },
+    { "72",	 510000 },
+    { "73",	 516000 },
+    { "74",	 522000 },
+    { "75",	 528000 },
+    { "76",	 534000 },
+    { "77",	 540000 },
+    { "78",	 546000 },
+    { "79",	 552000 },
+    { "80",	 558000 },
+    { "81",	 564000 },
+    { "82",	 570000 },
+    { "83",	 576000 },
+    { "84",	 582000 },
+    { "85",	 588000 },
+    { "86",	 594000 },
+    { "87",	 600000 },
+    { "88",	 606000 },
+    { "89",	 612000 },
+    { "90",	 618000 },
+    { "91",	 624000 },
+    { "92",	 630000 },
+    { "93",	 636000 },
+    { "94",	 642000 },
+    { "95",	 900000 },
+    { "96",	 960000 },
+    { "97",	 102000 },
+    { "98",	 108000 },
+    { "99",	 114000 },
+    { "100",	 648000 },
+    { "101",	 654000 },
+    { "102",	 660000 },
+    { "103",	 666000 },
+    { "104",	 672000 },
+    { "105",	 678000 },
+    { "106",	 684000 },
+    { "107",	 690000 },
+    { "108",	 696000 },
+    { "109",	 702000 },
+    { "110",	 708000 },
+    { "111",	 714000 },
+    { "112",	 720000 },
+    { "113",	 726000 },
+    { "114",	 732000 },
+    { "115",	 738000 },
+    { "116",	 744000 },
+    { "117",	 750000 },
+    { "118",	 756000 },
+    { "119",	 762000 },
+    { "120",	 768000 },
+    { "121",	 774000 },
+    { "122",	 780000 },
+    { "123",	 786000 },
+    { "124",	 792000 },
+    { "125",	 798000 },
+ 
+    { "T7",	   7000 },  
+    { "T8",	  13000 }, 
+    { "T9",	  19000 }, 
+    { "T10",	  25000 }, 
+    { "T11",	  31000 }, 
+    { "T12",	  37000 }, 
+    { "T13",	  43000 }, 
+    { "T14",	  49000 }, 
+};
+
+/* --------------------------------------------------------------------- */
+
+/* JP broadcast */
+static const struct CHANLIST ntsc_bcast_jp[] = {
+    { "1",   91250 },
+    { "2",   97250 },
+    { "3",  103250 },
+    { "4",  171250 },
+    { "5",  177250 },
+    { "6",  183250 },
+    { "7",  189250 },
+    { "8",  193250 },
+    { "9",  199250 },
+    { "10", 205250 },
+    { "11", 211250 },
+    { "12", 217250 },
+
+    { "13", 471250 },
+    { "14", 477250 },
+    { "15", 483250 },
+    { "16", 489250 },
+    { "17", 495250 },
+    { "18", 501250 },
+    { "19", 507250 },
+    { "20", 513250 },
+    { "21", 519250 },
+    { "22", 525250 },
+    { "23", 531250 },
+    { "24", 537250 },
+    { "25", 543250 },
+    { "26", 549250 },
+    { "27", 555250 },
+    { "28", 561250 },
+    { "29", 567250 },
+    { "30", 573250 },
+    { "31", 579250 },
+    { "32", 585250 },
+    { "33", 591250 },
+    { "34", 597250 },
+    { "35", 603250 },
+    { "36", 609250 },
+    { "37", 615250 },
+    { "38", 621250 },
+    { "39", 627250 },
+    { "40", 633250 },
+    { "41", 639250 },
+    { "42", 645250 },
+    { "43", 651250 },
+    { "44", 657250 },
+
+    { "45", 663250 },
+    { "46", 669250 },
+    { "47", 675250 },
+    { "48", 681250 },
+    { "49", 687250 },
+    { "50", 693250 },
+    { "51", 699250 },
+    { "52", 705250 },
+    { "53", 711250 },
+    { "54", 717250 },
+    { "55", 723250 },
+    { "56", 729250 },
+    { "57", 735250 },
+    { "58", 741250 },
+    { "59", 747250 },
+    { "60", 753250 },
+    { "61", 759250 },
+    { "62", 765250 },
+};
+
+/* JP cable */
+static const struct CHANLIST ntsc_cable_jp[] = {
+    { "13",	109250 },
+    { "14",	115250 },
+    { "15",	121250 },
+    { "16",	127250 },
+    { "17",	133250 },
+    { "18",	139250 },
+    { "19",	145250 },
+    { "20",	151250 },
+ 
+    { "21",	157250 },
+    { "22",	165250 },
+    { "23",	223250 },
+    { "24",	231250 },
+    { "25",	237250 },
+    { "26",	243250 },
+    { "27",	249250 },
+    { "28",	253250 },
+    { "29",	259250 },
+    { "30",	265250 },
+    { "31",	271250 },
+    { "32",	277250 },
+    { "33",	283250 },
+    { "34",	289250 },
+    { "35",	295250 },
+    { "36",	301250 },
+    { "37",	307250 },
+    { "38",	313250 },
+    { "39",	319250 },
+    { "40",	325250 },
+    { "41",	331250 },
+    { "42",	337250 },
+    { "43",	343250 },
+    { "44",	349250 },
+    { "45", 	355250 },
+    { "46", 	361250 },
+    { "47", 	367250 },
+    { "48", 	373250 },
+    { "49", 	379250 },
+    { "50", 	385250 },
+    { "51", 	391250 },
+    { "52", 	397250 },
+    { "53", 	403250 },
+    { "54", 	409250 },
+    { "55", 	415250 },
+    { "56", 	421250 },
+    { "57", 	427250 },
+    { "58", 	433250 },
+    { "59", 	439250 },
+    { "60", 	445250 },
+    { "61", 	451250 },
+    { "62", 	457250 },
+    { "63",	463250 },
+};
+
+/* --------------------------------------------------------------------- */
+
+/* australia */
+static const struct CHANLIST pal_australia[] = {
+    { "0",	 46250 },
+    { "1",	 57250 },
+    { "2",	 64250 },
+    { "3",	 86250 },
+    { "4",  	 95250 },
+    { "5",  	102250 },
+    { "5A",  	138250 },
+    { "6",  	175250 },
+    { "7",  	182250 },
+    { "8",  	189250 },
+    { "9",  	196250 },
+    { "10", 	209250 },
+    { "11",	216250 },
+    { "28",	527250 },
+    { "29",	534250 },
+    { "30",	541250 },
+    { "31",	548250 },
+    { "32",	555250 },
+    { "33",	562250 },
+    { "34",	569250 },
+    { "35",	576250 },
+    { "36",     591250 },
+    { "39",	604250 },
+    { "40",	611250 },
+    { "41",	618250 },
+    { "42",	625250 },
+    { "43",	632250 },
+    { "44",	639250 },
+    { "45",	646250 },
+    { "46",	653250 },
+    { "47",	660250 },
+    { "48",	667250 },
+    { "49",	674250 },
+    { "50",	681250 },
+    { "51",	688250 },
+    { "52",	695250 },
+    { "53",	702250 },
+    { "54",	709250 },
+    { "55",	716250 },
+    { "56",	723250 },
+    { "57",	730250 },
+    { "58",	737250 },
+    { "59",	744250 },
+    { "60",	751250 },
+    { "61",	758250 },
+    { "62",	765250 },
+    { "63",	772250 },
+    { "64",	779250 },
+    { "65",	786250 },
+    { "66",	793250 },
+    { "67",	800250 },
+    { "68",	807250 },
+    { "69",	814250 },
+};
+
+/* --------------------------------------------------------------------- */
+/* europe                                                                */
+
+/* CCIR frequencies */
+
+#define FREQ_CCIR_I_III		\
+    { "E2",	  48250 },	\
+    { "E3",	  55250 },	\
+    { "E4",	  62250 },	\
+				\
+    { "S01",	  69250 },	\
+    { "S02",	  76250 },	\
+    { "S03",	  83250 },	\
+				\
+    { "E5",	 175250 },	\
+    { "E6",	 182250 },	\
+    { "E7",	 189250 },	\
+    { "E8",	 196250 },	\
+    { "E9",	 203250 },	\
+    { "E10",	 210250 },	\
+    { "E11",	 217250 },	\
+    { "E12",	 224250 }
+
+#define FREQ_CCIR_SL_SH		\
+    { "SE1",	 105250 },	\
+    { "SE2",	 112250 },	\
+    { "SE3",	 119250 },	\
+    { "SE4",	 126250 },	\
+    { "SE5",	 133250 },	\
+    { "SE6",	 140250 },	\
+    { "SE7",	 147250 },	\
+    { "SE8",	 154250 },	\
+    { "SE9",	 161250 },	\
+    { "SE10",    168250 },	\
+				\
+    { "SE11",    231250 },	\
+    { "SE12",    238250 },	\
+    { "SE13",    245250 },	\
+    { "SE14",    252250 },	\
+    { "SE15",    259250 },	\
+    { "SE16",    266250 },	\
+    { "SE17",    273250 },	\
+    { "SE18",    280250 },	\
+    { "SE19",    287250 },	\
+    { "SE20",    294250 }
+
+#define FREQ_CCIR_H	\
+    { "S21", 303250 },	\
+    { "S22", 311250 },	\
+    { "S23", 319250 },	\
+    { "S24", 327250 },	\
+    { "S25", 335250 },	\
+    { "S26", 343250 },	\
+    { "S27", 351250 },	\
+    { "S28", 359250 },	\
+    { "S29", 367250 },	\
+    { "S30", 375250 },	\
+    { "S31", 383250 },	\
+    { "S32", 391250 },	\
+    { "S33", 399250 },	\
+    { "S34", 407250 },	\
+    { "S35", 415250 },	\
+    { "S36", 423250 },	\
+    { "S37", 431250 },	\
+    { "S38", 439250 },	\
+    { "S39", 447250 },	\
+    { "S40", 455250 },	\
+    { "S41", 463250 }
+
+/* OIRT frequencies */
+
+#define FREQ_OIRT_I_III		\
+    { "R1",       49750 },	\
+    { "R2",       59250 },	\
+				\
+    { "R3",       77250 },	\
+    { "R4",       85250 },	\
+    { "R5",       93250 },	\
+				\
+    { "R6",	 175250 },	\
+    { "R7",	 183250 },	\
+    { "R8",	 191250 },	\
+    { "R9",	 199250 },	\
+    { "R10",	 207250 },	\
+    { "R11",	 215250 },	\
+    { "R12",	 223250 }
+
+#define FREQ_OIRT_SL_SH		\
+    { "SR1",	 111250 },	\
+    { "SR2",	 119250 },	\
+    { "SR3",	 127250 },	\
+    { "SR4",	 135250 },	\
+    { "SR5",	 143250 },	\
+    { "SR6",	 151250 },	\
+    { "SR7",	 159250 },	\
+    { "SR8",	 167250 },	\
+				\
+    { "SR11",    231250 },	\
+    { "SR12",    239250 },	\
+    { "SR13",    247250 },	\
+    { "SR14",    255250 },	\
+    { "SR15",    263250 },	\
+    { "SR16",    271250 },	\
+    { "SR17",    279250 },	\
+    { "SR18",    287250 },	\
+    { "SR19",    295250 }
+
+#define FREQ_UHF	\
+    { "21",  471250 },	\
+    { "22",  479250 },	\
+    { "23",  487250 },	\
+    { "24",  495250 },	\
+    { "25",  503250 },	\
+    { "26",  511250 },	\
+    { "27",  519250 },	\
+    { "28",  527250 },	\
+    { "29",  535250 },	\
+    { "30",  543250 },	\
+    { "31",  551250 },	\
+    { "32",  559250 },	\
+    { "33",  567250 },	\
+    { "34",  575250 },	\
+    { "35",  583250 },	\
+    { "36",  591250 },	\
+    { "37",  599250 },	\
+    { "38",  607250 },	\
+    { "39",  615250 },	\
+    { "40",  623250 },	\
+    { "41",  631250 },	\
+    { "42",  639250 },	\
+    { "43",  647250 },	\
+    { "44",  655250 },	\
+    { "45",  663250 },	\
+    { "46",  671250 },	\
+    { "47",  679250 },	\
+    { "48",  687250 },	\
+    { "49",  695250 },	\
+    { "50",  703250 },	\
+    { "51",  711250 },	\
+    { "52",  719250 },	\
+    { "53",  727250 },	\
+    { "54",  735250 },	\
+    { "55",  743250 },	\
+    { "56",  751250 },	\
+    { "57",  759250 },	\
+    { "58",  767250 },	\
+    { "59",  775250 },	\
+    { "60",  783250 },	\
+    { "61",  791250 },	\
+    { "62",  799250 },	\
+    { "63",  807250 },	\
+    { "64",  815250 },	\
+    { "65",  823250 },	\
+    { "66",  831250 },	\
+    { "67",  839250 },	\
+    { "68",  847250 },	\
+    { "69",  855250 }
+
+static const struct CHANLIST europe_west[] = {
+    FREQ_CCIR_I_III,
+    FREQ_CCIR_SL_SH,
+    FREQ_CCIR_H,
+    FREQ_UHF
+};
+
+static const struct CHANLIST europe_east[] = {
+    FREQ_OIRT_I_III,
+    FREQ_OIRT_SL_SH,
+    FREQ_CCIR_I_III,
+    FREQ_CCIR_SL_SH,
+    FREQ_CCIR_H,
+    FREQ_UHF
+};
+
+static const struct CHANLIST pal_italy[] = {
+    { "A",	 53750 },
+    { "B",	 62250 },
+    { "C",	 82250 },
+    { "D",	175250 },
+    { "E",	183750 },
+    { "F",	192250 },
+    { "G",	201250 },
+    { "H",	210250 },
+    { "H1",	217250 },
+    { "H2",	224250 },
+    FREQ_UHF
+};
+
+static const struct CHANLIST pal_ireland[] = {
+    { "0",    45750 },
+    { "1",    53750 },
+    { "2",    61750 },
+    { "3",   175250 },
+    { "4",   183250 },
+    { "5",   191250 },
+    { "6",   199250 },
+    { "7",   207250 },
+    { "8",   215250 },
+    FREQ_UHF,
+};
+
+static const struct CHANLIST secam_france[] = {
+    { "K01",    47750 },
+    { "K02",    55750 },
+    { "K03",    60500 },
+    { "K04",    63750 },
+    { "K05",   176000 },
+    { "K06",   184000 },
+    { "K07",   192000 },
+    { "K08",   200000 },
+    { "K09",   208000 },
+    { "K10",   216000 },
+    { "KB",    116750 },
+    { "KC",    128750 },
+    { "KD",    140750 },
+    { "KE",    159750 },
+    { "KF",    164750 },
+    { "KG",    176750 },
+    { "KH",    188750 },
+    { "KI",    200750 },
+    { "KJ",    212750 },
+    { "KK",    224750 },
+    { "KL",    236750 },
+    { "KM",    248750 },
+    { "KN",    260750 },
+    { "KO",    272750 },
+    { "KP",    284750 },
+    { "KQ",    296750 },
+    { "H01",   303250 },
+    { "H02",   311250 },
+    { "H03",   319250 },
+    { "H04",   327250 },
+    { "H05",   335250 },
+    { "H06",   343250 },
+    { "H07",   351250 },
+    { "H08",   359250 },
+    { "H09",   367250 },
+    { "H10",   375250 },
+    { "H11",   383250 },
+    { "H12",   391250 },
+    { "H13",   399250 },
+    { "H14",   407250 },
+    { "H15",   415250 },
+    { "H16",   423250 },
+    { "H17",   431250 },
+    { "H18",   439250 },
+    { "H19",   447250 },
+    FREQ_UHF,
+};
+
+/* --------------------------------------------------------------------- */
+
+static const struct CHANLIST pal_newzealand[] = {
+    { "1", 	  45250 }, 
+    { "2",	  55250 }, 
+    { "3",	  62250 },
+    { "4",	 175250 },
+    { "5",	 182250 },
+    { "6",	 189250 },
+    { "7",	 196250 },
+    { "8",	 203250 },
+    { "9",	 210250 },
+    { "10",	 217250 },
+    { "11",	 224250 },
+    FREQ_UHF,
+};
+
+/* --------------------------------------------------------------------- */
+
+/* China broadcast */
+static const struct CHANLIST pal_bcast_cn[] = {
+    { "1",	49750 },
+    { "2",	57750 },
+    { "3",	65750 },
+    { "4",	77250 },
+    { "5",	85250 },
+    { "6",	112250 },
+    { "7",	120250 },
+    { "8",	128250 },
+    { "9",	136250 },
+    { "10",	144250 },
+    { "11",	152250 },
+    { "12",	160250 },
+    { "13",	168250 },
+    { "14",	176250 },
+    { "15",	184250 },
+    { "16",	192250 },
+    { "17",	200250 },
+    { "18",	208250 },
+    { "19",	216250 },
+    { "20",	224250 },
+    { "21",	232250 },
+    { "22",	240250 },
+    { "23",	248250 },
+    { "24",	256250 },
+    { "25",	264250 },
+    { "26",	272250 },
+    { "27",	280250 },
+    { "28",	288250 },
+    { "29",	296250 },
+    { "30",	304250 },
+    { "31",	312250 },
+    { "32",	320250 },
+    { "33",	328250 },
+    { "34",	336250 },
+    { "35",	344250 },
+    { "36",	352250 },
+    { "37",	360250 },
+    { "38",	368250 },
+    { "39",	376250 },
+    { "40",	384250 },
+    { "41",	392250 },
+    { "42",	400250 },
+    { "43",	408250 },
+    { "44",	416250 },
+    { "45",	424250 },
+    { "46",	432250 },
+    { "47",	440250 },
+    { "48",	448250 },
+    { "49",	456250 },
+    { "50",	463250 },
+    { "51",	471250 },
+    { "52",	479250 },
+    { "53",	487250 },
+    { "54",	495250 },
+    { "55",	503250 },
+    { "56",	511250 },
+    { "57",	519250 },
+    { "58",	527250 },
+    { "59",	535250 },
+    { "60",	543250 },
+    { "61",	551250 },
+    { "62",	559250 },
+    { "63",	607250 },
+    { "64",	615250 },
+    { "65",	623250 },
+    { "66",	631250 },
+    { "67",	639250 },
+    { "68",	647250 },
+    { "69",	655250 },
+    { "70",	663250 },
+    { "71",	671250 },
+    { "72",	679250 },
+    { "73",	687250 },
+    { "74",	695250 },
+    { "75",	703250 },
+    { "76",	711250 },
+    { "77",	719250 },
+    { "78",	727250 },
+    { "79",	735250 },
+    { "80",	743250 },
+    { "81",	751250 },
+    { "82",	759250 },
+    { "83",	767250 },
+    { "84",	775250 },
+    { "85",	783250 },
+    { "86",	791250 },
+    { "87",	799250 },
+    { "88",	807250 },
+    { "89",	815250 },
+    { "90",	823250 },
+    { "91",	831250 },
+    { "92",	839250 },
+    { "93",	847250 },
+    { "94",	855250 },
+};
+
+/* --------------------------------------------------------------------- */
+/* South Africa Broadcast */
+
+static const struct CHANLIST pal_bcast_za[] ={
+    { "1", 175250 },
+    { "2", 183250 },
+    { "3", 191250 },
+    { "4", 199250 },
+    { "5", 207250 },
+    { "6", 215250 },
+    { "7", 223250 },
+    { "8", 231250 },
+    FREQ_UHF
+};
+
+/* --------------------------------------------------------------------- */
+
+static const struct CHANLIST argentina[] = {
+    { "001",   56250 },
+    { "002",   62250 },
+    { "003",   68250 },
+    { "004",   78250 },
+    { "005",   84250 },
+    { "006",  176250 },
+    { "007",  182250 },
+    { "008",  188250 },
+    { "009",  194250 },
+    { "010",  200250 },
+    { "011",  206250 },
+    { "012",  212250 },
+    { "013",  122250 },
+    { "014",  128250 },
+    { "015",  134250 },
+    { "016",  140250 },
+    { "017",  146250 },
+    { "018",  152250 },
+    { "019",  158250 },
+    { "020",  164250 },
+    { "021",  170250 },
+    { "022",  218250 },
+    { "023",  224250 },
+    { "024",  230250 },
+    { "025",  236250 },
+    { "026",  242250 },
+    { "027",  248250 },
+    { "028",  254250 },
+    { "029",  260250 },
+    { "030",  266250 },
+    { "031",  272250 },
+    { "032",  278250 },
+    { "033",  284250 },
+    { "034",  290250 },
+    { "035",  296250 },
+    { "036",  302250 },
+    { "037",  308250 },
+    { "038",  314250 },
+    { "039",  320250 },
+    { "040",  326250 },
+    { "041",  332250 },
+    { "042",  338250 },
+    { "043",  344250 },
+    { "044",  350250 },
+    { "045",  356250 },
+    { "046",  362250 },
+    { "047",  368250 },
+    { "048",  374250 },
+    { "049",  380250 },
+    { "050",  386250 },
+    { "051",  392250 },
+    { "052",  398250 },
+    { "053",  404250 },
+    { "054",  410250 },
+    { "055",  416250 },
+    { "056",  422250 },
+    { "057",  428250 },
+    { "058",  434250 },
+    { "059",  440250 },
+    { "060",  446250 },
+    { "061",  452250 },
+    { "062",  458250 },
+    { "063",  464250 },
+    { "064",  470250 },
+    { "065",  476250 },
+    { "066",  482250 },
+    { "067",  488250 },
+    { "068",  494250 },
+    { "069",  500250 },
+    { "070",  506250 },
+    { "071",  512250 },
+    { "072",  518250 },
+    { "073",  524250 },
+    { "074",  530250 },
+    { "075",  536250 },
+    { "076",  542250 },
+    { "077",  548250 },
+    { "078",  554250 },
+    { "079",  560250 },
+    { "080",  566250 },
+    { "081",  572250 },
+    { "082",  578250 },
+    { "083",  584250 },
+    { "084",  590250 },
+    { "085",  596250 },
+    { "086",  602250 },
+    { "087",  608250 },
+    { "088",  614250 },
+    { "089",  620250 },
+    { "090",  626250 },
+    { "091",  632250 },
+    { "092",  638250 },
+    { "093",  644250 },
+};
+
+/* --------------------------------------------------------------------- */
+
+static const struct CHANLIST russia[] = {
+    {"1",     49750 },
+    {"2",     59250 },
+    {"3",     77250 },
+    {"4",     85250 },
+    {"5",     93250 },
+    {"SK1",   111250 },
+    {"SK2",   119250 },
+    {"SK3",   127250 },
+    {"SK4",   135250 },
+    {"SK5",   143250 },
+    {"SK6",   151250 },
+    {"SK7",   159250 },
+    {"SK8",   167250 },
+    {"6",     175250 },
+    {"7",     183250 },
+    {"8",     191250 },
+    {"9",     199250 },
+    {"10",    207250 },
+    {"11",    215250 },
+    {"12",    223250 },
+    {"SK11",  231250 },
+    {"SK12",  239250 },
+    {"SK13",  247250 },
+    {"SK14",  255250 },
+    {"SK15",  263250 },
+    {"SK16",  271250 },
+    {"SK17",  279250 },
+    {"SK18",  287250 },
+    {"S19",   295250 },
+    {"S20",   303250 },
+    {"S21",   311250 },
+    {"S22",   319250 },
+    {"S23",   327250 },
+    {"S24",   335250 },
+    {"S25",   343250 },
+    {"S26",   351250 },
+    {"S27",   359250 },
+    {"S28",   367250 },
+    {"S29",   375250 },
+    {"S30",   383250 },
+    {"S31",   391250 },
+    {"S32",   399250 },
+    {"S33",   407250 },
+    {"S34",   415250 },
+    {"S35",   423250 },
+    {"S36",   431250 },
+    {"S37",   439250 },
+    {"S38",   447250 },
+    {"S39",   455250 },
+    {"S40",   463250 },
+    {"21",    471250 },
+    {"22",    479250 },
+    {"23",    487250 },
+    {"24",    495250 },
+    {"25",    503250 },
+    {"26",    511250 },
+    {"27",    519250 },
+    {"28",    527250 },
+    {"29",    535250 },
+    {"30",    543250 },
+    {"31",    551250 },
+    {"32",    559250 },
+    {"33",    567250 },
+    {"34",    575250 },
+    {"35",    583250 },
+    {"36",    591250 },
+    {"37",    599250 },
+    {"38",    607250 },
+    {"39",    615250 },
+    {"40",    623250 },
+    {"41",    631250 },
+    {"42",    639250 },
+    {"43",    647250 },
+    {"44",    655250 },
+    {"45",    663250 },
+    {"46",    671250 },
+    {"47",    679250 },
+    {"48",    687250 },
+    {"49",    695250 },
+    {"50",    703250 },
+    {"51",    711250 },
+    {"52",    719250 },
+    {"53",    727250 },
+    {"54",    735250 },
+    {"55",    743250 },
+    {"56",    751250 },
+    {"57",    759250 },
+    {"58",    767250 },
+    {"59",    775250 },
+    {"60",    783250 },
+    {"61",    791250 },
+    {"62",    799250 },
+    {"63",    807250 },
+    {"64",    815250 },
+    {"65",    523250 },
+    {"66",    831250 },
+    {"67",    839250 },
+    {"68",    847250 },
+    {"69",    855250 },
+};
+/* --------------------------------------------------------------------- */
+
+const struct CHANLISTS chanlists[] = {
+    { "us-bcast",         ntsc_bcast,        CHAN_COUNT(ntsc_bcast)        },
+    { "us-cable",         ntsc_cable,        CHAN_COUNT(ntsc_cable)        },
+    { "us-cable-hrc",     ntsc_hrc,          CHAN_COUNT(ntsc_hrc)          },
+    { "japan-bcast",      ntsc_bcast_jp,     CHAN_COUNT(ntsc_bcast_jp)     },
+    { "japan-cable",      ntsc_cable_jp,     CHAN_COUNT(ntsc_cable_jp)     },
+    { "europe-west",      europe_west,       CHAN_COUNT(europe_west)       },
+    { "europe-east",      europe_east,       CHAN_COUNT(europe_east)       },
+    { "italy",	          pal_italy,         CHAN_COUNT(pal_italy)         },
+    { "newzealand",       pal_newzealand,    CHAN_COUNT(pal_newzealand)    },
+    { "australia",        pal_australia,     CHAN_COUNT(pal_australia)     },
+    { "ireland",          pal_ireland,       CHAN_COUNT(pal_ireland)       },
+    { "france",           secam_france,      CHAN_COUNT(secam_france)      },
+    { "china-bcast",      pal_bcast_cn,      CHAN_COUNT(pal_bcast_cn)      },
+    { "southafrica",      pal_bcast_za,      CHAN_COUNT(pal_bcast_za)      },
+    { "argentina",        argentina,         CHAN_COUNT(argentina)         },
+    { "russia",           russia,            CHAN_COUNT(russia)            },
+    { NULL, NULL, 0 } /* EOF */
+};
+
+int                chantab   = 5;
+const struct CHANLIST *chanlist  = europe_west;
+int                chancount = CHAN_COUNT(europe_west);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/frequencies.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,111 @@
+/*
+ * Worldwide channel/frequency list
+ *
+ * Nathan Laredo (laredo@broked.net)
+ *
+ * Frequencies are given in kHz 
+ */
+#define NTSC_AUDIO_CARRIER	4500
+#define PAL_AUDIO_CARRIER_I	6000
+#define PAL_AUDIO_CARRIER_BGHN	5500
+#define PAL_AUDIO_CARRIER_MN	4500
+#define PAL_AUDIO_CARRIER_D	6500
+#define SEACAM_AUDIO_DKK1L	6500
+#define SEACAM_AUDIO_BG		5500
+/* NICAM 728 32-kHz, 14-bit digital stereo audio is transmitted in 1ms frames
+   containing 8 bits frame sync, 5 bits control, 11 bits additional data, and
+   704 bits audio data.  The bit rate is reduced by transmitting only 10 bits
+   plus parity of each 14 bit sample, the largest sample in a frame determines
+   which 10 bits are transmitted.  The parity bits for audio samples also 
+   specify the scaling factor used for that channel during that frame.  The
+   companeded audio data is interleaved to reduce the influence of dropouts
+   and the whole frame except for sync bits is scrambled for spectrum shaping.
+   Data is modulated using QPSK, at below following subcarrier freqs */
+#define NICAM728_PAL_BGH	5850
+#define NICAM728_PAL_I		6552
+
+/* COMPREHENSIVE LIST OF FORMAT BY COUNTRY
+   (M) NTSC used in:
+	Antigua, Aruba, Bahamas, Barbados, Belize, Bermuda, Bolivia, Burma,
+	Canada, Chile, Colombia, Costa Rica, Cuba, Curacao, Dominican Republic,
+	Ecuador, El Salvador, Guam Guatemala, Honduras, Jamaica, Japan,
+	South Korea, Mexico, Montserrat, Myanmar, Nicaragua, Panama, Peru,
+	Philippines, Puerto Rico, St Christopher and Nevis, Samoa, Suriname,
+	Taiwan, Trinidad/Tobago, United States, Venezuela, Virgin Islands
+   (B) PAL used in:
+	Albania, Algeria, Australia, Austria, Bahrain, Bangladesh, Belgium,
+	Bosnia-Herzegovinia, Brunei Darussalam, Cambodia, Cameroon, Croatia,
+	Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, Finland, Germany,
+	Ghana, Gibraltar, Greenland, Iceland, India, Indonesia, Israel, Italy,
+	Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysa, Maldives,
+	Malta, Nepal, Netherlands, New Zeland, Nigeria, Norway, Oman, Pakistan,
+	Papua New Guinea, Portugal, Qatar, Sao Tome and Principe, Saudi Arabia,
+	Seychelles, Sierra Leone, Singapore, Slovenia, Somali, Spain,
+	Sri Lanka, Sudan, Swaziland, Sweden, Switzeland, Syria, Thailand,
+	Tunisia, Turkey, Uganda, United Arab Emirates, Yemen
+   (N) PAL used in: (Combination N = 4.5MHz audio carrier, 3.58MHz burst)
+	Argentina (Combination N), Paraguay, Uruguay
+   (M) PAL (525/60, 3.57MHz burst) used in:
+	Brazil
+   (G) PAL used in:
+	Albania, Algeria, Austria, Bahrain, Bosnia/Herzegovinia, Cambodia,
+	Cameroon, Croatia, Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea,
+	Finland, Germany, Gibraltar, Greenland, Iceland, Israel, Italy, Jordan,
+	Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysia, Monaco,
+	Mozambique, Netherlands, New Zealand, Norway, Oman, Pakistan,
+	Papa New Guinea, Portugal, Qatar, Romania, Sierra Leone, Singapore,
+	Slovenia, Somalia, Spain, Sri Lanka, Sudan, Swaziland, Sweeden,
+	Switzerland, Syria, Thailand, Tunisia, Turkey, United Arab Emirates,
+	Yemen, Zambia, Zimbabwe
+   (D) PAL used in:
+	China, North Korea, Romania, Czech Republic
+   (H) PAL used in:
+	Belgium
+   (I) PAL used in:
+	Angola, Botswana, Gambia, Guinea-Bissau, Hong Kong, Ireland, Lesotho,
+	Malawi, Nambia, Nigeria, South Africa, Tanzania, United Kingdom,
+	Zanzibar
+   (B) SECAM used in:
+	Djibouti, Greece, Iran, Iraq, Lebanon, Mali, Mauritania, Mauritus,
+	Morocco
+   (D) SECAM used in:
+	Afghanistan, Armenia, Azerbaijan, Belarus, Bulgaria,
+	Estonia, Georgia, Hungary, Zazakhstan, Lithuania, Mongolia, Moldova,
+	Russia, Slovak Republic, Ukraine, Vietnam
+   (G) SECAM used in:
+	Greecem Iran, Iraq, Mali, Mauritus, Morocco, Saudi Arabia
+   (K) SECAM used in:
+	Armenia, Azerbaijan, Bulgaria, Estonia, Georgia,
+	Hungary, Kazakhstan, Lithuania, Madagascar, Moldova, Poland, Russia,
+	Slovak Republic, Ukraine, Vietnam
+   (K1) SECAM used in:
+	Benin, Burkina Faso, Burundi, Chad, Cape Verde, Central African
+	Republic, Comoros, Congo, Gabon, Madagascar, Niger, Rwanda, Senegal,
+	Togo, Zaire
+   (L) SECAM used in:
+	France
+*/
+
+/* --------------------------------------------------------------------- */
+
+struct CHANLIST {
+    char  name[8];
+    int   freq;
+};
+
+struct CHANLISTS {
+    const char             *name;
+    const struct CHANLIST  *list;
+    int                    count;
+};
+
+#define CHAN_COUNT(x) (sizeof(x)/sizeof(struct CHANLIST))
+
+/* --------------------------------------------------------------------- */
+
+extern const struct CHANLISTS   chanlists[];
+//extern struct STRTAB chanlist_names[];
+
+extern int                chantab;
+extern const struct CHANLIST *chanlist;
+extern int                chancount;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/http.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,948 @@
+/* 
+ * HTTP Helper
+ * by Bertrand Baudet <bertrand_baudet@yahoo.com>
+ * (C) 2001, MPlayer team.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#include "http.h"
+#include "url.h"
+#include "mp_msg.h"
+
+#include "stream.h"
+#include "demuxer.h"
+#include "network.h"
+#include "help_mp.h"
+
+
+extern mime_struct_t mime_type_table[];
+extern int stream_cache_size;
+extern int network_bandwidth;
+
+extern int http_seek(stream_t *stream, off_t pos);
+
+typedef struct {
+  unsigned metaint;
+  unsigned metapos;
+  int is_ultravox;
+} scast_data_t;
+
+/**
+ * \brief first read any data from sc->buffer then from fd
+ * \param fd file descriptor to read data from
+ * \param buffer buffer to read into
+ * \param len how many bytes to read
+ * \param sc streaming control containing buffer to read from first
+ * \return len unless there is a read error or eof
+ */
+static unsigned my_read(int fd, char *buffer, int len, streaming_ctrl_t *sc) {
+  unsigned pos = 0;
+  unsigned cp_len = sc->buffer_size - sc->buffer_pos;
+  if (cp_len > len)
+    cp_len = len;
+  memcpy(buffer, &sc->buffer[sc->buffer_pos], cp_len);
+  sc->buffer_pos += cp_len;
+  pos += cp_len;
+  while (pos < len) {
+    int ret = recv(fd, &buffer[pos], len - pos, 0);
+    if (ret <= 0)
+      break;
+    pos += ret;
+  }
+  return pos;
+}
+
+/**
+ * \brief read and process (i.e. discard *g*) a block of ultravox metadata
+ * \param fd file descriptor to read from
+ * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd
+ * \return number of real data before next metadata block starts or 0 on error
+ */
+static unsigned uvox_meta_read(int fd, streaming_ctrl_t *sc) {
+  unsigned metaint;
+  unsigned char info[6] = {0, 0, 0, 0, 0, 0};
+  int info_read;
+  do {
+    info_read = my_read(fd, info, 1, sc);
+    if (info[0] == 0x00)
+      info_read = my_read(fd, info, 6, sc);
+    else
+      info_read += my_read(fd, &info[1], 5, sc);
+    if (info_read != 6) // read error or eof
+      return 0;
+    // sync byte and reserved flags
+    if (info[0] != 0x5a || (info[1] & 0xfc) != 0x00) {
+      mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid or unknown uvox metadata\n");
+      return 0;
+    }
+    if (info[1] & 0x01)
+      mp_msg(MSGT_DEMUXER, MSGL_WARN, "Encrypted ultravox data\n");
+    metaint = info[4] << 8 | info[5];
+    if ((info[3] & 0xf) < 0x07) { // discard any metadata nonsense
+      char *metabuf = malloc(metaint);
+      my_read(fd, metabuf, metaint, sc);
+      free(metabuf);
+    }
+  } while ((info[3] & 0xf) < 0x07);
+  return metaint;
+}
+
+/**
+ * \brief read one scast meta data entry and print it
+ * \param fd file descriptor to read from
+ * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd
+ */
+static void scast_meta_read(int fd, streaming_ctrl_t *sc) {
+  unsigned char tmp = 0;
+  unsigned metalen;
+  my_read(fd, &tmp, 1, sc);
+  metalen = tmp * 16;
+  if (metalen > 0) {
+    char *info = malloc(metalen + 1);
+    unsigned nlen = my_read(fd, info, metalen, sc);
+    info[nlen] = 0;
+    mp_msg(MSGT_DEMUXER, MSGL_INFO, "\nICY Info: %s\n", info);
+    free(info);
+  }
+}
+
+/**
+ * \brief read data from scast/ultravox stream without any metadata
+ * \param fd file descriptor to read from
+ * \param buffer buffer to read data into
+ * \param size number of bytes to read
+ * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd
+ */
+static int scast_streaming_read(int fd, char *buffer, int size,
+                                streaming_ctrl_t *sc) {
+  scast_data_t *sd = (scast_data_t *)sc->data;
+  unsigned block, ret;
+  unsigned done = 0;
+
+  // first read remaining data up to next metadata
+  block = sd->metaint - sd->metapos;
+  if (block > size)
+    block = size;
+  ret = my_read(fd, buffer, block, sc);
+  sd->metapos += ret;
+  done += ret;
+  if (ret != block) // read problems or eof
+    size = done;
+
+  while (done < size) { // now comes the metadata
+    if (sd->is_ultravox)
+    {
+      sd->metaint = uvox_meta_read(fd, sc);
+      if (!sd->metaint)
+        size = done;
+    }
+    else
+      scast_meta_read(fd, sc); // read and display metadata
+    sd->metapos = 0;
+    block = size - done;
+    if (block > sd->metaint)
+      block = sd->metaint;
+    ret = my_read(fd, &buffer[done], block, sc);
+    sd->metapos += ret;
+    done += ret;
+    if (ret != block) // read problems or eof
+      size = done;
+  }
+  return done;
+}
+
+static int scast_streaming_start(stream_t *stream) {
+  int metaint;
+  scast_data_t *scast_data;
+  HTTP_header_t *http_hdr = stream->streaming_ctrl->data;
+  int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0;
+  if (!stream || stream->fd < 0 || !http_hdr)
+    return -1;
+  if (is_ultravox)
+    metaint = 0;
+  else {
+    metaint = atoi(http_get_field(http_hdr, "Icy-MetaInt"));
+    if (metaint <= 0)
+      return -1;
+  }
+  stream->streaming_ctrl->buffer = malloc(http_hdr->body_size);
+  stream->streaming_ctrl->buffer_size = http_hdr->body_size;
+  stream->streaming_ctrl->buffer_pos = 0;
+  memcpy(stream->streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size);
+  scast_data = malloc(sizeof(scast_data_t));
+  scast_data->metaint = metaint;
+  scast_data->metapos = 0;
+  scast_data->is_ultravox = is_ultravox;
+  http_free(http_hdr);
+  stream->streaming_ctrl->data = scast_data;
+  stream->streaming_ctrl->streaming_read = scast_streaming_read;
+  stream->streaming_ctrl->streaming_seek = NULL;
+  stream->streaming_ctrl->prebuffer_size = 64 * 1024; // 64 KBytes
+  stream->streaming_ctrl->buffering = 1;
+  stream->streaming_ctrl->status = streaming_playing_e;
+  return 0;
+}
+
+static int nop_streaming_start( stream_t *stream ) {
+	HTTP_header_t *http_hdr = NULL;
+	char *next_url=NULL;
+	URL_t *rd_url=NULL;
+	int fd,ret;
+	if( stream==NULL ) return -1;
+
+	fd = stream->fd;
+	if( fd<0 ) {
+		fd = http_send_request( stream->streaming_ctrl->url, 0 ); 
+		if( fd<0 ) return -1;
+		http_hdr = http_read_response( fd );
+		if( http_hdr==NULL ) return -1;
+
+		switch( http_hdr->status_code ) {
+			case 200: // OK
+				mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") );
+				mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") );
+				if( http_hdr->body_size>0 ) {
+					if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
+						http_free( http_hdr );
+						return -1;
+					}
+				}
+				break;
+			// Redirect
+			case 301: // Permanently
+			case 302: // Temporarily
+				ret=-1;
+				next_url = http_get_field( http_hdr, "Location" );
+
+				if (next_url != NULL)
+					rd_url=url_new(next_url);
+
+				if (next_url != NULL && rd_url != NULL) {
+					mp_msg(MSGT_NETWORK,MSGL_STATUS,"Redirected: Using this url instead %s\n",next_url);
+							stream->streaming_ctrl->url=check4proxies(rd_url);
+					ret=nop_streaming_start(stream); //recursively get streaming started 
+				} else {
+					mp_msg(MSGT_NETWORK,MSGL_ERR,"Redirection failed\n");
+					closesocket( fd );
+					fd = -1;
+				}
+				return ret;
+				break;
+			case 401: //Authorization required
+			case 403: //Forbidden
+			case 404: //Not found
+			case 500: //Server Error
+			default:
+				mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned code %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase );
+				closesocket( fd );
+				fd = -1;
+				return -1;
+				break;
+		}
+		stream->fd = fd;
+	} else {
+		http_hdr = (HTTP_header_t*)stream->streaming_ctrl->data;
+		if( http_hdr->body_size>0 ) {
+			if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
+				http_free( http_hdr );
+				stream->streaming_ctrl->data = NULL;
+				return -1;
+			}
+		}
+	}
+
+	if( http_hdr ) {
+		http_free( http_hdr );
+		stream->streaming_ctrl->data = NULL;
+	}
+
+	stream->streaming_ctrl->streaming_read = nop_streaming_read;
+	stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
+	stream->streaming_ctrl->prebuffer_size = 64*1024; // 64 KBytes
+	stream->streaming_ctrl->buffering = 1;
+	stream->streaming_ctrl->status = streaming_playing_e;
+	return 0;
+}
+
+HTTP_header_t *
+http_new_header(void) {
+	HTTP_header_t *http_hdr;
+
+	http_hdr = malloc(sizeof(HTTP_header_t));
+	if( http_hdr==NULL ) return NULL;
+	memset( http_hdr, 0, sizeof(HTTP_header_t) );
+
+	return http_hdr;
+}
+
+void
+http_free( HTTP_header_t *http_hdr ) {
+	HTTP_field_t *field, *field2free;
+	if( http_hdr==NULL ) return;
+	if( http_hdr->protocol!=NULL ) free( http_hdr->protocol );
+	if( http_hdr->uri!=NULL ) free( http_hdr->uri );
+	if( http_hdr->reason_phrase!=NULL ) free( http_hdr->reason_phrase );
+	if( http_hdr->field_search!=NULL ) free( http_hdr->field_search );
+	if( http_hdr->method!=NULL ) free( http_hdr->method );
+	if( http_hdr->buffer!=NULL ) free( http_hdr->buffer );
+	field = http_hdr->first_field;
+	while( field!=NULL ) {
+		field2free = field;
+		if (field->field_name)
+		  free(field->field_name);
+		field = field->next;
+		free( field2free );
+	}
+	free( http_hdr );
+	http_hdr = NULL;
+}
+
+int
+http_response_append( HTTP_header_t *http_hdr, char *response, int length ) {
+	if( http_hdr==NULL || response==NULL || length<0 ) return -1;
+
+	if( (unsigned)length > SIZE_MAX - http_hdr->buffer_size - 1) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Bad size in memory (re)allocation\n");
+		return -1;
+	}
+	http_hdr->buffer = (char*)realloc( http_hdr->buffer, http_hdr->buffer_size+length+1 );
+	if( http_hdr->buffer==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory (re)allocation failed\n");
+		return -1;
+	}
+	memcpy( http_hdr->buffer+http_hdr->buffer_size, response, length );
+	http_hdr->buffer_size += length;
+	http_hdr->buffer[http_hdr->buffer_size]=0; // close the string!
+	return http_hdr->buffer_size;
+}
+
+int
+http_is_header_entire( HTTP_header_t *http_hdr ) {
+	if( http_hdr==NULL ) return -1;
+	if( http_hdr->buffer==NULL ) return 0; // empty
+	
+	if( strstr(http_hdr->buffer, "\r\n\r\n")==NULL &&
+	    strstr(http_hdr->buffer, "\n\n")==NULL ) return 0;
+	return 1;
+}
+
+int
+http_response_parse( HTTP_header_t *http_hdr ) {
+	char *hdr_ptr, *ptr;
+	char *field=NULL;
+	int pos_hdr_sep, hdr_sep_len;
+	size_t len;
+	if( http_hdr==NULL ) return -1;
+	if( http_hdr->is_parsed ) return 0;
+
+	// Get the protocol
+	hdr_ptr = strstr( http_hdr->buffer, " " );
+	if( hdr_ptr==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. No space separator found.\n");
+		return -1;
+	}
+	len = hdr_ptr-http_hdr->buffer;
+	http_hdr->protocol = malloc(len+1);
+	if( http_hdr->protocol==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		return -1;
+	}
+	strncpy( http_hdr->protocol, http_hdr->buffer, len );
+	http_hdr->protocol[len]='\0';
+	if( !strncasecmp( http_hdr->protocol, "HTTP", 4) ) {
+		if( sscanf( http_hdr->protocol+5,"1.%d", &(http_hdr->http_minor_version) )!=1 ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get HTTP minor version.\n");
+			return -1;
+		}
+	}
+
+	// Get the status code
+	if( sscanf( ++hdr_ptr, "%d", &(http_hdr->status_code) )!=1 ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get status code.\n");
+		return -1;
+	}
+	hdr_ptr += 4;
+
+	// Get the reason phrase
+	ptr = strstr( hdr_ptr, "\n" );
+	if( hdr_ptr==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get the reason phrase.\n");
+		return -1;
+	}
+	len = ptr-hdr_ptr;
+	http_hdr->reason_phrase = malloc(len+1);
+	if( http_hdr->reason_phrase==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		return -1;
+	}
+	strncpy( http_hdr->reason_phrase, hdr_ptr, len );
+	if( http_hdr->reason_phrase[len-1]=='\r' ) {
+		len--;
+	}
+	http_hdr->reason_phrase[len]='\0';
+
+	// Set the position of the header separator: \r\n\r\n
+	hdr_sep_len = 4;
+	ptr = strstr( http_hdr->buffer, "\r\n\r\n" );
+	if( ptr==NULL ) {
+		ptr = strstr( http_hdr->buffer, "\n\n" );
+		if( ptr==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"Header may be incomplete. No CRLF CRLF found.\n");
+			return -1;
+		}
+		hdr_sep_len = 2;
+	}
+	pos_hdr_sep = ptr-http_hdr->buffer;
+
+	// Point to the first line after the method line.
+	hdr_ptr = strstr( http_hdr->buffer, "\n" )+1;
+	do {
+		ptr = hdr_ptr;
+		while( *ptr!='\r' && *ptr!='\n' ) ptr++;
+		len = ptr-hdr_ptr;
+		if( len==0 ) break;
+		field = (char*)realloc(field, len+1);
+		if( field==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n");
+			return -1;
+		}
+		strncpy( field, hdr_ptr, len );
+		field[len]='\0';
+		http_set_field( http_hdr, field );
+		hdr_ptr = ptr+((*ptr=='\r')?2:1);
+	} while( hdr_ptr<(http_hdr->buffer+pos_hdr_sep) );
+	
+	if( field!=NULL ) free( field );
+
+	if( pos_hdr_sep+hdr_sep_len<http_hdr->buffer_size ) {
+		// Response has data!
+		http_hdr->body = http_hdr->buffer+pos_hdr_sep+hdr_sep_len;
+		http_hdr->body_size = http_hdr->buffer_size-(pos_hdr_sep+hdr_sep_len);
+	}
+
+	http_hdr->is_parsed = 1;
+	return 0;
+}
+
+char *
+http_build_request( HTTP_header_t *http_hdr ) {
+	char *ptr, *uri=NULL;
+	int len;
+	HTTP_field_t *field;
+	if( http_hdr==NULL ) return NULL;
+
+	if( http_hdr->method==NULL ) http_set_method( http_hdr, "GET");
+	if( http_hdr->uri==NULL ) http_set_uri( http_hdr, "/");
+	else {
+		uri = malloc(strlen(http_hdr->uri) + 1);
+		if( uri==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n");
+			return NULL;
+		}
+		strcpy(uri,http_hdr->uri);
+	}
+
+	//**** Compute the request length
+	// Add the Method line
+	len = strlen(http_hdr->method)+strlen(uri)+12;
+	// Add the fields
+	field = http_hdr->first_field; 
+	while( field!=NULL ) {
+		len += strlen(field->field_name)+2;
+		field = field->next;
+	}
+	// Add the CRLF
+	len += 2;
+	// Add the body
+	if( http_hdr->body!=NULL ) {
+		len += http_hdr->body_size;
+	}
+	// Free the buffer if it was previously used
+	if( http_hdr->buffer!=NULL ) {
+		free( http_hdr->buffer );
+		http_hdr->buffer = NULL;
+	}
+	http_hdr->buffer = malloc(len+1);
+	if( http_hdr->buffer==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n");
+		return NULL;
+	}
+	http_hdr->buffer_size = len;
+
+	//*** Building the request
+	ptr = http_hdr->buffer;
+	// Add the method line
+	ptr += sprintf( ptr, "%s %s HTTP/1.%d\r\n", http_hdr->method, uri, http_hdr->http_minor_version );
+	field = http_hdr->first_field;
+	// Add the field
+	while( field!=NULL ) {
+		ptr += sprintf( ptr, "%s\r\n", field->field_name );
+		field = field->next;
+	}
+	ptr += sprintf( ptr, "\r\n" );
+	// Add the body
+	if( http_hdr->body!=NULL ) {
+		memcpy( ptr, http_hdr->body, http_hdr->body_size );
+	}
+
+	if( uri ) free( uri );
+	return http_hdr->buffer;	
+}
+
+char *
+http_get_field( HTTP_header_t *http_hdr, const char *field_name ) {
+	if( http_hdr==NULL || field_name==NULL ) return NULL;
+	http_hdr->field_search_pos = http_hdr->first_field;
+	http_hdr->field_search = (char*)realloc( http_hdr->field_search, strlen(field_name)+1 );
+	if( http_hdr->field_search==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		return NULL;
+	}
+	strcpy( http_hdr->field_search, field_name );
+	return http_get_next_field( http_hdr );
+}
+
+char *
+http_get_next_field( HTTP_header_t *http_hdr ) {
+	char *ptr;
+	HTTP_field_t *field;
+	if( http_hdr==NULL ) return NULL;
+
+	field = http_hdr->field_search_pos;
+	while( field!=NULL ) { 
+		ptr = strstr( field->field_name, ":" );
+		if( ptr==NULL ) return NULL;
+		if( !strncasecmp( field->field_name, http_hdr->field_search, ptr-(field->field_name) ) ) {
+			ptr++;	// Skip the column
+			while( ptr[0]==' ' ) ptr++; // Skip the spaces if there is some
+			http_hdr->field_search_pos = field->next;
+			return ptr;	// return the value without the field name
+		}
+		field = field->next;
+	}
+	return NULL;
+}
+
+void
+http_set_field( HTTP_header_t *http_hdr, const char *field_name ) {
+	HTTP_field_t *new_field;
+	if( http_hdr==NULL || field_name==NULL ) return;
+
+	new_field = malloc(sizeof(HTTP_field_t));
+	if( new_field==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		return;
+	}
+	new_field->next = NULL;
+	new_field->field_name = malloc(strlen(field_name)+1);
+	if( new_field->field_name==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		return;
+	}
+	strcpy( new_field->field_name, field_name );
+
+	if( http_hdr->last_field==NULL ) {
+		http_hdr->first_field = new_field;
+	} else {
+		http_hdr->last_field->next = new_field;
+	}
+	http_hdr->last_field = new_field;
+	http_hdr->field_nb++;
+}
+
+void
+http_set_method( HTTP_header_t *http_hdr, const char *method ) {
+	if( http_hdr==NULL || method==NULL ) return;
+
+	http_hdr->method = malloc(strlen(method)+1);
+	if( http_hdr->method==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		return;
+	}
+	strcpy( http_hdr->method, method );
+}
+
+void
+http_set_uri( HTTP_header_t *http_hdr, const char *uri ) {
+	if( http_hdr==NULL || uri==NULL ) return;
+
+	http_hdr->uri = malloc(strlen(uri)+1);
+	if( http_hdr->uri==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		return;
+	}
+	strcpy( http_hdr->uri, uri );
+}
+
+int
+http_add_basic_authentication( HTTP_header_t *http_hdr, const char *username, const char *password ) {
+	char *auth = NULL, *usr_pass = NULL, *b64_usr_pass = NULL;
+	int encoded_len, pass_len=0, out_len;
+	int res = -1;
+	if( http_hdr==NULL || username==NULL ) return -1;
+
+	if( password!=NULL ) {
+		pass_len = strlen(password);
+	}
+	
+	usr_pass = malloc(strlen(username)+pass_len+2);
+	if( usr_pass==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		goto out;
+	}
+
+	sprintf( usr_pass, "%s:%s", username, (password==NULL)?"":password );
+
+	// Base 64 encode with at least 33% more data than the original size
+	encoded_len = strlen(usr_pass)*2;
+	b64_usr_pass = malloc(encoded_len);
+	if( b64_usr_pass==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		goto out;
+	}
+
+	out_len = base64_encode( usr_pass, strlen(usr_pass), b64_usr_pass, encoded_len);
+	if( out_len<0 ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Base64 out overflow\n");
+		goto out;
+	}
+
+	b64_usr_pass[out_len]='\0';
+	
+	auth = malloc(encoded_len+22);
+	if( auth==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n");
+		goto out;
+	}
+	
+	sprintf( auth, "Authorization: Basic %s", b64_usr_pass);
+	http_set_field( http_hdr, auth );
+	res = 0;
+	
+out:
+	free( usr_pass );
+	free( b64_usr_pass );
+	free( auth );
+	
+	return res;
+}
+
+void
+http_debug_hdr( HTTP_header_t *http_hdr ) {
+	HTTP_field_t *field;
+	int i = 0;
+	if( http_hdr==NULL ) return;
+
+	mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- START ---\n");
+	mp_msg(MSGT_NETWORK,MSGL_V,"protocol:           [%s]\n", http_hdr->protocol );
+	mp_msg(MSGT_NETWORK,MSGL_V,"http minor version: [%d]\n", http_hdr->http_minor_version );
+	mp_msg(MSGT_NETWORK,MSGL_V,"uri:                [%s]\n", http_hdr->uri );
+	mp_msg(MSGT_NETWORK,MSGL_V,"method:             [%s]\n", http_hdr->method );
+	mp_msg(MSGT_NETWORK,MSGL_V,"status code:        [%d]\n", http_hdr->status_code );
+	mp_msg(MSGT_NETWORK,MSGL_V,"reason phrase:      [%s]\n", http_hdr->reason_phrase );
+	mp_msg(MSGT_NETWORK,MSGL_V,"body size:          [%d]\n", http_hdr->body_size );
+
+	mp_msg(MSGT_NETWORK,MSGL_V,"Fields:\n");
+	field = http_hdr->first_field;
+	while( field!=NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_V," %d - %s\n", i++, field->field_name );
+		field = field->next;
+	}
+	mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- END ---\n");
+}
+
+int 
+base64_encode(const void *enc, int encLen, char *out, int outMax) {
+	static const char	b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+	unsigned char		*encBuf;
+	int			outLen;
+	unsigned int		bits;
+	unsigned int		shift;
+
+	encBuf = (unsigned char*)enc;
+	outLen = 0;
+	bits = 0;
+	shift = 0;
+	outMax &= ~3;
+
+	while( outLen<outMax ) {
+		if( encLen>0 ) {
+			// Shift in byte
+			bits <<= 8;
+			bits |= *encBuf;
+			shift += 8;
+			// Next byte
+			encBuf++;
+			encLen--;
+		} else if( shift>0 ) {
+			// Pad last bits to 6 bits - will end next loop
+			bits <<= 6 - shift;
+			shift = 6;
+		} else {
+			// As per RFC 2045, section 6.8,
+			// pad output as necessary: 0 to 2 '=' chars.
+			while( outLen & 3 ){
+				*out++ = '=';
+				outLen++;
+			}
+
+			return outLen;
+		}
+
+		// Encode 6 bit segments
+		while( shift>=6 ) {
+			shift -= 6;
+			*out = b64[ (bits >> shift) & 0x3F ];
+			out++;
+			outLen++;
+		}
+	}
+
+	// Output overflow
+	return -1;
+}
+
+static int http_streaming_start(stream_t *stream, int* file_format) {
+	HTTP_header_t *http_hdr;
+	unsigned int i;
+	int fd=-1;
+	int redirect = 0;
+	int auth_retry=0;
+	int seekable=0;
+	char *content_type;
+	char *next_url;
+	URL_t *url = stream->streaming_ctrl->url;
+
+	do
+	{
+		fd = http_send_request( url, 0 );
+		if( fd<0 ) {
+			return -1;
+		}
+
+		http_hdr = http_read_response( fd );
+		if( http_hdr==NULL ) {
+			closesocket( fd );
+			http_free( http_hdr );
+			return -1;
+		}
+
+		stream->fd=fd;
+		if( mp_msg_test(MSGT_NETWORK,MSGL_V) ) {
+			http_debug_hdr( http_hdr );
+		}
+		
+		stream->streaming_ctrl->data = (void*)http_hdr;
+
+		// Check if we can make partial content requests and thus seek in http-streams
+		if( http_hdr!=NULL && http_hdr->status_code==200 ) {
+		    char *accept_ranges;
+		    if( (accept_ranges = http_get_field(http_hdr,"Accept-Ranges")) != NULL )
+			seekable = strncmp(accept_ranges,"bytes",5)==0;
+		}
+
+		// Check if the response is an ICY status_code reason_phrase
+		if( !strcasecmp(http_hdr->protocol, "ICY") ) {
+			switch( http_hdr->status_code ) {
+				case 200: { // OK
+					char *field_data = NULL;
+					// note: I skip icy-notice1 and 2, as they contain html <BR>
+					// and are IMHO useless info ::atmos
+					if( (field_data = http_get_field(http_hdr, "icy-name")) != NULL )
+						mp_msg(MSGT_NETWORK,MSGL_INFO,"Name   : %s\n", field_data); field_data = NULL;
+					if( (field_data = http_get_field(http_hdr, "icy-genre")) != NULL )
+						mp_msg(MSGT_NETWORK,MSGL_INFO,"Genre  : %s\n", field_data); field_data = NULL;
+					if( (field_data = http_get_field(http_hdr, "icy-url")) != NULL )
+						mp_msg(MSGT_NETWORK,MSGL_INFO,"Website: %s\n", field_data); field_data = NULL;
+					// XXX: does this really mean public server? ::atmos
+					if( (field_data = http_get_field(http_hdr, "icy-pub")) != NULL )
+						mp_msg(MSGT_NETWORK,MSGL_INFO,"Public : %s\n", atoi(field_data)?"yes":"no"); field_data = NULL;
+					if( (field_data = http_get_field(http_hdr, "icy-br")) != NULL )
+						mp_msg(MSGT_NETWORK,MSGL_INFO,"Bitrate: %skbit/s\n", field_data); field_data = NULL;
+					
+					// If content-type == video/nsv we most likely have a winamp video stream 
+					// otherwise it should be mp3. if there are more types consider adding mime type 
+					// handling like later
+					if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "video/nsv") || !strcmp(field_data, "misc/ultravox")))
+						*file_format = DEMUXER_TYPE_NSV;
+					else if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "audio/aacp") || !strcmp(field_data, "audio/aac")))
+						*file_format = DEMUXER_TYPE_AAC;
+					else
+						*file_format = DEMUXER_TYPE_AUDIO;
+					return 0;
+				}
+				case 400: // Server Full
+					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server is full, skipping!\n");
+					return -1;
+				case 401: // Service Unavailable
+					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return service unavailable, skipping!\n");
+					return -1;
+				case 403: // Service Forbidden
+					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return 'Service Forbidden'\n");
+					return -1;
+				case 404: // Resource Not Found
+					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server couldn't find requested stream, skipping!\n");
+					return -1;
+				default:
+					mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: unhandled ICY-Errorcode, contact MPlayer developers!\n");
+					return -1;
+			}
+		}
+
+		// Assume standard http if not ICY			
+		switch( http_hdr->status_code ) {
+			case 200: // OK
+				// Look if we can use the Content-Type
+				content_type = http_get_field( http_hdr, "Content-Type" );
+				if( content_type!=NULL ) {
+					char *content_length = NULL;
+					mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", content_type );
+					if( (content_length = http_get_field(http_hdr, "Content-Length")) != NULL)
+						mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length"));
+					// Check in the mime type table for a demuxer type
+					i = 0;
+					while(mime_type_table[i].mime_type != NULL) {
+						if( !strcasecmp( content_type, mime_type_table[i].mime_type ) ) {
+							*file_format = mime_type_table[i].demuxer_type;
+							return seekable;
+						}
+						i++;
+					}
+				}
+				// Not found in the mime type table, don't fail,
+				// we should try raw HTTP
+				return seekable;
+			// Redirect
+			case 301: // Permanently
+			case 302: // Temporarily
+				// TODO: RFC 2616, recommand to detect infinite redirection loops
+				next_url = http_get_field( http_hdr, "Location" );
+				if( next_url!=NULL ) {
+					closesocket( fd );
+					url_free( url );
+					stream->streaming_ctrl->url = url = url_new( next_url );
+					http_free( http_hdr );
+					redirect = 1;	
+				}
+				break;
+			case 401: // Authentication required
+				if( http_authenticate(http_hdr, url, &auth_retry)<0 ) return STREAM_UNSUPORTED;
+				redirect = 1;
+				break;
+			default:
+				mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase );
+				return -1;
+		}
+	} while( redirect );
+
+	return -1;
+}
+
+static int fixup_open(stream_t *stream,int seekable) {
+	HTTP_header_t *http_hdr = stream->streaming_ctrl->data;
+	int is_icy = http_hdr && http_get_field(http_hdr, "Icy-MetaInt");
+	int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0;
+
+	stream->type = STREAMTYPE_STREAM;
+	if(!is_icy && !is_ultravox && seekable)
+	{
+		stream->flags |= STREAM_SEEK;
+		stream->seek = http_seek;
+	}
+	stream->streaming_ctrl->bandwidth = network_bandwidth;
+	if ((!is_icy && !is_ultravox) || scast_streaming_start(stream))
+	if(nop_streaming_start( stream )) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_start failed\n");
+		streaming_ctrl_free(stream->streaming_ctrl);
+		stream->streaming_ctrl = NULL;
+		return STREAM_UNSUPORTED;
+	}
+
+	fixup_network_stream_cache(stream);
+	return STREAM_OK;
+}
+
+static int open_s1(stream_t *stream,int mode, void* opts, int* file_format) {
+	int seekable=0;
+	URL_t *url;
+
+	stream->streaming_ctrl = streaming_ctrl_new();
+	if( stream->streaming_ctrl==NULL ) {
+		return STREAM_ERROR;
+	}
+	stream->streaming_ctrl->bandwidth = network_bandwidth;
+	url = url_new(stream->url);
+	stream->streaming_ctrl->url = check4proxies(url);
+	url_free(url);
+	
+	mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_HTTP(1), URL: %s\n", stream->url);
+	seekable = http_streaming_start(stream, file_format);
+	if((seekable < 0) || (*file_format == DEMUXER_TYPE_ASF)) {
+		streaming_ctrl_free(stream->streaming_ctrl);
+		stream->streaming_ctrl = NULL;
+		return STREAM_UNSUPORTED;
+	}
+
+	return fixup_open(stream, seekable);
+}
+
+static int open_s2(stream_t *stream,int mode, void* opts, int* file_format) {
+	int seekable=0;
+	URL_t *url;
+
+	stream->streaming_ctrl = streaming_ctrl_new();
+	if( stream->streaming_ctrl==NULL ) {
+		return STREAM_ERROR;
+	}
+	stream->streaming_ctrl->bandwidth = network_bandwidth;
+	url = url_new(stream->url);
+	stream->streaming_ctrl->url = check4proxies(url);
+	url_free(url);
+	
+	mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_HTTP(2), URL: %s\n", stream->url);
+	seekable = http_streaming_start(stream, file_format);
+	if(seekable < 0) {
+		streaming_ctrl_free(stream->streaming_ctrl);
+		stream->streaming_ctrl = NULL;
+		return STREAM_UNSUPORTED;
+	}
+
+	return fixup_open(stream, seekable);
+}
+
+
+stream_info_t stream_info_http1 = {
+  "http streaming",
+  "null",
+  "Bertrand, Albeau, Reimar Doeffinger, Arpi?",
+  "plain http",
+  open_s1,
+  {"http", "http_proxy", "unsv", NULL},
+  NULL,
+  0 // Urls are an option string
+};
+
+stream_info_t stream_info_http2 = {
+  "http streaming",
+  "null",
+  "Bertrand, Albeu, Arpi? who?",
+  "plain http, also used as fallback for many other protocols",
+  open_s2,
+  {"http", "http_proxy", "pnm", "mms", "mmsu", "mmst", "rtsp", NULL},	//all the others as fallback
+  NULL,
+  0 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/http.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,52 @@
+/* 
+ * HTTP Helper
+ * by Bertrand Baudet <bertrand_baudet@yahoo.com>
+ * (C) 2001, MPlayer team.
+ */
+
+#ifndef __HTTP_H
+#define __HTTP_H
+
+typedef struct HTTP_field_type {
+	char *field_name;
+	struct HTTP_field_type *next;
+} HTTP_field_t;
+
+typedef struct {
+	char *protocol;
+	char *method;
+	char *uri;
+	unsigned int status_code;
+	char *reason_phrase;
+	unsigned int http_minor_version;
+	// Field variables
+	HTTP_field_t *first_field;
+	HTTP_field_t *last_field;
+	unsigned int field_nb;
+	char *field_search;
+	HTTP_field_t *field_search_pos;
+	// Body variables
+	char *body;
+	size_t body_size;
+	char *buffer;
+	size_t buffer_size;
+	unsigned int is_parsed;
+} HTTP_header_t;
+
+HTTP_header_t*	http_new_header(void);
+void		http_free( HTTP_header_t *http_hdr );
+int		http_response_append( HTTP_header_t *http_hdr, char *data, int length );
+int		http_response_parse( HTTP_header_t *http_hdr );
+int		http_is_header_entire( HTTP_header_t *http_hdr );
+char* 		http_build_request( HTTP_header_t *http_hdr );
+char* 		http_get_field( HTTP_header_t *http_hdr, const char *field_name );
+char*		http_get_next_field( HTTP_header_t *http_hdr );
+void		http_set_field( HTTP_header_t *http_hdr, const char *field_name );
+void		http_set_method( HTTP_header_t *http_hdr, const char *method );
+void		http_set_uri( HTTP_header_t *http_hdr, const char *uri );
+int		http_add_basic_authentication( HTTP_header_t *http_hdr, const char *username, const char *password );
+
+void		http_debug_hdr( HTTP_header_t *http_hdr );
+
+int 		base64_encode(const void *enc, int encLen, char *out, int outMax);
+#endif // __HTTP_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/librtsp/rtsp.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,804 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp.c,v 1.9 2003/04/10 02:30:48
+ */
+
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * a minimalistic implementation of rtsp protocol,
+ * *not* RFC 2326 compilant yet.
+ *
+ *    2006, Benjamin Zores and Vincent Mussard
+ *      fixed a lot of RFC compliance issues.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#else
+#include <winsock2.h>
+#endif
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include "mp_msg.h"
+#include "rtsp.h"
+#include "rtsp_session.h"
+#include "osdep/timer.h"
+
+/*
+#define LOG
+*/
+
+#define BUF_SIZE 4096
+#define HEADER_SIZE 1024
+#define MAX_FIELDS 256
+
+struct rtsp_s {
+
+  int           s;
+
+  char         *host;
+  int           port;
+  char         *path;
+  char         *param;
+  char         *mrl;
+  char         *user_agent;
+
+  char         *server;
+  unsigned int  server_state;
+  uint32_t      server_caps;
+  
+  unsigned int  cseq;
+  char         *session;
+
+  char        *answers[MAX_FIELDS];   /* data of last message */
+  char        *scheduled[MAX_FIELDS]; /* will be sent with next message */
+};
+
+/*
+ * constants
+ */
+
+#define RTSP_PROTOCOL_VERSION "RTSP/1.0"
+
+/* server states */
+#define RTSP_CONNECTED 1
+#define RTSP_INIT      2
+#define RTSP_READY     4
+#define RTSP_PLAYING   8
+#define RTSP_RECORDING 16
+
+/* server capabilities */
+#define RTSP_OPTIONS       0x001
+#define RTSP_DESCRIBE      0x002
+#define RTSP_ANNOUNCE      0x004
+#define RTSP_SETUP         0x008
+#define RTSP_GET_PARAMETER 0x010
+#define RTSP_SET_PARAMETER 0x020
+#define RTSP_TEARDOWN      0x040
+#define RTSP_PLAY          0x080
+#define RTSP_RECORD        0x100
+
+/*
+ * network utilities
+ */
+ 
+static int write_stream(int s, const char *buf, int len) {
+  int total, timeout;
+
+  total = 0; timeout = 30;
+  while (total < len){ 
+    int n;
+
+    n = send (s, &buf[total], len - total, 0);
+
+    if (n > 0)
+      total += n;
+    else if (n < 0) {
+#ifndef HAVE_WINSOCK2
+      if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) {
+#else
+      if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) {
+#endif
+        usec_sleep (1000000); timeout--;
+      } else
+        return -1;
+    }
+  }
+
+  return total;
+}
+
+static ssize_t read_stream(int fd, void *buf, size_t count) {
+  
+  ssize_t ret, total;
+
+  total = 0;
+
+  while (total < count) {
+  
+    ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0);
+
+    if (ret<0) {
+      if(errno == EAGAIN) {
+        fd_set rset;
+        struct timeval timeout;
+    
+        FD_ZERO (&rset);
+        FD_SET  (fd, &rset);
+        
+        timeout.tv_sec  = 30;
+        timeout.tv_usec = 0;
+        
+        if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) {
+          return -1;
+        }
+        continue;
+      }
+      
+      mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: read error.\n");
+      return ret;
+    } else
+      total += ret;
+    
+    /* end of stream */
+    if (!ret) break;
+  }
+
+  return total;
+}
+
+/*
+ * rtsp_get gets a line from stream
+ * and returns a null terminated string.
+ */
+ 
+static char *rtsp_get(rtsp_t *s) {
+
+  int n=1;
+  char *buffer = malloc(BUF_SIZE);
+  char *string = NULL;
+
+  read_stream(s->s, buffer, 1);
+  while (n<BUF_SIZE) {
+    read_stream(s->s, &(buffer[n]), 1);
+    if ((buffer[n-1]==0x0d)&&(buffer[n]==0x0a)) break;
+    n++;
+  }
+
+  if (n>=BUF_SIZE) {
+    mp_msg(MSGT_OPEN, MSGL_FATAL, "librtsp: buffer overflow in rtsp_get\n");
+    exit(1);
+  }
+  string=malloc(n);
+  memcpy(string,buffer,n-1);
+  string[n-1]=0;
+
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << '%s'\n", string);
+#endif
+  
+
+  free(buffer);
+  return string;
+}
+
+/*
+ * rtsp_put puts a line on stream
+ */
+ 
+static void rtsp_put(rtsp_t *s, const char *string) {
+
+  int len=strlen(string);
+  char *buf=malloc(len+2);
+
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: >> '%s'", string);
+#endif
+
+  memcpy(buf,string,len);
+  buf[len]=0x0d;
+  buf[len+1]=0x0a;
+
+  write_stream(s->s, buf, len+2);
+  
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, " done.\n");
+#endif
+
+  free(buf);
+}
+
+/*
+ * extract server status code
+ */
+
+static int rtsp_get_code(const char *string) {
+
+  char buf[4];
+  int code=0;
+ 
+  if (!strncmp(string, RTSP_PROTOCOL_VERSION, strlen(RTSP_PROTOCOL_VERSION)))
+  {
+    memcpy(buf, string+strlen(RTSP_PROTOCOL_VERSION)+1, 3);
+    buf[3]=0;
+    code=atoi(buf);
+  } else if (!strncmp(string, RTSP_METHOD_SET_PARAMETER,8))
+  {
+    return RTSP_STATUS_SET_PARAMETER;
+  }
+
+  if(code != RTSP_STATUS_OK) mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: server responds: '%s'\n",string);
+
+  return code;
+}
+
+/*
+ * send a request
+ */
+
+static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) {
+
+  char **payload=s->scheduled;
+  char *buf;
+  
+  buf = malloc(strlen(type)+strlen(what)+strlen(RTSP_PROTOCOL_VERSION)+3);
+  
+  sprintf(buf,"%s %s %s",type, what, RTSP_PROTOCOL_VERSION);
+  rtsp_put(s,buf);
+  free(buf);
+  if (payload)
+    while (*payload) {
+      rtsp_put(s,*payload);
+      payload++;
+    }
+  rtsp_put(s,"");
+  rtsp_unschedule_all(s);
+}
+
+/*
+ * schedule standard fields
+ */
+
+static void rtsp_schedule_standard(rtsp_t *s) {
+
+  char tmp[17];
+  
+  snprintf(tmp, 17, "CSeq: %u", s->cseq);
+  rtsp_schedule_field(s, tmp);
+  
+  if (s->session) {
+    char *buf;
+    buf = malloc(strlen(s->session)+15);
+    sprintf(buf, "Session: %s", s->session);
+    rtsp_schedule_field(s, buf);
+    free(buf);
+  }
+}
+/*
+ * get the answers, if server responses with something != 200, return NULL
+ */
+ 
+static int rtsp_get_answers(rtsp_t *s) {
+
+  char *answer=NULL;
+  unsigned int answer_seq;
+  char **answer_ptr=s->answers;
+  int code;
+  int ans_count = 0;
+  
+  answer=rtsp_get(s);
+  if (!answer)
+    return 0;
+  code=rtsp_get_code(answer);
+  free(answer);
+
+  rtsp_free_answers(s);
+  
+  do { /* while we get answer lines */
+  
+    answer=rtsp_get(s);
+    if (!answer)
+      return 0;
+    
+    if (!strncasecmp(answer,"CSeq:",5)) {
+      sscanf(answer,"%*s %u",&answer_seq);
+      if (s->cseq != answer_seq) {
+#ifdef LOG
+        mp_msg(MSGT_OPEN, MSGL_WARN, "librtsp: warning: CSeq mismatch. got %u, assumed %u", answer_seq, s->cseq);
+#endif
+        s->cseq=answer_seq;
+      }
+    }
+    if (!strncasecmp(answer,"Server:",7)) {
+      char *buf = malloc(strlen(answer));
+      sscanf(answer,"%*s %s",buf);
+      if (s->server) free(s->server);
+      s->server=strdup(buf);
+      free(buf);
+    }
+    if (!strncasecmp(answer,"Session:",8)) {
+      char *buf = calloc(1, strlen(answer));
+      sscanf(answer,"%*s %s",buf);
+      if (s->session) {
+        if (strcmp(buf, s->session)) {
+          mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: setting NEW session: %s\n", buf);
+          free(s->session);
+          s->session=strdup(buf);
+        }
+      } else
+      {
+#ifdef LOG
+        mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: setting session id to: %s\n", buf);
+#endif
+        s->session=strdup(buf);
+      }
+      free(buf);
+    }
+    *answer_ptr=answer;
+    answer_ptr++;
+  } while ((strlen(answer)!=0) && (++ans_count < MAX_FIELDS));
+  
+  s->cseq++;
+  
+  *answer_ptr=NULL;
+  rtsp_schedule_standard(s);
+    
+  return code;
+}
+
+/*
+ * send an ok message
+ */
+
+int rtsp_send_ok(rtsp_t *s) {
+  char cseq[16];
+  
+  rtsp_put(s, "RTSP/1.0 200 OK");
+  sprintf(cseq,"CSeq: %u", s->cseq);
+  rtsp_put(s, cseq);
+  rtsp_put(s, "");
+  return 0;
+}
+
+/*
+ * implementation of must-have rtsp requests; functions return
+ * server status code.
+ */
+
+int rtsp_request_options(rtsp_t *s, const char *what) {
+
+  char *buf;
+
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(strlen(s->host)+16);
+    sprintf(buf,"rtsp://%s:%i", s->host, s->port);
+  }
+  rtsp_send_request(s,RTSP_METHOD_OPTIONS,buf);
+  free(buf);
+
+  return rtsp_get_answers(s);
+}
+
+int rtsp_request_describe(rtsp_t *s, const char *what) {
+
+  char *buf;
+
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(strlen(s->host)+strlen(s->path)+16);
+    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request(s,RTSP_METHOD_DESCRIBE,buf);
+  free(buf);
+  
+  return rtsp_get_answers(s);
+}
+
+int rtsp_request_setup(rtsp_t *s, const char *what, char *control) {
+
+  char *buf = NULL;
+
+  if (what)
+    buf = strdup (what);
+  else
+  {
+    int len = strlen (s->host) + strlen (s->path) + 16;
+    if (control)
+      len += strlen (control) + 1;
+    
+    buf = malloc (len);
+    sprintf (buf, "rtsp://%s:%i/%s%s%s", s->host, s->port, s->path,
+             control ? "/" : "", control ? control : "");
+  }
+  
+  rtsp_send_request (s, RTSP_METHOD_SETUP, buf);
+  free (buf);
+  return rtsp_get_answers (s);
+}
+
+int rtsp_request_setparameter(rtsp_t *s, const char *what) {
+
+  char *buf;
+
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(strlen(s->host)+strlen(s->path)+16);
+    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request(s,RTSP_METHOD_SET_PARAMETER,buf);
+  free(buf);
+  
+  return rtsp_get_answers(s);
+}
+
+int rtsp_request_play(rtsp_t *s, const char *what) {
+
+  char *buf;
+  int ret;
+  
+  if (what) {
+    buf=strdup(what);
+  } else
+  {
+    buf=malloc(strlen(s->host)+strlen(s->path)+16);
+    sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request(s,RTSP_METHOD_PLAY,buf);
+  free(buf);
+  
+  ret = rtsp_get_answers (s);
+  if (ret == RTSP_STATUS_OK)
+    s->server_state = RTSP_PLAYING;
+
+  return ret;
+}
+
+int rtsp_request_teardown(rtsp_t *s, const char *what) {
+
+  char *buf;
+  
+  if (what)
+    buf = strdup (what);
+  else
+  {
+    buf =
+      malloc (strlen (s->host) + strlen (s->path) + 16);
+    sprintf (buf, "rtsp://%s:%i/%s", s->host, s->port, s->path);
+  }
+  rtsp_send_request (s, RTSP_METHOD_TEARDOWN, buf);
+  free (buf);
+
+  /* after teardown we're done with RTSP streaming, no need to get answer as
+     reading more will only result to garbage and buffer overflow */
+  return RTSP_STATUS_OK;
+}
+
+/*
+ * read opaque data from stream
+ */
+
+int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) {
+
+  int i,seq;
+
+  if (size>=4) {
+    i=read_stream(s->s, buffer, 4);
+    if (i<4) return i;
+    if (((buffer[0]=='S')&&(buffer[1]=='E')&&(buffer[2]=='T')&&(buffer[3]=='_')) ||
+        ((buffer[0]=='O')&&(buffer[1]=='P')&&(buffer[2]=='T')&&(buffer[3]=='I'))) // OPTIONS
+    {
+      char *rest=rtsp_get(s);
+      if (!rest)
+        return -1;      
+
+      seq=-1;
+      do {
+        free(rest);
+        rest=rtsp_get(s);
+        if (!rest)
+          return -1;
+        if (!strncasecmp(rest,"CSeq:",5))
+          sscanf(rest,"%*s %u",&seq);
+      } while (strlen(rest)!=0);
+      free(rest);
+      if (seq<0) {
+#ifdef LOG
+        mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: CSeq not recognized!\n");
+#endif
+        seq=1;
+      }
+      /* let's make the server happy */
+      rtsp_put(s, "RTSP/1.0 451 Parameter Not Understood");
+      rest=malloc(17);
+      sprintf(rest,"CSeq: %u", seq);
+      rtsp_put(s, rest);
+      free(rest);
+      rtsp_put(s, "");
+      i=read_stream(s->s, buffer, size);
+    } else
+    {
+      i=read_stream(s->s, buffer+4, size-4);
+      i+=4;
+    }
+  } else
+    i=read_stream(s->s, buffer, size);
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << %d of %d bytes\n", i, size);
+#endif
+
+  return i;
+}
+
+/*
+ * connect to a rtsp server
+ */
+
+//rtsp_t *rtsp_connect(const char *mrl, const char *user_agent) {
+rtsp_t *rtsp_connect(int fd, char* mrl, char *path, char *host, int port, char *user_agent) {
+
+  rtsp_t *s=malloc(sizeof(rtsp_t));
+  int i;
+  
+  for (i=0; i<MAX_FIELDS; i++) {
+    s->answers[i]=NULL;
+    s->scheduled[i]=NULL;
+  }
+
+  s->server=NULL;
+  s->server_state=0;
+  s->server_caps=0;
+  
+  s->cseq=0;
+  s->session=NULL;
+  
+  if (user_agent)
+    s->user_agent=strdup(user_agent);
+  else
+    s->user_agent=strdup("User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)");
+
+  s->mrl = strdup(mrl);
+  s->host = strdup(host);
+  s->port = port;
+  s->path = strdup(path);
+  while (*path == '/')
+    path++;
+  if ((s->param = strchr(s->path, '?')) != NULL)
+    s->param++;
+  //mp_msg(MSGT_OPEN, MSGL_INFO, "path=%s\n", s->path);
+  //mp_msg(MSGT_OPEN, MSGL_INFO, "param=%s\n", s->param ? s->param : "NULL");
+  s->s = fd;
+
+  if (s->s < 0) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: failed to connect to '%s'\n", s->host);
+    rtsp_close(s);
+    return NULL;
+  }
+
+  s->server_state=RTSP_CONNECTED;
+
+  /* now let's send an options request. */
+  rtsp_schedule_field(s, "CSeq: 1");
+  rtsp_schedule_field(s, s->user_agent);
+  rtsp_schedule_field(s, "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7");
+  rtsp_schedule_field(s, "PlayerStarttime: [28/03/2003:22:50:23 00:00]");
+  rtsp_schedule_field(s, "CompanyID: KnKV4M4I/B2FjJ1TToLycw==");
+  rtsp_schedule_field(s, "GUID: 00000000-0000-0000-0000-000000000000");
+  rtsp_schedule_field(s, "RegionData: 0");
+  rtsp_schedule_field(s, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
+  /*rtsp_schedule_field(s, "Pragma: initiate-session");*/
+  rtsp_request_options(s, NULL);
+
+  return s;
+}
+
+
+/*
+ * closes an rtsp connection 
+ */
+
+void rtsp_close(rtsp_t *s) {
+
+  if (s->server_state)
+  {
+    if (s->server_state == RTSP_PLAYING)
+      rtsp_request_teardown (s, NULL);
+    closesocket (s->s);
+  }
+
+  if (s->path) free(s->path);
+  if (s->host) free(s->host);
+  if (s->mrl) free(s->mrl);
+  if (s->session) free(s->session);
+  if (s->user_agent) free(s->user_agent);
+  rtsp_free_answers(s);
+  rtsp_unschedule_all(s);
+  free(s);  
+}
+
+/*
+ * search in answers for tags. returns a pointer to the content
+ * after the first matched tag. returns NULL if no match found.
+ */
+
+char *rtsp_search_answers(rtsp_t *s, const char *tag) {
+
+  char **answer;
+  char *ptr;
+  
+  if (!s->answers) return NULL;
+  answer=s->answers;
+
+  while (*answer) {
+    if (!strncasecmp(*answer,tag,strlen(tag))) {
+      ptr=strchr(*answer,':');
+      if (!ptr) return NULL;
+      ptr++;
+      while(*ptr==' ') ptr++;
+      return ptr;
+    }
+    answer++;
+  }
+
+  return NULL;
+}
+
+/*
+ * session id management
+ */
+
+void rtsp_set_session(rtsp_t *s, const char *id) {
+
+  if (s->session) free(s->session);
+
+  s->session=strdup(id);
+
+}
+
+char *rtsp_get_session(rtsp_t *s) {
+
+  return s->session;
+
+}
+
+char *rtsp_get_mrl(rtsp_t *s) {
+
+  return s->mrl;
+
+}
+
+char *rtsp_get_param(rtsp_t *s, const char *p) {
+  int len;
+  char *param;
+  if (!s->param)
+    return NULL;
+  if (!p)
+    return strdup(s->param);
+  len = strlen(p);
+  param = s->param;
+  while (param && *param) {
+    char *nparam = strchr(param, '&');
+    if (strncmp(param, p, len) == 0 && param[len] == '=') {
+      param += len + 1;
+      len = nparam ? nparam - param : strlen(param);
+      nparam = malloc(len + 1);
+      memcpy(nparam, param, len);
+      nparam[len] = 0;
+      return nparam;
+    }
+    param = nparam ? nparam + 1 : NULL;
+  }
+  return NULL;
+}
+  
+/*
+ * schedules a field for transmission
+ */
+
+void rtsp_schedule_field(rtsp_t *s, const char *string) {
+
+  int i=0;
+  
+  if (!string) return;
+
+  while(s->scheduled[i]) {
+    i++;
+  }
+  s->scheduled[i]=strdup(string);
+}
+
+/*
+ * removes the first scheduled field which prefix matches string. 
+ */
+
+void rtsp_unschedule_field(rtsp_t *s, const char *string) {
+
+  char **ptr=s->scheduled;
+  
+  if (!string) return;
+
+  while(*ptr) {
+    if (!strncmp(*ptr, string, strlen(string)))
+      break;
+    else
+      ptr++;
+  }
+  if (*ptr) free(*ptr);
+  ptr++;
+  do {
+    *(ptr-1)=*ptr;
+  } while(*ptr);
+}
+
+/*
+ * unschedule all fields
+ */
+
+void rtsp_unschedule_all(rtsp_t *s) {
+
+  char **ptr;
+  
+  if (!s->scheduled) return;
+  ptr=s->scheduled;
+
+  while (*ptr) {
+    free(*ptr);
+    *ptr=NULL;
+    ptr++;
+  }
+}
+/*
+ * free answers
+ */
+
+void rtsp_free_answers(rtsp_t *s) {
+
+  char **answer;
+  
+  if (!s->answers) return;
+  answer=s->answers;
+
+  while (*answer) {
+    free(*answer);
+    *answer=NULL;
+    answer++;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/librtsp/rtsp.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,84 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp.h,v 1.2 2002/12/16 21:50:55
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * a minimalistic implementation of rtsp protocol,
+ * *not* RFC 2326 compilant yet.
+ *
+ *    2006, Benjamin Zores and Vincent Mussard
+ *      fixed a lot of RFC compliance issues.
+ */
+ 
+#ifndef HAVE_RTSP_H
+#define HAVE_RTSP_H
+
+
+/* some codes returned by rtsp_request_* functions */
+
+#define RTSP_STATUS_SET_PARAMETER  10
+#define RTSP_STATUS_OK            200
+
+#define RTSP_METHOD_OPTIONS "OPTIONS"
+#define RTSP_METHOD_DESCRIBE "DESCRIBE"
+#define RTSP_METHOD_SETUP "SETUP"
+#define RTSP_METHOD_PLAY "PLAY"
+#define RTSP_METHOD_TEARDOWN "TEARDOWN"
+#define RTSP_METHOD_SET_PARAMETER "SET_PARAMETER"
+
+typedef struct rtsp_s rtsp_t;
+
+rtsp_t*  rtsp_connect (int fd, char *mrl, char *path, char *host, int port, char *user_agent);
+
+int rtsp_request_options(rtsp_t *s, const char *what);
+int rtsp_request_describe(rtsp_t *s, const char *what);
+int rtsp_request_setup(rtsp_t *s, const char *what, char *control);
+int rtsp_request_setparameter(rtsp_t *s, const char *what);
+int rtsp_request_play(rtsp_t *s, const char *what);
+int rtsp_request_teardown(rtsp_t *s, const char *what);
+
+int rtsp_send_ok(rtsp_t *s);
+
+int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size);
+
+char* rtsp_search_answers(rtsp_t *s, const char *tag);
+void rtsp_add_to_payload(char **payload, const char *string);
+
+void rtsp_free_answers(rtsp_t *this);
+
+int      rtsp_read (rtsp_t *this, char *data, int len);
+void     rtsp_close (rtsp_t *this);
+
+void  rtsp_set_session(rtsp_t *s, const char *id);
+char *rtsp_get_session(rtsp_t *s);
+
+char *rtsp_get_mrl(rtsp_t *s);
+char *rtsp_get_param(rtsp_t *s, const char *param);
+
+/*int      rtsp_peek_header (rtsp_t *this, char *data); */
+
+void rtsp_schedule_field(rtsp_t *s, const char *string);
+void rtsp_unschedule_field(rtsp_t *s, const char *string);
+void rtsp_unschedule_all(rtsp_t *s);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/librtsp/rtsp_rtp.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,700 @@
+/*
+ *  Copyright (C) 2006 Benjamin Zores
+ *   based on the Freebox patch for xine by Vincent Mussard
+ *   but with many enhancements for better RTSP RFC compliance.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include "config.h"
+
+#ifndef HAVE_WINSOCK2
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#include "mp_msg.h"
+#include "rtsp.h"
+#include "rtsp_rtp.h"
+#include "rtsp_session.h"
+#include "../freesdp/common.h"
+#include "../freesdp/parser.h"
+
+#define RTSP_DEFAULT_PORT 31336
+#define MAX_LENGTH 256
+
+#define RTSP_ACCEPT_SDP "Accept: application/sdp"
+#define RTSP_CONTENT_LENGTH "Content-length"
+#define RTSP_CONTENT_TYPE "Content-Type"
+#define RTSP_APPLICATION_SDP "application/sdp"
+#define RTSP_RANGE "Range: "
+#define RTSP_NPT_NOW "npt=now-"
+#define RTSP_MEDIA_CONTAINER_MPEG_TS "33"
+#define RTSP_TRANSPORT_REQUEST "Transport: RTP/AVP;%s;%s%i-%i;mode=\"PLAY\""
+  
+#define RTSP_TRANSPORT_MULTICAST "multicast"
+#define RTSP_TRANSPORT_UNICAST "unicast"
+
+#define RTSP_MULTICAST_PORT "port="
+#define RTSP_UNICAST_CLIENT_PORT "client_port="
+#define RTSP_UNICAST_SERVER_PORT "server_port="
+#define RTSP_SETUP_DESTINATION "destination="
+
+#define RTSP_SESSION "Session"
+#define RTSP_TRANSPORT "Transport"
+
+/* hardcoded RTCP RR - this is _NOT_ RFC compliant */
+#define RTCP_RR_SIZE 32
+#define RTCP_RR "\201\311\0\7(.JD\31+\306\343\0\0\0\0\0\0/E\0\0\2&\0\0\0\0\0\0\0\0\201"
+#define RTCP_SEND_FREQUENCY 1024
+
+int rtsp_port = 0;
+char *rtsp_destination = NULL;
+
+void
+rtcp_send_rr (rtsp_t *s, struct rtp_rtsp_session_t *st)
+{
+  if (st->rtcp_socket == -1)
+    return;
+  
+  /* send RTCP RR every RTCP_SEND_FREQUENCY packets
+   * FIXME : NOT CORRECT, HARDCODED, BUT MAKES SOME SERVERS HAPPY
+   * not rfc compliant
+   * http://www.faqs.org/rfcs/rfc1889.html chapter 6 for RTCP
+   */
+
+  if (st->count == RTCP_SEND_FREQUENCY)
+  {
+    char rtcp_content[RTCP_RR_SIZE];
+    strcpy (rtcp_content, RTCP_RR);
+    send (st->rtcp_socket, rtcp_content, RTCP_RR_SIZE, 0);
+
+    /* ping RTSP server to keep connection alive.
+       we use OPTIONS instead of PING as not all servers support it */
+    rtsp_request_options (s, "*");
+    st->count = 0;
+  }
+  else
+    st->count++;
+}
+
+static struct rtp_rtsp_session_t *
+rtp_session_new (void)
+{
+  struct rtp_rtsp_session_t *st = NULL;
+  
+  st = malloc (sizeof (struct rtp_rtsp_session_t));
+  
+  st->rtp_socket = -1;
+  st->rtcp_socket = -1;
+  st->control_url = NULL;
+  st->count = 0;
+  
+  return st;
+}
+
+void
+rtp_session_free (struct rtp_rtsp_session_t *st)
+{
+  if (!st)
+    return;
+
+  if (st->rtp_socket != -1)
+    close (st->rtp_socket);
+  if (st->rtcp_socket != -1)
+    close (st->rtcp_socket);
+
+  if (st->control_url)
+    free (st->control_url);
+  free (st);
+}
+
+static void
+rtp_session_set_fd (struct rtp_rtsp_session_t *st,
+                    int rtp_sock, int rtcp_sock)
+{
+  if (!st)
+    return;
+
+  st->rtp_socket = rtp_sock;
+  st->rtcp_socket = rtcp_sock;
+}
+
+static int
+parse_port (const char *line, const char *param,
+            int *rtp_port, int *rtcp_port)
+{
+  char *parse1;
+  char *parse2;
+  char *parse3;
+  
+  char *line_copy = strdup (line);
+
+  parse1 = strstr (line_copy, param);
+
+  if (parse1)
+  {
+    parse2 = strstr (parse1, "-");
+    
+    if (parse2)
+    {
+      parse3 = strstr (parse2, ";");
+      
+      if (parse3)
+	parse3[0] = 0;
+      
+      parse2[0] = 0;
+    }
+    else
+    {
+      free (line_copy);
+      return 0;
+    }
+  }
+  else
+  {
+    free (line_copy);
+    return 0;
+  }
+  
+  *rtp_port = atoi (parse1 + strlen (param));
+  *rtcp_port = atoi (parse2 + 1);
+
+  free (line_copy);
+  
+  return 1;
+}
+
+static char *
+parse_destination (const char *line)
+{
+  char *parse1;
+  char *parse2;
+
+  char *dest = NULL;
+  char *line_copy = strdup (line);
+  int len;
+  
+  parse1 = strstr (line_copy, RTSP_SETUP_DESTINATION);
+  if (!parse1)
+  {
+    free (line_copy);
+    return NULL;
+  }
+  
+  parse2 = strstr (parse1, ";");
+  if (!parse2)
+  {
+    free (line_copy);
+    return NULL;
+  }
+ 
+  len = strlen (parse1) - strlen (parse2)
+    - strlen (RTSP_SETUP_DESTINATION) + 1;
+  dest = (char *) malloc (len + 1);
+  snprintf (dest, len, parse1 + strlen (RTSP_SETUP_DESTINATION));
+  free (line_copy);
+
+  return dest;
+}
+
+static int
+rtcp_connect (int client_port, int server_port, const char* server_hostname)
+{
+  struct sockaddr_in sin;
+  struct hostent *hp;
+  int s;
+  
+  if (client_port <= 1023)
+    return -1;
+
+  s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  if (s == -1)
+    return -1;
+
+  hp = gethostbyname (server_hostname);
+  if (!hp)
+  {
+    close (s);
+    return -1;
+  }
+
+  sin.sin_family = AF_INET;
+  sin.sin_addr.s_addr = INADDR_ANY;
+  sin.sin_port = htons (client_port);
+  
+  if (bind (s, (struct sockaddr *) &sin, sizeof (sin)))
+  {
+#ifndef HAVE_WINSOCK2
+    if (errno != EINPROGRESS)
+#else
+    if (WSAGetLastError() != WSAEINPROGRESS)
+#endif
+    {
+      close (s);
+      return -1;
+    }
+  }
+  
+  sin.sin_family = AF_INET;
+  memcpy (&(sin.sin_addr.s_addr), hp->h_addr, sizeof (hp->h_addr));
+  sin.sin_port = htons (server_port);
+
+  /* datagram socket */
+  if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) < 0)
+  {
+    close (s);
+    return -1;
+  }
+
+  return s;
+}
+
+static int
+rtp_connect (char *hostname, int port)
+{
+  struct sockaddr_in sin;
+  struct timeval tv;
+  int err, err_len;
+  int rxsockbufsz;
+  int s;
+  fd_set set;
+
+  if (port <= 1023)
+    return -1;
+
+  s = socket (PF_INET, SOCK_DGRAM, 0);
+  if (s == -1)
+    return -1;
+
+  sin.sin_family = AF_INET;
+  if (!hostname || !strcmp (hostname, "0.0.0.0"))
+    sin.sin_addr.s_addr = htonl (INADDR_ANY);
+  else
+#ifndef HAVE_WINSOCK2
+#ifdef USE_ATON
+    inet_aton (hostname, &sin.sin_addr);
+#else
+    inet_pton (AF_INET, hostname, &sin.sin_addr);
+#endif
+#else
+    sin.sin_addr.s_addr = htonl (INADDR_ANY);
+#endif
+  sin.sin_port = htons (port);
+
+  /* Increase the socket rx buffer size to maximum -- this is UDP */
+  rxsockbufsz = 240 * 1024;
+  if (setsockopt (s, SOL_SOCKET, SO_RCVBUF,
+                  &rxsockbufsz, sizeof (rxsockbufsz)))
+    mp_msg (MSGT_OPEN, MSGL_ERR, "Couldn't set receive socket buffer size\n");
+
+  /* if multicast address, add membership */
+  if ((ntohl (sin.sin_addr.s_addr) >> 28) == 0xe)
+  {
+    struct ip_mreq mcast;
+    mcast.imr_multiaddr.s_addr = sin.sin_addr.s_addr;
+    mcast.imr_interface.s_addr = 0;
+
+    if (setsockopt (s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof (mcast)))
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR, "IP_ADD_MEMBERSHIP failed\n");
+      close (s);
+      return -1;
+    }
+  }
+  
+  /* datagram socket */
+  if (bind (s, (struct sockaddr *) &sin, sizeof (sin)))
+  {
+#ifndef HAVE_WINSOCK2
+    if (errno != EINPROGRESS)
+#else
+    if (WSAGetLastError() != WSAEINPROGRESS)
+#endif
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR, "bind: %s\n", strerror (errno));
+      close (s);
+      return -1;
+    }
+  }
+
+  tv.tv_sec = 0;
+  tv.tv_usec = (1 * 1000000); /* 1 second timeout */
+  
+  FD_ZERO (&set);
+  FD_SET (s, &set);
+  
+  err = select (s + 1, &set, NULL, NULL, &tv);
+  if (err < 0)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR, "Select failed: %s\n", strerror (errno));
+    close (s);
+    return -1;
+  }
+  else if (err == 0)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR, "Timeout! No data from host %s\n", hostname);
+    close (s);
+    return -1;
+  }
+  
+  err_len = sizeof (err);
+  getsockopt (s, SOL_SOCKET, SO_ERROR, &err, (socklen_t *) &err_len);
+  if (err)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR, "Socket error: %d\n", err);
+    close (s);
+    return -1;
+  }
+  
+  return s;
+}
+
+static int
+is_multicast_address (char *addr)
+{
+  struct sockaddr_in sin;
+
+  if (!addr)
+    return -1;
+  
+  sin.sin_family = AF_INET;
+
+#ifndef HAVE_WINSOCK2
+#ifdef USE_ATON
+    inet_aton (addr, &sin.sin_addr);
+#else
+    inet_pton (AF_INET, addr, &sin.sin_addr);
+#endif
+#else
+    sin.sin_addr.s_addr = htonl (INADDR_ANY);
+#endif
+  
+  if ((ntohl (sin.sin_addr.s_addr) >> 28) == 0xe)
+    return 1;
+
+  return 0;
+}
+
+struct rtp_rtsp_session_t *
+rtp_setup_and_play (rtsp_t *rtsp_session)
+{
+  struct rtp_rtsp_session_t* rtp_session = NULL;
+  const fsdp_media_description_t *med_dsc = NULL;
+  char temp_buf[MAX_LENGTH + 1];
+  char npt[256];
+
+  char* answer;
+  char* sdp;
+  char *server_addr = NULL;
+  char *destination = NULL;
+
+  int statut;
+  int content_length = 0;
+  int is_multicast = 0;
+  
+  fsdp_description_t *dsc = NULL;
+  fsdp_error_t result;
+
+  int client_rtp_port = -1;
+  int client_rtcp_port = -1;
+  int server_rtp_port = -1;
+  int server_rtcp_port = -1;
+  int rtp_sock = -1;
+  int rtcp_sock = -1;
+
+  /* 1. send a RTSP DESCRIBE request to server */
+  rtsp_schedule_field (rtsp_session, RTSP_ACCEPT_SDP);
+  statut = rtsp_request_describe (rtsp_session, NULL);
+  if (statut < 200 || statut > 299)
+    return NULL;
+
+  answer = rtsp_search_answers (rtsp_session, RTSP_CONTENT_LENGTH);
+  if (answer)
+    content_length = atoi (answer);
+  else
+    return NULL;
+
+  answer = rtsp_search_answers (rtsp_session, RTSP_CONTENT_TYPE);
+  if (!answer || !strstr (answer, RTSP_APPLICATION_SDP))
+    return NULL;
+
+  /* 2. read SDP message from server */
+  sdp = (char *) malloc (content_length + 1);
+  if (rtsp_read_data (rtsp_session, sdp, content_length) <= 0)
+  {
+    free (sdp);
+    return NULL;
+  }
+  sdp[content_length] = 0;
+  
+  /* 3. parse SDP message */
+  dsc = fsdp_description_new ();
+  result = fsdp_parse (sdp, dsc);
+  if (result != FSDPE_OK)
+  {
+    free (sdp);
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+  mp_msg (MSGT_OPEN, MSGL_V, "SDP:\n%s\n", sdp);
+  free (sdp);
+
+  /* 4. check for number of media streams: only one is supported */
+  if (fsdp_get_media_count (dsc) != 1)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "A single media stream only is supported atm.\n");
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+
+  /* 5. set the Normal Play Time parameter
+   *    use range provided by server in SDP or start now if empty */
+  sprintf (npt, RTSP_RANGE);
+  if (fsdp_get_range (dsc))
+    strcat (npt, fsdp_get_range (dsc));
+  else
+    strcat (npt, RTSP_NPT_NOW);
+
+  /* 5. check for a valid media stream */
+  med_dsc = fsdp_get_media (dsc, 0);
+  if (!med_dsc)
+  {
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+
+  /* 6. parse the `m=<media>  <port>  <transport> <fmt list>' line */
+ 
+  /* check for an A/V media */
+  if (fsdp_get_media_type (med_dsc) != FSDP_MEDIA_VIDEO &&
+      fsdp_get_media_type (med_dsc) != FSDP_MEDIA_AUDIO)
+  {
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+  
+  /* only RTP/AVP transport method is supported right now */
+  if (fsdp_get_media_transport_protocol (med_dsc) != FSDP_TP_RTP_AVP)
+  {
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+
+  /* only MPEG-TS is supported at the moment */
+  if (!strstr (fsdp_get_media_format (med_dsc, 0),
+               RTSP_MEDIA_CONTAINER_MPEG_TS))
+  {
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+
+  /* get client port (if any) advised by server */
+  client_rtp_port = fsdp_get_media_port (med_dsc);
+  if (client_rtp_port == -1)
+  {
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+
+  /* if client_rtp_port = 0 => let client randomly pick one */
+  if (client_rtp_port == 0)
+  {
+    /* TODO: we should check if the port is in use first */
+    if (rtsp_port)
+      client_rtp_port = rtsp_port;
+    else
+      client_rtp_port = RTSP_DEFAULT_PORT;
+  }
+
+  /* RTCP port generally is RTP port + 1 */
+  client_rtcp_port = client_rtp_port + 1;
+  
+  mp_msg (MSGT_OPEN, MSGL_V,
+          "RTP Port from SDP appears to be: %d\n", client_rtp_port);
+  mp_msg (MSGT_OPEN, MSGL_V,
+          "RTCP Port from SDP appears to be: %d\n", client_rtcp_port);
+
+  /* 7. parse the `c=<network type> <addr type> <connection address>' line */
+
+  /* check for a valid media network type (inet) */
+  if (fsdp_get_media_network_type (med_dsc) != FSDP_NETWORK_TYPE_INET)
+  {
+    /* no control for media: try global one instead */
+    if (fsdp_get_global_conn_network_type (dsc) != FSDP_NETWORK_TYPE_INET)
+    {
+      fsdp_description_delete (dsc);
+      return NULL;
+    }
+  }
+
+  /* only IPv4 is supported atm. */
+  if (fsdp_get_media_address_type (med_dsc) != FSDP_ADDRESS_TYPE_IPV4)
+  {
+    /* no control for media: try global one instead */
+    if (fsdp_get_global_conn_address_type (dsc) != FSDP_ADDRESS_TYPE_IPV4)
+    {
+      fsdp_description_delete (dsc);
+      return NULL;
+    }
+  }
+
+  /* get the media server address to connect to */
+  if (fsdp_get_media_address (med_dsc))
+    server_addr = strdup (fsdp_get_media_address (med_dsc));
+  else if (fsdp_get_global_conn_address (dsc))
+  {
+    /* no control for media: try global one instead */
+    server_addr = strdup (fsdp_get_global_conn_address (dsc));
+  }
+    
+  if (!server_addr)
+  {
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+
+  /* check for a UNICAST or MULTICAST address to connect to */
+  is_multicast = is_multicast_address (server_addr);
+
+  /* 8. initiate an RTP session */
+  rtp_session = rtp_session_new ();
+  if (!rtp_session)
+  {
+    free (server_addr);
+    fsdp_description_delete (dsc);
+    return NULL;
+  }
+
+  /* get the media control URL */
+  if (fsdp_get_media_control (med_dsc, 0))
+    rtp_session->control_url = strdup (fsdp_get_media_control (med_dsc, 0));
+  fsdp_description_delete (dsc);
+  if (!rtp_session->control_url)
+  {
+    free (server_addr);
+    rtp_session_free (rtp_session);
+    return NULL;
+  }
+
+  /* 9. create the payload for RTSP SETUP request */
+  memset (temp_buf, '\0', MAX_LENGTH);
+  snprintf (temp_buf, MAX_LENGTH,
+            RTSP_TRANSPORT_REQUEST,
+            is_multicast ? RTSP_TRANSPORT_MULTICAST : RTSP_TRANSPORT_UNICAST,
+            is_multicast ? RTSP_MULTICAST_PORT : RTSP_UNICAST_CLIENT_PORT,
+            client_rtp_port, client_rtcp_port);
+  mp_msg (MSGT_OPEN, MSGL_V, "RTSP Transport: %s\n", temp_buf);
+  
+  rtsp_unschedule_field (rtsp_session, RTSP_SESSION);
+  rtsp_schedule_field (rtsp_session, temp_buf);
+
+  /* 10. check for the media control URL type and initiate RTSP SETUP */
+  if (!strncmp (rtp_session->control_url, "rtsp://", 7)) /* absolute URL */
+    statut = rtsp_request_setup (rtsp_session,
+                                 rtp_session->control_url, NULL);
+  else /* relative URL */
+    statut = rtsp_request_setup (rtsp_session,
+                                 NULL, rtp_session->control_url);
+    
+  if (statut < 200 || statut > 299)
+  {
+    free (server_addr);
+    rtp_session_free (rtp_session);
+    return NULL;
+  }
+
+  /* 11. parse RTSP SETUP response: we need it to actually determine
+   *     the real address and port to connect to */
+  answer = rtsp_search_answers (rtsp_session, RTSP_TRANSPORT);
+  if (!answer)
+  {
+    free (server_addr);
+    rtp_session_free (rtp_session);
+    return NULL;
+  }
+
+  /* check for RTP and RTCP ports to bind according to how request was done */
+  is_multicast = 0;
+  if (strstr (answer, RTSP_TRANSPORT_MULTICAST))
+    is_multicast = 1;
+
+  if (is_multicast)
+    parse_port (answer, RTSP_MULTICAST_PORT,
+                &client_rtp_port, &client_rtcp_port);
+  else
+  {
+    parse_port (answer, RTSP_UNICAST_CLIENT_PORT,
+                &client_rtp_port, &client_rtcp_port);
+    parse_port (answer, RTSP_UNICAST_SERVER_PORT,
+                &server_rtp_port, &server_rtcp_port);
+  }
+
+  /* now check network settings as determined by server */
+  if (rtsp_destination)
+    destination = strdup (rtsp_destination);
+  else
+    destination = parse_destination (answer);
+  if (!destination)
+    destination = strdup (server_addr);
+  free (server_addr);
+
+  mp_msg (MSGT_OPEN, MSGL_V, "RTSP Destination: %s\n", destination);
+  mp_msg (MSGT_OPEN, MSGL_V, "Client RTP port : %d\n", client_rtp_port);
+  mp_msg (MSGT_OPEN, MSGL_V, "Client RTCP port : %d\n", client_rtcp_port);
+  mp_msg (MSGT_OPEN, MSGL_V, "Server RTP port : %d\n", server_rtp_port);
+  mp_msg (MSGT_OPEN, MSGL_V, "Server RTCP port : %d\n", server_rtcp_port);
+
+  /* 12. performs RTSP PLAY request */
+  rtsp_schedule_field (rtsp_session, npt);
+  statut = rtsp_request_play (rtsp_session, NULL);
+  if (statut < 200 || statut > 299)
+  {
+    free (destination);
+    rtp_session_free (rtp_session);
+    return NULL;
+  }
+
+  /* 13. create RTP and RTCP connections */
+  rtp_sock = rtp_connect (destination, client_rtp_port);
+  rtcp_sock = rtcp_connect (client_rtcp_port, server_rtcp_port, destination);
+  rtp_session_set_fd (rtp_session, rtp_sock, rtcp_sock);
+  free (destination);
+
+  mp_msg (MSGT_OPEN, MSGL_V, "RTP Sock : %d\nRTCP Sock : %d\n",
+          rtp_session->rtp_socket, rtp_session->rtcp_socket);
+
+  if (rtp_session->rtp_socket == -1)
+  {
+    rtp_session_free (rtp_session);
+    return NULL;
+  }
+
+  return rtp_session;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/librtsp/rtsp_rtp.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (C) 2006 Benjamin Zores
+ *   heavily base on the Freebox patch for xine by Vincent Mussard
+ *   but with many enhancements for better RTSP RFC compliance.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _HAVE_RTSP_RTP_H_
+#define _HAVE_RTSP_RTP_H_
+
+#include "rtsp.h"
+
+#define MAX_PREVIEW_SIZE 4096
+
+struct rtp_rtsp_session_t {
+  int rtp_socket;
+  int rtcp_socket;
+  char *control_url;
+  int count;
+};
+
+struct rtp_rtsp_session_t *rtp_setup_and_play (rtsp_t* rtsp_session);
+off_t rtp_read (struct rtp_rtsp_session_t* st, char *buf, off_t length);
+void rtp_session_free (struct rtp_rtsp_session_t *st);
+void rtcp_send_rr (rtsp_t *s, struct rtp_rtsp_session_t *st);
+
+#endif /* _HAVE_RTSP_RTP_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/librtsp/rtsp_session.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,269 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp_session.c,v 1.9 2003/02/11 16:20:40
+ */
+
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * high level interface to rtsp servers.
+ *
+ *    2006, Benjamin Zores and Vincent Mussard
+ *      Support for MPEG-TS streaming through RFC compliant RTSP servers
+ */
+
+#include <sys/types.h>
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#else
+#include <winsock2.h>
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "mp_msg.h"
+#include "../rtp.h"
+#include "rtsp.h"
+#include "rtsp_rtp.h"
+#include "rtsp_session.h"
+#include "../realrtsp/real.h"
+#include "../realrtsp/rmff.h"
+#include "../realrtsp/asmrp.h"
+#include "../realrtsp/xbuffer.h"
+
+/*
+#define LOG
+*/
+
+#define RTSP_OPTIONS_PUBLIC "Public"
+#define RTSP_OPTIONS_SERVER "Server"
+#define RTSP_OPTIONS_LOCATION "Location"
+#define RTSP_OPTIONS_REAL "RealChallenge1"
+#define RTSP_SERVER_TYPE_REAL "Real"
+#define RTSP_SERVER_TYPE_HELIX "Helix"
+#define RTSP_SERVER_TYPE_UNKNOWN "unknown"
+
+struct rtsp_session_s {
+  rtsp_t       *s;
+  struct real_rtsp_session_t* real_session;
+  struct rtp_rtsp_session_t* rtp_session;
+};
+
+//rtsp_session_t *rtsp_session_start(char *mrl) {
+rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth) {
+
+  rtsp_session_t *rtsp_session = NULL;
+  char *server;
+  char *mrl_line = NULL;
+  rmff_header_t *h;
+
+  rtsp_session = malloc (sizeof (rtsp_session_t));
+  rtsp_session->s = NULL;
+  rtsp_session->real_session = NULL;
+  rtsp_session->rtp_session = NULL;
+ 
+//connect:
+  *redir = 0;
+
+  /* connect to server */
+  rtsp_session->s=rtsp_connect(fd,*mrl,path,host,port,NULL);
+  if (!rtsp_session->s)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: failed to connect to server %s\n", path);
+    free(rtsp_session);
+    return NULL;
+  }
+
+  /* looking for server type */
+  if (rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_SERVER))
+    server=strdup(rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_SERVER));
+  else {
+    if (rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_REAL))
+      server=strdup(RTSP_SERVER_TYPE_REAL);
+    else
+      server=strdup(RTSP_SERVER_TYPE_UNKNOWN);
+  }
+  if (strstr(server,RTSP_SERVER_TYPE_REAL) || strstr(server,RTSP_SERVER_TYPE_HELIX))
+  {
+    /* we are talking to a real server ... */
+
+    h=real_setup_and_get_header(rtsp_session->s, bandwidth);
+    if (!h) {
+      /* got an redirect? */
+      if (rtsp_search_answers(rtsp_session->s, RTSP_OPTIONS_LOCATION))
+      {
+        free(mrl_line);
+	mrl_line=strdup(rtsp_search_answers(rtsp_session->s, RTSP_OPTIONS_LOCATION));
+        mp_msg (MSGT_OPEN, MSGL_INFO,"rtsp_session: redirected to %s\n", mrl_line);
+	rtsp_close(rtsp_session->s);
+	free(server);
+        free(*mrl);
+        free(rtsp_session);
+        /* tell the caller to redirect, return url to redirect to in mrl */
+        *mrl = mrl_line;
+        *redir = 1;
+        return NULL;
+//	goto connect; /* *shudder* i made a design mistake somewhere */
+      } else
+      {
+        mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: session can not be established.\n");
+        rtsp_close(rtsp_session->s);
+        free (server);
+        free(rtsp_session);
+        return NULL;
+      }
+    }
+	
+    rtsp_session->real_session = init_real_rtsp_session ();
+    rtsp_session->real_session->header_len =
+      rmff_dump_header (h, (char *) rtsp_session->real_session->header, 1024);
+
+    rtsp_session->real_session->recv =
+      xbuffer_copyin (rtsp_session->real_session->recv, 0,
+                      rtsp_session->real_session->header,
+                      rtsp_session->real_session->header_len);
+
+    rtsp_session->real_session->recv_size =
+      rtsp_session->real_session->header_len;
+    rtsp_session->real_session->recv_read = 0;
+  } else /* not a Real server : try RTP instead */
+  {
+    char *public = NULL;
+
+    /* look for the Public: field in response to RTSP OPTIONS */
+    public = strdup (rtsp_search_answers (rtsp_session->s,
+                                          RTSP_OPTIONS_PUBLIC));
+    if (!public)
+    {
+      rtsp_close (rtsp_session->s);
+      free (server);
+      free (mrl_line);
+      free (rtsp_session);
+      return NULL;
+    }
+
+    /* check for minimalistic RTSP RFC compliance */
+    if (!strstr (public, RTSP_METHOD_DESCRIBE)
+        || !strstr (public, RTSP_METHOD_SETUP)
+        || !strstr (public, RTSP_METHOD_PLAY)
+        || !strstr (public, RTSP_METHOD_TEARDOWN))
+    {
+      free (public);
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "Remote server does not meet minimal RTSP 1.0 compliance.\n");
+      rtsp_close (rtsp_session->s);
+      free (server);
+      free (mrl_line);
+      free (rtsp_session);
+      return NULL;
+    }
+
+    free (public);
+    rtsp_session->rtp_session = rtp_setup_and_play (rtsp_session->s);
+
+    /* neither a Real or an RTP server */
+    if (!rtsp_session->rtp_session)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR, "rtsp_session: unsupported RTSP server. ");
+      mp_msg (MSGT_OPEN, MSGL_ERR, "Server type is '%s'.\n", server);
+      rtsp_close (rtsp_session->s);
+      free (server);
+      free (mrl_line);
+      free (rtsp_session);
+      return NULL;
+    }
+  }
+  free(server);
+  
+  return rtsp_session;
+}
+
+int rtsp_session_read (rtsp_session_t *this, char *data, int len) {
+  
+  if (this->real_session) {
+  int to_copy=len;
+  char *dest=data;
+  char *source =
+    (char *) (this->real_session->recv + this->real_session->recv_read);
+  int fill = this->real_session->recv_size - this->real_session->recv_read;
+
+  if (len < 0) return 0;
+  while (to_copy > fill) {
+    
+    memcpy(dest, source, fill);
+    to_copy -= fill;
+    dest += fill;
+    this->real_session->recv_read = 0;
+    this->real_session->recv_size =
+      real_get_rdt_chunk (this->s, (char **)&(this->real_session->recv));
+    if (this->real_session->recv_size < 0)
+      return -1;
+    source = (char *) this->real_session->recv;
+    fill = this->real_session->recv_size;
+
+    if (this->real_session->recv_size == 0) {
+#ifdef LOG
+      mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d of %d bytes provided\n", len-to_copy, len);
+#endif
+      return len-to_copy;
+    }
+  }
+  
+  memcpy(dest, source, to_copy);
+  this->real_session->recv_read += to_copy;
+
+#ifdef LOG
+  mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d bytes provided\n", len);
+#endif
+
+  return len;
+  }
+  else if (this->rtp_session)
+  {
+    int l = 0;
+
+    l = read_rtp_from_server (this->rtp_session->rtp_socket, data, len);
+    /* send RTSP and RTCP keepalive  */
+    rtcp_send_rr (this->s, this->rtp_session);
+
+    if (l == 0)
+      rtsp_session_end (this);
+    
+    return l;
+  }
+
+  return 0;
+}
+
+void rtsp_session_end(rtsp_session_t *session) {
+
+  rtsp_close(session->s);
+  if (session->real_session)
+    free_real_rtsp_session (session->real_session);
+  if (session->rtp_session)
+    rtp_session_free (session->rtp_session);
+  free(session);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/librtsp/rtsp_session.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,42 @@
+/*
+ * This file was ported to MPlayer from xine CVS rtsp_session.h,v 1.4 2003/01/31 14:06:18
+ */
+
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * high level interface to rtsp servers.
+ *
+ *    2006, Benjamin Zores and Vincent Mussard
+ *      Support for MPEG-TS streaming through RFC compliant RTSP servers
+ */
+
+#ifndef HAVE_RTSP_SESSION_H
+#define HAVE_RTSP_SESSION_H
+
+typedef struct rtsp_session_s rtsp_session_t;
+
+rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth);
+
+int rtsp_session_read(rtsp_session_t *session, char *data, int len);
+
+void rtsp_session_end(rtsp_session_t *session);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/mf.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,153 @@
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "config.h"
+
+#ifdef HAVE_GLOB
+#include <glob.h>
+#else
+#include "osdep/glob.h"
+#endif
+
+#include "mp_msg.h"
+#include "help_mp.h"
+#include "stream.h"
+
+#include "mf.h"
+
+int    mf_w = 0; //352; // let codecs to detect it
+int    mf_h = 0; //288;
+float  mf_fps = 25.0;
+char * mf_type = NULL; //"jpg";
+
+mf_t* open_mf(char * filename){
+#if defined(HAVE_GLOB) || defined(__MINGW32__)
+ glob_t        gg;
+ struct stat   fs;
+ int           i;
+ char        * fname;
+ mf_t        * mf;
+ int           error_count = 0;
+ int	       count = 0;
+
+ mf=calloc( 1,sizeof( mf_t ) );
+
+ if( filename[0] == '@' )
+  { 
+   FILE *lst_f=fopen(filename + 1,"r");
+   if ( lst_f ) 
+    {
+     fname=malloc( 255 );
+     while ( fgets( fname,255,lst_f ) ) 
+      {
+       /* remove spaces from end of fname */
+       char *t=fname + strlen( fname ) - 1;
+       while ( t > fname && isspace( *t ) ) *(t--)=0;
+       if ( stat( fname,&fs ) ) 
+        {
+         mp_msg( MSGT_STREAM,MSGL_V,"[mf] file not found: '%s'\n",fname );
+        }
+        else
+        {
+         mf->names=realloc( mf->names,( mf->nr_of_files + 1 ) * sizeof( char* ) );
+         mf->names[mf->nr_of_files]=strdup( fname );
+         mf->nr_of_files++;
+        }
+      }
+      fclose( lst_f );
+	     
+      mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d\n",mf->nr_of_files );
+      goto exit_mf;
+    }
+    mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] %s is not indirect filelist\n",filename+1 );
+  }
+
+ if( strchr( filename,',') )
+  { 
+   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] filelist: %s\n",filename );
+ 
+   while ( ( fname=strsep( &filename,"," ) ) )
+    {
+     if ( stat( fname,&fs ) ) 
+      {
+       mp_msg( MSGT_STREAM,MSGL_V,"[mf] file not found: '%s'\n",fname );
+      }
+      else
+      {
+       mf->names=realloc( mf->names,( mf->nr_of_files + 1 ) * sizeof( char* ) );
+       mf->names[mf->nr_of_files]=strdup( fname );
+//       mp_msg( MSGT_STREAM,MSGL_V,"[mf] added file %d.: %s\n",mf->nr_of_files,mf->names[mf->nr_of_files] );
+       mf->nr_of_files++;
+      }
+    }
+   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d\n",mf->nr_of_files );
+ 
+   goto exit_mf;
+  } 
+
+ fname=malloc( strlen( filename ) + 32 );
+
+ if ( !strchr( filename,'%' ) )
+  {
+   strcpy( fname,filename ); 
+   if ( !strchr( filename,'*' ) ) strcat( fname,"*" );
+
+   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] search expr: %s\n",fname );
+
+   if ( glob( fname,0,NULL,&gg ) )
+    { free( mf ); free( fname ); return NULL; }
+
+   mf->nr_of_files=gg.gl_pathc;
+   mf->names=calloc( gg.gl_pathc, sizeof( char* ) );
+
+   mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d (%d)\n",mf->nr_of_files, gg.gl_pathc * sizeof( char* ) );
+
+   for( i=0;i < gg.gl_pathc;i++ )
+    {
+     stat( gg.gl_pathv[i],&fs );
+     if( S_ISDIR( fs.st_mode ) ) continue;
+     mf->names[i]=strdup( gg.gl_pathv[i] );
+//     mp_msg( MSGT_STREAM,MSGL_DBG2,"[mf] added file %d.: %s\n",i,mf->names[i] );
+    }
+   globfree( &gg );
+   goto exit_mf;
+  }
+
+ mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] search expr: %s\n",filename );
+ 
+ while ( error_count < 5 )
+  {
+   sprintf( fname,filename,count++ );
+   if ( stat( fname,&fs ) ) 
+    {
+     error_count++;
+     mp_msg( MSGT_STREAM,MSGL_V,"[mf] file not found: '%s'\n",fname );
+    }
+    else
+    {
+     mf->names=realloc( mf->names,( mf->nr_of_files + 1 ) * sizeof( char* ) );
+     mf->names[mf->nr_of_files]=strdup( fname );
+//     mp_msg( MSGT_STREAM,MSGL_V,"[mf] added file %d.: %s\n",mf->nr_of_files,mf->names[mf->nr_of_files] );
+     mf->nr_of_files++;
+    }
+  }
+
+ mp_msg( MSGT_STREAM,MSGL_INFO,"[mf] number of files: %d\n",mf->nr_of_files );
+
+exit_mf:
+ free( fname );
+ return mf;
+#else
+ mp_msg(MSGT_STREAM,MSGL_FATAL,"[mf] mf support is disabled on your os\n");
+ return 0;
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/mf.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,19 @@
+
+#ifndef _MF_H
+#define _MF_H
+
+extern int    mf_w;
+extern int    mf_h;
+extern float  mf_fps;
+extern char * mf_type;
+
+typedef struct
+{
+ int curr_frame;
+ int nr_of_files;
+ char ** names;
+} mf_t;
+
+mf_t* open_mf(char * filename);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/netstream.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,136 @@
+
+/*
+ * Common stuff for netstream
+ * Packets and so on are defined here along with a few helpers
+ * wich are used by both the client and the server
+ *
+ * Data is always low endian
+ */
+
+typedef struct mp_net_stream_packet_st {
+  uint16_t len;
+  uint8_t cmd;
+  char data[0];
+} __attribute__ ((packed))  mp_net_stream_packet_t;
+
+#define PACKET_MAX_SIZE 4096
+
+// Commands sent by the client
+#define NET_STREAM_OPEN 0
+// data is the url
+#define NET_STREAM_FILL_BUFFER 1
+// data is an uint16 wich is the max len of the data to return
+#define NET_STREAM_SEEK 3
+// data is an uint64 wich the pos where to seek
+#define NET_STREAM_CLOSE 4
+// no data
+#define NET_STREAM_RESET 5
+// no data
+
+// Server response
+#define NET_STREAM_OK 128
+// Data returned if open is successful
+typedef struct mp_net_stream_opened_st {
+  uint32_t file_format;
+  uint32_t flags;
+  uint32_t sector_size;
+  uint64_t start_pos;
+  uint64_t end_pos;
+}  __attribute__ ((packed))  mp_net_stream_opened_t;
+// FILL_BUFFER return the data
+// CLOSE return nothing
+#define NET_STREAM_ERROR 129
+// Data is the error message (if any ;)
+
+static int net_read(int fd, char* buf, int len) {
+  int r = 0;
+  while(len) {
+    r = recv(fd,buf,len,0);
+    if(r <= 0) {
+      if(errno == EINTR) continue;
+      if(r < 0)
+	mp_msg(MSGT_NETST,MSGL_ERR,"Read failed: %s\n",strerror(errno));
+      return 0;
+    }
+    len -= r;
+    buf += r;
+  }
+  return 1;
+}
+
+static mp_net_stream_packet_t* read_packet(int fd) {
+  uint16_t len;
+  mp_net_stream_packet_t* pack = 
+    (mp_net_stream_packet_t*)malloc(sizeof(mp_net_stream_packet_t));
+  
+  if(!net_read(fd,(char*)pack,sizeof(mp_net_stream_packet_t))) {
+    free(pack);
+    return NULL;
+  }
+  pack->len = le2me_16(pack->len);
+
+  if(pack->len < sizeof(mp_net_stream_packet_t)) {
+    mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid packet (too small: %d)\n",pack->len);
+    free(pack);
+    return NULL;
+  }
+  if(pack->len > PACKET_MAX_SIZE) {
+    mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid packet (too big: %d)\n",pack->len);
+    free(pack);
+    return NULL;
+  }
+  len = pack->len;
+  if(len > sizeof(mp_net_stream_packet_t)) {
+    pack = realloc(pack,len);
+    if(!pack) {
+      mp_msg(MSGT_NETST,MSGL_ERR,"Failed to get memory for the packet (%d bytes)\n",len);
+      return NULL;
+    }
+    if(!net_read(fd,pack->data,len - sizeof(mp_net_stream_packet_t)))
+      return NULL;
+  }
+  //  printf ("Read packet %d %d %d\n",fd,pack->cmd,pack->len);
+  return pack;
+}
+
+static int net_write(int fd, char* buf, int len) {
+  int w;
+  while(len) {
+    w = send(fd,buf,len,0);
+    if(w <= 0) {
+      if(errno == EINTR) continue;
+      if(w < 0)
+	mp_msg(MSGT_NETST,MSGL_ERR,"Write failed: %s\n",strerror(errno));
+      return 0;
+    }
+    len -= w;
+    buf += w;
+  }
+  return 1;
+}
+
+static int write_packet(int fd, uint8_t cmd,char* data,int len) {
+  mp_net_stream_packet_t* pack = malloc(len + sizeof(mp_net_stream_packet_t));
+  
+  if(len > 0 && data)
+    memcpy(pack->data,data,len);
+  pack->len = len + sizeof(mp_net_stream_packet_t);
+  pack->cmd = cmd;
+  
+  //  printf("Write packet %d %d (%p) %d\n",fd,cmd,data,len);
+  pack->len = le2me_16(pack->len);
+  if(net_write(fd,(char*)pack,pack->len)) {
+    free(pack);
+    return 1;
+  }
+  free(pack);
+  return 0;
+}
+
+static void net_stream_opened_2_me(mp_net_stream_opened_t* o) {
+  o->file_format = le2me_32(o->file_format);
+  o->flags = le2me_32(o->flags);
+  o->sector_size = le2me_32(o->sector_size);
+  o->start_pos = le2me_64(o->start_pos);
+  o->end_pos = le2me_64(o->end_pos);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/network.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,657 @@
+/*
+ * Network layer for MPlayer
+ * by Bertrand BAUDET <bertrand_baudet@yahoo.com>
+ * (C) 2001, MPlayer team.
+ */
+
+//#define DUMP2FILE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <ctype.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#include "stream.h"
+#include "demuxer.h"
+#include "m_config.h"
+
+#include "network.h"
+#include "http.h"
+#include "cookies.h"
+#include "url.h"
+
+#include "version.h"
+
+extern int stream_cache_size;
+
+extern int mp_input_check_interrupt(int time);
+
+/* Variables for the command line option -user, -passwd, -bandwidth,
+   -user-agent and -nocookies */
+
+char *network_username=NULL;
+char *network_password=NULL;
+int   network_bandwidth=0;
+int   network_cookies_enabled = 0;
+char *network_useragent=NULL;
+
+/* IPv6 options */
+int   network_prefer_ipv4 = 0;
+int   network_ipv4_only_proxy = 0;
+
+
+mime_struct_t mime_type_table[] = {
+	// MP3 streaming, some MP3 streaming server answer with audio/mpeg
+	{ "audio/mpeg", DEMUXER_TYPE_AUDIO },
+	// MPEG streaming
+	{ "video/mpeg", DEMUXER_TYPE_UNKNOWN },
+	{ "video/x-mpeg", DEMUXER_TYPE_UNKNOWN },
+	{ "video/x-mpeg2", DEMUXER_TYPE_UNKNOWN },
+	// AVI ??? => video/x-msvideo
+	{ "video/x-msvideo", DEMUXER_TYPE_AVI },
+	// MOV => video/quicktime
+	{ "video/quicktime", DEMUXER_TYPE_MOV },
+	// ASF
+        { "audio/x-ms-wax", DEMUXER_TYPE_ASF },
+	{ "audio/x-ms-wma", DEMUXER_TYPE_ASF },
+	{ "video/x-ms-asf", DEMUXER_TYPE_ASF },
+	{ "video/x-ms-afs", DEMUXER_TYPE_ASF },
+	{ "video/x-ms-wvx", DEMUXER_TYPE_ASF },
+	{ "video/x-ms-wmv", DEMUXER_TYPE_ASF },
+	{ "video/x-ms-wma", DEMUXER_TYPE_ASF },
+	{ "application/x-mms-framed", DEMUXER_TYPE_ASF },
+	{ "application/vnd.ms.wms-hdr.asfv1", DEMUXER_TYPE_ASF },
+	{ "application/octet-stream", DEMUXER_TYPE_ASF },
+	// Playlists
+	{ "video/x-ms-wmx", DEMUXER_TYPE_PLAYLIST },
+	{ "audio/x-scpls", DEMUXER_TYPE_PLAYLIST },
+	{ "audio/x-mpegurl", DEMUXER_TYPE_PLAYLIST },
+	{ "audio/x-pls", DEMUXER_TYPE_PLAYLIST },
+	// Real Media
+//	{ "audio/x-pn-realaudio", DEMUXER_TYPE_REAL },
+	// OGG Streaming
+	{ "application/x-ogg", DEMUXER_TYPE_OGG },
+	// NullSoft Streaming Video
+	{ "video/nsv", DEMUXER_TYPE_NSV},
+	{ "misc/ultravox", DEMUXER_TYPE_NSV},
+	{ NULL, DEMUXER_TYPE_UNKNOWN},
+};
+
+
+streaming_ctrl_t *
+streaming_ctrl_new(void) {
+	streaming_ctrl_t *streaming_ctrl;
+	streaming_ctrl = malloc(sizeof(streaming_ctrl_t));
+	if( streaming_ctrl==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+		return NULL;
+	}
+	memset( streaming_ctrl, 0, sizeof(streaming_ctrl_t) );
+	return streaming_ctrl;
+}
+
+void
+streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl ) {
+	if( streaming_ctrl==NULL ) return;
+	if( streaming_ctrl->url ) url_free( streaming_ctrl->url );
+	if( streaming_ctrl->buffer ) free( streaming_ctrl->buffer );
+	if( streaming_ctrl->data ) free( streaming_ctrl->data );
+	free( streaming_ctrl );
+}
+
+
+// Converts an address family constant to a string
+
+const char *af2String(int af) {
+	switch (af) {
+		case AF_INET:	return "AF_INET";
+		
+#ifdef HAVE_AF_INET6
+		case AF_INET6:	return "AF_INET6";
+#endif
+		default:	return "Unknown address family!";
+	}
+}
+
+
+
+// Connect to a server using a TCP connection, with specified address family
+// return -2 for fatal error, like unable to resolve name, connection timeout...
+// return -1 is unable to connect to a particular port
+
+int
+connect2Server_with_af(char *host, int port, int af,int verb) {
+	int socket_server_fd;
+	int err, err_len;
+	int ret,count = 0;
+	fd_set set;
+	struct timeval tv;
+	union {
+		struct sockaddr_in four;
+#ifdef HAVE_AF_INET6
+		struct sockaddr_in6 six;
+#endif
+	} server_address;
+	size_t server_address_size;
+	void *our_s_addr;	// Pointer to sin_addr or sin6_addr
+	struct hostent *hp=NULL;
+	char buf[255];
+	
+#ifdef HAVE_WINSOCK2
+	u_long val;
+#endif
+	
+	socket_server_fd = socket(af, SOCK_STREAM, 0);
+	
+	
+	if( socket_server_fd==-1 ) {
+//		mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af));
+		return -2;
+	}
+
+	switch (af) {
+		case AF_INET:  our_s_addr = (void *) &server_address.four.sin_addr; break;
+#ifdef HAVE_AF_INET6
+		case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break;
+#endif
+		default:
+			mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af);
+			return -2;
+	}
+	
+	
+	memset(&server_address, 0, sizeof(server_address));
+	
+#ifndef HAVE_WINSOCK2
+#ifdef USE_ATON
+	if (inet_aton(host, our_s_addr)!=1)
+#else
+	if (inet_pton(af, host, our_s_addr)!=1)
+#endif
+#else
+	if ( inet_addr(host)==INADDR_NONE )
+#endif
+	{
+		if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af));
+		
+#ifdef HAVE_GETHOSTBYNAME2
+		hp=(struct hostent*)gethostbyname2( host, af );
+#else
+		hp=(struct hostent*)gethostbyname( host );
+#endif
+		if( hp==NULL ) {
+			if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host);
+			return -2;
+		}
+		
+		memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length );
+	}
+#ifdef HAVE_WINSOCK2
+	else {
+		unsigned long addr = inet_addr(host);
+		memcpy( our_s_addr, (void*)&addr, sizeof(addr) );
+	}
+#endif
+	
+	switch (af) {
+		case AF_INET:
+			server_address.four.sin_family=af;
+			server_address.four.sin_port=htons(port);			
+			server_address_size = sizeof(server_address.four);
+			break;
+#ifdef HAVE_AF_INET6		
+		case AF_INET6:
+			server_address.six.sin6_family=af;
+			server_address.six.sin6_port=htons(port);
+			server_address_size = sizeof(server_address.six);
+			break;
+#endif
+		default:
+			mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af);
+			return -2;
+	}
+
+#if defined(USE_ATON) || defined(HAVE_WINSOCK2)
+	strncpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255);
+#else
+	inet_ntop(af, our_s_addr, buf, 255);
+#endif
+	if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port );
+
+	// Turn the socket as non blocking so we can timeout on the connection
+#ifndef HAVE_WINSOCK2
+	fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK );
+#else
+	val = 1;
+	ioctlsocket( socket_server_fd, FIONBIO, &val );
+#endif
+	if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) {
+#ifndef HAVE_WINSOCK2
+		if( errno!=EINPROGRESS ) {
+#else
+		if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) {
+#endif
+			if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af));
+			closesocket(socket_server_fd);
+			return -1;
+		}
+	}
+	tv.tv_sec = 0;
+	tv.tv_usec = 500000;
+	FD_ZERO( &set );
+	FD_SET( socket_server_fd, &set );
+	// When the connection will be made, we will have a writable fd
+	while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) {
+	      if( ret<0 ) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed);
+	      else if(ret > 0) break;
+	      else if(count > 30 || mp_input_check_interrupt(500)) {
+		if(count > 30)
+		  mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout);
+		else
+		  mp_msg(MSGT_NETWORK,MSGL_V,"Connection interuppted by user\n");
+		return -3;
+	      }
+	      count++;
+	      FD_ZERO( &set );
+	      FD_SET( socket_server_fd, &set );
+	      tv.tv_sec = 0;
+	      tv.tv_usec = 500000;
+	}
+
+	// Turn back the socket as blocking
+#ifndef HAVE_WINSOCK2
+	fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK );
+#else
+	val = 0;
+	ioctlsocket( socket_server_fd, FIONBIO, &val );
+#endif
+	// Check if there were any error
+	err_len = sizeof(int);
+	ret =  getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len);
+	if(ret < 0) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno));
+		return -2;
+	}
+	if(err > 0) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err));
+		return -1;
+	}
+	
+	return socket_server_fd;
+}
+
+// Connect to a server using a TCP connection
+// return -2 for fatal error, like unable to resolve name, connection timeout...
+// return -1 is unable to connect to a particular port
+
+
+int
+connect2Server(char *host, int  port, int verb) {
+#ifdef HAVE_AF_INET6
+	int r;
+	int s = -2;
+
+	r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6,verb);	
+	if (r > -1) return r;
+
+	s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET,verb);
+	if (s == -2) return r;
+	return s;
+#else	
+	return connect2Server_with_af(host, port, AF_INET,verb);
+#endif
+
+	
+}
+
+URL_t*
+check4proxies( URL_t *url ) {
+	URL_t *url_out = NULL;
+	if( url==NULL ) return NULL;
+	url_out = url_new( url->url );
+	if( !strcasecmp(url->protocol, "http_proxy") ) {
+		mp_msg(MSGT_NETWORK,MSGL_V,"Using HTTP proxy: http://%s:%d\n", url->hostname, url->port );
+		return url_out;
+	}
+	// Check if the http_proxy environment variable is set.
+	if( !strcasecmp(url->protocol, "http") ) {
+		char *proxy;
+		proxy = getenv("http_proxy");
+		if( proxy!=NULL ) {
+			// We got a proxy, build the URL to use it
+			int len;
+			char *new_url;
+			URL_t *tmp_url;
+			URL_t *proxy_url = url_new( proxy );
+
+			if( proxy_url==NULL ) {
+				mp_msg(MSGT_NETWORK,MSGL_WARN,
+					MSGTR_MPDEMUX_NW_InvalidProxySettingTryingWithout);
+				return url_out;
+			}
+			
+#ifdef HAVE_AF_INET6
+			if (network_ipv4_only_proxy && (gethostbyname(url->hostname)==NULL)) {
+				mp_msg(MSGT_NETWORK,MSGL_WARN,
+					MSGTR_MPDEMUX_NW_CantResolvTryingWithoutProxy);
+				url_free(proxy_url);
+				return url_out;
+			}
+#endif
+
+			mp_msg(MSGT_NETWORK,MSGL_V,"Using HTTP proxy: %s\n", proxy_url->url );
+			len = strlen( proxy_url->hostname ) + strlen( url->url ) + 20;	// 20 = http_proxy:// + port
+			new_url = malloc( len+1 );
+			if( new_url==NULL ) {
+				mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+				url_free(proxy_url);
+				return url_out;
+			}
+			sprintf(new_url, "http_proxy://%s:%d/%s", proxy_url->hostname, proxy_url->port, url->url );
+			tmp_url = url_new( new_url );
+			if( tmp_url==NULL ) {
+				free( new_url );
+				url_free( proxy_url );
+				return url_out;
+			}
+			url_free( url_out );
+			url_out = tmp_url;
+			free( new_url );
+			url_free( proxy_url );
+		}
+	}
+	return url_out;
+}
+
+int
+http_send_request( URL_t *url, off_t pos ) {
+	HTTP_header_t *http_hdr;
+	URL_t *server_url;
+	char str[256];
+	int fd;
+	int ret;
+	int proxy = 0;		// Boolean
+
+	http_hdr = http_new_header();
+
+	if( !strcasecmp(url->protocol, "http_proxy") ) {
+		proxy = 1;
+		server_url = url_new( (url->file)+1 );
+		http_set_uri( http_hdr, server_url->url );
+	} else {
+		server_url = url;
+		http_set_uri( http_hdr, server_url->file );
+	}
+	if (server_url->port && server_url->port != 80)
+	    snprintf(str, 256, "Host: %s:%d", server_url->hostname, server_url->port );
+	else
+	    snprintf(str, 256, "Host: %s", server_url->hostname );
+	http_set_field( http_hdr, str);
+	if (network_useragent)
+	{
+	    snprintf(str, 256, "User-Agent: %s", network_useragent);
+	    http_set_field(http_hdr, str);
+	}
+	else
+	    http_set_field( http_hdr, "User-Agent: MPlayer/"VERSION);
+
+	http_set_field(http_hdr, "Icy-MetaData: 1");
+
+	if(pos>0) { 
+	// Extend http_send_request with possibility to do partial content retrieval
+	    snprintf(str, 256, "Range: bytes=%"PRId64"-", (int64_t)pos);
+	    http_set_field(http_hdr, str);
+	}
+	    
+	if (network_cookies_enabled) cookies_set( http_hdr, server_url->hostname, server_url->url );
+	
+	http_set_field( http_hdr, "Connection: close");
+	http_add_basic_authentication( http_hdr, url->username, url->password );
+	if( http_build_request( http_hdr )==NULL ) {
+		goto err_out;
+	}
+
+	if( proxy ) {
+		if( url->port==0 ) url->port = 8080;			// Default port for the proxy server
+		fd = connect2Server( url->hostname, url->port,1 );
+		url_free( server_url );
+		server_url = NULL;
+	} else {
+		if( server_url->port==0 ) server_url->port = 80;	// Default port for the web server
+		fd = connect2Server( server_url->hostname, server_url->port,1 );
+	}
+	if( fd<0 ) {
+		goto err_out;
+	}
+	mp_msg(MSGT_NETWORK,MSGL_DBG2,"Request: [%s]\n", http_hdr->buffer );
+	
+	ret = send( fd, http_hdr->buffer, http_hdr->buffer_size, 0 );
+	if( ret!=(int)http_hdr->buffer_size ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ErrSendingHTTPRequest);
+		goto err_out;
+	}
+	
+	http_free( http_hdr );
+
+	return fd;
+err_out:
+	http_free(http_hdr);
+	if (proxy && server_url)
+		url_free(server_url);
+	return -1;
+}
+
+HTTP_header_t *
+http_read_response( int fd ) {
+	HTTP_header_t *http_hdr;
+	char response[BUFFER_SIZE];
+	int i;
+
+	http_hdr = http_new_header();
+	if( http_hdr==NULL ) {
+		return NULL;
+	}
+
+	do {
+		i = recv( fd, response, BUFFER_SIZE, 0 ); 
+		if( i<0 ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ReadFailed);
+			http_free( http_hdr );
+			return NULL;
+		}
+		if( i==0 ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_Read0CouldBeEOF);
+			http_free( http_hdr );
+			return NULL;
+		}
+		http_response_append( http_hdr, response, i );
+	} while( !http_is_header_entire( http_hdr ) ); 
+	http_response_parse( http_hdr );
+	return http_hdr;
+}
+
+int
+http_authenticate(HTTP_header_t *http_hdr, URL_t *url, int *auth_retry) {
+	char *aut;
+
+	if( *auth_retry==1 ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_AuthFailed);
+		return -1;
+	}
+	if( *auth_retry>0 ) {
+		if( url->username ) {
+			free( url->username );
+			url->username = NULL;
+		}
+		if( url->password ) {
+			free( url->password );
+			url->password = NULL;
+		}
+	}
+
+	aut = http_get_field(http_hdr, "WWW-Authenticate");
+	if( aut!=NULL ) {
+		char *aut_space;
+		aut_space = strstr(aut, "realm=");
+		if( aut_space!=NULL ) aut_space += 6;
+		mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_AuthRequiredFor, aut_space);
+	} else {
+		mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_AuthRequired);
+	}
+	if( network_username ) {
+		url->username = strdup(network_username);
+		if( url->username==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+			return -1;
+		}
+	} else {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_AuthFailed);
+		return -1;
+	}
+	if( network_password ) {
+		url->password = strdup(network_password);
+		if( url->password==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+			return -1;
+		}
+	} else {
+		mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_NoPasswdProvidedTryingBlank);
+	}
+	(*auth_retry)++;
+	return 0;
+}
+
+int
+http_seek( stream_t *stream, off_t pos ) {
+	HTTP_header_t *http_hdr = NULL;
+	int fd;
+	if( stream==NULL ) return 0;
+
+	if( stream->fd>0 ) closesocket(stream->fd); // need to reconnect to seek in http-stream
+	fd = http_send_request( stream->streaming_ctrl->url, pos ); 
+	if( fd<0 ) return 0;
+
+	http_hdr = http_read_response( fd );
+
+	if( http_hdr==NULL ) return 0;
+
+	switch( http_hdr->status_code ) {
+		case 200:
+		case 206: // OK
+			mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") );
+			mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") );
+			if( http_hdr->body_size>0 ) {
+				if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
+					http_free( http_hdr );
+					return -1;
+				}
+			}
+			break;
+		default:
+			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ErrServerReturned, http_hdr->status_code, http_hdr->reason_phrase );
+			close( fd );
+			fd = -1;
+	}
+	stream->fd = fd;
+
+	if( http_hdr ) {
+		http_free( http_hdr );
+		stream->streaming_ctrl->data = NULL;
+	}
+
+	stream->pos=pos;
+
+	return 1;
+}
+
+
+int
+streaming_bufferize( streaming_ctrl_t *streaming_ctrl, char *buffer, int size) {
+//printf("streaming_bufferize\n");
+	streaming_ctrl->buffer = malloc(size);
+	if( streaming_ctrl->buffer==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+		return -1;
+	}
+	memcpy( streaming_ctrl->buffer, buffer, size );
+	streaming_ctrl->buffer_size = size;
+	return size;
+}
+
+int
+nop_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) {
+	int len=0;
+//printf("nop_streaming_read\n");
+	if( stream_ctrl->buffer_size!=0 ) {
+		int buffer_len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos;
+//printf("%d bytes in buffer\n", stream_ctrl->buffer_size);
+		len = (size<buffer_len)?size:buffer_len;
+		memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len );
+		stream_ctrl->buffer_pos += len;
+//printf("buffer_pos = %d\n", stream_ctrl->buffer_pos );
+		if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) {
+			free( stream_ctrl->buffer );
+			stream_ctrl->buffer = NULL;
+			stream_ctrl->buffer_size = 0;
+			stream_ctrl->buffer_pos = 0;
+//printf("buffer cleaned\n");
+		}
+//printf("read %d bytes from buffer\n", len );
+	}
+
+	if( len<size ) {
+		int ret;
+		ret = recv( fd, buffer+len, size-len, 0 );
+		if( ret<0 ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_read error : %s\n",strerror(errno));
+		}
+		len += ret;
+//printf("read %d bytes from network\n", len );
+	}
+	
+	return len;
+}
+
+int
+nop_streaming_seek( int fd, off_t pos, streaming_ctrl_t *stream_ctrl ) {
+	return -1;
+	// To shut up gcc warning
+	fd++;
+	pos++;
+	stream_ctrl=NULL;
+}
+
+
+void fixup_network_stream_cache(stream_t *stream) {
+  if(stream->streaming_ctrl->buffering) {
+    if(stream_cache_size<0) {
+      // cache option not set, will use our computed value.
+      // buffer in KBytes, *5 because the prefill is 20% of the buffer.
+      stream_cache_size = (stream->streaming_ctrl->prebuffer_size/1024)*5;
+      if( stream_cache_size<64 ) stream_cache_size = 64;	// 16KBytes min buffer
+    }
+    mp_msg(MSGT_NETWORK,MSGL_INFO,MSGTR_MPDEMUX_NW_CacheSizeSetTo, stream_cache_size);
+  }
+}
+
+
+int
+streaming_stop( stream_t *stream ) {
+	stream->streaming_ctrl->status = streaming_stopped_e;
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/network.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,68 @@
+/*
+ * Network layer for MPlayer
+ * by Bertrand BAUDET <bertrand_baudet@yahoo.com>
+ * (C) 2001, MPlayer team.
+ */
+
+#ifndef __NETWORK_H
+#define __NETWORK_H
+
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#endif
+
+#include "url.h"
+#include "http.h"
+#include "stream.h"
+
+#define BUFFER_SIZE		2048
+
+typedef struct {
+	const char *mime_type;
+	int demuxer_type;
+} mime_struct_t;
+
+typedef enum {
+	streaming_stopped_e,
+	streaming_playing_e
+} streaming_status;
+
+typedef struct streaming_control {
+	URL_t *url;
+	streaming_status status;
+	int buffering;	// boolean
+	unsigned int prebuffer_size;
+	char *buffer;
+	unsigned int buffer_size;
+	unsigned int buffer_pos;
+	unsigned int bandwidth;	// The downstream available
+	int (*streaming_read)( int fd, char *buffer, int buffer_size, struct streaming_control *stream_ctrl );
+	int (*streaming_seek)( int fd, off_t pos, struct streaming_control *stream_ctrl );
+	void *data;
+} streaming_ctrl_t;
+
+//int streaming_start( stream_t *stream, int *demuxer_type, URL_t *url );
+streaming_ctrl_t *streaming_ctrl_new(void);
+int streaming_bufferize( streaming_ctrl_t *streaming_ctrl, char *buffer, int size);
+
+int nop_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl );
+int nop_streaming_seek( int fd, off_t pos, streaming_ctrl_t *stream_ctrl );
+void streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl );
+
+int connect2Server(char *host, int port,int verb);
+
+int http_send_request(URL_t *url, off_t pos);
+HTTP_header_t *http_read_response(int fd);
+
+int http_authenticate(HTTP_header_t *http_hdr, URL_t *url, int *auth_retry);
+URL_t* check4proxies(URL_t *url);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/open.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,49 @@
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifdef __FreeBSD__
+#include <sys/cdrio.h>
+#endif
+
+#include "m_option.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "mf.h"
+
+
+/// We keep these 2 for the gui atm, but they will be removed.
+int vcd_track=0;
+char* cdrom_device=NULL;
+int dvd_chapter=1;
+int dvd_last_chapter=0;
+char* dvd_device=NULL;
+int dvd_title=0;
+
+// Open a new stream  (stdin/file/vcd/url)
+
+stream_t* open_stream(char* filename,char** options, int* file_format){
+  // Check if playlist or unknown 
+  if (*file_format != DEMUXER_TYPE_PLAYLIST){
+    *file_format=DEMUXER_TYPE_UNKNOWN;
+  }
+
+if(!filename) {
+   mp_msg(MSGT_OPEN,MSGL_ERR,"NULL filename, report this bug\n");
+   return NULL;
+}
+
+//============ Open STDIN or plain FILE ============
+
+  return open_stream_full(filename,STREAM_READ,options,file_format);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/pnm.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,921 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ * $Id$
+ *
+ * pnm protocol implementation 
+ * based upon code from joschka
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <inttypes.h>
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#include <sys/socket.h>
+//#include <netinet/in.h>
+//#include <netdb.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include "stream.h"
+#include "demuxer.h"
+#include "help_mp.h"
+#include "osdep/timer.h"
+
+#include "pnm.h"
+//#include "libreal/rmff.h"
+
+extern int network_bandwidth;
+
+#define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
+        (((long)(unsigned char)(ch3)       ) | \
+        ( (long)(unsigned char)(ch2) << 8  ) | \
+        ( (long)(unsigned char)(ch1) << 16 ) | \
+        ( (long)(unsigned char)(ch0) << 24 ) )
+
+
+#define RMF_TAG   FOURCC_TAG('.', 'R', 'M', 'F')
+#define PROP_TAG  FOURCC_TAG('P', 'R', 'O', 'P')
+#define MDPR_TAG  FOURCC_TAG('M', 'D', 'P', 'R')
+#define CONT_TAG  FOURCC_TAG('C', 'O', 'N', 'T')
+#define DATA_TAG  FOURCC_TAG('D', 'A', 'T', 'A')
+#define INDX_TAG  FOURCC_TAG('I', 'N', 'D', 'X')
+#define PNA_TAG   FOURCC_TAG('P', 'N', 'A',  0 )
+
+/*
+#define LOG
+*/
+
+#define BUF_SIZE 4096
+#define HEADER_SIZE 4096
+
+struct pnm_s {
+
+  int           s;
+
+//  char         *host;
+//  int           port;
+  char         *path;
+//  char         *url;
+
+  char          buffer[BUF_SIZE]; /* scratch buffer */
+
+  /* receive buffer */
+  uint8_t       recv[BUF_SIZE];
+  int           recv_size;
+  int           recv_read;
+
+  uint8_t       header[HEADER_SIZE];
+  int           header_len;
+  int           header_read;
+  unsigned int  seq_num[4];     /* two streams with two indices   */
+  unsigned int  seq_current[2]; /* seqs of last stream chunk read */
+  uint32_t      ts_current;     /* timestamp of current chunk     */
+  uint32_t      ts_last[2];     /* timestamps of last chunks      */
+  unsigned int  packet;         /* number of last recieved packet */
+};
+
+/*
+ * utility macros
+ */
+
+#define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
+#define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
+                   (((uint8_t*)(x))[1] << 16) | \
+                   (((uint8_t*)(x))[2] << 8) | \
+                    ((uint8_t*)(x))[3])
+
+/* D means direct (no pointer) */
+#define BE_16D(x) ((x & 0xff00) >> 8)|((x & 0x00ff) << 8)
+
+/* sizes */
+#define PREAMBLE_SIZE 8
+#define CHECKSUM_SIZE 3
+
+
+/* header of rm files */
+#define RM_HEADER_SIZE 0x12
+static const unsigned char rm_header[]={
+        0x2e, 0x52, 0x4d, 0x46, /* object_id      ".RMF" */
+        0x00, 0x00, 0x00, 0x12, /* header_size    0x12   */
+        0x00, 0x00,             /* object_version 0x00   */
+        0x00, 0x00, 0x00, 0x00, /* file_version   0x00   */
+        0x00, 0x00, 0x00, 0x06  /* num_headers    0x06   */
+};
+
+/* data chunk header */
+#define PNM_DATA_HEADER_SIZE 18
+static const unsigned char pnm_data_header[]={
+        'D','A','T','A',
+         0,0,0,0,       /* data chunk size  */
+         0,0,           /* object version   */
+         0,0,0,0,       /* num packets      */
+         0,0,0,0};      /* next data header */
+
+/* pnm request chunk ids */
+
+#define PNA_CLIENT_CAPS      0x03
+#define PNA_CLIENT_CHALLANGE 0x04
+#define PNA_BANDWIDTH        0x05
+#define PNA_GUID             0x13
+#define PNA_TIMESTAMP        0x17
+#define PNA_TWENTYFOUR       0x18
+
+#define PNA_CLIENT_STRING    0x63
+#define PNA_PATH_REQUEST     0x52
+
+static const unsigned char pnm_challenge[] = "0990f6b4508b51e801bd6da011ad7b56";
+static const unsigned char pnm_timestamp[] = "[15/06/1999:22:22:49 00:00]";
+static const unsigned char pnm_guid[]      = "3eac2411-83d5-11d2-f3ea-d7c3a51aa8b0";
+static const unsigned char pnm_response[]  = "97715a899cbe41cee00dd434851535bf";
+static const unsigned char client_string[] = "WinNT_9.0_6.0.6.45_plus32_MP60_en-US_686l";
+
+#define PNM_HEADER_SIZE 11
+static const unsigned char pnm_header[] = {
+        'P','N','A',
+        0x00, 0x0a,
+        0x00, 0x14,
+        0x00, 0x02,
+        0x00, 0x01 };
+
+#define PNM_CLIENT_CAPS_SIZE 126
+static const unsigned char pnm_client_caps[] = {
+    0x07, 0x8a, 'p','n','r','v', 
+       0, 0x90, 'p','n','r','v', 
+       0, 0x64, 'd','n','e','t', 
+       0, 0x46, 'p','n','r','v', 
+       0, 0x32, 'd','n','e','t', 
+       0, 0x2b, 'p','n','r','v', 
+       0, 0x28, 'd','n','e','t', 
+       0, 0x24, 'p','n','r','v', 
+       0, 0x19, 'd','n','e','t', 
+       0, 0x18, 'p','n','r','v', 
+       0, 0x14, 's','i','p','r', 
+       0, 0x14, 'd','n','e','t', 
+       0, 0x24, '2','8','_','8', 
+       0, 0x12, 'p','n','r','v', 
+       0, 0x0f, 'd','n','e','t', 
+       0, 0x0a, 's','i','p','r', 
+       0, 0x0a, 'd','n','e','t', 
+       0, 0x08, 's','i','p','r', 
+       0, 0x06, 's','i','p','r', 
+       0, 0x12, 'l','p','c','J', 
+       0, 0x07, '0','5','_','6' };
+
+static const uint32_t pnm_default_bandwidth=10485800;
+static const uint32_t pnm_available_bandwidths[]={14400,19200,28800,33600,34430,57600,
+                                  115200,262200,393216,524300,1544000,10485800};
+
+#define PNM_TWENTYFOUR_SIZE 16
+static unsigned char pnm_twentyfour[]={
+    0xd5, 0x42, 0xa3, 0x1b, 0xef, 0x1f, 0x70, 0x24,
+    0x85, 0x29, 0xb3, 0x8d, 0xba, 0x11, 0xf3, 0xd6 };
+
+/* now other data follows. marked with 0x0000 at the beginning */
+static int after_chunks_length=6;
+static unsigned char after_chunks[]={
+    0x00, 0x00, /* mark */
+    
+    0x50, 0x84, /* seems to be fixated */
+    0x1f, 0x3a  /* varies on each request (checksum ?)*/
+    };
+
+static void hexdump (char *buf, int length);
+
+static int rm_write(int s, const char *buf, int len) {
+  int total, timeout;
+
+  total = 0; timeout = 30;
+  while (total < len){ 
+    int n;
+
+    n = send (s, &buf[total], len - total, 0);
+
+    if (n > 0)
+      total += n;
+    else if (n < 0) {
+#ifndef HAVE_WINSOCK2
+      if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) {
+#else
+      if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) {
+#endif
+        usec_sleep (1000000); timeout--;
+      } else
+        return -1;
+    }
+  }
+
+  return total;
+}
+
+static ssize_t rm_read(int fd, void *buf, size_t count) {
+  
+  ssize_t ret, total;
+
+  total = 0;
+
+  while (total < count) {
+  
+    fd_set rset;
+    struct timeval timeout;
+
+    FD_ZERO (&rset);
+    FD_SET  (fd, &rset);
+    
+    timeout.tv_sec  = 3;
+    timeout.tv_usec = 0;
+    
+    if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) {
+      return -1;
+    }
+    
+    ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0);
+
+    if (ret<=0) {
+      mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: read error.\n");
+      return ret;
+    } else
+      total += ret;
+  }
+
+  return total;
+}
+
+/*
+ * debugging utilities
+ */
+ 
+static void hexdump (char *buf, int length) {
+
+  int i;
+
+  mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: ascii>");
+  for (i = 0; i < length; i++) {
+    unsigned char c = buf[i];
+
+    if ((c >= 32) && (c <= 128))
+      mp_msg(MSGT_OPEN, MSGL_INFO, "%c", c);
+    else
+      mp_msg(MSGT_OPEN, MSGL_INFO, ".");
+  }
+  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
+
+  mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: hexdump> ");
+  for (i = 0; i < length; i++) {
+    unsigned char c = buf[i];
+
+    mp_msg(MSGT_OPEN, MSGL_INFO, "%02x", c);
+
+    if ((i % 16) == 15)
+      mp_msg(MSGT_OPEN, MSGL_INFO, "\npnm:         ");
+
+    if ((i % 2) == 1)
+      mp_msg(MSGT_OPEN, MSGL_INFO, " ");
+
+  }
+  mp_msg(MSGT_OPEN, MSGL_INFO, "\n");
+}
+
+/*
+ * pnm_get_chunk gets a chunk from stream
+ * and returns number of bytes read 
+ */
+
+static int pnm_get_chunk(pnm_t *p, 
+                         unsigned int max,
+                         unsigned int *chunk_type,
+                         char *data, int *need_response) {
+
+  unsigned int chunk_size;
+  unsigned int n;
+  char *ptr;
+ 
+  if (max < PREAMBLE_SIZE)
+    return -1;
+
+  /* get first PREAMBLE_SIZE bytes and ignore checksum */
+  rm_read (p->s, data, CHECKSUM_SIZE);
+  if (data[0] == 0x72)
+    rm_read (p->s, data, PREAMBLE_SIZE);
+  else
+    rm_read (p->s, data+CHECKSUM_SIZE, PREAMBLE_SIZE-CHECKSUM_SIZE);
+  
+  max -= PREAMBLE_SIZE;
+
+  *chunk_type = BE_32(data);
+  chunk_size = BE_32(data+4);
+
+  switch (*chunk_type) {
+    case PNA_TAG:
+      *need_response=0;
+      ptr=data+PREAMBLE_SIZE;
+      if (max < 1)
+	return -1;
+      rm_read (p->s, ptr++, 1);
+      max -= 1;
+
+      while(1) {
+	/* expecting following chunk format: 0x4f <chunk size> <data...> */
+
+        if (max < 2)
+          return -1;
+        rm_read (p->s, ptr, 2);
+        max -= 2;
+	if (*ptr == 'X') /* checking for server message */
+	{
+	  mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: got a message from server:\n");
+	  if (max < 1)
+	    return -1;
+	  rm_read (p->s, ptr+2, 1);
+	  max = -1;
+	  n=BE_16(ptr+1);
+	  if (max < n)
+	    return -1;
+	  rm_read (p->s, ptr+3, n);
+	  max -= n;
+	  ptr[3+n]=0;
+	  mp_msg(MSGT_OPEN, MSGL_WARN, "%s\n",ptr+3);
+	  return -1;
+	}
+	
+	if (*ptr == 'F') /* checking for server error */
+	{
+	  mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: server error.\n");
+	  return -1;
+	}
+	if (*ptr == 'i')
+	{
+	  ptr+=2;
+	  *need_response=1;
+	  continue;
+	}
+	if (*ptr != 0x4f) break;
+	n=ptr[1];
+	if (max < n)
+	  return -1;
+	rm_read (p->s, ptr+2, n);
+	max -= n;
+	ptr+=(n+2);
+      }
+      /* the checksum of the next chunk is ignored here */
+      if (max < 1)
+        return -1;
+      rm_read (p->s, ptr+2, 1);
+      ptr+=3;
+      chunk_size=ptr-data;
+      break;
+    case RMF_TAG:
+    case DATA_TAG:
+    case PROP_TAG:
+    case MDPR_TAG:
+    case CONT_TAG:
+      if (chunk_size > max || chunk_size < PREAMBLE_SIZE) {
+        mp_msg(MSGT_OPEN, MSGL_ERR, "error: max chunk size exceded (max was 0x%04x)\n", max);
+#ifdef LOG
+        n=rm_read (p->s, &data[PREAMBLE_SIZE], 0x100 - PREAMBLE_SIZE);
+        hexdump(data,n+PREAMBLE_SIZE);
+#endif
+        return -1;
+      }
+      rm_read (p->s, &data[PREAMBLE_SIZE], chunk_size-PREAMBLE_SIZE);
+      break;
+    default:
+      *chunk_type = 0;
+      chunk_size  = PREAMBLE_SIZE; 
+      break;
+  }
+
+  return chunk_size;
+}
+
+/*
+ * writes a chunk to a buffer, returns number of bytes written
+ */
+
+static int pnm_write_chunk(uint16_t chunk_id, uint16_t length, 
+    const char *chunk, char *data) {
+
+  data[0]=(chunk_id>>8)%0xff;
+  data[1]=chunk_id%0xff;
+  data[2]=(length>>8)%0xff;
+  data[3]=length%0xff;
+  memcpy(&data[4],chunk,length);
+  
+  return length+4;
+}
+
+/*
+ * constructs a request and sends it
+ */
+
+static void pnm_send_request(pnm_t *p, uint32_t bandwidth) {
+
+  uint16_t i16;
+  int c=PNM_HEADER_SIZE;
+  char fixme[]={0,1};
+
+  memcpy(p->buffer,pnm_header,PNM_HEADER_SIZE);
+  c+=pnm_write_chunk(PNA_CLIENT_CHALLANGE,strlen(pnm_challenge),
+          pnm_challenge,&p->buffer[c]);
+  c+=pnm_write_chunk(PNA_CLIENT_CAPS,PNM_CLIENT_CAPS_SIZE,
+          pnm_client_caps,&p->buffer[c]);
+  c+=pnm_write_chunk(0x0a,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x0c,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x0d,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x16,2,fixme,&p->buffer[c]);
+  c+=pnm_write_chunk(PNA_TIMESTAMP,strlen(pnm_timestamp),
+          pnm_timestamp,&p->buffer[c]);
+  c+=pnm_write_chunk(PNA_BANDWIDTH,4,
+          (const char *)&pnm_default_bandwidth,&p->buffer[c]);
+  c+=pnm_write_chunk(0x08,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x0e,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x0f,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x11,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x10,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x15,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(0x12,0,NULL,&p->buffer[c]);
+  c+=pnm_write_chunk(PNA_GUID,strlen(pnm_guid),
+          pnm_guid,&p->buffer[c]);
+  c+=pnm_write_chunk(PNA_TWENTYFOUR,PNM_TWENTYFOUR_SIZE,
+          pnm_twentyfour,&p->buffer[c]);
+  
+  /* data after chunks */
+  memcpy(&p->buffer[c],after_chunks,after_chunks_length);
+  c+=after_chunks_length;
+
+  /* client id string */
+  p->buffer[c]=PNA_CLIENT_STRING;
+  i16=BE_16D((strlen(client_string)-1)); /* don't know why do we have -1 here */
+  memcpy(&p->buffer[c+1],&i16,2);
+  memcpy(&p->buffer[c+3],client_string,strlen(client_string)+1);
+  c=c+3+strlen(client_string)+1;
+
+  /* file path */
+  p->buffer[c]=0;
+  p->buffer[c+1]=PNA_PATH_REQUEST;
+  i16=BE_16D(strlen(p->path));
+  memcpy(&p->buffer[c+2],&i16,2);
+  memcpy(&p->buffer[c+4],p->path,strlen(p->path));
+  c=c+4+strlen(p->path);
+
+  /* some trailing bytes */
+  p->buffer[c]='y';
+  p->buffer[c+1]='B';
+  
+  rm_write(p->s,p->buffer,c+2);
+}
+
+/*
+ * pnm_send_response sends a response of a challenge
+ */
+
+static void pnm_send_response(pnm_t *p, const char *response) {
+
+  int size=strlen(response);
+
+  p->buffer[0]=0x23;
+  p->buffer[1]=0;
+  p->buffer[2]=(unsigned char) size;
+
+  memcpy(&p->buffer[3], response, size);
+
+  rm_write (p->s, p->buffer, size+3);
+
+}
+
+/*
+ * get headers and challenge and fix headers
+ * write headers to p->header
+ * write challenge to p->buffer
+ *
+ * return 0 on error.  != 0 on success
+ */
+
+static int pnm_get_headers(pnm_t *p, int *need_response) {
+
+  uint32_t chunk_type;
+  uint8_t  *ptr=p->header;
+  uint8_t  *prop_hdr=NULL;
+  int      chunk_size,size=0;
+  int      nr;
+/*  rmff_header_t *h; */
+
+  *need_response=0;
+
+  while(1) {
+    if (HEADER_SIZE-size<=0)
+    {
+      mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: header buffer overflow. exiting\n");
+      return 0;
+    }
+    chunk_size=pnm_get_chunk(p,HEADER_SIZE-size,&chunk_type,ptr,&nr);
+    if (chunk_size < 0) return 0;
+    if (chunk_type == 0) break;
+    if (chunk_type == PNA_TAG)
+    {
+      memcpy(ptr, rm_header, RM_HEADER_SIZE);
+      chunk_size=RM_HEADER_SIZE;
+      *need_response=nr;
+    }
+    if (chunk_type == DATA_TAG)
+      chunk_size=0;
+    if (chunk_type == RMF_TAG)
+      chunk_size=0;
+    if (chunk_type == PROP_TAG)
+        prop_hdr=ptr;
+    size+=chunk_size;
+    ptr+=chunk_size;
+  }
+  
+  if (!prop_hdr) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: error while parsing headers.\n");
+    return 0;
+  }
+  
+  /* set data offset */
+  size--;
+  prop_hdr[42]=(size>>24)%0xff;
+  prop_hdr[43]=(size>>16)%0xff;
+  prop_hdr[44]=(size>>8)%0xff;
+  prop_hdr[45]=(size)%0xff;
+  size++;
+
+  /* read challenge */
+  memcpy (p->buffer, ptr, PREAMBLE_SIZE);
+  rm_read (p->s, &p->buffer[PREAMBLE_SIZE], 64);
+
+  /* now write a data header */
+  memcpy(ptr, pnm_data_header, PNM_DATA_HEADER_SIZE);
+  size+=PNM_DATA_HEADER_SIZE;
+/*  
+  h=rmff_scan_header(p->header);
+  rmff_fix_header(h);
+  p->header_len=rmff_get_header_size(h);
+  rmff_dump_header(h, p->header, HEADER_SIZE);
+*/
+  p->header_len=size;
+  
+  return 1;
+}
+
+/* 
+ * determine correct stream number by looking at indices
+ */
+
+static int pnm_calc_stream(pnm_t *p) {
+
+  char str0=0,str1=0;
+
+  /* looking at the first index to
+   * find possible stream types
+   */
+  if (p->seq_current[0]==p->seq_num[0]) str0=1;
+  if (p->seq_current[0]==p->seq_num[2]) str1=1;
+
+  switch (str0+str1) {
+    case 1: /* one is possible, good. */
+      if (str0)
+      {
+        p->seq_num[0]++;
+        p->seq_num[1]=p->seq_current[1]+1;
+        return 0;
+      } else
+      {
+        p->seq_num[2]++;
+        p->seq_num[3]=p->seq_current[1]+1;
+        return 1;
+      }
+      break;
+    case 0:
+    case 2: /* both types or none possible, not so good */
+      /* try to figure out by second index */
+      if (  (p->seq_current[1] == p->seq_num[1])
+          &&(p->seq_current[1] != p->seq_num[3]))
+      {
+        /* ok, only stream0 matches */
+        p->seq_num[0]=p->seq_current[0]+1;
+        p->seq_num[1]++;
+        return 0;
+      }
+      if (  (p->seq_current[1] == p->seq_num[3])
+          &&(p->seq_current[1] != p->seq_num[1]))
+      {
+        /* ok, only stream1 matches */
+        p->seq_num[2]=p->seq_current[0]+1;
+        p->seq_num[3]++;
+        return 1;
+      }
+      /* wow, both streams match, or not.   */
+      /* now we try to decide by timestamps */
+      if (p->ts_current < p->ts_last[1])
+        return 0;
+      if (p->ts_current < p->ts_last[0])
+        return 1;
+      /* does not help, we guess type 0     */
+#ifdef LOG
+      mp_msg(MSGT_OPEN, MSGL_INFO, "guessing stream# 0\n");
+#endif
+      p->seq_num[0]=p->seq_current[0]+1;
+      p->seq_num[1]=p->seq_current[1]+1;
+      return 0;
+      break;
+  }
+  mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: wow, something very nasty happened in pnm_calc_stream\n");
+  return 2;
+}
+
+/*
+ * gets a stream chunk and writes it to a recieve buffer
+ */
+
+static int pnm_get_stream_chunk(pnm_t *p) {
+
+  int  n;
+  char keepalive='!';
+  unsigned int fof1, fof2, stream;
+
+  /* send a keepalive                               */
+  /* realplayer seems to do that every 43th package */
+  if ((p->packet%43) == 42)  
+  {
+    rm_write(p->s,&keepalive,1);
+  }
+
+  /* data chunks begin with: 'Z' <o> <o> <i1> 'Z' <i2>
+   * where <o> is the offset to next stream chunk,
+   * <i1> is a 16 bit index
+   * <i2> is a 8 bit index which counts from 0x10 to somewhere
+   */
+  
+  n = rm_read (p->s, p->buffer, 8);
+  if (n<0) return -1;
+  if (n<8) return 0;
+  
+  /* skip 8 bytes if 0x62 is read */
+  if (p->buffer[0] == 0x62)
+  {
+    n = rm_read (p->s, p->buffer, 8);
+    if (n<8) return 0;
+#ifdef LOG
+    mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: had to seek 8 bytes on 0x62\n");
+#endif
+  }
+  
+  /* a server message */
+  if (p->buffer[0] == 'X')
+  {
+    int size=BE_16(&p->buffer[1]);
+
+    rm_read (p->s, &p->buffer[8], size-5);
+    p->buffer[size+3]=0;
+    mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: got message from server while reading stream:\n%s\n", &p->buffer[3]);
+    return -1;
+  }
+  if (p->buffer[0] == 'F')
+  {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: server error.\n");
+    return -1;
+  }
+
+  /* skip bytewise to next chunk.
+   * seems, that we don't need that, if we send enough
+   * keepalives
+   */
+  n=0;
+  while (p->buffer[0] != 0x5a) {
+    int i;
+    for (i=1; i<8; i++) {
+      p->buffer[i-1]=p->buffer[i];
+    }
+    rm_read (p->s, &p->buffer[7], 1);
+    n++;
+  }
+
+#ifdef LOG
+  if (n) mp_msg(MSGT_OPEN, MSGL_WARN, "input_pnm: had to seek %i bytes to next chunk\n", n);
+#endif
+
+  /* check for 'Z's */
+  if ((p->buffer[0] != 0x5a)||(p->buffer[7] != 0x5a))
+  {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: bad boundaries\n");
+    hexdump(p->buffer, 8);
+    return 0;
+  }
+
+  /* check offsets */
+  fof1=BE_16(&p->buffer[1]);
+  fof2=BE_16(&p->buffer[3]);
+  if (fof1 != fof2)
+  {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: frame offsets are different: 0x%04x 0x%04x\n",fof1,fof2);
+    return 0;
+  }
+
+  /* get first index */
+  p->seq_current[0]=BE_16(&p->buffer[5]);
+  
+  /* now read the rest of stream chunk */
+  n = rm_read (p->s, &p->recv[5], fof1-5);
+  if (n<(fof1-5)) return 0;
+
+  /* get second index */
+  p->seq_current[1]=p->recv[5];
+
+  /* get timestamp */
+  p->ts_current=BE_32(&p->recv[6]);
+  
+  /* get stream number */
+  stream=pnm_calc_stream(p);
+
+  /* saving timestamp */
+  p->ts_last[stream]=p->ts_current;
+  
+  /* constructing a data packet header */
+  
+  p->recv[0]=0;        /* object version */
+  p->recv[1]=0;
+
+  fof2=BE_16(&fof2);
+  memcpy(&p->recv[2], &fof2, 2);
+  /*p->recv[2]=(fof2>>8)%0xff;*/   /* length */
+  /*p->recv[3]=(fof2)%0xff;*/
+
+  p->recv[4]=0;         /* stream number */
+  p->recv[5]=stream;
+  
+  p->recv[10]=p->recv[10] & 0xfe; /* streambox seems to do that... */
+
+  p->packet++;
+
+  p->recv_size=fof1;
+
+  return fof1;
+}
+
+// pnm_t *pnm_connect(const char *mrl) {
+static pnm_t *pnm_connect(int fd, char *path) {
+  
+  pnm_t *p=malloc(sizeof(pnm_t));
+  int need_response=0;
+  
+  p->path=strdup(path);
+  p->s=fd;
+
+  pnm_send_request(p,pnm_available_bandwidths[10]);
+  if (!pnm_get_headers(p, &need_response)) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "input_pnm: failed to set up stream\n");
+    free(p->path);
+    free(p);
+    return NULL;
+  }
+  if (need_response)
+    pnm_send_response(p, pnm_response);
+  p->ts_last[0]=0;
+  p->ts_last[1]=0;
+  
+  /* copy header to recv */
+
+  memcpy(p->recv, p->header, p->header_len);
+  p->recv_size = p->header_len;
+  p->recv_read = 0;
+
+  return p;
+}
+
+static int pnm_read (pnm_t *this, char *data, int len) {
+  
+  int to_copy=len;
+  char *dest=data;
+  char *source=this->recv + this->recv_read;
+  int fill=this->recv_size - this->recv_read;
+  int retval;
+  
+  if (len < 0) return 0;
+  while (to_copy > fill) {
+    
+    memcpy(dest, source, fill);
+    to_copy -= fill;
+    dest += fill;
+    this->recv_read=0;
+
+    if ((retval = pnm_get_stream_chunk (this)) <= 0) {
+#ifdef LOG
+      mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: %d of %d bytes provided\n", len-to_copy, len);
+#endif
+      if (retval < 0)
+        return retval;
+      else
+      return len-to_copy;
+    }
+    source = this->recv;
+    fill = this->recv_size - this->recv_read;
+  }
+
+  memcpy(dest, source, to_copy);
+  this->recv_read += to_copy;
+
+#ifdef LOG
+  mp_msg(MSGT_OPEN, MSGL_INFO, "input_pnm: %d bytes provided\n", len);
+#endif
+
+  return len;
+}
+
+static int pnm_peek_header (pnm_t *this, char *data) {
+
+  memcpy (data, this->header, this->header_len);
+  return this->header_len;
+}
+
+static void pnm_close(pnm_t *p) {
+
+  if (p->s >= 0) closesocket(p->s);
+  free(p->path);
+  free(p);
+}
+
+static int pnm_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) {
+	return pnm_read(stream_ctrl->data, buffer, size);
+}
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  int fd;
+  pnm_t *pnm;
+  URL_t *url;
+
+  mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_PNM, URL: %s\n", stream->url);
+  stream->streaming_ctrl = streaming_ctrl_new();
+  if(stream->streaming_ctrl==NULL) {
+    return STREAM_ERROR;
+  }
+  stream->streaming_ctrl->bandwidth = network_bandwidth;
+  url = url_new(stream->url);
+  stream->streaming_ctrl->url = check4proxies(url);
+  //url_free(url);
+
+  fd = connect2Server( stream->streaming_ctrl->url->hostname,
+    stream->streaming_ctrl->url->port ? stream->streaming_ctrl->url->port : 7070,1 );
+  
+  if(fd<0)
+    goto fail;
+
+  pnm = pnm_connect(fd,stream->streaming_ctrl->url->file);
+  if(!pnm) 
+    goto fail;
+  stream->type = STREAMTYPE_STREAM;
+  stream->fd=fd;
+  stream->streaming_ctrl->data=pnm;
+  stream->streaming_ctrl->streaming_read = pnm_streaming_read;
+  //stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
+  stream->streaming_ctrl->prebuffer_size = 8*1024;  // 8 KBytes
+  stream->streaming_ctrl->buffering = 1;
+  stream->streaming_ctrl->status = streaming_playing_e;
+  *file_format = DEMUXER_TYPE_REAL;
+  fixup_network_stream_cache(stream);
+  return STREAM_OK;
+
+fail:
+  streaming_ctrl_free(stream->streaming_ctrl);
+  stream->streaming_ctrl = NULL;
+  return STREAM_UNSUPORTED;
+}
+
+
+stream_info_t stream_info_pnm = {
+  "RealNetworks pnm",
+  "pnm",
+  "Arpi, xine team",
+  "ported from xine",
+  open_s,
+  {"pnm", NULL},	//pnm as fallback
+  NULL,
+  0 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/asmrp.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,677 @@
+/*
+ * This file was ported to MPlayer from xine CVS asmrp.c,v 1.2 2002/12/17 16:49:48
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ * 
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * a parser for real's asm rules
+ *
+ * grammar for these rules:
+ *
+
+   rule_book  = { rule }
+   rule       = ( '#' condition { ',' assignment } | [ assignment {',' assignment} ]) ';'
+   assignment = id '=' const
+   const      = ( number | string )
+   condition  = comp_expr { ( '&&' | '||' ) comp_expr }
+   comp_expr  = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand }
+   operand    = ( '$' id | num | '(' condition ')' )
+
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/*
+#define LOG
+*/
+
+#define ASMRP_SYM_NONE         0
+#define ASMRP_SYM_EOF          1
+
+#define ASMRP_SYM_NUM          2
+#define ASMRP_SYM_ID           3
+#define ASMRP_SYM_STRING       4
+
+#define ASMRP_SYM_HASH         10
+#define ASMRP_SYM_SEMICOLON    11
+#define ASMRP_SYM_COMMA        12
+#define ASMRP_SYM_EQUALS       13
+#define ASMRP_SYM_AND          14
+#define ASMRP_SYM_OR           15
+#define ASMRP_SYM_LESS         16
+#define ASMRP_SYM_LEQ          17
+#define ASMRP_SYM_GEQ          18
+#define ASMRP_SYM_GREATER      19
+#define ASMRP_SYM_DOLLAR       20
+#define ASMRP_SYM_LPAREN       21
+#define ASMRP_SYM_RPAREN       22
+
+#define ASMRP_MAX_ID         1024
+
+#define ASMRP_MAX_SYMTAB       10
+
+typedef struct {
+  char *id;
+  int   v;
+} asmrp_sym_t;
+
+typedef struct {
+
+  /* public part */
+
+  int         sym;
+  int         num;
+  
+  char        str[ASMRP_MAX_ID];
+
+  /* private part */
+
+  char       *buf;
+  int         pos;
+  char        ch;
+
+  asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB];
+  int         sym_tab_num;
+
+} asmrp_t;
+
+static asmrp_t *asmrp_new (void) {
+
+  asmrp_t *p;
+
+  p = malloc (sizeof (asmrp_t));
+
+  p->sym_tab_num = 0;
+  p->sym         = ASMRP_SYM_NONE;
+
+  return p;
+}
+
+static void asmrp_dispose (asmrp_t *p) {
+
+  int i;
+
+  for (i=0; i<p->sym_tab_num; i++) 
+    free (p->sym_tab[i].id);
+
+  free (p);
+}
+
+static void asmrp_getch (asmrp_t *p) {
+  p->ch = p->buf[p->pos];
+  p->pos++;
+
+#ifdef LOG
+  printf ("%c\n", p->ch);
+#endif
+
+}
+
+static void asmrp_init (asmrp_t *p, const char *str) {
+
+  p->buf = strdup (str);
+  p->pos = 0;
+  
+  asmrp_getch (p);
+}
+
+static void asmrp_number (asmrp_t *p) {
+
+  int num;
+
+  num = 0;
+  while ( (p->ch>='0') && (p->ch<='9') ) {
+
+    num = num*10 + (p->ch - '0');
+
+    asmrp_getch (p);
+  }
+
+  p->sym = ASMRP_SYM_NUM;
+  p->num = num;
+}
+
+static void asmrp_string (asmrp_t *p) {
+
+  int l;
+
+  l = 0;
+
+  while ( (p->ch!='"') && (p->ch>=32) ) {
+
+    p->str[l] = p->ch;
+
+    l++;
+    asmrp_getch (p);
+  }
+  p->str[l]=0;
+  
+  if (p->ch=='"')
+    asmrp_getch (p);
+  
+  p->sym = ASMRP_SYM_STRING;
+}
+
+static void asmrp_identifier (asmrp_t *p) {
+
+  int l;
+
+  l = 0;
+
+  while ( ((p->ch>='A') && (p->ch<='z'))
+	  || ((p->ch>='0') && (p->ch<='9'))) {
+
+    p->str[l] = p->ch;
+
+    l++;
+    asmrp_getch (p);
+  }
+  p->str[l]=0;
+  
+  p->sym = ASMRP_SYM_ID;
+}
+
+#ifdef LOG
+static void asmrp_print_sym (asmrp_t *p) {
+
+  printf ("symbol: ");
+
+  switch (p->sym) {
+
+  case ASMRP_SYM_NONE:
+    printf ("NONE\n");
+    break;
+
+  case ASMRP_SYM_EOF:
+    printf ("EOF\n");
+    break;
+
+  case ASMRP_SYM_NUM:
+    printf ("NUM %d\n", p->num);
+    break;
+
+  case ASMRP_SYM_ID:
+    printf ("ID '%s'\n", p->str);
+    break;
+
+  case ASMRP_SYM_STRING:
+    printf ("STRING \"%s\"\n", p->str);
+    break;
+
+  case ASMRP_SYM_HASH:
+    printf ("#\n");
+    break;
+
+  case ASMRP_SYM_SEMICOLON:
+    printf (";\n");
+    break;
+  case ASMRP_SYM_COMMA:
+    printf (",\n");
+    break;
+  case ASMRP_SYM_EQUALS:
+    printf ("==\n");
+    break;
+  case ASMRP_SYM_AND:
+    printf ("&&\n");
+    break;
+  case ASMRP_SYM_OR:
+    printf ("||\n");
+    break;
+  case ASMRP_SYM_LESS:
+    printf ("<\n");
+    break;
+  case ASMRP_SYM_LEQ:
+    printf ("<=\n");
+    break;
+  case ASMRP_SYM_GEQ:
+    printf (">=\n");
+    break;
+  case ASMRP_SYM_GREATER:
+    printf (">\n");
+    break;
+  case ASMRP_SYM_DOLLAR:
+    printf ("$\n");
+    break;
+  case ASMRP_SYM_LPAREN:
+    printf ("(\n");
+    break;
+  case ASMRP_SYM_RPAREN:
+    printf (")\n");
+    break;
+
+  default:
+    printf ("unknown symbol %d\n", p->sym);
+  }
+}
+#endif
+
+static void asmrp_get_sym (asmrp_t *p) {
+
+  while (p->ch <= 32) {
+    if (p->ch == 0) {
+      p->sym = ASMRP_SYM_EOF;
+      return;
+    }
+
+    asmrp_getch (p);
+  }
+
+  if (p->ch == '\\')
+    asmrp_getch (p);
+
+  switch (p->ch) {
+
+  case '#':
+    p->sym = ASMRP_SYM_HASH;
+    asmrp_getch (p);
+    break;
+  case ';':
+    p->sym = ASMRP_SYM_SEMICOLON;
+    asmrp_getch (p);
+    break;
+  case ',':
+    p->sym = ASMRP_SYM_COMMA;
+    asmrp_getch (p);
+    break;
+  case '=':
+    p->sym = ASMRP_SYM_EQUALS;
+    asmrp_getch (p);
+    if (p->ch=='=')
+      asmrp_getch (p);
+    break;
+  case '&':
+    p->sym = ASMRP_SYM_AND;
+    asmrp_getch (p);
+    if (p->ch=='&')
+      asmrp_getch (p);
+    break;
+  case '|':
+    p->sym = ASMRP_SYM_OR;
+    asmrp_getch (p);
+    if (p->ch=='|')
+      asmrp_getch (p);
+    break;
+  case '<':
+    p->sym = ASMRP_SYM_LESS;
+    asmrp_getch (p);
+    if (p->ch=='=') {
+      p->sym = ASMRP_SYM_LEQ;
+      asmrp_getch (p);
+    }
+    break;
+  case '>':
+    p->sym = ASMRP_SYM_GREATER;
+    asmrp_getch (p);
+    if (p->ch=='=') {
+      p->sym = ASMRP_SYM_GEQ;
+      asmrp_getch (p);
+    }
+    break;
+  case '$':
+    p->sym = ASMRP_SYM_DOLLAR;
+    asmrp_getch (p);
+    break;
+  case '(':
+    p->sym = ASMRP_SYM_LPAREN;
+    asmrp_getch (p);
+    break;
+  case ')':
+    p->sym = ASMRP_SYM_RPAREN;
+    asmrp_getch (p);
+    break;
+
+  case '"':
+    asmrp_getch (p);
+    asmrp_string (p);
+    break;
+
+  case '0': case '1': case '2': case '3': case '4':
+  case '5': case '6': case '7': case '8': case '9':
+    asmrp_number (p);
+    break;
+
+  default:
+    asmrp_identifier (p);
+  }
+
+#ifdef LOG
+  asmrp_print_sym (p);
+#endif
+
+}
+
+static int asmrp_find_id (asmrp_t *p, char *s) {
+
+  int i;
+
+  for (i=0; i<p->sym_tab_num; i++) {
+    if (!strcmp (s, p->sym_tab[i].id))
+      return i;
+  }
+
+  return -1;
+}
+
+static int asmrp_set_id (asmrp_t *p, char *s, int v) {
+
+  int i;
+
+  i = asmrp_find_id (p, s);
+
+  if (i<0) {
+    i = p->sym_tab_num;
+    p->sym_tab_num++;
+    p->sym_tab[i].id = strdup (s);
+
+#ifdef LOG
+    printf ("new symbol '%s'\n", s);
+#endif
+
+  }    
+
+  p->sym_tab[i].v = v;
+ 
+#ifdef LOG
+  printf ("symbol '%s' assigned %d\n", s, v);
+#endif
+
+  return i;
+}
+
+static int asmrp_condition (asmrp_t *p) ;
+
+static int asmrp_operand (asmrp_t *p) {
+
+  int i, ret;
+  
+#ifdef LOG
+  printf ("operand\n");
+#endif
+
+  ret = 0;
+
+  switch (p->sym) {
+
+  case ASMRP_SYM_DOLLAR:
+
+    asmrp_get_sym (p);
+    
+    if (p->sym != ASMRP_SYM_ID) {
+      printf ("error: identifier expected.\n");
+      abort();
+    }
+
+    i = asmrp_find_id (p, p->str);
+    if (i<0) {
+      printf ("error: unknown identifier %s\n", p->str);
+    }
+    ret = p->sym_tab[i].v;
+
+    asmrp_get_sym (p);
+    break;
+
+  case ASMRP_SYM_NUM:
+    ret = p->num;
+
+    asmrp_get_sym (p);
+    break;
+
+  case ASMRP_SYM_LPAREN:
+    asmrp_get_sym (p);
+
+    ret = asmrp_condition (p);
+
+    if (p->sym != ASMRP_SYM_RPAREN) {
+      printf ("error: ) expected.\n");
+      abort();
+    }
+
+    asmrp_get_sym (p);
+    break;
+
+  default:
+    printf ("syntax error, $ number or ( expected\n");
+    abort();
+  }
+
+#ifdef LOG
+  printf ("operand done, =%d\n", ret);
+#endif
+  
+  return ret;
+}
+
+static int asmrp_comp_expression (asmrp_t *p) {
+
+  int a;
+
+#ifdef LOG
+  printf ("comp_expression\n");
+#endif
+
+  a = asmrp_operand (p);
+
+  while ( (p->sym == ASMRP_SYM_LESS)
+	  || (p->sym == ASMRP_SYM_LEQ)
+	  || (p->sym == ASMRP_SYM_EQUALS)
+	  || (p->sym == ASMRP_SYM_GEQ)
+	  || (p->sym == ASMRP_SYM_GREATER) ) {
+    int op = p->sym;
+    int b;
+
+    asmrp_get_sym (p);
+
+    b = asmrp_operand (p);
+
+    switch (op) {
+    case ASMRP_SYM_LESS:
+      a = a<b;
+      break;
+    case ASMRP_SYM_LEQ:
+      a = a<=b;
+      break;
+    case ASMRP_SYM_EQUALS:
+      a = a==b;
+      break;
+    case ASMRP_SYM_GEQ:
+      a = a>=b;
+      break;
+    case ASMRP_SYM_GREATER:
+      a = a>b;
+      break;
+    }
+
+  }
+
+#ifdef LOG
+  printf ("comp_expression done = %d\n", a);
+#endif
+  return a;
+}
+
+static int asmrp_condition (asmrp_t *p) {
+  
+  int a;
+
+#ifdef LOG
+  printf ("condition\n");
+#endif
+
+  a = asmrp_comp_expression (p);
+
+  while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) {
+    int op, b;
+
+    op = p->sym;
+
+    asmrp_get_sym (p);
+
+    b = asmrp_comp_expression (p);
+
+    switch (op) {
+    case ASMRP_SYM_AND:
+      a = a & b;
+      break;
+    case ASMRP_SYM_OR:
+      a = a | b;
+      break;
+    }
+  }
+
+#ifdef LOG
+  printf ("condition done = %d\n", a);
+#endif
+  return a;
+}
+
+static void asmrp_assignment (asmrp_t *p) {
+
+#ifdef LOG
+  printf ("assignment\n");
+#endif
+
+  if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) {
+#ifdef LOG
+    printf ("empty assignment\n");
+#endif
+    return;
+  }
+
+  if (p->sym != ASMRP_SYM_ID) {
+    printf ("error: identifier expected\n");
+    abort ();
+  }
+  asmrp_get_sym (p);
+
+  if (p->sym != ASMRP_SYM_EQUALS) {
+    printf ("error: = expected\n");
+    abort ();
+  }
+  asmrp_get_sym (p);
+
+  if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) 
+       && (p->sym != ASMRP_SYM_ID)) {
+    printf ("error: number or string expected\n");
+    abort ();
+  }
+  asmrp_get_sym (p);
+
+#ifdef LOG
+  printf ("assignment done\n");
+#endif
+}
+
+static int asmrp_rule (asmrp_t *p) {
+  
+  int ret;
+
+#ifdef LOG
+  printf ("rule\n");
+#endif
+
+  ret = 1;
+  
+  if (p->sym == ASMRP_SYM_HASH) {
+
+    asmrp_get_sym (p);
+    ret = asmrp_condition (p);
+
+    while (p->sym == ASMRP_SYM_COMMA) {
+      
+      asmrp_get_sym (p);
+      
+      asmrp_assignment (p);
+    }
+
+  } else if (p->sym != ASMRP_SYM_SEMICOLON) {
+
+    asmrp_assignment (p);
+
+    while (p->sym == ASMRP_SYM_COMMA) {
+
+      asmrp_get_sym (p);
+      asmrp_assignment (p);
+    }
+  }
+
+#ifdef LOG
+  printf ("rule done = %d\n", ret);
+#endif
+
+  if (p->sym != ASMRP_SYM_SEMICOLON) {
+    printf ("semicolon expected.\n");
+    abort ();
+  }
+
+  asmrp_get_sym (p);
+
+  return ret;
+}
+
+static int asmrp_eval (asmrp_t *p, int *matches) {
+
+  int rule_num, num_matches;
+
+#ifdef LOG
+  printf ("eval\n");
+#endif
+
+  asmrp_get_sym (p);
+
+  rule_num = 0; num_matches = 0;
+  while (p->sym != ASMRP_SYM_EOF) {
+
+    if (asmrp_rule (p)) {
+#ifdef LOG
+      printf ("rule #%d is true\n", rule_num);
+#endif
+      matches[num_matches] = rule_num;
+      num_matches++;
+    }
+
+    rule_num++;
+  }
+
+  matches[num_matches] = -1;
+  return num_matches;
+}
+
+int asmrp_match (const char *rules, int bandwidth, int *matches) {
+
+  asmrp_t *p;
+  int      num_matches;
+
+  p = asmrp_new ();
+
+  asmrp_init (p, rules);
+
+  asmrp_set_id (p, "Bandwidth", bandwidth);
+  asmrp_set_id (p, "OldPNMPlayer", 0);
+
+  num_matches = asmrp_eval (p, matches);
+
+  asmrp_dispose (p);
+
+  return num_matches;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/asmrp.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,45 @@
+/*
+ * This file was ported to MPlayer from xine CVS asmrp.h,v 1.1 2002/12/12 22:14:54
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * a parser for real's asm rules
+ *
+ * grammar for these rules:
+ *
+
+   rule_book  = { '#' rule ';'}
+   rule       = condition {',' assignment}
+   assignment = id '=' const
+   const      = ( number | string )
+   condition  = comp_expr { ( '&&' | '||' ) comp_expr }
+   comp_expr  = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand }
+   operand    = ( '$' id | num | '(' condition ')' )
+
+ */
+
+#ifndef HAVE_ASMRP_H
+#define HAVE_ASMRP_H
+
+int asmrp_match (const char *rules, int bandwidth, int *matches) ;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/real.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,612 @@
+/*
+ * This file was ported to MPlayer from xine CVS real.c,v 1.8 2003/03/30 17:11:50
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * special functions for real streams.
+ * adopted from joschkas real tools.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../config.h"
+#include "../bswap.h"
+#include "real.h"
+#include "asmrp.h"
+#include "sdpplin.h"
+#include "xbuffer.h"
+#if USE_LIBAVUTIL_SO
+#include "ffmpeg/md5.h"
+#else
+#include "libavutil/md5.h"
+#endif
+
+/*
+#define LOG
+*/
+
+static const unsigned char xor_table[] = {
+    0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
+    0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
+    0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
+    0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
+    0x10, 0x57, 0x05, 0x18, 0x54, 0x00, 0x00, 0x00 };
+
+
+#define BE_32C(x,y) (*((uint32_t*)(x))=be2me_32(y))
+
+#define BE_16(x)  be2me_16(*(uint16_t*)(x))
+
+#define BE_32(x)  be2me_32(*(uint32_t*)(x))
+
+#ifndef MAX
+#define MAX(x,y) ((x>y) ? x : y)
+#endif
+
+#define BUF_SIZE 4096
+
+#ifdef LOG
+static void hexdump (const char *buf, int length) {
+
+  int i;
+
+  printf (" hexdump> ");
+  for (i = 0; i < length; i++) {
+    unsigned char c = buf[i];
+
+    printf ("%02x", c);
+
+    if ((i % 16) == 15)
+      printf ("\n         ");
+
+    if ((i % 2) == 1)
+      printf (" ");
+
+  }
+  printf ("\n");
+}
+#endif
+
+
+static void calc_response_string (char *result, char *challenge) {
+ 
+  char zres[16];
+  int  i;
+      
+  av_md5_sum(zres, challenge, 64);
+ 
+  /* convert zres to ascii string */
+  for (i=0; i<16; i++ ) {
+    char a, b;
+    
+    a = (zres[i] >> 4) & 15;
+    b = zres[i] & 15;
+
+    result[i*2]   = ((a<10) ? (a+48) : (a+87)) & 255;
+    result[i*2+1] = ((b<10) ? (b+48) : (b+87)) & 255;
+  }
+}
+
+static void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) {
+
+  int   ch_len, table_len, resp_len;
+  int   i;
+  char *ptr;
+  char  buf[128];
+
+  /* initialize return values */
+  memset(response, 0, 64);
+  memset(chksum, 0, 34);
+
+  /* initialize buffer */
+  memset(buf, 0, 128);
+  ptr=buf;
+  BE_32C(ptr, 0xa1e9149d);
+  ptr+=4;
+  BE_32C(ptr, 0x0e6b3b59);
+  ptr+=4;
+
+  /* some (length) checks */
+  if (challenge != NULL)
+  {
+    ch_len = strlen (challenge);
+
+    if (ch_len == 40) /* what a hack... */
+    {
+      challenge[32]=0;
+      ch_len=32;
+    }
+    if ( ch_len > 56 ) ch_len=56;
+    
+    /* copy challenge to buf */
+    memcpy(ptr, challenge, ch_len);
+  }
+  
+    table_len = strlen(xor_table);
+
+    if (table_len > 56) table_len=56;
+
+    /* xor challenge bytewise with xor_table */
+    for (i=0; i<table_len; i++)
+      ptr[i] = ptr[i] ^ xor_table[i];
+
+  calc_response_string (response, buf);
+
+  /* add tail */
+  resp_len = strlen (response);
+  strcpy (&response[resp_len], "01d0a8e3");
+
+  /* calculate checksum */
+  for (i=0; i<resp_len/4; i++)
+    chksum[i] = response[i*4];
+}
+
+
+/*
+ * takes a MLTI-Chunk and a rule number got from match_asm_rule,
+ * returns a pointer to selected data and number of bytes in that.
+ */
+
+static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out) {
+
+  int numrules, codec, size;
+  int i;
+  
+  /* MLTI chunk should begin with MLTI */
+
+  if ((mlti_chunk[0] != 'M')
+      ||(mlti_chunk[1] != 'L')
+      ||(mlti_chunk[2] != 'T')
+      ||(mlti_chunk[3] != 'I'))
+  {
+#ifdef LOG
+    printf("libreal: MLTI tag not detected, copying data\n");
+#endif
+    *out = xbuffer_copyin(*out, 0, mlti_chunk, mlti_size);
+    return mlti_size;
+  }
+
+  mlti_chunk+=4;
+
+  /* next 16 bits are the number of rules */
+  numrules=BE_16(mlti_chunk);
+  if (selection >= numrules) return 0;
+
+  /* now <numrules> indices of codecs follows */
+  /* we skip to selection                     */
+  mlti_chunk+=(selection+1)*2;
+
+  /* get our index */
+  codec=BE_16(mlti_chunk);
+
+  /* skip to number of codecs */
+  mlti_chunk+=(numrules-selection)*2;
+
+  /* get number of codecs */
+  numrules=BE_16(mlti_chunk);
+
+  if (codec >= numrules) {
+    printf("codec index >= number of codecs. %i %i\n", codec, numrules);
+    return 0;
+  }
+
+  mlti_chunk+=2;
+ 
+  /* now seek to selected codec */
+  for (i=0; i<codec; i++) {
+    size=BE_32(mlti_chunk);
+    mlti_chunk+=size+4;
+  }
+  
+  size=BE_32(mlti_chunk);
+
+#ifdef LOG
+  hexdump(mlti_chunk+4, size);
+#endif
+  *out = xbuffer_copyin(*out, 0, mlti_chunk+4, size);
+  return size;
+}
+
+/*
+ * looking at stream description.
+ */
+
+static rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {
+
+  sdpplin_t *desc;
+  rmff_header_t *header;
+  char *buf;
+  int len, i;
+  int max_bit_rate=0;
+  int avg_bit_rate=0;
+  int max_packet_size=0;
+  int avg_packet_size=0;
+  int duration=0;
+  
+
+  if (!data) return NULL;
+
+  desc=sdpplin_parse(data);
+
+  if (!desc) return NULL;
+  
+  buf = xbuffer_init(2048);
+  header=calloc(1,sizeof(rmff_header_t));
+
+  header->fileheader=rmff_new_fileheader(4+desc->stream_count);
+  header->cont=rmff_new_cont(
+      desc->title,
+      desc->author,
+      desc->copyright,
+      desc->abstract);
+  header->data=rmff_new_dataheader(0,0);
+  header->streams=calloc(1,sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
+#ifdef LOG
+    printf("number of streams: %u\n", desc->stream_count);
+#endif
+
+  for (i=0; i<desc->stream_count; i++) {
+
+    int j=0;
+    int n;
+    char b[64];
+    int rulematches[16];
+
+#ifdef LOG
+    printf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
+#endif
+    n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
+    for (j=0; j<n; j++) {
+#ifdef LOG
+      printf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
+#endif
+      sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
+      *stream_rules = xbuffer_strcat(*stream_rules, b);
+    }
+
+    if (!desc->stream[i]->mlti_data) {
+	len = 0;
+	buf = NULL;
+    } else
+    len=select_mlti_data(desc->stream[i]->mlti_data, desc->stream[i]->mlti_data_size, rulematches[0], &buf);
+    
+    header->streams[i]=rmff_new_mdpr(
+	desc->stream[i]->stream_id,
+        desc->stream[i]->max_bit_rate,
+        desc->stream[i]->avg_bit_rate,
+        desc->stream[i]->max_packet_size,
+        desc->stream[i]->avg_packet_size,
+        desc->stream[i]->start_time,
+        desc->stream[i]->preroll,
+        desc->stream[i]->duration,
+        desc->stream[i]->stream_name,
+        desc->stream[i]->mime_type,
+	len,
+	buf);
+
+    duration=MAX(duration,desc->stream[i]->duration);
+    max_bit_rate+=desc->stream[i]->max_bit_rate;
+    avg_bit_rate+=desc->stream[i]->avg_bit_rate;
+    max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size);
+    if (avg_packet_size)
+      avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2;
+    else
+      avg_packet_size=desc->stream[i]->avg_packet_size;
+  }
+  
+  if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
+    (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
+
+  header->prop=rmff_new_prop(
+      max_bit_rate,
+      avg_bit_rate,
+      max_packet_size,
+      avg_packet_size,
+      0,
+      duration,
+      0,
+      0,
+      0,
+      desc->stream_count,
+      desc->flags);
+
+  rmff_fix_header(header);
+  buf = xbuffer_free(buf);
+
+  return header;
+}
+
+int real_get_rdt_chunk(rtsp_t *rtsp_session, char **buffer) {
+
+  int n=1;
+  uint8_t header[8];
+  rmff_pheader_t ph;
+  int size;
+  int flags1, flags2;
+  int unknown1;
+  uint32_t ts;
+  static uint32_t prev_ts = -1;
+  static int prev_stream_number = -1;
+
+  n=rtsp_read_data(rtsp_session, header, 8);
+  if (n<8) return 0;
+  if (header[0] != 0x24)
+  {
+    printf("rdt chunk not recognized: got 0x%02x\n", header[0]);
+    return 0;
+  }
+  size=(header[1]<<16)+(header[2]<<8)+(header[3]);
+  flags1=header[4];
+  if ((flags1!=0x40)&&(flags1!=0x42))
+  {
+#ifdef LOG
+    printf("got flags1: 0x%02x\n",flags1);
+#endif
+    if(header[6] == 0x06) {
+      printf("Stream EOF detected\n");
+      return -1;
+    }
+    header[0]=header[5];
+    header[1]=header[6];
+    header[2]=header[7];
+    n=rtsp_read_data(rtsp_session, header+3, 5);
+    if (n<5) return 0;
+#ifdef LOG
+    printf("ignoring bytes:\n");
+    hexdump(header, 8);
+#endif
+    n=rtsp_read_data(rtsp_session, header+4, 4);
+    if (n<4) return 0;
+    flags1=header[4];
+    size-=9;
+  }
+  flags2=header[7];
+  // header[5..6] == frame number in stream
+  unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
+  n=rtsp_read_data(rtsp_session, header, 6);
+  if (n<6) return 0;
+  ts=BE_32(header);
+  
+#ifdef LOG
+  printf("ts: %u, size: %u, flags: 0x%02x, unknown values: 0x%06x 0x%02x 0x%02x\n", 
+          ts, size, flags1, unknown1, header[4], header[5]);
+#endif
+  size+=2;
+  
+  ph.object_version=0;
+  ph.length=size;
+  ph.stream_number=(flags1>>1)&1;
+  ph.timestamp=ts;
+  ph.reserved=0;
+  if ((flags2&1) == 0 && (prev_ts != ts || prev_stream_number != ph.stream_number))
+  {
+    prev_ts = ts;
+    prev_stream_number = ph.stream_number;
+    ph.flags=2;
+  }
+  else
+    ph.flags=0;
+  *buffer = xbuffer_ensure_size(*buffer, 12+size);
+  rmff_dump_pheader(&ph, *buffer);
+  size-=12;
+  n=rtsp_read_data(rtsp_session, (*buffer)+12, size);
+  
+  return (n <= 0) ? 0 : n+12;
+}
+
+static int convert_timestamp(char *str, int *sec, int *msec) {
+  int hh, mm, ss, ms = 0;
+  if (sscanf(str, "%d:%d:%d.%d", &hh, &mm, &ss, &ms) < 3) {
+    hh = 0;
+    if (sscanf(str, "%d:%d.%d", &mm, &ss, &ms) < 2) {
+      mm = 0;
+      if (sscanf(str, "%d.%d", &ss, &ms) < 1) {
+	ss = 0;
+	ms = 0;
+      }
+    }
+  }
+  if (sec)
+    *sec = hh * 3600 + mm * 60 + ss;
+  if (msec)
+    *msec = ms;
+  return 1;
+}
+
+//! maximum size of the rtsp description, must be < INT_MAX
+#define MAX_DESC_BUF (20 * 1024 * 1024)
+rmff_header_t  *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth) {
+
+  char *description=NULL;
+  char *session_id=NULL;
+  rmff_header_t *h;
+  char *challenge1;
+  char challenge2[64];
+  char checksum[34];
+  char *subscribe;
+  char *buf = xbuffer_init(256);
+  char *mrl=rtsp_get_mrl(rtsp_session);
+  unsigned int size;
+  int status;
+  uint32_t maxbandwidth = bandwidth;
+  
+  /* get challenge */
+  challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
+#ifdef LOG
+  printf("real: Challenge1: %s\n", challenge1);
+#endif
+
+  /* set a reasonable default to get the best stream, unless bandwidth given */
+  if (!bandwidth)
+      bandwidth = 10485800;
+  
+  /* request stream description */
+  rtsp_schedule_field(rtsp_session, "Accept: application/sdp");
+  sprintf(buf, "Bandwidth: %u", bandwidth);
+  rtsp_schedule_field(rtsp_session, buf);
+  rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000");
+  rtsp_schedule_field(rtsp_session, "RegionData: 0");
+  rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
+  rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
+  rtsp_schedule_field(rtsp_session, "Language: en-US");
+  rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
+  status=rtsp_request_describe(rtsp_session,NULL);
+
+  if ( status<200 || status>299 )
+  {
+    char *alert=rtsp_search_answers(rtsp_session,"Alert");
+    if (alert) {
+      printf("real: got message from server:\n%s\n", alert);
+    }
+    rtsp_send_ok(rtsp_session);
+    buf = xbuffer_free(buf);
+    return NULL;
+  }
+
+  /* receive description */
+  size=0;
+  if (!rtsp_search_answers(rtsp_session,"Content-length"))
+    printf("real: got no Content-length!\n");
+  else
+    size=atoi(rtsp_search_answers(rtsp_session,"Content-length"));
+
+  // as size is unsigned this also catches the case (size < 0)
+  if (size > MAX_DESC_BUF) {
+    printf("real: Content-length for description too big (> %uMB)!\n",
+            MAX_DESC_BUF/(1024*1024) );
+    xbuffer_free(buf);
+    return NULL;
+  }
+
+  if (!rtsp_search_answers(rtsp_session,"ETag"))
+    printf("real: got no ETag!\n");
+  else
+    session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
+    
+#ifdef LOG
+  printf("real: Stream description size: %u\n", size);
+#endif
+
+  description=malloc(size+1);
+
+  if( rtsp_read_data(rtsp_session, description, size) <= 0) {
+    buf = xbuffer_free(buf);
+    return NULL;
+  }
+  description[size]=0;
+
+  /* parse sdp (sdpplin) and create a header and a subscribe string */
+  subscribe = xbuffer_init(256);
+  strcpy(subscribe, "Subscribe: ");
+  h=real_parse_sdp(description, &subscribe, bandwidth);
+  if (!h) {
+    subscribe = xbuffer_free(subscribe);
+    buf = xbuffer_free(buf);
+    return NULL;
+  }
+  rmff_fix_header(h);
+
+#ifdef LOG
+  printf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
+    h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
+#endif
+  
+  /* setup our streams */
+  real_calc_response_and_checksum (challenge2, checksum, challenge1);
+  buf = xbuffer_ensure_size(buf, strlen(challenge2) + strlen(checksum) + 32);
+  sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum);
+  rtsp_schedule_field(rtsp_session, buf);
+  buf = xbuffer_ensure_size(buf, strlen(session_id) + 32);
+  sprintf(buf, "If-Match: %s", session_id);
+  rtsp_schedule_field(rtsp_session, buf);
+  rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
+  buf = xbuffer_ensure_size(buf, strlen(mrl) + 32);
+  sprintf(buf, "%s/streamid=0", mrl);
+  rtsp_request_setup(rtsp_session,buf,NULL);
+
+  if (h->prop->num_streams > 1) {
+    rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
+    buf = xbuffer_ensure_size(buf, strlen(session_id) + 32);
+    sprintf(buf, "If-Match: %s", session_id);
+    rtsp_schedule_field(rtsp_session, buf);
+
+    buf = xbuffer_ensure_size(buf, strlen(mrl) + 32);
+    sprintf(buf, "%s/streamid=1", mrl);
+    rtsp_request_setup(rtsp_session,buf,NULL);
+  }
+  /* set stream parameter (bandwidth) with our subscribe string */
+  rtsp_schedule_field(rtsp_session, subscribe);
+  rtsp_request_setparameter(rtsp_session,NULL);
+
+  /* set delivery bandwidth */
+  if (maxbandwidth) {
+      sprintf(buf, "SetDeliveryBandwidth: Bandwidth=%u;BackOff=0", maxbandwidth);
+      rtsp_schedule_field(rtsp_session, buf);
+      rtsp_request_setparameter(rtsp_session,NULL);
+  }
+
+  {
+    int s_ss = 0, s_ms = 0, e_ss = 0, e_ms = 0;
+    char *str;
+    if ((str = rtsp_get_param(rtsp_session, "start"))) {
+      convert_timestamp(str, &s_ss, &s_ms);
+      free(str);
+    }
+    if ((str = rtsp_get_param(rtsp_session, "end"))) {
+      convert_timestamp(str, &e_ss, &e_ms);
+      free(str);
+    }
+    str = buf + sprintf(buf, s_ms ? "%s%d.%d-" : "%s%d-", "Range: npt=", s_ss, s_ms);
+    if (e_ss || e_ms)
+      sprintf(str, e_ms ? "%d.%d" : "%d", e_ss, e_ms);
+  }
+  rtsp_schedule_field(rtsp_session, buf);
+  /* and finally send a play request */
+  rtsp_request_play(rtsp_session,NULL);
+
+  subscribe = xbuffer_free(subscribe);
+  buf = xbuffer_free(buf);
+  return h;
+}
+
+struct real_rtsp_session_t *
+init_real_rtsp_session (void)
+{
+  struct real_rtsp_session_t *real_rtsp_session = NULL;
+
+  real_rtsp_session = malloc (sizeof (struct real_rtsp_session_t));
+  real_rtsp_session->recv = xbuffer_init (BUF_SIZE);
+
+  return real_rtsp_session;
+}
+
+void
+free_real_rtsp_session (struct real_rtsp_session_t* real_session)
+{
+  if (!real_session)
+    return;
+  
+  xbuffer_free (real_session->recv);
+  free (real_session);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/real.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,56 @@
+/*
+ * This file was ported to MPlayer from xine CVS real.h,v 1.2 2002/12/24 01:30:22
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * special functions for real streams.
+ * adopted from joschkas real tools.
+ *
+ */
+ 
+#ifndef HAVE_REAL_H
+#define HAVE_REAL_H
+
+#include "rmff.h"
+#include "../librtsp/rtsp.h"
+
+#define HEADER_SIZE 4096
+
+struct real_rtsp_session_t {
+  /* receive buffer */
+  uint8_t *recv;
+  int recv_size;
+  int recv_read;
+
+  /* header buffer */
+  uint8_t header[HEADER_SIZE];
+  int header_len;
+  int header_read;
+};
+
+int real_get_rdt_chunk(rtsp_t *rtsp_session, char **buffer);
+rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth);
+struct real_rtsp_session_t *init_real_rtsp_session (void);
+void free_real_rtsp_session (struct real_rtsp_session_t* real_session);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/rmff.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,907 @@
+/*
+ * This file was ported to MPlayer from xine CVS rmff.c,v 1.3 2002/12/24 01:30:22
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * functions for real media file format
+ * adopted from joschkas real tools
+ */
+
+#include "rmff.h"
+#include "xbuffer.h"
+
+/*
+#define LOG
+*/
+
+#define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
+#define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
+                   (((uint8_t*)(x))[1] << 16) | \
+                   (((uint8_t*)(x))[2] << 8) | \
+                    ((uint8_t*)(x))[3])
+
+static void hexdump (const char *buf, int length) {
+
+  int i;
+
+  printf ("rmff: ascii>");
+  for (i = 0; i < length; i++) {
+    unsigned char c = buf[i];
+
+    if ((c >= 32) && (c <= 128))
+      printf ("%c", c);
+    else
+      printf (".");
+  }
+  printf ("\n");
+
+  printf ("rmff: hexdump> ");
+  for (i = 0; i < length; i++) {
+    unsigned char c = buf[i];
+
+    printf ("%02x", c);
+
+    if ((i % 16) == 15)
+      printf ("\nrmff:         ");
+
+    if ((i % 2) == 1)
+      printf (" ");
+
+  }
+  printf ("\n");
+}
+
+/*
+ * writes header data to a buffer
+ */
+
+static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) {
+
+  if (!fileheader) return;
+  fileheader->object_id=BE_32(&fileheader->object_id);
+  fileheader->size=BE_32(&fileheader->size);
+  fileheader->object_version=BE_16(&fileheader->object_version);
+  fileheader->file_version=BE_32(&fileheader->file_version);
+  fileheader->num_headers=BE_32(&fileheader->num_headers);
+  
+  memcpy(buffer, fileheader, 8);
+  memcpy(&buffer[8], &fileheader->object_version, 2);
+  memcpy(&buffer[10], &fileheader->file_version, 8);
+
+  fileheader->size=BE_32(&fileheader->size);
+  fileheader->object_version=BE_16(&fileheader->object_version);
+  fileheader->file_version=BE_32(&fileheader->file_version);
+  fileheader->num_headers=BE_32(&fileheader->num_headers);
+  fileheader->object_id=BE_32(&fileheader->object_id);
+}
+
+static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) {
+
+  if (!prop) return;
+  prop->object_id=BE_32(&prop->object_id);
+  prop->size=BE_32(&prop->size);
+  prop->object_version=BE_16(&prop->object_version);
+  prop->max_bit_rate=BE_32(&prop->max_bit_rate);
+  prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
+  prop->max_packet_size=BE_32(&prop->max_packet_size);
+  prop->avg_packet_size=BE_32(&prop->avg_packet_size);
+  prop->num_packets=BE_32(&prop->num_packets);
+  prop->duration=BE_32(&prop->duration);
+  prop->preroll=BE_32(&prop->preroll);
+  prop->index_offset=BE_32(&prop->index_offset);
+  prop->data_offset=BE_32(&prop->data_offset);
+  prop->num_streams=BE_16(&prop->num_streams);
+  prop->flags=BE_16(&prop->flags);
+
+  memcpy(buffer, prop, 8);
+  memcpy(&buffer[8], &prop->object_version, 2);
+  memcpy(&buffer[10], &prop->max_bit_rate, 36);
+  memcpy(&buffer[46], &prop->num_streams, 2);
+  memcpy(&buffer[48], &prop->flags, 2);
+  
+  prop->size=BE_32(&prop->size);
+  prop->object_version=BE_16(&prop->object_version);
+  prop->max_bit_rate=BE_32(&prop->max_bit_rate);
+  prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
+  prop->max_packet_size=BE_32(&prop->max_packet_size);
+  prop->avg_packet_size=BE_32(&prop->avg_packet_size);
+  prop->num_packets=BE_32(&prop->num_packets);
+  prop->duration=BE_32(&prop->duration);
+  prop->preroll=BE_32(&prop->preroll);
+  prop->index_offset=BE_32(&prop->index_offset);
+  prop->data_offset=BE_32(&prop->data_offset);
+  prop->num_streams=BE_16(&prop->num_streams);
+  prop->flags=BE_16(&prop->flags);
+  prop->object_id=BE_32(&prop->object_id);
+}
+
+static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) {
+
+  int s1, s2, s3;
+
+  if (!mdpr) return;
+  mdpr->object_id=BE_32(&mdpr->object_id);
+  mdpr->size=BE_32(&mdpr->size);
+  mdpr->object_version=BE_16(&mdpr->object_version);
+  mdpr->stream_number=BE_16(&mdpr->stream_number);
+  mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
+  mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
+  mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
+  mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
+  mdpr->start_time=BE_32(&mdpr->start_time);
+  mdpr->preroll=BE_32(&mdpr->preroll);
+  mdpr->duration=BE_32(&mdpr->duration);
+
+  memcpy(buffer, mdpr, 8);
+  memcpy(&buffer[8], &mdpr->object_version, 2);
+  memcpy(&buffer[10], &mdpr->stream_number, 2);
+  memcpy(&buffer[12], &mdpr->max_bit_rate, 28);
+  memcpy(&buffer[40], &mdpr->stream_name_size, 1);
+  s1=mdpr->stream_name_size;
+  memcpy(&buffer[41], mdpr->stream_name, s1);
+
+  memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1);
+  s2=mdpr->mime_type_size;
+  memcpy(&buffer[42+s1], mdpr->mime_type, s2);
+  
+  mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
+  memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4);
+  mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
+  s3=mdpr->type_specific_len;
+  memcpy(&buffer[46+s1+s2], mdpr->type_specific_data, s3);
+
+  mdpr->size=BE_32(&mdpr->size);
+  mdpr->stream_number=BE_16(&mdpr->stream_number);
+  mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
+  mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
+  mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
+  mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
+  mdpr->start_time=BE_32(&mdpr->start_time);
+  mdpr->preroll=BE_32(&mdpr->preroll);
+  mdpr->duration=BE_32(&mdpr->duration);
+  mdpr->object_id=BE_32(&mdpr->object_id);
+
+}
+
+static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) {
+
+  int p;
+
+  if (!cont) return;
+  cont->object_id=BE_32(&cont->object_id);
+  cont->size=BE_32(&cont->size);
+  cont->object_version=BE_16(&cont->object_version);
+
+  memcpy(buffer, cont, 8);
+  memcpy(&buffer[8], &cont->object_version, 2);
+  
+  cont->title_len=BE_16(&cont->title_len);
+  memcpy(&buffer[10], &cont->title_len, 2);
+  cont->title_len=BE_16(&cont->title_len);
+  memcpy(&buffer[12], cont->title, cont->title_len);
+  p=12+cont->title_len;
+
+  cont->author_len=BE_16(&cont->author_len);
+  memcpy(&buffer[p], &cont->author_len, 2);
+  cont->author_len=BE_16(&cont->author_len);
+  memcpy(&buffer[p+2], cont->author, cont->author_len);
+  p+=2+cont->author_len;
+
+  cont->copyright_len=BE_16(&cont->copyright_len);
+  memcpy(&buffer[p], &cont->copyright_len, 2);
+  cont->copyright_len=BE_16(&cont->copyright_len);
+  memcpy(&buffer[p+2], cont->copyright, cont->copyright_len);
+  p+=2+cont->copyright_len;
+
+  cont->comment_len=BE_16(&cont->comment_len);
+  memcpy(&buffer[p], &cont->comment_len, 2);
+  cont->comment_len=BE_16(&cont->comment_len);
+  memcpy(&buffer[p+2], cont->comment, cont->comment_len);
+
+  cont->size=BE_32(&cont->size);
+  cont->object_version=BE_16(&cont->object_version);
+  cont->object_id=BE_32(&cont->object_id);
+}
+
+static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) {
+
+  if (!data) return;
+  data->object_id=BE_32(&data->object_id);
+  data->size=BE_32(&data->size);
+  data->object_version=BE_16(&data->object_version);
+  data->num_packets=BE_32(&data->num_packets);
+  data->next_data_header=BE_32(&data->next_data_header);
+
+  memcpy(buffer, data, 8);
+  memcpy(&buffer[8], &data->object_version, 2);
+  memcpy(&buffer[10], &data->num_packets, 8);
+  
+  data->num_packets=BE_32(&data->num_packets);
+  data->next_data_header=BE_32(&data->next_data_header);
+  data->size=BE_32(&data->size);
+  data->object_version=BE_16(&data->object_version);
+  data->object_id=BE_32(&data->object_id);
+}
+
+int rmff_dump_header(rmff_header_t *h, char *buffer, int max) {
+
+  int written=0;
+  rmff_mdpr_t **stream=h->streams;
+
+  rmff_dump_fileheader(h->fileheader, &buffer[written]);
+  written+=h->fileheader->size;
+  rmff_dump_prop(h->prop, &buffer[written]);
+  written+=h->prop->size;
+  rmff_dump_cont(h->cont, &buffer[written]);
+  written+=h->cont->size;
+  if (stream)
+  {
+    while(*stream)
+    {
+      rmff_dump_mdpr(*stream, &buffer[written]);
+      written+=(*stream)->size;
+      stream++;
+    }
+  }
+    
+  rmff_dump_dataheader(h->data, &buffer[written]);
+  written+=18;
+
+  return written;
+}
+
+void rmff_dump_pheader(rmff_pheader_t *h, char *data) {
+
+  data[0]=(h->object_version>>8) & 0xff;
+  data[1]=h->object_version & 0xff;
+  data[2]=(h->length>>8) & 0xff;
+  data[3]=h->length & 0xff;
+  data[4]=(h->stream_number>>8) & 0xff;
+  data[5]=h->stream_number & 0xff;
+  data[6]=(h->timestamp>>24) & 0xff;
+  data[7]=(h->timestamp>>16) & 0xff;
+  data[8]=(h->timestamp>>8) & 0xff;
+  data[9]=h->timestamp & 0xff;
+  data[10]=h->reserved;
+  data[11]=h->flags;
+}
+
+static rmff_fileheader_t *rmff_scan_fileheader(const char *data) {
+
+  rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t));
+
+  fileheader->object_id=BE_32(data);
+  fileheader->size=BE_32(&data[4]);
+  fileheader->object_version=BE_16(&data[8]);
+  if (fileheader->object_version != 0)
+  {
+    printf("warning: unknown object version in .RMF: 0x%04x\n",
+      fileheader->object_version);
+  }
+  fileheader->file_version=BE_32(&data[10]);
+  fileheader->num_headers=BE_32(&data[14]);
+
+  return fileheader;
+}
+
+static rmff_prop_t *rmff_scan_prop(const char *data) {
+
+  rmff_prop_t *prop=malloc(sizeof(rmff_prop_t));
+
+  prop->object_id=BE_32(data);
+  prop->size=BE_32(&data[4]);
+  prop->object_version=BE_16(&data[8]);
+  if (prop->object_version != 0)
+  {
+    printf("warning: unknown object version in PROP: 0x%04x\n",
+      prop->object_version);
+  }
+  prop->max_bit_rate=BE_32(&data[10]);
+  prop->avg_bit_rate=BE_32(&data[14]);
+  prop->max_packet_size=BE_32(&data[18]);
+  prop->avg_packet_size=BE_32(&data[22]);
+  prop->num_packets=BE_32(&data[26]);
+  prop->duration=BE_32(&data[30]);
+  prop->preroll=BE_32(&data[34]);
+  prop->index_offset=BE_32(&data[38]);
+  prop->data_offset=BE_32(&data[42]);
+  prop->num_streams=BE_16(&data[46]);
+  prop->flags=BE_16(&data[48]);
+
+  return prop;
+}
+
+static rmff_mdpr_t *rmff_scan_mdpr(const char *data) {
+
+  rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t));
+
+  mdpr->object_id=BE_32(data);
+  mdpr->size=BE_32(&data[4]);
+  mdpr->object_version=BE_16(&data[8]);
+  if (mdpr->object_version != 0)
+  {
+    printf("warning: unknown object version in MDPR: 0x%04x\n",
+      mdpr->object_version);
+  }
+  mdpr->stream_number=BE_16(&data[10]);
+  mdpr->max_bit_rate=BE_32(&data[12]);
+  mdpr->avg_bit_rate=BE_32(&data[16]);
+  mdpr->max_packet_size=BE_32(&data[20]);
+  mdpr->avg_packet_size=BE_32(&data[24]);
+  mdpr->start_time=BE_32(&data[28]);
+  mdpr->preroll=BE_32(&data[32]);
+  mdpr->duration=BE_32(&data[36]);
+  
+  mdpr->stream_name_size=data[40];
+  mdpr->stream_name=malloc(mdpr->stream_name_size+1);
+  memcpy(mdpr->stream_name, &data[41], mdpr->stream_name_size);
+  mdpr->stream_name[mdpr->stream_name_size]=0;
+  
+  mdpr->mime_type_size=data[41+mdpr->stream_name_size];
+  mdpr->mime_type=malloc(mdpr->mime_type_size+1);
+  memcpy(mdpr->mime_type, &data[42+mdpr->stream_name_size], mdpr->mime_type_size);
+  mdpr->mime_type[mdpr->mime_type_size]=0;
+  
+  mdpr->type_specific_len=BE_32(&data[42+mdpr->stream_name_size+mdpr->mime_type_size]);
+  mdpr->type_specific_data=malloc(mdpr->type_specific_len);
+  memcpy(mdpr->type_specific_data, 
+      &data[46+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len);
+  
+  return mdpr;
+}
+
+static rmff_cont_t *rmff_scan_cont(const char *data) {
+
+  rmff_cont_t *cont=malloc(sizeof(rmff_cont_t));
+  int pos;
+
+  cont->object_id=BE_32(data);
+  cont->size=BE_32(&data[4]);
+  cont->object_version=BE_16(&data[8]);
+  if (cont->object_version != 0)
+  {
+    printf("warning: unknown object version in CONT: 0x%04x\n",
+      cont->object_version);
+  }
+  cont->title_len=BE_16(&data[10]);
+  cont->title=malloc(cont->title_len+1);
+  memcpy(cont->title, &data[12], cont->title_len);
+  cont->title[cont->title_len]=0;
+  pos=cont->title_len+12;
+  cont->author_len=BE_16(&data[pos]);
+  cont->author=malloc(cont->author_len+1);
+  memcpy(cont->author, &data[pos+2], cont->author_len);
+  cont->author[cont->author_len]=0;
+  pos=pos+2+cont->author_len;
+  cont->copyright_len=BE_16(&data[pos]);
+  cont->copyright=malloc(cont->copyright_len+1);
+  memcpy(cont->copyright, &data[pos+2], cont->copyright_len);
+  cont->copyright[cont->copyright_len]=0;
+  pos=pos+2+cont->copyright_len;
+  cont->comment_len=BE_16(&data[pos]);
+  cont->comment=malloc(cont->comment_len+1);
+  memcpy(cont->comment, &data[pos+2], cont->comment_len);
+  cont->comment[cont->comment_len]=0;
+
+  return cont;
+}
+
+static rmff_data_t *rmff_scan_dataheader(const char *data) {
+
+  rmff_data_t *dh=malloc(sizeof(rmff_data_t));
+
+  dh->object_id=BE_32(data);
+  dh->size=BE_32(&data[4]);
+  dh->object_version=BE_16(&data[8]);
+  if (dh->object_version != 0)
+  {
+    printf("warning: unknown object version in DATA: 0x%04x\n",
+      dh->object_version);
+  }
+  dh->num_packets=BE_32(&data[10]);
+  dh->next_data_header=BE_32(&data[14]);
+
+  return dh;
+}
+ 
+rmff_header_t *rmff_scan_header(const char *data) {
+
+	rmff_header_t *header=malloc(sizeof(rmff_header_t));
+	rmff_mdpr_t   *mdpr=NULL;
+	int           chunk_size;
+	uint32_t      chunk_type;
+  const char    *ptr=data;
+  int           i;
+
+  header->fileheader=NULL;
+	header->prop=NULL;
+	header->cont=NULL;
+	header->data=NULL;
+
+  chunk_type = BE_32(ptr);
+  if (chunk_type != RMF_TAG)
+  {
+    printf("rmff: not an real media file header (.RMF tag not found).\n");
+    free(header);
+    return NULL;
+  }
+  header->fileheader=rmff_scan_fileheader(ptr);
+  ptr += header->fileheader->size;
+	
+	header->streams=malloc(sizeof(rmff_mdpr_t*)*(header->fileheader->num_headers));
+  for (i=0; i<header->fileheader->num_headers; i++) {
+    header->streams[i]=NULL;
+  }
+  
+  for (i=1; i<header->fileheader->num_headers; i++) {
+    chunk_type = BE_32(ptr);
+  
+    if (ptr[0] == 0)
+    {
+      printf("rmff: warning: only %d of %d header found.\n", i, header->fileheader->num_headers);
+      break;
+    }
+    
+    chunk_size=1;
+    switch (chunk_type) {
+    case PROP_TAG:
+      header->prop=rmff_scan_prop(ptr);
+      chunk_size=header->prop->size;
+      break;
+    case MDPR_TAG:
+      mdpr=rmff_scan_mdpr(ptr);
+      chunk_size=mdpr->size;
+      header->streams[mdpr->stream_number]=mdpr;
+      break;
+    case CONT_TAG:
+      header->cont=rmff_scan_cont(ptr);
+      chunk_size=header->cont->size;
+      break;
+    case DATA_TAG:
+      header->data=rmff_scan_dataheader(ptr);
+      chunk_size=34;     /* hard coded header size */
+      break;
+    default:
+      printf("unknown chunk\n");
+      hexdump(ptr,10);
+      chunk_size=1;
+      break;
+    }
+    ptr+=chunk_size;
+  }
+
+	return header;
+}
+
+rmff_header_t *rmff_scan_header_stream(int fd) {
+
+  rmff_header_t *header;
+  char *buf=xbuffer_init(1024);
+  int index=0;
+  uint32_t chunk_type;
+  uint32_t chunk_size;
+
+  do {
+    buf = xbuffer_ensure_size(buf, index+8);
+    recv(fd, buf+index, 8, 0);
+    chunk_type=BE_32(buf+index); index+=4;
+    chunk_size=BE_32(buf+index); index+=4;
+
+    switch (chunk_type) {
+      case DATA_TAG:
+        chunk_size=18;
+      case MDPR_TAG:
+      case CONT_TAG:
+      case RMF_TAG:
+      case PROP_TAG:
+        buf = xbuffer_ensure_size(buf, index+chunk_size-8);
+        recv(fd, buf+index, (chunk_size-8), 0);
+	index+=(chunk_size-8);
+        break;
+      default:
+        printf("rmff_scan_header_stream: unknown chunk");
+        hexdump(buf+index-8, 8);
+        chunk_type=DATA_TAG;
+    }
+  } while (chunk_type != DATA_TAG);
+
+  header = rmff_scan_header(buf);
+
+  xbuffer_free(buf);
+
+  return header;
+}
+
+void rmff_scan_pheader(rmff_pheader_t *h, char *data) {
+
+  h->object_version=BE_16(data);
+  h->length=BE_16(data+2);
+  h->stream_number=BE_16(data+4);
+  h->timestamp=BE_32(data+6);
+  h->reserved=(uint8_t)data[10];
+  h->flags=(uint8_t)data[11];
+}
+
+rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) {
+
+  rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t));
+
+  fileheader->object_id=RMF_TAG;
+  fileheader->size=18;
+  fileheader->object_version=0;
+  fileheader->file_version=0;
+  fileheader->num_headers=num_headers;
+
+  return fileheader;
+}
+
+rmff_prop_t *rmff_new_prop (
+    uint32_t max_bit_rate,
+    uint32_t avg_bit_rate,
+    uint32_t max_packet_size,
+    uint32_t avg_packet_size,
+    uint32_t num_packets,
+    uint32_t duration,
+    uint32_t preroll,
+    uint32_t index_offset,
+    uint32_t data_offset,
+    uint16_t num_streams,
+    uint16_t flags ) {
+
+  rmff_prop_t *prop=malloc(sizeof(rmff_prop_t));
+
+  prop->object_id=PROP_TAG;
+  prop->size=50;
+  prop->object_version=0;
+
+  prop->max_bit_rate=max_bit_rate;
+  prop->avg_bit_rate=avg_bit_rate;
+  prop->max_packet_size=max_packet_size;
+  prop->avg_packet_size=avg_packet_size;
+  prop->num_packets=num_packets;
+  prop->duration=duration;
+  prop->preroll=preroll;
+  prop->index_offset=index_offset;
+  prop->data_offset=data_offset;
+  prop->num_streams=num_streams;
+  prop->flags=flags;
+   
+  return prop;
+}
+
+rmff_mdpr_t *rmff_new_mdpr(
+      uint16_t   stream_number,
+      uint32_t   max_bit_rate,
+      uint32_t   avg_bit_rate,
+      uint32_t   max_packet_size,
+      uint32_t   avg_packet_size,
+      uint32_t   start_time,
+      uint32_t   preroll,
+      uint32_t   duration,
+      const char *stream_name,
+      const char *mime_type,
+      uint32_t   type_specific_len,
+      const char *type_specific_data ) {
+
+  rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t));
+  
+  mdpr->object_id=MDPR_TAG;
+  mdpr->object_version=0;
+
+  mdpr->stream_number=stream_number;
+  mdpr->max_bit_rate=max_bit_rate;
+  mdpr->avg_bit_rate=avg_bit_rate;
+  mdpr->max_packet_size=max_packet_size;
+  mdpr->avg_packet_size=avg_packet_size;
+  mdpr->start_time=start_time;
+  mdpr->preroll=preroll;
+  mdpr->duration=duration;
+  mdpr->stream_name_size=0;
+  if (stream_name) {
+    mdpr->stream_name=strdup(stream_name);
+    mdpr->stream_name_size=strlen(stream_name);
+  }
+  mdpr->mime_type_size=0;
+  if (mime_type) {
+    mdpr->mime_type=strdup(mime_type);
+    mdpr->mime_type_size=strlen(mime_type);
+  }
+  mdpr->type_specific_len=type_specific_len;
+  mdpr->type_specific_data=malloc(type_specific_len);
+  memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len);
+  mdpr->mlti_data=NULL;
+  
+  mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46;
+
+  return mdpr;
+}
+
+rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment) {
+
+  rmff_cont_t *cont=malloc(sizeof(rmff_cont_t));
+
+  cont->object_id=CONT_TAG;
+  cont->object_version=0;
+
+  cont->title=NULL;
+  cont->author=NULL;
+  cont->copyright=NULL;
+  cont->comment=NULL;
+  
+  cont->title_len=0;
+  cont->author_len=0;
+  cont->copyright_len=0;
+  cont->comment_len=0;
+
+  if (title) {
+    cont->title_len=strlen(title);
+    cont->title=strdup(title);
+  }
+  if (author) {
+    cont->author_len=strlen(author);
+    cont->author=strdup(author);
+  }
+  if (copyright) {
+    cont->copyright_len=strlen(copyright);
+    cont->copyright=strdup(copyright);
+  }
+  if (comment) {
+    cont->comment_len=strlen(comment);
+    cont->comment=strdup(comment);
+  }
+  cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18;
+
+  return cont;
+}
+
+rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header) {
+
+  rmff_data_t *data=malloc(sizeof(rmff_data_t));
+
+  data->object_id=DATA_TAG;
+  data->size=18;
+  data->object_version=0;
+  data->num_packets=num_packets;
+  data->next_data_header=next_data_header;
+
+  return data;
+}
+  
+void rmff_print_header(rmff_header_t *h) {
+
+  rmff_mdpr_t **stream;
+  
+  if(!h) {
+    printf("rmff_print_header: NULL given\n");
+    return;
+  }
+  if(h->fileheader)
+  {
+    printf("\nFILE:\n");
+    printf("file version      : %d\n", h->fileheader->file_version);
+    printf("number of headers : %d\n", h->fileheader->num_headers);
+  }
+  if(h->cont)
+  {
+    printf("\nCONTENT:\n");
+    printf("title     : %s\n", h->cont->title);
+    printf("author    : %s\n", h->cont->author);
+    printf("copyright : %s\n", h->cont->copyright);
+    printf("comment   : %s\n", h->cont->comment);
+  }
+  if(h->prop)
+  {
+    printf("\nSTREAM PROPERTIES:\n");
+    printf("bit rate (max/avg)    : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate);
+    printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size);
+    printf("packets       : %i\n", h->prop->num_packets);
+    printf("duration      : %i ms\n", h->prop->duration);
+    printf("pre-buffer    : %i ms\n", h->prop->preroll);
+    printf("index offset  : %i bytes\n", h->prop->index_offset);
+    printf("data offset   : %i bytes\n", h->prop->data_offset);
+    printf("media streams : %i\n", h->prop->num_streams);
+    printf("flags         : ");
+    if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled ");
+    if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled ");
+    if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast ");
+    printf("\n");
+  }
+  stream=h->streams;
+  if(stream)
+  {
+    while (*stream)
+    {
+      printf("\nSTREAM %i:\n", (*stream)->stream_number);
+      printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type);
+      printf("bit rate (max/avg)      : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate);
+      printf("packet size (max/avg)   : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size);
+      printf("start time : %i\n", (*stream)->start_time);
+      printf("pre-buffer : %i ms\n", (*stream)->preroll);
+      printf("duration   : %i ms\n", (*stream)->duration);
+      printf("type specific data:\n");
+      hexdump((*stream)->type_specific_data, (*stream)->type_specific_len);
+      stream++;
+    }
+  }
+  if(h->data)
+  {
+    printf("\nDATA:\n");
+    printf("size      : %i\n", h->data->size);
+    printf("packets   : %i\n", h->data->num_packets);
+    printf("next DATA : 0x%08x\n", h->data->next_data_header);
+  } 
+}
+
+void rmff_fix_header(rmff_header_t *h) {
+
+  int num_headers=0;
+  int header_size=0;
+  rmff_mdpr_t **streams;
+  int num_streams=0;
+
+  if (!h) {
+    printf("rmff_fix_header: fatal: no header given.\n");
+    return;
+  }
+
+  if (!h->streams) {
+    printf("rmff_fix_header: warning: no MDPR chunks\n");
+  } else
+  {
+    streams=h->streams;
+    while (*streams)
+    {
+      num_streams++;
+      num_headers++;
+      header_size+=(*streams)->size;
+      streams++;
+    }
+  }
+  
+  if (h->prop) {
+    if (h->prop->size != 50)
+    {
+#ifdef LOG
+      printf("rmff_fix_header: correcting prop.size from %i to %i\n", h->prop->size, 50);
+#endif
+      h->prop->size=50;
+    }
+    if (h->prop->num_streams != num_streams)
+    {
+#ifdef LOG
+      printf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h->prop->num_streams, num_streams);
+#endif
+      h->prop->num_streams=num_streams;
+    }
+    num_headers++;
+    header_size+=50;
+  } else
+    printf("rmff_fix_header: warning: no PROP chunk.\n");
+
+  if (h->cont) {
+    num_headers++;
+    header_size+=h->cont->size;
+  } else
+    printf("rmff_fix_header: warning: no CONT chunk.\n");
+
+  if (!h->data) {
+#ifdef LOG
+    printf("rmff_fix_header: no DATA chunk, creating one\n");
+#endif
+    h->data=malloc(sizeof(rmff_data_t));
+    h->data->object_id=DATA_TAG;
+    h->data->object_version=0;
+    h->data->size=34;
+    h->data->num_packets=0;
+    h->data->next_data_header=0;
+  }
+  num_headers++;
+
+  
+  if (!h->fileheader) {
+#ifdef LOG
+    printf("rmff_fix_header: no fileheader, creating one");
+#endif
+    h->fileheader=malloc(sizeof(rmff_fileheader_t));
+    h->fileheader->object_id=RMF_TAG;
+    h->fileheader->size=34;
+    h->fileheader->object_version=0;
+    h->fileheader->file_version=0;
+    h->fileheader->num_headers=num_headers+1;
+  }
+  header_size+=h->fileheader->size;
+  num_headers++;
+
+  if(h->fileheader->num_headers != num_headers) {
+#ifdef LOG
+    printf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers); 
+#endif
+    h->fileheader->num_headers=num_headers;
+  }
+
+  if(h->prop) {
+    if (h->prop->data_offset != header_size) {
+#ifdef LOG
+      printf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size); 
+#endif
+      h->prop->data_offset=header_size;
+    }
+    if (h->prop->num_packets == 0) {
+      int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size);
+#ifdef LOG
+      printf("rmff_fix_header: assuming prop.num_packets=%i\n", p); 
+#endif
+      h->prop->num_packets=p;
+    }
+    if (h->data->num_packets == 0) {
+#ifdef LOG
+      printf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets); 
+#endif
+      h->data->num_packets=h->prop->num_packets;
+    }
+    
+#ifdef LOG
+    printf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size); 
+#endif
+    h->data->size=h->prop->num_packets*h->prop->avg_packet_size;
+  }
+}
+
+int rmff_get_header_size(rmff_header_t *h) {
+
+  if (!h) return 0;
+  if (!h->prop) return -1;
+
+  return h->prop->data_offset+18;
+  
+}
+
+void rmff_free_header(rmff_header_t *h) {
+
+  if (!h) return;
+
+  if (h->fileheader) free(h->fileheader);
+  if (h->prop) free(h->prop);
+  if (h->data) free(h->data);
+  if (h->cont)
+  {
+    free(h->cont->title);
+    free(h->cont->author);
+    free(h->cont->copyright);
+    free(h->cont->comment);
+    free(h->cont);
+  }
+  if (h->streams)
+  {
+    rmff_mdpr_t **s=h->streams;
+
+    while(*s) {
+      free((*s)->stream_name);
+      free((*s)->mime_type);
+      free((*s)->type_specific_data);
+      free(*s);
+      s++;
+    }
+    free(h->streams);
+  }
+  free(h);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/rmff.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,270 @@
+/*
+ * This file was ported to MPlayer from xine CVS rmff.h,v 1.3 2003/02/10 22:11:10
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * some functions for real media file headers
+ * adopted from joschkas real tools
+ */
+
+#include <sys/types.h>
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#else
+#include <winsock2.h>
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+
+#ifndef HAVE_RMFF_H
+#define HAVE_RMFF_H
+
+
+#define RMFF_HEADER_SIZE 0x12
+
+#define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
+        (((long)(unsigned char)(ch3)       ) | \
+        ( (long)(unsigned char)(ch2) << 8  ) | \
+        ( (long)(unsigned char)(ch1) << 16 ) | \
+        ( (long)(unsigned char)(ch0) << 24 ) )
+
+
+#define RMF_TAG   FOURCC_TAG('.', 'R', 'M', 'F')
+#define PROP_TAG  FOURCC_TAG('P', 'R', 'O', 'P')
+#define MDPR_TAG  FOURCC_TAG('M', 'D', 'P', 'R')
+#define CONT_TAG  FOURCC_TAG('C', 'O', 'N', 'T')
+#define DATA_TAG  FOURCC_TAG('D', 'A', 'T', 'A')
+#define INDX_TAG  FOURCC_TAG('I', 'N', 'D', 'X')
+#define PNA_TAG   FOURCC_TAG('P', 'N', 'A',  0 )
+
+#define MLTI_TAG  FOURCC_TAG('M', 'L', 'T', 'I')
+
+/* prop flags */
+#define PN_SAVE_ENABLED         0x01
+#define PN_PERFECT_PLAY_ENABLED 0x02
+#define PN_LIVE_BROADCAST       0x04
+
+/*
+ * rm header data structs
+ */
+
+typedef struct {
+
+  uint32_t object_id;
+  uint32_t size;
+  uint16_t object_version;
+
+  uint32_t file_version;
+  uint32_t num_headers;
+} rmff_fileheader_t;
+
+typedef struct {
+
+  uint32_t object_id;
+  uint32_t size;
+  uint16_t object_version;
+
+  uint32_t max_bit_rate;
+  uint32_t avg_bit_rate;
+  uint32_t max_packet_size;
+  uint32_t avg_packet_size;
+  uint32_t num_packets;
+  uint32_t duration;
+  uint32_t preroll;
+  uint32_t index_offset;
+  uint32_t data_offset;
+  uint16_t num_streams;
+  uint16_t flags;
+    
+} rmff_prop_t;
+
+typedef struct {
+
+  uint32_t  object_id;
+  uint32_t  size;
+  uint16_t  object_version;
+
+  uint16_t  stream_number;
+  uint32_t  max_bit_rate;
+  uint32_t  avg_bit_rate;
+  uint32_t  max_packet_size;
+  uint32_t  avg_packet_size;
+  uint32_t  start_time;
+  uint32_t  preroll;
+  uint32_t  duration;
+  uint8_t   stream_name_size;
+  char      *stream_name;
+  uint8_t   mime_type_size;
+  char      *mime_type;
+  uint32_t  type_specific_len;
+  char      *type_specific_data;
+
+  int       mlti_data_size;
+  char      *mlti_data;
+
+} rmff_mdpr_t;
+
+typedef struct {
+
+  uint32_t  object_id;
+  uint32_t  size;
+  uint16_t  object_version;
+
+  uint16_t  title_len;
+  char      *title;
+  uint16_t  author_len;
+  char      *author;
+  uint16_t  copyright_len;
+  char      *copyright;
+  uint16_t  comment_len;
+  char      *comment;
+  
+} rmff_cont_t;
+
+typedef struct {
+  
+  uint32_t object_id;
+  uint32_t size;
+  uint16_t object_version;
+
+  uint32_t num_packets;
+  uint32_t next_data_header; /* rarely used */
+} rmff_data_t;
+
+typedef struct {
+
+  rmff_fileheader_t *fileheader;
+  rmff_prop_t *prop;
+  rmff_mdpr_t **streams;
+  rmff_cont_t *cont;
+  rmff_data_t *data;
+} rmff_header_t;
+
+typedef struct {
+
+  uint16_t object_version;
+
+  uint16_t length;
+  uint16_t stream_number;
+  uint32_t timestamp;
+  uint8_t reserved;
+  uint8_t flags;
+
+} rmff_pheader_t;
+
+/*
+ * constructors for header structs
+ */
+ 
+rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers);
+
+rmff_prop_t *rmff_new_prop (
+    uint32_t max_bit_rate,
+    uint32_t avg_bit_rate,
+    uint32_t max_packet_size,
+    uint32_t avg_packet_size,
+    uint32_t num_packets,
+    uint32_t duration,
+    uint32_t preroll,
+    uint32_t index_offset,
+    uint32_t data_offset,
+    uint16_t num_streams,
+    uint16_t flags );
+
+rmff_mdpr_t *rmff_new_mdpr(
+    uint16_t   stream_number,
+    uint32_t   max_bit_rate,
+    uint32_t   avg_bit_rate,
+    uint32_t   max_packet_size,
+    uint32_t   avg_packet_size,
+    uint32_t   start_time,
+    uint32_t   preroll,
+    uint32_t   duration,
+    const char *stream_name,
+    const char *mime_type,
+    uint32_t   type_specific_len,
+    const char *type_specific_data );
+
+rmff_cont_t *rmff_new_cont(
+    const char *title,
+    const char *author,
+    const char *copyright,
+    const char *comment);
+
+rmff_data_t *rmff_new_dataheader(
+    uint32_t num_packets, uint32_t next_data_header);
+
+/*
+ * reads header infos from data and returns a newly allocated header struct
+ */
+rmff_header_t *rmff_scan_header(const char *data);
+
+/*
+ * scans a data packet header. Notice, that this function does not allocate
+ * the header struct itself.
+ */
+void rmff_scan_pheader(rmff_pheader_t *h, char *data);
+
+/*
+ * reads header infos from stream and returns a newly allocated header struct
+ */
+rmff_header_t *rmff_scan_header_stream(int fd);
+
+/*
+ * prints header information in human readible form to stdout
+ */
+void rmff_print_header(rmff_header_t *h);
+
+/*
+ * does some checks and fixes header if possible
+ */
+void rmff_fix_header(rmff_header_t *h);
+
+/*
+ * returns the size of the header (incl. first data-header)
+ */
+int rmff_get_header_size(rmff_header_t *h);
+ 
+/*
+ * dumps the header <h> to <buffer>. <max> is the size of <buffer>
+ */
+int rmff_dump_header(rmff_header_t *h, char *buffer, int max);
+
+/*
+ * dumps a packet header
+ */
+void rmff_dump_pheader(rmff_pheader_t *h, char *data);
+
+/*
+ * frees a header struct
+ */
+void rmff_free_header(rmff_header_t *h);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/sdpplin.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,366 @@
+/*
+ * This file was ported to MPlayer from xine CVS sdpplin.c,v 1.1 2002/12/24 01:30:22
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * sdp/sdpplin parser.
+ *
+ */
+ 
+#include "config.h"
+#include "../librtsp/rtsp.h"
+#include "sdpplin.h"
+#include "xbuffer.h"
+#include "mp_msg.h"
+
+/*
+#define LOG
+*/
+
+/*
+ * Decodes base64 strings (based upon b64 package)
+ */
+
+static char *b64_decode(const char *in, char *out, int *size)
+{
+  char dtable[256];              /* Encode / decode table */
+  int i,j,k;
+
+  for (i = 0; i < 255; i++) {
+    dtable[i] = 0x80;
+  }
+  for (i = 'A'; i <= 'Z'; i++) {
+    dtable[i] = 0 + (i - 'A');
+  }
+  for (i = 'a'; i <= 'z'; i++) {
+    dtable[i] = 26 + (i - 'a');
+  }
+  for (i = '0'; i <= '9'; i++) {
+    dtable[i] = 52 + (i - '0');
+  }
+  dtable['+'] = 62;
+  dtable['/'] = 63;
+  dtable['='] = 0;
+
+  k=0;
+  
+  /*CONSTANTCONDITION*/
+  for (j=0; j<strlen(in); j+=4)
+  {
+    char a[4], b[4];
+
+    for (i = 0; i < 4; i++) {
+      int c = in[i+j];
+
+      if (dtable[c] & 0x80) {
+        printf("Illegal character '%c' in input.\n", c);
+//        exit(1);
+        return NULL;
+      }
+      a[i] = (char) c;
+      b[i] = (char) dtable[c];
+    }
+    out = xbuffer_ensure_size(out, k+4);
+    out[k++] = (b[0] << 2) | (b[1] >> 4);
+    out[k++] = (b[1] << 4) | (b[2] >> 2);
+    out[k++] = (b[2] << 6) | b[3];
+    i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
+    if (i < 3) {
+      out[k]=0;
+      *size=k;
+      return out;
+    }
+  }
+  out[k]=0;
+  *size=k;
+  return out;
+}
+
+static char *nl(char *data) {
+
+  char *nlptr = (data) ? strchr(data,'\n') : NULL;
+  return (nlptr) ? nlptr + 1 : NULL;
+}
+
+static int filter(const char *in, const char *filter, char **out) {
+
+  int flen=strlen(filter);
+  int len;
+
+  if (!in)
+    return 0;
+
+  len = (strchr(in,'\n')) ? strchr(in,'\n')-in : strlen(in);
+
+  if (!strncmp(in,filter,flen))
+  {
+    if(in[flen]=='"') flen++;
+    if(in[len-1]==13) len--;
+    if(in[len-1]=='"') len--;
+    *out = xbuffer_copyin(*out, 0, in+flen, len-flen+1);
+    (*out)[len-flen]=0;
+
+    return len-flen;
+  }
+  
+  return 0;
+}
+static sdpplin_stream_t *sdpplin_parse_stream(char **data) {
+
+  sdpplin_stream_t *desc=calloc(1,sizeof(sdpplin_stream_t));
+  char      *buf=xbuffer_init(32);
+  char      *decoded=xbuffer_init(32);
+  int       handled;
+  int       got_mimetype;
+    
+  if (filter(*data, "m=", &buf)) {
+    desc->id = strdup(buf);
+  } else
+  {
+    printf("sdpplin: no m= found.\n");
+    free(desc);
+    xbuffer_free(buf);
+    return NULL;
+  }
+  *data=nl(*data);
+
+  got_mimetype = 0;
+
+  while (*data && **data && *data[0]!='m') {
+#ifdef LOG
+    {
+      int len=strchr(*data,'\n')-(*data);
+      buf = xbuffer_copyin(buf, 0, *data, len+1);
+      buf[len]=0;
+      printf("libreal: sdpplin_stream: '%s'\n", buf);
+    }
+#endif
+
+    handled=0;
+    
+    if(filter(*data,"a=control:streamid=",&buf)) {
+      desc->stream_id=atoi(buf);
+      handled=1;
+      *data=nl(*data);
+    }
+
+    if(filter(*data,"a=MaxBitRate:integer;",&buf)) {
+      desc->max_bit_rate=atoi(buf);
+      if (!desc->avg_bit_rate)
+        desc->avg_bit_rate=desc->max_bit_rate;
+      handled=1;
+      *data=nl(*data);
+    }
+
+    if(filter(*data,"a=MaxPacketSize:integer;",&buf)) {
+      desc->max_packet_size=atoi(buf);
+      if (!desc->avg_packet_size)
+        desc->avg_packet_size=desc->max_packet_size;
+      handled=1;
+      *data=nl(*data);
+    }
+    
+    if(filter(*data,"a=StartTime:integer;",&buf)) {
+      desc->start_time=atoi(buf);
+      handled=1;
+      *data=nl(*data);
+    }
+
+    if(filter(*data,"a=Preroll:integer;",&buf)) {
+      desc->preroll=atoi(buf);
+      handled=1;
+      *data=nl(*data);
+    }
+
+    if(filter(*data,"a=length:npt=",&buf)) {
+      desc->duration=(uint32_t)(atof(buf)*1000);
+      handled=1;
+      *data=nl(*data);
+    }
+
+    if(filter(*data,"a=StreamName:string;",&buf)) {
+      desc->stream_name=strdup(buf);
+      desc->stream_name_size=strlen(desc->stream_name);
+      handled=1;
+      *data=nl(*data);
+    }
+
+    if(filter(*data,"a=mimetype:string;",&buf)) {
+      desc->mime_type=strdup(buf);
+      desc->mime_type_size=strlen(desc->mime_type);
+      handled=1;
+      got_mimetype = 1;
+      *data=nl(*data);
+    }
+
+    if(filter(*data,"a=OpaqueData:buffer;",&buf)) {
+      decoded = b64_decode(buf, decoded, &(desc->mlti_data_size));
+      desc->mlti_data=malloc(desc->mlti_data_size);
+      memcpy(desc->mlti_data, decoded, desc->mlti_data_size);
+      handled=1;
+      *data=nl(*data);
+#ifdef LOG
+      printf("mlti_data_size: %i\n", desc->mlti_data_size);
+#endif
+    }
+    
+    if(filter(*data,"a=ASMRuleBook:string;",&buf)) {
+      desc->asm_rule_book=strdup(buf);
+      handled=1;
+      *data=nl(*data);
+    }
+
+    if(!handled) {
+#ifdef LOG
+      int len=strchr(*data,'\n')-(*data);
+      buf = xbuffer_copyin(buf, 0, *data, len+1);
+      buf[len]=0;
+      printf("libreal: sdpplin_stream: not handled: '%s'\n", buf);
+#endif
+      *data=nl(*data);
+    }
+  }
+
+  if (!got_mimetype) {
+    mp_msg(MSGT_OPEN, MSGL_V, "libreal: sdpplin_stream: no mimetype\n");
+    desc->mime_type = strdup("audio/x-pn-realaudio");
+    desc->mime_type_size = strlen(desc->mime_type);
+    if (desc->stream_id)
+      mp_msg(MSGT_OPEN, MSGL_WARN, "libreal: sdpplin_stream: implicit mimetype for stream_id != 0, weird.\n");
+  }
+
+  xbuffer_free(buf);
+  xbuffer_free(decoded);
+  
+  return desc;
+}
+
+sdpplin_t *sdpplin_parse(char *data) {
+
+  sdpplin_t        *desc=calloc(1,sizeof(sdpplin_t));
+  char             *buf=xbuffer_init(32);
+  char             *decoded=xbuffer_init(32);
+  int              handled;
+  int              len;
+
+  while (data && *data) {
+#ifdef LOG
+    {
+      int len=strchr(data,'\n')-(data);
+      buf = xbuffer_copyin(buf, 0, data, len+1);
+      buf[len]=0;
+      printf("libreal: sdpplin: '%s'\n", buf);
+    }
+#endif
+
+    handled=0;
+    
+    if (filter(data, "m=", &buf)) {
+      sdpplin_stream_t *stream=sdpplin_parse_stream(&data);
+#ifdef LOG
+      printf("got data for stream id %u\n", stream->stream_id);
+#endif
+      if (desc->stream && (stream->stream_id >= 0) && (stream->stream_id < desc->stream_count))
+      desc->stream[stream->stream_id]=stream;
+      else if (desc->stream)
+      {
+      mp_msg(MSGT_OPEN, MSGL_ERR, "sdpplin: bad stream_id %d (must be >= 0, < %d). Broken sdp?\n",
+        stream->stream_id, desc->stream_count);
+      free(stream);
+      } else {
+        mp_msg(MSGT_OPEN, MSGL_V, "sdpplin: got 'm=', but 'a=StreamCount' is still unknown.\n");
+        if (stream->stream_id == 0) {
+          desc->stream_count=1;
+          desc->stream=malloc(sizeof(sdpplin_stream_t*));
+          desc->stream[0]=stream;
+        } else {
+          mp_msg(MSGT_OPEN, MSGL_ERR, "sdpplin: got 'm=', but 'a=StreamCount' is still unknown and stream_id != 0. Broken sdp?\n");
+          free(stream);
+        }
+      }
+      continue;
+    }
+
+    if(filter(data,"a=Title:buffer;",&buf)) {
+      decoded=b64_decode(buf, decoded, &len);
+      desc->title=strdup(decoded);
+      handled=1;
+      data=nl(data);
+    }
+    
+    if(filter(data,"a=Author:buffer;",&buf)) {
+      decoded=b64_decode(buf, decoded, &len);
+      desc->author=strdup(decoded);
+      handled=1;
+      data=nl(data);
+    }
+    
+    if(filter(data,"a=Copyright:buffer;",&buf)) {
+      decoded=b64_decode(buf, decoded, &len);
+      desc->copyright=strdup(decoded);
+      handled=1;
+      data=nl(data);
+    }
+    
+    if(filter(data,"a=Abstract:buffer;",&buf)) {
+      decoded=b64_decode(buf, decoded, &len);
+      desc->abstract=strdup(decoded);
+      handled=1;
+      data=nl(data);
+    }
+    
+    if(filter(data,"a=StreamCount:integer;",&buf)) {
+      desc->stream_count=(unsigned int)atoi(buf);
+      desc->stream=malloc(sizeof(sdpplin_stream_t*)*desc->stream_count);
+      handled=1;
+      data=nl(data);
+    }
+
+    if(filter(data,"a=Flags:integer;",&buf)) {
+      desc->flags=atoi(buf);
+      handled=1;
+      data=nl(data);
+    }
+
+    if(!handled) {
+#ifdef LOG
+      int len=strchr(data,'\n')-data;
+      buf = xbuffer_copyin(buf, 0, data, len+1);
+      buf[len]=0;
+      printf("libreal: sdpplin: not handled: '%s'\n", buf);
+#endif
+      data=nl(data);
+    }
+  }
+
+  xbuffer_free(buf);
+  xbuffer_free(decoded);
+  
+  return desc;
+}
+
+void sdpplin_free(sdpplin_t *description) {
+
+  /* TODO: free strings */
+  free(description);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/sdpplin.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,109 @@
+/*
+ * This file was ported to MPlayer from xine CVS sdpplin.h,v 1.1 2002/12/24 01:30:22
+ */
+
+/*
+ * Copyright (C) 2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ *
+ *
+ * sdp/sdpplin parser.
+ *
+ */
+ 
+#ifndef HAVE_SDPPLIN_H
+#define HAVE_SDPPLIN_H
+
+#include "rmff.h"
+#include "../librtsp/rtsp.h"
+
+typedef struct {
+
+  char *id;
+  char *bandwidth;
+
+  int stream_id;
+  char *range;
+  char *length;
+  char *rtpmap;
+  char *mimetype;
+  int min_switch_overlap;
+  int start_time;
+  int end_one_rule_end_all;
+  int avg_bit_rate;
+  int max_bit_rate;
+  int avg_packet_size;
+  int max_packet_size;
+  int end_time;
+  int seek_greater_on_switch;
+  int preroll;
+
+  int duration;
+  char *stream_name;
+  int stream_name_size;
+  char *mime_type;
+  int mime_type_size;
+  char *mlti_data;
+  int mlti_data_size;
+  int  rmff_flags_length;
+  char *rmff_flags;
+  int  asm_rule_book_length;
+  char *asm_rule_book;
+
+} sdpplin_stream_t;
+
+typedef struct {
+
+  int sdp_version, sdpplin_version;
+  char *owner;
+  char *session_name;
+  char *session_info;
+  char *uri;
+  char *email;
+  char *phone;
+  char *connection;
+  char *bandwidth;
+
+  int flags;
+  int is_real_data_type;
+  int stream_count;
+  char *title;
+  char *author;
+  char *copyright;
+  char *keywords;
+  int  asm_rule_book_length;
+  char *asm_rule_book;
+  char *abstract;
+  char *range;
+  int avg_bit_rate;
+  int max_bit_rate;
+  int avg_packet_size;
+  int max_packet_size;
+  int preroll;
+  int duration;
+
+  sdpplin_stream_t **stream;
+  
+} sdpplin_t;
+
+sdpplin_t *sdpplin_parse(char *data);
+
+void sdpplin_free(sdpplin_t *description);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/xbuffer.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,102 @@
+/* 
+ * xbuffer code
+ *
+ * Includes a minimalistic replacement for xine_buffer functions used in
+ * Real streaming code. Only function needed by this code are implemented.
+ *
+ * Most code comes from xine_buffer.c Copyright (C) 2002 the xine project
+ *
+ * WARNING: do not mix original xine_buffer functions with this code!
+ * xbuffers behave like xine_buffers, but are not byte-compatible with them.
+ * You must take care of pointers returned by xbuffers functions (no macro to
+ * do it automatically)
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include "xbuffer.h"
+
+
+typedef struct {
+  uint32_t size;
+  uint32_t chunk_size;
+} xbuffer_header_t;
+
+#define XBUFFER_HEADER_SIZE sizeof (xbuffer_header_t)
+
+
+
+void *xbuffer_init(int chunk_size) {  
+  uint8_t *data=calloc(1,chunk_size+XBUFFER_HEADER_SIZE);
+
+  xbuffer_header_t *header=(xbuffer_header_t*)data;
+
+  header->size=chunk_size;
+  header->chunk_size=chunk_size;
+
+  return data+XBUFFER_HEADER_SIZE;
+}
+
+
+
+void *xbuffer_free(void *buf) {
+  if (!buf) {
+    return NULL;
+  }
+
+  free(((uint8_t*)buf)-XBUFFER_HEADER_SIZE);
+
+  return NULL;
+}
+
+
+
+void *xbuffer_copyin(void *buf, int index, const void *data, int len) {
+    if (!buf || !data) {
+    return NULL;
+  }
+
+  buf = xbuffer_ensure_size(buf, index+len);
+  memcpy(((uint8_t*)buf)+index, data, len);
+
+  return buf;
+}
+
+
+
+void *xbuffer_ensure_size(void *buf, int size) {
+  xbuffer_header_t *xbuf;
+  int new_size;
+
+  if (!buf) {
+    return 0;
+  }
+
+  xbuf = ((xbuffer_header_t*)(((uint8_t*)buf)-XBUFFER_HEADER_SIZE));
+  
+  if (xbuf->size < size) {
+    new_size = size + xbuf->chunk_size - (size % xbuf->chunk_size);
+    xbuf->size = new_size;
+    buf = ((uint8_t*)realloc(((uint8_t*)buf)-XBUFFER_HEADER_SIZE,
+          new_size+XBUFFER_HEADER_SIZE)) + XBUFFER_HEADER_SIZE;
+  }
+
+  return buf;
+}
+
+
+
+void *xbuffer_strcat(void *buf, char *data) {
+
+  if (!buf || !data) {
+    return NULL;
+  }
+
+  buf = xbuffer_ensure_size(buf, strlen(buf)+strlen(data)+1);
+
+  strcat(buf, data);
+
+  return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/realrtsp/xbuffer.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,26 @@
+/* 
+ * xbuffer code
+ *
+ * Includes a minimalistic replacement for xine_buffer functions used in
+ * Real streaming code. Only function needed by this code are implemented.
+ *
+ * Most code comes from xine_buffer.c Copyright (C) 2002 the xine project
+ *
+ * WARNING: do not mix original xine_buffer functions with this code!
+ * xbuffers behave like xine_buffers, but are not byte-compatible with them.
+ * You must take care of pointers returned by xbuffers functions (no macro to
+ * do it automatically)
+ *
+ */
+
+
+#ifndef _XCL_H_
+#define _XCL_H_
+
+void *xbuffer_init(int chunk_size);
+void *xbuffer_free(void *buf);
+void *xbuffer_copyin(void *buf, int index, const void *data, int len);
+void *xbuffer_ensure_size(void *buf, int size);
+void *xbuffer_strcat(void *buf, char *data);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/rtp.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,434 @@
+/* Imported from the dvbstream-0.2 project
+ *
+ * Modified for use with MPlayer, for details see the changelog at
+ * http://svn.mplayerhq.hu/mplayer/trunk/
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#define closesocket close
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#include <errno.h>
+#include "stream.h"
+
+/* MPEG-2 TS RTP stack */
+
+#define DEBUG        1
+#include "rtp.h"
+
+extern int network_bandwidth;
+
+
+#define DEBUG        1
+#include "../mp_msg.h"
+#include "rtp.h"
+
+// RTP reorder routines
+// Also handling of repeated UDP packets (a bug of ExtremeNetworks switches firmware)
+// rtpreord procedures
+// write rtp packets in cache
+// get rtp packets reordered
+
+#define MAXRTPPACKETSIN 32   // The number of max packets being reordered
+
+struct rtpbuffer
+{
+	unsigned char  data[MAXRTPPACKETSIN][STREAM_BUFFER_SIZE];
+	unsigned short  seq[MAXRTPPACKETSIN];
+	unsigned short  len[MAXRTPPACKETSIN];
+	unsigned short first;
+};
+static struct rtpbuffer rtpbuf;
+
+// RTP Reordering functions
+// Algorithm works as follows:
+// If next packet is in sequence just copy it to buffer
+// Otherwise copy it in cache according to its sequence number
+// Cache is a circular array where "rtpbuf.first" points to next sequence slot
+// and keeps track of expected sequence
+
+// Initialize rtp cache
+static void rtp_cache_reset(unsigned short seq)
+{
+	int i;
+	
+	rtpbuf.first = 0;
+	rtpbuf.seq[0] = ++seq;
+	
+	for (i=0; i<MAXRTPPACKETSIN; i++) {
+		rtpbuf.len[i] = 0;
+	}
+}
+
+// Write in a cache the rtp packet in right rtp sequence order
+static int rtp_cache(int fd, char *buffer, int length)
+{
+	struct rtpheader rh;
+	int newseq;
+	char *data;
+	unsigned short seq;
+	static int is_first = 1;
+	
+	getrtp2(fd, &rh, &data, &length);
+	if(!length)
+		return 0;
+	seq = rh.b.sequence;
+	
+	newseq = seq - rtpbuf.seq[rtpbuf.first];
+	
+	if ((newseq == 0) || is_first)
+	{
+		is_first = 0;
+		
+		//mp_msg(MSGT_NETWORK, MSGL_DBG4, "RTP (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
+		rtpbuf.first = ( 1 + rtpbuf.first ) % MAXRTPPACKETSIN;
+		rtpbuf.seq[rtpbuf.first] = ++seq;
+		goto feed;
+	}
+	
+	if (newseq > MAXRTPPACKETSIN)
+	{
+		mp_msg(MSGT_NETWORK, MSGL_DBG2, "Overrun(seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
+		rtp_cache_reset(seq);
+		goto feed;
+	}
+	
+	if (newseq < 0)
+	{
+		int i;
+		
+		// Is it a stray packet re-sent to network?
+		for (i=0; i<MAXRTPPACKETSIN; i++) {
+			if (rtpbuf.seq[i] == seq) {
+				mp_msg(MSGT_NETWORK, MSGL_ERR, "Stray packet (seq[%d]=%d seq=%d, newseq=%d found at %d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq, i);
+				return  0; // Yes, it is!
+			}
+		}
+		// Some heuristic to decide when to drop packet or to restart everything
+		if (newseq > -(3 * MAXRTPPACKETSIN)) {
+			mp_msg(MSGT_NETWORK, MSGL_ERR, "Too Old packet (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
+			return  0; // Yes, it is!
+		}
+		
+		mp_msg(MSGT_NETWORK, MSGL_ERR,  "Underrun(seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
+		
+		rtp_cache_reset(seq);
+		goto feed;
+	}
+	
+	mp_msg(MSGT_NETWORK, MSGL_DBG4, "Out of Seq (seq[%d]=%d seq=%d, newseq=%d)\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first], seq, newseq);
+	newseq = ( newseq + rtpbuf.first ) % MAXRTPPACKETSIN;
+	memcpy (rtpbuf.data[newseq], data, length);
+	rtpbuf.len[newseq] = length;
+	rtpbuf.seq[newseq] = seq;
+	
+	return 0;
+
+feed:
+	memcpy (buffer, data, length);
+	return length;
+}
+
+// Get next packet in cache
+// Look in cache to get first packet in sequence
+static int rtp_get_next(int fd, char *buffer, int length)
+{
+	int i;
+	unsigned short nextseq;
+
+	// If we have empty buffer we loop to fill it
+	for (i=0; i < MAXRTPPACKETSIN -3; i++) {
+		if (rtpbuf.len[rtpbuf.first] != 0) break;
+		
+		length = rtp_cache(fd, buffer, length) ;
+		
+		// returns on first packet in sequence 
+		if (length > 0) {
+			//mp_msg(MSGT_NETWORK, MSGL_DBG4, "Getting rtp [%d] %hu\n", i, rtpbuf.first);
+			return length;
+		} else if (length < 0) break;
+		
+		// Only if length == 0 loop continues!
+	}
+	
+	i = rtpbuf.first;
+	while (rtpbuf.len[i] == 0) {
+		mp_msg(MSGT_NETWORK, MSGL_ERR,  "Lost packet %hu\n", rtpbuf.seq[i]);
+		i = ( 1 + i ) % MAXRTPPACKETSIN;
+		if (rtpbuf.first == i) break;
+	}
+	rtpbuf.first = i;
+	
+	// Copy next non empty packet from cache
+	mp_msg(MSGT_NETWORK, MSGL_DBG4, "Getting rtp from cache [%d] %hu\n", rtpbuf.first, rtpbuf.seq[rtpbuf.first]);
+	memcpy (buffer, rtpbuf.data[rtpbuf.first], rtpbuf.len[rtpbuf.first]);
+	length = rtpbuf.len[rtpbuf.first]; // can be zero?
+	
+	// Reset fisrt slot and go next in cache
+	rtpbuf.len[rtpbuf.first] = 0;
+	nextseq = rtpbuf.seq[rtpbuf.first];
+	rtpbuf.first = ( 1 + rtpbuf.first ) % MAXRTPPACKETSIN;
+	rtpbuf.seq[rtpbuf.first] = nextseq + 1;
+	
+	return length;
+}
+
+
+// Read next rtp packet using cache 
+int read_rtp_from_server(int fd, char *buffer, int length) {
+	// Following test is ASSERT (i.e. uneuseful if code is correct)
+	if(buffer==NULL || length<STREAM_BUFFER_SIZE) {
+		mp_msg(MSGT_NETWORK, MSGL_ERR, "RTP buffer invalid; no data return from network\n");
+		return 0;
+	}
+	
+	// loop just to skip empty packets
+	while ((length = rtp_get_next(fd, buffer, length)) == 0) {
+		mp_msg(MSGT_NETWORK, MSGL_ERR, "Got empty packet from RTP cache!?\n");
+	}
+	
+	return(length);
+}
+
+// Start listening on a UDP port. If multicast, join the group.
+static int rtp_open_socket( URL_t *url ) {
+	int socket_server_fd, rxsockbufsz;
+	int err, err_len;
+	fd_set set;
+	struct sockaddr_in server_address;
+	struct ip_mreq mcast;
+        struct timeval tv;
+	struct hostent *hp;
+
+	mp_msg(MSGT_NETWORK,MSGL_V,"Listening for traffic on %s:%d ...\n", url->hostname, url->port );
+
+	socket_server_fd = socket(AF_INET, SOCK_DGRAM, 0);
+//	fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK );
+	if( socket_server_fd==-1 ) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create socket\n");
+		return -1;
+	}
+
+	if( isalpha(url->hostname[0]) ) {
+#ifndef HAVE_WINSOCK2
+		hp =(struct hostent*)gethostbyname( url->hostname );
+		if( hp==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname);
+			goto err_out;
+		}
+		memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr_list[0], hp->h_length );
+#else
+		server_address.sin_addr.s_addr = htonl(INADDR_ANY);
+#endif
+	} else {
+#ifndef HAVE_WINSOCK2
+#ifdef USE_ATON
+		inet_aton(url->hostname, &server_address.sin_addr);
+#else
+		inet_pton(AF_INET, url->hostname, &server_address.sin_addr);
+#endif
+#else
+		server_address.sin_addr.s_addr = htonl(INADDR_ANY);
+#endif
+	}
+	server_address.sin_family=AF_INET;
+	server_address.sin_port=htons(url->port);
+
+	if( bind( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) {
+#ifndef HAVE_WINSOCK2
+		if( errno!=EINPROGRESS ) {
+#else
+		if( WSAGetLastError() != WSAEINPROGRESS ) {
+#endif
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to connect to server\n");
+			goto err_out;
+		}
+	}
+	
+#ifdef HAVE_WINSOCK2
+	if (isalpha(url->hostname[0])) {
+		hp =(struct hostent*)gethostbyname( url->hostname );
+		if( hp==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname);
+			goto err_out;
+		}
+		memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length );
+	} else {
+		unsigned int addr = inet_addr(url->hostname);
+		memcpy( (void*)&server_address.sin_addr, (void*)&addr, sizeof(addr) );
+	}
+#endif
+
+	// Increase the socket rx buffer size to maximum -- this is UDP
+	rxsockbufsz = 240 * 1024;
+	if( setsockopt( socket_server_fd, SOL_SOCKET, SO_RCVBUF, &rxsockbufsz, sizeof(rxsockbufsz))) {
+		mp_msg(MSGT_NETWORK,MSGL_ERR,"Couldn't set receive socket buffer size\n");
+	}
+
+	if((ntohl(server_address.sin_addr.s_addr) >> 28) == 0xe) {
+		mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr;
+		//mcast.imr_interface.s_addr = inet_addr("10.1.1.2");
+		mcast.imr_interface.s_addr = 0;
+		if( setsockopt( socket_server_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))) {
+			mp_msg(MSGT_NETWORK,MSGL_ERR,"IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n");
+			goto err_out;
+		}
+	}
+
+	tv.tv_sec = 0;
+	tv.tv_usec = (1 * 1000000);	// 1 second timeout
+	FD_ZERO( &set );
+	FD_SET( socket_server_fd, &set );
+	err = select(socket_server_fd+1, &set, NULL, NULL, &tv);
+	if (err < 0) {
+	  mp_msg(MSGT_NETWORK, MSGL_FATAL, "Select failed: %s\n", strerror(errno));
+	  goto err_out;
+	}
+	if (err == 0) {
+	  mp_msg(MSGT_NETWORK,MSGL_ERR,"Timeout! No data from host %s\n", url->hostname );
+	  goto err_out;
+	}
+		err_len = sizeof( err );
+		getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len );
+		if( err ) {
+			mp_msg(MSGT_NETWORK,MSGL_DBG2,"Socket error: %d\n", err );
+			goto err_out;
+		}
+	return socket_server_fd;
+
+err_out:
+  closesocket(socket_server_fd);
+  return -1;	
+}
+
+static int rtp_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) {
+	return read_rtp_from_server( fd, buffer, size );
+}
+
+static int rtp_streaming_start( stream_t *stream, int raw_udp ) {
+	streaming_ctrl_t *streaming_ctrl;
+	int fd;
+
+	if( stream==NULL ) return -1;
+	streaming_ctrl = stream->streaming_ctrl;
+	fd = stream->fd;
+	
+	if( fd<0 ) {
+		fd = rtp_open_socket( (streaming_ctrl->url) ); 
+		if( fd<0 ) return -1;
+		stream->fd = fd;
+	}
+
+	if(raw_udp)
+		streaming_ctrl->streaming_read = nop_streaming_read;
+	else
+		streaming_ctrl->streaming_read = rtp_streaming_read;
+	streaming_ctrl->streaming_seek = nop_streaming_seek;
+	streaming_ctrl->prebuffer_size = 64*1024;	// 64 KBytes	
+	streaming_ctrl->buffering = 0;
+	streaming_ctrl->status = streaming_playing_e;
+	return 0;
+}
+
+
+static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) {
+  static char buf[1600];
+  unsigned int intP;
+  char* charP = (char*) &intP;
+  int headerSize;
+  int lengthPacket;
+  lengthPacket=recv(fd,buf,1590,0);
+  if (lengthPacket<0)
+    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp: socket read error\n");
+  else if (lengthPacket<12)
+    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp: packet too small (%d) to be an rtp frame (>12bytes)\n", lengthPacket);
+  if(lengthPacket<12) {
+    *lengthData = 0;
+    return 0;
+  }
+  rh->b.v  = (unsigned int) ((buf[0]>>6)&0x03);
+  rh->b.p  = (unsigned int) ((buf[0]>>5)&0x01);
+  rh->b.x  = (unsigned int) ((buf[0]>>4)&0x01);
+  rh->b.cc = (unsigned int) ((buf[0]>>0)&0x0f);
+  rh->b.m  = (unsigned int) ((buf[1]>>7)&0x01);
+  rh->b.pt = (unsigned int) ((buf[1]>>0)&0x7f);
+  intP = 0;
+  memcpy(charP+2,&buf[2],2);
+  rh->b.sequence = ntohl(intP);
+  intP = 0;
+  memcpy(charP,&buf[4],4);
+  rh->timestamp = ntohl(intP);
+
+  headerSize = 12 + 4*rh->b.cc; /* in bytes */
+
+  *lengthData = lengthPacket - headerSize;
+  *data = (char*) buf + headerSize;
+
+  //  mp_msg(MSGT_NETWORK,MSGL_DBG2,"Reading rtp: v=%x p=%x x=%x cc=%x m=%x pt=%x seq=%x ts=%x lgth=%d\n",rh->b.v,rh->b.p,rh->b.x,rh->b.cc,rh->b.m,rh->b.pt,rh->b.sequence,rh->timestamp,lengthPacket);
+
+  return(0);
+}
+
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  URL_t *url;
+  int udp = 0;
+
+  mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_RTP, URL: %s\n", stream->url);
+  stream->streaming_ctrl = streaming_ctrl_new();
+  if( stream->streaming_ctrl==NULL ) {
+    return STREAM_ERROR;
+  }
+  stream->streaming_ctrl->bandwidth = network_bandwidth;
+  url = url_new(stream->url);
+  stream->streaming_ctrl->url = check4proxies(url);
+
+  if( url->port==0 ) {
+    mp_msg(MSGT_NETWORK,MSGL_ERR,"You must enter a port number for RTP and UDP streams!\n");
+    goto fail;
+  }
+  if(!strncmp(stream->url, "udp", 3))
+    udp = 1;
+
+  if(rtp_streaming_start(stream, udp) < 0) {
+    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp_streaming_start(rtp) failed\n");
+    goto fail;
+  }
+
+  stream->type = STREAMTYPE_STREAM;
+  fixup_network_stream_cache(stream);
+  return STREAM_OK;
+
+fail:
+  streaming_ctrl_free( stream->streaming_ctrl );
+  stream->streaming_ctrl = NULL;
+  return STREAM_UNSUPORTED;
+}
+
+
+stream_info_t stream_info_rtp_udp = {
+  "mpeg rtp and upd streaming",
+  "rtp and udp",
+  "Dave Chapman",
+  "native rtp support",
+  open_s,
+  {"rtp", "udp", NULL},
+  NULL,
+  0 // Urls are an option string
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/rtp.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,38 @@
+/* Imported from the dvbstream project
+ *
+ * Modified for use with MPlayer, for details see the changelog at
+ * http://svn.mplayerhq.hu/mplayer/trunk/
+ * $Id$
+ */
+
+#ifndef _RTP_H
+#define _RTP_H
+
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#include <sys/socket.h>
+#else
+#include <winsock2.h>
+#endif
+
+struct rtpbits {
+  unsigned int v:2;           /* version: 2 */
+  unsigned int p:1;           /* is there padding appended: 0 */
+  unsigned int x:1;           /* number of extension headers: 0 */
+  unsigned int cc:4;          /* number of CSRC identifiers: 0 */
+  unsigned int m:1;           /* marker: 0 */
+  unsigned int pt:7;          /* payload type: 33 for MPEG2 TS - RFC 1890 */
+  unsigned int sequence:16;   /* sequence number: random */
+};
+
+struct rtpheader {	/* in network byte order */
+  struct rtpbits b;
+  int timestamp;	/* start: random */
+  int ssrc;		/* random */
+};
+
+
+static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData);
+int read_rtp_from_server(int fd, char *buffer, int length);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,434 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef __MINGW32__
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#endif
+#include <fcntl.h>
+#include <signal.h>
+#include <strings.h>
+
+#include "config.h"
+
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#else
+#include <winsock2.h>
+#endif
+
+#include "mp_msg.h"
+#include "help_mp.h"
+#include "osdep/shmem.h"
+
+#include "stream.h"
+#include "demuxer.h"
+
+#include "m_option.h"
+#include "m_struct.h"
+
+
+void cache_uninit(stream_t *s); // defined in cache2.c
+
+//#include "vcd_read_bincue.h"
+
+#ifdef HAVE_VCD
+extern stream_info_t stream_info_vcd;
+#endif
+#ifdef HAVE_CDDA
+extern stream_info_t stream_info_cdda;
+#endif
+#ifdef MPLAYER_NETWORK
+extern stream_info_t stream_info_netstream;
+extern stream_info_t stream_info_pnm;
+extern stream_info_t stream_info_asf;
+extern stream_info_t stream_info_rtsp;
+extern stream_info_t stream_info_rtp_udp;
+extern stream_info_t stream_info_http1;
+extern stream_info_t stream_info_http2;
+#endif
+#ifdef HAS_DVBIN_SUPPORT
+extern stream_info_t stream_info_dvb;
+#endif
+#ifdef HAVE_PVR
+extern stream_info_t stream_info_pvr;
+#endif
+#ifdef HAVE_FTP
+extern stream_info_t stream_info_ftp;
+#endif
+#ifdef HAVE_VSTREAM
+extern stream_info_t stream_info_vstream;
+#endif
+#ifdef USE_DVDNAV
+extern stream_info_t stream_info_dvdnav;
+#endif
+#ifdef LIBSMBCLIENT
+extern stream_info_t stream_info_smb;
+#endif
+#ifdef STREAMING_LIVE555
+extern stream_info_t stream_info_sdp;
+extern stream_info_t stream_info_rtsp_sip;
+#endif
+
+extern stream_info_t stream_info_cue;
+extern stream_info_t stream_info_null;
+extern stream_info_t stream_info_file;
+#ifdef HAVE_DVD
+extern stream_info_t stream_info_dvd;
+#endif
+
+stream_info_t* auto_open_streams[] = {
+#ifdef HAVE_VCD
+  &stream_info_vcd,
+#endif
+#ifdef HAVE_CDDA
+  &stream_info_cdda,
+#endif
+#ifdef MPLAYER_NETWORK
+  &stream_info_netstream,
+  &stream_info_http1,
+  &stream_info_asf,
+  &stream_info_pnm,
+  &stream_info_rtsp,
+#ifdef STREAMING_LIVE555
+  &stream_info_sdp,
+  &stream_info_rtsp_sip,
+#endif
+  &stream_info_rtp_udp,
+  &stream_info_http2,
+#endif
+#ifdef HAS_DVBIN_SUPPORT
+  &stream_info_dvb,
+#endif
+#ifdef HAVE_PVR
+  &stream_info_pvr,
+#endif
+#ifdef HAVE_FTP
+  &stream_info_ftp,
+#endif
+#ifdef HAVE_VSTREAM
+  &stream_info_vstream,
+#endif
+#ifdef LIBSMBCLIENT
+  &stream_info_smb,
+#endif
+  &stream_info_cue,
+#ifdef HAVE_DVD
+  &stream_info_dvd,
+#endif
+#ifdef USE_DVDNAV
+  &stream_info_dvdnav,
+#endif
+
+  &stream_info_null,
+  &stream_info_file,
+  NULL
+};
+
+stream_t* open_stream_plugin(stream_info_t* sinfo,char* filename,int mode,
+			     char** options, int* file_format, int* ret) {
+  void* arg = NULL;
+  stream_t* s;
+  m_struct_t* desc = (m_struct_t*)sinfo->opts;
+
+  // Parse options
+  if(desc) {
+    arg = m_struct_alloc(desc);
+    if(sinfo->opts_url) {
+      m_option_t url_opt = 
+	{ "stream url", arg , CONF_TYPE_CUSTOM_URL, 0, 0 ,0, sinfo->opts };
+      if(m_option_parse(&url_opt,"stream url",filename,arg,M_CONFIG_FILE) < 0) {
+	mp_msg(MSGT_OPEN,MSGL_ERR, "URL parsing failed on url %s\n",filename);
+	m_struct_free(desc,arg);
+	return NULL;
+      }	
+    }
+    if(options) {
+      int i;
+      for(i = 0 ; options[i] != NULL ; i += 2) {
+	mp_msg(MSGT_OPEN,MSGL_DBG2, "Set stream arg %s=%s\n",
+	       options[i],options[i+1]);
+	if(!m_struct_set(desc,arg,options[i],options[i+1]))
+	  mp_msg(MSGT_OPEN,MSGL_WARN, "Failed to set stream option %s=%s\n",
+		 options[i],options[i+1]);
+      }
+    }
+  }
+  s = new_stream(-2,-2);
+  s->url=strdup(filename);
+  s->flags |= mode;
+  *ret = sinfo->open(s,mode,arg,file_format);
+  if((*ret) != STREAM_OK) {
+    free(s->url);
+    free(s);
+    return NULL;
+  }
+  if(s->type <= -2)
+    mp_msg(MSGT_OPEN,MSGL_WARN, "Warning streams need a type !!!!\n");
+  if(s->flags & STREAM_SEEK && !s->seek)
+    s->flags &= ~STREAM_SEEK;
+  if(s->seek && !(s->flags & STREAM_SEEK))
+    s->flags |= STREAM_SEEK;
+  
+
+  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: [%s] %s\n",sinfo->name,filename);
+  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Description: %s\n",sinfo->info);
+  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Author: %s\n", sinfo->author);
+  mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Comment: %s\n", sinfo->comment);
+  
+  return s;
+}
+
+
+stream_t* open_stream_full(char* filename,int mode, char** options, int* file_format) {
+  int i,j,l,r;
+  stream_info_t* sinfo;
+  stream_t* s;
+
+  for(i = 0 ; auto_open_streams[i] ; i++) {
+    sinfo = auto_open_streams[i];
+    if(!sinfo->protocols) {
+      mp_msg(MSGT_OPEN,MSGL_WARN, "Stream type %s has protocols == NULL, it's a bug\n", sinfo->name);
+      continue;
+    }
+    for(j = 0 ; sinfo->protocols[j] ; j++) {
+      l = strlen(sinfo->protocols[j]);
+      // l == 0 => Don't do protocol matching (ie network and filenames)
+      if((l == 0) || ((strncmp(sinfo->protocols[j],filename,l) == 0) &&
+		      (strncmp("://",filename+l,3) == 0))) {
+	*file_format = DEMUXER_TYPE_UNKNOWN;
+	s = open_stream_plugin(sinfo,filename,mode,options,file_format,&r);
+	if(s) return s;
+	if(r != STREAM_UNSUPORTED) {
+	  mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_FailedToOpen,filename);
+	  return NULL;
+	}
+	break;
+      }
+    }
+  }
+
+  mp_msg(MSGT_OPEN,MSGL_ERR, "No stream found to handle url %s\n",filename);
+  return NULL;
+}
+
+//=================== STREAMER =========================
+
+int stream_fill_buffer(stream_t *s){
+  int len;
+  if (/*s->fd == NULL ||*/ s->eof) { s->buf_pos = s->buf_len = 0; return 0; }
+  switch(s->type){
+  case STREAMTYPE_STREAM:
+#ifdef MPLAYER_NETWORK
+    if( s->streaming_ctrl!=NULL ) {
+	    len=s->streaming_ctrl->streaming_read(s->fd,s->buffer,STREAM_BUFFER_SIZE, s->streaming_ctrl);break;
+    } else {
+      len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break;
+    }
+#else
+    len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break;
+#endif
+  case STREAMTYPE_DS:
+    len = demux_read_data((demux_stream_t*)s->priv,s->buffer,STREAM_BUFFER_SIZE);
+    break;
+  
+    
+  default: 
+    len= s->fill_buffer ? s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE) : 0;
+  }
+  if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
+  s->buf_pos=0;
+  s->buf_len=len;
+  s->pos+=len;
+//  printf("[%d]",len);fflush(stdout);
+  return len;
+}
+
+int stream_seek_long(stream_t *s,off_t pos){
+off_t newpos=0;
+
+//  if( mp_msg_test(MSGT_STREAM,MSGL_DBG3) ) printf("seek_long to 0x%X\n",(unsigned int)pos);
+
+  s->buf_pos=s->buf_len=0;
+
+  switch(s->type){
+  case STREAMTYPE_STREAM:
+#ifdef _LARGEFILE_SOURCE
+    newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break;
+#else
+    newpos=pos&(~(STREAM_BUFFER_SIZE-1));break;
+#endif
+  default:
+    // Round on sector size
+    if(s->sector_size)
+      newpos=(pos/s->sector_size)*s->sector_size;
+    else { // Otherwise on the buffer size
+#ifdef _LARGEFILE_SOURCE
+      newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break;
+#else
+      newpos=pos&(~(STREAM_BUFFER_SIZE-1));break;
+#endif
+    }
+    break;
+  }
+
+if( mp_msg_test(MSGT_STREAM,MSGL_DBG3) ){
+  mp_msg(MSGT_STREAM,MSGL_DBG3, "s->pos=%"PRIX64"  newpos=%"PRIX64"  new_bufpos=%"PRIX64"  buflen=%X  \n",
+    (int64_t)s->pos,(int64_t)newpos,(int64_t)pos,s->buf_len);
+}
+  pos-=newpos;
+
+if(newpos==0 || newpos!=s->pos){
+  switch(s->type){
+  case STREAMTYPE_STREAM:
+    //s->pos=newpos; // real seek
+    // Some streaming protocol allow to seek backward and forward
+    // A function call that return -1 can tell that the protocol
+    // doesn't support seeking.
+#ifdef MPLAYER_NETWORK
+    if(s->seek) { // new stream seek is much cleaner than streaming_ctrl one
+      if(!s->seek(s,newpos)) {
+      	mp_msg(MSGT_STREAM,MSGL_ERR, "Seek failed\n");
+      	return 0;
+      }
+      break;
+    }
+	
+    if( s->streaming_ctrl!=NULL && s->streaming_ctrl->streaming_seek ) {
+      if( s->streaming_ctrl->streaming_seek( s->fd, pos, s->streaming_ctrl )<0 ) {
+        mp_msg(MSGT_STREAM,MSGL_INFO,"Stream not seekable!\n");
+        return 1;
+      }
+    } 
+#else
+    if(newpos<s->pos){
+      mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n");
+      return 1;
+    }
+    while(s->pos<newpos){
+      if(stream_fill_buffer(s)<=0) break; // EOF
+    }
+#endif
+    break;
+  default:
+    // This should at the beginning as soon as all streams are converted
+    if(!s->seek)
+      return 0;
+    // Now seek
+    if(!s->seek(s,newpos)) {
+      mp_msg(MSGT_STREAM,MSGL_ERR, "Seek failed\n");
+      return 0;
+    }
+  }
+//   putchar('.');fflush(stdout);
+//} else {
+//   putchar('%');fflush(stdout);
+}
+
+while(stream_fill_buffer(s) > 0 && pos >= 0) {
+  if(pos<=s->buf_len){
+    s->buf_pos=pos; // byte position in sector
+    return 1;
+  }
+  pos -= s->buf_len;
+}
+  
+//  if(pos==s->buf_len) printf("XXX Seek to last byte of file -> EOF\n");
+  
+  mp_msg(MSGT_STREAM,MSGL_V,"stream_seek: WARNING! Can't seek to 0x%"PRIX64" !\n",(int64_t)(pos+newpos));
+  return 0;
+}
+
+
+void stream_reset(stream_t *s){
+  if(s->eof){
+    s->pos=0; //ftell(f);
+//    s->buf_pos=s->buf_len=0;
+    s->eof=0;
+  }
+  if(s->control) s->control(s,STREAM_CTRL_RESET,NULL);
+  //stream_seek(s,0);
+}
+
+int stream_control(stream_t *s, int cmd, void *arg){
+  if(!s->control) return STREAM_UNSUPORTED;
+  return s->control(s, cmd, arg);
+}
+
+stream_t* new_memory_stream(unsigned char* data,int len){
+  stream_t *s;
+
+  if(len < 0)
+    return NULL;
+  s=malloc(sizeof(stream_t)+len);
+  memset(s,0,sizeof(stream_t));
+  s->fd=-1;
+  s->type=STREAMTYPE_MEMORY;
+  s->buf_pos=0; s->buf_len=len;
+  s->start_pos=0; s->end_pos=len;
+  stream_reset(s);
+  s->pos=len;
+  memcpy(s->buffer,data,len);
+  return s;
+}
+
+stream_t* new_stream(int fd,int type){
+  stream_t *s=malloc(sizeof(stream_t));
+  if(s==NULL) return NULL;
+  memset(s,0,sizeof(stream_t));
+
+#ifdef HAVE_WINSOCK2
+  {
+    WSADATA wsdata;
+    int temp = WSAStartup(0x0202, &wsdata); // there might be a better place for this (-> later)
+    mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 init: %i\n", temp);
+  }
+#endif
+  
+  s->fd=fd;
+  s->type=type;
+  s->buf_pos=s->buf_len=0;
+  s->start_pos=s->end_pos=0;
+  s->priv=NULL;
+  s->url=NULL;
+  s->cache_pid=0;
+  stream_reset(s);
+  return s;
+}
+
+void free_stream(stream_t *s){
+//  printf("\n*** free_stream() called ***\n");
+#ifdef USE_STREAM_CACHE
+  if(s->cache_pid) {
+    cache_uninit(s);
+  }
+#endif
+  if(s->close) s->close(s);
+  if(s->fd>0){
+    /* on unix we define closesocket to close
+       on windows however we have to distinguish between
+       network socket and file */
+    if(s->url && strstr(s->url,"://"))
+      closesocket(s->fd);
+    else close(s->fd);
+  }
+#ifdef HAVE_WINSOCK2
+  mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 uninit\n");
+  WSACleanup(); // there might be a better place for this (-> later)
+#endif
+  // Disabled atm, i don't like that. s->priv can be anything after all
+  // streams should destroy their priv on close
+  //if(s->priv) free(s->priv);
+  if(s->url) free(s->url);
+  free(s);
+}
+
+stream_t* new_ds_stream(demux_stream_t *ds) {
+  stream_t* s = new_stream(-1,STREAMTYPE_DS);
+  s->priv = ds;
+  return s;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,301 @@
+#ifndef __STREAM_H
+#define __STREAM_H
+
+#include "mp_msg.h"
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+#define STREAMTYPE_DUMMY -1    // for placeholders, when the actual reading is handled in the demuxer
+#define STREAMTYPE_FILE 0      // read from seekable file
+#define STREAMTYPE_VCD  1      // raw mode-2 CDROM reading, 2324 bytes/sector
+#define STREAMTYPE_STREAM 2    // same as FILE but no seeking (for net/stdin)
+#define STREAMTYPE_DVD  3      // libdvdread
+#define STREAMTYPE_MEMORY  4   // read data from memory area
+#define STREAMTYPE_PLAYLIST 6  // FIXME!!! same as STREAMTYPE_FILE now
+#define STREAMTYPE_DS   8      // read from a demuxer stream
+#define STREAMTYPE_DVDNAV 9    // we cannot safely "seek" in this...
+#define STREAMTYPE_CDDA 10     // raw audio CD reader
+#define STREAMTYPE_SMB 11      // smb:// url, using libsmbclient (samba)
+#define STREAMTYPE_VCDBINCUE 12      // vcd directly from bin/cue files
+#define STREAMTYPE_DVB 13
+#define STREAMTYPE_VSTREAM 14
+#define STREAMTYPE_SDP 15
+#define STREAMTYPE_PVR 16
+
+#define STREAM_BUFFER_SIZE 2048
+
+#define VCD_SECTOR_SIZE 2352
+#define VCD_SECTOR_OFFS 24
+#define VCD_SECTOR_DATA 2324
+
+/// atm it will always use mode == STREAM_READ
+/// streams that use the new api should check the mode at open
+#define STREAM_READ  0
+#define STREAM_WRITE 1
+/// Seek flags, if not mannualy set and s->seek isn't NULL
+/// STREAM_SEEK is automaticly set
+#define STREAM_SEEK_BW  2
+#define STREAM_SEEK_FW  4
+#define STREAM_SEEK  (STREAM_SEEK_BW|STREAM_SEEK_FW)
+
+//////////// Open return code
+/// This can't open the requested protocol (used by stream wich have a
+/// * protocol when they don't know the requested protocol)
+#define STREAM_UNSUPORTED -1
+#define STREAM_ERROR 0
+#define STREAM_OK    1
+
+#define MAX_STREAM_PROTOCOLS 10
+
+#define STREAM_CTRL_RESET 0
+#define STREAM_CTRL_GET_TIME_LENGTH 1
+
+#ifdef MPLAYER_NETWORK
+#include "network.h"
+#endif
+
+struct stream_st;
+typedef struct stream_info_st {
+  const char *info;
+  const char *name;
+  const char *author;
+  const char *comment;
+  /// mode isn't used atm (ie always READ) but it shouldn't be ignored
+  /// opts is at least in it's defaults settings and may have been
+  /// altered by url parsing if enabled and the options string parsing.
+  int (*open)(struct stream_st* st, int mode, void* opts, int* file_format);
+  char* protocols[MAX_STREAM_PROTOCOLS];
+  void* opts;
+  int opts_url; /* If this is 1 we will parse the url as an option string
+		 * too. Otherwise options are only parsed from the
+		 * options string given to open_stream_plugin */
+} stream_info_t;
+
+typedef struct stream_st {
+  // Read
+  int (*fill_buffer)(struct stream_st *s, char* buffer, int max_len);
+  // Write
+  int (*write_buffer)(struct stream_st *s, char* buffer, int len);
+  // Seek
+  int (*seek)(struct stream_st *s,off_t pos);
+  // Control
+  // Will be later used to let streams like dvd and cdda report
+  // their structure (ie tracks, chapters, etc)
+  int (*control)(struct stream_st *s,int cmd,void* arg);
+  // Close
+  void (*close)(struct stream_st *s);
+
+  int fd;   // file descriptor, see man open(2)
+  int type; // see STREAMTYPE_*
+  int flags;
+  int sector_size; // sector size (seek will be aligned on this size if non 0)
+  unsigned int buf_pos,buf_len;
+  off_t pos,start_pos,end_pos;
+  int eof;
+  unsigned int cache_pid;
+  void* cache_data;
+  void* priv; // used for DVD, TV, RTSP etc
+  char* url;  // strdup() of filename/url
+#ifdef MPLAYER_NETWORK
+  streaming_ctrl_t *streaming_ctrl;
+#endif
+  unsigned char buffer[STREAM_BUFFER_SIZE>VCD_SECTOR_SIZE?STREAM_BUFFER_SIZE:VCD_SECTOR_SIZE];
+} stream_t;
+
+#ifdef USE_STREAM_CACHE
+int stream_enable_cache(stream_t *stream,int size,int min,int prefill);
+int cache_stream_fill_buffer(stream_t *s);
+int cache_stream_seek_long(stream_t *s,off_t pos);
+#else
+// no cache, define wrappers:
+#define cache_stream_fill_buffer(x) stream_fill_buffer(x)
+#define cache_stream_seek_long(x,y) stream_seek_long(x,y)
+#define stream_enable_cache(x,y,z,w) 1
+#endif
+void fixup_network_stream_cache(stream_t *stream);
+
+inline static int stream_read_char(stream_t *s){
+  return (s->buf_pos<s->buf_len)?s->buffer[s->buf_pos++]:
+    (cache_stream_fill_buffer(s)?s->buffer[s->buf_pos++]:-256);
+//  if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++];
+//  stream_fill_buffer(s);
+//  if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++];
+//  return 0; // EOF
+}
+
+inline static unsigned int stream_read_word(stream_t *s){
+  int x,y;
+  x=stream_read_char(s);
+  y=stream_read_char(s);
+  return (x<<8)|y;
+}
+
+inline static unsigned int stream_read_dword(stream_t *s){
+  unsigned int y;
+  y=stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  return y;
+}
+
+#define stream_read_fourcc stream_read_dword_le
+
+inline static unsigned int stream_read_word_le(stream_t *s){
+  int x,y;
+  x=stream_read_char(s);
+  y=stream_read_char(s);
+  return (y<<8)|x;
+}
+
+inline static unsigned int stream_read_dword_le(stream_t *s){
+  unsigned int y;
+  y=stream_read_char(s);
+  y|=stream_read_char(s)<<8;
+  y|=stream_read_char(s)<<16;
+  y|=stream_read_char(s)<<24;
+  return y;
+}
+
+inline static uint64_t stream_read_qword(stream_t *s){
+  uint64_t y;
+  y = stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  return y;
+}
+
+inline static uint64_t stream_read_qword_le(stream_t *s){
+  uint64_t y;
+  y = stream_read_char(s);
+  y|=stream_read_char(s)<<8;
+  y|=stream_read_char(s)<<16;
+  y|=stream_read_char(s)<<24;
+  y|=(uint64_t)stream_read_char(s)<<32;
+  y|=(uint64_t)stream_read_char(s)<<40;
+  y|=(uint64_t)stream_read_char(s)<<48;
+  y|=(uint64_t)stream_read_char(s)<<56;
+  return y;
+}
+
+inline static unsigned int stream_read_int24(stream_t *s){
+  unsigned int y;
+  y = stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  y=(y<<8)|stream_read_char(s);
+  return y;
+}
+
+inline static int stream_read(stream_t *s,char* mem,int total){
+  int len=total;
+  while(len>0){
+    int x;
+    x=s->buf_len-s->buf_pos;
+    if(x==0){
+      if(!cache_stream_fill_buffer(s)) return total-len; // EOF
+      x=s->buf_len-s->buf_pos;
+    }
+    if(s->buf_pos>s->buf_len) mp_msg(MSGT_DEMUX, MSGL_WARN, "stream_read: WARNING! s->buf_pos>s->buf_len\n");
+    if(x>len) x=len;
+    memcpy(mem,&s->buffer[s->buf_pos],x);
+    s->buf_pos+=x; mem+=x; len-=x;
+  }
+  return total;
+}
+
+inline static unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max) {
+  int len;
+  unsigned char* end,*ptr = mem;;
+  do {
+    len = s->buf_len-s->buf_pos;
+    // try to fill the buffer
+    if(len <= 0 &&
+       (!cache_stream_fill_buffer(s) || 
+        (len = s->buf_len-s->buf_pos) <= 0)) break;
+    end = (unsigned char*) memchr((void*)(s->buffer+s->buf_pos),'\n',len);
+    if(end) len = end - (s->buffer+s->buf_pos) + 1;
+    if(len > 0 && max > 1) {
+      int l = len > max-1 ? max-1 : len;
+      memcpy(ptr,s->buffer+s->buf_pos,l);
+      max -= l;
+      ptr += l;
+    }
+    s->buf_pos += len;
+  } while(!end);
+  if(s->eof && ptr == mem) return NULL;
+  if(max > 0) ptr[0] = 0;
+  return mem;
+}
+
+
+inline static int stream_eof(stream_t *s){
+  return s->eof;
+}
+
+inline static off_t stream_tell(stream_t *s){
+  return s->pos+s->buf_pos-s->buf_len;
+}
+
+inline static int stream_seek(stream_t *s,off_t pos){
+
+  mp_dbg(MSGT_DEMUX, MSGL_DBG3, "seek to 0x%qX\n",(long long)pos);
+
+  if(pos<s->pos){
+    off_t x=pos-(s->pos-s->buf_len);
+    if(x>=0){
+      s->buf_pos=x;
+//      putchar('*');fflush(stdout);
+      return 1;
+    }
+  }
+  
+  return cache_stream_seek_long(s,pos);
+}
+
+inline static int stream_skip(stream_t *s,off_t len){
+  if( (len<0 && (s->flags & STREAM_SEEK_BW)) || (len>2*STREAM_BUFFER_SIZE && (s->flags & STREAM_SEEK_FW)) ) {
+    // negative or big skip!
+    return stream_seek(s,stream_tell(s)+len);
+  }
+  while(len>0){
+    int x=s->buf_len-s->buf_pos;
+    if(x==0){
+      if(!cache_stream_fill_buffer(s)) return 0; // EOF
+      x=s->buf_len-s->buf_pos;
+    }
+    if(x>len) x=len;
+    //memcpy(mem,&s->buf[s->buf_pos],x);
+    s->buf_pos+=x; len-=x;
+  }
+  return 1;
+}
+
+void stream_reset(stream_t *s);
+int stream_control(stream_t *s, int cmd, void *arg);
+stream_t* new_stream(int fd,int type);
+void free_stream(stream_t *s);
+stream_t* new_memory_stream(unsigned char* data,int len);
+stream_t* open_stream(char* filename,char** options,int* file_format);
+stream_t* open_stream_full(char* filename,int mode, char** options, int* file_format);
+
+extern int dvd_title;
+extern int dvd_chapter;
+extern int dvd_last_chapter;
+extern int dvd_angle;
+
+extern char * audio_stream;
+
+typedef struct {
+ int id; // 0 - 31 mpeg; 128 - 159 ac3; 160 - 191 pcm
+ int language; 
+ int type;
+ int channels;
+} stream_language_t;
+
+#endif // __STREAM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_dvd.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,851 @@
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifdef __FreeBSD__
+#include <sys/cdrio.h>
+#endif
+
+#define FIRST_AC3_AID 128
+#define FIRST_DTS_AID 136
+#define FIRST_MPG_AID 0
+#define FIRST_PCM_AID 160
+
+#include "stream.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+#include "stream_dvd.h"
+
+/// We keep these 2 for the gui atm, but they will be removed.
+extern int dvd_title;
+extern int dvd_chapter;
+extern int dvd_last_chapter;
+extern char* dvd_device;
+int dvd_angle=1;
+
+#ifdef USE_DVDREAD
+#define	LIBDVDREAD_VERSION(maj,min,micro)	((maj)*10000 + (min)*100 + (micro))
+/*
+ * Try to autodetect the libdvd-0.9.0 library
+ * (0.9.0 removed the <dvdread/dvd_udf.h> header, and moved the two defines
+ * DVD_VIDEO_LB_LEN and MAX_UDF_FILE_NAME_LEN from it to
+ * <dvdread/dvd_reader.h>)
+ */
+#ifndef DVDREAD_VERSION
+#if defined(DVD_VIDEO_LB_LEN) && defined(MAX_UDF_FILE_NAME_LEN)
+#define	DVDREAD_VERSION	LIBDVDREAD_VERSION(0,9,0)
+#else
+#define	DVDREAD_VERSION	LIBDVDREAD_VERSION(0,8,0)
+#endif
+#endif
+
+char * dvd_audio_stream_types[8] = { "ac3","unknown","mpeg1","mpeg2ext","lpcm","unknown","dts" };
+char * dvd_audio_stream_channels[6] = { "mono", "stereo", "unknown", "unknown", "5.1/6.1", "5.1" };
+#endif /* #ifdef USE_DVDREAD */
+
+
+static struct stream_priv_s {
+  int title;
+} stream_priv_dflts = {
+  1
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  { "hostname", ST_OFF(title), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "dvd",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+int dvd_parse_chapter_range(m_option_t *conf, const char *range) {
+  const char *s;
+  char *t;
+  if (!range)
+    return M_OPT_MISSING_PARAM;
+  s = range;
+  dvd_chapter = 1;
+  dvd_last_chapter = 0;
+  if(*range && isdigit(*range)) {
+    dvd_chapter = strtol(range, &s, 10);
+    if(range == s) {
+      mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
+      return M_OPT_INVALID;
+    }
+  }
+  if(*s == 0)
+    return 0;
+  else if(*s != '-') {
+    mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
+    return M_OPT_INVALID;
+  }
+  ++s;
+  if(*s == 0)
+      return 0;
+  if(! isdigit(*s)) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
+    return M_OPT_INVALID;
+  }
+  dvd_last_chapter = strtol(s, &t, 10);
+  if (s == t || *t) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_DVDinvalidChapterRange, range);
+    return M_OPT_INVALID;
+  }
+  return 0;
+}
+
+#ifdef USE_DVDREAD
+int dvd_chapter_from_cell(dvd_priv_t* dvd,int title,int cell)
+{
+  pgc_t * cur_pgc;
+  ptt_info_t* ptt;
+  int chapter = cell;
+  int pgc_id,pgn;
+  if(title < 0 || cell < 0){
+    return 0;
+  }
+  /* for most DVD's chapter == cell */
+  /* but there are more complecated cases... */
+  if(chapter >= dvd->vmg_file->tt_srpt->title[title].nr_of_ptts) {
+    chapter = dvd->vmg_file->tt_srpt->title[title].nr_of_ptts-1;
+  }
+  title = dvd->tt_srpt->title[title].vts_ttn-1;
+  ptt = dvd->vts_file->vts_ptt_srpt->title[title].ptt;
+  while(chapter >= 0) {
+    pgc_id = ptt[chapter].pgcn;
+    pgn = ptt[chapter].pgn;
+    cur_pgc = dvd->vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
+    if(cell >= cur_pgc->program_map[pgn-1]-1) {
+      return chapter;
+    }
+    --chapter;
+  }
+  /* didn't find a chapter ??? */
+  return chapter;
+}
+
+int dvd_aid_from_lang(stream_t *stream, unsigned char* lang) {
+  dvd_priv_t *d=stream->priv;
+  int code,i;
+  if(lang) {
+    while(strlen(lang)>=2) {
+      code=lang[1]|(lang[0]<<8);
+      for(i=0;i<d->nr_of_channels;i++) {
+        if(d->audio_streams[i].language==code) {
+          mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDaudioChannel,
+          d->audio_streams[i].id, lang[0],lang[1]);
+          return d->audio_streams[i].id;
+        }
+        //printf("%X != %X  (%c%c)\n",code,d->audio_streams[i].language,lang[0],lang[1]);
+      }
+      lang+=2; while (lang[0]==',' || lang[0]==' ') ++lang;
+    }
+    mp_msg(MSGT_OPEN,MSGL_WARN,MSGTR_DVDnoMatchingAudio);
+  }
+  return -1;
+}
+
+int dvd_number_of_subs(stream_t *stream) {
+  dvd_priv_t *d;
+  if (!stream) return -1;
+  d = stream->priv;
+  if (!d) return -1;
+  return d->nr_of_subtitles;
+}
+
+int dvd_lang_from_sid(stream_t *stream, int id) {
+  dvd_priv_t *d;
+  if (!stream) return 0;
+  d = stream->priv;
+  if (!d) return 0;
+  if (id >= d->nr_of_subtitles) return 0;
+  return d->subtitles[id].language;
+}
+
+int dvd_sid_from_lang(stream_t *stream, unsigned char* lang) {
+  dvd_priv_t *d=stream->priv;
+  int code,i;
+  while(lang && strlen(lang)>=2) {
+    code=lang[1]|(lang[0]<<8);
+    for(i=0;i<d->nr_of_subtitles;i++) {
+      if(d->subtitles[i].language==code) {
+        mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDsubtitleChannel, i, lang[0],lang[1]);
+        return i;
+      }
+    }
+    lang+=2; 
+    while (lang[0]==',' || lang[0]==' ') ++lang;
+  }
+  mp_msg(MSGT_OPEN,MSGL_WARN,MSGTR_DVDnoMatchingSubtitle);
+  return -1;
+}
+
+static int dvd_next_cell(dvd_priv_t *d) {
+  int next_cell=d->cur_cell;
+
+  mp_msg(MSGT_DVD,MSGL_DBG2, "dvd_next_cell: next1=0x%X  \n",next_cell);
+  if( d->cur_pgc->cell_playback[ next_cell ].block_type == BLOCK_TYPE_ANGLE_BLOCK ) {
+    while(next_cell<d->last_cell) {
+      if( d->cur_pgc->cell_playback[next_cell].block_mode == BLOCK_MODE_LAST_CELL )
+        break;
+      ++next_cell;
+    }
+  }
+  mp_msg(MSGT_DVD,MSGL_DBG2, "dvd_next_cell: next2=0x%X  \n",next_cell);
+
+  ++next_cell;
+  if(next_cell>=d->last_cell) 
+    return -1; // EOF
+  if(d->cur_pgc->cell_playback[next_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ) {
+    next_cell+=dvd_angle;
+    if(next_cell>=d->last_cell) 
+      return -1; // EOF
+  }
+  mp_msg(MSGT_DVD,MSGL_DBG2, "dvd_next_cell: next3=0x%X  \n",next_cell);
+  return next_cell;
+}
+
+int dvd_read_sector(dvd_priv_t *d,unsigned char* data) {
+  int len;
+
+  if(d->packs_left==0) {
+    /**
+     * 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.
+     *
+     * Otherwise, we set our next address past the end of this cell to
+     * force the code above to go to the next cell in the program.
+     */
+    if(d->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL) {
+       d->cur_pack= d->dsi_pack.dsi_gi.nv_pck_lbn + ( d->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+       mp_msg(MSGT_DVD,MSGL_DBG2, "Navi  new pos=0x%X  \n",d->cur_pack);
+    } else {
+      // end of cell! find next cell!
+      mp_msg(MSGT_DVD,MSGL_V, "--- END OF CELL !!! ---\n");
+      d->cur_pack=d->cell_last_pack+1;
+    }
+  }
+
+read_next:
+  if(d->cur_pack>d->cell_last_pack) {
+    // end of cell!
+    int next=dvd_next_cell(d);
+    if(next>=0) {
+      d->cur_cell=next;
+      // if( d->cur_pgc->cell_playback[d->cur_cell].block_type 
+      // == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle;
+      d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
+      d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
+      mp_msg(MSGT_DVD,MSGL_V, "DVD next cell: %d  pack: 0x%X-0x%X  \n",d->cur_cell,d->cur_pack,d->cell_last_pack);
+    } else 
+        return -1; // EOF
+  }
+
+  len = DVDReadBlocks(d->title, d->cur_pack, 1, data);
+  if(!len) return -1; //error
+
+  if(data[38]==0 && data[39]==0 && data[40]==1 && data[41]==0xBF &&
+    data[1024]==0 && data[1025]==0 && data[1026]==1 && data[1027]==0xBF) {
+       // found a Navi packet!!!
+#if DVDREAD_VERSION >= LIBDVDREAD_VERSION(0,9,0)
+    navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ]));
+#else
+    navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t));
+#endif
+    if(d->cur_pack != d->dsi_pack.dsi_gi.nv_pck_lbn ) {
+      mp_msg(MSGT_DVD,MSGL_V, "Invalid NAVI packet! lba=0x%X  navi=0x%X  \n",
+        d->cur_pack,d->dsi_pack.dsi_gi.nv_pck_lbn);
+    } else {
+      // process!
+      d->packs_left = d->dsi_pack.dsi_gi.vobu_ea;
+      mp_msg(MSGT_DVD,MSGL_DBG2, "Found NAVI packet! lba=0x%X  len=%d  \n",d->cur_pack,d->packs_left);
+      //navPrint_DSI(&d->dsi_pack);
+      mp_msg(MSGT_DVD,MSGL_DBG3,"\r### CELL %d: Navi: %d/%d  IFO: %d/%d   \n",d->cur_cell,
+        d->dsi_pack.dsi_gi.vobu_c_idn,d->dsi_pack.dsi_gi.vobu_vob_idn,
+        d->cur_pgc->cell_position[d->cur_cell].cell_nr,
+        d->cur_pgc->cell_position[d->cur_cell].vob_id_nr);
+
+      if(d->angle_seek) {
+        int i,skip=0;
+#if defined(__GNUC__) && ( defined(__sparc__) || defined(hpux) )
+        // workaround for a bug in the sparc/hpux version of gcc 2.95.X ... 3.2,
+        // it generates incorrect code for unaligned access to a packed
+        // structure member, resulting in an mplayer crash with a SIGBUS
+        // signal.
+        //
+        // See also gcc problem report PR c/7847:
+        // http://gcc.gnu.org/cgi-bin/gnatsweb.pl?database=gcc&cmd=view+audit-trail&pr=7847
+        for(i=0;i<9;i++) {	// check if all values zero:
+          typeof(d->dsi_pack.sml_agli.data[i].address) tmp_addr;
+          memcpy(&tmp_addr,&d->dsi_pack.sml_agli.data[i].address,sizeof(tmp_addr));
+          if((skip=tmp_addr)!=0) break;
+        }
+#else
+        for(i=0;i<9;i++)	// check if all values zero:
+          if((skip=d->dsi_pack.sml_agli.data[i].address)!=0) break;
+#endif
+        if(skip) {
+          // sml_agli table has valid data (at least one non-zero):
+         d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+
+         d->dsi_pack.sml_agli.data[dvd_angle].address;
+         d->angle_seek=0;
+         mp_msg(MSGT_DVD,MSGL_V, "Angle-seek synced using sml_agli map!  new_lba=0x%X  \n",d->cur_pack);
+        } else {
+          // check if we're in the right cell, jump otherwise:
+          if( (d->dsi_pack.dsi_gi.vobu_c_idn==d->cur_pgc->cell_position[d->cur_cell].cell_nr) &&
+            (d->dsi_pack.dsi_gi.vobu_vob_idn==d->cur_pgc->cell_position[d->cur_cell].vob_id_nr) ){
+            d->angle_seek=0;
+            mp_msg(MSGT_DVD,MSGL_V, "Angle-seek synced by cell/vob IDN search!  \n");
+          } else {
+            // wrong angle, skip this vobu:
+            d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+
+            d->dsi_pack.dsi_gi.vobu_ea;
+            d->angle_seek=2; // DEBUG
+          }
+        }
+      }
+    }
+    ++d->cur_pack;
+    goto read_next;
+  }
+
+  ++d->cur_pack;
+  if(d->packs_left>=0) --d->packs_left;
+
+  if(d->angle_seek) {
+    if(d->angle_seek==2) mp_msg(MSGT_DVD,MSGL_V, "!!! warning! reading packet while angle_seek !!!\n");
+    goto read_next; // searching for Navi packet
+  }
+
+  return d->cur_pack-1;
+}
+
+void dvd_seek(dvd_priv_t *d,int pos) {
+  d->packs_left=-1;
+  d->cur_pack=pos;
+
+  // check if we stay in current cell (speedup things, and avoid angle skip)
+  if(d->cur_pack>d->cell_last_pack ||
+     d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector) {
+
+    // ok, cell change, find the right cell!
+    d->cur_cell=0;
+    if(d->cur_pgc->cell_playback[d->cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
+      d->cur_cell+=dvd_angle;
+
+    while(1) {
+      int next;
+      d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
+      if(d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector) {
+        d->cur_pack=d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
+        break;
+      }
+      if(d->cur_pack<=d->cell_last_pack) break; // ok, we find it! :)
+      next=dvd_next_cell(d);
+      if(next<0) {
+        //d->cur_pack=d->cell_last_pack+1;
+        break; // we're after the last cell
+      }
+      d->cur_cell=next;
+    }
+  }
+
+  mp_msg(MSGT_DVD,MSGL_V, "DVD Seek! lba=0x%X  cell=%d  packs: 0x%X-0x%X  \n",
+    d->cur_pack,d->cur_cell,d->cur_pgc->cell_playback[ d->cur_cell ].first_sector,d->cell_last_pack);
+
+  // if we're in interleaved multi-angle cell, find the right angle chain!
+  // (read Navi block, and use the seamless angle jump table)
+  d->angle_seek=1;
+}
+
+void dvd_close(dvd_priv_t *d) {
+  ifoClose(d->vts_file);
+  ifoClose(d->vmg_file);
+  DVDCloseFile(d->title);
+  DVDClose(d->dvd);
+  dvd_chapter = 1;
+  dvd_last_chapter = 0;
+}
+
+#endif /* #ifdef USE_DVDREAD */
+
+static int fill_buffer(stream_t *s, char *but, int len)
+{
+#ifdef USE_DVDREAD
+  if(s->type == STREAMTYPE_DVD) {
+    off_t pos=dvd_read_sector(s->priv,s->buffer);
+    if(pos>=0) {
+      len=2048; // full sector
+      s->pos=2048*pos-len;
+    } else len=-1; // error
+  }
+#endif
+  return len;
+}
+
+static int seek(stream_t *s, off_t newpos) {
+#ifdef USE_DVDREAD
+  s->pos=newpos; // real seek
+  dvd_seek(s->priv,s->pos/2048);
+#endif
+  return 1;
+}
+
+static void stream_dvd_close(stream_t *s) {
+#ifdef USE_DVDREAD
+  dvd_close(s->priv);
+#endif
+}
+
+/** 
+\brief Converts DVD time structure to milliseconds.
+\param *dev the DVD time structure to convert
+\return returns the time in milliseconds
+*/
+static int dvdtimetomsec(dvd_time_t *dt)
+{
+  static int framerates[4] = {0, 2500, 0, 2997};
+  int framerate = framerates[(dt->frame_u & 0xc0) >> 6];
+  int msec = (((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f)) * 3600000;
+  msec += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60000;
+  msec += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000;
+  if(framerate > 0)
+    msec += (((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f)) * 100000 / framerate;
+  return msec;
+}
+
+static int mp_get_titleset_length(ifo_handle_t *vts_file, tt_srpt_t *tt_srpt, int title_no)
+{
+    int vts_ttn;  ///< title number within video title set
+    int pgc_no;   ///< program chain number
+    int msec;     ///< time length in milliseconds
+
+    msec=0;
+    if(!vts_file || !tt_srpt)
+        return 0;
+
+    if(vts_file->vtsi_mat && vts_file->vts_pgcit)
+    {
+            vts_ttn = tt_srpt->title[title_no].vts_ttn - 1;
+            pgc_no = vts_file->vts_ptt_srpt->title[vts_ttn].ptt[0].pgcn - 1;
+            msec = dvdtimetomsec(&vts_file->vts_pgcit->pgci_srp[pgc_no].pgc->playback_time);
+    }
+    return msec;
+}
+
+
+static int mp_describe_titleset(dvd_reader_t *dvd, tt_srpt_t *tt_srpt, int vts_no)
+{
+    ifo_handle_t *vts_file;
+    int title_no, msec=0;
+
+    vts_file = ifoOpen(dvd, vts_no);
+    if(!vts_file)
+        return 0;
+
+    if(!vts_file->vtsi_mat || !vts_file->vts_pgcit)
+    {
+        ifoClose(vts_file);
+        return 0;
+    }
+
+    for(title_no = 0; title_no < tt_srpt->nr_of_srpts; title_no++)
+    {
+        if (tt_srpt->title[title_no].title_set_nr != vts_no)
+            continue;
+        msec = mp_get_titleset_length(vts_file, tt_srpt, title_no);
+        mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_TITLE_%d_LENGTH=%d.%03d\n", title_no + 1, msec / 1000, msec % 1000);
+    }
+    ifoClose(vts_file);
+    return 1;
+}
+
+static int control(stream_t *stream,int cmd,void* arg) 
+{
+    switch(cmd) 
+    {
+        case STREAM_CTRL_GET_TIME_LENGTH:
+        {
+            dvd_priv_t *d = stream->priv;
+            *((unsigned int *)arg) = mp_get_titleset_length(d->vts_file, d->tt_srpt, d->cur_title-1);
+            return 1;
+        }
+    }
+    return STREAM_UNSUPORTED;
+}
+
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+  char *filename;
+
+  filename = strdup(stream->url);
+  mp_msg(MSGT_OPEN,MSGL_V,"URL: %s\n", filename);
+  dvd_title = p->title;
+#ifdef USE_DVDREAD
+  if(1){
+    //int ret,ret2;
+    dvd_priv_t *d;
+    int ttn,pgc_id,pgn;
+    dvd_reader_t *dvd;
+    dvd_file_t *title;
+    ifo_handle_t *vmg_file;
+    tt_srpt_t *tt_srpt;
+    ifo_handle_t *vts_file;
+    /**
+     * Open the disc.
+     */
+    if(!dvd_device) dvd_device=strdup(DEFAULT_DVD_DEVICE);
+#ifdef SYS_DARWIN
+    /* Dynamic DVD drive selection on Darwin */
+    if(!strcmp(dvd_device, "/dev/rdiskN")) {
+      int i;
+      char *temp_device = malloc(strlen(dvd_device)+1);
+
+      for (i = 1; i < 10; i++) {
+        sprintf(temp_device, "/dev/rdisk%d", i);
+        dvd = DVDOpen(temp_device);
+        if(!dvd) {
+          mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,temp_device);
+        } else {
+#if DVDREAD_VERSION <= LIBDVDREAD_VERSION(0,9,4)
+          int len;
+          if(!UDFFindFile(dvd,"/",&len)) {
+            mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,temp_device);
+            DVDClose(dvd);
+          } else
+#endif
+          {
+          free(temp_device);
+          break;
+          }
+        }
+      }
+
+      if(!dvd) {
+        m_struct_free(&stream_opts,opts);
+        return STREAM_UNSUPORTED;
+      }
+    } else
+#endif /* SYS_DARWIN */
+    {
+        dvd = DVDOpen(dvd_device);
+        if(!dvd) {
+          mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,dvd_device);
+          m_struct_free(&stream_opts,opts);
+          return STREAM_UNSUPORTED;
+        }
+    }
+
+    mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDwait);
+
+    /**
+     * Load the video manager to find out the information about the titles on
+     * this disc.
+     */
+    vmg_file = ifoOpen(dvd, 0);
+    if(!vmg_file) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVMG);
+      DVDClose( dvd );
+      m_struct_free(&stream_opts,opts);
+      return STREAM_UNSUPORTED;
+    }
+    tt_srpt = vmg_file->tt_srpt;
+    if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
+    {
+      int title_no; ///< title number
+      mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLES=%d\n", tt_srpt->nr_of_srpts);
+      for (title_no = 0; title_no < tt_srpt->nr_of_srpts; title_no++)
+      {
+        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_CHAPTERS=%d\n", title_no + 1, tt_srpt->title[title_no].nr_of_ptts);
+        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_ANGLES=%d\n", title_no + 1, tt_srpt->title[title_no].nr_of_angles);
+      }
+    }
+    if (mp_msg_test(MSGT_IDENTIFY, MSGL_V))
+    {
+      unsigned char discid [16]; ///< disk ID, a 128 bit MD5 sum
+      int vts_no;   ///< video title set number
+      for (vts_no = 1; vts_no <= vmg_file->vts_atrt->nr_of_vtss; vts_no++)
+        mp_describe_titleset(dvd, tt_srpt, vts_no);
+      if (DVDDiscID(dvd, discid) >= 0)
+      {
+        int i;
+        char buf[33];
+        for (i = 0; i < 16; i ++)
+          sprintf(buf+2*i, "%02X", discid[i]);
+        mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_DISC_ID=%s\n", buf);
+      }
+    }
+    /**
+     * Make sure our title number is valid.
+     */
+    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumTitles, tt_srpt->nr_of_srpts );
+    if(dvd_title < 1 || dvd_title > tt_srpt->nr_of_srpts) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidTitle, dvd_title);
+      ifoClose( vmg_file );
+      DVDClose( dvd );
+      m_struct_free(&stream_opts,opts);
+      return STREAM_UNSUPORTED;
+    }
+    --dvd_title; // remap 1.. -> 0..
+    /**
+     * Make sure the chapter number is valid for this title.
+     */
+    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumChapters, tt_srpt->title[dvd_title].nr_of_ptts);
+    if(dvd_chapter<1 || dvd_chapter>tt_srpt->title[dvd_title].nr_of_ptts) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidChapter, dvd_chapter);
+      ifoClose( vmg_file );
+      DVDClose( dvd );
+      m_struct_free(&stream_opts,opts);
+      return STREAM_UNSUPORTED;
+    }
+    if(dvd_last_chapter>0) {
+      if(dvd_last_chapter<dvd_chapter || dvd_last_chapter>tt_srpt->title[dvd_title].nr_of_ptts) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidLastChapter, dvd_last_chapter);
+        ifoClose( vmg_file );
+        DVDClose( dvd );
+        m_struct_free(&stream_opts,opts);
+        return STREAM_UNSUPORTED;
+      }
+    }
+    --dvd_chapter; // remap 1.. -> 0..
+    /* XXX No need to remap dvd_last_chapter */
+    /**
+     * Make sure the angle number is valid for this title.
+     */
+    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumAngles, tt_srpt->title[dvd_title].nr_of_angles);
+    if(dvd_angle<1 || dvd_angle>tt_srpt->title[dvd_title].nr_of_angles) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidAngle, dvd_angle);
+      ifoClose( vmg_file );
+      DVDClose( dvd );
+      m_struct_free(&stream_opts,opts);
+      return STREAM_UNSUPORTED;
+    }
+    --dvd_angle; // remap 1.. -> 0..
+
+    ttn = tt_srpt->title[dvd_title].vts_ttn - 1;
+    /**
+     * Load the VTS information for the title set our title is in.
+     */
+    vts_file = ifoOpen( dvd, tt_srpt->title[dvd_title].title_set_nr );
+    if(!vts_file) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoIFO, tt_srpt->title[dvd_title].title_set_nr );
+      ifoClose( vmg_file );
+      DVDClose( dvd );
+      m_struct_free(&stream_opts,opts);
+      return STREAM_UNSUPORTED;
+    }
+    /**
+     * We've got enough info, time to open the title set data.
+     */
+    title = DVDOpenFile(dvd, tt_srpt->title[dvd_title].title_set_nr, DVD_READ_TITLE_VOBS);
+    if(!title) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVOBs, tt_srpt->title[dvd_title].title_set_nr);
+      ifoClose( vts_file );
+      ifoClose( vmg_file );
+      DVDClose( dvd );
+      m_struct_free(&stream_opts,opts);
+      return STREAM_UNSUPORTED;
+    }
+
+    mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDopenOk);
+    // store data
+    d=malloc(sizeof(dvd_priv_t)); memset(d,0,sizeof(dvd_priv_t));
+    d->dvd=dvd;
+    d->title=title;
+    d->vmg_file=vmg_file;
+    d->tt_srpt=tt_srpt;
+    d->vts_file=vts_file;
+    d->cur_title = dvd_title+1;
+
+    /**
+     * Check number of audio channels and types
+     */
+    {
+      d->nr_of_channels=0;
+      if(vts_file->vts_pgcit) {
+        int i;
+        for(i=0;i<8;i++)
+#ifdef USE_MPDVDKIT
+          if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i].present) {
+#else
+          if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i] & 0x8000) {
+#endif
+            audio_attr_t * audio = &vts_file->vtsi_mat->vts_audio_attr[i];
+            int language = 0;
+            char tmp[] = "unknown";
+
+            if(audio->lang_type == 1) {
+              language=audio->lang_code;
+              tmp[0]=language>>8;
+              tmp[1]=language&0xff;
+              tmp[2]=0;
+            }
+
+            d->audio_streams[d->nr_of_channels].language=language;
+#ifdef USE_MPDVDKIT
+            d->audio_streams[d->nr_of_channels].id=vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i].s_audio;
+#else
+            d->audio_streams[d->nr_of_channels].id=vts_file->vts_pgcit->pgci_srp[ttn].pgc->audio_control[i] >> 8 & 7;
+#endif
+            switch(audio->audio_format) {
+              case 0: // ac3
+                d->audio_streams[d->nr_of_channels].id+=FIRST_AC3_AID;
+                break;
+              case 6: // dts
+                d->audio_streams[d->nr_of_channels].id+=FIRST_DTS_AID;
+                break;
+              case 2: // mpeg layer 1/2/3
+              case 3: // mpeg2 ext
+                d->audio_streams[d->nr_of_channels].id+=FIRST_MPG_AID;
+                break;
+              case 4: // lpcm
+                d->audio_streams[d->nr_of_channels].id+=FIRST_PCM_AID;
+                break;
+           }
+
+           d->audio_streams[d->nr_of_channels].type=audio->audio_format;
+           // Pontscho: to my mind, tha channels:
+           //  1 - stereo
+           //  5 - 5.1
+           d->audio_streams[d->nr_of_channels].channels=audio->channels;
+           mp_msg(MSGT_OPEN,MSGL_V,"[open] audio stream: %d audio format: %s (%s) language: %s aid: %d\n",
+             d->nr_of_channels,
+             dvd_audio_stream_types[ audio->audio_format ],
+             dvd_audio_stream_channels[ audio->channels ],
+             tmp,
+             d->audio_streams[d->nr_of_channels].id
+           );
+           mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_ID=%d\n", d->audio_streams[d->nr_of_channels].id);
+           if(language && tmp[0])
+             mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", d->audio_streams[d->nr_of_channels].id, tmp);
+
+           d->nr_of_channels++;
+         }
+      }
+      mp_msg(MSGT_OPEN,MSGL_V,"[open] number of audio channels on disk: %d.\n",d->nr_of_channels );
+    }
+
+    /**
+     * Check number of subtitles and language
+     */
+    {
+      int i;
+
+      d->nr_of_subtitles=0;
+      for(i=0;i<32;i++)
+#ifdef USE_MPDVDKIT
+      if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i].present) {
+#else
+      if(vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i] & 0x80000000) {
+#endif
+        subp_attr_t * subtitle = &vts_file->vtsi_mat->vts_subp_attr[i];
+        video_attr_t *video = &vts_file->vtsi_mat->vts_video_attr;
+        int language = 0;
+        char tmp[] = "unknown";
+
+        if(subtitle->type == 1) {
+          language=subtitle->lang_code;
+          tmp[0]=language>>8;
+          tmp[1]=language&0xff;
+          tmp[2]=0;
+        }
+
+        d->subtitles[ d->nr_of_subtitles ].language=language;
+        d->subtitles[ d->nr_of_subtitles ].id=d->nr_of_subtitles;
+        if(video->display_aspect_ratio == 0) /* 4:3 */
+#ifdef USE_MPDVDKIT
+          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i].s_4p3;
+#else
+          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i] >> 24 & 31;
+#endif
+        else if(video->display_aspect_ratio == 3) /* 16:9 */
+#ifdef USE_MPDVDKIT
+          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i].s_lbox;
+#else
+          d->subtitles[d->nr_of_subtitles].id = vts_file->vts_pgcit->pgci_srp[ttn].pgc->subp_control[i] >> 8 & 31;
+#endif
+
+        mp_msg(MSGT_OPEN,MSGL_V,"[open] subtitle ( sid ): %d language: %s\n", d->nr_of_subtitles, tmp);
+        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", d->subtitles[d->nr_of_subtitles].id);
+        if(language && tmp[0])
+          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", d->nr_of_subtitles, tmp);
+        d->nr_of_subtitles++;
+      }
+      mp_msg(MSGT_OPEN,MSGL_V,"[open] number of subtitles on disk: %d\n",d->nr_of_subtitles );
+    }
+
+    /**
+     * Determine which program chain we want to watch.  This is based on the
+     * chapter number.
+     */
+    pgc_id = vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_chapter].pgcn; // local
+    pgn  = vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_chapter].pgn;  // local
+    d->cur_pgc = vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
+    d->cur_cell = d->cur_pgc->program_map[pgn-1] - 1; // start playback here
+    d->packs_left=-1;      // for Navi stuff
+    d->angle_seek=0;
+    /* XXX dvd_last_chapter is in the range 1..nr_of_ptts */
+    if(dvd_last_chapter > 0 && dvd_last_chapter < tt_srpt->title[dvd_title].nr_of_ptts) {
+      pgn=vts_file->vts_ptt_srpt->title[ttn].ptt[dvd_last_chapter].pgn;
+      d->last_cell=d->cur_pgc->program_map[pgn-1] - 1;
+    } else
+      d->last_cell=d->cur_pgc->nr_of_cells;
+
+    if(d->cur_pgc->cell_playback[d->cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ) 
+      d->cur_cell+=dvd_angle;
+    d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
+    d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
+    mp_msg(MSGT_DVD,MSGL_V, "DVD start cell: %d  pack: 0x%X-0x%X  \n",d->cur_cell,d->cur_pack,d->cell_last_pack);
+
+    // ... (unimplemented)
+    //    return NULL;
+    stream->type = STREAMTYPE_DVD;
+    stream->sector_size = 2048;
+    stream->flags = STREAM_READ | STREAM_SEEK;
+    stream->fill_buffer = fill_buffer;
+    stream->seek = seek;
+    stream->control = control;
+    stream->close = stream_dvd_close;
+    stream->start_pos = (off_t)d->cur_pack*2048;
+    stream->end_pos = (off_t)(d->cur_pgc->cell_playback[d->last_cell-1].last_sector)*2048;
+    mp_msg(MSGT_DVD,MSGL_V,"DVD start=%d end=%d  \n",d->cur_pack,d->cur_pgc->cell_playback[d->last_cell-1].last_sector);
+    stream->priv = (void*)d;
+    return STREAM_OK;
+  }
+#endif /* #ifdef USE_DVDREAD */
+  mp_msg(MSGT_DVD,MSGL_ERR,MSGTR_NoDVDSupport);
+  m_struct_free(&stream_opts,opts);
+  return STREAM_UNSUPORTED;
+}
+
+
+stream_info_t stream_info_dvd = {
+  "DVD stream",
+  "null",
+  "",
+  "",
+  open_s,
+  { "dvd", NULL },
+  &stream_opts,
+  1 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_dvd.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,48 @@
+
+#ifdef USE_DVDREAD
+
+#ifdef USE_MPDVDKIT
+#include "libmpdvdkit2/dvd_reader.h"
+#include "libmpdvdkit2/ifo_types.h"
+#include "libmpdvdkit2/ifo_read.h"
+#include "libmpdvdkit2/nav_read.h"
+#else
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+#include <dvdread/nav_read.h>
+#endif
+
+typedef struct {
+  dvd_reader_t *dvd;
+  dvd_file_t *title;
+  ifo_handle_t *vmg_file;
+  tt_srpt_t *tt_srpt;
+  ifo_handle_t *vts_file;
+  vts_ptt_srpt_t *vts_ptt_srpt;
+  pgc_t *cur_pgc;
+//
+  int cur_title;
+  int cur_cell;
+  int last_cell;
+  int cur_pack;
+  int cell_last_pack;
+// Navi:
+  int packs_left;
+  dsi_t dsi_pack;
+  int angle_seek;
+// audio datas
+  int nr_of_channels;
+  stream_language_t audio_streams[32];
+// subtitles
+  int nr_of_subtitles;
+  stream_language_t subtitles[32];
+} dvd_priv_t;
+
+int dvd_number_of_subs(stream_t *stream);
+int dvd_lang_from_sid(stream_t *stream, int id);
+int dvd_aid_from_lang(stream_t *stream, unsigned char* lang);
+int dvd_sid_from_lang(stream_t *stream, unsigned char* lang);
+int dvd_chapter_from_cell(dvd_priv_t *dvd,int title,int cell);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_file.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,162 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "mp_msg.h"
+#include "stream.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+static struct stream_priv_s {
+  char* filename;
+  char *filename2;
+} stream_priv_dflts = {
+  NULL, NULL
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  {"string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  {"filename", ST_OFF(filename2), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "file",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};  
+
+static int fill_buffer(stream_t *s, char* buffer, int max_len){
+  int r = read(s->fd,buffer,max_len);
+  return (r <= 0) ? -1 : r;
+}
+
+static int write_buffer(stream_t *s, char* buffer, int len) {
+  int r = write(s->fd,buffer,len);
+  return (r <= 0) ? -1 : r;
+}
+
+static int seek(stream_t *s,off_t newpos) {
+  s->pos = newpos;
+  if(lseek(s->fd,s->pos,SEEK_SET)<0) {
+    s->eof=1;
+    return 0;
+  }
+  return 1;
+}
+
+static int seek_forward(stream_t *s,off_t newpos) {
+  if(newpos<s->pos){
+    mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n");
+    return 0;
+  }
+  while(s->pos<newpos){
+    int len=s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE);
+    if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; break; } // EOF
+    s->buf_pos=0;
+    s->buf_len=len;
+    s->pos+=len;
+  }
+  return 1;
+}
+
+static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
+  int f;
+  mode_t m = 0;
+  off_t len;
+  unsigned char *filename;
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+
+  if(mode == STREAM_READ)
+    m = O_RDONLY;
+  else if(mode == STREAM_WRITE)
+    m = O_WRONLY;
+  else {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[file] Unknown open mode %d\n",mode);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_UNSUPORTED;
+  }
+
+  if(p->filename)
+    filename = p->filename;
+  else if(p->filename2)
+    filename = p->filename2;
+  else
+    filename = NULL;
+  if(!filename) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[file] No filename\n");
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+
+#if defined(__CYGWIN__)|| defined(__MINGW32__)
+  m |= O_BINARY;
+#endif    
+
+  if(!strcmp(filename,"-")){
+    if(mode == STREAM_READ) {
+      // read from stdin
+      mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ReadSTDIN);
+      f=0; // 0=stdin
+#ifdef __MINGW32__
+	  setmode(fileno(stdin),O_BINARY);
+#endif
+    } else {
+      mp_msg(MSGT_OPEN,MSGL_INFO,"Writing to stdout\n");
+      f=1;
+#ifdef __MINGW32__
+	  setmode(fileno(stdout),O_BINARY);
+#endif
+    }
+  } else {
+    f=open(filename,m);
+    if(f<0) {
+      mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,filename);
+      m_struct_free(&stream_opts,opts);
+      return STREAM_ERROR;
+    }
+  }
+
+  len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET);
+#ifdef __MINGW32__
+  if(f==0 || len == -1) {
+#else
+  if(len == -1) {
+#endif
+    stream->seek = seek_forward;
+    stream->type = STREAMTYPE_STREAM; // Must be move to STREAMTYPE_FILE
+    stream->flags |= STREAM_SEEK_FW;
+  } else if(len >= 0) {
+    stream->seek = seek;
+    stream->end_pos = len;
+    stream->type = STREAMTYPE_FILE;
+  }
+
+  mp_msg(MSGT_OPEN,MSGL_V,"[file] File size is %"PRId64" bytes\n", (int64_t)len);
+
+  stream->fd = f;
+  stream->fill_buffer = fill_buffer;
+  stream->write_buffer = write_buffer;
+
+  m_struct_free(&stream_opts,opts);
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_file = {
+  "File",
+  "file",
+  "Albeu",
+  "based on the code from ??? (probably Arpi)",
+  open_f,
+  { "file", "", NULL },
+  &stream_opts,
+  1 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_ftp.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,469 @@
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#ifndef HAVE_WINSOCK2
+#include <sys/socket.h>
+#define closesocket close
+#else
+#include <winsock2.h>
+#endif
+
+#include "mp_msg.h"
+#include "stream.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+static struct stream_priv_s {
+  char* user;
+  char* pass;
+  char* host;
+  int port;
+  char* filename;
+
+  char *cput,*cget;
+  int handle;
+  int cavail,cleft;
+  char *buf;
+} stream_priv_dflts = {
+  "anonymous","no@spam",
+  NULL,
+  21,
+  NULL,
+  NULL,
+  NULL,
+
+  0,
+  0,0,
+  NULL
+};
+
+#define BUFSIZE 2048
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  {"username", ST_OFF(user), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  {"password", ST_OFF(pass), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  {"hostname", ST_OFF(host), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  {"port", ST_OFF(port), CONF_TYPE_INT, 0, 0 ,65635, NULL},
+  {"filename", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "ftp",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+#define TELNET_IAC      255             /* interpret as command: */
+#define TELNET_IP       244             /* interrupt process--permanently */
+#define TELNET_SYNCH    242             /* for telfunc calls */
+
+// Check if there is something to read on a fd. This avoid hanging
+// forever if the network stop responding.
+static int fd_can_read(int fd,int timeout) {
+  fd_set fds;
+  struct timeval tv;
+
+  FD_ZERO(&fds);
+  FD_SET(fd,&fds);
+  tv.tv_sec = timeout;
+  tv.tv_usec = 0;
+  
+  return (select(fd+1, &fds, NULL, NULL, &tv) > 0);
+}
+
+/*
+ * read a line of text
+ *
+ * return -1 on error or bytecount
+ */
+static int readline(char *buf,int max,struct stream_priv_s *ctl)
+{
+    int x,retval = 0;
+    char *end,*bp=buf;
+    int eof = 0;
+ 
+    do {
+      if (ctl->cavail > 0) {
+	x = (max >= ctl->cavail) ? ctl->cavail : max-1;
+	end = memccpy(bp,ctl->cget,'\n',x);
+	if (end != NULL)
+	  x = end - bp;
+	retval += x;
+	bp += x;
+	*bp = '\0';
+	max -= x;
+	ctl->cget += x;
+	ctl->cavail -= x;
+	if (end != NULL) {
+	  bp -= 2;
+	  if (strcmp(bp,"\r\n") == 0) {
+	    *bp++ = '\n';
+	    *bp++ = '\0';
+	    --retval;
+	  }
+	  break;
+	}
+      }
+      if (max == 1) {
+	*buf = '\0';
+	break;
+      }
+      if (ctl->cput == ctl->cget) {
+	ctl->cput = ctl->cget = ctl->buf;
+	ctl->cavail = 0;
+	ctl->cleft = BUFSIZE;
+      }
+      if(eof) {
+	if (retval == 0)
+	  retval = -1;
+	break;
+      }
+
+      if(!fd_can_read(ctl->handle, 15)) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] read timed out\n");
+        retval = -1;
+        break;
+      }
+
+      if ((x = recv(ctl->handle,ctl->cput,ctl->cleft,0)) == -1) {
+	mp_msg(MSGT_STREAM,MSGL_ERR, "[ftp] read error: %s\n",strerror(errno));
+	retval = -1;
+	break;
+      }
+      if (x == 0)
+	eof = 1;
+      ctl->cleft -= x;
+      ctl->cavail += x;
+      ctl->cput += x;
+    } while (1);
+    
+    return retval;
+}
+
+/*
+ * read a response from the server
+ *
+ * return 0 if first char doesn't match
+ * return 1 if first char matches
+ */
+static int readresp(struct stream_priv_s* ctl,char* rsp)
+{
+    static char response[256];
+    char match[5];
+    int r;
+
+    if (readline(response,256,ctl) == -1)
+      return 0;
+ 
+    r = atoi(response)/100;
+    if(rsp) strcpy(rsp,response);
+
+    mp_msg(MSGT_STREAM,MSGL_V, "[ftp] < %s",response);
+
+    if (response[3] == '-') {
+      strncpy(match,response,3);
+      match[3] = ' ';
+      match[4] = '\0';
+      do {
+	if (readline(response,256,ctl) == -1) {
+	  mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Control socket read failed\n");
+	  return 0;
+	}
+	mp_msg(MSGT_OPEN,MSGL_V, "[ftp] < %s",response);
+      }	while (strncmp(response,match,4));
+    }
+    return r;
+}
+
+
+static int FtpSendCmd(const char *cmd, struct stream_priv_s *nControl,char* rsp)
+{
+  int l = strlen(cmd);
+  int hascrlf = cmd[l - 2] == '\r' && cmd[l - 1] == '\n';
+
+  if(hascrlf && l == 2) mp_msg(MSGT_STREAM,MSGL_V, "\n");
+  else mp_msg(MSGT_STREAM,MSGL_V, "[ftp] > %s",cmd);
+  while(l > 0) {
+    int s = send(nControl->handle,cmd,l,0);
+
+    if(s <= 0) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] write error: %s\n",strerror(errno));
+      return 0;
+    }
+    
+    cmd += s;
+    l -= s;
+  }
+    
+  if (hascrlf)  
+    return readresp(nControl,rsp);
+  else
+    return FtpSendCmd("\r\n", nControl, rsp);
+}
+
+static int FtpOpenPort(struct stream_priv_s* p) {
+  int resp,fd;
+  char rsp_txt[256];
+  char* par,str[128];
+  int num[6];
+
+  resp = FtpSendCmd("PASV",p,rsp_txt);
+  if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'PASV' failed: %s\n",rsp_txt);
+    return 0;
+  }
+  
+  par = strchr(rsp_txt,'(');
+  
+  if(!par || !par[0] || !par[1]) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] invalid server response: %s ??\n",rsp_txt);
+    return 0;
+  }
+
+  sscanf(par+1,"%u,%u,%u,%u,%u,%u",&num[0],&num[1],&num[2],
+	 &num[3],&num[4],&num[5]);
+  snprintf(str,127,"%d.%d.%d.%d",num[0],num[1],num[2],num[3]);
+  fd = connect2Server(str,(num[4]<<8)+num[5],0);
+
+  if(fd < 0)
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] failed to create data connection\n");
+
+  return fd;
+}
+
+static int FtpOpenData(stream_t* s,size_t newpos) {
+  struct stream_priv_s* p = s->priv;
+  int resp;
+  char str[256],rsp_txt[256];
+
+  // Open a new connection
+  s->fd = FtpOpenPort(p);
+
+  if(s->fd < 0) return 0;
+
+  if(newpos > 0) {
+    snprintf(str,255,"REST %"PRId64, (int64_t)newpos);
+
+    resp = FtpSendCmd(str,p,rsp_txt);
+    if(resp != 3) {
+      mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+      newpos = 0;
+    }
+  }
+
+  // Get the file
+  snprintf(str,255,"RETR %s",p->filename);
+  resp = FtpSendCmd(str,p,rsp_txt);
+
+  if(resp != 1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+    return 0;
+  }
+
+  s->pos = newpos;
+  return 1;
+}
+
+static int fill_buffer(stream_t *s, char* buffer, int max_len){
+  int r;
+
+  if(s->fd < 0 && !FtpOpenData(s,s->pos))
+    return -1;
+  
+  if(!fd_can_read(s->fd, 15)) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] read timed out\n");
+    return -1;
+  }
+
+  r = recv(s->fd,buffer,max_len,0);
+  return (r <= 0) ? -1 : r;
+}
+
+static int seek(stream_t *s,off_t newpos) {
+  struct stream_priv_s* p = s->priv;
+  int resp;
+  char rsp_txt[256];
+
+  if(s->pos > s->end_pos) {
+    s->eof=1;
+    return 0;
+  }
+
+  // Check to see if the server doesn't alredy terminated the transfert
+  if(fd_can_read(p->handle, 0)) {
+    if(readresp(p,rsp_txt) != 2)
+      mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] Warning the server didn't finished the transfert correctly: %s\n",rsp_txt);
+    closesocket(s->fd);
+    s->fd = -1;
+  }
+
+  // Close current download
+  if(s->fd >= 0) {
+    static const char pre_cmd[]={TELNET_IAC,TELNET_IP,TELNET_IAC,TELNET_SYNCH};
+    //int fl;
+    
+    // First close the fd
+    closesocket(s->fd);
+    s->fd = 0;
+    
+    // Send send the telnet sequence needed to make the server react
+    
+    // Dunno if this is really needed, lftp have it. I let
+    // it here in case it turn out to be needed on some other OS
+    //fl=fcntl(p->handle,F_GETFL);
+    //fcntl(p->handle,F_SETFL,fl&~O_NONBLOCK);
+
+    // send only first byte as OOB due to OOB braindamage in many unices
+    send(p->handle,pre_cmd,1,MSG_OOB);
+    send(p->handle,pre_cmd+1,sizeof(pre_cmd)-1,0);
+    
+    //fcntl(p->handle,F_SETFL,fl);
+
+    // Get the 426 Transfer aborted
+    // Or the 226 Transfer complete
+    resp = readresp(p,rsp_txt);
+    if(resp != 4 && resp != 2) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Server didn't abort correctly: %s\n",rsp_txt);
+      s->eof = 1;
+      return 0;
+    }
+    // Send the ABOR command
+    // Ignore the return code as sometimes it fail with "nothing to abort"
+    FtpSendCmd("ABOR",p,rsp_txt);
+  }
+  return FtpOpenData(s,newpos);
+}
+
+
+static void close_f(stream_t *s) {
+  struct stream_priv_s* p = s->priv;
+
+  if(!p) return;
+
+  if(s->fd > 0) {
+    closesocket(s->fd);
+    s->fd = 0;
+  }
+
+  FtpSendCmd("QUIT",p,NULL);
+
+  if(p->handle) closesocket(p->handle);
+  if(p->buf) free(p->buf);
+
+  m_struct_free(&stream_opts,p);
+}
+
+
+
+static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
+  int len = 0,resp;
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+  char str[256],rsp_txt[256];
+
+  if(mode != STREAM_READ) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Unknown open mode %d\n",mode);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_UNSUPORTED;
+  }
+
+  if(!p->filename || !p->host) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Bad url\n");
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+
+  // Open the control connection
+  p->handle = connect2Server(p->host,p->port,1);
+  
+  if(p->handle < 0) {
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+
+  // We got a connection, let's start serious things
+  stream->fd = -1;
+  stream->priv = p;
+  p->buf = malloc(BUFSIZE);
+
+  if (readresp(p, NULL) == 0) {
+    close_f(stream);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+
+  // Login
+  snprintf(str,255,"USER %s",p->user);
+  resp = FtpSendCmd(str,p,rsp_txt);
+
+  // password needed
+  if(resp == 3) {
+    snprintf(str,255,"PASS %s",p->pass);
+    resp = FtpSendCmd(str,p,rsp_txt);
+    if(resp != 2) {
+      mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+      close_f(stream);
+      return STREAM_ERROR;
+    }
+  } else if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+    close_f(stream);
+    return STREAM_ERROR;
+  }
+    
+  // Set the transfert type
+  resp = FtpSendCmd("TYPE I",p,rsp_txt);
+  if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command 'TYPE I' failed: %s\n",rsp_txt);
+    close_f(stream);
+    return STREAM_ERROR;
+  }
+
+  // Get the filesize
+  snprintf(str,255,"SIZE %s",p->filename);
+  resp = FtpSendCmd(str,p,rsp_txt);
+  if(resp != 2) {
+    mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+  } else {
+    int dummy;
+    sscanf(rsp_txt,"%d %d",&dummy,&len);
+  }
+
+  if(len > 0) {
+    stream->seek = seek;
+    stream->end_pos = len;
+  }
+
+  // The data connection is really opened only at the first
+  // read/seek. This must be done when the cache is used
+  // because the connection would stay open in the main process,
+  // preventing correct abort with many servers.
+  stream->fd = -1;
+  stream->priv = p;
+  stream->fill_buffer = fill_buffer;
+  stream->close = close_f;
+
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_ftp = {
+  "File Transfer Protocol",
+  "ftp",
+  "Albeu",
+  "reuse a bit of code from ftplib written by Thomas Pfau",
+  open_f,
+  { "ftp", NULL },
+  &stream_opts,
+  1 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_livedotcom.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,119 @@
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "stream.h"
+#include "network.h"
+#include "demuxer.h"
+#include "help_mp.h"
+
+extern int network_bandwidth;
+
+static int _rtsp_streaming_seek(int fd, off_t pos, streaming_ctrl_t* streaming_ctrl) {
+  return -1; // For now, we don't handle RTSP stream seeking
+}
+
+static int rtsp_streaming_start(stream_t* stream) {
+  stream->streaming_ctrl->streaming_seek = _rtsp_streaming_seek;
+  return 0;
+}
+
+
+static int open_live_rtsp_sip(stream_t *stream,int mode, void* opts, int* file_format) {
+  URL_t *url;
+
+  stream->streaming_ctrl = streaming_ctrl_new();
+  if( stream->streaming_ctrl==NULL ) {
+    return STREAM_ERROR;
+  }
+  stream->streaming_ctrl->bandwidth = network_bandwidth;
+  url = url_new(stream->url);
+  stream->streaming_ctrl->url = check4proxies(url);
+  //url_free(url);
+
+  mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_LIVE555, URL: %s\n", stream->url);
+
+  if(rtsp_streaming_start(stream) < 0) {
+    mp_msg(MSGT_NETWORK,MSGL_ERR,"rtsp_streaming_start failed\n");
+    goto fail;
+  }
+
+  *file_format = DEMUXER_TYPE_RTP;
+  stream->type = STREAMTYPE_STREAM;
+  return STREAM_OK;
+
+fail:
+  streaming_ctrl_free( stream->streaming_ctrl );
+  stream->streaming_ctrl = NULL;
+  return STREAM_ERROR;
+}
+
+static int open_live_sdp(stream_t *stream,int mode, void* opts, int* file_format) {
+  int f;
+  char *filename = stream->url;
+  off_t len;
+  char* sdpDescription;
+  ssize_t numBytesRead;
+
+  if(strncmp("sdp://",filename,6) == 0) {
+    filename += 6;
+#if defined(__CYGWIN__) || defined(__MINGW32__)
+    f = open(filename,O_RDONLY|O_BINARY);
+#else
+    f = open(filename,O_RDONLY);
+#endif
+    if(f < 0) {
+      mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,filename);
+      return STREAM_ERROR;
+    }
+
+    len=lseek(f,0,SEEK_END); 
+    lseek(f,0,SEEK_SET);
+    if(len == -1)
+      return STREAM_ERROR;
+    if(len > SIZE_MAX - 1)
+      return STREAM_ERROR;
+
+    sdpDescription = malloc(len+1);
+    if(sdpDescription == NULL) return STREAM_ERROR;
+    numBytesRead = read(f, sdpDescription, len);
+    if(numBytesRead != len) {
+      free(sdpDescription);
+      return STREAM_ERROR;
+    }
+    sdpDescription[len] = '\0'; // to be safe
+    stream->priv = sdpDescription;
+
+    stream->type = STREAMTYPE_SDP;
+    *file_format = DEMUXER_TYPE_RTP;
+    return STREAM_OK;
+  }
+  return STREAM_UNSUPORTED;
+}
+
+
+stream_info_t stream_info_rtsp_sip = {
+  "standard RTSP and SIP",
+  "RTSP and SIP",
+  "Ross Finlayson",
+  "Uses LIVE555 Streaming Media library.",
+  open_live_rtsp_sip,
+  {"rtsp", "sip", NULL },
+  NULL,
+  0 // Urls are an option string
+};
+
+stream_info_t stream_info_sdp = {
+  "SDP stream descriptor",
+  "SDP",
+  "Ross Finlayson",
+  "Uses LIVE555 Streaming Media library.",
+  open_live_sdp,
+  {"sdp", NULL },
+  NULL,
+  0 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_netstream.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,308 @@
+/*
+ *  stream_netstream.c
+ *
+ *	Copyright (C) Alban Bedel - 04/2003
+ *
+ *  This file is part of MPlayer, a free movie player.
+ *	
+ *  MPlayer is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  MPlayer is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *
+ */
+
+/*
+ *  Net stream allow you to access MPlayer stream accross a tcp
+ *  connection.
+ *  Note that at least mf and tv use a dummy stream (they are
+ *  implemented at the demuxer level) so you won't be able to
+ *  access those :(( but dvd, vcd and so on should work perfectly
+ *  (if you have the bandwidth ;)
+ *   A simple server is in TOOLS/netstream.
+ *
+ */
+
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#ifndef HAVE_WINSOCK2
+#define closesocket close
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include "mp_msg.h"
+#include "stream.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+#include "bswap.h"
+
+#include "netstream.h"
+
+static struct stream_priv_s {
+  char* host;
+  int port;
+  char* url;
+} stream_priv_dflts = {
+  NULL,
+  10000,
+  NULL
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  {"hostname", ST_OFF(host), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  {"port", ST_OFF(port), CONF_TYPE_INT, M_OPT_MIN, 1 ,0, NULL},
+  {"filename", ST_OFF(url), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "netstream",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+//// When the cache is running we need a lock as
+//// fill_buffer is called from another proccess
+static int lock_fd(int fd) {
+#ifndef HAVE_WINSOCK2
+  struct flock lock;
+
+  memset(&lock,0,sizeof(struct flock));
+  lock.l_type = F_WRLCK;
+
+  mp_msg(MSGT_STREAM,MSGL_DBG2, "Lock (%d)\n",getpid());
+  do {    
+    if(fcntl(fd,F_SETLKW,&lock)) {
+      if(errno == EAGAIN) continue;
+      mp_msg(MSGT_STREAM,MSGL_ERR, "Failed to get the lock: %s\n",
+	     strerror(errno));
+      return 0;
+    }
+  } while(0);
+  mp_msg(MSGT_STREAM,MSGL_DBG2, "Locked (%d)\n",getpid());
+#else
+printf("FIXME? should lock here\n");
+#endif
+  return 1;
+}
+
+static int unlock_fd(int fd) {
+#ifndef HAVE_WINSOCK2
+  struct flock lock;
+
+  memset(&lock,0,sizeof(struct flock));
+  lock.l_type = F_UNLCK;
+
+  mp_msg(MSGT_STREAM,MSGL_DBG2, "Unlock (%d)\n",getpid());
+  if(fcntl(fd,F_SETLK,&lock)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR, "Failed to release the lock: %s\n",
+	   strerror(errno));
+    return 0;
+  }
+#else
+printf("FIXME? should unlock here\n");
+#endif
+  return 1;
+}
+
+static mp_net_stream_packet_t* send_net_stream_cmd(stream_t *s,uint16_t cmd,char* data,int len) {
+  mp_net_stream_packet_t* pack;
+
+  // Cache is enabled : lock
+  if(s->cache_data && !lock_fd(s->fd))
+    return NULL;
+  // Send a command
+  if(!write_packet(s->fd,cmd,data,len)) {
+    if(s->cache_data) unlock_fd(s->fd);
+    return 0;
+  }
+  // Read the response
+  pack = read_packet(s->fd);
+  // Now we can unlock
+  if(s->cache_data) unlock_fd(s->fd);
+
+  if(!pack)
+    return NULL;
+
+  switch(pack->cmd) {
+  case NET_STREAM_OK:
+    return pack;
+  case NET_STREAM_ERROR:
+    if(pack->len > sizeof(mp_net_stream_packet_t))
+      mp_msg(MSGT_STREAM,MSGL_ERR, "Fill buffer failed: %s\n",pack->data);
+    else
+      mp_msg(MSGT_STREAM,MSGL_ERR, "Fill buffer failed\n");
+    free(pack);
+    return NULL;
+  }
+  
+  mp_msg(MSGT_STREAM,MSGL_ERR, "Unknown response to %d: %d\n",cmd,pack->cmd);
+  free(pack);
+  return NULL;
+}
+
+static int fill_buffer(stream_t *s, char* buffer, int max_len){
+  uint16_t len = le2me_16(max_len);
+  mp_net_stream_packet_t* pack;
+
+  pack = send_net_stream_cmd(s,NET_STREAM_FILL_BUFFER,(char*)&len,2);
+  if(!pack) {
+    return -1;
+  }
+  len = pack->len - sizeof(mp_net_stream_packet_t);
+  if(len > max_len) {
+    mp_msg(MSGT_STREAM,MSGL_ERR, "Got a too big a packet %d / %d\n",len,max_len);
+    free(pack);
+    return 0;
+  }
+  if(len > 0)
+    memcpy(buffer,pack->data,len);
+  free(pack);
+  return len;
+}
+
+
+static int seek(stream_t *s,off_t newpos) {
+  uint64_t pos = le2me_64((uint64_t)newpos);
+  mp_net_stream_packet_t* pack;
+  
+  pack = send_net_stream_cmd(s,NET_STREAM_SEEK,(char*)&pos,8);
+  if(!pack) {    
+    return 0;
+  }
+  s->pos = newpos;
+  free(pack);
+  return 1;
+}
+
+static int net_stream_reset(struct stream_st *s) {
+  mp_net_stream_packet_t* pack;
+  
+  pack = send_net_stream_cmd(s,NET_STREAM_RESET,NULL,0);  
+  if(!pack) {
+    return 0;
+  }
+  free(pack);
+  return 1;
+}
+ 
+static int control(struct stream_st *s,int cmd,void* arg) {
+  switch(cmd) {
+  case STREAM_CTRL_RESET:
+    return net_stream_reset(s);
+  }
+  return STREAM_UNSUPORTED;
+}
+
+static void close_s(struct stream_st *s) {
+  mp_net_stream_packet_t* pack;
+  
+  pack = send_net_stream_cmd(s,NET_STREAM_CLOSE,NULL,0);
+  if(pack)
+    free(pack);
+}
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  int f;
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+  mp_net_stream_packet_t* pack;
+  mp_net_stream_opened_t* opened;
+
+  if(mode != STREAM_READ)
+    return STREAM_UNSUPORTED;
+
+  if(!p->host) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "We need an host name (ex: mpst://server.net/cdda://5)\n");
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+  if(!p->url || strlen(p->url) == 0) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "We need a remote url (ex: mpst://server.net/cdda://5)\n");
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+
+  f = connect2Server(p->host,p->port,1);
+  if(f < 0) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "Connection to %s:%d failed\n",p->host,p->port);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+  stream->fd = f;
+  /// Now send an open command
+  pack = send_net_stream_cmd(stream,NET_STREAM_OPEN,p->url,strlen(p->url) + 1);
+  if(!pack) {
+    goto error;
+  }
+  
+  if(pack->len != sizeof(mp_net_stream_packet_t) + 
+     sizeof(mp_net_stream_opened_t)) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "Invalid open response packet len (%d bytes)\n",pack->len);
+    free(pack);
+    goto error;
+  }
+  
+  opened = (mp_net_stream_opened_t*)pack->data;
+  net_stream_opened_2_me(opened);
+
+  *file_format = opened->file_format;
+  stream->flags = opened->flags;
+  stream->sector_size = opened->sector_size;
+  stream->start_pos = opened->start_pos;
+  stream->end_pos = opened->end_pos;
+
+  stream->fill_buffer = fill_buffer;
+  stream->control = control;
+  if(stream->flags & STREAM_SEEK)
+    stream->seek = seek;
+  stream->close = close_s;
+
+  free(pack);
+  m_struct_free(&stream_opts,opts);
+
+  return STREAM_OK;
+
+  error:
+  closesocket(f);
+  m_struct_free(&stream_opts,opts);
+  return STREAM_ERROR;
+}
+
+stream_info_t stream_info_netstream = {
+  "Net stream",
+  "netstream",
+  "Albeu",
+  "",
+  open_s,
+  { "mpst",NULL },
+  &stream_opts,
+  1 // Url is an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_null.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,45 @@
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "stream.h"
+#include "demuxer.h"
+
+#ifdef USE_TV
+extern char* tv_param_channel;
+#endif
+
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  stream->type = STREAMTYPE_DUMMY;
+
+  if(strncmp("mf://",stream->url,5) == 0) {
+    *file_format =  DEMUXER_TYPE_MF;
+  } 
+#ifdef USE_TV
+  else if (strncmp("tv://",stream->url,5) == 0) {
+    *file_format =  DEMUXER_TYPE_TV;
+    if(stream->url[5] != '\0')
+      tv_param_channel = strdup(stream->url + 5);
+  }
+#endif
+  return 1;
+}
+
+
+stream_info_t stream_info_null = {
+  "Null stream",
+  "null",
+  "Albeu",
+  "",
+  open_s,
+  { 
+#ifdef USE_TV
+"tv", 
+#endif
+"mf", "null", NULL },
+  NULL,
+  0 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_pvr.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,1026 @@
+/*
+ *  Copyright (C) 2006 Benjamin Zores
+ *   Stream layer for WinTV PVR-150/250/350 (a.k.a IVTV) PVR cards.
+ *   See http://ivtvdriver.org/index.php/Main_Page for more details on the
+ *    cards supported by the ivtv driver.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <inttypes.h>
+#include <sys/poll.h>
+#include <linux/videodev2.h>
+#include <linux/ivtv.h>
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "stream.h"
+#include "tv.h"
+
+#define PVR_DEFAULT_DEVICE "/dev/video0"
+
+/* logging mechanisms */
+#define LOG_LEVEL_PVR  "[pvr]"
+#define LOG_LEVEL_V4L2 "[v4l2]"
+#define LOG_LEVEL_IVTV "[ivtv]"
+
+/* IVTV driver settings (see http://ivtvdriver.org/index.php/Ivtvctl ) */
+
+/* codec aspect ratio (1:1, 4:3, 16:9, 2.21:1) */
+#define PVR_ASPECT_RATIO_1_1                                   1
+#define PVR_ASPECT_RATIO_4_3                                   2
+#define PVR_ASPECT_RATIO_16_9                                  3
+#define PVR_ASPECT_RATIO_2_21_1                                4
+
+/* audio codec sample rate (32KHz, CD 44.1 KHz, AC97 48 KHz) */
+#define PVR_AUDIO_SAMPLE_RATE_44_1_KHZ                         0x0000
+#define PVR_AUDIO_SAMPLE_RATE_48_KHZ                           0x0001
+#define PVR_AUDIO_SAMPLE_RATE_32_KHZ                           0x0002
+
+/* audio codec layer (1 or 2) */
+#define PVR_AUDIO_LAYER_1                                      0x0004
+#define PVR_AUDIO_LAYER_2                                      0x0008
+
+/* audio codec bitrate */
+#define PVR_AUDIO_BITRATE_32                                   0x0010
+#define PVR_AUDIO_BITRATE_L1_64                                0x0020
+#define PVR_AUDIO_BITRATE_L1_96                                0x0030
+#define PVR_AUDIO_BITRATE_L1_128                               0x0040
+#define PVR_AUDIO_BITRATE_L1_160                               0x0050
+#define PVR_AUDIO_BITRATE_L1_192                               0x0060
+#define PVR_AUDIO_BITRATE_L1_224                               0x0070
+#define PVR_AUDIO_BITRATE_L1_256                               0x0080
+#define PVR_AUDIO_BITRATE_L1_288                               0x0090
+#define PVR_AUDIO_BITRATE_L1_320                               0x00A0
+#define PVR_AUDIO_BITRATE_L1_352                               0x00B0
+#define PVR_AUDIO_BITRATE_L1_384                               0x00C0
+#define PVR_AUDIO_BITRATE_L1_416                               0x00D0
+#define PVR_AUDIO_BITRATE_L1_448                               0x00E0
+#define PVR_AUDIO_BITRATE_L2_48                                0x0020
+#define PVR_AUDIO_BITRATE_L2_56                                0x0030
+#define PVR_AUDIO_BITRATE_L2_64                                0x0040
+#define PVR_AUDIO_BITRATE_L2_80                                0x0050
+#define PVR_AUDIO_BITRATE_L2_96                                0x0060
+#define PVR_AUDIO_BITRATE_L2_112                               0x0070
+#define PVR_AUDIO_BITRATE_L2_128                               0x0080
+#define PVR_AUDIO_BITRATE_L2_160                               0x0090
+#define PVR_AUDIO_BITRATE_L2_192                               0x00A0
+#define PVR_AUDIO_BITRATE_L2_224                               0x00B0
+#define PVR_AUDIO_BITRATE_L2_256                               0x00C0
+#define PVR_AUDIO_BITRATE_L2_320                               0x00D0
+#define PVR_AUDIO_BITRATE_L2_384                               0x00E0
+
+/* audio codec mode */
+#define PVR_AUDIO_MODE_ARG_STEREO                              "stereo"
+#define PVR_AUDIO_MODE_ARG_JOINT_STEREO                        "joint_stereo"
+#define PVR_AUDIO_MODE_ARG_DUAL                                "dual"
+#define PVR_AUDIO_MODE_ARG_MONO                                "mono"
+#define PVR_AUDIO_MODE_STEREO                                  0x0000
+#define PVR_AUDIO_MODE_JOINT_STEREO                            0x0100
+#define PVR_AUDIO_MODE_DUAL                                    0x0200
+#define PVR_AUDIO_MODE_MONO                                    0x0300
+
+/* video codec bitrate mode */
+#define PVR_VIDEO_BITRATE_MODE_ARG_VBR                         "vbr"
+#define PVR_VIDEO_BITRATE_MODE_ARG_CBR                         "cbr"
+#define PVR_VIDEO_BITRATE_MODE_VBR                             0
+#define PVR_VIDEO_BITRATE_MODE_CBR                             1
+
+/* video codec stream type */
+#define PVR_VIDEO_STREAM_TYPE_PS                               "ps"
+#define PVR_VIDEO_STREAM_TYPE_TS                               "ts"
+#define PVR_VIDEO_STREAM_TYPE_MPEG1                            "mpeg1"
+#define PVR_VIDEO_STREAM_TYPE_DVD                              "dvd"
+#define PVR_VIDEO_STREAM_TYPE_VCD                              "vcd"
+#define PVR_VIDEO_STREAM_TYPE_SVCD                             "svcd"
+#define PVR_VIDEO_STREAM_TYPE_DVD_S1                           "dvds1"
+#define PVR_VIDEO_STREAM_TYPE_DVD_S2                           "dvds2"
+
+/* command line arguments */
+int pvr_param_aspect_ratio = 0;
+int pvr_param_sample_rate = 0;
+int pvr_param_audio_layer = 0;
+int pvr_param_audio_bitrate = 0;
+char *pvr_param_audio_mode = NULL;
+int pvr_param_bitrate = 0;
+char *pvr_param_bitrate_mode = NULL;
+int pvr_param_bitrate_peak = 0;
+char *pvr_param_stream_type = NULL;
+
+struct pvr_t {
+  int dev_fd;
+  char *video_dev;
+
+  /* v4l2 params */
+  int mute;
+  int input;
+  int normid;
+  int brightness;
+  int contrast;
+  int hue;
+  int saturation;
+  int width;
+  int height;
+  char *freq;
+
+  /* ivtv params */
+  int aspect;
+  int samplerate;
+  int layer;
+  int audio_rate;
+  int audio_mode;
+  int bitrate;
+  int bitrate_mode;
+  int bitrate_peak;
+  int stream_type;
+};
+
+static struct pvr_t *
+pvr_init (void)
+{
+  struct pvr_t *pvr = NULL;
+
+  pvr = malloc (sizeof (struct pvr_t)); 
+  pvr->dev_fd = -1;
+  pvr->video_dev = strdup (PVR_DEFAULT_DEVICE);
+
+  /* v4l2 params */
+  pvr->mute = 0;
+  pvr->input = 0;
+  pvr->normid = -1;
+  pvr->brightness = 0;
+  pvr->contrast = 0;
+  pvr->hue = 0;
+  pvr->saturation = 0;
+  pvr->width = -1;
+  pvr->height = -1;
+  pvr->freq = NULL;
+
+  /* ivtv params */
+  pvr->aspect = -1;
+  pvr->samplerate = -1;
+  pvr->layer = -1;
+  pvr->audio_rate = -1;
+  pvr->audio_mode = -1;
+  pvr->bitrate = -1;
+  pvr->bitrate_mode = -1;
+  pvr->bitrate_peak = -1;
+  pvr->stream_type = -1;
+  
+  return pvr;
+}
+
+static void
+pvr_uninit (struct pvr_t *pvr)
+{
+  if (!pvr)
+    return;
+
+  /* close device */
+  if (pvr->dev_fd)
+    close (pvr->dev_fd);
+  
+  if (pvr->video_dev)
+    free (pvr->video_dev);
+  if (pvr->freq)
+    free (pvr->freq);
+  free (pvr);
+}
+
+/* IVTV layer */
+
+static void
+parse_ivtv_options (struct pvr_t *pvr)
+{
+  if (!pvr)
+    return;
+
+  /* -pvr aspect=digit */
+  if (pvr_param_aspect_ratio >= 1 && pvr_param_aspect_ratio <= 4)
+    pvr->aspect = pvr_param_aspect_ratio;
+
+  /* -pvr arate=x */
+  if (pvr_param_sample_rate != 0)
+  {
+    switch (pvr_param_sample_rate)
+    {
+    case 32000:
+      pvr->samplerate = PVR_AUDIO_SAMPLE_RATE_32_KHZ;
+      break;
+    case 44100:
+      pvr->samplerate = PVR_AUDIO_SAMPLE_RATE_44_1_KHZ;
+      break;
+    case 48000:
+      pvr->samplerate = PVR_AUDIO_SAMPLE_RATE_48_KHZ;
+      break;
+    default:
+      break;
+    }
+  }
+
+  /* -pvr alayer=x */
+  if (pvr_param_audio_layer == 1)
+    pvr->layer = PVR_AUDIO_LAYER_1;
+  else if (pvr_param_audio_layer == 2)
+    pvr->layer = PVR_AUDIO_LAYER_2;
+
+  /* -pvr abitrate=x */
+  if (pvr_param_audio_bitrate != 0)
+  {
+    /* set according to layer or use layer 1 by default if not specified */
+    switch (pvr_param_audio_bitrate)
+    {
+    case 32:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_32;
+      break;
+    case 48:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_48;
+      break;
+    case 56:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_56;
+      break;
+    case 64:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_64 : PVR_AUDIO_BITRATE_L1_64;
+      break;
+    case 80:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_80;
+      break;
+    case 96:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_96 : PVR_AUDIO_BITRATE_L1_96;
+      break;
+    case 112:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L2_112;
+      break;
+    case 128:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_128 : PVR_AUDIO_BITRATE_L1_128;
+      break;
+    case 160:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_160 : PVR_AUDIO_BITRATE_L1_160;
+      break;
+    case 192:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_192 : PVR_AUDIO_BITRATE_L1_192;
+      break;
+    case 224:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_224 : PVR_AUDIO_BITRATE_L1_224;
+      break;
+    case 256:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_256 : PVR_AUDIO_BITRATE_L1_256;
+      break;
+    case 288:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_288;
+      break;
+    case 320:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_320 : PVR_AUDIO_BITRATE_L1_320;
+      break;
+    case 352:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_352;
+      break;
+    case 384:
+      pvr->audio_rate = (pvr_param_audio_layer == 2) ?
+        PVR_AUDIO_BITRATE_L2_384 : PVR_AUDIO_BITRATE_L1_384;
+      break;
+    case 416:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_416;
+      break;
+    case 448:
+      pvr->audio_rate = PVR_AUDIO_BITRATE_L1_448;
+      break;
+    default:
+      break;
+    }
+  }
+  
+  /* -pvr amode=x */
+  if (pvr_param_audio_mode)
+  {
+    if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_STEREO))
+      pvr->audio_mode = PVR_AUDIO_MODE_STEREO;
+    else if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_JOINT_STEREO))
+      pvr->audio_mode = PVR_AUDIO_MODE_JOINT_STEREO;
+    else if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_DUAL))
+      pvr->audio_mode = PVR_AUDIO_MODE_DUAL;
+    else if (!strcmp (pvr_param_audio_mode, PVR_AUDIO_MODE_ARG_MONO))
+      pvr->audio_mode = PVR_AUDIO_MODE_MONO;
+    else /* for anything else, set to stereo */
+      pvr->audio_mode = PVR_AUDIO_MODE_STEREO;
+  }
+
+  /* -pvr vbitrate=x */
+  if (pvr_param_bitrate)
+    pvr->bitrate = pvr_param_bitrate;
+
+  /* -pvr vmode=x */
+  if (pvr_param_bitrate_mode)
+  {
+    if (!strcmp (pvr_param_bitrate_mode, PVR_VIDEO_BITRATE_MODE_ARG_VBR))
+      pvr->bitrate_mode = PVR_VIDEO_BITRATE_MODE_VBR;
+    else if (!strcmp (pvr_param_bitrate_mode, PVR_VIDEO_BITRATE_MODE_ARG_CBR))
+      pvr->bitrate_mode = PVR_VIDEO_BITRATE_MODE_CBR;
+    else /* for anything else, set to VBR */
+      pvr->bitrate_mode = PVR_VIDEO_BITRATE_MODE_VBR;
+  }
+
+  /* -pvr vpeak=x */
+  if (pvr_param_bitrate_peak)
+    pvr->bitrate_peak = pvr_param_bitrate_peak;
+
+  /* -pvr fmt=x */
+  if (pvr_param_stream_type)
+  {
+    if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_PS))
+      pvr->stream_type = IVTV_STREAM_PS;
+    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_TS))
+      pvr->stream_type = IVTV_STREAM_TS;
+    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_MPEG1))
+      pvr->stream_type = IVTV_STREAM_MPEG1;
+    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_DVD))
+      pvr->stream_type = IVTV_STREAM_DVD;
+    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_VCD))
+      pvr->stream_type = IVTV_STREAM_VCD;
+    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_SVCD))
+      pvr->stream_type = IVTV_STREAM_SVCD;
+    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_DVD_S1))
+      pvr->stream_type = IVTV_STREAM_DVD_S1;
+    else if (!strcmp (pvr_param_stream_type, PVR_VIDEO_STREAM_TYPE_DVD_S2))
+      pvr->stream_type = IVTV_STREAM_DVD_S2;
+    else /* for anything else, set to MPEG PS */
+      pvr->stream_type = IVTV_STREAM_PS;
+  }
+}
+
+static int
+set_ivtv_settings (struct pvr_t *pvr)
+{
+  struct ivtv_ioctl_codec codec;
+
+  if (!pvr)
+    return -1;
+  
+  if (pvr->dev_fd < 0)
+    return -1;
+
+  /* get current settings */
+  if (ioctl (pvr->dev_fd, IVTV_IOC_G_CODEC, &codec) < 0)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't get codec (%s).\n", LOG_LEVEL_IVTV, strerror (errno));
+    return -1;
+  }
+  
+  /* set default encoding settings
+   * may be overlapped by user parameters
+   * Use VBR MPEG_PS encoding at 6 Mbps (peak at 9.6 Mbps)
+   * with 48 KHz L2 384 kbps audio.
+   */
+  codec.aspect = PVR_ASPECT_RATIO_4_3;
+  codec.bitrate_mode = PVR_VIDEO_BITRATE_MODE_VBR;
+  codec.bitrate = 6000000;
+  codec.bitrate_peak = 9600000;
+  codec.stream_type = IVTV_STREAM_PS;
+  codec.audio_bitmask = PVR_AUDIO_LAYER_2
+    | PVR_AUDIO_BITRATE_L2_384 | PVR_AUDIO_SAMPLE_RATE_48_KHZ;
+
+  /* set aspect ratio */
+  if (pvr->aspect != -1)
+    codec.aspect = pvr->aspect;
+
+  /* if user value is given, we need to reset audio bitmask */
+  if ((pvr->samplerate != -1) || (pvr->layer != -1)
+      || (pvr->audio_rate != -1) || (pvr->audio_mode != -1))
+    codec.audio_bitmask = 0;
+  
+  /* set audio samplerate */
+  if (pvr->samplerate != -1)
+    codec.audio_bitmask |= pvr->samplerate;
+
+  /* set audio layer */
+  if (pvr->layer != -1)
+    codec.audio_bitmask |= pvr->layer;
+
+  /* set audio bitrate */
+  if (pvr->audio_rate != -1)
+    codec.audio_bitmask |= pvr->audio_rate;
+
+  /* set audio mode */
+  if (pvr->audio_mode != -1)
+    codec.audio_bitmask |= pvr->audio_mode;
+
+  /* set video bitrate */
+  if (pvr->bitrate != -1)
+    codec.bitrate = pvr->bitrate;
+
+  /* set video bitrate mode */
+  if (pvr->bitrate_mode != -1)
+    codec.bitrate_mode = pvr->bitrate_mode;
+
+  /* set video bitrate peak */
+  if (pvr->bitrate != -1)
+    codec.bitrate_peak = pvr->bitrate_peak;
+
+  /* set video stream type */
+  if (pvr->stream_type != -1)
+    codec.stream_type = pvr->stream_type;
+
+  /* set new encoding settings */
+  if (ioctl (pvr->dev_fd, IVTV_IOC_S_CODEC, &codec) < 0)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't set codec (%s).\n", LOG_LEVEL_IVTV, strerror (errno));
+    return -1;
+  }
+
+  return 0;
+}
+
+/* V4L2 layer */
+
+static void
+parse_v4l2_tv_options (struct pvr_t *pvr)
+{
+  if (!pvr)
+    return;
+  
+  if (tv_param_device)
+  {
+    if (pvr->video_dev)
+      free (pvr->video_dev);
+    pvr->video_dev = strdup (tv_param_device);
+  }
+  
+  if (tv_param_noaudio)
+    pvr->mute = tv_param_noaudio;
+
+  if (tv_param_input)
+    pvr->input = tv_param_input;
+  
+  if (tv_param_normid)
+    pvr->normid = tv_param_normid;
+  
+  if (tv_param_brightness)
+    pvr->brightness = tv_param_brightness;
+  
+  if (tv_param_contrast)
+    pvr->contrast = tv_param_contrast;
+  
+  if (tv_param_hue)
+    pvr->hue = tv_param_hue;
+  
+  if (tv_param_saturation)
+    pvr->saturation = tv_param_saturation;
+
+  if (tv_param_width)
+    pvr->width = tv_param_width;
+
+  if (tv_param_height)
+    pvr->height = tv_param_height;
+
+  if (tv_param_freq)
+    pvr->freq = strdup (tv_param_freq);
+}
+
+static int
+set_v4l2_settings (struct pvr_t *pvr)
+{
+  if (!pvr)
+    return -1;
+  
+  if (pvr->dev_fd < 0)
+    return -1;
+
+  /* -tv noaudio */
+  if (pvr->mute)
+  {
+    struct v4l2_control ctrl;
+    ctrl.id = V4L2_CID_AUDIO_MUTE;
+    ctrl.value = 1;
+    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't mute (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
+      return -1;
+    }
+  }
+
+  /* -tv input=x */
+  if (pvr->input != 0)
+  {
+    if (ioctl (pvr->dev_fd, VIDIOC_S_INPUT, &pvr->input) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set input (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
+      return -1;
+    }
+  }
+  
+  /* -tv normid=x */
+  if (pvr->normid != -1)
+  {
+    struct v4l2_standard std;
+    std.index = pvr->normid;
+
+    if (ioctl (pvr->dev_fd, VIDIOC_ENUMSTD, &std) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set norm (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
+      return -1;
+    }
+
+    mp_msg (MSGT_OPEN, MSGL_V,
+            "%s set norm to %s\n", LOG_LEVEL_V4L2, std.name);
+
+    if (ioctl (pvr->dev_fd, VIDIOC_S_STD, &std.id) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set norm (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
+      return -1;
+    }
+  }
+  
+  /* -tv brightness=x */
+  if (pvr->brightness != 0)
+  {
+    struct v4l2_control ctrl;
+    ctrl.id = V4L2_CID_BRIGHTNESS;
+    ctrl.value = pvr->brightness;
+
+    if (ctrl.value < 0)
+      ctrl.value = 0;
+    if (ctrl.value > 255)
+      ctrl.value = 255;
+    
+    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set brightness to %d (%s).\n",
+              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
+      return -1;
+    }
+  }
+
+  /* -tv contrast=x */
+  if (pvr->contrast != 0)
+  {
+    struct v4l2_control ctrl;
+    ctrl.id = V4L2_CID_CONTRAST;
+    ctrl.value = pvr->contrast;
+
+    if (ctrl.value < 0)
+      ctrl.value = 0;
+    if (ctrl.value > 127)
+      ctrl.value = 127;
+    
+    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set contrast to %d (%s).\n",
+              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
+      return -1;
+    }
+  }
+
+  /* -tv hue=x */
+  if (pvr->hue != 0)
+  {
+    struct v4l2_control ctrl;
+    ctrl.id = V4L2_CID_HUE;
+    ctrl.value = pvr->hue;
+
+    if (ctrl.value < -128)
+      ctrl.value = -128;
+    if (ctrl.value > 127)
+      ctrl.value = 127;
+    
+    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set hue to %d (%s).\n",
+              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
+      return -1;
+    }
+  }
+  
+  /* -tv saturation=x */
+  if (pvr->saturation != 0)
+  {
+    struct v4l2_control ctrl;
+    ctrl.id = V4L2_CID_SATURATION;
+    ctrl.value = pvr->saturation;
+
+    if (ctrl.value < 0)
+      ctrl.value = 0;
+    if (ctrl.value > 127)
+      ctrl.value = 127;
+    
+    if (ioctl (pvr->dev_fd, VIDIOC_S_CTRL, &ctrl) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set saturation to %d (%s).\n",
+              LOG_LEVEL_V4L2, ctrl.value, strerror (errno));
+      return -1;
+    }
+  }
+  
+  /* -tv width=x:height=y */
+  if (pvr->width && pvr->height)
+  {
+    struct v4l2_format vfmt;
+    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    vfmt.fmt.pix.width = pvr->width;
+    vfmt.fmt.pix.height = pvr->height;
+
+    if (ioctl (pvr->dev_fd, VIDIOC_S_FMT, &vfmt) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't set resolution to %dx%d (%s).\n",
+              LOG_LEVEL_V4L2, pvr->width, pvr->height, strerror (errno));
+      return -1;
+    }
+  }
+
+  /* -tv freq=x */
+  if (pvr->freq)
+  {
+    struct v4l2_frequency vf;
+    vf.tuner = 0;
+    vf.type = 0;
+    vf.frequency = strtol (pvr->freq, 0L, 0);
+    mp_msg (MSGT_OPEN, MSGL_INFO,
+            "%s setting frequency to %d\n", LOG_LEVEL_V4L2, vf.frequency);
+    
+    if (ioctl (pvr->dev_fd, VIDIOC_S_FREQUENCY, &vf) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR, "%s can't set frequency (%s).\n",
+              LOG_LEVEL_V4L2, strerror (errno));
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+static int
+v4l2_list_capabilities (struct pvr_t *pvr)
+{
+  struct v4l2_audio vaudio;
+  struct v4l2_standard vs;
+  struct v4l2_input vin;
+  int err = 0;
+  
+  if (!pvr)
+    return -1;
+
+  if (pvr->dev_fd < 0)
+    return -1;
+  
+  /* list available video inputs */
+  vin.index = 0;
+  err = 1;
+  mp_msg (MSGT_OPEN, MSGL_INFO,
+          "%s Available video inputs: ", LOG_LEVEL_V4L2);
+  while (ioctl (pvr->dev_fd, VIDIOC_ENUMINPUT, &vin) >= 0)
+  {
+    err = 0;
+    mp_msg (MSGT_OPEN, MSGL_INFO, "'#%d, %s' ", vin.index, vin.name);
+    vin.index++;
+  }
+  if (err)
+  {
+    mp_msg (MSGT_OPEN, MSGL_INFO, "none\n");
+    return -1;
+  }
+  else
+    mp_msg (MSGT_OPEN, MSGL_INFO, "\n");
+
+  /* list available audio inputs */
+  vaudio.index = 0;
+  err = 1;
+  mp_msg (MSGT_OPEN, MSGL_INFO,
+          "%s Available audio inputs: ", LOG_LEVEL_V4L2);
+  while (ioctl (pvr->dev_fd, VIDIOC_ENUMAUDIO, &vaudio) >= 0)
+  {
+    err = 0;
+    mp_msg (MSGT_OPEN, MSGL_INFO, "'#%d, %s' ", vaudio.index, vaudio.name);
+    vaudio.index++;
+  }
+  if (err)
+  {
+    mp_msg (MSGT_OPEN, MSGL_INFO, "none\n");
+    return -1;
+  }
+  else
+    mp_msg (MSGT_OPEN, MSGL_INFO, "\n");
+
+  /* list available norms */
+  vs.index = 0;
+  mp_msg (MSGT_OPEN, MSGL_INFO, "%s Available norms: ", LOG_LEVEL_V4L2);
+  while (ioctl (pvr->dev_fd, VIDIOC_ENUMSTD, &vs) >= 0)
+  {
+    err = 0;
+    mp_msg (MSGT_OPEN, MSGL_INFO, "'#%d, %s' ", vs.index, vs.name);
+    vs.index++;
+  }
+  if (err)
+  {
+    mp_msg (MSGT_OPEN, MSGL_INFO, "none\n");
+    return -1;
+  }
+  else
+    mp_msg (MSGT_OPEN, MSGL_INFO, "\n");
+
+  return 0;
+}
+
+static int
+v4l2_display_settings (struct pvr_t *pvr)
+{
+  struct v4l2_audio vaudio;
+  struct v4l2_standard vs;
+  struct v4l2_input vin;
+  v4l2_std_id std;
+  int input;
+  
+  if (!pvr)
+    return -1;
+
+  if (pvr->dev_fd < 0)
+    return -1;
+
+  /* get current video input */
+  if (ioctl (pvr->dev_fd, VIDIOC_G_INPUT, &input) == 0)
+  {
+    vin.index = input;
+    if (ioctl (pvr->dev_fd, VIDIOC_ENUMINPUT, &vin) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
+      return -1;
+    }
+    else
+      mp_msg (MSGT_OPEN, MSGL_INFO,
+              "%s Video input: %s\n", LOG_LEVEL_V4L2, vin.name);
+  }
+  else
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
+    return -1;
+  }
+
+  /* get current audio input */
+  if (ioctl (pvr->dev_fd, VIDIOC_G_AUDIO, &vaudio) == 0)
+  {
+    vaudio.index = input;
+    if (ioctl (pvr->dev_fd, VIDIOC_ENUMAUDIO, &vaudio) < 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
+      return -1;
+    }
+    else
+      mp_msg (MSGT_OPEN, MSGL_INFO,
+              "%s Audio input: %s\n", LOG_LEVEL_V4L2, vaudio.name);
+  }
+  else
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't get input (%s).\n", LOG_LEVEL_V4L2, strerror (errno));
+    return -1;
+  }
+
+  /* get current video format */
+  if (ioctl (pvr->dev_fd, VIDIOC_G_STD, &std) == 0)
+  {
+    vs.index = 0;
+
+    while (ioctl (pvr->dev_fd, VIDIOC_ENUMSTD, &vs) >= 0)
+    {
+      if (vs.id == std)
+      {
+        mp_msg (MSGT_OPEN, MSGL_INFO,
+                "%s Norm: %s.\n", LOG_LEVEL_V4L2, vs.name);
+        break;
+      }
+      vs.index++;
+    }
+  }
+  else
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't get norm (%s)\n", LOG_LEVEL_V4L2, strerror (errno));
+    return -1;
+  }
+
+  return 0;
+}
+
+/* stream layer */
+
+static void
+pvr_stream_close (stream_t *stream)
+{
+  struct pvr_t *pvr;
+
+  if (!stream)
+    return;
+  
+  pvr = (struct pvr_t *) stream->priv;
+  pvr_uninit (pvr);
+}
+
+static int
+pvr_stream_read (stream_t *stream, char *buffer, int size)
+{
+  struct pollfd pfds[1];
+  struct pvr_t *pvr;
+  int rk, fd, pos;
+
+  if (!stream || !buffer)
+    return 0;
+  
+  pvr = (struct pvr_t *) stream->priv;
+  fd = pvr->dev_fd;
+  pos = 0;
+
+  if (fd < 0)
+    return 0;
+  
+  while (pos < size)
+  {
+    pfds[0].fd = fd;
+    pfds[0].events = POLLIN | POLLPRI;
+
+    rk = size - pos;
+
+    if (poll (pfds, 1, 500) <= 0)
+    {
+      mp_msg (MSGT_OPEN, MSGL_ERR,
+              "%s failed with errno %d when reading %d bytes\n",
+              LOG_LEVEL_PVR, errno, size-pos);
+      break;
+    }
+
+    rk = read (fd, &buffer[pos], rk);
+    if (rk > 0)
+    {
+      pos += rk;
+      mp_msg (MSGT_OPEN, MSGL_DBG3,
+              "%s read (%d) bytes\n", LOG_LEVEL_PVR, pos);
+    }
+  }
+		
+  if (!pos)
+    mp_msg (MSGT_OPEN, MSGL_ERR, "%s read %d bytes\n", LOG_LEVEL_PVR, pos);
+
+  return pos;
+}
+
+static int
+pvr_stream_open (stream_t *stream, int mode, void *opts, int *file_format)
+{
+  struct ivtv_ioctl_codec codec;
+  struct ivtv_driver_info info;
+  struct v4l2_capability vcap;
+  struct pvr_t *pvr = NULL;
+  
+  if (mode != STREAM_READ)
+    return STREAM_UNSUPORTED;
+  
+  pvr = pvr_init ();
+
+  parse_v4l2_tv_options (pvr);
+  parse_ivtv_options (pvr);
+  
+  /* open device */
+  pvr->dev_fd = open (pvr->video_dev, O_RDWR);
+  mp_msg (MSGT_OPEN, MSGL_INFO,
+          "%s Using device %s\n", LOG_LEVEL_PVR, pvr->video_dev);
+  if (pvr->dev_fd == -1)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s error opening device %s\n", LOG_LEVEL_PVR, pvr->video_dev);
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+  
+  /* query capabilities (i.e test V4L2 support) */
+  if (ioctl (pvr->dev_fd, VIDIOC_QUERYCAP, &vcap) < 0)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s device is not V4L2 compliant (%s).\n",
+            LOG_LEVEL_PVR, strerror (errno));
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+  else
+    mp_msg (MSGT_OPEN, MSGL_INFO,
+            "%s Detected %s\n", LOG_LEVEL_PVR, vcap.card);
+
+  /* get codec and initialize card (i.e test IVTV support) */
+  if (ioctl (pvr->dev_fd, IVTV_IOC_G_CODEC, &codec) < 0)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s device is not IVTV compliant (%s).\n",
+            LOG_LEVEL_PVR, strerror (errno));
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+  
+  /* get ivtv driver info */
+  if (ioctl (pvr->dev_fd, IVTV_IOC_G_DRIVER_INFO, &info) < 0)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s device is not IVTV compliant (%s).\n",
+            LOG_LEVEL_PVR, strerror (errno));
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+  else
+    mp_msg (MSGT_OPEN, MSGL_INFO,
+            "%s Detected ivtv driver: %s\n", LOG_LEVEL_PVR, info.comment);
+
+  /* list V4L2 capabilities */
+  if (v4l2_list_capabilities (pvr) == -1)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't get v4l2 capabilities\n", LOG_LEVEL_PVR);
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+  
+  /* apply V4L2 settings */
+  if (set_v4l2_settings (pvr) == -1)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't set v4l2 settings\n", LOG_LEVEL_PVR);
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+
+  /* apply IVTV settings */
+  if (set_ivtv_settings (pvr) == -1)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't set ivtv settings\n", LOG_LEVEL_PVR);
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+  
+  /* display current V4L2 settings */
+  if (v4l2_display_settings (pvr) == -1)
+  {
+    mp_msg (MSGT_OPEN, MSGL_ERR,
+            "%s can't get v4l2 settings\n", LOG_LEVEL_PVR);
+    pvr_uninit (pvr);
+    return STREAM_ERROR;
+  }
+
+  stream->priv = pvr;
+  stream->type = STREAMTYPE_PVR;
+  stream->fill_buffer = pvr_stream_read;
+  stream->close = pvr_stream_close;
+  
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_pvr = {
+  "PVR (V4L2/IVTV) Input",
+  "pvr",
+  "Benjamin Zores",
+  "",
+  pvr_stream_open, 			
+  { "pvr", NULL },
+  NULL,
+  1
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_rtsp.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,176 @@
+/*
+ *  Copyright (C) 2006 Benjamin Zores
+ *   based on previous Real RTSP support from Roberto Togni and xine team.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include "config.h"
+#ifndef HAVE_WINSOCK2
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#define closesocket close
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#include <errno.h>
+
+#include "stream.h"
+#include "librtsp/rtsp.h"
+#include "librtsp/rtsp_session.h"
+
+#define RTSP_DEFAULT_PORT 554
+
+extern int network_bandwidth;
+
+static int
+rtsp_streaming_read (int fd, char *buffer,
+                     int size, streaming_ctrl_t *stream_ctrl)
+{
+  return rtsp_session_read (stream_ctrl->data, buffer, size);
+}
+
+static int
+rtsp_streaming_start (stream_t *stream)
+{
+  int fd;
+  rtsp_session_t *rtsp;
+  char *mrl;
+  char *file;
+  int port;
+  int redirected, temp;
+
+  if (!stream)
+    return -1;
+
+  /* counter so we don't get caught in infinite redirections */
+  temp = 5;
+
+  do {
+    redirected = 0;
+
+    fd = connect2Server (stream->streaming_ctrl->url->hostname,
+                         port = (stream->streaming_ctrl->url->port ?
+                                 stream->streaming_ctrl->url->port :
+                                 RTSP_DEFAULT_PORT), 1);
+    
+    if (fd < 0 && !stream->streaming_ctrl->url->port)
+      fd = connect2Server (stream->streaming_ctrl->url->hostname,
+                           port = 7070, 1);
+
+    if (fd < 0)
+      return -1;
+    
+    file = stream->streaming_ctrl->url->file;
+    if (file[0] == '/')
+      file++;
+
+    mrl = malloc (strlen (stream->streaming_ctrl->url->hostname)
+                  + strlen (file) + 16);
+    
+    sprintf (mrl, "rtsp://%s:%i/%s",
+             stream->streaming_ctrl->url->hostname, port, file);
+
+    rtsp = rtsp_session_start (fd, &mrl, file,
+                               stream->streaming_ctrl->url->hostname,
+                               port, &redirected,
+                               stream->streaming_ctrl->bandwidth);
+
+    if (redirected == 1)
+    {
+      url_free (stream->streaming_ctrl->url);
+      stream->streaming_ctrl->url = url_new (mrl);
+      closesocket (fd);
+    }
+
+    free (mrl);
+    temp--;
+  } while ((redirected != 0) && (temp > 0));    
+
+  if (!rtsp)
+    return -1;
+
+  stream->fd = fd;
+  stream->streaming_ctrl->data = rtsp;
+  
+  stream->streaming_ctrl->streaming_read = rtsp_streaming_read;
+  stream->streaming_ctrl->streaming_seek = NULL;
+  stream->streaming_ctrl->prebuffer_size = 128*1024;  // 640 KBytes
+  stream->streaming_ctrl->buffering = 1;
+  stream->streaming_ctrl->status = streaming_playing_e;
+  
+  return 0;
+}
+
+static void
+rtsp_streaming_close (struct stream_st *s)
+{
+  rtsp_session_t *rtsp = NULL;
+  
+  rtsp = (rtsp_session_t *) s->streaming_ctrl->data;
+  if (rtsp)
+    rtsp_session_end (rtsp);
+}
+
+static int
+rtsp_streaming_open (stream_t *stream, int mode, void *opts, int *file_format)
+{
+  URL_t *url;
+  extern int index_mode;
+  
+  mp_msg (MSGT_OPEN, MSGL_INFO, "STREAM_RTSP, URL: %s\n", stream->url);
+  stream->streaming_ctrl = streaming_ctrl_new ();
+  if (!stream->streaming_ctrl)
+    return STREAM_ERROR;
+
+  stream->streaming_ctrl->bandwidth = network_bandwidth;
+  url = url_new (stream->url);
+  stream->streaming_ctrl->url = check4proxies (url);
+
+  stream->fd = -1;
+  index_mode = -1; /* prevent most RTSP streams from locking due to -idx */
+  if (rtsp_streaming_start (stream) < 0)
+  {
+    streaming_ctrl_free (stream->streaming_ctrl);
+    stream->streaming_ctrl = NULL;
+    return STREAM_UNSUPORTED;
+  }
+
+  fixup_network_stream_cache (stream);
+  stream->type = STREAMTYPE_STREAM;
+  stream->close = rtsp_streaming_close;
+
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_rtsp = {
+  "RTSP streaming",
+  "rtsp",
+  "Benjamin Zores, Roberto Togni",
+  "ported from xine",
+  rtsp_streaming_open,
+  {"rtsp", NULL},
+  NULL,
+  0 /* Urls are an option string */
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_smb.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,148 @@
+
+#include "config.h"
+
+#include <libsmbclient.h>
+#include <unistd.h>
+
+#include "mp_msg.h"
+#include "stream.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+static struct stream_priv_s {
+} stream_priv_dflts = {
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+// URL definition
+static m_option_t stream_opts_fields[] = {
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+
+static struct m_struct_st stream_opts = {
+  "smb",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+static char smb_password[15];
+static char smb_username[15];
+
+static void smb_auth_fn(const char *server, const char *share,
+             char *workgroup, int wgmaxlen, char *username, int unmaxlen,
+	     char *password, int pwmaxlen)
+{
+  char temp[128];
+  
+  strcpy(temp, "LAN");				  
+  if (temp[strlen(temp) - 1] == 0x0a)
+    temp[strlen(temp) - 1] = 0x00;
+  
+  if (temp[0]) strncpy(workgroup, temp, wgmaxlen - 1);
+  
+  strcpy(temp, smb_username); 
+  if (temp[strlen(temp) - 1] == 0x0a)
+    temp[strlen(temp) - 1] = 0x00;
+  
+  if (temp[0]) strncpy(username, temp, unmaxlen - 1);
+						      
+  strcpy(temp, smb_password); 
+  if (temp[strlen(temp) - 1] == 0x0a)
+    temp[strlen(temp) - 1] = 0x00;
+								
+   if (temp[0]) strncpy(password, temp, pwmaxlen - 1);
+}
+
+static int seek(stream_t *s,off_t newpos) {
+  s->pos = newpos;
+  if(smbc_lseek(s->fd,s->pos,SEEK_SET)<0) {
+    s->eof=1;
+    return 0;
+  }
+  return 1;
+}
+
+static int fill_buffer(stream_t *s, char* buffer, int max_len){
+  int r = smbc_read(s->fd,buffer,max_len);
+  return (r <= 0) ? -1 : r;
+}
+
+static int write_buffer(stream_t *s, char* buffer, int len) {
+  int r = smbc_write(s->fd,buffer,len);
+  return (r <= 0) ? -1 : r;
+}
+
+static void close_f(stream_t *s){
+  smbc_close(s->fd);
+}
+
+static int open_f (stream_t *stream, int mode, void *opts, int* file_format) {
+  struct stream_priv_s *p = (struct stream_priv_s*)opts;
+  char *filename;
+  mode_t m = 0;
+  off_t len;
+  int fd, err;
+  
+  filename = stream->url;
+  
+  if(mode == STREAM_READ)
+    m = O_RDONLY;
+  else if (mode == STREAM_WRITE) //who's gonna do that ?
+    m = O_WRONLY;
+  else {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "[smb] Unknown open mode %d\n", mode);
+    m_struct_free (&stream_opts, opts);
+    return STREAM_UNSUPORTED;
+  }
+  
+  if(!filename) {
+    mp_msg(MSGT_OPEN,MSGL_ERR, "[smb] Bad url\n");
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+  
+  err = smbc_init(smb_auth_fn, 1);
+  if (err < 0) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_SMBInitError,err);
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+  
+  fd = smbc_open(filename, m,0644);
+  if (fd < 0) {	
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_SMBFileNotFound, filename);
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+  
+  len = smbc_lseek(fd,0,SEEK_END);
+  smbc_lseek (fd, 0, SEEK_SET);
+  if (len <= 0)
+    stream->flags = 0;
+  else {
+    stream->flags = STREAM_READ | STREAM_SEEK;
+    stream->end_pos = len;
+    stream->seek = seek;
+  }
+  stream->type = STREAMTYPE_SMB;
+  stream->fd = fd;
+  stream->fill_buffer = fill_buffer;
+  stream->write_buffer = write_buffer;
+  stream->close = close_f;
+  
+  m_struct_free(&stream_opts, opts);
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_smb = {
+  "Server Message Block",
+  "smb",
+  "M. Tourne",
+  "based on the code from 'a bulgarian' (one says)",
+  open_f,
+  {"smb", NULL},
+  &stream_opts,
+  0 //Url is an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_vcd.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,152 @@
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "stream.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/cdrio.h>
+#include "vcd_read_fbsd.h" 
+#elif defined(__NetBSD__) || defined (__OpenBSD__)
+#include "vcd_read_nbsd.h"
+#elif defined(SYS_DARWIN)
+#include "vcd_read_darwin.h" 
+#else
+#include "vcd_read.h"
+#endif
+
+extern char *cdrom_device;
+
+static struct stream_priv_s {
+  int track;
+  char* device;
+} stream_priv_dflts = {
+  1,
+  NULL
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  { "track", ST_OFF(track), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
+  { "device", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  /// For url parsing
+  { "hostname", ST_OFF(track), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
+  { "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+  "vcd",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+static int fill_buffer(stream_t *s, char* buffer, int max_len){
+  if(s->pos > s->end_pos) /// don't past end of current track
+    return 0;
+  return vcd_read(s->priv,buffer);
+}
+
+static int seek(stream_t *s,off_t newpos) {
+  s->pos = newpos;
+  vcd_set_msf(s->priv,s->pos/VCD_SECTOR_DATA);
+  return 1;
+}
+
+static void close_s(stream_t *stream) {
+  free(stream->priv);
+}
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+  int ret,ret2,f;
+  mp_vcd_priv_t* vcd;
+#ifdef __FreeBSD__
+  int bsize = VCD_SECTOR_SIZE;
+#endif
+
+  if(mode != STREAM_READ) {
+    m_struct_free(&stream_opts,opts);
+    return STREAM_UNSUPORTED;
+  }
+
+  if (!p->device) {
+    if(cdrom_device)
+      p->device = strdup(cdrom_device);
+    else
+      p->device = strdup(DEFAULT_CDROM_DEVICE);
+  }
+
+  f=open(p->device,O_RDONLY);
+  if(f<0){ 
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CdDevNotfound,p->device);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+
+  vcd = vcd_read_toc(f);
+  if(!vcd) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"Failed to get cd toc\n");
+    close(f);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+  ret2=vcd_get_track_end(vcd,p->track);
+  if(ret2<0){
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (get)\n");
+    close(f);
+    free(vcd);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+  ret=vcd_seek_to_track(vcd,p->track);
+  if(ret<0){
+    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");
+    close(f);
+    free(vcd);
+    m_struct_free(&stream_opts,opts);
+    return STREAM_ERROR;
+  }
+  mp_msg(MSGT_OPEN,MSGL_V,"VCD start byte position: 0x%X  end: 0x%X\n",ret,ret2);
+
+#ifdef __FreeBSD__
+  if (ioctl (f, CDRIOCSETBLOCKSIZE, &bsize) == -1) {
+    mp_msg(MSGT_OPEN,MSGL_WARN,"Error in CDRIOCSETBLOCKSIZE");
+  }
+#endif
+
+  stream->fd = f;
+  stream->type = STREAMTYPE_VCD;
+  stream->sector_size = VCD_SECTOR_DATA;
+  stream->start_pos=ret;
+  stream->end_pos=ret2;
+  stream->priv = vcd;
+
+  stream->fill_buffer = fill_buffer;
+  stream->seek = seek;
+  stream->close = close_s;
+
+  m_struct_free(&stream_opts,opts);
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_vcd = {
+  "Video CD",
+  "vcd",
+  "Albeu",
+  "based on the code from ???",
+  open_s,
+  { "vcd", NULL },
+  &stream_opts,
+  1 // Urls are an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/stream_vstream.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,180 @@
+/*
+ *  stream_vstream.c
+ *
+ *	Copyright (C) Joey Parrish
+ *
+ *  This file is part of MPlayer, a free movie player.
+ *	
+ *  MPlayer is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  MPlayer is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ *
+ */
+
+/*
+ *   If you have a tivo with the vstream server installed, (and most tivo
+ *   hackers do,) then you can connect to it and stream ty files using
+ *   this module.  The url syntax is tivo://host/fsid or tivo://host/list
+ *   to list the available recordings and their fsid's.
+ *   This module depends on libvstream-client, which is available from
+ *   http://armory.nicewarrior.org/projects/vstream-client .
+ *
+ */
+
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include "mp_msg.h"
+#include "stream.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+
+#include <vstream-client.h>
+
+void vstream_error(const char *format, ...) {
+    char buf[1024];
+    va_list va;
+    va_start(va, format);
+    vsnprintf(buf, 1024, format, va);
+    va_end(va);
+    mp_msg(MSGT_STREAM, MSGL_ERR, buf);
+}
+
+static struct stream_priv_s {
+  char* host;
+  char* fsid;
+} stream_priv_dflts = {
+  NULL,
+  NULL
+};
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+  {"hostname", ST_OFF(host), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  {"filename", ST_OFF(fsid), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+  { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+
+static struct m_struct_st stream_opts = {
+  "vstream",
+  sizeof(struct stream_priv_s),
+  &stream_priv_dflts,
+  stream_opts_fields
+};
+
+static int fill_buffer(stream_t *s, char* buffer, int max_len){
+  struct stream_priv_s* p = (struct stream_priv_s*)s->priv;
+  int len = vstream_load_chunk(p->fsid, buffer, max_len, s->pos);
+  if (len <= 0) return 0;
+  return len;
+}
+
+static int seek(stream_t *s,off_t newpos) {
+  s->pos = newpos;
+  return 1;
+}
+
+static int control(struct stream_st *s,int cmd,void* arg) {
+  return STREAM_UNSUPORTED;
+}
+
+static void close_s(struct stream_st *s) {
+}
+
+static int open_s(stream_t *stream, int mode, void* opts, int* file_format) {
+  int f;
+  struct stream_priv_s* p = (struct stream_priv_s*)opts;
+
+  if(mode != STREAM_READ)
+    return STREAM_UNSUPORTED;
+
+  if(!p->host) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "We need a host name (ex: tivo://hostname/fsid)\n");
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+
+  if(!p->fsid || strlen(p->fsid) == 0) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "We need an fsid (ex: tivo://hostname/fsid)\n");
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+
+  f = connect2Server(p->host, VSERVER_PORT, 1);
+
+  if(f < 0) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "Connection to %s failed\n", p->host);
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+  stream->fd = f;
+
+  vstream_set_socket_fd(f);
+
+  if (!strcmp(p->fsid, "list")) {
+    vstream_list_streams(0);
+    return STREAM_ERROR;
+  } else if (!strcmp(p->fsid, "llist")) {
+    vstream_list_streams(1);
+    return STREAM_ERROR;
+  }
+
+  if (vstream_start()) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "Cryptic internal error #1\n");
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+  if (vstream_startstream(p->fsid)) {
+    mp_msg(MSGT_OPEN, MSGL_ERR, "Cryptic internal error #2\n");
+    m_struct_free(&stream_opts, opts);
+    return STREAM_ERROR;
+  }
+  
+  stream->start_pos = 0;
+  stream->end_pos = vstream_streamsize();
+  mp_msg(MSGT_OPEN, MSGL_DBG2, "Tivo stream size is %d\n", stream->end_pos);
+
+  stream->priv = p;
+  stream->fill_buffer = fill_buffer;
+  stream->control = control;
+  stream->seek = seek;
+  stream->close = close_s;
+  stream->type = STREAMTYPE_VSTREAM;
+
+  return STREAM_OK;
+}
+
+stream_info_t stream_info_vstream = {
+  "vstream client",
+  "vstream",
+  "Joey",
+  "",
+  open_s,
+  { "tivo", NULL },
+  &stream_opts,
+  1 // Url is an option string
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/tv.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,919 @@
+/*
+ TV Interface for MPlayer
+ 
+ (C) Alex Beregszaszi
+ 
+ API idea based on libvo2
+
+ Feb 19, 2002: Significant rewrites by Charles R. Henrich (henrich@msu.edu)
+				to add support for audio, and bktr *BSD support.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "config.h"
+
+int tv_param_on = 0;
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
+
+#include "libaf/af_format.h"
+#include "libvo/img_format.h"
+#include "libvo/fastmemcpy.h"
+
+#include "tv.h"
+
+#include "frequencies.h"
+
+/* some default values */
+int tv_param_audiorate = 44100;
+int tv_param_noaudio = 0;
+int tv_param_immediate = 0;
+char *tv_param_freq = NULL;
+char *tv_param_channel = NULL;
+char *tv_param_norm = "pal";
+#ifdef HAVE_TV_V4L2
+int tv_param_normid = -1;
+#endif
+char *tv_param_chanlist = "europe-east";
+char *tv_param_device = NULL;
+char *tv_param_driver = "dummy";
+int tv_param_width = -1;
+int tv_param_height = -1;
+int tv_param_input = 0; /* used in v4l and bttv */
+int tv_param_outfmt = -1;
+float tv_param_fps = -1.0;
+char **tv_param_channels = NULL;
+int tv_param_audio_id = 0;
+#if defined(HAVE_TV_V4L)
+int tv_param_amode = -1;
+int tv_param_volume = -1;
+int tv_param_bass = -1;
+int tv_param_treble = -1;
+int tv_param_balance = -1;
+int tv_param_forcechan = -1;
+int tv_param_force_audio = 0;
+int tv_param_buffer_size = -1;
+int tv_param_mjpeg = 0;
+int tv_param_decimation = 2;
+int tv_param_quality = 90;
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+int tv_param_alsa = 0;
+#endif
+char* tv_param_adevice = NULL;
+#endif
+int tv_param_brightness = 0;
+int tv_param_contrast = 0;
+int tv_param_hue = 0;
+int tv_param_saturation = 0;
+tv_channels_t *tv_channel_list;
+tv_channels_t *tv_channel_current, *tv_channel_last;
+char *tv_channel_last_real;
+
+/* ================== DEMUX_TV ===================== */
+/*
+  Return value:
+    0 = EOF(?) or no stream
+    1 = successfully read a packet
+*/
+/* fill demux->video and demux->audio */
+
+static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
+{
+    tvi_handle_t *tvh=(tvi_handle_t*)(demux->priv);
+    demux_packet_t* dp;
+    unsigned int len=0;
+
+    /* ================== ADD AUDIO PACKET =================== */
+
+    if (ds==demux->audio && tv_param_noaudio == 0 && 
+        tvh->functions->control(tvh->priv, 
+                                TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
+        {
+        len = tvh->functions->get_audio_framesize(tvh->priv);
+
+        dp=new_demux_packet(len);
+        dp->flags|=1; /* Keyframe */
+        dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len);
+        ds_add_packet(demux->audio,dp);
+        }
+
+    /* ================== ADD VIDEO PACKET =================== */
+
+    if (ds==demux->video && tvh->functions->control(tvh->priv, 
+                            TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE)
+        {
+		len = tvh->functions->get_video_framesize(tvh->priv);
+       	dp=new_demux_packet(len);
+		dp->flags|=1; /* Keyframe */
+  		dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len);
+   		ds_add_packet(demux->video,dp);
+	 }
+
+    return 1;
+}
+
+static int norm_from_string(tvi_handle_t *tvh, char* norm)
+{
+#ifdef HAVE_TV_V4L2
+    if (strcmp(tv_param_driver, "v4l2") != 0) {
+#endif
+    if (!strcasecmp(norm, "pal"))
+	return TV_NORM_PAL;
+    else if (!strcasecmp(norm, "ntsc"))
+	return TV_NORM_NTSC;
+    else if (!strcasecmp(norm, "secam"))
+	return TV_NORM_SECAM;
+    else if (!strcasecmp(norm, "palnc"))
+	return TV_NORM_PALNC;
+    else if (!strcasecmp(norm, "palm"))
+	return TV_NORM_PALM;
+    else if (!strcasecmp(norm, "paln"))
+	return TV_NORM_PALN;
+    else if (!strcasecmp(norm, "ntscjp"))
+	return TV_NORM_NTSCJP;
+    else {
+	mp_msg(MSGT_TV, MSGL_V, "tv.c: norm_from_string(%s): Bogus norm parameter, setting PAL.\n", norm);
+	return TV_NORM_PAL;
+    }
+#ifdef HAVE_TV_V4L2
+    } else {
+	tvi_functions_t *funcs = tvh->functions;
+	char str[8];
+	strncpy(str, norm, sizeof(str)-1);
+	str[sizeof(str)-1] = '\0';
+        if (funcs->control(tvh->priv, TVI_CONTROL_SPC_GET_NORMID, str) != TVI_CONTROL_TRUE)
+	    return 0;
+	return *(int *)str;
+    }
+#endif
+}
+
+static int open_tv(tvi_handle_t *tvh)
+{
+    int i;
+    tvi_functions_t *funcs = tvh->functions;
+    int tv_fmt_list[] = {
+      IMGFMT_YV12,
+      IMGFMT_I420,
+      IMGFMT_UYVY,
+      IMGFMT_YUY2,
+      IMGFMT_RGB32,
+      IMGFMT_RGB24,
+      IMGFMT_RGB16,
+      IMGFMT_RGB15
+    };
+
+    if (funcs->control(tvh->priv, TVI_CONTROL_IS_VIDEO, 0) != TVI_CONTROL_TRUE)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "Error: No video input present!\n");
+	return 0;
+    }
+
+    if (tv_param_outfmt == -1)
+      for (i = 0; i < sizeof (tv_fmt_list) / sizeof (*tv_fmt_list); i++)
+        {
+          tv_param_outfmt = tv_fmt_list[i];
+          if (funcs->control (tvh->priv, TVI_CONTROL_VID_SET_FORMAT,
+                              &tv_param_outfmt) == TVI_CONTROL_TRUE)
+            break;
+        }
+    else
+    {
+    switch(tv_param_outfmt)
+    {
+	case IMGFMT_YV12:
+	case IMGFMT_I420:
+	case IMGFMT_UYVY:
+	case IMGFMT_YUY2:
+	case IMGFMT_RGB32:
+	case IMGFMT_RGB24:
+	case IMGFMT_BGR32:
+	case IMGFMT_BGR24:
+	case IMGFMT_BGR16:
+	case IMGFMT_BGR15:
+	    break;
+	default:
+	    mp_msg(MSGT_TV, MSGL_ERR, "==================================================================\n");
+	    mp_msg(MSGT_TV, MSGL_ERR, " WARNING: UNTESTED OR UNKNOWN OUTPUT IMAGE FORMAT REQUESTED (0x%x)\n", tv_param_outfmt);
+	    mp_msg(MSGT_TV, MSGL_ERR, " This may cause buggy playback or program crash! Bug reports will\n");
+	    mp_msg(MSGT_TV, MSGL_ERR, " be ignored! You should try again with YV12 (which is the default\n");
+	    mp_msg(MSGT_TV, MSGL_ERR, " colorspace) and read the documentation!\n");
+	    mp_msg(MSGT_TV, MSGL_ERR, "==================================================================\n");
+    }
+    funcs->control(tvh->priv, TVI_CONTROL_VID_SET_FORMAT, &tv_param_outfmt);
+    }
+
+    /* set some params got from cmdline */
+    funcs->control(tvh->priv, TVI_CONTROL_SPC_SET_INPUT, &tv_param_input);
+
+#ifdef HAVE_TV_V4L2
+    if (!strcmp(tv_param_driver, "v4l2") && tv_param_normid >= 0) {
+	mp_msg(MSGT_TV, MSGL_V, "Selected norm id: %d\n", tv_param_normid);
+	if (funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tv_param_normid) != TVI_CONTROL_TRUE) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
+	}
+    } else {
+#endif
+    /* select video norm */
+    tvh->norm = norm_from_string(tvh, tv_param_norm);
+
+    mp_msg(MSGT_TV, MSGL_V, "Selected norm: %s\n", tv_param_norm);
+    if (funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->norm) != TVI_CONTROL_TRUE) {
+	mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
+    }
+#ifdef HAVE_TV_V4L2
+    }
+#endif
+
+#ifdef HAVE_TV_V4L1
+    if ( tv_param_mjpeg )
+    {
+      /* set width to expected value */
+      if (tv_param_width == -1)
+        {
+          tv_param_width = 704/tv_param_decimation;
+        }
+      if (tv_param_height == -1)
+        {
+	  if ( tvh->norm != TV_NORM_NTSC )
+            tv_param_height = 576/tv_param_decimation; 
+	  else
+            tv_param_height = 480/tv_param_decimation; 
+        }
+      mp_msg(MSGT_TV, MSGL_INFO, 
+	       "  MJP: width %d height %d\n", tv_param_width, tv_param_height);
+    }
+#endif
+
+    /* limits on w&h are norm-dependent -- JM */
+    /* set width */
+    if (tv_param_width != -1)
+    {
+	if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_WIDTH, &tv_param_width) == TVI_CONTROL_TRUE)
+	    funcs->control(tvh->priv, TVI_CONTROL_VID_SET_WIDTH, &tv_param_width);
+	else
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "Unable to set requested width: %d\n", tv_param_width);
+	    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &tv_param_width);
+	}    
+    }
+
+    /* set height */
+    if (tv_param_height != -1)
+    {
+	if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_HEIGHT, &tv_param_height) == TVI_CONTROL_TRUE)
+	    funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HEIGHT, &tv_param_height);
+	else
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "Unable to set requested height: %d\n", tv_param_height);
+	    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &tv_param_height);
+	}    
+    }
+
+    if (funcs->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE)
+    {
+	mp_msg(MSGT_TV, MSGL_WARN, "Selected input hasn't got a tuner!\n");	
+	goto done;
+    }
+
+    /* select channel list */
+    for (i = 0; chanlists[i].name != NULL; i++)
+    {
+	if (!strcasecmp(chanlists[i].name, tv_param_chanlist))
+	{
+	    tvh->chanlist = i;
+	    tvh->chanlist_s = chanlists[i].list;
+	    break;
+	}
+    }
+
+    if (tvh->chanlist == -1)
+	mp_msg(MSGT_TV, MSGL_WARN, "Unable to find selected channel list! (%s)\n",
+	    tv_param_chanlist);
+    else
+	mp_msg(MSGT_TV, MSGL_V, "Selected channel list: %s (including %d channels)\n",
+	    chanlists[tvh->chanlist].name, chanlists[tvh->chanlist].count);
+
+    if (tv_param_freq && tv_param_channel)
+    {
+	mp_msg(MSGT_TV, MSGL_WARN, "You can't set frequency and channel simultaneously!\n");
+	goto done;
+    }
+
+    /* Handle channel names */
+    if (tv_param_channels) {
+	char** channels = tv_param_channels;
+	mp_msg(MSGT_TV, MSGL_INFO, "TV channel names detected.\n");
+	tv_channel_list = malloc(sizeof(tv_channels_t));
+	tv_channel_list->index=1;
+	tv_channel_list->next=NULL;
+	tv_channel_list->prev=NULL;
+	tv_channel_current = tv_channel_list;
+
+	while (*channels) {
+		char* tmp = *(channels++);
+		char* sep = strchr(tmp,'-');
+		int i;
+		struct CHANLIST cl;
+
+		if (!sep) continue; // Wrong syntax, but mplayer should not crash
+
+		strlcpy(tv_channel_current->name, sep + 1,
+		        sizeof(tv_channel_current->name));
+		sep[0] = '\0';
+		strncpy(tv_channel_current->number, tmp, 5);
+
+		while ((sep=strchr(tv_channel_current->name, '_')))
+		    sep[0] = ' ';
+
+		tv_channel_current->freq = 0;
+		for (i = 0; i < chanlists[tvh->chanlist].count; i++) {
+		    cl = tvh->chanlist_s[i];
+		    if (!strcasecmp(cl.name, tv_channel_current->number)) {
+			tv_channel_current->freq=cl.freq;
+			break;
+		    }
+		}
+	        if (tv_channel_current->freq == 0)
+		    mp_msg(MSGT_TV, MSGL_ERR, "Couldn't find frequency for channel %s (%s)\n",
+				    tv_channel_current->number, tv_channel_current->name);
+		else {
+		  sep = strchr(tv_channel_current->name, '-');
+		  if ( !sep ) sep = strchr(tv_channel_current->name, '+');
+
+		  if ( sep ) {
+		    i = atoi (sep+1);
+		    if ( sep[0] == '+' ) tv_channel_current->freq += i * 100;
+		    if ( sep[0] == '-' ) tv_channel_current->freq -= i * 100;
+		    sep[0] = '\0';
+		  }
+		}
+
+		/*mp_msg(MSGT_TV, MSGL_INFO, "-- Detected channel %s - %s (%5.3f)\n",
+				tv_channel_current->number, tv_channel_current->name,
+				(float)tv_channel_current->freq/1000);*/
+
+		tv_channel_current->next = malloc(sizeof(tv_channels_t));
+		tv_channel_current->next->index = tv_channel_current->index + 1;
+		tv_channel_current->next->prev = tv_channel_current;
+		tv_channel_current->next->next = NULL;
+		tv_channel_current = tv_channel_current->next;
+	}
+	if (tv_channel_current->prev)
+  	  tv_channel_current->prev->next = NULL;
+	free(tv_channel_current);
+    } else 
+	    tv_channel_last_real = malloc(5);
+
+    if (tv_channel_list) {
+	int i;
+	int channel = 0;
+	if (tv_param_channel)
+	 {
+	   if (isdigit(*tv_param_channel))
+		/* if tv_param_channel begins with a digit interpret it as a number */
+		channel = atoi(tv_param_channel);
+	   else
+	      {
+		/* if tv_param_channel does not begin with a digit 
+		   set the first channel that contains tv_param_channel in its name */
+
+		tv_channel_current = tv_channel_list;
+		while ( tv_channel_current ) {
+			if ( strstr(tv_channel_current->name, tv_param_channel) )
+			  break;
+			tv_channel_current = tv_channel_current->next;
+			}
+		if ( !tv_channel_current ) tv_channel_current = tv_channel_list;
+	      }
+	 }
+	else
+		channel = 1;
+
+	if ( channel ) {
+	tv_channel_current = tv_channel_list;
+	for (i = 1; i < channel; i++)
+		if (tv_channel_current->next)
+			tv_channel_current = tv_channel_current->next;
+	}
+
+	mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
+			tv_channel_current->name, (float)tv_channel_current->freq/1000);
+	tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+	tv_channel_last = tv_channel_current;
+    } else {
+    /* we need to set frequency */
+    if (tv_param_freq)
+    {
+	unsigned long freq = atof(tv_param_freq)*16;
+
+        /* set freq in MHz */
+	funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_FREQ, &freq);
+
+	funcs->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, &freq);
+	mp_msg(MSGT_TV, MSGL_V, "Selected frequency: %lu (%.3f)\n",
+	    freq, (float)freq/16);
+    }
+
+	    if (tv_param_channel) {
+	struct CHANLIST cl;
+
+	mp_msg(MSGT_TV, MSGL_V, "Requested channel: %s\n", tv_param_channel);
+	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
+	{
+	    cl = tvh->chanlist_s[i];
+		    //  printf("count%d: name: %s, freq: %d\n",
+		    //	i, cl.name, cl.freq);
+	    if (!strcasecmp(cl.name, tv_param_channel))
+	    {
+			strcpy(tv_channel_last_real, cl.name);
+		tvh->channel = i;
+		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
+		    cl.name, (float)cl.freq/1000);
+		tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
+		break;
+	    }
+	}
+    }
+    }
+    
+    /* grep frequency in chanlist */
+    {
+	unsigned long i2;
+	int freq;
+	
+	tv_get_freq(tvh, &i2);
+	
+	freq = (int) (((float)(i2/16))*1000)+250;
+	
+	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
+	{
+	    if (tvh->chanlist_s[i].freq == freq)
+	    {
+		tvh->channel = i+1;
+		break;
+	    }
+	}
+    }
+
+done:    
+    /* also start device! */
+	return 1;
+}
+
+static demuxer_t* demux_open_tv(demuxer_t *demuxer)
+{
+    tvi_handle_t *tvh;
+    sh_video_t *sh_video;
+    sh_audio_t *sh_audio = NULL;
+    tvi_functions_t *funcs;
+    
+    if(!(tvh=tv_begin())) return NULL;
+    if (!tv_init(tvh)) return NULL;
+    if (!open_tv(tvh)){
+	tv_uninit(tvh);
+	return NULL;
+    }
+    funcs = tvh->functions;
+    demuxer->priv=tvh;
+    
+    sh_video = new_sh_video(demuxer, 0);
+
+    /* get IMAGE FORMAT */
+    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &sh_video->format);
+//    if (IMGFMT_IS_RGB(sh_video->format) || IMGFMT_IS_BGR(sh_video->format))
+//	sh_video->format = 0x0;
+
+    /* set FPS and FRAMETIME */
+
+    if(!sh_video->fps)
+    {
+        float tmp;
+        if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &tmp) != TVI_CONTROL_TRUE)
+             sh_video->fps = 25.0f; /* on PAL */
+        else sh_video->fps = tmp;
+    }
+
+    if (tv_param_fps != -1.0f)
+        sh_video->fps = tv_param_fps;
+
+    sh_video->frametime = 1.0f/sh_video->fps;
+
+    /* If playback only mode, go to immediate mode, fail silently */
+    if(tv_param_immediate == 1)
+        {
+        funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0);
+        tv_param_noaudio = 1; 
+        }
+
+    /* disable TV audio if -nosound is present */
+    if (!demuxer->audio || demuxer->audio->id == -2) {
+        tv_param_noaudio = 1; 
+    }
+
+    /* set width */
+    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w);
+
+    /* set height */
+    funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h);
+
+    demuxer->video->sh = sh_video;
+    sh_video->ds = demuxer->video;
+    demuxer->video->id = 0;
+    demuxer->seekable = 0;
+
+    /* here comes audio init */
+    if (tv_param_noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
+    {
+	int audio_format;
+	int sh_audio_format;
+	char buf[128];
+
+	/* yeah, audio is present */
+
+	funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE, 
+				  &tv_param_audiorate);
+
+	if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE)
+	    goto no_audio;
+
+	switch(audio_format)
+	{
+	    case AF_FORMAT_U8:
+	    case AF_FORMAT_S8:
+	    case AF_FORMAT_U16_LE:
+	    case AF_FORMAT_U16_BE:
+	    case AF_FORMAT_S16_LE:
+	    case AF_FORMAT_S16_BE:
+	    case AF_FORMAT_S32_LE:
+	    case AF_FORMAT_S32_BE:
+		sh_audio_format = 0x1; /* PCM */
+		break;
+	    case AF_FORMAT_IMA_ADPCM:
+	    case AF_FORMAT_MU_LAW:
+	    case AF_FORMAT_A_LAW:
+	    case AF_FORMAT_MPEG2:
+	    case AF_FORMAT_AC3:
+	    default:
+		mp_msg(MSGT_TV, MSGL_ERR, "Audio type '%s (%x)' unsupported!\n",
+		    af_fmt2str(audio_format, buf, 128), audio_format);
+		goto no_audio;
+	}
+	
+	sh_audio = new_sh_audio(demuxer, 0);
+
+	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, 
+                   &sh_audio->samplerate);
+	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE, 
+                   &sh_audio->samplesize);
+	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, 
+                   &sh_audio->channels);
+
+	sh_audio->format = sh_audio_format;
+	sh_audio->sample_format = audio_format;
+
+	sh_audio->i_bps = sh_audio->o_bps =
+	    sh_audio->samplerate * sh_audio->samplesize * 
+	    sh_audio->channels;
+
+	// emulate WF for win32 codecs:
+	sh_audio->wf = malloc(sizeof(WAVEFORMATEX));
+	sh_audio->wf->wFormatTag = sh_audio->format;
+	sh_audio->wf->nChannels = sh_audio->channels;
+	sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8;
+	sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
+	sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels;
+	sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps;
+
+	mp_msg(MSGT_DECVIDEO, MSGL_V, "  TV audio: %d channels, %d bits, %d Hz\n",
+          sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
+          sh_audio->wf->nSamplesPerSec);
+
+	demuxer->audio->sh = sh_audio;
+	sh_audio->ds = demuxer->audio;
+	demuxer->audio->id = 0;
+    }
+no_audio:
+
+    if(!(funcs->start(tvh->priv))){
+	// start failed :(
+	tv_uninit(tvh);
+	return NULL;
+    }
+
+    /* set color eq */
+    tv_set_color_options(tvh, TV_COLOR_BRIGHTNESS, tv_param_brightness);
+    tv_set_color_options(tvh, TV_COLOR_HUE, tv_param_hue);
+    tv_set_color_options(tvh, TV_COLOR_SATURATION, tv_param_saturation);
+    tv_set_color_options(tvh, TV_COLOR_CONTRAST, tv_param_contrast);
+
+    return demuxer;
+}
+
+static void demux_close_tv(demuxer_t *demuxer)
+{
+    tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv);
+    tvh->functions->uninit(tvh->priv);
+}
+
+/* ================== STREAM_TV ===================== */
+tvi_handle_t *tvi_init_dummy(char *device);
+tvi_handle_t *tvi_init_v4l(char *device, char *adevice);
+tvi_handle_t *tvi_init_v4l2(char *device, char *adevice);
+tvi_handle_t *tvi_init_bsdbt848(char *device);
+
+tvi_handle_t *tv_begin(void)
+{
+    if (!strcmp(tv_param_driver, "dummy"))
+	return tvi_init_dummy(tv_param_device);
+#ifdef HAVE_TV_V4L1
+    if (!strcmp(tv_param_driver, "v4l"))
+	return tvi_init_v4l(tv_param_device, tv_param_adevice);
+#endif
+#ifdef HAVE_TV_V4L2
+    if (!strcmp(tv_param_driver, "v4l2"))
+	return tvi_init_v4l2(tv_param_device, tv_param_adevice);
+#endif
+#ifdef HAVE_TV_BSDBT848
+    if (!strcmp(tv_param_driver, "bsdbt848"))
+	return tvi_init_bsdbt848(tv_param_device);
+#endif
+
+    mp_msg(MSGT_TV, MSGL_ERR, "No such driver: %s\n", tv_param_driver); 
+    return(NULL);
+}
+
+int tv_init(tvi_handle_t *tvh)
+{
+    mp_msg(MSGT_TV, MSGL_INFO, "Selected driver: %s\n", tvh->info->short_name);
+    mp_msg(MSGT_TV, MSGL_INFO, " name: %s\n", tvh->info->name);
+    mp_msg(MSGT_TV, MSGL_INFO, " author: %s\n", tvh->info->author);
+    if (tvh->info->comment)
+	mp_msg(MSGT_TV, MSGL_INFO, " comment: %s\n", tvh->info->comment);
+
+    return(tvh->functions->init(tvh->priv));
+}
+
+int tv_uninit(tvi_handle_t *tvh)
+{
+    return(tvh->functions->uninit(tvh->priv));
+}
+
+/* utilities for mplayer (not mencoder!!) */
+int tv_set_color_options(tvi_handle_t *tvh, int opt, int value)
+{
+    tvi_functions_t *funcs = tvh->functions;
+
+    switch(opt)
+    {
+	case TV_COLOR_BRIGHTNESS:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_BRIGHTNESS, &value);
+	case TV_COLOR_HUE:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HUE, &value);
+	case TV_COLOR_SATURATION:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_SATURATION, &value);
+	case TV_COLOR_CONTRAST:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_CONTRAST, &value);
+	default:
+	    mp_msg(MSGT_TV, MSGL_WARN, "Unknown color option (%d) specified!\n", opt);
+    }
+    
+    return(TVI_CONTROL_UNKNOWN);
+}
+
+int tv_get_color_options(tvi_handle_t *tvh, int opt, int* value)
+{
+    tvi_functions_t *funcs = tvh->functions;
+
+    switch(opt)
+    {
+	case TV_COLOR_BRIGHTNESS:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_BRIGHTNESS, value);
+	case TV_COLOR_HUE:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HUE, value);
+	case TV_COLOR_SATURATION:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_SATURATION, value);
+	case TV_COLOR_CONTRAST:
+	    return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_CONTRAST, value);
+	default:
+	    mp_msg(MSGT_TV, MSGL_WARN, "Unknown color option (%d) specified!\n", opt);
+    }
+    
+    return(TVI_CONTROL_UNKNOWN);
+}
+
+int tv_get_freq(tvi_handle_t *tvh, unsigned long *freq)
+{
+    if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) == TVI_CONTROL_TRUE)
+    {
+	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, freq);
+	mp_msg(MSGT_TV, MSGL_V, "Current frequency: %lu (%.3f)\n",
+	    *freq, (float)*freq/16);
+    }
+    return(1);
+}
+
+int tv_set_freq(tvi_handle_t *tvh, unsigned long freq)
+{
+    if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) == TVI_CONTROL_TRUE)
+    {
+//	unsigned long freq = atof(tv_param_freq)*16;
+
+        /* set freq in MHz */
+	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_FREQ, &freq);
+
+	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, &freq);
+	mp_msg(MSGT_TV, MSGL_V, "Current frequency: %lu (%.3f)\n",
+	    freq, (float)freq/16);
+    }
+    return(1);
+}
+
+int tv_step_channel_real(tvi_handle_t *tvh, int direction)
+{
+    struct CHANLIST cl;
+
+    if (direction == TV_CHANNEL_LOWER)
+    {
+	if (tvh->channel-1 >= 0)
+	{
+	    strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
+	    cl = tvh->chanlist_s[--tvh->channel];
+	    mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
+		cl.name, (float)cl.freq/1000);
+	    tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
+	}	
+    }
+
+    if (direction == TV_CHANNEL_HIGHER)
+    {
+	if (tvh->channel+1 < chanlists[tvh->chanlist].count)
+	{
+	    strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
+	    cl = tvh->chanlist_s[++tvh->channel];
+	    mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
+		cl.name, (float)cl.freq/1000);
+	    tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
+	}	
+    }
+    return(1);
+}
+
+int tv_step_channel(tvi_handle_t *tvh, int direction) {
+	if (tv_channel_list) {
+		if (direction == TV_CHANNEL_HIGHER) {
+			tv_channel_last = tv_channel_current;
+			if (tv_channel_current->next)
+				tv_channel_current = tv_channel_current->next;
+			else
+				tv_channel_current = tv_channel_list;
+				tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+				mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n",
+			tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
+		}
+		if (direction == TV_CHANNEL_LOWER) {
+			tv_channel_last = tv_channel_current;
+			if (tv_channel_current->prev)
+				tv_channel_current = tv_channel_current->prev;
+			else
+				while (tv_channel_current->next)
+					tv_channel_current = tv_channel_current->next;
+				tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+				mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n",
+			tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
+		}
+	} else tv_step_channel_real(tvh, direction);
+	return(1);
+}
+
+int tv_set_channel_real(tvi_handle_t *tvh, char *channel) {
+	int i;
+	struct CHANLIST cl;
+
+        strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
+	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
+	{
+	    cl = tvh->chanlist_s[i];
+//	    printf("count%d: name: %s, freq: %d\n",
+//		i, cl.name, cl.freq);
+	    if (!strcasecmp(cl.name, channel))
+	    {
+		tvh->channel = i;
+		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
+		    cl.name, (float)cl.freq/1000);
+		tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
+		break;
+	    }
+	}
+	return(1);
+}
+
+int tv_set_channel(tvi_handle_t *tvh, char *channel) {
+	int i, channel_int;
+
+	if (tv_channel_list) {
+		tv_channel_last = tv_channel_current;
+		channel_int = atoi(channel);
+		tv_channel_current = tv_channel_list;
+		for (i = 1; i < channel_int; i++)
+			if (tv_channel_current->next)
+				tv_channel_current = tv_channel_current->next;
+		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
+				tv_channel_current->name, (float)tv_channel_current->freq/1000);
+		tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+	} else tv_set_channel_real(tvh, channel);
+	return(1);
+}
+
+int tv_last_channel(tvi_handle_t *tvh) {
+
+	if (tv_channel_list) {
+		tv_channels_t *tmp;
+
+		tmp = tv_channel_last;
+		tv_channel_last = tv_channel_current;
+		tv_channel_current = tmp;
+
+		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
+				tv_channel_current->name, (float)tv_channel_current->freq/1000);
+		tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+	} else {
+		int i;
+		struct CHANLIST cl;
+
+		for (i = 0; i < chanlists[tvh->chanlist].count; i++)
+		{
+		    cl = tvh->chanlist_s[i];
+		    if (!strcasecmp(cl.name, tv_channel_last_real))
+		    {
+			strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
+			tvh->channel = i;
+			mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
+			    cl.name, (float)cl.freq/1000);
+			tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
+			break;
+		    }
+		}
+	}
+	return(1);
+}
+
+int tv_step_norm(tvi_handle_t *tvh)
+{
+  tvh->norm++;
+  if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM,
+                              &tvh->norm) != TVI_CONTROL_TRUE) {
+    tvh->norm = 0;
+    if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM,
+                                &tvh->norm) != TVI_CONTROL_TRUE) {
+      mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
+      return 0;
+    }
+  }
+    return(1);
+}
+
+int tv_step_chanlist(tvi_handle_t *tvh)
+{
+    return(1);
+}
+
+int tv_set_norm(tvi_handle_t *tvh, char* norm)
+{
+    tvh->norm = norm_from_string(tvh, norm);
+
+    mp_msg(MSGT_TV, MSGL_V, "Selected norm: %s\n", tv_param_norm);
+    if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->norm) != TVI_CONTROL_TRUE) {
+	mp_msg(MSGT_TV, MSGL_ERR, "Error: Cannot set norm!\n");
+	return 0;
+    }
+    return(1);
+}
+
+demuxer_desc_t demuxer_desc_tv = {
+  "Tv card demuxer",
+  "tv",
+  "TV",
+  "Alex Beregszaszi, Charles R. Henrich",
+  "?",
+  DEMUXER_TYPE_TV,
+  0, // no autodetect
+  NULL,
+  demux_tv_fill_buffer,
+  demux_open_tv,
+  demux_close_tv,
+  NULL,
+  NULL
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/tv.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,200 @@
+#ifndef TV_H
+#define TV_H
+
+extern int tv_param_on;
+
+#ifdef USE_TV
+//#include "libao2/afmt.h"
+//#include "libvo/img_format.h"
+//#include "libvo/fastmemcpy.h"
+//#include "mp_msg.h"
+
+extern char *tv_param_freq;
+extern char *tv_param_channel;
+extern char *tv_param_chanlist;
+extern char *tv_param_norm;
+#ifdef HAVE_TV_V4L2
+extern int tv_param_normid;
+#endif
+extern char *tv_param_device;
+extern char *tv_param_driver;
+extern int tv_param_width;
+extern int tv_param_height;
+extern int tv_param_input;
+extern int tv_param_outfmt;
+extern float tv_param_fps;
+extern char **tv_param_channels;
+extern int tv_param_noaudio;
+extern int tv_param_immediate;
+extern int tv_param_audiorate;
+extern int tv_param_audio_id;
+#if defined(HAVE_TV_V4L)
+extern int tv_param_amode;
+extern int tv_param_volume;
+extern int tv_param_bass;
+extern int tv_param_treble;
+extern int tv_param_balance;
+extern int tv_param_forcechan;
+extern int tv_param_force_audio;
+extern int tv_param_buffer_size;
+extern int tv_param_mjpeg;
+extern int tv_param_decimation;
+extern int tv_param_quality;
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+extern int tv_param_alsa;
+#endif
+extern char* tv_param_adevice;
+#endif
+extern int tv_param_brightness;
+extern int tv_param_contrast;
+extern int tv_param_hue;
+extern int tv_param_saturation;
+
+typedef struct tvi_info_s
+{
+    const char *name;
+    const char *short_name;
+    const char *author;
+    const char *comment;
+} tvi_info_t;
+
+typedef struct tvi_functions_s
+{
+    int (*init)();
+    int (*uninit)();
+    int (*control)();
+    int (*start)();
+    double (*grab_video_frame)();
+#ifdef HAVE_TV_BSDBT848
+    double (*grabimmediate_video_frame)();
+#endif
+    int (*get_video_framesize)();
+    double (*grab_audio_frame)();
+    int (*get_audio_framesize)();
+} tvi_functions_t;
+
+typedef struct tvi_handle_s {
+    tvi_info_t		*info;
+    tvi_functions_t	*functions;
+    void		*priv;
+    int 		seq;
+
+    /* specific */
+    int			norm;
+    int			chanlist;
+    const struct CHANLIST *chanlist_s;
+    int			channel;
+} tvi_handle_t;
+
+typedef struct tv_channels_s {
+    int index;
+    char number[5];
+    char name[20];
+    int   freq;
+    struct tv_channels_s *next;
+    struct tv_channels_s *prev;
+} tv_channels_t;
+
+extern tv_channels_t *tv_channel_list;
+extern tv_channels_t *tv_channel_current, *tv_channel_last;
+extern char *tv_channel_last_real;
+
+#define TVI_CONTROL_FALSE		0
+#define TVI_CONTROL_TRUE		1
+#define TVI_CONTROL_NA			-1
+#define TVI_CONTROL_UNKNOWN		-2
+
+/* ======================== CONTROLS =========================== */
+
+/* GENERIC controls */
+#define TVI_CONTROL_IS_AUDIO		0x1
+#define TVI_CONTROL_IS_VIDEO		0x2
+#define TVI_CONTROL_IS_TUNER		0x3
+#define TVI_CONTROL_IMMEDIATE           0x4
+
+/* VIDEO controls */
+#define TVI_CONTROL_VID_GET_FPS		0x101
+#define TVI_CONTROL_VID_GET_PLANES	0x102
+#define TVI_CONTROL_VID_GET_BITS	0x103
+#define TVI_CONTROL_VID_CHK_BITS	0x104
+#define TVI_CONTROL_VID_SET_BITS	0x105
+#define TVI_CONTROL_VID_GET_FORMAT	0x106
+#define TVI_CONTROL_VID_CHK_FORMAT	0x107
+#define TVI_CONTROL_VID_SET_FORMAT	0x108
+#define TVI_CONTROL_VID_GET_WIDTH	0x109
+#define TVI_CONTROL_VID_CHK_WIDTH	0x110
+#define TVI_CONTROL_VID_SET_WIDTH	0x111
+#define TVI_CONTROL_VID_GET_HEIGHT	0x112
+#define TVI_CONTROL_VID_CHK_HEIGHT	0x113
+#define TVI_CONTROL_VID_SET_HEIGHT	0x114
+#define TVI_CONTROL_VID_GET_BRIGHTNESS	0x115
+#define TVI_CONTROL_VID_SET_BRIGHTNESS	0x116
+#define TVI_CONTROL_VID_GET_HUE		0x117
+#define TVI_CONTROL_VID_SET_HUE		0x118
+#define TVI_CONTROL_VID_GET_SATURATION	0x119
+#define TVI_CONTROL_VID_SET_SATURATION	0x11a
+#define TVI_CONTROL_VID_GET_CONTRAST	0x11b
+#define TVI_CONTROL_VID_SET_CONTRAST	0x11c
+#define TVI_CONTROL_VID_GET_PICTURE	0x11d
+#define TVI_CONTROL_VID_SET_PICTURE	0x11e
+
+/* TUNER controls */
+#define TVI_CONTROL_TUN_GET_FREQ	0x201
+#define TVI_CONTROL_TUN_SET_FREQ	0x202
+#define TVI_CONTROL_TUN_GET_TUNER	0x203	/* update priv->tuner struct for used input */
+#define TVI_CONTROL_TUN_SET_TUNER	0x204	/* update priv->tuner struct for used input */
+#define TVI_CONTROL_TUN_GET_NORM	0x205
+#define TVI_CONTROL_TUN_SET_NORM	0x206
+
+/* AUDIO controls */
+#define TVI_CONTROL_AUD_GET_FORMAT	0x301
+#define TVI_CONTROL_AUD_GET_SAMPLERATE	0x302
+#define TVI_CONTROL_AUD_GET_SAMPLESIZE	0x303
+#define TVI_CONTROL_AUD_GET_CHANNELS	0x304
+#define TVI_CONTROL_AUD_SET_SAMPLERATE	0x305
+
+/* SPECIFIC controls */
+#define TVI_CONTROL_SPC_GET_INPUT	0x401	/* set input channel (tv,s-video,composite..) */
+#define TVI_CONTROL_SPC_SET_INPUT	0x402	/* set input channel (tv,s-video,composite..) */
+#define TVI_CONTROL_SPC_GET_NORMID	0x403	/* get normid from norm name */
+
+extern tvi_handle_t *tv_begin(void);
+extern int tv_init(tvi_handle_t *tvh);
+extern int tv_uninit(tvi_handle_t *tvh);
+
+int tv_set_color_options(tvi_handle_t *tvh, int opt, int val);
+int tv_get_color_options(tvi_handle_t *tvh, int opt, int* val);
+#define TV_COLOR_BRIGHTNESS	1
+#define TV_COLOR_HUE		2
+#define TV_COLOR_SATURATION	3
+#define TV_COLOR_CONTRAST	4
+
+int tv_step_channel_real(tvi_handle_t *tvh, int direction);
+int tv_step_channel(tvi_handle_t *tvh, int direction);
+#define TV_CHANNEL_LOWER	1
+#define TV_CHANNEL_HIGHER	2
+
+int tv_last_channel(tvi_handle_t *tvh);
+
+int tv_set_channel_real(tvi_handle_t *tvh, char *channel);
+int tv_set_channel(tvi_handle_t *tvh, char *channel);
+
+int tv_step_norm(tvi_handle_t *tvh);
+int tv_step_chanlist(tvi_handle_t *tvh);
+
+int tv_set_freq(tvi_handle_t *tvh, unsigned long freq);
+int tv_get_freq(tvi_handle_t *tvh, unsigned long *freq);
+
+int tv_set_norm(tvi_handle_t *tvh, char* norm);
+
+#define TV_NORM_PAL		1
+#define TV_NORM_NTSC		2
+#define TV_NORM_SECAM		3
+#define TV_NORM_PALNC		4
+#define TV_NORM_PALM		5
+#define TV_NORM_PALN		6
+#define TV_NORM_NTSCJP		7
+
+#endif /* USE_TV */
+
+#endif /* TV_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/tvi_bsdbt848.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,846 @@
+/*
+    (C)2002 Charles R. Henrich (henrich@msu.edu)
+    *BSD (hopefully, requires working driver!) BrookTree capture support.
+
+    Still in (active) development!
+
+	v1.1	Mar 13 2002   Fully functional, need to move ring buffer to
+						  the kernel driver. 
+    v1.0    Feb 19 2002   First Release, need to add support for changing
+                            audio parameters.
+*/
+
+#include "config.h"
+
+#define RINGSIZE 8
+#define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */
+
+#define TRUE  (1==1)
+#define FALSE (1==0)
+
+#define PAL_WIDTH  768
+#define PAL_HEIGHT 576
+#define PAL_FPS    25
+
+#define NTSC_WIDTH  640
+#define NTSC_HEIGHT 480
+#define NTSC_FPS    29.97
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/filio.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <string.h>
+
+#include <sys/param.h>
+#ifdef __NetBSD__
+#include <dev/ic/bt8xx.h>
+#include <sys/audioio.h>
+#elif defined(__DragonFly__)
+#include <dev/video/meteor/ioctl_meteor.h>
+#include <dev/video/bktr/ioctl_bt848.h>
+#elif __FreeBSD_version >= 502100
+#include <dev/bktr/ioctl_meteor.h>
+#include <dev/bktr/ioctl_bt848.h>
+#else
+#include <machine/ioctl_meteor.h>
+#include <machine/ioctl_bt848.h>
+#endif
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#else
+#ifdef HAVE_SOUNDCARD_H
+#include <soundcard.h>
+#else
+#include <machine/soundcard.h>
+#endif
+#endif
+
+#include "libaf/af_format.h"
+#include "libvo/img_format.h"
+#include "tv.h"
+
+/* information about this file */
+static tvi_info_t info = {
+    "Brooktree848 Support",
+    "bsdbt848",
+    "Charles Henrich",
+    "in development"
+};
+
+typedef struct {
+    int dirty;
+    double timestamp;
+    char *buf;
+} RBFRAME;
+
+/* private data's */
+typedef struct {
+
+/* Audio */
+    char *dspdev;
+    int dspready;
+    int dspfd;
+    int dspsamplesize;
+    int dspstereo;
+    int dspspeed;
+    int dspfmt;
+    int dspframesize;
+    int dsprate;
+    long long dspbytesread;
+
+/* Video */
+    char *btdev;
+    int videoready;
+    int btfd;
+    int source;
+    float maxfps;
+    float fps;
+    int iformat;
+    int maxheight;
+    int maxwidth;
+    struct meteor_geomet geom;
+    struct meteor_capframe capframe;
+
+/* Frame Buffer */
+
+    int framebufsize;
+    float timestamp;
+    int curpaintframe;
+    int curbufframe;
+    unsigned char *livebuf;
+    RBFRAME framebuf[RINGSIZE];
+
+/* Inputs */
+
+    int input;
+
+/* Tuner */
+
+    char *tunerdev;
+    int tunerfd;
+    int tunerready;
+    u_long tunerfreq;
+    struct bktr_chnlset cset;
+
+/* Other */
+
+    int immediatemode;
+    double starttime;
+
+} priv_t;
+
+#include "tvi_def.h"
+
+static priv_t *G_private=NULL;
+
+static int getinput(int innumber);
+
+static void processframe(int signal)
+{
+struct timeval curtime;
+
+if(G_private->immediatemode == TRUE) return;
+
+gettimeofday(&curtime, NULL);
+
+if(G_private->framebuf[G_private->curpaintframe].dirty == TRUE)
+    {
+    memcpy(G_private->framebuf[G_private->curpaintframe].buf, 
+            G_private->livebuf, G_private->framebufsize);
+
+    G_private->framebuf[G_private->curpaintframe].dirty = FALSE;
+
+    G_private->framebuf[G_private->curpaintframe].timestamp = 
+            curtime.tv_sec + curtime.tv_usec*.000001;
+
+    G_private->curpaintframe++;
+
+    if(G_private->curpaintframe >= RINGSIZE) G_private->curpaintframe = 0;
+    }
+
+return;
+}
+
+/* handler creator - entry point ! */
+tvi_handle_t *tvi_init_bsdbt848(char *device)
+{
+    return(new_handle());
+}
+
+static int control(priv_t *priv, int cmd, void *arg)
+{
+    switch(cmd)
+    {
+
+/* Tuner Controls */
+
+    case TVI_CONTROL_IS_TUNER:
+        if(priv->tunerready == FALSE) return TVI_CONTROL_FALSE;
+        return(TVI_CONTROL_TRUE);
+
+    case TVI_CONTROL_TUN_GET_FREQ:
+        {
+        if(ioctl(priv->tunerfd, TVTUNER_GETFREQ, &priv->tunerfreq) < 0)
+            {
+            perror("GETFREQ:ioctl");
+            return(TVI_CONTROL_FALSE);
+            }
+
+        (int)*(void **)arg = priv->tunerfreq;
+        return(TVI_CONTROL_TRUE);
+        }
+    
+    case TVI_CONTROL_TUN_SET_FREQ:
+        {
+        priv->tunerfreq = (int)*(void **)arg;
+
+        if(ioctl(priv->tunerfd, TVTUNER_SETFREQ, &priv->tunerfreq) < 0) 
+            {
+            perror("SETFREQ:ioctl");
+            return(0);
+            }
+
+        return(TVI_CONTROL_TRUE);        
+        }
+
+    case TVI_CONTROL_TUN_GET_TUNER:
+    case TVI_CONTROL_TUN_SET_TUNER:
+
+/* Inputs */
+
+    case TVI_CONTROL_SPC_GET_INPUT:
+        {
+        if(ioctl(priv->btfd, METEORGINPUT, &priv->input) < 0)
+            {
+            perror("GINPUT:ioctl");
+            return(TVI_CONTROL_FALSE);
+            }
+
+        (int)*(void **)arg = priv->input;
+        return(TVI_CONTROL_TRUE);
+        }
+    
+    case TVI_CONTROL_SPC_SET_INPUT:
+        {
+        priv->input = getinput((int)*(void **)arg);
+
+        if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0) 
+            {
+            perror("tunerfreq:ioctl");
+            return(0);
+            }
+
+        return(TVI_CONTROL_TRUE);        
+        }
+
+/* Audio Controls */
+
+    case TVI_CONTROL_IS_AUDIO:
+        if(priv->dspready == FALSE) return TVI_CONTROL_FALSE;
+        return(TVI_CONTROL_TRUE);
+
+    case TVI_CONTROL_AUD_GET_FORMAT:
+        {
+        (int)*(void **)arg = AF_FORMAT_S16_LE;
+        return(TVI_CONTROL_TRUE);
+        }
+    case TVI_CONTROL_AUD_GET_CHANNELS:
+        {
+        (int)*(void **)arg = 2;
+        return(TVI_CONTROL_TRUE);
+        }
+    case TVI_CONTROL_AUD_SET_SAMPLERATE:
+        {
+        int dspspeed = (int)*(void **)arg;
+
+           if(ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &dspspeed) == -1) 
+            {
+            perror("invalidaudiorate");
+            return(TVI_CONTROL_FALSE);
+            }
+
+        priv->dspspeed = dspspeed;
+
+        priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
+                                priv->fps * (priv->dspstereo+1);
+        priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*
+                                (priv->dspstereo+1);
+
+        return(TVI_CONTROL_TRUE);
+        }
+    case TVI_CONTROL_AUD_GET_SAMPLERATE:
+        {
+        (int)*(void **)arg = priv->dspspeed;
+        return(TVI_CONTROL_TRUE);
+        }
+    case TVI_CONTROL_AUD_GET_SAMPLESIZE:
+        {
+        (int)*(void **)arg = priv->dspsamplesize/8;
+        return(TVI_CONTROL_TRUE);
+        }
+
+/* Video Controls */
+
+    case TVI_CONTROL_IS_VIDEO:
+        if(priv->videoready == FALSE) return TVI_CONTROL_FALSE;
+        return(TVI_CONTROL_TRUE);
+
+    case TVI_CONTROL_TUN_SET_NORM:
+        {
+        int req_mode = (int)*(void **)arg;
+	u_short tmp_fps;
+
+        priv->iformat = METEOR_FMT_AUTOMODE;
+
+        if(req_mode == TV_NORM_PAL) 
+            {
+            priv->iformat = METEOR_FMT_PAL;
+            priv->maxheight = PAL_HEIGHT;
+            priv->maxwidth = PAL_WIDTH;
+            priv->maxfps = PAL_FPS;
+            priv->fps = PAL_FPS;
+
+            if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
+
+            if(priv->geom.rows > priv->maxheight) 
+                {
+                priv->geom.rows = priv->maxheight;
+                }
+
+            if(priv->geom.columns > priv->maxwidth) 
+                {
+                priv->geom.columns = priv->maxwidth;
+                }
+            }
+
+        if(req_mode == TV_NORM_NTSC) 
+            {
+            priv->iformat = METEOR_FMT_NTSC;
+            priv->maxheight = NTSC_HEIGHT;
+            priv->maxwidth = NTSC_WIDTH;
+            priv->maxfps = NTSC_FPS;
+            priv->fps = NTSC_FPS;
+
+            priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
+                                 priv->fps * (priv->dspstereo+1);
+            priv->dsprate = priv->dspspeed * priv->dspsamplesize/8 *
+                                (priv->dspstereo+1);
+
+            if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
+
+            if(priv->geom.rows > priv->maxheight) 
+                {
+                priv->geom.rows = priv->maxheight;
+                }
+
+            if(priv->geom.columns > priv->maxwidth) 
+                {
+                priv->geom.columns = priv->maxwidth;
+                }
+            }
+
+        if(req_mode == TV_NORM_SECAM) priv->iformat = METEOR_FMT_SECAM;
+
+        if(ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) 
+            {
+            perror("format:ioctl");
+            return(TVI_CONTROL_FALSE);
+            }
+    
+        if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
+            {
+            perror("geo:ioctl");
+            return(0);
+            }
+
+	tmp_fps = priv->fps;
+        if(ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0) 
+            {
+            perror("fps:ioctl");
+            return(0);
+            }
+
+#ifdef BT848_SAUDIO
+	if(priv->tunerready == TRUE &&
+	    ioctl(priv->tunerfd, BT848_SAUDIO, &tv_param_audio_id) < 0)
+	    {
+	    perror("audioid:ioctl");
+	    }
+#endif
+
+        return(TVI_CONTROL_TRUE);
+        }
+    
+    case TVI_CONTROL_VID_GET_FORMAT:
+        (int)*(void **)arg = IMGFMT_UYVY;
+        return(TVI_CONTROL_TRUE);
+
+    case TVI_CONTROL_VID_SET_FORMAT:
+        {
+        int req_fmt = (int)*(void **)arg;
+
+        if(req_fmt != IMGFMT_UYVY) return(TVI_CONTROL_FALSE);
+
+        return(TVI_CONTROL_TRUE);
+        }
+    case TVI_CONTROL_VID_SET_WIDTH:
+        priv->geom.columns = (int)*(void **)arg;
+
+        if(priv->geom.columns > priv->maxwidth) 
+            {
+            priv->geom.columns = priv->maxwidth;
+            }
+
+        if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
+            {
+            perror("width:ioctl");
+            return(0);
+            }
+
+        return(TVI_CONTROL_TRUE);
+
+    case TVI_CONTROL_VID_GET_WIDTH:
+        (int)*(void **)arg = priv->geom.columns;
+        return(TVI_CONTROL_TRUE);
+
+    case TVI_CONTROL_VID_SET_HEIGHT:
+        priv->geom.rows = (int)*(void **)arg;
+
+        if(priv->geom.rows > priv->maxheight) 
+            {
+            priv->geom.rows = priv->maxheight;
+            }
+
+        if(priv->geom.rows <= priv->maxheight / 2)
+            {
+            priv->geom.oformat |= METEOR_GEO_EVEN_ONLY;
+            }  
+
+        if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
+            {
+            perror("height:ioctl");
+            return(0);
+            }
+
+        return(TVI_CONTROL_TRUE);        
+
+    case TVI_CONTROL_VID_GET_HEIGHT:
+        (int)*(void **)arg = priv->geom.rows;
+        return(TVI_CONTROL_TRUE);        
+
+    case TVI_CONTROL_VID_GET_FPS:
+        *(float *)arg = priv->fps;
+        return(TVI_CONTROL_TRUE);        
+
+/*
+    case TVI_CONTROL_VID_SET_FPS:
+        priv->fps = (int)*(void **)arg;
+
+        if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
+
+        if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) 
+            {
+            perror("fps:ioctl");
+            return(0);
+            }
+
+        return(TVI_CONTROL_TRUE);        
+*/
+
+    case TVI_CONTROL_VID_CHK_WIDTH:
+    case TVI_CONTROL_VID_CHK_HEIGHT:
+        return(TVI_CONTROL_TRUE);
+
+    case TVI_CONTROL_IMMEDIATE:
+        priv->immediatemode = TRUE;
+        return(TVI_CONTROL_TRUE);
+    }
+
+    return(TVI_CONTROL_UNKNOWN);
+}
+
+static int init(priv_t *priv)
+{
+int marg;
+int count;
+u_short tmp_fps;
+
+G_private = priv; /* Oooh, sick */
+
+/* Video Configuration */
+
+priv->videoready = TRUE;
+priv->btdev = strdup("/dev/bktr0");
+priv->immediatemode = FALSE;
+priv->iformat = METEOR_FMT_PAL;
+priv->maxheight = PAL_HEIGHT;
+priv->maxwidth = PAL_WIDTH;
+priv->maxfps = PAL_FPS;
+priv->source = METEOR_INPUT_DEV0;
+priv->fps = priv->maxfps;
+
+priv->starttime=0;
+priv->curpaintframe=0;
+priv->curbufframe=0;
+
+priv->geom.columns = priv->maxwidth;
+priv->geom.rows = priv->maxheight;
+priv->geom.frames = 1;
+priv->geom.oformat = METEOR_GEO_YUV_PACKED;
+
+priv->btfd = open(priv->btdev, O_RDONLY);
+
+if(priv->btfd < 0)
+    {
+    perror("bktr open");
+    priv->videoready = FALSE;
+    }
+
+if(priv->videoready == TRUE && 
+   ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) 
+    {
+    perror("FMT:ioctl");
+    }
+
+if(priv->videoready == TRUE &&
+   ioctl(priv->btfd, METEORSINPUT, &priv->source) < 0) 
+    {
+    perror("SINPUT:ioctl");
+    }
+
+tmp_fps = priv->fps;
+if(priv->videoready == TRUE &&
+   ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0) 
+    {
+    perror("SFPS:ioctl");
+    }
+
+if(priv->videoready == TRUE &&
+   ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) 
+    {
+    perror("SGEO:ioctl");
+    }
+
+if(priv->videoready == TRUE)
+    {
+    priv->framebufsize = (priv->geom.columns * priv->geom.rows * 2);
+
+    priv->livebuf = (u_char *)mmap((caddr_t)0, priv->framebufsize, PROT_READ,
+                                MAP_SHARED, priv->btfd, (off_t)0);
+
+    if(priv->livebuf == (u_char *) MAP_FAILED)
+        {
+        perror("mmap");
+        priv->videoready = FALSE;
+        }
+
+    for(count=0;count<RINGSIZE;count++)
+        {
+        priv->framebuf[count].buf = malloc(priv->framebufsize);
+
+        if(priv->framebuf[count].buf == NULL)
+            {
+            perror("framebufmalloc");
+            priv->videoready = FALSE;
+            break;
+            }
+
+        priv->framebuf[count].dirty = TRUE;
+        priv->framebuf[count].timestamp = 0;
+        }
+    }
+
+/* Tuner Configuration */
+
+priv->tunerdev = strdup("/dev/tuner0");
+priv->tunerready = TRUE;
+
+priv->tunerfd = open(priv->tunerdev, O_RDONLY);
+
+if(priv->tunerfd < 0)
+    {
+    perror("tune open");
+    priv->tunerready = FALSE;
+    }
+
+/* Audio Configuration */
+
+priv->dspready = TRUE;
+#ifdef __NetBSD__
+priv->dspdev = strdup("/dev/sound");
+#else
+priv->dspdev = strdup("/dev/dsp");
+#endif
+priv->dspsamplesize = 16;
+priv->dspstereo = 1;
+priv->dspspeed = 44100;
+priv->dspfmt = AFMT_S16_LE;
+priv->dspbytesread = 0;
+priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*(priv->dspstereo+1);
+priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/priv->fps * 
+                     (priv->dspstereo+1);
+
+if((priv->dspfd = open (priv->dspdev, O_RDONLY, 0)) < 0)
+    {
+    perror("dsp open");
+    priv->dspready = FALSE;
+    } 
+
+marg = (256 << 16) | 12;
+
+if (ioctl(priv->dspfd, SNDCTL_DSP_SETFRAGMENT, &marg ) < 0 ) 
+    {
+    perror("setfrag");
+    priv->dspready = FALSE;
+    }
+
+if((priv->dspready == TRUE) &&
+   ((ioctl(priv->dspfd, SNDCTL_DSP_SAMPLESIZE, &priv->dspsamplesize) == -1) ||
+   (ioctl(priv->dspfd, SNDCTL_DSP_STEREO, &priv->dspstereo) == -1) ||
+   (ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &priv->dspspeed) == -1) ||
+   (ioctl(priv->dspfd, SNDCTL_DSP_SETFMT, &priv->dspfmt) == -1)))
+    {
+    perror ("configuration of dsp failed");
+    close(priv->dspfd);
+    priv->dspready = FALSE;
+    }
+
+return(1);
+}
+
+/* that's the real start, we'got the format parameters (checked with control) */
+static int start(priv_t *priv)
+{
+int tmp;
+struct timeval curtime;
+int marg;
+
+fprintf(stderr,"START\n");
+if(priv->videoready == FALSE) return(0);
+
+signal(SIGUSR1, processframe);
+signal(SIGALRM, processframe);
+
+marg = SIGUSR1;
+
+if(ioctl(priv->btfd, METEORSSIGNAL, &marg) < 0) 
+    {
+    perror("METEORSSIGNAL failed");
+    return(0);
+    }
+
+read(priv->dspfd, &tmp, 2);
+
+gettimeofday(&curtime, NULL);
+
+priv->starttime = curtime.tv_sec + (curtime.tv_usec *.000001);
+
+marg = METEOR_CAP_CONTINOUS;
+
+if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0) 
+    {
+    perror("METEORCAPTUR failed");
+    return(0);
+    }
+
+return(1);
+}
+
+static int uninit(priv_t *priv)
+{
+int marg;
+
+if(priv->videoready == FALSE) return(0);
+
+marg = METEOR_SIG_MODE_MASK;
+
+if(ioctl( priv->btfd, METEORSSIGNAL, &marg) < 0 ) 
+    {
+    perror("METEORSSIGNAL");
+    return(0);
+    }
+
+marg = METEOR_CAP_STOP_CONT;
+
+if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0 ) 
+    {
+    perror("METEORCAPTUR STOP");
+    return(0);
+    }
+
+close(priv->btfd);
+close(priv->dspfd);
+
+priv->dspfd = -1;
+priv->btfd = -1;
+
+priv->dspready = priv->videoready = FALSE;
+
+return(1);
+}
+
+
+static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
+{
+struct timeval curtime;
+sigset_t sa_mask;
+
+if(priv->videoready == FALSE) return(0);
+
+alarm(1);
+sigfillset(&sa_mask);
+sigdelset(&sa_mask,SIGINT);
+sigdelset(&sa_mask,SIGUSR1);
+sigdelset(&sa_mask,SIGALRM);
+sigsuspend(&sa_mask);
+alarm(0);
+
+memcpy(buffer, priv->livebuf, len);
+
+/* PTS = 0, show the frame NOW, this routine is only used in playback mode
+    without audio capture .. */
+
+return(0); 
+}
+
+static double grab_video_frame(priv_t *priv, char *buffer, int len)
+{
+struct timeval curtime;
+double timestamp=0;
+sigset_t sa_mask;
+
+if(priv->videoready == FALSE) return(0);
+
+if(priv->immediatemode == TRUE) 
+    {
+    return grabimmediate_video_frame(priv, buffer, len);
+    }
+
+while(priv->framebuf[priv->curbufframe].dirty == TRUE)
+    {
+    alarm(1);
+    sigemptyset(&sa_mask);
+    sigsuspend(&sa_mask);
+    alarm(0);
+    }
+
+memcpy(buffer, priv->framebuf[priv->curbufframe].buf, len);
+timestamp = priv->framebuf[priv->curbufframe].timestamp;
+priv->framebuf[priv->curbufframe].dirty = TRUE;
+
+priv->curbufframe++;
+if(priv->curbufframe >= RINGSIZE) priv->curbufframe = 0;
+
+return(timestamp-priv->starttime);
+}
+
+static int get_video_framesize(priv_t *priv)
+{
+return(priv->geom.columns*priv->geom.rows*16/8);
+}
+
+static double grab_audio_frame(priv_t *priv, char *buffer, int len)
+{
+struct timeval curtime;
+double curpts;
+double timeskew;
+int bytesavail;
+int bytesread;
+int ret;
+
+if(priv->dspready == FALSE) return 0;
+
+gettimeofday(&curtime, NULL);
+
+/* Get exactly one frame of audio, which forces video sync to audio.. */
+
+bytesread=read(priv->dspfd, buffer, len); 
+
+while(bytesread < len)
+    {
+    ret=read(priv->dspfd, &buffer[bytesread], len-bytesread);
+
+    if(ret == -1)
+        {
+        perror("Audio read failed!");
+        return 0;
+        }
+
+    bytesread+=ret;
+    }
+
+priv->dspbytesread += bytesread;
+
+curpts = curtime.tv_sec + curtime.tv_usec * .000001;
+
+timeskew = priv->dspbytesread * 1.0 / priv->dsprate - (curpts-priv->starttime);
+
+if(timeskew > .125/priv->fps) 
+    {
+    priv->starttime -= timeskew;
+    }
+else
+    {
+    if(timeskew < -.125/priv->fps) 
+        {
+        priv->starttime -= timeskew;
+        }
+    }
+
+return(priv->dspbytesread * 1.0 / priv->dsprate);
+}
+
+static int get_audio_framesize(priv_t *priv)
+{
+int bytesavail;
+#ifdef __NetBSD__
+struct audio_info auinf;
+#endif
+
+if(priv->dspready == FALSE) return 0;
+
+#ifdef __NetBSD__
+if(ioctl(priv->dspfd, AUDIO_GETINFO, &auinf) < 0) 
+    {
+    perror("AUDIO_GETINFO");
+    return(TVI_CONTROL_FALSE);
+    }
+else
+    bytesavail = auinf.record.seek; /* *priv->dspsamplesize; */
+#else
+if(ioctl(priv->dspfd, FIONREAD, &bytesavail) < 0) 
+    {
+    perror("FIONREAD");
+    return(TVI_CONTROL_FALSE);
+    }
+#endif
+
+/* When mencoder wants audio data, it wants data..
+   it won't go do anything else until it gets it :( */
+
+if(bytesavail == 0) return FRAGSIZE;
+
+return(bytesavail);
+}
+
+static int getinput(int innumber)
+{
+switch(innumber)
+    {
+    case 0: return METEOR_INPUT_DEV0;     /* RCA   */
+    case 1: return METEOR_INPUT_DEV1;     /* Tuner */
+    case 2: return METEOR_INPUT_DEV2;     /* In 1  */
+    case 3: return METEOR_INPUT_DEV3;     /* In 2  */
+    case 4: return METEOR_INPUT_DEV_RGB;     /* RGB   */
+    case 5: return METEOR_INPUT_DEV_SVIDEO; /* SVid  */
+    }
+
+return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/tvi_def.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,61 @@
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+static int init(priv_t *priv);
+static int uninit(priv_t *priv);
+static int control(priv_t *priv, int cmd, void *arg);
+static int start(priv_t *priv);
+static double grab_video_frame(priv_t *priv, char *buffer, int len);
+#ifdef HAVE_TV_BSDBT848
+static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len);
+#endif
+static int get_video_framesize(priv_t *priv);
+static double grab_audio_frame(priv_t *priv, char *buffer, int len);
+static int get_audio_framesize(priv_t *priv);
+
+static tvi_functions_t functions =
+{
+    init,
+    uninit,
+    control,
+    start,
+    grab_video_frame,
+#ifdef HAVE_TV_BSDBT848
+    grabimmediate_video_frame,
+#endif
+    get_video_framesize,
+    grab_audio_frame,
+    get_audio_framesize
+};
+
+static tvi_handle_t *new_handle(void)
+{
+    tvi_handle_t *h = (tvi_handle_t *)malloc(sizeof(tvi_handle_t));
+
+    if (!h)
+	return(NULL);
+    h->priv = (priv_t *)malloc(sizeof(priv_t));
+    if (!h->priv)
+    {
+	free(h);
+	return(NULL);
+    }
+    memset(h->priv, 0, sizeof(priv_t));
+    h->info = &info;
+    h->functions = &functions;
+    h->seq = 0;
+    h->chanlist = -1;
+    h->chanlist_s = NULL;
+    h->norm = -1;
+    h->channel = -1;
+    return(h);
+}
+
+static void free_handle(tvi_handle_t *h)
+{
+    if (h) {
+	if (h->priv)
+	    free(h->priv);
+	free(h);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/tvi_dummy.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,120 @@
+/*
+    Only a sample!
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include "libvo/img_format.h"
+#include "tv.h"
+
+/* information about this file */
+static tvi_info_t info = {
+	"NULL-TV",
+	"dummy",
+	"alex",
+	NULL
+};
+
+/* private data's */
+typedef struct {
+    int width;
+    int height;
+} priv_t;
+
+#include "tvi_def.h"
+
+/* handler creator - entry point ! */
+tvi_handle_t *tvi_init_dummy(char *device)
+{
+    return(new_handle());
+}
+
+/* initialisation */
+static int init(priv_t *priv)
+{
+    priv->width = 320;
+    priv->height = 200;
+    return(1);
+}
+
+/* that's the real start, we'got the format parameters (checked with control) */
+static int start(priv_t *priv)
+{
+    return(1);
+}
+
+static int uninit(priv_t *priv)
+{
+    return(1);
+}
+
+static int control(priv_t *priv, int cmd, void *arg)
+{
+    switch(cmd)
+    {
+	case TVI_CONTROL_IS_VIDEO:
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_GET_FORMAT:
+//	    *(int *)arg = IMGFMT_YV12;
+	    *(int *)arg = IMGFMT_YV12;
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_SET_FORMAT:
+	{
+//	    int req_fmt = *(int *)arg;
+	    int req_fmt = *(int *)arg;
+	    if (req_fmt != IMGFMT_YV12)
+		return(TVI_CONTROL_FALSE);
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_VID_SET_WIDTH:
+	    priv->width = *(int *)arg;
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_GET_WIDTH:
+	    *(int *)arg = priv->width;
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_SET_HEIGHT:
+	    priv->height = *(int *)arg;
+	    return(TVI_CONTROL_TRUE);	    
+	case TVI_CONTROL_VID_GET_HEIGHT:
+	    *(int *)arg = priv->height;
+	    return(TVI_CONTROL_TRUE);	    
+	case TVI_CONTROL_VID_CHK_WIDTH:
+	case TVI_CONTROL_VID_CHK_HEIGHT:
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_TUN_SET_NORM:
+	    return(TVI_CONTROL_TRUE);
+    }
+    return(TVI_CONTROL_UNKNOWN);
+}
+
+#ifdef HAVE_TV_BSDBT848
+static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
+{
+    memset(buffer, 0xCC, len);
+    return(1);
+}
+#endif
+
+static double grab_video_frame(priv_t *priv, char *buffer, int len)
+{
+    memset(buffer, 0x42, len);
+    return(1);
+}
+
+static int get_video_framesize(priv_t *priv)
+{
+    /* YV12 */
+    return(priv->width*priv->height*12/8);
+}
+
+static double grab_audio_frame(priv_t *priv, char *buffer, int len)
+{
+    memset(buffer, 0x42, len);
+    return(1);
+}
+
+static int get_audio_framesize(priv_t *priv)
+{
+    return(1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/tvi_v4l.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,1759 @@
+/*
+  Video 4 Linux input
+
+  (C) Alex Beregszaszi
+  
+  Some ideas are based on xawtv/libng's grab-v4l.c written by
+    Gerd Knorr <kraxel@bytesex.org>
+
+  Multithreading, a/v sync and native ALSA support by
+    Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
+
+  Mjpeg hardware encoding support by 
+    Iván Szántó <szivan@freemail.hu>
+
+  CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+/* Necessary to prevent collisions between <linux/time.h> and <sys/time.h> when V4L2 is installed. */
+#define _LINUX_TIME_H
+
+#include <linux/videodev.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#ifdef HAVE_SYS_SYSINFO_H
+#include <sys/sysinfo.h>
+#endif
+
+#include "mp_msg.h"
+#include "libaf/af_format.h"
+#include "libvo/img_format.h"
+#include "libvo/fastmemcpy.h"
+#include "libvo/videodev_mjpeg.h"
+
+#include "tv.h"
+
+#include "audio_in.h"
+
+static tvi_info_t info = {
+	"Video 4 Linux input",
+	"v4l",
+	"Alex Beregszaszi",
+	"under development"
+};
+
+#define PAL_WIDTH  768
+#define PAL_HEIGHT 576
+#define PAL_FPS    25
+
+#define NTSC_WIDTH  640
+#define NTSC_HEIGHT 480
+#define NTSC_FPS    (30000.0/1001.0)
+
+#define MAX_AUDIO_CHANNELS	10
+
+#define VID_BUF_SIZE_IMMEDIATE 2
+#define VIDEO_AVG_BUFFER_SIZE 600
+
+typedef struct {
+    /* general */
+    char			*video_device;
+    int                         video_fd;
+    struct video_capability	capability;
+    struct video_channel	*channels;
+    int				act_channel;
+    struct video_tuner		tuner;
+
+    /* video */
+    struct video_picture	picture;
+    int				format;		/* output format */
+    int				width;
+    int				height;
+    int				bytesperline;
+    float			fps;
+
+    struct video_mbuf		mbuf;
+    unsigned char               *mmap;
+    struct video_mmap		*buf;
+    int				nbuf;
+
+    /* audio */
+    char			*audio_device;
+    audio_in_t                  audio_in;
+
+    int				audio_id;
+    struct video_audio		audio[MAX_AUDIO_CHANNELS];
+    int				audio_channels[MAX_AUDIO_CHANNELS];
+
+    /* buffering stuff */
+    int                         immediate_mode;
+
+    int                         audio_buffer_size;
+    int                         aud_skew_cnt;
+    unsigned char		*audio_ringbuffer;
+    long long			*audio_skew_buffer;
+    volatile int		audio_head;
+    volatile int		audio_tail;
+    volatile int		audio_cnt;
+    volatile long long          audio_skew;
+    volatile double             audio_skew_factor;
+    volatile long long          audio_skew_measure_time;
+    volatile int                audio_drop;
+
+    int                         first;
+    int                         video_buffer_size_max;
+    volatile int                video_buffer_size_current;
+    unsigned char		**video_ringbuffer;
+    long long                   *video_timebuffer;
+    long long                   *video_avg_buffer;
+    int		                video_avg_ptr;
+    int		                video_interval_sum;
+    volatile int		video_head;
+    volatile int		video_tail;
+    volatile int		video_cnt;
+
+    volatile int                shutdown;
+
+    pthread_t			audio_grabber_thread;
+    pthread_t			video_grabber_thread;
+    pthread_mutex_t             audio_starter;
+    pthread_mutex_t             skew_mutex;
+    pthread_mutex_t             video_buffer_mutex;
+
+    long long                   starttime;
+    double                      audio_secs_per_block;
+    long long                   audio_skew_total;
+    long			audio_recv_blocks_total;
+    long			audio_sent_blocks_total;
+    long                        mjpeg_bufsize;
+    
+} priv_t;
+
+#include "tvi_def.h"
+
+static const char *device_cap2name[] = {
+    "capture", "tuner", "teletext", "overlay", "chromakey", "clipping",
+    "frameram", "scales", "monochrome", "subcapture", "mpeg-decoder",
+    "mpeg-encoder", "mjpeg-decoder", "mjpeg-encoder", NULL
+};
+
+static const char *device_palette2name[] = {
+    "-", "grey", "hi240", "rgb16", "rgb24", "rgb32", "rgb15", "yuv422",
+    "yuyv", "uyvy", "yuv420", "yuv411", "raw", "yuv422p", "yuv411p",
+    "yuv420p", "yuv410p"
+};
+#define PALETTE(x) ((x < sizeof(device_palette2name)/sizeof(char*)) ? device_palette2name[x] : "UNKNOWN")
+
+static const char *norm2name(int mode)
+{
+    switch (mode) {
+    case VIDEO_MODE_PAL:
+	return "pal";
+    case VIDEO_MODE_SECAM:
+	return "secam";
+    case VIDEO_MODE_NTSC:
+	return "ntsc";
+    case VIDEO_MODE_AUTO:
+	return "auto";
+    default:
+	return "unknown";
+    }
+};
+
+static const char *audio_mode2name(int mode)
+{
+    switch (mode) {
+    case VIDEO_SOUND_MONO:
+	return "mono";
+    case VIDEO_SOUND_STEREO:
+	return "stereo";
+    case VIDEO_SOUND_LANG1:
+	return "language1";
+    case VIDEO_SOUND_LANG2:
+	return "language2";
+    default:
+	return "unknown";
+    }
+};
+
+static void *audio_grabber(void *data);
+static void *video_grabber(void *data);
+
+static int palette2depth(int palette)
+{
+    switch(palette)
+    {
+	/* component */
+	case VIDEO_PALETTE_RGB555:
+	    return(15);
+	case VIDEO_PALETTE_RGB565:
+	    return(16);
+	case VIDEO_PALETTE_RGB24:
+	    return(24);
+	case VIDEO_PALETTE_RGB32:
+	    return(32);
+	/* planar */
+	case VIDEO_PALETTE_YUV411P:
+	case VIDEO_PALETTE_YUV420P:
+	case VIDEO_PALETTE_YUV410P:
+	    return(12);
+	/* packed */
+	case VIDEO_PALETTE_YUV422P:
+	case VIDEO_PALETTE_YUV422:
+	case VIDEO_PALETTE_YUYV:
+	case VIDEO_PALETTE_UYVY:
+	case VIDEO_PALETTE_YUV420:
+	case VIDEO_PALETTE_YUV411:
+	    return(16);
+    }
+    return(-1);
+}
+
+static int format2palette(int format)
+{
+    switch(format)
+    {
+	case IMGFMT_BGR15:
+	    return(VIDEO_PALETTE_RGB555);
+	case IMGFMT_BGR16:
+	    return(VIDEO_PALETTE_RGB565);
+	case IMGFMT_BGR24:
+	    return(VIDEO_PALETTE_RGB24);
+	case IMGFMT_BGR32:
+	    return(VIDEO_PALETTE_RGB32);
+	case IMGFMT_YV12:
+	case IMGFMT_I420:
+	    return(VIDEO_PALETTE_YUV420P);
+	case IMGFMT_YUY2:
+	    return(VIDEO_PALETTE_YUV422);
+    case IMGFMT_UYVY:
+       return(VIDEO_PALETTE_UYVY);
+    }
+    return(-1);
+}
+
+// sets and sanitizes audio buffer/block sizes
+static void setup_audio_buffer_sizes(priv_t *priv)
+{
+    int bytes_per_sample = priv->audio_in.bytes_per_sample;
+
+    // make the audio buffer at least 5 seconds long
+    priv->audio_buffer_size = 1 + 5*priv->audio_in.samplerate
+	*priv->audio_in.channels
+	*bytes_per_sample/priv->audio_in.blocksize;
+    if (priv->audio_buffer_size < 256) priv->audio_buffer_size = 256;
+
+    // make the skew buffer at least 1 second long
+    priv->aud_skew_cnt = 1 + 1*priv->audio_in.samplerate
+	*priv->audio_in.channels
+	*bytes_per_sample/priv->audio_in.blocksize;
+    if (priv->aud_skew_cnt < 16) priv->aud_skew_cnt = 16;
+
+    mp_msg(MSGT_TV, MSGL_V, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
+	   priv->audio_buffer_size, priv->audio_in.blocksize, priv->aud_skew_cnt);
+}
+
+tvi_handle_t *tvi_init_v4l(char *device, char *adevice)
+{
+    tvi_handle_t *h;
+    priv_t *priv;
+    
+    h = new_handle();
+    if (!h)
+	return(NULL);
+
+    priv = h->priv;
+
+    /* set video device name */
+    if (!device)
+	priv->video_device = strdup("/dev/video0");
+    else
+	priv->video_device = strdup(device);
+
+    /* set video device name */
+    if (!adevice)
+	priv->audio_device = NULL;
+    else {
+	priv->audio_device = strdup(adevice);
+    }
+    
+    /* allocation failed */
+    if (!priv->video_device) {
+	free_handle(h);
+	return(NULL);
+    }
+
+    return(h);
+}
+
+/* retrieves info about audio channels from the BTTV */
+static void init_v4l_audio(priv_t *priv)
+{
+    int i;
+    int reqmode;
+
+    if (!priv->capability.audios) return;
+
+    /* audio chanlist */
+
+    mp_msg(MSGT_TV, MSGL_V, " Audio devices: %d\n", priv->capability.audios);
+
+    mp_msg(MSGT_TV, MSGL_V, "Video capture card reports the audio setup as follows:\n");
+    for (i = 0; i < priv->capability.audios; i++)
+    {
+	if (i >= MAX_AUDIO_CHANNELS)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "no space for more audio channels (increase in source!) (%d > %d)\n",
+		   i, MAX_AUDIO_CHANNELS);
+	    i = priv->capability.audios;
+	    break;
+	}
+
+	priv->audio[i].audio = i;
+	if (ioctl(priv->video_fd, VIDIOCGAUDIO, &priv->audio[i]) == -1)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get audio failed: %s\n", strerror(errno));
+	    break;
+	}
+
+	/* mute all channels */
+	priv->audio[i].flags |= VIDEO_AUDIO_MUTE;
+	reqmode = -1;
+	if (tv_param_amode >= 0) {
+	    switch (tv_param_amode) {
+	    case 0:
+		reqmode = VIDEO_SOUND_MONO;
+		break;
+	    case 1:
+		reqmode = VIDEO_SOUND_STEREO;
+		break;
+	    case 2:
+		reqmode = VIDEO_SOUND_LANG1;
+		break;
+	    case 3:
+		reqmode = VIDEO_SOUND_LANG2;
+		break;
+	    default:
+		mp_msg(MSGT_TV, MSGL_ERR, "Unknown audio mode requested.\n");
+		break;
+	    }
+	    if (reqmode >= 0) priv->audio[i].mode = reqmode;
+	}
+	ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[i]);
+	
+	// get the parameters back
+	if (ioctl(priv->video_fd, VIDIOCGAUDIO, &priv->audio[i]) == -1)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get audio failed: %s\n", strerror(errno));
+	    break;
+	}
+	    
+	switch(priv->audio[i].mode)
+	{
+	case VIDEO_SOUND_MONO:
+	case VIDEO_SOUND_LANG1:
+	case VIDEO_SOUND_LANG2:
+	    priv->audio_channels[i] = 1;
+	    break;
+	case VIDEO_SOUND_STEREO:
+	    priv->audio_channels[i] = 2;
+	    break;
+	default:
+	    mp_msg(MSGT_TV, MSGL_ERR, "Card reports an unknown audio mode !\n");
+	    mp_msg(MSGT_TV, MSGL_ERR, "Trying two channel audio. Use forcechan to override.\n");
+	    priv->audio_channels[i] = 2;
+	    break;
+	}
+
+	if (reqmode >= 0 && priv->audio[i].mode != reqmode) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "Audio mode setup warning!\n");
+	    mp_msg(MSGT_TV, MSGL_ERR, "Requested mode was %s, but v4l still reports %s.\n",
+		   audio_mode2name(reqmode), audio_mode2name(priv->audio[i].mode));
+	    mp_msg(MSGT_TV, MSGL_ERR, "You may need \"forcechan\" option to force stereo/mono audio recording.\n");
+	}
+
+	/* display stuff */
+	mp_msg(MSGT_TV, MSGL_V, "  %d: %s: ", priv->audio[i].audio,
+	       priv->audio[i].name);
+	if (priv->audio[i].flags & VIDEO_AUDIO_MUTABLE) {
+	    mp_msg(MSGT_TV, MSGL_V, "muted=%s ",
+		   (priv->audio[i].flags & VIDEO_AUDIO_MUTE) ? "yes" : "no");
+	}
+	mp_msg(MSGT_TV, MSGL_V, "vol=%d bass=%d treble=%d balance=%d mode=%s",
+	       priv->audio[i].volume, priv->audio[i].bass, priv->audio[i].treble,
+	       priv->audio[i].balance, audio_mode2name(priv->audio[i].mode));
+	mp_msg(MSGT_TV, MSGL_V, " chan=%d\n", priv->audio_channels[i]);
+
+	if (tv_param_forcechan >= 0)
+	    priv->audio_channels[i] = tv_param_forcechan;
+
+	// we'll call VIDIOCSAUDIO again when starting capture
+	// let's set audio mode to requested mode again for the case
+	// when VIDIOCGAUDIO just cannot report the mode correctly
+	if (reqmode >= 0) priv->audio[i].mode = reqmode;
+    }
+}
+
+#if !defined(__LINUX_VIDEODEV2_H) && !defined(VIDIOC_QUERYCAP)
+struct v4l2_capability
+{
+        __u8    driver[16];     /* i.e. "bttv" */
+        __u8    card[32];       /* i.e. "Hauppauge WinTV" */
+        __u8    bus_info[32];   /* "PCI:" + pci_dev->slot_name */
+        __u32   version;        /* should use KERNEL_VERSION() */
+        __u32   capabilities;   /* Device capabilities */
+        __u32   reserved[4];
+};
+
+#define VIDIOC_QUERYCAP         _IOR  ('V',  0, struct v4l2_capability)
+#endif
+
+static int init(priv_t *priv)
+{
+    int i;
+
+    if (tv_param_immediate == 1)
+	tv_param_noaudio = 1;
+    
+    priv->video_ringbuffer = NULL;
+    priv->video_timebuffer = NULL;
+    priv->video_avg_buffer = NULL;
+    priv->audio_ringbuffer = NULL;
+    priv->audio_skew_buffer = NULL;
+
+    priv->video_fd = open(priv->video_device, O_RDWR);
+    mp_msg(MSGT_TV, MSGL_DBG2, "Video fd: %d, %p\n", priv->video_fd,
+	priv->video_device);
+    if (priv->video_fd == -1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "unable to open '%s': %s\n",
+	    priv->video_device, strerror(errno));
+	goto err;
+    }
+    
+    /* check for v4l2 */
+    if (ioctl(priv->video_fd, VIDIOC_QUERYCAP, &priv->capability) == 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "=================================================================\n");
+	mp_msg(MSGT_TV, MSGL_ERR, " WARNING: YOU ARE USING V4L DEMUXER WITH V4L2 DRIVERS!!!\n");
+	mp_msg(MSGT_TV, MSGL_ERR, " As the V4L1 compatibility layer is broken, this may not work.\n");
+	mp_msg(MSGT_TV, MSGL_ERR, " If you encounter any problems, use driver=v4l2 instead.\n");
+	mp_msg(MSGT_TV, MSGL_ERR, " Bugreports on driver=v4l with v4l2 drivers will be ignored.\n");
+	mp_msg(MSGT_TV, MSGL_ERR, "=================================================================\n");
+    }
+    
+    /* get capabilities (priv->capability is needed!) */
+    if (ioctl(priv->video_fd, VIDIOCGCAP, &priv->capability) == -1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "ioctl get capabilites failed: %s\n", strerror(errno));
+	goto err;
+    }
+
+    fcntl(priv->video_fd, F_SETFD, FD_CLOEXEC);
+
+    mp_msg(MSGT_TV, MSGL_INFO, "Selected device: %s\n", priv->capability.name);
+    mp_msg(MSGT_TV, MSGL_INFO, " Capabilites: ");
+    for (i = 0; device_cap2name[i] != NULL; i++)
+	if (priv->capability.type & (1 << i))
+	    mp_msg(MSGT_TV, MSGL_INFO, "%s ", device_cap2name[i]);
+    mp_msg(MSGT_TV, MSGL_INFO, "\n");
+    mp_msg(MSGT_TV, MSGL_INFO, " Device type: %d\n", priv->capability.type);
+    mp_msg(MSGT_TV, MSGL_INFO, " Supported sizes: %dx%d => %dx%d\n",
+	priv->capability.minwidth, priv->capability.minheight,
+	priv->capability.maxwidth, priv->capability.maxheight);
+    priv->width = priv->capability.minwidth;
+    priv->height = priv->capability.minheight;
+
+    /* somewhere here could disable tv_param_mjpeg, if it is not a capability */
+
+    /* initialize if necessary */
+    if ( tv_param_mjpeg )
+      {
+        struct mjpeg_params bparm;
+        struct mjpeg_requestbuffers breq;          /* buffer requests */
+
+        if (ioctl(priv->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)
+        {
+           mp_msg(MSGT_TV, MSGL_ERR, 
+              "  MJP: Error getting video parameters: %s\n", strerror(errno));
+           goto err;
+        }
+
+        mp_msg(MSGT_TV, MSGL_INFO, 
+	       "  MJP: previous params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n",
+	           bparm.img_x, bparm.img_y, bparm.img_width, bparm.img_height,          
+		   bparm.decimation, bparm.field_per_buff);
+
+        mp_msg(MSGT_TV, MSGL_INFO, 
+	       "  MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n",
+	           bparm.HorDcm, bparm.VerDcm, bparm.TmpDcm);
+
+        bparm.input = tv_param_input; /* tv */
+        if (!strcasecmp(tv_param_norm, "pal"))
+	  bparm.norm =  0; /* PAL */
+        else if (!strcasecmp(tv_param_norm, "ntsc"))
+	  bparm.norm =  1; /* NTSC */
+        else if (!strcasecmp(tv_param_norm, "secam"))
+	  bparm.norm =  2; /* SECAM */
+        bparm.quality = tv_param_quality;
+        bparm.decimation = tv_param_decimation;
+
+        mp_msg(MSGT_TV, MSGL_INFO, "  MJP: setting params to decimation: %d, quality: %d\n", 
+	                                 bparm.decimation, bparm.quality);
+
+        if (ioctl(priv->video_fd, MJPIOC_S_PARAMS, &bparm) < 0)
+         {
+            mp_msg(MSGT_TV, MSGL_ERR,
+               "  MJP: Error setting video parameters: %s\n", strerror(errno));
+            goto err;
+         }
+
+        if (ioctl(priv->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)
+        {
+           mp_msg(MSGT_TV, MSGL_ERR, 
+              "  MJP: Error getting video parameters: %s\n", strerror(errno));
+           goto err;
+        }
+
+        mp_msg(MSGT_TV, MSGL_INFO, 
+	       "  MJP: current params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n",
+	           bparm.img_x, bparm.img_y, bparm.img_width, bparm.img_height,          
+		   bparm.decimation, bparm.field_per_buff);
+
+        mp_msg(MSGT_TV, MSGL_INFO, 
+	       "  MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n",
+	           bparm.HorDcm, bparm.VerDcm, bparm.TmpDcm);
+
+
+        breq.count = 64;
+	priv -> nbuf = breq.count;
+        priv->mbuf.frames = priv -> nbuf;
+        priv->mjpeg_bufsize = 256*1024;
+        if (tv_param_buffer_size >= 0) {
+          priv->mjpeg_bufsize = tv_param_buffer_size*1024;
+	  }
+        breq.size  = priv -> mjpeg_bufsize;
+        if (ioctl(priv->video_fd, MJPIOC_REQBUFS,&(breq)) < 0)
+        {
+           mp_msg (MSGT_TV, MSGL_ERR,
+              "  MJP: Error requesting video buffers: %s\n", strerror(errno));
+           goto err;
+        }
+        mp_msg(MSGT_TV, MSGL_INFO,
+           "  MJP: Got %ld buffers of size %ld KB\n", 
+                    breq.count, breq.size/1024);
+
+        priv -> mmap = mmap(0, breq.count * breq.size, 
+           PROT_READ|PROT_WRITE, MAP_SHARED, priv->video_fd, 0);
+        if (priv -> mmap == MAP_FAILED)
+        {
+           mp_msg(MSGT_TV, MSGL_INFO,
+              "  MJP: Error mapping video buffers: %s\n", strerror(errno));
+           goto err;
+        }
+      }
+
+    mp_msg(MSGT_TV, MSGL_INFO, " Inputs: %d\n", priv->capability.channels);
+    priv->channels = calloc(priv->capability.channels, sizeof(struct video_channel));
+    if (!priv->channels)
+	goto malloc_failed;
+    memset(priv->channels, 0, sizeof(struct video_channel)*priv->capability.channels);
+    for (i = 0; i < priv->capability.channels; i++)
+    {
+	priv->channels[i].channel = i;
+	if (ioctl(priv->video_fd, VIDIOCGCHAN, &priv->channels[i]) == -1)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get channel failed: %s\n", strerror(errno));
+	    break;
+	}
+	mp_msg(MSGT_TV, MSGL_INFO, "  %d: %s: %s%s%s%s (tuner:%d, norm:%s)\n", i,
+	    priv->channels[i].name,
+	    (priv->channels[i].flags & VIDEO_VC_TUNER) ? "tuner " : "",
+	    (priv->channels[i].flags & VIDEO_VC_AUDIO) ? "audio " : "",
+	    (priv->channels[i].flags & VIDEO_TYPE_TV) ? "tv " : "",
+	    (priv->channels[i].flags & VIDEO_TYPE_CAMERA) ? "camera " : "",
+	    priv->channels[i].tuners,
+	    norm2name(priv->channels[i].norm));
+    }
+    priv->act_channel = 0;
+
+    if (!(priv->capability.type & VID_TYPE_CAPTURE))
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "Only grabbing supported (for overlay use another program)\n");
+	goto err;
+    }
+    
+    if ( !tv_param_mjpeg )
+    {
+    /* map grab buffer */
+    if (ioctl(priv->video_fd, VIDIOCGMBUF, &priv->mbuf) == -1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "ioctl get mbuf failed: %s\n", strerror(errno));
+	goto err;
+    }
+
+    mp_msg(MSGT_TV, MSGL_V, "mbuf: size=%d, frames=%d\n",
+	priv->mbuf.size, priv->mbuf.frames);
+    priv->mmap = mmap(0, priv->mbuf.size, PROT_READ|PROT_WRITE,
+		MAP_SHARED, priv->video_fd, 0);
+    if (priv->mmap == (unsigned char *)-1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "Unable to map memory for buffers: %s\n", strerror(errno));
+	goto err;
+    }
+    mp_msg(MSGT_TV, MSGL_DBG2, "our buffer: %p\n", priv->mmap);
+
+    /* num of buffers */
+    priv->nbuf = priv->mbuf.frames;
+    
+    /* video buffers */
+    priv->buf = calloc(priv->nbuf, sizeof(struct video_mmap));
+    if (!priv->buf)
+	goto malloc_failed;
+    memset(priv->buf, 0, priv->nbuf * sizeof(struct video_mmap));
+    }
+    
+    /* init v4l audio even when we don't capture */
+    init_v4l_audio(priv);
+
+    if (!priv->capability.audios && !tv_param_force_audio) tv_param_noaudio = 1;
+
+    /* audio init */
+    if (!tv_param_noaudio) {
+	
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+	if (tv_param_alsa)
+	    audio_in_init(&priv->audio_in, AUDIO_IN_ALSA);
+	else
+	    audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
+#else
+	audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
+#endif
+
+	if (priv->audio_device) {
+	    audio_in_set_device(&priv->audio_in, priv->audio_device);
+	}
+
+	if (tv_param_audio_id < priv->capability.audios)
+	    priv->audio_id = tv_param_audio_id;
+	else
+	    priv->audio_id = 0;
+	audio_in_set_samplerate(&priv->audio_in, 44100);
+	if (priv->capability.audios) {
+	    audio_in_set_channels(&priv->audio_in, priv->audio_channels[priv->audio_id]);
+	} else {
+	    if (tv_param_forcechan >= 0) {
+		audio_in_set_channels(&priv->audio_in, tv_param_forcechan);
+	    } else {
+		audio_in_set_channels(&priv->audio_in, 2);
+	    }
+	}
+	if (audio_in_setup(&priv->audio_in) < 0) return 0;
+	setup_audio_buffer_sizes(priv);
+    }
+
+    return(1);
+
+malloc_failed:
+    if (priv->channels)
+	free(priv->channels);
+    if (priv->buf)
+	free(priv->buf);
+err:
+    if (priv->video_fd != -1)
+	close(priv->video_fd);
+    return(0);
+}
+
+static int uninit(priv_t *priv)
+{
+    unsigned long num;
+    priv->shutdown = 1;
+
+    mp_msg(MSGT_TV, MSGL_V, "Waiting for threads to finish... ");
+    if (!tv_param_noaudio) {
+	pthread_join(priv->audio_grabber_thread, NULL);
+	pthread_mutex_destroy(&priv->audio_starter);
+	pthread_mutex_destroy(&priv->skew_mutex);
+    }
+    pthread_mutex_destroy(&priv->video_buffer_mutex);
+    pthread_join(priv->video_grabber_thread, NULL);
+    mp_msg(MSGT_TV, MSGL_V, "done\n");
+
+    if (priv->capability.audios) {
+	priv->audio[priv->audio_id].flags |= VIDEO_AUDIO_MUTE;
+	ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
+    }
+    
+    if ( tv_param_mjpeg )
+      {
+	num = -1;
+        if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)
+          {
+            mp_msg(MSGT_TV, MSGL_ERR, "\n  MJP: ioctl MJPIOC_QBUF_CAPT failed: %s\n", strerror(errno));
+          }
+      }
+    else
+      {
+	// We need to munmap as close don't close mem mappings
+	if(munmap(priv->mmap,priv->mbuf.size))
+	  mp_msg(MSGT_TV, MSGL_ERR, "Munmap failed: %s\n",strerror(errno));
+      }
+
+    if(close(priv->video_fd))
+      mp_msg(MSGT_TV, MSGL_ERR, "Close tv failed: %s\n",strerror(errno));
+
+    audio_in_uninit(&priv->audio_in);
+
+    if (priv->video_ringbuffer) {
+	int i;
+	for (i = 0; i < priv->video_buffer_size_current; i++) {
+	    free(priv->video_ringbuffer[i]);
+	}
+	free(priv->video_ringbuffer);
+    }
+    
+    if (priv->video_timebuffer)
+	free(priv->video_timebuffer);
+    if (priv->video_avg_buffer)
+	free(priv->video_avg_buffer);
+    if (!tv_param_noaudio) {
+	if (priv->audio_ringbuffer)
+	    free(priv->audio_ringbuffer);
+	if (priv->audio_skew_buffer)
+	    free(priv->audio_skew_buffer);
+    }
+
+    return(1);
+}
+
+static int get_capture_buffer_size(priv_t *priv)
+{
+    int bufsize, cnt;
+
+    if (tv_param_buffer_size >= 0) {
+	bufsize = tv_param_buffer_size*1024*1024;
+    } else {
+#ifdef HAVE_SYS_SYSINFO_H
+	struct sysinfo si;
+	
+	sysinfo(&si);
+	if (si.totalram<2*1024*1024) {
+	    bufsize = 1024*1024;
+	} else {
+	    bufsize = si.totalram/2;
+	}
+#else
+	bufsize = 16*1024*1024;
+#endif
+    }
+    
+    cnt = bufsize/(priv->height*priv->bytesperline);
+    if (cnt < 2) cnt = 2;
+    
+    return cnt;
+}
+
+static int start(priv_t *priv)
+{
+    int i;
+    int bytes_per_sample;
+    
+    if (ioctl(priv->video_fd, VIDIOCGPICT, &priv->picture) == -1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "ioctl get picture failed: %s\n", strerror(errno));
+	return(0);
+    }
+
+    priv->picture.palette = format2palette(priv->format);
+    priv->picture.depth = palette2depth(priv->picture.palette);
+
+    if (priv->format != IMGFMT_BGR15) {
+	priv->bytesperline = priv->width * priv->picture.depth / 8;
+    } else {
+	priv->bytesperline = priv->width * 2;
+    }
+
+    mp_msg(MSGT_TV, MSGL_V, "Picture values:\n");
+    mp_msg(MSGT_TV, MSGL_V, " Depth: %d, Palette: %s (Format: %s)\n", priv->picture.depth,
+	PALETTE(priv->picture.palette), vo_format_name(priv->format));
+    mp_msg(MSGT_TV, MSGL_V, " Brightness: %d, Hue: %d, Colour: %d, Contrast: %d\n",
+	priv->picture.brightness, priv->picture.hue,
+	priv->picture.colour, priv->picture.contrast);
+    
+
+    if (ioctl(priv->video_fd, VIDIOCSPICT, &priv->picture) == -1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "ioctl set picture failed: %s\n", strerror(errno));
+    }
+
+    if ( !tv_param_mjpeg )
+    {
+    priv->nbuf = priv->mbuf.frames;
+    for (i=0; i < priv->nbuf; i++)
+    {
+	priv->buf[i].format = priv->picture.palette;
+	priv->buf[i].frame = i;
+	priv->buf[i].width = priv->width;
+	priv->buf[i].height = priv->height;
+	mp_msg(MSGT_TV, MSGL_DBG2, "buffer: %d => %p\n", i, &priv->buf[i]);
+    } 
+    } 
+
+#if 0
+    {
+	struct video_play_mode pmode;
+	
+	pmode.mode = VID_PLAY_NORMAL;
+	pmode.p1 = 1;
+	pmode.p2 = 0;
+	if (ioctl(priv->video_fd, VIDIOCSPLAYMODE, &pmode) == -1)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl set play mode failed: %s\n", strerror(errno));
+//	    return(0);
+	}
+    }
+#endif
+
+#if 0
+    {
+	struct video_window win;
+
+	win.x = 0;
+	win.y = 0;
+	win.width = priv->width;
+	win.height = priv->height;
+	win.chromakey = -1;
+	win.flags = 0;
+	//win.clipcount = 0;
+	
+	ioctl(priv->video_fd, VIDIOCSWIN, &win);
+    }
+
+    // initialize video capture
+    if (ioctl(priv->video_fd, VIDIOCCAPTURE, &one) == -1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "FATAL: ioctl ccapture failed: %s\n", strerror(errno));
+	return(0);
+    }
+#endif
+
+    /* setup audio parameters */
+    if (!tv_param_noaudio) {
+	setup_audio_buffer_sizes(priv);
+	bytes_per_sample = priv->audio_in.bytes_per_sample;
+	priv->audio_skew_buffer = calloc(priv->aud_skew_cnt, sizeof(long long));
+	if (!priv->audio_skew_buffer) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
+	    return 0;
+	}
+
+	priv->audio_ringbuffer = calloc(priv->audio_in.blocksize, priv->audio_buffer_size);
+	if (!priv->audio_ringbuffer) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate audio buffer: %s\n", strerror(errno));
+	    return 0;
+	}
+
+	priv->audio_secs_per_block = (double)priv->audio_in.blocksize/(priv->audio_in.samplerate
+								    *priv->audio_in.channels
+								    *bytes_per_sample);
+	priv->audio_head = 0;
+	priv->audio_tail = 0;
+	priv->audio_cnt = 0;
+	priv->audio_drop = 0;
+	priv->audio_skew = 0;
+	priv->audio_skew_total = 0;
+	priv->audio_recv_blocks_total = 0;
+	priv->audio_sent_blocks_total = 0;
+    }
+
+    /* setup video parameters */
+    if (priv->immediate_mode) {
+	priv->video_buffer_size_max = VID_BUF_SIZE_IMMEDIATE;
+    } else {
+	priv->video_buffer_size_max = get_capture_buffer_size(priv);
+    }
+    priv->video_buffer_size_current = 0;
+
+    if (!tv_param_noaudio) {
+	if (priv->video_buffer_size_max < 3.0*priv->fps*priv->audio_secs_per_block) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "Video buffer shorter than 3 times audio frame duration.\n"
+		   "You will probably experience heavy framedrops.\n");
+	}
+    }
+
+    mp_msg(MSGT_TV, MSGL_V, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
+	   priv->video_buffer_size_max,
+	   priv->video_buffer_size_max*priv->height*priv->bytesperline/(1024*1024));
+
+    priv->video_ringbuffer = calloc(priv->video_buffer_size_max, sizeof(unsigned char*));
+    if (!priv->video_ringbuffer) {
+	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate video buffer: %s\n", strerror(errno));
+	return 0;
+    }
+    for (i = 0; i < priv->video_buffer_size_max; i++)
+	priv->video_ringbuffer[i] = NULL;
+    
+    priv->video_timebuffer = calloc(priv->video_buffer_size_max, sizeof(long long));
+    if (!priv->video_timebuffer) {
+	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate time buffer: %s\n", strerror(errno));
+	return 0;
+    }
+    priv->video_avg_buffer = malloc(sizeof(long long) * VIDEO_AVG_BUFFER_SIZE);
+    if (!priv->video_avg_buffer) {
+	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate period buffer: %s\n", strerror(errno));
+	return 0;
+    }
+    priv->video_interval_sum = (1e6/priv->fps)*VIDEO_AVG_BUFFER_SIZE;
+    for (i = 0; i < VIDEO_AVG_BUFFER_SIZE; i++) {
+	priv->video_avg_buffer[i] = 1e6/priv->fps;
+    }
+
+    priv->video_avg_ptr = 0;
+    
+    priv->video_head = 0;
+    priv->video_tail = 0;
+    priv->video_cnt = 0;
+    priv->first = 1;
+
+    if (priv->capability.audios) {
+	/* enable audio */
+	if (tv_param_volume >= 0)
+	    priv->audio[priv->audio_id].volume = tv_param_volume;
+	if (tv_param_bass >= 0)
+	    priv->audio[priv->audio_id].bass = tv_param_bass;
+	if (tv_param_treble >= 0)
+	    priv->audio[priv->audio_id].treble = tv_param_treble;
+	if (tv_param_balance >= 0)
+	    priv->audio[priv->audio_id].balance = tv_param_balance;
+	priv->audio[priv->audio_id].flags &= ~VIDEO_AUDIO_MUTE;
+	mp_msg(MSGT_TV, MSGL_V, "Enabling tv audio. Requested setup is:\n");
+	mp_msg(MSGT_TV, MSGL_V, "id=%d vol=%d bass=%d treble=%d balance=%d mode=%s",
+	       priv->audio_id,
+	       priv->audio[priv->audio_id].volume, priv->audio[priv->audio_id].bass, priv->audio[priv->audio_id].treble,
+	       priv->audio[priv->audio_id].balance, audio_mode2name(priv->audio[priv->audio_id].mode));
+	mp_msg(MSGT_TV, MSGL_V, " chan=%d\n", priv->audio_channels[priv->audio_id]);
+	ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
+    }
+    
+    /* launch capture threads */
+    priv->shutdown = 0;
+    if (!tv_param_noaudio) {
+	pthread_mutex_init(&priv->audio_starter, NULL);
+	pthread_mutex_init(&priv->skew_mutex, NULL);
+	pthread_mutex_lock(&priv->audio_starter);
+	pthread_create(&priv->audio_grabber_thread, NULL, audio_grabber, priv);
+    }
+    pthread_mutex_init(&priv->video_buffer_mutex, NULL);
+    /* we'll launch the video capture later, when a first request for a frame arrives */
+
+    return(1);
+}
+
+
+static int control(priv_t *priv, int cmd, void *arg)
+{
+    mp_msg(MSGT_TV, MSGL_DBG2, "\ndebug: control(priv=%p, cmd=%d, arg=%p)\n",
+	priv, cmd, arg);
+    switch(cmd)
+    {
+	/* ========== GENERIC controls =========== */
+	case TVI_CONTROL_IS_VIDEO:
+	{
+	    if (priv->capability.type & VID_TYPE_CAPTURE)
+		return(TVI_CONTROL_TRUE);
+	    return(TVI_CONTROL_FALSE);
+	}
+	case TVI_CONTROL_IS_AUDIO:
+	    if (tv_param_force_audio) return(TVI_CONTROL_TRUE);
+	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_AUDIO)
+	    {
+		return(TVI_CONTROL_TRUE);
+	    }
+	    return(TVI_CONTROL_FALSE);
+	case TVI_CONTROL_IS_TUNER:
+	{
+//	    if (priv->capability.type & VID_TYPE_TUNER)
+	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_TUNER)
+		return(TVI_CONTROL_TRUE);
+	    return(TVI_CONTROL_FALSE);
+	}
+
+	/* ========== VIDEO controls =========== */
+	case TVI_CONTROL_VID_GET_FORMAT:
+	{
+	    int output_fmt = -1;
+
+	    output_fmt = priv->format;
+            if ( tv_param_mjpeg )
+	    {
+              mp_msg(MSGT_TV, MSGL_INFO, "  MJP: setting sh_video->format to mjpg\n");
+	      output_fmt = 0x47504a4d;
+	      output_fmt = 0x67706a6d;
+	      *(int *)arg = output_fmt;
+	      mp_msg(MSGT_TV, MSGL_V, "Output format: %s\n", "mjpg");
+	    }
+	    else
+	    {
+	    *(int *)arg = output_fmt;
+	    mp_msg(MSGT_TV, MSGL_V, "Output format: %s\n", vo_format_name(output_fmt));
+	    }
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_VID_SET_FORMAT:
+	    priv->format = *(int *)arg;
+	    // !HACK! v4l uses BGR format instead of RGB
+	    // and we have to correct this. Fortunately,
+	    // tv.c reads later the format back so we
+	    // can persuade it to use what we want.
+	    if (IMGFMT_IS_RGB(priv->format)) {
+		priv->format &= ~IMGFMT_RGB_MASK;
+		priv->format |= IMGFMT_BGR;
+	    }
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_GET_PLANES:
+	    *(int *)arg = 1; /* FIXME, also not needed at this time */
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_GET_BITS:
+	    *(int *)arg = palette2depth(format2palette(priv->format));
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_GET_WIDTH:
+	    *(int *)arg = priv->width;
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_CHK_WIDTH:
+	{
+	    int req_width = *(int *)arg;
+	    
+	    mp_msg(MSGT_TV, MSGL_V, "Requested width: %d\n", req_width);
+	    if ((req_width >= priv->capability.minwidth) &&
+		(req_width <= priv->capability.maxwidth))
+		return(TVI_CONTROL_TRUE);
+	    return(TVI_CONTROL_FALSE);
+	}
+	case TVI_CONTROL_VID_SET_WIDTH:
+	    priv->width = *(int *)arg;
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_GET_HEIGHT:
+	    *(int *)arg = priv->height;
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_CHK_HEIGHT:
+	{
+	    int req_height = *(int *)arg;
+	    
+	    mp_msg(MSGT_TV, MSGL_V, "Requested height: %d\n", req_height);
+	    if ((req_height >= priv->capability.minheight) &&
+		(req_height <= priv->capability.maxheight))
+		return(TVI_CONTROL_TRUE);
+	    return(TVI_CONTROL_FALSE);
+	}
+	case TVI_CONTROL_VID_SET_HEIGHT:
+	    priv->height = *(int *)arg;
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_GET_PICTURE:
+	    if (ioctl(priv->video_fd, VIDIOCGPICT, &priv->picture) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get picture failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_SET_PICTURE:
+	    if (ioctl(priv->video_fd, VIDIOCSPICT, &priv->picture) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get picture failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_VID_SET_BRIGHTNESS:
+	    priv->picture.brightness = (327*(*(int *)arg+100)) + 68;
+	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
+	case TVI_CONTROL_VID_SET_HUE:
+	    priv->picture.hue = (327*(*(int *)arg+100)) + 68;
+	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
+	case TVI_CONTROL_VID_SET_SATURATION:
+	    priv->picture.colour = (327*(*(int *)arg+100)) + 68;
+	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
+	case TVI_CONTROL_VID_SET_CONTRAST:
+	    priv->picture.contrast = (327*(*(int *)arg+100)) + 68;
+	    return control(priv, TVI_CONTROL_VID_SET_PICTURE, 0);
+	case TVI_CONTROL_VID_GET_BRIGHTNESS:
+	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
+	    *(int*)arg = ((int)priv->picture.brightness-68)/327-100;
+	    return 1;
+	case TVI_CONTROL_VID_GET_HUE:
+	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
+	    *(int*)arg = ((int)priv->picture.hue-68)/327-100;
+	    return 1;
+	case TVI_CONTROL_VID_GET_SATURATION:
+	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
+	    *(int*)arg = ((int)priv->picture.colour-68)/327-100;
+	    return 1;
+	case TVI_CONTROL_VID_GET_CONTRAST:
+	    if(!control(priv, TVI_CONTROL_VID_GET_PICTURE, 0)) return 0;
+	    *(int*)arg = ((int)priv->picture.contrast-68)/327-100;
+	    return 1;
+	case TVI_CONTROL_VID_GET_FPS:
+	    *(float *)arg=priv->fps;
+	    return(TVI_CONTROL_TRUE);
+
+	/* ========== TUNER controls =========== */
+	case TVI_CONTROL_TUN_GET_FREQ:
+	{
+	    unsigned long freq;
+	    
+	    if (ioctl(priv->video_fd, VIDIOCGFREQ, &freq) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get freq failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    
+	    /* tuner uses khz not mhz ! */
+//	    if (priv->tuner.flags & VIDEO_TUNER_LOW)
+//	        freq /= 1000;
+	    *(unsigned long *)arg = freq;
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_TUN_SET_FREQ:
+	{
+	    /* argument is in MHz ! */
+	    unsigned long freq = *(unsigned long *)arg;
+	    
+	    if (priv->capability.audios) {
+		priv->audio[priv->audio_id].flags |= VIDEO_AUDIO_MUTE;
+		ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
+	    }
+
+	    mp_msg(MSGT_TV, MSGL_V, "requested frequency: %.3f\n", (float)freq/16);
+	    
+	    /* tuner uses khz not mhz ! */
+//	    if (priv->tuner.flags & VIDEO_TUNER_LOW)
+//	        freq *= 1000;
+//	    mp_msg(MSGT_TV, MSGL_V, " requesting from driver: freq=%.3f\n", (float)freq/16);
+	    if (ioctl(priv->video_fd, VIDIOCSFREQ, &freq) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set freq failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    usleep(100000); // wait to suppress noise during switching
+
+	    if (priv->capability.audios) {
+		priv->audio[priv->audio_id].flags &= ~VIDEO_AUDIO_MUTE;
+		ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]);
+	    }
+
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_TUN_GET_TUNER:
+	{
+	    if (ioctl(priv->video_fd, VIDIOCGTUNER, &priv->tuner) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get tuner failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    
+	    mp_msg(MSGT_TV, MSGL_V, "Tuner (%s) range: %lu -> %lu\n", priv->tuner.name,
+		priv->tuner.rangelow, priv->tuner.rangehigh);
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_TUN_SET_TUNER:
+	{
+	    if (ioctl(priv->video_fd, VIDIOCSTUNER, &priv->tuner) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set tuner failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_TUN_SET_NORM:
+	{
+	    int req_mode = *(int *)arg;
+
+	    if ((req_mode != TV_NORM_PAL) && (req_mode != TV_NORM_NTSC) && (req_mode != TV_NORM_SECAM)
+		&& (req_mode != TV_NORM_PALNC) && (req_mode != TV_NORM_PALM) && (req_mode != TV_NORM_PALN)
+		&& (req_mode != TV_NORM_NTSCJP)) {
+		mp_msg(MSGT_TV, MSGL_ERR, "Unknown norm!\n");
+		return(TVI_CONTROL_FALSE);
+	    }
+
+	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_TUNER) {
+		int prev_mode;
+		
+		control(priv, TVI_CONTROL_TUN_GET_TUNER, 0);
+		if (((req_mode == TV_NORM_PAL
+		      || req_mode == TV_NORM_PALNC
+		      || req_mode == TV_NORM_PALN) && !(priv->tuner.flags & VIDEO_TUNER_PAL)) ||
+		    ((req_mode == TV_NORM_NTSC
+		      || req_mode == TV_NORM_NTSCJP
+		      || req_mode == TV_NORM_PALM) && !(priv->tuner.flags & VIDEO_TUNER_NTSC)) ||
+		    ((req_mode == TV_NORM_SECAM) && !(priv->tuner.flags & VIDEO_TUNER_SECAM)))
+		{
+		    mp_msg(MSGT_TV, MSGL_ERR, "Tuner isn't capable to set norm!\n");
+		    return(TVI_CONTROL_FALSE);
+		}
+
+		prev_mode = priv->tuner.mode;
+
+		switch(req_mode) {
+		case TV_NORM_PAL:
+		case TV_NORM_PALNC:
+		case TV_NORM_PALN:
+		    priv->tuner.mode = VIDEO_MODE_PAL;
+		    break;
+		case TV_NORM_NTSC:
+		case TV_NORM_NTSCJP:
+		case TV_NORM_PALM:
+		    priv->tuner.mode = VIDEO_MODE_NTSC;
+		    break;
+		case TV_NORM_SECAM:
+		    priv->tuner.mode = VIDEO_MODE_SECAM;
+		    break;
+		}
+	    
+		if (control(priv, TVI_CONTROL_TUN_SET_TUNER, &priv->tuner) != TVI_CONTROL_TRUE) {
+		    // norm setting failed, but maybe it's only because it's fixed
+		    if (priv->tuner.mode != prev_mode) return(TVI_CONTROL_FALSE); // no it really failed
+		}
+
+	    }
+
+	    switch(req_mode) {
+	    case TV_NORM_PAL:
+		priv->channels[priv->act_channel].norm = VIDEO_MODE_PAL;
+		break;
+	    case TV_NORM_NTSC:
+		priv->channels[priv->act_channel].norm = VIDEO_MODE_NTSC;
+		break;
+	    case TV_NORM_SECAM:
+		priv->channels[priv->act_channel].norm = VIDEO_MODE_SECAM;
+		break;
+	    case TV_NORM_PALNC:
+		priv->channels[priv->act_channel].norm = 3;
+		break;
+	    case TV_NORM_PALM:
+		priv->channels[priv->act_channel].norm = 4;
+		break;
+	    case TV_NORM_PALN:
+		priv->channels[priv->act_channel].norm = 5;
+		break;
+	    case TV_NORM_NTSCJP:
+		priv->channels[priv->act_channel].norm = 6;
+		break;
+	    }
+	    if (ioctl(priv->video_fd, VIDIOCSCHAN, &priv->channels[priv->act_channel]) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set chan failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+
+	    if (ioctl(priv->video_fd, VIDIOCGCAP, &priv->capability) == -1) {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get capabilites failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+
+	    if(req_mode == TV_NORM_PAL || req_mode == TV_NORM_SECAM || req_mode == TV_NORM_PALN || req_mode == TV_NORM_PALNC) {
+		priv->fps = PAL_FPS;
+            }
+
+	    if(req_mode == TV_NORM_NTSC || req_mode == TV_NORM_NTSCJP || req_mode == TV_NORM_PALM) {
+		priv->fps = NTSC_FPS;
+            }
+
+	    if(priv->height > priv->capability.maxheight) {
+		priv->height = priv->capability.maxheight;
+	    }
+
+	    if(priv->width > priv->capability.maxwidth) {
+		priv->width = priv->capability.maxwidth;
+	    }
+	    
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_TUN_GET_NORM:
+	{
+	    *(int *)arg = priv->tuner.mode;
+
+	    return(TVI_CONTROL_TRUE);
+	}
+	
+	/* ========== AUDIO controls =========== */
+	case TVI_CONTROL_AUD_GET_FORMAT:
+	{
+	    *(int *)arg = AF_FORMAT_S16_LE;
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_AUD_GET_CHANNELS:
+	{
+	    *(int *)arg = priv->audio_in.channels;
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_AUD_GET_SAMPLERATE:
+	{
+	    *(int *)arg = priv->audio_in.samplerate;
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_AUD_GET_SAMPLESIZE:
+	{
+	    *(int *)arg = priv->audio_in.bytes_per_sample;
+	    return(TVI_CONTROL_TRUE);
+	}
+	case TVI_CONTROL_AUD_SET_SAMPLERATE:
+	{
+	    if (audio_in_set_samplerate(&priv->audio_in, *(int *)arg) < 0) return TVI_CONTROL_FALSE;
+	    setup_audio_buffer_sizes(priv);
+	    return(TVI_CONTROL_TRUE);
+	}
+	/* ========== SPECIFIC controls =========== */
+	case TVI_CONTROL_SPC_GET_INPUT:
+	{
+	    int req_chan = *(int *)arg;
+	    int i;
+
+	    for (i = 0; i < priv->capability.channels; i++)
+	    {
+		if (priv->channels[i].channel == req_chan)
+		    break;
+	    }
+	    
+	    priv->act_channel = i;
+
+	    if (ioctl(priv->video_fd, VIDIOCGCHAN, &priv->channels[i]) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get channel failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    return(TVI_CONTROL_TRUE);
+	}
+
+	case TVI_CONTROL_SPC_SET_INPUT:
+	{
+	    struct video_channel chan;
+	    int req_chan = *(int *)arg;
+	    int i;
+	    
+	    if (req_chan >= priv->capability.channels)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "Invalid input requested: %d, valid: 0-%d\n",
+		    req_chan, priv->capability.channels - 1);
+		return(TVI_CONTROL_FALSE);
+	    }
+
+	    for (i = 0; i < priv->capability.channels; i++)
+	    {
+		if (priv->channels[i].channel == req_chan)
+		    chan = priv->channels[i];
+	    }
+
+	    if (ioctl(priv->video_fd, VIDIOCSCHAN, &chan) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set chan failed: %s\n", strerror(errno));
+		return(TVI_CONTROL_FALSE);
+	    }
+	    mp_msg(MSGT_TV, MSGL_INFO, "Using input '%s'\n", chan.name);
+
+	    priv->act_channel = i;
+
+	    /* update tuner state */
+//	    if (priv->capability.type & VID_TYPE_TUNER)
+	    if (priv->channels[priv->act_channel].flags & VIDEO_VC_TUNER)
+		control(priv, TVI_CONTROL_TUN_GET_TUNER, 0);
+
+	    /* update local channel list */	
+	    control(priv, TVI_CONTROL_SPC_GET_INPUT, &req_chan);
+	    return(TVI_CONTROL_TRUE);
+	case TVI_CONTROL_IMMEDIATE:
+	    priv->immediate_mode = 1;
+	    return(TVI_CONTROL_TRUE);
+	}
+    }
+
+    return(TVI_CONTROL_UNKNOWN);
+}
+
+// copies a video frame
+// for RGB (i.e. BGR in mplayer) flips the image upside down
+// for YV12 swaps the 2nd and 3rd plane
+static inline void copy_frame(priv_t *priv, unsigned char *dest, unsigned char *source)
+{
+    int i;
+    unsigned char *sptr;
+
+    // YV12 uses VIDEO_PALETTE_YUV420P, but the planes are swapped
+    if (priv->format == IMGFMT_YV12) {
+	memcpy(dest, source, priv->width * priv->height);
+	memcpy(dest+priv->width * priv->height*5/4, source+priv->width * priv->height, priv->width * priv->height/4);
+	memcpy(dest+priv->width * priv->height, source+priv->width * priv->height*5/4, priv->width * priv->height/4);
+	return;
+    }
+
+    switch (priv->picture.palette) {
+    case VIDEO_PALETTE_RGB24:
+    case VIDEO_PALETTE_RGB32:
+    case VIDEO_PALETTE_RGB555:
+    case VIDEO_PALETTE_RGB565:
+	sptr = source + (priv->height-1)*priv->bytesperline;
+	for (i = 0; i < priv->height; i++) {
+	    memcpy(dest, sptr, priv->bytesperline);
+	    dest += priv->bytesperline;
+	    sptr -= priv->bytesperline;
+	}
+	break;
+    case VIDEO_PALETTE_UYVY:
+    case VIDEO_PALETTE_YUV420P:
+    default:
+	memcpy(dest, source, priv->bytesperline * priv->height);
+    }
+    
+}
+
+// maximum skew change, in frames
+#define MAX_SKEW_DELTA 0.6
+static void *video_grabber(void *data)
+{
+#define MAXTOL (priv->nbuf)
+    priv_t *priv = (priv_t*)data;
+    struct timeval curtime;
+    long long skew, prev_skew, xskew, interval, prev_interval;
+    int frame;
+    int i;
+    int framecount;
+    int tolerance;
+    unsigned long num;
+
+    /* start the capture process */
+
+    if ( tv_param_mjpeg )
+      {
+        mp_msg(MSGT_TV, MSGL_INFO, "  MJP: gonna capture ! \n");
+        for (i=0; i < priv->nbuf; i++) {
+	num = i;
+        if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)
+          {
+            mp_msg(MSGT_TV, MSGL_ERR, 
+	           "\n  MJP: ioctl MJPIOC_QBUF_CAPT b failed: %s\n", strerror(errno));
+          }
+	  }
+      }
+    else
+      {
+    for (i=0; i < priv->nbuf; i++) {
+	if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[i]) == -1)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno));
+	}
+      }
+    }
+
+    gettimeofday(&curtime, NULL);
+    priv->starttime = (long long)1e6*curtime.tv_sec + curtime.tv_usec;
+    priv->audio_skew_measure_time = 0;
+    pthread_mutex_unlock(&priv->audio_starter);
+    xskew = 0;
+    skew = 0;
+    interval = 0;
+
+    prev_interval = 0;
+    prev_skew = 0;
+
+    tolerance = MAXTOL;
+
+    for (framecount = 0; !priv->shutdown;)
+    {
+	for (i = 0; i < priv->nbuf && !priv->shutdown; i++, framecount++) {
+
+	    if (priv->immediate_mode) {
+		while (priv->video_cnt == priv->video_buffer_size_max) {
+		    usleep(10000);
+                    if (priv->shutdown) {
+                      return NULL;
+                    }
+		}
+	    }
+		
+	    frame = i;
+
+	    if ( tv_param_mjpeg )
+	    {
+	    while (ioctl(priv->video_fd, MJPIOC_SYNC, &priv->buf[frame].frame) < 0 &&
+		   (errno == EAGAIN || errno == EINTR));
+
+	    }
+	    else
+	    {
+	    while (ioctl(priv->video_fd, VIDIOCSYNC, &priv->buf[frame].frame) < 0 &&
+		   (errno == EAGAIN || errno == EINTR));
+	    }
+	    mp_dbg(MSGT_TV, MSGL_DBG3, "\npicture sync failed\n");
+
+	    gettimeofday(&curtime, NULL);
+	    if (!priv->immediate_mode) {
+		interval = (long long)1e6*curtime.tv_sec + curtime.tv_usec - priv->starttime;
+	    } else {
+		interval = (long long)1e6*framecount/priv->fps;
+	    }
+
+	    if (!priv->immediate_mode) {
+		long long period, orig_interval;
+
+		if (tolerance == 0) {
+		    if (interval - prev_interval == 0) {
+			mp_msg(MSGT_TV, MSGL_V, "\nvideo capture thread: frame delta = 0\n");
+		    } else if ((interval - prev_interval < (long long)0.85e6/priv->fps)
+			       || (interval - prev_interval > (long long)1.15e6/priv->fps) ) {
+			mp_msg(MSGT_TV, MSGL_V, "\nvideo capture thread: frame delta ~ %.1lf fps\n",
+			       (double)1e6/(interval - prev_interval));
+		    }
+		}
+
+		// correct the rate fluctuations on a small scale
+		orig_interval = interval;
+		period = priv->video_interval_sum/VIDEO_AVG_BUFFER_SIZE;
+		if (interval - prev_interval > 105*period/100) {
+		    if (tolerance > 0) {
+			mp_msg(MSGT_TV, MSGL_DBG3, "correcting timestamp\n");
+			interval = prev_interval + priv->video_interval_sum/VIDEO_AVG_BUFFER_SIZE;
+			tolerance--;
+		    } else {
+			mp_msg(MSGT_TV, MSGL_DBG3, "bad - frames were dropped\n");
+			tolerance = MAXTOL;
+		    }
+		} else {
+		    if (tolerance < MAXTOL) {
+			mp_msg(MSGT_TV, MSGL_DBG3, "fluctuation overcome\n");
+		    }
+		    tolerance = MAXTOL;
+		}
+		    
+		priv->video_interval_sum -= priv->video_avg_buffer[priv->video_avg_ptr];
+		priv->video_avg_buffer[priv->video_avg_ptr++] = orig_interval-prev_interval;
+		priv->video_interval_sum += orig_interval-prev_interval;
+		if (priv->video_avg_ptr >= VIDEO_AVG_BUFFER_SIZE) priv->video_avg_ptr = 0;
+
+//		fprintf(stderr, "fps: %lf\n", (double)1e6*VIDEO_AVG_BUFFER_SIZE/priv->video_interval_sum);
+		
+		// interpolate the skew in time
+		pthread_mutex_lock(&priv->skew_mutex);
+		xskew = priv->audio_skew + (interval - priv->audio_skew_measure_time)*priv->audio_skew_factor;
+		pthread_mutex_unlock(&priv->skew_mutex);
+		// correct extreme skew changes to avoid (especially) moving backwards in time
+		if (xskew - prev_skew > (interval - prev_interval)*MAX_SKEW_DELTA) {
+		    skew = prev_skew + (interval - prev_interval)*MAX_SKEW_DELTA;
+		} else if (xskew - prev_skew < -(interval - prev_interval)*MAX_SKEW_DELTA) {
+		    skew = prev_skew - (interval - prev_interval)*MAX_SKEW_DELTA;
+		} else {
+		    skew = xskew;
+		}
+	    }
+
+	    mp_msg(MSGT_TV, MSGL_DBG3, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
+		   (interval != prev_interval) ? (double)1e6/(interval - prev_interval) : -1,
+		   (double)1e-6*interval, (double)1e-6*xskew, (double)1e-6*skew);
+	    mp_msg(MSGT_TV, MSGL_DBG3, "vcnt = %d, acnt = %d\n", priv->video_cnt, priv->audio_cnt);
+
+	    prev_skew = skew;
+	    prev_interval = interval;
+
+	    /* allocate a new buffer, if needed */
+	    pthread_mutex_lock(&priv->video_buffer_mutex);
+	    if (priv->video_buffer_size_current < priv->video_buffer_size_max) {
+		if (priv->video_cnt == priv->video_buffer_size_current) {
+		    unsigned char *newbuf = calloc(priv->bytesperline, priv->height);
+		    if (newbuf) {
+			memmove(priv->video_ringbuffer+priv->video_tail+1, priv->video_ringbuffer+priv->video_tail,
+			       (priv->video_buffer_size_current-priv->video_tail)*sizeof(unsigned char *));
+			memmove(priv->video_timebuffer+priv->video_tail+1, priv->video_timebuffer+priv->video_tail,
+			       (priv->video_buffer_size_current-priv->video_tail)*sizeof(long long));
+			priv->video_ringbuffer[priv->video_tail] = newbuf;
+			if ((priv->video_head >= priv->video_tail) && (priv->video_cnt > 0)) priv->video_head++;
+			priv->video_buffer_size_current++;
+		    }
+		}
+	    }
+	    pthread_mutex_unlock(&priv->video_buffer_mutex);
+
+	    if (priv->video_cnt == priv->video_buffer_size_current) {
+		if (!priv->immediate_mode) {
+		    mp_msg(MSGT_TV, MSGL_ERR, "\nvideo buffer full - dropping frame\n");
+		}
+	    } else {
+		if (priv->immediate_mode) {
+		    priv->video_timebuffer[priv->video_tail] = interval;
+		} else {
+		    // compensate for audio skew
+		    // negative skew => there are more audio samples, increase interval
+		    // positive skew => less samples, shorten the interval
+		    priv->video_timebuffer[priv->video_tail] = interval - skew;
+		}
+		
+                if ( tv_param_mjpeg )
+		copy_frame(priv, priv->video_ringbuffer[priv->video_tail], 
+		           priv->mmap+(priv->mjpeg_bufsize)*i);
+		else
+		copy_frame(priv, priv->video_ringbuffer[priv->video_tail], priv->mmap+priv->mbuf.offsets[frame]);
+		priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current;
+		priv->video_cnt++;
+	    }
+
+            if ( tv_param_mjpeg )
+            {
+	      num = frame;
+              if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)
+                {
+                  mp_msg(MSGT_TV, MSGL_ERR, "\n  MJP: ioctl MJPIOC_QBUF_CAPT end failed: %s\n", 
+		                                    strerror(errno));
+		  continue;
+                }
+	    }
+	    else
+	    {
+	    if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[frame]) == -1)
+	    {
+		mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno));
+		continue;
+	    }
+	    }
+
+	}
+
+    }
+    mp_msg(MSGT_TV, MSGL_INFO, "  MJP: returning! \n");
+    return NULL;
+}
+
+static double grab_video_frame(priv_t *priv, char *buffer, int len)
+{
+    double interval;
+
+    if (priv->first) {
+	pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);
+	priv->first = 0;
+    }
+
+    while (priv->video_cnt == 0) {
+	usleep(10000);
+    }
+
+    pthread_mutex_lock(&priv->video_buffer_mutex);
+    interval = (double)priv->video_timebuffer[priv->video_head]*1e-6;
+    memcpy(buffer, priv->video_ringbuffer[priv->video_head], len);
+    priv->video_cnt--;
+    priv->video_head = (priv->video_head+1)%priv->video_buffer_size_current;
+    pthread_mutex_unlock(&priv->video_buffer_mutex);
+
+    return interval;
+}
+
+static int get_video_framesize(priv_t *priv)
+{
+    return(priv->bytesperline * priv->height);
+}
+
+static void *audio_grabber(void *data)
+{
+    priv_t *priv = (priv_t*)data;
+    struct timeval tv;
+    int i, audio_skew_ptr = 0;
+    long long current_time, prev_skew = 0;
+
+    pthread_mutex_lock(&priv->audio_starter);
+
+    audio_in_start_capture(&priv->audio_in);
+    for (i = 0; i < priv->aud_skew_cnt; i++)
+	priv->audio_skew_buffer[i] = 0;
+
+    for (; !priv->shutdown;)
+    {
+	if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0)
+	    continue;
+
+	gettimeofday(&tv, NULL);
+
+	priv->audio_recv_blocks_total++;
+	current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->starttime;
+
+	priv->audio_skew_total -= priv->audio_skew_buffer[audio_skew_ptr];
+	priv->audio_skew_buffer[audio_skew_ptr] = current_time
+	    - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total;
+	priv->audio_skew_total += priv->audio_skew_buffer[audio_skew_ptr];
+	audio_skew_ptr = (audio_skew_ptr+1) % priv->aud_skew_cnt;
+
+	pthread_mutex_lock(&priv->skew_mutex);
+	// linear interpolation - here we interpolate current skew value
+	// from the moving average, which we expect to be in the middle
+	// of the interval
+	if (priv->audio_recv_blocks_total > priv->aud_skew_cnt) {
+	    priv->audio_skew = priv->audio_skew_total/priv->aud_skew_cnt;
+	    priv->audio_skew += (priv->audio_skew*priv->aud_skew_cnt)/(2*priv->audio_recv_blocks_total-priv->aud_skew_cnt);
+	} else {
+	    // this smoothes the evolution of audio_skew at startup a bit
+	    priv->audio_skew = ((priv->aud_skew_cnt+priv->audio_recv_blocks_total)*priv->audio_skew_total)/(priv->aud_skew_cnt*priv->audio_recv_blocks_total);
+	}
+	// current skew factor (assuming linearity)
+	// used for further interpolation in video_grabber
+	// probably overkill but seems to be necessary for
+	// stress testing by dropping half of the audio frames ;)
+	// especially when using ALSA with large block sizes
+	// where audio_skew remains a long while behind
+	if ((priv->audio_skew_measure_time != 0) && (current_time - priv->audio_skew_measure_time != 0)) {
+	    priv->audio_skew_factor = (double)(priv->audio_skew-prev_skew)/(current_time - priv->audio_skew_measure_time);
+	} else {
+	    priv->audio_skew_factor = 0.0;
+	}
+	
+	priv->audio_skew_measure_time = current_time;
+	prev_skew = priv->audio_skew;
+	pthread_mutex_unlock(&priv->skew_mutex);
+	
+	if ((priv->audio_tail+1) % priv->audio_buffer_size == priv->audio_head) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "\ntoo bad - dropping audio frame !\n");
+	    priv->audio_drop++;
+	} else {
+	    priv->audio_tail = (priv->audio_tail+1) % priv->audio_buffer_size;
+	    priv->audio_cnt++;
+	}
+    }
+    return NULL;
+}
+
+static double grab_audio_frame(priv_t *priv, char *buffer, int len)
+{
+    mp_dbg(MSGT_TV, MSGL_DBG2, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
+	priv, buffer, len);
+
+    if (priv->first) {
+	pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);
+	priv->first = 0;
+    }
+
+    // compensate for dropped audio frames
+    if (priv->audio_drop && (priv->audio_head == priv->audio_tail)) {
+	priv->audio_drop--;
+	priv->audio_sent_blocks_total++;
+	memset(buffer, 0, len);
+	return (double)priv->audio_sent_blocks_total*priv->audio_secs_per_block;
+    }
+
+    while (priv->audio_head == priv->audio_tail) {
+	usleep(10000);
+    }
+    memcpy(buffer, priv->audio_ringbuffer+priv->audio_head*priv->audio_in.blocksize, len);
+    priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
+    priv->audio_cnt--;
+    priv->audio_sent_blocks_total++;
+    return (double)priv->audio_sent_blocks_total*priv->audio_secs_per_block;
+}
+
+static int get_audio_framesize(priv_t *priv)
+{
+    return(priv->audio_in.blocksize);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/tvi_v4l2.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,1746 @@
+/*
+**  Video 4 Linux 2 input
+**
+**  This file is part of MPlayer, see http://mplayerhq.hu/ for info.  
+**
+**  (c) 2003 Martin Olschewski <olschewski@zpr.uni-koeln.de>
+**  (c) 2003 Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
+**  
+**  File licensed under the GPL, see http://www.fsf.org/ for more info.
+**
+**  Some ideas are based on works from
+**    Alex Beregszaszi <alex@fsn.hu>
+**    Gerd Knorr <kraxel@bytesex.org>
+**
+**  CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!
+*/
+
+/*
+
+known issues:
+- norm setting isn't consistent with tvi_v4l
+- the same for volume/bass/treble/balance
+
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SYSINFO_H
+#include <sys/sysinfo.h>
+#endif
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include "mp_msg.h"
+#include "libvo/img_format.h"
+#include "libaf/af_format.h"
+#include "tv.h"
+#include "audio_in.h"
+
+/* information about this file */
+static tvi_info_t info = {
+    "Video 4 Linux 2 input",
+    "v4l2",
+    "Martin Olschewski <olschewski@zpr.uni-koeln.de>",
+    "first try, more to come ;-)"
+};
+
+struct map {
+    struct v4l2_buffer buf;
+    void   *addr;
+    size_t len;
+};
+
+#define BUFFER_COUNT 6
+
+/* private data */
+typedef struct {
+    /* video */
+    char			*video_dev;
+    int				video_fd;
+    int                         mp_format;
+    struct v4l2_capability	capability;
+    struct v4l2_input           input;
+    struct v4l2_format		format;
+    struct v4l2_standard	standard;
+    struct v4l2_tuner		tuner;
+    struct map			*map;
+    int				mapcount;
+    int				frames;
+    volatile long long          first_frame;
+    long long                   curr_frame;
+    /* audio video interleaving ;-) */
+    volatile int		streamon;
+    pthread_t			audio_grabber_thread;
+    pthread_mutex_t		skew_mutex;
+
+    /* 2nd level video buffers */
+    int                         first;
+    int                         immediate_mode;
+
+    int                         video_buffer_size_max;
+    volatile int                video_buffer_size_current;
+    unsigned char		**video_ringbuffer;
+    long long                   *video_timebuffer;
+    volatile int		video_head;
+    volatile int		video_tail;
+    volatile int		video_cnt;
+    pthread_t			video_grabber_thread;
+    pthread_mutex_t             video_buffer_mutex;
+
+    /* audio */
+    char			*audio_dev;
+    audio_in_t                  audio_in;
+
+    long long                   audio_start_time;
+    int                         audio_buffer_size;
+    int                         aud_skew_cnt;
+    unsigned char		*audio_ringbuffer;
+    long long			*audio_skew_buffer;
+    long long			*audio_skew_delta_buffer;
+    volatile int		audio_head;
+    volatile int		audio_tail;
+    volatile int		audio_cnt;
+    volatile long long          audio_skew;
+    volatile double             audio_skew_factor;
+    volatile long long          audio_skew_measure_time;
+    volatile int                audio_drop;
+    volatile int                shutdown;
+
+    int                         audio_inited;
+    double                      audio_secs_per_block;
+    long long                   audio_usecs_per_block;
+    long long                   audio_skew_total;
+    long long                   audio_skew_delta_total;
+    long			audio_recv_blocks_total;
+    long			audio_sent_blocks_total;
+    pthread_mutex_t             audio_mutex;
+    int                         audio_insert_null_samples;
+    volatile long               audio_null_blocks_inserted;
+    volatile long long          dropped_frames_timeshift;
+    long long                   dropped_frames_compensated;
+} priv_t;
+
+#include "tvi_def.h"
+
+static void *audio_grabber(void *data);
+static void *video_grabber(void *data);
+
+/**********************************************************************\
+
+    Only few of the fourccs are the same in v4l2 and mplayer:
+
+    IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410
+    IMGFMT_YV12 == V4L2_PIX_FMT_YVU420
+    IMGFMT_NV12 == V4L2_PIX_FMT_NV12
+    IMGFMT_422P == V4L2_PIX_FMT_YUV422P
+    IMGFMT_411P == V4L2_PIX_FMT_YUV411P
+    IMGFMT_UYVY == V4L2_PIX_FMT_UYVY
+    IMGFMT_Y41P == V4L2_PIX_FMT_Y41P
+
+    This may be an useful translation table for some others:
+
+    IMGFMT_RGB8  == V4L2_PIX_FMT_RGB332
+    IMGFMT_BGR15 == V4L2_PIX_FMT_RGB555
+    IMGFMT_BGR16 == V4L2_PIX_FMT_RGB565
+    IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24
+    IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32
+    IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24
+    IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32
+    IMGFMT_Y800  == V4L2_PIX_FMT_GREY
+    IMGFMT_IF09  == V4L2_PIX_FMT_YUV410
+    IMGFMT_I420  == V4L2_PIX_FMT_YUV420
+    IMGFMT_YUY2  == V4L2_PIX_FMT_YUYV
+
+\**********************************************************************/
+
+/*
+** Translate a mplayer fourcc to a video4linux2 pixel format.
+*/
+static int fcc_mp2vl(int fcc)
+{
+    switch (fcc) {
+    case IMGFMT_RGB8:	return V4L2_PIX_FMT_RGB332;
+    case IMGFMT_BGR15:	return V4L2_PIX_FMT_RGB555;
+    case IMGFMT_BGR16:	return V4L2_PIX_FMT_RGB565;
+    case IMGFMT_RGB24:	return V4L2_PIX_FMT_RGB24;
+    case IMGFMT_RGB32:	return V4L2_PIX_FMT_RGB32;
+    case IMGFMT_BGR24:	return V4L2_PIX_FMT_BGR24;
+    case IMGFMT_BGR32:	return V4L2_PIX_FMT_BGR32;
+    case IMGFMT_Y800:	return V4L2_PIX_FMT_GREY;
+    case IMGFMT_IF09:	return V4L2_PIX_FMT_YUV410;
+    case IMGFMT_I420:	return V4L2_PIX_FMT_YUV420;
+    case IMGFMT_YUY2:	return V4L2_PIX_FMT_YUYV;
+    case IMGFMT_YV12:	return V4L2_PIX_FMT_YVU420;
+    case IMGFMT_UYVY:   return V4L2_PIX_FMT_UYVY;
+    }
+    return fcc;
+}
+
+/*
+** Translate a video4linux2 fourcc aka pixel format to mplayer.
+*/
+static int fcc_vl2mp(int fcc)
+{
+    switch (fcc) {
+    case V4L2_PIX_FMT_RGB332:	return IMGFMT_RGB8;
+    case V4L2_PIX_FMT_RGB555:	return IMGFMT_BGR15;
+    case V4L2_PIX_FMT_RGB565:	return IMGFMT_BGR16;
+    case V4L2_PIX_FMT_RGB24:	return IMGFMT_RGB24;
+    case V4L2_PIX_FMT_RGB32:	return IMGFMT_RGB32;
+    case V4L2_PIX_FMT_BGR24:	return IMGFMT_BGR24;
+    case V4L2_PIX_FMT_BGR32:	return IMGFMT_BGR32;
+    case V4L2_PIX_FMT_GREY:		return IMGFMT_Y800;
+    case V4L2_PIX_FMT_YUV410:	return IMGFMT_IF09;
+    case V4L2_PIX_FMT_YUV420:	return IMGFMT_I420;
+    case V4L2_PIX_FMT_YVU420:	return IMGFMT_YV12;
+    case V4L2_PIX_FMT_YUYV:		return IMGFMT_YUY2;
+    case V4L2_PIX_FMT_UYVY:     return IMGFMT_UYVY;
+    }
+    return fcc;
+}
+
+/*
+** Translate a video4linux2 fourcc aka pixel format
+** to a human readable string.
+*/
+static const char *pixfmt2name(int pixfmt)
+{
+    static char unknown[24];
+
+    switch (pixfmt) {
+    case V4L2_PIX_FMT_RGB332:	return "RGB332";
+    case V4L2_PIX_FMT_RGB555:	return "RGB555";
+    case V4L2_PIX_FMT_RGB565:	return "RGB565";
+    case V4L2_PIX_FMT_RGB555X:	return "RGB555X";
+    case V4L2_PIX_FMT_RGB565X:	return "RGB565X";
+    case V4L2_PIX_FMT_BGR24:	return "BGR24";
+    case V4L2_PIX_FMT_RGB24:	return "RGB24";
+    case V4L2_PIX_FMT_BGR32:	return "BGR32";
+    case V4L2_PIX_FMT_RGB32:	return "RGB32";
+    case V4L2_PIX_FMT_GREY:		return "GREY";
+    case V4L2_PIX_FMT_YVU410:	return "YVU410";
+    case V4L2_PIX_FMT_YVU420:	return "YVU420";
+    case V4L2_PIX_FMT_YUYV:		return "YUYV";
+    case V4L2_PIX_FMT_UYVY:		return "UYVY";
+/*	case V4L2_PIX_FMT_YVU422P:	return "YVU422P"; */
+/*	case V4L2_PIX_FMT_YVU411P:	return "YVU411P"; */
+    case V4L2_PIX_FMT_YUV422P:	return "YUV422P";
+    case V4L2_PIX_FMT_YUV411P:	return "YUV411P";
+    case V4L2_PIX_FMT_Y41P:		return "Y41P";
+    case V4L2_PIX_FMT_NV12:		return "NV12";
+    case V4L2_PIX_FMT_NV21:		return "NV21";
+    case V4L2_PIX_FMT_YUV410:	return "YUV410";
+    case V4L2_PIX_FMT_YUV420:	return "YUV420";
+    case V4L2_PIX_FMT_YYUV:		return "YYUV";
+    case V4L2_PIX_FMT_HI240:	return "HI240";
+    case V4L2_PIX_FMT_WNVA:		return "WNVA";
+    }
+    sprintf(unknown, "unknown (0x%x)", pixfmt);
+    return unknown;
+}
+
+
+/*
+** Gives the depth of a video4linux2 fourcc aka pixel format in bits.
+*/
+static int pixfmt2depth(int pixfmt)
+{
+    switch (pixfmt) {
+    case V4L2_PIX_FMT_RGB332:
+	return 8;
+    case V4L2_PIX_FMT_RGB555:
+    case V4L2_PIX_FMT_RGB565:
+    case V4L2_PIX_FMT_RGB555X:
+    case V4L2_PIX_FMT_RGB565X:
+	return 16;
+    case V4L2_PIX_FMT_BGR24:
+    case V4L2_PIX_FMT_RGB24:
+	return 24;
+    case V4L2_PIX_FMT_BGR32:
+    case V4L2_PIX_FMT_RGB32:
+	return 32;
+    case V4L2_PIX_FMT_GREY:
+	return 8;
+    case V4L2_PIX_FMT_YVU410:
+	return 9;
+    case V4L2_PIX_FMT_YVU420:
+	return 12;
+    case V4L2_PIX_FMT_YUYV:
+    case V4L2_PIX_FMT_UYVY:
+    case V4L2_PIX_FMT_YUV422P:
+    case V4L2_PIX_FMT_YUV411P:
+	return 16;
+    case V4L2_PIX_FMT_Y41P:
+    case V4L2_PIX_FMT_NV12:
+    case V4L2_PIX_FMT_NV21:
+	return 12;
+    case V4L2_PIX_FMT_YUV410:
+	return 9;
+    case V4L2_PIX_FMT_YUV420:
+	return 12;
+    case V4L2_PIX_FMT_YYUV:
+	return 16;
+    case V4L2_PIX_FMT_HI240:
+	return 8;
+
+    }
+    return 0;
+}
+
+static int amode2v4l(int amode) 
+{
+    switch (amode) {
+    case 0:
+	return V4L2_TUNER_MODE_MONO;
+    case 1:
+	return V4L2_TUNER_MODE_STEREO;
+    case 2:
+	return V4L2_TUNER_MODE_LANG1;
+    case 3:
+	return V4L2_TUNER_MODE_LANG2;
+    default:
+	return -1;
+    }
+}
+
+
+// sets and sanitizes audio buffer/block sizes
+static void setup_audio_buffer_sizes(priv_t *priv)
+{
+    int bytes_per_sample = priv->audio_in.bytes_per_sample;
+    double fps = (double)priv->standard.frameperiod.denominator /
+	priv->standard.frameperiod.numerator;
+    int seconds = priv->video_buffer_size_max/fps;
+
+    if (seconds < 5) seconds = 5;
+    if (seconds > 500) seconds = 500;
+
+    // make the audio buffer at least as the video buffer capacity (or 5 seconds) long
+    priv->audio_buffer_size = 1 + seconds*priv->audio_in.samplerate
+	*priv->audio_in.channels
+	*bytes_per_sample/priv->audio_in.blocksize;
+    if (priv->audio_buffer_size < 256) priv->audio_buffer_size = 256;
+
+    // make the skew buffer at least 1 second long
+    priv->aud_skew_cnt = 1 + 1*priv->audio_in.samplerate
+	*priv->audio_in.channels
+	*bytes_per_sample/priv->audio_in.blocksize;
+    if (priv->aud_skew_cnt < 16) priv->aud_skew_cnt = 16;
+
+    mp_msg(MSGT_TV, MSGL_V, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
+	   priv->audio_buffer_size, priv->audio_in.blocksize, priv->aud_skew_cnt);
+}
+
+static void init_audio(priv_t *priv)
+{
+    if (priv->audio_inited) return;
+
+    if (!tv_param_noaudio) {
+#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
+	if (tv_param_alsa)
+	    audio_in_init(&priv->audio_in, AUDIO_IN_ALSA);
+	else
+	    audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
+#else
+	audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
+#endif
+
+	if (priv->audio_dev) {
+	    audio_in_set_device(&priv->audio_in, priv->audio_dev);
+	}
+
+	audio_in_set_samplerate(&priv->audio_in, 44100);
+	if (priv->capability.capabilities & V4L2_CAP_TUNER) {
+	    if (priv->tuner.audmode == V4L2_TUNER_MODE_STEREO) {
+		audio_in_set_channels(&priv->audio_in, 2);
+	    } else {
+		audio_in_set_channels(&priv->audio_in, 1);
+	    }
+	} else {
+	    if (tv_param_forcechan >= 0) {
+		audio_in_set_channels(&priv->audio_in, tv_param_forcechan);
+	    } else {
+		audio_in_set_channels(&priv->audio_in, 2);
+	    }
+	}
+
+	if (audio_in_setup(&priv->audio_in) < 0) return;
+
+	priv->audio_inited = 1;
+    }
+}
+
+#if 0
+/*
+** the number of milliseconds elapsed between time0 and time1
+*/
+static size_t difftv(struct timeval time1, struct timeval time0)
+{
+    return	(time1.tv_sec  - time0.tv_sec)  * 1000 +
+	(time1.tv_usec - time0.tv_usec) / 1000;
+}
+#endif
+
+/*
+** Get current video capture format.
+*/
+static int getfmt(priv_t *priv)
+{
+    int i;
+
+    priv->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    if ((i = ioctl(priv->video_fd, VIDIOC_G_FMT, &priv->format)) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get format failed: %s\n",
+	       info.short_name, strerror(errno));
+    }
+    return i;
+}
+
+
+/*
+** Get current video capture standard.
+*/
+static int getstd(priv_t *priv)
+{
+    v4l2_std_id id;
+    int i=0;
+
+    if (ioctl(priv->video_fd, VIDIOC_G_STD, &id) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get standard failed: %s\n",
+	       info.short_name, strerror(errno));
+	return -1;
+    }
+    do {
+	priv->standard.index = i++;
+	if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) {
+	    return -1;
+	}
+    } while (priv->standard.id != id);
+    return 0;
+}
+
+/***********************************************************************\
+ *									*
+ *									*
+ *	Interface to mplayer						*
+ *									*
+ *									*
+\***********************************************************************/
+
+static int set_mute(priv_t *priv, int value) 
+{
+    struct v4l2_control control;
+    control.id = V4L2_CID_AUDIO_MUTE;
+    control.value = value;
+    if (ioctl(priv->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+	mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set mute failed: %s\n",
+	       info.short_name, strerror(errno));
+	return 0;
+    }
+    return 1;
+}
+
+/*
+** MPlayer uses values from -100 up to 100 for controls.
+** Here they are scaled to what the tv card needs and applied.
+*/
+static int set_control(priv_t *priv, struct v4l2_control *control, int val_signed) {
+    struct v4l2_queryctrl	qctrl;
+
+    qctrl.id = control->id;
+    if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n",
+	 info.short_name, strerror(errno));
+	return TVI_CONTROL_FALSE;
+    }
+
+    if (val_signed) {
+	if (control->value < 0) {
+	    control->value = qctrl.default_value + control->value *
+		(qctrl.default_value - qctrl.minimum) / 100;
+	} else {
+	    control->value = qctrl.default_value + control->value *
+		(qctrl.maximum - qctrl.default_value) / 100;
+	}
+    } else {
+	if (control->value < 50) {
+	    control->value = qctrl.default_value + (control->value-50) *
+		(qctrl.default_value - qctrl.minimum) / 50;
+	} else {
+	    control->value = qctrl.default_value + (control->value-50) *
+		(qctrl.maximum - qctrl.default_value) / 50;
+	}
+    }
+    
+
+    if (ioctl(priv->video_fd, VIDIOC_S_CTRL, control) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl set %s %d failed: %s\n",
+	 info.short_name, qctrl.name, control->value, strerror(errno));
+	return TVI_CONTROL_FALSE;
+    }
+    mp_msg(MSGT_TV, MSGL_V, "%s: set %s: %d [%d, %d]\n", info.short_name,
+     qctrl.name, control->value, qctrl.minimum, qctrl.maximum);
+
+    return TVI_CONTROL_TRUE;
+}
+
+
+/*
+** Scale the control values back to what mplayer needs.
+*/
+static int get_control(priv_t *priv, struct v4l2_control *control, int val_signed) {
+    struct v4l2_queryctrl	qctrl;
+
+    qctrl.id = control->id;
+    if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n",
+	 info.short_name, strerror(errno));
+	return TVI_CONTROL_FALSE;
+    }
+
+    if (ioctl(priv->video_fd, VIDIOC_G_CTRL, control) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl get %s failed: %s\n",
+	 info.short_name, qctrl.name, strerror(errno));
+	return TVI_CONTROL_FALSE;
+    }
+    mp_msg(MSGT_TV, MSGL_V, "%s: get %s: %d [%d, %d]\n", info.short_name,
+     qctrl.name, control->value, qctrl.minimum, qctrl.maximum);
+
+    if (val_signed) {
+	if (control->value < qctrl.default_value) {
+	    control->value = (control->value - qctrl.default_value) * 100 /
+		(qctrl.default_value - qctrl.minimum);
+	} else {
+	    control->value = (control->value - qctrl.default_value) * 100 /
+		(qctrl.maximum - qctrl.default_value);
+	}
+    } else {
+	if (control->value < qctrl.default_value) {
+	    control->value = (control->value - qctrl.default_value) * 50 /
+		(qctrl.default_value - qctrl.minimum) + 50;
+	} else {
+	    control->value = (control->value - qctrl.default_value) * 50 /
+		(qctrl.maximum - qctrl.default_value) + 50;
+	}
+    }
+
+    return TVI_CONTROL_TRUE;
+}
+
+static int control(priv_t *priv, int cmd, void *arg)
+{
+    struct v4l2_control control;
+    struct v4l2_frequency frequency;
+
+    switch(cmd) {
+    case TVI_CONTROL_IS_VIDEO:
+	return priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE?
+	    TVI_CONTROL_TRUE: TVI_CONTROL_FALSE;
+    case TVI_CONTROL_IS_AUDIO:
+	if (tv_param_force_audio) return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_IS_TUNER:
+	return priv->capability.capabilities & V4L2_CAP_TUNER?
+	    TVI_CONTROL_TRUE: TVI_CONTROL_FALSE;
+    case TVI_CONTROL_IMMEDIATE:
+	priv->immediate_mode = 1;
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_GET_FPS:
+	*(float *)arg = (float)priv->standard.frameperiod.denominator /
+	    priv->standard.frameperiod.numerator;
+	mp_msg(MSGT_TV, MSGL_V, "%s: get fps: %f\n", info.short_name,
+	       *(float *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_GET_BITS:
+	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
+	*(int *)arg = pixfmt2depth(priv->format.fmt.pix.pixelformat);
+	mp_msg(MSGT_TV, MSGL_V, "%s: get depth: %d\n", info.short_name,
+	       *(int *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_GET_FORMAT:
+	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
+	*(int *)arg = fcc_vl2mp(priv->format.fmt.pix.pixelformat);
+	mp_msg(MSGT_TV, MSGL_V, "%s: get format: %s\n", info.short_name,
+	       pixfmt2name(priv->format.fmt.pix.pixelformat));
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_SET_FORMAT:
+	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
+	priv->format.fmt.pix.pixelformat = fcc_mp2vl(*(int *)arg);
+	priv->format.fmt.pix.field = V4L2_FIELD_ANY;
+	    
+	priv->mp_format = *(int *)arg;
+	mp_msg(MSGT_TV, MSGL_V, "%s: set format: %s\n", info.short_name,
+	       pixfmt2name(priv->format.fmt.pix.pixelformat));
+	if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set format failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	/* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers
+	  might even always return the default parameters -> update the format here*/
+	priv->mp_format = fcc_vl2mp(priv->format.fmt.pix.pixelformat);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_GET_WIDTH:
+	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
+	*(int *)arg = priv->format.fmt.pix.width;
+	mp_msg(MSGT_TV, MSGL_V, "%s: get width: %d\n", info.short_name,
+	       *(int *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_CHK_WIDTH:
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_SET_WIDTH:
+	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
+	priv->format.fmt.pix.width = *(int *)arg;
+	mp_msg(MSGT_TV, MSGL_V, "%s: set width: %d\n", info.short_name,
+	       *(int *)arg);
+	if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set width failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_GET_HEIGHT:
+	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
+	*(int *)arg = priv->format.fmt.pix.height;
+	mp_msg(MSGT_TV, MSGL_V, "%s: get height: %d\n", info.short_name,
+	       *(int *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_CHK_HEIGHT:
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_VID_SET_HEIGHT:
+	if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
+	priv->format.fmt.pix.height = *(int *)arg;
+	priv->format.fmt.pix.field = V4L2_FIELD_ANY;
+	mp_msg(MSGT_TV, MSGL_V, "%s: set height: %d\n", info.short_name,
+	       *(int *)arg);
+	if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set height failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	return TVI_CONTROL_TRUE;
+	case TVI_CONTROL_VID_GET_BRIGHTNESS:
+	    control.id = V4L2_CID_BRIGHTNESS;
+	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
+		*(int *)arg = control.value;
+		return TVI_CONTROL_TRUE;
+	    }
+	    return TVI_CONTROL_FALSE;
+	case TVI_CONTROL_VID_SET_BRIGHTNESS:
+	    control.id = V4L2_CID_BRIGHTNESS;
+	    control.value = *(int *)arg;
+	    return set_control(priv, &control, 1);
+	case TVI_CONTROL_VID_GET_HUE:
+	    control.id = V4L2_CID_HUE;
+	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
+		*(int *)arg = control.value;
+		return TVI_CONTROL_TRUE;
+	    }
+	    return TVI_CONTROL_FALSE;
+	case TVI_CONTROL_VID_SET_HUE:
+	    control.id = V4L2_CID_HUE;
+	    control.value = *(int *)arg;
+	    return set_control(priv, &control, 1);
+	case TVI_CONTROL_VID_GET_SATURATION:
+	    control.id = V4L2_CID_SATURATION;
+	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
+		*(int *)arg = control.value;
+		return TVI_CONTROL_TRUE;
+	    }
+	    return TVI_CONTROL_FALSE;
+	case TVI_CONTROL_VID_SET_SATURATION:
+	    control.id = V4L2_CID_SATURATION;
+	    control.value = *(int *)arg;
+	    return set_control(priv, &control, 1);
+	case TVI_CONTROL_VID_GET_CONTRAST:
+	    control.id = V4L2_CID_CONTRAST;
+	    if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
+		*(int *)arg = control.value;
+		return TVI_CONTROL_TRUE;
+	    }
+	    return TVI_CONTROL_FALSE;
+	case TVI_CONTROL_VID_SET_CONTRAST:
+	    control.id = V4L2_CID_CONTRAST;
+	    control.value = *(int *)arg;
+	    return set_control(priv, &control, 1);
+    case TVI_CONTROL_TUN_GET_FREQ:
+	frequency.tuner = 0;
+	frequency.type  = V4L2_TUNER_ANALOG_TV;
+	if (ioctl(priv->video_fd, VIDIOC_G_FREQUENCY, &frequency) < 0) {
+	    mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl get frequency failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	*(int *)arg = frequency.frequency;
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_TUN_SET_FREQ:
+#if 0
+	set_mute(priv, 1);
+	usleep(100000); // wait to suppress noise during switching
+#endif
+	frequency.tuner = 0;
+	frequency.type  = V4L2_TUNER_ANALOG_TV;
+	frequency.frequency = *(int *)arg;
+	if (ioctl(priv->video_fd, VIDIOC_S_FREQUENCY, &frequency) < 0) {
+	    mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set frequency failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+#if 0
+	usleep(100000); // wait to suppress noise during switching
+	set_mute(priv, 0);
+#endif
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_TUN_GET_TUNER:
+	mp_msg(MSGT_TV, MSGL_V, "%s: get tuner\n",info.short_name);
+	if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_TUN_SET_TUNER:
+	mp_msg(MSGT_TV, MSGL_V, "%s: set tuner\n",info.short_name);
+	if (ioctl(priv->video_fd, VIDIOC_S_TUNER, &priv->tuner) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set tuner failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_TUN_GET_NORM:
+	*(int *)arg = priv->standard.index;
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_TUN_SET_NORM:
+	priv->standard.index = *(int *)arg;
+	if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum norm failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	mp_msg(MSGT_TV, MSGL_V, "%s: set norm: %s\n", info.short_name, priv->standard.name);
+	if (ioctl(priv->video_fd, VIDIOC_S_STD, &priv->standard.id) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set norm failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_SPC_GET_NORMID:
+	{
+	    int i;
+	    for (i = 0;; i++) {
+		struct v4l2_standard standard;
+		memset(&standard, 0, sizeof(standard));
+		standard.index = i;
+		if (-1 == ioctl(priv->video_fd, VIDIOC_ENUMSTD, &standard))
+		    return TVI_CONTROL_FALSE;
+		if (!strcasecmp(standard.name, (char *)arg)) {
+		    *(int *)arg = i;
+		    return TVI_CONTROL_TRUE;
+		}
+	    }
+	    return TVI_CONTROL_FALSE;
+	}
+    case TVI_CONTROL_SPC_GET_INPUT:
+	if (ioctl(priv->video_fd, VIDIOC_G_INPUT, (int *)arg) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get input failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_SPC_SET_INPUT:
+	mp_msg(MSGT_TV, MSGL_V, "%s: set input: %d\n", info.short_name, *(int *)arg);
+	priv->input.index = *(int *)arg;
+	if (ioctl(priv->video_fd, VIDIOC_ENUMINPUT, &priv->input) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum input failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	if (ioctl(priv->video_fd, VIDIOC_S_INPUT, (int *)arg) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set input failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return TVI_CONTROL_FALSE;
+	}
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_AUD_GET_FORMAT:
+	init_audio(priv);
+	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
+	*(int *)arg = AF_FORMAT_S16_LE;
+	mp_msg(MSGT_TV, MSGL_V, "%s: get audio format: %d\n",
+	       info.short_name, *(int *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_AUD_GET_SAMPLERATE:
+	init_audio(priv);
+	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
+	*(int *)arg = priv->audio_in.samplerate;
+	mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplerate: %d\n",
+	       info.short_name, *(int *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_AUD_GET_SAMPLESIZE:
+	init_audio(priv);
+	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
+	*(int *)arg = priv->audio_in.bytes_per_sample;
+	mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplesize: %d\n",
+	       info.short_name, *(int *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_AUD_GET_CHANNELS:
+	init_audio(priv);
+	if (!priv->audio_inited) return TVI_CONTROL_FALSE;
+	*(int *)arg = priv->audio_in.channels;
+	mp_msg(MSGT_TV, MSGL_V, "%s: get audio channels: %d\n",
+	       info.short_name, *(int *)arg);
+	return TVI_CONTROL_TRUE;
+    case TVI_CONTROL_AUD_SET_SAMPLERATE:
+	init_audio(priv);
+	mp_msg(MSGT_TV, MSGL_V, "%s: set audio samplerate: %d\n",
+	       info.short_name, *(int *)arg);
+	if (audio_in_set_samplerate(&priv->audio_in, *(int*)arg) < 0) return TVI_CONTROL_FALSE;
+//	setup_audio_buffer_sizes(priv);
+	return TVI_CONTROL_TRUE;
+    }
+    mp_msg(MSGT_TV, MSGL_V, "%s: unknown control: %d\n", info.short_name, cmd);
+    return(TVI_CONTROL_UNKNOWN);
+}
+
+
+#define PRIV ((priv_t *) (tvi_handle->priv))
+
+/* handler creator - entry point ! */
+tvi_handle_t *tvi_init_v4l2(char *video_dev, char *audio_dev)
+{
+    tvi_handle_t *tvi_handle;
+
+    /* new_handle initializes priv with memset 0 */
+    tvi_handle = new_handle();
+    if (!tvi_handle) {
+	return NULL;
+    }
+    PRIV->video_fd = -1;
+
+    PRIV->video_dev = strdup(video_dev? video_dev: "/dev/video0");
+    if (!PRIV->video_dev) {
+	free_handle(tvi_handle);
+	return NULL;
+    }
+
+    if (audio_dev) {
+	PRIV->audio_dev = strdup(audio_dev);
+	if (!PRIV->audio_dev) {
+	    free(PRIV->video_dev);
+	    free_handle(tvi_handle);
+	    return NULL;
+	}
+    }
+
+    return tvi_handle;
+}
+
+#undef PRIV
+
+
+static int uninit(priv_t *priv)
+{
+    int i, frames, dropped = 0;
+
+    priv->shutdown = 1;
+    if(priv->video_grabber_thread)
+	pthread_join(priv->video_grabber_thread, NULL);
+    pthread_mutex_destroy(&priv->video_buffer_mutex);
+
+    if (priv->streamon) {
+	struct v4l2_buffer buf;
+
+	/* get performance */
+	frames = 1 + (priv->curr_frame - priv->first_frame +
+		      priv->standard.frameperiod.numerator * 500000 /
+		      priv->standard.frameperiod.denominator) *
+	    priv->standard.frameperiod.denominator /
+	    priv->standard.frameperiod.numerator / 1000000;
+	dropped = frames - priv->frames;
+
+	/* turn off streaming */
+	if (ioctl(priv->video_fd, VIDIOC_STREAMOFF, &(priv->map[0].buf.type)) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl streamoff failed: %s\n",
+		   info.short_name, strerror(errno));
+	}
+	priv->streamon = 0;
+
+	/* unqueue all remaining buffers */
+	memset(&buf,0,sizeof(buf));
+	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	while (!ioctl(priv->video_fd, VIDIOC_DQBUF, &buf));
+    }
+
+    /* unmap all buffers */
+    for (i = 0; i < priv->mapcount; i++) {
+	if (munmap(priv->map[i].addr, priv->map[i].len) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: munmap capture buffer failed: %s\n",
+		   info.short_name, strerror(errno));
+	}
+    }
+
+    /* stop audio thread */
+    if (!tv_param_noaudio && priv->audio_grabber_thread) {
+	pthread_join(priv->audio_grabber_thread, NULL);
+	pthread_mutex_destroy(&priv->skew_mutex);
+	pthread_mutex_destroy(&priv->audio_mutex);
+    }
+
+    set_mute(priv, 1);
+
+    /* free memory and close device */
+    free(priv->map);		priv->map = NULL;
+    priv->mapcount = 0;
+    if(priv->video_fd!=-1)close(priv->video_fd);	priv->video_fd  = -1;
+    free(priv->video_dev);	priv->video_dev = NULL;
+
+    if (priv->video_ringbuffer) {
+	int i;
+	for (i = 0; i < priv->video_buffer_size_current; i++) {
+	    free(priv->video_ringbuffer[i]);
+	}
+	free(priv->video_ringbuffer);
+    }
+    if (priv->video_timebuffer)
+	free(priv->video_timebuffer);
+    if (!tv_param_noaudio) {
+	if (priv->audio_ringbuffer)
+	    free(priv->audio_ringbuffer);
+	if (priv->audio_skew_buffer)
+	    free(priv->audio_skew_buffer);
+	if (priv->audio_skew_delta_buffer)
+	    free(priv->audio_skew_delta_buffer);
+    }
+
+    /* show some nice statistics ;-) */
+    mp_msg(MSGT_TV, MSGL_INFO,
+	   "%s: %d frames successfully processed, %d frames dropped.\n",
+	   info.short_name, priv->frames, dropped);
+    mp_msg(MSGT_TV, MSGL_V, "%s: up to %u video frames buffered.\n",
+	   info.short_name, priv->video_buffer_size_current);
+    return 1;
+}
+
+
+/* initialisation */
+static int init(priv_t *priv)
+{
+    int i;
+
+    priv->audio_ringbuffer = NULL;
+    priv->audio_skew_buffer = NULL;
+    priv->audio_skew_delta_buffer = NULL;
+
+    priv->audio_inited = 0;
+
+    /* Open the video device. */
+    priv->video_fd = open(priv->video_dev, O_RDWR);
+    if (priv->video_fd < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: unable to open '%s': %s\n",
+	       info.short_name, priv->video_dev, strerror(errno));
+	uninit(priv);
+	return 0;
+    }
+    mp_msg(MSGT_TV, MSGL_DBG2, "%s: video fd: %s: %d\n",
+	   info.short_name, priv->video_dev, priv->video_fd);
+
+    /*
+    ** Query the video capabilities and current settings
+    ** for further control calls.
+    */
+    if (ioctl(priv->video_fd, VIDIOC_QUERYCAP, &priv->capability) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query capabilities failed: %s\n",
+	       info.short_name, strerror(errno));
+	uninit(priv);
+	return 0;
+    }
+
+    if (!(priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "Device %s is not a video capture device.\n",
+	       priv->video_dev);
+	return 0;
+    }
+
+    if (getfmt(priv) < 0) {
+	uninit(priv);
+	return 0;
+    }
+    getstd(priv);
+    /*
+    ** if this device has got a tuner query it's settings
+    ** otherwise set some nice defaults
+    */
+    if (priv->capability.capabilities & V4L2_CAP_TUNER) {
+	if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n",
+		   info.short_name, strerror(errno));
+	    uninit(priv);
+	    return 0;
+	}
+    }
+    mp_msg(MSGT_TV, MSGL_INFO, "Selected device: %s\n", priv->capability.card);
+    if (priv->capability.capabilities & V4L2_CAP_TUNER) {
+	mp_msg(MSGT_TV, MSGL_INFO, " Tuner cap:%s%s%s\n",
+		(priv->tuner.capability & V4L2_TUNER_CAP_STEREO) ? " STEREO" : "",
+		(priv->tuner.capability & V4L2_TUNER_CAP_LANG1)  ? " LANG1"  : "",
+		(priv->tuner.capability & V4L2_TUNER_CAP_LANG2)  ? " LANG2"  : "");
+	mp_msg(MSGT_TV, MSGL_INFO, " Tuner rxs:%s%s%s%s\n",
+		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_MONO)   ? " MONO"   : "",
+		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_STEREO) ? " STEREO" : "",
+		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_LANG1)  ? " LANG1"  : "",
+		(priv->tuner.rxsubchans & V4L2_TUNER_SUB_LANG2)  ? " LANG2"  : "");
+    }
+    mp_msg(MSGT_TV, MSGL_INFO, " Capabilites:%s%s%s%s%s%s%s%s%s%s%s\n",
+	   priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE?
+	   "  video capture": "",
+	   priv->capability.capabilities & V4L2_CAP_VIDEO_OUTPUT?
+	   "  video output": "",
+	   priv->capability.capabilities & V4L2_CAP_VIDEO_OVERLAY?
+	   "  video overlay": "",
+	   priv->capability.capabilities & V4L2_CAP_VBI_CAPTURE?
+	   "  VBI capture device": "",
+	   priv->capability.capabilities & V4L2_CAP_VBI_OUTPUT?
+	   "  VBI output": "",
+	   priv->capability.capabilities & V4L2_CAP_RDS_CAPTURE?
+	   "  RDS data capture": "",
+	   priv->capability.capabilities & V4L2_CAP_TUNER?
+	   "  tuner": "",
+	   priv->capability.capabilities & V4L2_CAP_AUDIO?
+	   "  audio": "",
+	   priv->capability.capabilities & V4L2_CAP_READWRITE?
+	   "  read/write": "",
+	   priv->capability.capabilities & V4L2_CAP_ASYNCIO?
+	   "  async i/o": "",
+	   priv->capability.capabilities & V4L2_CAP_STREAMING?
+	   "  streaming": "");
+    mp_msg(MSGT_TV, MSGL_INFO, " supported norms:");
+    for (i = 0;; i++) {
+	struct v4l2_standard standard;
+	memset(&standard, 0, sizeof(standard));
+	standard.index = i;
+	if (-1 == ioctl(priv->video_fd, VIDIOC_ENUMSTD, &standard))
+	    break;
+	mp_msg(MSGT_TV, MSGL_INFO, " %d = %s;", i, standard.name);
+    }
+    mp_msg(MSGT_TV, MSGL_INFO, "\n inputs:");
+    for (i = 0; 1; i++) {
+	struct v4l2_input input;
+
+	input.index = i;
+	if (ioctl(priv->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
+	    break;
+	}
+	mp_msg(MSGT_TV, MSGL_INFO, " %d = %s;", i, input.name);
+    }
+    if (ioctl(priv->video_fd, VIDIOC_G_INPUT, &i) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get input failed: %s\n",
+	       info.short_name, strerror(errno));
+    }
+    mp_msg(MSGT_TV, MSGL_INFO, "\n Current input: %d\n", i);
+    for (i = 0; ; i++) {
+	struct v4l2_fmtdesc fmtdesc;
+
+	fmtdesc.index = i;
+	fmtdesc.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	if (ioctl(priv->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0) {
+	    break;
+	}
+	mp_msg(MSGT_TV, MSGL_V, " Format %-6s (%2d bits, %s): %s\n",
+	       pixfmt2name(fmtdesc.pixelformat), pixfmt2depth(fmtdesc.pixelformat),
+	       fmtdesc.description, vo_format_name(fcc_vl2mp(fmtdesc.pixelformat)));
+    }
+    mp_msg(MSGT_TV, MSGL_INFO, " Current format: %s\n",
+	   pixfmt2name(priv->format.fmt.pix.pixelformat));
+
+    /* set some nice defaults */
+    if (getfmt(priv) < 0) return 0;
+    priv->format.fmt.pix.width  = 640;
+    priv->format.fmt.pix.height = 480;
+    if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set format failed: %s\n",
+	       info.short_name, strerror(errno));
+	uninit(priv);
+	return 0;
+    }
+
+//    if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !tv_param_force_audio) tv_param_noaudio = 1;
+
+    if (priv->capability.capabilities & V4L2_CAP_TUNER) {
+	struct v4l2_control control;
+	if (tv_param_amode >= 0) {
+	    mp_msg(MSGT_TV, MSGL_V, "%s: setting audio mode\n", info.short_name);
+	    priv->tuner.audmode = amode2v4l(tv_param_amode);
+	    if (ioctl(priv->video_fd, VIDIOC_S_TUNER, &priv->tuner) < 0) {
+		mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set tuner failed: %s\n",
+		       info.short_name, strerror(errno));
+		return TVI_CONTROL_FALSE;
+	    }
+	}
+	mp_msg(MSGT_TV, MSGL_INFO, "%s: current audio mode is :%s%s%s%s\n", info.short_name,
+		(priv->tuner.audmode == V4L2_TUNER_MODE_MONO)   ? " MONO"   : "",
+		(priv->tuner.audmode == V4L2_TUNER_MODE_STEREO) ? " STEREO" : "",
+		(priv->tuner.audmode == V4L2_TUNER_MODE_LANG1)  ? " LANG1"  : "",
+		(priv->tuner.audmode == V4L2_TUNER_MODE_LANG2)  ? " LANG2"  : "");
+
+	if (tv_param_volume >= 0) {
+	    control.id = V4L2_CID_AUDIO_VOLUME;
+	    control.value = tv_param_volume;
+	    set_control(priv, &control, 0);
+	}
+	if (tv_param_bass >= 0) {
+	    control.id = V4L2_CID_AUDIO_BASS;
+	    control.value = tv_param_bass;
+	    set_control(priv, &control, 0);
+	}
+	if (tv_param_treble >= 0) {
+	    control.id = V4L2_CID_AUDIO_TREBLE;
+	    control.value = tv_param_treble;
+	    set_control(priv, &control, 0);
+	}
+	if (tv_param_balance >= 0) {
+	    control.id = V4L2_CID_AUDIO_BALANCE;
+	    control.value = tv_param_balance;
+	    set_control(priv, &control, 0);
+	}
+    }
+
+    return 1;
+}
+
+static int get_capture_buffer_size(priv_t *priv)
+{
+    int bufsize, cnt;
+    int w = priv->format.fmt.pix.width;
+    int h = priv->format.fmt.pix.height;
+    int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
+    int bytesperline = w*d/8;
+
+    if (tv_param_buffer_size >= 0) {
+	bufsize = tv_param_buffer_size*1024*1024;
+    } else {
+#ifdef HAVE_SYS_SYSINFO_H
+	struct sysinfo si;
+	
+	sysinfo(&si);
+	if (si.totalram<2*1024*1024) {
+	    bufsize = 1024*1024;
+	} else {
+	    bufsize = si.totalram/2;
+	}
+#else
+	bufsize = 16*1024*1024;
+#endif
+    }
+    
+    cnt = bufsize/(h*bytesperline);
+    if (cnt < 2) cnt = 2;
+    
+    return cnt;
+}
+
+/* that's the real start, we'got the format parameters (checked with control) */
+static int start(priv_t *priv)
+{
+    struct v4l2_requestbuffers request;
+    int i;
+
+    /* setup audio parameters */
+
+    init_audio(priv);
+    if (!tv_param_noaudio && !priv->audio_inited) return 0;
+
+    /* we need this to size the audio buffer properly */
+    if (priv->immediate_mode) {
+	priv->video_buffer_size_max = 2;
+    } else {
+	priv->video_buffer_size_max = get_capture_buffer_size(priv);
+    }
+    
+    if (!tv_param_noaudio) {
+	setup_audio_buffer_sizes(priv);
+	priv->audio_skew_buffer = calloc(priv->aud_skew_cnt, sizeof(long long));
+	if (!priv->audio_skew_buffer) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
+	    return 0;
+	}
+	priv->audio_skew_delta_buffer = calloc(priv->aud_skew_cnt, sizeof(long long));
+	if (!priv->audio_skew_delta_buffer) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
+	    return 0;
+	}
+
+	priv->audio_ringbuffer = calloc(priv->audio_in.blocksize, priv->audio_buffer_size);
+	if (!priv->audio_ringbuffer) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate audio buffer: %s\n", strerror(errno));
+	    return 0;
+	}
+
+	priv->audio_secs_per_block = (double)priv->audio_in.blocksize/(priv->audio_in.samplerate
+								    *priv->audio_in.channels
+								    *priv->audio_in.bytes_per_sample);
+	priv->audio_usecs_per_block = 1e6*priv->audio_secs_per_block;
+	priv->audio_head = 0;
+	priv->audio_tail = 0;
+	priv->audio_cnt = 0;
+	priv->audio_drop = 0;
+	priv->audio_skew = 0;
+	priv->audio_skew_total = 0;
+	priv->audio_skew_delta_total = 0;
+	priv->audio_recv_blocks_total = 0;
+	priv->audio_sent_blocks_total = 0;
+	priv->audio_null_blocks_inserted = 0;
+	priv->audio_insert_null_samples = 0;
+	priv->dropped_frames_timeshift = 0;
+	priv->dropped_frames_compensated = 0;
+
+	pthread_mutex_init(&priv->skew_mutex, NULL);
+	pthread_mutex_init(&priv->audio_mutex, NULL);
+    }
+
+    /* setup video parameters */
+    if (!tv_param_noaudio) {
+	if (priv->video_buffer_size_max < (3*priv->standard.frameperiod.denominator) /
+					       priv->standard.frameperiod.numerator
+	    *priv->audio_secs_per_block) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "Video buffer shorter than 3 times audio frame duration.\n"
+		   "You will probably experience heavy framedrops.\n");
+	}
+    }
+    
+    {
+	int bytesperline = priv->format.fmt.pix.width*pixfmt2depth(priv->format.fmt.pix.pixelformat)/8;
+	
+	mp_msg(MSGT_TV, MSGL_V, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
+	       priv->video_buffer_size_max,
+	       priv->video_buffer_size_max*priv->format.fmt.pix.height*bytesperline/(1024*1024));
+    }
+
+    priv->video_ringbuffer = calloc(priv->video_buffer_size_max, sizeof(unsigned char*));
+    if (!priv->video_ringbuffer) {
+	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate video buffer: %s\n", strerror(errno));
+	return 0;
+    }
+    for (i = 0; i < priv->video_buffer_size_max; i++)
+	priv->video_ringbuffer[i] = NULL;
+    priv->video_timebuffer = calloc(priv->video_buffer_size_max, sizeof(long long));
+    if (!priv->video_timebuffer) {
+	mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate time buffer: %s\n", strerror(errno));
+	return 0;
+    }
+
+    pthread_mutex_init(&priv->video_buffer_mutex, NULL);
+
+    priv->video_head = 0;
+    priv->video_tail = 0;
+    priv->video_cnt = 0;
+    
+    /* request buffers */
+    if (priv->immediate_mode) {
+	request.count = 2;
+    } else {
+	request.count = BUFFER_COUNT;
+    }
+    
+    request.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    request.memory = V4L2_MEMORY_MMAP;
+    if (ioctl(priv->video_fd, VIDIOC_REQBUFS, &request) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl request buffers failed: %s\n",
+	       info.short_name, strerror(errno));
+	return 0;
+    }
+
+    /* query buffers */
+    if (!(priv->map = calloc(request.count, sizeof(struct map)))) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: malloc capture buffers failed: %s\n",
+	       info.short_name, strerror(errno));
+	return 0;
+    }
+
+    /* map and queue buffers */
+    for (i = 0; i < request.count; i++) {
+	memset(&priv->map[i].buf,0,sizeof(priv->map[i].buf));
+	priv->map[i].buf.index = i;
+	priv->map[i].buf.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	priv->map[i].buf.memory  = V4L2_MEMORY_MMAP;
+	if (ioctl(priv->video_fd, VIDIOC_QUERYBUF, &(priv->map[i].buf)) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query buffer failed: %s\n",
+		   info.short_name, strerror(errno));
+	    free(priv->map);
+	    priv->map = NULL;
+	    return 0;
+	}
+	priv->map[i].addr = mmap (0, priv->map[i].buf.length, PROT_READ |
+				  PROT_WRITE, MAP_SHARED, priv->video_fd, priv->map[i].buf.m.offset);
+	if (priv->map[i].addr == MAP_FAILED) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: mmap capture buffer failed: %s\n",
+		   info.short_name, strerror(errno));
+	    priv->map[i].len = 0;
+	    return 0;
+	}
+	priv->map[i].len = priv->map[i].buf.length;
+	/* count up to make sure this is correct everytime */
+	priv->mapcount++;
+
+	if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return 0;
+	}
+    }
+
+    /* start audio thread */
+    priv->shutdown = 0;
+    priv->audio_skew_measure_time = 0;
+    priv->first_frame = 0;
+    priv->audio_skew = 0;
+    priv->first = 1;
+
+    set_mute(priv, 0);
+    
+    return 1;
+}
+
+
+#ifdef HAVE_TV_BSDBT848
+static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
+{
+    memset(buffer, 0xCC, len);
+    return(1);
+}
+#endif /* HAVE_TV_BSDBT848 */
+
+// copies a video frame
+static inline void copy_frame(priv_t *priv, unsigned char *dest, unsigned char *source)
+{
+    int w = priv->format.fmt.pix.width;
+    int h = priv->format.fmt.pix.height;
+    int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
+    int bytesperline = w*d/8;
+
+    memcpy(dest, source, bytesperline * h);
+}
+
+// maximum skew change, in frames
+#define MAX_SKEW_DELTA 0.6
+static void *video_grabber(void *data)
+{
+    priv_t *priv = (priv_t*)data;
+    long long skew, prev_skew, xskew, interval, prev_interval, delta;
+    int i;
+    int framesize = priv->format.fmt.pix.height*priv->format.fmt.pix.width*
+	pixfmt2depth(priv->format.fmt.pix.pixelformat)/8;
+    fd_set rdset;
+    struct timeval timeout;
+    struct v4l2_buffer buf;
+
+    xskew = 0;
+    skew = 0;
+    interval = 0;
+    prev_interval = 0;
+    prev_skew = 0;
+
+    mp_msg(MSGT_TV, MSGL_V, "%s: going to capture\n", info.short_name);
+    if (ioctl(priv->video_fd, VIDIOC_STREAMON, &(priv->format.type)) < 0) {
+	mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl streamon failed: %s\n",
+	       info.short_name, strerror(errno));
+	return 0;
+    }
+    priv->streamon = 1;
+
+    if (!tv_param_noaudio) {
+	pthread_create(&priv->audio_grabber_thread, NULL, audio_grabber, priv);
+    }
+
+    for (priv->frames = 0; !priv->shutdown;)
+    {
+	int ret;
+	
+	if (priv->immediate_mode) {
+	    while (priv->video_cnt == priv->video_buffer_size_max) {
+		usleep(10000);
+		if (priv->shutdown) {
+		    return NULL;
+		}
+	    }
+	}
+		
+	FD_ZERO (&rdset);
+	FD_SET (priv->video_fd, &rdset);
+
+	timeout.tv_sec = 1;
+	timeout.tv_usec = 0;
+
+	i = select(priv->video_fd + 1, &rdset, NULL, NULL, &timeout);
+	if (i < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: select failed: %s\n",
+		   info.short_name, strerror(errno));
+	    continue;
+	}
+	else if (i == 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: select timeout\n", info.short_name);
+	    continue;
+	}
+	else if (!FD_ISSET(priv->video_fd, &rdset)) {
+	    continue;
+	}
+
+	memset(&buf,0,sizeof(buf));
+	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	ret = ioctl(priv->video_fd, VIDIOC_DQBUF, &buf);
+
+	if (ret < 0) {
+	    /*
+	      if there's no signal, the buffer might me dequeued
+	      so we query all the buffers to see which one we should
+	      put back to queue
+
+	      observed with saa7134 0.2.8
+	      don't know if is it a bug or (mis)feature
+	     */
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
+		   info.short_name, strerror(errno), buf.index);
+	    for (i = 0; i < priv->mapcount; i++) {
+		memset(&buf,0,sizeof(buf));
+		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		buf.index = i;
+		ret = ioctl(priv->video_fd, VIDIOC_QUERYBUF, &buf);
+		if (ret < 0) {
+		    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query buffer failed: %s, idx = %d\n",
+			   info.short_name, strerror(errno), buf.index);
+		    return 0;
+		}
+		if ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE)) == V4L2_BUF_FLAG_MAPPED) {
+		    if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) {
+			mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
+			       info.short_name, strerror(errno));
+			return 0;
+		    }		
+		}
+	    }
+	    continue;
+	}
+
+	/* store the timestamp of the very first frame as reference */
+	if (!priv->frames++) {
+	    if (!tv_param_noaudio) pthread_mutex_lock(&priv->skew_mutex);
+	    priv->first_frame = (long long)1e6*buf.timestamp.tv_sec + buf.timestamp.tv_usec;
+	    if (!tv_param_noaudio) pthread_mutex_unlock(&priv->skew_mutex);
+	}
+	priv->curr_frame = (long long)buf.timestamp.tv_sec*1e6+buf.timestamp.tv_usec;
+//	fprintf(stderr, "idx = %d, ts = %lf\n", buf.index, (double)(priv->curr_frame) / 1e6);
+
+	interval = priv->curr_frame - priv->first_frame;
+	delta = interval - prev_interval;
+
+	if (!priv->immediate_mode) {
+	    // interpolate the skew in time
+	    if (!tv_param_noaudio) pthread_mutex_lock(&priv->skew_mutex);
+	    xskew = priv->audio_skew + (interval - priv->audio_skew_measure_time)*priv->audio_skew_factor;
+	    if (!tv_param_noaudio) pthread_mutex_unlock(&priv->skew_mutex);
+ 	    // correct extreme skew changes to avoid (especially) moving backwards in time
+	    if (xskew - prev_skew > delta*MAX_SKEW_DELTA) {
+		skew = prev_skew + delta*MAX_SKEW_DELTA;
+	    } else if (xskew - prev_skew < -delta*MAX_SKEW_DELTA) {
+		skew = prev_skew - delta*MAX_SKEW_DELTA;
+	    } else {
+		skew = xskew;
+	    }
+	}
+
+	mp_msg(MSGT_TV, MSGL_DBG3, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
+	       delta ? (double)1e6/delta : -1,
+	       (double)1e-6*interval, (double)1e-6*xskew, (double)1e-6*skew);
+	mp_msg(MSGT_TV, MSGL_DBG3, "vcnt = %d, acnt = %d\n", priv->video_cnt, priv->audio_cnt);
+
+	prev_skew = skew;
+	prev_interval = interval;
+
+	/* allocate a new buffer, if needed */
+	pthread_mutex_lock(&priv->video_buffer_mutex);
+	if (priv->video_buffer_size_current < priv->video_buffer_size_max) {
+	    if (priv->video_cnt == priv->video_buffer_size_current) {
+		unsigned char *newbuf = malloc(framesize);
+		if (newbuf) {
+		    memmove(priv->video_ringbuffer+priv->video_tail+1, priv->video_ringbuffer+priv->video_tail,
+			    (priv->video_buffer_size_current-priv->video_tail)*sizeof(unsigned char *));
+		    memmove(priv->video_timebuffer+priv->video_tail+1, priv->video_timebuffer+priv->video_tail,
+			    (priv->video_buffer_size_current-priv->video_tail)*sizeof(long long));
+		    priv->video_ringbuffer[priv->video_tail] = newbuf;
+		    if ((priv->video_head >= priv->video_tail) && (priv->video_cnt > 0)) priv->video_head++;
+		    priv->video_buffer_size_current++;
+		}
+	    }
+	}
+	pthread_mutex_unlock(&priv->video_buffer_mutex);
+
+	if (priv->video_cnt == priv->video_buffer_size_current) {
+	    if (!priv->immediate_mode) {
+		mp_msg(MSGT_TV, MSGL_ERR, "\nvideo buffer full - dropping frame\n");
+		if (priv->audio_insert_null_samples) {
+		    pthread_mutex_lock(&priv->audio_mutex);
+		    priv->dropped_frames_timeshift += delta;
+		    pthread_mutex_unlock(&priv->audio_mutex);
+		}
+	    }
+	} else {
+	    if (priv->immediate_mode) {
+		priv->video_timebuffer[priv->video_tail] = 0;
+	    } else {
+		// compensate for audio skew
+		// negative skew => there are more audio samples, increase interval
+		// positive skew => less samples, shorten the interval
+		priv->video_timebuffer[priv->video_tail] = interval - skew;
+		if (priv->audio_insert_null_samples && priv->video_timebuffer[priv->video_tail] > 0) {
+		    pthread_mutex_lock(&priv->audio_mutex);
+		    priv->video_timebuffer[priv->video_tail] += 
+			(priv->audio_null_blocks_inserted
+			 - priv->dropped_frames_timeshift/priv->audio_usecs_per_block)
+			*priv->audio_usecs_per_block;
+		    pthread_mutex_unlock(&priv->audio_mutex);
+		}
+	    }
+
+	    copy_frame(priv, priv->video_ringbuffer[priv->video_tail], priv->map[buf.index].addr);
+	    priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current;
+	    priv->video_cnt++;
+	}
+	if (ioctl(priv->video_fd, VIDIOC_QBUF, &buf) < 0) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
+		   info.short_name, strerror(errno));
+	    return 0;
+	}
+    }
+    return NULL;
+}
+
+#define MAX_LOOP 50
+static double grab_video_frame(priv_t *priv, char *buffer, int len)
+{
+    double interval;
+    int loop_cnt = 0;
+
+    if (priv->first) {
+	pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);
+	priv->first = 0;
+    }
+
+    while (priv->video_cnt == 0) {
+	usleep(10000);
+	if (loop_cnt++ > MAX_LOOP) return 0;
+    }
+
+    pthread_mutex_lock(&priv->video_buffer_mutex);
+    interval = (double)priv->video_timebuffer[priv->video_head]*1e-6;
+    memcpy(buffer, priv->video_ringbuffer[priv->video_head], len);
+    priv->video_cnt--;
+    priv->video_head = (priv->video_head+1)%priv->video_buffer_size_current;
+    pthread_mutex_unlock(&priv->video_buffer_mutex);
+
+    return interval;
+}
+
+static int get_video_framesize(priv_t *priv)
+{
+    return priv->format.fmt.pix.sizeimage;
+}
+
+//#define DOUBLESPEED
+#ifdef DOUBLESPEED
+// for testing purposes only
+static void read_doublespeed(priv_t *priv)
+{
+    char *bufx = calloc(priv->audio_in.blocksize, 2);
+    short *s;
+    short *d;
+    int i;
+    
+    audio_in_read_chunk(&priv->audio_in, bufx);
+    audio_in_read_chunk(&priv->audio_in, bufx+priv->audio_in.blocksize);
+
+    s = bufx;
+    d = priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize;
+    for (i = 0; i < priv->audio_in.blocksize/2; i++) {
+	*d++ = *s++;
+	*s++;
+    }
+    
+}
+#endif
+
+static void *audio_grabber(void *data)
+{
+    priv_t *priv = (priv_t*)data;
+    struct timeval tv;
+    int i, audio_skew_ptr = 0;
+    long long current_time, prev_skew = 0, prev_skew_uncorr = 0;
+    long long start_time_avg;
+
+    gettimeofday(&tv, NULL);
+    start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
+    audio_in_start_capture(&priv->audio_in);
+    for (i = 0; i < priv->aud_skew_cnt; i++)
+	priv->audio_skew_buffer[i] = 0;
+    for (i = 0; i < priv->aud_skew_cnt; i++)
+	priv->audio_skew_delta_buffer[i] = 0;
+
+    for (; !priv->shutdown;)
+    {
+#ifdef DOUBLESPEED
+	read_doublespeed(priv);
+#else
+	if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0)
+	    continue;
+#endif
+	pthread_mutex_lock(&priv->skew_mutex);
+	if (priv->first_frame == 0) {
+	    // there is no first frame yet (unlikely to happen)
+	    gettimeofday(&tv, NULL);
+	    start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
+//	    fprintf(stderr, "warning - first frame not yet available!\n");
+	    pthread_mutex_unlock(&priv->skew_mutex);
+	    continue;
+	}
+	pthread_mutex_unlock(&priv->skew_mutex);
+
+	gettimeofday(&tv, NULL);
+
+	priv->audio_recv_blocks_total++;
+	current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_start_time;
+
+	if (priv->audio_recv_blocks_total < priv->aud_skew_cnt*2) {
+	    start_time_avg += (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
+	    priv->audio_start_time = start_time_avg/(priv->audio_recv_blocks_total+1);
+	}
+
+//	fprintf(stderr, "spb = %lf, bs = %d, skew = %lf\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
+//		(double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
+
+	// put the current skew into the ring buffer
+	priv->audio_skew_total -= priv->audio_skew_buffer[audio_skew_ptr];
+	priv->audio_skew_buffer[audio_skew_ptr] = current_time
+	    - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
+	priv->audio_skew_total += priv->audio_skew_buffer[audio_skew_ptr];
+
+	pthread_mutex_lock(&priv->skew_mutex);
+
+	// skew calculation
+
+	// compute the sliding average of the skews
+	if (priv->audio_recv_blocks_total > priv->aud_skew_cnt) {
+	    priv->audio_skew = priv->audio_skew_total/priv->aud_skew_cnt;
+	} else {
+	    priv->audio_skew = priv->audio_skew_total/priv->audio_recv_blocks_total;
+	}
+
+	// put the current skew change (skew-prev_skew) into the ring buffer
+	priv->audio_skew_delta_total -= priv->audio_skew_delta_buffer[audio_skew_ptr];
+	priv->audio_skew_delta_buffer[audio_skew_ptr] = priv->audio_skew - prev_skew_uncorr;
+	priv->audio_skew_delta_total += priv->audio_skew_delta_buffer[audio_skew_ptr];
+	prev_skew_uncorr = priv->audio_skew; // remember the _uncorrected_ average value
+
+	audio_skew_ptr = (audio_skew_ptr+1) % priv->aud_skew_cnt; // rotate the buffer pointer
+
+	// sliding average approximates the value in the middle of the interval
+	// so interpolate the skew value further to the current time
+	priv->audio_skew += priv->audio_skew_delta_total/2;
+
+	// now finally, priv->audio_skew contains fairly good approximation
+	// of the current value 
+
+	// current skew factor (assuming linearity)
+	// used for further interpolation in video_grabber
+	// probably overkill but seems to be necessary for
+	// stress testing by dropping half of the audio frames ;)
+	// especially when using ALSA with large block sizes
+	// where audio_skew remains a long while behind
+	if ((priv->audio_skew_measure_time != 0) && (current_time - priv->audio_skew_measure_time != 0)) {
+	    priv->audio_skew_factor = (double)(priv->audio_skew-prev_skew)/(current_time - priv->audio_skew_measure_time);
+	} else {
+	    priv->audio_skew_factor = 0.0;
+	}
+
+	priv->audio_skew_measure_time = current_time;
+	prev_skew = priv->audio_skew;
+	priv->audio_skew += priv->audio_start_time - priv->first_frame;
+	pthread_mutex_unlock(&priv->skew_mutex);
+	
+//	fprintf(stderr, "audio_skew = %lf, delta = %lf\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
+
+	pthread_mutex_lock(&priv->audio_mutex);
+	if ((priv->audio_tail+1) % priv->audio_buffer_size == priv->audio_head) {
+	    mp_msg(MSGT_TV, MSGL_ERR, "\ntoo bad - dropping audio frame !\n");
+	    priv->audio_drop++;
+	} else {
+	    priv->audio_tail = (priv->audio_tail+1) % priv->audio_buffer_size;
+	    priv->audio_cnt++;
+	}
+	pthread_mutex_unlock(&priv->audio_mutex);
+    }
+    return NULL;
+}
+
+static double grab_audio_frame(priv_t *priv, char *buffer, int len)
+{
+    mp_dbg(MSGT_TV, MSGL_DBG2, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
+	priv, buffer, len);
+
+    // hack: if grab_audio_frame is called first, it means we are used by mplayer
+    // => switch to the mode which outputs audio immediately, even if
+    // it should be silence
+    if (priv->first) priv->audio_insert_null_samples = 1;
+
+    pthread_mutex_lock(&priv->audio_mutex);
+    while (priv->audio_insert_null_samples
+	   && priv->dropped_frames_timeshift - priv->dropped_frames_compensated >= priv->audio_usecs_per_block) {
+	// some frames were dropped - drop the corresponding number of audio blocks
+	if (priv->audio_drop) {
+	    priv->audio_drop--;
+	} else {
+	    if (priv->audio_head == priv->audio_tail) break;
+	    priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
+	}
+	priv->dropped_frames_compensated += priv->audio_usecs_per_block;
+    }
+
+    // compensate for dropped audio frames
+    if (priv->audio_drop && (priv->audio_head == priv->audio_tail)) {
+	priv->audio_drop--;
+	memset(buffer, 0, len);
+	goto out;
+    }
+
+    if (priv->audio_insert_null_samples && (priv->audio_head == priv->audio_tail)) {
+	// return silence to avoid desync and stuttering
+	memset(buffer, 0, len);
+	priv->audio_null_blocks_inserted++;
+	goto out;
+    }
+
+    pthread_mutex_unlock(&priv->audio_mutex);
+    while (priv->audio_head == priv->audio_tail) {
+	// this is mencoder => just wait until some audio is available
+	usleep(10000);
+    }
+    pthread_mutex_lock(&priv->audio_mutex);
+    memcpy(buffer, priv->audio_ringbuffer+priv->audio_head*priv->audio_in.blocksize, len);
+    priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
+    priv->audio_cnt--;
+out:
+    pthread_mutex_unlock(&priv->audio_mutex);
+    priv->audio_sent_blocks_total++;
+    return (double)priv->audio_sent_blocks_total*priv->audio_secs_per_block;
+}
+
+static int get_audio_framesize(priv_t *priv)
+{
+    return(priv->audio_in.blocksize);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/url.c	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,373 @@
+/*
+ * URL Helper
+ * by Bertrand Baudet <bertrand_baudet@yahoo.com>
+ * (C) 2001, MPlayer team.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "url.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif
+
+URL_t*
+url_new(const char* url) {
+	int pos1, pos2,v6addr = 0;
+	URL_t* Curl = NULL;
+        char *escfilename=NULL;
+	char *ptr1=NULL, *ptr2=NULL, *ptr3=NULL, *ptr4=NULL;
+	int jumpSize = 3;
+
+	if( url==NULL ) return NULL;
+	
+        if (strlen(url) > (SIZE_MAX / 3 - 1)) {
+                mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+                goto err_out;
+        }
+        escfilename=malloc(strlen(url)*3+1);
+        if (!escfilename ) {
+                mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+                goto err_out;
+        }
+
+	// Create the URL container
+	Curl = malloc(sizeof(URL_t));
+	if( Curl==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+		goto err_out;
+	}
+
+	// Initialisation of the URL container members
+	memset( Curl, 0, sizeof(URL_t) );
+
+	url_escape_string(escfilename,url);
+
+	// Copy the url in the URL container
+	Curl->url = strdup(escfilename);
+	if( Curl->url==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+		goto err_out;
+	}
+        mp_msg(MSGT_OPEN,MSGL_V,"Filename for url is now %s\n",escfilename);
+
+	// extract the protocol
+	ptr1 = strstr(escfilename, "://");
+	if( ptr1==NULL ) {
+	        // Check for a special case: "sip:" (without "//"):
+	        if (strstr(escfilename, "sip:") == escfilename) {
+		        ptr1 = (char *)&url[3]; // points to ':'
+			jumpSize = 1;
+		} else {
+		        mp_msg(MSGT_NETWORK,MSGL_V,"Not an URL!\n");
+			goto err_out;
+		}
+	}
+	pos1 = ptr1-escfilename;
+	Curl->protocol = malloc(pos1+1);
+	if( Curl->protocol==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+		goto err_out;
+	}
+	strncpy(Curl->protocol, escfilename, pos1);
+	Curl->protocol[pos1] = '\0';
+
+	// jump the "://"
+	ptr1 += jumpSize;
+	pos1 += jumpSize;
+
+	// check if a username:password is given
+	ptr2 = strstr(ptr1, "@");
+	ptr3 = strstr(ptr1, "/");
+	if( ptr3!=NULL && ptr3<ptr2 ) {
+		// it isn't really a username but rather a part of the path
+		ptr2 = NULL;
+	}
+	if( ptr2!=NULL ) {
+		// We got something, at least a username...
+		int len = ptr2-ptr1;
+		Curl->username = malloc(len+1);
+		if( Curl->username==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+			goto err_out;
+		}
+		strncpy(Curl->username, ptr1, len);
+		Curl->username[len] = '\0';
+
+		ptr3 = strstr(ptr1, ":");
+		if( ptr3!=NULL && ptr3<ptr2 ) {
+			// We also have a password
+			int len2 = ptr2-ptr3-1;
+			Curl->username[ptr3-ptr1]='\0';
+			Curl->password = malloc(len2+1);
+			if( Curl->password==NULL ) {
+				mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+				goto err_out;
+			}
+			strncpy( Curl->password, ptr3+1, len2);
+			Curl->password[len2]='\0';
+		}
+		ptr1 = ptr2+1;
+		pos1 = ptr1-escfilename;
+	}
+
+	// before looking for a port number check if we have an IPv6 type numeric address
+	// in IPv6 URL the numeric address should be inside square braces.
+	ptr2 = strstr(ptr1, "[");
+	ptr3 = strstr(ptr1, "]");
+	ptr4 = strstr(ptr1, "/");
+	if( ptr2!=NULL && ptr3!=NULL && ptr2 < ptr3 && (!ptr4 || ptr4 > ptr3)) {
+		// we have an IPv6 numeric address
+		ptr1++;
+		pos1++;
+		ptr2 = ptr3;
+		v6addr = 1;
+	} else {
+		ptr2 = ptr1;
+
+	}
+	
+	// look if the port is given
+	ptr2 = strstr(ptr2, ":");
+	// If the : is after the first / it isn't the port
+	ptr3 = strstr(ptr1, "/");
+	if(ptr3 && ptr3 - ptr2 < 0) ptr2 = NULL;
+	if( ptr2==NULL ) {
+		// No port is given
+		// Look if a path is given
+		if( ptr3==NULL ) {
+			// No path/filename
+			// So we have an URL like http://www.hostname.com
+			pos2 = strlen(escfilename);
+		} else {
+			// We have an URL like http://www.hostname.com/file.txt
+                        pos2 = ptr3-escfilename;
+		}
+	} else {
+		// We have an URL beginning like http://www.hostname.com:1212
+		// Get the port number
+		Curl->port = atoi(ptr2+1);
+		pos2 = ptr2-escfilename;
+	}
+	if( v6addr ) pos2--;
+	// copy the hostname in the URL container
+	Curl->hostname = malloc(pos2-pos1+1);
+	if( Curl->hostname==NULL ) {
+		mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+		goto err_out;
+	}
+	strncpy(Curl->hostname, ptr1, pos2-pos1);
+	Curl->hostname[pos2-pos1] = '\0';
+
+	// Look if a path is given
+	ptr2 = strstr(ptr1, "/");
+	if( ptr2!=NULL ) {
+		// A path/filename is given
+		// check if it's not a trailing '/'
+		if( strlen(ptr2)>1 ) {
+			// copy the path/filename in the URL container
+			Curl->file = strdup(ptr2);
+			if( Curl->file==NULL ) {
+				mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+				goto err_out;
+			}
+		}
+	} 
+	// Check if a filename was given or set, else set it with '/'
+	if( Curl->file==NULL ) {
+		Curl->file = malloc(2);
+		if( Curl->file==NULL ) {
+			mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MemAllocFailed);
+			goto err_out;
+		}
+		strcpy(Curl->file, "/");
+	}
+	
+        free(escfilename);
+	return Curl;
+err_out:
+	if (escfilename) free(escfilename);
+	if (Curl) url_free(Curl);
+	return NULL;
+}
+
+void
+url_free(URL_t* url) {
+	if(!url) return;
+	if(url->url) free(url->url);
+	if(url->protocol) free(url->protocol);
+	if(url->hostname) free(url->hostname);
+	if(url->file) free(url->file);
+	if(url->username) free(url->username);
+	if(url->password) free(url->password);
+	free(url);
+}
+
+
+/* Replace escape sequences in an URL (or a part of an URL) */
+/* works like strcpy(), but without return argument */
+void
+url_unescape_string(char *outbuf, const char *inbuf)
+{
+	unsigned char c,c1,c2;
+        int i,len=strlen(inbuf);
+        for (i=0;i<len;i++){
+		c = inbuf[i];
+		if (c == '%' && i<len-2) { //must have 2 more chars
+			c1 = toupper(inbuf[i+1]); // we need uppercase characters
+			c2 = toupper(inbuf[i+2]);
+			if (	((c1>='0' && c1<='9') || (c1>='A' && c1<='F')) &&
+				((c2>='0' && c2<='9') || (c2>='A' && c2<='F')) ) {
+				if (c1>='0' && c1<='9') c1-='0';
+				else c1-='A'-10;
+				if (c2>='0' && c2<='9') c2-='0';
+				else c2-='A'-10;
+				c = (c1<<4) + c2;
+                                i=i+2; //only skip next 2 chars if valid esc
+			}
+		}
+		*outbuf++ = c;
+	} 
+        *outbuf++='\0'; //add nullterm to string
+}
+
+static void
+url_escape_string_part(char *outbuf, const char *inbuf) {
+	unsigned char c,c1,c2;
+        int i,len=strlen(inbuf);
+
+	for  (i=0;i<len;i++) {
+		c = inbuf[i];
+                if ((c=='%') && i<len-2 ) { //need 2 more characters
+                    c1=toupper(inbuf[i+1]); c2=toupper(inbuf[i+2]); // need uppercase chars
+                   } else {
+                    c1=129; c2=129; //not escape chars
+                   }
+
+		if(	(c >= 'A' && c <= 'Z') ||
+			(c >= 'a' && c <= 'z') ||
+			(c >= '0' && c <= '9') ||
+			(c >= 0x7f)) {
+			*outbuf++ = c;
+                } else if ( c=='%' && ((c1 >= '0' && c1 <= '9') || (c1 >= 'A' && c1 <= 'F')) &&
+                           ((c2 >= '0' && c2 <= '9') || (c2 >= 'A' && c2 <= 'F'))) {
+                                                              // check if part of an escape sequence
+                            *outbuf++=c;                      // already
+			      
+                                                              // dont escape again
+                            mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_URL_StringAlreadyEscaped,c,c1,c2);
+                                                              // error as this should not happen against RFC 2396
+                                                              // to escape a string twice
+		} else {
+			/* all others will be escaped */
+			c1 = ((c & 0xf0) >> 4);
+			c2 = (c & 0x0f);
+			if (c1 < 10) c1+='0';
+			else c1+='A'-10;
+			if (c2 < 10) c2+='0';
+			else c2+='A'-10;
+			*outbuf++ = '%';
+			*outbuf++ = c1;
+			*outbuf++ = c2;
+		}
+	}
+        *outbuf++='\0';
+}
+
+/* Replace specific characters in the URL string by an escape sequence */
+/* works like strcpy(), but without return argument */
+void
+url_escape_string(char *outbuf, const char *inbuf) {
+	unsigned char c;
+        int i = 0,j,len = strlen(inbuf);
+	char* tmp,*unesc = NULL, *in;
+	
+	// Look if we have an ip6 address, if so skip it there is
+	// no need to escape anything in there.
+	tmp = strstr(inbuf,"://[");
+	if(tmp) {
+		tmp = strchr(tmp+4,']');
+		if(tmp && (tmp[1] == '/' || tmp[1] == ':' ||
+			   tmp[1] == '\0')) {
+			i = tmp+1-inbuf;
+			strncpy(outbuf,inbuf,i);
+			outbuf += i;
+			tmp = NULL;
+		}
+	}
+	
+	while(i < len) {
+		// look for the next char that must be kept
+		for  (j=i;j<len;j++) {
+			c = inbuf[j];
+			if(c=='-' || c=='_' || c=='.' || c=='!' || c=='~' ||	/* mark characters */
+			   c=='*' || c=='\'' || c=='(' || c==')' || 	 	/* do not touch escape character */
+			   c==';' || c=='/' || c=='?' || c==':' || c=='@' || 	/* reserved characters */
+			   c=='&' || c=='=' || c=='+' || c=='$' || c==',') 	/* see RFC 2396 */
+				break;
+		}
+		// we are on a reserved char, write it out
+		if(j == i) {
+			*outbuf++ = c;
+			i++;
+			continue;
+		}
+		// we found one, take that part of the string
+		if(j < len) {
+			if(!tmp) tmp = malloc(len+1);
+			strncpy(tmp,inbuf+i,j-i);
+			tmp[j-i] = '\0';
+			in = tmp;
+		} else // take the rest of the string
+			in = (char*)inbuf+i;
+		
+		if(!unesc) unesc = malloc(len+1);
+		// unescape first to avoid escaping escape
+		url_unescape_string(unesc,in);
+		// then escape, including mark and other reserved chars
+		// that can come from escape sequences
+		url_escape_string_part(outbuf,unesc);
+		outbuf += strlen(outbuf);
+		i += strlen(in);
+	}
+	*outbuf = '\0';
+	if(tmp) free(tmp);
+	if(unesc) free(unesc);
+}
+
+#ifdef __URL_DEBUG
+void
+url_debug(const URL_t *url) {
+	if( url==NULL ) {
+		printf("URL pointer NULL\n");
+		return;
+	}
+	if( url->url!=NULL ) {
+		printf("url=%s\n", url->url );
+	}
+	if( url->protocol!=NULL ) {
+		printf("protocol=%s\n", url->protocol );
+	}
+	if( url->hostname!=NULL ) {
+		printf("hostname=%s\n", url->hostname );
+	}
+	printf("port=%d\n", url->port );
+	if( url->file!=NULL ) {
+		printf("file=%s\n", url->file );
+	}
+	if( url->username!=NULL ) {
+		printf("username=%s\n", url->username );
+	}
+	if( url->password!=NULL ) {
+		printf("password=%s\n", url->password );
+	}
+}
+#endif //__URL_DEBUG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/url.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,32 @@
+/* 
+ * URL Helper
+ * by Bertrand Baudet <bertrand_baudet@yahoo.com>
+ * (C) 2001, MPlayer team.
+ */
+
+#ifndef __URL_H
+#define __URL_H
+
+//#define __URL_DEBUG
+
+typedef struct {
+	char *url;
+	char *protocol;
+	char *hostname;
+	char *file;
+	unsigned int port;
+	char *username;
+	char *password;
+} URL_t;
+
+URL_t* url_new(const char* url);
+void   url_free(URL_t* url);
+
+void url_unescape_string(char *outbuf, const char *inbuf);
+void url_escape_string(char *outbuf, const char *inbuf);
+
+#ifdef __URL_DEBUG
+void url_debug(const URL_t* url);
+#endif // __URL_DEBUG
+
+#endif // __URL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/vcd_read.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,245 @@
+//=================== VideoCD ==========================
+#if	defined(linux) || defined(sun) || defined(__bsdi__)
+
+typedef struct mp_vcd_priv_st mp_vcd_priv_t;
+
+#if	defined(linux)
+#include <linux/cdrom.h>
+#elif	defined(sun)
+#include <sys/cdio.h>
+static int sun_vcd_read(mp_vcd_priv_t*, int*);
+#elif	defined(__bsdi__)
+#include <dvd.h>
+#endif
+
+struct mp_vcd_priv_st {
+  int fd;
+  struct cdrom_tocentry entry;
+  char buf[VCD_SECTOR_SIZE];
+};
+
+static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect){
+  vcd->entry.cdte_addr.msf.frame=sect%75;
+  sect=sect/75;
+  vcd->entry.cdte_addr.msf.second=sect%60;
+  sect=sect/60;
+  vcd->entry.cdte_addr.msf.minute=sect;
+}
+
+static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd){
+  return vcd->entry.cdte_addr.msf.frame +
+        (vcd->entry.cdte_addr.msf.second+
+         vcd->entry.cdte_addr.msf.minute*60)*75;
+}
+
+int vcd_seek_to_track(mp_vcd_priv_t* vcd,int track){
+  vcd->entry.cdte_format = CDROM_MSF;
+  vcd->entry.cdte_track  = track;
+  if (ioctl(vcd->fd, CDROMREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+}
+
+int vcd_get_track_end(mp_vcd_priv_t* vcd,int track){
+  struct cdrom_tochdr tochdr;
+  if (ioctl(vcd->fd,CDROMREADTOCHDR,&tochdr)==-1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return -1;
+  }
+  vcd->entry.cdte_format = CDROM_MSF;
+  vcd->entry.cdte_track  = track<tochdr.cdth_trk1?(track+1):CDROM_LEADOUT;
+  if (ioctl(vcd->fd, CDROMREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+}
+
+mp_vcd_priv_t* vcd_read_toc(int fd){
+  struct cdrom_tochdr tochdr;
+  mp_vcd_priv_t* vcd;
+  int i, min = 0, sec = 0, frame = 0;
+  if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return NULL;
+  }
+  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", tochdr.cdth_trk0);
+  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", tochdr.cdth_trk1);
+  for (i=tochdr.cdth_trk0 ; i<=tochdr.cdth_trk1 + 1; i++){
+      struct cdrom_tocentry tocentry;
+
+      tocentry.cdte_track  = i<=tochdr.cdth_trk1 ? i : CDROM_LEADOUT;
+      tocentry.cdte_format = CDROM_MSF;
+
+      if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)==-1) {
+	mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
+	return NULL;
+      }
+        
+      if (i<=tochdr.cdth_trk1)
+      mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d  mode: %d\n",
+          (int)tocentry.cdte_track,
+          (int)tocentry.cdte_adr,
+          (int)tocentry.cdte_ctrl,
+          (int)tocentry.cdte_format,
+          (int)tocentry.cdte_addr.msf.minute,
+          (int)tocentry.cdte_addr.msf.second,
+          (int)tocentry.cdte_addr.msf.frame,
+          (int)tocentry.cdte_datamode
+      );
+
+      if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
+      {
+        if (i > tochdr.cdth_trk0)
+        {
+          min = tocentry.cdte_addr.msf.minute - min;
+          sec = tocentry.cdte_addr.msf.second - sec;
+          frame = tocentry.cdte_addr.msf.frame - frame;
+          if ( frame < 0 )
+          {
+            frame += 75;
+            sec --;
+          }
+          if ( sec < 0 )
+          {
+            sec += 60;
+            min --;
+          }
+          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
+        }
+        min = tocentry.cdte_addr.msf.minute;
+        sec = tocentry.cdte_addr.msf.second;
+        frame = tocentry.cdte_addr.msf.frame;
+      }
+    }
+  vcd = malloc(sizeof(mp_vcd_priv_t));
+  vcd->fd = fd;
+  return vcd;
+}
+
+static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
+#if	defined(linux) || defined(__bsdi__)
+  memcpy(vcd->buf,&vcd->entry.cdte_addr.msf,sizeof(struct cdrom_msf));
+  if(ioctl(vcd->fd,CDROMREADRAW,vcd->buf)==-1) return 0; // EOF?
+  memcpy(mem,&vcd->buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA);
+#elif	defined(sun)
+  {
+    int offset;
+    if (sun_vcd_read(vcd->fd, &offset) <= 0) return 0;
+    memcpy(mem,&vcd->buf[offset],VCD_SECTOR_DATA);
+  }
+#endif
+
+  vcd->entry.cdte_addr.msf.frame++;
+  if (vcd->entry.cdte_addr.msf.frame==75){
+    vcd->entry.cdte_addr.msf.frame=0;
+    vcd->entry.cdte_addr.msf.second++;
+    if (vcd->entry.cdte_addr.msf.second==60){
+      vcd->entry.cdte_addr.msf.second=0;
+      vcd->entry.cdte_addr.msf.minute++;
+    }
+  }
+    
+  return VCD_SECTOR_DATA;
+}
+
+
+#ifdef	sun
+#include <sys/scsi/generic/commands.h>
+#include <sys/scsi/impl/uscsi.h>
+
+#define	SUN_XAREAD	1	/*fails on atapi drives*/
+#define	SUN_MODE2READ	2	/*fails on atapi drives*/
+#define	SUN_SCSIREAD	3
+#define	SUN_VCDREAD	SUN_SCSIREAD
+
+static int sun_vcd_read(mp_vcd_priv_t* vcd, int *offset)
+{
+#if SUN_VCDREAD == SUN_XAREAD
+  struct cdrom_cdxa cdxa;
+  cdxa.cdxa_addr = vcd_get_msf(vcd);
+  cdxa.cdxa_length = 1;
+  cdxa.cdxa_data = vcd->buf;
+  cdxa.cdxa_format = CDROM_XA_SECTOR_DATA;
+  
+  if(ioctl(vcd->fd,CDROMCDXA,&cdxa)==-1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"CDROMCDXA: %s\n",strerror(errno));
+    return 0;
+  }
+  *offset = 0;
+#elif SUN_VCDREAD == SUN_MODE2READ
+  struct cdrom_read cdread;
+  cdread.cdread_lba = 4*vcd_get_msf(vcd);
+  cdread.cdread_bufaddr = vcd->buf;
+  cdread.cdread_buflen = 2336;
+
+  if(ioctl(vcd->fd,CDROMREADMODE2,&cdread)==-1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"CDROMREADMODE2: %s\n",strerror(errno));
+    return 0;
+  }
+  *offset = 8;
+#elif SUN_VCDREAD == SUN_SCSIREAD
+  struct uscsi_cmd sc;
+  union scsi_cdb cdb;
+  int lba = vcd_get_msf(vcd);
+  int blocks = 1;
+  int sector_type;
+  int sync, header_code, user_data, edc_ecc, error_field;
+  int sub_channel;
+
+  /* sector_type = 3; *//* mode2 */
+  sector_type = 5;	/* mode2/form2 */
+  sync = 0;
+  header_code = 0;
+  user_data = 1;
+  edc_ecc = 0;
+  error_field = 0;
+  sub_channel = 0;
+
+  memset(&cdb, 0, sizeof(cdb));
+  memset(&sc, 0, sizeof(sc));
+  cdb.scc_cmd = 0xBE;
+  cdb.cdb_opaque[1] = (sector_type) << 2;
+  cdb.cdb_opaque[2] = (lba >> 24) & 0xff;
+  cdb.cdb_opaque[3] = (lba >> 16) & 0xff;
+  cdb.cdb_opaque[4] = (lba >>  8) & 0xff;
+  cdb.cdb_opaque[5] =  lba & 0xff;
+  cdb.cdb_opaque[6] = (blocks >> 16) & 0xff;
+  cdb.cdb_opaque[7] = (blocks >>  8) & 0xff;
+  cdb.cdb_opaque[8] =  blocks & 0xff;
+  cdb.cdb_opaque[9] = (sync << 7) |
+		      (header_code << 5) |
+		      (user_data << 4) |
+		      (edc_ecc << 3) |
+		      (error_field << 1);
+  cdb.cdb_opaque[10] = sub_channel;
+
+  sc.uscsi_cdb = (caddr_t)&cdb;
+  sc.uscsi_cdblen = 12;
+  sc.uscsi_bufaddr = vcd->buf;
+  sc.uscsi_buflen = 2336;
+  sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ;
+  sc.uscsi_timeout = 20;
+  if (ioctl(vcd->fd, USCSICMD, &sc)) {
+      mp_msg(MSGT_STREAM,MSGL_ERR,"USCSICMD: READ CD: %s\n",strerror(errno));
+      return -1;
+  }
+  if (sc.uscsi_status) {
+      mp_msg(MSGT_STREAM,MSGL_ERR,"scsi command failed with status %d\n", sc.uscsi_status);
+      return -1;
+  }
+  *offset = 0;
+  return 1;
+#else
+#error SUN_VCDREAD
+#endif
+}
+#endif	/*sun*/
+
+#else /* linux || sun || __bsdi__ */
+
+#error vcd is not yet supported on this arch...
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/vcd_read_darwin.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,212 @@
+#include <sys/types.h>
+#include <CoreFoundation/CFBase.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOCDTypes.h>
+#include <IOKit/storage/IOCDMedia.h>
+#include <IOKit/storage/IOCDMediaBSDClient.h>
+
+//=================== VideoCD ==========================
+#define	CDROM_LEADOUT	0xAA
+
+typedef struct
+{
+	uint8_t sync            [12];
+	uint8_t header          [4];
+	uint8_t subheader       [8];
+	uint8_t data            [2324];
+	uint8_t spare           [4];
+} cdsector_t;
+
+typedef struct mp_vcd_priv_st
+{
+	int fd;
+	dk_cd_read_track_info_t entry;
+	CDMSF msf;
+	cdsector_t buf;
+} mp_vcd_priv_t;
+
+static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect)
+{
+  vcd->msf.frame=sect%75;
+  sect=sect/75;
+  vcd->msf.second=sect%60;
+  sect=sect/60;
+  vcd->msf.minute=sect;
+}
+
+static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd)
+{
+  return vcd->msf.frame +
+        (vcd->msf.second+
+         vcd->msf.minute*60)*75;
+
+return 0;
+}
+
+int vcd_seek_to_track(mp_vcd_priv_t* vcd, int track)
+{
+	dk_cd_read_track_info_t tocentry;
+	struct CDTrackInfo entry;
+
+	memset( &vcd->entry, 0, sizeof(vcd->entry));
+	vcd->entry.addressType = kCDTrackInfoAddressTypeTrackNumber;
+	vcd->entry.address = track;
+	vcd->entry.bufferLength = sizeof(entry);
+	vcd->entry.buffer = &entry;
+  
+	if (ioctl(vcd->fd, DKIOCCDREADTRACKINFO, &vcd->entry))
+	{
+		mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
+		return -1;
+	}
+	return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+  
+return -1;
+}
+
+int vcd_get_track_end(mp_vcd_priv_t* vcd, int track)
+{
+	dk_cd_read_disc_info_t tochdr;
+	struct CDDiscInfo hdr;
+	
+	dk_cd_read_track_info_t tocentry;
+	struct CDTrackInfo entry;
+	
+	//read toc header
+    memset(&tochdr, 0, sizeof(tochdr));
+    tochdr.buffer = &hdr;
+    tochdr.bufferLength = sizeof(hdr);
+  
+    if (ioctl(vcd->fd, DKIOCCDREADDISCINFO, &tochdr) < 0)
+	{
+		mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+		return NULL;
+    }
+	
+	//read track info
+	memset( &vcd->entry, 0, sizeof(vcd->entry));
+	vcd->entry.addressType = kCDTrackInfoAddressTypeTrackNumber;
+	vcd->entry.address = track<(hdr.lastTrackNumberInLastSessionLSB+1)?(track):CDROM_LEADOUT;
+	vcd->entry.bufferLength = sizeof(entry);
+	vcd->entry.buffer = &entry;
+  
+	if (ioctl(vcd->fd, DKIOCCDREADTRACKINFO, &vcd->entry))
+	{
+		mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
+		return -1;
+	}
+	return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+
+return -1;
+}
+
+mp_vcd_priv_t* vcd_read_toc(int fd)
+{
+	dk_cd_read_disc_info_t tochdr;
+	struct CDDiscInfo hdr;
+	
+	dk_cd_read_track_info_t tocentry;
+	struct CDTrackInfo entry;
+	CDMSF trackMSF;
+	
+	mp_vcd_priv_t* vcd;
+	int i, min = 0, sec = 0, frame = 0;
+  
+	//read toc header
+    memset(&tochdr, 0, sizeof(tochdr));
+    tochdr.buffer = &hdr;
+    tochdr.bufferLength = sizeof(hdr);
+  
+    if (ioctl(fd, DKIOCCDREADDISCINFO, &tochdr) < 0)
+	{
+		mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+		return NULL;
+    }
+	
+	//print all track info
+	mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", hdr.firstTrackNumberInLastSessionLSB);
+	mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", hdr.lastTrackNumberInLastSessionLSB);
+	for (i=hdr.firstTrackNumberInLastSessionLSB ; i<=hdr.lastTrackNumberInLastSessionLSB + 1; i++)
+	{
+		memset( &tocentry, 0, sizeof(tocentry));
+		tocentry.addressType = kCDTrackInfoAddressTypeTrackNumber;
+		tocentry.address = i<=hdr.lastTrackNumberInLastSessionLSB ? i : CDROM_LEADOUT;
+		tocentry.bufferLength = sizeof(entry);
+		tocentry.buffer = &entry;
+
+		if (ioctl(fd,DKIOCCDREADTRACKINFO,&tocentry)==-1)
+		{
+			mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
+			return NULL;
+		}
+		
+		trackMSF = CDConvertLBAToMSF(entry.trackStartAddress);
+        
+		//mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
+		if (i<=hdr.lastTrackNumberInLastSessionLSB)
+		mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d: format=%d  %02d:%02d:%02d\n",
+          (int)tocentry.address,
+          //(int)tocentry.entry.addr_type,
+          //(int)tocentry.entry.control,
+          (int)tocentry.addressType,
+          (int)trackMSF.minute,
+          (int)trackMSF.second,
+          (int)trackMSF.frame
+		);
+
+		if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
+		{
+		  if (i > hdr.firstTrackNumberInLastSessionLSB)
+		  {
+		    min = trackMSF.minute - min;
+		    sec = trackMSF.second - sec;
+		    frame = trackMSF.frame - frame;
+		    if ( frame < 0 )
+		    {
+		      frame += 75;
+		      sec --;
+		    }
+		    if ( sec < 0 )
+		    {
+		      sec += 60;
+		      min --;
+		    }
+		    mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
+		  }
+		  min = trackMSF.minute;
+		  sec = trackMSF.second;
+		  frame = trackMSF.frame;
+		}
+	}
+ 
+	vcd = malloc(sizeof(mp_vcd_priv_t));
+	vcd->fd = fd;
+	vcd->msf = trackMSF;
+	return vcd;
+
+	return NULL;
+}
+
+static int vcd_read(mp_vcd_priv_t* vcd,char *mem)
+{
+	if (pread(vcd->fd,&vcd->buf,VCD_SECTOR_SIZE,vcd_get_msf(vcd)*VCD_SECTOR_SIZE) != VCD_SECTOR_SIZE)
+		return 0;  // EOF?
+
+	vcd->msf.frame++;
+	if (vcd->msf.frame==75)
+	{
+		vcd->msf.frame=0;
+		vcd->msf.second++;
+        
+		if (vcd->msf.second==60)
+		{
+			vcd->msf.second=0;
+			vcd->msf.minute++;
+        }
+      }
+	  
+      memcpy(mem,vcd->buf.data,VCD_SECTOR_DATA);
+      return VCD_SECTOR_DATA;
+return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/vcd_read_fbsd.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,138 @@
+#include <sys/cdio.h>
+#include <sys/cdrio.h>
+
+//=================== VideoCD ==========================
+#define	CDROM_LEADOUT	0xAA
+
+typedef struct {
+	uint8_t sync            [12];
+	uint8_t header          [4];
+	uint8_t subheader       [8];
+	uint8_t data            [2324];
+	uint8_t spare           [4];
+} cdsector_t;
+
+typedef struct mp_vcd_priv_st {
+  int fd;
+  struct ioc_read_toc_single_entry entry;
+  cdsector_t buf;
+} mp_vcd_priv_t;
+
+static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect){
+  vcd->entry.entry.addr.msf.frame=sect%75;
+  sect=sect/75;
+  vcd->entry.entry.addr.msf.second=sect%60;
+  sect=sect/60;
+  vcd->entry.entry.addr.msf.minute=sect;
+}
+
+static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd){
+  return vcd->entry.entry.addr.msf.frame +
+        (vcd->entry.entry.addr.msf.second+
+         vcd->entry.entry.addr.msf.minute*60)*75;
+}
+
+int vcd_seek_to_track(mp_vcd_priv_t* vcd, int track){
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.track  = track;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+}
+
+int vcd_get_track_end(mp_vcd_priv_t* vcd, int track){
+  struct ioc_toc_header tochdr;
+  if (ioctl(vcd->fd,CDIOREADTOCHEADER,&tochdr)==-1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return -1;
+  }
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.track  = track<tochdr.ending_track?(track+1):CDROM_LEADOUT;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRY, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA*vcd_get_msf(vcd);
+}
+
+mp_vcd_priv_t* vcd_read_toc(int fd){
+  struct ioc_toc_header tochdr;
+  mp_vcd_priv_t* vcd;
+  int i, min = 0, sec = 0, frame = 0;
+  if (ioctl(fd,CDIOREADTOCHEADER,&tochdr)==-1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return NULL;
+  }
+  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", tochdr.starting_track);
+  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", tochdr.ending_track);
+  for (i=tochdr.starting_track ; i<=tochdr.ending_track + 1; i++){
+      struct ioc_read_toc_single_entry tocentry;
+
+      tocentry.track  = i<=tochdr.ending_track ? i : CDROM_LEADOUT;
+      tocentry.address_format = CD_MSF_FORMAT;
+
+      if (ioctl(fd,CDIOREADTOCENTRY,&tocentry)==-1) {
+	mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
+	return NULL;
+      }
+        
+      if (i<=tochdr.ending_track)
+      mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
+          (int)tocentry.track,
+          (int)tocentry.entry.addr_type,
+          (int)tocentry.entry.control,
+          (int)tocentry.address_format,
+          (int)tocentry.entry.addr.msf.minute,
+          (int)tocentry.entry.addr.msf.second,
+          (int)tocentry.entry.addr.msf.frame
+      );
+
+      if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
+      {
+        if (i > tochdr.starting_track)
+        {
+          min = tocentry.entry.addr.msf.minute - min;
+          sec = tocentry.entry.addr.msf.second - sec;
+          frame = tocentry.entry.addr.msf.frame - frame;
+          if ( frame < 0 )
+          {
+            frame += 75;
+            sec --;
+          }
+          if ( sec < 0 )
+          {
+            sec += 60;
+            min --;
+          }
+          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
+        }
+        min = tocentry.entry.addr.msf.minute;
+        sec = tocentry.entry.addr.msf.second;
+        frame = tocentry.entry.addr.msf.frame;
+      }
+    }
+  vcd = malloc(sizeof(mp_vcd_priv_t));
+  vcd->fd = fd;
+  return vcd;  
+}
+
+static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
+
+      if (pread(vcd->fd,&vcd->buf,VCD_SECTOR_SIZE,vcd_get_msf(vcd)*VCD_SECTOR_SIZE)
+	 != VCD_SECTOR_SIZE) return 0;  // EOF?
+
+      vcd->entry.entry.addr.msf.frame++;
+      if (vcd->entry.entry.addr.msf.frame==75){
+        vcd->entry.entry.addr.msf.frame=0;
+        vcd->entry.entry.addr.msf.second++;
+        if (vcd->entry.entry.addr.msf.second==60){
+          vcd->entry.entry.addr.msf.second=0;
+          vcd->entry.entry.addr.msf.minute++;
+        }
+      }
+      memcpy(mem,vcd->buf.data,VCD_SECTOR_DATA);
+      return VCD_SECTOR_DATA;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stream/vcd_read_nbsd.h	Mon Jul 31 17:39:17 2006 +0000
@@ -0,0 +1,199 @@
+
+#include <sys/types.h>
+#ifdef __NetBSD__
+#include <sys/inttypes.h>
+#endif
+#include <sys/cdio.h>
+#include <sys/scsiio.h>
+
+#define	CDROM_LEADOUT	0xAA
+
+typedef struct mp_vcd_priv_st {
+  int fd;
+  struct ioc_read_toc_entry entry;
+  struct cd_toc_entry entry_data;
+} mp_vcd_priv_t;
+
+static inline void 
+vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect)
+{
+  vcd->entry_data.addr.msf.frame = sect % 75;
+  sect = sect / 75;
+  vcd->entry_data.addr.msf.second = sect % 60;
+  sect = sect / 60;
+  vcd->entry_data.addr.msf.minute = sect;
+}
+
+static inline void
+vcd_inc_msf(mp_vcd_priv_t* vcd)
+{
+  vcd->entry_data.addr.msf.frame++;
+  if (vcd->entry_data.addr.msf.frame==75){
+    vcd->entry_data.addr.msf.frame=0;
+    vcd->entry_data.addr.msf.second++;
+    if (vcd->entry_data.addr.msf.second==60){
+      vcd->entry_data.addr.msf.second=0;
+      vcd->entry_data.addr.msf.minute++;
+    }
+  }
+}
+
+static inline unsigned int 
+vcd_get_msf(mp_vcd_priv_t* vcd)
+{
+  return vcd->entry_data.addr.msf.frame +
+  (vcd->entry_data.addr.msf.second +
+   vcd->entry_data.addr.msf.minute * 60) * 75;
+}
+
+int 
+vcd_seek_to_track(mp_vcd_priv_t* vcd, int track)
+{
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.starting_track = track;
+  vcd->entry.data_len = sizeof(struct cd_toc_entry);
+  vcd->entry.data = &vcd->entry_data;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRIES, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA * vcd_get_msf(vcd);
+}
+
+int 
+vcd_get_track_end(mp_vcd_priv_t* vcd, int track)
+{
+  struct ioc_toc_header tochdr;
+  if (ioctl(vcd->fd, CDIOREADTOCHEADER, &tochdr) == -1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return -1;
+  }
+  vcd->entry.address_format = CD_MSF_FORMAT;
+  vcd->entry.starting_track = track < tochdr.ending_track ? (track + 1) : CDROM_LEADOUT;
+  vcd->entry.data_len = sizeof(struct cd_toc_entry);
+  vcd->entry.data = &vcd->entry_data;
+  if (ioctl(vcd->fd, CDIOREADTOCENTRYS, &vcd->entry)) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
+    return -1;
+  }
+  return VCD_SECTOR_DATA * vcd_get_msf(vcd);
+}
+
+mp_vcd_priv_t*
+vcd_read_toc(int fd)
+{
+  struct ioc_toc_header tochdr;
+  mp_vcd_priv_t* vcd;
+  int i, min = 0, sec = 0, frame = 0;
+  if (ioctl(fd, CDIOREADTOCHEADER, &tochdr) == -1) {
+    mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
+    return;
+  }
+  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", tochdr.starting_track);
+  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", tochdr.ending_track);
+  for (i = tochdr.starting_track; i <= tochdr.ending_track + 1; i++) {
+    struct ioc_read_toc_entry tocentry;
+    struct cd_toc_entry tocentry_data;
+
+    tocentry.starting_track = i<=tochdr.ending_track ? i : CDROM_LEADOUT;
+    tocentry.address_format = CD_MSF_FORMAT;
+    tocentry.data_len = sizeof(struct cd_toc_entry);
+    tocentry.data = &tocentry_data;
+
+    if (ioctl(fd, CDIOREADTOCENTRYS, &tocentry) == -1) {
+      mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
+      return NULL;
+    }
+    if (i <= tochdr.ending_track)
+    mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d:  adr=%d  ctrl=%d  format=%d  %02d:%02d:%02d\n",
+	   (int) tocentry.starting_track,
+	   (int) tocentry.data->addr_type,
+	   (int) tocentry.data->control,
+	   (int) tocentry.address_format,
+	   (int) tocentry.data->addr.msf.minute,
+	   (int) tocentry.data->addr.msf.second,
+	   (int) tocentry.data->addr.msf.frame
+      );
+
+    if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
+    {
+      if (i > tochdr.starting_track)
+      {
+        min = tocentry.data->addr.msf.minute - min;
+        sec = tocentry.data->addr.msf.second - sec;
+        frame = tocentry.data->addr.msf.frame - frame;
+        if ( frame < 0 )
+        {
+          frame += 75;
+          sec --;
+        }
+        if ( sec < 0 )
+        {
+          sec += 60;
+          min --;
+        }
+        mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
+      }
+      min = tocentry.data->addr.msf.minute;
+      sec = tocentry.data->addr.msf.second;
+      frame = tocentry.data->addr.msf.frame;
+    }
+  }
+  vcd = malloc(sizeof(mp_vcd_priv_t));
+  vcd->fd = fd;
+  return vcd;
+}
+
+static int 
+vcd_read(mp_vcd_priv_t* vcd, char *mem)
+{
+  struct scsireq  sc;
+  int             lba = vcd_get_msf(vcd);
+  int             blocks;
+  int             sector_type;
+  int             sync, header_code, user_data, edc_ecc, error_field;
+  int             sub_channel;
+  int             rc;
+
+  blocks = 1;
+  sector_type = 5;		/* mode2/form2 */
+  sync = 0;
+  header_code = 0;
+  user_data = 1;
+  edc_ecc = 0;
+  error_field = 0;
+  sub_channel = 0;
+
+  memset(&sc, 0, sizeof(sc));
+  sc.cmd[0] = 0xBE;
+  sc.cmd[1] = (sector_type) << 2;
+  sc.cmd[2] = (lba >> 24) & 0xff;
+  sc.cmd[3] = (lba >> 16) & 0xff;
+  sc.cmd[4] = (lba >> 8) & 0xff;
+  sc.cmd[5] = lba & 0xff;
+  sc.cmd[6] = (blocks >> 16) & 0xff;
+  sc.cmd[7] = (blocks >> 8) & 0xff;
+  sc.cmd[8] = blocks & 0xff;
+  sc.cmd[9] = (sync << 7) | (header_code << 5) | (user_data << 4) |
+    (edc_ecc << 3) | (error_field << 1);
+  sc.cmd[10] = sub_channel;
+  sc.cmdlen = 12;
+  sc.databuf = (caddr_t) mem;
+  sc.datalen = 2328;
+  sc.senselen = sizeof(sc.sense);
+  sc.flags = SCCMD_READ;
+  sc.timeout = 10000;
+  rc = ioctl(vcd->fd, SCIOCCOMMAND, &sc);
+  if (rc == -1) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"SCIOCCOMMAND: %s\n",strerror(errno));
+    return -1;
+  }
+  if (sc.retsts || sc.error) {
+    mp_msg(MSGT_STREAM,MSGL_ERR,"scsi command failed: status %d error %d\n",
+	   sc.retsts,sc.error);
+    return -1;
+  }
+  vcd_inc_msf(vcd);
+  return VCD_SECTOR_DATA;
+}
+
--- a/subreader.c	Mon Jul 31 12:35:04 2006 +0000
+++ b/subreader.c	Mon Jul 31 17:39:17 2006 +0000
@@ -18,7 +18,7 @@
 #include "config.h"
 #include "mp_msg.h"
 #include "subreader.h"
-#include "libmpdemux/stream.h"
+#include "stream/stream.h"
 
 #ifdef HAVE_ENCA
 #include <enca.h>