User:Yeffetn

From MythTV Official Wiki
Jump to: navigation, search

I'm documenting my mythtv setup so others can used ideas and code...

This page (including the code) is here 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.

Hardware

  • Computer: modified dell e520: 3GB Ram, 1TB disks total (inc. ext. USB drives), some old Firewire card and Nvidia 8600GT (for best HD experience)
  • Tuner 1: Comcast HD box (motorolla DCT62xx) connected using FireWire
  • Tuner 2+3: Silicondust_HDHomeRun

Software

  • Ubuntu Feisty, and mythtv packages that comes from the repositories of Feisty.

Getting the DCT6200 to work

First, it is important to read the FireWire page. I've found out that it is better to "prime" the firewire after every channel change. This way there are much less failures; so I'm not using mythtv's internal channel changer, instead I have the following script:

/usr/local/bin/6200ch.sh:

#!/bin/bash
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2, or (at your option)
#  any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */ 
(
/usr/local/bin/6200ch $2 -n $1 
/usr/local/bin/firewire_tester -B -n $1 || \
/usr/local/bin/firewire_tester -B -n $1 || \
/usr/local/bin/firewire_tester -B -n $1 || \
/usr/local/bin/firewire_tester -B -n $1
) >/dev/null 2>&1

The reasons I'm not using firewire_tester -r <n> (run action <n> times) are: once it is ok, I'd like it to return, and -r isn't fixing well as rerunning.

I also had to patch 6200ch.c to match my DCT6200 device:

--- 6200ch.c	2006-08-12 15:49:00.000000000 -0700
+++ ../../../6200ch.c	2007-09-21 19:38:21.397796375 -0700
@@ -40,6 +40,7 @@
 #define DCT6200_VENDOR_ID9 0x000014e8
 #define DCT6200_VENDOR_ID10 0x000016b5
 #define DCT6200_VENDOR_ID11 0x00001371
+#define DCT6200_VENDOR_ID12 0x000019a6
 #define DCT6200_SPEC_ID    0x00005068
 #define DCT6200_SW_VERSION 0x00010101
 #define DCT6200_MODEL_ID1  0x0000620a
@@ -173,6 +174,7 @@
             (dir.vendor_id == DCT6200_VENDOR_ID9) ||
             (dir.vendor_id == DCT6200_VENDOR_ID10) ||
             (dir.vendor_id == DCT6200_VENDOR_ID11) ||
+            (dir.vendor_id == DCT6200_VENDOR_ID12) ||
             (dir.vendor_id == DCT6412_VENDOR_ID1)) &&
            ((dir.model_id == DCT6200_MODEL_ID1) ||
             (dir.model_id == DCT6200_MODEL_ID2) ||


Making sure mythconverg (mysql db) is in memory all the time

Some function of mythtv will work much faster if the DB (mythconverg) is in memory all the time. Functions such as program guide, searches and even watch recordings are using the DB. However, since in most cases the mysql DB server is also the video recorder, the video files being recorded or watched will cause the DB files to be swapped out of cache. The very simple way around it is to read the files all the time. once every minute is more than enough. The size of the DB is about ~250MB which fits well in 3GB total RAM (2GB cache) and will stay there for 1 minute even while recording multiple HD shows and watching HD. I've used "cd /var/lib/mysql/mythconverg && cat * >/dev/null" in crontab, but I wanted to be more efficient, so I wrote nocat.c, that will only read 1 byte from each page (reading 1 byte is enough to tell the cache that this page is "hot"):

nocat.c:

/* This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <error.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> 

#define _GNU_SOURCE 1
#define _FILE_OFFSET_BITS 64
#define READSIZE 1
#define MYERR { error (0, errno, "%s", argv[argind]); ret=1; }

int main (int argc, char **argv) {

	int ret=0;
	int argind=0;
	int pageskip=getpagesize()-READSIZE;
	int fd;
	ssize_t rd;
	char buf[READSIZE];

	while (++argind < argc) {
		fd = open(argv[argind], O_RDONLY);
		if (fd < 0) MYERR else {
			while (rd=read(fd,&buf,READSIZE)==READSIZE) {
				if (lseek(fd,pageskip,SEEK_CUR) < 0) MYERR;
			}
			if (rd < 0) MYERR;
			if (close(fd) < 0) MYERR;
		}
	}	
	return ret;
}

I'm not using cron anymore, since it filled logfiles with messages. See below how it works.

One script that guard it all

I've noticed lack of robustness in the following areas;

  • mythbacked is crashing from time to time. (rarely, but still annoying).
  • HDHomeRun does not save config, and since I'm using it as the remote receiver as well, I'd like it to be configured all the time.
  • The DCT6200 reboots itself from time to time, and could move firewire node number becuase of that. mythtv will stop using it.

In addition, I wanted to keep mythconverg in memory (see above), but wanted to avoid cron messages every minute.

The following script prevents failures like the above, and helps keeping mythconverg in memory. I run it from /etc/rc.local with redirecting std* to and from /dev/null.

#!/bin/bash
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2, or (at your option)
#  any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */


# my hdhomerun
hdhr=10106EE1

# my dct6200
dct6200=0019a6fffef3a046
plugreport=/usr/bin/plugreport
cardid=4
cardidfilter='where cardid='
getnode='select firewire_node from capturecard'
setnode='update capturecard set firewire_node='
setextcmd='update cardinput set externalcommand='
extcmd='/usr/local/bin/6200ch.sh'
dbname=mythconverg
dbhost=localhost
dbuser=mythtv
dbpass=yourpassword
mysql=/usr/bin/mysql
mysqlcmd="$mysql -h$dbhost -u$dbuser -p$dbpass $dbname"

# Monitor
mythbackendpid=/var/run/mythtv/mythbackend.pid

# mysql cache
mysqlcachecmd='cd /var/lib/mysql/mythconverg && /usr/local/bin/nocat *'
mysqlcacheint=60

# What port
myport=5000

# Where is hdhomerun_config
hdhr_config=/usr/local/bin/hdhomerun_config

# Check every (too high might skip a powercycle, 5 is good)
interval=5

# Find my IP
hostname=`hostname`
myip=`getent hosts $hostname | cut -d' ' -f1`

# Leave blank
hdhrip=

#mysql counter init
mysqlcount=0

mythdct=`echo $getnode $cardidfilter $cardid | $mysqlcmd | tail -1`

while sleep $interval; do
	# HdHomeRun
	while ! ping -c1 -w1 $hdhrip >/dev/null 2>&1; do
		hdhrip=`$hdhr_config discover | grep $hdhr | cut -d' ' -f 6 2>/dev/null`
		$hdhr_config $hdhr set /ir/target $myip:$myport >/dev/null 2>&1
	done

	# MysqlCache
	let "mysqlcount = mysqlcount + interval"
	if [ $mysqlcount -ge $mysqlcacheint ]; then
		mysqlcount=0
		eval $mysqlcachecmd 
	fi

	# check dct6200 node
	dctisat=`$plugreport 2>/dev/null | grep $dct6200 | cut -d' ' -f 2`
	if [ -n "$dctisat" -a $dctisat -ne $mythdct ]; then
		mythdct=$dctisat
		echo $setnode $dctisat $cardidfilter $cardid \; $setextcmd \"$extcmd $dctisat\" $cardidfilter $cardid | $mysqlcmd
		/etc/init.d/mythtv-backend restart
	fi

	# check mythbackend
	if [ -f $mythbackendpid ]; then
		grep mythbackend /proc/`cat $mythbackendpid`/cmdline 2>&1 >/dev/null || \
                /etc/init.d/mythtv-backend restart
	fi
done