This project has moved. For the latest updates, please go here.

DVBLink recordings metadata

Dec 14, 2013 at 5:25 PM
Hi,

My DVBLink recordings are totally mashed by MCE Buddy.

There is a reference in the new version to using PreMetaCustomCommand but no indication of how to do this.

Could someone post an example configuration for this section with DBL Link please?

da mouse
Coordinator
Dec 15, 2013 at 3:39 AM
One of the users had developed a perl script which uses the DVBLink API's to extract the metadata. I have provided the premetacustomcommand as an option to call that script so that data could be extracted into an XML file which would then be read by MCEBuddy.

I guess we'll just have to wait for someone to post that script here or maybe you can search the internet for it.
Coordinator
Dec 20, 2013 at 2:44 PM
Edited Dec 20, 2013 at 2:46 PM
Thanks to @igor - he has been experimenting with extracting metadata from DVBLink. I'm reposting his script and details on how he has extracted metadata

The DVBLink metadata extraction script (PERL) has been hosted on the MCEBuddy2x server at
Server: http://files.mcebuddy2x.com
Login: mcebuddy
Password: mcebuddy

File name: SHARED_INFORMATION\DBVLink\dvblink-query.pl

@igor's comments:
I also check the episode name against the .csv files from the Internet. The sample of  the .csv is here:
1,1,1,"276023",24/Sep/07,"Pilot",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/550436"
2,1,2,"3T6601",01/Oct/07,"The Big Bran Hypothesis",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/603610"
3,1,3,"3T6602",08/Oct/07,"The Fuzzy Boots Corollary",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/604480"
4,1,4,"3T6603",15/Oct/07,"The Luminous Fish Effect",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/607807"
5,1,5,"3T6604",22/Oct/07,"The Hamburger Postulate",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/614283"
6,1,6,"3T6605",29/Oct/07,"The Middle Earth Paradigm",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/618205"
7,1,7,"3T6606",05/Nov/07,"The Dumpling Paradox",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/618419"
8,1,8,"3T6607",12/Nov/07,"The Grasshopper Experiment",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/622781"
9,1,9,"3T6608",17/Mar/08,"The Cooper-Hofstadter Polarization",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/624751"
10,1,10,"3T6609",24/Mar/08,"The Loobenfeld Decay",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/641156"
11,1,11,"3T6610",31/Mar/08,"The Pancake Batter Anomaly",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/641157"
12,1,12,"3T6611",14/Apr/08,"The Jerusalem Duality",n,"http://www.tvrage.com/The_Big_Bang_Theory/episodes/641158"
Dec 21, 2013 at 8:03 PM
That's great.

I have updaed the script as follows and it is working for me. I am kicking out a .arg file because it seemed to be the easiest format to support.

The parameters in my profile file are as follows:

PreMetaCustomCommandPath=C:\Perl64\bin\perl.exe
PreMetaCustomCommandParameters=c:\code\dvblink.pl %sourcefile%
PreMetaCustomCommandHangPeriod=0
PreMetaCustomCommandCritical=true

To use this you just need to copy the code below into a file dvblink.pl and update your profile file.
#!/usr/bin/perl -w

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Request::Common;
use XML::Simple;
use XML::Parser;
use XML::LibXML;
use Data::Dumper;
use Text::CSV;
use XML::LibXML::PrettyPrint;
use XML::LibXML::Iterator;
use XML::Writer;

my @epg;

main();

sub main
{
    (my $file) = @ARGV;
    
    print 'searching for file =' . $file . "\n\r";
    
my $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.0.30/server_address>" .
  "</object_requester>";

####
 my $cnt = call_dvblink("127.0.0.1","8080","username","password",$message);

 my $objectid1 = get_objectid ($cnt);

#### #second query 

 $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_id>$objectid1</object_id>" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.0.30</server_address>" .
  "</object_requester>";

 my $ccnt =call_dvblink("127.0.0.1","8080","username","password",$message);

 my $objectid2 = get_objectid($ccnt);

##### third query 
 $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_id>$objectid2</object_id>" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.0.30</server_address>" .
  "</object_requester>";

 my $ccnt =call_dvblink("127.0.0.1","8080","username","password",$message);

 parse_list ($ccnt, $file);
 

}

sub get_objectid{                                      

 my $inputstring = $_[0];
 my $parser = XML::LibXML-> new();
 my $tree = $parser->parse_string($inputstring);

 my $root = $tree->getDocumentElement ;
 my $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");

 my $rec = $xpc->findnodes('//dvbl:response/dvbl:xml_result');
 my ($xmlres) = $rec->get_nodelist; 

# print $xmlres;
 $xmlres =~ s/\&lt\;/\</g;
 $xmlres =~ s/\&gt\;/\>/g;
 $xmlres =~ s/<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>//g;
 

                                                                       
 $tree = $parser->parse_string($xmlres);
 $root = $tree->getDocumentElement;
 $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");
 # my @rec = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container[@dvbl:source_id="8F94B459-EFC0-4D91-9B29-EC3D72E92677"]');
 #my @recc = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container/dvbl:object_id[@source_id="8F94B459-EFC0-4D91-9B29-EC3D72E92677"]');
 my ($recc) = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container/dvbl:object_id');
 my $objectid=$recc->to_literal;
 return $objectid;
}


