Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Re: Resort channels.conf



Hi Rainer,

here's my version of your script which should solve
these problems:

> There are 2 problems still to solve:
>
>  -Informations about channels which are not in the "new"
>   channels.conf will be lost (without a warning!)
>
>  -Grouping infos will be lost (without a warning!).
>
>  -Better rename solution.

And I tried to apply my "business" coding rules and added
many more comments and some other perlish things but I
hope you will like it anyway.

> (Please: Don't take it as a "reference implementation" ;-)
> It's only a -very- quick hack with a lot of work to done.
> If here is a perl hacker: pls. don't hesitate to sent a better
> version!)

The eye of the beholder :-)
Ok, here's my new version 0.03:

#!/usr/bin/perl
# Version 0.03
# Aranges a new VDR channel.conf file to the channel order
# given by a reference  channel.conf file
#
# new channels will be added at the end of the new channel.conf
#
# channels with signal IDs not existing in new channel.conf
# are kept on their old place.
#
# renamed channels will keep their old name if lookup
# via sid is possible
#
# History:
# 140808 mf keep deleted channels
#           keep grouping lines
#           more perlish style
# 030808 rz accept norma channels.conf as input
#           try to detect renames
# 020605 cp initial version
#
####################################################################

use strict;
use warnings;


####################################################################
# Constant Definitions
####################################################################

use constant DEBUG => 0; # not used yet



####################################################################
# Parameter Checks
####################################################################

if ( @ARGV < 3 ) {
  Usage();
  exit;
}

my $sourceFilename = $ARGV[0];
my $orderFilename  = $ARGV[1];
my $targetFilename = $ARGV[2];

die "Source File '$sourceFilename' not found\n" if ( ! -f $sourceFilename );
die "Ordering File '$orderFilename' not found\n" if ( ! -f $orderFilename );



####################################################################
# Load Ordering File
####################################################################

# Open Ordering File and load complete
# contents into sortedChannels Array:
my @sortedChannels = ();

# Process complete File
open( ORDERFILE, "< $orderFilename" ) || die "Cannot open Ordering File 
'$orderFilename': $!\n";
while ( my $line = <ORDERFILE> ) {
  # Extract this line and put Channel Data into the
  # Sorted Channel Array:
  my $channel = ExtractChannelData( $line );
  push( @sortedChannels, $channel );
} # while
close( ORDERFILE );



####################################################################
# Load new Source File
####################################################################

# Open the new channels.conf Source File and
# load Channels in two Lookup Hashes
my %newChannelName = ();   # Hash: Key=Name, Value=New Channel Data
my %newChannelSID  = ();   # Hash: Key=SID, Value=New Channel Data
my @unsortedChannels = (); # Array: all new Channels

open( SOURCEFILE, "< $sourceFilename" ) || die "Cannot open Source File 
'$sourceFilename': $!\n";
while ( my $lineBuffer = <SOURCEFILE> ) {

  # Extract Channel data
  my $channel = ExtractChannelData( $lineBuffer );

  # Mark Channel unused first
  $channel->{'Used'} = 0;

  # No need to remember any Grouping or Command Lines
  # because this file will never be sorted.
  if ( IsChannelData( $channel ) ) {

    # Remember this new Channel for later use
    push( @unsortedChannels, $channel );

    # We put this new Channel in two Lookup Hashes:
    # One for Name-Lookup and one for SID-Lookup
    $newChannelName{ $channel->{'Name'} } = $channel;
    $newChannelSID{ $channel->{'SID'} } = $channel;
  }

} # while
close( SOURCEFILE );



####################################################################
# Write ordered channels in given order
####################################################################

# We create the new target file and
open( TARGETFILE, "> $targetFilename" ) || die "Cannot open Target File 
'$targetFilename': $!\n";

# Walk through all sorted Channels and try to find the new
# Channel Data for this line:
my $renamedChannels = 0;
my $removedChannels = 0;
foreach my $oldChannel ( @sortedChannels ) {

  # Try to find the matching new Channel now:
  my $newChannel;

  # Is this Channel Object just a Group Line
  # or a real Channel.
  if ( IsChannelData( $oldChannel ) ) {

    # We try to find the new Channel Data by Name first:
    if ( exists $newChannelName{ $oldChannel->{'Name'} } ) {
      # Ok, this is our new Channel Data
      $newChannel = $newChannelName{ $oldChannel->{'Name'} };
    }
    elsif ( exists $newChannelSID{ $oldChannel->{'SID'} } ) {
      # Ok, this is our new Channel Data
      $newChannel = $newChannelSID{ $oldChannel->{'SID'} };
      # But we want to keep the old name:
      $newChannel->{'Name'} = $oldChannel->{'Name'};
      # This is a renamed Channel:
      $renamedChannels++;
    }
    else {
      # New channel.conf has no matching channel. Not
      # found by name nor by sid...
      # ...well, we just keep the old Channel Data :-)
      $newChannel = $oldChannel;
      # This is a removed Channel
      $removedChannels++;
    }
  }
  else {
    # Just a Group Line, we just keep it
    $newChannel = $oldChannel;
  }

  # Write the new channel.conf line of this channel
  print TARGETFILE ComputeChannelLine( $newChannel );

  # Mark this new Channel as used, so we can
  # examine the new unused channels later...
  $newChannel->{'Used'} = 1;
}


