Building a TV Server on a Synology NAS

1. Work Environment

NAS:  Synology DS213 with DSM 4.2-­â€3211
OS for Cross Compiling:  CentOS 6.3

Before you begin:

Enable SSH.

If you have a battery backup unit then enable UPS.

Enable guest account.

Enable Web Station (for channel icons).

Create Windows Share folders (temp, recordings, documents, pictures, music, & videos)

You will need to donate $20 to mc2xml.dyndns.org to get a version of the software that will run on your Synology DS213 which has an Arm processor and won’t run the standard x86 version that you can download from the site.

You will also need a subscription to Schedules Direct.

2. Bootstrap

	DiskStation> cd /volume1/@tmp

	DiskStation> wget http://wizjos.endofinternet.net/synology/archief/syno-mvkw-bootstrap_1.2-7_arm-ds111.xsh

	DiskStation> chmod +x syno-mvkw-bootstrap_1.2-7_arm-ds111.xsh

	DiskStation> sh syno-mvkw-bootstrap_1.2-7_arm-ds111.xsh

	#-- needed since DSM 4.0

	DiskStation> vi /root/.profile

	#-- add /opt/bin:/opt/sbin: after PATH=

	#-- PATH=/opt/bin:/opt/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/syno/...

	#-- add this line at the end: export LD_LIBRARY_PATH="/opt/lib/:/lib/:$LD_LIBRARY_PATH"

	DiskStation> reboot

2.1 Dependencies for Compiling

	DiskStation> ipkg update

	DiskStation> ipkg upgrade

	DiskStation> ipkg install optware-devel

	DiskStation> ipkg install git

	DiskStation> ipkg install openssl

	DiskStation> ipkg install gcc

	DiskStation> ipkg install openssl-dev

	DiskStation> ipkg install nano

	#-- copy some libraries

	DiskStation> cp /opt/arm-none-linux-gnueabi/lib/libpthread-2.5.so /opt/arm-none-linux-gnueabi/lib/libpthread-2.5.so.bk

	DiskStation> cp /lib/libpthread.so.0 /opt/arm-none-linux-gnueabi/lib/libpthread-2.5.so

	DiskStation> cp /opt/lib/libssl.so.0.9.8 /opt/arm-none-linux-gnueabi/lib

	DiskStation> cp /opt/lib/libssl.so.0.9.8 /lib

	DiskStation> cp /opt/lib/libcrypto.so.0.9.8 /lib

3. Update GCC

Versions of TVHeadend above 3.2 require GCC 4.3+, therefore, it is necessary to update GCC in order to use the latest version of TVHeadend.  This can take half a day to compile.  Another option is to create a chroot environment.

	#-- If /bin/bash doesn't exist then create a symlink to it.

	DiskStation> ln -s /opt/bin/bash /bin/bash

	# Create a build directory and change to it

	DiskStation> mkdir /volume1/src

	DiskStation> ln -s /volume1/src /src

	DiskStation> cd /src

	# Fetch tarballs

	DiskStation> wget ftp://ftp.gmplib.org/pub/gmp-5.0.2/gmp-5.0.2.tar.bz2

	DiskStation> wget http://www.mpfr.org/mpfr-current/mpfr-3.1.2.tar.bz2

	DiskStation> wget http://www.multiprecision.org/mpc/download/mpc-0.9.tar.gz

	DiskStation> wget http://www.mr511.de/software/libelf-0.8.13.tar.gz

	DiskStation> wget http://ftp.gnu.org/gnu/gcc/gcc-4.7.2/gcc-4.7.2.tar.gz

	# Unpack tarballs

	DiskStation> tar xvjf gmp-5.0.2.tar.bz2

	DiskStation> tar xvjf mpfr-3.1.2.tar.bz2

	DiskStation> tar xvzf mpc-0.9.tar.gz

	DiskStation> tar xvzf libelf-0.8.13.tar.gz

	DiskStation> tar xvzf gcc-4.7.2.tar.gz

	# Build GMP

	DiskStation> cd /src/gmp-5.0.2

	DiskStation> CPPFLAGS=-fexceptions ./configure --enable-cxx --prefix=/opt

	DiskStation> make

	DiskStation> make install

	# Build MPFR

	DiskStation> cd /src/mpfr-3.1.2

	DiskStation> ./configure --prefix=/opt

	DiskStation> make

	DiskStation> make install

	# Build MPC

	DiskStation> cd /src/mpc-0.9

	DiskStation> ./configure --prefix=/opt

	DiskStation> make

	DiskStation> make install

	# Build Libelf

	DiskStation> cd /src/libelf-0.8.13

	DiskStation> ./configure --disable-nls --prefix=/opt

	DiskStation> make

	DiskStation> make install

	# fix some problems which would occur during gcc build process

	DiskStation> ln -s /opt/arm-none-linux-gnueabi/lib/crt1.o /usr/lib/crt1.o

	DiskStation> ln -s /opt/arm-none-linux-gnueabi/lib/crti.o /usr/lib/crti.o

	DiskStation> ln -s /opt/arm-none-linux-gnueabi/lib/crtn.o /usr/lib/crtn.o

	DiskStation> ln -s /opt/include /usr/include

	# GCC build (takes a very long time since a 3-stage bootstrap process is used)

	DiskStation> mkdir -p /src/gcc-4.7.2/build

	DiskStation> cd /src/gcc-4.7.2/build

	DiskStation> ../configure --disable-nls --disable-multilib --disable-libgomp --prefix=/opt --oldincludedir=/opt --enable-languages=c

	DiskStation> make

	DiskStation> ipkg -force-depends remove gcc

	DiskStation> make install