sub call_dvblink {
# server ip, port username, password, message
 my $userAgent = LWP::UserAgent->new(agent => 'perl post');

 my $message = $_[4];

 $userAgent->credentials($_[0].":".$_[1],"DVBLink Server",$_[2],$_[3]);

 my $response = $userAgent->request(POST 'http://'.$_[0].":".$_[1].'/cs/',
                           Content_Type => 'application/x-www-form-urlencoded',
                           Content => $message);
 print $response->error_as_HTML unless $response->is_success;
 return $response->content;

}

sub parse_list{                                      

 my $inputstring = $_[0];
 my $file = $_[1];

 my $parser = XML::LibXML-> new();
 my $tree = $parser->parse_string($inputstring);

 my $root = $tree->getDocumentElement ;
 my $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");

my $rec = $xpc->findnodes('//dvbl:response/dvbl:xml_result');
my ($xmlres) = $rec->get_nodelist; 

 $xmlres =~ s/\&lt\;/\</g;
 $xmlres =~ s/\&gt\;/\>/g;
 $xmlres =~ s/<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>//g;

# print $xmlres;
 my $name;
 my $subname;
 my $starttime;
 my $plot;
 my $channel;\
 my $season;
 my $episode;
                                                                       
 $tree = $parser->parse_string($xmlres);
 $root = $tree->getDocumentElement;
 $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");
 my $recc = $xpc->findnodes('//dvbl:object/dvbl:items/dvbl:recorded_tv');
 if ($file =~ m/([0-9]*-[0-9]*-[0-9]+)\.ts/g){
    my $id = $1;
    foreach my $context ($recc->get_nodelist) {
        my $objectid = $context->getElementsByTagName('object_id');
        my @tag = split("/",$objectid);
        
        if ($id =~ $tag[1]){
            print 'found file '. $file;
            my $scheduleid = $context->getElementsByTagName('schedule_id');
            my $xpc2 = XML::LibXML::XPathContext->new($context);
            $xpc2->registerNs("dvbl","http://www.dvblogic.com");
            $name = $xpc2->findnodes('./dvbl:video_info/dvbl:name');

            $subname = $xpc2->findnodes('./dvbl:video_info/dvbl:subname');
            $plot = $xpc2->findnodes('./dvbl:video_info/dvbl:short_desc');
            $channel = $xpc2->findnodes('./dvbl:channel_name');
            $episode = $xpc2->findnodes('./dvbl:video_info/dvbl:episode_num');
            $season = $xpc2->findnodes('./dvbl:video_info/dvbl:season_num');
            $starttime = $xpc2->findnodes('./dvbl:video_info/dvbl:start_time');
            my $duration = $xpc2->findnodes('./dvbl:video_info/dvbl:duration');


            my $rectime = timestamp($starttime);
            $file =~ s/\.ts/\.arg/g;

            my $xml = XML::LibXML::Document->new( '1.0', 'utf-8' ); 

            open (MYFILE, '>'.$file); 

            my $output = '';
            my $writer = XML::Writer->new(
            OUTPUT=> \$output,
            ENCODING => 'utf8',
            );

            $writer->xmlDecl('UTF-8');
            $writer->startTag('Recording');
            $writer->dataElement(ChannelDisplayName => $channel);
            $writer->dataElement(Title => $name);
            $writer->dataElement(Description => $plot);
            $writer->dataElement(RecordingStartTime => (substr $rectime, 5,4). '-'.(substr $rectime, 9,2).'-'.(substr $rectime, 11,2) . ' ' .(substr $rectime, 0,2).':'.(substr $rectime, 2,2));
            
            if ($season->size() > 0){
                $writer->dataElement(SeriesNumber => $season);}
            if ($episode->size() > 0){
                $writer->dataElement(EpisodeNumber => $episode);}
            
            if ($subname->size() > 0){
                $writer->dataElement( SubTitle => $subname);
                }
            $writer->endTag('Recording');
            
           print MYFILE $output;
            close (MYFILE); 
        }
    }
 }


}


sub timestamp {
use warnings;
use strict;
 
my $time = shift;
 
die "Usage: $0 [TIME_IN_SECS_SINCE_EPOCH]\n" unless $time;
if ( length($time) > 10 ) {
    $time = substr($time, 0, 10);
}
 
my @mon  = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my @day  = qw( Sun Mon Tue Wed Thu Fri Sat );
 
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
    = localtime($time);
 my $ret = sprintf("%02d",$hour) . sprintf("%02d",$min) . "_" . sprintf("%04d%02d%02d",$year+1900, $mon+1, $mday);
 return $ret;


}
Marked as answer by rboy1 on 1/1/2014 at 7:03 AM
Jan 11, 2014 at 1:37 PM
More on this for anyone using it... I was getting failures where shows didn't have a season/episode or a subtitle set so have added original broadcast time in this case. However, as argus TV files don't support this I've had to switch to creating nvpr files.

