summaryrefslogtreecommitdiffstats
path: root/abs/core
diff options
context:
space:
mode:
Diffstat (limited to 'abs/core')
-rwxr-xr-xabs/core/LinHES-system/LinHES-run3
-rwxr-xr-xabs/core/LinHES-system/LinHES-session6
-rw-r--r--abs/core/LinHES-system/PKGBUILD30
-rwxr-xr-xabs/core/LinHES-system/cacheclean134
-rw-r--r--abs/core/LinHES-system/cacheclean.cron2
-rwxr-xr-xabs/core/LinHES-system/diskspace2
-rwxr-xr-xabs/core/LinHES-system/diskspace.sh81
-rwxr-xr-xabs/core/LinHES-system/firstboot.sh21
-rw-r--r--abs/core/LinHES-system/myth_status.py19
-rw-r--r--abs/core/linhes-scripts/PKGBUILD2
-rw-r--r--abs/core/mythinstall/PKGBUILD2
-rwxr-xr-xabs/core/mythinstall/checkout_MythVantage.sh4
-rw-r--r--abs/core/mythtv/stable-0.25/git_src/checkout_mythtv.sh18
m---------abs/core/mythtv/stable-0.25/git_src/mythtv0
-rw-r--r--abs/core/mythtv/stable-0.25/mythplugins/PKGBUILD143
-rw-r--r--abs/core/mythtv/stable-0.25/mythplugins/mythburn.py.patch303
-rw-r--r--abs/core/mythtv/stable-0.25/mythplugins/mythplugins-mythzoneminder.install3
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/PKGBUILD113
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/__changelog1
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/git_version.patch13
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/HOST_SETTINGS.xml94
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/is.xml3
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/library.xml.patch12
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/linhes.xml59
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/mainmenu.xml.patch37
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythbackup.xml20
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/mythrestore.xml20
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/optical_menu.xml.patch16
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/original/create_patch.sh5
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/setup.xml111
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/siriusmenu.xml419
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/update.xml9
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/update2.xml20
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/util_menu.xml.patch16
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/menu-xml/xmmenu.xml574
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/myth.sh4
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/myth_settings.patch1816
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/mythbackend38
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/mythbackend.lr9
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/mythbackend.sh117
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/mythfrontend.lr9
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/mythtv.install63
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/pretty9
-rw-r--r--abs/core/mythtv/stable-0.25/mythtv/smolt_jump.patch10
-rw-r--r--abs/core/mythtv/stable-0.25/mythweb/PKGBUILD46
-rw-r--r--abs/core/mythtv/stable-0.25/mythweb/mythweb.php.patch11
-rwxr-xr-xabs/core/runit-scripts/PKGBUILD3
-rwxr-xr-xabs/core/runit-scripts/runitscripts/services/mythbackend/run2
48 files changed, 4423 insertions, 29 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..18d67e5 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=44
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,10 +19,12 @@ binfiles="LinHES-start optimize_mythdb.py
lh_system_restore_job
lh_system_host_update
lh_system_all_host_update
- add_storage.py"
-
-source=(LinHES-session LinHES-profile.sh $binfiles alsa-base myth_mtc.lr)
+ add_storage.py
+ diskspace.sh
+ cacheclean"
+source=(LinHES-session LinHES-profile.sh $binfiles alsa-base myth_mtc.lr
+ diskspace smolt.cron cacheclean.cron)
build() {
cd $startdir/src
install -m755 -D LinHES-session $startdir/pkg/etc/X11/Sessions/LinHES
@@ -45,24 +47,25 @@ 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
}
-md5sums=('d6a564f3286590875874573107940908'
+md5sums=('e8a0e71dabadb5a860b4e113615c3071'
'5881bdb43d578ec3a79d1f77ea58a3db'
'a875ee97f86e46f34a741c2bc455f894'
'76b2637cac0452b3acdbeeb4e8a5474b'
'd1f27cb422010077c841376526fe46ea'
'2ef9f945e034119f77d9b6beb17e4fa5'
- '5c96527397a35519d72c78d6e3c8dbea'
- '18a884a73344ff6eb74f63b49745e0f5'
+ 'c1c5f68835afbb2bad5d5e6cec0fc1dc'
+ '5e67a8b7ff57ec32d668bce7aab0aa6d'
'dc3eef2a624754e16805d72bbe488b67'
'dc0be354ce77ba2b89868fc29b942c43'
'542e670e78d117657f93141e9689f54d'
- 'abe887472a170bd1a8e6da6a7b7e93e4'
'752488eb8bfb672ce0e4c924f7faf3d1'
'ba351b92e69bcaf26a9bf80417b09c3c'
- '1d534843cc4e55fe4ce21c3e95e3f766'
+ '294e54209538018008323d164ce39fb3'
'962a3e9eaba2d1466251b7ab0956705d'
'd03aedeeeda0f5e9c1eb437411c88477'
'94ce8f1d5085c0db7b267db8c2e9a3ff'
@@ -71,5 +74,10 @@ md5sums=('d6a564f3286590875874573107940908'
'859a80ddb4c234506379c605114c1343'
'47e093e8cfe4b5b96602358e1f540832'
'6faeba0aeb38e772121f751cabda8683'
+ '68e3e87571f3b0fa4a48a10df50dc220'
+ '9603b0ca6e090eff31e76482a3c335e7'
'eb879fee9603a05d5420d4ce8ed9e450'
- 'f1870a9522c79e6b248fcbf81dec3280')
+ 'f1870a9522c79e6b248fcbf81dec3280'
+ '84492954db16740f949d795b74383189'
+ '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).
+ # <showing_off>
+ #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])
+ # </showing_off>
+ 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
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-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
diff --git a/abs/core/LinHES-system/myth_status.py b/abs/core/LinHES-system/myth_status.py
index f8222cb..4637b90 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()
@@ -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 ""
@@ -107,5 +110,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 ""
diff --git a/abs/core/linhes-scripts/PKGBUILD b/abs/core/linhes-scripts/PKGBUILD
index 0be8d93..68a02ef 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=33
pkgdesc="Various scripts that help to make LinHES, LinHES."
arch=('i686' 'x86_64')
license=('GPL2')
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 {
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
+Subproject 76df8e6c8f7b84a157607d8c25fd19f39d8dc83
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 <giovanni@archlinux.org>
+
+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 <giovanni@archlinux.org>
+# Contributor: Juergen Hoetzel <juergen@archlinux.org>
+# Contributor: <kleptophobiac@gmail.com>
+# Contributor: dorphell <dorphell@archlinux.org>
+
+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 @@
+<mythmenu name="HOST_SETTINGS">
+
+ <button>
+ <type>MV_NETWORK_SETUP_MENU</type>
+ <text>Network Settings</text>
+ <action>EXEC mythinstall -s network </action>
+ </button>
+
+ <button>
+ <type>MV_NETWORK_SETUP_MENU</type>
+ <text>DDNS Settings</text>
+ <action>EXEC mythinstall -s ddns </action>
+ </button>
+ <button>
+ <type>MV_SYSTEM_SETUP_MENU</type>
+ <text>System Type</text>
+ <action>EXEC mythinstall -s hostype </action>
+ </button>
+
+ <button>
+ <type>MV_SCREENSAVER_SETUP_MENU</type>
+ <text>Screensaver Settings</text>
+ <action>EXEC mythinstall -s screensaver </action>
+ </button>
+
+ <button>
+ <type>MV_IR_SETUP_MENU</type>
+ <text>Remotes</text>
+ <action>EXEC mythinstall -s ir </action>
+ </button>
+
+ <button>
+ <type>MV_MISC_SETUP_MENU</type>
+ <text>Miscellanous Settings</text>
+ <action>EXEC mythinstall -s misc </action>
+ </button>
+
+ <button>
+ <type>MV_SOFTWARE_MENU</type>
+ <text>Software</text>
+ <action>EXEC mythinstall -s plugins </action>
+ </button>
+
+ <button>
+ <type>MV_SHUTDOWN_SETUP_MENU</type>
+ <text>Shutdown Settings</text>
+ <action>EXEC mythinstall -s sleep </action>
+ </button>
+
+ <button>
+ <type>MV_ADVANCED_X_SETUP_MENU</type>
+ <text>Display Settings</text>
+ <action>EXEC mythinstall -s advancedX</action>
+ </button>
+
+ <button>
+ <type>MV_ADVANCED_SETUP_MENU</type>
+ <text>Advanced Settings</text>
+ <action>EXEC mythinstall -s advanced</action>
+ </button>
+
+ <button>
+ <type>MV_AUDIO_SETUP_MENU</type>
+ <text>Audio Settings</text>
+ <action>EXEC mythinstall -s sound </action>
+ </button>
+
+ <button>
+ <type>MV_ACCESS_SETUP_MENU</type>
+ <text>Access Control</text>
+ <action>EXEC mythinstall -s accesscontrol </action>
+ </button>
+
+ <button>
+ <type>MV_USER_SETUP_MENU</type>
+ <text>User Accounts</text>
+ <action>EXEC mythinstall -s user </action>
+ </button>
+
+ <button>
+ <type>MV_WEBACCESS_SETUP_MENU</type>
+ <text>Web Security</text>
+ <action>EXEC mythinstall -s webuser </action>
+ </button>
+
+ <!--
+ <button>
+ <type>SETUP_MENU</type>
+ <text>Settings Profile Manager</text>
+ <action>EXEC mythinstall -t </action>
+ </button>
+ -->
+
+</mythmenu>
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 @@
+<mythmenu name="Internet Steams">
+
+</mythmenu>
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 @@
+ <type>STREAM</type>
+ <text>Play Online Streams</text>
+ <description></description>
+- <action>PLUGIN mythstream</action>
+- <depends>mythstream</depends>
++ <action>MENU is.xml</action>
+ </button>
+
+ <button>
diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/linhes.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/linhes.xml
new file mode 100644
index 0000000..01b6ffa
--- /dev/null
+++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/linhes.xml
@@ -0,0 +1,59 @@
+<mythmenu name="LinHES">
+
+ <button>
+ <type>SETUP_GENERAL</type>
+ <text>MythTV Configuration</text>
+ <text lang="IT">Impostazioni</text>
+ <text lang="ES">Configuración</text>
+ <text lang="DE">Zubehör / Konfiguration</text>
+ <text lang="DA">Tilbehør/Indstillinger</text>
+ <text lang="IS">Uppsetning</text>
+ <text lang="NL">Configuratie</text>
+ <text lang="PT">Utensílios</text>
+ <text lang="SV">Verktyg / Inställningar</text>
+ <text lang="JA">設å®~Z</text>
+ <text lang="FI">Oheis/Asetukset</text>
+ <text lang="ZH_TW">å·¥å~E·/設å®~Z</text>
+ <text lang="SL">Nastavitve</text>
+ <text lang="ET">Utiliidid / sätted</text>
+ <text lang="RU">УÑ~BилиÑ~BÑ~K / Ð~]аÑ~AÑ~BÑ~@ойки</text>
+ <text lang="AR">تضبÙ~Jطات</text>
+ <text lang="PL">NarzÄ~Ydzia / ustawienia</text>
+ <text lang="HE">×¢×~Vר×~Y×~] / ×~T×~R×~Sר×~Uת</text>
+ <text lang="HU">Eszközök / Beállítások</text>
+ <alttext lang="DE">Verschiedenes</alttext>
+ <alttext lang="SV">Inställningar</alttext>
+ <alttext lang="ET">Sätted</alttext>
+ <alttext lang="RU">Ð~]аÑ~AÑ~BÑ~@ойки</alttext>
+ <alttext lang="AR">تضبÙ~Jطات</alttext>
+ <description>Configure MythTV and plugins</description>
+ <description lang="DE">MythTV und Plugins konfigurieren</description>
+ <action>MENU util_menu.xml</action>
+ </button>
+
+ <button>
+ <type>LINHES_SETUP</type>
+ <text>LinHES Configuration</text>
+ <action>MENU HOST_SETTINGS.xml</action>
+ </button>
+
+ <button>
+ <type>BACKUP</type>
+ <text>Backup LinHES</text>
+ <action>MENU mythbackup.xml</action>
+ </button>
+
+ <button>
+ <type>RESTORE</type>
+ <text>Restore LinHES</text>
+ <action>MENU mythrestore.xml</action>
+ </button>
+
+<!--#Check for updates-->
+ <button>
+ <type>UPGRADE</type>
+ <text>Update LinHES</text>
+ <action>MENU update.xml</action>
+ </button>
+<!--#Check for updates-->
+</mythmenu>
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 @@
+ <mythmenu name="MAIN">
+
+ <button>
++ <type>TV_WATCH_TV</type>
++ <text>Watch TV</text>
++ <description>Watch live television</description>
++ <action>TV_WATCH_LIVE</action>
++ </button>
++
++ <button>
+ <type>MENU_MEDIA_LIBRARY</type>
+ <text>Media Library</text>
+ <action>MENU library.xml</action>
+@@ -31,17 +38,10 @@
+ </button>
+
+ <button>
+- <type>TV_WATCH_TV</type>
+- <text>Watch TV</text>
+- <description>Watch live television</description>
+- <action>TV_WATCH_LIVE</action>
+- </button>
+-
+- <button>
+ <type>MENU_UTILITIES_SETUP</type>
+- <text>Utilities / Setup</text>
+- <description>Configure MythTV and plugins</description>
+- <action>MENU util_menu.xml</action>
++ <text>Service Menu</text>
++ <description>Configure your system</description>
++ <action>MENU linhes.xml</action>
+ </button>
+
+ </mythmenu>
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 @@
+<mythmenu name="LinHES">
+
+ <button>
+ <type>BACKUP</type>
+ <text>Do you wish to backup?</text>
+ <action>NONE</action>
+ </button>
+
+ <button>
+ <type>BACKUP</type>
+ <text>Yes</text>
+ <action>EXEC sudo /usr/LH/bin/mythbackup</action>
+ </button>
+
+ <button>
+ <type>BACKUP</type>
+ <text>No</text>
+ <action>UPMENU</action>
+ </button>
+</mythmenu>
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 @@
+<mythmenu name="LinHES">
+
+ <button>
+ <type>RESTORE</type>
+ <text>Do you wish to restore?</text>
+ <action>NONE</action>
+ </button>
+
+ <button>
+ <type>RESTORE</type>
+ <text>Yes</text>
+ <action>EXEC sudo /usr/LH/bin/mythrestore</action>
+ </button>
+
+ <button>
+ <type>BACKUP</type>
+ <text>No</text>
+ <action>UPMENU</action>
+ </button>
+</mythmenu>
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 @@
+ </button>
+
+ <button>
++ <type>DVD_RIP</type>
++ <text>Import video files from DVD</text>
++ <description>Import video files from a data DVD</description>
++ <action>EXEC /usr/LH/bin/importfiles.sh</action>
++ </button>
++
++ <button>
+ <type>MUSIC_RIP</type>
+ <text>Import CD</text>
+ <description>Import music from an audio CD</description>
diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/original/create_patch.sh b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/original/create_patch.sh
new file mode 100644
index 0000000..34d8b8c
--- /dev/null
+++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/original/create_patch.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+for i in *.xml
+do
+ diff -u $i.orig $i > ../$i.patch
+done
diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/setup.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/setup.xml
new file mode 100644
index 0000000..f56bb6f
--- /dev/null
+++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/setup.xml
@@ -0,0 +1,111 @@
+<mythmenu name="MAIN">
+
+ <button>
+ <type>SETUP_GENERAL</type>
+ <text>1. General</text>
+ <text lang="IT">1. Generale</text>
+ <text lang="PT">1. Geral</text>
+ <text lang="SV">1. Generellt</text>
+ <text lang="JA">1. 一般</text>
+ <text lang="DE">1. Allgemeines</text>
+ <text lang="FI">1. Yleiset</text>
+ <text lang="FR">1. Général</text>
+ <text lang="SI">1. Splošno</text>
+ <text lang="ET">1. Ãœldine</text>
+ <text lang="NB">1 Generelt</text>
+ <text lang="DK">1. Generelt</text>
+ <text lang="ES">1. General</text>
+ <text lang="CZ">1. Obecný</text>
+ <text lang="RU">1. Общие</text>
+ <action>GENERAL</action>
+ </button>
+
+ <button>
+ <type>SETUP_CAPTURE_CARDS</type>
+ <text>2. Capture cards</text>
+ <text lang="IT">2. Schede di Acquisizione</text>
+ <text lang="PT">2. Placas de Captura</text>
+ <text lang="SV">2. TV-kort</text>
+ <text lang="JA">2. キャプãƒãƒ£ã‚«ãƒ¼ãƒ‰</text>
+ <text lang="DE">2. TV-Karten</text>
+ <text lang="FI">2. TV-kortit</text>
+ <text lang="FR">2. Cartes d'acquisition</text>
+ <text lang="SI">2. Kartice za zajem</text>
+ <text lang="ET">2. TV-kaardid</text>
+ <text lang="NB">2 TV-kort</text>
+ <text lang="DK">2. TV-kort</text>
+ <text lang="ES">2. Capturadoras</text>
+ <text lang="CZ">2. Zachytávací karty</text>
+ <text lang="RU">2. Карты захвата</text>
+ <action>CAPTURE CARDS</action>
+ </button>
+
+ <button>
+ <type>SETUP_VIDEO_SOURCES</type>
+ <text>3. Video sources</text>
+ <text lang="IT">3. Fonte Video</text>
+ <text lang="PT">3. Fontes de Vídeo</text>
+ <text lang="SV">3. Videokällor</text>
+ <text lang="JA">3. ビデオソース</text>
+ <text lang="DE">3. Videoquellen</text>
+ <text lang="FI">3. Kuvanlähteet</text>
+ <text lang="FR">3. Sources vidéo</text>
+ <text lang="SI">3. Video viri</text>
+ <text lang="ET">3. Videosisendid</text>
+ <text lang="NB">3 Videokilder</text>
+ <text lang="DK">3. Videokilder</text>
+ <text lang="ES">3. Fuentes de Vídeo</text>
+ <text lang="CZ">3. Zdroje obrazu</text>
+ <text lang="RU">3. Видео иÑточники</text>
+ <action>VIDEO SOURCES</action>
+ </button>
+
+ <button>
+ <type>SETUP_INPUT_CONNECTIONS</type>
+ <text>4. Input connections</text>
+ <text lang="IT">4. Connessioni di Ingresso</text>
+ <text lang="PT">4. Ligações de Entrada</text>
+ <text lang="SV">4. Anslutningar</text>
+ <text lang="JA">4. 入力ã¨ã‚½ãƒ¼ã‚¹ã®æŽ¥ç¶š</text>
+ <text lang="DE">4. Verknüpfungen</text>
+ <text lang="FI">4. Sisääntuloasetukset</text>
+ <text lang="FR">4. Entrées Vidéos</text>
+ <text lang="SI">4. Vhodne povezave</text>
+ <text lang="ET">4. Sisendite ühendused</text>
+ <text lang="NB">4 Inndata</text>
+ <text lang="DK">4. Indgange</text>
+ <text lang="ES">4. Conexiones</text>
+ <text lang="CZ">4. Připojení vstupů</text>
+ <text lang="RU">4. Соединение входов</text>
+ <action>CARD INPUTS</action>
+ </button>
+
+ <button>
+ <type>SETUP_CHANNEL_EDITOR</type>
+ <text>5. Channel Editor</text>
+ <text lang="IT">5. Modifica Canali</text>
+ <text lang="SV">5. Kanaleditor</text>
+ <text lang="JA">5. ãƒãƒ£ãƒ³ãƒãƒ«è¨­å®š</text>
+ <text lang="DE">5. Sender bearbeiten</text>
+ <text lang="FI">5. Kanavanviritys</text>
+ <text lang="FR">5. Editeur de chaînes</text>
+ <text lang="SI">5. Urejanje kanalov</text>
+ <text lang="ET">5. Kanaliredaktor</text>
+ <text lang="NB">5 Kanalredigerer</text>
+ <text lang="DK">5. Kanal opsætning</text>
+ <text lang="ES">5. Editor Canales</text>
+ <text lang="CZ">5. Editor kanálů</text>
+ <text lang="RU">5. Редактор каналов</text>
+ <action>CHANNEL EDITOR</action>
+ </button>
+
+ <button>
+ <type>SETUP_STORAGE_GROUPS</type>
+ <text>6. Storage Directories</text>
+ <text lang="IT">6. Cartelle</text>
+ <text lang="FI">Tallennusryhmät</text>
+ <text lang="SV">Lagringsgrupper</text>
+ <action>STORAGE GROUPS</action>
+ </button>
+
+</mythmenu>
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 @@
+<mythmenu name="SIRIUS">
+ <button>
+ <type>MUSIC</type>
+ <text>Sirius Hits 1</text>
+ <action>EXEC /usr/bin/cliSipie siriushits1</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>StarLite</text>
+ <action>EXEC /usr/bin/cliSipie starlite</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Sirius Love</text>
+ <action>EXEC /usr/bin/cliSipie siriuslove</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Movin EZ</text>
+ <action>EXEC /usr/bin/cliSipie movineasy</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Sirius Gold</text>
+ <action>EXEC /usr/bin/cliSipie siriusgold</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>'60s Vibrations</text>
+ <action>EXEC /usr/bin/cliSipie 60svibrations</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Totally '70s</text>
+ <action>EXEC /usr/bin/cliSipie totally70s</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Big '80s</text>
+ <action>EXEC /usr/bin/cliSipie big80s</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>ThePulse</text>
+ <action>EXEC /usr/bin/cliSipie thepulse</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Bridge</text>
+ <action>EXEC /usr/bin/cliSipie thebridge</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>BBC Radio 1</text>
+ <action>EXEC /usr/bin/cliSipie bbcradio1</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Super Shuffle</text>
+ <action>EXEC /usr/bin/cliSipie supershuffle</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Elvis Radio</text>
+ <action>EXEC /usr/bin/cliSipie elvisradio</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Classic Vinyl</text>
+ <action>EXEC /usr/bin/cliSipie classicvinyl</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Classic Rewind</text>
+ <action>EXEC /usr/bin/cliSipie classicrewind</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>TheVault</text>
+ <action>EXEC /usr/bin/cliSipie thevault</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Jam_ON</text>
+ <action>EXEC /usr/bin/cliSipie jamon</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Spectrum</text>
+ <action>EXEC /usr/bin/cliSipie thespectrum</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>BuzzSaw</text>
+ <action>EXEC /usr/bin/cliSipie buzzsaw</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Octane</text>
+ <action>EXEC /usr/bin/cliSipie octane</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Alt Nation</text>
+ <action>EXEC /usr/bin/cliSipie altnation</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>1st Wave</text>
+ <action>EXEC /usr/bin/cliSipie firstwave</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Hair Nation</text>
+ <action>EXEC /usr/bin/cliSipie hairnation</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>'90s Alternative</text>
+ <action>EXEC /usr/bin/cliSipie 90salternative</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Garage</text>
+ <action>EXEC /usr/bin/cliSipie undergroundgarage</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Left of Center</text>
+ <action>EXEC /usr/bin/cliSipie leftofcenter</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Hard Attack</text>
+ <action>EXEC /usr/bin/cliSipie hardattack</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Faction</text>
+ <action>EXEC /usr/bin/cliSipie faction</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Punk</text>
+ <action>EXEC /usr/bin/cliSipie punk</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>The Coffee House</text>
+ <action>EXEC /usr/bin/cliSipie coffeehouse</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Margaritaville</text>
+ <action>EXEC /usr/bin/cliSipie radiomargaritaville</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Sirius Disorder</text>
+ <action>EXEC /usr/bin/cliSipie siriusdisorder</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Reggae</text>
+ <action>EXEC /usr/bin/cliSipie reggaerhythms</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Area 33</text>
+ <action>EXEC /usr/bin/cliSipie area33</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Boombox</text>
+ <action>EXEC /usr/bin/cliSipie boombox</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Chill</text>
+ <action>EXEC /usr/bin/cliSipie chill</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>The Beat</text>
+ <action>EXEC /usr/bin/cliSipie thebeat</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Strobe</text>
+ <action>EXEC /usr/bin/cliSipie thestrobe</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Hip-Hop Nation</text>
+ <action>EXEC /usr/bin/cliSipie hiphopnation</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>BackSpin</text>
+ <action>EXEC /usr/bin/cliSipie backspin</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Shade 45</text>
+ <action>EXEC /usr/bin/cliSipie shade45</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Hot Jamz</text>
+ <action>EXEC /usr/bin/cliSipie hotjamz</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Heart &amp; Soul</text>
+ <action>EXEC /usr/bin/cliSipie heartandsoul</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>SoulTown</text>
+ <action>EXEC /usr/bin/cliSipie soultown</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>New Country</text>
+ <action>EXEC /usr/bin/cliSipie newcountry</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Prime Country</text>
+ <action>EXEC /usr/bin/cliSipie primecountry</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Roadhouse</text>
+ <action>EXEC /usr/bin/cliSipie theroadhouse</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Outlaw Country</text>
+ <action>EXEC /usr/bin/cliSipie outlawcountry</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Bluegrass</text>
+ <action>EXEC /usr/bin/cliSipie bluegrass</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Spirit</text>
+ <action>EXEC /usr/bin/cliSipie spirit</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Praise</text>
+ <action>EXEC /usr/bin/cliSipie praise</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Planet Jazz</text>
+ <action>EXEC /usr/bin/cliSipie planetjazz</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>JazzCafe</text>
+ <action>EXEC /usr/bin/cliSipie jazzcafe</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>PureJazz</text>
+ <action>EXEC /usr/bin/cliSipie purejazz</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Spa 73</text>
+ <action>EXEC /usr/bin/cliSipie spa73</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Blues</text>
+ <action>EXEC /usr/bin/cliSipie siriusblues</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Siriusly Sinatra</text>
+ <action>EXEC /usr/bin/cliSipie siriuslysinatra</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Broadway's Best</text>
+ <action>EXEC /usr/bin/cliSipie broadwaysbest</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Symphony Hall</text>
+ <action>EXEC /usr/bin/cliSipie symphonyhall</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Met Opera Radio</text>
+ <action>EXEC /usr/bin/cliSipie metropolitanopera</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Sirius Pops</text>
+ <action>EXEC /usr/bin/cliSipie siriuspops</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Universo Latino</text>
+ <action>EXEC /usr/bin/cliSipie universolatino</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Rumbon</text>
+ <action>EXEC /usr/bin/cliSipie rumbon</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Martha Stewart</text>
+ <action>EXEC /usr/bin/cliSipie marthastewartlivingradio</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Sirius Stars</text>
+ <action>EXEC /usr/bin/cliSipie siriusstars</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>OutQ Gay Radio</text>
+ <action>EXEC /usr/bin/cliSipie siriusoutq</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Patriot</text>
+ <action>EXEC /usr/bin/cliSipie siriuspatriot</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Left</text>
+ <action>EXEC /usr/bin/cliSipie siriusleft</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>CNN</text>
+ <action>EXEC /usr/bin/cliSipie cnn</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>wrn</text>
+ <action>EXEC /usr/bin/cliSipie wrn</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Blue Collar Comedy</text>
+ <action>EXEC /usr/bin/cliSipie bluecollarcomedy</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Raw Dog Comedy</text>
+ <action>EXEC /usr/bin/cliSipie rawdog</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Laugh Break Comedy</text>
+ <action>EXEC /usr/bin/cliSipie laughbreak</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>thefoxxhole</text>
+ <action>EXEC /usr/bin/cliSipie thefoxxhole</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>lime</text>
+ <action>EXEC /usr/bin/cliSipie lime</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Kids Stuff</text>
+ <action>EXEC /usr/bin/cliSipie kidsstuff</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Catholic Channel</text>
+ <action>EXEC /usr/bin/cliSipie thecatholicchannel</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>EWTN</text>
+ <action>EXEC /usr/bin/cliSipie ewtnglobal</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>christiantalk</text>
+ <action>EXEC /usr/bin/cliSipie christiantalk</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Sirius NFL Radio</text>
+ <action>EXEC /usr/bin/cliSipie siriusnflradio</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Maxim Radio</text>
+ <action>EXEC /usr/bin/cliSipie maximradio</action>
+ </button>
+ <button>
+ <type>MUSIC</type>
+ <text>Cosmo Radio</text>
+ <action>EXEC /usr/bin/cliSipie cosmopolitanradio</action>
+ </button>
+ <button>
+ <type>TV_DELETE</type>
+ <text>Stop Listening</text>
+ <action>EXEC /usr/bin/sipie_kill</action>
+ </button>
+
+</mythmenu>
+
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 @@
+<mythmenu name="LinHES">
+
+ <button>
+ <type>UPGRADE</type>
+ <text>Check for Updates</text>
+ <action>EXEC sudo /usr/LH/bin/linhes_update.sh</action>
+ </button>
+
+</mythmenu>
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 @@
+<mythmenu name="LinHES">
+
+ <button>
+ <type>UPGRADE</type>
+ <text>Install Updates</text>
+ <action>EXEC sudo /usr/LH/bin/linhes_update2.sh install</action>
+ </button>
+
+ <button>
+ <type>UPGRADE</type>
+ <text>Cancel Updates</text>
+ <action>EXEC sudo /usr/LH/bin/linhes_update2.sh</action>
+ </button>
+
+ <button>
+ <type>UPGRADE</type>
+ <text>View Updates</text>
+ <action>MENU update3.xml</action>
+ </button>
+</mythmenu>
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 @@
+ </button>
+
+ <button>
++ <type>VIDEO_SCREENSHOOTER</type>
++ <text>Thumbnail Generator</text>
++ <description>Generate thumbnail images for videos</description>
++ <action>EXEC /usr/LH/bin/shootscreens-mythtv.sh</action>
++ </button>
++
++ <button>
+ <type>SETUP_MENU</type>
+ <text>Setup</text>
+ <description>Configure MythTV and plugins</description>
diff --git a/abs/core/mythtv/stable-0.25/mythtv/menu-xml/xmmenu.xml b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/xmmenu.xml
new file mode 100644
index 0000000..6b26d11
--- /dev/null
+++ b/abs/core/mythtv/stable-0.25/mythtv/menu-xml/xmmenu.xml
@@ -0,0 +1,574 @@
+<!-- Current as of April 25, 2007 -->
+<mythmenu name="XM">
+
+ <button>
+ <type>MUSIC</type>
+ <text>The '40s</text>
+ <action>EXEC /usr/bin/xamp kill 4</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The '50s</text>
+ <action>EXEC /usr/bin/xamp kill 5</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The '60s</text>
+ <action>EXEC /usr/bin/xamp kill 6</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The '70s</text>
+ <action>EXEC /usr/bin/xamp kill 7</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The '80s</text>
+ <action>EXEC /usr/bin/xamp kill 8</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The '90s</text>
+ <action>EXEC /usr/bin/xamp kill 9</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>America</text>
+ <action>EXEC /usr/bin/xamp kill 10</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>X Country</text>
+ <action>EXEC /usr/bin/xamp kill 12</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Willie's Place</text>
+ <action>EXEC /usr/bin/xamp kill 13</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Bluegrass Junction</text>
+ <action>EXEC /usr/bin/xamp kill 14</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Village</text>
+ <action>EXEC /usr/bin/xamp kill 15</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Highway 16</text>
+ <action>EXEC /usr/bin/xamp kill 16</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>US Country</text>
+ <action>EXEC /usr/bin/xamp kill 17</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>20 on 20</text>
+ <action>EXEC /usr/bin/xamp kill 20</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Heart</text>
+ <action>EXEC /usr/bin/xamp kill 23</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Blend</text>
+ <action>EXEC /usr/bin/xamp kill 25</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Flight 26</text>
+ <action>EXEC /usr/bin/xamp kill 26</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Cinemagic</text>
+ <action>EXEC /usr/bin/xamp kill 27</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>On Broadway</text>
+ <action>EXEC /usr/bin/xamp kill 28</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>U-Pop</text>
+ <action>EXEC /usr/bin/xamp kill 29</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Hitlist</text>
+ <action>EXEC /usr/bin/xamp kill 30</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Torch</text>
+ <action>EXEC /usr/bin/xamp kill 31</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Message</text>
+ <action>EXEC /usr/bin/xamp kill 32</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Spirit</text>
+ <action>EXEC /usr/bin/xamp kill 33</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>enLighten</text>
+ <action>EXEC /usr/bin/xamp kill 34</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Deep Tracks</text>
+ <action>EXEC /usr/bin/xamp kill 40</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Boneyard</text>
+ <action>EXEC /usr/bin/xamp kill 41</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Liquid Metal</text>
+ <action>EXEC /usr/bin/xamp kill 42</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XMU</text>
+ <action>EXEC /usr/bin/xamp kill 43</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Fred</text>
+ <action>EXEC /usr/bin/xamp kill 44</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Cafe</text>
+ <action>EXEC /usr/bin/xamp kill 45</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Top Tracks</text>
+ <action>EXEC /usr/bin/xamp kill 46</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Ethel</text>
+ <action>EXEC /usr/bin/xamp kill 47</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Squizz</text>
+ <action>EXEC /usr/bin/xamp kill 48</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Big Tracks</text>
+ <action>EXEC /usr/bin/xamp kill 49</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Loft</text>
+ <action>EXEC /usr/bin/xamp kill 50</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Music Lab</text>
+ <action>EXEC /usr/bin/xamp kill 51</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Verge</text>
+ <action>EXEC /usr/bin/xamp kill 52</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Fungus</text>
+ <action>EXEC /usr/bin/xamp kill 53</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Lucy</text>
+ <action>EXEC /usr/bin/xamp kill 54</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Soul Street</text>
+ <action>EXEC /usr/bin/xamp kill 60</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Flow</text>
+ <action>EXEC /usr/bin/xamp kill 61</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Suite 62</text>
+ <action>EXEC /usr/bin/xamp kill 62</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Groove</text>
+ <action>EXEC /usr/bin/xamp kill 64</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Rhyme</text>
+ <action>EXEC /usr/bin/xamp kill 65</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>RAW</text>
+ <action>EXEC /usr/bin/xamp kill 66</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The City</text>
+ <action>EXEC /usr/bin/xamp kill 67</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Heat</text>
+ <action>EXEC /usr/bin/xamp kill 68</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Real Jazz</text>
+ <action>EXEC /usr/bin/xamp kill 70</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Watercolors</text>
+ <action>EXEC /usr/bin/xamp kill 71</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Beyond Jazz</text>
+ <action>EXEC /usr/bin/xamp kill 72</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>High Standards</text>
+ <action>EXEC /usr/bin/xamp kill 73</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Bluesville</text>
+ <action>EXEC /usr/bin/xamp kill 74</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Hear Music</text>
+ <action>EXEC /usr/bin/xamp kill 75</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Fine Tuning</text>
+ <action>EXEC /usr/bin/xamp kill 76</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Audio Visions</text>
+ <action>EXEC /usr/bin/xamp kill 77</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Escape</text>
+ <action>EXEC /usr/bin/xamp kill 78</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>On The Rocks</text>
+ <action>EXEC /usr/bin/xamp kill 79</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Move</text>
+ <action>EXEC /usr/bin/xamp kill 80</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>BPM</text>
+ <action>EXEC /usr/bin/xamp kill 81</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The System</text>
+ <action>EXEC /usr/bin/xamp kill 82</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Chrome</text>
+ <action>EXEC /usr/bin/xamp kill 83</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM-Chill</text>
+ <action>EXEC /usr/bin/xamp kill 84</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Fuego</text>
+ <action>EXEC /usr/bin/xamp kill 90</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Viva</text>
+ <action>EXEC /usr/bin/xamp kill 91</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Aguila</text>
+ <action>EXEC /usr/bin/xamp kill 92</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Caliente</text>
+ <action>EXEC /usr/bin/xamp kill 94</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Luna</text>
+ <action>EXEC /usr/bin/xamp kill 95</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Air Musique</text>
+ <action>EXEC /usr/bin/xamp kill 100</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Joint</text>
+ <action>EXEC /usr/bin/xamp kill 101</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Sur La Route</text>
+ <action>EXEC /usr/bin/xamp kill 102</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>World Zone</text>
+ <action>EXEC /usr/bin/xamp kill 103</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Ngoma</text>
+ <action>EXEC /usr/bin/xamp kill 104</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Classics</text>
+ <action>EXEC /usr/bin/xamp kill 110</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Vox</text>
+ <action>EXEC /usr/bin/xamp kill 112</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Pops</text>
+ <action>EXEC /usr/bin/xamp kill 113</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Kids</text>
+ <action>EXEC /usr/bin/xamp kill 116</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Bob Edwards Show</text>
+ <action>EXEC /usr/bin/xamp kill 133</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>XM Comedy</text>
+ <action>EXEC /usr/bin/xamp kill 150</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Laugh USA</text>
+ <action>EXEC /usr/bin/xamp kill 151</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Special X</text>
+ <action>EXEC /usr/bin/xamp kill 154</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Agenda</text>
+ <action>EXEC /usr/bin/xamp kill 134</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Oprah and Friends</text>
+ <action>EXEC /usr/bin/xamp kill 156</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>The Virus</text>
+ <action>EXEC /usr/bin/xamp kill 202</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>1 Hit Wonders</text>
+ <action>EXEC /usr/bin/xamp kill 300</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Metalcore</text>
+ <action>EXEC /usr/bin/xamp kill 301</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>New Indie First</text>
+ <action>EXEC /usr/bin/xamp kill 302</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Late Night Mix</text>
+ <action>EXEC /usr/bin/xamp kill 303</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Sessions@AOL</text>
+ <action>EXEC /usr/bin/xamp kill 304</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>Shuffle</text>
+ <action>EXEC /usr/bin/xamp kill 305</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>New Rock First</text>
+ <action>EXEC /usr/bin/xamp kill 306</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>New Country First</text>
+ <action>EXEC /usr/bin/xamp kill 307</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>New Hip Hop First</text>
+ <action>EXEC /usr/bin/xamp kill 308</action>
+ </button>
+
+ <button>
+ <type>MUSIC</type>
+ <text>New Pop First</text>
+ <action>EXEC /usr/bin/xamp kill 309</action>
+ </button>
+
+ <button>
+ <type>TV_DELETE</type>
+ <text>Stop Listening</text>
+ <action>EXEC /usr/bin/xamp kill</action>
+ </button>
+
+</mythmenu>
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<QString,QStringList> MythCoreContext::list_settingsgroupname()
++{
++ return d->m_database->list_settingsgroupname();
++}
++
++QMap<QString,QStringList> 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<QString,QString> vp_map,
++ QString table)
++{
++ return d->m_database->import_settings(vp_map, table);
++}
++
++
++QMap<QString, QMap<QString,QString> > 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<QString,QStringList> list_settingsgroupname();
++ QMap<QString,QStringList> 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<QString,QString> vp_map, QString table);
++
++ QMap<QString,QMap <QString,QString> > 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<QString,QStringList> 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<QString,QStringList> 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<QString,QStringList> 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<QString,QStringList> 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<QString,QString> 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<QString, QMap<QString,QString> >
++ MythDB::export_settings(QString src_hostname,
++ QString saved_settingsgroupname,
++ QStringList table_list)
++{
++ QMap<QString, QMap<QString,QString> > 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<QString,QString> 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<QString,QStringList> list_settingsgroupname();
++
++ QMap<QString,QStringList> 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<QString,QString> vp_map, QString table);
++
++
++ QMap<QString,QMap <QString,QString> > 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 <iostream>
++
++//QT includes
++#include <qdom.h>
++#include <QFile>
++#include <QDomElement>
++
++// 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<QString, QStringList> 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<QString, QStringList>::iterator i;
++
++
++ for (i = resultset.begin(); i != resultset.end(); ++i)
++ {
++ cout << endl<<i.key().toLocal8Bit().constData() << ": \t" << endl;;
++ //construct the headers
++ if (i.key() == "Settings")
++ {
++ //settings header
++ tempList = (i.value().at(0)).split("|", QString::SkipEmptyParts);
++ host_1 = tempList.at(1);
++ host_2 = tempList.at(3);
++ tempString="|";
++ tempItem = "Value";
++ tempString.append(tempItem.leftJustified(value_width));
++ tempString.append("|");
++ tempItem = host_1; //hostname 1
++ tempString.append(tempItem.leftJustified(data_width));
++ tempString.append("|");
++ tempItem = host_2; //hostname 2
++ tempString.append(tempItem.leftJustified(data_width));
++ tempString.append("|");
++ settings_header = tempString;
++
++ cout << settings_header.toLocal8Bit().constData() << endl;;
++ cout << dashline_settings.toLocal8Bit().constData() << endl;
++ }
++
++ if (i.key() == "Keybindings")
++ {
++ //keybindings_header
++ tempList = (i.value().at(0)).split("|", QString::SkipEmptyParts);
++ host_1 = tempList.at(2);
++ host_2 = tempList.at(4);
++ tempString="|";
++ tempItem = "Context";
++ tempString.append(tempItem.leftJustified(context_width));
++ tempString.append("|");
++ tempItem = "Action";
++ tempString.append(tempItem.leftJustified(action_width));
++ tempString.append("|");
++ tempItem = host_1;
++ tempString.append(tempItem.leftJustified(key_width));
++ tempString.append("|");
++ tempItem = host_2;
++ tempString.append(tempItem.leftJustified(key_width));
++ tempString.append("|");
++ keybindings_header = tempString;
++
++ cout << keybindings_header.toLocal8Bit().constData() << endl;;
++ cout << dashline_key.toLocal8Bit().constData() << endl;
++
++ }
++ // format each line
++ for (int y = 0; y < i.value().size(); ++y)
++ {
++ if (i.key() == "Settings")
++ {
++ tempList = (i.value().at(y)).split("|",
++ QString::SkipEmptyParts);
++ data_1 = tempList.at(2);
++ data_2 = tempList.at(4);
++ value = tempList.at(0);
++ tempString="|";
++ tempItem = value;
++ tempString.append(tempItem.leftJustified(value_width));
++ tempString.append("|");
++ tempItem = data_1;
++ tempString.append(tempItem.leftJustified(data_width));
++ tempString.append("|");
++ tempItem = data_2;
++ tempString.append(tempItem.leftJustified(data_width));
++ tempString.append("|");
++ }
++ if (i.key() == "Keybindings")
++ {
++ tempList = (i.value().at(y)).split("|",
++ QString::SkipEmptyParts);
++ data_1 = tempList.at(3);
++ data_2 = tempList.at(5);
++ context = tempList.at(0);
++ action = tempList.at(1);
++
++ tempString="|";
++ tempItem = context;
++ tempString.append(tempItem.leftJustified(context_width));
++ tempString.append("|");
++ tempItem = action;
++ tempString.append(tempItem.leftJustified(action_width));
++ tempString.append("|");
++ tempItem = data_1;
++ tempString.append(tempItem.leftJustified(key_width));
++ tempString.append("|");
++ tempItem = data_2;
++ tempString.append(tempItem.leftJustified(key_width));
++ tempString.append("|");
++ }
++
++ cout << tempString.toLocal8Bit().constData()<<endl;
++ }
++ }
++};
++
++static int DiffSettings(const MythUtilCommandLineParser &cmdline)
++{
++ QMap<QString, QStringList> resultset;
++ QString diff_hostname1;
++ QString diff_hostname2;
++ QStringList table_list;
++ bool format_results = FALSE;
++ QMap<QString, QStringList>::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()<<endl;
++ cout << endl;
++ }
++ }
++ }
++ return GENERIC_EXIT_OK;
++};// DiffSettings
++
++static int ListGroups(const MythUtilCommandLineParser &cmdline)
++{
++ QMap<QString, QStringList> resultset;
++ resultset = gCoreContext->list_settingsgroupname();
++ QMap<QString, QStringList>::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<QString,QString> 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<QString, QMap<QString,QString> > 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<QString,int> record_count;
++ QMap<QString,QMap<QString,QString> >::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<QString,QString> value_pair = i.value();
++ QMap<QString, QString>::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<QString, int >::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 <linux at m-thomson dot net>
+# With thanks to Stu Tomlinson <stu at nosnilmot dot com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-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 "<!--#XBMC-->" >> /tmp/library.xml.tmp
+ echo " <button>" >> /tmp/library.xml.tmp
+ echo " <type>MENU_XBMC</type>" >> /tmp/library.xml.tmp
+ echo " <text>Launch XBMC</text>" >> /tmp/library.xml.tmp
+ echo " <action>EXEC /usr/bin/xbmc</action>" >> /tmp/library.xml.tmp
+ echo " </button>" >> /tmp/library.xml.tmp
+ echo "<!--#XBMC-->" >> /tmp/library.xml.tmp
+ echo "" >> /tmp/library.xml.tmp
+ echo "</mythmenu>" >> /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';
+ }
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