4. SiliconDust Driver & Tool

	DiskStation> cd /opt

	DiskStation> wget http://download.silicondust.com/hdhomerun/libhdhomerun_20120405.tgz

	DiskStation> tar -xpf libhdhomerun_20120405.tgz

	DiskStation> cd /opt/libhdhomerun

	DiskStation> make

5. DVB Drivers

The following steps will build kernel modules for your Synology NAS. You can save time by downloading the files here.

5.1 Kernel Part (compiled with CentOS 6.3)

	#-- CentOS 6.3 needs the package ncurses-devel

	#-- 'make menuconfig' requires the ncurses libraries

	root@centos> yum install ncurses-devel

	root@centos> cd /home/administrator/Downloads

	#-- Synology Kernel Sources -- has to match with the cpu in your NAS

	root@centos> wget http://sourceforge.net/projects/dsgpl/files/Synology%20NAS%20GPL%20Source/2636branch/synogpl-2636-6281.tbz/download

	#-- DSM Tool Chain -- has to match with the cpu in your NAS

	root@centos> wget http://sourceforge.net/projects/dsgpl/files/DSM%204.1%20Tool%20Chains/Marvell%2088F628x%20Linux%202.6.32/gcc421_glibc25_88f6281-GPL.tgz/download

	root@centos> tar -xvzf gcc421_glibc25_88f6281-GPL.tgz -C /usr/local/

	root@centos> tar -xvjf synogpl-2636-6281.tbz -C /usr/local/arm-none-linux-gnueabi/

	#-- compile DVB Core Driver

	root@centos> cd /usr/local/arm-none-linux-gnueabi/source/linux-2.6.32/

	root@centos> cp /usr/local/arm-none-linux-gnueabi/source/linux-2.6.32/synoconfigs/88f6281 /usr/local/arm-none-linux-gnueabi/source/linux-2.6.32/.config

	root@centos> make ARCH=arm CROSS_COMPILE=/usr/local/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi- menuconfig

	#-- a menu appears, where you have to choose the device drivers for the tuners.

	#-- select "Device Drivers".

	#-- go to "Multimedia support", press Y to include

	#-- select "Multimedia support".

	#-- go to "Video For Linux", press M to include as module.

	#-- go to "DVB for Linux", press M to include as module.

	#-- select "Customize analog and hybrid tuner modules to build" and make sure that everything is selected in that section.

	#-- go back to "Multimedia Support" and select “Video Capture Adapters”.

	#-- go to “Conexant cx23416/cx23415 MPEG encoder/decoder support”, press M to include as module.

	#-- select “V4L USB devices” and place an M next to “USB Video Class (UVC)”, “Hauppage WinTV-PVR USB2 support”, and "Conexant cx231xx USB video capture support".

	#-- go back to main screen and exit (yes to save the new config).

	root@centos> make ARCH=arm CROSS_COMPILE=/usr/local/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi- prepare scripts

	root@centos> make ARCH=arm CROSS_COMPILE=/usr/local/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi- modules

	#-- compile DVB Drivers for HDHomeRun

	root@centos> cd /home/administrator/src

	root@centos> cvs -z3 -d:pserver:anonymous@dvbhdhomerun.cvs.sourceforge.net:/cvsroot/dvbhdhomerun co -P dvbhdhomerun

	root@centos> cd /home/administrator/src/dvbhdhomerun/kernel

	#-- edit the Makefile

	root@centos> nano Makefile

	#-- change KERNEL_VERSION

	#-- KERNEL_VERSION := 2.6.32.12

	#-- change KERNEL_DIR

	#-- KERNEL_DIR := /usr/local/arm-none-linux-gnueabi/source/linux-2.6.32

	root@centos> make ARCH=arm CROSS_COMPILE=/usr/local/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-

	#-- V4L modules are located at:

	#-- /usr/local/arm-none-linux-gnueabi/source/linux-2.6.32/drivers/media

	#-- (with the exception of the i2c files which are located in the i2c folder under drivers)
	
	#-- dvb-core.ko is located at:

	#-- /usr/local/arm-none-linux-gnueabi/source/linux-2.6.32/drivers/media/dvb/dvb-core

	#-- dvb_hdhomerun_core.ko

	#-- dvb_hdhomerun_fe.ko

	#-- dvb_hdhomerun.ko are located at:

	#-- /home/administrator/src/dvbhdhomerun/kernel

	DiskStation> mkdir /opt/lib/modules

	DiskStation> mkdir /opt/lib/modules/2.6.32

	DiskStation> mkdir /opt/dvb_native

	DiskStation> mkdir /root/.xmltv