All works fine but I suggest removing the 'download metadata' option for the profile.
#!/usr/bin/perl -w

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Request::Common;
use XML::Simple;
use XML::Parser;
use XML::LibXML;
use Data::Dumper;
use Text::CSV;
use XML::LibXML::PrettyPrint;
use XML::LibXML::Iterator;
use XML::Writer;

my @epg;

main();

sub main
{
    (my $file) = @ARGV;
    
    print 'searching for file =' . $file . "\n\r";
    
my $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.0.30/server_address>" .
  "</object_requester>";

####
 my $cnt = call_dvblink("127.0.0.1","8080","username","password",$message);

 my $objectid1 = get_objectid ($cnt);

#### #second query 

 $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_id>$objectid1</object_id>" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.0.30</server_address>" .
  "</object_requester>";

 my $ccnt =call_dvblink("127.0.0.1","8080","username","password",$message);

 my $objectid2 = get_objectid($ccnt);

##### third query 
 $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_id>$objectid2</object_id>" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.0.30</server_address>" .
  "</object_requester>";

 my $ccnt =call_dvblink("127.0.0.1","8080","username","password",$message);

 parse_list ($ccnt, $file);
 

}

sub get_objectid{                                      

 my $inputstring = $_[0];
 my $parser = XML::LibXML-> new();
 my $tree = $parser->parse_string($inputstring);

 my $root = $tree->getDocumentElement ;
 my $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");

 my $rec = $xpc->findnodes('//dvbl:response/dvbl:xml_result');
 my ($xmlres) = $rec->get_nodelist; 

# print $xmlres;
 $xmlres =~ s/\&lt\;/\</g;
 $xmlres =~ s/\&gt\;/\>/g;
 $xmlres =~ s/<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>//g;
 

                                                                       
 $tree = $parser->parse_string($xmlres);
 $root = $tree->getDocumentElement;
 $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");
 # my @rec = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container[@dvbl:source_id="8F94B459-EFC0-4D91-9B29-EC3D72E92677"]');
 #my @recc = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container/dvbl:object_id[@source_id="8F94B459-EFC0-4D91-9B29-EC3D72E92677"]');
 my ($recc) = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container/dvbl:object_id');
 my $objectid=$recc->to_literal;
 return $objectid;
}


sub call_dvblink {
# server ip, port username, password, message
 my $userAgent = LWP::UserAgent->new(agent => 'perl post');

 my $message = $_[4];

 $userAgent->credentials($_[0].":".$_[1],"DVBLink Server",$_[2],$_[3]);

 my $response = $userAgent->request(POST 'http://'.$_[0].":".$_[1].'/cs/',
                           Content_Type => 'application/x-www-form-urlencoded',
                           Content => $message);
 print $response->error_as_HTML unless $response->is_success;
 return $response->content;

}

sub parse_list{                                      

 my $inputstring = $_[0];
 my $file = $_[1];

 my $parser = XML::LibXML-> new();
 my $tree = $parser->parse_string($inputstring);

 my $root = $tree->getDocumentElement ;
 my $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");

my $rec = $xpc->findnodes('//dvbl:response/dvbl:xml_result');
my ($xmlres) = $rec->get_nodelist; 

 $xmlres =~ s/\&lt\;/\</g;
 $xmlres =~ s/\&gt\;/\>/g;
 $xmlres =~ s/<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>//g;

# print $xmlres;
 my $name;
 my $subname;
 my $starttime;
 my $plot;
 my $channel;\
 my $season;
 my $episode;
 my $categories;
                                                                       
 $tree = $parser->parse_string($xmlres);
 $root = $tree->getDocumentElement;
 $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");
 my $recc = $xpc->findnodes('//dvbl:object/dvbl:items/dvbl:recorded_tv');
 if ($file =~ m/([0-9]*-[0-9]*-[0-9]+)\.ts/g){
    my $id = $1;
    foreach my $context ($recc->get_nodelist) {
        my $objectid = $context->getElementsByTagName('object_id');
        my @tag = split("/",$objectid);
        
        if ($id =~ $tag[1]){
            print 'found file '. $file;
            my $scheduleid = $context->getElementsByTagName('schedule_id');
            my $xpc2 = XML::LibXML::XPathContext->new($context);
            $xpc2->registerNs("dvbl","http://www.dvblogic.com");
            $name = $xpc2->findnodes('./dvbl:video_info/dvbl:name');

            $subname = $xpc2->findnodes('./dvbl:video_info/dvbl:subname');
            $plot = $xpc2->findnodes('./dvbl:video_info/dvbl:short_desc');
            $channel = $xpc2->findnodes('./dvbl:channel_name');
            $episode = $xpc2->findnodes('./dvbl:video_info/dvbl:episode_num');
            $season = $xpc2->findnodes('./dvbl:video_info/dvbl:season_num');
            $starttime = $xpc2->findnodes('./dvbl:video_info/dvbl:start_time');
            $categories =  $xpc2->findnodes('./dvbl:video_info/dvbl:start_time');
            my $duration = $xpc2->findnodes('./dvbl:video_info/dvbl:categories');


            my $rectime = timestamp($starttime);
            $file =~ s/\.ts/\.xml/g;

            my $xml = XML::LibXML::Document->new( '1.0', 'utf-8' ); 

            open (MYFILE, '>'.$file); 

            my $output = '';
            my $writer = XML::Writer->new(
            OUTPUT=> \$output,
            ENCODING => 'utf8',
            );

            my $haveSubtitle = 'no';
            $writer->xmlDecl('UTF-8');
            $writer->startTag('recording');
            $writer->dataElement(channel => $channel);
            $writer->dataElement(title => $name);
            $writer->dataElement(description => $plot);
            $writer->dataElement(startTime => (substr $rectime, 5,4). '-'.(substr $rectime, 9,2).'-'.(substr $rectime, 11,2) . ' ' .(substr $rectime, 0,2).':'.(substr $rectime, 2,2));
            
            
            if ($season->size() > 0){
                if ($season > 0){
                $writer->dataElement(season => $season);}}
            if ($episode->size() > 0){
                if ($episode > 0){
                $writer->dataElement(episode => $episode);
                $haveSubtitle = 'yes';}}
            
            if ($subname->size() > 0){
                $writer->dataElement( subtitle => $subname);
                $haveSubtitle = 'yes';
                }
                
            if ($haveSubtitle == 'no'){
                $writer->dataElement( original_air_date => (substr $rectime, 5,4). '-'.(substr $rectime, 9,2).'-'.(substr $rectime, 11,2));
            }
            if ($categories->size() > 0){
                $writer->startTag('genres');
                $writer->dataElement( genre => $categories);
                $writer->endTag('genres');
            }
            $writer->endTag('recording');
            
           print MYFILE $output;
            close (MYFILE); 
        }
    }
 }


}


