Sign up here and you can log into the forum!

[PLUGIN] EyeTV Live TV + channel List + SD / HD (updated)

UMSP Plugin Depot, the place for sharing plugins & info about them. No requests, just plugins/code.

[PLUGIN] EyeTV Live TV + channel List + SD / HD (updated)   

Postby dan » Wed Jun 02, 2010 11:52 am

Hi,

thanks to you all I have managed to watch live TV on my WD Live. All this works by a UMSP Plugin, a modified version of the freeview proxy, VLC, a python script and of course EyeTV.

Features:
    * channel list
    * change channel with your WD Live remote (very convenient)
    * SD & HD support
    * fast start (< 10 sec.)

Todo:
    * add EPG data to channel name
    * further improvement of stream start

Requirements:

Changelog:
    * ip of the EyeTV server is now stored in /conf/conf


SPECIAL THANKS TO:
b-rad, zoster, loulou123, Parnas



/conf/umsp.php
Code: Select all
$myMediaItems[] = array(
   'id' => 'umsp://plugins/eyetv',
   'parentID' => '0',
   'restricted' => '1',
   'dc:title' => 'TV',
   'dc:creator' => 'myCreator',
   'dc:date'   => '2009-12-30',
   'upnp:author' => 'myAuthor',
   'upnp:artist' => 'myArtist',
   'upnp:album' => 'myAlbum',
   'upnp:genre' => 'myGenre',
   'upnp:length'   => '2:10:20',
   'desc' => 'myDesc',
   'upnp:class' => 'object.container',
   'upnp:album_art'=> '',
   'duration' => '99:99:99',
   'size' => 'mySize3',
   'bitrate' => 'myBitr',
   'protocolInfo' => '*:*:*:*',
   'resolution' => 'myReso',
   'colorDepth' => 'myColor',
);


/etc/umsp/plugins/eyetv.php
Add "config_tool -c EYETV_IP=<your ip address>" to "/boot/S00custom-options" (IP from your Mac running EyeTV).
Code: Select all
<?php
/**
* CONFIG
*/
if (file_exists('/conf/config')) {
   $config = file_get_contents('/conf/config');

   if(preg_match('/EYETV_IP=\'(.+)\'/', $config, $m)) {
        $EYETV_IP = $m[1];
   }
}

define("LOG_FILE",'/tmp/umsp-log.txt');
define("PLUGIN_NAME",str_replace('.php','',basename(__file__)));
define("PLUGIN_PROXY",str_replace('.php','',basename(__file__)).'-proxy');
define('EYETV_IP',$EYETV_IP);
define('SERVER_PORT_STREAM','8484');
define('SERVER_PORT_CONTROLLER','8485');

function _pluginMain($prmQuery) {
  return _pluginCreateChannelList();
}

function _pluginCreateChannelList()
{
   $retMediaItems = array();
   $t = gzdecode(file_get_contents("http://".EYETV_IP.":2170/live/channels/0/0/",false,$context));

   if ($t) {
      $channels = json_decode($t);
   }

   if ($channels)
   {
      foreach($channels->channelList as $channel)
      {
         $item = $channel->displayNumber;
         $name = $channel->name;

         $url_data = array('item' => $item, 'itemurl' => "http://".EYETV_IP.":".SERVER_PORT_STREAM);
          $url_data_string = http_build_query($url_data, '', '&amp;');

         $retMediaItems[] = array (
            'id' => 'umsp://plugins/'.PLUGIN_NAME.'?' . $item,
            'dc:title' => $name,
            'duration' => '99:99:99',
            'upnp:class' => 'object.item.videoitem',
            'res' => 'http://127.0.0.1/umsp/plugins/'.PLUGIN_PROXY.'.php?'.$url_data_string,
            'protocolInfo' => 'http-get:*:*:*',
         );      
      }      
   }
   return $retMediaItems;
}

/**
* HELPER FUNCTIONS
*/

function gzdecode($data){
  $g=tempnam('/tmp','ff');
  @file_put_contents($g,$data);
  ob_start();
  readgzfile($g);
  $d=ob_get_clean();
  return $d;
}

/**
* Debug Logs
* stops if last param is 1
*/
function l()
{
   $t = debug_backtrace();
   $args = func_get_args();
   ob_start();
   echo basename($t[0]["file"]).":{$t[0]["line"]} > ";
   var_dump($args);
   $data = ob_get_contents();
   ob_end_clean();
   file_put_contents(LOG_FILE,$data,FILE_APPEND);
   if(end($args) === 1) die;
}

?>


/etc/umsp/plugins/eyetv-proxy.php
Code: Select all
<?php
require_once(str_replace('-proxy','',basename(__file__)));

header("Content-Size: 65535");
header("Content-Length: 65535");