# Now write all new unused channels in
# original order. This is the only use
# of our unsortedChannels Array ;-)
print TARGETFILE ":NEW CHANNELS\n";
my $addedChannels = 0;
foreach my $newChannel ( @unsortedChannels ) {
  # Only print channels not already used
  if( $newChannel->{'Used'} == 0 ) {
    # Write the new channel.conf line of this channel
    print TARGETFILE ComputeChannelLine( $newChannel );
    # Mark Channel as used
    $newChannel->{'Used'} = 1;
    # One new Channel added
    $addedChannels++;
  }
}
close( TARGETFILE );

printf STDERR "Updated %s existing channels.\n", scalar( @sortedChannels );
printf STDERR "Added %s new channels.\n", $addedChannels;
printf STDERR "Found %s renamed channels.\n", $renamedChannels;
printf STDERR "Found %s removed channels.\n", $removedChannels;

# Finish
exit 0;


##########################################################################
# Subroutines follow here...
##########################################################################


# ExtractChannelData
#
# Takes a line from an channel.conf and creates a Channel Data
# Hash with all it's data. The Hash reference will be returned.
#
# Parameter
#   [0] single line of channel.conf
#
# Returns
#   Reference to Channel Data Hash
#
sub ExtractChannelData {
  # Parameters
  my $lineBuffer = $_[0];

  # Rückgabe
  my $channelData = { };

  # Remove CR/LF
  chomp( $lineBuffer );

  # Split this line
  my ( $Name, $Frequency, $Parameters, $Source, $Srate,
       $VPIFD, $APID, $TPID, $CA, $SID, $NID, $TID, $RID,
       @Remarks ) = split( /:/, $lineBuffer );

  # Line without Name or SID? Probably a new group:
  if ( ! defined $Name || $Name eq '' ||
       ! defined $SID  || $SID  eq '' ) {
    # Grouping line: we simply save the complete
    # line contents now:
    $channelData = {
        'Name'  => '',
        'SID'   => '',
        'Group' => $lineBuffer,
       };
  }
  else {
    # Create Hash Reference
    $channelData = {
        'Name' => $Name,
        'Frequency' =>$Frequency,
        'Parameters' => $Parameters,
        'Source' => $Source,
        'Srate' => $Srate,
        'VPIFD' => $VPIFD,
        'APID' => $APID,
        'TPID' => $TPID,
        'CA' => $CA,
        'SID' => $SID,
        'NID' => $NID,
        'TID' => $TID,
        'RID' => $RID,
        'Remark' => join( ":", @Remarks ),
      };
  }

  # Done
  return $channelData;
}


# ComputeChannelLine
#
# Takes the Reference of a Channel Data Hash and computes
# an new line for channel.conf. The line (including CR)
# will be returned.
#
# Parameter
#   [0] Reference to Channel Data Hash
#
# Returns
#   Hash Reference
#
sub ComputeChannelLine {
  # Parameters
  my $channelData = $_[0];

  # Return
  my $lineBuffer = "";

  # Group Line Detection:
  if ( $channelData->{'Name'} eq '' ||
       $channelData->{'SID'} eq '' ) {
    # Compute channel.conf group line
    $lineBuffer = "$channelData->{Group}\n";
  }
  else {
    # Compute channel.conf line format
    $lineBuffer = 
"$channelData->{Name}:$channelData->{Frequency}:$channelData->{Parameters}:".
                  
"$channelData->{Source}:$channelData->{Srate}:$channelData->{VPIFD}:".
                  
"$channelData->{APID}:$channelData->{TPID}:$channelData->{CA}:".
                  
"$channelData->{SID}:$channelData->{NID}:$channelData->{TID}:$channelData->{RID}";
    # Add additional Information if any
    $lineBuffer .= ":$channelData->{Remark}" if ( $channelData->{Remark} ne '' 
);
    # End Of Line
    $lineBuffer .= "\n";
  }

  # Done
  return $lineBuffer;
}


# IsChannelData
#
# Return 1 if this Channel Data Hash contains data of
# a real channel. Return 0 if this Channel Data Hash
# is just a Grouping line ":Group".
#
# Parameter
#   [0] Reference to Channel Data Hash
#
# Returns
#   0 or 1
#
sub IsChannelData {
  # Parameters
  my $channelData = $_[0];
  # Real CHannel Data has a name and a SID as miminum
  return ( ( $channelData->{'Name'} ne '' && $channelData->{'SID'} ne '' ) ? 1 
: 0 );
}


# Usage
#
# Explains the usage of this script.
#
sub Usage {
  print "\n";
  print "USAGE:\n";
  print "$0 <Source File> <Sort Order File> <Destination File>\n";
  print "\n";
  print "Sorts the VDR channels from the <Source File> according to the\n";
  print "sort order given in the <Sort Order File> and writes them to\n";
  print "the <Destination File>.\n";
  print "\n";
  print "HINTS:\n";
  print "- The <Sort Order File> is usually an older channel.conf\n";
  print "- All channels not mentioned in the <Sort Order File> are 
appended.\n";
  print "\n";
  print "SAMPLE:\n";
  print "$0 channels.conf channels.conf.my channels.conf.resorted\n";
  print "\n";
}



-- 
Info:
To unsubscribe send a mail to ecartis@linuxtv.org with "unsubscribe vdr" as subject.



Home | Main Index | Thread Index