sub timestamp {
use warnings;
use strict;
 
my $time = shift;
 
die "Usage: $0 [TIME_IN_SECS_SINCE_EPOCH]\n" unless $time;
if ( length($time) > 10 ) {
    $time = substr($time, 0, 10);
}
 
my @mon  = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my @day  = qw( Sun Mon Tue Wed Thu Fri Sat );
 
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
    = localtime($time);
 my $ret = sprintf("%02d",$hour) . sprintf("%02d",$min) . "_" . sprintf("%04d%02d%02d",$year+1900, $mon+1, $mday);
 return $ret;


}
Mar 8, 2014 at 4:24 AM
Hi guys,
I am trying to use this script and it seems to work but as I non-programer I have found an error that I don't understand.

I get the error: "my variable $ccnt masks earlier declaration in same scope at c:\code\dvblink.pl line 74"

Line 74 is in the third query "my $ccnt =call_dvblink("127.0.0.1","8080","user","admin",$message);"

If I comment this out the script seems to work (still testing). It just seems strange since the script seems to be working for others. Any advice?
Mar 8, 2014 at 8:22 AM
It is a warning and you can safely ignore it. The script should run anyway.


Mar 8, 2014 at 11:07 AM
Hi again,
Thanks for the above, I am still not having any luck with this. I am getting 0 byte xml files. DVBLink is collecting metadata. The code is from your last post, I have changed dvblink username, password, and server IP address. Again any advice appreciated?

``` V:\ServerFolders\Recorded TV>perl c:\code\dvblink.pl S01E14-The_Originals-2220_2
0140308-24-11560000-1394277600.ts
"my" variable $ccnt masks earlier declaration in same scope at c:\code\dvblink.p
l line 74.
Useless use of single ref constructor in void context at c:\code\dvblink.pl line
154.
searching for file =S01E14-The_Originals-2220_20140308-24-11560000-1394277600.ts

Operation ">": no method found,
    left argument in overloaded package XML::LibXML::NodeList,
    right argument has no overloaded magic at c:\code\dvblink.pl line 209.
found file S01E14-The_Originals-2220_20140308-24-11560000-1394277600.ts```
Mar 8, 2014 at 10:22 PM
Edited Mar 9, 2014 at 2:18 AM
Update.
Appears the errors I was seeing were due to reprocessing the file. Not sure I can explain why but I am getting xml data and correctly renamed files now. I don't see any SxxEyy in the XML, even if DVBLink has it. Is that right?

Update 2.
In the profile.conf I now have:
perl c:\code\dvblink.pl "%sourcefile%"
This means script writes the xml to the location as the original file "V:\ServerFolders\Recorded TV[program name].xml"
However while the recoded file is copied to the working folder the xml is not. MCEBuddy seems to ignore the xml. What have I missed?
Mar 9, 2014 at 10:28 AM
So the one issue I have with this is that there is not an XML format that I can feed MCEbuddy that includes all the fields that DVBLink can use.


Mar 9, 2014 at 12:14 PM
Understand, its a little hit and miss. This is still a neat piece of code so thanks for that.
May 20, 2014 at 11:54 AM
Edited May 20, 2014 at 11:56 AM
Hi again, I am having another play with this. I am pleased to see that the metadata is being read from the database. However, the error referred to above
Operation ">": no method found
left argument in overloaded package XML::LibXML::NodeList,
    right argument has no overloaded magic at c:\code\dvblink.pl line 209
