2015-08-17, 13:13
Hi!
I want to share with you my hack of using an EyeTV dongle on Mac OS X for the native Kodi PVR interface.
I am using PVR IPTV Simple Client as the PVR client and the EyeTV application + VLC + a web server as the backend.
This is meant to be a proof-of-concept to show that it is possible to develop an EyeTV backend on Mac OS X for the Kodi PVR interface. The functionality could be ported into a native PVR plugin for a simpler setup, without the need for a separate web server and possibly without the need for VLC.
Benefits over using EyeTV Parser:
- Being able to use the native PVR interface, including EPG listings
- Better video quality
- Faster channel switching
Things that does not work but that could be possible with a native PVR plugin:
- Time-shifting
- Scheduling and recording
- EPG from DVB
The following external applications is required for this setup:
MAMP or any PHP capable server
VLC
EyeTV
VLC EyeTV Capture Plugin
EyeTV will also need to be enabled for iPhone access.
We will use the iPhone service to silently change channels, but VLC to get the video stream.
In the htdocs folder for MAMP is the following files:
.htaccess
eyetv-config.php
eyetv-stream.php
eyetv-poll.php
eyetv-playlist.php
eyetv-launch.scpt
Then, in the configuration for PVR IPTV Simple Client, set the m3u playlist to: http://localhost:8080/eyetv-playlist.m3u8 , and the XMLTV to your favorite service. It would be possible to export the EPG from EyeTV, but for my setup it's enough with an external XMLTV service.
Restart Kodi and you should then see all your EyeTV channels in the PVR interface! In uncompressed HD quality.
This setup works pretty flawless once it is set up. But to simplify the installation process and to enable recording and time shifting, someone could develop a native PVR add-on that could read directly from the EyeTV stream provided by the VLC plug-in. It seems like VLC is getting the video stream in MPEG format via a UNIX socket, according to the code available here: vlc/modules/access/eyetv.m
I want to share with you my hack of using an EyeTV dongle on Mac OS X for the native Kodi PVR interface.
I am using PVR IPTV Simple Client as the PVR client and the EyeTV application + VLC + a web server as the backend.
This is meant to be a proof-of-concept to show that it is possible to develop an EyeTV backend on Mac OS X for the Kodi PVR interface. The functionality could be ported into a native PVR plugin for a simpler setup, without the need for a separate web server and possibly without the need for VLC.
Benefits over using EyeTV Parser:
- Being able to use the native PVR interface, including EPG listings
- Better video quality
- Faster channel switching
Things that does not work but that could be possible with a native PVR plugin:
- Time-shifting
- Scheduling and recording
- EPG from DVB
The following external applications is required for this setup:
MAMP or any PHP capable server
VLC
EyeTV
VLC EyeTV Capture Plugin
EyeTV will also need to be enabled for iPhone access.
We will use the iPhone service to silently change channels, but VLC to get the video stream.
In the htdocs folder for MAMP is the following files:
.htaccess
Code:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^channel/(.+)$ eyetv-stream.php?serviceID=$1 [L,QSA]
RewriteRule ^eyetv-playlist\.m3u8$ eyetv-playlist.php [L,QSA]
# Protect the htaccess file
<Files .htaccess>
Order Allow,Deny
Deny from all
</Files>
# Disable directory browsing
Options All -Indexes
eyetv-config.php
PHP Code:
<?php
$VLC_PATH = "/Applications/VLC.app/Contents/MacOS/VLC";
$VLC_PORT = "6363";
$EYETV_SERVICE = "http://127.0.0.1:2170/";
$PHP_PATH = "/usr/bin/php";
$LOGGING_ENABLED = false;
$LOG_PATH = "/Users/Server/Library/Logs/";
$STREAM_BASE_URL = "http://localhost:8080/channel/";
function my_log($message)
{
global $LOG_PATH,$LOGGING_ENABLED;
if($LOGGING_ENABLED)
{
file_put_contents($LOG_PATH."eyetv-stream.log",date(DATE_ATOM)." \t".$message."\n",FILE_APPEND);
}
}
eyetv-stream.php
PHP Code:
<?php
include "eyetv-config.php";
ini_set('display_errors','off');
if($LOGGING_ENABLED)
{
ini_set("log_errors", 1);
ini_set("error_log", $LOG_PATH."eyetv-stream-php-error.log");
}
set_time_limit(0);
my_log($_SERVER['REQUEST_METHOD']."\t".$_GET['serviceID']);
if($_GET['serviceID']) {
//Kodi will request this page 2 times
if($_SERVER['REQUEST_METHOD'] == "HEAD")//First request, change channel
{
//Kill VLC and wait for it to close
$pid = exec("pgrep -o -x VLC");
if($pid)
{
exec("kill ".$pid);
exec("wait ".$pid);
}
//Launch EyeTV if it's not running
$pid = exec("pgrep -o -x EyeTV");
if(!$pid)
{
exec("osascript eyetv-launch.scpt");
sleep(4);
}
file_get_contents($EYETV_SERVICE."live/tuneto/1/320/".$_GET['serviceID']);
//Wait for the channel to change
$eyetv_ready = false;
$retries = 0;
while(!$eyetv_ready && $retries < 10)
{
sleep(1);
$gzip = file_get_contents($EYETV_SERVICE."live/ready");
$json = gzdecode($gzip);
$obj = json_decode($json);
my_log("Waiting for EyeTV");
$eyetv_ready = $obj->doneEncoding > 0;
$retries++;
}
//Start VLC streaming
exec($VLC_PATH." -I dummy eyetv:// --sout '#standard{access=http,mux=ts,dst=:".$VLC_PORT."}' > /dev/null 2>&1 & echo $!",$return);
$vlcpid = $return[0];
//Wait for streaming to start
sleep(1);
header("HTTP/1.1 200 OK");
header("Content-Type: application/octet-stream");
exit();
}
else //Second request, passthrough the video stream
{
header("HTTP/1.1 200 OK");
header("Content-Type: application/octet-stream");
//Poll EyeTV to keep the tuner alive
exec($PHP_PATH." eyetv-poll.php > /dev/null 2>&1 & echo $!",$return);
$pollpid = $return[0];
//When connection is closed, stop polling EyeTV and kill VLC
function shutdown($pollpid)
{
my_log("shutdown()");
exec("kill ".$pollpid);
exec("killall VLC");
}
register_shutdown_function('shutdown',$pollpid);
//Passthrough the VLC stream
$file = @fopen("http://127.0.0.1:".$VLC_PORT,"rb");
if($file)
{
fpassthru($file);
fclose($file);
} else {
my_log("no connection to stream");
}
my_log("passthru aborted, trying again");
sleep(1);
$file = @fopen("http://127.0.0.1:".$VLC_PORT,"rb");
if($file)
{
fpassthru($file);
fclose($file);
} else {
my_log("no connection to stream");
}
my_log("abort");
}
}
eyetv-poll.php
PHP Code:
<?php
include "eyetv-config.php";
set_time_limit(0);
//Sends requests to the EyeTV service every 5 seconds to keep the tuner alive
while(true) {
my_log("Polling EyeTV service");
file_get_contents($EYETV_SERVICE."live/ready");
sleep(5);
}
eyetv-playlist.php
PHP Code:
<?php
include "eyetv-config.php";
$channels_gzip = file_get_contents($EYETV_SERVICE."live/channels");
$channels_json = gzdecode($gzip);
$channels = json_decode($json);
header("Content-Type: application/vnd.apple.mpegurl");
echo "#EXTM3U";
foreach ($channels->channelList as $channel) {
echo "\n\n";
echo "#EXTINF:-1, ".$channel->name."\n";
echo $STREAM_BASE_URL.$channel->serviceID;
}
echo "\n";
eyetv-launch.scpt
Code:
tell application "EyeTV"
launch with server mode
end tell
Then, in the configuration for PVR IPTV Simple Client, set the m3u playlist to: http://localhost:8080/eyetv-playlist.m3u8 , and the XMLTV to your favorite service. It would be possible to export the EPG from EyeTV, but for my setup it's enough with an external XMLTV service.
Restart Kodi and you should then see all your EyeTV channels in the PVR interface! In uncompressed HD quality.
This setup works pretty flawless once it is set up. But to simplify the installation process and to enable recording and time shifting, someone could develop a native PVR add-on that could read directly from the EyeTV stream provided by the VLC plug-in. It seems like VLC is getting the video stream in MPEG format via a UNIX socket, according to the code available here: vlc/modules/access/eyetv.m