LinHES Forums
http://forum.linhes.org/

DVB channnel setup
http://forum.linhes.org/viewtopic.php?f=3&t=2120
Page 1 of 1

Author:  nigelpearson [ Wed Aug 04, 2004 12:57 am ]
Post subject:  DVB channnel setup

Setting up channels in MythTV for DVB is a bit tricky because you need the frequency of the transponder, the bandwidth, the encoding rates, the modulation scheme, hiererchy and at least 3 IDs for each channel.

This guide was what I used to help me: http://www.ethics-gradient.net/myth/mythdvb.html

but it is still hard going. If you have already got DVB channel data (e.g. from the linuxtv-dvb-apps scan utility) then there are a few ways to import this data into the MythTV database:

1) zap2myth from here: http://www.cs.man.ac.uk/~brejc8/dvb

2) A script for inserting channel data from a channels.conf file, here:
Code:
#!/usr/bin/perl -w
# ============================================================================
# = NAME
# channels.conf-import
#
# = PURPOSE
# Insert DVB channel information into the MythTV database
#
# = USAGE
# channels.conf-import
# channels.conf-import -c       # Parse czap format channels.conf file
# channels.conf-import -s       # Parse szap format channels.conf file
# channels.conf-import -t       # Parse tzap format channels.conf file
# channels.conf-import -d       # Extra debugging output
# channels.conf-import -n       # No execute (safe or simulation) mode
#
# = PREREQUISITES
# 1. A MythTV backend with valid VideoSource data
#    (i.e. a listings provider which has downloaded channel information)
# 2. A channels.conf file generated from linuxtv-dvb-apps util/scan.
#    DVB-T (i.e. tzap) is assumed
#
# = DESCRIPTION
# For each channel in the database, this script tries to match
# a line from channels.conf. If it doesn't find a good match,
# it will prompt the user for a search term.
# (e.g. My database had "Seven",
#       but the network publishes itself as "7 Digital")
#
# = KNOWN BUGS
# If this is run before any channel data is inserted
# into the MythTV database, it silently hangs.
#
# = REVISION
# $Id$
#
# = AUTHORS
# Malcolm Smith, Nigel Pearson
# ============================================================================

use strict;
use DBI();
use Getopt::Long;
use File::Basename;

# configuration
#my $channelsconf = "/root/.szap/channels.conf";
#my $channelsconf = "/usr/src/DVB/apps/szap/channels.conf-dvbt-oxford";
my $channelsconf = "channels.conf";

# type of channels.conf file
my $channelsconftype = "tzap";

my $sourceid = 1;

# whether to ask for some "optional" fields
my $ask_networkid   = 0;
my $ask_providerid  = 0;
my $ask_serviceid   = 1;
my $ask_transportid = 0;

my $sql1="Invalid";

# do nothing
my $simulate = 0;

# extra console output
my $DEBUG = 0;

# ============================================================================
# Parse any command-line arguments
#
my $arg;

for $arg ( @ARGV )
{
    if ( $arg eq '-c' )
    {   $channelsconftype = 'czap'   }
    elsif ( $arg eq '-d' )
    {   $DEBUG = 1   }
    elsif ( $arg eq '-n' )
    {   $simulate = 1   }
    elsif ( $arg eq '-s' )
    {   $channelsconftype = 'szap'   }
    elsif ( $arg eq '-s' )
    {   $channelsconftype = 'tzap'   }
    elsif ( $arg eq '-v' )
    {   $channelsconftype = 'vdr'   }
    else
    {   die "Invalid argument '$arg'\n"   }
}

# ============================================================================
# variable definition
#
my $doinserts;
my $dofind;
my $networkid;
my $transportid;
my @channeldata;
my %channelhash;
my $db_host;
my $db_user;
my $db_name;
my $db_pass;

# ============================================================================
# Given a list of parsed fields, generate an SQL statement to
# insert these # fields and values into the dvb_channel table