is caused by the lines similar to:
if ($season > 0){
                $writer->dataElement(season => $season);}
This test stops the script with the error message above and nothing is written to the file. Why should this be a problem?
Nov 13, 2014 at 7:58 AM
Hi
I have the XML extraction working base on wisermouse's script, but how do I get MCE Buddy to use the generated XML file? It would be nice if the info could be written to the XBMC nfo file.
Nov 13, 2014 at 10:19 AM
Hi,
The following modified version works for me. The XML has to be in the same location as the recorded file, note the filename. The MCEBuddy config is also below, of course you need to add the relevant parts to all the profiles you use.

Perl Script
#!/usr/bin/perl -w

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Request::Common;
use XML::Simple;
use XML::Parser;
use XML::LibXML;
use Data::Dumper;
use Text::CSV;
use XML::LibXML::PrettyPrint;
use XML::LibXML::Iterator;
use XML::Writer;

my @epg;

main();

sub main
{
    (my $file) = @ARGV;
    
    print 'searching for file =' . $file . "\n\r";
    
my $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.20.100</server_address>" .
  "</object_requester>";

####
 my $cnt = call_dvblink("127.0.0.1","8100","user","admin",$message);

 my $objectid1 = get_objectid ($cnt);

#### #second query 

 $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_id>$objectid1</object_id>" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.20.100</server_address>" .
  "</object_requester>";

 my $ccnt =call_dvblink("127.0.0.1","8100","user","admin",$message);

 my $objectid2 = get_objectid($ccnt);

##### third query 
 $message = "command=get_object&xml_param=<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " .
 "<object_requester xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" .
      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://www.dvblogic.com\">" .
     " <object_id>$objectid2</object_id>" .
     " <object_type>-1</object_type>" .
     " <item_type>-1</item_type>" .
     " <start_position>0</start_position>" .
     " <requested_count>-1</requested_count>" .
     " <children_request>true</children_request>" .
     " <server_address>192.168.20.100</server_address>" .
  "</object_requester>";

 my $ccnt =call_dvblink("127.0.0.1","8100","user","admin",$message);

 parse_list ($ccnt, $file);
 

}

sub get_objectid{                                      

 my $inputstring = $_[0];
 my $parser = XML::LibXML-> new();
 my $tree = $parser->parse_string($inputstring);

 my $root = $tree->getDocumentElement ;
 my $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");

 my $rec = $xpc->findnodes('//dvbl:response/dvbl:xml_result');
 my ($xmlres) = $rec->get_nodelist; 

 #print $xmlres;
 $xmlres =~ s/\&lt\;/\</g;
 $xmlres =~ s/\&gt\;/\>/g;
 $xmlres =~ s/<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>//g;
 

                                                                       
 $tree = $parser->parse_string($xmlres);
 $root = $tree->getDocumentElement;
 $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");
 # my @rec = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container[@dvbl:source_id="8F94B459-EFC0-4D91-9B29-EC3D72E92677"]');
 #my @recc = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container/dvbl:object_id[@source_id="8F94B459-EFC0-4D91-9B29-EC3D72E92677"]');
 my ($recc) = $xpc->findnodes('//dvbl:object/dvbl:containers/dvbl:container/dvbl:object_id');
 my $objectid=$recc->to_literal;
 return $objectid;
}


sub call_dvblink {
# server ip, port username, password, message
 my $userAgent = LWP::UserAgent->new(agent => 'perl post');

 my $message = $_[4];

 $userAgent->credentials($_[0].":".$_[1],"DVBLink Server",$_[2],$_[3]);

 my $response = $userAgent->request(POST 'http://'.$_[0].":".$_[1].'/cs/',
                           Content_Type => 'application/x-www-form-urlencoded',
                           Content => $message);
 print $response->error_as_HTML unless $response->is_success;
 return $response->content;

}