if ( $_SERVER[''] == 'HEAD' ) {
   header('Content-Type: video/mpeg2ts');
   exit;
}

$rawURL = $_GET['itemurl'];
$parsedURL = parse_url($rawURL);
$itemHost = $parsedURL['host'];
$itemPath = $parsedURL['path'];
$itemPort = $parsedURL['port'];

if (isset($_GET['item']) && is_numeric($_GET['item'])) {
   file_get_contents('http://'.EYETV_IP.':'.SERVER_PORT_CONTROLLER.'/'.$_GET['item'], NULL, NULL, 0, 1);
}

_eyetvGet($itemHost, ($itemPath ? $itemPath : "/"), ($itemPort ? $itemPort : 80));

function _eyetvGet($prmHost, $prmPath, $prmPort)
{
   $fp = fsockopen($prmHost, $prmPort, $errno, $errstr, 30);
   
   if ($fp) {
      $out  = "GET ". $prmPath ." HTTP/1.1" ."\r\n";
      $out .= "User-Agent: Wget/1.12 (elf)" ."\r\n";
      $out .= "Host: " . $prmHost . "\r\n";
      $out .= "Cache-Control: no-cache" ."\r\n";
      $out .= "Connection: Close"."\r\n"."\r\n";
      fwrite($fp, $out); 
   
      $headerpassed = false;
      while ($headerpassed == false) {
         $line = fgets( $fp);
         list($tag, $value) = explode(": ", $line, 2);
         
         if (stristr($tag, 'Location')) {
            $target_url = trim($value);
            $url_data_string = http_build_query(array('itemurl' => "http://".EYETV_IP.":".SERVER_PORT_STREAM));
            header("Location: http://127.0.0.1/umsp/plugins/".basename(__file__)."?".$url_data_string."\r\n");
            continue;
         }

         if (trim($line) == "") {
            $headerpassed = true;
         header('Content-Type: video/mpeg2ts');
         }
         header($line);
      }
      set_time_limit(0);
      fpassthru($fp);
      fclose($fp);
   }
}

?>



On your Mac create a file like eyetv-controller.py
Replace <your ip address> with the IP from your Mac running EyeTV.
Code: Select all
#!/usr/bin/env python
#-*- coding: UTF-8 -*-

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import subprocess, time

last_ch = 0

class TvServerHandler(BaseHTTPRequestHandler):
   def do_GET(self):
      global last_ch
      cmd = self.path.split('/')
      if 'favicon.ico' in cmd:
         return
      ch = int(cmd[1])
      if not ch or ch < 1:
         ch = 1
      if ch == last_ch:
         return
      last_ch = ch
      
      p = subprocess.Popen("killall VLC",shell=True)
      time.sleep(0.5)
      cmd = "/Applications/VLC.app/Contents/MacOS/VLC -I dummy eyetv:// --sout='#std{access=http,mux=ts,dst=<your ip>:8484}' --sout-keep --autocrop --intf dummy --eyetv-channel=%s" % ch
      p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,close_fds=True)
      time.sleep(0.5)

      self.send_response(301)
      self.send_header("Location", "http://<your ip>:8484?t=%f" % time.time())
      self.end_headers()
      return
      
   def do_POST(self):
      pass
      return

def main():
   try:
      server = HTTPServer(('',8485),TvServerHandler)
      print 'server started'
      server.serve_forever()
   except KeyboardInterrupt:
      print 'shutting down'
      server.socket.close()

if __name__ == '__main__':
   main()



Start up EyeTV and run python eyetv-controller.py in Terminal.

Now you can browse and watch all your TV channels on you WD Live.

Feedback is welcome :P
Last edited by dan on Fri Jun 18, 2010 2:00 pm, edited 4 times in total.
dan
Developer
 
Posts: 40
Joined: Fri May 28, 2010 11:35 pm

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD   

Postby b-rad.cc » Wed Jun 02, 2010 4:56 pm

I really hate to make you re-program this, but python has already been removed from the dev version of the firmware--and it will not be re-added due to size constraints. You have perl at your disposal however.

In addition you should look at some of the other webend php files to see how we grab values from /conf/config, to let your plugin be as dynamic as possible. Theres no chance it will be included if it requires hardcoded values, but if it polls from /conf/config then its a good candidate for inclusion.

good work :mrgreen:
PM's are for private matters only, please post public matters on the forum to help others who might have the same issue.
:mrgreen:
User avatar
b-rad.cc
WDLXTV Team
 
Posts: 3002
Joined: Sat Apr 03, 2010 9:35 am
Location: New York

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD   

Postby dan » Wed Jun 02, 2010 5:02 pm

Hi b-rad,