sub genChan($@)
{
    my ($chanid, @fields) = @_;

    my $sql = 'REPLACE INTO dvb_channel (chanid, ' .
              join (', ', @fields) . ")\n" .
              "VALUES ($chanid, ";

    my $field;
    foreach $field ( @fields )
    {
        if ( defined $channelhash{$field} )
        {
            my $val = $channelhash{$field};

            if ( $val =~ /^\d*$/ )   # If value is a number
            {   $sql .= "$val, "    }
            else
            {   $sql .= "'$val', "  }
        }
        else
        {   print "\$channelhash{'$field'} does not exist\n"   }
    }

    chop $sql;chop $sql;    # Remove trailing ', '

    return "$sql);\n";
}

# ============================================================================
# Routines to parse ZAP-style files
#

sub fix_zFEC
{
    $channelhash{'fec'} =~ s/FEC_//g;
    $channelhash{'fec'} =~ s/_/\//g;
}

sub fix_zInversion
{
    if ($channelhash{'inversion'} eq "INVERSION_ON" )
    {   $channelhash{'inversion'} = '1'  }

    if ($channelhash{'inversion'} eq "INVERSION_OFF" )
    {   $channelhash{'inversion'} = '0'  }

    if ($channelhash{'inversion'} eq "INVERSION_AUTO" )
    {   $channelhash{'inversion'} = 'a'  }
}

sub fix_zMod
{
    # make modulation lowercase
    $channelhash{'modulation'} =~ s/QAM/qam/g;
}

sub parseCZAP(@)
{
    $channelhash{'frequency'}  = shift @channeldata;
    $channelhash{'inversion'}  = shift @channeldata;
    $channelhash{'symbolrate'} = shift @channeldata;
    $channelhash{'fec'}        = shift @channeldata;
    $channelhash{'modulation'} = shift @channeldata;

    &fix_zInversion;
    &fix_zFEC;
    &fix_zMod;
}

sub parseSZAP(@)
{
    $channelhash{'frequency'}  = (shift @channeldata) . '000';
    $channelhash{'polarity'}   = shift @channeldata;
    $channelhash{'satid'}      = shift @channeldata;
    $channelhash{'symbolrate'} = (shift @channeldata) . '000';

    # on dvb-s we always have qpsk
    $channelhash{'modulation'} = 'qpsk';
}

sub parseTZAP(@)
{
    $channelhash{'frequency'} = shift @channeldata;
    $channelhash{'inversion'} = shift @channeldata;
    $channelhash{'bandwidth'} = shift @channeldata;
    $channelhash{'fec'}       = shift @channeldata;
    $channelhash{'lp_code_rate'}      = shift @channeldata;
    $channelhash{'modulation'}        = shift @channeldata;
    $channelhash{'transmission_mode'} = shift @channeldata;
    $channelhash{'guard_interval'}    = shift @channeldata;
    $channelhash{'hierarchy'}         = shift @channeldata;

    # Set polarity and symbolrate here to defaults
    $channelhash{'polarity'}   = 'V';
    $channelhash{'symbolrate'} = '69000';

    &fix_zInversion;
    &fix_zFEC;
    &fix_zMod;

    $channelhash{'bandwidth'} =~ s/BANDWIDTH_//;
    $channelhash{'bandwidth'} =~ s/_.*//;

    $channelhash{'guard_interval'} =~ s/GUARD_INTERVAL_//g;
    $channelhash{'guard_interval'} =~ s/_/\//g;

    if ($channelhash{'hierarchy'} eq "HIERARCHY_NONE" )
    {   $channelhash{'hierarchy'} = 'n'  }
    else
    {   $channelhash{'hierarchy'} = 'auto'  }

    $channelhash{'lp_code_rate'} =~ s/FEC_//g;
    $channelhash{'lp_code_rate'} =~ s/_/\//g;

    $channelhash{'transmission_mode'} =~ s/TRANSMISSION_MODE_//g;
    $channelhash{'transmission_mode'} =~ s/K//g;
}