sub parse_list{                                      

 my $inputstring = $_[0];
 my $file = $_[1];

 my $parser = XML::LibXML-> new();
 my $tree = $parser->parse_string($inputstring);

 my $root = $tree->getDocumentElement ;
 my $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");

my $rec = $xpc->findnodes('//dvbl:response/dvbl:xml_result');
my ($xmlres) = $rec->get_nodelist; 

 $xmlres =~ s/\&lt\;/\</g;
 $xmlres =~ s/\&gt\;/\>/g;
 $xmlres =~ s/<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>//g;

# print $xmlres;
 my $name;
 my $subname;
 my $starttime;
 my $plot;
 my $channel;
 my $season;
 my $episode;
 my $categories;
                                                                       
 $tree = $parser->parse_string($xmlres);
 $root = $tree->getDocumentElement;
 $xpc = XML::LibXML::XPathContext->new($root);
 $xpc->registerNs("dvbl","http://www.dvblogic.com");
 my $recc = $xpc->findnodes('//dvbl:object/dvbl:items/dvbl:recorded_tv');
 if ($file =~ m/([0-9]*-[0-9]*-[0-9]+)\.ts/g){
    my $id = $1;
    foreach my $context ($recc->get_nodelist) {
        my $objectid = $context->getElementsByTagName('object_id');
        my @tag = split("/",$objectid);
        
        if ($id =~ $tag[1]){
            print 'found file '. $file;
            my $scheduleid = $context->getElementsByTagName('schedule_id');
            my $xpc2 = XML::LibXML::XPathContext->new($context);
            $xpc2->registerNs("dvbl","http://www.dvblogic.com");
            $name = $xpc2->findnodes('./dvbl:video_info/dvbl:name');

            $subname = $xpc2->findnodes('./dvbl:video_info/dvbl:subname');
            $plot = $xpc2->findnodes('./dvbl:video_info/dvbl:short_desc');
            $channel = $xpc2->findnodes('./dvbl:channel_name');
            $episode = $xpc2->findnodes('./dvbl:video_info/dvbl:episode_num');
            $season = $xpc2->findnodes('./dvbl:video_info/dvbl:season_num');
            $starttime = $xpc2->findnodes('./dvbl:video_info/dvbl:start_time');
            $categories =  $xpc2->findnodes('./dvbl:video_info/dvbl:start_time');
            my $duration = $xpc2->findnodes('./dvbl:video_info/dvbl:categories');
print $name;

            my $rectime = timestamp($starttime);
            $file =~ s/\.ts/\.xml/g;

            my $xml = XML::LibXML::Document->new( '1.0', 'utf-8' ); 

            open (MYFILE, '>'.$file); 

            my $output = '';
            my $writer = XML::Writer->new(
            OUTPUT=> \$output,
            ENCODING => 'utf8',
            );

            my $haveSubtitle = 'no';
            $writer->xmlDecl('UTF-8');
            $writer->startTag('recording');
            $writer->dataElement(channel => $channel);
            $writer->dataElement(title => $name);
            $writer->dataElement(description => $plot);
            $writer->dataElement(startTime => (substr $rectime, 5,4). '-'.(substr $rectime, 9,2).'-'.(substr $rectime, 11,2) . ' ' .(substr $rectime, 0,2).':'.(substr $rectime, 2,2));
                        
            if ($season->size() > 0){
#                if ($season > 0){
                $writer->dataElement(season => $season);}#}
            if ($episode->size() > 0){
#                if ($episode > 0){
                $writer->dataElement(episode => $episode);
                $haveSubtitle = 'yes';}#}
            
#            if ($subname->size() > 0){
                $writer->dataElement( subtitle => $subname);
                $haveSubtitle = 'yes';
                #}
                
            if ($haveSubtitle == 'no'){
                $writer->dataElement( original_air_date => (substr $rectime, 5,4). '-'.(substr $rectime, 9,2).'-'.(substr $rectime, 11,2));
            }
            if ($categories->size() > 0){
                $writer->startTag('genres');
                $writer->dataElement( genre => $categories);
                $writer->endTag('genres');
            }
            $writer->endTag('recording');
            print "Outputs ". $output;
           print MYFILE $output;
            close (MYFILE); 
        }
    }
 }


}


sub timestamp {
use warnings;
use strict;
 
my $time = shift;
 
die "Usage: $0 [TIME_IN_SECS_SINCE_EPOCH]\n" unless $time;
if ( length($time) > 10 ) {
    $time = substr($time, 0, 10);
}
 
my @mon  = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my @day  = qw( Sun Mon Tue Wed Thu Fri Sat );
 
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
    = localtime($time);
 my $ret = sprintf("%02d",$hour) . sprintf("%02d",$min) . "_" . sprintf("%04d%02d%02d",$year+1900, $mon+1, $mday);
 return $ret;


}
MCEBuddy Configuration
PreMetaCustomCommandPath=C:\strawberry\perl\bin\perl.exe 
PreMetaCustomCommandParameters=c:\strawberry\dvblink.pl "%sourcefile%"
Marked as answer by rboy1 on 11/13/2014 at 5:56 AM
Nov 15, 2014 at 10:03 AM
Well not much difference between the scripts, both works for me, that not the issue.

This perl script outputs a .xml file with the DVBlink episode info, but not formatted for XBMC (i can just change it myself no problem). But it does not contain the codec info resolution as this is first available after conversion (I guess, pleas correct me if i am wrong)

MceBuddy afterwards outputs a .nfo file for XMBC (if "Save information" selected in options). This has the codec info but not the DVBlink episode info from the generated .xml file.

So I am looking for a way for MceBuddy to combine these information in one file formatted so that XBMC can read the info. Or if you convert to a file format that can carry metadata (MP4, MKV) put it all the generated info in the file.
Coordinator
Nov 15, 2014 at 1:52 PM
Can you upload/post a link to your conversion log. Does MCEBuddy find the episode info?

Also what is the TAG in the XBMC file which is supposed to contain the episode info? Can you also upload a sample xml file which is correctly formatted with the right info in it. We can look at that to see how to enhance the mcebuddy created nfo
Nov 16, 2014 at 7:35 PM
Edited Nov 16, 2014 at 7:44 PM
Hi,
I am happy to up load a recent log file - its too big to quote here. Please tell me where I can upload it.
Also, I am not a programmer so can only give limited assistance on the mechanics of this.
Nov 18, 2014 at 5:01 AM
I have uploaded some files into
ftp://files.mcebuddy2x.com/upload/discussion_473593/