thanks for your reply. The python part is the server running on the Mac for controlling EyeTV and VLC. So all the WD Live code is written in plain PHP, therefor hopefully future proof ;)

What do you mean by "hardcoded values"? The IP Adress? I will try to put this into the config. Thanks for the hint.

Update:
I have updated the code in my first post to meet wdlxtv coding standards. (moved hard coded IP address to the config file)
dan
Developer
 
Posts: 40
Joined: Fri May 28, 2010 11:35 pm

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD (updated   

Postby adrianc1982 » Tue Jul 27, 2010 2:35 pm

Im trying to follow your guide but I cant create files via telnet as root on /etc/umsp/plugins

How do I make the files eyetv.php and eyetv-proxy.php? Also under the folder boot theres no subfolder or could you explain a little more this:

/etc/umsp/plugins/eyetv.php
Add "config_tool -c EYETV_IP=<your ip address>" to "/boot/S00custom-options" (IP from your Mac running EyeTV).

Do I have to create a file called S00custom-options and then add the config_tool line?

Thanks
adrianc1982
n00b
 
Posts: 6
Joined: Sun May 09, 2010 9:51 am

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD (updated   

Postby adrianc1982 » Tue Jul 27, 2010 3:04 pm

Sorry I just figured out I need ext3 installed and an external device to read/write.

Can this be done under the normal firmware using the bind command?

mount -o bind /conf/eyetv.php /etc/umsp/plugins/eyetv.php

because I dont want to use an external device, I dont mind doing the bindings everytime I boot since I can probably do a script and run it each time I boot.

Help?
adrianc1982
n00b
 
Posts: 6
Joined: Sun May 09, 2010 9:51 am

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD (updated   

Postby dan » Sun Aug 15, 2010 7:57 am

Hi adrianc1982, what version of wdlxtv fw are you using?
dan
Developer
 
Posts: 40
Joined: Fri May 28, 2010 11:35 pm

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD (updated   

Postby Montreal1 » Sun Aug 15, 2010 8:03 am

Nice one...u said: * fast start (< 10 sec.)...can be done with UMSP live channels?
Montreal1
DLX'er
 
Posts: 73
Joined: Mon Jun 07, 2010 4:09 am

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD (updated   

Postby dan » Sun Aug 15, 2010 8:15 am

UMSP live channels
For what plugin?
dan
Developer
 
Posts: 40
Joined: Fri May 28, 2010 11:35 pm

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD (updated   

Postby Montreal1 » Sun Aug 15, 2010 1:37 pm

Montreal1
DLX'er
 
Posts: 73
Joined: Mon Jun 07, 2010 4:09 am

Re: [PLUGIN] EyeTV Live TV + channel List + SD / HD (updated   

Postby irod » Tue Sep 14, 2010 12:45 am

Hey guys. First of all, thanks Dan for your valuable contribution, your EyeTV plug-in rocks.

Now for my question... has anybody had issues not being able to play video smoothly? Ironically enough, if I use Dan's plug-in to stream EyeTV HD component input to my WDTV Live Plus, I get stuttery video that's full of artifacts and basically unwatchable. But if I use the same script to stream an uncompressed live recording that's being generated by EyeTV from the same input on the fly, it plays fine! Is this a problem with VLC and it's handling of the EyeTV stream? Anybody encountered this before? By the way, I'm streaming using 802.11n, not wired Ethernet (but it plays perfectly fine using the latter method, so it doesn't sound like a bandwidth issue.)

The other problem I'm having is that sometimes my WDTV Live Plus will access streams fine (using Dan's plug-in), and other times it will tell me "Unable to play the selected file. Please refer to the manual for a list of supported formats." (I suspect it just fails to connect at all). It's very random. Anyone run into this? The errors it sometimes spews out in the php log are:

[14-Sep-2010 09:30:22] PHP Warning: Cannot modify header information - headers already sent by (output started at /tmp/conf/umsp.php:25) in /tmp/umsp-plugins/eyetv/eyetv.php on line 7

[14-Sep-2010 09:30:23] PHP Warning: array_shift() expects parameter 1 to be array, null given in /tmp/umsp-plugins/eyetv/eyetv.php on line 62

[14-Sep-2010 09:30:27] PHP Warning: fsockopen() [<a href='function.fsockopen'>function.fsockopen</a>]: unable to connect to 192.168.1.54:8484 (Connection refused) in /tmp/umsp-plugins/eyetv/eyetv-proxy.php on line 31

They don't always appear though so I'm not sure if these errors are related to the issue.

Thanks a bunch!
irod
Donor
 
Posts: 2
Joined: Sat Sep 11, 2010 12:38 pm

Next

Return to UMSP Plugins

Who is online

Users browsing this forum: No registered users and 1 guest