sub parseZAP
{
    if (    $channelsconftype eq 'szap' )
    {    &parseSZAP(@channeldata)    }
    elsif ( $channelsconftype eq 'czap' )
    {    &parseCZAP(@channeldata)    }
    elsif ( $channelsconftype eq 'tzap' )
    {    &parseTZAP(@channeldata)    }
    else
    {    die "Illegal channelconftype in perl script"    }

    $channelhash{'vpid'}      = shift @channeldata;
    $channelhash{'apid'}      = shift @channeldata;
    $channelhash{'serviceid'} = shift @channeldata;
    chop $channelhash{'serviceid'};
}

# ============================================================================
# Routines to parse VDR-style file

sub parseVDRs
{
    die "Sorry - Nigel hasn't implemented VDRs parsing yet";
}

sub parseVDRc
{
    die "Sorry - Nigel hasn't implemented VDRc parsing yet";
}

sub parseVDRt
{
    die "Sorry - Nigel hasn't implemented VDRt parsing yet";
}

sub parseVDR
{
    if ( grep m/:T:27500:/, @channeldata )
    {   &parseVDRt   }
    elsif ( grep m/:M.*:C:/, @channeldata )
    {   &parseVDRc   }
    else
    {   &parseVDRs   }
}

# ============================================================================

# Read the mysql.txt file in use by MythTV.
# could be in a couple places, so try the usual suspects
open(CONF, "/usr/share/mythtv/mysql.txt")
  or open(CONF, "/usr/local/share/mythtv/mysql.txt")
    or die ("Unable to open /usr/share/mythtv/mysql.txt:  $!\n\n");
while (my $line = <CONF>) {
  chomp($line);
  $line =~ s/^str //;
  my ($var, $val) = split(/\=/, $line, 2);
  next unless ($var && $var =~ /\w/);
  if ($var eq 'DBHostName') {
    $db_host = $val;
  }
  elsif ($var eq 'DBUserName') {
    $db_user = $val;
  }
  elsif ($var eq 'DBName') {
    $db_name = $val;
  }
  elsif ($var eq 'DBPassword') {
    $db_pass = $val;
  }
}
close CONF;

# Connect to the database
my $dbh = DBI->connect("dbi:mysql:database=$db_name:host=$db_host",
                       $db_user, $db_pass)
          or die "Cannot connect to database: $!\n\n";

if ($simulate) {
  print "Simulation mode. SQL not done.\n";
};