1: An .jpeg screendump of what the world looks like in XMBC with DVBLink recordings
2: A .xml generated by the perlscript, I have modified it slightly
3: My perlscript dvblink.pl
4: A .nfo file generated by thirdparty tool
5: The .nfo created by MceBuddy
6: The MdeBuddy log file

I am not sure what would be the right format, but what is currently stored match the data on the screendump
Coordinator
Nov 18, 2014 at 5:26 AM
What have you modified about the Perl Script? The XML file being created is not being recognized by MCEBuddy. so it isn't loading the data
Coordinator
Nov 18, 2014 at 6:20 AM
Edited Nov 18, 2014 at 6:20 AM
Okay found the issue. The problem lies with your XML file. The identifier in your XML file says:
<?xml version="1.0" encoding="UTF-8"?>
But your XML file is encoded in ISO-8859-1 (Latin-1). That's why MCEBuddy isn't able to read it, it's erroring out because you have a extended character set (non english characters) which according to the header is UTF-8 but is actually Latin-1.

Fix your script to generate a UTF-8 XML file and the problem will go away.

In addition, as a safety measure we have added a fall back to parse XML files with Latin-1 if UTF-8 fails in today's build (ignoring the directory to use UTF-8) but this isn't foolproof.

Users must ensure the XML files are encoded in UTF-8 if the XML header specifies UTF-8.
Nov 18, 2014 at 6:41 AM
Edited Nov 18, 2014 at 6:44 AM
Yes i have Danish Regional settings on my PC

The only change i did was to put in line feed to the output XML and then I was experimenting with giving more parameters to the perl script so it would get moved to destination folder.
Nov 19, 2014 at 9:34 AM
Edited Nov 19, 2014 at 10:20 AM
I got the latest version from early download and it works without changing anything. Three things I observed:
1: If I select to also download from internet, mcebuddy hangs at this download step

2: There is some name conversions that could be cleaned up
DVBlink->plot->perlscript->description in .xml->mcebuddy->plot->.nfo
I think you should enforce "plot" in order to stick to the same name convention all the way through!

3: Since I had to do an uninstall old/install new version, the profiles.conf was overwritten and I had to redo that one. Also I had put my Perl script in the config folder and it was deleted also my comskip donator version was delete. Not harmful happen i had backup of it all, but why can't I do a re-install on top of the old version?
Coordinator
Nov 19, 2014 at 2:44 PM
  1. MCEBuddy doens't hang, sometime the websites are slow to respond. MCEBuddy does an exhaustive check on multiple websites to get all the info and that takes time depending upon internet and website speed, typically 1 minutes but sometimes upto 30 minutes if hte websites don't respond. Will see if we can optimize it further
  2. I don't understand, the NFO writes plot. Where are you seeing description?
  3. You can't upgrade this is a limitation of the setup installer in Visual Studio (maybe someday we'll have the time to get an write a new installer package). As a workaround when MCEBuddy is installed it creates a backup of the history file, profiles.conf and mcebuddy.conf in the USERS windows profile directory. When the new version is installed, MCEBuddy reads the relevant settings and update them in the new installation and the old ones are saved in the config directory as .old. (this is been documented, am sure you would have read it). Anything else in the installation directory is removed, that's why we tell the users to use external directories and point to them in teh custom commands. For Comskip, we have given the option to point to a external directory for ini and for the donator version of comskip in the System settings and expert settings pages.
Nov 24, 2014 at 4:57 PM
Edited Nov 24, 2014 at 5:10 PM
Ok read the manual is always a good starting point ;-)

If you run the perl script from wisermouse it will extract what the DVBLINK field plot to the xml file as <description></description> (see below). Then MCE buddy take the description keyword and dumps it into a <plot></plot> in its .nfo file. I am just saying that is confusing that the terminology is changed from plot->description->plot

The I am having problems with title, subtitle and showtitle, Maby its because its handled as a tv series and not movie, not sure. Perscript outputs
<recording>
<channel>HD DR1</channel>
<title>Agent 007 - Never Say Never Again</title>
<description>Da to amerikanske atommissiler forsvinder, er Agent 007 allerede på sporet. En britisk officer er blevet myrdet, og hans søster Domino er på Bahama hos den rige og gale pengemand Largo, som er Spectre-chefen Blofelds højre hånd. I kapløb med tiden følger Bond sporet til Largos lystyacht ved Rivieraen, hvor han må redde både verden og Domino.</description>_
<startTime>2014-11-21 23:18</startTime>
<subtitle>Amerikansk agentfilm fra 1983.</subtitle>
<original_air_date>2014-11-21</original_air_date>
<genres>
    <genre>1416608285</genre>