Copy all of the V4L KO files within the media folder (including the i2c folder under drivers) to /opt/lib/modules/2.6.32 of your NAS. Copy dvb-core.ko, dvb_hdhomerun_core.ko, dvb_hdhomerun_fe.ko, and dvb_hdhomerun.ko to /opt/dvb_native of your NAS.  Copy the firmware files to /usr/syno/hotplug/firmware of your NAS.

5.2. Userspace Part

Copy the dvbhdhomerun folder from /home/administrator/src to /opt of your NAS.

	#-- edit the dvbhdhomerun config file

	DiskStation> nano /opt/dvbhdhomerun/etc/dvbhdhomerun

	#-- change the [XXXXYYYY-Z] to the serial #'s of your adapters.

	#-- [10343B98-0], [10343B98-1], [10368D88-0], & [10368D88-1]

	#-- change tuner_type=ATSC and save to /etc/dvbhdhomerun.
	#-- compiling userspace part requires cmake, not available through ipkg

	#-- CMAKE Sources

	DiskStation> cd /opt

	DiskStation> wget http://www.cmake.org/files/v2.8/cmake-2.8.8.tar.gz

	DiskStation> tar -xpf cmake-2.8.8.tar.gz

	DiskStation> cd /opt/cmake-2.8.8

	DiskStation> ./bootstrap

	DiskStation> make

	DiskStation> make install

	#-- compile userspace part

	DiskStation> cd /opt/dvbhdhomerun/userhdhomerun

	#-- edit CMakeLists.txt

	DiskStation> nano CMakeLists.txt

	#-- change LIBHDHOMERUN_PATH to where the

	#-- compiled SiliconDust driver/tools are

	#-- SET(LIBHDHOMERUN_PATH /opt/libhdhomerun)

	DiskStation> make

6. Scripts

Create the following scripts in their respective locations and make them executable (ie. chmod ug+x /script/path).

6.1. /opt/start_hauppauge

	#!/bin/sh
	# Original script has been written by Davy Leggieri (hey another French guy :-)
	# Modified by Charles-Henri Hallard on April 2012 to fit with my configuration
	#
	MODULES_DIR="/opt/lib/modules/2.6.32"
	MAINMODULE="i2c-core.ko"
	SUBMODULES="i2c-algo-bit.ko tuner-xc2028.ko tuner-types.ko tuner-simple.ko mt20xx.ko tea5767.ko tea5761.ko tda9887.ko tda827x.ko tda18271.ko tda8290.ko xc5000.ko mt2060.ko mt2266.ko qt1010.ko mt2131.ko mxl5005s.ko mxl5007t.ko mc44s803.ko ir-common.ko v4l1-compat.ko videodev.ko v4l2-int-device.ko v4l2-common.ko tuner.ko saa7115.ko saa717x.ko saa7127.ko msp3400.ko cs53l32a.ko m52790.ko wm8775.ko wm8739.ko vp27smpx.ko cx25840.ko upd64031a.ko upd64083.ko tveeprom.ko videobuf-core.ko videobuf-vmalloc.ko cx231xx.ko cx2341x.ko pvrusb2.ko ivtv.ko uvcvideo.ko ir-kbd-i2c.ko"

	start_modules(){
	  echo "--- Load modules ---"
	  for i in $MAINMODULE $SUBMODULES; do
	    echo "Loading $i"
	    insmod $MODULES_DIR/$i
	  done
	  # Create the Video Devices (4 should be enough for me)
	  if [ ! -c /dev/video0 ]; then
	    mknod /dev/video0 c 81 0
	    mknod /dev/video1 c 81 1
	    mknod /dev/video2 c 81 2
	    mknod /dev/video3 c 81 3
	    # Set permissions
	    chown root:root /dev/video*
	  fi
	}

	stop_modules(){
	  echo "--- Unload modules ---"
	  for i in $SUBMODULES $MAINMODULE; do
	    echo "Unloading $i"
	    rmmod $MODULES_DIR/$i
	  done
	}

	case "$1" in
	start)
	  start_modules
	  ;;
	stop)
	  stop_modules
	  ;;
	*)
	  echo "usage: $0 { start | stop }" >&2
	  exit 1
	  ;;
	esac

