Ticket #1274: siparser-eitfixup-surgery.diff

File siparser-eitfixup-surgery.diff, 42.2 KB (added by Stuart Auchterlonie, 14 years ago)

Separate eitfixup's & siparser

  • new file test/libs/libmythtv/eitfixup.cpp

    - +  
     1#include "eitfixup.h"
     2#include <qstring.h>
     3#include <qregexp.h>
     4/*------------------------------------------------------------------------
     5 * Event Fix Up Scripts - Turned on by entry in dtv_privatetype table
     6 *------------------------------------------------------------------------*/
     7
     8void EITFixUp(const privateTypes &PrivateTypes, Event &event)
     9{
     10    event.Year = event.StartTime.toString(QString("yyyy"));
     11    if (event.Description == "" && event.Event_Subtitle != "")
     12    {
     13         event.Description = event.Event_Subtitle;
     14         event.Event_Subtitle="";
     15    }
     16
     17    switch (PrivateTypes.EITFixUp)
     18    {
     19        case 1:
     20            EITFixUpStyle1(PrivateTypes, event);
     21            break;
     22        case 2:
     23            EITFixUpStyle2(PrivateTypes, event);
     24            break;
     25        case 3:
     26            EITFixUpStyle3(PrivateTypes, event);
     27            break;
     28        case 4:
     29            EITFixUpStyle4(PrivateTypes, event);
     30            break;
     31        default:
     32            break;
     33    }
     34
     35    event.Event_Name.stripWhiteSpace();
     36    event.Event_Subtitle.stripWhiteSpace();
     37    event.Description.stripWhiteSpace();
     38
     39}
     40
     41/** \fn SIParser::EITFixUpStyle1(Event&)
     42 *  \brief This function does some regexps on Guide data to get
     43 *         more powerful guide. Use this for BellExpressVu
     44 *  \TODO deal with events that don't have eventype at the begining?
     45 */
     46void EITFixUpStyle1(const privateTypes &PrivateTypes, Event &event)
     47{
     48    QString Temp = "";
     49
     50    int8_t position;
     51
     52    // A 0x0D character is present between the content
     53    // and the subtitle if its present
     54    position = event.Description.find(0x0D);
     55
     56    if (position != -1)
     57    {
     58        // Subtitle present in the title, so get
     59        // it and adjust the description
     60        event.Event_Subtitle = event.Description.left(position);
     61        event.Description = event.Description.right(
     62            event.Description.length()-position-2);
     63    }
     64
     65    // Take out the content description which is
     66    // always next with a period after it
     67    position = event.Description.find(".");
     68    // Make sure they didn't leave it out and
     69    // you come up with an odd category
     70    if (position < 10)
     71    {
     72       event.ContentDescription = event.Description.left(position);
     73       event.Description = event.Description.right(
     74           event.Description.length()-position-2);
     75    }
     76    else
     77    {
     78       event.ContentDescription = "Unknown";
     79    }
     80
     81    // When a channel is off air the category is "-"
     82    // so leave the category as blank
     83    if (event.ContentDescription == "-")
     84       event.ContentDescription = "OffAir";
     85
     86    if (event.ContentDescription.length() > 10)
     87       event.ContentDescription = "Unknown";
     88
     89
     90    // See if a year is present as (xxxx)
     91    position = event.Description.find(QRegExp("[\\(]{1}[0-9]{4}[\\)]{1}"));
     92    if (position != -1 && event.ContentDescription != "")
     93    {
     94       Temp = "";
     95       // Parse out the year
     96       event.Year = event.Description.mid(position+1,4);
     97       // Get the actors if they exist
     98       if (position > 3)
     99       {
     100          Temp = event.Description.left(position-3);
     101          event.Actors = QStringList::split(QRegExp("\\set\\s|,"), Temp);
     102       }
     103       // Remove the year and actors from the description
     104       event.Description = event.Description.right(
     105           event.Description.length()-position-7);
     106    }
     107
     108    // Check for (CC) in the decription and
     109    // set the <subtitles type="teletext"> flag
     110    position = event.Description.find("(CC)");
     111    if (position != -1)
     112    {
     113       event.SubTitled = true;
     114       event.Description = event.Description.replace("(CC)","");
     115    }
     116
     117    // Check for (Stereo) in the decription and set the <audio> tags
     118    position = event.Description.find("(Stereo)");
     119    if (position != -1)
     120    {
     121       event.Stereo = true;
     122       event.Description = event.Description.replace("(Stereo)","");
     123    }
     124}
     125
     126/** \fn SIParser::EITFixUpStyle2(Event&)
     127 *  \brief This function does some regexps on Guide data to get
     128 *         more powerful guide. Use this for the United Kingdom.
     129 */
     130void EITFixUpStyle2(const privateTypes &PrivateTypes, Event &event)
     131{
     132    const uint16_t SUBTITLE_PCT = 50; //% of description to allow subtitle up to
     133    int16_t position = event.Description.find("New Series");
     134    if (position != -1)
     135    {
     136        //Do something here
     137    }
     138    //BBC three case (could add another record here ?)
     139    QRegExp rx("\\s*(Then|Followed by) 60 Seconds\\.");
     140    rx.setCaseSensitive(false);
     141    event.Description = event.Description.replace(rx,"");
     142
     143    rx.setPattern("\\s*(Brand New|New) Series\\s*[:\\.\\-]");
     144    event.Description = event.Description.replace(rx,"");
     145
     146    rx.setPattern("^[tT]4:");
     147    event.Event_Name = event.Event_Name.replace(rx,"");
     148
     149    QRegExp terminatesWith("[\\!\\?]");
     150    //This is trying to catch the case where the subtitle is in the main title
     151    //but avoid cases where it isn't a subtitle e.g cd:uk
     152    if (((position = event.Event_Name.find(":")) != -1) &&
     153        (event.Description.find(":") == -1) &&
     154        (event.Event_Name[position+1].upper()==event.Event_Name[position+1]))
     155    {
     156        event.Event_Subtitle = event.Event_Name.mid(position+1);
     157        event.Event_Name = event.Event_Name.left(position);
     158    }
     159    else if ((position = event.Description.find(":")) != -1)
     160    {
     161        // if the subtitle is less than 50% of the description use it.
     162        if ((position*100)/event.Description.length() < SUBTITLE_PCT)
     163        {
     164            event.Event_Subtitle = event.Description.left(position);
     165            event.Description = event.Description.mid(position+1);
     166        }
     167    }
     168    else if ((position = event.Description.find(terminatesWith)) != -1)
     169    {
     170        if ((position*100)/event.Description.length() < SUBTITLE_PCT)
     171        {
     172            event.Event_Subtitle = event.Description.left(position+1);
     173            event.Description = event.Description.mid(position+2);
     174        }
     175    }
     176
     177    QRegExp endsWith("\\.+$");
     178    QRegExp startsWith("^\\.+");
     179    terminatesWith.setPattern("[:\\!\\.\\?]");
     180    if (event.Event_Name.endsWith("...") &&
     181        event.Event_Subtitle.startsWith(".."))
     182    {
     183        //try and make the subtitle
     184        QString Full = event.Event_Name.replace(endsWith,"")+" "+
     185                       event.Event_Subtitle.replace(startsWith,"");
     186
     187        if ((position = Full.find(terminatesWith)) != -1)
     188        {
     189           if (Full[position] == '!' || Full[position] == '?')
     190               position++;
     191           event.Event_Name = Full.left(position);
     192           event.Event_Subtitle = Full.mid(position+1);
     193        }
     194        else
     195        {
     196           event.Event_Name = Full;
     197           event.Event_Subtitle="";
     198        }
     199    }
     200    else if (event.Event_Subtitle.endsWith("...") &&
     201        event.Description.startsWith("..."))
     202    {
     203        QString Full = event.Event_Subtitle.replace(endsWith,"")+" "+
     204                       event.Description.replace(startsWith,"");
     205        if ((position = Full.find(terminatesWith)) != -1)
     206        {
     207           if (Full[position] == '!' || Full[position] == '?')
     208               position++;
     209           event.Event_Subtitle = Full.left(position);
     210           event.Description = Full.mid(position+1);
     211        }
     212    }
     213    else if (event.Event_Name.endsWith("...") &&
     214        event.Description.startsWith("...") && event.Event_Subtitle.isEmpty())
     215    {
     216        QString Full = event.Event_Name.replace(endsWith,"")+" "+
     217                       event.Description.replace(startsWith,"");
     218        if ((position = Full.find(terminatesWith)) != -1)
     219        {
     220           if (Full[position] == '!' || Full[position] == '?')
     221               position++;
     222           event.Event_Name = Full.left(position);
     223           event.Description = Full.mid(position+1);
     224        }
     225    }
     226
     227    //Work out the episode numbers (if any)
     228    bool series = false;
     229    rx.setPattern("^\\s*(\\d{1,2})/(\\d{1,2})\\.");
     230    QRegExp rx1("\\((Part|Pt)\\s+(\\d{1,2})\\s+of\\s+(\\d{1,2})\\)");
     231    rx1.setCaseSensitive(false);
     232    if ((position = rx.search(event.Event_Name)) != -1)
     233    {
     234        event.PartNumber=rx.cap(1).toUInt();
     235        event.PartTotal=rx.cap(2).toUInt();
     236        //Remove from the title
     237        event.Event_Name=event.Event_Name.mid(position+rx.cap(0).length());
     238        //but add it to the description
     239        event.Description+=rx.cap(0);
     240        series=true;
     241    }
     242    else if ((position = rx.search(event.Event_Subtitle)) != -1)
     243    {
     244        event.PartNumber=rx.cap(1).toUInt();
     245        event.PartTotal=rx.cap(2).toUInt();
     246        //Remove from the sub title
     247        event.Event_Subtitle=event.Event_Subtitle.mid(position+rx.cap(0).length());
     248        //but add it to the description
     249        event.Description+=rx.cap(0);
     250        series=true;
     251    }
     252    else if ((position = rx.search(event.Description)) != -1)
     253    {
     254        event.PartNumber=rx.cap(1).toUInt();
     255        event.PartTotal=rx.cap(2).toUInt();
     256        //Don't cut it from the description
     257        //event.Description=event.Description.left(position)+
     258        //                  event.Description.mid(position+rx.cap(0).length());
     259        series=true;
     260    }
     261    else if ((position = rx1.search(event.Description)) != -1)
     262    {
     263        event.PartNumber=rx1.cap(2).toUInt();
     264        event.PartTotal=rx1.cap(3).toUInt();
     265        //Don't cut it from the description
     266        //event.Description=event.Description.left(position)+
     267        //                  event.Description.mid(position+rx1.cap(0).length());
     268        series=true;
     269    }
     270    if (series)
     271        event.CategoryType="series";
     272    //Work out the closed captions and Audio descriptions  (if any)
     273    rx.setPattern("\\[(AD)(,(S)){,1}(,SL){,1}\\]|"
     274               "\\[(S)(,AD){,1}(,SL){,1}\\]|"
     275               "\\[(SL)(,AD){,1}(,(S)){,1}\\]");
     276    if ((position = rx.search(event.Description)) != -1)
     277    {
     278        //Enumerate throught and see if we have subtitles, don't modify
     279        //the description as we might destroy other useful information
     280        QStringList captures = rx.capturedTexts();
     281        QStringList::Iterator i = captures.begin();
     282        QStringList::Iterator end = captures.end();
     283        while (i!=end)
     284            if (*(i++) == "S")
     285                 event.SubTitled = true;
     286    }
     287    else if ((position = rx.search(event.Event_Subtitle)) != -1)
     288    {
     289        QStringList captures = rx.capturedTexts();
     290        QStringList::Iterator i = captures.begin();
     291        QStringList::Iterator end = captures.end();
     292        while (i!=end)
     293            if (*(i++) == "S")
     294                 event.SubTitled = true;
     295        //We do remove [AD,S] from the subtitle as it probably shouldn't be
     296        //there.
     297        QString Temp = event.Event_Subtitle;
     298        event.Event_Subtitle = Temp.left(position)+Temp.mid(position+rx.cap(0).length());
     299    }
     300    //Work out the year (if any)
     301    rx.setPattern("[\\[\\(]([\\d]{4})[\\)\\]]");
     302    if ((position = rx.search(event.Description)) != -1)
     303    {
     304        event.Description=event.Description.left(position)+
     305                          event.Description.mid(position+rx.cap(0).length());
     306        event.Year=rx.cap(1);
     307    }
     308
     309    event.Event_Name = event.Event_Name.stripWhiteSpace();
     310    event.Event_Subtitle = event.Event_Subtitle.stripWhiteSpace();
     311    event.Description = event.Description.stripWhiteSpace();
     312}
     313
     314/** \fn SIParser::EITFixUpStyle3(Event&)
     315 *  \brief This function does some regexps on Guide data to get
     316 *         more powerful guide. Use this for PBS channels.
     317 */
     318void EITFixUpStyle3(const privateTypes &PrivateTypes, Event &event)
     319{
     320    /* Used for PBS ATSC Subtitles are seperated by a colon */
     321    int16_t position = event.Description.find(':');
     322    if (position != -1)
     323    {
     324        event.Event_Subtitle = event.Description.left(position);
     325        event.Description = event.Description.right(
     326            event.Description.length()-position-2);
     327    }
     328}
     329
     330/** \fn SIParser::EITFixUpStyle4(Event&)
     331 *  \brief This function does some regexps on Guide data to get
     332 *         more powerful guide. Use this in Sweden (ComHem DVB).
     333 */
     334void EITFixUpStyle4(const privateTypes &PrivateTypes, Event &event)
     335{
     336    // Used for swedish dvb cable provider ComHem
     337
     338    // the format of the subtitle is:
     339    // country. category. year.
     340    // the year is optional and if the subtitle is
     341    // empty the same information is in the Description instead.
     342
     343    if (event.Event_Subtitle.length() == 0 && event.Description.length() > 0)
     344    {
     345        event.Event_Subtitle = event.Description;
     346        event.Description = "";
     347    }
     348
     349    // try to find country category and year
     350    QRegExp rx("^(.+)\\.\\s(.+)\\.\\s(?:([0-9]{2,4})\\.\\s*)?");
     351    int pos = rx.search(event.Event_Subtitle);
     352    if (pos != -1)
     353    {
     354        QStringList list = rx.capturedTexts();
     355
     356        // sometimes the category is empty, in that case use the category from
     357        // the subtitle. this category is in swedish and all others
     358        // are in english
     359        if (event.ContentDescription.length() == 0)
     360        {
     361            event.ContentDescription = list[2].stripWhiteSpace();
     362        }
     363
     364        if (list[3].length() > 0)
     365        {
     366            event.Year = list[3].stripWhiteSpace();
     367        }
     368
     369        // not 100% sure about this one.
     370        event.Event_Subtitle="";
     371    }
     372
     373    if (event.Description.length() > 0)
     374    {
     375        // everything up to the first 3 spaces is duplicated from title and
     376        // subtitle so remove it
     377        int pos = event.Description.find("   ");
     378        if (pos != -1)
     379        {
     380            event.Description =
     381                event.Description.mid(pos + 3).stripWhiteSpace();
     382            //fprintf(stdout,"SIParser::EITFixUpStyle4: New: %s\n",
     383            //event.Description.mid(pos+3).stripWhiteSpace().ascii());
     384        }
     385
     386        // in the description at this point everything up to the first 4 spaces
     387        // in a row is a list of director(s) and actors.
     388        // different lists are separated by 3 spaces in a row
     389        // end of all lists is when there is 4 spaces in a row
     390        bool bDontRemove=false;
     391        pos = event.Description.find("    ");
     392        if (pos != -1)
     393        {
     394            QStringList lists;
     395            lists=QStringList::split("   ",event.Description.left(pos));
     396            for (QStringList::Iterator it=lists.begin();it!=lists.end();it++)
     397            {
     398                QStringList list =
     399                    QStringList::split(": ",(*it).remove(QRegExp("\\.$")));
     400                if (list.count() == 2)
     401                {
     402                    if (list[0].find(QRegExp("[Rr]egi"))!=-1)
     403                    {
     404                        //director(s)
     405                        QStringList persons = QStringList::split(", ",list[1]);
     406                        for (QStringList::Iterator it2 = persons.begin();
     407                             it2 != persons.end(); it2++)
     408                        {
     409                            event.Credits.append(Person("director",*it2));
     410                        }
     411                    }
     412                    else if (list[0].find(QRegExp("[Ss]kådespelare"))!=-1)
     413                    {
     414                        //actor(s)
     415                        QStringList persons = QStringList::split(", ",list[1]);
     416                        for(QStringList::Iterator it2 = persons.begin();
     417                            it2 != persons.end(); it2++)
     418                        {
     419                            event.Credits.append(Person("actor",*it2));
     420                        }
     421                    }
     422                    else
     423                    {
     424                        // unknown type, posibly a new one that
     425                        // this code shoud be updated to handle
     426                        fprintf(stdout, "SIParser::EITFixUpStyle4: "
     427                                "%s is not actor or director\n",
     428                                list[0].ascii());
     429                        bDontRemove=true;
     430                    }
     431                }
     432                else
     433                {
     434                    //oops, improperly formated list, ignore it
     435                    //fprintf(stdout,"SIParser::EITFixUpStyle4:"
     436                    //"%s is not a properly formated list of persons\n",
     437                    //(*it).ascii());
     438                    bDontRemove=true;
     439                }
     440            }
     441            // remove list of persons from description if
     442            // we coud parse it properly
     443            if (!bDontRemove)
     444            {
     445                event.Description=event.Description.mid(pos).stripWhiteSpace();
     446            }
     447        }
     448
     449        //fprintf(stdout,"SIParser::EITFixUpStyle4: Number of persons: %d\n",
     450        //event.Credits.count());
     451
     452        /*
     453        a regexp like this coud be used to get the episode number, shoud be at
     454        the begining of the description
     455        "^(?:[dD]el|[eE]pisode)\\s([0-9]+)(?:\\s?(?:/|:|av)\\s?([0-9]+))?\\."
     456        */
     457
     458        //is this event on a channel we shoud look for a subtitle?
     459        if (PrivateTypes.ParseSubtitleServiceIDs.contains(event.ServiceID))
     460        {
     461            int pos=event.Description.find(QRegExp("[.\?] "));
     462            if (pos!=-1 && pos<=55 && (event.Description.length()-(pos+2))>0 )
     463            {
     464                event.Event_Subtitle = event.Description.left(
     465                    pos+(event.Description[pos]=='?' ? 1 : 0));
     466                event.Description = event.Description.mid(pos+2);
     467            }
     468        }
     469
     470        //try to findout if this is a rerun and if so the date.
     471        QRegExp rx("[Rr]epris\\sfrån\\s([^\\.]+)(?:\\.|$)");
     472        if (rx.search(event.Description) != -1)
     473        {
     474            QStringList list = rx.capturedTexts();
     475            if (list[1]=="i dag")
     476            {
     477                event.OriginalAirDate=event.StartTime.date();
     478            }
     479            else if (list[1]=="eftermiddagen")
     480            {
     481                event.OriginalAirDate=event.StartTime.date().addDays(-1);
     482            }
     483            else
     484            {
     485                QRegExp rxdate("([0-9]+)/([0-9]+)(?:\\s-\\s([0-9]{4}))?");
     486                if (rxdate.search(list[1]) != -1)
     487                {
     488                    QStringList datelist = rxdate.capturedTexts();
     489                    int day=datelist[1].toInt();
     490                    int month=datelist[2].toInt();
     491                    int year;
     492                    if (datelist[3].length() > 0)
     493                    {
     494                        year=datelist[3].toInt();
     495                    }
     496                    else
     497                    {
     498                        year=event.StartTime.date().year();
     499                    }
     500
     501                    if (day>0 && month>0)
     502                    {
     503                        QDate date(event.StartTime.date().year(),month,day);
     504                        //it's a rerun so it must be in the past
     505                        if (date>event.StartTime.date())
     506                        {
     507                            date=date.addYears(-1);
     508                        }
     509                        event.OriginalAirDate=date;
     510                        //fprintf(stdout,"SIParser::EITFixUpStyle4: "
     511                        //"OriginalAirDate set to: %s for '%s'\n",
     512                        //event.OriginalAirDate.toString(Qt::ISODate).ascii(),
     513                        //event.Description.ascii());
     514                    }
     515                }
     516                else
     517                {
     518                    //unknown date, posibly only a year.
     519                    //fprintf(stdout,"SIParser::EITFixUpStyle4: "
     520                    //"unknown rerun date: %s\n",list[1].ascii());
     521                }
     522            }
     523        }
     524    }
     525}
     526
  • libs/libmythtv/siparser.cpp

    old new  
    1616#include "pespacket.h"
    1717#include "atsctables.h"
    1818#include "mpegdescriptors.h"
     19#include "eitfixup.h"
    1920
    2021// MythTV DVB headers
    2122#include "siparser.h"
     
    14931494            ProcessShortEventDescriptor(desc, descLen + 2, event);
    14941495        }
    14951496
    1496         EITFixUp(event);
     1497        EITFixUp(PrivateTypes, event);
    14971498
    14981499#ifdef EIT_DEBUG_SID
    14991500        if (event.ServiceID == EIT_DEBUG_SID)
     
    25112512        }
    25122513
    25132514        pos += (descriptors_length + 2);
    2514         EITFixUp(e);
     2515        EITFixUp(PrivateTypes, e);
    25152516
    25162517        EventHandler *eh = (EventHandler*) Table[EVENTS];
    25172518        eh->Events[head->table_id_ext][event_id] = e;
     
    25422543        eh->Events[source_id][etm_id2].Description =
    25432544            ParseMSS(&buffer[5], size - 5);
    25442545
    2545         EITFixUp(eh->Events[source_id][etm_id2]);
     2546        EITFixUp(PrivateTypes, eh->Events[source_id][etm_id2]);
    25462547
    25472548        eh->Events[source_id][etm_id2].ETM_Location = 0;
    25482549    }
     
    28612862    return decompressed;
    28622863}
    28632864
    2864 /*------------------------------------------------------------------------
    2865  * Event Fix Up Scripts - Turned on by entry in dtv_privatetype table
    2866  *------------------------------------------------------------------------*/
    2867 
    2868 void SIParser::EITFixUp(Event &event)
    2869 {
    2870     event.Year = event.StartTime.toString(QString("yyyy"));
    2871     if (event.Description == "" && event.Event_Subtitle != "")
    2872     {
    2873          event.Description = event.Event_Subtitle;       
    2874          event.Event_Subtitle="";       
    2875     }
    2876 
    2877     switch (PrivateTypes.EITFixUp)
    2878     {
    2879         case 1:
    2880             EITFixUpStyle1(event);
    2881             break;
    2882         case 2:
    2883             EITFixUpStyle2(event);
    2884             break;
    2885         case 3:
    2886             EITFixUpStyle3(event);
    2887             break;
    2888         case 4:
    2889             EITFixUpStyle4(event);
    2890             break;
    2891         default:
    2892             break;
    2893     }
    2894 
    2895     event.Event_Name.stripWhiteSpace();
    2896     event.Event_Subtitle.stripWhiteSpace();
    2897     event.Description.stripWhiteSpace();
    2898 
    2899 }
    2900 
    2901 /** \fn SIParser::EITFixUpStyle1(Event&)
    2902  *  \brief This function does some regexps on Guide data to get
    2903  *         more powerful guide. Use this for BellExpressVu
    2904  *  \TODO deal with events that don't have eventype at the begining?
    2905  */
    2906 void SIParser::EITFixUpStyle1(Event &event)
    2907 {
    2908     QString Temp = "";
    2909 
    2910     int8_t position;
    2911 
    2912     // A 0x0D character is present between the content
    2913     // and the subtitle if its present
    2914     position = event.Description.find(0x0D);
    2915 
    2916     if (position != -1)
    2917     {
    2918         // Subtitle present in the title, so get
    2919         // it and adjust the description
    2920         event.Event_Subtitle = event.Description.left(position);
    2921         event.Description = event.Description.right(
    2922             event.Description.length()-position-2);
    2923     }
    2924 
    2925     // Take out the content description which is
    2926     // always next with a period after it
    2927     position = event.Description.find(".");
    2928     // Make sure they didn't leave it out and
    2929     // you come up with an odd category
    2930     if (position < 10)
    2931     {
    2932        event.ContentDescription = event.Description.left(position);
    2933        event.Description = event.Description.right(
    2934            event.Description.length()-position-2);
    2935     }
    2936     else
    2937     {
    2938        event.ContentDescription = "Unknown";
    2939     }
    2940 
    2941     // When a channel is off air the category is "-"
    2942     // so leave the category as blank
    2943     if (event.ContentDescription == "-")
    2944        event.ContentDescription = "OffAir";
    2945 
    2946     if (event.ContentDescription.length() > 10)
    2947        event.ContentDescription = "Unknown";
    2948 
    2949 
    2950     // See if a year is present as (xxxx)
    2951     position = event.Description.find(QRegExp("[\\(]{1}[0-9]{4}[\\)]{1}"));
    2952     if (position != -1 && event.ContentDescription != "")
    2953     {
    2954        Temp = "";
    2955        // Parse out the year
    2956        event.Year = event.Description.mid(position+1,4);
    2957        // Get the actors if they exist
    2958        if (position > 3)
    2959        {
    2960           Temp = event.Description.left(position-3);
    2961           event.Actors = QStringList::split(QRegExp("\\set\\s|,"), Temp);
    2962        }
    2963        // Remove the year and actors from the description
    2964        event.Description = event.Description.right(
    2965            event.Description.length()-position-7);
    2966     }
    2967 
    2968     // Check for (CC) in the decription and
    2969     // set the <subtitles type="teletext"> flag
    2970     position = event.Description.find("(CC)");
    2971     if (position != -1)
    2972     {
    2973        event.SubTitled = true;
    2974        event.Description = event.Description.replace("(CC)","");
    2975     }
    2976 
    2977     // Check for (Stereo) in the decription and set the <audio> tags
    2978     position = event.Description.find("(Stereo)");
    2979     if (position != -1)
    2980     {
    2981        event.Stereo = true;
    2982        event.Description = event.Description.replace("(Stereo)","");
    2983     }
    2984 }
    2985 
    2986 /** \fn SIParser::EITFixUpStyle2(Event&)
    2987  *  \brief This function does some regexps on Guide data to get
    2988  *         more powerful guide. Use this for the United Kingdom.
    2989  */
    2990 void SIParser::EITFixUpStyle2(Event &event)
    2991 {
    2992     const uint16_t SUBTITLE_PCT = 50; //% of description to allow subtitle up to
    2993     int16_t position = event.Description.find("New Series");
    2994     if (position != -1)
    2995     {
    2996         //Do something here
    2997     }
    2998     //BBC three case (could add another record here ?)
    2999     QRegExp rx("\\s*(Then|Followed by) 60 Seconds\\.");
    3000     rx.setCaseSensitive(false);
    3001     event.Description = event.Description.replace(rx,"");
    3002 
    3003     rx.setPattern("\\s*(Brand New|New) Series\\s*[:\\.\\-]");
    3004     event.Description = event.Description.replace(rx,"");
    3005 
    3006     rx.setPattern("^[tT]4:");
    3007     event.Event_Name = event.Event_Name.replace(rx,"");
    3008 
    3009     QRegExp terminatesWith("[\\!\\?]");
    3010     //This is trying to catch the case where the subtitle is in the main title
    3011     //but avoid cases where it isn't a subtitle e.g cd:uk
    3012     if (((position = event.Event_Name.find(":")) != -1) &&
    3013         (event.Description.find(":") == -1) &&
    3014         (event.Event_Name[position+1].upper()==event.Event_Name[position+1]))
    3015     {
    3016         event.Event_Subtitle = event.Event_Name.mid(position+1);
    3017         event.Event_Name = event.Event_Name.left(position);
    3018     }
    3019     else if ((position = event.Description.find(":")) != -1)
    3020     {
    3021         // if the subtitle is less than 50% of the description use it.
    3022         if ((position*100)/event.Description.length() < SUBTITLE_PCT)
    3023         {
    3024             event.Event_Subtitle = event.Description.left(position);
    3025             event.Description = event.Description.mid(position+1);
    3026         }
    3027     }
    3028     else if ((position = event.Description.find(terminatesWith)) != -1)
    3029     {
    3030         if ((position*100)/event.Description.length() < SUBTITLE_PCT)
    3031         {
    3032             event.Event_Subtitle = event.Description.left(position+1);
    3033             event.Description = event.Description.mid(position+2);
    3034         }
    3035     }
    3036 
    3037     QRegExp endsWith("\\.+$");
    3038     QRegExp startsWith("^\\.+");
    3039     terminatesWith.setPattern("[:\\!\\.\\?]");
    3040     if (event.Event_Name.endsWith("...") &&
    3041         event.Event_Subtitle.startsWith(".."))
    3042     {
    3043         //try and make the subtitle
    3044         QString Full = event.Event_Name.replace(endsWith,"")+" "+
    3045                        event.Event_Subtitle.replace(startsWith,"");
    3046 
    3047         if ((position = Full.find(terminatesWith)) != -1)
    3048         {
    3049            if (Full[position] == '!' || Full[position] == '?')
    3050                position++;
    3051            event.Event_Name = Full.left(position);
    3052            event.Event_Subtitle = Full.mid(position+1);
    3053         }
    3054         else
    3055         {
    3056            event.Event_Name = Full;
    3057            event.Event_Subtitle="";
    3058         }
    3059     }
    3060     else if (event.Event_Subtitle.endsWith("...") &&
    3061         event.Description.startsWith("..."))
    3062     {
    3063         QString Full = event.Event_Subtitle.replace(endsWith,"")+" "+
    3064                        event.Description.replace(startsWith,"");
    3065         if ((position = Full.find(terminatesWith)) != -1)
    3066         {
    3067            if (Full[position] == '!' || Full[position] == '?')
    3068                position++;
    3069            event.Event_Subtitle = Full.left(position);
    3070            event.Description = Full.mid(position+1);
    3071         }
    3072     }
    3073     else if (event.Event_Name.endsWith("...") &&
    3074         event.Description.startsWith("...") && event.Event_Subtitle.isEmpty())
    3075     {
    3076         QString Full = event.Event_Name.replace(endsWith,"")+" "+
    3077                        event.Description.replace(startsWith,"");
    3078         if ((position = Full.find(terminatesWith)) != -1)
    3079         {
    3080            if (Full[position] == '!' || Full[position] == '?')
    3081                position++;
    3082            event.Event_Name = Full.left(position);
    3083            event.Description = Full.mid(position+1);
    3084         }
    3085     }
    3086 
    3087     //Work out the episode numbers (if any)
    3088     bool series = false;
    3089     rx.setPattern("^\\s*(\\d{1,2})/(\\d{1,2})\\.");
    3090     QRegExp rx1("\\((Part|Pt)\\s+(\\d{1,2})\\s+of\\s+(\\d{1,2})\\)");
    3091     rx1.setCaseSensitive(false);
    3092     if ((position = rx.search(event.Event_Name)) != -1)
    3093     {
    3094         event.PartNumber=rx.cap(1).toUInt();
    3095         event.PartTotal=rx.cap(2).toUInt();
    3096         //Remove from the title
    3097         event.Event_Name=event.Event_Name.mid(position+rx.cap(0).length());
    3098         //but add it to the description
    3099         event.Description+=rx.cap(0);
    3100         series=true;
    3101     }
    3102     else if ((position = rx.search(event.Event_Subtitle)) != -1)
    3103     {
    3104         event.PartNumber=rx.cap(1).toUInt();
    3105         event.PartTotal=rx.cap(2).toUInt();
    3106         //Remove from the sub title
    3107         event.Event_Subtitle=event.Event_Subtitle.mid(position+rx.cap(0).length());
    3108         //but add it to the description
    3109         event.Description+=rx.cap(0);
    3110         series=true;
    3111     }
    3112     else if ((position = rx.search(event.Description)) != -1)
    3113     {
    3114         event.PartNumber=rx.cap(1).toUInt();
    3115         event.PartTotal=rx.cap(2).toUInt();
    3116         //Don't cut it from the description
    3117         //event.Description=event.Description.left(position)+
    3118         //                  event.Description.mid(position+rx.cap(0).length());
    3119         series=true;
    3120     }
    3121     else if ((position = rx1.search(event.Description)) != -1)
    3122     {
    3123         event.PartNumber=rx1.cap(2).toUInt();
    3124         event.PartTotal=rx1.cap(3).toUInt();
    3125         //Don't cut it from the description
    3126         //event.Description=event.Description.left(position)+
    3127         //                  event.Description.mid(position+rx1.cap(0).length());
    3128         series=true;
    3129     }
    3130     if (series)
    3131         event.CategoryType="series";
    3132     //Work out the closed captions and Audio descriptions  (if any)
    3133     rx.setPattern("\\[(AD)(,(S)){,1}(,SL){,1}\\]|"
    3134                "\\[(S)(,AD){,1}(,SL){,1}\\]|"
    3135                "\\[(SL)(,AD){,1}(,(S)){,1}\\]");
    3136     if ((position = rx.search(event.Description)) != -1)
    3137     {
    3138         //Enumerate throught and see if we have subtitles, don't modify
    3139         //the description as we might destroy other useful information
    3140         QStringList captures = rx.capturedTexts();
    3141         QStringList::Iterator i = captures.begin();
    3142         QStringList::Iterator end = captures.end();
    3143         while (i!=end)
    3144             if (*(i++) == "S")
    3145                  event.SubTitled = true;
    3146     }
    3147     else if ((position = rx.search(event.Event_Subtitle)) != -1)
    3148     {
    3149         QStringList captures = rx.capturedTexts();
    3150         QStringList::Iterator i = captures.begin();
    3151         QStringList::Iterator end = captures.end();
    3152         while (i!=end)
    3153             if (*(i++) == "S")
    3154                  event.SubTitled = true;
    3155         //We do remove [AD,S] from the subtitle as it probably shouldn't be
    3156         //there.
    3157         QString Temp = event.Event_Subtitle;
    3158         event.Event_Subtitle = Temp.left(position)+Temp.mid(position+rx.cap(0).length());
    3159     }
    3160     //Work out the year (if any)
    3161     rx.setPattern("[\\[\\(]([\\d]{4})[\\)\\]]");
    3162     if ((position = rx.search(event.Description)) != -1)
    3163     {
    3164         event.Description=event.Description.left(position)+
    3165                           event.Description.mid(position+rx.cap(0).length());
    3166         event.Year=rx.cap(1);
    3167     }
    3168 
    3169     event.Event_Name = event.Event_Name.stripWhiteSpace();
    3170     event.Event_Subtitle = event.Event_Subtitle.stripWhiteSpace();
    3171     event.Description = event.Description.stripWhiteSpace();
    3172 }
    3173 
    3174 /** \fn SIParser::EITFixUpStyle3(Event&)
    3175  *  \brief This function does some regexps on Guide data to get
    3176  *         more powerful guide. Use this for PBS channels.
    3177  */
    3178 void SIParser::EITFixUpStyle3(Event &event)
    3179 {
    3180     /* Used for PBS ATSC Subtitles are seperated by a colon */
    3181     int16_t position = event.Description.find(':');
    3182     if (position != -1)
    3183     {
    3184         event.Event_Subtitle = event.Description.left(position);
    3185         event.Description = event.Description.right(
    3186             event.Description.length()-position-2);
    3187     }
    3188 }
    3189 
    3190 /** \fn SIParser::EITFixUpStyle4(Event&)
    3191  *  \brief This function does some regexps on Guide data to get
    3192  *         more powerful guide. Use this in Sweden (ComHem DVB).
    3193  */
    3194 void SIParser::EITFixUpStyle4(Event &event)
    3195 {
    3196     // Used for swedish dvb cable provider ComHem
    3197 
    3198     // the format of the subtitle is:
    3199     // country. category. year.
    3200     // the year is optional and if the subtitle is
    3201     // empty the same information is in the Description instead.
    3202 
    3203     if (event.Event_Subtitle.length() == 0 && event.Description.length() > 0)
    3204     {
    3205         event.Event_Subtitle = event.Description;
    3206         event.Description = "";
    3207     }
    3208 
    3209     // try to find country category and year
    3210     QRegExp rx("^(.+)\\.\\s(.+)\\.\\s(?:([0-9]{2,4})\\.\\s*)?");
    3211     int pos = rx.search(event.Event_Subtitle);
    3212     if (pos != -1)
    3213     {
    3214         QStringList list = rx.capturedTexts();
    3215 
    3216         // sometimes the category is empty, in that case use the category from
    3217         // the subtitle. this category is in swedish and all others
    3218         // are in english
    3219         if (event.ContentDescription.length() == 0)
    3220         {
    3221             event.ContentDescription = list[2].stripWhiteSpace();
    3222         }
    3223 
    3224         if (list[3].length() > 0)
    3225         {
    3226             event.Year = list[3].stripWhiteSpace();
    3227         }
    3228 
    3229         // not 100% sure about this one.
    3230         event.Event_Subtitle="";
    3231     }
    3232 
    3233     if (event.Description.length() > 0)
    3234     {
    3235         // everything up to the first 3 spaces is duplicated from title and
    3236         // subtitle so remove it
    3237         int pos = event.Description.find("   ");
    3238         if (pos != -1)
    3239         {
    3240             event.Description =
    3241                 event.Description.mid(pos + 3).stripWhiteSpace();
    3242             //fprintf(stdout,"SIParser::EITFixUpStyle4: New: %s\n",
    3243             //event.Description.mid(pos+3).stripWhiteSpace().ascii());
    3244         }
    3245 
    3246         // in the description at this point everything up to the first 4 spaces
    3247         // in a row is a list of director(s) and actors.
    3248         // different lists are separated by 3 spaces in a row
    3249         // end of all lists is when there is 4 spaces in a row
    3250         bool bDontRemove=false;
    3251         pos = event.Description.find("    ");
    3252         if (pos != -1)
    3253         {
    3254             QStringList lists;
    3255             lists=QStringList::split("   ",event.Description.left(pos));
    3256             for (QStringList::Iterator it=lists.begin();it!=lists.end();it++)
    3257             {
    3258                 QStringList list =
    3259                     QStringList::split(": ",(*it).remove(QRegExp("\\.$")));
    3260                 if (list.count() == 2)
    3261                 {
    3262                     if (list[0].find(QRegExp("[Rr]egi"))!=-1)
    3263                     {
    3264                         //director(s)
    3265                         QStringList persons = QStringList::split(", ",list[1]);
    3266                         for (QStringList::Iterator it2 = persons.begin();
    3267                              it2 != persons.end(); it2++)
    3268                         {
    3269                             event.Credits.append(Person("director",*it2));
    3270                         }
    3271                     }
    3272                     else if (list[0].find(QRegExp("[Ss]kådespelare"))!=-1)
    3273                     {
    3274                         //actor(s)
    3275                         QStringList persons = QStringList::split(", ",list[1]);
    3276                         for(QStringList::Iterator it2 = persons.begin();
    3277                             it2 != persons.end(); it2++)
    3278                         {
    3279                             event.Credits.append(Person("actor",*it2));
    3280                         }
    3281                     }
    3282                     else
    3283                     {
    3284                         // unknown type, posibly a new one that
    3285                         // this code shoud be updated to handle
    3286                         fprintf(stdout, "SIParser::EITFixUpStyle4: "
    3287                                 "%s is not actor or director\n",
    3288                                 list[0].ascii());
    3289                         bDontRemove=true;
    3290                     }
    3291                 }
    3292                 else
    3293                 {
    3294                     //oops, improperly formated list, ignore it
    3295                     //fprintf(stdout,"SIParser::EITFixUpStyle4:"
    3296                     //"%s is not a properly formated list of persons\n",
    3297                     //(*it).ascii());
    3298                     bDontRemove=true;
    3299                 }
    3300             }
    3301             // remove list of persons from description if
    3302             // we coud parse it properly
    3303             if (!bDontRemove)
    3304             {
    3305                 event.Description=event.Description.mid(pos).stripWhiteSpace();
    3306             }
    3307         }
    3308 
    3309         //fprintf(stdout,"SIParser::EITFixUpStyle4: Number of persons: %d\n",
    3310         //event.Credits.count());
    3311 
    3312         /*
    3313         a regexp like this coud be used to get the episode number, shoud be at
    3314         the begining of the description
    3315         "^(?:[dD]el|[eE]pisode)\\s([0-9]+)(?:\\s?(?:/|:|av)\\s?([0-9]+))?\\."
    3316         */
    3317 
    3318         //is this event on a channel we shoud look for a subtitle?
    3319         if (PrivateTypes.ParseSubtitleServiceIDs.contains(event.ServiceID))
    3320         {
    3321             int pos=event.Description.find(QRegExp("[.\?] "));
    3322             if (pos!=-1 && pos<=55 && (event.Description.length()-(pos+2))>0 )
    3323             {
    3324                 event.Event_Subtitle = event.Description.left(
    3325                     pos+(event.Description[pos]=='?' ? 1 : 0));
    3326                 event.Description = event.Description.mid(pos+2);
    3327             }
    3328         }
    3329 
    3330         //try to findout if this is a rerun and if so the date.
    3331         QRegExp rx("[Rr]epris\\sfrån\\s([^\\.]+)(?:\\.|$)");
    3332         if (rx.search(event.Description) != -1)
    3333         {
    3334             QStringList list = rx.capturedTexts();
    3335             if (list[1]=="i dag")
    3336             {
    3337                 event.OriginalAirDate=event.StartTime.date();
    3338             }
    3339             else if (list[1]=="eftermiddagen")
    3340             {
    3341                 event.OriginalAirDate=event.StartTime.date().addDays(-1);
    3342             }
    3343             else
    3344             {
    3345                 QRegExp rxdate("([0-9]+)/([0-9]+)(?:\\s-\\s([0-9]{4}))?");
    3346                 if (rxdate.search(list[1]) != -1)
    3347                 {
    3348                     QStringList datelist = rxdate.capturedTexts();
    3349                     int day=datelist[1].toInt();
    3350                     int month=datelist[2].toInt();
    3351                     int year;
    3352                     if (datelist[3].length() > 0)
    3353                     {
    3354                         year=datelist[3].toInt();
    3355                     }
    3356                     else
    3357                     {
    3358                         year=event.StartTime.date().year();
    3359                     }
    3360 
    3361                     if (day>0 && month>0)
    3362                     {
    3363                         QDate date(event.StartTime.date().year(),month,day);
    3364                         //it's a rerun so it must be in the past
    3365                         if (date>event.StartTime.date())
    3366                         {
    3367                             date=date.addYears(-1);
    3368                         }
    3369                         event.OriginalAirDate=date;
    3370                         //fprintf(stdout,"SIParser::EITFixUpStyle4: "
    3371                         //"OriginalAirDate set to: %s for '%s'\n",
    3372                         //event.OriginalAirDate.toString(Qt::ISODate).ascii(),
    3373                         //event.Description.ascii());
    3374                     }
    3375                 }
    3376                 else
    3377                 {
    3378                     //unknown date, posibly only a year.
    3379                     //fprintf(stdout,"SIParser::EITFixUpStyle4: "
    3380                     //"unknown rerun date: %s\n",list[1].ascii());
    3381                 }
    3382             }
    3383         }
    3384     }
    3385 }
    3386 
    33872865void SIParser::InitializeCategories()
    33882866{
    33892867    m_mapCategories[0x10] = tr("Movie");
  • new file test/libs/libmythtv/eitfixup.h

    - +  
     1#include "siparser.h"
     2
     3// EIT Fix Up Functions
     4void EITFixUp      (const privateTypes &privateTypes, Event &event);
     5void EITFixUpStyle1(const privateTypes &privateTypes, Event &event);
     6void EITFixUpStyle2(const privateTypes &privateTypes, Event &event);
     7void EITFixUpStyle3(const privateTypes &privateTypes, Event &event);
     8void EITFixUpStyle4(const privateTypes &privateTypes, Event &event);
     9
  • libs/libmythtv/libmythtv.pro

    old new  
    297297
    298298        DEFINES += USING_DVB
    299299        using_dvb_eit {
    300             HEADERS += eithelper.h   eitscanner.h
    301             SOURCES += eithelper.cpp eitscanner.cpp
     300            HEADERS += eithelper.h   eitscanner.h   eitfixup.h
     301            SOURCES += eithelper.cpp eitscanner.cpp eitfixup.cpp
    302302            DEFINES += USING_DVB_EIT
    303303        }
    304304    }
  • libs/libmythtv/siparser.h

    old new  
    214214
    215215    void InitializeCategories(void);
    216216
    217     // EIT Fix Up Functions
    218     void EITFixUp      (Event &event);
    219     void EITFixUpStyle1(Event &event);
    220     void EITFixUpStyle2(Event &event);
    221     void EITFixUpStyle3(Event &event);
    222     void EITFixUpStyle4(Event &event);
    223 
    224217  private:
    225218    bool PAT_ready;
    226219    bool PMT_ready;