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 ++ clear ++ 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_DVD ++ KEY_MENU ++ 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