6.2. /opt/start_homerun

	#!/bin/sh

	# Load Core modules
	#
	insmod /opt/dvb_native/dvb-core.ko
	insmod /opt/dvb_native/dvb_hdhomerun_core.ko
	#
	# Load BE & FE modules
	#
	insmod /opt/dvb_native/dvb_hdhomerun_fe.ko
	insmod /opt/dvb_native/dvb_hdhomerun.ko
	#
	#lsmod to check if everything is running
	#grep -i dvb /proc/devices
	#
	DYNAMIC_ID=$(grep hdhomerun_control /proc/misc | awk "{print $1}")
	DYNAMIC_ID=${DYNAMIC_ID:0:4}
	if [ "$DYNAMIC_ID" != "" ]; then
	  echo "making node hdhomerun_control" $DYNAMIC_ID
	  mknod /dev/hdhomerun_control c 10 $DYNAMIC_ID
	else
	  echo "Unable to detect hdhomerun_control inside /proc/misc."
	fi
	# Set permissions
	chmod 666 /dev/hdhomerun_control
	chown root:root /dev/hdhomerun_control
	#
	# Clear userhdhomerun log
	rm -f "/opt/dvbhdhomerun/dvbhdhomerun.log"
	#
	# Run userhdhomerun with LD_PRELOAD
	/opt/dvbhdhomerun/userhdhomerun/build/userhdhomerun -f -u root -g root -l "/opt/dvbhdhomerun/dvbhdhomerun.log"
	#
	sleep 1
	#
	# Retrieve the major device number for DVB
	# (normally it should be 212)
	DYNAMIC_ID=$(grep DVB /proc/devices | awk "{print $1}")
	DYNAMIC_ID=${DYNAMIC_ID:0:4}
	if [ "$DYNAMIC_ID" != "" ]; then
	        echo "Creating DVB device nodes to major device #$DYNAMIC_ID..."

	        # Create device nodes for DVB
	        mkdir -p /dev/dvb/adapter0
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb0.frontend0/dev)
	        mknod /dev/dvb/adapter0/frontend0 c $DYNAMIC_ID $DYNAMIC_ID2
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb0.demux0/dev)
	        mknod /dev/dvb/adapter0/demux0 c $DYNAMIC_ID $DYNAMIC_ID2
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb0.dvr0/dev)
	        mknod /dev/dvb/adapter0/dvr0 c $DYNAMIC_ID $DYNAMIC_ID2

	        mkdir -p /dev/dvb/adapter1
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb1.frontend0/dev)
	        mknod /dev/dvb/adapter1/frontend0 c $DYNAMIC_ID $DYNAMIC_ID2
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb1.demux0/dev)
	        mknod /dev/dvb/adapter1/demux0 c $DYNAMIC_ID $DYNAMIC_ID2
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb1.dvr0/dev)
	        mknod /dev/dvb/adapter1/dvr0 c $DYNAMIC_ID $DYNAMIC_ID2

	        mkdir -p /dev/dvb/adapter2
	        DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb2.frontend0/dev)
        	mknod /dev/dvb/adapter2/frontend0 c $DYNAMIC_ID $DYNAMIC_ID2
	        DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb2.demux0/dev)
        	mknod /dev/dvb/adapter2/demux0 c $DYNAMIC_ID $DYNAMIC_ID2
	        DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb2.dvr0/dev)
        	mknod /dev/dvb/adapter2/dvr0 c $DYNAMIC_ID $DYNAMIC_ID2

	        mkdir -p /dev/dvb/adapter3
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb3.frontend0/dev)
	        mknod /dev/dvb/adapter3/frontend0 c $DYNAMIC_ID $DYNAMIC_ID2
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb3.demux0/dev)
	        mknod /dev/dvb/adapter3/demux0 c $DYNAMIC_ID $DYNAMIC_ID2
        	DYNAMIC_ID2=$(cut -f2 -d':' /sys/class/dvb/dvb3.dvr0/dev)
	        mknod /dev/dvb/adapter3/dvr0 c $DYNAMIC_ID $DYNAMIC_ID2

	        DYNAMIC_ID=$(grep hdhomerun_data /proc/devices | awk "{print $1}")
		DYNAMIC_ID=${DYNAMIC_ID:0:4}
	        if [ "$DYNAMIC_ID" != "" ]; then
		        rm -rf /dev/hdhomerun_data*

		        echo "Making node hdhomerun_data" $DYNAMIC_ID
		        mknod /dev/hdhomerun_data0 c $DYNAMIC_ID 0
		        mknod /dev/hdhomerun_data1 c $DYNAMIC_ID 1
		        mknod /dev/hdhomerun_data2 c $DYNAMIC_ID 2
		        mknod /dev/hdhomerun_data3 c $DYNAMIC_ID 3

		        chmod 666 /dev/hdhomerun_data*
		        chown root:root /dev/hdhomerun_data*
	        else
		        echo "Unable to detect hdhomerun_data inside /proc/devices."
	        fi

	        # Set permissions
        	chmod 755 /dev/dvb/adapter*
	        chmod 666 /dev/dvb/adapter*/*
        	chown root:root /dev/dvb/adapter*/*
	else
        	echo "ERROR: Unable to detect DVB inside /proc/devices;	dvb-core.k$"
        	exit 10
	fi

