From eb9ce9a0ac072df0931dc9cec6f96a7f01d06a6f Mon Sep 17 00:00:00 2001 From: Britney Fransen Date: Thu, 12 Apr 2012 17:13:23 -0500 Subject: linhes-scripts: add diskspace.sh and cron job to warn user about low disk space on /. --- abs/core/linhes-scripts/PKGBUILD | 10 ++++- abs/core/linhes-scripts/diskspace | 2 + abs/core/linhes-scripts/diskspace.sh | 81 ++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100755 abs/core/linhes-scripts/diskspace create mode 100755 abs/core/linhes-scripts/diskspace.sh diff --git a/abs/core/linhes-scripts/PKGBUILD b/abs/core/linhes-scripts/PKGBUILD index 0be8d93..bc4052d 100644 --- a/abs/core/linhes-scripts/PKGBUILD +++ b/abs/core/linhes-scripts/PKGBUILD @@ -3,7 +3,7 @@ pkgname=linhes-scripts pkgver=7 -pkgrel=31 +pkgrel=32 pkgdesc="Various scripts that help to make LinHES, LinHES." arch=('i686' 'x86_64') license=('GPL2') @@ -49,6 +49,8 @@ upgrade_linhes_script.sh find_orphans.py acl_fix_fstab.py stop_xss.sh +diskspace +diskspace.sh ) build() { @@ -63,6 +65,8 @@ build() { cp run-limit-mythcommflag ${pkgdir}/etc/sv/limit-mythcommflag/run mkdir -p ${pkgdir}/etc/logrotate.d/ cp pause_mythcommflag ${pkgdir}/etc/logrotate.d/ + mkdir -p ${pkgdir}/etc/cron.tenminutes/ + cp diskspace ${pkgdir}/etc/cron.tenminutes/ } md5sums=('f56985b2d602e11dc1e10d3e7848b2a5' '10ad1a4da669adccd01e0be6e5e4a3ed' @@ -101,4 +105,6 @@ md5sums=('f56985b2d602e11dc1e10d3e7848b2a5' '4b8671376fad6d76874508434d42fbfd' 'd8838461af9d446a1fd7e7883fdc75d1' 'cc9cdabcdfc969c2829b58c0e513488c' - 'acb72dfeda6f957bfdf4113a04fb91c0') + 'acb72dfeda6f957bfdf4113a04fb91c0' + '84492954db16740f949d795b74383189' + '68e3e87571f3b0fa4a48a10df50dc220') diff --git a/abs/core/linhes-scripts/diskspace b/abs/core/linhes-scripts/diskspace new file mode 100755 index 0000000..ab3c91b --- /dev/null +++ b/abs/core/linhes-scripts/diskspace @@ -0,0 +1,2 @@ +#!/bin/bash +/usr/bin/nice -n19 /usr/LH/bin/diskspace.sh -osd diff --git a/abs/core/linhes-scripts/diskspace.sh b/abs/core/linhes-scripts/diskspace.sh new file mode 100755 index 0000000..2173c6e --- /dev/null +++ b/abs/core/linhes-scripts/diskspace.sh @@ -0,0 +1,81 @@ +#!/bin/sh +### Monitor free disk space +# Display alert if the free percentage of space is >= $ALERT + +# +# Static Config Variables +# +ALERT=90 # free space percentage to trigger an alert + +# +# Static Binary Paths +# +DF='/bin/df' +GREP='/bin/grep' +AWK='/bin/awk' +CUT='/bin/cut' +HOSTNAME='/bin/hostname' +DATE='/bin/date' +OSD_CAT='/usr/bin/osd_cat' +export DISPLAY=:0.0 +# +# Static System Variables +# +THIS_HOST=`${HOSTNAME}` + +# +# Check CLI Options +# +VERBOSE=false +OSD=false +for ARG in "$@" ; do + case $ARG in + "-v") + VERBOSE=true + ;; + "-osd") + OSD=true + ;; + esac +done + +#---------------------------------------------------------------------------- +. /etc/osd_cat.cfg || { + color=yellow + outline=2 + outlinecolour=black + shadow=0 + shadowcolour=black + font="-adobe-helvetica-bold-*-*-*-34-*-*-*-*-*-*-*" +} +#---------------------------------------------------------------------------- + +[ $VERBOSE = true ] && echo "Checking free disk space on ${THIS_HOST}" +[ $VERBOSE = true ] && echo "Threshold for warning is ${ALERT}%" +[ $VERBOSE = true ] && echo "------------------------------------------------------------------" + +# Dynamic Variables +#DATE_STR=`${DATE} "+%d-%B-%y @ %H%Mhrs"` + +# Call df to find the used percentages. Grep for only local disks (not remote mounts like nfs or smb) +# Pipe the output to awk to get the needed columns, then start a while loop to process each line. +$DF -HPl | $GREP -E "^/dev/" | $AWK '{ print $5 " " $6 " " $1 }' | while read OUTPUT ; do + USED_PCENT=$(echo ${OUTPUT} | $AWK '{ print $1}' | $CUT -d'%' -f1 ) # Used space as a percentage + PARTITION=$(echo ${OUTPUT} | $AWK '{ print $2 }' ) # Mount Point (eg, /home) + DEVICE=$(echo ${OUTPUT} | $AWK '{ print $3 }' ) # Device (eg, /dev/sda1 or LABEL or UUID) + if [ $VERBOSE = true ] ; then + echo -e "Checking device ${DEVICE} which is mounted to ${PARTITION} \t${USED_PCENT}% used" + fi + if [ ${USED_PCENT} -ge $ALERT ]; then + if [ $VERBOSE = true ] ; then + echo "WARNING: ${PARTITION} (${DEVICE}) is ${USED_PCENT}% full on ${THIS_HOST}." + else + echo "WARNING: ${PARTITION} (${DEVICE}) is ${USED_PCENT}% full on ${THIS_HOST}." #| + if [ $OSD = true ] && [ ${PARTITION} = / ]; then + echo "WARNING: The root (${PARTITION}) partition is ${USED_PCENT}% full on ${THIS_HOST}." | $OSD_CAT --pos=top --offset=40 --align=center --delay=10 --color=$color --outline=$outline --outlinecolour=$outlinecolour --shadow=$shadow --shadowcolour=$shadowcolour --font=$font & + fi + fi + fi +done + +exit 0 -- cgit v0.12 From de3a3fdbe9f392b0d6c017e325025aaf44d70a23 Mon Sep 17 00:00:00 2001 From: Britney Fransen Date: Thu, 12 Apr 2012 17:22:58 -0500 Subject: LinHES-system: myth_status.py: add call to diskspace.sh to warn user of full disks. --- abs/core/LinHES-system/PKGBUILD | 4 ++-- abs/core/LinHES-system/myth_status.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/abs/core/LinHES-system/PKGBUILD b/abs/core/LinHES-system/PKGBUILD index d53adee..d2fb0f8 100644 --- a/abs/core/LinHES-system/PKGBUILD +++ b/abs/core/LinHES-system/PKGBUILD @@ -1,6 +1,6 @@ pkgname=LinHES-system pkgver=2 -pkgrel=38 +pkgrel=39 arch=('i686') MVDIR=$startdir/pkg/usr/LH BINDIR=$startdir/pkg/usr/bin @@ -62,7 +62,7 @@ md5sums=('d6a564f3286590875874573107940908' 'abe887472a170bd1a8e6da6a7b7e93e4' '752488eb8bfb672ce0e4c924f7faf3d1' 'ba351b92e69bcaf26a9bf80417b09c3c' - '1d534843cc4e55fe4ce21c3e95e3f766' + 'b41b08ea923d94b90d22f92e291ad9ee' '962a3e9eaba2d1466251b7ab0956705d' 'd03aedeeeda0f5e9c1eb437411c88477' '94ce8f1d5085c0db7b267db8c2e9a3ff' diff --git a/abs/core/LinHES-system/myth_status.py b/abs/core/LinHES-system/myth_status.py index f8222cb..53d64d9 100644 --- a/abs/core/LinHES-system/myth_status.py +++ b/abs/core/LinHES-system/myth_status.py @@ -1,6 +1,6 @@ #!/usr/bin/python2 from MythTV import MythBE,MythDB,MythLog -import datetime,time,sys +import datetime,time,sys,subprocess try: be=MythBE() db = MythDB() @@ -107,5 +107,5 @@ else: ur=formatTD(next_start_diff) print "The next recording starts in:\n %s" %(ur) print "" - - +subprocess.call("/usr/LH/bin/diskspace.sh",shell=True) +print "" -- cgit v0.12 From fadd791ceddc196e958e9a108f26532a0a2d1170 Mon Sep 17 00:00:00 2001 From: Britney Fransen Date: Thu, 12 Apr 2012 19:09:26 -0500 Subject: LinHES-system: firstboot.sh: add fix_lirc_socket; closes #822 --- abs/core/LinHES-system/PKGBUILD | 4 ++-- abs/core/LinHES-system/firstboot.sh | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/abs/core/LinHES-system/PKGBUILD b/abs/core/LinHES-system/PKGBUILD index d2fb0f8..607bda1 100644 --- a/abs/core/LinHES-system/PKGBUILD +++ b/abs/core/LinHES-system/PKGBUILD @@ -1,6 +1,6 @@ pkgname=LinHES-system pkgver=2 -pkgrel=39 +pkgrel=40 arch=('i686') MVDIR=$startdir/pkg/usr/LH BINDIR=$startdir/pkg/usr/bin @@ -55,7 +55,7 @@ md5sums=('d6a564f3286590875874573107940908' 'd1f27cb422010077c841376526fe46ea' '2ef9f945e034119f77d9b6beb17e4fa5' '5c96527397a35519d72c78d6e3c8dbea' - '18a884a73344ff6eb74f63b49745e0f5' + '5e67a8b7ff57ec32d668bce7aab0aa6d' 'dc3eef2a624754e16805d72bbe488b67' 'dc0be354ce77ba2b89868fc29b942c43' '542e670e78d117657f93141e9689f54d' diff --git a/abs/core/LinHES-system/firstboot.sh b/abs/core/LinHES-system/firstboot.sh index 7e2f603..8e3dc57 100755 --- a/abs/core/LinHES-system/firstboot.sh +++ b/abs/core/LinHES-system/firstboot.sh @@ -23,6 +23,26 @@ function try_smolt { } +function fix_lirc_socket { + . /etc/systemconfig + + # Fix LircSocket in mythtv database + SOCKET=`mysql -u mythtv -pmythtv -B --skip-column-names -h "${dbhost}" -D mythconverg -e \ + "SELECT data FROM settings WHERE value = 'LircSocket' AND hostname = '${hostname}';"` + if [ "${SOCKET}" != "/var/run/lirc/lircd" ]; then + mysql -u mythtv -pmythtv -B --skip-column-names -h "${dbhost}" -D mythconverg -e \ + "UPDATE settings SET data = '/var/run/lirc/lircd' WHERE value = 'LircSocket' AND hostname = '${hostname}';" + else + echo ">>>" + echo ">>> ATTENTION! ATTENTION! ATTENTION!" + echo ">>> Unable to connect the the MySQL database to make needed" + echo ">>> changes to the LIRC socket." + echo ">>> LIRC now uses /var/run/lirc/lircd and /dev/lirc is now" + echo ">>> obsolete. Update your MythTV settings to reflect this." + echo ">>>" + fi +} + if [ ! -e /tmp/debug ] then @@ -35,6 +55,7 @@ then fb_status=4 while [ $fb_status != 0 ] do + fix_lirc_socket try_smolt if [ $fb_status != 0 ] then -- cgit v0.12 From 502a19b42d9df3fb3c3e521a37eebd20f9fbd984 Mon Sep 17 00:00:00 2001 From: Britney Fransen Date: Thu, 12 Apr 2012 19:35:27 -0500 Subject: LinHES-system & linhes-scripts: move diskspace to LinHES-system --- abs/core/LinHES-system/PKGBUILD | 17 +++++--- abs/core/LinHES-system/diskspace | 2 + abs/core/LinHES-system/diskspace.sh | 81 ++++++++++++++++++++++++++++++++++++ abs/core/linhes-scripts/PKGBUILD | 10 +---- abs/core/linhes-scripts/diskspace | 2 - abs/core/linhes-scripts/diskspace.sh | 81 ------------------------------------ 6 files changed, 96 insertions(+), 97 deletions(-) create mode 100755 abs/core/LinHES-system/diskspace create mode 100755 abs/core/LinHES-system/diskspace.sh delete mode 100755 abs/core/linhes-scripts/diskspace delete mode 100755 abs/core/linhes-scripts/diskspace.sh diff --git a/abs/core/LinHES-system/PKGBUILD b/abs/core/LinHES-system/PKGBUILD index 607bda1..f8baeaf 100644 --- a/abs/core/LinHES-system/PKGBUILD +++ b/abs/core/LinHES-system/PKGBUILD @@ -1,6 +1,6 @@ pkgname=LinHES-system pkgver=2 -pkgrel=40 +pkgrel=41 arch=('i686') MVDIR=$startdir/pkg/usr/LH BINDIR=$startdir/pkg/usr/bin @@ -11,7 +11,7 @@ backup=(etc/modprobe.d/alsa-base) binfiles="LinHES-start optimize_mythdb.py myth_mtc.py myth_mtc.sh LinHES-run firstboot.sh load-modules-mythvantage.sh - unclutter-toggle.sh tvterm.sh smolt.cron + unclutter-toggle.sh tvterm.sh mythfrontend-start set_windowmanager.sh myth_status.py myth_status.sh xmsg.py install_supplemental_service.sh @@ -19,9 +19,11 @@ binfiles="LinHES-start optimize_mythdb.py lh_system_restore_job lh_system_host_update lh_system_all_host_update - add_storage.py" + add_storage.py + diskspace.sh" -source=(LinHES-session LinHES-profile.sh $binfiles alsa-base myth_mtc.lr) +source=(LinHES-session LinHES-profile.sh $binfiles alsa-base myth_mtc.lr + diskspace smolt.cron) build() { cd $startdir/src @@ -45,6 +47,7 @@ build() { install -m644 -D $startdir/src/alsa-base $startdir/pkg/etc/modprobe.d/alsa-base.conf install -m755 -D $startdir/src/smolt.cron $startdir/pkg/etc/cron.weekly/smolt.cron + install -m755 -D $startdir/src/diskspace $startdir/pkg/etc/cron.tenminutes/diskspace mkdir $startdir/pkg/etc/logrotate.d cp $startdir/myth_mtc.lr $startdir/pkg/etc/logrotate.d } @@ -59,7 +62,6 @@ md5sums=('d6a564f3286590875874573107940908' 'dc3eef2a624754e16805d72bbe488b67' 'dc0be354ce77ba2b89868fc29b942c43' '542e670e78d117657f93141e9689f54d' - 'abe887472a170bd1a8e6da6a7b7e93e4' '752488eb8bfb672ce0e4c924f7faf3d1' 'ba351b92e69bcaf26a9bf80417b09c3c' 'b41b08ea923d94b90d22f92e291ad9ee' @@ -71,5 +73,8 @@ md5sums=('d6a564f3286590875874573107940908' '859a80ddb4c234506379c605114c1343' '47e093e8cfe4b5b96602358e1f540832' '6faeba0aeb38e772121f751cabda8683' + '68e3e87571f3b0fa4a48a10df50dc220' 'eb879fee9603a05d5420d4ce8ed9e450' - 'f1870a9522c79e6b248fcbf81dec3280') + 'f1870a9522c79e6b248fcbf81dec3280' + '84492954db16740f949d795b74383189' + 'abe887472a170bd1a8e6da6a7b7e93e4') diff --git a/abs/core/LinHES-system/diskspace b/abs/core/LinHES-system/diskspace new file mode 100755 index 0000000..ab3c91b --- /dev/null +++ b/abs/core/LinHES-system/diskspace @@ -0,0 +1,2 @@ +#!/bin/bash +/usr/bin/nice -n19 /usr/LH/bin/diskspace.sh -osd diff --git a/abs/core/LinHES-system/diskspace.sh b/abs/core/LinHES-system/diskspace.sh new file mode 100755 index 0000000..2173c6e --- /dev/null +++ b/abs/core/LinHES-system/diskspace.sh @@ -0,0 +1,81 @@ +#!/bin/sh +### Monitor free disk space +# Display alert if the free percentage of space is >= $ALERT + +# +# Static Config Variables +# +ALERT=90 # free space percentage to trigger an alert + +# +# Static Binary Paths +# +DF='/bin/df' +GREP='/bin/grep' +AWK='/bin/awk' +CUT='/bin/cut' +HOSTNAME='/bin/hostname' +DATE='/bin/date' +OSD_CAT='/usr/bin/osd_cat' +export DISPLAY=:0.0 +# +# Static System Variables +# +THIS_HOST=`${HOSTNAME}` + +# +# Check CLI Options +# +VERBOSE=false +OSD=false +for ARG in "$@" ; do + case $ARG in + "-v") + VERBOSE=true + ;; + "-osd") + OSD=true + ;; + esac +done + +#---------------------------------------------------------------------------- +. /etc/osd_cat.cfg || { + color=yellow + outline=2 + outlinecolour=black + shadow=0 + shadowcolour=black + font="-adobe-helvetica-bold-*-*-*-34-*-*-*-*-*-*-*" +} +#---------------------------------------------------------------------------- + +[ $VERBOSE = true ] && echo "Checking free disk space on ${THIS_HOST}" +[ $VERBOSE = true ] && echo "Threshold for warning is ${ALERT}%" +[ $VERBOSE = true ] && echo "------------------------------------------------------------------" + +# Dynamic Variables +#DATE_STR=`${DATE} "+%d-%B-%y @ %H%Mhrs"` + +# Call df to find the used percentages. Grep for only local disks (not remote mounts like nfs or smb) +# Pipe the output to awk to get the needed columns, then start a while loop to process each line. +$DF -HPl | $GREP -E "^/dev/" | $AWK '{ print $5 " " $6 " " $1 }' | while read OUTPUT ; do + USED_PCENT=$(echo ${OUTPUT} | $AWK '{ print $1}' | $CUT -d'%' -f1 ) # Used space as a percentage + PARTITION=$(echo ${OUTPUT} | $AWK '{ print $2 }' ) # Mount Point (eg, /home) + DEVICE=$(echo ${OUTPUT} | $AWK '{ print $3 }' ) # Device (eg, /dev/sda1 or LABEL or UUID) + if [ $VERBOSE = true ] ; then + echo -e "Checking device ${DEVICE} which is mounted to ${PARTITION} \t${USED_PCENT}% used" + fi + if [ ${USED_PCENT} -ge $ALERT ]; then + if [ $VERBOSE = true ] ; then + echo "WARNING: ${PARTITION} (${DEVICE}) is ${USED_PCENT}% full on ${THIS_HOST}." + else + echo "WARNING: ${PARTITION} (${DEVICE}) is ${USED_PCENT}% full on ${THIS_HOST}." #| + if [ $OSD = true ] && [ ${PARTITION} = / ]; then + echo "WARNING: The root (${PARTITION}) partition is ${USED_PCENT}% full on ${THIS_HOST}." | $OSD_CAT --pos=top --offset=40 --align=center --delay=10 --color=$color --outline=$outline --outlinecolour=$outlinecolour --shadow=$shadow --shadowcolour=$shadowcolour --font=$font & + fi + fi + fi +done + +exit 0 diff --git a/abs/core/linhes-scripts/PKGBUILD b/abs/core/linhes-scripts/PKGBUILD index bc4052d..68a02ef 100644 --- a/abs/core/linhes-scripts/PKGBUILD +++ b/abs/core/linhes-scripts/PKGBUILD @@ -3,7 +3,7 @@ pkgname=linhes-scripts pkgver=7 -pkgrel=32 +pkgrel=33 pkgdesc="Various scripts that help to make LinHES, LinHES." arch=('i686' 'x86_64') license=('GPL2') @@ -49,8 +49,6 @@ upgrade_linhes_script.sh find_orphans.py acl_fix_fstab.py stop_xss.sh -diskspace -diskspace.sh ) build() { @@ -65,8 +63,6 @@ build() { cp run-limit-mythcommflag ${pkgdir}/etc/sv/limit-mythcommflag/run mkdir -p ${pkgdir}/etc/logrotate.d/ cp pause_mythcommflag ${pkgdir}/etc/logrotate.d/ - mkdir -p ${pkgdir}/etc/cron.tenminutes/ - cp diskspace ${pkgdir}/etc/cron.tenminutes/ } md5sums=('f56985b2d602e11dc1e10d3e7848b2a5' '10ad1a4da669adccd01e0be6e5e4a3ed' @@ -105,6 +101,4 @@ md5sums=('f56985b2d602e11dc1e10d3e7848b2a5' '4b8671376fad6d76874508434d42fbfd' 'd8838461af9d446a1fd7e7883fdc75d1' 'cc9cdabcdfc969c2829b58c0e513488c' - 'acb72dfeda6f957bfdf4113a04fb91c0' - '84492954db16740f949d795b74383189' - '68e3e87571f3b0fa4a48a10df50dc220') + 'acb72dfeda6f957bfdf4113a04fb91c0') diff --git a/abs/core/linhes-scripts/diskspace b/abs/core/linhes-scripts/diskspace deleted file mode 100755 index ab3c91b..0000000 --- a/abs/core/linhes-scripts/diskspace +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -/usr/bin/nice -n19 /usr/LH/bin/diskspace.sh -osd diff --git a/abs/core/linhes-scripts/diskspace.sh b/abs/core/linhes-scripts/diskspace.sh deleted file mode 100755 index 2173c6e..0000000 --- a/abs/core/linhes-scripts/diskspace.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -### Monitor free disk space -# Display alert if the free percentage of space is >= $ALERT - -# -# Static Config Variables -# -ALERT=90 # free space percentage to trigger an alert - -# -# Static Binary Paths -# -DF='/bin/df' -GREP='/bin/grep' -AWK='/bin/awk' -CUT='/bin/cut' -HOSTNAME='/bin/hostname' -DATE='/bin/date' -OSD_CAT='/usr/bin/osd_cat' -export DISPLAY=:0.0 -# -# Static System Variables -# -THIS_HOST=`${HOSTNAME}` - -# -# Check CLI Options -# -VERBOSE=false -OSD=false -for ARG in "$@" ; do - case $ARG in - "-v") - VERBOSE=true - ;; - "-osd") - OSD=true - ;; - esac -done - -#---------------------------------------------------------------------------- -. /etc/osd_cat.cfg || { - color=yellow - outline=2 - outlinecolour=black - shadow=0 - shadowcolour=black - font="-adobe-helvetica-bold-*-*-*-34-*-*-*-*-*-*-*" -} -#---------------------------------------------------------------------------- - -[ $VERBOSE = true ] && echo "Checking free disk space on ${THIS_HOST}" -[ $VERBOSE = true ] && echo "Threshold for warning is ${ALERT}%" -[ $VERBOSE = true ] && echo "------------------------------------------------------------------" - -# Dynamic Variables -#DATE_STR=`${DATE} "+%d-%B-%y @ %H%Mhrs"` - -# Call df to find the used percentages. Grep for only local disks (not remote mounts like nfs or smb) -# Pipe the output to awk to get the needed columns, then start a while loop to process each line. -$DF -HPl | $GREP -E "^/dev/" | $AWK '{ print $5 " " $6 " " $1 }' | while read OUTPUT ; do - USED_PCENT=$(echo ${OUTPUT} | $AWK '{ print $1}' | $CUT -d'%' -f1 ) # Used space as a percentage - PARTITION=$(echo ${OUTPUT} | $AWK '{ print $2 }' ) # Mount Point (eg, /home) - DEVICE=$(echo ${OUTPUT} | $AWK '{ print $3 }' ) # Device (eg, /dev/sda1 or LABEL or UUID) - if [ $VERBOSE = true ] ; then - echo -e "Checking device ${DEVICE} which is mounted to ${PARTITION} \t${USED_PCENT}% used" - fi - if [ ${USED_PCENT} -ge $ALERT ]; then - if [ $VERBOSE = true ] ; then - echo "WARNING: ${PARTITION} (${DEVICE}) is ${USED_PCENT}% full on ${THIS_HOST}." - else - echo "WARNING: ${PARTITION} (${DEVICE}) is ${USED_PCENT}% full on ${THIS_HOST}." #| - if [ $OSD = true ] && [ ${PARTITION} = / ]; then - echo "WARNING: The root (${PARTITION}) partition is ${USED_PCENT}% full on ${THIS_HOST}." | $OSD_CAT --pos=top --offset=40 --align=center --delay=10 --color=$color --outline=$outline --outlinecolour=$outlinecolour --shadow=$shadow --shadowcolour=$shadowcolour --font=$font & - fi - fi - fi -done - -exit 0 -- cgit v0.12 From 8e721470713e6a5a164f1d7682b0d248cb87b03c Mon Sep 17 00:00:00 2001 From: Michael Hanson Date: Sat, 14 Apr 2012 05:09:55 +0000 Subject: bluez: Minor fixes v4.99 --- abs/extra/bluez/PKGBUILD | 17 +++++++++++------ abs/extra/bluez/__changelog | 3 +++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/abs/extra/bluez/PKGBUILD b/abs/extra/bluez/PKGBUILD index 4090fdc..bfc7e25 100644 --- a/abs/extra/bluez/PKGBUILD +++ b/abs/extra/bluez/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Geoffroy Carrier pkgname=bluez -pkgver=4.98 -pkgrel=2 +pkgver=4.99 +pkgrel=3 pkgdesc="Libraries and tools for the Bluetooth protocol stack" url="http://www.bluez.org/" arch=('i686' 'x86_64') @@ -13,7 +13,6 @@ optdepends=("gstreamer0.10-base: bluetooth GStreamer support" "dbus-python: to run bluez-simple-agent" "pygobject: to run bluez-simple-agent" "libusb-compat: USB adapters support" - "cups: CUPS backend" "libnl: netlink plugin") conflicts=('bluez-libs' 'bluez-utils') provides=('bluez-libs' 'bluez-utils') @@ -29,7 +28,7 @@ source=("http://www.kernel.org/pub/linux/bluetooth/$pkgname-$pkgver.tar.bz2" build() { cd "$srcdir/$pkgname-$pkgver" - # Add directive that allows audio streaming + # Add directive that allows audio streaming out-of-the-box patch -Np1 -i ${srcdir}/bluez-4.98_audio-streaming.patch || return 1 ./configure --prefix=/usr \ @@ -45,6 +44,8 @@ build() { --enable-hidd \ --enable-pand \ --enable-dund \ + --enable-wiimote \ + --disable-test \ --disable-cups || return 1 make || return 1 @@ -65,9 +66,13 @@ package() { "$pkgdir/etc/conf.d/bluetooth" || return 1 install -Dm755 test/simple-agent ${pkgdir}/usr/bin/bluez-simple-agent + install -Dm755 test/test-device "${pkgdir}"/usr/bin/bluez-test-device + install -Dm755 test/test-input "${pkgdir}"/usr/bin/bluez-test-input sed -i 's#/usr/bin/python#/usr/bin/python2#' \ - ${pkgdir}/usr/bin/bluez-simple-agent + ${pkgdir}/usr/bin/bluez-simple-agent \ + ${pkgdir}/usr/bin/bluez-test-device \ + ${pkgdir}/usr/bin/bluez-test-input } -md5sums=('4aca8a0929250212e9a75fb60dd75b05' +md5sums=('2387053eb5a7b02f37df4871df022a02' 'da4ec22ee1a5c3e84d5d934440167526' 'd12be5b494525bb1ba6eac5c3983dd3e') diff --git a/abs/extra/bluez/__changelog b/abs/extra/bluez/__changelog index 124d0eb..7627514 100644 --- a/abs/extra/bluez/__changelog +++ b/abs/extra/bluez/__changelog @@ -9,3 +9,6 @@ own run scripts. Of particular interest is rfcomm and hid2hci utilities. They are not daemons and I added "/sbin/sv down ." in their respective run files. All based on this thread: http://article.gmane.org/gmane.comp.sysutils.supervision.general/1585/ + +2012-04-13 +disable cups -- cgit v0.12 From 9d277e0c1abfcd8aeb0331663abcacb11b2883fd Mon Sep 17 00:00:00 2001 From: Michael Hanson Date: Sat, 14 Apr 2012 05:27:20 +0000 Subject: bluez: fixup audio streaming again v4.99 --- abs/extra/bluez/PKGBUILD | 88 ++++++++++++++++++++++++ abs/extra/bluez/__changelog | 19 +++++ abs/extra/bluez/audio-streaming.patch | 13 ++++ abs/extra/bluez/bluez-4.98_audio-streaming.patch | 14 ---- abs/extra/bluez/bluez.install | 4 +- 5 files changed, 122 insertions(+), 16 deletions(-) create mode 100644 abs/extra/bluez/PKGBUILD create mode 100644 abs/extra/bluez/__changelog create mode 100644 abs/extra/bluez/audio-streaming.patch delete mode 100644 abs/extra/bluez/bluez-4.98_audio-streaming.patch diff --git a/abs/extra/bluez/PKGBUILD b/abs/extra/bluez/PKGBUILD new file mode 100644 index 0000000..e6837e9 --- /dev/null +++ b/abs/extra/bluez/PKGBUILD @@ -0,0 +1,88 @@ +# $Id$ +# Maintainer: Tom Gundersen +# Contributor: Andrea Scarpino +# Contributor: Geoffroy Carrier + +pkgname=bluez +pkgver=4.99 +pkgrel=3 +pkgdesc="Libraries and tools for the Bluetooth protocol stack" +url="http://www.bluez.org/" +arch=('i686' 'x86_64') +license=('GPL2') +depends=('dbus-core' 'python2' 'udev') +makedepends=('gstreamer0.10-base' 'libusb-compat' 'libsndfile') +optdepends=("gstreamer0.10-base: bluetooth GStreamer support" + "alsa-lib: Audio bluetooth devices support" + "dbus-python: to run bluez-simple-agent" + "pygobject: to run bluez-simple-agent" + "libusb-compat: USB adapters support" + "cups: CUPS backend") +conflicts=('bluez-libs' 'bluez-utils') +provides=('bluez-libs' 'bluez-utils') +replaces=('bluez-libs' 'bluez-utils') +options=('!libtool') +backup=(etc/bluetooth/{main,rfcomm,audio,network,input,serial}.conf + 'etc/conf.d/bluetooth' 'etc/dbus-1/system.d/bluetooth.conf') +install='bluez.install' +source=("http://www.kernel.org/pub/linux/bluetooth/${pkgname}-${pkgver}.tar.bz2" + 'bluetooth.conf.d' + 'audio-streaming.patch') + +build() { + cd "${srcdir}/${pkgname}-${pkgver}" + +# Add setting that allows audio streaming out-of-the-box + patch -Np1 -i ${srcdir}/audio-streaming.patch || return 1 + + ./configure --prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ + --libexecdir=/lib \ + --enable-gstreamer \ + --enable-alsa \ + --enable-usb \ + --enable-tools \ + --enable-bccmd \ + --enable-dfutool \ + --enable-hid2hci \ + --enable-hidd \ + --enable-pand \ + --enable-dund \ + --disable-cups \ + --enable-wiimote \ + --disable-test + make +} + +package() { + cd ${srcdir}/${pkgname}-${pkgver} + make DESTDIR=${pkgdir} install + +# install -Dm755 ${srcdir}/rc.bluetooth ${pkgdir}/etc/rc.d/bluetooth + + install -d ${pkgdir}/etc/bluetooth + install -m644 network/network.conf \ + input/input.conf \ + audio/audio.conf \ + serial/serial.conf \ + ${pkgdir}/etc/bluetooth/ + + install -Dm644 ${srcdir}/bluetooth.conf.d \ + ${pkgdir}/etc/conf.d/bluetooth + + # FS#27630 + install -Dm755 test/simple-agent "${pkgdir}"/usr/bin/bluez-simple-agent + install -Dm755 test/test-device "${pkgdir}"/usr/bin/bluez-test-device + install -Dm755 test/test-input "${pkgdir}"/usr/bin/bluez-test-input + sed -i 's#/usr/bin/python#/usr/bin/python2#' \ + "${pkgdir}"/usr/bin/bluez-simple-agent \ + "${pkgdir}"/usr/bin/bluez-test-device \ + "${pkgdir}"/usr/bin/bluez-test-input + + # http://mailman.archlinux.org/pipermail/arch-general/2011-April/019787.html +# rm "${pkgdir}"/usr/lib/udev/rules.d/97-bluetooth.rules +} +md5sums=('2387053eb5a7b02f37df4871df022a02' + '7412982b440f29fa7f76a41a87fef985' + 'cc9c86af1ced7ad46fc7be114d32adfb') diff --git a/abs/extra/bluez/__changelog b/abs/extra/bluez/__changelog new file mode 100644 index 0000000..62a2048 --- /dev/null +++ b/abs/extra/bluez/__changelog @@ -0,0 +1,19 @@ +# by mihanson +I really have no idea how this bluetooth stuff works. If anyone wants to +take a stab at getting this working properly with runit, feel free. I +only need this package to get mythpywii working. + +2010-04-01: +Make this package work with runit. All daemons were seperated into their +own run scripts. Of particular interest is rfcomm and hid2hci utilities. +They are not daemons and I added "/sbin/sv down ." in their +respective run files. All based on this thread: +http://article.gmane.org/gmane.comp.sysutils.supervision.general/1585/ + +2012-04-07 +- remove rc.bluetooth as we use runit +- disable-cups +- comment out removal of udev line + +2012-04-13 +re-add audio-streaming.patch for ootb audio streaming diff --git a/abs/extra/bluez/audio-streaming.patch b/abs/extra/bluez/audio-streaming.patch new file mode 100644 index 0000000..83705c5 --- /dev/null +++ b/abs/extra/bluez/audio-streaming.patch @@ -0,0 +1,13 @@ +--- bluez-4.98/audio/audio.conf.orig 2012-02-27 23:52:30.960349047 +0000 ++++ bluez-4.98/audio/audio.conf 2012-02-27 23:54:19.768069787 +0000 +@@ -4,6 +4,11 @@ + # particular interface + [General] + ++# Allow audio streaming with bluez-4.98 and alsa-lib 1.0.24.1 ++# https://wiki.archlinux.org/index.php/Bluetooth#Audio_streaming ++ ++Enable=Socket ++ + # Switch to master role for incoming connections (defaults to true) + #Master=true diff --git a/abs/extra/bluez/bluez-4.98_audio-streaming.patch b/abs/extra/bluez/bluez-4.98_audio-streaming.patch deleted file mode 100644 index 085d8ca..0000000 --- a/abs/extra/bluez/bluez-4.98_audio-streaming.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- bluez-4.98/audio/audio.conf.orig 2012-02-27 23:52:30.960349047 +0000 -+++ bluez-4.98/audio/audio.conf 2012-02-27 23:54:19.768069787 +0000 -@@ -4,6 +4,11 @@ - # particular interface - [General] - -+# Allow audio streaming with bluez-4.98 and alsa-lib 1.0.24.1 -+# https://wiki.archlinux.org/index.php/Bluetooth#Audio_streaming -+ -+Enable=Socket -+ - # Switch to master role for incoming connections (defaults to true) - #Master=true - diff --git a/abs/extra/bluez/bluez.install b/abs/extra/bluez/bluez.install index f9b757b..30bd262 100644 --- a/abs/extra/bluez/bluez.install +++ b/abs/extra/bluez/bluez.install @@ -2,12 +2,12 @@ post_install() { add_service.sh bluetoothd echo ">>> Only the bluetoothd daemon is started by default." echo ">>> You can optionally add the following as required:" - echo ">>> hidd dund pand rfcomm" + echo ">>> hidd dund pand sdpd rfcomm hid2hci" echo ">>> $ sudo add_service.sh " } pre_remove() { - for d in { bluetoothd,hidd,dund,pand,rfcomm } ; do + for d in { bluetoothd,hidd,dund,pand,sdpd,rfcomm,hid2hci } ; do if [ -d /var/service/${d} ] ; then remove_servcie.sh $d fi -- cgit v0.12 From ab2b92bf6743790902c68e764b7e28b4aa0a681a Mon Sep 17 00:00:00 2001 From: Britney Fransen Date: Sat, 14 Apr 2012 15:44:45 -0500 Subject: LinHES-system: add cacheclean and cron job to keep 3 newest pkgs in pacman cache. --- abs/core/LinHES-system/PKGBUILD | 13 ++-- abs/core/LinHES-system/cacheclean | 134 +++++++++++++++++++++++++++++++++ abs/core/LinHES-system/cacheclean.cron | 2 + 3 files changed, 144 insertions(+), 5 deletions(-) create mode 100755 abs/core/LinHES-system/cacheclean create mode 100644 abs/core/LinHES-system/cacheclean.cron diff --git a/abs/core/LinHES-system/PKGBUILD b/abs/core/LinHES-system/PKGBUILD index f8baeaf..94f592d 100644 --- a/abs/core/LinHES-system/PKGBUILD +++ b/abs/core/LinHES-system/PKGBUILD @@ -1,6 +1,6 @@ pkgname=LinHES-system pkgver=2 -pkgrel=41 +pkgrel=42 arch=('i686') MVDIR=$startdir/pkg/usr/LH BINDIR=$startdir/pkg/usr/bin @@ -20,11 +20,11 @@ binfiles="LinHES-start optimize_mythdb.py lh_system_host_update lh_system_all_host_update add_storage.py - diskspace.sh" + diskspace.sh + cacheclean" source=(LinHES-session LinHES-profile.sh $binfiles alsa-base myth_mtc.lr - diskspace smolt.cron) - + diskspace smolt.cron cacheclean.cron) build() { cd $startdir/src install -m755 -D LinHES-session $startdir/pkg/etc/X11/Sessions/LinHES @@ -47,6 +47,7 @@ build() { install -m644 -D $startdir/src/alsa-base $startdir/pkg/etc/modprobe.d/alsa-base.conf install -m755 -D $startdir/src/smolt.cron $startdir/pkg/etc/cron.weekly/smolt.cron + install -m755 -D $startdir/src/cacheclean.cron $startdir/pkg/etc/cron.weekly/cacheclean.cron install -m755 -D $startdir/src/diskspace $startdir/pkg/etc/cron.tenminutes/diskspace mkdir $startdir/pkg/etc/logrotate.d cp $startdir/myth_mtc.lr $startdir/pkg/etc/logrotate.d @@ -74,7 +75,9 @@ md5sums=('d6a564f3286590875874573107940908' '47e093e8cfe4b5b96602358e1f540832' '6faeba0aeb38e772121f751cabda8683' '68e3e87571f3b0fa4a48a10df50dc220' + '9603b0ca6e090eff31e76482a3c335e7' 'eb879fee9603a05d5420d4ce8ed9e450' 'f1870a9522c79e6b248fcbf81dec3280' '84492954db16740f949d795b74383189' - 'abe887472a170bd1a8e6da6a7b7e93e4') + 'abe887472a170bd1a8e6da6a7b7e93e4' + '02c810c2f47b7c4495fdacaf54189473') diff --git a/abs/core/LinHES-system/cacheclean b/abs/core/LinHES-system/cacheclean new file mode 100755 index 0000000..d32d16b --- /dev/null +++ b/abs/core/LinHES-system/cacheclean @@ -0,0 +1,134 @@ +#!/usr/bin/env python +"""cacheclean - a simple python script to clean up the /data/var/cache/pacman/pkg directory. +More versatile than 'pacman -Sc' in that you can select how many old versions +to keep. +Usage: cacheclean {-p} {-v} <# of copies to keep> + # of copies to keep - (required) how many generations of each package to keep + -p - (optional) preview what would be deleted; forces verbose (-v) mode. + -v - (optional) show deleted packages. + +Adapted from https://github.com/graysky2/cacheclean for LinHES pacman cache directories +and python 2.6.""" + +# Note that the determination of package age is done by simply looking at the date-time +# modified stamp on the file. There is just enough variation in the way package version +# is done that I thought this would be simpler & just as good. +# Also note that you must be root to run this script. + +import getopt +import os +import re +import sys + +# helper function to get tuple of (file dtm, file name, file sz) +def fn_stats(fn): + s = os.stat(fn) + return (s[8], fn, s[6]) + +# cleanup does the actual pkg file deletion +def cleanup(run_list): + # strictly speaking only the first two of these globals need to be listed. + global n_deleted, bytes_deleted, opt_verbose, opt_preview, n_to_keep + # return if the run_list is too short + #print run_list + #return + if len(run_list) <= n_to_keep: return + # Build list of tuples (date-time file modified, file name, file size) + dtm_list = [fn_stats(tfn) for tfn in run_list] + # Sort the list by date-time + dtm_list.sort() + # Build list of the filenames to delete (all but last n_to_keep). + # + #kill_list = [tfn[1] for tfn in dtm_list[:-n_to_keep]] + #bytes_deleted = sum(x[2] for x in dtm_list[:-n_to_keep]) + # + kill_list = [] + for x in dtm_list[:-n_to_keep]: + if os.path.isfile(x[1]): + kill_list.append(x[1]) + bytes_deleted += x[2] + if opt_verbose and kill_list: print (kill_list) + n_deleted += len(kill_list) + # and finally delete (if not in preview mode) + if not opt_preview: + for dfn in kill_list: + os.unlink(dfn) + +###################################################################### +# mainline processing + +# process command line options +try: + opts, pargs = getopt.getopt(sys.argv[1:], 'vp') + opt_dict = dict(opts) + opt_preview = '-p' in opt_dict + opt_verbose = '-v' in opt_dict + if opt_preview: opt_verbose = True + if len(pargs) == 1: + n_to_keep = pargs[0] + else: + raise getopt.GetoptError("missing required argument.") + try: + n_to_keep = int(n_to_keep) + if n_to_keep <= 0: raise ValueError + except ValueError as e: + raise getopt.GetoptError("# of copies to keep must be numeric > 0!") +except getopt.GetoptError as msg: + print ("Error:",msg,"\n",__doc__) + sys.exit(1) + +# change to the pkg directory & get a sorted list of its contents +os.chdir('/data/var/cache/pacman/pkg') +pkg_fns = os.listdir('.') +pkg_fns.sort() + +# Pattern to use to extract the package name from the tar file name: +# for pkg e.g. 'gnome-common-2.8.0-1-i686.pkg.tar.gz' group(1) is 'gnome-common'. + +bpat = re.compile(""" +^([^-/][^/]*?)- # (1) package name +[^-/\s]+- # (2) version +[^-/\s]+ # (3) release +(-i686|-x86_64|-any)? # (4) architecture +\.pkg\.tar # (5) extension +(?:\.(?:gz|bz2|xz|Z))? # (6) compresssion extension +(?:\.aria2|.sig)? # (7) other extension +(?:\.part)?$ # (8) partially-downloaded files' extension +""", re.X) + +n_deleted = 0 +bytes_deleted = 0 +pkg_base_nm = '' +# now look for "runs" of the same package name differing only in version info. +for run_end in range(len(pkg_fns)): + fn = pkg_fns[run_end] + + # make sure we skip directories + if os.path.isfile(fn): + mo = bpat.match(fn) # test for a match of the package name pattern + if mo: + # print ("Processing file '" + fn + "' " + str(mo.lastindex), file=sys.stdout) + tbase = mo.group(1) # gets the 'base' package name + # include the architecture in the name if it's present + if mo.group(2) is not None: + tbase += mo.group(2) + # print ('tbase: ' + tbase + ' ' + str(mo.lastindex), file=sys.stdout) + # is it a new base name, i.e. the start of a new run? + if tbase != pkg_base_nm: # if so then process the prior run + if pkg_base_nm != '': + cleanup(pkg_fns[run_start:run_end]) + pkg_base_nm = tbase # & setup for the new run + run_start = run_end + else: + print >>sys.stderr, "File '"+fn+"' doesn't match package pattern!" + else: + print >>sys.stdout, "skipping directory '"+fn+"'!" + +# catch the final run of the list +run_end += 1 +cleanup(pkg_fns[run_start:run_end]) + +if opt_verbose: + if opt_preview: + print ("Preview mode (no files deleted):"), + print n_deleted,"files deleted,",bytes_deleted/(2**10),"kbytes /",bytes_deleted/(2**20),"MBytes /",bytes_deleted/(2**30), "GBytes." diff --git a/abs/core/LinHES-system/cacheclean.cron b/abs/core/LinHES-system/cacheclean.cron new file mode 100644 index 0000000..b47a3ef --- /dev/null +++ b/abs/core/LinHES-system/cacheclean.cron @@ -0,0 +1,2 @@ +#!/bin/bash +/usr/LH/bin/cacheclean 3 -- cgit v0.12 From 824ae0105eacb0247e33ce29cebd65c1134786c7 Mon Sep 17 00:00:00 2001 From: James Meyer Date: Sun, 15 Apr 2012 13:05:47 -0500 Subject: linhes-system: myth_status.py, handle case where conflicts is null and catch the excpetion --- abs/core/LinHES-system/myth_status.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/abs/core/LinHES-system/myth_status.py b/abs/core/LinHES-system/myth_status.py index f8222cb..ed5058c 100644 --- a/abs/core/LinHES-system/myth_status.py +++ b/abs/core/LinHES-system/myth_status.py @@ -90,12 +90,15 @@ print "" print "Conflicted Recordings:" print "----------------------" a=be.getConflictedRecordings() -if len(a) == 0: +try: + if len(a) == 0: + print " No conflicts" + else: + for i in a: + title_chan="%s (%s)" %(i.title, i.channame) + print " %s - %-50s " %(i.starttime,title_chan) +except: print " No conflicts" -else: - for i in a: - title_chan="%s (%s)" %(i.title, i.channame) - print " %s - %-50s " %(i.starttime,title_chan) print "" print "" -- cgit v0.12 From eef6735a9c5038dd41e63d744e07ba698a92ccf2 Mon Sep 17 00:00:00 2001 From: James Meyer Date: Sun, 15 Apr 2012 13:07:08 -0500 Subject: LinHES-system: change frontend logging to use --syslog -silence the grep for osd --- abs/core/LinHES-system/LinHES-run | 3 ++- abs/core/LinHES-system/LinHES-session | 6 +++--- abs/core/LinHES-system/PKGBUILD | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/abs/core/LinHES-system/LinHES-run b/abs/core/LinHES-system/LinHES-run index 883bcda..0bb66ea 100755 --- a/abs/core/LinHES-system/LinHES-run +++ b/abs/core/LinHES-system/LinHES-run @@ -111,7 +111,8 @@ if [ x"$UseMythWelcome" = "x1" ] then STARTCMD="/usr/bin/mythwelcome" else - STARTCMD="/usr/bin/mythfrontend -d -l /var/log/mythtv/mythfrontend.log" + #STARTCMD="/usr/bin/mythfrontend -d -l /var/log/mythtv/mythfrontend.log" + STARTCMD="/usr/bin/mythfrontend -d --syslog local6" fi echo "=====================================================================" diff --git a/abs/core/LinHES-system/LinHES-session b/abs/core/LinHES-system/LinHES-session index da2f14e..16705de 100755 --- a/abs/core/LinHES-system/LinHES-session +++ b/abs/core/LinHES-system/LinHES-session @@ -49,9 +49,9 @@ export MALLOC_CHECK_=0 function delay_osd(){ if [ x$STARTUP_STYLE = xmythvantage ] then - cmd="ps -ef | grep -v grep | grep xmsg.py" + cmd="ps -ef | grep -v grep | grep -q xmsg.py" else - cmd="ps -ef | grep -v grep | grep osd_cat" + cmd="ps -ef | grep -v grep | grep -q osd_cat" fi eval $cmd @@ -276,7 +276,7 @@ function start_myth() { then STARTCMD="/usr/bin/mythwelcome" else - STARTCMD="/usr/bin/mythfrontend -d -l /var/log/mythtv/mythfrontend.log" + STARTCMD="/usr/bin/mythfrontend -d --syslog local6" fi echo "=====================================================================" diff --git a/abs/core/LinHES-system/PKGBUILD b/abs/core/LinHES-system/PKGBUILD index d53adee..d04a658 100644 --- a/abs/core/LinHES-system/PKGBUILD +++ b/abs/core/LinHES-system/PKGBUILD @@ -1,6 +1,6 @@ pkgname=LinHES-system pkgver=2 -pkgrel=38 +pkgrel=42 arch=('i686') MVDIR=$startdir/pkg/usr/LH BINDIR=$startdir/pkg/usr/bin @@ -48,13 +48,13 @@ build() { mkdir $startdir/pkg/etc/logrotate.d cp $startdir/myth_mtc.lr $startdir/pkg/etc/logrotate.d } -md5sums=('d6a564f3286590875874573107940908' +md5sums=('e8a0e71dabadb5a860b4e113615c3071' '5881bdb43d578ec3a79d1f77ea58a3db' 'a875ee97f86e46f34a741c2bc455f894' '76b2637cac0452b3acdbeeb4e8a5474b' 'd1f27cb422010077c841376526fe46ea' '2ef9f945e034119f77d9b6beb17e4fa5' - '5c96527397a35519d72c78d6e3c8dbea' + 'c1c5f68835afbb2bad5d5e6cec0fc1dc' '18a884a73344ff6eb74f63b49745e0f5' 'dc3eef2a624754e16805d72bbe488b67' 'dc0be354ce77ba2b89868fc29b942c43' @@ -62,7 +62,7 @@ md5sums=('d6a564f3286590875874573107940908' 'abe887472a170bd1a8e6da6a7b7e93e4' '752488eb8bfb672ce0e4c924f7faf3d1' 'ba351b92e69bcaf26a9bf80417b09c3c' - '1d534843cc4e55fe4ce21c3e95e3f766' + '657fef69a1da2f6b6cfac97a9d1be043' '962a3e9eaba2d1466251b7ab0956705d' 'd03aedeeeda0f5e9c1eb437411c88477' '94ce8f1d5085c0db7b267db8c2e9a3ff' -- cgit v0.12 From a085ed0242e319f5739831b2166e6f0d5798b900 Mon Sep 17 00:00:00 2001 From: James Meyer Date: Sun, 15 Apr 2012 13:07:30 -0500 Subject: mythinstall: update package for myth .25 --- abs/core/mythinstall/PKGBUILD | 2 +- abs/core/mythinstall/checkout_MythVantage.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/abs/core/mythinstall/PKGBUILD b/abs/core/mythinstall/PKGBUILD index ce0ec36..d48b586 100644 --- a/abs/core/mythinstall/PKGBUILD +++ b/abs/core/mythinstall/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Jams pkgname=mythinstall pkgver=3 -pkgrel=17 +pkgrel=18 pkgdesc="LinHES installer/systemconfig GUI." arch=i686 depends=() diff --git a/abs/core/mythinstall/checkout_MythVantage.sh b/abs/core/mythinstall/checkout_MythVantage.sh index a61ed95..ecc7cd0 100755 --- a/abs/core/mythinstall/checkout_MythVantage.sh +++ b/abs/core/mythinstall/checkout_MythVantage.sh @@ -2,8 +2,8 @@ MYDIR=`pwd` PREFIX="\/usr\/include\/mythtv" -LIBVERSION=0.24 -VERSION=0.24.0 +LIBVERSION=0.25 +VERSION=0.25.0 function setup_links { -- cgit v0.12 From c4b1cc7f705de9b4d539e8bba18170607e2c93f9 Mon Sep 17 00:00:00 2001 From: James Meyer Date: Sun, 15 Apr 2012 13:08:01 -0500 Subject: runit-scripts: change mythbackend to use --logpath --- abs/core/runit-scripts/PKGBUILD | 3 ++- abs/core/runit-scripts/runitscripts/services/mythbackend/run | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/abs/core/runit-scripts/PKGBUILD b/abs/core/runit-scripts/PKGBUILD index 7e0a71c..30acc6a 100755 --- a/abs/core/runit-scripts/PKGBUILD +++ b/abs/core/runit-scripts/PKGBUILD @@ -1,6 +1,6 @@ pkgname=runit-scripts pkgver=2.1.1 -pkgrel=56 +pkgrel=57 pkgdesc="collection of startup scripts for runit" url="http://smarden.org/runit/" license="BSD" @@ -26,5 +26,6 @@ build() { install -m755 $startdir/src/fbsplash-runit.sh $startdir/pkg/etc/rc.d/functions.d/fbsplash-runit.sh install -m0755 reboot-runit halt-runit logger $startdir/pkg/sbin rsync -a --exclude=.svn services/* $startdir/pkg/etc/sv + chmod -R 755 $startdir/pkg/etc/sv } md5sums=('c79246677d5ffe687bcf6df1b9c2abc2') diff --git a/abs/core/runit-scripts/runitscripts/services/mythbackend/run b/abs/core/runit-scripts/runitscripts/services/mythbackend/run index e3ef721..9683dd7 100755 --- a/abs/core/runit-scripts/runitscripts/services/mythbackend/run +++ b/abs/core/runit-scripts/runitscripts/services/mythbackend/run @@ -39,5 +39,5 @@ fi # sleep 10 # # else - exec su mythtv -c "/usr/bin/mythbackend --logfile /var/log/mythtv/mythbackend.log" + exec su mythtv -c "/usr/bin/mythbackend --logpath /var/log/mythtv/" # fi -- cgit v0.12 From 294a757e2774990e7a788d6437089e730118b5d1 Mon Sep 17 00:00:00 2001 From: James Meyer Date: Sun, 15 Apr 2012 13:13:12 -0500 Subject: mythtv .25: First checkin, still needs a bit of cleanup. This commit introduces the dir git_src which is used as a common dir to build plugins/mythweb/mythtv. To update the mythtv pkg, first run git_src/checkout_mythtv.sh then switch to the mythtv package dir and build the package as normal. Same applies to mythplugins. I plan to introduce another script that will build it all in one step. Also this checkin doesn't handle the menu updates. Those will be corrected at a later date. --- .../mythtv/stable-0.25/git_src/checkout_mythtv.sh | 18 + abs/core/mythtv/stable-0.25/git_src/mythtv | 1 + abs/core/mythtv/stable-0.25/mythplugins/PKGBUILD | 143 ++ .../stable-0.25/mythplugins/mythburn.py.patch | 303 ++++ .../mythplugins/mythplugins-mythzoneminder.install | 3 + abs/core/mythtv/stable-0.25/mythtv/PKGBUILD | 113 ++ abs/core/mythtv/stable-0.25/mythtv/__changelog | 1 + .../mythtv/stable-0.25/mythtv/git_version.patch | 13 + .../stable-0.25/mythtv/menu-xml/HOST_SETTINGS.xml | 94 + abs/core/mythtv/stable-0.25/mythtv/menu-xml/is.xml | 3 + .../stable-0.25/mythtv/menu-xml/library.xml.patch | 12 + .../mythtv/stable-0.25/mythtv/menu-xml/linhes.xml | 59 + .../stable-0.25/mythtv/menu-xml/mainmenu.xml.patch | 37 + .../stable-0.25/mythtv/menu-xml/mythbackup.xml | 20 + .../stable-0.25/mythtv/menu-xml/mythrestore.xml | 20 + .../mythtv/menu-xml/optical_menu.xml.patch | 16 + .../mythtv/menu-xml/original/create_patch.sh | 5 + .../mythtv/stable-0.25/mythtv/menu-xml/setup.xml | 111 ++ .../stable-0.25/mythtv/menu-xml/siriusmenu.xml | 419 +++++ .../mythtv/stable-0.25/mythtv/menu-xml/update.xml | 9 + .../mythtv/stable-0.25/mythtv/menu-xml/update2.xml | 20 + .../mythtv/menu-xml/util_menu.xml.patch | 16 + .../mythtv/stable-0.25/mythtv/menu-xml/xmmenu.xml | 574 +++++++ abs/core/mythtv/stable-0.25/mythtv/myth.sh | 4 + .../mythtv/stable-0.25/mythtv/myth_settings.patch | 1816 ++++++++++++++++++++ abs/core/mythtv/stable-0.25/mythtv/mythbackend | 38 + abs/core/mythtv/stable-0.25/mythtv/mythbackend.lr | 9 + abs/core/mythtv/stable-0.25/mythtv/mythbackend.sh | 117 ++ abs/core/mythtv/stable-0.25/mythtv/mythfrontend.lr | 9 + abs/core/mythtv/stable-0.25/mythtv/mythtv.install | 63 + abs/core/mythtv/stable-0.25/mythtv/pretty | 9 + .../mythtv/stable-0.25/mythtv/smolt_jump.patch | 10 + abs/core/mythtv/stable-0.25/mythweb/PKGBUILD | 46 + .../mythtv/stable-0.25/mythweb/mythweb.php.patch | 11 + 34 files changed, 4142 insertions(+) create mode 100644 abs/core/mythtv/stable-0.25/git_src/checkout_mythtv.sh create mode 160000 abs/core/mythtv/stable-0.25/git_src/mythtv create mode 100644 abs/core/mythtv/stable-0.25/mythplugins/PKGBUILD create mode 100644 abs/core/mythtv/stable-0.25/mythplugins/mythburn.py.patch create mode 100644 abs/core/mythtv/stable-0.25/mythplugins/mythplugins-mythzoneminder.install create mode 100644 abs/core/mythtv/stable-0.25/mythtv/PKGBUILD create mode 100644 abs/core/mythtv/stable-0.25/mythtv/__changelog create mode 100644 abs/core/mythtv/stable-0.25/mythtv/git_version.patch create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/HOST_SETTINGS.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/is.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/library.xml.patch create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/linhes.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/mainmenu.xml.patch create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythbackup.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythrestore.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/optical_menu.xml.patch create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/original/create_patch.sh create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/setup.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/siriusmenu.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/update.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/update2.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/util_menu.xml.patch create mode 100644 abs/core/mythtv/stable-0.25/mythtv/menu-xml/xmmenu.xml create mode 100644 abs/core/mythtv/stable-0.25/mythtv/myth.sh create mode 100644 abs/core/mythtv/stable-0.25/mythtv/myth_settings.patch create mode 100644 abs/core/mythtv/stable-0.25/mythtv/mythbackend create mode 100644 abs/core/mythtv/stable-0.25/mythtv/mythbackend.lr create mode 100644 abs/core/mythtv/stable-0.25/mythtv/mythbackend.sh create mode 100644 abs/core/mythtv/stable-0.25/mythtv/mythfrontend.lr create mode 100644 abs/core/mythtv/stable-0.25/mythtv/mythtv.install create mode 100644 abs/core/mythtv/stable-0.25/mythtv/pretty create mode 100644 abs/core/mythtv/stable-0.25/mythtv/smolt_jump.patch create mode 100644 abs/core/mythtv/stable-0.25/mythweb/PKGBUILD create mode 100644 abs/core/mythtv/stable-0.25/mythweb/mythweb.php.patch diff --git a/abs/core/mythtv/stable-0.25/git_src/checkout_mythtv.sh b/abs/core/mythtv/stable-0.25/git_src/checkout_mythtv.sh new file mode 100644 index 0000000..7691a29 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/git_src/checkout_mythtv.sh @@ -0,0 +1,18 @@ +#!/bin/bash +#Quick script used to checkout the MythTV source +#This source should be used build all mythplugins & main program + +_gitroot="https://github.com/MythTV/mythtv.git" +_gitname="mythtv" + + +if [ -d $_gitname ] +then + cd $_gitname && git pull + echo "The local files are updated." +else + git clone -b fixes/0.25 $_gitroot +fi +echo "GIT checkout done or server timeout" + + diff --git a/abs/core/mythtv/stable-0.25/git_src/mythtv b/abs/core/mythtv/stable-0.25/git_src/mythtv new file mode 160000 index 0000000..76df8e6 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/git_src/mythtv @@ -0,0 +1 @@ +Subproject commit 76df8e6c8f7b84a157607d8c25fd19f39d8dc830 diff --git a/abs/core/mythtv/stable-0.25/mythplugins/PKGBUILD b/abs/core/mythtv/stable-0.25/mythplugins/PKGBUILD new file mode 100644 index 0000000..5a579b6 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythplugins/PKGBUILD @@ -0,0 +1,143 @@ +# $Id: PKGBUILD 91281 2010-09-26 06:04:21Z remy $ +# Maintainer: Giovanni Scafora + +pkgbase=mythplugins +pkgname=('mytharchive' + 'mythbrowser' + 'mythgallery' + 'mythgame' + 'mythmusic' + 'mythnetvision' + 'mythnews' + 'mythweather' + 'mythzoneminder') +pkgver=0.25 +pkgrel=1 +arch=('i686' 'x86_64') +url="http://www.mythtv.org" +license=('GPL') +conflicts=('mythmovies') +makedepends=("mythtv>=${pkgver}" 'mplayer' 'fftw2' 'dvdauthor' 'libexif' + 'python-imaging' 'libcdaudio' 'taglib' 'perl-xml-simple' 'dcraw' + 'libvisual' 'perl-xml-xpath' 'perl-image-size' 'perl-json' + 'perl-class-inspector' 'perl-datetime-format-iso8601' + 'flac' 'libvorbis' 'python2' 'python-pycurl' 'python-oauth') + +source=(mythburn.py.patch) + + +#_gitroot="https://github.com/MythTV/mythtv.git" +#_gitname="mythplugins" + +build() { + + if [ -e ${srcdir}/mythplugins ] + then + rm -rf ${srcdir}/mythplugins + fi + + cd ${startdir} + msg "copy in myth plugins src" + cp -rp ../git_src/mythtv/mythplugins $srcdir + cd ${srcdir}/${pkgbase} + + + + msg "The local files are updated." + #find . -name '*.py' -type f | xargs sed -i 's@^#!.*python$@#!/usr/bin/python2@' + cd ${srcdir}/${pkgbase} + ./configure --prefix=/usr \ + --enable-all + + qmake mythplugins.pro || return 1 + make || return 1 +} + +package_mytharchive() { + pkgdesc="MythTV plugin that lets you create DVDs from or archive your recorded shows" + depends=("mythtv>=${pkgver}" 'libxmu' 'pil' 'dvdauthor' 'm2vrequantiser') +# replaces=('mytharchive') + cd "${srcdir}/${_gitname}/${pkgbase}/mytharchive" + +# patch mythburn/scripts/mythburn.py < $srcdir/mythburn.py.patch || return 1 + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythbrowser() { + pkgdesc="Mini web browser for MythTV" + depends=("mythtv>=${pkgver}") +# replaces=('mythbrowser') + cd "${srcdir}/${_gitname}/${pkgbase}/mythbrowser" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythgallery() { + pkgdesc="Image gallery plugin for MythTV" + depends=("mythtv>=${pkgver}" 'libexif') +# replaces=('mythgallery') + cd "${srcdir}/${_gitname}/${pkgbase}/mythgallery" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythgame() { + pkgdesc="Game emulator module for MythTV" + depends=("mythtv>=${pkgver}" 'zlib') +# replaces=('mythgame') + cd "${srcdir}/${_gitname}/${pkgbase}/mythgame" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythmusic() { + pkgdesc="Music playing plugin for MythTV" + depends=("mythtv>=${pkgver}" 'flac' 'libvorbis' 'libcdaudio' 'cdparanoia' 'taglib' 'libvisual-plugins' 'projectm') +# replaces=('mythmusic') + cd "${srcdir}/${_gitname}/${pkgbase}/mythmusic" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythnetvision() { + pkgdesc="MythNetvision plugin for MythTV" + + + depends=("mythtv>=${pkgver}" 'python-pycurl' 'python-oauth' 'python-lxml' ) +# replaces=('mythnetvision') + cd "${srcdir}/${_gitname}/${pkgbase}/mythnetvision" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythnews() { + pkgdesc="News checking plugin for MythTV" + depends=("mythtv>=${pkgver}") +# replaces=('mythnews') + cd "${srcdir}/${_gitname}/${pkgbase}/mythnews" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythvideo() { + pkgdesc="Video playback and browsing plugin for MythTV" + depends=("mythtv>=${pkgver}" 'mplayer' 'perl-xml-simple') +# replaces=('mythvideo') + cd "${srcdir}/${_gitname}/${pkgbase}/mythvideo" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythweather() { + pkgdesc="Weather checking plugin for MythTV" + depends=("mythtv>=${pkgver}" 'perl-xml-xpath' 'perl-image-size' + 'perl-class-inspector' 'perl-datetime-format-iso8601' + 'perl-date-manip' 'perl-json') +# replaces=('mythweather') + cd "${srcdir}/${_gitname}/${pkgbase}/mythweather" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +package_mythzoneminder() { + pkgdesc="Allows for viewing of CCTV cameras through zoneminder" + depends=("mythtv>=${pkgver}" zoneminder) +# replaces=('mythzoneminder') +# install=mythplugins-mythzoneminder.install + cd "${srcdir}/${_gitname}/${pkgbase}/mythzoneminder" + make INSTALL_ROOT="${pkgdir}" install || return 1 +} + +md5sums=('cc7e6887acda167fcc5336af33f29411') diff --git a/abs/core/mythtv/stable-0.25/mythplugins/mythburn.py.patch b/abs/core/mythtv/stable-0.25/mythplugins/mythburn.py.patch new file mode 100644 index 0000000..abac7df --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythplugins/mythburn.py.patch @@ -0,0 +1,303 @@ +--- mythburn.py.orig 2011-09-16 13:41:43.000000000 -0500 ++++ mythburn.py 2011-09-17 10:51:36.000000000 -0500 +@@ -38,7 +38,7 @@ + #****************************************************************************** + + # version of script - change after each update +-VERSION="0.1.20101206-1" ++VERSION="0.1.20110821-1" + + # keep all temporary files for debugging purposes + # set this to True before a first run through when testing +@@ -75,6 +75,7 @@ + from fcntl import ioctl + import CDROM + from shutil import copy ++from subprocess import Popen, PIPE + + # media types (should match the enum in mytharchivewizard.h) + DVD_SL = 0 +@@ -606,7 +607,7 @@ + # of a video file from its stream info file + + def getVideoParams(folder): +- """Returns the video resolution, fps and aspect ratio for the video file from the streamindo.xml file""" ++ """Returns the video resolution, fps and aspect ratio for the video file from the streaminfo.xml file""" + + #open the XML containing information about this file + infoDOM = xml.dom.minidom.parse(os.path.join(folder, 'streaminfo.xml')) +@@ -642,14 +643,14 @@ + # Gets the aspect ratio of a video file from its stream info file + + def getAspectRatioOfVideo(index): +- """Returns the aspect ratio of the video file (1.333, 1.778, etc)""" ++ """Returns the aspect ratio of the original video file (1.333, 1.778, etc)""" + + #open the XML containing information about this file +- infoDOM = xml.dom.minidom.parse(os.path.join(getItemTempPath(index), 'streaminfo.xml')) ++ infoDOM = xml.dom.minidom.parse(os.path.join(getItemTempPath(index), 'streaminfo_orig.xml')) + + #error out if its the wrong XML + if infoDOM.documentElement.tagName != "file": +- fatalError("Stream info file doesn't look right (%s)" % os.path.join(getItemTempPath(index), 'streaminfo.xml')) ++ fatalError("Stream info file doesn't look right (%s)" % os.path.join(getItemTempPath(index), 'streaminfo_orig.xml')) + video = infoDOM.getElementsByTagName("file")[0].getElementsByTagName("streams")[0].getElementsByTagName("video")[0] + if video.attributes["aspectratio"].value != 'N/A': + aspect_ratio = float(video.attributes["aspectratio"].value) +@@ -1762,6 +1763,37 @@ + + + ############################################################# ++# Finds the path of a video file from the local video path ++# or Storage Group ++ ++def getVideoPath(filename): ++ # connect ++ db = getDatabaseConnection() ++ # create a cursor ++ cursor = db.cursor() ++ # execute SQL statement ++ cursor.execute("""SELECT dirname ++ FROM storagegroup ++ WHERE groupname='Videos'""") ++ # get the resultset as a tuple ++ result = cursor.fetchall() ++ # make result a list and add local video path if exists ++ result = [videopath] + list(result) ++ ++ # iterate through result set ++ for sg in result: ++ if doesFileExist(os.path.join("".join(sg), filename)) == True: ++ filepath = "".join(sg) ++ write("Video Path: %s" % filepath) ++ return (filepath) ++ break ++ ++ db.close() ++ del db ++ del cursor ++ ++ ++############################################################# + # Pre-process a single video/recording file + + def preProcessFile(file, folder, count): +@@ -1775,11 +1807,11 @@ + #3. Extract a single frame from the video to use as a thumbnail and resolution check + mediafile="" + +- if file.attributes["type"].value == "recording": ++ if file.attributes["type"].value=="recording": + mediafile = file.attributes["filename"].value +- elif file.attributes["type"].value == "video": +- mediafile = os.path.join(videopath, file.attributes["filename"].value) +- elif file.attributes["type"].value == "file": ++ elif file.attributes["type"].value=="video": ++ mediafile = os.path.join(getVideoPath(file.attributes["filename"].value), file.attributes["filename"].value) ++ elif file.attributes["type"].value=="file": + mediafile = file.attributes["filename"].value + else: + fatalError("Unknown type of video file it must be 'recording', 'video' or 'file'.") +@@ -1935,9 +1967,39 @@ + + if result <> 0: + fatalError("Failed while running mytharchivehelper to get stream information from %s" % filename) ++ ++ #open the XML containing information about this file ++ infoDOM = xml.dom.minidom.parse(xmlFilename) ++ ++ #error out if its the wrong XML ++ if infoDOM.documentElement.tagName != "file": ++ fatalError("This info file doesn't look right (%s)." % xmlFilename) ++ ++ file = infoDOM.getElementsByTagName("file")[0] ++ video = infoDOM.getElementsByTagName("file")[0].getElementsByTagName("streams")[0].getElementsByTagName("video")[0] ++ ++ #use ffmpeg to get display aspect ratio (DAR) of video ++ cmd = path_ffmpeg[0] + " -i " + quoteFilename(file.attributes["filename"].value) + " 2>&1" ++ aspect_ratio = Popen(cmd, shell=True, stdout=PIPE).stdout.read() ++ if "DAR" in aspect_ratio: ++ #clean DAR string ++ aspect_ratio = aspect_ratio.split("DAR ")[-1].split(",")[0] ++ aspect_ratio = ''.join([c for c in aspect_ratio if c in '1234567890:']).split(":") ++ else: ++ #calculate aspect from video size ++ aspect_ratio = getVideoSize(xmlFilename) ++ ++ #convert to decimal ++ aspect_ratio = float(aspect_ratio[0]) / float(aspect_ratio[1]) ++ ++ write("Video %s aspect ratio is: %s" % (filename, aspect_ratio)) ++ ++ #set aspect ratio ++ video.setAttribute("aspectratio",str(aspect_ratio)) ++ ++ WriteXMLToFile (infoDOM,xmlFilename) + + # print out the streaminfo.xml file to the log +- infoDOM = xml.dom.minidom.parse(xmlFilename) + write("streaminfo.xml :-\n" + infoDOM.toprettyxml(" ", ""), False) + + ############################################################# +@@ -2322,7 +2384,7 @@ + ############################################################# + # Re-encodes a file to mpeg2 + +-def encodeVideoToMPEG2(source, destvideofile, video, audio1, audio2, aspectratio, profile): ++def encodeVideoToMPEG2(source, destvideofile, video, folder, audio1, audio2, aspectratio, profile): + """Encodes an unknown video source file eg. AVI to MPEG2 video and AC3 audio, use ffmpeg""" + + profileNode = findEncodingProfile(profile) +@@ -2347,6 +2409,18 @@ + value = quoteFilename(destvideofile) + if value == "%aspect": + value = aspectratio ++ if value == "720x480" or value == "720x576": ++ #add padding to correct for aspects > than 1.9:1 ++ videores, fps, videoAR = getVideoParams(folder) ++ if float(videoAR) >= 1.9: ++ if videomode == "ntsc": ++ videoheight = 480 ++ else: ++ videoheight = 576 ++ ++ croppixels = videoheight - (720 / float(videoAR)) ++ write("CropPixels Total: %s" % croppixels) ++ value = "720x%d -vf pad=720:%d:0:%d:black" % (videoheight - croppixels, videoheight, croppixels / 2) + + # only re-encode the audio if it is not already in AC3 format + if audio1[AUDIO_CODEC] == "AC3": +@@ -2383,12 +2457,12 @@ + command += " -newaudio" + + #make sure we get the correct stream(s) that we want +- command += " -map 0:%d -map 0:%d " % (video[VIDEO_INDEX], audio1[AUDIO_INDEX]) ++ command += " -map 0:%d -map 0:%d" % (video[VIDEO_INDEX], audio1[AUDIO_INDEX]) + if audio2[AUDIO_ID] != -1: + command += "-map 0:%d" % (audio2[AUDIO_INDEX]) + + if passes == 1: +- write(command) ++ write("Running ffmpeg: %s" % command) + result = runCommand(command) + if result!=0: + fatalError("Failed while running ffmpeg to re-encode video.\n" +@@ -2399,7 +2473,7 @@ + + pass1 = string.replace(command, "%passno","1") + pass1 = string.replace(pass1, "%passlogfile", passLog) +- write("Pass 1 - " + pass1) ++ write("Running ffmpeg Pass 1: %s" % pass1) + result = runCommand(pass1) + + if result!=0: +@@ -2411,7 +2485,7 @@ + + pass2 = string.replace(command, "%passno","2") + pass2 = string.replace(pass2, "%passlogfile", passLog) +- write("Pass 2 - " + pass2) ++ write("Running ffmpeg Pass 2: %s" % pass2) + result = runCommand(pass2) + + if result!=0: +@@ -2443,10 +2517,6 @@ + outaudiosamplerate = 48000 + outaudiocodec = "ac3" + deinterlace = 0 +- croptop = 0 +- cropright = 0 +- cropbottom = 0 +- cropleft = 0 + qmin = 5 + qmax = 31 + qdiff = 31 +@@ -2470,14 +2540,6 @@ + outvideores = value + if name == "-deinterlace": + deinterlace = 1 +- if name == "-croptop": +- croptop = value +- if name == "-cropright": +- cropright = value +- if name == "-cropbottom": +- cropbottom = value +- if name == "-cropleft": +- cropleft = value + if name == "-qmin": + qmin = value + if name == "-qmax": +@@ -2526,7 +2588,6 @@ + command += "-aspect %s -r %s " % (aspectratio, fps) + if (deinterlace == 1): + command += "-deinterlace " +- command += "-croptop %s -cropright %s -cropbottom %s -cropleft %s " % (croptop, cropright, cropbottom, cropleft) + command += "-s %s -b %s -vcodec mpeg2video " % (outvideores, outvideobitrate) + command += "-qmin %s -qmax %s -qdiff %s " % (qmin, qmax, qdiff) + command += "-ab %s -ar %s -acodec %s " % (outaudiobitrate, outaudiosamplerate, outaudiocodec) +@@ -2543,7 +2604,7 @@ + if (not(doesFileExist(os.path.join(folder, "audout")) and doesFileExist(os.path.join(folder, "vidout")))): + fatalError("Waited too long for mythtranscode to create the fifos - giving up!!") + +- write("Running ffmpeg") ++ write("Running ffmpeg: %s" % command) + result = runCommand(command) + if result != 0: + os.kill(PID, signal.SIGKILL) +@@ -4724,7 +4785,7 @@ + elif file.attributes["type"].value=="recording": + mediafile = file.attributes["filename"].value + elif file.attributes["type"].value=="video": +- mediafile=os.path.join(videopath, file.attributes["filename"].value) ++ mediafile = os.path.join(getVideoPath(file.attributes["filename"].value), file.attributes["filename"].value) + elif file.attributes["type"].value=="file": + mediafile=file.attributes["filename"].value + else: +@@ -4834,8 +4895,7 @@ + starttime = -1 + usecutlist = -1 + +- encodeNuvToMPEG2(chanid, starttime, mediafile, os.path.join(folder, "newfile2.mpg"), folder, +- profile, usecutlist) ++ encodeNuvToMPEG2(chanid, starttime, mediafile, os.path.join(folder, "newfile2.mpg"), folder, profile, usecutlist) + mediafile = os.path.join(folder, 'newfile2.mpg') + else: + #we need to re-encode the file, make sure we get the right video/audio streams +@@ -4861,8 +4921,7 @@ + profile = defaultEncodingProfile + + #do the re-encode +- encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video, +- audio1, audio2, aspectratio, profile) ++ encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video, folder, audio1, audio2, aspectratio, profile) + mediafile = os.path.join(folder, 'newfile2.mpg') + + #remove the old mediafile that was run through mythtranscode +@@ -4936,7 +4995,7 @@ + elif file.attributes["type"].value=="recording": + mediafile = file.attributes["filename"].value + elif file.attributes["type"].value=="video": +- mediafile=os.path.join(videopath, file.attributes["filename"].value) ++ mediafile = os.path.join(getVideoPath(file.attributes["filename"].value), file.attributes["filename"].value) + elif file.attributes["type"].value=="file": + mediafile=file.attributes["filename"].value + else: +@@ -4988,8 +5047,7 @@ + starttime = -1 + usecutlist = -1 + +- encodeNuvToMPEG2(chanid, starttime, mediafile, os.path.join(folder, "newfile2.mpg"), folder, +- profile, usecutlist) ++ encodeNuvToMPEG2(chanid, starttime, mediafile, os.path.join(folder, "newfile2.mpg"), folder, profile, usecutlist) + mediafile = os.path.join(folder, 'newfile2.mpg') + else: + #we need to re-encode the file, make sure we get the right video/audio streams +@@ -5015,8 +5073,7 @@ + profile = defaultEncodingProfile + + #do the re-encode +- encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video, +- audio1, audio2, aspectratio, profile) ++ encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video, folder, audio1, audio2, aspectratio, profile) + mediafile = os.path.join(folder, 'newfile2.mpg') + + #remove an intermediate file diff --git a/abs/core/mythtv/stable-0.25/mythplugins/mythplugins-mythzoneminder.install b/abs/core/mythtv/stable-0.25/mythplugins/mythplugins-mythzoneminder.install new file mode 100644 index 0000000..142212b --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythplugins/mythplugins-mythzoneminder.install @@ -0,0 +1,3 @@ +post_install() { + echo "If you want to use this plugin, install zoneminder from AUR." +} diff --git a/abs/core/mythtv/stable-0.25/mythtv/PKGBUILD b/abs/core/mythtv/stable-0.25/mythtv/PKGBUILD new file mode 100644 index 0000000..d4e4751 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/PKGBUILD @@ -0,0 +1,113 @@ +# $Id: PKGBUILD 91139 2010-09-23 10:45:09Z remy $ +# Maintainer: Giovanni Scafora +# Contributor: Juergen Hoetzel +# Contributor: +# Contributor: dorphell + +pkgname=mythtv +pkgver=0.25 +pkgrel=1 +pkgdesc="A Homebrew PVR project" +arch=('i686' 'x86_64') +url="http://www.mythtv.org/" +license=('GPL') +depends=('mysql-clients' 'qt' 'lame' 'lirc-utils' 'ffmpeg-svn' 'libxvmc' + 'fribidi' 'perl-soap-lite' 'perl-date-manip' 'perl-xml-sax' + 'perl-math-round' 'perl-net-upnp' 'perl-dbd-mysql' 'perl-time-hires' + 'libavc1394' 'wget' 'libiec61883' 'mysql-python' 'python-lxml' + 'mesa' 'libxinerama' 'libxrandr' 'faad2' 'libvdpau' 'libcrystalhd-git' + 'urlgrabber' 'python-pycurl' 'avahi' 'libcec') + +makedepends=('yasm' 'libgl' 'git' 'rsync') +replaces=() +groups=('pvr') +#backup=(/usr/share/mythtv/is.xml) +#options=(!strip) +#MAKEFLAGS="-j6" +install='mythtv.install' +patchs=('myth_settings.patch' 'git_version.patch') +optdepends=('xmltv: to download tv listings') +#replaces=('mythtv-contrib') +conflicts=('mythvideo') +source=('mythbackend' 'myth.sh' `echo ${patchs[@]:0}` + 'mythbackend.lr' 'mythfrontend.lr' 'pretty' ) + +#_gitroot="https://github.com/MythTV/mythtv.git" +#_gitname="${pkgname}" + +build() { + if [ -e ${srcdir}/mythtv ] + then + rm -rf ${srcdir}/mythtv + fi + + cd ${startdir} + msg "copy in mythtv src" + cp -rp ../git_src/mythtv/mythtv $srcdir + cd ${srcdir}/$pkgname + + # apply patches + + echo "--------------------------applying patches----------------------------------------------------" + for i in `echo ${patchs[@]:0} ` + do + echo applying $i + echo "-----------------------------" + patch -Np2 -i ${startdir}/src/$i || return 1 + done + echo "--------------------------done applying patches-----------------------------------------------" + + #sed -i -e "s/\`(svnversion \$\${SVNTREEDIR} 2>\/dev\/null) || echo Unknown\`/$pkgver/" version.pro + #find bindings/python contrib -type f | xargs sed -i 's@^#!.*python$@#!/usr/bin/python2@' + + ARCH=${CARCH/_/-} + ./configure --prefix=/usr --cpu=${ARCH} \ + --disable-audio-jack \ + --disable-audio-pulse \ + --disable-altivec \ + --disable-distcc \ + --disable-ccache \ + --enable-vdpau \ + --enable-crystalhd \ + --dvb-path=/usr/include \ + --with-bindings=perl,python --python=python2 || return 1 + + make all || return 1 +} + +package() { + cd "${srcdir}/${pkgname}" + # basic install + make INSTALL_ROOT="${pkgdir}" install + # install contrib files + rsync -arp --exclude .svn --delete-excluded contrib ${pkgdir}/usr/share/mythtv/ || return 1 + # install database structure + rsync -arp --exclude .svn --delete-excluded database ${pkgdir}/usr/share/mythtv/ || return 1 + # install docs + rsync -arp --exclude .svn --delete-excluded docs ${pkgdir}/usr/share/mythtv/ || return 1 + + # patch the xml LinHES style + cp -r ${startdir}/menu-xml/*.xml ${pkgdir}/usr/share/mythtv/themes/defaultmenu/ + mv ${pkgdir}/usr/share/mythtv/themes/defaultmenu/is.xml ${pkgdir}/usr/share/mythtv/ + cd ${pkgdir}/usr/share/mythtv +# patch -p0 < ${startdir}/menu-xml/mainmenu.xml.patch || return 1 +# patch -p0 < ${startdir}/menu-xml/optical_menu.xml.patch || return 1 +# patch -p0 < ${startdir}/menu-xml/library.xml.patch || return 1 + patch -p0 < ${startdir}/menu-xml/util_menu.xml.patch || return 1 + + # make log dir + mkdir -p ${pkgdir}/var/log/mythtv + chown 1000.1000 ${pkgdir}/var/log/mythtv + mkdir -p ${pkgdir}/etc/logrotate.d + cp ${srcdir}/*.lr ${pkgdir}/etc/logrotate.d + mkdir -p ${pkgdir}/etc/cron.hourly/ + install -m0755 ${srcdir}/pretty ${pkgdir}/etc/cron.hourly/ +} + +md5sums=('7ef6de58240e7aad389a0b13d91b1cf6' + '2babd4b8e146a7538d18dcd55695b0be' + '58ab374d2c51b577359ae77385ab3edf' + '03850677ea69ad83ccb92b4c0819224b' + 'f735805a80b0d1180dee01f9df1b7004' + 'f407d6af23e74a49540755420f84fa58' + '5469d9921b726db750b991c87d226158') diff --git a/abs/core/mythtv/stable-0.25/mythtv/__changelog b/abs/core/mythtv/stable-0.25/mythtv/__changelog new file mode 100644 index 0000000..940f84b --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/__changelog @@ -0,0 +1 @@ +update to 0.24-fixes diff --git a/abs/core/mythtv/stable-0.25/mythtv/git_version.patch b/abs/core/mythtv/stable-0.25/mythtv/git_version.patch new file mode 100644 index 0000000..8b1def8 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/git_version.patch @@ -0,0 +1,13 @@ +diff --git a/mythtv/version.sh b/mythtv/version.sh +index d2c53af..2cf971f 100755 +--- a/mythtv/version.sh ++++ b/mythtv/version.sh +@@ -22,7 +22,7 @@ GITREPOPATH="exported" + + cd ${GITTREEDIR} + +-SOURCE_VERSION=$(git describe --dirty || git describe || echo Unknown) ++SOURCE_VERSION=$(git describe | cut -d- -f 3 || echo Unknown) + + case "${SOURCE_VERSION}" in + exported|Unknown) diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/HOST_SETTINGS.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/HOST_SETTINGS.xml new file mode 100644 index 0000000..ac52497 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/HOST_SETTINGS.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/is.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/is.xml new file mode 100644 index 0000000..88b7e6b --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/is.xml @@ -0,0 +1,3 @@ + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/library.xml.patch b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/library.xml.patch new file mode 100644 index 0000000..be06e34 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/library.xml.patch @@ -0,0 +1,12 @@ +--- themes/defaultmenu/library.xml.orig 2010-11-06 00:39:51.000000000 +0000 ++++ themes/defaultmenu/library.xml 2010-11-06 00:44:54.000000000 +0000 +@@ -44,8 +44,7 @@ + STREAM + Play Online Streams + +- PLUGIN mythstream +- mythstream ++ MENU is.xml + + + + + + + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mainmenu.xml.patch b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mainmenu.xml.patch new file mode 100644 index 0000000..0491803 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mainmenu.xml.patch @@ -0,0 +1,37 @@ +--- themes/defaultmenu/mainmenu.xml.orig 2010-11-08 22:30:08.000000000 +0000 ++++ themes/defaultmenu/mainmenu.xml 2010-11-08 22:35:51.000000000 +0000 +@@ -2,6 +2,13 @@ + + + ++ ++ + + +- +- + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythbackup.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythbackup.xml new file mode 100644 index 0000000..5914b33 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythbackup.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythrestore.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythrestore.xml new file mode 100644 index 0000000..8f5c285 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythrestore.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/optical_menu.xml.patch b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/optical_menu.xml.patch new file mode 100644 index 0000000..143424f --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/optical_menu.xml.patch @@ -0,0 +1,16 @@ +--- themes/defaultmenu/optical_menu.xml.orig 2010-11-06 00:39:43.000000000 +0000 ++++ themes/defaultmenu/optical_menu.xml 2010-11-06 00:42:59.000000000 +0000 +@@ -26,6 +26,13 @@ + + + ++ ++ + + + + + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/siriusmenu.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/siriusmenu.xml new file mode 100644 index 0000000..e317b36 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/siriusmenu.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/update.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/update.xml new file mode 100644 index 0000000..d2ac3fe --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/update.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/update2.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/update2.xml new file mode 100644 index 0000000..64388cb --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/update2.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/util_menu.xml.patch b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/util_menu.xml.patch new file mode 100644 index 0000000..82d303e --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/util_menu.xml.patch @@ -0,0 +1,16 @@ +--- themes/defaultmenu/util_menu.xml.orig 2010-11-06 00:40:01.000000000 +0000 ++++ themes/defaultmenu/util_menu.xml 2010-11-06 00:45:42.000000000 +0000 +@@ -17,6 +17,13 @@ + + + ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/abs/core/mythtv/stable-0.25/mythtv/myth.sh b/abs/core/mythtv/stable-0.25/mythtv/myth.sh new file mode 100644 index 0000000..fb7122c --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/myth.sh @@ -0,0 +1,4 @@ +export PATH=$PATH:/usr/local/bin +# set core file size to 0 +ulimit -c 0 +export MALLOC_CHECK_=0 \ No newline at end of file diff --git a/abs/core/mythtv/stable-0.25/mythtv/myth_settings.patch b/abs/core/mythtv/stable-0.25/mythtv/myth_settings.patch new file mode 100644 index 0000000..abdabfe --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/myth_settings.patch @@ -0,0 +1,1816 @@ +diff --git a/mythtv/libs/libmythbase/mythcorecontext.cpp b/mythtv/libs/libmythbase/mythcorecontext.cpp +index ad58f59..809d662 100644 +--- a/mythtv/libs/libmythbase/mythcorecontext.cpp ++++ b/mythtv/libs/libmythbase/mythcorecontext.cpp +@@ -1260,6 +1260,90 @@ void MythCoreContext::ResetLanguage(void) + d->language.clear(); + } + ++//JM ADDED ++void MythCoreContext::savesettings_togroup (QString src_hostname, ++ QString saved_settingsgroupname ) ++{ ++ return d->m_database->savesettings_togroup(src_hostname, ++ saved_settingsgroupname); ++} ++ ++void MythCoreContext::deletesettings(QString delete_hostname, ++ QString saved_settingsgroupname) ++{ ++ return d->m_database->deletesettings(delete_hostname, ++ saved_settingsgroupname); ++} ++ ++QMap MythCoreContext::list_settingsgroupname() ++{ ++ return d->m_database->list_settingsgroupname(); ++} ++ ++QMap MythCoreContext::diff_settingsgroupname( ++ QString diff_hostname1, ++ QString diff_hostname2, ++ QStringList table_list) ++{ ++ return d->m_database->diff_settingsgroupname(diff_hostname1, ++ diff_hostname2, ++ table_list); ++} ++ ++void MythCoreContext::clonesettings(QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list, ++ bool is_full_clone, ++ QString dest_hostname) ++{ ++ return d->m_database->clonesettings(src_hostname, ++ saved_settingsgroupname, ++ table_list, ++ is_full_clone, ++ dest_hostname); ++} ++ ++void MythCoreContext::restoresettings(QString dest_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list ) ++{ ++ return d->m_database->restoresettings( dest_hostname, ++ saved_settingsgroupname, ++ table_list); ++} ++ ++void MythCoreContext::change_hostname(QString old_hostname, ++ QString new_hostname) ++{ ++ return d->m_database->change_hostname(old_hostname, new_hostname) ; ++} ++ ++bool MythCoreContext::settings_check(QString src_hostname, ++ QString saved_settingsgroupname) ++{ ++ return d->m_database->settings_check(src_hostname,saved_settingsgroupname); ++} ++ ++void MythCoreContext::import_settings(QMap vp_map, ++ QString table) ++{ ++ return d->m_database->import_settings(vp_map, table); ++} ++ ++ ++QMap > MythCoreContext::export_settings( ++ QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list) ++{ ++ return d->m_database->export_settings(src_hostname, ++ saved_settingsgroupname, ++ table_list); ++} ++ ++//END JM ADDED ++ ++ + void MythCoreContext::InitLocale(void ) + { + if (!d->m_locale) +diff --git a/mythtv/libs/libmythbase/mythcorecontext.h b/mythtv/libs/libmythbase/mythcorecontext.h +index 0917313..db3bbb9 100644 +--- a/mythtv/libs/libmythbase/mythcorecontext.h ++++ b/mythtv/libs/libmythbase/mythcorecontext.h +@@ -168,6 +168,39 @@ class MBASE_PUBLIC MythCoreContext : public MythObservable, public MythSocketCBs + QString GetLanguageAndVariant(void); + void ResetLanguage(void); + ++ //JM ADDED ++ void savesettings_togroup(QString src_hostname, ++ QString saved_settingsgroupname ); ++ ++ void deletesettings(QString delete_hostname, ++ QString saved_settingsgroupname); ++ ++ QMap list_settingsgroupname(); ++ QMap diff_settingsgroupname(QString diff_hostname1, ++ QString diff_hostname2, ++ QStringList table_list); ++ ++ void clonesettings(QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list, ++ bool is_full_clone=TRUE, ++ QString dest_hostname=""); ++ ++ void restoresettings (QString dest_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list); ++ ++ void change_hostname (QString old_hostname, QString new_hostname); ++ ++ bool settings_check (QString src_hostname ,QString saved_settingsgroupname); ++ void import_settings(QMap vp_map, QString table); ++ ++ QMap > export_settings( ++ QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list); ++ //END JM ADDED ++ + private: + MythCoreContextPrivate *d; + +diff --git a/mythtv/libs/libmythbase/mythdb.cpp b/mythtv/libs/libmythbase/mythdb.cpp +index ea30783..730fc3e 100644 +--- a/mythtv/libs/libmythbase/mythdb.cpp ++++ b/mythtv/libs/libmythbase/mythdb.cpp +@@ -774,7 +774,7 @@ void MythDB::OverrideSettingForSession( + QString mk = key.toLower(), mk2 = d->m_localhostname + ' ' + mk, mv = value; + if ("dbschemaver" == mk) + { +- LOG(VB_GENERAL, LOG_ERR, ++ LOG(VB_GENERAL, LOG_ERR, + QString("ERROR: Refusing to allow override for '%1'.").arg(key)); + return; + } +@@ -1055,6 +1055,901 @@ void MythDB::WriteDelayedSettings(void) + } + } + ++//JM ADDED ++void MythDB::savesettings_togroup(QString src_hostname, ++ QString saved_settingsgroupname ) ++{ ++ LOG(VB_GENERAL, LOG_ERR, QString("Using hostname of : %1") ++ .arg(src_hostname)); ++ LOG(VB_GENERAL, LOG_ERR, QString("Saving to group: %1") ++ .arg(saved_settingsgroupname)); ++ if ( settings_check( src_hostname , "current" ) ) ++ { ++ QStringList table_list; ++ QString hostname_clause; ++ table_list.append("settings"); ++ table_list.append("keybindings"); ++ if ( src_hostname == "GLOBAL" ) ++ hostname_clause = "hostname IS NULL"; ++ else ++ hostname_clause ="hostname = :HOSTNAME"; ++ ++ foreach (QString table, table_list) ++ { ++ QString dest_tablename = table +"_" + saved_settingsgroupname ; ++ create_new_table(dest_tablename,table); ++ ++ QString query_string; ++ // Remove old saved values ++ MSqlQuery query(MSqlQuery::InitCon()); ++ query_string = QString("DELETE FROM %1 WHERE %2") ++ .arg(dest_tablename) ++ .arg(hostname_clause); ++ ++ //query_string = QString("DELETE FROM %1 WHERE " ++ // "hostname = :HOSTNAME").arg(dest_tablename); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME" ,src_hostname); ++ query.exec(); ++ ++ //insert all new settings ++ query_string = QString("REPLACE INTO %1 " ++ "SELECT * from %2 where %3") ++ .arg(dest_tablename) ++ .arg(table) ++ .arg(hostname_clause); ++// query_string = QString("REPLACE INTO %1 " ++// "SELECT * from %2 where hostname = :HOSTNAME)") ++// .arg(dest_tablename) ++// .arg(table); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME",src_hostname); ++ query.exec(); ++ } ++ } ++ else ++ LOG(VB_GENERAL| VB_STDIO|VB_FLUSH, LOG_ERR, ++ QString("Couldn't find settings for: %1 \n").arg(src_hostname)); ++ return; ++ ++}; ++ ++void MythDB::deletesettings(QString delete_hostname, ++ QString saved_settingsgroupname) ++{ ++ LOG(VB_GENERAL, LOG_ERR, QString("Using hostname of : %1") ++ .arg(delete_hostname)); ++ LOG(VB_GENERAL, LOG_ERR, QString("Deleting: %1") ++ .arg(saved_settingsgroupname)); ++ int tempItem; ++ QString src_tablename; ++ QStringList table_list; ++ ++ table_list.append("settings"); ++ table_list.append("keybindings"); ++ QString hostname_clause; ++ if ( delete_hostname == "GLOBAL" ) ++ hostname_clause = "hostname IS NULL"; ++ else ++ hostname_clause ="hostname = :HOSTNAME"; ++ ++ foreach (QString table, table_list) ++ { ++ src_tablename = find_group_table_name(table, saved_settingsgroupname); ++ MSqlQuery query(MSqlQuery::InitCon()); ++ // Remove old saved values ++ if ( does_table_exist(src_tablename)) ++ { ++ QString query_string = QString("DELETE from %1 " ++ "WHERE %2") ++ .arg(src_tablename) ++ .arg(hostname_clause); ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME" ,delete_hostname); ++ query.exec(); ++ ++ //check if ok to delete table ++ query_string = QString("SELECT count(*) from %1") ++ .arg(src_tablename); ++ query.prepare(query_string); ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ query.next(); ++ tempItem = query.value(0).toInt(); ++ if ( tempItem == 0 ) ++ drop_temp_table(src_tablename); ++ } ++ } ++ else ++ LOG(VB_GENERAL, LOG_ERR, ++ QString("Couldn't find table: %1").arg(src_tablename)); ++ } ++ return; ++}; // end delete settings ++ ++ ++QMap MythDB::list_settingsgroupname() ++{ ++ //Returns a QMAP of "settings_groups: hostname" ++ MSqlQuery query(MSqlQuery::InitCon()); ++ MSqlQuery subquery(MSqlQuery::InitCon()); ++ QString tempItem; ++ QString temp_hostnameItem; ++ QStringList hostname_list; ++ QMap return_list; ++ QString full_table_name; ++ query.prepare( "show tables like \"settings%\" " ); ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ while (query.next()) ++ { ++ full_table_name = query.value(0).toString(); ++ tempItem=query.value(0).toString().remove(QRegExp("settings_")); ++ if ( tempItem != "distro_default" ) ++ { ++ //loop over tables looking for hostnames ++ QString query_string = QString("SELECT DISTINCT " ++ "hostname from %1") ++ .arg(full_table_name); ++ subquery.prepare(query_string); ++ ++ if (subquery.exec() && subquery.isActive() ++ && subquery.size() > 0) ++ { ++ while (subquery.next()) ++ { ++ temp_hostnameItem = subquery.value(0).toString(); ++ hostname_list.append(temp_hostnameItem); ++ } ++ } ++ //Special case of naming for the settings table; ++ //This only affects output. ++ if ( tempItem == "settings" ) ++ return_list["current"] = hostname_list; ++ else ++ return_list[tempItem] = hostname_list; ++ ++ //reset hostname_list for the next group ++ hostname_list = QStringList(); ++ } ++ } ++ } ++ return return_list; ++}; // end list_settingsgroupname ++ ++QMap MythDB::diff_settingsgroupname( ++ QString diff_hostname1 , ++ QString diff_hostname2, ++ QStringList table_list ) ++{ ++ // Returns a QMAP of tablename : diff results ++ LOG(VB_GENERAL, LOG_ERR, QString("Comparing settings for:")); ++ LOG(VB_GENERAL, LOG_ERR, QString("host 1: %1").arg(diff_hostname1)); ++ LOG(VB_GENERAL, LOG_ERR, QString("host 2: %1").arg(diff_hostname2)); ++ ++ QString qstr; ++ QString tempItem; ++ QString tempString; ++ ++ QStringList diff_list; ++ QStringList settings_list; ++ QStringList keybinding_list; ++ ++ QMap return_list; ++ if ( table_list.isEmpty() ) ++ { ++ table_list.append("settings"); ++ table_list.append("keybindings"); ++ } ++ ++ MSqlQuery query(MSqlQuery::InitCon()); ++ foreach (QString table, table_list) ++ { ++ if ( table == "settings") ++ { ++ ++ qstr= "SELECT distinct settings.value, :DIFF_HOSTNAME1 AS `hostname`, settings_a.data, :DIFF_HOSTNAME2 AS `hostname`" ++ " , settings_b.data FROM settings LEFT JOIN settings AS settings_a ON settings_a.value = settings.value AND settings_a.hostname = :DIFF_HOSTNAME1" ++ " LEFT JOIN settings AS settings_b ON settings_b.value = settings.value AND settings_b.hostname = :DIFF_HOSTNAME2" ++ " WHERE settings_a.data != settings_b.data OR " ++ " (settings_a.data IS NULL AND settings_b.data IS NOT NULL) OR (settings_a.data IS NOT NULL AND settings_b.data IS NULL);"; ++ ++ query.prepare(qstr); ++ query.bindValue(":DIFF_HOSTNAME1" , diff_hostname1); ++ query.bindValue(":DIFF_HOSTNAME2" , diff_hostname2); ++ ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ while (query.next()) ++ { ++ tempString=""; ++ //value ++ tempItem = query.value(0).toString(); ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //hostname_1 ++ tempItem = query.value(1).toString(); ++ if (tempItem.isEmpty()) ++ tempItem=diff_hostname1; ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //data ++ tempItem = query.value(2).toString(); ++ if (tempItem.isEmpty()) ++ tempItem="NULL"; ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //hostname_2 ++ tempItem = query.value(3).toString(); ++ if (tempItem.isEmpty()) ++ tempItem=diff_hostname2; ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //data ++ tempItem = query.value(4).toString(); ++ if (tempItem.isEmpty()) ++ tempItem="NULL"; ++ tempString.append(tempItem); ++ ++ settings_list.append(tempString); ++ } ++ return_list["Settings"] = settings_list; ++ } ++ } ++ else if ( table == "keybindings") ++ { ++ ++ qstr="SELECT distinct keybindings.context, keybindings.action, :DIFF_HOSTNAME1 AS `hostname`, keybindings_a.keylist, :DIFF_HOSTNAME2 AS `hostname`, keybindings_b.keylist FROM keybindings " ++ " LEFT JOIN keybindings AS keybindings_a ON keybindings_a.context = keybindings.context AND keybindings_a.action = keybindings.action " ++ " AND keybindings_a.hostname = :DIFF_HOSTNAME1 " ++ " LEFT JOIN keybindings AS keybindings_b ON keybindings_b.context = keybindings.context " ++ " AND keybindings_b.action = keybindings.action AND keybindings_b.hostname = :DIFF_HOSTNAME2 " ++ " WHERE keybindings_a.keylist != keybindings_b.keylist OR " ++ " (keybindings_a.keylist IS NULL AND keybindings_b.keylist IS NOT NULL) OR (keybindings_a.keylist IS NOT NULL AND keybindings_b.keylist IS NULL);"; ++ query.prepare(qstr); ++ query.bindValue(":DIFF_HOSTNAME1" , diff_hostname1); ++ query.bindValue(":DIFF_HOSTNAME2" , diff_hostname2); ++ ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ while (query.next()) ++ { ++ tempString=""; ++ //context ++ tempItem = query.value(0).toString(); ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //action ++ tempItem = query.value(1).toString(); ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //hostname ++ tempItem = query.value(2).toString(); ++ if (tempItem.isEmpty()) ++ tempItem=diff_hostname1; ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //keylist ++ tempItem = query.value(3).toString(); ++ if (tempItem.isEmpty()) ++ tempItem="NULL"; ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //hostname ++ tempItem = query.value(4).toString(); ++ if (tempItem.isEmpty()) ++ tempItem=diff_hostname2; ++ tempString.append(tempItem); ++ tempString.append("|"); ++ ++ //keylist ++ tempItem = query.value(5).toString(); ++ if (tempItem.isEmpty()) ++ tempItem="NULL"; ++ tempString.append(tempItem); ++ keybinding_list.append(tempString); ++ } ++ return_list["Keybindings"] = keybinding_list; ++ } ++ } ++ ++ } ++ return return_list; ++}; //end diff_settingsgroupname ++ ++void MythDB::clonesettings(QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list, ++ bool is_full_clone, QString dest_hostname) ++{ ++ LOG(VB_GENERAL, LOG_ERR, QString("Using src hostname of : %1") ++ .arg(src_hostname)); ++ LOG(VB_GENERAL, LOG_ERR, QString("Using dest hostname of : %1") ++ .arg(dest_hostname)); ++ LOG(VB_GENERAL, LOG_ERR, QString("Cloning setting group: %1") ++ .arg(saved_settingsgroupname)); ++ LOG(VB_GENERAL, LOG_ERR, QString("Full Copy : %1") ++ .arg(is_full_clone)); ++ ++ MSqlQuery query(MSqlQuery::InitCon()); ++ QStringList::Iterator it; ++ QString current_table; ++ QString dest_tablename; ++ QString temptable; ++ ++ if ( table_list.isEmpty() ) ++ { ++ table_list.append("settings"); ++ table_list.append("keybindings"); ++ } ++ ++ for ( it = table_list.begin(); it != table_list.end(); ++it ) ++ { ++ current_table = *it ; ++ dest_tablename = find_group_table_name(current_table, ++ saved_settingsgroupname); ++ ++ if ( does_table_exist(dest_tablename)) ++ { ++ // create temp table for merging settings ++ temptable="temp_table_" + dest_tablename; ++ create_temp_table(temptable, current_table ); ++ ++ // copy in stored settings ++ QString query_string = QString("REPLACE INTO %1 " ++ "(SELECT * from %2 where hostname = :HOSTNAME)") ++ .arg(temptable) ++ .arg(dest_tablename); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME",src_hostname ); ++ query.exec(); ++ ++ // update hostname for dest_hostname ++ query_string = QString("UPDATE %1 set hostname = :HOSTNAME") ++ .arg(temptable); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME" , dest_hostname ); ++ query.exec(); ++ ++ //if not full clone remove HOST% settings from temp table; ++ if ( current_table == "settings" && !is_full_clone) ++ { ++ query_string = QString("DELETE FROM %1 WHERE " ++ "hostname=:HOSTNAME and value like 'HOST%' " ) ++ .arg(temptable); ++ ++ query.prepare(query_string); ++ query.bindValue( ":HOSTNAME" , dest_hostname ); ++ query.exec(); ++ } ++ ++ //remove current settings from dest table, ++ //if not full clone, then leave HOST% ++ //Need to remove because the old table allows for duplicates ++ ++ if ( current_table == "settings" && !is_full_clone) ++ query_string = QString ("DELETE FROM %1 WHERE " ++ "hostname = :HOSTNAME " ++ "and value not like 'HOST%'") ++ .arg(dest_tablename); ++ ++ else ++ query_string = QString ("DELETE FROM %1 WHERE " ++ "hostname = :HOSTNAME ") ++ .arg(dest_tablename); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME",dest_hostname); ++ query.exec(); ++ ++ // copy new settings from temp to current ++ query_string = QString("REPLACE INTO %1 " ++ "(SELECT * from %2)") ++ .arg(dest_tablename) ++ .arg(temptable); ++ ++ query.prepare(query_string); ++ query.exec(); ++ ++ // drop temptable ++ drop_temp_table(temptable); ++ } ++ else ++ LOG(VB_GENERAL, LOG_NOTICE, QString("Couldn't find table: %1") ++ .arg(dest_tablename)); ++ } ++}; //end clonesettings ++ ++void MythDB::restoresettings (QString dest_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list ) ++{ ++ LOG(VB_GENERAL, LOG_NOTICE, QString("Restoring Settings:")); ++ LOG(VB_GENERAL, LOG_NOTICE, QString(" src: %1") ++ .arg(saved_settingsgroupname)); ++ LOG(VB_GENERAL, LOG_NOTICE, QString(" dest:%1") ++ .arg(dest_hostname)); ++ ++ QString hostname_clause; ++ if ( dest_hostname == "GLOBAL" ) ++ hostname_clause = "hostname IS NULL"; ++ else ++ hostname_clause ="hostname = :HOSTNAME"; ++ ++ if ( settings_check ( dest_hostname , saved_settingsgroupname ) ) ++ { ++ MSqlQuery query(MSqlQuery::InitCon()); ++ QStringList::Iterator it; ++ QString current_table; ++ if ( table_list.isEmpty() ) ++ { ++ table_list.append("settings"); ++ table_list.append("keybindings"); ++ } ++ ++ for ( it = table_list.begin(); it != table_list.end(); ++it ) ++ { ++ current_table = *it ; ++ //find tablenames to use ++ QString src_tablename = find_group_table_name(current_table, ++ saved_settingsgroupname); ++ ++ QString temptable="temp_table_" + src_tablename; ++ ++ // create temp table for merging settings ++ create_temp_table(temptable, current_table ); ++ ++ //could copy in current settings here to account for new stuff ++ ++ // copy in stored settings ++ QString query_string = QString("REPLACE INTO %1 " ++ "(SELECT * from %2 WHERE %3)") ++ .arg(temptable) ++ .arg(src_tablename) ++ .arg(hostname_clause); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME",dest_hostname ); ++ query.exec(); ++ ++ //Remove current settings. ++ //Need to remove because the old table allows for duplicates ++ query_string = QString("DELETE FROM %1 WHERE " ++ "%2") ++ .arg(current_table) ++ .arg(hostname_clause); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME",dest_hostname); ++ query.exec(); ++ ++ // copy new settings from temp to current ++ query_string = QString("REPLACE INTO %1 " ++ "(SELECT * from %2)") ++ .arg(current_table) ++ .arg(temptable); ++ ++ query.prepare(query_string); ++ query.exec(); ++ // drop temptable ++ drop_temp_table(temptable); ++ } ++ } ++}; //end restore settings ++ ++void MythDB::change_hostname (QString old_hostname, QString new_hostname) ++{ ++ LOG(VB_GENERAL, LOG_NOTICE, QString("Changing hostname from %1 -> %2") ++ .arg(old_hostname) ++ .arg(new_hostname)); ++ ++ MSqlQuery query(MSqlQuery::InitCon()); ++ MSqlQuery sub_query(MSqlQuery::InitCon()); ++ query.prepare( "SHOW TABLES" ); ++ ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ while (query.next()) ++ { ++ QString table_name = query.value(0).toString(); ++ LOG(VB_GENERAL, LOG_NOTICE, QString("Scanning %1") ++ .arg(table_name)); ++ ++ // LOOP OVER TABLES, CHECK IF IT HAS A HOSTNAME FIELD ++ QString query_string=QString("SHOW COLUMNS from %1 " ++ "where field='hostname'") ++ .arg(table_name); ++ sub_query.prepare(query_string); ++ ++ if (sub_query.exec() && sub_query.size() > 0) ++ { //update hostname ++ LOG(VB_GENERAL, LOG_NOTICE, QString(" Updating hostname in: %1") ++ .arg(table_name)); ++ query_string = QString("UPDATE %1 SET hostname = :NEW_HOSTNAME " ++ "WHERE hostname = :OLD_HOSTNAME") ++ .arg(table_name); ++ sub_query.prepare(query_string); ++ sub_query.bindValue(":NEW_HOSTNAME" , new_hostname); ++ sub_query.bindValue(":OLD_HOSTNAME" , old_hostname); ++ sub_query.exec(); ++ } ++ } ++ } ++ ++ ++ ++ ++ ++ ++} ++ ++bool MythDB::settings_check(QString src_hostname, ++ QString saved_settingsgroupname) ++{ ++ int tempItem; ++ bool returncode = FALSE ; ++ QString table="settings"; ++ ++ QString tablename = find_group_table_name(table, saved_settingsgroupname); ++ QString hostname_clause; ++ if ( src_hostname == "GLOBAL" ) ++ hostname_clause = "hostname IS NULL"; ++ else ++ hostname_clause ="hostname = :HOSTNAME"; ++ ++ if (does_table_exist (tablename)) ++ { ++ MSqlQuery query(MSqlQuery::InitCon()); ++ QString query_string = QString("SELECT COUNT(data) from %1 " ++ "WHERE %2") ++ .arg(tablename) ++ .arg(hostname_clause); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME" , src_hostname ); ++ ++ if (query.exec() && query.isActive() && query.size() > 0 ) ++ { ++ while (query.next()) ++ { ++ tempItem = query.value(0).toInt(); ++ if ( tempItem >= 1 ) ++ returncode = TRUE; ++ else ++ { ++ LOG(VB_GENERAL, LOG_NOTICE, ++ QString("Group %1 does not contain" ++ " valid settings") ++ .arg(saved_settingsgroupname)); ++ } ++ } ++ } ++ } ++ else ++ LOG(VB_GENERAL, LOG_NOTICE, QString("Couldn't find table: %1") ++ .arg(tablename)); ++ return returncode; ++}; // end settings_check ++ ++void MythDB::import_settings(QMap vp_map, ++ QString table) ++{ ++ MSqlQuery query(MSqlQuery::InitCon()); ++ ++ //IMPORT SETTINGS TABLE ++ if (table.startsWith("settings")) ++ { ++ if ( table != "settings" ) ++ create_new_table(table,"settings"); ++ QString hostname = vp_map.value("hostname"); ++ QString value = vp_map.value("value"); ++ QString data = vp_map.value("data"); ++ ++ QString hostname_clause; ++ QVariant import_hostname = QVariant(QVariant::String); ++ ++ if ( hostname.isEmpty()) ++ hostname_clause = "hostname IS NULL"; ++ else ++ { ++ hostname_clause ="hostname = :HOSTNAME"; ++ import_hostname = hostname; ++ } ++ ++ QString query_string=QString("SELECT value, data, hostname " ++ "FROM %1 " ++ "WHERE %2 AND value = :VALUE " ++ "ORDER BY value") ++ .arg(table) ++ .arg(hostname_clause); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME", hostname); ++ query.bindValue(":VALUE", value); ++ ++ // if already exisiting records then update, otherwise insert ++ if (query.exec() && query.isActive()) ++ { ++ MSqlQuery sub_query(MSqlQuery::InitCon()); ++ if ( query.size() > 0 ) ++ { ++ query_string = QString("UPDATE " ++ "%1 " ++ "set data = :DATA " ++ "WHERE %2 AND " ++ "value = :VALUE ") ++ .arg(table) ++ .arg(hostname_clause); ++ ++ sub_query.prepare(query_string); ++ sub_query.bindValue(":HOSTNAME", import_hostname); ++ sub_query.bindValue(":VALUE", value); ++ sub_query.bindValue(":DATA", data); ++ sub_query.exec(); ++ } ++ else ++ { ++ query_string = QString("INSERT INTO " ++ " %1 " ++ "(value,data,hostname) " ++ "VALUES ( :VALUE , :DATA , :HOSTNAME)").arg(table); ++ ++ sub_query.prepare(query_string); ++ sub_query.bindValue(":HOSTNAME", import_hostname); ++ sub_query.bindValue(":VALUE", value); ++ sub_query.bindValue(":DATA", data); ++ sub_query.exec(); ++ } ++ } ++ } ++ //KEYBINDINGS TABLE ++ else if (table.startsWith("keybindings")) ++ { ++ if ( table != "keybindings" ) ++ create_new_table(table,"keybindings"); ++ QString hostname = vp_map.value("hostname"); ++ QString context = vp_map.value("context"); ++ QString action = vp_map.value("action"); ++ QString description = vp_map.value("description"); ++ QString keylist = vp_map.value("keylist"); ++ ++ QString query_string=QString("SELECT context,action,hostname " ++ "FROM %1 " ++ "WHERE hostname = :HOSTNAME AND " ++ "context = :CONTEXT " ++ "AND action = :ACTION ").arg(table); ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME", hostname); ++ query.bindValue(":CONTEXT", context); ++ query.bindValue(":ACTION", action); ++ ++ if (query.exec() && query.isActive()) ++ { ++ MSqlQuery sub_query(MSqlQuery::InitCon()); ++ if ( query.size() > 0 ) ++ { ++ query_string = QString("UPDATE " ++ " %1 " ++ "set keylist = :KEYLIST " ++ "WHERE hostname = :HOSTNAME AND " ++ "context = :CONTEXT " ++ "AND action = :ACTION ").arg(table); ++ ++ sub_query.prepare(query_string); ++ sub_query.bindValue(":HOSTNAME", hostname); ++ sub_query.bindValue(":KEYLIST", keylist); ++ sub_query.bindValue(":CONTEXT", context); ++ sub_query.bindValue(":ACTION", action); ++ sub_query.exec(); ++ } ++ else ++ { ++ query_string = QString("INSERT INTO " ++ " %1 " ++ " (context , action , description , keylist , hostname) " ++ " VALUES( " ++ " :CONTEXT ," ++ " :ACTION , " ++ " :DESCRIPTION , " ++ " :KEYLIST , " ++ " :HOSTNAME)").arg(table) ; ++ ++ sub_query.prepare(query_string); ++ sub_query.bindValue(":HOSTNAME", hostname); ++ sub_query.bindValue(":KEYLIST", keylist); ++ sub_query.bindValue(":CONTEXT", context); ++ sub_query.bindValue(":ACTION", action); ++ sub_query.bindValue(":DESCRIPTION", description); ++ sub_query.exec(); ++ } ++ } ++ } ++ ++}; //end import_settings ++ ++QMap > ++ MythDB::export_settings(QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list) ++{ ++ QMap > result_set; ++ QStringList::Iterator it; ++ QString current_table; ++ int record_count = 0; ++ ++ if ( table_list.isEmpty() ) ++ { ++ table_list.append("settings"); ++ table_list.append("keybindings"); ++ } ++ ++ MSqlQuery query(MSqlQuery::InitCon()); ++ QString query_string; ++ ++ //loop over tablelist ++ for ( it = table_list.begin(); it != table_list.end(); ++it ) ++ { ++ current_table = *it ; ++ QString sub_sql; ++ QStringList fields; ++ QString field_query; ++ ++ QString table_name = find_group_table_name(current_table, ++ saved_settingsgroupname); ++ ++ QString hostname_clause; ++ if ( src_hostname == "GLOBAL" ) ++ hostname_clause = "hostname IS NULL"; ++ else ++ hostname_clause ="hostname = :HOSTNAME"; ++ // find field names ++ query_string = QString("SHOW COLUMNS from %1").arg(table_name); ++ query.prepare(query_string); ++ ++ //build up field name vars ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ while (query.next()) ++ { ++ if (! field_query.isEmpty()) ++ field_query +=','; ++ QString tempItem = query.value(0).toString(); ++ fields.append(tempItem); ++ field_query += tempItem; ++ } ++ } ++ ++ query_string = QString("SELECT %1 FROM %2 WHERE %3") ++ .arg(field_query) ++ .arg(table_name) ++ .arg(hostname_clause); ++ ++ query.prepare(query_string); ++ query.bindValue(":HOSTNAME" , src_hostname); ++ ++ //looping over each record in the table query ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ while (query.next()) ++ { ++ //construct qmap of elements ++ //add table name ++ QMap value_pair; ++ value_pair["table"]=table_name; ++ ++ for ( int i=0 ; i < fields.size();i++ ) ++ { ++ QString tempvalue = fields[i]; ++ QString tempItem = query.value(i).toString(); ++ value_pair[tempvalue]=tempItem; ++ } ++ result_set[QString(record_count)] = value_pair; ++ record_count++; ++ } ++ } ++ ++ } // end table loop ++ return result_set; ++}; //end export_settings ++ ++ ++void MythDB::create_new_table (QString create_table_name,QString like_name) ++{ ++ if ( ! does_table_exist(create_table_name)) ++ { ++ MSqlQuery query(MSqlQuery::InitCon()); ++ QString query_string = QString("CREATE TABLE %1 like %2") ++ .arg(create_table_name) ++ .arg(like_name); ++ ++ query.prepare(query_string); ++ query.exec(); ++ } ++ else ++ LOG(VB_GENERAL, LOG_NOTICE, QString("Table is already present," ++ "will not create it: %1") ++ .arg(create_table_name)); ++}; ++ ++ ++void MythDB::drop_temp_table (QString table_name) ++{ ++ MSqlQuery query(MSqlQuery::InitCon()); ++ if (table_name == "settings" | table_name == "keybindings") ++ return; ++ QString query_string = QString("DROP TABLE %1").arg(table_name); ++ query.prepare(query_string); ++ query.exec(); ++ return; ++} ++ ++void MythDB::create_temp_table (QString create_table_name,QString like_name) ++{ ++ MSqlQuery query(MSqlQuery::InitCon()); ++ create_new_table(create_table_name,like_name); ++ QString query_string; ++ if ( like_name == "settings") ++ { ++ query_string = QString ("ALTER TABLE %1 ADD UNIQUE( value)") ++ .arg(create_table_name); ++ query.prepare(query_string); ++ query.exec(); ++ } ++ ++ query_string = QString("TRUNCATE %1").arg(create_table_name); ++ query.prepare(query_string); ++ query.exec(); ++ return; ++} ++ ++bool MythDB::does_table_exist(QString table_name) ++{ ++ bool table_exist = FALSE; ++ QString full_table_name; ++ MSqlQuery query(MSqlQuery::InitCon()); ++ ++ query.prepare( "SHOW TABLES" ); ++ if (query.exec() && query.isActive() && query.size() > 0) ++ { ++ while (query.next()) ++ { ++ full_table_name = query.value(0).toString(); ++ if (table_name == full_table_name) ++ { ++ table_exist = TRUE; ++ break; ++ } ++ } ++ } ++ return table_exist; ++}; ++ ++ ++QString MythDB::find_group_table_name(QString current_table, ++ QString saved_settingsgroupname) ++{ ++ QString table_name; ++ if ( saved_settingsgroupname.toLower() == "current" ) ++ table_name = current_table ; ++ else ++ table_name = current_table + "_" + saved_settingsgroupname ; ++ ++ return table_name; ++}; ++//END JM ADDED ++ + /** + * \brief Set a flag indicating we have successfully connected to the database + */ +diff --git a/mythtv/libs/libmythbase/mythdb.h b/mythtv/libs/libmythbase/mythdb.h +index 79abe56..fe3c91c 100644 +--- a/mythtv/libs/libmythbase/mythdb.h ++++ b/mythtv/libs/libmythbase/mythdb.h +@@ -75,6 +75,48 @@ class MBASE_PUBLIC MythDB + + void WriteDelayedSettings(void); + ++ //JM ADDED ++ void savesettings_togroup(QString src_hostname, ++ QString saved_settingsgroupname ); ++ void deletesettings(QString delete_hostname, ++ QString saved_settingsgroupname); ++ ++ QMap list_settingsgroupname(); ++ ++ QMap diff_settingsgroupname(QString diff_hostname1, ++ QString diff_hostname2, ++ QStringList table_list); ++ ++ void clonesettings(QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list, ++ bool is_full_clone=TRUE, ++ QString dest_hostname=""); ++ ++ void restoresettings (QString dest_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list); ++ ++ void change_hostname (QString old_hostname, QString new_hostname); ++ bool settings_check (QString src_hostname, QString saved_settingsgroupname); ++ void import_settings(QMap vp_map, QString table); ++ ++ ++ QMap > export_settings( ++ QString src_hostname, ++ QString saved_settingsgroupname, ++ QStringList table_list); ++ ++ void create_new_table (QString create_table_name,QString like_name); ++ void drop_temp_table (QString table_name); ++ void create_temp_table (QString create_table_name,QString like_name); ++ bool does_table_exist(QString table_name); ++ QString find_group_table_name(QString current_table, ++ QString saved_settingsgroupname); ++ //END JM ADDED ++ ++ ++ + void SetHaveDBConnection(bool connected); + void SetHaveSchema(bool schema); + bool HaveSchema(void) const; +diff --git a/mythtv/programs/mythutil/commandlineparser.cpp b/mythtv/programs/mythutil/commandlineparser.cpp +index 7f00e50..03f1792 100644 +--- a/mythtv/programs/mythutil/commandlineparser.cpp ++++ b/mythtv/programs/mythutil/commandlineparser.cpp +@@ -114,6 +114,37 @@ void MythUtilCommandLineParser::LoadArguments(void) + << add("--print-template", "printtemplate", false, + "Print the template to be sent to the frontend", "") + ->SetGroup("Messaging") ++ ++ //settingsutil.cpp ++ << add("--save-settings", "savesettings", false, ++ "Save current settings", "") ++ ->SetGroup("Settings") ++ << add("--delete-settings", "deletesettings", false, ++ "Delete current settings", "") ++ ->SetGroup("Settings") ++ << add("--restore-settings", "restoresettings", false, ++ "Restore settings from previous backup", "") ++ ->SetGroup("Settings") ++ << add("--list-groups", "listgroups", false, ++ "List hosts and groups of settings", "") ++ ->SetGroup("Settings") ++ << add("--copy-settings", "copysettings", false, ++ "Copy or Clone settings from one host to another", "") ++ ->SetGroup("Settings") ++ << add("--diff-settings", "diffsettings", false, ++ "Show settings that are different between two hosts", "") ++ ->SetGroup("Settings") ++ << add("--change-hostname", "changehostname", false, ++ "Change the hostname", "") ++ ->SetGroup("Settings") ++ << add("--import-settings", "importsettings", false, ++ "import settings", "") ++ ->SetRequiredChild("infile") ++ ++ << add("--export-settings", "exportsettings", false, ++ "export settings", "") ++ ->SetRequiredChild("outfile") ++ + ); + + // mpegutils.cpp +@@ -136,6 +167,55 @@ void MythUtilCommandLineParser::LoadArguments(void) + add("--bcastaddr", "bcastaddr", "127.0.0.1", "(optional) IP address to send to", "") + ->SetChildOf("message"); + ++ //settingsutils.cpp ++ add("--groupname", "groupname", "", "Group of settings name", "") ++ ->SetRequiredChildOf("savesettings") ++ ->SetRequiredChildOf("restoresettings") ++ ->SetRequiredChildOf("deletesettings") ++ ->SetChildOf("copysettings"); ++ ++ add("--hostname", "hostname", "", "System name to save/restore settings", "") ++ ->SetChildOf("savesettings") ++ ->SetChildOf("restoresettings") ++ ->SetChildOf("copysettings") ++ ->SetChildOf("deletesettings") ++ ->SetChildOf("exportsettings"); ++ ++ add("--host_1", "host_1", "", "First host in compare list", "") ++ ->SetRequiredChildOf("diffsettings"); ++ ++ add("--host_2", "host_2", "", "Second host in compare list", "") ++ ->SetRequiredChildOf("diffsettings"); ++ ++ ++ add("--tablelist", "table_list", "", "List of tables to operate on " ++ "[keybindings,settings]", "") ++ ->SetChildOf("diffsettings") ++ ->SetChildOf("restoresettings") ++ ->SetChildOf("copysettings") ++ ->SetChildOf("exportsettings"); ++ ++ add("--clone", "fullclone", false, "Enable copy of all settings, " ++ "including those that are unique to each system.", "") ++ ->SetChildOf("copysettings"); ++ ++ ++ add("--old-host", "oldhost", "", "Hostname to change", "") ++ ->SetRequiredChildOf("changehostname"); ++ ++ add("--new-host", "newhost", "", "New hostname", "") ++ ->SetRequiredChildOf("changehostname") ++ ->SetRequiredChildOf("copysettings"); ++ ++ add("--format", "format", false, "Format output of differences", "") ++ ->SetChildOf("diffsettings"); ++ add("--distro-default", "distro-default", false, "Export settings for" ++ "import into the default table", "") ++ ->SetChildOf("exportsettings"); ++ ++ ++ ++ + // Generic Options used by more than one utility + addRecording(); + addInFile(true); +diff --git a/mythtv/programs/mythutil/main.cpp b/mythtv/programs/mythutil/main.cpp +index 418ea01..bd4a1f4 100644 +--- a/mythtv/programs/mythutil/main.cpp ++++ b/mythtv/programs/mythutil/main.cpp +@@ -20,7 +20,7 @@ + #include "jobutils.h" + #include "markuputils.h" + #include "messageutils.h" +- ++#include "settingsutils.h" + + int main(int argc, char *argv[]) + { +@@ -92,6 +92,7 @@ int main(int argc, char *argv[]) + registerJobUtils(utilMap); + registerMarkupUtils(utilMap); + registerMessageUtils(utilMap); ++ registerSettingsUtils(utilMap); + + bool cmdFound = false; + int cmdResult = GENERIC_EXIT_OK; +diff --git a/mythtv/programs/mythutil/mythutil.pro b/mythtv/programs/mythutil/mythutil.pro +index 774528f..5be3ec7 100644 +--- a/mythtv/programs/mythutil/mythutil.pro ++++ b/mythtv/programs/mythutil/mythutil.pro +@@ -3,6 +3,7 @@ include ( ../../version.pro ) + include ( ../programs-libs.pro ) + + QT += network sql ++QT += xml + + TEMPLATE = app + CONFIG += thread +@@ -10,7 +11,7 @@ TARGET = mythutil + target.path = $${PREFIX}/bin + INSTALLS = target + +-LIBS += $$EXTRA_LIBS ++LIBS += $$EXTRA_LIBS + INCLUDEPATH += ../../libs/libmythbase + + QMAKE_CLEAN += $(TARGET) +@@ -19,8 +20,10 @@ QMAKE_CLEAN += $(TARGET) + HEADERS += mythutil.h commandlineparser.h + HEADERS += backendutils.h fileutils.h jobutils.h markuputils.h + HEADERS += messageutils.h mpegutils.h ++HEADERS += settingsutils.h ++ + SOURCES += main.cpp mythutil.cpp commandlineparser.cpp + SOURCES += backendutils.cpp fileutils.cpp jobutils.cpp markuputils.cpp + SOURCES += messageutils.cpp mpegutils.cpp +- ++SOURCES += settingsutils.cpp + mingw: LIBS += -lwinmm -lws2_32 +diff --git a/mythtv/programs/mythutil/settingsutils.cpp b/mythtv/programs/mythutil/settingsutils.cpp +new file mode 100644 +index 0000000..ed3c9a3 +--- /dev/null ++++ b/mythtv/programs/mythutil/settingsutils.cpp +@@ -0,0 +1,541 @@ ++// C++ includes ++#include ++ ++//QT includes ++#include ++#include ++#include ++ ++// libmyth* includes ++#include "compat.h" ++#include "exitcodes.h" ++#include "mythlogging.h" ++#include "mythcontext.h" ++ ++ ++#include "settingsutils.h" ++ ++ ++static int SaveSettings(const MythUtilCommandLineParser &cmdline) ++{ ++ QString src_hostname; ++ QString groupname; ++ ++ if (cmdline.toBool("groupname")) ++ groupname = cmdline.toString("groupname"); ++ ++ if (cmdline.toBool("hostname")) ++ src_hostname = cmdline.toString("hostname"); ++ else ++ src_hostname = gCoreContext->GetHostName(); ++ ++ gCoreContext->savesettings_togroup(src_hostname,groupname); ++ return GENERIC_EXIT_OK; ++} ++ ++static int DeleteSettings(const MythUtilCommandLineParser &cmdline) ++{ ++ ++ QString delete_hostname; ++ QString groupname; ++ ++ if (cmdline.toBool("groupname")) ++ groupname = cmdline.toString("groupname"); ++ ++ if (cmdline.toBool("hostname")) ++ delete_hostname = cmdline.toString("hostname"); ++ else ++ delete_hostname = gCoreContext->GetHostName(); ++ ++ ++ gCoreContext->deletesettings(delete_hostname,groupname); ++ ++ return GENERIC_EXIT_OK; ++} ++ ++ ++static int RestoreSettings(const MythUtilCommandLineParser &cmdline) ++{ ++ QString dest_hostname; ++ QString groupname; ++ QString tablestring; ++ QStringList table_list; ++ ++ if (cmdline.toBool("groupname")) ++ groupname = cmdline.toString("groupname"); ++ ++ ++ if (cmdline.toBool("hostname")) ++ dest_hostname = cmdline.toString("hostname"); ++ else ++ dest_hostname = gCoreContext->GetHostName(); ++ ++ if (cmdline.toBool("table_list")) ++ { ++ tablestring = QString(cmdline.toString("table_list")); ++ table_list = tablestring.split(",", QString::SkipEmptyParts); ++ } ++ ++ gCoreContext->restoresettings(dest_hostname, ++ groupname, ++ table_list); ++ ++ return GENERIC_EXIT_OK; ++} ++ ++ ++static int CopySettings(const MythUtilCommandLineParser &cmdline) ++{ ++ QString src_hostname; ++ QString groupname; ++ QString tablestring; ++ QStringList table_list; ++ bool is_full_clone; ++ QString dest_hostname; ++ ++ if (cmdline.toBool("groupname")) ++ groupname = cmdline.toString("groupname"); ++ else ++ groupname = "Current"; ++ ++ if (cmdline.toBool("hostname")) ++ src_hostname = cmdline.toString("hostname"); ++ else ++ src_hostname = gCoreContext->GetHostName(); ++ ++ if (cmdline.toBool("newhost")) ++ dest_hostname = cmdline.toString("newhost"); ++ ++ if (cmdline.toBool("table_list")) ++ { ++ tablestring = QString(cmdline.toString("table_list")); ++ table_list = tablestring.split(",", QString::SkipEmptyParts); ++ } ++ ++ if (cmdline.toBool("fullclone")) ++ is_full_clone = TRUE; ++ else ++ is_full_clone = FALSE; ++ ++ gCoreContext->clonesettings(src_hostname, ++ groupname, ++ table_list, ++ is_full_clone, ++ dest_hostname); ++ ++ return GENERIC_EXIT_OK; ++} ++ ++void print_out_diff_formated(QMap resultset) ++{ ++ QString settings_header; ++ QString keybindings_header; ++ QString tempString; ++ QString tempItem; ++ QString dashline_settings; ++ QString dashline_key; ++ QStringList tempList; ++ ++ QString host_1; ++ QString host_2; ++ QString data_1; ++ QString data_2; ++ QString value; ++ QString context; ++ QString action; ++ ++ int value_width = 35; ++ int data_width = 40; ++ ++ int context_width = 22; ++ int action_width = 22; ++ int key_width = 35; ++ ++ dashline_key = (tempString.fill('-', 133)); ++ dashline_settings = (tempString.fill('-', 130)); ++ ++ QMap::iterator i; ++ ++ ++ for (i = resultset.begin(); i != resultset.end(); ++i) ++ { ++ cout << endl< resultset; ++ QString diff_hostname1; ++ QString diff_hostname2; ++ QStringList table_list; ++ bool format_results = FALSE; ++ QMap::iterator i; ++ ++ if (cmdline.toBool("host_1")) ++ diff_hostname1 = cmdline.toString("host_1"); ++ if (cmdline.toBool("host_2")) ++ diff_hostname2 = cmdline.toString("host_2"); ++ ++ if (cmdline.toBool("table_list")) ++ { ++ QString tablestring = QString(cmdline.toString("table_list")); ++ table_list = tablestring.split(",", QString::SkipEmptyParts); ++ } ++ ++ if (cmdline.toBool("format")) ++ format_results = TRUE; ++ ++ resultset = gCoreContext->diff_settingsgroupname(diff_hostname1, ++ diff_hostname2, ++ table_list); ++ if (resultset.isEmpty()) ++ cout << "No differences found" << endl; ++ else ++ { ++ if (format_results) ++ print_out_diff_formated(resultset); ++ else ++ { ++ for (i = resultset.begin(); i != resultset.end(); ++i) ++ { ++ cout << i.key().toLocal8Bit().constData() << " : \t" << endl;; ++ for (int y = 0; y < i.value().size(); ++y) ++ cout << i.value().at(y).toLocal8Bit().constData()< resultset; ++ resultset = gCoreContext->list_settingsgroupname(); ++ QMap::iterator i; ++ cout << endl; ++ for (i = resultset.begin(); i != resultset.end(); ++i) ++ { ++ cout << i.key().toLocal8Bit().constData() << " : \t"; ++ for (int y = 0; y < i.value().size(); ++y) ++ cout << i.value().at(y).toLocal8Bit().constData()<<" " ; ++ cout << endl; ++ } ++ return GENERIC_EXIT_OK; ++}; ++ ++static int ImportSettings(const MythUtilCommandLineParser &cmdline) ++{ ++ if (cmdline.toString("infile").isEmpty()) ++ { ++ LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --infile option\n"); ++ return GENERIC_EXIT_INVALID_CMDLINE; ++ } ++ ++ QString import_filename = cmdline.toString("infile"); ++ QFile myFile(import_filename); ++ ++ QDomDocument doc( "exported_xml" ); ++ doc.setContent( &myFile ); ++ ++ QDomElement docElement = doc.documentElement(); ++ QDomElement record_element; ++ ++ if ( docElement.nodeName() != "exported_xml" ) ++ { ++ cout << "not a valid exported xml file" << endl; ++ return 1; ++ } ++ ++ QString out_string = "Importing records, please be patient"; ++ cout << out_string.toLocal8Bit().constData() << endl; ++ //Gives list of records in the file + count ++ QDomNodeList nodeList = docElement.childNodes(); ++ int total_records = nodeList.count(); ++ out_string = QString("\nFound %1 records \n").arg(total_records); ++ cout << out_string.toLocal8Bit().constData() << endl; ++ LOG(VB_STDIO|VB_FLUSH, LOG_ERR, out_string); ++ ++ for(QDomNode n = docElement.firstChild(); !n.isNull(); n = n.nextSibling()) ++ { ++ QString table_name=QString(); ++ QMap value_pair_map ; ++ ++ //find table name for this record ++ QDomNode tablenode=n.namedItem("table"); ++ record_element = tablenode.toElement(); ++ table_name = record_element.text(); ++ ++ //loop over childern of n and convert to element ++ for(QDomNode subn = n.firstChild(); ++ !subn.isNull(); ++ subn = subn.nextSibling()) ++ { ++ record_element = subn.toElement(); ++ if ( record_element.nodeName() == "table" ) ++ continue; ++ value_pair_map[record_element.nodeName()] = record_element.text(); ++ } ++ //perform insert ++ gCoreContext->import_settings(value_pair_map,table_name); ++ } ++ return GENERIC_EXIT_OK; ++}; //end ImportSettings ++ ++ ++static int ExportSettings(const MythUtilCommandLineParser &cmdline) ++{ ++ QMap > records; ++ QString src_hostname; ++ QString groupname; ++ QStringList table_list; ++ QString tablestring; ++ bool distro_default = FALSE; ++ QDomDocument doc("mythutils_exported_settings"); ++ ++ if (cmdline.toBool("groupname")) ++ groupname = cmdline.toString("groupname"); ++ else ++ groupname = "current"; ++ ++ if (cmdline.toBool("hostname")) ++ src_hostname = cmdline.toString("hostname"); ++ else ++ src_hostname = gCoreContext->GetHostName(); ++ ++ if (cmdline.toBool("distro-default")) ++ distro_default = TRUE; ++ ++ if (cmdline.toBool("table_list")) ++ { ++ tablestring = QString(cmdline.toString("table_list")); ++ table_list = tablestring.split(",", QString::SkipEmptyParts); ++ } ++ else ++ table_list << "settings" <<"keybindings" ; ++ ++ if (cmdline.toString("outfile").isEmpty()) ++ { ++ LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --outfile option\n"); ++ return GENERIC_EXIT_INVALID_CMDLINE; ++ } ++ ++ QString export_filename = cmdline.toString("outfile"); ++ ++ records = gCoreContext->export_settings(src_hostname,groupname,table_list); ++ ++ QDomElement exported_xml = doc.createElement("exported_xml"); ++ doc.appendChild(exported_xml); ++ ++ QMap record_count; ++ QMap >::iterator i; ++ for (i = records.begin(); i != records.end(); ++i ) ++ { ++ QDomElement record = doc.createElement("record"); ++ exported_xml.appendChild(record); ++ ++ //loop over all values in the record ++ QMap value_pair = i.value(); ++ QMap::iterator y; ++ //because we don't know the name of the key, we loop over it ++ for (y = value_pair.begin(); y != value_pair.end(); ++y) ++ { ++ //add key/pair to xml document ++ QDomElement tag = doc.createElement(y.key()); ++ record.appendChild(tag); ++ QDomText t; ++ ++ if ( distro_default == TRUE ) ++ { // If exporting distro_default then change hostname + table ++ if ( y.key() == "hostname" ) ++ { //check for global values here, empty value means global ++ if ( y.value().isEmpty() ) ++ t = doc.createTextNode(y.value()); ++ else ++ t = doc.createTextNode("distro_default"); ++ } ++ else if ( y.key() == "table") ++ t = doc.createTextNode(y.value()+"_distro_default"); ++ else ++ t = doc.createTextNode(y.value()); ++ } ++ else ++ { ++ t = doc.createTextNode(y.value()); ++ } ++ tag.appendChild(t); ++ ++ //create record counts ++ if ( y.key() == "table" ) ++ { ++ if ( record_count.contains( y.value()) ) ++ { ++ int record_num = record_count[y.value()]; ++ record_count[y.value()] = ++record_num; ++ } ++ else ++ record_count[y.value()] = 1; ++ } ++ } ++ } ++ QFile file( export_filename ); ++ if( !file.open(QIODevice::WriteOnly) ) ++ return -1; ++ ++ QTextStream ts( &file ); ++ ts << doc.toString(); ++ file.close(); ++ QMap::iterator rc_it; ++ for ( rc_it = record_count.begin(); rc_it != record_count.end(); ++rc_it) ++ { ++ QString table = rc_it.key(); ++ int rc_count = rc_it.value(); ++ QString out_string = QString ("Exported table %1: %2 records") ++ .arg(table) ++ .arg(rc_count); ++ cout << out_string.toLocal8Bit().constData() << endl; ++ } ++ return GENERIC_EXIT_OK; ++}; // end export_settings ++ ++ ++static int ChangeHostname(const MythUtilCommandLineParser &cmdline) ++{ ++ ++ QString old_hostname; ++ QString new_hostname; ++ ++ ++ if (cmdline.toBool("oldhost")) ++ old_hostname = cmdline.toString("oldhost"); ++ ++ if (cmdline.toBool("newhost")) ++ new_hostname = cmdline.toString("newhost"); ++ ++ if (old_hostname.isEmpty()) ++ { ++ LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing or empty --old-host option\n"); ++ return GENERIC_EXIT_INVALID_CMDLINE; ++ } ++ ++ if (new_hostname.isEmpty()) ++ { ++ LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing or empty --new-host option\n"); ++ return GENERIC_EXIT_INVALID_CMDLINE; ++ } ++ ++ gCoreContext->change_hostname(old_hostname, new_hostname); ++ ++ return GENERIC_EXIT_OK; ++}; //end ChangeHostname ++ ++void registerSettingsUtils(UtilMap &utilMap) ++{ ++ utilMap["savesettings"] = &SaveSettings; ++ utilMap["deletesettings"] = &DeleteSettings; ++ utilMap["restoresettings"] = &RestoreSettings; ++ utilMap["copysettings"] = &CopySettings; ++ utilMap["diffsettings"] = &DiffSettings; ++ utilMap["listgroups"] = &ListGroups; ++ utilMap["importsettings"] = &ImportSettings; ++ utilMap["exportsettings"] = &ExportSettings; ++ utilMap["changehostname"] = &ChangeHostname; ++} ++ ++/* vim: set expandtab tabstop=4 shiftwidth=4: */ +\ No newline at end of file +diff --git a/mythtv/programs/mythutil/settingsutils.h b/mythtv/programs/mythutil/settingsutils.h +new file mode 100644 +index 0000000..413496c +--- /dev/null ++++ b/mythtv/programs/mythutil/settingsutils.h +@@ -0,0 +1,3 @@ ++#include "mythutil.h" ++ ++void registerSettingsUtils(UtilMap &utilMap); diff --git a/abs/core/mythtv/stable-0.25/mythtv/mythbackend b/abs/core/mythtv/stable-0.25/mythtv/mythbackend new file mode 100644 index 0000000..93773a2 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/mythbackend @@ -0,0 +1,38 @@ +#!/bin/bash + +. /etc/rc.conf +. /etc/rc.d/functions + +PID=`pidof -o %PPID /usr/bin/mythbackend` +case "$1" in + start) + stat_busy "Starting MythTV Backend" + [ ! -e /var/run/mysqld.pid ] && echo -n "mysqld not started" && stat_fail && exit + [ -z "$PID" ] && /usr/bin/mythbackend -d -l /var/log/mythbackend.log -v important + if [ $? -gt 0 ]; then + stat_fail + else + echo $PID > /var/run/mythbackend.pid + add_daemon mythbackend + stat_done + fi + ;; + stop) + stat_busy "Stopping MythTV Backend" + [ ! -z "$PID" ] && kill $PID &>/dev/null + if [ $? -gt 0 ]; then + stat_fail + else + rm_daemon mythbackend + stat_done + fi + ;; + restart) + $0 stop + sleep 1s + $0 start + ;; + *) + echo "usage: $0 {start|stop|restart}" +esac +exit 0 diff --git a/abs/core/mythtv/stable-0.25/mythtv/mythbackend.lr b/abs/core/mythtv/stable-0.25/mythtv/mythbackend.lr new file mode 100644 index 0000000..4f218bc --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/mythbackend.lr @@ -0,0 +1,9 @@ +/var/log/mythtv/mythbackend.log { + copytruncate + daily + size 10M + missingok + rotate 7 + compress + notifempty +} diff --git a/abs/core/mythtv/stable-0.25/mythtv/mythbackend.sh b/abs/core/mythtv/stable-0.25/mythtv/mythbackend.sh new file mode 100644 index 0000000..e7a7b70 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/mythbackend.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# +# /etc/rc.d/init.d/mythbackend +# +# Starts the mythbackend as a daemon +# +# chkconfig: 345 90 10 +# description: Starts the mythbackend process as a daemon after the XWindows \ +# system is started, in runlevel 5. This allows scheduled \ +# recordings to occur without manual intervention. +# processname: mythbackend + +# Copyright (c) by Michael Thomson +# With thanks to Stu Tomlinson +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Default values to use if none are supplied in the config file. +# User who should start the mythbackend processes +MBE_USER="root" +# Directory holding the mythbackend binary +MBE_LOCATION="/usr/local/bin/" +# Name of mythbackend binary +MBE_PROG="mythbackend" +# Full path to mythbackend log file +MBE_LOGFILE="/var/log/mythtv/mythbackend.log" + +# Source function library. +. /etc/init.d/functions + +# Source config file if available +if [ -f "/etc/sysconfig/mythbackend" ]; then + . /etc/sysconfig/mythbackend +fi + +test -x ${MBE_LOCATION}${MBE_PROG} || exit 0 + +RETVAL=0 + +# +# See how we were called. +# + +start() { + # Check if mythbackend is already running + if [ ! -f /var/lock/subsys/${MBE_PROG} ]; then + echo -n "Starting ${MBE_PROG}: " + # /usr/local/bin/mythbackend -d -l /some/log/file + #daemon --user ${MBE_USER} ${MBE_LOCATION}${MBE_PROG} -d -l ${MBE_LOGFILE} + ${MBE_LOCATION}${MBE_PROG} -d -l ${MBE_LOGFILE} + RETVAL=$? + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/${MBE_PROG} + echo + fi + return $RETVAL +} + +stop() { + echo -n "Stopping ${MBE_PROG}: " + killproc ${MBE_LOCATION}${MBE_PROG} + RETVAL=$? + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/${MBE_PROG} + echo + return $RETVAL +} + + +restart() { + stop + start +} + +reload() { + restart +} + +status_at() { + status ${MBE_LOCATION}${MBE_PROG} +} + +case "$1" in +start) + start + ;; +stop) + stop + ;; +reload|restart) + restart + ;; +condrestart) + if [ -f /var/lock/subsys/${MBE_PROG} ]; then + restart + fi + ;; +status) + status_at + ;; +*) + echo "Usage: $0 {start|stop|restart|condrestart|status}" + exit 1 +esac + +exit $? +exit $RETVAL diff --git a/abs/core/mythtv/stable-0.25/mythtv/mythfrontend.lr b/abs/core/mythtv/stable-0.25/mythtv/mythfrontend.lr new file mode 100644 index 0000000..1580533 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/mythfrontend.lr @@ -0,0 +1,9 @@ +/var/log/mythtv/mythfrontend.log { + copytruncate + daily + size 10M + missingok + rotate 7 + compress + notifempty +} diff --git a/abs/core/mythtv/stable-0.25/mythtv/mythtv.install b/abs/core/mythtv/stable-0.25/mythtv/mythtv.install new file mode 100644 index 0000000..3f2e304 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/mythtv.install @@ -0,0 +1,63 @@ +# arg 1: the new package version +post_install() { + if [ ! -d /var/log/mythtv ] + then + mkdir -p /var/log/mythv + chown -R mythtv /var/log/mythtv + echo "---" > /var/log/mythtv/mythbackend.log + chown mythtv /var/log/mythtv/mythbackend.log + fi + ln -s /usr/share/mythtv/themes/defaultmenu/is.xml /usr/share/mythtv/is.xml +} + +pre_upgrade() { + if [ ! -L /usr/share/mythtv/is.xml ] + then + mv /usr/share/mythtv/is.xml /usr/share/mythtv/is.xml.pre + else + mv /usr/share/mythtv/themes/defaultmenu/is.xml /usr/share/mythtv/themes/defaultmenu/is.xml.pre + fi +} + +post_upgrade() { + if [ ! -d /var/log/mythtv ] + then + mkdir -p /var/log/mythv + chown -R mythtv /var/log/mythtv + fi + if [ -e /usr/share/mythtv/is.xml.pre ] + then + rm -fr /usr/share/mythtv/themes/defaultmenu/is.xml + mv /usr/share/mythtv/is.xml.pre /usr/share/mythtv/themes/defaultmenu/is.xml + ln -s /usr/share/mythtv/themes/defaultmenu/is.xml /usr/share/mythtv/is.xml + else + mv /usr/share/mythtv/themes/defaultmenu/is.xml.pre /usr/share/mythtv/themes/defaultmenu/is.xml + fi + pacxmbc=`pacman -Q xbmc` + if [ -z "$pacxbmc" ] + then + mv /usr/share/mythtv/themes/defaultmenu/library.xml /tmp + grep -v -e /mythmenu /tmp/library.xml > /tmp/library.xml.tmp + echo "" >> /tmp/library.xml.tmp + echo " " >> /tmp/library.xml.tmp + echo "" >> /tmp/library.xml.tmp + echo "" >> /tmp/library.xml.tmp + echo "" >> /tmp/library.xml.tmp + mv /tmp/library.xml.tmp /usr/share/mythtv/themes/defaultmenu/library.xml + fi +} + + +# arg 1: the old package version +post_remove() { + /bin/true + +} + +op=$1 +shift +$op $* diff --git a/abs/core/mythtv/stable-0.25/mythtv/pretty b/abs/core/mythtv/stable-0.25/mythtv/pretty new file mode 100644 index 0000000..7e0ab21 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/pretty @@ -0,0 +1,9 @@ +#!/bin/bash +if [ -f /usr/share/mythtv/contrib/user_jobs/mythlink.pl ] +then + su - mythtv -c "perl /usr/share/mythtv/contrib/user_jobs/mythlink.pl --link /myth/pretty" +elif [ -f /usr/share/mythtv/contrib/user_jobs/mythrename.pl ] +then + su - mythtv -c "perl /usr/share/mythtv/contrib/user_jobs/mythrename.pl --link /myth/pretty" +fi + diff --git a/abs/core/mythtv/stable-0.25/mythtv/smolt_jump.patch b/abs/core/mythtv/stable-0.25/mythtv/smolt_jump.patch new file mode 100644 index 0000000..76f884c --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythtv/smolt_jump.patch @@ -0,0 +1,10 @@ +--- programs/mythfrontend/networkcontrol.cpp.orig 2010-11-08 23:07:04.000000000 +0000 ++++ programs/mythfrontend/networkcontrol.cpp 2010-11-08 23:08:06.000000000 +0000 +@@ -88,6 +88,7 @@ + jumpMap["zoneminderliveview"] = "ZoneMinder Live View"; + jumpMap["zoneminderevents"] = "ZoneMinder Events"; + jumpMap["snapshot"] = "ScreenShot"; ++ jumpMap["mythsmolt"] = "MythSmolt"; + + jumpMap["channelrecpriority"] = "Channel Recording Priorities"; + jumpMap["viewscheduled"] = "Manage Recordings / Fix Conflicts"; diff --git a/abs/core/mythtv/stable-0.25/mythweb/PKGBUILD b/abs/core/mythtv/stable-0.25/mythweb/PKGBUILD new file mode 100644 index 0000000..cab8fbd --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythweb/PKGBUILD @@ -0,0 +1,46 @@ +pkgname=mythweb +pkgver=0.24 +pkgrel=16 +pkgdesc="Web interface for MythTV's backend" +url="http://www.mythtv.org" +license="GPL" +arch=('i686' 'x86_64') + +depends=('mythtv>=0.24' 'lighttpd' 'php' 'local-website') +groups=('mythtv-extras') + +patches=() +source=('ftp://ftp.knoppmyth.net/R6/sources/mythweb-0.24-fixes.tar.bz2' `echo ${patches[@]:0}`) + +DOCROOT=/data/srv/httpd/htdocs/mythweb +_gitroot="https://github.com/mythtv/mythweb.git" +_gitname="${pkgname}" +build() { + + cd $startdir/src/mythweb + git pull + + echo "--------------------------applying patches----------------------------------------------------" + for i in `echo ${patches[@]:0} ` + do + echo applying $i + echo "-----------------------------" + patch -Np0 -i ${srcdir}/$i || return 1 + done + echo "--------------------------done applying patches-----------------------------------------------" + + [ "$CARCH" = "i686" ] && ARCH="i686" + [ "$CARCH" = "x86_64" ] && ARCH="x86-64" + + mkdir -p $startdir/pkg/$DOCROOT/{image_cache,php_sessions,data} + rsync -arp --exclude .git --delete-excluded $startdir/src/mythweb/* $startdir/pkg/$DOCROOT + rm $startdir/pkg/$DOCROOT/README + chown -R http:http $startdir/pkg/$DOCROOT + chmod g+rw $pkgdir/$DOCROOT/{image_cache,php_sessions,data} + + # mythweb modules_path fix for 0.24 + # http://code.mythtv.org/trac/ticket/9255 + cd ${pkgdir}/${DOCROOT} + ln -s modules modules_path +} +md5sums=('45703fa3899c4ee84d1b087bfcc6654e') diff --git a/abs/core/mythtv/stable-0.25/mythweb/mythweb.php.patch b/abs/core/mythtv/stable-0.25/mythweb/mythweb.php.patch new file mode 100644 index 0000000..4525e68 --- /dev/null +++ b/abs/core/mythtv/stable-0.25/mythweb/mythweb.php.patch @@ -0,0 +1,11 @@ +--- mythweb.php.orig 2011-02-01 03:33:56.000000000 +0000 ++++ mythweb.php 2011-02-01 03:34:20.000000000 +0000 +@@ -30,7 +30,7 @@ + if (Modules::getModule($Path[0])) { + // Add the current module directory to our search path, so modules can + // define includes, etc. +- ini_set('include_path', ini_get('include_path').':'.modules_path.'/'.$Path[0]); ++ ini_set('include_path', ini_get('include_path').':'.modules.'/'.$Path[0]); + // Load the module handler + require_once 'handler.php'; + } -- cgit v0.12