# Now retrieve data from the channel table.
my $tb_channel = $dbh->prepare("SELECT * FROM channel WHERE sourceid=$sourceid");
$tb_channel->execute();
while (my $ref = $tb_channel->fetchrow_hashref()) {
  $dofind = 0;
  print "\nFound a row: chanid = $ref->{'chanid'}, name = $ref->{'name'}\n";

  # search corresponding rows in dvb_channel
  my $tb_dvb_channel = $dbh->prepare("SELECT * FROM dvb_channel WHERE chanid=" .
 $ref->{'chanid'});
  my $count_dvbchannel = $tb_dvb_channel->execute();

  if ($count_dvbchannel >= 1) {
    # channel already exists in dvb_channel
    print "Found $count_dvbchannel corresponding row(s) in dvb_channel table\n";

    # integrity check: there have to be at least two rows in dvb_pids
    my $tb_dvb_pids = $dbh->prepare("SELECT * FROM dvb_pids WHERE chanid=" . $re
f->{'chanid'});
    my $count_dvbpids = $tb_dvb_pids->execute();
   
    if ($count_dvbpids < 2) {
      print "Warning: Less than 2 dvb_pids not found\n";
    }
    print "Do you want to re-insert? [n]/y:";
    my $selection = <>;
    chomp($selection);
    if ($selection eq "y" ) {
      $dofind = 1 ;
    }
    $tb_dvb_pids->finish();
  } else {
    # no corresponding row in dvb_channel, so let's insert data
    print "no corresponding row in dvb_channel, need data, searching channels.conf\n";
    $dofind = 1;
  }

  if ($dofind) {
    open (CHANNELSCONF, "cat $channelsconf | grep -i \"" . $ref->{'name'} . "\"
|") or die "failed opening channels.conf: $!";
    my @channelsconf = <CHANNELSCONF>;
    close CHANNELSCONF;

    my $channelsconfrows=$#channelsconf + 1;

    if ( $channelsconfrows == 0 ) {
      print "Zero rows found. Do you want to enter a search term? [n]/y:";
      my $selection = <>;
      chomp($selection);
      if ($selection eq "y" ) {
        print "Enter search term:";
        $selection = <>;
        chomp($selection);

        open (CHANNELSCONF, "cat $channelsconf | grep -i \"" . $selection . "\"
|") or die "failed opening channels.conf: $!";
        @channelsconf = <CHANNELSCONF>;
        close CHANNELSCONF;
        $channelsconfrows=$#channelsconf + 1;
      }
    }

    print "found $channelsconfrows matching rows in channels.conf\n";
   
    for (my $i = 1;$i < $channelsconfrows + 1; $i++) {
      if ( $DEBUG )
      { print "$i: $channelsconf[$i-1]" }
      else
      {
        # Print just the name, frequency and ids

        @channeldata=split(/:/, $channelsconf[$i-1]);

        print "$i: ", shift @channeldata, "\t:", shift @channeldata;
        my $sid = pop @channeldata;
        my $aid = pop @channeldata;
        my $vid = pop @channeldata;
        print ":...:$vid:$aid:$sid";
      }
    }

    print "What to do [number to select, anything else to ignore]? ";
    my $selection = <>;
    chomp($selection);

    #print $selection . "\n";

    if ($selection =~ /^\d+$/) {
      ($DEBUG) && print "using row $selection\n";

      # get the information out of the channelsconf row
      @channeldata=split(/:/, $channelsconf[$selection-1]);

      %channelhash = ();         # Clear previous insert's values
      $channelhash{'satid'} = 0; # Default of NULL is inappropriate

      shift @channeldata; # Station-published service name not used

      if ( $channelsconftype =~ m/zap$/ )
      {  &parseZAP  }
      elsif ($channelsconftype eq 'vdr')
      {  &parseVDR(@channeldata)  }
 

      if ( $DEBUG )
      {
        print "fec : $channelhash{'fec'}, ",
              "fec_lp : $channelhash{'lp_code_rate'}\n";
        print "inversion         : $channelhash{'inversion'}\n";
        print "transmission_mode : $channelhash{'transmission_mode'}\n";
        print "guard_interval    : $channelhash{'guard_interval'}\n";
        print "hierarchy    : $channelhash{'hierarchy'}\n";
        print "chanid       : $ref->{'chanid'}\n";
        print "frequency    : $channelhash{'frequency'}\n";
        print "bandwidth    : $channelhash{'bandwidth'}\n";
        print "polarity     : $channelhash{'polarity'}\n";
        print "symbolrate   : $channelhash{'symbolrate'}\n";
        print "satid        : $channelhash{'satid'}\n";
        print "modulation   : $channelhash{'modulation'}\n";
        print "VPID         : $channelhash{'vpid'}\n";
        print "APID         : $channelhash{'apid'}\n";
      }

      if ( $ask_serviceid && ! defined $channelhash{'serviceid'} ) {
        print "serviceid    : ";
        $channelhash{'serviceid'}=<>;
        chomp ($channelhash{'serviceid'});
      } else {
        print "serviceid    : $channelhash{'serviceid'}\n";
      }

      if ( $ask_transportid && ! defined $channelhash{'transportid'} ) {       
        print "transportid  : ";
        $channelhash{'transportid'}=<>;
        chomp ($channelhash{'transportid'});
      } else {
        $channelhash{'transportid'} = '0';
        print "transportid  : $channelhash{'transportid'}\n";
      }

      if ( $ask_networkid && ! defined $channelhash{'networkid'} ) {
        print "networkid    : ";
        $channelhash{'networkid'}=<>;
        chomp ($channelhash{'networkid'});
      } else {
        $channelhash{'networkid'} = '0';
        print "networkid    : $channelhash{'networkid'}\n";
      }

      if ( $ask_providerid && ! defined $channelhash{'providerid'} ) {
        print "providerid   : ";
        $channelhash{'providerid'}=<>;
        chomp ($channelhash{'providerid'});
      } else {
        $channelhash{'providerid'} = '0';
        print "providerid   : $channelhash{'providerid'}\n";
      }

      $doinserts=1;
    } else {
      $doinserts=0;
    }

    if ($doinserts==1) {
      # insert1: dvb_channel

      print "Channel type : $channelsconftype\n";

      if ($channelsconftype eq 'szap') {
        $sql1 = &genChan($ref->{'chanid'},
                         ('serviceid', 'networkid', 'transportid',
                          'frequency', 'inversion', 'symbolrate',
                          'polarity', 'satid', 'modulation') );
      }

      if ($channelsconftype eq 'szap') {
        $sql1 = &genChan($ref->{'chanid'},
                         ('serviceid', 'networkid', 'transportid',
                          'frequency', 'inversion', 'symbolrate',
                          'polarity', 'satid', 'modulation') );
      }

      if ($channelsconftype eq 'tzap') {
        $sql1 = &genChan($ref->{'chanid'},
                         ('serviceid', 'networkid', 'providerid',
                          'transportid', 'frequency', 'inversion',
                          'symbolrate', 'fec', 'polarity', 'modulation',
                          'bandwidth', 'lp_code_rate', 'transmission_mode',
                          'guard_interval', 'hierarchy') );
      }

      #insert2: vpid
      my $sql2 = "REPLACE INTO dvb_pids (chanid, pid, type) VALUES (" .
                 $ref->{'chanid'} . ", $channelhash{'vpid'}, \'v\');";

      #insert3: apid
      my $sql3 = "REPLACE INTO dvb_pids (chanid, pid, type) VALUES (" .
                 $ref->{'chanid'} . ", $channelhash{'apid'}, \'a\');";

      print "Generated SQL:\n$sql1\n$sql2\n$sql3\n";

      if ($simulate) {
        print "Simulation mode. SQL not done.\n";
      } else {
        $dbh->do($sql1);
        $dbh->do($sql2);
        $dbh->do($sql3);

        print "SQL insert complete.\n";
      }
    }
  }
  $tb_dvb_channel->finish();
}
$tb_channel->finish();

$dbh->disconnect();

Author:  cesman [ Wed Aug 04, 2004 3:19 am ]
Post subject: 

Thanks again! Added to the alpha.

Author:  nigelpearson [ Wed Aug 04, 2004 4:52 am ]
Post subject: 

Oops. Just found a mistake in the script. The DVB-C output wasn't there. The first
Code:
      if ($channelsconftype eq 'szap') {
        $sql1 = &genChan($ref->{'chanid'},
                         ('serviceid', 'networkid', 'transportid',
                          'frequency', 'inversion', 'symbolrate',
                          'polarity', 'satid', 'modulation') );
      }
should have been
Code:
      if ($channelsconftype eq 'czap') {
        $sql1 = &genChan($ref->{'chanid'},
                         ('serviceid', 'networkid', 'transportid',
                          'frequency', 'inversion', 'symbolrate',
                          'bandwidth', 'modulation', 'fec') );
      }
(I have only tested this with DVB-T)

The script isn't foolproof yet, but after some more testing (maybe by KnoppMyth R5 users?) I will ask for it to be added into the contrib directory of mythtv's source tarball.

Author:  nigelpearson [ Sun Aug 15, 2004 8:08 pm ]
Post subject: 

Fix to make it accept the '-t' argument. Change:

Code:
    elsif ( $arg eq '-s' )
    {   $channelsconftype = 'tzap'   }
to
Code:
    elsif ( $arg eq '-t' )
    {   $channelsconftype = 'tzap'   }


Discovered by Dan

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/