6.3. /opt/etc/init.d/S10modules

	/root/start_hauppauge start
	sleep 1
	/root/start_homerun
	sleep 10
	/opt/tvheadend/bin/tvheadend start -C -f -u root -g root

6.4. /root/.xmltv/grab_listings (Grab listings from Schedules Direct)

	/root/.xmltv/mc2xml -T [username]:[password] -D /root/.xmltv/mc2xml.dat -o /root/.xmltv/xmltv.xml

7. TVHeadend

	DiskStation> mkdir -p /opt/tvheadend

	DiskStation> git clone https://github.com/tvheadend/tvheadend.git /opt/tvheadend

	DiskStation> cd /opt/tvheadend

	#-- edit the src/v4l.c file

	DiskStation> nano /opt/tvheadend/src/v4l.c

	#-- Search [Ctrl-W] for 'can_mpeg' and change the value to 1.

	#-- int can_mpeg = 1;

	#-- Also search for'v4l2_std_id' and change the value to V4L2_STD_NTSC;

	#-- v4l2_std_id std = V4L2_STD_NTSC;

	#-- edit the Makefile

	DiskStation> nano Makefile

	#-- add bash after MKBUNDLE =

	#-- MKBUNDLE = bash $(CURDIR)/support/mkbundle

	#-- configure compilation

	DiskStation> export CC=gcc

	DiskStation> bash configure --host=armle-unknown-linux --target=armle-unknown-linux --build=i686-pc-linux --disable-avahi --release --openssl=/opt/lib --prefix=/opt/tvheadend

	DiskStation> make

	DiskStation> make install

	#-- start TVDeadend for testing purposes (-C for login without user/pwd)

	DiskStation> /opt/tvheadend/bin/tvheadend -C

	#-- http://DiskStation:9981 and create an admin user

8. Setup Channel Listings

Place ‘tv_grab_file’ into /usr/bin.  Copy the mc2xml software to /root/.xmltv of your NAS.

	#-- set permissions
	DiskStation> chmod ug+x /usr/bin/tv_grab_file
	DiskStation> chmod ug+x /root/.xmltv/mc2xml
	DiskStation> nano /etc/crontab
	0       1       *       *       *       root    /root/.xmltv/grab_listings
	DiskStation> synoservice --restart crond
	#-- try it out
	DiskStation> /root/.xmltv/grab_listings

9. XBMC Media Center

Download and install XBMC to the frontend computers. You can download the Pandora add-on here.

References

http://forum.xbmc.org/showthread.php?tid=141981

https://www.lonelycoder.com/redmine/issues/1386