diff --git a/packages/mediacenter/xbmc-rpi/build b/packages/mediacenter/xbmc-rpi/build
new file mode 100755
index 0000000000..bcdf26a9dd
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/build
@@ -0,0 +1,290 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+. config/options $1
+
+if [ "$XORG_SUPPORT" = yes ]; then
+ XBMC_XORG="--enable-x11 --enable-xrandr"
+else
+ XBMC_XORG="--disable-x11 --disable-xrandr"
+fi
+
+if [ "$OPENGL_SUPPORT" = yes ]; then
+ XBMC_OPENGL="--enable-gl"
+else
+ XBMC_OPENGL="--disable-gl"
+fi
+
+if [ "$OPENGLES_SUPPORT" = yes ]; then
+ XBMC_OPENGLES="--enable-gles"
+else
+ XBMC_OPENGLES="--disable-gles"
+fi
+
+if [ "$SDL_SUPPORT" = yes ]; then
+ XBMC_SDL="--enable-sdl"
+else
+ XBMC_SDL="--disable-sdl"
+fi
+
+if [ "$XBMC_SCR_RSXS" = yes ]; then
+ XBMC_RSXS="--enable-rsxs"
+ # fix build of RSXS Screensaver support if not using libiconv
+ if [ ! "$ICONV" = "libiconv" ]; then
+ export jm_cv_func_gettimeofday_clobber=no
+ fi
+else
+ XBMC_RSXS="--disable-rsxs"
+fi
+
+if [ "$XBMC_VIS_PROJECTM" = yes ]; then
+ XBMC_PROJECTM="--enable-projectm"
+else
+ XBMC_PROJECTM="--disable-projectm"
+fi
+
+if [ "$XBMC_VIS_GOOM" = yes ]; then
+ XBMC_GOOM="--enable-goom"
+else
+ XBMC_GOOM="--disable-goom"
+fi
+
+if [ "$PULSEAUDIO_SUPPORT" = yes ]; then
+ XBMC_PULSEAUDIO="--enable-pulse"
+else
+ XBMC_PULSEAUDIO="--disable-pulse"
+fi
+
+if [ "$CEC_SUPPORT" = yes ]; then
+ XBMC_CEC="--enable-libcec --enable-external-libcec --enable-udev --disable-libusb"
+else
+ XBMC_CEC="--disable-libcec --disable-udev --disable-libusb"
+fi
+
+if [ "$JOYSTICK_SUPPORT" = yes ]; then
+ XBMC_JOYSTICK="--enable-joystick"
+else
+ XBMC_JOYSTICK="--disable-joystick"
+fi
+
+if [ "$NONFREE_SUPPORT" = yes ]; then
+ XBMC_NONFREE="--enable-non-free"
+else
+ XBMC_NONFREE="--disable-non-free"
+fi
+
+if [ "$AIRPLAY_SUPPORT" = yes ]; then
+ XBMC_AIRPLAY="--enable-airplay"
+else
+ XBMC_AIRPLAY="--disable-airplay"
+fi
+
+if [ "$AIRTUNES_SUPPORT" = yes ]; then
+ XBMC_AIRTUNES="--enable-airtunes"
+else
+ XBMC_AIRTUNES="--disable-airtunes"
+fi
+
+if [ "$DVDCSS_SUPPORT" = yes ]; then
+ XBMC_DVDCSS="--enable-dvdcss"
+else
+ XBMC_DVDCSS="--disable-dvdcss"
+fi
+
+if [ "$BLURAY_SUPPORT" = yes ]; then
+ XBMC_BLURAY="--enable-libbluray"
+else
+ XBMC_BLURAY="--disable-libbluray"
+fi
+
+if [ "$AVAHI_DAEMON" = yes ]; then
+ XBMC_AVAHI="--enable-avahi"
+else
+ XBMC_AVAHI="--disable-avahi"
+fi
+
+if [ "$NFS_SUPPORT" = yes ]; then
+ XBMC_NFS="--enable-nfs"
+else
+ XBMC_NFS="--disable-nfs"
+fi
+
+if [ "$AFP_SUPPORT" = yes ]; then
+ XBMC_AFP="--enable-afpclient"
+else
+ XBMC_AFP="--disable-afpclient"
+fi
+
+if [ "$SAMBA_CLIENT" = yes ]; then
+ XBMC_SAMBA="--enable-samba"
+else
+ XBMC_SAMBA="--disable-samba"
+fi
+
+if [ "$WEBSERVER" = yes ]; then
+ XBMC_WEBSERVER="--enable-webserver"
+else
+ XBMC_WEBSERVER="--disable-webserver"
+fi
+
+if [ "$OPENMAX_SUPPORT" = yes ]; then
+ XBMC_OPENMAX="--enable-openmax"
+ if [ "$OPENMAX" = "bcm2835-driver" ]; then
+ PLATFORM_SUPPORT_RPI="yes"
+ fi
+else
+ XBMC_OPENMAX="--disable-openmax"
+fi
+
+if [ "$VDPAU" = yes ]; then
+ XBMC_VDPAU="--enable-vdpau"
+else
+ XBMC_VDPAU="--disable-vdpau"
+fi
+
+if [ "$VAAPI" = yes ]; then
+ XBMC_VAAPI="--enable-vaapi"
+else
+ XBMC_VAAPI="--disable-vaapi"
+fi
+
+if [ "$XVBA" = yes ]; then
+ XBMC_XVBA="--enable-xvba"
+else
+ XBMC_XVBA="--disable-xvba"
+fi
+
+if [ "$CRYSTALHD" = yes ]; then
+ XBMC_CRYSTALHD="--enable-crystalhd"
+else
+ XBMC_CRYSTALHD="--disable-crystalhd"
+fi
+
+if [ "$PLATFORM_SUPPORT_RPI" = "yes" ]; then
+ XBMC_PLATFORM_RPI="--enable-platform-raspberry-pi"
+else
+ XBMC_PLATFORM_RPI="--disable-platform-raspberry-pi"
+fi
+
+# dont build parallel
+ MAKEFLAGS=-j1
+
+# xbmc (ffmpeg) fails to build with LTO optimization
+ strip_lto
+ strip_gold
+
+# dont use some optimizations because of problems
+# this fixes problems with faac implementation of ffmpeg
+ LDFLAGS=`echo $LDFLAGS | sed -e "s|-Wl,--as-needed||"`
+
+ export PYTHON_VERSION="2.7"
+ export PYTHON_CPPFLAGS="-I$SYSROOT_PREFIX/usr/include/python$PYTHON_VERSION"
+ export PYTHON_LDFLAGS="-L$SYSROOT_PREFIX/usr/lib/python$PYTHON_VERSION -lpython$PYTHON_VERSION"
+ export PYTHON_SITE_PKG="$SYSROOT_PREFIX/usr/lib/python$PYTHON_VERSION/site-packages"
+ export ac_python_version="$PYTHON_VERSION"
+
+# setup skin dir from default skin
+ SKIN_DIR="skin.`tolower $SKIN_DEFAULT`"
+
+cd $PKG_BUILD
+
+# adding fake Makefile for stripped skin
+ mkdir -p addons/skin.confluence/media
+ touch addons/skin.confluence/media/Makefile.in
+
+# autoreconf
+ do_autoreconf
+ do_autoreconf lib/libid3tag/libid3tag
+ do_autoreconf xbmc/screensavers/rsxs-0.9
+ do_autoreconf xbmc/visualizations/Goom/goom2k4-0
+ do_autoreconf lib/libapetag
+ do_autoreconf lib/cpluff
+ # order matters with libdvd and friends
+ [ -d lib/libdvd/libdvdcss ] && do_autoreconf lib/libdvd/libdvdcss
+ do_autoreconf lib/libdvd/libdvdread
+ do_autoreconf lib/libdvd/libdvdnav
+
+# Clean the generated files
+ find . -depth -type d -name "autom4te.cache" -exec rm -rf {} \;
+
+./configure --host=$TARGET_NAME \
+ --build=$HOST_NAME \
+ --with-arch=$TARGET_ARCH \
+ --with-cpu=$TARGET_CPU \
+ --prefix=/usr \
+ --exec-prefix=/usr \
+ --sysconfdir=/etc \
+ --datadir=/usr/share \
+ GIT_REV=`cat git.version` \
+ --disable-debug \
+ --disable-optimizations \
+ $XBMC_OPENGL \
+ $XBMC_OPENGLES \
+ $XBMC_SDL \
+ $XBMC_OPENMAX \
+ $XBMC_VDPAU \
+ $XBMC_VAAPI \
+ $XBMC_CRYSTALHD \
+ $XBMC_XVBA \
+ --disable-vdadecoder \
+ --disable-vtbdecoder \
+ --disable-tegra \
+ --disable-profiling \
+ $XBMC_JOYSTICK \
+ $XBMC_CEC \
+ $XBMC_GOOM \
+ $XBMC_RSXS \
+ $XBMC_PROJECTM \
+ $XBMC_XORG \
+ --disable-ccache \
+ $XBMC_PULSEAUDIO \
+ --enable-rtmp \
+ $XBMC_SAMBA \
+ $XBMC_NFS \
+ $XBMC_AFP \
+ --enable-ffmpeg-libvorbis \
+ --enable-lame \
+ $XBMC_DVDCSS \
+ --disable-mid \
+ --disable-hal \
+ $XBMC_AVAHI \
+ $XBMC_AIRPLAY \
+ $XBMC_AIRTUNES \
+ $XBMC_NONFREE \
+ --disable-asap-codec \
+ $XBMC_WEBSERVER \
+ --enable-optical-drive \
+ $XBMC_BLURAY \
+ --enable-texturepacker \
+ --disable-external-libraries \
+ --disable-external-ffmpeg \
+ $XBMC_PLATFORM_RPI \
+
+# setup default skin inside the sources
+ sed -i -e "s|skin.confluence|$SKIN_DIR|g" xbmc/settings/Settings.h
+
+make externals
+make xbmc.bin
+
+if [ "$XORG_SUPPORT" = yes ]; then
+ make xbmc-xrandr
+fi
diff --git a/packages/mediacenter/xbmc-rpi/config/advancedsettings.xml b/packages/mediacenter/xbmc-rpi/config/advancedsettings.xml
new file mode 100644
index 0000000000..c6f22f0a3a
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/config/advancedsettings.xml
@@ -0,0 +1,10 @@
+
+
+ false
+ false
+ cputemp
+ gputemp
+
+ 30
+
+
diff --git a/packages/mediacenter/xbmc-rpi/config/os.openelec.tv/addon.xml b/packages/mediacenter/xbmc-rpi/config/os.openelec.tv/addon.xml
new file mode 100644
index 0000000000..f786fbfc1d
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/config/os.openelec.tv/addon.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/packages/mediacenter/xbmc-rpi/config/repository.openelec.tv/addon.xml b/packages/mediacenter/xbmc-rpi/config/repository.openelec.tv/addon.xml
new file mode 100644
index 0000000000..7ebb2ad74b
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/config/repository.openelec.tv/addon.xml
@@ -0,0 +1,17 @@
+
+
+
+ @ADDON_URL@/addons.xml
+ @ADDON_URL@/addons.xml.md5
+ @ADDON_URL@
+
+
+ Install Add-ons, Plugins, Games and Programs from OpenELEC.tv
+ Download and install Add-ons, Plugins, Games and Programs from the Official OpenELEC.tv addon repository.[CR] By using the official Repository you will be able to take advantage of our extensive file mirror service to help get you faster downloads from a region close to you.[CR] All addons on this repository have under gone basic testing, if you find a broken or not working addon please report it to OpenELEC.tv so we can take any action needed.
+ all
+
+
diff --git a/packages/mediacenter/xbmc-rpi/fonts/DejaVuSans.ttf b/packages/mediacenter/xbmc-rpi/fonts/DejaVuSans.ttf
new file mode 100644
index 0000000000..84ca1d7503
Binary files /dev/null and b/packages/mediacenter/xbmc-rpi/fonts/DejaVuSans.ttf differ
diff --git a/packages/mediacenter/xbmc-rpi/fonts/Trebuchet MS Bold.ttf b/packages/mediacenter/xbmc-rpi/fonts/Trebuchet MS Bold.ttf
new file mode 100644
index 0000000000..867f56d776
Binary files /dev/null and b/packages/mediacenter/xbmc-rpi/fonts/Trebuchet MS Bold.ttf differ
diff --git a/packages/mediacenter/xbmc-rpi/fonts/YanoneKaffeesatz-Bold.ttf b/packages/mediacenter/xbmc-rpi/fonts/YanoneKaffeesatz-Bold.ttf
new file mode 100644
index 0000000000..e9964b0809
Binary files /dev/null and b/packages/mediacenter/xbmc-rpi/fonts/YanoneKaffeesatz-Bold.ttf differ
diff --git a/packages/mediacenter/xbmc-rpi/init.d/92_setup-xbmc b/packages/mediacenter/xbmc-rpi/init.d/92_setup-xbmc
new file mode 100644
index 0000000000..d241a5f2cc
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/init.d/92_setup-xbmc
@@ -0,0 +1,123 @@
+################################################################################
+# Copyright (C) 2009-2010 OpenELEC.tv
+# http://www.openelec.tv
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+# setup XBMC
+#
+# runlevels: openelec
+
+progress "setup XBMC"
+
+#
+# clean temp dir
+#
+ rm -rf $HOME/.xbmc/temp/*
+
+#
+# add some default settings
+#
+ mkdir -p $HOME/.xbmc/userdata
+
+#
+# setup directories for XBMC sources
+#
+
+ [ ! -d "$HOME/music" ] && mkdir -p $HOME/music
+ [ ! -d "$HOME/pictures" ] && mkdir -p $HOME/pictures
+ [ ! -d "$HOME/tvshows" ] && mkdir -p $HOME/tvshows
+ [ ! -d "$HOME/videos" ] && mkdir -p $HOME/videos
+
+ mkdir -p $HOME/.xbmc/userdata
+
+ if [ ! -f $HOME/.xbmc/userdata/sources.xml ]; then
+ if [ -f /usr/share/xbmc/config/sources.xml ]; then
+ # include project specific sources
+ cp /usr/share/xbmc/config/sources.xml $HOME/.xbmc/userdata
+ else
+ cat > $HOME/.xbmc/userdata/sources.xml << EOF
+
+
+
+
+
+ Music
+ $HOME/music/
+
+
+
+
+
+ Pictures
+ $HOME/pictures/
+
+
+
+EOF
+ fi
+ fi
+
+#
+# common setup guisettings
+#
+
+ mkdir -p $HOME/.xbmc/userdata
+
+ [ ! -d "$HOME/screenshots" ] && mkdir -p $HOME/screenshots
+
+ if [ ! -f $HOME/.xbmc/userdata/guisettings.xml ] ; then
+ echo "" > $HOME/.xbmc/userdata/guisettings.xml
+
+ cat >> $HOME/.xbmc/userdata/guisettings.xml << EOF
+
+ $HOME/screenshots/
+
+EOF
+
+ #
+ # include project specific options
+ #
+
+ if [ -f /usr/share/xbmc/config/guisettings.xml ]; then
+ cat /usr/share/xbmc/config/guisettings.xml >> $HOME/.xbmc/userdata/guisettings.xml
+ fi
+
+ #
+ # common setup for amd and nvidia graphic
+ #
+
+ # Always sync to vblank
+ if [ "$GPUTYPE" = "NVIDIA" -o "$GPUTYPE" = "AMD" ] ; then
+ cat >> $HOME/.xbmc/userdata/guisettings.xml << EOF
+
+ 2
+
+EOF
+ fi
+ echo "" >> $HOME/.xbmc/userdata/guisettings.xml
+ fi
diff --git a/packages/mediacenter/xbmc-rpi/init.d/93_xbmc b/packages/mediacenter/xbmc-rpi/init.d/93_xbmc
new file mode 100644
index 0000000000..b8af6b2b3a
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/init.d/93_xbmc
@@ -0,0 +1,101 @@
+################################################################################
+# Copyright (C) 2009-2010 OpenELEC.tv
+# http://www.openelec.tv
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+# starting XBMC
+#
+# runlevels: openelec
+
+LIRCDEV="/var/run/lirc/lircd"
+[ -e /var/run/lirc/lircd.irtrans ] && LIRCDEV="/var/run/lirc/lircd.irtrans"
+XBMC_ARGS="--standalone -fs --lircdev $LIRCDEV"
+
+progress "starting XBMC"
+
+# hack for Boxee Remote
+if grep -q "Vendor=0471 Product=20d9" /proc/bus/input/devices; then
+ export SDL_MOUSE_RELATIVE=0
+fi
+
+# hack: make addon-bins executable
+ chmod +x /storage/.xbmc/addons/*/bin/* > /dev/null 2>&1
+
+# hack: make addon-libs executable
+ chmod +x /storage/.xbmc/addons/*/lib/* > /dev/null 2>&1
+
+# hack to support user installed fonts
+ SUBFONTS="/storage/.xbmc/userdata/fonts"
+ if [ -d "$SUBFONTS" ]; then
+ files=$(ls $SUBFONTS/*.[tT][tT][fF] 2>/dev/null | wc -l)
+ if [ "$files" = "0" ]; then
+ cp /usr/share/xbmc/media/Fonts/*.[tT][tT][fF] $SUBFONTS/
+ fi
+ mount --bind $SUBFONTS /usr/share/xbmc/media/Fonts/
+ fi
+
+# starting autostart script (will be removed later again, dont use it!!!)
+ AUTOSTART="/storage/.config/autostart.sh"
+ if [ -f $AUTOSTART ]; then
+ echo "!!! AUTOSTART script detected !!!" >> /var/log/messages
+ cat "$AUTOSTART" >> /var/log/messages
+ echo "!!! -End of autostart script- !!!" >> /var/log/messages
+
+ sh $AUTOSTART
+ fi
+
+# starting autoupdate
+ [ -f /usr/bin/autoupdate ] && /usr/bin/autoupdate &
+
+# waiting for Xorg to start
+ wait_for_xorg
+
+# set cpu's to 'on demand'
+ ( usleep 15000000
+ progress "set cpu's to 'on demand'"
+ cpupower frequency-set -g ondemand > /dev/null 2>&1
+ )&
+
+# starting XBMC
+ usleep $XBMC_STARTDELAY
+ while true; do
+
+ DISPLAY=:0.0 /usr/lib/xbmc/xbmc.bin $XBMC_ARGS > /dev/null 2>&1
+ RET=$?
+
+ case "$RET" in
+ 0)
+ poweroff -f
+ ;;
+ 64)
+ poweroff -f
+ ;;
+ 66)
+ reboot
+ ;;
+ 255)
+ echo "Abnormal Exit. Exited with code $RET"
+ echo "is Xorg running? check /var/log/Xorg.log"
+ ;;
+ *)
+ echo "Abnormal Exit. Exited with code $RET"
+ ;;
+ esac
+
+ usleep 250000
+ done
diff --git a/packages/mediacenter/xbmc-rpi/install b/packages/mediacenter/xbmc-rpi/install
new file mode 100755
index 0000000000..731dc18ce2
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/install
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+. config/options $1
+
+PYTHON_LIBDIR="`ls -d $INSTALL/usr/lib/python*`"
+
+mkdir -p $INSTALL/usr/bin
+ cp $PKG_DIR/scripts/cputemp $INSTALL/usr/bin
+ cp $PKG_DIR/scripts/gputemp $INSTALL/usr/bin
+ cp $PKG_BUILD/tools/EventClients/Clients/XBMC\ Send/xbmc-send.py $INSTALL/usr/bin/xbmc-send
+
+mkdir -p $INSTALL/usr/lib/xbmc
+ cp $PKG_BUILD/xbmc.bin $INSTALL/usr/lib/xbmc
+ if [ "$XORG_SUPPORT" = yes ]; then
+ cp $PKG_BUILD/xbmc-xrandr $INSTALL/usr/lib/xbmc
+ fi
+
+cd $PKG_BUILD
+ find system addons \
+ -regextype posix-extended -type f \
+ -not -iregex ".*svn.*|.*win32(dx)?\.vis|.*osx\.vis" \
+ -iregex ".*-linux.*|.*\.vis|.*\.xbs" \
+ -exec install -D "{}" $ROOT/$INSTALL/usr/lib/xbmc/"{}" ";"
+
+ find addons language media sounds userdata system \
+ -regextype posix-extended -type f \
+ -not -iregex ".*-linux.*|.*\.vis|.*\.xbs|.*svn.*|.*\.orig|.*\.so|.*\.dll|.*\.pyd|.*python/.*\.zlib" \
+ -exec install -D -m 0644 "{}" $ROOT/$INSTALL/usr/share/xbmc/"{}" ";"
+cd -
+
+if [ ! "$XBMC_SCR_RSXS" = yes ]; then
+ rm -rf $ROOT/$INSTALL/usr/share/xbmc/addons/screensaver.rsxs.*
+fi
+
+if [ ! "$XBMC_VIS_PROJECTM" = yes ]; then
+ rm -rf $ROOT/$INSTALL/usr/share/xbmc/addons/visualization.projectm
+fi
+
+rm -rf $ROOT/$INSTALL/usr/share/xbmc/addons/visualization.dxspectrum
+rm -rf $ROOT/$INSTALL/usr/share/xbmc/addons/visualization.itunes
+rm -rf $ROOT/$INSTALL/usr/share/xbmc/addons/visualization.milkdrop
+
+# overriding Splash image
+mkdir -p $INSTALL/usr/share/xbmc/media
+ rm -rf $INSTALL/usr/share/xbmc/media/Splash.png
+# if [ -f $PROJECT_DIR/$PROJECT/splash/splash.png ]; then
+# cp $PROJECT_DIR/$PROJECT/splash/splash.png $INSTALL/usr/share/xbmc/media/Splash.png
+# else
+# cp $PKG_DIR/splash/splash.png $INSTALL/usr/share/xbmc/media/Splash.png
+# fi
+
+# cleanup and python addon fixes
+ mkdir -p $INSTALL/usr/share/xbmc/addons/script.module.pil/lib
+ ln -s `ls -d $INSTALL/usr/lib/python*/site-packages | sed -e "s,$INSTALL,,"`/PIL \
+ $INSTALL/usr/share/xbmc/addons/script.module.pil/lib/PIL
+ rm -rf $INSTALL/usr/share/xbmc/addons/script.module.pysqlite
+
+mkdir -p $INSTALL/usr/share/xbmc/addons
+ cp -R $PKG_DIR/config/os.openelec.tv $INSTALL/usr/share/xbmc/addons
+ $SED "s|@ADDON_OS_VERSION@|$OS_VERSION|g" -i $INSTALL/usr/share/xbmc/addons/os.openelec.tv/addon.xml
+ cp -R $PKG_DIR/config/repository.openelec.tv $INSTALL/usr/share/xbmc/addons
+ $SED "s|@ADDON_URL@|$ADDON_URL|g" -i $INSTALL/usr/share/xbmc/addons/repository.openelec.tv/addon.xml
+
+mkdir -p $PYTHON_LIBDIR/site-packages/xbmc
+ cp -R $PKG_BUILD/tools/EventClients/lib/python/* $PYTHON_LIBDIR/site-packages/xbmc
+
+# install powermanagement hooks
+ mkdir -p $INSTALL/etc/pm/sleep.d
+ cp $PKG_DIR/sleep.d/* $INSTALL/etc/pm/sleep.d
+
+# install project specific configs
+ mkdir -p $INSTALL/usr/share/xbmc/config
+ if [ -f $PROJECT_DIR/$PROJECT/xbmc/guisettings.xml ]; then
+ cp -R $PROJECT_DIR/$PROJECT/xbmc/guisettings.xml $INSTALL/usr/share/xbmc/config
+ fi
+
+ if [ -f $PROJECT_DIR/$PROJECT/xbmc/sources.xml ]; then
+ cp -R $PROJECT_DIR/$PROJECT/xbmc/sources.xml $INSTALL/usr/share/xbmc/config
+ fi
+
+ mkdir -p $INSTALL/usr/share/xbmc/system/
+ if [ -f $PROJECT_DIR/$PROJECT/xbmc/advancedsettings.xml ]; then
+ cp $PROJECT_DIR/$PROJECT/xbmc/advancedsettings.xml $INSTALL/usr/share/xbmc/system/
+ else
+ cp $PKG_DIR/config/advancedsettings.xml $INSTALL/usr/share/xbmc/system/
+ fi
+
+if [ "$XBMC_EXTRA_FONTS" = yes ]; then
+ mkdir -p $INSTALL/usr/share/xbmc/media/Fonts
+ cp $PKG_DIR/fonts/*.ttf $INSTALL/usr/share/xbmc/media/Fonts
+fi
diff --git a/packages/mediacenter/xbmc-rpi/meta b/packages/mediacenter/xbmc-rpi/meta
new file mode 100644
index 0000000000..bdadb7a8c7
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/meta
@@ -0,0 +1,156 @@
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+PKG_NAME="xbmc-rpi"
+PKG_VERSION="cc57efc"
+PKG_REV="1"
+PKG_ARCH="any"
+PKG_LICENSE="GPL"
+PKG_SITE="http://www.xbmc.org"
+PKG_URL="http://sraue.openelec.tv/$PKG_NAME-$PKG_VERSION.tar.xz"
+PKG_DEPENDS="boost Python zlib bzip2 lzo pcre libass enca curl libssh rtmpdump fontconfig fribidi libjpeg-turbo libpng tiff freetype jasper libmad libsamplerate libogg libvorbis libcdio libmodplug faad2 flac lame libmpeg2 yajl sqlite mysql bc xbmc-addon-settings"
+PKG_BUILD_DEPENDS="toolchain boost Python zlib bzip2 lzo pcre libass enca curl libssh rtmpdump fontconfig fribidi libjpeg-turbo libpng tiff freetype jasper libmad libsamplerate libogg libvorbis libcdio libmodplug faad2 flac lame libmpeg2 yajl sqlite mysql"
+PKG_PRIORITY="optional"
+PKG_SECTION="mediacenter"
+PKG_SHORTDESC="xbmc: XBMC Mediacenter"
+PKG_LONGDESC="XBMC Media Center (which was formerly named Xbox Media Center) is a free and open source cross-platform media player and home entertainment system software with a 10-foot user interface designed for the living-room TV. Its graphical user interface allows the user to easily manage video, photos, podcasts, and music from a computer, optical disk, local network, and the internet using a remote control."
+PKG_IS_ADDON="no"
+
+PKG_AUTORECONF="no"
+
+if [ "$XORG_SUPPORT" = yes ]; then
+ # for libX11 support
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libX11 libXext"
+ PKG_DEPENDS="$PKG_DEPENDS libX11 libXext"
+
+ # for libXrandr support
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libXrandr"
+ PKG_DEPENDS="$PKG_DEPENDS libXrandr"
+
+ # for SDL support
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS SDL SDL_mixer SDL_image"
+ PKG_DEPENDS="$PKG_DEPENDS SDL SDL_mixer SDL_image"
+fi
+
+if [ "$OPENGL_SUPPORT" = yes ]; then
+ # for OpenGL (GLX) support
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS $OPENGL glew"
+ PKG_DEPENDS="$PKG_DEPENDS $OPENGL glew"
+fi
+
+if [ "$OPENGLES_SUPPORT" = yes ]; then
+ # for OpenGL-ES support
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS $OPENGLES"
+ PKG_DEPENDS="$PKG_DEPENDS $OPENGLES"
+fi
+
+# for dbus support
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS dbus"
+ PKG_DEPENDS="$PKG_DEPENDS dbus"
+
+if [ "$ALSA_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS alsa-lib"
+ PKG_DEPENDS="$PKG_DEPENDS alsa alsa-lib"
+fi
+
+if [ "$PULSEAUDIO_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS pulseaudio"
+ PKG_DEPENDS="$PKG_DEPENDS pulseaudio"
+fi
+
+if [ "$CEC_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libcec"
+ PKG_DEPENDS="$PKG_DEPENDS libcec"
+fi
+
+if [ "$XBMC_SCR_RSXS" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libXt libXmu"
+ PKG_DEPENDS="$PKG_DEPENDS libXt libXmu"
+fi
+
+if [ "$FAAC_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS faac"
+ PKG_DEPENDS="$PKG_DEPENDS faac"
+fi
+
+if [ "$BLURAY_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libbluray"
+ PKG_DEPENDS="$PKG_DEPENDS libbluray"
+fi
+
+if [ "$AVAHI_DAEMON" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS avahi"
+ PKG_DEPENDS="$PKG_DEPENDS avahi"
+fi
+
+if [ "$AIRPLAY_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libplist"
+ PKG_DEPENDS="$PKG_DEPENDS libplist"
+fi
+
+if [ "$AIRTUNES_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libshairport"
+ PKG_DEPENDS="$PKG_DEPENDS libshairport"
+fi
+
+if [ "$NFS_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libnfs"
+ PKG_DEPENDS="$PKG_DEPENDS libnfs"
+fi
+
+if [ "$AFP_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS afpfs-ng"
+ PKG_DEPENDS="$PKG_DEPENDS afpfs-ng"
+fi
+
+if [ "$SAMBA_CLIENT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS samba"
+ PKG_DEPENDS="$PKG_DEPENDS samba"
+fi
+
+if [ "$WEBSERVER" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libmicrohttpd"
+ PKG_DEPENDS="$PKG_DEPENDS libmicrohttpd"
+fi
+
+if [ "$OPENMAX_SUPPORT" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS $OPENMAX"
+ PKG_DEPENDS="$PKG_DEPENDS $OPENMAX"
+fi
+
+if [ "$VDPAU" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libvdpau"
+ PKG_DEPENDS="$PKG_DEPENDS libvdpau"
+fi
+
+if [ "$VAAPI" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS libva"
+ PKG_DEPENDS="$PKG_DEPENDS libva"
+fi
+
+if [ "$CRYSTALHD" = yes ]; then
+ PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS crystalhd"
+ PKG_DEPENDS="$PKG_DEPENDS crystalhd"
+fi
+
+# some python stuff needed for various addons
+ PKG_DEPENDS="$PKG_DEPENDS Imaging"
+ PKG_DEPENDS="$PKG_DEPENDS simplejson"
+
diff --git a/packages/mediacenter/xbmc-rpi/patches/rename.sh b/packages/mediacenter/xbmc-rpi/patches/rename.sh
new file mode 100755
index 0000000000..64715435df
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/rename.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+
+for i in `ls xbmc-*.patch`; do
+ mv $i `echo $i | sed "s,$1,$2,g"`
+done
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-001-add_support_to_specify_GIT_REV-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-001-add_support_to_specify_GIT_REV-0.1.patch
new file mode 100644
index 0000000000..c013e0ae3a
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-001-add_support_to_specify_GIT_REV-0.1.patch
@@ -0,0 +1,39 @@
+diff -Naur xbmc-9389dc8/configure.in xbmc-9389dc8.patch/configure.in
+--- xbmc-9389dc8/configure.in 2011-09-01 17:21:47.000000000 +0200
++++ xbmc-9389dc8.patch/configure.in 2011-09-01 23:30:40.419399392 +0200
+@@ -428,6 +428,14 @@
+ esac
+ AC_SUBST([ARCH])
+
++AC_CHECK_PROG(HAVE_GIT,git,"yes","no",)
++if test "$HAVE_GIT" = "yes" -a "$GIT_REV" = ""; then
++ GIT_REV=$(git --no-pager log --abbrev=7 -n 1 --pretty=format:"%h %ci" HEAD | awk '{gsub("-", "");print $2"-"$1}')
++elif test "$GIT_REV" = ""; then
++ GIT_REV="Unknown"
++fi
++final_message="$final_message\n git Rev.:\t${GIT_REV}"
++
+ # platform debug flags
+ if test "$use_debug" = "yes"; then
+ final_message="$final_message\n Debugging:\tYes"
+@@ -1177,7 +1185,6 @@
+ fi
+ fi
+
+-AC_CHECK_PROG(HAVE_GIT,git,"yes","no",)
+
+ # Checks for header files.
+ AC_HEADER_DIRENT
+@@ -1408,12 +1415,6 @@
+ final_message="$final_message\n Avahi:\tNo"
+ fi
+
+-if test "$HAVE_GIT" = "yes"; then
+- GIT_REV=$(git --no-pager log --abbrev=7 -n 1 --pretty=format:"%h %ci" HEAD | awk '{gsub("-", "");print $2"-"$1}')
+-fi
+-if test "$GIT_REV" = ""; then
+- GIT_REV="Unknown"
+-fi
+ if test "$host_vendor" = "apple"; then
+ echo "#define GIT_REV \"$GIT_REV\"" > git_revision.h
+ else
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-303-fix_libdvd_xFLAGS-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-303-fix_libdvd_xFLAGS-0.1.patch
new file mode 100644
index 0000000000..5e76acefe4
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-303-fix_libdvd_xFLAGS-0.1.patch
@@ -0,0 +1,119 @@
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdcss/src/libdvdcss.pc.in xbmc-pvr-3513480.patch/lib/libdvd/libdvdcss/src/libdvdcss.pc.in
+--- xbmc-pvr-3513480/lib/libdvd/libdvdcss/src/libdvdcss.pc.in 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdcss/src/libdvdcss.pc.in 2011-04-25 05:01:20.091837122 +0200
+@@ -6,5 +6,5 @@
+ Name: libdvdcss
+ Description: DVD access and decryption library.
+ Version: @VERSION@
+-Libs: -L${libdir} -ldvdcss
+-Cflags: -I{includedir} -I${includedir}/@PACKAGE@
++Libs: -ldvdcss
++Cflags: -I.
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh
+--- xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh 2011-04-25 05:01:20.549828701 +0200
+@@ -56,17 +56,17 @@
+ fi
+
+ if test "$echo_cflags" = "yes"; then
+- echo -I$prefix/include $dvdread_cflags $extracflags $threadcflags
++ echo $dvdread_cflags $extracflags $threadcflags
+ fi
+
+ if test "$echo_minicflags" = "yes"; then
+- echo -I$prefix/include -I$prefix/include/dvdnav $extracflags $threadcflags
++ echo $extracflags $threadcflags
+ fi
+
+ if test "$echo_libs" = "yes"; then
+- echo -L$libdir -ldvdnav $dvdread_libs $threadlib
++ echo -ldvdnav $dvdread_libs $threadlib
+ fi
+
+ if test "$echo_minilibs" = "yes"; then
+- echo -L$libdir -ldvdnavmini $threadlib
++ echo -ldvdnavmini $threadlib
+ fi
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnav-config.in xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnav-config.in
+--- xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnav-config.in 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnav-config.in 2011-04-25 05:01:20.624827321 +0200
+@@ -76,13 +76,13 @@
+ fi
+
+ if test "$echo_cflags" = "yes"; then
+- echo -I@includedir@ -I@includedir@/libdvdread @THREAD_CFLAGS@
++ echo @THREAD_CFLAGS@
+ fi
+
+ if test "$echo_libs" = "yes"; then
+- echo -L@libdir@ -ldvdnav -ldvdread @THREAD_LIBS@
++ echo -ldvdnav -ldvdread @THREAD_LIBS@
+ fi
+
+ if test "$echo_minilibs" = "yes"; then
+- echo -L@libdir@ -ldvdnavmini @THREAD_LIBS@
++ echo -ldvdnavmini @THREAD_LIBS@
+ fi
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in
+--- xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in 2011-04-25 05:01:21.042819641 +0200
+@@ -7,5 +7,5 @@
+ Description: DVD Navigation mini library
+ Version: @VERSION@
+
+-Cflags: -I${includedir} @DVDREAD_CFLAGS@ @THREAD_CFLAGS@
+-Libs: -L${libdir} -ldvdnav @THREAD_LIBS@
++Cflags: @DVDREAD_CFLAGS@ @THREAD_CFLAGS@
++Libs: -ldvdnav @THREAD_LIBS@
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnav.pc.in xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnav.pc.in
+--- xbmc-pvr-3513480/lib/libdvd/libdvdnav/misc/dvdnav.pc.in 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdnav/misc/dvdnav.pc.in 2011-04-25 05:01:21.262815601 +0200
+@@ -8,5 +8,5 @@
+ Version: @VERSION@
+
+ Requires.private: dvdread >= 4.1.2
+-Cflags: -I${includedir} @THREAD_CFLAGS@
+-Libs: -L${libdir} -ldvdnav @THREAD_LIBS@
++Cflags: @THREAD_CFLAGS@
++Libs: -ldvdnav @THREAD_LIBS@
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdread/misc/dvdread-config.in xbmc-pvr-3513480.patch/lib/libdvd/libdvdread/misc/dvdread-config.in
+--- xbmc-pvr-3513480/lib/libdvd/libdvdread/misc/dvdread-config.in 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdread/misc/dvdread-config.in 2011-04-25 05:01:21.278815307 +0200
+@@ -72,9 +72,9 @@
+ fi
+
+ if test "$echo_cflags" = "yes"; then
+- echo -I@includedir@
++ echo ""
+ fi
+
+ if test "$echo_libs" = "yes"; then
+- echo -L@libdir@ -ldvdread
++ echo -ldvdread
+ fi
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdread/misc/dvdread-config.sh xbmc-pvr-3513480.patch/lib/libdvd/libdvdread/misc/dvdread-config.sh
+--- xbmc-pvr-3513480/lib/libdvd/libdvdread/misc/dvdread-config.sh 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdread/misc/dvdread-config.sh 2011-04-25 05:01:21.278815307 +0200
+@@ -48,9 +48,9 @@
+ fi
+
+ if test "$echo_cflags" = "yes"; then
+- echo -I$prefix/include $extracflags
++ echo $extracflags
+ fi
+
+ if test "$echo_libs" = "yes"; then
+- echo -L$libdir $dvdreadlib
++ echo $dvdreadlib
+ fi
+diff -Naur xbmc-pvr-3513480/lib/libdvd/libdvdread/misc/dvdread.pc.in xbmc-pvr-3513480.patch/lib/libdvd/libdvdread/misc/dvdread.pc.in
+--- xbmc-pvr-3513480/lib/libdvd/libdvdread/misc/dvdread.pc.in 2011-04-25 02:36:42.000000000 +0200
++++ xbmc-pvr-3513480.patch/lib/libdvd/libdvdread/misc/dvdread.pc.in 2011-04-25 05:01:21.279815289 +0200
+@@ -7,5 +7,5 @@
+ Description: Low level DVD access library
+ Version: @VERSION@
+
+-Cflags: -I${includedir}
+-Libs: -L${libdir} -ldvdread
++Cflags: -I.
++Libs: -ldvdread
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-311-fix_rsxs_build-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-311-fix_rsxs_build-0.1.patch
new file mode 100644
index 0000000000..fe0ee49cab
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-311-fix_rsxs_build-0.1.patch
@@ -0,0 +1,12 @@
+diff -Naur xbmc-dab646e/xbmc/screensavers/rsxs-0.9/lib/argp-namefrob.h xbmc-dab646e.patch/xbmc/screensavers/rsxs-0.9/lib/argp-namefrob.h
+--- xbmc-dab646e/xbmc/screensavers/rsxs-0.9/lib/argp-namefrob.h 2011-09-27 15:56:19.000000000 +0200
++++ xbmc-dab646e.patch/xbmc/screensavers/rsxs-0.9/lib/argp-namefrob.h 2011-10-16 02:13:13.805433847 +0200
+@@ -17,7 +17,7 @@
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+-#if !_LIBC
++#if 0
+ /* This code is written for inclusion in gnu-libc, and uses names in the
+ namespace reserved for libc. If we're not compiling in libc, define those
+ names to be the normal ones instead. */
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-402-enable_yasm_in_ffmpeg-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-402-enable_yasm_in_ffmpeg-0.1.patch
new file mode 100644
index 0000000000..b8f5b8afcf
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-402-enable_yasm_in_ffmpeg-0.1.patch
@@ -0,0 +1,21 @@
+diff -Naur xbmc-pvr-3513480/configure.in xbmc-pvr-3513480.patch/configure.in
+--- xbmc-pvr-3513480/configure.in 2011-04-25 02:36:33.000000000 +0200
++++ xbmc-pvr-3513480.patch/configure.in 2011-04-25 05:14:49.220848143 +0200
+@@ -885,6 +885,9 @@
+ AC_MSG_NOTICE($external_ffmpeg_disabled)
+ USE_EXTERNAL_FFMPEG=0
+ AC_DEFINE([PIX_FMT_VDPAU_MPEG4_IN_AVUTIL], [1], [Whether AVUtil defines PIX_FMT_VDPAU_MPEG4.])
++
++ # check for yasm
++ AC_CHECK_PROG(HAVE_YASM,yasm,"yes","no",)
+ fi
+
+ # Python
+@@ -1547,6 +1550,7 @@
+ `if test "$use_arch" != "no"; then echo --arch=$use_arch; fi`\
+ `if test "$use_cpu" != "no"; then echo --cpu=$use_cpu; fi`\
+ --target-os=$(tolower $(uname -s)) \
++ `if test "$HAVE_YASM" = "yes"; then echo --enable-yasm; fi` \
+ --disable-muxers \
+ --enable-muxer=spdif \
+ --enable-muxer=adts \
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-404-add_lame_check-0.6.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-404-add_lame_check-0.6.patch
new file mode 100644
index 0000000000..a459219108
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-404-add_lame_check-0.6.patch
@@ -0,0 +1,125 @@
+diff -Naur xbmc-pvr-3513480/configure.in xbmc-pvr-3513480.patch/configure.in
+--- xbmc-pvr-3513480/configure.in 2011-04-25 05:46:35.000000000 +0200
++++ xbmc-pvr-3513480.patch/configure.in 2011-04-25 05:50:02.982401390 +0200
+@@ -72,6 +72,8 @@
+ rsxs_disabled="== RSXS disabled. =="
+ pulse_not_found="== Could not find libpulse. PulseAudio support disabled. =="
+ pulse_disabled="== PulseAudio support manually disabled. =="
++lame_not_found="== Could not find libmp3lame. LAME support disabled. =="
++lame_disabled="== LAME support manually disabled. =="
+ dvdcss_enabled="== DVDCSS support enabled. =="
+ dvdcss_disabled="== DVDCSS support disabled. =="
+ hal_not_found="== Could not find hal. HAL support disabled. =="
+@@ -244,6 +246,12 @@
+ [use_ffmpeg_libvorbis=$enableval],
+ [use_ffmpeg_libvorbis=no])
+
++AC_ARG_ENABLE([lame],
++ [AS_HELP_STRING([--enable-lame],
++ [enable lame support (default is yes)])],
++ [use_lame=$enableval],
++ [use_lame=yes])
++
+ AC_ARG_ENABLE([dvdcss],
+ [AS_HELP_STRING([--enable-dvdcss],
+ [enable DVDCSS support (default is yes)])],
+@@ -758,6 +766,20 @@
+ USE_PULSE=0
+ fi
+
++# LAME
++if test "$use_lame" = "yes"; then
++ AC_CHECK_LIB([mp3lame], [main],
++ AC_DEFINE([HAVE_LIBMP3LAME], [1], [Define to 1 if you have the 'libmp3lame' library (-lmp3lame).]),
++ use_lame=no;AC_MSG_RESULT($lame_not_found))
++else
++ AC_MSG_RESULT($lame_disabled)
++fi
++if test "$use_lame" = "yes"; then
++ AC_SUBST([HAVE_LIBMP3LAME], 1)
++else
++ AC_SUBST([HAVE_LIBMP3LAME], 0)
++fi
++
+ # HAL
+ if test "$host_vendor" = "apple" ; then
+ use_hal="no"
+@@ -1311,6 +1333,12 @@
+ final_message="$final_message\n HAL Support:\tNo"
+ fi
+
++if test "$use_lame" = "yes"; then
++ final_message="$final_message\n LAME:\t\tYes"
++else
++ final_message="$final_message\n LAME:\t\tNo"
++fi
++
+ # DVDCSS
+ if test "$use_dvdcss" = "yes"; then
+ AC_MSG_NOTICE($dvdcss_enabled)
+diff -Naur xbmc-pvr-3513480/configure.in.orig xbmc-pvr-3513480.patch/configure.in.orig
+diff -Naur xbmc-pvr-3513480/Makefile.in.orig xbmc-pvr-3513480.patch/Makefile.in.orig
+diff -Naur xbmc-pvr-3513480/xbmc/cdrip/CDDARipper.cpp xbmc-pvr-3513480.patch/xbmc/cdrip/CDDARipper.cpp
+--- xbmc-pvr-3513480/xbmc/cdrip/CDDARipper.cpp 2011-04-25 02:36:33.000000000 +0200
++++ xbmc-pvr-3513480.patch/xbmc/cdrip/CDDARipper.cpp 2011-04-25 05:48:10.487548571 +0200
+@@ -27,7 +27,11 @@
+ #include "CDDAReader.h"
+ #include "utils/StringUtils.h"
+ #include "Util.h"
++
++#ifdef HAVE_LIBMP3LAME
+ #include "EncoderLame.h"
++#endif
++
+ #include "EncoderWav.h"
+ #include "EncoderVorbis.h"
+ #include "EncoderFFmpeg.h"
+@@ -78,9 +82,16 @@
+ case CDDARIP_ENCODER_FLAC:
+ m_pEncoder = new CEncoderFlac();
+ break;
+- default:
++#ifdef HAVE_LIBMP3LAME
++ case CDDARIP_ENCODER_LAME:
+ m_pEncoder = new CEncoderLame();
+ break;
++#else
++ default:
++ CLog::Log(LOGERROR,"invalid encoder selected");
++ return false;
++ break;
++#endif
+ }
+
+ // we have to set the tags before we init the Encoder
+diff -Naur xbmc-pvr-3513480/xbmc/cdrip/Makefile.in xbmc-pvr-3513480.patch/xbmc/cdrip/Makefile.in
+--- xbmc-pvr-3513480/xbmc/cdrip/Makefile.in 2011-04-25 02:36:33.000000000 +0200
++++ xbmc-pvr-3513480.patch/xbmc/cdrip/Makefile.in 2011-04-25 05:51:13.013064387 +0200
+@@ -3,10 +3,13 @@
+ Encoder.cpp \
+ EncoderFFmpeg.cpp \
+ EncoderFlac.cpp \
+- EncoderLame.cpp \
+ EncoderVorbis.cpp \
+ EncoderWav.cpp \
+
++ifeq (@HAVE_LIBMP3LAME@,1)
++ SRCS+=EncoderLame.cpp
++endif
++
+ LIB=cdrip.a
+
+ include @abs_top_srcdir@/Makefile.include
+diff -Naur xbmc-pvr-3513480/xbmc/settings/GUISettings.cpp xbmc-pvr-3513480.patch/xbmc/settings/GUISettings.cpp
+--- xbmc-pvr-3513480/xbmc/settings/GUISettings.cpp 2011-04-25 05:47:12.000000000 +0200
++++ xbmc-pvr-3513480.patch/xbmc/settings/GUISettings.cpp 2011-04-25 05:48:47.956833472 +0200
+@@ -324,7 +324,9 @@
+ AddPath(acd,"audiocds.recordingpath",20000,"select writable folder",BUTTON_CONTROL_PATH_INPUT,false,657);
+ AddString(acd, "audiocds.trackpathformat", 13307, "%A - %B/[%N. ][%A - ]%T", EDIT_CONTROL_INPUT, false, 16016);
+ map encoders;
++#ifdef HAVE_LIBMP3LAME
+ encoders.insert(make_pair(34000,CDDARIP_ENCODER_LAME));
++#endif
+ encoders.insert(make_pair(34001,CDDARIP_ENCODER_VORBIS));
+ encoders.insert(make_pair(34002,CDDARIP_ENCODER_WAV));
+ encoders.insert(make_pair(34005,CDDARIP_ENCODER_FLAC));
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-408-enable_PYTHONOPTIMIZE_with_external_Python-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-408-enable_PYTHONOPTIMIZE_with_external_Python-0.1.patch
new file mode 100644
index 0000000000..821c1cc7bd
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-408-enable_PYTHONOPTIMIZE_with_external_Python-0.1.patch
@@ -0,0 +1,18 @@
+diff -Naur xbmc-a3c804b/xbmc/interfaces/python/XBPython.cpp xbmc-a3c804b.patch/xbmc/interfaces/python/XBPython.cpp
+--- xbmc-a3c804b/xbmc/interfaces/python/XBPython.cpp 2011-08-17 23:40:00.000000000 +0200
++++ xbmc-a3c804b.patch/xbmc/interfaces/python/XBPython.cpp 2011-08-18 03:50:49.652475572 +0200
+@@ -335,11 +335,9 @@
+ // at http://docs.python.org/using/cmdline.html#environment-variables
+
+ #if !defined(_WIN32)
+- /* PYTHONOPTIMIZE is set off intentionally when using external Python.
+- Reason for this is because we cannot be sure what version of Python
+- was used to compile the various Python object files (i.e. .pyo,
+- .pyc, etc.). */
+- // check if we are running as real xbmc.app or just binary
++ // Required for python to find optimized code (pyo) files
++ setenv("PYTHONOPTIMIZE", "1", 1);
++ // check if we are running as real xbmc.app or just binary
+ if (!CUtil::GetFrameworksPath(true).IsEmpty())
+ {
+ // using external python, it's build looking for xxx/lib/python2.6
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-452-change_lcd_content-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-452-change_lcd_content-0.1.patch
new file mode 100644
index 0000000000..0427b534f9
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-452-change_lcd_content-0.1.patch
@@ -0,0 +1,12 @@
+diff -Naur xbmc-pvr-3513480/userdata/LCD.xml xbmc-pvr-3513480.patch/userdata/LCD.xml
+--- xbmc-pvr-3513480/userdata/LCD.xml 2011-04-25 02:36:33.000000000 +0200
++++ xbmc-pvr-3513480.patch/userdata/LCD.xml 2011-04-25 05:27:34.956125133 +0200
+@@ -21,7 +21,7 @@
+ Freemem: $INFO[System.FreeMemory]
+
+
+- XBMC running...
++ *** OpenELEC ***
+ $INFO[System.Time] $INFO[System.Date]
+ Freemem: $INFO[System.FreeMemory]
+ $INFO[System.ScreenWidth]x$INFO[System.ScreenHeight] $INFO[System.ScreenMode]
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-453-add_openelec.tv_RSS_news-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-453-add_openelec.tv_RSS_news-0.1.patch
new file mode 100644
index 0000000000..5b32c0cce7
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-453-add_openelec.tv_RSS_news-0.1.patch
@@ -0,0 +1,11 @@
+diff -Naur xbmc-10.1-Dharma/userdata/RssFeeds.xml xbmc-10.1-Dharma.patch/userdata/RssFeeds.xml
+--- xbmc-10.1-Dharma/userdata/RssFeeds.xml 2011-03-08 02:49:24.000000000 +0100
++++ xbmc-10.1-Dharma.patch/userdata/RssFeeds.xml 2011-06-14 17:07:08.450880123 +0200
+@@ -3,6 +3,7 @@
+
+
+
++ http://openelec.tv/news?format=feed&type=rss
+ http://feeds.feedburner.com/xbmc
+
+
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-454-disable_backslash-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-454-disable_backslash-0.1.patch
new file mode 100644
index 0000000000..0888920258
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-454-disable_backslash-0.1.patch
@@ -0,0 +1,12 @@
+diff -Naur xbmc-30a9070/system/keymaps/keyboard.xml xbmc-30a9070.patch/system/keymaps/keyboard.xml
+--- xbmc-30a9070/system/keymaps/keyboard.xml 2011-07-28 06:20:13.000000000 +0200
++++ xbmc-30a9070.patch/system/keymaps/keyboard.xml 2011-07-28 09:39:57.210973380 +0200
+@@ -90,7 +90,7 @@
+ Number7
+ Number8
+ Number9
+- ToggleFullScreen
++
+ FirstPage
+ LastPage
+
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-457-fix_connection_check-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-457-fix_connection_check-0.1.patch
new file mode 100644
index 0000000000..f4982ec635
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-457-fix_connection_check-0.1.patch
@@ -0,0 +1,15 @@
+diff -Naur xbmc-10.1-Dharma/xbmc/FileSystem/FileCurl.cpp xbmc-10.1-Dharma.patch/xbmc/FileSystem/FileCurl.cpp
+--- xbmc-10.1-Dharma/xbmc/filesystem/FileCurl.cpp 2011-03-08 02:49:14.000000000 +0100
++++ xbmc-10.1-Dharma.patch/xbmc/filesystem/FileCurl.cpp 2011-10-17 19:21:04.180783870 +0200
+@@ -803,9 +803,9 @@
+ // Detect whether we are "online" or not! Very simple and dirty!
+ bool CFileCurl::IsInternet(bool checkDNS /* = true */)
+ {
+- CStdString strURL = "http://www.google.com";
++ CStdString strURL = "http://www.openelec.tv";
+ if (!checkDNS)
+- strURL = "http://74.125.19.103"; // www.google.com ip
++ strURL = "http://212.101.13.10"; // www.openelec.tv ip
+
+ bool found = Exists(strURL);
+ Close();
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-462-add_remote_irtrans_mediacenter-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-462-add_remote_irtrans_mediacenter-0.1.patch
new file mode 100644
index 0000000000..0edef5a7a5
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-462-add_remote_irtrans_mediacenter-0.1.patch
@@ -0,0 +1,52 @@
+diff -Naur xbmc-pvr-3513480/system/Lircmap.xml xbmc-pvr-3513480.patch/system/Lircmap.xml
+--- xbmc-pvr-3513480/system/Lircmap.xml 2011-04-25 02:36:33.000000000 +0200
++++ xbmc-pvr-3513480.patch/system/Lircmap.xml 2011-04-25 05:31:39.632429078 +0200
+@@ -409,4 +409,48 @@
+ KEY_YELLOW
+ KEY_BLUE
+
++
++ pause
++ stop
++ fwd
++ rew
++ left
++ right
++ up
++ down
++
++ ch+
++ ch-
++ back
++
++ play
++ info
++ next
++ prev
++ teletext
++ ehome
++ rec
++ vol+
++ vol-
++ mute
++ power
++ video
++ music
++ pictures
++ tv
++ 1
++ 2
++ 3
++ 4
++ 5
++ 6
++ 7
++ 8
++ 9
++ 0
++ red
++ green
++ yellow
++ blue
++
+
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-463-add_remote_devinput-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-463-add_remote_devinput-0.1.patch
new file mode 100644
index 0000000000..85d635b61b
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-463-add_remote_devinput-0.1.patch
@@ -0,0 +1,71 @@
+diff -Naur xbmc-10.1-Dharma/system/Lircmap.xml xbmc-10.1-Dharma.patch/system/Lircmap.xml
+--- xbmc-10.1-Dharma/system/Lircmap.xml 2011-06-18 01:43:43.132101246 +0200
++++ xbmc-10.1-Dharma.patch/system/Lircmap.xml 2011-06-18 01:44:53.777025290 +0200
+@@ -365,7 +365,6 @@
+
+
+ cx23885_remote
+- devinput
+ KEY_LEFT
+ KEY_RIGHT
+ KEY_UP
+@@ -452,4 +451,59 @@
+ yellow
+ blue
+
++
++
++ KEY_LEFT
++ KEY_RIGHT
++ KEY_UP
++ KEY_DOWN
++
++ KEY_ENTER
++ KEY_DELETE
++ KEY_PROG1
++ KEY_EXIT
++ KEY_RECORD
++ KEY_PLAY
++ KEY_PAUSE
++ KEY_STOP
++ KEY_FASTFORWARD
++ KEY_REWIND
++ KEY_VOLUMEUP
++ KEY_VOLUMEDOWN
++ KEY_CHANNELUP
++ KEY_CHANNELDOWN
++ KEY_NEXT
++ KEY_PREVIOUS
++ KEY_EPG
++ KEY_SUBTITLE
++ KEY_LANGUAGE
++ KEY_INFO
++ KEY_ZOOM
++ KEY_MUTE
++ KEY_POWER
++ KEY_EJECT
++
++
++ KEY_VIDEO
++ KEY_AUDIO
++ KEY_CAMERA
++ KEY_TUNER
++ KEY_TEXT
++ KEY_NUMERIC_1
++ KEY_NUMERIC_2
++ KEY_NUMERIC_3
++ KEY_NUMERIC_4
++ KEY_NUMERIC_5
++ KEY_NUMERIC_6
++ KEY_NUMERIC_7
++ KEY_NUMERIC_8
++ KEY_NUMERIC_9
++ KEY_NUMERIC_0
++ KEY_NUMERIC_STAR
++ KEY_NUMERIC_POUND
++ KEY_RED
++ KEY_GREEN
++ KEY_YELLOW
++ KEY_BLUE
++
+
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-464-add_eject_keymapping_for_lirc-0.1.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-464-add_eject_keymapping_for_lirc-0.1.patch
new file mode 100644
index 0000000000..56c56016b5
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-464-add_eject_keymapping_for_lirc-0.1.patch
@@ -0,0 +1,11 @@
+diff -Naur xbmc-10.1-Dharma/system/keymaps/remote.xml xbmc-10.1-Dharma.patch/system/keymaps/remote.xml
+--- xbmc-10.1-Dharma/system/keymaps/remote.xml 2011-03-08 02:49:23.000000000 +0100
++++ xbmc-10.1-Dharma.patch/system/keymaps/remote.xml 2011-06-18 01:48:26.887811969 +0200
+@@ -63,6 +63,7 @@
+ VolumeDown
+ Mute
+ XBMC.ShutDown()
++ XBMC.EjectTray()
+ XBMC.ActivateWindow(MyVideos)
+ XBMC.ActivateWindow(MyMusic)
+ XBMC.ActivateWindow(MyPictures)
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-801-cec-PR570.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-801-cec-PR570.patch
new file mode 100644
index 0000000000..a274bdddc0
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-801-cec-PR570.patch
@@ -0,0 +1,1137 @@
+From 220e74259c67e106acc106fbb9546d750605814f Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp
+Date: Thu, 12 Jan 2012 22:16:49 +0100
+Subject: [PATCH 1/7] cec: added volume control on a CEC enabled amplifier
+ when one is found
+
+---
+ xbmc/Application.cpp | 64 +++++++++
+ xbmc/Application.h | 1 +
+ xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 145 ++++++++++++++++++++-
+ xbmc/peripherals/devices/PeripheralCecAdapter.h | 17 +++
+ 4 files changed, 225 insertions(+), 2 deletions(-)
+
+diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
+index 5ed5de2..6f3fff7 100644
+--- a/xbmc/Application.cpp
++++ b/xbmc/Application.cpp
+@@ -2574,6 +2574,26 @@ bool CApplication::OnAction(const CAction &action)
+ // Check for global volume control
+ if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
+ {
++ /* try to set the volume on a connected amp */
++ #ifdef HAVE_LIBCEC
++ vector peripherals;
++ if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC))
++ {
++ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++)
++ {
++ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr);
++ if (cecDevice && cecDevice->HasConnectedAudioSystem())
++ {
++ if (action.GetID() == ACTION_VOLUME_UP)
++ cecDevice->ScheduleVolumeUp();
++ else
++ cecDevice->ScheduleVolumeDown();
++ return true;
++ }
++ }
++ }
++ #endif
++
+ if (!m_pPlayer || !m_pPlayer->IsPassthrough())
+ {
+ // increase or decrease the volume
+@@ -5000,11 +5020,49 @@ void CApplication::ShowVolumeBar(const CAction *action)
+
+ bool CApplication::IsMuted() const
+ {
++ /* try to set the mute setting on a connected amp */
++#ifdef HAVE_LIBCEC
++ vector peripherals;
++ if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC))
++ {
++ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++)
++ {
++ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr);
++ if (cecDevice && cecDevice->HasConnectedAudioSystem())
++ return false;
++ }
++ }
++#endif
+ return g_settings.m_bMute;
+ }
+
++bool CApplication::CecMute(void)
++{
++ /* try to set the mute setting on a connected amp */
++#ifdef HAVE_LIBCEC
++ vector peripherals;
++ if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC))
++ {
++ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++)
++ {
++ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr);
++ if (cecDevice && cecDevice->HasConnectedAudioSystem())
++ {
++ cecDevice->ScheduleMute();
++ return true;
++ }
++ }
++ }
++#endif
++
++ return false;
++}
++
+ void CApplication::ToggleMute(void)
+ {
++ if (CecMute())
++ return;
++
+ if (g_settings.m_bMute)
+ UnMute();
+ else
+@@ -5013,6 +5071,9 @@ void CApplication::ToggleMute(void)
+
+ void CApplication::Mute()
+ {
++ if (CecMute())
++ return;
++
+ g_settings.m_iPreMuteVolumeLevel = GetVolume();
+ SetVolume(0);
+ g_settings.m_bMute = true;
+@@ -5020,6 +5081,9 @@ void CApplication::Mute()
+
+ void CApplication::UnMute()
+ {
++ if (CecMute())
++ return;
++
+ SetVolume(g_settings.m_iPreMuteVolumeLevel);
+ g_settings.m_iPreMuteVolumeLevel = 0;
+ g_settings.m_bMute = false;
+diff --git a/xbmc/Application.h b/xbmc/Application.h
+index 6e6a005..2fd09aa 100644
+--- a/xbmc/Application.h
++++ b/xbmc/Application.h
+@@ -167,6 +167,7 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
+ void SetVolume(long iValue, bool isPercentage = true);
+ bool IsMuted() const;
+ void ToggleMute(void);
++ bool CecMute(void);
+ void ShowVolumeBar(const CAction *action = NULL);
+ int GetPlaySpeed() const;
+ int GetSubtitleDelay() const;
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+index c1c3658..84d5464 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+@@ -31,6 +31,7 @@
+ #include "peripherals/Peripherals.h"
+ #include "peripherals/bus/PeripheralBus.h"
+ #include "settings/GUISettings.h"
++#include "settings/Settings.h"
+ #include "utils/log.h"
+
+ #include
+@@ -43,6 +44,8 @@
+
+ /* time in seconds to ignore standby commands from devices after the screensaver has been activated */
+ #define SCREENSAVER_TIMEOUT 10
++#define VOLUME_CHANGE_TIMEOUT 250
++#define VOLUME_REFRESH_TIMEOUT 100
+
+ class DllLibCECInterface
+ {
+@@ -72,7 +75,8 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface
+ m_bHasButton(false),
+ m_bIsReady(false),
+ m_strMenuLanguage("???"),
+- m_lastKeypress(0)
++ m_lastKeypress(0),
++ m_lastChange(VOLUME_CHANGE_NONE)
+ {
+ m_button.iButton = 0;
+ m_button.iDuration = 0;
+@@ -269,8 +273,24 @@ void CPeripheralCecAdapter::Process(void)
+ SetMenuLanguage(language.language);
+ }
+
++ CStdString strNotification;
++ cec_osd_name tvName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV);
++ strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name);
++
++ /* disable the mute setting when an amp is found, because the amp handles the mute setting and
++ set PCM output to 100% */
++ if (HasConnectedAudioSystem())
++ {
++ cec_osd_name ampName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM);
++ CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name);
++ strNotification.AppendFormat(" - %s", ampName.name);
++
++ g_settings.m_bMute = false;
++ g_settings.m_nVolumeLevel = VOLUME_MAXIMUM;
++ }
++
+ m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str());
+- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(36016));
++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification);
+
+ while (!m_bStop)
+ {
+@@ -278,6 +298,8 @@ void CPeripheralCecAdapter::Process(void)
+ if (!m_bStop)
+ ProcessNextCommand();
+ if (!m_bStop)
++ ProcessVolumeChange();
++ if (!m_bStop)
+ Sleep(5);
+ }
+
+@@ -339,6 +361,125 @@ bool CPeripheralCecAdapter::SetHdmiPort(int iHdmiPort)
+ return bReturn;
+ }
+
++bool CPeripheralCecAdapter::HasConnectedAudioSystem(void)
++{
++ return m_cecAdapter && m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM);
++}
++
++void CPeripheralCecAdapter::ScheduleVolumeUp(void)
++{
++ {
++ CSingleLock lock(m_critSection);
++ m_volumeChangeQueue.push(VOLUME_CHANGE_UP);
++ }
++ Sleep(5);
++}
++
++void CPeripheralCecAdapter::ScheduleVolumeDown(void)
++{
++ {
++ CSingleLock lock(m_critSection);
++ m_volumeChangeQueue.push(VOLUME_CHANGE_DOWN);
++ }
++ Sleep(5);
++}
++
++void CPeripheralCecAdapter::ScheduleMute(void)
++{
++ {
++ CSingleLock lock(m_critSection);
++ m_volumeChangeQueue.push(VOLUME_CHANGE_MUTE);
++ }
++ Sleep(5);
++}
++
++void CPeripheralCecAdapter::ProcessVolumeChange(void)
++{
++ bool bSendRelease(false);
++ CecVolumeChange pendingVolumeChange = VOLUME_CHANGE_NONE;
++ {
++ CSingleLock lock(m_critSection);
++ if (m_volumeChangeQueue.size() > 0)
++ {
++ /* get the first change from the queue */
++ pendingVolumeChange = m_volumeChangeQueue.front();
++ m_volumeChangeQueue.pop();
++
++ /* remove all dupe entries */
++ while (m_volumeChangeQueue.size() > 0 && m_volumeChangeQueue.front() == pendingVolumeChange)
++ m_volumeChangeQueue.pop();
++
++ /* send another keypress after VOLUME_REFRESH_TIMEOUT ms */
++ bool bRefresh(m_lastKeypress + VOLUME_REFRESH_TIMEOUT < XbmcThreads::SystemClockMillis());
++
++ /* only send the keypress when it hasn't been sent yet */
++ if (pendingVolumeChange != m_lastChange)
++ {
++ m_lastKeypress = XbmcThreads::SystemClockMillis();
++ m_lastChange = pendingVolumeChange;
++ }
++ else if (bRefresh)
++ {
++ m_lastKeypress = XbmcThreads::SystemClockMillis();
++ pendingVolumeChange = m_lastChange;
++ }
++ else
++ pendingVolumeChange = VOLUME_CHANGE_NONE;
++ }
++ else if (m_lastKeypress > 0 && m_lastKeypress + VOLUME_CHANGE_TIMEOUT < XbmcThreads::SystemClockMillis())
++ {
++ /* send a key release */
++ m_lastKeypress = 0;
++ bSendRelease = true;
++ m_lastChange = VOLUME_CHANGE_NONE;
++ }
++ }
++
++ switch (pendingVolumeChange)
++ {
++ case VOLUME_CHANGE_UP:
++ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_VOLUME_UP, false);
++ break;
++ case VOLUME_CHANGE_DOWN:
++ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_VOLUME_DOWN, false);
++ break;
++ case VOLUME_CHANGE_MUTE:
++ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_MUTE, false);
++ break;
++ case VOLUME_CHANGE_NONE:
++ if (bSendRelease)
++ m_cecAdapter->SendKeyRelease(CECDEVICE_AUDIOSYSTEM, false);
++ break;
++ }
++}
++
++void CPeripheralCecAdapter::VolumeUp(void)
++{
++ if (HasConnectedAudioSystem())
++ {
++ CSingleLock lock(m_critSection);
++ m_volumeChangeQueue.push(VOLUME_CHANGE_UP);
++ }
++}
++
++void CPeripheralCecAdapter::VolumeDown(void)
++{
++ if (HasConnectedAudioSystem())
++ {
++ CSingleLock lock(m_critSection);
++ m_volumeChangeQueue.push(VOLUME_CHANGE_DOWN);
++ }
++}
++
++void CPeripheralCecAdapter::Mute(void)
++{
++ if (HasConnectedAudioSystem())
++ {
++ CSingleLock lock(m_critSection);
++ m_volumeChangeQueue.push(VOLUME_CHANGE_MUTE);
++ }
++}
++
+ void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage)
+ {
+ if (m_strMenuLanguage.Equals(strLanguage))
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+index 2fcbb1d..e1e302d 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.h
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+@@ -49,6 +49,13 @@
+ unsigned int iDuration;
+ } CecButtonPress;
+
++ typedef enum
++ {
++ VOLUME_CHANGE_NONE,
++ VOLUME_CHANGE_UP,
++ VOLUME_CHANGE_DOWN,
++ VOLUME_CHANGE_MUTE
++ } CecVolumeChange;
+
+ class CPeripheralCecAdapter : public CPeripheralHID, public ANNOUNCEMENT::IAnnouncer, private CThread
+ {
+@@ -59,6 +66,13 @@
+ virtual void Announce(ANNOUNCEMENT::EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data);
+ virtual bool PowerOnCecDevices(CEC::cec_logical_address iLogicalAddress);
+ virtual bool StandbyCecDevices(CEC::cec_logical_address iLogicalAddress);
++ virtual bool HasConnectedAudioSystem(void);
++ virtual void ScheduleVolumeUp(void);
++ virtual void VolumeUp(void);
++ virtual void ScheduleVolumeDown(void);
++ virtual void VolumeDown(void);
++ virtual void ScheduleMute(void);
++ virtual void Mute(void);
+
+ virtual bool SendPing(void);
+ virtual bool SetHdmiPort(int iHdmiPort);
+@@ -77,6 +91,7 @@
+ virtual bool InitialiseFeature(const PeripheralFeature feature);
+ virtual void Process(void);
+ virtual void ProcessNextCommand(void);
++ virtual void ProcessVolumeChange(void);
+ virtual void SetMenuLanguage(const char *strLanguage);
+ static bool FindConfigLocation(CStdString &strString);
+ static bool TranslateComPort(CStdString &strPort);
+@@ -90,7 +105,9 @@
+ CDateTime m_screensaverLastActivated;
+ CecButtonPress m_button;
+ std::queue m_buttonQueue;
++ std::queue m_volumeChangeQueue;
+ unsigned int m_lastKeypress;
++ CecVolumeChange m_lastChange;
+ CCriticalSection m_critSection;
+ };
+ }
+--
+1.7.5.4
+
+
+From 19fcb081a184533fec42ef914a2a409ad2a99591 Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp
+Date: Thu, 12 Jan 2012 22:18:31 +0100
+Subject: [PATCH 2/7] cec: set the HDMI port and the device to which the CEC
+ adapter was connected, to be able to determine the
+ correct physical address. this is a work around, until
+ the CEC adapter's firmware supports physical address
+ detection, but is needed for people who have connected
+ XBMC to something else than the TV
+
+---
+ language/Dutch/strings.xml | 1 +
+ language/English/strings.xml | 1 +
+ system/peripherals.xml | 1 +
+ xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 13 +++++++------
+ xbmc/peripherals/devices/PeripheralCecAdapter.h | 2 +-
+ 5 files changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/language/Dutch/strings.xml b/language/Dutch/strings.xml
+index 7d7fa9b..d49143d 100644
+\ No newline at end of file
+diff --git a/language/English/strings.xml b/language/English/strings.xml
+index ece866a..dd7fec7 100644
+--- a/language/English/strings.xml
++++ b/language/English/strings.xml
+@@ -2389,4 +2389,5 @@
+ Connected
+ Adapter found, but libcec is not available
+ Use the TV's language setting
++ Connected to HDMI device
+
+diff --git a/system/peripherals.xml b/system/peripherals.xml
+index f5cf50d..94b9d85 100644
+--- a/system/peripherals.xml
++++ b/system/peripherals.xml
+@@ -18,5 +18,6 @@
+
+
+
++
+
+
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+index 84d5464..1992b6a 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+@@ -235,8 +235,9 @@ void CPeripheralCecAdapter::Process(void)
+ return;
+
+ // set correct physical address from peripheral settings
++ int iDevice = GetSettingInt("connected_device");
+ int iHdmiPort = GetSettingInt("cec_hdmi_port");
+- SetHdmiPort(iHdmiPort);
++ m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort);
+ FlushLog();
+
+ // open the CEC adapter
+@@ -347,15 +348,15 @@ bool CPeripheralCecAdapter::SendPing(void)
+ return bReturn;
+ }
+
+-bool CPeripheralCecAdapter::SetHdmiPort(int iHdmiPort)
++bool CPeripheralCecAdapter::SetHdmiPort(int iDevice, int iHdmiPort)
+ {
+ bool bReturn(false);
+ if (m_cecAdapter && m_bIsReady)
+ {
+ if (iHdmiPort <= 0 || iHdmiPort > 16)
+ iHdmiPort = 1;
+- CLog::Log(LOGDEBUG, "%s - changing active HDMI port to %d", __FUNCTION__, iHdmiPort);
+- bReturn = m_cecAdapter->SetPhysicalAddress(iHdmiPort << 12);
++ CLog::Log(LOGDEBUG, "%s - changing active HDMI port to %d on device %d", __FUNCTION__, iHdmiPort, iDevice);
++ bReturn = m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort);
+ }
+
+ return bReturn;
+@@ -863,9 +864,9 @@ void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting
+ else if (bEnabled && !m_cecAdapter && m_bStarted)
+ InitialiseFeature(FEATURE_CEC);
+ }
+- else if (strChangedSetting.Equals("cec_hdmi_port"))
++ else if (strChangedSetting.Equals("connected_device") || strChangedSetting.Equals("cec_hdmi_port"))
+ {
+- SetHdmiPort(GetSettingInt("cec_hdmi_port"));
++ SetHdmiPort(GetSettingInt("connected_device"), GetSettingInt("cec_hdmi_port"));
+ }
+ }
+
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+index e1e302d..768e38a 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.h
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+@@ -75,7 +75,7 @@
+ virtual void Mute(void);
+
+ virtual bool SendPing(void);
+- virtual bool SetHdmiPort(int iHdmiPort);
++ virtual bool SetHdmiPort(int iDevice, int iHdmiPort);
+
+ virtual void OnSettingChanged(const CStdString &strChangedSetting);
+
+--
+1.7.5.4
+
+
+From 4369707420b58f8151a4769181aa3a4d4b798c1e Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp
+Date: Tue, 3 Jan 2012 20:40:19 +0100
+Subject: [PATCH 3/7] cec: also mark XBMC as active source when powering up
+ devices
+
+---
+ xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+index 1992b6a..380c40e 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+@@ -264,6 +264,7 @@ void CPeripheralCecAdapter::Process(void)
+ if (GetSettingBool("cec_power_on_startup"))
+ {
+ PowerOnCecDevices(CECDEVICE_TV);
++ m_cecAdapter->SetActiveSource();
+ FlushLog();
+ }
+
+--
+1.7.5.4
+
+
+From ecfbe68309888cb5befa4a8359a23bffdb0e0fe0 Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp
+Date: Tue, 10 Jan 2012 11:56:34 +0100
+Subject: [PATCH 4/7] cec: delete m_dll when it's been created. fixes leak
+ when the libCEC version is invalid
+
+---
+ xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+index 380c40e..9cb195d 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+@@ -119,11 +119,14 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface
+ m_bStop = true;
+ StopThread(true);
+
+- if (m_dll && m_cecAdapter)
++ if (m_cecAdapter)
+ {
+ FlushLog();
+ m_dll->CECDestroy(m_cecAdapter);
+ m_cecAdapter = NULL;
++ }
++ if (m_dll)
++ {
+ delete m_dll;
+ m_dll = NULL;
+ }
+--
+1.7.5.4
+
+
+From 9434d5b9a5d8d5290f0af6bc0b85b17219c2eccd Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp
+Date: Wed, 11 Jan 2012 00:09:02 +0100
+Subject: [PATCH 5/7] cec: some TVs don't like us querying it while activating
+ sources. moved the queries to a background thread, and
+ only query after the TV reports power state active.
+
+---
+ xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 102 +++++++++++++++------
+ xbmc/peripherals/devices/PeripheralCecAdapter.h | 46 +++++++---
+ 2 files changed, 108 insertions(+), 40 deletions(-)
+
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+index 9cb195d..a8632f2 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+@@ -260,9 +260,8 @@ void CPeripheralCecAdapter::Process(void)
+ return;
+ }
+
++ CAnnouncementManager::AddAnnouncer(m_cecAdapter);
+ CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__);
+- m_bIsReady = true;
+- CAnnouncementManager::AddAnnouncer(this);
+
+ if (GetSettingBool("cec_power_on_startup"))
+ {
+@@ -271,31 +270,8 @@ void CPeripheralCecAdapter::Process(void)
+ FlushLog();
+ }
+
+- if (GetSettingBool("use_tv_menu_language"))
+- {
+- cec_menu_language language;
+- if (m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language))
+- SetMenuLanguage(language.language);
+- }
+-
+- CStdString strNotification;
+- cec_osd_name tvName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV);
+- strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name);
+-
+- /* disable the mute setting when an amp is found, because the amp handles the mute setting and
+- set PCM output to 100% */
+- if (HasConnectedAudioSystem())
+- {
+- cec_osd_name ampName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM);
+- CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name);
+- strNotification.AppendFormat(" - %s", ampName.name);
+-
+- g_settings.m_bMute = false;
+- g_settings.m_nVolumeLevel = VOLUME_MAXIMUM;
+- }
+-
+- m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str());
+- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification);
++ m_queryThread = new CPeripheralCecAdapterQueryThread(this);
++ m_queryThread->Create(false);
+
+ while (!m_bStop)
+ {
+@@ -304,10 +280,12 @@ void CPeripheralCecAdapter::Process(void)
+ ProcessNextCommand();
+ if (!m_bStop)
+ ProcessVolumeChange();
++
+ if (!m_bStop)
+ Sleep(5);
+ }
+
++ delete m_queryThread;
+ m_cecAdapter->Close();
+
+ CLog::Log(LOGDEBUG, "%s - CEC adapter processor thread ended", __FUNCTION__);
+@@ -609,6 +587,15 @@ void CPeripheralCecAdapter::ProcessNextCommand(void)
+ }
+ }
+ break;
++ case CEC_OPCODE_REPORT_POWER_STATUS:
++ if (command.initiator == CECDEVICE_TV &&
++ command.parameters.size == 1 &&
++ command.parameters[0] == CEC_POWER_STATUS_ON &&
++ m_queryThread)
++ {
++ m_queryThread->Signal();
++ }
++ break;
+ default:
+ break;
+ }
+@@ -916,4 +903,65 @@ bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation)
+
+ return false;
+ }
++
++CPeripheralCecAdapterQueryThread::CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter) :
++ CThread("CEC Adapter Query Thread"),
++ m_adapter(adapter)
++{
++ m_event.Reset();
++}
++
++CPeripheralCecAdapterQueryThread::~CPeripheralCecAdapterQueryThread(void)
++{
++ m_event.Set();
++ StopThread(true);
++}
++
++void CPeripheralCecAdapterQueryThread::Signal(void)
++{
++ m_event.Set();
++}
++
++void CPeripheralCecAdapterQueryThread::Process(void)
++{
++ bool bContinue(false);
++ do
++ {
++ m_event.WaitMSec(5000);
++ if (m_adapter->m_bStop)
++ return;
++
++ if (m_adapter->m_cecAdapter->GetDevicePowerStatus(CECDEVICE_TV) == CEC_POWER_STATUS_ON)
++ bContinue = true;
++ }while(!bContinue);
++
++ if (m_adapter->GetSettingBool("use_tv_menu_language"))
++ {
++ cec_menu_language language;
++ if (m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language))
++ m_adapter->SetMenuLanguage(language.language);
++ }
++
++ CStdString strNotification;
++ cec_osd_name tvName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV);
++ strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name);
++
++ /* disable the mute setting when an amp is found, because the amp handles the mute setting and
++ set PCM output to 100% */
++ if (m_adapter->HasConnectedAudioSystem())
++ {
++ cec_osd_name ampName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM);
++ CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name);
++ strNotification.AppendFormat(" - %s", ampName.name);
++
++ g_settings.m_bMute = false;
++ g_settings.m_nVolumeLevel = VOLUME_MAXIMUM;
++ }
++
++ m_adapter->m_bIsReady = true;
++
++ m_adapter->m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str());
++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification);
++}
++
+ #endif
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+index 768e38a..f10f2ea 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.h
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+@@ -43,6 +43,8 @@
+
+ namespace PERIPHERALS
+ {
++ class CPeripheralCecAdapterQueryThread;
++
+ typedef struct
+ {
+ WORD iButton;
+@@ -59,6 +61,8 @@
+
+ class CPeripheralCecAdapter : public CPeripheralHID, public ANNOUNCEMENT::IAnnouncer, private CThread
+ {
++ friend class CPeripheralCecAdapterQueryThread;
++
+ public:
+ CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId);
+ virtual ~CPeripheralCecAdapter(void);
+@@ -96,19 +100,35 @@
+ static bool FindConfigLocation(CStdString &strString);
+ static bool TranslateComPort(CStdString &strPort);
+
+- DllLibCEC* m_dll;
+- CEC::ICECAdapter* m_cecAdapter;
+- bool m_bStarted;
+- bool m_bHasButton;
+- bool m_bIsReady;
+- CStdString m_strMenuLanguage;
+- CDateTime m_screensaverLastActivated;
+- CecButtonPress m_button;
+- std::queue m_buttonQueue;
+- std::queue m_volumeChangeQueue;
+- unsigned int m_lastKeypress;
+- CecVolumeChange m_lastChange;
+- CCriticalSection m_critSection;
++ DllLibCEC* m_dll;
++ CEC::ICECAdapter* m_cecAdapter;
++ bool m_bStarted;
++ bool m_bHasButton;
++ bool m_bIsReady;
++ CStdString m_strMenuLanguage;
++ CDateTime m_screensaverLastActivated;
++ CecButtonPress m_button;
++ std::queue m_buttonQueue;
++ std::queue m_volumeChangeQueue;
++ unsigned int m_lastKeypress;
++ CecVolumeChange m_lastChange;
++ CPeripheralCecAdapterQueryThread *m_queryThread;
++ CCriticalSection m_critSection;
++ };
++
++ class CPeripheralCecAdapterQueryThread : public CThread
++ {
++ public:
++ CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter);
++ virtual ~CPeripheralCecAdapterQueryThread(void);
++
++ virtual void Signal(void);
++
++ protected:
++ virtual void Process(void);
++
++ CPeripheralCecAdapter *m_adapter;
++ CEvent m_event;
+ };
+ }
+
+--
+1.7.5.4
+
+
+From a621adb7400a65fca4afc9e25a3849de5cbd5d4e Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp
+Date: Thu, 12 Jan 2012 22:22:17 +0100
+Subject: [PATCH 6/7] cec: use callback methods instead of constant polling.
+ this requires libCEC 1.4.0 or higher
+
+---
+ xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 123 ++++++++++++---------
+ xbmc/peripherals/devices/PeripheralCecAdapter.h | 10 +-
+ 2 files changed, 76 insertions(+), 57 deletions(-)
+
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+index a8632f2..13338bb 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+@@ -121,7 +121,6 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface
+
+ if (m_cecAdapter)
+ {
+- FlushLog();
+ m_dll->CECDestroy(m_cecAdapter);
+ m_cecAdapter = NULL;
+ }
+@@ -169,7 +168,6 @@ void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender,
+ if (!m_cecAdapter->Open(strPort.c_str(), 10000))
+ {
+ CLog::Log(LOGERROR, "%s - failed to reconnect to the CEC adapter", __FUNCTION__);
+- FlushLog();
+ m_bStop = true;
+ }
+ else
+@@ -237,11 +235,12 @@ void CPeripheralCecAdapter::Process(void)
+ if (strPort.empty())
+ return;
+
++ EnableCallbacks();
++
+ // set correct physical address from peripheral settings
+ int iDevice = GetSettingInt("connected_device");
+ int iHdmiPort = GetSettingInt("cec_hdmi_port");
+ m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort);
+- FlushLog();
+
+ // open the CEC adapter
+ CLog::Log(LOGDEBUG, "%s - opening a connection to the CEC adapter: %s", __FUNCTION__, strPort.c_str());
+@@ -253,21 +252,19 @@ void CPeripheralCecAdapter::Process(void)
+
+ if (!m_cecAdapter->Open(strPort.c_str(), 10000))
+ {
+- FlushLog();
+ CLog::Log(LOGERROR, "%s - could not opening a connection to the CEC adapter", __FUNCTION__);
+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012));
+ m_bStarted = false;
+ return;
+ }
+
+- CAnnouncementManager::AddAnnouncer(m_cecAdapter);
++ CAnnouncementManager::AddAnnouncer(this);
+ CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__);
+
+ if (GetSettingBool("cec_power_on_startup"))
+ {
+ PowerOnCecDevices(CECDEVICE_TV);
+ m_cecAdapter->SetActiveSource();
+- FlushLog();
+ }
+
+ m_queryThread = new CPeripheralCecAdapterQueryThread(this);
+@@ -275,9 +272,6 @@ void CPeripheralCecAdapter::Process(void)
+
+ while (!m_bStop)
+ {
+- FlushLog();
+- if (!m_bStop)
+- ProcessNextCommand();
+ if (!m_bStop)
+ ProcessVolumeChange();
+
+@@ -524,10 +518,13 @@ void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage)
+ CLog::Log(LOGWARNING, "%s - TV menu language set to unknown value '%s'", __FUNCTION__, strLanguage);
+ }
+
+-void CPeripheralCecAdapter::ProcessNextCommand(void)
++int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command &command)
+ {
+- cec_command command;
+- if (m_cecAdapter && m_bIsReady && m_cecAdapter->GetNextCommand(&command))
++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
++ if (!adapter)
++ return 0;
++
++ if (adapter->m_bIsReady)
+ {
+ CLog::Log(LOGDEBUG, "%s - processing command: initiator=%1x destination=%1x opcode=%02x", __FUNCTION__, command.initiator, command.destination, command.opcode);
+
+@@ -536,21 +533,21 @@ void CPeripheralCecAdapter::ProcessNextCommand(void)
+ case CEC_OPCODE_STANDBY:
+ /* a device was put in standby mode */
+ CLog::Log(LOGDEBUG, "%s - device %1x was put in standby mode", __FUNCTION__, command.initiator);
+- if (command.initiator == CECDEVICE_TV && GetSettingBool("standby_pc_on_tv_standby") &&
+- (!m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT)))
++ if (command.initiator == CECDEVICE_TV && adapter->GetSettingBool("standby_pc_on_tv_standby") &&
++ (!adapter->m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - adapter->m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT)))
+ {
+- m_bStarted = false;
++ adapter->m_bStarted = false;
+ g_application.getApplicationMessenger().Suspend();
+ }
+ break;
+ case CEC_OPCODE_SET_MENU_LANGUAGE:
+- if (GetSettingBool("use_tv_menu_language") && command.initiator == CECDEVICE_TV && command.parameters.size == 3)
++ if (adapter->GetSettingBool("use_tv_menu_language") && command.initiator == CECDEVICE_TV && command.parameters.size == 3)
+ {
+ char strNewLanguage[4];
+ for (int iPtr = 0; iPtr < 3; iPtr++)
+ strNewLanguage[iPtr] = command.parameters[iPtr];
+ strNewLanguage[3] = 0;
+- SetMenuLanguage(strNewLanguage);
++ adapter->SetMenuLanguage(strNewLanguage);
+ }
+ break;
+ case CEC_OPCODE_DECK_CONTROL:
+@@ -558,11 +555,11 @@ void CPeripheralCecAdapter::ProcessNextCommand(void)
+ command.parameters.size == 1 &&
+ command.parameters[0] == CEC_DECK_CONTROL_MODE_STOP)
+ {
+- CSingleLock lock(m_critSection);
++ CSingleLock lock(adapter->m_critSection);
+ cec_keypress key;
+ key.duration = 500;
+ key.keycode = CEC_USER_CONTROL_CODE_STOP;
+- m_buttonQueue.push(key);
++ adapter->m_buttonQueue.push(key);
+ }
+ break;
+ case CEC_OPCODE_PLAY:
+@@ -571,19 +568,19 @@ void CPeripheralCecAdapter::ProcessNextCommand(void)
+ {
+ if (command.parameters[0] == CEC_PLAY_MODE_PLAY_FORWARD)
+ {
+- CSingleLock lock(m_critSection);
++ CSingleLock lock(adapter->m_critSection);
+ cec_keypress key;
+ key.duration = 500;
+ key.keycode = CEC_USER_CONTROL_CODE_PLAY;
+- m_buttonQueue.push(key);
++ adapter->m_buttonQueue.push(key);
+ }
+ else if (command.parameters[0] == CEC_PLAY_MODE_PLAY_STILL)
+ {
+- CSingleLock lock(m_critSection);
++ CSingleLock lock(adapter->m_critSection);
+ cec_keypress key;
+ key.duration = 500;
+ key.keycode = CEC_USER_CONTROL_CODE_PAUSE;
+- m_buttonQueue.push(key);
++ adapter->m_buttonQueue.push(key);
+ }
+ }
+ break;
+@@ -591,15 +588,27 @@ void CPeripheralCecAdapter::ProcessNextCommand(void)
+ if (command.initiator == CECDEVICE_TV &&
+ command.parameters.size == 1 &&
+ command.parameters[0] == CEC_POWER_STATUS_ON &&
+- m_queryThread)
++ adapter->m_queryThread)
+ {
+- m_queryThread->Signal();
++ adapter->m_queryThread->Signal();
+ }
+ break;
+ default:
+ break;
+ }
+ }
++ return 1;
++}
++
++int CPeripheralCecAdapter::CecKeyPress(void *cbParam, const cec_keypress &key)
++{
++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
++ if (!adapter)
++ return 0;
++
++ CSingleLock lock(adapter->m_critSection);
++ adapter->m_buttonQueue.push(key);
++ return 1;
+ }
+
+ bool CPeripheralCecAdapter::GetNextCecKey(cec_keypress &key)
+@@ -612,10 +621,6 @@ bool CPeripheralCecAdapter::GetNextCecKey(cec_keypress &key)
+ m_buttonQueue.pop();
+ bReturn = true;
+ }
+- else if (m_cecAdapter->GetNextKeypress(&key))
+- {
+- bReturn = true;
+- }
+
+ return bReturn;
+ }
+@@ -861,35 +866,37 @@ void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting
+ }
+ }
+
+-void CPeripheralCecAdapter::FlushLog(void)
++int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message &message)
+ {
+- cec_log_message message;
+- while (m_cecAdapter && m_cecAdapter->GetNextLogMessage(&message))
++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam;
++ if (!adapter)
++ return 0;
++
++ int iLevel = -1;
++ switch (message.level)
+ {
+- int iLevel = -1;
+- switch (message.level)
+- {
+- case CEC_LOG_ERROR:
+- iLevel = LOGERROR;
+- break;
+- case CEC_LOG_WARNING:
+- iLevel = LOGWARNING;
+- break;
+- case CEC_LOG_NOTICE:
++ case CEC_LOG_ERROR:
++ iLevel = LOGERROR;
++ break;
++ case CEC_LOG_WARNING:
++ iLevel = LOGWARNING;
++ break;
++ case CEC_LOG_NOTICE:
++ iLevel = LOGDEBUG;
++ break;
++ case CEC_LOG_TRAFFIC:
++ case CEC_LOG_DEBUG:
++ if (adapter->GetSettingBool("cec_debug_logging"))
+ iLevel = LOGDEBUG;
+- break;
+- case CEC_LOG_TRAFFIC:
+- case CEC_LOG_DEBUG:
+- if (GetSettingBool("cec_debug_logging"))
+- iLevel = LOGDEBUG;
+- break;
+- default:
+- break;
+- }
+-
+- if (iLevel >= 0)
+- CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message);
++ break;
++ default:
++ break;
+ }
++
++ if (iLevel >= 0)
++ CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message);
++
++ return 1;
+ }
+
+ bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation)
+@@ -964,4 +971,12 @@ void CPeripheralCecAdapterQueryThread::Process(void)
+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification);
+ }
+
++void CPeripheralCecAdapter::EnableCallbacks(void)
++{
++ m_callbacks.CBCecLogMessage = &CecLogMessage;
++ m_callbacks.CBCecKeyPress = &CecKeyPress;
++ m_callbacks.CBCecCommand = &CecCommand;
++ m_cecAdapter->EnableCallbacks(this, &m_callbacks);
++}
++
+ #endif
+diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+index f10f2ea..085b683 100644
+--- a/xbmc/peripherals/devices/PeripheralCecAdapter.h
++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h
+@@ -89,12 +89,15 @@
+ virtual CStdString GetComPort(void);
+
+ protected:
+- virtual void FlushLog(void);
+- virtual bool GetNextCecKey(CEC::cec_keypress &key);
++ virtual void EnableCallbacks(void);
++ static int CecKeyPress(void *cbParam, const CEC::cec_keypress &key);
++ static int CecLogMessage(void *cbParam, const CEC::cec_log_message &message);
++ static int CecCommand(void *cbParam, const CEC::cec_command &command);
++
+ virtual bool GetNextKey(void);
++ virtual bool GetNextCecKey(CEC::cec_keypress &key);
+ virtual bool InitialiseFeature(const PeripheralFeature feature);
+ virtual void Process(void);
+- virtual void ProcessNextCommand(void);
+ virtual void ProcessVolumeChange(void);
+ virtual void SetMenuLanguage(const char *strLanguage);
+ static bool FindConfigLocation(CStdString &strString);
+@@ -113,6 +116,7 @@
+ unsigned int m_lastKeypress;
+ CecVolumeChange m_lastChange;
+ CPeripheralCecAdapterQueryThread *m_queryThread;
++ CEC::ICECCallbacks m_callbacks;
+ CCriticalSection m_critSection;
+ };
+
+--
+1.7.5.4
+
+
+From 51ab157f8dbc79c3c5e13d589b8523c5d59cb48e Mon Sep 17 00:00:00 2001
+From: Lars Op den Kamp
+Date: Thu, 12 Jan 2012 22:22:37 +0100
+Subject: [PATCH 7/7] cec: these new features and fixes need libCEC v1.4.0 or
+ higher
+
+---
+ configure.in | 2 +-
+ lib/libcec/Makefile | 2 +-
+ project/BuildDependencies/scripts/libcec_d.txt | 2 +-
+ tools/darwin/depends/libcec/Makefile | 2 +-
+ 4 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/configure.in b/configure.in
+index bca9239..d6909cd 100755
+--- a/configure.in
++++ b/configure.in
+@@ -1173,7 +1173,7 @@ if test "x$use_libcec" != "xno"; then
+
+ # libcec is dyloaded, so we need to check for its headers and link any depends.
+ if test "x$use_libcec" != "xno"; then
+- PKG_CHECK_MODULES([CEC],[libcec >= 1.1.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)])
++ PKG_CHECK_MODULES([CEC],[libcec >= 1.4.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)])
+
+ if test "x$use_libcec" != "xno"; then
+ INCLUDES="$INCLUDES $CEC_CFLAGS"
+diff --git a/lib/libcec/Makefile b/lib/libcec/Makefile
+index 8776161..5ca2a54 100644
+--- a/lib/libcec/Makefile
++++ b/lib/libcec/Makefile
+@@ -7,7 +7,7 @@
+
+ # lib name, version
+ LIBNAME=libcec
+-VERSION=1.2.0
++VERSION=1.4.0
+ SOURCE=$(LIBNAME)-$(VERSION)
+
+ # download location and format
+diff --git a/project/BuildDependencies/scripts/libcec_d.txt b/project/BuildDependencies/scripts/libcec_d.txt
+index ec9df80..867d639 100644
+diff --git a/tools/darwin/depends/libcec/Makefile b/tools/darwin/depends/libcec/Makefile
+index c6b44c0..e72dc10 100644
+--- a/tools/darwin/depends/libcec/Makefile
++++ b/tools/darwin/depends/libcec/Makefile
+@@ -2,7 +2,7 @@ include ../Makefile.include
+
+ # lib name, version
+ LIBNAME=libcec
+-VERSION=1.2.0
++VERSION=1.4.0
+ SOURCE=$(LIBNAME)-$(VERSION)
+ ARCHIVE=$(SOURCE).tar.gz
+
+--
+1.7.5.4
+
diff --git a/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-981-toggleButtonState.patch b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-981-toggleButtonState.patch
new file mode 100644
index 0000000000..17a606f1b1
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/patches/xbmc-rpi-cc57efc-981-toggleButtonState.patch
@@ -0,0 +1,304 @@
+diff -Naur xbmc-f3b0020/xbmc/guilib/GUIToggleButtonControl.h xbmc-f3b0020.patch/xbmc/guilib/GUIToggleButtonControl.h
+--- xbmc-f3b0020/xbmc/guilib/GUIToggleButtonControl.h 2011-12-10 22:16:22.000000000 +0100
++++ xbmc-f3b0020.patch/xbmc/guilib/GUIToggleButtonControl.h 2011-12-17 18:43:42.183704449 +0100
+@@ -57,6 +57,7 @@
+ virtual CStdString GetDescription() const;
+ void SetToggleSelect(const CStdString &toggleSelect);
+ void SetAltClickActions(const CGUIAction &clickActions);
++ bool IsSelected() const { return m_bSelected; };
+
+ protected:
+ virtual bool UpdateColors();
+diff -Naur xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/control.h xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/control.h
+--- xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/control.h 2011-12-10 22:16:21.000000000 +0100
++++ xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/control.h 2011-12-17 18:43:42.216705084 +0100
+@@ -135,6 +135,11 @@
+
+ typedef struct {
+ PyObject_HEAD_XBMC_CONTROL
++ bool bIsSelected;
++ } ControlToggle;
++
++ typedef struct {
++ PyObject_HEAD_XBMC_CONTROL
+ std::string strFont;
+ color_t textColor;
+ std::vector vecLabels;
+@@ -263,7 +268,8 @@
+ extern PyTypeObject ControlRadioButton_Type;
+ extern PyTypeObject ControlSlider_Type;
+ extern PyTypeObject ControlEdit_Type;
+-
++ extern PyTypeObject ControlToggle_Type;
++
+ CGUIControl* ControlLabel_Create(ControlLabel* pControl);
+ CGUIControl* ControlFadeLabel_Create(ControlFadeLabel* pControl);
+ CGUIControl* ControlTextBox_Create(ControlTextBox* pControl);
+@@ -276,6 +282,7 @@
+ CGUIControl* ControlRadioButton_Create(ControlRadioButton* pControl);
+ CGUIControl* ControlSlider_Create(ControlSlider* pControl);
+ CGUIControl* ControlEdit_Create(ControlEdit* pControl);
++ CGUIControl* ControlToggle_Create(ControlToggle* pControl);
+
+ void initControl_Type();
+ void initControlSpin_Type();
+@@ -291,6 +298,7 @@
+ void initControlRadioButton_Type();
+ void initControlSlider_Type();
+ void initControlEdit_Type();
++ void initControlToggle_Type();
+ }
+
+ #ifdef __cplusplus
+diff -Naur xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/controltogglebutton.cpp xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/controltogglebutton.cpp
+--- xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/controltogglebutton.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/controltogglebutton.cpp 2011-12-17 18:43:42.217705104 +0100
+@@ -0,0 +1,181 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include
++
++#include "guilib/GUIToggleButtonControl.h"
++#include "guilib/GUIFontManager.h"
++#include "control.h"
++#include "pyutil.h"
++
++using namespace std;
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++namespace PYXBMC
++{
++ PyObject* ControlToggle_New(
++ PyTypeObject *type,
++ PyObject *args,
++ PyObject *kwds )
++ {
++ static const char *keywords[] = {
++ "x", "y", "width", "height", "label",
++ "focusTexture", "noFocusTexture",
++ "textOffsetX", "textOffsetY", "alignment",
++ "font", "textColor", "disabledColor", "angle", "shadowColor", "focusedColor", NULL };
++ ControlToggle *self;
++ char* cFont = NULL;
++ char* cTextureFocus = NULL;
++ char* cTextureNoFocus = NULL;
++ char* cTextColor = NULL;
++ char* cDisabledColor = NULL;
++ char* cShadowColor = NULL;
++ char* cFocusedColor = NULL;
++
++ PyObject* pObjectText;
++
++ self = (ControlToggle*)type->tp_alloc(type, 0);
++ if (!self) return NULL;
++ new(&self->bIsSelected) bool();
++
++ if (!PyArg_ParseTupleAndKeywords(
++ args,
++ kwds,
++ (char*)"llllO|sslllssslss",
++ (char**)keywords,
++ &self->dwPosX,
++ &self->dwPosY,
++ &self->dwWidth,
++ &self->dwHeight,
++ &pObjectText,
++ &cTextureFocus,
++ &cTextureNoFocus,
++ &cFont,
++ &cTextColor,
++ &cDisabledColor,
++ &cShadowColor,
++ &cFocusedColor))
++ {
++ Py_DECREF( self );
++ return NULL;
++ }
++
++
++ cTextureFocus :
++ PyXBMCGetDefaultImage((char*)"button", (char*)"texturefocus", (char*)"button-focus.png");
++ cTextureNoFocus :
++ PyXBMCGetDefaultImage((char*)"button", (char*)"texturenofocus", (char*)"button-nofocus.jpg");
++
++ return (PyObject*)self;
++ }
++
++ void ControlToggle_Dealloc(ControlToggle* self)
++ {
++ self->ob_type->tp_free((PyObject*)self);
++ }
++
++
++ // isSelected() Method
++ PyDoc_STRVAR(isSelected__doc__,
++ "isSelected() -- Returns the toggle buttons's selected status.\n"
++ "\n"
++ "example:\n"
++ " - is = self.togglebutton.isSelected()\n");
++
++ PyObject* ControlToggle_IsSelected(ControlToggle *self, PyObject *args)
++ {
++ bool isSelected = false;
++
++ PyXBMCGUILock();
++ if (self->pGUIControl)
++ isSelected = ((CGUIToggleButtonControl*)self->pGUIControl)->IsSelected();
++ PyXBMCGUIUnlock();
++
++ return Py_BuildValue((char*)"b", isSelected);
++ }
++
++
++ PyMethodDef ControlToggle_methods[] = {
++ {(char*)"isSelected", (PyCFunction)ControlToggle_IsSelected, METH_VARARGS, isSelected__doc__},
++ {NULL, NULL, 0, NULL}
++ };
++
++ // ControlRadioButton class
++ PyDoc_STRVAR(ControlToggle__doc__,
++ "ControlRadioButton class.\n"
++ "\n"
++ "ControlRadioButton(x, y, width, height, label[, focusTexture, noFocusTexture, textOffsetX, textOffsetY,\n"
++ " alignment, font, textColor, disabledColor, angle, shadowColor, focusedColor,\n"
++ " radioFocusTexture, noRadioFocusTexture])\n"
++ "\n"
++ "x : integer - x coordinate of control.\n"
++ "y : integer - y coordinate of control.\n"
++ "width : integer - width of control.\n"
++ "height : integer - height of control.\n"
++ "label : string or unicode - text string.\n"
++ "focusTexture : [opt] string - filename for focus texture.\n"
++ "noFocusTexture : [opt] string - filename for no focus texture.\n"
++ "textOffsetX : [opt] integer - x offset of label.\n"
++ "textOffsetY : [opt] integer - y offset of label.\n"
++ "alignment : [opt] integer - alignment of label - *Note, see xbfont.h\n"
++ "font : [opt] string - font used for label text. (e.g. 'font13')\n"
++ "textColor : [opt] hexstring - color of enabled radio button's label. (e.g. '0xFFFFFFFF')\n"
++ "disabledColor : [opt] hexstring - color of disabled radio button's label. (e.g. '0xFFFF3300')\n"
++ "angle : [opt] integer - angle of control. (+ rotates CCW, - rotates CW)\n"
++ "shadowColor : [opt] hexstring - color of radio button's label's shadow. (e.g. '0xFF000000')\n"
++ "focusedColor : [opt] hexstring - color of focused radio button's label. (e.g. '0xFF00FFFF')\n"
++ "radioFocusTexture : [opt] string - filename for radio focus texture.\n"
++ "noRadioFocusTexture : [opt] string - filename for radio no focus texture.\n"
++ "\n"
++ "*Note, You can use the above as keywords for arguments and skip certain optional arguments.\n"
++ " Once you use a keyword, all following arguments require the keyword.\n"
++ " After you create the control, you need to add it to the window with addControl().\n"
++ "\n"
++ "example:\n"
++ " - self.radiobutton = xbmcgui.ControlToggleButton(100, 250, 200, 50, 'Status', font='font14')\n");
++
++ // Restore code and data sections to normal.
++
++ PyTypeObject ControlToggle_Type;
++
++ void initControlToggle_Type()
++ {
++ PyXBMCInitializeTypeObject(&ControlToggle_Type);
++
++ ControlToggle_Type.tp_name = (char*)"xbmcgui.ControlToggleButton";
++ ControlToggle_Type.tp_basicsize = sizeof(ControlToggle);
++ ControlToggle_Type.tp_dealloc = (destructor)ControlToggle_Dealloc;
++ ControlToggle_Type.tp_compare = 0;
++ ControlToggle_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
++ ControlToggle_Type.tp_doc = ControlToggle__doc__;
++ ControlToggle_Type.tp_methods = ControlToggle_methods;
++ ControlToggle_Type.tp_base = &Control_Type;
++ ControlToggle_Type.tp_new = ControlToggle_New;
++ }
++}
++
++#ifdef __cplusplus
++}
++#endif
+diff -Naur xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/Makefile.in xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/Makefile.in
+--- xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/Makefile.in 2011-12-10 22:16:21.000000000 +0100
++++ xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/Makefile.in 2011-12-17 18:44:47.447960296 +0100
+@@ -13,6 +13,7 @@
+ controlslider.cpp \
+ controlspin.cpp \
+ controltextbox.cpp \
++ controltogglebutton.cpp \
+ dialog.cpp \
+ GUIPythonWindow.cpp \
+ GUIPythonWindowDialog.cpp \
+diff -Naur xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/window.cpp xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/window.cpp
+--- xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/window.cpp 2011-12-10 22:16:21.000000000 +0100
++++ xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/window.cpp 2011-12-17 18:43:42.218705123 +0100
+@@ -277,6 +277,12 @@
+ if (li.font) ((ControlEdit*)pControl)->strFont = li.font->GetFontName();
+ ((ControlButton*)pControl)->align = li.align;
+ break;
++ case CGUIControl::GUICONTROL_TOGGLEBUTTON:
++ pControl = (Control*)ControlToggle_Type.tp_alloc(&ControlToggle_Type, 0);
++ new(&((ControlToggle*)pControl)->bIsSelected) bool();
++
++ break;
++
+ default:
+ break;
+ }
+diff -Naur xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/xbmcguimodule.cpp xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/xbmcguimodule.cpp
+--- xbmc-f3b0020/xbmc/interfaces/python/xbmcmodule/xbmcguimodule.cpp 2011-12-10 22:16:21.000000000 +0100
++++ xbmc-f3b0020.patch/xbmc/interfaces/python/xbmcmodule/xbmcguimodule.cpp 2011-12-17 18:43:42.219705142 +0100
+@@ -138,6 +138,7 @@
+ initAction_Type();
+ initControlRadioButton_Type();
+ initControlEdit_Type();
++ initControlToggle_Type();
+
+ if (PyType_Ready(&Window_Type) < 0 ||
+ PyType_Ready(&WindowDialog_Type) < 0 ||
+@@ -160,7 +161,8 @@
+ PyType_Ready(&ControlSlider_Type) < 0 ||
+ PyType_Ready(&ControlRadioButton_Type) < 0 ||
+ PyType_Ready(&ControlEdit_Type) < 0 ||
+- PyType_Ready(&Action_Type) < 0)
++ PyType_Ready(&Action_Type) < 0 ||
++ PyType_Ready(&ControlToggle_Type) < 0)
+ return;
+
+ }
+@@ -200,6 +202,7 @@
+ Py_INCREF(&Action_Type);
+ Py_INCREF(&ControlRadioButton_Type);
+ Py_INCREF(&ControlEdit_Type);
++ Py_INCREF(&ControlToggle_Type);
+
+ pXbmcGuiModule = Py_InitModule3((char*)"xbmcgui", xbmcGuiMethods, xbmcgui_module_documentation);
+
+@@ -227,7 +230,8 @@
+ PyModule_AddObject(pXbmcGuiModule, (char*)"Action", (PyObject *)&Action_Type);
+ PyModule_AddObject(pXbmcGuiModule, (char*)"ControlRadioButton", (PyObject*)&ControlRadioButton_Type);
+ PyModule_AddObject(pXbmcGuiModule, (char*)"ControlEdit", (PyObject*)&ControlEdit_Type);
+-
++ PyModule_AddObject(pXbmcGuiModule, (char*)"ControlToggle", (PyObject*)&ControlToggle_Type);
++
+ PyModule_AddStringConstant(pXbmcGuiModule, (char*)"__author__", (char*)PY_XBMC_AUTHOR);
+ PyModule_AddStringConstant(pXbmcGuiModule, (char*)"__date__", (char*)"14 July 2006");
+ PyModule_AddStringConstant(pXbmcGuiModule, (char*)"__version__", (char*)"1.2");
+diff -Naur xbmc-f3b0020/XBMC.xcodeproj/project.pbxproj xbmc-f3b0020.patch/XBMC.xcodeproj/project.pbxproj
diff --git a/packages/mediacenter/xbmc-rpi/profile.d/xbmc.conf b/packages/mediacenter/xbmc-rpi/profile.d/xbmc.conf
new file mode 100644
index 0000000000..7677f0d264
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/profile.d/xbmc.conf
@@ -0,0 +1,41 @@
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+# Copyright (C) 2010-2011 Roman Weber (roman@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+# Mediacenter environment variables.
+#
+# This file contains non-OpenELEC evironment variables as well as OpenELEC
+# evironment variables that are not user defined.
+################################################################################
+
+if [ -z "$XBMC_STARTDELAY" ]; then
+ XBMC_STARTDELAY="1000000"
+fi
+
+XBMC_HOME="/usr/share/xbmc"
+
+export XBMC_HOME
+
+GPUDEVICE=$(lspci -n | grep 0300)
+GPUTYPE="OTHER"
+[ "$(echo $GPUDEVICE | grep 8086)" ] && GPUTYPE="INTEL" # 8086 == INTEL
+[ "$(echo $GPUDEVICE | grep 10de)" ] && GPUTYPE="NVIDIA" # 10de == NVIDIA
+[ "$(echo $GPUDEVICE | grep 1002)" ] && GPUTYPE="AMD" # 1002 == AMD
+
+export GPUTYPE
\ No newline at end of file
diff --git a/packages/mediacenter/xbmc-rpi/scripts/cputemp b/packages/mediacenter/xbmc-rpi/scripts/cputemp
new file mode 100755
index 0000000000..3c35564ed1
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/scripts/cputemp
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+# inspired by
+# https://github.com/xtranophilist/gnome-shell-extension-cpu-temperature/blob/master/extension.js
+
+TEMP=0
+
+if [ -f /sys/devices/platform/coretemp.0/temp1_input ]; then
+ # used with coretemp
+ TEMP=`cat /sys/devices/platform/coretemp.0/temp1_input`
+elif [ -f /sys/devices/platform/coretemp.0/temp2_input ]; then
+ # used with coretemp
+ TEMP=`cat /sys/devices/platform/coretemp.0/temp2_input`
+elif [ -f /sys/bus/acpi/devices/LNXTHERM\:00/thermal_zone/temp ]; then
+ # used on some intel systems
+ TEMP=`cat /sys/bus/acpi/devices/LNXTHERM\:00/thermal_zone/temp`
+elif [ -f /sys/devices/virtual/thermal/thermal_zone0/temp ]; then
+ # used on some intel systems
+ TEMP=`cat /sys/devices/virtual/thermal/thermal_zone0/temp`
+elif [ -f /sys/class/hwmon/hwmon0/temp1_input ]; then
+ # hwmon for new 2.6.39, 3.0 linux kernels
+ TEMP=`cat /sys/class/hwmon/hwmon0/temp1_input`
+elif [ -f /sys/class/hwmon/hwmon0/device/temp1_input ]; then
+ # used on AMD systems
+ TEMP=`cat /sys/class/hwmon/hwmon0/device/temp1_input`
+elif [ -f /sys/class/hwmon/hwmon0/device/temp2_input ]; then
+ # used on ION systems
+ TEMP=`cat /sys/class/hwmon/hwmon0/device/temp2_input`
+fi
+
+echo "$(( $TEMP / 1000 )) C"
diff --git a/packages/mediacenter/xbmc-rpi/scripts/gputemp b/packages/mediacenter/xbmc-rpi/scripts/gputemp
new file mode 100755
index 0000000000..7767e885a9
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/scripts/gputemp
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+################################################################################
+# Copyright (C) 2009-2010 OpenELEC.tv
+# http://www.openelec.tv
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+TEMP="0"
+
+if lspci -n | grep 0300 | grep -q 10de; then
+ [ -f /usr/bin/nvidia-smi ] && TEMP=`/usr/bin/nvidia-smi -q -x | grep 'gpu_temp' | awk '{ print $1 }' | sed 's,,,g'`
+fi
+
+if lspci -n | grep 0300 | grep -q 1002; then
+ if [ -f /storage/.config/xorg.conf ]; then
+ XORG="/storage/.config/xorg.conf"
+ else
+ XORG="/etc/X11/xorg-fglrx.conf"
+ fi
+ [ -f /usr/bin/aticonfig ] && TEMP=`/usr/bin/aticonfig -i $XORG --od-gettemperature | grep Temperature | cut -f 2 -d "-" | cut -f 1 -d "." | sed -e "s, ,,"`
+fi
+
+echo "${TEMP} C"
diff --git a/packages/mediacenter/xbmc-rpi/sleep.d/00_addon-sleep b/packages/mediacenter/xbmc-rpi/sleep.d/00_addon-sleep
new file mode 100755
index 0000000000..0a9d84e0c4
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/sleep.d/00_addon-sleep
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+. /etc/profile
+
+for script in $HOME/.xbmc/addons/*/sleep.d/*.power; do
+ progress "running addon sleep script $script ($1)..."
+ sh $script $1
+done
diff --git a/packages/mediacenter/xbmc-rpi/sleep.d/61_xbmc_lirc b/packages/mediacenter/xbmc-rpi/sleep.d/61_xbmc_lirc
new file mode 100755
index 0000000000..6df3ad6b31
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/sleep.d/61_xbmc_lirc
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+. /etc/profile
+
+case "$1" in
+ hibernate|suspend)
+ xbmc-send --host=127.0.0.1 -a "LIRC.Stop"
+ ;;
+ thaw|resume)
+ xbmc-send --host=127.0.0.1 -a "LIRC.Start"
+ ;;
+ *) exit $NA
+ ;;
+esac
diff --git a/packages/mediacenter/xbmc-rpi/sleep.d/62_xbmc_lcd b/packages/mediacenter/xbmc-rpi/sleep.d/62_xbmc_lcd
new file mode 100755
index 0000000000..7b93b3c3a3
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/sleep.d/62_xbmc_lcd
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+. /etc/profile
+
+case "$1" in
+ hibernate|suspend)
+ xbmc-send --host=127.0.0.1 -a "LCD.Suspend"
+ ;;
+ thaw|resume)
+ xbmc-send --host=127.0.0.1 -a "LCD.Resume"
+ ;;
+ *) exit $NA
+ ;;
+esac
diff --git a/packages/mediacenter/xbmc-rpi/sleep.d/99_reload_skin b/packages/mediacenter/xbmc-rpi/sleep.d/99_reload_skin
new file mode 100755
index 0000000000..fd0a13ed3c
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/sleep.d/99_reload_skin
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+. /etc/profile
+
+case "$1" in
+ thaw|resume)
+ xbmc-send --host=127.0.0.1 -a "ReloadSkin()" &
+ ;;
+ *) exit $NA
+ ;;
+esac
diff --git a/packages/mediacenter/xbmc-rpi/splash/splash.png b/packages/mediacenter/xbmc-rpi/splash/splash.png
new file mode 100644
index 0000000000..6b2897b0a1
Binary files /dev/null and b/packages/mediacenter/xbmc-rpi/splash/splash.png differ
diff --git a/packages/mediacenter/xbmc-rpi/splash/splash1.png b/packages/mediacenter/xbmc-rpi/splash/splash1.png
new file mode 100644
index 0000000000..ac0aa0052f
Binary files /dev/null and b/packages/mediacenter/xbmc-rpi/splash/splash1.png differ
diff --git a/packages/mediacenter/xbmc-rpi/unpack b/packages/mediacenter/xbmc-rpi/unpack
new file mode 100755
index 0000000000..04e7dbae71
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/unpack
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+. config/options $1
+
+echo "### Applying project based patches ###"
+
+for patch in `ls $PROJECT_DIR/$PROJECT/patches/$1`; do
+ cat $PROJECT_DIR/$PROJECT/patches/$1/$patch | patch -d \
+ `echo $PKG_BUILD | cut -f1 -d\ ` -p1
+done
diff --git a/packages/mediacenter/xbmc-rpi/xbmc-rpi-cc57efc-013-reenable_lcd_config_settings-0.1.patch b/packages/mediacenter/xbmc-rpi/xbmc-rpi-cc57efc-013-reenable_lcd_config_settings-0.1.patch
new file mode 100644
index 0000000000..656dcac934
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/xbmc-rpi-cc57efc-013-reenable_lcd_config_settings-0.1.patch
@@ -0,0 +1,13 @@
+diff -Naur xbmc-9389dc8/xbmc/settings/GUISettings.cpp xbmc-9389dc8.patch/xbmc/settings/GUISettings.cpp
+--- xbmc-9389dc8/xbmc/settings/GUISettings.cpp 2011-09-01 23:34:05.267139356 +0200
++++ xbmc-9389dc8.patch/xbmc/settings/GUISettings.cpp 2011-09-01 23:34:52.098765331 +0200
+@@ -423,7 +423,8 @@
+ AddString(vs, "videoscreen.testpattern",226,"", BUTTON_CONTROL_STANDARD);
+ #endif
+ #if defined(_LINUX) && !defined(__APPLE__)
+- AddBool(NULL, "videoscreen.haslcd", 4501, false);
++ AddSeparator(vs, "videoscreen.sep2");
++ AddBool(vs, "videoscreen.haslcd", 4501, false);
+ #endif
+
+ CSettingsCategory* ao = AddCategory(4, "audiooutput", 772);
diff --git a/packages/mediacenter/xbmc-rpi/xbmc-rpi-cc57efc-902.01-xvba_support-eb7c9d5b4988582b041b97c88903e1d771bdbc33.patch b/packages/mediacenter/xbmc-rpi/xbmc-rpi-cc57efc-902.01-xvba_support-eb7c9d5b4988582b041b97c88903e1d771bdbc33.patch
new file mode 100644
index 0000000000..c16d5aee65
--- /dev/null
+++ b/packages/mediacenter/xbmc-rpi/xbmc-rpi-cc57efc-902.01-xvba_support-eb7c9d5b4988582b041b97c88903e1d771bdbc33.patch
@@ -0,0 +1,7485 @@
+diff --git a/configure.in b/configure.in
+index e1cc9d2..d0d3beb 100755
+--- a/configure.in
++++ b/configure.in
+@@ -98,6 +98,8 @@ vaapi_not_found="== Could not find libva. VAAPI support disabled. =="
+ vaapi_disabled="== VAAPI support manually disabled. =="
+ crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. =="
+ crystalhd_disabled="== CrystalHD support manually disabled. =="
++xvba_not_found="== Could not find amdxvba.h. XVBA support disabled. =="
++xvba_disabled="== XVBA support manually disabled. =="
+ vdadecoder_enabled="== VDADecoder support enabled. =="
+ vdadecoder_disabled="== VDADecoder support manually disabled. =="
+ vtbdecoder_enabled="== VTBDecoder support enabled. =="
+@@ -204,6 +206,12 @@ AC_ARG_ENABLE([crystalhd],
+ [enable CrystalHD decoding (default is auto)])],
+ [use_crystalhd=$enableval],
+ [use_crystalhd=auto])
++
++AC_ARG_ENABLE([xvba],
++ [AS_HELP_STRING([--enable-xvba],
++ [enable XVBA decoding (default is auto)])],
++ [use_xvba=$enableval],
++ [use_xvba=auto])
+
+ AC_ARG_ENABLE([vdadecoder],
+ [AS_HELP_STRING([--enable-vdadecoder],
+@@ -1382,6 +1390,38 @@ else
+ USE_CRYSTALHD=0
+ fi
+
++# XVBA
++if test "x$use_xvba" != "xno"; then
++ if test "$host_vendor" = "apple" ; then
++ if test "x$use_xvba" = "xyes"; then
++ AC_MSG_ERROR([XVBA not supported on this platform])
++ else
++ use_xvba="no"
++ AC_MSG_NOTICE($xvba_disabled)
++ fi
++ USE_XVBA=0
++ else
++ initial_val=$use_xvba
++ AC_CHECK_HEADER([amd/amdxvba.h],, use_xvba=no, [#include ])
++
++ if test "x$use_xvba" = "xno"; then
++ if test "x$initial_val" = "xyes"; then
++ AC_MSG_ERROR($xvba_not_found)
++ else
++ AC_MSG_RESULT($xvba_not_found)
++ fi
++ USE_XVBA=0
++ else
++ AC_DEFINE([HAVE_LIBXVBA], [1], [Define to 1 if you have the 'xvba' header (amdxvba.h)])
++ USE_XVBA=1
++ fi
++ fi
++else
++ AC_MSG_NOTICE($xvba_disabled)
++ USE_XVBA=0
++fi
++
++
+ # VDADecoder
+ if test "x$use_vdadecoder" != "xno"; then
+ if test "$host_vendor" = "apple" ; then
+@@ -1578,6 +1618,12 @@ else
+ final_message="$final_message\n CrystalHD:\tNo"
+ fi
+
++if test "x$use_xvba" != "xno"; then
++ final_message="$final_message\n XVBA:\t\tYes"
++else
++ final_message="$final_message\n XVBA:\t\tNo"
++fi
++
+ if test "x$use_vdadecoder" != "xno"; then
+ final_message="$final_message\n VDADecoder:\tYes"
+ else
+@@ -1952,6 +1998,7 @@ AC_SUBST(USE_OPENGLES)
+ AC_SUBST(USE_VDPAU)
+ AC_SUBST(USE_VAAPI)
+ AC_SUBST(USE_CRYSTALHD)
++AC_SUBST(USE_XVBA)
+ AC_SUBST(USE_LIBSMBCLIENT)
+ AC_SUBST(USE_LIBNFS)
+ AC_SUBST(USE_LIBAFPCLIENT)
+@@ -2094,6 +2141,7 @@ XB_CONFIG_MODULE([lib/ffmpeg], [
+ --enable-gpl \
+ `if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \
+ `if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \
++ `if test "x$use_xvba" != "xno"; then echo --enable-xvba; else echo --disable-xvba; fi` \
+ --enable-protocol=http \
+ --enable-pthreads \
+ --enable-runtime-cpudetect \
+diff --git a/language/English/strings.xml b/language/English/strings.xml
+index 090a1b9..7a976cf 100644
+--- a/language/English/strings.xml
++++ b/language/English/strings.xml
+@@ -1232,6 +1232,8 @@
+ Allow hardware acceleration (OpenMax)
+ Pixel Shaders
+ Allow hardware acceleration (VideoToolbox)
++ Allow hardware acceleration (XVBA)
++ Use XvBA shared surfaces
+
+ A/V sync method
+ Audio clock
+diff --git a/lib/UnrarXLib/extract.cpp b/lib/UnrarXLib/extract.cpp
+index b4a8091..da60857 100644
+--- a/lib/UnrarXLib/extract.cpp
++++ b/lib/UnrarXLib/extract.cpp
+@@ -1,9 +1,5 @@
+ #include "rar.hpp"
+ #include "Util.h"
+-#ifdef _LINUX
+-#include "XSyncUtils.h"
+-#include "XEventUtils.h"
+-#endif
+
+ // a cautious wrapper around strncpy
+ char *strncpy_null_terminated(char *dest, const char *src, size_t n)
+diff --git a/lib/UnrarXLib/unpack.cpp b/lib/UnrarXLib/unpack.cpp
+index 265b54f..bc2f220 100644
+--- a/lib/UnrarXLib/unpack.cpp
++++ b/lib/UnrarXLib/unpack.cpp
+@@ -8,11 +8,6 @@
+ #include "unpack20.cpp"
+ #endif
+
+-#ifdef _LINUX
+-#include "XSyncUtils.h"
+-#include "XEventUtils.h"
+-#endif
+-
+ Unpack::Unpack(ComprDataIO *DataIO)
+ {
+ UnpIO=DataIO;
+diff --git a/lib/UnrarXLib/unpack15.cpp b/lib/UnrarXLib/unpack15.cpp
+index e1b5f10..725e2be 100644
+--- a/lib/UnrarXLib/unpack15.cpp
++++ b/lib/UnrarXLib/unpack15.cpp
+@@ -1,7 +1,3 @@
+-#ifdef _LINUX
+-#include "XSyncUtils.h"
+-#endif
+-
+ #define STARTL1 2
+ static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
+ 0xee00,0xf000,0xf200,0xf200,0xffff};
+diff --git a/lib/ffmpeg/configure b/lib/ffmpeg/configure
+index fec801c..fc73296 100755
+--- a/lib/ffmpeg/configure
++++ b/lib/ffmpeg/configure
+@@ -111,6 +111,7 @@ Configuration options:
+ --disable-vaapi disable VAAPI code
+ --disable-vdpau disable VDPAU code
+ --disable-dxva2 disable DXVA2 code
++ --disable-xvba disable XVBA code
+ --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
+ --enable-hardcoded-tables use hardcoded tables instead of runtime generation
+ --enable-memalign-hack emulate memalign, interferes with memory debuggers
+@@ -932,6 +933,7 @@ CONFIG_LIST="
+ swscale_alpha
+ vaapi
+ vdpau
++ xvba
+ version3
+ x11grab
+ zlib
+@@ -1240,6 +1242,7 @@ h264_decoder_select="golomb h264dsp h264pred"
+ h264_dxva2_hwaccel_deps="dxva2api_h"
+ h264_dxva2_hwaccel_select="dxva2 h264_decoder"
+ h264_vaapi_hwaccel_select="vaapi"
++h264_xvba_hwaccel_select="xvba"
+ h264_vdpau_decoder_select="vdpau h264_decoder"
+ imc_decoder_select="fft mdct"
+ jpegls_decoder_select="golomb"
+@@ -1263,6 +1266,7 @@ mpeg2_dxva2_hwaccel_deps="dxva2api_h"
+ mpeg2_dxva2_hwaccel_select="dxva2 mpeg2video_decoder"
+ mpeg2_vaapi_hwaccel_select="vaapi mpeg2video_decoder"
+ mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder"
++mpeg2_xvba_hwaccel_select="xvba mpeg2video_decoder"
+ mpeg4_vdpau_decoder_deps="vdpau_vdpau_h vdpau_vdpau_x11_h vdpau_mpeg4_support"
+ mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder"
+ mpeg_xvmc_decoder_deps="X11_extensions_XvMClib_h"
+@@ -1306,6 +1310,7 @@ vc1_decoder_select="h263_decoder"
+ vc1_dxva2_hwaccel_deps="dxva2api_h DXVA_PictureParameters_wDecodedPictureIndex"
+ vc1_dxva2_hwaccel_select="dxva2 vc1_decoder"
+ vc1_vaapi_hwaccel_select="vaapi vc1_decoder"
++vc1_xvba_hwaccel_select="xvba vc1_decoder"
+ vc1_vdpau_decoder_select="vdpau vc1_decoder"
+ vorbis_decoder_select="mdct"
+ vorbis_encoder_select="mdct"
+@@ -1327,12 +1332,14 @@ wmv3_decoder_select="vc1_decoder"
+ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
+ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
+ wmv3_vdpau_decoder_select="vc1_vdpau_decoder"
++wmv3_xvba_hwaccel_select="vc1_xvba_hwaccel"
+ zlib_decoder_select="zlib"
+ zlib_encoder_select="zlib"
+ zmbv_decoder_select="zlib"
+ zmbv_encoder_select="zlib"
+
+ vaapi_deps="va_va_h"
++xvba_deps="amd_amdxvba_h"
+ vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
+
+ # parsers
+@@ -2762,6 +2769,7 @@ check_header sys/select.h
+ check_header termios.h
+ check_header vdpau/vdpau.h
+ check_header vdpau/vdpau_x11.h
++check_header amd/amdxvba.h
+ check_cpp_condition vdpau/vdpau.h "defined(VDP_DECODER_PROFILE_MPEG4_PART2_SP)" && enable vdpau_mpeg4_support
+
+ check_header X11/extensions/XvMClib.h
+diff --git a/lib/ffmpeg/libavcodec/Makefile b/lib/ffmpeg/libavcodec/Makefile
+index 6a0a05b..65cca69 100644
+--- a/lib/ffmpeg/libavcodec/Makefile
++++ b/lib/ffmpeg/libavcodec/Makefile
+@@ -3,7 +3,7 @@ include $(SUBDIR)../config.mak
+ NAME = avcodec
+ FFLIBS = avcore avutil
+
+-HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h
++HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h xvba.h
+
+ OBJS = allcodecs.o \
+ audioconvert.o \
+@@ -43,6 +43,7 @@ RDFT-OBJS-$(CONFIG_HARDCODED_TABLES) += sin_tables.o
+ OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes)
+ OBJS-$(CONFIG_VAAPI) += vaapi.o
+ OBJS-$(CONFIG_VDPAU) += vdpau.o
++OBJS-$(CONFIG_XVBA) += xvba.o
+
+ # decoders/encoders/hardware accelerators
+ OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
+@@ -169,6 +170,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264.o \
+ mpegvideo.o error_resilience.o
+ OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
+ OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
++OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o
+ OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o
+ OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o
+ OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o
+@@ -246,6 +248,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \
+ mpegvideo.o error_resilience.o
+ OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
+ OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
++OBJS-$(CONFIG_MPEG2_XVBA_HWACCEL) += xvba_mpeg2.o
+ OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o \
+ mpegvideo.o error_resilience.o
+ OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \
+@@ -379,6 +382,7 @@ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \
+ intrax8.o intrax8dsp.o
+ OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
+ OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
++OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o
+ OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
+ OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
+ OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
+@@ -647,6 +651,7 @@ SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
+ SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h
+ SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h
+ SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h
++SKIPHEADERS-$(CONFIG_XVBA) += xvba_internal.h
+ SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h
+ SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
+ SKIPHEADERS += mpegaudio3.h
+diff --git a/lib/ffmpeg/libavcodec/allcodecs.c b/lib/ffmpeg/libavcodec/allcodecs.c
+index 04c5c6a..38b8791 100644
+--- a/lib/ffmpeg/libavcodec/allcodecs.c
++++ b/lib/ffmpeg/libavcodec/allcodecs.c
+@@ -57,13 +57,17 @@ void avcodec_register_all(void)
+ REGISTER_HWACCEL (H263_VAAPI, h263_vaapi);
+ REGISTER_HWACCEL (H264_DXVA2, h264_dxva2);
+ REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);
++ REGISTER_HWACCEL (H264_XVBA, h264_xvba);
+ REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2);
+ REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);
+ REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi);
++ REGISTER_HWACCEL (MPEG2_XVBA, mpeg2_xvba);
+ REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2);
+ REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi);
++ REGISTER_HWACCEL (VC1_XVBA, vc1_xvba);
+ REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2);
+ REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi);
++ REGISTER_HWACCEL (WMV3_XVBA, wmv3_xvba);
+
+ /* video codecs */
+ REGISTER_ENCODER (A64MULTI, a64multi);
+diff --git a/lib/ffmpeg/libavcodec/h264.c b/lib/ffmpeg/libavcodec/h264.c
+index 0e002ce..d054b20 100644
+--- a/lib/ffmpeg/libavcodec/h264.c
++++ b/lib/ffmpeg/libavcodec/h264.c
+@@ -55,6 +55,7 @@ static const uint8_t div6[52]={
+ static const enum PixelFormat hwaccel_pixfmt_list_h264_jpeg_420[] = {
+ PIX_FMT_DXVA2_VLD,
+ PIX_FMT_VAAPI_VLD,
++ PIX_FMT_XVBA_VLD,
+ PIX_FMT_YUVJ420P,
+ PIX_FMT_NONE
+ };
+diff --git a/lib/ffmpeg/libavcodec/mpegvideo.c b/lib/ffmpeg/libavcodec/mpegvideo.c
+index 31642e6..56113c7 100644
+--- a/lib/ffmpeg/libavcodec/mpegvideo.c
++++ b/lib/ffmpeg/libavcodec/mpegvideo.c
+@@ -117,6 +117,7 @@ const enum PixelFormat ff_pixfmt_list_420[] = {
+ const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = {
+ PIX_FMT_DXVA2_VLD,
+ PIX_FMT_VAAPI_VLD,
++ PIX_FMT_XVBA_VLD,
+ PIX_FMT_YUV420P,
+ PIX_FMT_NONE
+ };
+diff --git a/lib/ffmpeg/libavcodec/xvba.c b/lib/ffmpeg/libavcodec/xvba.c
+new file mode 100644
+index 0000000..48fd905
+--- /dev/null
++++ b/lib/ffmpeg/libavcodec/xvba.c
+@@ -0,0 +1,65 @@
++/*
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++
++/**
++ * \addtogroup XVBA_Decoding
++ *
++ * @{
++ */
++
++#include
++#include "xvba.h"
++#include "avcodec.h"
++
++int ff_xvba_translate_profile(int profile) {
++
++ if (profile == 66)
++ return 1;
++ else if (profile == 77)
++ return 2;
++ else if (profile == 100)
++ return 3;
++ else if (profile == 0)
++ return 4;
++ else if (profile == 1)
++ return 5;
++ else if (profile == 3)
++ return 6;
++ else
++ return -1;
++}
++
++void ff_xvba_add_slice_data(struct xvba_render_state *render, const void *buffer, uint32_t size) {
++
++ render->buffers = av_fast_realloc(
++ render->buffers,
++ &render->buffers_alllocated,
++ sizeof(struct xvba_bitstream_buffers)*(render->num_slices + 1)
++ );
++
++ render->buffers[render->num_slices].buffer = buffer;
++ render->buffers[render->num_slices].size = size;
++
++ render->num_slices++;
++}
++
+diff --git a/lib/ffmpeg/libavcodec/xvba.h b/lib/ffmpeg/libavcodec/xvba.h
+new file mode 100644
+index 0000000..a62d649
+--- /dev/null
++++ b/lib/ffmpeg/libavcodec/xvba.h
+@@ -0,0 +1,65 @@
++/*
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef AVCODEC_XVBA_H
++#define AVCODEC_XVBA_H
++
++#include
++#include
++#include
++
++
++/**
++ * \defgroup XVBA_Decoding VA API Decoding
++ * \ingroup Decoder
++ * @{
++ */
++
++/** \brief The videoSurface is used for rendering. */
++#define FF_XVBA_STATE_USED_FOR_RENDER 1
++
++/**
++ * \brief The videoSurface is needed for reference/prediction.
++ * The codec manipulates this.
++ */
++#define FF_XVBA_STATE_USED_FOR_REFERENCE 2
++
++/* @} */
++
++struct xvba_bitstream_buffers
++{
++ const void *buffer;
++ unsigned int size;
++};
++
++struct xvba_render_state {
++
++ int state; ///< Holds FF_XVBA_STATE_* values.
++ void *surface;
++ XVBAPictureDescriptor *picture_descriptor;
++ XVBAQuantMatrixAvc *iq_matrix;
++ unsigned int num_slices;
++ struct xvba_bitstream_buffers *buffers;
++ uint32_t buffers_alllocated;
++};
++
++#endif /* AVCODEC_XVBA_H */
+diff --git a/lib/ffmpeg/libavcodec/xvba_h264.c b/lib/ffmpeg/libavcodec/xvba_h264.c
+new file mode 100644
+index 0000000..0d98dea
+--- /dev/null
++++ b/lib/ffmpeg/libavcodec/xvba_h264.c
+@@ -0,0 +1,180 @@
++/*
++ * H.264 HW decode acceleration through XVBA
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "xvba.h"
++#include "xvba_internal.h"
++#include "h264.h"
++#include
++
++/** @file
++ * This file implements the glue code between FFmpeg's and XvBA API's
++ * structures for H.264 decoding.
++ */
++
++
++/** Initialize and start decoding a frame with XVBA. */
++static int start_frame(AVCodecContext *avctx,
++ av_unused const uint8_t *buffer,
++ av_unused uint32_t size)
++{
++ H264Context * const h = avctx->priv_data;
++ MpegEncContext * const s = &h->s;
++ struct xvba_render_state *render;
++ XVBAPictureDescriptor *pic_descriptor;
++ int i;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (render->picture_descriptor == 0)
++ return -1;
++
++ pic_descriptor = render->picture_descriptor;
++
++ for (i = 0; i < 2; ++i) {
++ int foc = s->current_picture_ptr->field_poc[i];
++ if (foc == INT_MAX)
++ foc = 0;
++ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc;
++ }
++
++ pic_descriptor->avc_frame_num = h->frame_num;
++
++ render->num_slices = 0;
++
++ return 0;
++}
++
++/** End a hardware decoding based frame. */
++static int end_frame(AVCodecContext *avctx)
++{
++ H264Context * const h = avctx->priv_data;
++ MpegEncContext * const s = &h->s;
++ struct xvba_render_state *render;
++ XVBAPictureDescriptor *pic_descriptor;
++ XVBAQuantMatrixAvc *iq_matrix;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (render->picture_descriptor == 0 || render->iq_matrix == 0)
++ return -1;
++
++ pic_descriptor = render->picture_descriptor;
++ iq_matrix = render->iq_matrix;
++
++ av_dlog(avctx, "end_frame()\n");
++
++ /* Fill in Picture Parameters*/
++ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile);
++ pic_descriptor->level = avctx->level;
++ pic_descriptor->width_in_mb = s->mb_width;
++ pic_descriptor->height_in_mb = s->mb_height;
++ pic_descriptor->picture_structure = s->picture_structure;
++ pic_descriptor->chroma_format = s->chroma_format ? s->chroma_format : 1;
++ pic_descriptor->avc_intra_flag = (h->slice_type == FF_I_TYPE) ? 1 : 0;
++ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0;
++
++ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8;
++ pic_descriptor->avc_bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8;
++ pic_descriptor->avc_log2_max_frame_num_minus4 = h->sps.log2_max_frame_num -4;
++ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type;
++ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
++ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count;
++ pic_descriptor->avc_reserved_8bit = 0;
++
++ pic_descriptor->avc_num_slice_groups_minus1 = h->pps.slice_group_count - 1;
++ pic_descriptor->avc_num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1;
++ pic_descriptor->avc_num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1;
++
++ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26;
++ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26;
++ pic_descriptor->avc_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0];
++ pic_descriptor->avc_second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
++ pic_descriptor->avc_slice_group_change_rate_minus1 = 0; // not implemented in ffmpeg
++ pic_descriptor->avc_reserved_16bit = 0; // must be 0
++ memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0
++ memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0
++
++ // sps
++ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
++ pic_descriptor->sps_info.avc.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag;
++ pic_descriptor->sps_info.avc.frame_mbs_only_flag = h->sps.frame_mbs_only_flag;
++ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag;
++ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag = h->sps.mb_aff;
++ pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag;
++ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0;
++
++ // pps
++ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac;
++ pic_descriptor->pps_info.avc.pic_order_present_flag = h->pps.pic_order_present;
++ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred;
++ pic_descriptor->pps_info.avc.weighted_bipred_idc = h->pps.weighted_bipred_idc;
++ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
++ pic_descriptor->pps_info.avc.constrained_intra_pred_flag = h->pps.constrained_intra_pred;
++ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present;
++ pic_descriptor->pps_info.avc.transform_8x8_mode_flag = h->pps.transform_8x8_mode;
++ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0; // must be 0
++
++ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4));
++ memcpy(iq_matrix->bScalingLists8x8, h->pps.scaling_matrix8, sizeof(iq_matrix->bScalingLists8x8));
++
++ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs
++ if (!h->got_first_iframe) {
++ if (h->slice_type != FF_I_TYPE && h->slice_type != FF_SI_TYPE)
++ return -1;
++ h->got_first_iframe = 1;
++ }
++
++ ff_draw_horiz_band(s, 0, s->avctx->height);
++
++ return 0;
++}
++
++/** Decode the given H.264 slice with VA API. */
++static int decode_slice(AVCodecContext *avctx,
++ const uint8_t *buffer,
++ uint32_t size)
++{
++ H264Context * const h = avctx->priv_data;
++ MpegEncContext * const s = &h->s;
++ struct xvba_render_state *render;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ ff_xvba_add_slice_data(render, buffer, size);
++
++ return 0;
++}
++
++AVHWAccel ff_h264_xvba_hwaccel = {
++ .name = "h264_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_H264,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
+diff --git a/lib/ffmpeg/libavcodec/xvba_internal.h b/lib/ffmpeg/libavcodec/xvba_internal.h
+new file mode 100644
+index 0000000..9653f85
+--- /dev/null
++++ b/lib/ffmpeg/libavcodec/xvba_internal.h
+@@ -0,0 +1,24 @@
++/*
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++int ff_xvba_translate_profile(int profile);
++void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size);
+diff --git a/lib/ffmpeg/libavcodec/xvba_mpeg2.c b/lib/ffmpeg/libavcodec/xvba_mpeg2.c
+new file mode 100644
+index 0000000..552ef95
+--- /dev/null
++++ b/lib/ffmpeg/libavcodec/xvba_mpeg2.c
+@@ -0,0 +1,52 @@
++/*
++ * MPEG-2 HW decode acceleration through XVBA
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "dsputil.h"
++
++static int start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
++{
++ struct MpegEncContext * const s = avctx->priv_data;
++ return 0;
++}
++
++static int end_frame(AVCodecContext *avctx)
++{
++ return 0;
++}
++
++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
++{
++ struct MpegEncContext * const s = avctx->priv_data;
++ return 0;
++}
++
++AVHWAccel ff_mpeg2_xvba_hwaccel = {
++ .name = "mpeg2_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_MPEG2VIDEO,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
+diff --git a/lib/ffmpeg/libavcodec/xvba_vc1.c b/lib/ffmpeg/libavcodec/xvba_vc1.c
+new file mode 100644
+index 0000000..e7b9211
+--- /dev/null
++++ b/lib/ffmpeg/libavcodec/xvba_vc1.c
+@@ -0,0 +1,194 @@
++/*
++ * VC-1 HW decode acceleration through XVBA
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "xvba.h"
++#include "xvba_internal.h"
++#include "vc1.h"
++#include "vc1data.h"
++#include
++
++
++/** @file
++ * Implement structures of ffmpeg <-> XvBA
++ */
++
++/* Initialize and start decoding a frame with XvBA */
++static int start_frame(AVCodecContext *avctx,
++ av_unused const uint8_t *buffer,
++ av_unused uint32_t size)
++{
++ VC1Context * const v = avctx->priv_data;
++ MpegEncContext * const s = &v->s;
++ struct xvba_render_state *render;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ render->num_slices = 0;
++ return 0;
++}
++
++/* End a hardware decoding based frame */
++static int end_frame(AVCodecContext *avctx)
++{
++ VC1Context* const v = avctx->priv_data;
++ MpegEncContext* const s = &v->s;
++ struct xvba_render_state *render, *last, *next;
++ XVBAPictureDescriptor *pic_descriptor;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (render->picture_descriptor == 0)
++ return -1;
++
++ pic_descriptor = render->picture_descriptor;
++
++ av_dlog(avctx, "xvba_vc1_end_frame()\n");
++
++ memset(pic_descriptor, 0, sizeof(*pic_descriptor));
++
++ /* Fill in Parameters - for reference see AMD sdk documentation */
++ pic_descriptor->profile = ff_xvba_translate_profile(v->profile);
++ pic_descriptor->level = v->level;
++ //done like in va-driver and vaapi
++ if (v->profile == PROFILE_ADVANCED) {
++ pic_descriptor->width_in_mb = s->avctx->coded_width;
++ pic_descriptor->height_in_mb = s->avctx->coded_height;
++ } else {
++ pic_descriptor->width_in_mb = s->mb_width;
++ pic_descriptor->height_in_mb = s->mb_height;
++ }
++ pic_descriptor->picture_structure = s->picture_structure;
++ // xvba-video set this to 1 only 4:2:0 supported
++ // doc says: if not set, choose 1 - we try this
++ pic_descriptor->chroma_format = 1;
++ pic_descriptor->avc_intra_flag = s->pict_type == FF_I_TYPE || v->bi_type == 1;
++ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0;
++
++ // VC-1 explicit parameters see page 30 of sdk
++ // sps_info
++ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag;
++
++ // done as in vaapi
++ pic_descriptor->sps_info.vc1.pulldown = v->broadcast;
++ pic_descriptor->sps_info.vc1.interlace = v->interlace;
++ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag;
++ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag;
++ pic_descriptor->sps_info.vc1.reserved = 1;
++ // eventually check if this makes sense together with interlace
++ pic_descriptor->sps_info.vc1.psf = v->psf;
++ // what about if it is a frame (page 31)
++ // looked at xvba-driver
++ pic_descriptor->sps_info.vc1.second_field = !s->first_field;
++ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0;
++
++ // VC-1 explicit parameters see page 30 of sdk
++ // pps_info
++ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag;
++ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag;
++ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter;
++ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc;
++ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv;
++ pic_descriptor->pps_info.vc1.dquant = v->dquant;
++ pic_descriptor->pps_info.vc1.vstransform = v->vstransform;
++ pic_descriptor->pps_info.vc1.overlap = v->overlap;
++ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode;
++ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv;
++ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames;
++ pic_descriptor->pps_info.vc1.rangered = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered;
++ pic_descriptor->pps_info.vc1.syncmarker = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker;
++ pic_descriptor->pps_info.vc1.multires = v->multires;
++ pic_descriptor->pps_info.vc1.reserved = 1;
++ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag;
++ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy;
++ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag;
++ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv;
++ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0;
++
++ pic_descriptor->past_surface = 0;
++ pic_descriptor->future_surface = 0;
++ switch (s->pict_type) {
++ case FF_B_TYPE:
++ next = (struct xvba_render_state *)s->next_picture.data[0];
++ assert(next);
++ if (next)
++ pic_descriptor->past_surface = next->surface;
++ // fall-through
++ case FF_P_TYPE:
++ last = (struct xvba_render_state *)s->last_picture.data[0];
++ assert(last);
++ if (last)
++ pic_descriptor->future_surface = last->surface;
++ break;
++ }
++
++ ff_draw_horiz_band(s, 0, s->avctx->height);
++
++ return 0;
++}
++
++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
++{
++ VC1Context* const v = avctx->priv_data;
++ MpegEncContext* const s = &v->s;
++ struct xvba_render_state *render;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (avctx->codec_id == CODEC_ID_VC1 &&
++ size >= 4 && IS_MARKER(AV_RB32(buffer))) {
++ buffer += 4;
++ size -= 4;
++ }
++
++ ff_xvba_add_slice_data(render, buffer, size);
++
++ return 0;
++}
++
++#if CONFIG_WMV3_XVBA_HWACCEL
++AVHWAccel ff_wmv3_xvba_hwaccel = {
++ .name = "wmv3_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_WMV3,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
++#endif
++
++AVHWAccel ff_vc1_xvba_hwaccel = {
++ .name = "vc1_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_VC1,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
+diff --git a/lib/ffmpeg/libavcodec/xvmc_internal.h b/lib/ffmpeg/libavcodec/xvmc_internal.h
+index 9bb8909..a64d6ee 100644
+--- a/lib/ffmpeg/libavcodec/xvmc_internal.h
++++ b/lib/ffmpeg/libavcodec/xvmc_internal.h
+@@ -1,5 +1,7 @@
+ /*
+- * XVideo Motion Compensation internal functions
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
+ *
+ * This file is part of FFmpeg.
+ *
+diff --git a/lib/ffmpeg/libavutil/pixdesc.c b/lib/ffmpeg/libavutil/pixdesc.c
+index 83aa8b0..fcc20d0 100644
+--- a/lib/ffmpeg/libavutil/pixdesc.c
++++ b/lib/ffmpeg/libavutil/pixdesc.c
+@@ -717,6 +717,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = {
+ .log2_chroma_h = 1,
+ .flags = PIX_FMT_HWACCEL,
+ },
++ [PIX_FMT_XVBA_VLD] = {
++ .name = "xvba_vld",
++ .log2_chroma_w = 1,
++ .log2_chroma_h = 1,
++ .flags = PIX_FMT_HWACCEL,
++ },
+ [PIX_FMT_YUV420P16LE] = {
+ .name = "yuv420p16le",
+ .nb_components= 3,
+diff --git a/lib/ffmpeg/libavutil/pixfmt.h b/lib/ffmpeg/libavutil/pixfmt.h
+index 8ec91c8..4803dd7 100644
+--- a/lib/ffmpeg/libavutil/pixfmt.h
++++ b/lib/ffmpeg/libavutil/pixfmt.h
+@@ -127,6 +127,7 @@ enum PixelFormat {
+ PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
++ PIX_FMT_XVBA_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+
+ PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
+ PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
+diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp
+index e95ecdc..892948a 100644
+--- a/xbmc/ApplicationMessenger.cpp
++++ b/xbmc/ApplicationMessenger.cpp
+@@ -72,7 +72,7 @@
+
+ using namespace std;
+
+-CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay)
++CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("CDelayedMessage")
+ {
+ m_msg.dwMessage = msg.dwMessage;
+ m_msg.dwParam1 = msg.dwParam1;
+diff --git a/xbmc/cdrip/CDDAReader.cpp b/xbmc/cdrip/CDDAReader.cpp
+index 16fa7b6..6c242d8 100644
+--- a/xbmc/cdrip/CDDAReader.cpp
++++ b/xbmc/cdrip/CDDAReader.cpp
+@@ -29,7 +29,7 @@
+
+ #define SECTOR_COUNT 52
+
+-CCDDAReader::CCDDAReader()
++CCDDAReader::CCDDAReader() : CThread("CCDDAReader")
+ {
+ m_sRipBuffer[0].pbtStream = NULL;
+ m_sRipBuffer[1].pbtStream = NULL;
+diff --git a/xbmc/cores/DllLoader/exports/emu_kernel32.cpp b/xbmc/cores/DllLoader/exports/emu_kernel32.cpp
+index 13a23e2..493d64d 100644
+--- a/xbmc/cores/DllLoader/exports/emu_kernel32.cpp
++++ b/xbmc/cores/DllLoader/exports/emu_kernel32.cpp
+@@ -240,15 +240,6 @@ extern "C" DWORD WINAPI dllGetCurrentProcessId(void)
+ #endif
+ }
+
+-extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
+-{
+- // since the xbox has only one process, we just take the current thread
+- HANDLE h = GetCurrentThread();
+- BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
+-
+- return res;
+-}
+-
+ extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
+ HANDLE hSourceHandle, // handle to duplicate
+ HANDLE hTargetProcessHandle, // handle to target process
+diff --git a/xbmc/cores/DllLoader/exports/emu_kernel32.h b/xbmc/cores/DllLoader/exports/emu_kernel32.h
+index 2e637a7..9cc2f0b 100644
+--- a/xbmc/cores/DllLoader/exports/emu_kernel32.h
++++ b/xbmc/cores/DllLoader/exports/emu_kernel32.h
+@@ -686,7 +686,6 @@ extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProc
+
+ extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE module, HRSRC res);
+ extern "C" HRSRC WINAPI dllFindResourceA(HMODULE module, LPCTSTR name, LPCTSTR type);
+-extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
+ extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData);
+ extern "C" UINT WINAPI dllGetConsoleCP();
+ extern "C" UINT WINAPI dllGetConsoleOutputCP();
+diff --git a/xbmc/cores/DummyVideoPlayer.cpp b/xbmc/cores/DummyVideoPlayer.cpp
+index f0b4aeb..47d25e4 100644
+--- a/xbmc/cores/DummyVideoPlayer.cpp
++++ b/xbmc/cores/DummyVideoPlayer.cpp
+@@ -33,7 +33,7 @@
+
+ CDummyVideoPlayer::CDummyVideoPlayer(IPlayerCallback& callback)
+ : IPlayer(callback),
+- CThread()
++ CThread("CDummyVideoPlayer")
+ {
+ m_paused = false;
+ m_clock = 0;
+diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
+index 4961b7d..70f20d7 100644
+--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
++++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
+@@ -60,6 +60,9 @@
+ VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5)))
+
+ #endif
++#ifdef HAVE_LIBXVBA
++#include "cores/dvdplayer/DVDCodecs/Video/XVBA.h"
++#endif
+
+ #ifdef HAS_GLX
+ #include
+@@ -120,6 +123,10 @@ CLinuxRendererGL::YUVBUFFER::YUVBUFFER()
+ #ifdef HAVE_LIBVDPAU
+ vdpau = NULL;
+ #endif
++#ifdef HAVE_LIBXVBA
++ xvba = NULL;
++ xvba_tmp = NULL;
++#endif
+ }
+
+ CLinuxRendererGL::YUVBUFFER::~YUVBUFFER()
+@@ -159,6 +166,7 @@ CLinuxRendererGL::CLinuxRendererGL()
+ m_rgbPbo = 0;
+
+ m_dllSwScale = new DllSwScale;
++ m_bValidated = false;
+ }
+
+ CLinuxRendererGL::~CLinuxRendererGL()
+@@ -223,7 +231,7 @@ bool CLinuxRendererGL::ValidateRenderer()
+
+ void CLinuxRendererGL::ManageTextures()
+ {
+- m_NumYV12Buffers = 2;
++ m_NumYV12Buffers = 3;
+ //m_iYV12RenderBuffer = 0;
+ return;
+ }
+@@ -568,6 +576,11 @@ void CLinuxRendererGL::Flush()
+ m_bValidated = false;
+ }
+
++unsigned int CLinuxRendererGL::GetProcessorSize()
++{
++ return m_NumYV12Buffers;
++}
++
+ void CLinuxRendererGL::Update(bool bPauseDrawing)
+ {
+ if (!m_bConfigured) return;
+@@ -729,14 +742,15 @@ unsigned int CLinuxRendererGL::PreInit()
+ {
+ CSingleLock lock(g_graphicsContext);
+ m_bConfigured = false;
+- m_bValidated = false;
+- UnInit();
++ if (m_bValidated)
++ UnInit();
++
+ m_resolution = g_guiSettings.m_LookAndFeelResolution;
+ if ( m_resolution == RES_WINDOW )
+ m_resolution = RES_DESKTOP;
+
+ m_iYV12RenderBuffer = 0;
+- m_NumYV12Buffers = 2;
++ m_NumYV12Buffers = 3;
+
+ // setup the background colour
+ m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
+@@ -816,7 +830,7 @@ void CLinuxRendererGL::UpdateVideoFilter()
+ case VS_SCALINGMETHOD_LINEAR:
+ SetTextureFilter(m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR);
+ m_renderQuality = RQ_SINGLEPASS;
+- if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) && m_nonLinStretch)
++ if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) && m_nonLinStretch)
+ {
+ m_pVideoFilterShader = new StretchFilterShader();
+ if (!m_pVideoFilterShader->CompileAndLink())
+@@ -897,6 +911,11 @@ void CLinuxRendererGL::LoadShaders(int field)
+ CLog::Log(LOGNOTICE, "GL: Using VAAPI render method");
+ m_renderMethod = RENDER_VAAPI;
+ }
++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA)
++ {
++ CLog::Log(LOGNOTICE, "GL: Using XVBA render method");
++ m_renderMethod = RENDER_XVBA;
++ }
+ else
+ {
+ int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod");
+@@ -1031,6 +1050,18 @@ void CLinuxRendererGL::LoadShaders(int field)
+ m_textureCreate = &CLinuxRendererGL::CreateVAAPITexture;
+ m_textureDelete = &CLinuxRendererGL::DeleteVAAPITexture;
+ }
++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA)
++ {
++ m_textureUpload = &CLinuxRendererGL::UploadXVBATexture;
++ m_textureCreate = &CLinuxRendererGL::CreateXVBATexture;
++ m_textureDelete = &CLinuxRendererGL::DeleteXVBATexture;
++ }
++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA_YV12)
++ {
++ m_textureUpload = &CLinuxRendererGL::UploadXVBAyv12Texture;
++ m_textureCreate = &CLinuxRendererGL::CreateXVBAyv12Texture;
++ m_textureDelete = &CLinuxRendererGL::DeleteXVBAyv12Texture;
++ }
+ else
+ {
+ // setup default YV12 texture handlers
+@@ -1124,6 +1155,13 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
+ RenderVDPAU(renderBuffer, m_currentField);
+ }
+ #endif
++#ifdef HAVE_LIBXVBA
++ else if (m_renderMethod & RENDER_XVBA)
++ {
++ UpdateVideoFilter();
++ RenderXVBA(renderBuffer, m_currentField);
++ }
++#endif
+ #ifdef HAVE_LIBVA
+ else if (m_renderMethod & RENDER_VAAPI)
+ {
+@@ -1597,6 +1635,77 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field)
+ #endif
+ }
+
++void CLinuxRendererGL::RenderXVBA(int index, int field)
++{
++#ifdef HAVE_LIBXVBA
++ YUVPLANE &plane = m_buffers[index].fields[field][0];
++
++ glEnable(m_textureTarget);
++ glActiveTextureARB(GL_TEXTURE0);
++ glBindTexture(m_textureTarget, plane.id);
++
++ // Try some clamping or wrapping
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++
++ if (m_pVideoFilterShader)
++ {
++ GLint filter;
++ if (!m_pVideoFilterShader->GetTextureFilter(filter))
++ filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
++
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
++ m_pVideoFilterShader->SetSourceTexture(0);
++ m_pVideoFilterShader->SetWidth(m_sourceWidth);
++ m_pVideoFilterShader->SetHeight(m_sourceHeight);
++
++ //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer
++ //having non-linear stretch on breaks the alignment
++ if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
++ m_pVideoFilterShader->SetNonLinStretch(1.0);
++ else
++ m_pVideoFilterShader->SetNonLinStretch(pow(g_settings.m_fPixelRatio, g_advancedSettings.m_videoNonLinStretchRatio));
++
++ m_pVideoFilterShader->Enable();
++ }
++ else
++ {
++ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
++ }
++
++ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
++ VerifyGLState();
++
++ glBegin(GL_QUADS);
++ if (m_textureTarget==GL_TEXTURE_2D)
++ {
++ glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_destRect.x1, m_destRect.y1);
++ glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_destRect.x2, m_destRect.y1);
++ glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_destRect.x2, m_destRect.y2);
++ glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_destRect.x1, m_destRect.y2);
++ }
++ else
++ {
++ glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f);
++ glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f);
++ glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f);
++ glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f);
++ }
++ glEnd();
++ VerifyGLState();
++
++ if (m_pVideoFilterShader)
++ m_pVideoFilterShader->Disable();
++
++ glBindTexture (m_textureTarget, 0);
++ glDisable(m_textureTarget);
++#endif
++}
++
++
+ void CLinuxRendererGL::RenderSoftware(int index, int field)
+ {
+ YUVPLANES &planes = m_buffers[index].fields[field];
+@@ -2351,6 +2460,424 @@ void CLinuxRendererGL::UploadVAAPITexture(int index)
+ #endif
+ }
+
++void CLinuxRendererGL::DeleteXVBATexture(int index)
++{
++#ifdef HAVE_LIBXVBA
++ YUVPLANE &plane = m_buffers[index].fields[0][1];
++
++ if (m_buffers[index].xvba)
++ m_buffers[index].xvba->FinishGL();
++
++ SAFE_RELEASE(m_buffers[index].xvba);
++ SAFE_RELEASE(m_buffers[index].xvba_tmp);
++
++ if(plane.id && glIsTexture(plane.id))
++ glDeleteTextures(1, &plane.id);
++ plane.id = 0;
++ m_buffers[index].fields[0][0].id = 0;
++
++#endif
++}
++
++
++bool CLinuxRendererGL::CreateXVBATexture(int index)
++{
++#ifdef HAVE_LIBXVBA
++ YV12Image &im = m_buffers[index].image;
++ YUVFIELDS &fields = m_buffers[index].fields;
++ YUVPLANE &plane = fields[0][0];
++ YUVPLANE &planeFallback = fields[0][1];
++
++ DeleteXVBATexture(index);
++
++ memset(&im , 0, sizeof(im));
++ memset(&fields, 0, sizeof(fields));
++ im.height = m_sourceHeight;
++ im.width = m_sourceWidth;
++
++ for(int f = 0;fSet();
++#endif
++ return true;
++}
++
++void CLinuxRendererGL::UploadXVBATexture(int index)
++{
++#ifdef HAVE_LIBXVBA
++ XVBA::CDecoder *xvba = m_buffers[index].xvba;
++
++ if (m_buffers[index].xvba_tmp)
++ {
++ SAFE_RELEASE(m_buffers[index].xvba);
++ xvba = m_buffers[index].xvba = m_buffers[index].xvba_tmp;
++ m_buffers[index].xvba_tmp = NULL;
++ }
++
++ YUVFIELDS &fields = m_buffers[index].fields;
++ YUVPLANE &planeFallback = fields[0][1];
++ YUVPLANE &plane = fields[m_currentField][0];
++
++ if (!xvba)
++ {
++ fields[0][0].id = planeFallback.id;
++ fields[1][0].id = planeFallback.id;
++ fields[2][0].id = planeFallback.id;
++ m_eventTexturesDone[index]->Set();
++ return;
++ }
++
++ XVBA_SURFACE_FLAG field;
++ if (m_currentField == FIELD_TOP)
++ field = XVBA_TOP_FIELD;
++ else if (m_currentField == FIELD_BOT)
++ field = XVBA_BOTTOM_FIELD;
++ else
++ field = XVBA_FRAME;
++
++ glEnable(m_textureTarget);
++ if (xvba->UploadTexture(index, field, m_textureTarget) == 1)
++ plane.id = xvba->GetTexture(index, field);
++
++ // crop texture
++ CRect crop = xvba->GetCropRect();
++ plane.rect = m_sourceRect;
++ plane.rect.x1 += crop.x1;
++ plane.rect.x2 -= m_sourceWidth - crop.x2;
++ plane.rect.y1 += crop.y1;
++ plane.rect.y2 -= m_sourceHeight - crop.y2;
++ plane.rect.y1 /= plane.pixpertex_y;
++ plane.rect.y2 /= plane.pixpertex_y;
++ plane.rect.x1 /= plane.pixpertex_x;
++ plane.rect.x2 /= plane.pixpertex_x;
++ if (m_textureTarget == GL_TEXTURE_2D)
++ {
++ plane.rect.y1 /= plane.texheight;
++ plane.rect.y2 /= plane.texheight;
++ plane.rect.x1 /= plane.texwidth;
++ plane.rect.x2 /= plane.texwidth;
++ }
++
++ glDisable(m_textureTarget);
++
++ m_eventTexturesDone[index]->Set();
++#endif
++}
++
++//********************************************************************************************************
++// XVBA YV12 Texture creation, deletion, copying + clearing
++//********************************************************************************************************
++void CLinuxRendererGL::DeleteXVBAyv12Texture(int index)
++{
++#ifdef HAVE_LIBXVBA
++ YV12Image &im = m_buffers[index].image;
++ YUVFIELDS &fields = m_buffers[index].fields;
++ GLuint *pbo = m_buffers[index].pbo;
++
++ if (m_buffers[index].xvba)
++ m_buffers[index].xvba->FinishGL();
++
++ SAFE_RELEASE(m_buffers[index].xvba);
++ SAFE_RELEASE(m_buffers[index].xvba_tmp);
++
++ if( fields[FIELD_FULL][0].id == 0 ) return;
++
++ /* finish up all textures, and delete them */
++ g_graphicsContext.BeginPaint(); //FIXME
++ for(int f = 0;f> im.cshift_x;
++ im.stride[2] = im.width >> im.cshift_x;
++
++ im.planesize[0] = im.stride[0] * im.height;
++ im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
++ im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
++
++ im.plane[1] = im.plane[2] = 0;
++ pbo[1] = pbo[2] = 0;
++
++ bool pboSetup = false;
++ if (m_pboUsed)
++ {
++ pboSetup = true;
++
++ glGenBuffersARB(1, pbo);
++ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[0]);
++ glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, im.planesize[0] + im.planesize[0]/2 + PBO_OFFSET, 0, GL_STREAM_DRAW_ARB);
++ void* pboPtr = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
++ if (pboPtr)
++ {
++ im.plane[0] = (BYTE*) pboPtr + PBO_OFFSET;
++ memset(im.plane[0], 0, im.planesize[0]);
++ }
++ else
++ {
++ CLog::Log(LOGWARNING,"GL: failed to set up pixel buffer object");
++ pboSetup = false;
++ }
++
++ if (!pboSetup)
++ {
++ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[0]);
++ glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
++ glDeleteBuffersARB(1, pbo);
++ memset(m_buffers[index].pbo, 0, sizeof(m_buffers[index].pbo));
++ }
++
++ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
++ }
++
++ if (!pboSetup)
++ {
++ im.plane[0] = new BYTE[im.planesize[0]+im.planesize[0]/2];
++ }
++
++ glEnable(m_textureTarget);
++ for(int f = 0;f> fieldshift;
++
++ if (m_renderMethod & RENDER_SW)
++ {
++ planes[1].texwidth = 0;
++ planes[1].texheight = 0;
++ planes[2].texwidth = 0;
++ planes[2].texheight = 0;
++ }
++ else
++ {
++ planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
++ planes[1].texheight = planes[0].texheight >> im.cshift_y;
++ planes[2].texwidth = planes[0].texwidth >> im.cshift_x;
++ planes[2].texheight = planes[0].texheight >> im.cshift_y;
++ }
++
++ for (int p = 0; p < 3; p++)
++ {
++ planes[p].pixpertex_x = 1;
++ planes[p].pixpertex_y = 1;
++ }
++
++ if(m_renderMethod & RENDER_POT)
++ {
++ for(int p = 0; p < 3; p++)
++ {
++ planes[p].texwidth = NP2(planes[p].texwidth);
++ planes[p].texheight = NP2(planes[p].texheight);
++ }
++ }
++
++ for(int p = 0; p < 3; p++)
++ {
++ YUVPLANE &plane = planes[p];
++ if (plane.texwidth * plane.texheight == 0)
++ continue;
++
++ glBindTexture(m_textureTarget, plane.id);
++ if (m_renderMethod & RENDER_SW)
++ {
++ glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
++ }
++ else
++ {
++ GLint format;
++ if (p == 2) //V plane needs an alpha texture
++ format = GL_ALPHA;
++ else
++ format = GL_LUMINANCE;
++
++ glTexImage2D(m_textureTarget, 0, format, plane.texwidth, plane.texheight, 0, format, GL_UNSIGNED_BYTE, NULL);
++ }
++
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++ VerifyGLState();
++ }
++ }
++ glDisable(m_textureTarget);
++ m_eventTexturesDone[index]->Set();
++#endif
++ return true;
++}
++
++void CLinuxRendererGL::UploadXVBAyv12Texture(int source)
++{
++#ifdef HAVE_LIBXVBA
++ YUVBUFFER& buf = m_buffers[source];
++ YV12Image* im = &buf.image;
++ YUVFIELDS& fields = buf.fields;
++ XVBA::CDecoder *xvba = m_buffers[source].xvba;
++
++ if (m_buffers[source].xvba_tmp)
++ {
++ SAFE_RELEASE(m_buffers[source].xvba);
++ xvba = m_buffers[source].xvba = m_buffers[source].xvba_tmp;
++ m_buffers[source].xvba_tmp = NULL;
++ }
++
++ if (!(im->flags&IMAGE_FLAG_READY) || !xvba)
++ {
++ m_eventTexturesDone[source]->Set();
++ return;
++ }
++
++ bool deinterlacing;
++ if (m_currentField == FIELD_FULL)
++ deinterlacing = false;
++ else
++ deinterlacing = true;
++
++ glEnable(m_textureTarget);
++ VerifyGLState();
++
++ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
++
++ if (deinterlacing)
++ {
++ // Load Even Y Field
++ LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
++ , im->width, im->height >> 1
++ , im->stride[0]*2, im->plane[0] );
++
++ //load Odd Y Field
++ LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
++ , im->width, im->height >> 1
++ , im->stride[0]*2, im->plane[0] + im->stride[0], &buf.pbo[0] ) ;
++
++ // Load Even U & V Fields
++ LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
++ , im->stride[1]*2, im->plane[0] + im->planesize[0] + im->planesize[1], &buf.pbo[0] );
++
++ LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex
++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
++ , im->stride[2]*2, im->plane[0] + im->planesize[0], &buf.pbo[0] );
++
++ // Load Odd U & V Fields
++ LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
++ , im->stride[1]*2, im->plane[0] + im->stride[1] + im->planesize[0] + im->planesize[1], &buf.pbo[0] );
++
++ LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex
++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
++ , im->stride[2]*2, im->plane[0] + im->stride[2] + im->planesize[0], &buf.pbo[0] );
++ }
++ else
++ {
++ //Load Y plane
++ LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
++ , im->width, im->height
++ , im->stride[0], im->plane[0], &buf.pbo[0] );
++
++ //load U plane
++ LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
++ , im->width >> im->cshift_x, im->height >> im->cshift_y
++ , im->stride[1], im->plane[0] + im->planesize[0] + im->planesize[1] , &buf.pbo[0] );
++
++ //load V plane
++ LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex
++ , im->width >> im->cshift_x, im->height >> im->cshift_y
++ , im->stride[2], im->plane[0] + im->planesize[0], &buf.pbo[0] );
++ }
++
++ m_eventTexturesDone[source]->Set();
++
++ VerifyGLState();
++
++ // crop texture
++ CRect crop = xvba->GetCropRect();
++ m_sourceRect.x1 += crop.x1;
++ m_sourceRect.x2 -= m_sourceWidth - crop.x2;
++ m_sourceRect.y1 += crop.y1;
++ m_sourceRect.y2 -= m_sourceHeight - crop.y2;
++ CalculateTextureSourceRects(source, 3);
++
++ glDisable(m_textureTarget);
++#endif
++}
++
+ void CLinuxRendererGL::UploadYUV422PackedTexture(int source)
+ {
+ YUVBUFFER& buf = m_buffers[source];
+@@ -2934,6 +3461,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
+ if (m_renderMethod & RENDER_VAAPI)
+ return false;
+
++ if (m_renderMethod & RENDER_XVBA)
++ return false;
++
+ return (m_renderMethod & RENDER_GLSL)
+ || (m_renderMethod & RENDER_ARB)
+ || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
+@@ -2947,6 +3477,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
+ if (m_renderMethod & RENDER_VAAPI)
+ return false;
+
++ if (m_renderMethod & RENDER_XVBA)
++ return false;
++
+ return (m_renderMethod & RENDER_GLSL)
+ || (m_renderMethod & RENDER_ARB)
+ || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
+@@ -2970,7 +3503,8 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
+ if (feature == RENDERFEATURE_NONLINSTRETCH)
+ {
+ if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) ||
+- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) ||
++ (m_renderMethod & RENDER_XVBA))
+ return true;
+ }
+
+@@ -3010,10 +3544,22 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method)
+ if(m_renderMethod & RENDER_VAAPI)
+ return false;
+
+- if(method == VS_INTERLACEMETHOD_DEINTERLACE
+- || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
+- || method == VS_INTERLACEMETHOD_SW_BLEND)
+- return true;
++ if(m_renderMethod & RENDER_XVBA)
++ {
++ if (method == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED
++ || method == VS_INTERLACEMETHOD_RENDER_BOB)
++ return true;
++ else
++ return false;
++ }
++
++ if (CONF_FLAGS_FORMAT_MASK(m_iFlags) != CONF_FLAGS_FORMAT_XVBA)
++ {
++ if(method == VS_INTERLACEMETHOD_DEINTERLACE
++ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
++ || method == VS_INTERLACEMETHOD_SW_BLEND)
++ return true;
++ }
+
+ if((method == VS_INTERLACEMETHOD_RENDER_BLEND
+ || method == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED
+@@ -3045,7 +3591,7 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method)
+ || method == VS_SCALINGMETHOD_LANCZOS3)
+ {
+ if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) ||
+- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA))
+ {
+ // spline36 and lanczos3 are only allowed through advancedsettings.xml
+ if(method != VS_SCALINGMETHOD_SPLINE36
+@@ -3104,7 +3650,7 @@ void CLinuxRendererGL::UnBindPbo(YUVBUFFER& buff)
+ pbo = true;
+
+ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.pbo[plane]);
+- glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.image.planesize[plane] + PBO_OFFSET, NULL, GL_STREAM_DRAW_ARB);
++ glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.image.planesize[plane] + buff.image.planesize[plane]/2 + PBO_OFFSET, NULL, GL_STREAM_DRAW_ARB);
+ buff.image.plane[plane] = (BYTE*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB) + PBO_OFFSET;
+ }
+ if(pbo)
+@@ -3128,4 +3674,13 @@ void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder)
+ }
+ #endif
+
++#ifdef HAVE_LIBXVBA
++void CLinuxRendererGL::AddProcessor(XVBA::CDecoder* xvba)
++{
++ YUVBUFFER &buf = m_buffers[NextYV12Texture()];
++ SAFE_RELEASE(buf.xvba_tmp);
++ buf.xvba_tmp = (XVBA::CDecoder*)xvba->Acquire();
++}
++#endif
++
+ #endif
+diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
+index 38c84aa..ae0b81b 100644
+--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h
++++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
+@@ -40,6 +40,7 @@ class CBaseTexture;
+ namespace Shaders { class BaseYUV2RGBShader; }
+ namespace Shaders { class BaseVideoFilterShader; }
+ namespace VAAPI { struct CHolder; }
++namespace XVBA { class CDecoder; }
+
+ #define NUM_BUFFERS 3
+
+@@ -94,6 +95,7 @@ enum RenderMethod
+ RENDER_VDPAU=0x08,
+ RENDER_POT=0x10,
+ RENDER_VAAPI=0x20,
++ RENDER_XVBA=0x40,
+ };
+
+ enum RenderQuality
+@@ -141,6 +143,7 @@ public:
+ virtual void UnInit();
+ virtual void Reset(); /* resets renderer after seek for example */
+ virtual void Flush();
++ virtual unsigned int GetProcessorSize();
+
+ #ifdef HAVE_LIBVDPAU
+ virtual void AddProcessor(CVDPAU* vdpau);
+@@ -148,6 +151,9 @@ public:
+ #ifdef HAVE_LIBVA
+ virtual void AddProcessor(VAAPI::CHolder& holder);
+ #endif
++#ifdef HAVE_LIBXVBA
++ virtual void AddProcessor(XVBA::CDecoder* xvba);
++#endif
+
+ virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255);
+
+@@ -194,6 +200,14 @@ protected:
+ void DeleteVAAPITexture(int index);
+ bool CreateVAAPITexture(int index);
+
++ void UploadXVBATexture(int index);
++ void DeleteXVBATexture(int index);
++ bool CreateXVBATexture(int index);
++
++ void UploadXVBAyv12Texture(int index);
++ void DeleteXVBAyv12Texture(int index);
++ bool CreateXVBAyv12Texture(int index);
++
+ void UploadYUV422PackedTexture(int index);
+ void DeleteYUV422PackedTexture(int index);
+ bool CreateYUV422PackedTexture(int index);
+@@ -211,6 +225,7 @@ protected:
+ void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer
+ void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
+ void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
++ void RenderXVBA(int renderBuffer, int field); // render using xvba hardware
+
+ CFrameBufferObject m_fbo;
+
+@@ -270,6 +285,10 @@ protected:
+ #ifdef HAVE_LIBVA
+ VAAPI::CHolder& vaapi;
+ #endif
++#ifdef HAVE_LIBXVBA
++ XVBA::CDecoder* xvba;
++ XVBA::CDecoder* xvba_tmp;
++#endif
+ };
+
+ typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS];
+diff --git a/xbmc/cores/VideoRenderers/RenderFlags.h b/xbmc/cores/VideoRenderers/RenderFlags.h
+index f663380..cbe82c5 100644
+--- a/xbmc/cores/VideoRenderers/RenderFlags.h
++++ b/xbmc/cores/VideoRenderers/RenderFlags.h
+@@ -79,5 +79,7 @@
+ #define CONF_FLAGS_FORMAT_VAAPI 0x030000
+ #define CONF_FLAGS_FORMAT_OMXEGL 0x040000
+ #define CONF_FLAGS_FORMAT_CVBREF 0x080000
++#define CONF_FLAGS_FORMAT_XVBA 0x011000
++#define CONF_FLAGS_FORMAT_XVBA_YV12 0x012000
+ #define CONF_FLAGS_FORMAT_BYPASS 0x100000
+ #endif
+diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
+index 31bb49a..8f0506d 100644
+--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
+@@ -53,6 +53,10 @@
+ #include "../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h"
+ #include "../dvdplayer/DVDCodecs/DVDCodecUtils.h"
+
++#ifdef HAVE_LIBXVBA
++ #include "../dvdplayer/DVDCodecs/Video/XVBA.h"
++#endif
++
+ #define MAXPRESENTDELAY 0.500
+
+ /* at any point we want an exclusive lock on rendermanager */
+@@ -779,6 +783,25 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
+ else if(pic.format == DVDVideoPicture::FMT_VAAPI)
+ m_pRenderer->AddProcessor(*pic.vaapi);
+ #endif
++#ifdef HAVE_LIBXVBA
++ else if(pic.format == DVDVideoPicture::FMT_XVBA)
++ {
++ if (pic.xvba)
++ {
++ m_pRenderer->AddProcessor(pic.xvba);
++ pic.xvba->Present(index);
++ }
++ }
++ else if(pic.format == DVDVideoPicture::FMT_XVBA_YV12)
++ {
++ if (pic.xvba)
++ {
++ m_pRenderer->AddProcessor(pic.xvba);
++ pic.xvba->Present(index);
++ pic.xvba->CopyYV12(index, image.plane[0]);
++ }
++ }
++#endif
+ m_pRenderer->ReleaseImage(index, false);
+
+ return index;
+diff --git a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
+index fa9f68a..68f4008 100644
+--- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
++++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
+@@ -186,6 +186,8 @@ BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, bool str
+ m_defines += "#define XBMC_YUY2\n";
+ else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_UYVY)
+ m_defines += "#define XBMC_UYVY\n";
++ if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_XVBA_YV12)
++ m_defines += "#define XBMC_YV12\n";
+
+ VertexShader()->LoadSource("yuv2rgb_vertex.glsl", m_defines);
+ #elif HAS_GLES == 2
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp
+index ae107a6..1b8cd96 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp
+@@ -323,7 +323,7 @@ CPictureBuffer::~CPictureBuffer()
+ #pragma mark -
+ #endif
+ CMPCOutputThread::CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015) :
+- CThread(),
++ CThread("CMPCOutputThread"),
+ m_dll(dll),
+ m_device(device),
+ m_has_bcm70015(has_bcm70015),
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
+index e4bd9c9..edc2fe1 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
+@@ -34,6 +34,7 @@
+
+ namespace DXVA { class CSurfaceContext; }
+ namespace VAAPI { struct CHolder; }
++namespace XVBA { class CDecoder; }
+ class CVDPAU;
+ class COpenMax;
+ class COpenMaxVideo;
+@@ -64,6 +65,9 @@ struct DVDVideoPicture
+ struct {
+ VAAPI::CHolder* vaapi;
+ };
++ struct {
++ XVBA::CDecoder* xvba;
++ };
+
+ struct {
+ COpenMax *openMax;
+@@ -109,6 +113,8 @@ struct DVDVideoPicture
+ FMT_VAAPI,
+ FMT_OMXEGL,
+ FMT_CVBREF,
++ FMT_XVBA,
++ FMT_XVBA_YV12,
+ } format;
+ };
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+index 1728e82..7b528ab 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+@@ -56,6 +56,9 @@
+ #ifdef HAVE_LIBVA
+ #include "VAAPI.h"
+ #endif
++#ifdef HAVE_LIBXVBA
++#include "XVBA.h"
++#endif
+
+ using namespace boost;
+
+@@ -100,6 +103,22 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
+ dec->Release();
+ }
+ #endif
++#ifdef HAVE_LIBXVBA
++ if(*cur == PIX_FMT_XVBA_VLD && g_guiSettings.GetBool("videoplayer.usexvba"))
++ {
++ if(ctx->GetHardware())
++ return *cur;
++
++ XVBA::CDecoder* dec = new XVBA::CDecoder();
++ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
++ {
++ ctx->SetHardware(dec);
++ return *cur;
++ }
++ else
++ dec->Release();
++ }
++#endif
+ #ifdef HAVE_LIBVA
+ if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi"))
+ {
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
+index 1dce256..8b7d5fb 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
+@@ -17,6 +17,10 @@ SRCS+= CrystalHD.cpp \
+ DVDVideoCodecCrystalHD.cpp \
+
+ endif
++ifeq (@USE_XVBA@,1)
++SRCS+= XVBA.cpp \
++
++endif
+ ifeq (@USE_VDA@,1)
+ SRCS+= DVDVideoCodecVDA.cpp \
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
+new file mode 100644
+index 0000000..d6317e0
+--- /dev/null
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
+@@ -0,0 +1,1401 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include "system.h"
++#ifdef HAVE_LIBXVBA
++#include
++#include
++#include "XVBA.h"
++#include "windowing/WindowingFactory.h"
++#include "guilib/GraphicContext.h"
++#include "settings/GUISettings.h"
++#include "utils/TimeUtils.h"
++
++using namespace XVBA;
++
++// XVBA interface
++
++#define XVBA_LIBRARY "libXvBAW.so.1"
++
++typedef Bool (*XVBAQueryExtensionProc) (Display *dpy, int *vers);
++typedef Status (*XVBACreateContextProc) (void *input, void *output);
++typedef Status (*XVBADestroyContextProc) (void *context);
++typedef Bool (*XVBAGetSessionInfoProc) (void *input, void *output);
++typedef Status (*XVBACreateSurfaceProc) (void *input, void *output);
++typedef Status (*XVBACreateGLSharedSurfaceProc)(void *input, void *output);
++typedef Status (*XVBADestroySurfaceProc) (void *surface);
++typedef Status (*XVBACreateDecodeBuffersProc) (void *input, void *output);
++typedef Status (*XVBADestroyDecodeBuffersProc) (void *input);
++typedef Status (*XVBAGetCapDecodeProc) (void *input, void *output);
++typedef Status (*XVBACreateDecodeProc) (void *input, void *output);
++typedef Status (*XVBADestroyDecodeProc) (void *session);
++typedef Status (*XVBAStartDecodePictureProc) (void *input);
++typedef Status (*XVBADecodePictureProc) (void *input);
++typedef Status (*XVBAEndDecodePictureProc) (void *input);
++typedef Status (*XVBASyncSurfaceProc) (void *input, void *output);
++typedef Status (*XVBAGetSurfaceProc) (void *input);
++typedef Status (*XVBATransferSurfaceProc) (void *input);
++
++static struct
++{
++ XVBAQueryExtensionProc QueryExtension;
++ XVBACreateContextProc CreateContext;
++ XVBADestroyContextProc DestroyContext;
++ XVBAGetSessionInfoProc GetSessionInfo;
++ XVBACreateSurfaceProc CreateSurface;
++ XVBACreateGLSharedSurfaceProc CreateGLSharedSurface;
++ XVBADestroySurfaceProc DestroySurface;
++ XVBACreateDecodeBuffersProc CreateDecodeBuffers;
++ XVBADestroyDecodeBuffersProc DestroyDecodeBuffers;
++ XVBAGetCapDecodeProc GetCapDecode;
++ XVBACreateDecodeProc CreateDecode;
++ XVBADestroyDecodeProc DestroyDecode;
++ XVBAStartDecodePictureProc StartDecodePicture;
++ XVBADecodePictureProc DecodePicture;
++ XVBAEndDecodePictureProc EndDecodePicture;
++ XVBASyncSurfaceProc SyncSurface;
++ XVBAGetSurfaceProc GetSurface;
++ XVBATransferSurfaceProc TransferSurface;
++}g_XVBA_vtable;
++
++//-----------------------------------------------------------------------------
++//-----------------------------------------------------------------------------
++
++CXVBAContext *CXVBAContext::m_context = 0;
++CCriticalSection CXVBAContext::m_section;
++Display *CXVBAContext::m_display = 0;
++
++CXVBAContext::CXVBAContext()
++{
++ m_context = 0;
++ m_dlHandle = 0;
++ m_xvbaContext = 0;
++ m_refCount = 0;
++}
++
++void CXVBAContext::Release()
++{
++ CSingleLock lock(m_section);
++
++ m_refCount--;
++ if (m_refCount <= 0)
++ {
++ Close();
++ delete this;
++ m_context = 0;
++ }
++}
++
++void CXVBAContext::Close()
++{
++ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder context");
++
++ DestroyContext();
++ if (m_dlHandle)
++ {
++ dlclose(m_dlHandle);
++ m_dlHandle = 0;
++ }
++}
++
++bool CXVBAContext::EnsureContext(CXVBAContext **ctx)
++{
++ CSingleLock lock(m_section);
++
++ if (m_context)
++ {
++ m_context->m_refCount++;
++ *ctx = m_context;
++ return true;
++ }
++
++ m_context = new CXVBAContext();
++ *ctx = m_context;
++ {
++ CSingleLock gLock(g_graphicsContext);
++ if (!m_context->LoadSymbols() || !m_context->CreateContext())
++ {
++ delete m_context;
++ m_context = 0;
++ return false;
++ }
++ }
++
++ m_context->m_refCount++;
++
++ *ctx = m_context;
++ return true;
++}
++
++bool CXVBAContext::LoadSymbols()
++{
++ if (!m_dlHandle)
++ {
++ m_dlHandle = dlopen(XVBA_LIBRARY, RTLD_LAZY);
++ if (!m_dlHandle)
++ {
++ const char* error = dlerror();
++ if (!error)
++ error = "dlerror() returned NULL";
++
++ CLog::Log(LOGERROR,"XVBA::LoadSymbols: Unable to get handle to lib: %s", error);
++ return false;
++ }
++ }
++ else
++ return true;
++
++#define INIT_PROC(PREFIX, PROC) do { \
++ g_##PREFIX##_vtable.PROC = (PREFIX##PROC##Proc) \
++ dlsym(m_dlHandle, #PREFIX #PROC); \
++ } while (0)
++
++#define INIT_PROC_CHECK(PREFIX, PROC) do { \
++ dlerror(); \
++ INIT_PROC(PREFIX, PROC); \
++ if (dlerror()) { \
++ dlclose(m_dlHandle); \
++ m_dlHandle = NULL; \
++ return false; \
++ } \
++ } while (0)
++
++#define XVBA_INIT_PROC(PROC) INIT_PROC_CHECK(XVBA, PROC)
++
++ XVBA_INIT_PROC(QueryExtension);
++ XVBA_INIT_PROC(CreateContext);
++ XVBA_INIT_PROC(DestroyContext);
++ XVBA_INIT_PROC(GetSessionInfo);
++ XVBA_INIT_PROC(CreateSurface);
++ XVBA_INIT_PROC(CreateGLSharedSurface);
++ XVBA_INIT_PROC(DestroySurface);
++ XVBA_INIT_PROC(CreateDecodeBuffers);
++ XVBA_INIT_PROC(DestroyDecodeBuffers);
++ XVBA_INIT_PROC(GetCapDecode);
++ XVBA_INIT_PROC(CreateDecode);
++ XVBA_INIT_PROC(DestroyDecode);
++ XVBA_INIT_PROC(StartDecodePicture);
++ XVBA_INIT_PROC(DecodePicture);
++ XVBA_INIT_PROC(EndDecodePicture);
++ XVBA_INIT_PROC(SyncSurface);
++ XVBA_INIT_PROC(GetSurface);
++ XVBA_INIT_PROC(TransferSurface);
++
++#undef XVBA_INIT_PROC
++#undef INIT_PROC
++
++ return true;
++}
++
++bool CXVBAContext::CreateContext()
++{
++ if (m_xvbaContext)
++ return true;
++
++ CLog::Log(LOGNOTICE,"XVBA::CreateContext - creating decoder context");
++
++ Drawable window;
++ { CSingleLock lock(g_graphicsContext);
++ if (!m_display)
++ m_display = XOpenDisplay(NULL);
++ window = g_Windowing.GetWindow();
++ }
++
++ int version;
++ if (!g_XVBA_vtable.QueryExtension(m_display, &version))
++ return false;
++ CLog::Log(LOGNOTICE,"XVBA::CreateContext - opening xvba version: %i", version);
++
++ // create XVBA Context
++ XVBA_Create_Context_Input contextInput;
++ XVBA_Create_Context_Output contextOutput;
++ contextInput.size = sizeof(contextInput);
++ contextInput.display = m_display;
++ contextInput.draw = window;
++ contextOutput.size = sizeof(contextOutput);
++ if(Success != g_XVBA_vtable.CreateContext(&contextInput, &contextOutput))
++ {
++ CLog::Log(LOGERROR,"XVBA::CreateContext - failed to create context");
++ return false;
++ }
++ m_xvbaContext = contextOutput.context;
++
++ return true;
++}
++
++void CXVBAContext::DestroyContext()
++{
++ if (!m_xvbaContext)
++ return;
++
++ g_XVBA_vtable.DestroyContext(m_xvbaContext);
++ m_xvbaContext = 0;
++// XCloseDisplay(m_display);
++}
++
++void *CXVBAContext::GetContext()
++{
++ return m_xvbaContext;
++}
++
++//-----------------------------------------------------------------------------
++//-----------------------------------------------------------------------------
++
++static unsigned int decoderId = 0;
++
++CDecoder::CDecoder()
++{
++ m_context = 0;
++ m_xvbaSession = 0;
++ m_flipBuffer = 0;
++}
++
++CDecoder::~CDecoder()
++{
++ Close();
++}
++
++typedef struct {
++ unsigned int size;
++ unsigned int num_of_decodecaps;
++ XVBADecodeCap decode_caps_list[];
++} XVBA_GetCapDecode_Output_Base;
++
++void CDecoder::OnLostDevice()
++{
++ CLog::Log(LOGNOTICE,"XVBA::OnLostDevice event");
++
++ CExclusiveLock lock(m_decoderSection);
++ DestroySession();
++ if (m_context)
++ m_context->Release();
++ m_context = 0;
++
++ m_displayState = XVBA_LOST;
++ m_displayEvent.Reset();
++}
++
++void CDecoder::OnResetDevice()
++{
++ CLog::Log(LOGNOTICE,"XVBA::OnResetDevice event");
++
++ CExclusiveLock lock(m_displaySection);
++ if (m_displayState == XVBA_LOST)
++ {
++ m_displayState = XVBA_RESET;
++ m_displayEvent.Set();
++ }
++}
++
++bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces)
++{
++ std::string Vendor = g_Windowing.GetRenderVendor();
++ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower);
++ if (Vendor.compare(0, 3, "ati") != 0)
++ {
++ return false;
++ }
++
++ m_decoderId = decoderId++;
++
++ CLog::Log(LOGNOTICE,"(XVBA::Open) opening xvba decoder, id: %d", m_decoderId);
++
++ if(avctx->coded_width == 0
++ || avctx->coded_height == 0)
++ {
++ CLog::Log(LOGWARNING,"(XVBA) no width/height available, can't init");
++ return false;
++ }
++
++ if (!m_dllAvUtil.Load())
++ return false;
++
++ if (!CXVBAContext::EnsureContext(&m_context))
++ return false;
++
++ // xvba get session info
++ XVBA_GetSessionInfo_Input sessionInput;
++ XVBA_GetSessionInfo_Output sessionOutput;
++ sessionInput.size = sizeof(sessionInput);
++ sessionInput.context = m_context->GetContext();
++ sessionOutput.size = sizeof(sessionOutput);
++ if (Success != g_XVBA_vtable.GetSessionInfo(&sessionInput, &sessionOutput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) can't get session info");
++ return false;
++ }
++ if (sessionOutput.getcapdecode_output_size == 0)
++ {
++ CLog::Log(LOGERROR,"(XVBA) session decode not supported");
++ return false;
++ }
++
++ // get decoder capabilities
++ XVBA_GetCapDecode_Input capInput;
++ XVBA_GetCapDecode_Output *capOutput;
++ capInput.size = sizeof(capInput);
++ capInput.context = m_context->GetContext();
++ capOutput = (XVBA_GetCapDecode_Output *)calloc(sessionOutput.getcapdecode_output_size, 1);
++ capOutput->size = sessionOutput.getcapdecode_output_size;
++ if (Success != g_XVBA_vtable.GetCapDecode(&capInput, capOutput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) can't get decode capabilities");
++ return false;
++ }
++
++ int match = -1;
++ if (avctx->codec_id == CODEC_ID_H264)
++ {
++ // search for profile high
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_H264 &&
++ capOutput->decode_caps_list[i].flags == XVBA_H264_HIGH)
++ {
++ match = (int) i;
++ break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_H264_HIGH not found");
++ }
++ }
++ else if (avctx->codec_id == CODEC_ID_VC1)
++ {
++ // search for profile advanced
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
++ capOutput->decode_caps_list[i].flags == XVBA_VC1_ADVANCED)
++ {
++ match = (int) i;
++ break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_ADVANCED not found");
++ }
++ }
++ else if (avctx->codec_id == CODEC_ID_MPEG2VIDEO)
++ {
++ // search for profile high
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_MPEG2_VLD)
++ {
++ // XXX: uncomment when implemented
++ // match = (int) i;
++ // break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_MPEG2_VLD not found");
++ }
++ }
++ else if (avctx->codec_id == CODEC_ID_WMV3)
++ {
++ // search for profile high
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
++ capOutput->decode_caps_list[i].flags == XVBA_VC1_MAIN)
++ {
++ match = (int) i;
++ break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_MAIN not found");
++ }
++ }
++
++ if (match < 0)
++ {
++ free(capOutput);
++ return false;
++ }
++
++ CLog::Log(LOGNOTICE,"(XVBA) using decoder capability id: %i flags: %i",
++ capOutput->decode_caps_list[match].capability_id,
++ capOutput->decode_caps_list[match].flags);
++ CLog::Log(LOGNOTICE,"(XVBA) using surface type: %x",
++ capOutput->decode_caps_list[match].surface_type);
++
++ m_decoderCap = capOutput->decode_caps_list[match];
++
++ free(capOutput);
++
++ // set some varables
++ m_xvbaSession = 0;
++ m_xvbaBufferPool.data_buffer = 0;
++ m_xvbaBufferPool.iq_matrix_buffer = 0;
++ m_xvbaBufferPool.picture_descriptor_buffer = 0;
++ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
++ m_surfaceWidth = 0;
++ m_surfaceHeight = 0;
++ m_presentPicture = 0;
++ m_numRenderBuffers = surfaces;
++ m_flipBuffer = new RenderPicture[m_numRenderBuffers];
++ for (unsigned int i = 0; i < m_numRenderBuffers; ++i)
++ {
++ m_flipBuffer[i].outPic = 0;
++ m_flipBuffer[i].glSurface[0] =
++ m_flipBuffer[i].glSurface[1] =
++ m_flipBuffer[i].glSurface[2] = 0;
++ m_flipBuffer[i].glTexture[0] =
++ m_flipBuffer[i].glTexture[1] =
++ m_flipBuffer[i].glTexture[2] = 0;
++ }
++ for (unsigned int j = 0; j < NUM_OUTPUT_PICS; ++j)
++ m_freeOutPic.push_back(&m_allOutPic[j]);
++ m_displayState = XVBA_OPEN;
++
++ // setup ffmpeg
++ avctx->thread_count = 1;
++ avctx->get_buffer = CDecoder::FFGetBuffer;
++ avctx->release_buffer = CDecoder::FFReleaseBuffer;
++ avctx->draw_horiz_band = CDecoder::FFDrawSlice;
++ avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
++
++ g_Windowing.Register(this);
++ return true;
++}
++
++void CDecoder::Close()
++{
++ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder, id: %d", m_decoderId);
++
++ if (!m_context)
++ return;
++
++ FinishGL();
++
++ DestroySession();
++ if (m_context)
++ m_context->Release();
++ m_context = 0;
++
++ while (!m_videoSurfaces.empty())
++ {
++ xvba_render_state *render = m_videoSurfaces.back();
++ if(render->buffers_alllocated > 0)
++ m_dllAvUtil.av_free(render->buffers);
++ m_videoSurfaces.pop_back();
++ free(render);
++ }
++
++ if (m_flipBuffer)
++ delete [] m_flipBuffer;
++
++ g_Windowing.Unregister(this);
++ m_dllAvUtil.Unload();
++}
++
++void CDecoder::ResetState()
++{
++ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
++ m_presentPicture = 0;
++ m_freeOutPic.clear();
++ m_usedOutPic.clear();
++ for (int j = 0; j < NUM_OUTPUT_PICS; ++j)
++ m_freeOutPic.push_back(&m_allOutPic[j]);
++ m_displayState = XVBA_OPEN;
++}
++
++int CDecoder::Check(AVCodecContext* avctx)
++{
++ EDisplayState state;
++
++ { CSharedLock lock(m_displaySection);
++ state = m_displayState;
++ }
++
++ if (state == XVBA_LOST)
++ {
++ CLog::Log(LOGNOTICE,"XVBA::Check waiting for display reset event");
++ if (!m_displayEvent.WaitMSec(2000))
++ {
++ CLog::Log(LOGERROR, "XVBA::Check - device didn't reset in reasonable time");
++ return VC_ERROR;
++ }
++ { CSharedLock lock(m_displaySection);
++ state = m_displayState;
++ }
++ }
++ if (state == XVBA_RESET || state == XVBA_ERROR)
++ {
++ CLog::Log(LOGNOTICE,"XVBA::Check - Attempting recovery");
++
++ CSingleLock gLock(g_graphicsContext);
++ CExclusiveLock lock(m_decoderSection);
++
++ DestroySession();
++ ResetState();
++ CXVBAContext::EnsureContext(&m_context);
++
++ if (state == XVBA_RESET)
++ return VC_FLUSHED;
++ else
++ return VC_ERROR;
++ }
++ return 0;
++}
++
++void CDecoder::SetError(const char* function, const char* msg, int line)
++{
++ CLog::Log(LOGERROR, "XVBA::%s - %s, line %d", function, msg, line);
++ CExclusiveLock lock(m_displaySection);
++ m_displayState = XVBA_ERROR;
++}
++
++bool CDecoder::CreateSession(AVCodecContext* avctx)
++{
++ m_surfaceWidth = (avctx->coded_width+15) & ~15;
++ m_surfaceHeight = (avctx->coded_height+15) & ~15;
++
++ m_vidWidth = avctx->width;
++ m_vidHeight = avctx->height;
++
++ XVBA_Create_Decode_Session_Input sessionInput;
++ XVBA_Create_Decode_Session_Output sessionOutput;
++
++ sessionInput.size = sizeof(sessionInput);
++ sessionInput.width = m_surfaceWidth;
++ sessionInput.height = m_surfaceHeight;
++ sessionInput.context = m_context->GetContext();
++ sessionInput.decode_cap = &m_decoderCap;
++ sessionOutput.size = sizeof(sessionOutput);
++
++ if (Success != g_XVBA_vtable.CreateDecode(&sessionInput, &sessionOutput))
++ {
++ SetError(__FUNCTION__, "failed to create decoder session", __LINE__);
++ CLog::Log(LOGERROR, "Decoder failed with following stats: m_surfaceWidth %u, m_surfaceHeight %u,"
++ " m_vidWidth %u, m_vidHeight %u, coded_width %d, coded_height %d",
++ m_surfaceWidth,
++ m_surfaceHeight,
++ m_vidWidth,
++ m_vidHeight,
++ avctx->coded_width,
++ avctx->coded_height);
++ return false;
++ }
++ m_xvbaSession = sessionOutput.session;
++
++
++ // create decode buffers
++ XVBA_Create_DecodeBuff_Input bufferInput;
++ XVBA_Create_DecodeBuff_Output bufferOutput;
++
++ bufferInput.size = sizeof(bufferInput);
++ bufferInput.session = m_xvbaSession;
++ bufferInput.buffer_type = XVBA_PICTURE_DESCRIPTION_BUFFER;
++ bufferInput.num_of_buffers = 1;
++ bufferOutput.size = sizeof(bufferOutput);
++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
++ || bufferOutput.num_of_buffers_in_list != 1)
++ {
++ SetError(__FUNCTION__, "failed to create picture buffer", __LINE__);
++ return false;
++ }
++ m_xvbaBufferPool.picture_descriptor_buffer = bufferOutput.buffer_list;
++
++ // data buffer
++ bufferInput.buffer_type = XVBA_DATA_BUFFER;
++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
++ || bufferOutput.num_of_buffers_in_list != 1)
++ {
++ SetError(__FUNCTION__, "failed to create data buffer", __LINE__);
++ return false;
++ }
++ m_xvbaBufferPool.data_buffer = bufferOutput.buffer_list;
++
++ // QO Buffer
++ bufferInput.buffer_type = XVBA_QM_BUFFER;
++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
++ || bufferOutput.num_of_buffers_in_list != 1)
++ {
++ SetError(__FUNCTION__, "failed to create qm buffer", __LINE__);
++ return false;
++ }
++ m_xvbaBufferPool.iq_matrix_buffer = bufferOutput.buffer_list;
++
++ return true;
++}
++
++void CDecoder::DestroySession()
++{
++ XVBA_Destroy_Decode_Buffers_Input bufInput;
++ bufInput.size = sizeof(bufInput);
++ bufInput.num_of_buffers_in_list = 1;
++
++ for (unsigned int i=0; isurface)
++ {
++ g_XVBA_vtable.DestroySurface(render->surface);
++ render->surface = 0;
++ render->picture_descriptor = 0;
++ render->iq_matrix = 0;
++ }
++ }
++
++ if (m_xvbaSession)
++ g_XVBA_vtable.DestroyDecode(m_xvbaSession);
++ m_xvbaSession = 0;
++}
++
++bool CDecoder::IsSurfaceValid(xvba_render_state *render)
++{
++ // find render state in queue
++ bool found(false);
++ unsigned int i;
++ for(i = 0; i < m_videoSurfaces.size(); ++i)
++ {
++ if(m_videoSurfaces[i] == render)
++ {
++ found = true;
++ break;
++ }
++ }
++ if (!found)
++ {
++ CLog::Log(LOGERROR,"%s - video surface not found", __FUNCTION__);
++ return false;
++ }
++ if (m_videoSurfaces[i]->surface == 0)
++ {
++ m_videoSurfaces[i]->state = 0;
++ return false;
++ }
++
++ return true;
++}
++
++bool CDecoder::EnsureDataControlBuffers(unsigned int num)
++{
++ if (m_xvbaBufferPool.data_control_buffers.size() >= num)
++ return true;
++
++ unsigned int missing = num - m_xvbaBufferPool.data_control_buffers.size();
++
++ XVBA_Create_DecodeBuff_Input bufferInput;
++ XVBA_Create_DecodeBuff_Output bufferOutput;
++ bufferInput.size = sizeof(bufferInput);
++ bufferInput.session = m_xvbaSession;
++ bufferInput.buffer_type = XVBA_DATA_CTRL_BUFFER;
++ bufferInput.num_of_buffers = 1;
++ bufferOutput.size = sizeof(bufferOutput);
++
++ for (unsigned int i=0; iopaque;
++ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
++ unsigned int i;
++
++ CSharedLock lock(xvba->m_decoderSection);
++
++ xvba_render_state * render = NULL;
++ render = (xvba_render_state*)pic->data[0];
++ if(!render)
++ {
++ CLog::Log(LOGERROR, "XVBA::FFReleaseBuffer - invalid context handle provided");
++ return;
++ }
++
++ for(i=0; i<4; i++)
++ pic->data[i]= NULL;
++
++ // find render state in queue
++ if (!xvba->IsSurfaceValid(render))
++ {
++ CLog::Log(LOGDEBUG, "XVBA::FFReleaseBuffer - ignoring invalid buffer");
++ return;
++ }
++
++ render->state &= ~FF_XVBA_STATE_USED_FOR_REFERENCE;
++}
++
++void CDecoder::FFDrawSlice(struct AVCodecContext *avctx,
++ const AVFrame *src, int offset[4],
++ int y, int type, int height)
++{
++ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
++ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
++
++ CSharedLock lock(xvba->m_decoderSection);
++
++ { CSharedLock dLock(xvba->m_displaySection);
++ if(xvba->m_displayState != XVBA_OPEN)
++ return;
++ }
++
++ if(src->linesize[0] || src->linesize[1] || src->linesize[2]
++ || offset[0] || offset[1] || offset[2])
++ {
++ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid linesizes or offsets provided");
++ return;
++ }
++
++ xvba_render_state * render;
++
++ render = (xvba_render_state*)src->data[0];
++ if(!render)
++ {
++ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid context handle provided");
++ return;
++ }
++
++ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
++ if (!xvba->IsSurfaceValid(render))
++ {
++ CLog::Log(LOGWARNING, "XVBA::FFDrawSlice - ignoring invalid buffer");
++ return;
++ }
++
++ // decoding
++ XVBA_Decode_Picture_Start_Input startInput;
++ startInput.size = sizeof(startInput);
++ startInput.session = xvba->m_xvbaSession;
++ startInput.target_surface = render->surface;
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.StartDecodePicture(&startInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to start decoding", __LINE__);
++ return;
++ }
++ }
++ XVBA_Decode_Picture_Input picInput;
++ picInput.size = sizeof(picInput);
++ picInput.session = xvba->m_xvbaSession;
++ XVBABufferDescriptor *list[2];
++ picInput.buffer_list = list;
++ list[0] = xvba->m_xvbaBufferPool.picture_descriptor_buffer;
++ picInput.num_of_buffers_in_list = 1;
++ if (avctx->codec_id == CODEC_ID_H264)
++ {
++ list[1] = xvba->m_xvbaBufferPool.iq_matrix_buffer;
++ picInput.num_of_buffers_in_list = 2;
++ }
++
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to decode picture 1", __LINE__);
++ return;
++ }
++ }
++
++ if (!xvba->EnsureDataControlBuffers(render->num_slices))
++ return;
++
++ XVBADataCtrl *dataControl;
++ int location = 0;
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer = 0;
++ for (unsigned int j = 0; j < render->num_slices; ++j)
++ {
++ int startCodeSize = 0;
++ uint8_t startCode[] = {0x00,0x00,0x01};
++ if (avctx->codec_id == CODEC_ID_H264)
++ {
++ startCodeSize = 3;
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
++ startCode, 3);
++ }
++ else if (avctx->codec_id == CODEC_ID_VC1 &&
++ (memcmp(render->buffers[j].buffer, startCode, 3) != 0))
++ {
++ startCodeSize = 4;
++ uint8_t sdf = 0x0d;
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
++ startCode, 3);
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+3,
++ &sdf, 1);
++ }
++ // check for potential buffer overwrite
++ unsigned int bytesToCopy = render->buffers[j].size;
++ unsigned int freeBufferSize = xvba->m_xvbaBufferPool.data_buffer->buffer_size -
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
++ if (bytesToCopy >= freeBufferSize)
++ {
++ xvba->SetError(__FUNCTION__, "bitstream buffer too large, maybe corrupted packet", __LINE__);
++ return;
++ }
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+startCodeSize,
++ render->buffers[j].buffer,
++ render->buffers[j].size);
++ dataControl = (XVBADataCtrl*)xvba->m_xvbaBufferPool.data_control_buffers[j]->bufferXVBA;
++ dataControl->SliceDataLocation = location;
++ dataControl->SliceBytesInBuffer = render->buffers[j].size+startCodeSize;
++ dataControl->SliceBitsInBuffer = dataControl->SliceBytesInBuffer * 8;
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += dataControl->SliceBytesInBuffer;
++ location += dataControl->SliceBytesInBuffer;
++ }
++
++ int bufSize = xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
++ int padding = bufSize % 128;
++ if (padding)
++ {
++ padding = 128 - padding;
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += padding;
++ memset((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+bufSize,0,padding);
++ }
++
++ picInput.num_of_buffers_in_list = 2;
++ for (unsigned int i = 0; i < render->num_slices; ++i)
++ {
++ list[0] = xvba->m_xvbaBufferPool.data_buffer;
++ list[0]->data_offset = 0;
++ list[1] = xvba->m_xvbaBufferPool.data_control_buffers[i];
++ list[1]->data_size_in_buffer = sizeof(*dataControl);
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to decode picture 2", __LINE__);
++ return;
++ }
++ }
++ }
++ XVBA_Decode_Picture_End_Input endInput;
++ endInput.size = sizeof(endInput);
++ endInput.session = xvba->m_xvbaSession;
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.EndDecodePicture(&endInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to decode picture 3", __LINE__);
++ return;
++ }
++ }
++
++ // decode sync and error
++ XVBA_Surface_Sync_Input syncInput;
++ XVBA_Surface_Sync_Output syncOutput;
++ syncInput.size = sizeof(syncInput);
++ syncInput.session = xvba->m_xvbaSession;
++ syncInput.surface = render->surface;
++ syncInput.query_status = XVBA_GET_SURFACE_STATUS;
++ syncOutput.size = sizeof(syncOutput);
++ int64_t start = CurrentHostCounter();
++ while (1)
++ {
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput))
++ {
++ xvba->SetError(__FUNCTION__, "failed sync surface 1", __LINE__);
++ return;
++ }
++ }
++ if (!(syncOutput.status_flags & XVBA_STILL_PENDING))
++ break;
++ if (CurrentHostCounter() - start > CurrentHostFrequency())
++ {
++ xvba->SetError(__FUNCTION__, "timed out waiting for surface", __LINE__);
++ break;
++ }
++ usleep(100);
++ }
++}
++
++int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
++{
++ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
++ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
++ struct pictureAge* pA = &xvba->picAge;
++
++ pic->data[0] =
++ pic->data[1] =
++ pic->data[2] =
++ pic->data[3] = 0;
++
++ pic->linesize[0] =
++ pic->linesize[1] =
++ pic->linesize[2] =
++ pic->linesize[3] = 0;
++
++ CSharedLock lock(xvba->m_decoderSection);
++
++ { CSharedLock dLock(xvba->m_displaySection);
++ if(xvba->m_displayState != XVBA_OPEN)
++ return -1;
++ }
++
++ if (xvba->m_xvbaSession == 0)
++ {
++ if (!xvba->CreateSession(avctx))
++ return -1;
++ }
++
++ xvba_render_state * render = NULL;
++ // find unused surface
++ { CSingleLock lock(xvba->m_videoSurfaceSec);
++ for(unsigned int i = 0; i < xvba->m_videoSurfaces.size(); ++i)
++ {
++ if(!(xvba->m_videoSurfaces[i]->state & (FF_XVBA_STATE_USED_FOR_REFERENCE | FF_XVBA_STATE_USED_FOR_RENDER)))
++ {
++ render = xvba->m_videoSurfaces[i];
++ render->state = 0;
++ break;
++ }
++ }
++ }
++
++ // create a new render state
++ if (render == NULL)
++ {
++ render = (xvba_render_state*)calloc(sizeof(xvba_render_state), 1);
++ if (render == NULL)
++ {
++ CLog::Log(LOGERROR, "XVBA::FFGetBuffer - calloc failed");
++ return -1;
++ }
++ render->surface = 0;
++ render->buffers_alllocated = 0;
++ CSingleLock lock(xvba->m_videoSurfaceSec);
++ xvba->m_videoSurfaces.push_back(render);
++ }
++
++ // create a new surface
++ if (render->surface == 0)
++ {
++ XVBA_Create_Surface_Input surfaceInput;
++ XVBA_Create_Surface_Output surfaceOutput;
++ surfaceInput.size = sizeof(surfaceInput);
++ surfaceInput.surface_type = xvba->m_decoderCap.surface_type;
++ surfaceInput.width = xvba->m_surfaceWidth;
++ surfaceInput.height = xvba->m_surfaceHeight;
++ surfaceInput.session = xvba->m_xvbaSession;
++ surfaceOutput.size = sizeof(surfaceOutput);
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.CreateSurface(&surfaceInput, &surfaceOutput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to create video surface", __LINE__);
++ return -1;
++ }
++ }
++ render->surface = surfaceOutput.surface;
++ render->picture_descriptor = (XVBAPictureDescriptor *)xvba->m_xvbaBufferPool.picture_descriptor_buffer->bufferXVBA;
++ render->iq_matrix = (XVBAQuantMatrixAvc *)xvba->m_xvbaBufferPool.iq_matrix_buffer->bufferXVBA;
++ CLog::Log(LOGDEBUG, "XVBA::FFGetBuffer - created video surface");
++ }
++
++ if (render == NULL)
++ return -1;
++
++ pic->data[0] = (uint8_t*)render;
++
++ if(pic->reference)
++ {
++ pic->age = pA->ip_age[0];
++ pA->ip_age[0]= pA->ip_age[1]+1;
++ pA->ip_age[1]= 1;
++ pA->b_age++;
++ }
++ else
++ {
++ pic->age = pA->b_age;
++ pA->ip_age[0]++;
++ pA->ip_age[1]++;
++ pA->b_age = 1;
++ }
++ pic->type= FF_BUFFER_TYPE_USER;
++
++ render->state |= FF_XVBA_STATE_USED_FOR_REFERENCE;
++ pic->reordered_opaque= avctx->reordered_opaque;
++
++ return 0;
++}
++
++int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
++{
++ int result = Check(avctx);
++ if (result)
++ return result;
++
++ CSharedLock lock(m_decoderSection);
++
++ int iReturn(0);
++ if(frame)
++ { // we have a new frame from decoder
++
++ xvba_render_state * render = (xvba_render_state*)frame->data[0];
++ if(!render)
++ return VC_ERROR;
++
++ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
++ if (!IsSurfaceValid(render))
++ {
++ CLog::Log(LOGWARNING, "XVBA::Decode - ignoring invalid buffer");
++ return VC_BUFFER;
++ }
++
++ render->state |= FF_XVBA_STATE_USED_FOR_RENDER;
++
++ CSingleLock lock(m_outPicSec);
++ if (m_freeOutPic.empty())
++ {
++ return VC_ERROR;
++ }
++ OutputPicture *outPic = m_freeOutPic.front();
++ m_freeOutPic.pop_front();
++ memset(&outPic->dvdPic, 0, sizeof(DVDVideoPicture));
++ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&outPic->dvdPic);
++ outPic->render = render;
++
++ if (g_guiSettings.GetBool("videoplayer.usexvbasharedsurface"))
++ outPic->dvdPic.format = DVDVideoPicture::FMT_XVBA;
++ else
++ outPic->dvdPic.format = DVDVideoPicture::FMT_XVBA_YV12;
++ outPic->dvdPic.iWidth = m_surfaceWidth;
++ outPic->dvdPic.iHeight = m_surfaceHeight;
++ outPic->dvdPic.xvba = this;
++
++ m_usedOutPic.push_back(outPic);
++ lock.Leave();
++
++ iReturn |= VC_PICTURE;
++ }
++
++ { CSingleLock lock(m_outPicSec);
++ if (!m_freeOutPic.empty())
++ iReturn |= VC_BUFFER;
++ }
++
++ return iReturn;
++}
++
++bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
++{
++ CSharedLock lock(m_decoderSection);
++
++ { CSharedLock dLock(m_displaySection);
++ if(m_displayState != XVBA_OPEN)
++ return false;
++ }
++
++ { CSingleLock lock(m_outPicSec);
++
++ if (DiscardPresentPicture())
++ CLog::Log(LOGWARNING,"XVBA::GetPicture: old presentPicture was still valid - now discarded");
++ if (m_usedOutPic.size() > 0)
++ {
++ m_presentPicture = m_usedOutPic.front();
++ m_usedOutPic.pop_front();
++ *picture = m_presentPicture->dvdPic;
++ }
++ else
++ {
++ CLog::Log(LOGERROR,"XVBA::GetPicture: no picture");
++ return false;
++ }
++ }
++ return true;
++}
++
++bool CDecoder::DiscardPresentPicture()
++{
++ CSingleLock lock(m_outPicSec);
++ if (m_presentPicture)
++ {
++ if (m_presentPicture->render)
++ m_presentPicture->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
++ m_presentPicture->render = NULL;
++ m_freeOutPic.push_back(m_presentPicture);
++ m_presentPicture = NULL;
++ return true;
++ }
++ return false;
++}
++
++void CDecoder::Present(int index)
++{
++ CSharedLock lock(m_decoderSection);
++
++ { CSharedLock dLock(m_displaySection);
++ if(m_displayState != XVBA_OPEN)
++ return;
++ }
++
++ if (!m_presentPicture)
++ {
++ // use last picture, we might processing a still frame here
++ int lastIndex = (index + m_numRenderBuffers -1) % m_numRenderBuffers;
++ m_presentPicture = m_flipBuffer[lastIndex].outPic;
++ m_flipBuffer[lastIndex].isDuplicate = true;
++ if (!m_presentPicture)
++ {
++ CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL");
++ return;
++ }
++ }
++
++ if (m_flipBuffer[index].outPic && !m_flipBuffer[index].isDuplicate)
++ {
++ if (m_flipBuffer[index].outPic->render)
++ {
++ CSingleLock lock(m_videoSurfaceSec);
++ m_flipBuffer[index].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
++ m_flipBuffer[index].outPic->render = NULL;
++ }
++ CSingleLock lock(m_outPicSec);
++ m_freeOutPic.push_back(m_flipBuffer[index].outPic);
++ m_flipBuffer[index].outPic = NULL;
++ }
++
++ m_flipBuffer[index].outPic = m_presentPicture;
++ m_flipBuffer[index].isDuplicate = false;
++ m_presentPicture = NULL;
++}
++
++void CDecoder::CopyYV12(int index, uint8_t *dest)
++{
++ CSharedLock lock(m_decoderSection);
++
++ { CSharedLock dLock(m_displaySection);
++ if(m_displayState != XVBA_OPEN)
++ return;
++ }
++
++ if (!m_flipBuffer[index].outPic)
++ {
++ CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL");
++ return;
++ }
++
++ XVBA_GetSurface_Target target;
++ target.size = sizeof(target);
++ target.surfaceType = XVBA_YV12;
++ target.flag = XVBA_FRAME;
++
++ XVBA_Get_Surface_Input input;
++ input.size = sizeof(input);
++ input.session = m_xvbaSession;
++ input.src_surface = m_flipBuffer[index].outPic->render->surface;
++ input.target_buffer = dest;
++ input.target_pitch = m_surfaceWidth;
++ input.target_width = m_surfaceWidth;
++ input.target_height = m_surfaceHeight;
++ input.target_parameter = target;
++ { CSingleLock lock(m_apiSec);
++ if (Success != g_XVBA_vtable.GetSurface(&input))
++ {
++ CLog::Log(LOGERROR,"(XVBA::CopyYV12) failed to get surface");
++ }
++ }
++}
++
++void CDecoder::Reset()
++{
++
++}
++
++int CDecoder::UploadTexture(int index, XVBA_SURFACE_FLAG field, GLenum textureTarget)
++{
++ CSharedLock lock(m_decoderSection);
++
++ { CSharedLock dLock(m_displaySection);
++ if(m_displayState != XVBA_OPEN)
++ return -1;
++ }
++
++ if (!m_flipBuffer[index].outPic ||
++ !m_flipBuffer[index].outPic->render ||
++ !m_flipBuffer[index].outPic->render->surface)
++ return -1;
++
++ int i = field;
++// unsigned int first, last;
++// first = last = 0;
++// if (field != XVBA_FRAME)
++// {
++// first = 1;
++// last = 2;
++// }
++// for (unsigned int i = first; i <= last; ++i)
++ {
++ XVBA_SURFACE_FLAG field;
++ if (i==0) field = XVBA_FRAME;
++ else if (i==1) field = XVBA_TOP_FIELD;
++ else field = XVBA_BOTTOM_FIELD;
++
++ if (!glIsTexture(m_flipBuffer[index].glTexture[i]))
++ {
++ glEnable(textureTarget);
++ glGenTextures(1, &m_flipBuffer[index].glTexture[i]);
++ glBindTexture(textureTarget, m_flipBuffer[index].glTexture[i]);
++ glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_surfaceWidth, m_surfaceHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
++
++ XVBA_Create_GLShared_Surface_Input surfInput;
++ XVBA_Create_GLShared_Surface_Output surfOutput;
++ surfInput.size = sizeof(surfInput);
++ surfInput.session = m_xvbaSession;
++ surfInput.gltexture = m_flipBuffer[index].glTexture[i];
++ surfInput.glcontext = glXGetCurrentContext();
++ surfOutput.size = sizeof(surfOutput);
++ surfOutput.surface = 0;
++ if (Success != g_XVBA_vtable.CreateGLSharedSurface(&surfInput, &surfOutput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) failed to create shared surface");
++ return -1;
++ }
++ m_flipBuffer[index].glSurface[i] = surfOutput.surface;
++ CLog::Log(LOGDEBUG, "XVBA::GetTexture - created shared surface");
++ }
++
++ XVBA_Transfer_Surface_Input transInput;
++ transInput.size = sizeof(transInput);
++ transInput.session = m_xvbaSession;
++ transInput.src_surface = m_flipBuffer[index].outPic->render->surface;
++ transInput.target_surface = m_flipBuffer[index].glSurface[i];
++ transInput.flag = field;
++ { CSingleLock lock(m_apiSec);
++ if (Success != g_XVBA_vtable.TransferSurface(&transInput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
++ return -1;
++ }
++ }
++ }
++
++// { CSingleLock lock(m_videoSurfaceSec);
++// m_flipBuffer[index].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
++// m_flipBuffer[index].outPic->render = NULL;
++// }
++// {
++// CSingleLock lock(m_outPicSec);
++// m_freeOutPic.push_back(m_flipBuffer[index].outPic);
++// m_flipBuffer[index].outPic = NULL;
++// }
++
++ return 1;
++}
++
++GLuint CDecoder::GetTexture(int index, XVBA_SURFACE_FLAG field)
++{
++ return m_flipBuffer[index].glTexture[field];
++}
++
++CRect CDecoder::GetCropRect()
++{
++ CRect crop;
++ crop.x1 = 0;
++ crop.y1 = 0;
++ crop.x2 = m_vidWidth;
++ crop.y2 = m_vidHeight;
++ return crop;
++}
++
++void CDecoder::FinishGL()
++{
++ CLog::Log(LOGNOTICE, "XVBA::FinishGL - clearing down gl resources");
++
++ CExclusiveLock lock(m_decoderSection);
++ // if decoder was created with non supported codec, we would not have a flipBuffer and segfault
++ if(!m_flipBuffer)
++ return;
++
++ for (unsigned int i=0; irender)
++ {
++ { CSingleLock lock(m_videoSurfaceSec);
++ m_flipBuffer[i].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
++ m_flipBuffer[i].outPic->render = NULL;
++ }
++ { CSingleLock lock(m_outPicSec);
++ m_freeOutPic.push_back(m_flipBuffer[i].outPic);
++ m_flipBuffer[i].outPic = 0;
++ }
++ }
++
++ for (unsigned int j=0; j<3; ++j)
++ {
++ if (glIsTexture(m_flipBuffer[i].glTexture[j]))
++ {
++ glDeleteTextures(1, &m_flipBuffer[i].glTexture[j]);
++ m_flipBuffer[i].glTexture[j] = 0;
++ CLog::Log(LOGDEBUG, "XVBA::FinishGL - destroyed texture, index: %d, field %d", i, j);
++ }
++ if (m_flipBuffer[i].glSurface[j] && m_xvbaSession)
++ {
++ { CSingleLock lock(m_apiSec);
++ g_XVBA_vtable.DestroySurface(m_flipBuffer[i].glSurface[j]);
++ }
++ m_flipBuffer[i].glSurface[j] = 0;
++ CLog::Log(LOGDEBUG, "XVBA::FinishGL - destroyed shared surface");
++ }
++ }
++ }
++}
++
++#endif
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
+new file mode 100644
+index 0000000..5ca39ab
+--- /dev/null
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
+@@ -0,0 +1,161 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++#pragma once
++
++#include "X11/Xlib.h"
++#include "amd/amdxvba.h"
++#include "DllAvCodec.h"
++#include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h"
++#include "threads/CriticalSection.h"
++#include "threads/SharedSection.h"
++#include "threads/Event.h"
++#include "guilib/DispResource.h"
++#include "guilib/Geometry.h"
++#include "libavcodec/xvba.h"
++#include
++#include
++
++#define NUM_OUTPUT_PICS 7
++
++namespace XVBA
++{
++
++struct pictureAge
++{
++ int b_age;
++ int ip_age[2];
++};
++
++enum EDisplayState
++{ XVBA_OPEN
++, XVBA_RESET
++, XVBA_LOST
++, XVBA_ERROR
++};
++
++class CXVBAContext
++{
++public:
++ static bool EnsureContext(CXVBAContext **ctx);
++ void *GetContext();
++ void Release();
++private:
++ CXVBAContext();
++ void Close();
++ bool LoadSymbols();
++ bool CreateContext();
++ void DestroyContext();
++ static CXVBAContext *m_context;
++ static CCriticalSection m_section;
++ static Display *m_display;
++ int m_refCount;
++ void *m_dlHandle;
++ void *m_xvbaContext;
++};
++
++class CDecoder : public CDVDVideoCodecFFmpeg::IHardwareDecoder,
++ public IDispResource
++{
++public:
++ CDecoder();
++ virtual ~CDecoder();
++ virtual void OnLostDevice();
++ virtual void OnResetDevice();
++
++ virtual bool Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces = 0);
++ virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
++ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
++ virtual void Reset();
++ virtual void Close();
++ virtual int Check(AVCodecContext* avctx);
++ virtual const std::string Name() { return "xvba"; }
++
++ void Present(int index);
++ void CopyYV12(int index, uint8_t *dest);
++ int UploadTexture(int index, XVBA_SURFACE_FLAG field, GLenum textureTarget);
++ GLuint GetTexture(int index, XVBA_SURFACE_FLAG field);
++ CRect GetCropRect();
++ void FinishGL();
++
++protected:
++ bool CreateSession(AVCodecContext* avctx);
++ void DestroySession();
++ bool EnsureDataControlBuffers(unsigned int num);
++ bool DiscardPresentPicture();
++ void ResetState();
++ void SetError(const char* function, const char* msg, int line);
++ bool IsSurfaceValid(xvba_render_state *render);
++
++ // callbacks for ffmpeg
++ static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
++ static void FFDrawSlice(struct AVCodecContext *avctx,
++ const AVFrame *src, int offset[4],
++ int y, int type, int height);
++ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
++
++ DllAvUtil m_dllAvUtil;
++ CXVBAContext *m_context;
++ CSharedSection m_displaySection, m_decoderSection;
++ CEvent m_displayEvent;
++ EDisplayState m_displayState;
++
++ unsigned int m_surfaceWidth, m_surfaceHeight;
++ unsigned int m_vidWidth, m_vidHeight;
++ unsigned int m_numRenderBuffers;
++
++ XVBADecodeCap m_decoderCap;
++ void *m_xvbaSession;
++ unsigned int m_decoderId;
++ struct XVBABufferPool
++ {
++ XVBABufferDescriptor *picture_descriptor_buffer;
++ XVBABufferDescriptor *iq_matrix_buffer;
++ XVBABufferDescriptor *data_buffer;
++ std::vector data_control_buffers;
++ };
++ XVBABufferPool m_xvbaBufferPool;
++
++ std::vector m_videoSurfaces;
++ pictureAge picAge;
++
++ struct OutputPicture
++ {
++ DVDVideoPicture dvdPic;
++ xvba_render_state *render;
++ void *glSurface;
++ };
++ struct RenderPicture
++ {
++ OutputPicture *outPic;
++ bool isDuplicate;
++ void *glSurface[3];
++ GLuint glTexture[3];
++ };
++ CCriticalSection m_outPicSec, m_videoSurfaceSec;
++ CCriticalSection m_apiSec;
++ OutputPicture m_allOutPic[NUM_OUTPUT_PICS];
++ std::deque m_freeOutPic;
++ std::deque m_usedOutPic;
++ OutputPicture *m_presentPicture;
++ RenderPicture *m_flipBuffer;
++};
++
++}
+diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+index b0a3796..858a2ed 100644
+--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+@@ -19,7 +19,6 @@
+ *
+ */
+
+-#include "threads/SystemClock.h"
+ #include "system.h"
+ #ifndef __STDC_CONSTANT_MACROS
+ #define __STDC_CONSTANT_MACROS
+@@ -44,6 +43,7 @@
+ #include "filesystem/Directory.h"
+ #include "utils/log.h"
+ #include "threads/Thread.h"
++#include "threads/SystemClock.h"
+ #include "utils/TimeUtils.h"
+
+ void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo)
+@@ -153,16 +153,12 @@ static void ff_flush_avutil_log_buffers(void)
+ ++it;
+ }
+
+-#ifdef _MSC_VER
+-static __declspec(thread) CDVDDemuxFFmpeg* g_demuxer = 0;
+-#else
+-static TLS g_tls;
+-#define g_demuxer (*((CDVDDemuxFFmpeg**)g_tls.Get()))
+-#endif
++static XbmcThreads::ThreadLocal g_demuxer;
+
+ static int interrupt_cb(void)
+ {
+- if(g_demuxer && g_demuxer->Aborted())
++ CDVDDemuxFFmpeg* demuxer = g_demuxer.get();
++ if(demuxer && demuxer->Aborted())
+ return 1;
+ return 0;
+ }
+@@ -234,7 +230,7 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
+ std::string strFile;
+ m_iCurrentPts = DVD_NOPTS_VALUE;
+ m_speed = DVD_PLAYSPEED_NORMAL;
+- g_demuxer = this;
++ g_demuxer.set(this);
+ m_program = UINT_MAX;
+
+ if (!pInput) return false;
+@@ -506,7 +502,7 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
+
+ void CDVDDemuxFFmpeg::Dispose()
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ if (m_pFormatContext)
+ {
+@@ -555,7 +551,7 @@ void CDVDDemuxFFmpeg::Reset()
+
+ void CDVDDemuxFFmpeg::Flush()
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ // naughty usage of an internal ffmpeg function
+ if (m_pFormatContext)
+@@ -571,7 +567,7 @@ void CDVDDemuxFFmpeg::Abort()
+
+ void CDVDDemuxFFmpeg::SetSpeed(int iSpeed)
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ if(!m_pFormatContext)
+ return;
+@@ -633,7 +629,7 @@ double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num)
+
+ DemuxPacket* CDVDDemuxFFmpeg::Read()
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ AVPacket pkt;
+ DemuxPacket* pPacket = NULL;
+@@ -832,7 +828,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
+
+ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ if(time < 0)
+ time = 0;
+@@ -892,7 +888,7 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
+
+ bool CDVDDemuxFFmpeg::SeekByte(__int64 pos)
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ CSingleLock lock(m_critSection);
+ int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, pos, AVSEEK_FLAG_BYTE);
+diff --git a/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp b/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp
+index 23c5e3e..129674a 100644
+--- a/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp
++++ b/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp
+@@ -21,6 +21,7 @@
+
+ #include "DVDPerformanceCounter.h"
+ #include "DVDMessageQueue.h"
++#include "utils/TimeUtils.h"
+
+ #include "dvd_config.h"
+
+@@ -68,22 +69,16 @@ HRESULT __stdcall DVDPerformanceCounterVideoQueue(PLARGE_INTEGER numerator, PLAR
+
+ inline __int64 get_thread_cpu_usage(ProcessPerformance* p)
+ {
+- if (p->hThread)
++ if (p->thread)
+ {
+- FILETIME dummy;
+- FILETIME current_time_thread;
+- FILETIME current_time_system;
+ ULARGE_INTEGER old_time_thread;
+ ULARGE_INTEGER old_time_system;
+
+ old_time_thread.QuadPart = p->timer_thread.QuadPart;
+ old_time_system.QuadPart = p->timer_system.QuadPart;
+
+- GetThreadTimes(p->hThread, &dummy, &dummy, ¤t_time_thread, &dummy);
+- GetSystemTimeAsFileTime(¤t_time_system);
+-
+- FILETIME_TO_ULARGE_INTEGER(p->timer_thread, current_time_thread);
+- FILETIME_TO_ULARGE_INTEGER(p->timer_system, current_time_system);
++ p->timer_thread.QuadPart = p->thread->GetAbsoluteUsage();
++ p->timer_system.QuadPart = CurrentHostCounter();
+
+ __int64 threadTime = (p->timer_thread.QuadPart - old_time_thread.QuadPart);
+ __int64 systemTime = (p->timer_system.QuadPart - old_time_system.QuadPart);
+diff --git a/xbmc/cores/dvdplayer/DVDPerformanceCounter.h b/xbmc/cores/dvdplayer/DVDPerformanceCounter.h
+index 2f0b5ac..e97a14c 100644
+--- a/xbmc/cores/dvdplayer/DVDPerformanceCounter.h
++++ b/xbmc/cores/dvdplayer/DVDPerformanceCounter.h
+@@ -24,7 +24,7 @@
+ #define FILETIME_TO_ULARGE_INTEGER(ularge, filetime) { ularge.u.HighPart = filetime.dwHighDateTime; ularge.u.LowPart = filetime.dwLowDateTime; }
+
+ #include "system.h"
+-
++#include "threads/Thread.h"
+ #include "threads/SingleLock.h"
+
+ class CDVDMessageQueue;
+@@ -33,7 +33,7 @@ typedef struct stProcessPerformance
+ {
+ ULARGE_INTEGER timer_thread;
+ ULARGE_INTEGER timer_system;
+- HANDLE hThread;
++ CThread* thread;
+ } ProcessPerformance;
+
+ class CDVDPerformanceCounter
+@@ -45,20 +45,20 @@ public:
+ bool Initialize();
+ void DeInitialize();
+
+- void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; }
+- void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; }
++ void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; }
++ void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; }
+
+- void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; }
+- void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; }
++ void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; }
++ void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; }
+
+- void EnableVideoDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = hThread; }
+- void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = NULL; }
++ void EnableVideoDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = thread; }
++ void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = NULL; }
+
+- void EnableAudioDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = hThread; }
+- void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = NULL; }
++ void EnableAudioDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = thread; }
++ void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = NULL; }
+
+- void EnableMainPerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_mainPerformance.hThread = hThread; }
+- void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.hThread = NULL; }
++ void EnableMainPerformance(CThread *thread) { CSingleLock lock(m_critSection); m_mainPerformance.thread = thread; }
++ void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.thread = NULL; }
+
+ CDVDMessageQueue* m_pAudioQueue;
+ CDVDMessageQueue* m_pVideoQueue;
+diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+index 1d8cdf5..f7d31d4 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+@@ -348,7 +348,7 @@ bool CDVDPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
+
+ // if playing a file close it first
+ // this has to be changed so we won't have to close it.
+- if(ThreadHandle())
++ if(IsRunning())
+ CloseFile();
+
+ m_bAbortRequest = false;
+@@ -440,9 +440,8 @@ void CDVDPlayer::OnStartup()
+
+ m_messenger.Init();
+
+- g_dvdPerformanceCounter.EnableMainPerformance(ThreadHandle());
+-
+ CUtil::ClearTempFonts();
++ g_dvdPerformanceCounter.EnableMainPerformance(this);
+ }
+
+ bool CDVDPlayer::OpenInputStream()
+@@ -2879,7 +2878,7 @@ bool CDVDPlayer::OpenAudioStream(int iStream, int source)
+ m_dvdPlayerAudio.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1);
+
+ /* audio normally won't consume full cpu, so let it have prio */
+- m_dvdPlayerAudio.SetPriority(GetThreadPriority(*this)+1);
++ m_dvdPlayerAudio.SetPriority(GetPriority()+1);
+
+ return true;
+ }
+@@ -2941,11 +2940,11 @@ bool CDVDPlayer::OpenVideoStream(int iStream, int source)
+ // the CoreAudio audio device handler thread. We do the same for
+ // the DVDPlayerVideo thread so it can run to sleep without getting
+ // swapped out by a busy OS.
+- m_dvdPlayerVideo.SetPrioritySched_RR();
++ m_dvdPlayerVideo.SetPriority(GetSchedRRPriority());
+ #else
+ /* use same priority for video thread as demuxing thread, as */
+ /* otherwise demuxer will starve if video consumes the full cpu */
+- m_dvdPlayerVideo.SetPriority(GetThreadPriority(*this));
++ m_dvdPlayerVideo.SetPriority(GetPriority());
+ #endif
+ return true;
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+index 41fbaaf..9f2128c 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+@@ -518,7 +518,7 @@ void CDVDPlayerAudio::OnStartup()
+ m_decode.msg = NULL;
+ m_decode.Release();
+
+- g_dvdPerformanceCounter.EnableAudioDecodePerformance(ThreadHandle());
++ g_dvdPerformanceCounter.EnableAudioDecodePerformance(this);
+
+ #ifdef _WIN32
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+index 695cb7e..4c99c48 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+@@ -189,7 +189,7 @@ bool CDVDPlayerVideo::OpenStream( CDVDStreamInfo &hint )
+ return false;
+ }
+
+- if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && g_VideoReferenceClock.ThreadHandle() == NULL)
++ if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && !g_VideoReferenceClock.IsRunning())
+ {
+ g_VideoReferenceClock.Create();
+ //we have to wait for the clock to start otherwise alsa can cause trouble
+@@ -288,7 +288,7 @@ void CDVDPlayerVideo::OnStartup()
+ m_iCurrentPts = DVD_NOPTS_VALUE;
+ m_FlipTimeStamp = m_pClock->GetAbsoluteClock();
+
+- g_dvdPerformanceCounter.EnableVideoDecodePerformance(ThreadHandle());
++ g_dvdPerformanceCounter.EnableVideoDecodePerformance(this);
+ }
+
+ void CDVDPlayerVideo::Process()
+@@ -1051,6 +1051,14 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
+ flags |= CONF_FLAGS_FORMAT_CVBREF;
+ formatstr = "BGRA";
+ break;
++ case DVDVideoPicture::FMT_XVBA:
++ flags |= CONF_FLAGS_FORMAT_XVBA;
++ formatstr = "XVBA";
++ break;
++ case DVDVideoPicture::FMT_XVBA_YV12:
++ flags |= CONF_FLAGS_FORMAT_XVBA_YV12;
++ formatstr = "XVBA";
++ break;
+ }
+
+ if(m_bAllowFullscreen)
+diff --git a/xbmc/cores/paplayer/PAPlayer.cpp b/xbmc/cores/paplayer/PAPlayer.cpp
+index 43b57d3..13f5238 100644
+--- a/xbmc/cores/paplayer/PAPlayer.cpp
++++ b/xbmc/cores/paplayer/PAPlayer.cpp
+@@ -52,7 +52,7 @@
+ // Supporting all open audio codec standards.
+ // First one being nullsoft's nsv audio decoder format
+
+-PAPlayer::PAPlayer(IPlayerCallback& callback) : IPlayer(callback)
++PAPlayer::PAPlayer(IPlayerCallback& callback) : CThread("PAPlayer"), IPlayer(callback)
+ {
+ m_bIsPlaying = false;
+ m_bPaused = false;
+@@ -168,7 +168,7 @@ bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
+
+ *m_currentFile = file;
+
+- if (ThreadHandle() == NULL)
++ if (!IsRunning())
+ Create();
+
+ m_startEvent.Set();
+diff --git a/xbmc/dialogs/GUIDialogCache.cpp b/xbmc/dialogs/GUIDialogCache.cpp
+index 1114cc6..85548e4 100644
+--- a/xbmc/dialogs/GUIDialogCache.cpp
++++ b/xbmc/dialogs/GUIDialogCache.cpp
+@@ -29,7 +29,7 @@
+ #include "threads/SingleLock.h"
+ #include "utils/TimeUtils.h"
+
+-CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg)
++CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg) : CThread("CGUIDialogCache")
+ {
+ m_pDlg = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
+
+diff --git a/xbmc/filesystem/FileCache.cpp b/xbmc/filesystem/FileCache.cpp
+index c6af9d0..63937ef 100644
+--- a/xbmc/filesystem/FileCache.cpp
++++ b/xbmc/filesystem/FileCache.cpp
+@@ -79,7 +79,7 @@ private:
+ };
+
+
+-CFileCache::CFileCache()
++CFileCache::CFileCache() : CThread("CFileCache")
+ {
+ m_bDeleteCache = true;
+ m_nSeekResult = 0;
+@@ -95,7 +95,7 @@ CFileCache::CFileCache()
+ m_cacheFull = false;
+ }
+
+-CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache)
++CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache) : CThread("CFileCache")
+ {
+ m_pCache = pCache;
+ m_bDeleteCache = bDeleteCache;
+diff --git a/xbmc/filesystem/FilePipe.cpp b/xbmc/filesystem/FilePipe.cpp
+index 8426af0..c99aa6e 100644
+--- a/xbmc/filesystem/FilePipe.cpp
++++ b/xbmc/filesystem/FilePipe.cpp
+@@ -24,6 +24,8 @@
+ #include "PipesManager.h"
+ #include "utils/StringUtils.h"
+
++#define INFINITE 0xFFFFFFFF
++
+ using namespace XFILE;
+
+ CFilePipe::CFilePipe() : m_pos(0), m_length(-1), m_pipe(NULL)
+diff --git a/xbmc/filesystem/FileRar.cpp b/xbmc/filesystem/FileRar.cpp
+index 9c87a35..202b3ee 100644
+--- a/xbmc/filesystem/FileRar.cpp
++++ b/xbmc/filesystem/FileRar.cpp
+@@ -43,7 +43,7 @@ using namespace std;
+ #define SEEKTIMOUT 30000
+
+ #ifdef HAS_FILESYSTEM_RAR
+-CFileRarExtractThread::CFileRarExtractThread() : hRunning(true), hQuit(true)
++CFileRarExtractThread::CFileRarExtractThread() : CThread("CFileRarExtractThread"), hRunning(true), hQuit(true)
+ {
+ m_pArc = NULL;
+ m_pCmd = NULL;
+diff --git a/xbmc/filesystem/HTSPDirectory.cpp b/xbmc/filesystem/HTSPDirectory.cpp
+index 83a1fca..152754d 100644
+--- a/xbmc/filesystem/HTSPDirectory.cpp
++++ b/xbmc/filesystem/HTSPDirectory.cpp
+@@ -76,7 +76,7 @@ static SSessions g_sessions;
+ static CCriticalSection g_section;
+
+
+-CHTSPDirectorySession::CHTSPDirectorySession()
++CHTSPDirectorySession::CHTSPDirectorySession() : CThread("CHTSPDirectorySession")
+ {
+ }
+
+diff --git a/xbmc/filesystem/LastFMDirectory.cpp b/xbmc/filesystem/LastFMDirectory.cpp
+index af5621c..a4b23fc 100644
+--- a/xbmc/filesystem/LastFMDirectory.cpp
++++ b/xbmc/filesystem/LastFMDirectory.cpp
+@@ -69,7 +69,7 @@ bool CLastFMDirectory::RetrieveList(CStdString url)
+ m_dlgProgress->Progress();
+ }
+
+- CThread thread(this);
++ CThread thread(this, "CLastFMDirectory");
+ m_strSource = url;
+ m_strDestination = "special://temp/lastfm.xml";
+ thread.Create();
+diff --git a/xbmc/filesystem/MythSession.cpp b/xbmc/filesystem/MythSession.cpp
+index 45de2cc..304ecdd 100644
+--- a/xbmc/filesystem/MythSession.cpp
++++ b/xbmc/filesystem/MythSession.cpp
+@@ -359,7 +359,7 @@ void CMythSession::SetSeasonAndEpisode(const cmyth_proginfo_t &program, int *sea
+ return;
+ }
+
+-CMythSession::CMythSession(const CURL& url)
++CMythSession::CMythSession(const CURL& url) : CThread("CMythSession")
+ {
+ m_control = NULL;
+ m_event = NULL;
+diff --git a/xbmc/filesystem/PipesManager.cpp b/xbmc/filesystem/PipesManager.cpp
+index 73f4aa2..80a1044 100644
+--- a/xbmc/filesystem/PipesManager.cpp
++++ b/xbmc/filesystem/PipesManager.cpp
+@@ -23,6 +23,8 @@
+ #include "threads/SingleLock.h"
+ #include "Application.h"
+
++#define INFINITE 0xFFFFFFFF
++
+ #ifndef min
+ #define min(a,b) ((a) < (b) ? (a) : (b))
+ #endif
+diff --git a/xbmc/filesystem/RarManager.h b/xbmc/filesystem/RarManager.h
+index dd4b2f0..6f93f79 100644
+--- a/xbmc/filesystem/RarManager.h
++++ b/xbmc/filesystem/RarManager.h
+@@ -71,7 +71,7 @@ public:
+ CRarManager();
+ ~CRarManager();
+ bool CacheRarredFile(CStdString& strPathInCache, const CStdString& strRarPath,
+- const CStdString& strPathInRar, BYTE bOptions = EXFILE_AUTODELETE,
++ const CStdString& strPathInRar, uint8_t bOptions = EXFILE_AUTODELETE,
+ const CStdString& strDir =RAR_DEFAULT_CACHE, const int64_t iSize=-1);
+ bool GetPathInCache(CStdString& strPathInCache, const CStdString& strRarPath,
+ const CStdString& strPathInRar = "");
+diff --git a/xbmc/filesystem/SAPDirectory.cpp b/xbmc/filesystem/SAPDirectory.cpp
+index d8931b8..b997c12 100644
+--- a/xbmc/filesystem/SAPDirectory.cpp
++++ b/xbmc/filesystem/SAPDirectory.cpp
+@@ -272,7 +272,7 @@ namespace SDP
+ using namespace SDP;
+
+
+-CSAPSessions::CSAPSessions()
++CSAPSessions::CSAPSessions() : CThread("CSAPSessions")
+ {
+ m_socket = INVALID_SOCKET;
+ }
+@@ -486,7 +486,7 @@ namespace XFILE
+
+ CSingleLock lock(g_sapsessions.m_section);
+
+- if(g_sapsessions.ThreadHandle() == NULL)
++ if(!g_sapsessions.IsRunning())
+ g_sapsessions.Create();
+
+ // check if we can find this session in our cache
+diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp
+index 9f43894..8cb3e61 100644
+--- a/xbmc/interfaces/python/XBPython.cpp
++++ b/xbmc/interfaces/python/XBPython.cpp
+@@ -676,11 +676,11 @@ void XBPython::PulseGlobalEvent()
+ m_globalEvent.Set();
+ }
+
+-void XBPython::WaitForEvent(CEvent& hEvent, unsigned int timeout)
++void XBPython::WaitForEvent(CEvent& hEvent)
+ {
+ // wait for either this event our our global event
+ XbmcThreads::CEventGroup eventGroup(&hEvent, &m_globalEvent, NULL);
+- eventGroup.wait(timeout);
++ eventGroup.wait();
+ m_globalEvent.Reset();
+ }
+
+diff --git a/xbmc/interfaces/python/XBPython.h b/xbmc/interfaces/python/XBPython.h
+index 7737744..8877b54 100644
+--- a/xbmc/interfaces/python/XBPython.h
++++ b/xbmc/interfaces/python/XBPython.h
+@@ -61,7 +61,7 @@ public:
+ void Process();
+
+ void PulseGlobalEvent();
+- void WaitForEvent(CEvent& hEvent, unsigned int timeout);
++ void WaitForEvent(CEvent& hEvent);
+
+ int ScriptsSize();
+ int GetPythonScriptId(int scriptPosition);
+diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
+index 4ec7e23..d44fc23 100644
+--- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
++++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
+@@ -181,9 +181,9 @@ void CGUIPythonWindow::SetCallbackWindow(void *state, void *object)
+ m_threadState = state;
+ }
+
+-void CGUIPythonWindow::WaitForActionEvent(unsigned int timeout)
++void CGUIPythonWindow::WaitForActionEvent()
+ {
+- g_pythonParser.WaitForEvent(m_actionEvent, timeout);
++ g_pythonParser.WaitForEvent(m_actionEvent);
+ m_actionEvent.Reset();
+ }
+
+diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h
+index c776187..09c0d42 100644
+--- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h
++++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h
+@@ -51,7 +51,7 @@ public:
+ virtual bool OnAction(const CAction &action);
+ virtual bool OnBack(int actionID);
+ void SetCallbackWindow(void* state, void *object);
+- void WaitForActionEvent(unsigned int timeout);
++ void WaitForActionEvent();
+ void PulseActionEvent();
+ void SetDestroyAfterDeinit(bool destroy = true);
+ protected:
+diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
+index 2db79f1..9644351 100644
+--- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
++++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
+@@ -279,9 +279,9 @@ void CGUIPythonWindowXML::ClearList()
+ UpdateButtons();
+ }
+
+-void CGUIPythonWindowXML::WaitForActionEvent(unsigned int timeout)
++void CGUIPythonWindowXML::WaitForActionEvent()
+ {
+- g_pythonParser.WaitForEvent(m_actionEvent, timeout);
++ g_pythonParser.WaitForEvent(m_actionEvent);
+ m_actionEvent.Reset();
+ }
+
+diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h
+index 27bc3a2..340be8b 100644
+--- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h
++++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h
+@@ -40,7 +40,7 @@ public:
+ virtual void AllocResources(bool forceLoad = false);
+ virtual void FreeResources(bool forceUnLoad = false);
+ void Process(unsigned int currentTime, CDirtyRegionList ®ions);
+- void WaitForActionEvent(unsigned int timeout);
++ void WaitForActionEvent();
+ void PulseActionEvent();
+ void AddItem(CFileItemPtr fileItem,int itemPosition);
+ void RemoveItem(int itemPosition);
+diff --git a/xbmc/interfaces/python/xbmcmodule/window.cpp b/xbmc/interfaces/python/xbmcmodule/window.cpp
+index 9b9184a..1b72644 100644
+--- a/xbmc/interfaces/python/xbmcmodule/window.cpp
++++ b/xbmc/interfaces/python/xbmcmodule/window.cpp
+@@ -540,11 +540,11 @@ namespace PYXBMC
+
+ CPyThreadState pyState;
+ if (WindowXML_Check(self))
+- ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent(INFINITE);
++ ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent();
+ else if (WindowXMLDialog_Check(self))
+- ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent(INFINITE);
++ ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent();
+ else
+- ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent(INFINITE);
++ ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent();
+ }
+ }
+ Py_INCREF(Py_None);
+diff --git a/xbmc/linux/Makefile.in b/xbmc/linux/Makefile.in
+index c3a5877..43f552b 100644
+--- a/xbmc/linux/Makefile.in
++++ b/xbmc/linux/Makefile.in
+@@ -10,14 +10,11 @@ SRCS=ConvUtils.cpp \
+ LinuxResourceCounter.cpp \
+ LinuxTimezone.cpp \
+ PosixMountProvider.cpp \
+- XEventUtils.cpp \
+ XFileUtils.cpp \
+ XHandle.cpp \
+ XLCDproc.cpp \
+ XMemUtils.cpp \
+- XSyncUtils.cpp \
+ XTimeUtils.cpp \
+- XThreadUtils.cpp \
+
+ LIB=linux.a
+
+diff --git a/xbmc/linux/PlatformDefs.h b/xbmc/linux/PlatformDefs.h
+index 33d1c96..55d20c5 100644
+--- a/xbmc/linux/PlatformDefs.h
++++ b/xbmc/linux/PlatformDefs.h
+@@ -182,8 +182,6 @@
+ #define EXCEPTION_EXECUTE_HANDLER ...
+ //NOTE: dont try to define __except because it breaks g++ (already uses it).
+
+-typedef pthread_t ThreadIdentifier;
+-
+ struct CXHandle; // forward declaration
+ typedef CXHandle* HANDLE;
+
+diff --git a/xbmc/linux/PlatformInclude.h b/xbmc/linux/PlatformInclude.h
+index 1f7e7e9..4e44ed8 100644
+--- a/xbmc/linux/PlatformInclude.h
++++ b/xbmc/linux/PlatformInclude.h
+@@ -25,10 +25,7 @@
+ #include "PlatformDefs.h"
+ #include "XHandlePublic.h"
+ #include "XFileUtils.h"
+-#include "XSyncUtils.h"
+-#include "XEventUtils.h"
+ #include "XTimeUtils.h"
+-#include "XThreadUtils.h"
+ #include "XMemUtils.h"
+ #include "ConvUtils.h"
+
+diff --git a/xbmc/linux/XEventUtils.cpp b/xbmc/linux/XEventUtils.cpp
+deleted file mode 100644
+index 639b7b9..0000000
+--- a/xbmc/linux/XEventUtils.cpp
++++ /dev/null
+@@ -1,144 +0,0 @@
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "system.h"
+-#include "PlatformDefs.h"
+-#include "XEventUtils.h"
+-#include "XHandle.h"
+-#include "utils/log.h"
+-#include "threads/SingleLock.h"
+-
+-using namespace std;
+-
+-HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName)
+-{
+- CXHandle *pHandle = new CXHandle(CXHandle::HND_EVENT);
+- pHandle->m_bManualEvent = bManualReset;
+- pHandle->m_hCond = new XbmcThreads::ConditionVariable();
+- pHandle->m_hMutex = new CCriticalSection();
+- pHandle->m_bEventSet = false;
+-
+- if (bInitialState)
+- SetEvent(pHandle);
+-
+- return pHandle;
+-}
+-
+-//
+-// The state of a manual-reset event object remains signaled until it is set explicitly to the nonsignaled
+-// state by the ResetEvent function. Any number of waiting threads, or threads that subsequently begin wait
+-// operations for the specified event object by calling one of the wait functions, can be released while the
+-// object's state is signaled.
+-//
+-// The state of an auto-reset event object remains signaled until a single waiting thread is released, at
+-// which time the system automatically sets the state to nonsignaled. If no threads are waiting, the event
+-// object's state remains signaled.
+-//
+-bool WINAPI SetEvent(HANDLE hEvent)
+-{
+- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
+- return false;
+-
+- CSingleLock lock(*(hEvent->m_hMutex));
+- hEvent->m_bEventSet = true;
+-
+- // we must guarantee that these handle's won't be deleted, until we are done
+- list events = hEvent->m_hParents;
+- for(list::iterator it = events.begin();it != events.end();it++)
+- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
+-
+- lock.Leave();
+-
+- for(list::iterator it = events.begin();it != events.end();it++)
+- {
+- SetEvent(*it);
+- CloseHandle(*it);
+- }
+-
+- DuplicateHandle(GetCurrentProcess(), hEvent, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
+-
+- if (hEvent->m_bManualEvent == true)
+- hEvent->m_hCond->notifyAll();
+- else
+- hEvent->m_hCond->notify();
+-
+- CloseHandle(hEvent);
+-
+- return true;
+-}
+-
+-bool WINAPI ResetEvent(HANDLE hEvent)
+-{
+- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
+- return false;
+-
+- CSingleLock lock(*(hEvent->m_hMutex));
+- hEvent->m_bEventSet = false;
+-
+- return true;
+-}
+-
+-bool WINAPI PulseEvent(HANDLE hEvent)
+-{
+- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
+- return false;
+-
+- CSingleLock lock(*(hEvent->m_hMutex));
+- // we must guarantee that these handle's won't be deleted, until we are done
+- list events = hEvent->m_hParents;
+- for(list::iterator it = events.begin();it != events.end();it++)
+- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
+-
+- if(events.size())
+- {
+- CLog::Log(LOGWARNING,"PulseEvent - ineffecient multiwait detected");
+- hEvent->m_bEventSet = true;
+- }
+-
+- lock.Leave();
+-
+- for(list::iterator it = events.begin();it != events.end();it++)
+- {
+- SetEvent(*it);
+- CloseHandle(*it);
+-
+- if (hEvent->m_bManualEvent == false)
+- break;
+- }
+-
+- // for multiwaits, we must yield some time to get the multiwaits to notice it was signaled
+- if(events.size())
+- Sleep(10);
+-
+- // we should always unset the event on pulse
+- {
+- CSingleLock lock2(*(hEvent->m_hMutex));
+- hEvent->m_bEventSet = false;
+- }
+-
+- if (hEvent->m_bManualEvent == true)
+- hEvent->m_hCond->notifyAll();
+- else
+- hEvent->m_hCond->notify();
+-
+- return true;
+-}
+-
+diff --git a/xbmc/linux/XEventUtils.h b/xbmc/linux/XEventUtils.h
+deleted file mode 100644
+index a77f843..0000000
+--- a/xbmc/linux/XEventUtils.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-#ifndef __X_EVENT_UTIL_H__
+-#define __X_EVENT_UTIL_H__
+-
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "XHandlePublic.h"
+-
+-#ifdef _LINUX
+-
+-HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName);
+-bool WINAPI SetEvent(HANDLE hEvent);
+-bool WINAPI ResetEvent(HANDLE hEvent);
+-bool WINAPI PulseEvent(HANDLE hEvent);
+-
+-#endif
+-
+-
+-#endif
+-
+diff --git a/xbmc/linux/XHandle.cpp b/xbmc/linux/XHandle.cpp
+index 61520b2..52f540a 100644
+--- a/xbmc/linux/XHandle.cpp
++++ b/xbmc/linux/XHandle.cpp
+@@ -20,12 +20,15 @@
+ */
+
+ #include "XHandle.h"
+-#include "XThreadUtils.h"
+ #include "utils/log.h"
+ #include "threads/SingleLock.h"
+
+ int CXHandle::m_objectTracker[10] = {0};
+
++HANDLE WINAPI GetCurrentProcess(void) {
++ return (HANDLE)-1; // -1 a special value - pseudo handle
++}
++
+ CXHandle::CXHandle()
+ {
+ Init();
+@@ -47,11 +50,6 @@ CXHandle::CXHandle(const CXHandle &src)
+
+ Init();
+
+- if (m_threadValid)
+- {
+- CLog::Log(LOGERROR, "%s - thread handle copied instead of passed!", __FUNCTION__);
+- }
+-
+ if (src.m_hMutex)
+ m_hMutex = new CCriticalSection();
+
+@@ -80,7 +78,7 @@ CXHandle::~CXHandle()
+ CLog::Log(LOGERROR,"%s, destroying handle with ref count %d", __FUNCTION__, m_nRefCount);
+ assert(false);
+ }
+-
++
+ if (m_hMutex) {
+ delete m_hMutex;
+ }
+@@ -93,10 +91,6 @@ CXHandle::~CXHandle()
+ delete m_hCond;
+ }
+
+- if (m_threadValid) {
+- pthread_join(m_hThread, NULL);
+- }
+-
+ if ( fd != 0 ) {
+ close(fd);
+ }
+@@ -107,11 +101,9 @@ void CXHandle::Init()
+ {
+ fd=0;
+ m_hMutex=NULL;
+- m_threadValid=false;
+ m_hCond=NULL;
+ m_type = HND_NULL;
+ RecursionCount=0;
+- OwningThread=0;
+ m_bManualEvent=FALSE;
+ m_bEventSet=FALSE;
+ m_nFindFileIterator=0 ;
+diff --git a/xbmc/linux/XHandle.h b/xbmc/linux/XHandle.h
+index 0e119bc..dd7f37d 100644
+--- a/xbmc/linux/XHandle.h
++++ b/xbmc/linux/XHandle.h
+@@ -25,7 +25,6 @@
+ #ifndef _WIN32
+
+ #include
+-#include
+
+ #include "PlatformDefs.h"
+ #include "XHandlePublic.h"
+@@ -36,7 +35,7 @@
+ struct CXHandle {
+
+ public:
+- typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_THREAD, HND_FIND_FILE } HandleType;
++ typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_FIND_FILE } HandleType;
+
+ CXHandle();
+ CXHandle(HandleType nType);
+@@ -47,8 +46,6 @@ public:
+ inline HandleType GetType() { return m_type; }
+ void ChangeType(HandleType newType);
+
+- ThreadIdentifier m_hThread;
+- bool m_threadValid;
+ XbmcThreads::ConditionVariable *m_hCond;
+ std::list m_hParents;
+
+@@ -62,7 +59,6 @@ public:
+ // simulate mutex and critical section
+ CCriticalSection *m_hMutex;
+ int RecursionCount; // for mutex - for compatibility with WIN32 critical section
+- pthread_t OwningThread;
+ int fd;
+ bool m_bManualEvent;
+ time_t m_tmCreation;
+diff --git a/xbmc/linux/XMemUtils.cpp b/xbmc/linux/XMemUtils.cpp
+index 906fe4e..c0006fe 100644
+--- a/xbmc/linux/XMemUtils.cpp
++++ b/xbmc/linux/XMemUtils.cpp
+@@ -25,6 +25,10 @@
+
+ #include "XMemUtils.h"
+
++#ifdef __APPLE__
++#include
++#endif
++
+ #undef ALIGN
+ #define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1))
+
+@@ -49,4 +53,130 @@ void _aligned_free(void *p) {
+ free(pFull);
+ }
+
++#ifndef _WIN32
++
++#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__)
++static FILE* procMeminfoFP = NULL;
++#endif
++
++void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
++{
++ if (!lpBuffer)
++ return;
++
++ memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
++
++#ifdef __APPLE__
++ uint64_t physmem;
++ size_t len = sizeof physmem;
++ int mib[2] = { CTL_HW, HW_MEMSIZE };
++ size_t miblen = sizeof(mib) / sizeof(mib[0]);
++
++ // Total physical memory.
++ if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
++ lpBuffer->ullTotalPhys = physmem;
++
++ // Virtual memory.
++ mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE;
++ struct xsw_usage swap;
++ len = sizeof(struct xsw_usage);
++ if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0)
++ {
++ lpBuffer->ullAvailPageFile = swap.xsu_avail;
++ lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
++ }
++
++ // In use.
++ mach_port_t stat_port = mach_host_self();
++ vm_statistics_data_t vm_stat;
++ mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
++ if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0)
++ {
++ // Find page size.
++ int pageSize;
++ mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
++ len = sizeof(int);
++ if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
++ {
++ uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
++
++ lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
++ lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME.
++ }
++ }
++#elif defined(__FreeBSD__)
++ /* sysctl hw.physmem */
++ size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0;
++ size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0;
++
++ /* physmem */
++ len = sizeof(physmem);
++ if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
++ lpBuffer->ullTotalPhys = physmem;
++ lpBuffer->ullTotalVirtual = physmem;
++ }
++ /* pagesize */
++ len = sizeof(pagesize);
++ if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
++ pagesize = 4096;
++ /* mem_inactive */
++ len = sizeof(mem_inactive);
++ if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
++ mem_inactive *= pagesize;
++ /* mem_cache */
++ len = sizeof(mem_cache);
++ if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
++ mem_cache *= pagesize;
++ /* mem_free */
++ len = sizeof(mem_free);
++ if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
++ mem_free *= pagesize;
++
++ /* mem_avail = mem_inactive + mem_cache + mem_free */
++ lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free;
++ lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free;
++
++ if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
++ lpBuffer->ullAvailPageFile = swap_free * pagesize;
++#else
++ struct sysinfo info;
++ char name[32];
++ unsigned val;
++ if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
++ sysinfo(&info);
++ else
++ {
++ memset(&info, 0, sizeof(struct sysinfo));
++ info.mem_unit = 4096;
++ while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
++ {
++ if (strncmp("MemTotal:", name, 9) == 0)
++ info.totalram = val/4;
++ else if (strncmp("MemFree:", name, 8) == 0)
++ info.freeram = val/4;
++ else if (strncmp("Buffers:", name, 8) == 0)
++ info.bufferram += val/4;
++ else if (strncmp("Cached:", name, 7) == 0)
++ info.bufferram += val/4;
++ else if (strncmp("SwapTotal:", name, 10) == 0)
++ info.totalswap = val/4;
++ else if (strncmp("SwapFree:", name, 9) == 0)
++ info.freeswap = val/4;
++ else if (strncmp("HighTotal:", name, 10) == 0)
++ info.totalhigh = val/4;
++ else if (strncmp("HighFree:", name, 9) == 0)
++ info.freehigh = val/4;
++ }
++ rewind(procMeminfoFP);
++ fflush(procMeminfoFP);
++ }
++ lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit);
++ lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit);
++ lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit);
++ lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit);
++ lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit);
++#endif
++}
++
++#endif
+
+diff --git a/xbmc/linux/XMemUtils.h b/xbmc/linux/XMemUtils.h
+index d6d314a..83fc95d 100644
+--- a/xbmc/linux/XMemUtils.h
++++ b/xbmc/linux/XMemUtils.h
+@@ -22,10 +22,14 @@
+ *
+ */
+
++#include "linux/PlatformDefs.h"
++
+ // aligned memory allocation and free. memory returned will be aligned to "alignTo" bytes.
+ // this is a linux (actually platfom free) implementation of the win32 CRT methods _aligned_malloc and _aligned_free.
+ void *_aligned_malloc(size_t s, size_t alignTo);
+ void _aligned_free(void *p) ;
+
++void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer);
++
+ #endif
+
+diff --git a/xbmc/linux/XSyncUtils.cpp b/xbmc/linux/XSyncUtils.cpp
+deleted file mode 100644
+index 19c4b5a..0000000
+--- a/xbmc/linux/XSyncUtils.cpp
++++ /dev/null
+@@ -1,169 +0,0 @@
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#ifndef _WIN32
+-
+-
+-#include
+-#include
+-#include
+-#include
+-#include
+-#ifdef __APPLE__
+-#include
+-#endif
+-
+-#include "XSyncUtils.h"
+-#include "XTimeUtils.h"
+-#include "PlatformDefs.h"
+-#include "XHandle.h"
+-#include "XEventUtils.h"
+-
+-using namespace std;
+-using namespace XbmcThreads;
+-
+-#include "../utils/log.h"
+-#include "../utils/TimeUtils.h"
+-
+-#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__)
+-static FILE* procMeminfoFP = NULL;
+-#endif
+-
+-void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
+-{
+- if (!lpBuffer)
+- return;
+-
+- memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
+-
+-#ifdef __APPLE__
+- uint64_t physmem;
+- size_t len = sizeof physmem;
+- int mib[2] = { CTL_HW, HW_MEMSIZE };
+- size_t miblen = sizeof(mib) / sizeof(mib[0]);
+-
+- // Total physical memory.
+- if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
+- lpBuffer->ullTotalPhys = physmem;
+-
+- // Virtual memory.
+- mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE;
+- struct xsw_usage swap;
+- len = sizeof(struct xsw_usage);
+- if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0)
+- {
+- lpBuffer->ullAvailPageFile = swap.xsu_avail;
+- lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
+- }
+-
+- // In use.
+- mach_port_t stat_port = mach_host_self();
+- vm_statistics_data_t vm_stat;
+- mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
+- if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0)
+- {
+- // Find page size.
+- int pageSize;
+- mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
+- len = sizeof(int);
+- if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
+- {
+- uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
+-
+- lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
+- lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME.
+- }
+- }
+-#elif defined(__FreeBSD__)
+- /* sysctl hw.physmem */
+- size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0;
+- size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0;
+-
+- /* physmem */
+- len = sizeof(physmem);
+- if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
+- lpBuffer->ullTotalPhys = physmem;
+- lpBuffer->ullTotalVirtual = physmem;
+- }
+- /* pagesize */
+- len = sizeof(pagesize);
+- if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
+- pagesize = 4096;
+- /* mem_inactive */
+- len = sizeof(mem_inactive);
+- if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
+- mem_inactive *= pagesize;
+- /* mem_cache */
+- len = sizeof(mem_cache);
+- if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
+- mem_cache *= pagesize;
+- /* mem_free */
+- len = sizeof(mem_free);
+- if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
+- mem_free *= pagesize;
+-
+- /* mem_avail = mem_inactive + mem_cache + mem_free */
+- lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free;
+- lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free;
+-
+- if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
+- lpBuffer->ullAvailPageFile = swap_free * pagesize;
+-#else
+- struct sysinfo info;
+- char name[32];
+- unsigned val;
+- if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
+- sysinfo(&info);
+- else
+- {
+- memset(&info, 0, sizeof(struct sysinfo));
+- info.mem_unit = 4096;
+- while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
+- {
+- if (strncmp("MemTotal:", name, 9) == 0)
+- info.totalram = val/4;
+- else if (strncmp("MemFree:", name, 8) == 0)
+- info.freeram = val/4;
+- else if (strncmp("Buffers:", name, 8) == 0)
+- info.bufferram += val/4;
+- else if (strncmp("Cached:", name, 7) == 0)
+- info.bufferram += val/4;
+- else if (strncmp("SwapTotal:", name, 10) == 0)
+- info.totalswap = val/4;
+- else if (strncmp("SwapFree:", name, 9) == 0)
+- info.freeswap = val/4;
+- else if (strncmp("HighTotal:", name, 10) == 0)
+- info.totalhigh = val/4;
+- else if (strncmp("HighFree:", name, 9) == 0)
+- info.freehigh = val/4;
+- }
+- rewind(procMeminfoFP);
+- fflush(procMeminfoFP);
+- }
+- lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit);
+- lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit);
+- lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit);
+- lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit);
+- lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit);
+-#endif
+-}
+-
+-#endif
+diff --git a/xbmc/linux/XSyncUtils.h b/xbmc/linux/XSyncUtils.h
+deleted file mode 100644
+index f3ad36f..0000000
+--- a/xbmc/linux/XSyncUtils.h
++++ /dev/null
+@@ -1,44 +0,0 @@
+-#ifndef __X_SYNC_UTILS_
+-#define __X_SYNC_UTILS_
+-
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "PlatformDefs.h"
+-#include "XHandlePublic.h"
+-
+-#ifdef _LINUX
+-
+-#define STATUS_WAIT_0 ((DWORD )0x00000000L)
+-#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
+-#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 )
+-#define WAIT_TIMEOUT 258L
+-#define INFINITE 0xFFFFFFFF
+-#define STATUS_ABANDONED_WAIT_0 0x00000080
+-#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
+-#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
+-
+-void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer);
+-
+-#endif
+-
+-#endif
+-
+diff --git a/xbmc/linux/XThreadUtils.cpp b/xbmc/linux/XThreadUtils.cpp
+deleted file mode 100644
+index 9d68481..0000000
+--- a/xbmc/linux/XThreadUtils.cpp
++++ /dev/null
+@@ -1,210 +0,0 @@
+-/*
+- * Copyright (C) 2005-2009 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "PlatformDefs.h"
+-#include "XHandle.h"
+-#include "XThreadUtils.h"
+-#include "XTimeUtils.h"
+-#include "XEventUtils.h"
+-#include "system.h"
+-#include "utils/log.h"
+-
+-#ifdef _LINUX
+-#include
+-#include
+-#include
+-
+-HANDLE WINAPI CreateThread(
+- LPSECURITY_ATTRIBUTES lpThreadAttributes,
+- SIZE_T dwStackSize,
+- LPTHREAD_START_ROUTINE lpStartAddress,
+- LPVOID lpParameter,
+- DWORD dwCreationFlags,
+- LPDWORD lpThreadId
+- ) {
+-
+- // a thread handle would actually contain an event
+- // the event would mark if the thread is running or not. it will be used in the Wait functions.
+- HANDLE h = CreateEvent(NULL, TRUE, FALSE, NULL);
+- h->ChangeType(CXHandle::HND_THREAD);
+-#ifdef __APPLE__
+- h->m_machThreadPort = MACH_PORT_NULL;
+-#endif
+- pthread_attr_t attr;
+- pthread_attr_init(&attr);
+- if (dwStackSize > PTHREAD_STACK_MIN)
+- pthread_attr_setstacksize(&attr, dwStackSize);
+- if (pthread_create(&(h->m_hThread), &attr, (void*(*)(void*))lpStartAddress, lpParameter) == 0)
+- h->m_threadValid = true;
+- else
+- {
+- CloseHandle(h);
+- h = NULL;
+- }
+- pthread_attr_destroy(&attr);
+-
+- if (h && lpThreadId)
+- // WARNING: This can truncate thread IDs on x86_64.
+- *lpThreadId = (DWORD)h->m_hThread;
+- return h;
+-}
+-
+-
+-#if 0 // Deprecated, use CThread::GetCurrentThreadId() instead
+-DWORD WINAPI GetCurrentThreadId(void) {
+- // WARNING: This can truncate thread IDs on x86_64.
+- return (DWORD)pthread_self();
+-}
+-#endif
+-
+-HANDLE WINAPI GetCurrentThread(void) {
+- return (HANDLE)-1; // -1 a special value - pseudo handle
+-}
+-
+-HANDLE WINAPI GetCurrentProcess(void) {
+- return (HANDLE)-1; // -1 a special value - pseudo handle
+-}
+-
+-HANDLE _beginthreadex(
+- void *security,
+- unsigned stack_size,
+- int ( *start_address )( void * ),
+- void *arglist,
+- unsigned initflag,
+- unsigned *thrdaddr
+-) {
+-
+- HANDLE h = CreateThread(NULL, stack_size, start_address, arglist, initflag, (LPDWORD)thrdaddr);
+- return h;
+-
+-}
+-
+-uintptr_t _beginthread(
+- void( *start_address )( void * ),
+- unsigned stack_size,
+- void *arglist
+-) {
+- HANDLE h = CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)start_address, arglist, 0, NULL);
+- return (uintptr_t)h;
+-}
+-
+-BOOL WINAPI GetThreadTimes (
+- HANDLE hThread,
+- LPFILETIME lpCreationTime,
+- LPFILETIME lpExitTime,
+- LPFILETIME lpKernelTime,
+- LPFILETIME lpUserTime
+-) {
+- if (!hThread)
+- return false;
+- if (!hThread->m_threadValid)
+- return false;
+-
+- if (hThread == (HANDLE)-1) {
+- if (lpCreationTime)
+- TimeTToFileTime(0,lpCreationTime);
+- if (lpExitTime)
+- TimeTToFileTime(time(NULL),lpExitTime);
+- if (lpKernelTime)
+- TimeTToFileTime(0,lpKernelTime);
+- if (lpUserTime)
+- TimeTToFileTime(0,lpUserTime);
+-
+- return true;
+- }
+-
+- if (lpCreationTime)
+- TimeTToFileTime(hThread->m_tmCreation,lpCreationTime);
+- if (lpExitTime)
+- TimeTToFileTime(time(NULL),lpExitTime);
+- if (lpKernelTime)
+- TimeTToFileTime(0,lpKernelTime);
+-
+-#ifdef __APPLE__
+- thread_info_data_t threadInfo;
+- mach_msg_type_number_t threadInfoCount = THREAD_INFO_MAX;
+-
+- if (hThread->m_machThreadPort == MACH_PORT_NULL)
+- hThread->m_machThreadPort = pthread_mach_thread_np(hThread->m_hThread);
+-
+- kern_return_t ret = thread_info(hThread->m_machThreadPort, THREAD_BASIC_INFO, (thread_info_t)threadInfo, &threadInfoCount);
+- if (ret == KERN_SUCCESS)
+- {
+- thread_basic_info_t threadBasicInfo = (thread_basic_info_t)threadInfo;
+-
+- if (lpUserTime)
+- {
+- // User time.
+- unsigned long long time = ((__int64)threadBasicInfo->user_time.seconds * 10000000L) + threadBasicInfo->user_time.microseconds*10L;
+- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF);
+- lpUserTime->dwHighDateTime = (time >> 32);
+- }
+-
+- if (lpKernelTime)
+- {
+- // System time.
+- unsigned long long time = ((__int64)threadBasicInfo->system_time.seconds * 10000000L) + threadBasicInfo->system_time.microseconds*10L;
+- lpKernelTime->dwLowDateTime = (time & 0xFFFFFFFF);
+- lpKernelTime->dwHighDateTime = (time >> 32);
+- }
+- }
+- else
+- {
+- if (lpUserTime)
+- lpUserTime->dwLowDateTime = lpUserTime->dwHighDateTime = 0;
+-
+- if (lpKernelTime)
+- lpKernelTime->dwLowDateTime = lpKernelTime->dwHighDateTime = 0;
+- }
+-#elif _POSIX_THREAD_CPUTIME != -1
+- if(lpUserTime)
+- {
+- lpUserTime->dwLowDateTime = 0;
+- lpUserTime->dwHighDateTime = 0;
+- clockid_t clock;
+- if (pthread_getcpuclockid(hThread->m_hThread, &clock) == 0)
+- {
+- struct timespec tp = {};
+- clock_gettime(clock, &tp);
+- unsigned long long time = (unsigned long long)tp.tv_sec * 10000000 + (unsigned long long)tp.tv_nsec/100;
+- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF);
+- lpUserTime->dwHighDateTime = (time >> 32);
+- }
+- }
+-#else
+- if (lpUserTime)
+- TimeTToFileTime(0,lpUserTime);
+-#endif
+- return true;
+-}
+-
+-BOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority)
+-{
+- return true;
+-}
+-
+-int GetThreadPriority(HANDLE hThread)
+-{
+- return 0;
+-}
+-
+-#endif
+-
+diff --git a/xbmc/linux/XThreadUtils.h b/xbmc/linux/XThreadUtils.h
+deleted file mode 100644
+index 41b659e..0000000
+--- a/xbmc/linux/XThreadUtils.h
++++ /dev/null
+@@ -1,100 +0,0 @@
+-#ifndef __XTHREAD_UTILS__H__
+-#define __XTHREAD_UTILS__H__
+-
+-/*
+- * Copyright (C) 2005-2009 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include
+-
+-HANDLE WINAPI CreateThread(
+- LPSECURITY_ATTRIBUTES lpThreadAttributes,
+- SIZE_T dwStackSize,
+- LPTHREAD_START_ROUTINE lpStartAddress,
+- LPVOID lpParameter,
+- DWORD dwCreationFlags,
+- LPDWORD lpThreadId
+- );
+-
+-HANDLE _beginthreadex(
+- void *security,
+- unsigned stack_size,
+- int ( *start_address )( void * ),
+- void *arglist,
+- unsigned initflag,
+- unsigned *thrdaddr
+-);
+-
+-uintptr_t _beginthread(
+- void( *start_address )( void * ),
+- unsigned stack_size,
+- void *arglist
+-);
+-
+-#if 0 // Deprecated, use CThread::GetCurrentThreadId() instead
+-DWORD WINAPI GetCurrentThreadId(void);
+-#endif
+-
+-HANDLE WINAPI GetCurrentThread(void);
+-HANDLE WINAPI GetCurrentProcess(void);
+-
+-BOOL WINAPI GetThreadTimes (
+- HANDLE hThread,
+- LPFILETIME lpCreationTime,
+- LPFILETIME lpExitTime,
+- LPFILETIME lpKernelTime,
+- LPFILETIME lpUserTime
+-);
+-
+-int GetThreadPriority(
+- HANDLE hThread
+-);
+-
+-BOOL WINAPI SetThreadPriority(
+- HANDLE hThread,
+- int nPriority
+-);
+-
+-// helper class for TLS handling
+-class TLS
+-{
+-public:
+- TLS()
+- {
+- pthread_key_create(&m_key, free);
+- }
+-
+- ~TLS()
+- {
+- pthread_key_delete(m_key);
+- }
+-
+- void *Get()
+- {
+- if (pthread_getspecific(m_key) == NULL)
+-pthread_setspecific(m_key, malloc(8));
+-
+- return pthread_getspecific(m_key);
+- }
+-
+- pthread_key_t m_key;
+-};
+-
+-#endif
+diff --git a/xbmc/music/LastFmManager.cpp b/xbmc/music/LastFmManager.cpp
+index 700f28a..b97fdf2 100644
+--- a/xbmc/music/LastFmManager.cpp
++++ b/xbmc/music/LastFmManager.cpp
+@@ -70,7 +70,7 @@ using namespace XFILE;
+
+ CLastFmManager* CLastFmManager::m_pInstance=NULL;
+
+-CLastFmManager::CLastFmManager()
++CLastFmManager::CLastFmManager() : CThread("CLastFmManager")
+ {
+ m_RadioTrackQueue = new CPlayList;
+ }
+@@ -534,7 +534,7 @@ void CLastFmManager::Update()
+ if (iNrCachedTracks == 0)
+ {
+ //get more tracks
+- if (ThreadHandle() != NULL)
++ if (IsRunning())
+ {
+ m_hWorkerEvent.Set();
+ }
+@@ -633,7 +633,7 @@ void CLastFmManager::StopRadio(bool bKillSession /*= true*/)
+ {
+ m_RadioSession = "";
+ }
+- if (m_ThreadHandle)
++ if (IsRunning())
+ {
+ m_bStop = true;
+ m_hWorkerEvent.Set();
+diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp
+index 3400f27..445edaf 100644
+--- a/xbmc/music/infoscanner/MusicInfoScanner.cpp
++++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp
+@@ -57,7 +57,7 @@ using namespace MUSIC_INFO;
+ using namespace XFILE;
+ using namespace MUSIC_GRABBER;
+
+-CMusicInfoScanner::CMusicInfoScanner()
++CMusicInfoScanner::CMusicInfoScanner() : CThread("CMusicInfoScanner")
+ {
+ m_bRunning = false;
+ m_pObserver = NULL;
+@@ -99,7 +99,7 @@ void CMusicInfoScanner::Process()
+
+ // Create the thread to count all files to be scanned
+ SetPriority( GetMinPriority() );
+- CThread fileCountReader(this);
++ CThread fileCountReader(this, "CMusicInfoScanner");
+ if (m_pObserver)
+ fileCountReader.Create();
+
+diff --git a/xbmc/music/infoscanner/MusicInfoScraper.cpp b/xbmc/music/infoscanner/MusicInfoScraper.cpp
+index 09aeb14..aad726c 100644
+--- a/xbmc/music/infoscanner/MusicInfoScraper.cpp
++++ b/xbmc/music/infoscanner/MusicInfoScraper.cpp
+@@ -28,7 +28,7 @@ using namespace MUSIC_GRABBER;
+ using namespace ADDON;
+ using namespace std;
+
+-CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper)
++CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper) : CThread("CMusicInfoScraper")
+ {
+ m_bSucceeded=false;
+ m_bCanceled=false;
+diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp
+index 5a14773..dda7f0b 100644
+--- a/xbmc/network/AirPlayServer.cpp
++++ b/xbmc/network/AirPlayServer.cpp
+@@ -182,7 +182,7 @@ void CAirPlayServer::StopServer(bool bWait)
+ }
+ }
+
+-CAirPlayServer::CAirPlayServer(int port, bool nonlocal)
++CAirPlayServer::CAirPlayServer(int port, bool nonlocal) : CThread("AirPlayServer")
+ {
+ m_port = port;
+ m_nonlocal = nonlocal;
+diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp
+index 8779c7c..24ffa6f 100644
+--- a/xbmc/network/AirTunesServer.cpp
++++ b/xbmc/network/AirTunesServer.cpp
+@@ -295,7 +295,7 @@ void CAirTunesServer::StopServer(bool bWait)
+ }
+ }
+
+-CAirTunesServer::CAirTunesServer(int port, bool nonlocal)
++CAirTunesServer::CAirTunesServer(int port, bool nonlocal) : CThread("CAirTunesServer")
+ {
+ m_port = port;
+ m_pLibShairport = new DllLibShairport();
+diff --git a/xbmc/network/Network.h b/xbmc/network/Network.h
+index cb0ea52..e514e05 100644
+--- a/xbmc/network/Network.h
++++ b/xbmc/network/Network.h
+@@ -24,6 +24,7 @@
+
+ #include
+ #include "utils/StdString.h"
++#include "system.h"
+
+ enum EncMode { ENC_NONE = 0, ENC_WEP = 1, ENC_WPA = 2, ENC_WPA2 = 3 };
+ enum NetworkAssignment { NETWORK_DASH = 0, NETWORK_DHCP = 1, NETWORK_STATIC = 2, NETWORK_DISABLED = 3 };
+diff --git a/xbmc/network/TCPServer.cpp b/xbmc/network/TCPServer.cpp
+index 4b0d9ad..fd46236 100644
+--- a/xbmc/network/TCPServer.cpp
++++ b/xbmc/network/TCPServer.cpp
+@@ -85,7 +85,7 @@ void CTCPServer::StopServer(bool bWait)
+ }
+ }
+
+-CTCPServer::CTCPServer(int port, bool nonlocal)
++CTCPServer::CTCPServer(int port, bool nonlocal) : CThread("CTCPServer")
+ {
+ m_port = port;
+ m_nonlocal = nonlocal;
+diff --git a/xbmc/network/UdpClient.cpp b/xbmc/network/UdpClient.cpp
+index 8e1ef2e..8f49ce8 100644
+--- a/xbmc/network/UdpClient.cpp
++++ b/xbmc/network/UdpClient.cpp
+@@ -35,7 +35,7 @@
+
+ #define UDPCLIENT_DEBUG_LEVEL LOGDEBUG
+
+-CUdpClient::CUdpClient(void) : CThread()
++CUdpClient::CUdpClient(void) : CThread("CUdpClient")
+ {}
+
+ CUdpClient::~CUdpClient(void)
+diff --git a/xbmc/network/UdpClient.h b/xbmc/network/UdpClient.h
+index 97acb28..a1aa597 100644
+--- a/xbmc/network/UdpClient.h
++++ b/xbmc/network/UdpClient.h
+@@ -25,6 +25,7 @@
+ #include "threads/CriticalSection.h"
+ #include
+ #include
++#include "system.h"
+
+ class CUdpClient : CThread
+ {
+diff --git a/xbmc/network/libscrobbler/scrobbler.cpp b/xbmc/network/libscrobbler/scrobbler.cpp
+index cb08d1b..cf5f927 100644
+--- a/xbmc/network/libscrobbler/scrobbler.cpp
++++ b/xbmc/network/libscrobbler/scrobbler.cpp
+@@ -46,7 +46,7 @@
+ #define SCROBBLER_ACTION_NOWPLAYING 2
+
+ CScrobbler::CScrobbler(const CStdString &strHandshakeURL, const CStdString &strLogPrefix)
+- : CThread()
++ : CThread("CScrobbler")
+ {
+ m_bBanned = false;
+ m_bBadAuth = false;
+@@ -67,7 +67,7 @@ void CScrobbler::Init()
+ ResetState();
+ LoadCredentials();
+ LoadJournal();
+- if (!ThreadHandle())
++ if (!IsRunning())
+ Create();
+ }
+
+diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp
+index 3868cc7..ffd78d2 100644
+--- a/xbmc/peripherals/Peripherals.cpp
++++ b/xbmc/peripherals/Peripherals.cpp
+@@ -19,6 +19,7 @@
+ *
+ */
+
++#include "system.h"
+ #include "Peripherals.h"
+ #include "bus/PeripheralBus.h"
+ #include "devices/PeripheralBluetooth.h"
+diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp
+index ffe47a5..a7b54d2 100644
+--- a/xbmc/pictures/GUIWindowSlideShow.cpp
++++ b/xbmc/pictures/GUIWindowSlideShow.cpp
+@@ -67,7 +67,7 @@ using namespace XFILE;
+
+ static float zoomamount[10] = { 1.0f, 1.2f, 1.5f, 2.0f, 2.8f, 4.0f, 6.0f, 9.0f, 13.5f, 20.0f };
+
+-CBackgroundPicLoader::CBackgroundPicLoader()
++CBackgroundPicLoader::CBackgroundPicLoader() : CThread("CBackgroundPicLoader")
+ {
+ m_pCallback = NULL;
+ m_isLoading = false;
+diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp
+index 938cb36..ed92a41 100644
+--- a/xbmc/rendering/dx/RenderSystemDX.cpp
++++ b/xbmc/rendering/dx/RenderSystemDX.cpp
+@@ -569,7 +569,7 @@ bool CRenderSystemDX::PresentRenderImpl(const CDirtyRegionList &dirty)
+
+ //CVideoReferenceClock polls GetRasterStatus too,
+ //polling it from two threads at the same time is bad
+- if (g_advancedSettings.m_sleepBeforeFlip > 0 && g_VideoReferenceClock.ThreadHandle() == NULL)
++ if (g_advancedSettings.m_sleepBeforeFlip > 0 && !g_VideoReferenceClock.IsRunning())
+ {
+ //save current thread priority and set thread priority to THREAD_PRIORITY_TIME_CRITICAL
+ int priority = GetThreadPriority(GetCurrentThread());
+diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp
+index e228621..b31dec0 100644
+--- a/xbmc/settings/GUISettings.cpp
++++ b/xbmc/settings/GUISettings.cpp
+@@ -592,6 +592,10 @@ void CGUISettings::Initialize()
+ #ifdef HAVE_LIBVA
+ AddBool(vp, "videoplayer.usevaapi", 13426, true);
+ #endif
++#ifdef HAVE_LIBXVBA
++ AddBool(vp, "videoplayer.usexvba", 13433, true);
++ AddBool(vp, "videoplayer.usexvbasharedsurface", 13434, true);
++#endif
+ #ifdef HAS_DX
+ AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false);
+ #endif
+diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp
+index eb04966..408152a 100644
+--- a/xbmc/settings/GUIWindowSettingsCategory.cpp
++++ b/xbmc/settings/GUIWindowSettingsCategory.cpp
+@@ -936,6 +936,15 @@ void CGUIWindowSettingsCategory::UpdateSettings()
+ pControl->SetEnabled(enabled);
+ }
+ }
++ else if (strSetting.Equals("videoplayer.usexvbasharedsurface"))
++ {
++ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
++ if (pControl)
++ {
++ bool enabled = (g_guiSettings.GetBool("videoplayer.usexvba"));
++ pControl->SetEnabled(enabled);
++ }
++ }
+ else if (strSetting.Equals("weather.addonsettings"))
+ {
+ AddonPtr addon;
+diff --git a/xbmc/threads/Thread.cpp b/xbmc/threads/Thread.cpp
+index bd213e2..becc594 100644
+--- a/xbmc/threads/Thread.cpp
++++ b/xbmc/threads/Thread.cpp
+@@ -20,41 +20,27 @@
+
+ #include "threads/SystemClock.h"
+ #include "Thread.h"
+-#ifndef _LINUX
+-#include
+-#include "utils/win32exception.h"
+-#ifndef _MT
+-#pragma message( "Please compile using multithreaded run-time libraries" )
+-#endif
+-typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter);
+-#else
+-#include "PlatformInclude.h"
+-#include "XHandle.h"
+-#include
+-typedef int (*PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter);
+-#endif
+-
+-#if defined(__GNUC__) && !defined(__clang__)
+-#include
+-using namespace __cxxabiv1;
+-#endif
+-
+ #include "utils/log.h"
+ #include "utils/TimeUtils.h"
+ #include "threads/ThreadLocal.h"
+
++#define __STDC_FORMAT_MACROS
++#include
++
+ static XbmcThreads::ThreadLocal currentThread;
+
++#include "threads/platform/ThreadImpl.cpp"
++
+ //////////////////////////////////////////////////////////////////////
+ // Construction/Destruction
+ //////////////////////////////////////////////////////////////////////
+
+-CThread::CThread(const char* ThreadName) : m_StopEvent(true,true)
++CThread::CThread(const char* ThreadName)
++: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true)
+ {
+ m_bStop = false;
+
+ m_bAutoDelete = false;
+- m_ThreadHandle = NULL;
+ m_ThreadId = 0;
+ m_iLastTime = 0;
+ m_iLastUsage = 0;
+@@ -66,12 +52,12 @@ CThread::CThread(const char* ThreadName) : m_StopEvent(true,true)
+ m_ThreadName = ThreadName;
+ }
+
+-CThread::CThread(IRunnable* pRunnable, const char* ThreadName) : m_StopEvent(true,true)
++CThread::CThread(IRunnable* pRunnable, const char* ThreadName)
++: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true)
+ {
+ m_bStop = false;
+
+ m_bAutoDelete = false;
+- m_ThreadHandle = NULL;
+ m_ThreadId = 0;
+ m_iLastTime = 0;
+ m_iLastUsage = 0;
+@@ -85,171 +71,62 @@ CThread::CThread(IRunnable* pRunnable, const char* ThreadName) : m_StopEvent(tru
+
+ CThread::~CThread()
+ {
+- if (m_ThreadHandle != NULL)
+- {
+- CloseHandle(m_ThreadHandle);
+- }
+- m_ThreadHandle = NULL;
+-
++ StopThread();
+ }
+
+-#ifndef _WIN32
+-void CThread::term_handler (int signum)
++bool CThread::IsRunning()
+ {
+- CLog::Log(LOGERROR,"thread 0x%lx (%lu) got signal %d. calling OnException and terminating thread abnormally.", (long unsigned int)pthread_self(), (long unsigned int)pthread_self(), signum);
+-
+- CThread* curThread = currentThread.get();
+- if (curThread)
+- {
+- curThread->m_bStop = TRUE;
+- curThread->m_StopEvent.Set();
+-
+- curThread->OnException();
+- if( curThread->IsAutoDelete() )
+- delete curThread;
+- }
+-
+- pthread_exit(NULL);
++ return m_ThreadId ? true : false;
+ }
+
+-int CThread::staticThread(void* data)
+-#else
+-DWORD WINAPI CThread::staticThread(LPVOID* data)
+-#endif
++THREADFUNC CThread::staticThread(void* data)
+ {
+ CThread* pThread = (CThread*)(data);
++ std::string name;
++ ThreadIdentifier id;
++ bool autodelete;
++
+ if (!pThread) {
+ CLog::Log(LOGERROR,"%s, sanity failed. thread is NULL.",__FUNCTION__);
+ return 1;
+ }
+
+- if (pThread->m_ThreadName.empty())
+- pThread->m_ThreadName = pThread->GetTypeName();
+- pThread->SetDebugCallStackName(pThread->m_ThreadName.c_str());
++ name = pThread->m_ThreadName;
++ id = pThread->m_ThreadId;
++ autodelete = pThread->m_bAutoDelete;
+
+- CLog::Log(LOGDEBUG,"Thread %s start, auto delete: %d", pThread->m_ThreadName.c_str(), pThread->IsAutoDelete());
++ pThread->SetThreadInfo();
++
++ CLog::Log(LOGNOTICE,"Thread %s start, auto delete: %s", name.c_str(), (autodelete ? "true" : "false"));
+
+ currentThread.set(pThread);
+-#ifndef _LINUX
+- /* install win32 exception translator */
+- win32_exception::install_handler();
+-#else
+- struct sigaction action;
+- action.sa_handler = term_handler;
+- sigemptyset (&action.sa_mask);
+- action.sa_flags = 0;
+- //sigaction (SIGABRT, &action, NULL);
+- //sigaction (SIGSEGV, &action, NULL);
+-#endif
+-
+-
+- try
+- {
+- pThread->OnStartup();
+- }
+-#ifndef _LINUX
+- catch (const win32_exception &e)
+- {
+- e.writelog(__FUNCTION__);
+- if( pThread->IsAutoDelete() )
+- {
+- delete pThread;
+- _endthreadex(123);
+- return 0;
+- }
+- }
+-#endif
+- catch(...)
+- {
+- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread startup, aborting. auto delete: %d", __FUNCTION__, pThread->m_ThreadName.c_str(), pThread->IsAutoDelete());
+- if( pThread->IsAutoDelete() )
+- {
+- delete pThread;
+-#ifndef _LINUX
+- _endthreadex(123);
+-#endif
+- return 0;
+- }
+- }
++ pThread->m_StartEvent.Set();
+
+- try
+- {
+- pThread->Process();
+- }
+-#ifndef _LINUX
+- catch (const access_violation &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+- catch (const win32_exception &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+-#endif
+- catch(...)
+- {
+- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread process, attemping cleanup in OnExit", __FUNCTION__, pThread->m_ThreadName.c_str());
+- }
++ pThread->OnStartup();
++ pThread->Process();
++ pThread->OnExit();
+
+- try
+- {
+- pThread->OnExit();
+- }
+-#ifndef _LINUX
+- catch (const access_violation &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+- catch (const win32_exception &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+-#endif
+- catch(...)
+- {
+- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread exit", __FUNCTION__, pThread->m_ThreadName.c_str());
+- }
++ // lock during termination
++ CSingleLock lock(pThread->m_CriticalSection);
++
++ pThread->m_ThreadId = 0;
++ pThread->m_TermEvent.Set();
++ pThread->TermHandler();
+
+- if ( pThread->IsAutoDelete() )
++ lock.Leave();
++
++ if (autodelete)
+ {
+- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId());
++ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", name.c_str(), (uint64_t)id);
+ delete pThread;
+ pThread = NULL;
+ }
+ else
+- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId());
+-
+-// DXMERGE - this looks like it might have used to have been useful for something...
+-// g_graphicsContext.DeleteThreadContext();
++ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", name.c_str(), (uint64_t)id);
+
+-#ifndef _LINUX
+- _endthreadex(123);
+-#endif
+ return 0;
+ }
+
+-void CThread::Create(bool bAutoDelete, unsigned stacksize)
+-{
+- if (m_ThreadHandle != NULL)
+- {
+- throw 1; //ERROR should not b possible!!!
+- }
+- m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
+- m_iLastUsage = 0;
+- m_fLastUsage = 0.0f;
+- m_bAutoDelete = bAutoDelete;
+- m_bStop = false;
+- m_StopEvent.Reset();
+-
+- m_ThreadHandle = (HANDLE)_beginthreadex(NULL, stacksize, (PBEGINTHREADEX_THREADFUNC)staticThread, (void*)this, 0, &m_ThreadId);
+-
+-#ifdef _LINUX
+- if (m_ThreadHandle && m_ThreadHandle->m_threadValid && m_bAutoDelete)
+- // FIXME: WinAPI can truncate 64bit pthread ids
+- pthread_detach(m_ThreadHandle->m_hThread);
+-#endif
+-}
+-
+ bool CThread::IsAutoDelete() const
+ {
+ return m_bAutoDelete;
+@@ -259,213 +136,15 @@ void CThread::StopThread(bool bWait /*= true*/)
+ {
+ m_bStop = true;
+ m_StopEvent.Set();
+- if (m_ThreadHandle && bWait)
++ if (m_ThreadId && bWait)
+ {
+- WaitForThreadExit(INFINITE);
+- CloseHandle(m_ThreadHandle);
+- m_ThreadHandle = NULL;
++ WaitForThreadExit(0xFFFFFFFF);
+ }
+ }
+
+ ThreadIdentifier CThread::ThreadId() const
+ {
+-#ifdef _LINUX
+- if (m_ThreadHandle && m_ThreadHandle->m_threadValid)
+- return m_ThreadHandle->m_hThread;
+- else
+- return 0;
+-#else
+ return m_ThreadId;
+-#endif
+-}
+-
+-
+-CThread::operator HANDLE()
+-{
+- return m_ThreadHandle;
+-}
+-
+-CThread::operator HANDLE() const
+-{
+- return m_ThreadHandle;
+-}
+-
+-bool CThread::SetPriority(const int iPriority)
+-// Set thread priority
+-// Return true for success
+-{
+- bool rtn = false;
+-
+- if (m_ThreadHandle)
+- {
+- rtn = SetThreadPriority( m_ThreadHandle, iPriority ) == TRUE;
+- }
+-
+- return(rtn);
+-}
+-
+-void CThread::SetPrioritySched_RR(void)
+-{
+-#ifdef __APPLE__
+- // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the
+- // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects
+- // the thread running away. OSX automatically does this with the CoreAudio audio
+- // device handler thread.
+- int32_t result;
+- thread_extended_policy_data_t theFixedPolicy;
+-
+- // make thread fixed, set to 'true' for a non-fixed thread
+- theFixedPolicy.timeshare = false;
+- result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY,
+- (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
+-
+- int policy;
+- struct sched_param param;
+- result = pthread_getschedparam(ThreadId(), &policy, ¶m );
+- // change from default SCHED_OTHER to SCHED_RR
+- policy = SCHED_RR;
+- result = pthread_setschedparam(ThreadId(), policy, ¶m );
+-#endif
+-}
+-
+-int CThread::GetMinPriority(void)
+-{
+-#if 0
+-//#if defined(__APPLE__)
+- struct sched_param sched;
+- int rtn, policy;
+-
+- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
+- int min = sched_get_priority_min(policy);
+-
+- return(min);
+-#else
+- return(THREAD_PRIORITY_IDLE);
+-#endif
+-}
+-
+-int CThread::GetMaxPriority(void)
+-{
+-#if 0
+-//#if defined(__APPLE__)
+- struct sched_param sched;
+- int rtn, policy;
+-
+- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
+- int max = sched_get_priority_max(policy);
+-
+- return(max);
+-#else
+- return(THREAD_PRIORITY_HIGHEST);
+-#endif
+-}
+-
+-int CThread::GetNormalPriority(void)
+-{
+-#if 0
+-//#if defined(__APPLE__)
+- struct sched_param sched;
+- int rtn, policy;
+-
+- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
+- int min = sched_get_priority_min(policy);
+- int max = sched_get_priority_max(policy);
+-
+- return( min + ((max-min) / 2) );
+-#else
+- return(THREAD_PRIORITY_NORMAL);
+-#endif
+-}
+-
+-
+-void CThread::SetDebugCallStackName( const char *name )
+-{
+-#ifdef _WIN32
+- const unsigned int MS_VC_EXCEPTION = 0x406d1388;
+- struct THREADNAME_INFO
+- {
+- DWORD dwType; // must be 0x1000
+- LPCSTR szName; // pointer to name (in same addr space)
+- DWORD dwThreadID; // thread ID (-1 caller thread)
+- DWORD dwFlags; // reserved for future use, most be zero
+- } info;
+-
+- info.dwType = 0x1000;
+- info.szName = name;
+- info.dwThreadID = m_ThreadId;
+- info.dwFlags = 0;
+-
+- try
+- {
+- RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
+- }
+- catch(...)
+- {
+- }
+-#endif
+-}
+-
+-// Get the thread name using the implementation dependant typeid() class
+-// and attempt to clean it.
+-std::string CThread::GetTypeName(void)
+-{
+- std::string name = typeid(*this).name();
+-
+-#if defined(_MSC_VER)
+- // Visual Studio 2010 returns the name as "class CThread" etc
+- if (name.substr(0, 6) == "class ")
+- name = name.substr(6, name.length() - 6);
+-#elif defined(__GNUC__) && !defined(__clang__)
+- // gcc provides __cxa_demangle to demangle the name
+- char* demangled = NULL;
+- int status;
+-
+- demangled = __cxa_demangle(name.c_str(), NULL, 0, &status);
+- if (status == 0)
+- name = demangled;
+- else
+- CLog::Log(LOGDEBUG,"%s, __cxa_demangle(%s) failed with status %d", __FUNCTION__, name.c_str(), status);
+-
+- if (demangled)
+- free(demangled);
+-#endif
+-
+- return name;
+-}
+-
+-bool CThread::WaitForThreadExit(unsigned int milliseconds)
+-// Waits for thread to exit, timeout in given number of msec.
+-// Returns true when thread ended
+-{
+- if (!m_ThreadHandle) return true;
+-
+-#ifndef _LINUX
+- // boost priority of thread we are waiting on to same as caller
+- int callee = GetThreadPriority(m_ThreadHandle);
+- int caller = GetThreadPriority(GetCurrentThread());
+- if(caller > callee)
+- SetThreadPriority(m_ThreadHandle, caller);
+-
+- if (::WaitForSingleObject(m_ThreadHandle, milliseconds) != WAIT_TIMEOUT)
+- return true;
+-
+- // restore thread priority if thread hasn't exited
+- if(caller > callee)
+- SetThreadPriority(m_ThreadHandle, callee);
+-#else
+- if (!(m_ThreadHandle->m_threadValid) || pthread_join(m_ThreadHandle->m_hThread, NULL) == 0)
+- {
+- m_ThreadHandle->m_threadValid = false;
+- return true;
+- }
+-#endif
+-
+- return false;
+-}
+-
+-HANDLE CThread::ThreadHandle()
+-{
+- return m_ThreadHandle;
+ }
+
+ void CThread::Process()
+@@ -474,54 +153,14 @@ void CThread::Process()
+ m_pRunnable->Run();
+ }
+
+-float CThread::GetRelativeUsage()
+-{
+- unsigned __int64 iTime = XbmcThreads::SystemClockMillis();
+- iTime *= 10000; // convert into 100ns tics
+-
+- // only update every 1 second
+- if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
+-
+- FILETIME CreationTime, ExitTime, UserTime, KernelTime;
+- if( GetThreadTimes( m_ThreadHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
+- {
+- unsigned __int64 iUsage = 0;
+- iUsage += (((unsigned __int64)UserTime.dwHighDateTime) << 32) + ((unsigned __int64)UserTime.dwLowDateTime);
+- iUsage += (((unsigned __int64)KernelTime.dwHighDateTime) << 32) + ((unsigned __int64)KernelTime.dwLowDateTime);
+-
+- if(m_iLastUsage > 0 && m_iLastTime > 0)
+- m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
+-
+- m_iLastUsage = iUsage;
+- m_iLastTime = iTime;
+-
+- return m_fLastUsage;
+- }
+- return 0.0f;
+-}
+-
+ bool CThread::IsCurrentThread() const
+ {
+ return IsCurrentThread(ThreadId());
+ }
+
+-
+-ThreadIdentifier CThread::GetCurrentThreadId()
+-{
+-#ifdef _LINUX
+- return pthread_self();
+-#else
+- return ::GetCurrentThreadId();
+-#endif
+-}
+-
+-bool CThread::IsCurrentThread(const ThreadIdentifier tid)
++CThread* CThread::GetCurrentThread()
+ {
+-#ifdef _LINUX
+- return pthread_equal(pthread_self(), tid);
+-#else
+- return (::GetCurrentThreadId() == tid);
+-#endif
++ return currentThread.get();
+ }
+
+ void CThread::Sleep(unsigned int milliseconds)
+@@ -529,7 +168,7 @@ void CThread::Sleep(unsigned int milliseconds)
+ if(milliseconds > 10 && IsCurrentThread())
+ m_StopEvent.WaitMSec(milliseconds);
+ else
+- ::Sleep(milliseconds);
++ XbmcThreads::ThreadSleep(milliseconds);
+ }
+
+
+diff --git a/xbmc/threads/Thread.h b/xbmc/threads/Thread.h
+index 768d6f8..bebd9ee 100644
+--- a/xbmc/threads/Thread.h
++++ b/xbmc/threads/Thread.h
+@@ -23,19 +23,13 @@
+ //
+ //////////////////////////////////////////////////////////////////////
+
+-#if !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_) && !defined(AFX_THREAD_H__67621B15_8724_4B5D_9343_7667075C89F2__INCLUDED_)
+-#define AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_
+-
+-#if _MSC_VER > 1000
+ #pragma once
+-#endif // _MSC_VER > 1000
+
+ #include
+-#include "system.h" // for HANDLE
+-#ifdef _LINUX
+-#include "PlatformInclude.h"
+-#endif
++#include
+ #include "Event.h"
++#include "threads/ThreadImpl.h"
++#include "threads/ThreadLocal.h"
+
+ class IRunnable
+ {
+@@ -44,37 +38,36 @@ public:
+ virtual ~IRunnable() {}
+ };
+
+-#ifdef CTHREAD
+-#undef CTHREAD
+-#endif
+-
+ // minimum as mandated by XTL
+ #define THREAD_MINSTACKSIZE 0x10000
+
+ class CThread
+ {
+ public:
+- CThread(const char* ThreadName = NULL);
+- CThread(IRunnable* pRunnable, const char* ThreadName = NULL);
++ CThread(const char* ThreadName);
++ CThread(IRunnable* pRunnable, const char* ThreadName);
+ virtual ~CThread();
+ void Create(bool bAutoDelete = false, unsigned stacksize = 0);
+ bool WaitForThreadExit(unsigned int milliseconds);
+ void Sleep(unsigned int milliseconds);
+ bool SetPriority(const int iPriority);
+- void SetPrioritySched_RR(void);
++ int GetPriority(void);
+ int GetMinPriority(void);
+ int GetMaxPriority(void);
+ int GetNormalPriority(void);
+- HANDLE ThreadHandle();
+- operator HANDLE();
+- operator HANDLE() const;
++ int GetSchedRRPriority(void);
++ bool SetPrioritySched_RR(int iPriority);
+ bool IsAutoDelete() const;
+ virtual void StopThread(bool bWait = true);
+ float GetRelativeUsage(); // returns the relative cpu usage of this thread since last call
++ int64_t GetAbsoluteUsage();
+ bool IsCurrentThread() const;
++ bool IsRunning();
+
+ static bool IsCurrentThread(const ThreadIdentifier tid);
+ static ThreadIdentifier GetCurrentThreadId();
++ static CThread* GetCurrentThread();
++ static int64_t GetCurrentThreadUsage();
+ protected:
+ virtual void OnStartup(){};
+ virtual void OnExit(){};
+@@ -82,7 +75,6 @@ protected:
+ virtual void Process();
+
+ volatile bool m_bStop;
+- HANDLE m_ThreadHandle;
+
+ enum WaitResponse { WAIT_INTERRUPTED = -1, WAIT_SIGNALED = 0, WAIT_TIMEDOUT = 1 };
+
+@@ -108,36 +100,22 @@ protected:
+ }
+
+ private:
+- /*! \brief set the threadname for the debugger/callstack, implementation dependent.
+- */
+- void SetDebugCallStackName( const char *threadName );
+- std::string GetTypeName(void);
+-
+-private:
++ static THREADFUNC staticThread(void *data);
+ ThreadIdentifier ThreadId() const;
++ void SetThreadInfo();
++ void TermHandler();
++
++ ThreadIdentifier m_ThreadId;
++ ThreadOpaque m_ThreadOpaque;
+ bool m_bAutoDelete;
+ CEvent m_StopEvent;
+- unsigned m_ThreadId; // This value is unreliable on platforms using pthreads
+- // Use m_ThreadHandle->m_hThread instead
++ CEvent m_TermEvent;
++ CEvent m_StartEvent;
++ CCriticalSection m_CriticalSection;
+ IRunnable* m_pRunnable;
+-
+- unsigned __int64 m_iLastUsage;
+- unsigned __int64 m_iLastTime;
++ uint64_t m_iLastUsage;
++ uint64_t m_iLastTime;
+ float m_fLastUsage;
+
+ std::string m_ThreadName;
+-
+-#ifdef _LINUX
+- static void term_handler (int signum);
+-#endif
+-
+-#ifndef _WIN32
+- static int staticThread(void* data);
+-#else
+- static DWORD WINAPI staticThread(LPVOID* data);
+-#endif
+-
+-private:
+ };
+-
+-#endif // !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_)
+diff --git a/xbmc/threads/ThreadImpl.h b/xbmc/threads/ThreadImpl.h
+new file mode 100644
+index 0000000..ad10e3b
+--- /dev/null
++++ b/xbmc/threads/ThreadImpl.h
+@@ -0,0 +1,25 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#pragma once
++
++#include "threads/platform/ThreadImpl.h"
++
+diff --git a/xbmc/threads/platform/ThreadImpl.cpp b/xbmc/threads/platform/ThreadImpl.cpp
+new file mode 100644
+index 0000000..7f0213b
+--- /dev/null
++++ b/xbmc/threads/platform/ThreadImpl.cpp
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#pragma once
++
++#if (defined TARGET_POSIX)
++#include "threads/platform/pthreads/ThreadImpl.cpp"
++#if defined(TARGET_DARWIN_IOS)
++#include "threads/platform/darwin/ThreadSchedImpl.cpp"
++#else
++#include "threads/platform/linux/ThreadSchedImpl.cpp"
++#endif
++#elif (defined TARGET_WINDOWS)
++#include "threads/platform/win/ThreadImpl.cpp"
++#endif
++
+diff --git a/xbmc/threads/platform/ThreadImpl.h b/xbmc/threads/platform/ThreadImpl.h
+new file mode 100644
+index 0000000..f37709e
+--- /dev/null
++++ b/xbmc/threads/platform/ThreadImpl.h
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#pragma once
++
++#if (defined TARGET_POSIX)
++#include "threads/platform/pthreads/ThreadImpl.h"
++#elif (defined TARGET_WINDOWS)
++#include "threads/platform/win/ThreadImpl.h"
++#endif
+diff --git a/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp b/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp
+new file mode 100644
+index 0000000..7612fe7
+--- /dev/null
++++ b/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++int CThread::GetSchedRRPriority(void)
++{
++ return 96;
++}
++
++bool CThread::SetPrioritySched_RR(int iPriority)
++{
++ // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the
++ // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects
++ // the thread running away. OSX automatically does this with the CoreAudio audio
++ // device handler thread.
++ int32_t result;
++ thread_extended_policy_data_t theFixedPolicy;
++
++ // make thread fixed, set to 'true' for a non-fixed thread
++ theFixedPolicy.timeshare = false;
++ result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY,
++ (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
++
++ int policy;
++ struct sched_param param;
++ result = pthread_getschedparam(ThreadId(), &policy, ¶m );
++ // change from default SCHED_OTHER to SCHED_RR
++ policy = SCHED_RR;
++ result = pthread_setschedparam(ThreadId(), policy, ¶m );
++}
+diff --git a/xbmc/threads/platform/linux/ThreadSchedImpl.cpp b/xbmc/threads/platform/linux/ThreadSchedImpl.cpp
+new file mode 100644
+index 0000000..034a100
+--- /dev/null
++++ b/xbmc/threads/platform/linux/ThreadSchedImpl.cpp
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++int CThread::GetSchedRRPriority(void)
++{
++ return GetNormalPriority();
++}
++
++bool CThread::SetPrioritySched_RR(int iPriority)
++{
++ return false;
++}
+diff --git a/xbmc/threads/platform/pthreads/ThreadImpl.cpp b/xbmc/threads/platform/pthreads/ThreadImpl.cpp
+new file mode 100644
+index 0000000..58b602c
+--- /dev/null
++++ b/xbmc/threads/platform/pthreads/ThreadImpl.cpp
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include
++#include
++#include
++#include
++
++void CThread::Create(bool bAutoDelete, unsigned stacksize)
++{
++ if (m_ThreadId != 0)
++ {
++ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__);
++ exit(1);
++ }
++ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
++ m_iLastUsage = 0;
++ m_fLastUsage = 0.0f;
++ m_bAutoDelete = bAutoDelete;
++ m_bStop = false;
++ m_StopEvent.Reset();
++ m_TermEvent.Reset();
++ m_StartEvent.Reset();
++
++ pthread_attr_t attr;
++ pthread_attr_init(&attr);
++ if (stacksize > PTHREAD_STACK_MIN)
++ pthread_attr_setstacksize(&attr, stacksize);
++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++ if (pthread_create(&m_ThreadId, &attr, (void*(*)(void*))staticThread, this) != 0)
++ {
++ CLog::Log(LOGNOTICE, "%s - fatal error creating thread",__FUNCTION__);
++ }
++ pthread_attr_destroy(&attr);
++}
++
++void CThread::TermHandler()
++{
++
++}
++
++void CThread::SetThreadInfo()
++{
++ m_ThreadOpaque.LwpId = syscall(SYS_gettid);
++
++ // start thread with nice level of appication
++ int appNice = getpriority(PRIO_PROCESS, getpid());
++ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0)
++ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno));
++}
++
++ThreadIdentifier CThread::GetCurrentThreadId()
++{
++ return pthread_self();
++}
++
++bool CThread::IsCurrentThread(const ThreadIdentifier tid)
++{
++ return pthread_equal(pthread_self(), tid);
++}
++
++int CThread::GetMinPriority(void)
++{
++ // one level lower than application
++ return -1;
++}
++
++int CThread::GetMaxPriority(void)
++{
++ // one level higher than application
++ return 1;
++}
++
++int CThread::GetNormalPriority(void)
++{
++ // same level as application
++ return 0;
++}
++
++bool CThread::SetPriority(const int iPriority)
++{
++ bool bReturn = false;
++
++ // wait until thread is running, it needs to get its lwp id
++ m_StartEvent.Wait();
++
++ CSingleLock lock(m_CriticalSection);
++
++ // get min prio for SCHED_RR
++ int minRR = GetMaxPriority() + 1;
++
++ if (!m_ThreadId)
++ bReturn = false;
++ else if (iPriority >= minRR)
++ bReturn = SetPrioritySched_RR(iPriority);
++ else
++ {
++ // get user max prio
++ struct rlimit limit;
++ int userMaxPrio;
++ if (getrlimit(RLIMIT_NICE, &limit) == 0)
++ {
++ userMaxPrio = limit.rlim_cur - 20;
++ }
++ else
++ userMaxPrio = 0;
++
++ // keep priority in bounds
++ int prio = iPriority;
++ if (prio >= GetMaxPriority())
++ prio = std::min(GetMaxPriority(), userMaxPrio);
++ if (prio < GetMinPriority())
++ prio = GetMinPriority();
++
++ // nice level of application
++ int appNice = getpriority(PRIO_PROCESS, getpid());
++ if (prio)
++ prio = prio > 0 ? appNice-1 : appNice+1;
++
++ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, prio) == 0)
++ bReturn = true;
++ else
++ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno));
++ }
++
++ return bReturn;
++}
++
++int CThread::GetPriority()
++{
++ int iReturn;
++
++ // lwp id is valid after start signel has fired
++ m_StartEvent.Wait();
++
++ CSingleLock lock(m_CriticalSection);
++
++ int appNice = getpriority(PRIO_PROCESS, getpid());
++ int prio = getpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId);
++ iReturn = appNice - prio;
++
++ return iReturn;
++}
++
++bool CThread::WaitForThreadExit(unsigned int milliseconds)
++{
++ bool bReturn = m_TermEvent.WaitMSec(milliseconds);
++
++ return bReturn;
++}
++
++int64_t CThread::GetAbsoluteUsage()
++{
++ CSingleLock lock(m_CriticalSection);
++
++ if (!m_ThreadId)
++ return 0;
++
++ clockid_t clock;
++ int64_t time = 0;
++ if (pthread_getcpuclockid(m_ThreadId, &clock) == 0)
++ {
++ struct timespec tp;
++ clock_gettime(clock, &tp);
++ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100;
++ }
++ return time;
++}
++
++float CThread::GetRelativeUsage()
++{
++ unsigned int iTime = XbmcThreads::SystemClockMillis();
++ iTime *= 10000; // convert into 100ns tics
++
++ // only update every 1 second
++ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
++
++ int64_t iUsage = GetAbsoluteUsage();
++
++ if (m_iLastUsage > 0 && m_iLastTime > 0)
++ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
++
++ m_iLastUsage = iUsage;
++ m_iLastTime = iTime;
++
++ return m_fLastUsage;
++}
++
++int64_t CThread::GetCurrentThreadUsage()
++{
++ pthread_t tid = pthread_self();
++ clockid_t clock;
++ int64_t time = 0;
++ if (pthread_getcpuclockid(tid, &clock) == 0)
++ {
++ struct timespec tp;
++ clock_gettime(clock, &tp);
++ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100;
++ }
++ return time;
++}
++
+diff --git a/xbmc/threads/platform/pthreads/ThreadImpl.h b/xbmc/threads/platform/pthreads/ThreadImpl.h
+new file mode 100644
+index 0000000..3f4dd39
+--- /dev/null
++++ b/xbmc/threads/platform/pthreads/ThreadImpl.h
+@@ -0,0 +1,39 @@
++/*
++* Copyright (C) 2005-2011 Team XBMC
++* http://www.xbmc.org
++*
++* This Program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by
++* the Free Software Foundation; either version 2, or (at your option)
++* any later version.
++*
++* This Program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with XBMC; see the file COPYING. If not, write to
++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++* http://www.gnu.org/copyleft/gpl.html
++*
++*/
++
++#pragma once
++
++#include
++
++struct threadOpaque
++{
++ pid_t LwpId;
++};
++
++typedef pthread_t ThreadIdentifier;
++typedef threadOpaque ThreadOpaque;
++typedef int THREADFUNC;
++
++namespace XbmcThreads
++{
++ inline static void ThreadSleep(unsigned int millis) { usleep(millis*1000); }
++}
++
+diff --git a/xbmc/threads/platform/win/ThreadImpl.cpp b/xbmc/threads/platform/win/ThreadImpl.cpp
+new file mode 100644
+index 0000000..6650ee6
+--- /dev/null
++++ b/xbmc/threads/platform/win/ThreadImpl.cpp
+@@ -0,0 +1,207 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include
++
++
++void CThread::Create(bool bAutoDelete, unsigned stacksize)
++{
++ if (m_ThreadId != 0)
++ {
++ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__);
++ exit(1);
++ }
++ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
++ m_iLastUsage = 0;
++ m_fLastUsage = 0.0f;
++ m_bAutoDelete = bAutoDelete;
++ m_bStop = false;
++ m_StopEvent.Reset();
++ m_TermEvent.Reset();
++ m_StartEvent.Reset();
++
++ m_ThreadOpaque.handle = CreateThread(NULL,stacksize, (LPTHREAD_START_ROUTINE)&staticThread, this, 0, &m_ThreadId);
++ if (m_ThreadOpaque.handle == NULL)
++ {
++ CLog::Log(LOGERROR, "%s - fatal error creating thread", __FUNCTION__);
++ }
++}
++
++void CThread::TermHandler()
++{
++ CloseHandle(m_ThreadOpaque.handle);
++ m_ThreadOpaque.handle = NULL;
++}
++
++void CThread::SetThreadInfo()
++{
++ const unsigned int MS_VC_EXCEPTION = 0x406d1388;
++ struct THREADNAME_INFO
++ {
++ DWORD dwType; // must be 0x1000
++ LPCSTR szName; // pointer to name (in same addr space)
++ DWORD dwThreadID; // thread ID (-1 caller thread)
++ DWORD dwFlags; // reserved for future use, most be zero
++ } info;
++
++ info.dwType = 0x1000;
++ info.szName = m_ThreadName.c_str();
++ info.dwThreadID = m_ThreadId;
++ info.dwFlags = 0;
++
++ try
++ {
++ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
++ }
++ catch(...)
++ {
++ }
++}
++
++ThreadIdentifier CThread::GetCurrentThreadId()
++{
++ return ::GetCurrentThreadId();
++}
++
++bool CThread::IsCurrentThread(const ThreadIdentifier tid)
++{
++ return (::GetCurrentThreadId() == tid);
++}
++
++int CThread::GetMinPriority(void)
++{
++ return(THREAD_PRIORITY_IDLE);
++}
++
++int CThread::GetMaxPriority(void)
++{
++ return(THREAD_PRIORITY_HIGHEST);
++}
++
++int CThread::GetNormalPriority(void)
++{
++ return(THREAD_PRIORITY_NORMAL);
++}
++
++int CThread::GetSchedRRPriority(void)
++{
++ return GetNormalPriority();
++}
++
++bool CThread::SetPriority(const int iPriority)
++{
++ bool bReturn = false;
++
++ CSingleLock lock(m_CriticalSection);
++ if (m_ThreadOpaque.handle)
++ {
++ bReturn = SetThreadPriority(m_ThreadOpaque.handle, iPriority) == TRUE;
++ }
++
++ return bReturn;
++}
++
++int CThread::GetPriority()
++{
++ CSingleLock lock(m_CriticalSection);
++
++ int iReturn = THREAD_PRIORITY_NORMAL;
++ if (m_ThreadOpaque.handle)
++ {
++ iReturn = GetThreadPriority(m_ThreadOpaque.handle);
++ }
++ return iReturn;
++}
++
++bool CThread::WaitForThreadExit(unsigned int milliseconds)
++{
++ bool bReturn = true;
++
++ CSingleLock lock(m_CriticalSection);
++ if (m_ThreadId && m_ThreadOpaque.handle != NULL)
++ {
++ // boost priority of thread we are waiting on to same as caller
++ int callee = GetThreadPriority(m_ThreadOpaque.handle);
++ int caller = GetThreadPriority(GetCurrentThread());
++ if(caller > callee)
++ SetThreadPriority(m_ThreadOpaque.handle, caller);
++
++ lock.Leave();
++ bReturn = m_TermEvent.WaitMSec(milliseconds);
++ lock.Enter();
++
++ // restore thread priority if thread hasn't exited
++ if(caller > callee && m_ThreadOpaque.handle)
++ SetThreadPriority(m_ThreadOpaque.handle, callee);
++ }
++ return bReturn;
++}
++
++int64_t CThread::GetAbsoluteUsage()
++{
++ CSingleLock lock(m_CriticalSection);
++
++ if (!m_ThreadOpaque.handle)
++ return 0;
++
++ uint64_t time = 0;
++ FILETIME CreationTime, ExitTime, UserTime, KernelTime;
++ if( GetThreadTimes(m_ThreadOpaque.handle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
++ {
++ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
++ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
++ }
++ return time;
++}
++
++float CThread::GetRelativeUsage()
++{
++ unsigned int iTime = XbmcThreads::SystemClockMillis();
++ iTime *= 10000; // convert into 100ns tics
++
++ // only update every 1 second
++ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
++
++ int64_t iUsage = GetAbsoluteUsage();
++
++ if (m_iLastUsage > 0 && m_iLastTime > 0)
++ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
++
++ m_iLastUsage = iUsage;
++ m_iLastTime = iTime;
++
++ return m_fLastUsage;
++}
++
++int64_t CThread::GetCurrentThreadUsage()
++{
++ HANDLE h = GetCurrentThread();
++
++ uint64_t time = 0;
++ FILETIME CreationTime, ExitTime, UserTime, KernelTime;
++ if( GetThreadTimes(h, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
++ {
++ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
++ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
++ }
++ return time;
++}
++
+diff --git a/xbmc/threads/platform/win/ThreadImpl.h b/xbmc/threads/platform/win/ThreadImpl.h
+new file mode 100644
+index 0000000..ea9a0db
+--- /dev/null
++++ b/xbmc/threads/platform/win/ThreadImpl.h
+@@ -0,0 +1,40 @@
++/*
++* Copyright (C) 2005-2011 Team XBMC
++* http://www.xbmc.org
++*
++* This Program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by
++* the Free Software Foundation; either version 2, or (at your option)
++* any later version.
++*
++* This Program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with XBMC; see the file COPYING. If not, write to
++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++* http://www.gnu.org/copyleft/gpl.html
++*
++*/
++
++#pragma once
++
++#include
++
++
++struct threadOpaque
++{
++ HANDLE handle;
++};
++
++typedef DWORD ThreadIdentifier;
++typedef threadOpaque ThreadOpaque;
++typedef DWORD THREADFUNC;
++
++namespace XbmcThreads
++{
++ inline static void ThreadSleep(unsigned int millis) { Sleep(millis); }
++}
++
+diff --git a/xbmc/utils/AlarmClock.cpp b/xbmc/utils/AlarmClock.cpp
+index 0f61171..75af866 100644
+--- a/xbmc/utils/AlarmClock.cpp
++++ b/xbmc/utils/AlarmClock.cpp
+@@ -28,7 +28,7 @@
+
+ using namespace std;
+
+-CAlarmClock::CAlarmClock() : m_bIsRunning(false)
++CAlarmClock::CAlarmClock() : CThread("CAlarmClock"), m_bIsRunning(false)
+ {
+ }
+
+diff --git a/xbmc/utils/AsyncFileCopy.cpp b/xbmc/utils/AsyncFileCopy.cpp
+index e9b7bc0..44e7043 100644
+--- a/xbmc/utils/AsyncFileCopy.cpp
++++ b/xbmc/utils/AsyncFileCopy.cpp
+@@ -26,7 +26,7 @@
+ #include "log.h"
+ #include "utils/TimeUtils.h"
+
+-CAsyncFileCopy::CAsyncFileCopy()
++CAsyncFileCopy::CAsyncFileCopy() : CThread("CAsyncFileCopy")
+ {
+ m_cancelled = false;
+ m_succeeded = false;
+diff --git a/xbmc/utils/DownloadQueue.cpp b/xbmc/utils/DownloadQueue.cpp
+index 4101090..0210241 100644
+--- a/xbmc/utils/DownloadQueue.cpp
++++ b/xbmc/utils/DownloadQueue.cpp
+@@ -32,7 +32,7 @@ using namespace XFILE;
+
+ WORD CDownloadQueue::m_wNextQueueId = 0;
+
+-CDownloadQueue::CDownloadQueue(void) : CThread()
++CDownloadQueue::CDownloadQueue(void) : CThread("CDownloadQueue")
+ {
+ m_bStop = false;
+ m_wQueueId = m_wNextQueueId++;
+diff --git a/xbmc/utils/DownloadQueue.h b/xbmc/utils/DownloadQueue.h
+index c314792..543a825 100644
+--- a/xbmc/utils/DownloadQueue.h
++++ b/xbmc/utils/DownloadQueue.h
+@@ -26,6 +26,8 @@
+ #include "threads/CriticalSection.h"
+ #include "StdString.h"
+
++#include "system.h"
++
+ struct TICKET
+ {
+ TICKET(WORD aQueueId, DWORD aItemId)
+diff --git a/xbmc/utils/DownloadQueueManager.h b/xbmc/utils/DownloadQueueManager.h
+index 3fb0d9f..9bda3ea 100644
+--- a/xbmc/utils/DownloadQueueManager.h
++++ b/xbmc/utils/DownloadQueueManager.h
+@@ -22,6 +22,7 @@
+ */
+
+ #include "DownloadQueue.h"
++#include "system.h"
+
+ #define MAX_DOWNLOAD_QUEUES 3
+
+diff --git a/xbmc/utils/JobManager.cpp b/xbmc/utils/JobManager.cpp
+index dd7b28d..07c9502 100644
+--- a/xbmc/utils/JobManager.cpp
++++ b/xbmc/utils/JobManager.cpp
+@@ -23,6 +23,9 @@
+ #include
+ #include "threads/SingleLock.h"
+
++#include "system.h"
++
++
+ using namespace std;
+
+ bool CJob::ShouldCancel(unsigned int progress, unsigned int total) const
+diff --git a/xbmc/utils/LCD.h b/xbmc/utils/LCD.h
+index 7892d64..6b45008 100644
+--- a/xbmc/utils/LCD.h
++++ b/xbmc/utils/LCD.h
+@@ -66,8 +66,9 @@ public:
+ void LoadSkin(const CStdString &xmlFile);
+ void Reset();
+ void Render(LCD_MODE mode);
+- ILCD() : m_disableOnPlay(DISABLE_ON_PLAY_NONE),
+- m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {}
++ ILCD() : CThread("ILCD"),
++ m_disableOnPlay(DISABLE_ON_PLAY_NONE),
++ m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {}
+ protected:
+ virtual void Process() = 0;
+ void StringToLCDCharSet(CStdString& strText);
+diff --git a/xbmc/utils/RssReader.cpp b/xbmc/utils/RssReader.cpp
+index 18fcdb4..fff6f5e 100644
+--- a/xbmc/utils/RssReader.cpp
++++ b/xbmc/utils/RssReader.cpp
+@@ -44,7 +44,7 @@ using namespace XFILE;
+ // Construction/Destruction
+ //////////////////////////////////////////////////////////////////////
+
+-CRssReader::CRssReader() : CThread()
++CRssReader::CRssReader() : CThread("CRssReader")
+ {
+ m_pObserver = NULL;
+ m_spacesBetweenFeeds = 0;
+diff --git a/xbmc/utils/RssReader.h b/xbmc/utils/RssReader.h
+index f94e2be..d202b37 100644
+--- a/xbmc/utils/RssReader.h
++++ b/xbmc/utils/RssReader.h
+@@ -39,6 +39,9 @@
+
+ #include "tinyXML/tinyxml.h"
+
++#include "system.h"
++
++
+ #define RSS_COLOR_BODY 0
+ #define RSS_COLOR_HEADLINE 1
+ #define RSS_COLOR_CHANNEL 2
+diff --git a/xbmc/utils/Splash.cpp b/xbmc/utils/Splash.cpp
+index 58093b0..a53c90e 100644
+--- a/xbmc/utils/Splash.cpp
++++ b/xbmc/utils/Splash.cpp
+@@ -31,7 +31,7 @@
+
+ using namespace XFILE;
+
+-CSplash::CSplash(const CStdString& imageName)
++CSplash::CSplash(const CStdString& imageName) : CThread("CSplash")
+ {
+ m_ImageName = imageName;
+ fade = 0.5;
+@@ -139,5 +139,5 @@ void CSplash::Stop()
+
+ bool CSplash::IsRunning()
+ {
+- return (m_ThreadHandle != NULL);
++ return (IsRunning());
+ }
+diff --git a/xbmc/utils/TuxBoxUtil.cpp b/xbmc/utils/TuxBoxUtil.cpp
+index c15b634..ab5a5ce 100644
+--- a/xbmc/utils/TuxBoxUtil.cpp
++++ b/xbmc/utils/TuxBoxUtil.cpp
+@@ -48,7 +48,7 @@ using namespace std;
+ CTuxBoxUtil g_tuxbox;
+ CTuxBoxService g_tuxboxService;
+
+-CTuxBoxService::CTuxBoxService()
++CTuxBoxService::CTuxBoxService() : CThread("CTuxBoxService")
+ {
+ }
+ CTuxBoxService::~CTuxBoxService()
+diff --git a/xbmc/video/VideoInfoDownloader.cpp b/xbmc/video/VideoInfoDownloader.cpp
+index 3185d2b..5a46034 100644
+--- a/xbmc/video/VideoInfoDownloader.cpp
++++ b/xbmc/video/VideoInfoDownloader.cpp
+@@ -116,7 +116,7 @@ int CVideoInfoDownloader::FindMovie(const CStdString &strMovie,
+ m_state = FIND_MOVIE;
+ m_strMovie = strMovie;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (m_state != DO_NOTHING)
+@@ -160,7 +160,7 @@ bool CVideoInfoDownloader::GetDetails(const CScraperUrl &url,
+ { // threaded version
+ m_state = GET_DETAILS;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (!m_found)
+@@ -195,7 +195,7 @@ bool CVideoInfoDownloader::GetEpisodeDetails(const CScraperUrl &url,
+ { // threaded version
+ m_state = GET_EPISODE_DETAILS;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (!m_found)
+@@ -230,7 +230,7 @@ bool CVideoInfoDownloader::GetEpisodeList(const CScraperUrl& url,
+ { // threaded version
+ m_state = GET_EPISODE_LIST;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (!m_found)
+diff --git a/xbmc/video/VideoInfoDownloader.h b/xbmc/video/VideoInfoDownloader.h
+index b91477d..8a05568 100644
+--- a/xbmc/video/VideoInfoDownloader.h
++++ b/xbmc/video/VideoInfoDownloader.h
+@@ -42,7 +42,7 @@ typedef std::vector MOVIELIST;
+ class CVideoInfoDownloader : public CThread
+ {
+ public:
+- CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : m_info(scraper) {}
++ CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : CThread("CVideoInfoDownloader"), m_info(scraper) {}
+ virtual ~CVideoInfoDownloader() {}
+
+ // threaded lookup functions
+diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp
+index 4534aa1..c245679 100644
+--- a/xbmc/video/VideoInfoScanner.cpp
++++ b/xbmc/video/VideoInfoScanner.cpp
+@@ -54,7 +54,7 @@ using namespace ADDON;
+ namespace VIDEO
+ {
+
+- CVideoInfoScanner::CVideoInfoScanner()
++ CVideoInfoScanner::CVideoInfoScanner() : CThread("CVideoInfoScanner")
+ {
+ m_bRunning = false;
+ m_pObserver = NULL;
+diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp
+index 83fabfe..b5c8154 100644
+--- a/xbmc/video/VideoReferenceClock.cpp
++++ b/xbmc/video/VideoReferenceClock.cpp
+@@ -30,6 +30,7 @@
+ #if defined(HAS_GLX) && defined(HAS_XRANDR)
+ #include
+ #include
++ #include "windowing/WindowingFactory.h"
+ #define NVSETTINGSCMD "nvidia-settings -nt -q RefreshRate3"
+ #elif defined(__APPLE__) && !defined(__arm__)
+ #include
+@@ -106,7 +107,7 @@ using namespace std;
+
+ #endif
+
+-CVideoReferenceClock::CVideoReferenceClock()
++CVideoReferenceClock::CVideoReferenceClock() : CThread("CVideoReferenceClock")
+ {
+ m_SystemFrequency = CurrentHostFrequency();
+ m_ClockSpeed = 1.0;
+@@ -160,6 +161,8 @@ void CVideoReferenceClock::Process()
+ m_RefreshChanged = 0;
+ m_Started.Set();
+
++ SetPriority(1);
++
+ if (SetupSuccess)
+ {
+ m_UseVblank = true; //tell other threads we're using vblank as clock
+@@ -228,6 +231,8 @@ bool CVideoReferenceClock::SetupGLX()
+ m_vInfo = NULL;
+ m_Context = NULL;
+ m_Window = 0;
++ m_pixmap = None;
++ m_glPixmap = None;
+
+ CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setting up GLX");
+
+@@ -267,6 +272,14 @@ bool CVideoReferenceClock::SetupGLX()
+ return false;
+ }
+
++ CStdString Vendor = g_Windowing.GetRenderVendor();
++ Vendor.ToLower();
++ if (Vendor.compare(0, 3, "ati") == 0)
++ {
++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: GL_VENDOR: %s, using ati workaround", Vendor.c_str());
++ m_bIsATI = true;
++ }
++
+ m_vInfo = glXChooseVisual(m_Dpy, DefaultScreen(m_Dpy), singleBufferAttributes);
+ if (!m_vInfo)
+ {
+@@ -274,13 +287,26 @@ bool CVideoReferenceClock::SetupGLX()
+ return false;
+ }
+
+- Swa.border_pixel = 0;
+- Swa.event_mask = StructureNotifyMask;
+- Swa.colormap = XCreateColormap(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), m_vInfo->visual, AllocNone );
+- SwaMask = CWBorderPixel | CWColormap | CWEventMask;
++ if (!m_bIsATI)
++ {
++ Swa.border_pixel = 0;
++ Swa.event_mask = StructureNotifyMask;
++ Swa.colormap = XCreateColormap(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), m_vInfo->visual, AllocNone );
++ SwaMask = CWBorderPixel | CWColormap | CWEventMask;
+
+- m_Window = XCreateWindow(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), 0, 0, 256, 256, 0,
++ m_Window = XCreateWindow(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), 0, 0, 256, 256, 0,
+ m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa);
++ }
++ else
++ {
++ m_pixmap = XCreatePixmap(m_Dpy, DefaultRootWindow(m_Dpy), 256, 256, m_vInfo->depth);
++ if (!m_pixmap)
++ {
++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: unable to create pixmap");
++ return false;
++ }
++ m_glPixmap = glXCreateGLXPixmap(m_Dpy, m_vInfo, m_pixmap);
++ }
+
+ m_Context = glXCreateContext(m_Dpy, m_vInfo, NULL, True);
+ if (!m_Context)
+@@ -289,25 +315,32 @@ bool CVideoReferenceClock::SetupGLX()
+ return false;
+ }
+
+- ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context);
++ if (!m_bIsATI)
++ ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context);
++ else
++ ReturnV = glXMakeCurrent(m_Dpy, m_glPixmap, m_Context);
++
+ if (ReturnV != True)
+ {
+ CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV);
+ return false;
+ }
+
+- m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI");
+- if (!m_glXWaitVideoSyncSGI)
++ if (!m_bIsATI)
+ {
+- CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI not found");
+- return false;
+- }
++ m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI");
++ if (!m_glXWaitVideoSyncSGI)
++ {
++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI not found");
++ return false;
++ }
+
+- ReturnV = m_glXWaitVideoSyncSGI(2, 0, &GlxTest);
+- if (ReturnV)
+- {
+- CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV);
+- return false;
++ ReturnV = m_glXWaitVideoSyncSGI(2, 0, &GlxTest);
++ if (ReturnV)
++ {
++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV);
++ return false;
++ }
+ }
+
+ m_glXGetVideoSyncSGI = (int (*)(unsigned int*))glXGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI");
+@@ -479,19 +512,6 @@ void CVideoReferenceClock::CleanupGLX()
+ {
+ CLog::Log(LOGDEBUG, "CVideoReferenceClock: Cleaning up GLX");
+
+- bool AtiWorkaround = false;
+- const char* VendorPtr = (const char*)glGetString(GL_VENDOR);
+- if (VendorPtr)
+- {
+- CStdString Vendor = VendorPtr;
+- Vendor.ToLower();
+- if (Vendor.compare(0, 3, "ati") == 0)
+- {
+- CLog::Log(LOGDEBUG, "CVideoReferenceClock: GL_VENDOR: %s, using ati dpy workaround", VendorPtr);
+- AtiWorkaround = true;
+- }
+- }
+-
+ if (m_vInfo)
+ {
+ XFree(m_vInfo);
+@@ -508,9 +528,18 @@ void CVideoReferenceClock::CleanupGLX()
+ XDestroyWindow(m_Dpy, m_Window);
+ m_Window = 0;
+ }
++ if (m_glPixmap)
++ {
++ glXDestroyPixmap(m_Dpy, m_glPixmap);
++ m_glPixmap = None;
++ }
++ if (m_pixmap)
++ {
++ XFreePixmap(m_Dpy, m_pixmap);
++ m_pixmap = None;
++ }
+
+- //ati saves the Display* in their libGL, if we close it here, we crash
+- if (m_Dpy && !AtiWorkaround)
++ if (m_Dpy)
+ {
+ XCloseDisplay(m_Dpy);
+ m_Dpy = NULL;
+@@ -532,10 +561,55 @@ void CVideoReferenceClock::RunGLX()
+ m_glXGetVideoSyncSGI(&VblankCount);
+ PrevVblankCount = VblankCount;
+
++ int precision = 1;
++ int proximity;
++ uint64_t lastVblankTime = CurrentHostCounter();
++ int sleepTime, correction;
++
+ while(!m_bStop)
+ {
+ //wait for the next vblank
+- ReturnV = m_glXWaitVideoSyncSGI(2, (VblankCount + 1) % 2, &VblankCount);
++ if (!m_bIsATI)
++ ReturnV = m_glXWaitVideoSyncSGI(2, (VblankCount + 1) % 2, &VblankCount);
++ else
++ {
++ proximity = 0;
++
++ // calculate sleep time in micro secs
++ // we start with 10% of interval multiplied with precision
++ sleepTime = m_SystemFrequency / m_RefreshRate / 10000LL * precision;
++
++ // correct sleepTime
++ correction = (CurrentHostCounter() - lastVblankTime) / m_SystemFrequency * 1000000LL;
++ if (sleepTime > correction)
++ sleepTime -= correction;
++ usleep(sleepTime);
++ m_glXGetVideoSyncSGI(&VblankCount);
++ if (VblankCount == PrevVblankCount)
++ {
++ usleep(sleepTime/2);
++ m_glXGetVideoSyncSGI(&VblankCount);
++ while (VblankCount == PrevVblankCount)
++ {
++ usleep(sleepTime/20);
++ m_glXGetVideoSyncSGI(&VblankCount);
++ proximity++;
++ }
++ }
++ // we might have waited too long, reduce sleep time
++ else if (precision > 1)
++ precision--;
++
++ // lets try to increase precision in order to reduce number
++ // of required steps
++ if (proximity > 4 && precision < 6)
++ precision++;
++
++ lastVblankTime = CurrentHostCounter();
++
++ ReturnV = 0;
++ }
++
+ m_glXGetVideoSyncSGI(&VblankCount); //the vblank count returned by glXWaitVideoSyncSGI is not always correct
+ Now = CurrentHostCounter(); //get the timestamp of this vblank
+
+@@ -554,13 +628,14 @@ void CVideoReferenceClock::RunGLX()
+ SingleLock.Leave();
+ SendVblankSignal();
+ UpdateRefreshrate();
+-
+ IsReset = false;
+ }
+ else
+ {
+ CLog::Log(LOGDEBUG, "CVideoReferenceClock: Vblank counter has reset");
+
++ precision = 1;
++
+ //only try reattaching once
+ if (IsReset)
+ return;
+diff --git a/xbmc/video/VideoReferenceClock.h b/xbmc/video/VideoReferenceClock.h
+index 9699cd4..465d313 100644
+--- a/xbmc/video/VideoReferenceClock.h
++++ b/xbmc/video/VideoReferenceClock.h
+@@ -119,9 +119,12 @@ class CVideoReferenceClock : public CThread
+ XVisualInfo *m_vInfo;
+ Window m_Window;
+ GLXContext m_Context;
++ Pixmap m_pixmap;
++ GLXPixmap m_glPixmap;
+ int m_RREventBase;
+
+ bool m_UseNvSettings;
++ bool m_bIsATI;
+
+ #elif defined(_WIN32) && defined(HAS_DX)
+ bool SetupD3D();
+diff --git a/xbmc/win32/PlatformDefs.h b/xbmc/win32/PlatformDefs.h
+index 57cab8f..74e3d53 100644
+--- a/xbmc/win32/PlatformDefs.h
++++ b/xbmc/win32/PlatformDefs.h
+@@ -33,7 +33,6 @@ typedef __int64 off64_t;
+ typedef __int64 fpos64_t;
+ typedef __int64 __off64_t;
+ typedef long __off_t;
+-typedef unsigned long ThreadIdentifier;
+
+ #define ssize_t int
+
+diff --git a/xbmc/win32/WindowHelper.cpp b/xbmc/win32/WindowHelper.cpp
+index 56856ac..8aa7da9 100644
+--- a/xbmc/win32/WindowHelper.cpp
++++ b/xbmc/win32/WindowHelper.cpp
+@@ -28,7 +28,7 @@ using namespace std;
+
+ CWHelper g_windowHelper;
+
+-CWHelper::CWHelper(void)
++CWHelper::CWHelper(void) : CThread("CWHelper")
+ {
+ m_hwnd = NULL;
+ m_hProcess = NULL;
+diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
+index 62cf554..931700b 100644
+--- a/xbmc/windowing/X11/WinSystemX11.cpp
++++ b/xbmc/windowing/X11/WinSystemX11.cpp
+@@ -35,6 +35,8 @@
+ #include
+ #include "cores/VideoRenderers/RenderManager.h"
+ #include "utils/TimeUtils.h"
++#include "settings/AdvancedSettings.h"
++#include "settings/GUISettings.h"
+
+ #if defined(HAS_XRANDR)
+ #include
+@@ -52,6 +54,7 @@ CWinSystemX11::CWinSystemX11() : CWinSystemBase()
+ m_wmWindow = 0;
+ m_bWasFullScreenBeforeMinimize = false;
+ m_dpyLostTime = 0;
++ m_internalModeSwitch = false;
+ }
+
+ CWinSystemX11::~CWinSystemX11()
+@@ -176,6 +179,45 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
+ return false;
+ }
+
++void CWinSystemX11::RefreshWindow()
++{
++ // save current mode if this is not an internal request
++ if (!m_internalModeSwitch)
++ {
++ CLog::Log(LOGNOTICE, "CWinSystemX11::RefreshWindow - external or initial xrandr event");
++ m_xrandrOut = g_xrandr.GetCurrentOutput();
++ m_xrandrMode = g_xrandr.GetCurrentMode(m_xrandrOut.name);
++ }
++ m_internalModeSwitch = false;
++
++ g_xrandr.Query(true);
++ XOutput out = g_xrandr.GetCurrentOutput();
++ XMode mode = g_xrandr.GetCurrentMode(out.name);
++
++ RESOLUTION_INFO res;
++ unsigned int i;
++ bool found(false);
++ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i)
++ {
++ if (g_settings.m_ResInfo[i].strId == mode.id)
++ {
++ found = true;
++ break;
++ }
++ }
++
++ if (!found)
++ {
++ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution");
++ return;
++ }
++
++ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true);
++ g_guiSettings.SetInt("window.width", mode.w);
++ g_guiSettings.SetInt("window.height", mode.h);
++ g_settings.Save();
++}
++
+ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
+ {
+ m_nWidth = res.iWidth;
+@@ -191,13 +233,32 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
+ mode.hz = res.fRefreshRate;
+ mode.id = res.strId;
+
+- if(m_bFullScreen)
++ XOutput currout = g_xrandr.GetCurrentOutput();
++ XMode currmode = g_xrandr.GetCurrentMode(currout.name);
++
++ if (m_xrandrOut.name.empty())
++ {
++ m_xrandrOut = currout;
++ m_xrandrMode = currmode;
++ }
++
++ if(!m_bFullScreen)
+ {
++ // reset to mode we had before internal mode switch
++ out = m_xrandrOut;
++ mode = m_xrandrMode;
++ }
++
++ // only call xrandr if mode changes
++ if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h ||
++ currmode.hz != mode.hz || currmode.id != mode.id)
++ {
++ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr");
+ OnLostDevice();
++ m_internalModeSwitch = true;
+ g_xrandr.SetMode(out, mode);
+ }
+- else
+- g_xrandr.RestoreState();
++
+ #endif
+
+ int options = SDL_OPENGL;
+@@ -491,6 +552,7 @@ void CWinSystemX11::CheckDisplayEvents()
+ if (bGotEvent || bTimeout)
+ {
+ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
++ RefreshWindow();
+
+ CSingleLock lock(m_resourceSection);
+
+diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
+index 5b941be..be59c5c 100644
+--- a/xbmc/windowing/X11/WinSystemX11.h
++++ b/xbmc/windowing/X11/WinSystemX11.h
+@@ -27,6 +27,7 @@
+ #include "utils/Stopwatch.h"
+ #include
+ #include "threads/CriticalSection.h"
++#include "XRandR.h"
+
+ class IDispResource;
+
+@@ -60,6 +61,7 @@ public:
+ // Local to WinSystemX11 only
+ Display* GetDisplay() { return m_dpy; }
+ GLXWindow GetWindow() { return m_glWindow; }
++ void RefreshWindow();
+
+ protected:
+ bool RefreshGlxContext();
+@@ -76,6 +78,9 @@ protected:
+ CCriticalSection m_resourceSection;
+ std::vector m_resources;
+ uint64_t m_dpyLostTime;
++ XOutput m_xrandrOut;
++ XMode m_xrandrMode;
++ bool m_internalModeSwitch;
+
+ private:
+ bool IsSuitableVisual(XVisualInfo *vInfo);
diff --git a/tools/mkpkg/mkpkg_xbmc-rpi b/tools/mkpkg/mkpkg_xbmc-rpi
new file mode 100755
index 0000000000..1785382b2c
--- /dev/null
+++ b/tools/mkpkg/mkpkg_xbmc-rpi
@@ -0,0 +1,80 @@
+#!/bin/sh
+################################################################################
+# This file is part of OpenELEC - http://www.openelec.tv
+# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv)
+#
+# This Program is free software; you can redistribute 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.
+#
+# This Program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with OpenELEC.tv; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+# http://www.gnu.org/copyleft/gpl.html
+################################################################################
+
+PKG_NAME="xbmc-rpi"
+GIT_REPO="-b master git@github.com:xbmc/xbmc-rbp.git"
+DEST_DIR="$PKG_NAME"
+
+echo "getting sources..."
+ if [ ! -d $DEST_DIR-latest ]; then
+ git clone $GIT_REPO $DEST_DIR-latest
+ fi
+
+ cd $DEST_DIR-latest
+ git pull
+
+echo "getting version..."
+ GIT_REV=`git log -n1 --format=%h`
+ echo $GIT_REV
+ cd ..
+
+echo "copying sources..."
+ rm -rf $PKG_NAME-$GIT_REV
+ cp -R $DEST_DIR-latest $PKG_NAME-$GIT_REV
+ echo "$GIT_REV" > $PKG_NAME-$GIT_REV/git.version
+
+echo "cleaning sources..."
+ rm -rf $PKG_NAME-$GIT_REV/.git
+
+echo "seperating theme..."
+ rm -rf $PKG_NAME-theme-Confluence-$GIT_REV
+ mv $PKG_NAME-$GIT_REV/addons/skin.confluence $PKG_NAME-theme-Confluence-$GIT_REV
+# rm -rf $PKG_NAME-theme-Touched-$GIT_REV
+# mv $PKG_NAME-$GIT_REV/addons/skin.touched $PKG_NAME-theme-Touched-$GIT_REV
+
+echo "cleaning sources..."
+ rm -rf $PKG_NAME-$GIT_REV/visualisations
+ rm -rf $PKG_NAME-$GIT_REV/lib/libSDL-*
+ rm -rf $PKG_NAME-$GIT_REV/lib/libcurl-*
+ rm -rf $PKG_NAME-$GIT_REV/project
+
+ for i in "Changelog" "Fake\ Episode\ Maker" "MingwBuildEnvironment" \
+ "PackageMaker" "Translator" "XBMCLive" "XprPack" \
+ "HardwareConfigure" "Mach5" "osx" "UpdateThumbs.py" "XBMCTex"; do
+ rm -rf $PKG_NAME-$GIT_REV/tools/$i
+ done
+
+ for i in dll a lib so bat; do
+ find $PKG_NAME-$GIT_REV -name *.$i -exec rm -rf {} ";"
+ done
+
+ # bundled win32 binaries
+ rm -r $PKG_NAME-$GIT_REV/xbmc/visualizations/XBMCProjectM/win32
+
+echo "packing sources..."
+ tar cvJf $PKG_NAME-$GIT_REV.tar.xz $PKG_NAME-$GIT_REV
+ tar cvJf $PKG_NAME-theme-Confluence-$GIT_REV.tar.xz $PKG_NAME-theme-Confluence-$GIT_REV
+# tar cvJf $PKG_NAME-theme-Touched-$GIT_REV.tar.xz $PKG_NAME-theme-Touched-$GIT_REV
+
+echo "remove temporary sourcedir..."
+ rm -rf $PKG_NAME-$GIT_REV
+ rm -rf $PKG_NAME-theme-Confluence-$GIT_REV
+# rm -rf $PKG_NAME-theme-Touched-$GIT_REV