</genres>
</recording>
nfo files gets
<?xml version="1.0" encoding="utf-8"?>
<episodedetails>
<xshow>Agent 007 - Never Say Never Again</xshow>
<xrating />
<xsport>False</xsport>
<xrecorded>2014-11-21</xrecorded>
<xtvdbid />
<xtmdbid />
<title>Amerikansk agentfilm fra 1983.</title>
<showtitle>Agent 007 - Never Say Never Again</showtitle>
<season />
<episode />
<plot>Da to amerikanske atommissiler forsvinder, er Agent 007 allerede på sporet. En britisk officer er blevet myrdet, og hans søster Domino er på Bahama hos den rige og gale pengemand Largo, som er Spectre-chefen Blofelds højre hånd. I kapløb med tiden følger Bond sporet til Largos lystyacht ved Rivieraen, hvor han må redde både verden og Domino.</plot>
<thumb />
<id />
<credits />
<genre>1416608285</genre>
<premiered />
<aired>2014-11-21</aired>
<studio>HD DR1</studio>
<fileinfo>
    <streamdetails>
        <audio>
            <channels>2</channels>
            <codec>mp2</codec>
        </audio>
        <video>
            <codec>h264</codec>
            <durationinseconds>7537</durationinseconds>
            <height>720</height>
            <language />
            <longlanguage>&lt;Default&gt;</longlanguage>
            <width>1280</width>
        </video>
    </streamdetails>
</fileinfo>
</episodedetails>
So they are inter changed.<subtitle> goes into <title> and <title> goes into <showtitle>.
XMBC need the title to be <title>

I will try to set force Movie
Nov 24, 2014 at 5:33 PM
I found bug in perl script
$categories = $xpc2->findnodes('./dvbl:video_info/dvbl:start_time');
should be
$categories = $xpc2->findnodes('./dvbl:video_info/dvbl:categories');
Coordinator
Nov 24, 2014 at 6:58 PM
What you're looking at is for TV Series (shows) and that the specification defined by XBMC http://wiki.xbmc.org/index.php?title=NFO_files/tvepisodes
The Show Title goes into showname and Episode Name goes into Title. If that is incorrect please point us to the correct documentation.
Also there is no "Description" in the specifications above. Again, if we're missing please point us. Why do you need Description anyways?

You may want to set the Genre as Movie and it'll pick up the movies specs where the Movie name is put into Title and description goes into outline. Here also there is no description field.
Nov 24, 2014 at 10:23 PM
Hi

With the fix to the perlscript I can now set the <genre> based on the category frim dvblink to either, movie, serial, sports, news, documentary and maybe more. MCE Budy then give out an .nfo file withe the correct xml tag :-)

I can also pull Actors and directors from dvblink but are not sure how to provide this data to MCE buddy. None of these ends up in the .nfo file.
Currently the output of my perlscript looks like this
<recording>
  <title>Behind Enemy Lines</title>
  <subtitle>Amerikansk krigsdrama fra 2001</subtitle>
  <genres>
    <genre>movie</genre>
  </genres>
  <description>Chris Burnett (Owen Wilson), pilot i det amerikanske forsvar, bliver skudt ned over fjendens territorium p塂alkanhalv𥮬 hvorefter han bliver forfulgt af en fra det hemmelige politi samt af bosniske tropper. Hans chef, admiral Reigart (Gene Hackman), s絴er sin karriere p塳pil, da han g沠imod ordrer og igangs絴er en redningsaktion. Men NATO frygter, at Reigarts mission vil forstyrre den skr𢥬ige fred i regionen, og fors𧥲 at stoppe ham.</description>
  <actors>Owen Wilson/Gene Hackman/Gabriel Macht/Charles Malik Whitfield/Joaquim De Almeida</actors>
  <director>John Moore</director>
</recording>
Based on this http://kodi.wiki/view/NFO_files/movies i believe there should be an <Actor> tag for each the actors
Coordinator
Nov 25, 2014 at 8:07 PM
Basically this script is converting the metadata into a nPVR format XML file. I don't know of any tags in nPVR format that has actors/credits as a tag. If you're aware please point us and we'll include the support
Coordinator
Nov 25, 2014 at 8:10 PM
So to clarify, MCEBuddy reads the credits/actors (but here the nPVR format doesn't have support or atleast we aren't aware) and if it does (e.g. from SageTV or WTV MCEBuddy extracts this info) it then creates a tag called "credits" in the NFO file. So the issue here is what'st the tag in nPVR XML to storing the credits/actors that MCEBuddy can read
Coordinator
Dec 1, 2014 at 5:22 PM
Okay added support to read actors tags from the nPVR XML files, since the format is not clearly specified anywhere MCEBuddy is using the following convention, the tag <actors> followed by subtags <actor>, one for each actor.
<actors>
   <actor>Sean Con</actor>
   <actor>Brad Pitt</actor>
 </actors>
Dec 2, 2014 at 6:27 PM
Edited Dec 2, 2014 at 6:29 PM
Did you have a look here http://kodi.wiki/view/NFO_files/movies

Format is:
<actor>
    <name>Paul Begala</name>
    <role>Himself</role>
</actor>
So there is a <actor> tag for each actor but no <actors> tag

As far as I can tell DVBLink does not give out the role so that might have to be left out.
Coordinator
Dec 2, 2014 at 8:23 PM
That's the NFO format. The headers and format is different from the XML file generated by nPVr at least as I see