MythTV  master
eitfixup.cpp
Go to the documentation of this file.
1 // C++ headers
2 #include <algorithm>
3 
4 // MythTV headers
5 #include "eitfixup.h"
6 #include "programinfo.h" // for CategoryType
7 #include "channelutil.h" // for GetDefaultAuthority()
8 
9 #include "programinfo.h" // for subtitle types and audio and video properties
10 #include "dishdescriptors.h" // for dish_theme_type_to_string
11 #include "mythlogging.h"
12 
13 /*------------------------------------------------------------------------
14  * Event Fix Up Scripts - Turned on by entry in dtv_privatetype table
15  *------------------------------------------------------------------------*/
16 
17 // Constituents of UK season regexp, decomposed for clarity
18 
19 // Matches Season 2, S 2 and "Series 2," etc but not "hits 2"
20 // cap1 = season
21 const QString seasonStr = "\\b(?:Season|Series|S)\\s*(\\d+)\\s*,?";
22 
23 // Matches Episode 3, Ep 3/4, Ep 3 of 4 etc but not "step 1"
24 // cap1 = ep, cap2 = total
25 const QString longEp = "\\b(?:Ep|Episode)\\s*(\\d+)\\s*(?:(?:/|of)\\s*(\\d*))?";
26 
27 // Matches S2 Ep 3/4, "Season 2, Ep 3 of 4", Episode 3 etc
28 // cap1 = season, cap2 = ep, cap3 = total
29 const QString longSeasEp = QString("\\(?(?:%1)?\\s*%2").arg(seasonStr, longEp);
30 
31 // Matches long seas/ep with surrounding parenthesis & trailing period
32 // cap1 = season, cap2 = ep, cap3 = total
33 const QString longContext = QString("\\(*%1\\s*\\)?\\s*\\.?").arg(longSeasEp);
34 
35 // Matches 3/4, 3 of 4
36 // cap1 = ep, cap2 = total
37 const QString shortEp = "(\\d+)\\s*(?:/|of)\\s*(\\d+)";
38 
39 // Matches short ep/total, ignoring Parts and idioms such as 9/11, 24/7 etc.
40 // ie. x/y in parenthesis or has no leading or trailing text in the sentence.
41 // cap0 may include previous/anchoring period
42 // cap1 = shortEp with surrounding parenthesis & trailing period (to remove)
43 // cap2 = ep, cap3 = total,
44 const QString shortContext =
45  QString("(?:^|\\.)(\\s*\\(*\\s*%1[\\s)]*(?:[).:]|$))").arg(shortEp);
46 
47 
49  : m_bellYear("[\\(]{1}[0-9]{4}[\\)]{1}"),
50  m_bellActors("\\set\\s|,"),
51  m_bellPPVTitleAllDayHD("\\s*\\(All Day\\, HD\\)\\s*$"),
52  m_bellPPVTitleAllDay("\\s*\\(All Day.*\\)\\s*$"),
53  m_bellPPVTitleHD("^HD\\s?-\\s?"),
54  m_bellPPVSubtitleAllDay("^All Day \\(.*\\sEastern\\)\\s*$"),
55  m_bellPPVDescriptionAllDay("^\\(.*\\sEastern\\)"),
56  m_bellPPVDescriptionAllDay2("^\\([0-9].*am-[0-9].*am\\sET\\)"),
57  m_bellPPVDescriptionEventId("\\([0-9]{5}\\)"),
58  m_dishPPVTitleHD("\\sHD\\s*$"),
59  m_dishPPVTitleColon("\\:\\s*$"),
60  m_dishPPVSpacePerenEnd("\\s\\)\\s*$"),
61  m_dishDescriptionNew("\\s*New\\.\\s*"),
62  m_dishDescriptionFinale("\\s*(Series|Season)\\sFinale\\.\\s*"),
63  m_dishDescriptionFinale2("\\s*Finale\\.\\s*"),
64  m_dishDescriptionPremiere("\\s*(Series|Season)\\s(Premier|Premiere)\\.\\s*"),
65  m_dishDescriptionPremiere2("\\s*(Premier|Premiere)\\.\\s*"),
66  m_dishPPVCode("\\s*\\(([A-Z]|[0-9]){5}\\)\\s*$"),
67  m_ukThen("\\s*(Then|Followed by) 60 Seconds\\.", Qt::CaseInsensitive),
68  m_ukNew("(New\\.|\\s*(Brand New|New)\\s*(Series|Episode)\\s*[:\\.\\-])",Qt::CaseInsensitive),
69  m_ukNewTitle("^(Brand New|New:)\\s*",Qt::CaseInsensitive),
70  m_ukAlsoInHD("\\s*Also in HD\\.",Qt::CaseInsensitive),
71  m_ukCEPQ("[:\\!\\.\\?]\\s"),
72  m_ukColonPeriod("[:\\.]"),
73  m_ukDotSpaceStart("^\\. "),
74  m_ukDotEnd("\\.$"),
75  m_ukSpaceColonStart("^[ |:]*"),
76  m_ukSpaceStart("^ "),
77  m_ukPart("[-(\\:,.]\\s*(?:Part|Pt)\\s*(\\d+)\\s*(?:(?:of|/)\\s*(\\d+))?\\s*[-):,.]", Qt::CaseInsensitive),
78  // Prefer long format resorting to short format
79  // cap0 = long match to remove, cap1 = long season, cap2 = long ep, cap3 = long total,
80  // cap4 = short match to remove, cap5 = short ep, cap6 = short total
81  m_ukSeries("(?:" + longContext + "|" + shortContext + ")", Qt::CaseInsensitive),
82  m_ukCC("\\[(?:(AD|SL|S|W|HD),?)+\\]"),
83  m_ukYear("[\\[\\(]([\\d]{4})[\\)\\]]"),
84  m_uk24ep("^\\d{1,2}:00[ap]m to \\d{1,2}:00[ap]m: "),
85  m_ukStarring("(?:Western\\s)?[Ss]tarring ([\\w\\s\\-']+)[Aa]nd\\s([\\w\\s\\-']+)[\\.|,](?:\\s)*(\\d{4})?(?:\\.\\s)?"),
86  m_ukBBC7rpt("\\[Rptd?[^]]+\\d{1,2}\\.\\d{1,2}[ap]m\\]\\."),
87  m_ukDescriptionRemove("^(?:CBBC\\s*\\.|CBeebies\\s*\\.|Class TV\\s*:|BBC Switch\\.)"),
88  m_ukTitleRemove("^(?:[tT]4:|Schools\\s*:)"),
89  m_ukDoubleDotEnd("\\.\\.+$"),
90  m_ukDoubleDotStart("^\\.\\.+"),
91  m_ukTime("\\d{1,2}[\\.:]\\d{1,2}\\s*(am|pm|)"),
92  m_ukBBC34("BBC (?:THREE|FOUR) on BBC (?:ONE|TWO)\\.",Qt::CaseInsensitive),
93  m_ukYearColon("^[\\d]{4}:"),
94  m_ukExclusionFromSubtitle("(starring|stars\\s|drama|series|sitcom)",Qt::CaseInsensitive),
95  m_ukCompleteDots("^\\.\\.+$"),
96  m_ukQuotedSubtitle("(?:^')([\\w\\s\\-,]+)(?:\\.' )"),
97  m_ukAllNew("All New To 4Music!\\s?"),
98  m_ukLaONoSplit("^Law & Order: (?:Criminal Intent|LA|Special Victims Unit|Trial by Jury|UK|You the Jury)"),
99  m_comHemCountry("^(\\(.+\\))?\\s?([^ ]+)\\s([^\\.0-9]+)"
100  "(?:\\sfr\xE5n\\s([0-9]{4}))(?:\\smed\\s([^\\.]+))?\\.?"),
101  m_comHemDirector("[Rr]egi"),
102  m_comHemActor("[Ss]k\xE5""despelare|[Ii] rollerna"),
103  m_comHemHost("[Pp]rogramledare"),
104  m_comHemSub("[.\\?\\!] "),
105  m_comHemRerun1("[Rr]epris\\sfr\xE5n\\s([^\\.]+)(?:\\.|$)"),
106  m_comHemRerun2("([0-9]+)/([0-9]+)(?:\\s-\\s([0-9]{4}))?"),
107  m_comHemTT("[Tt]ext-[Tt][Vv]"),
108  m_comHemPersSeparator("(, |\\soch\\s)"),
109  m_comHemPersons("\\s?([Rr]egi|[Ss]k\xE5""despelare|[Pp]rogramledare|"
110  "[Ii] rollerna):\\s([^\\.]+)\\."),
111  m_comHemSubEnd("\\s?\\.\\s?$"),
112  m_comHemSeries1("\\s?(?:[dD]el|[eE]pisode)\\s([0-9]+)"
113  "(?:\\s?(?:/|:|av)\\s?([0-9]+))?\\."),
114  m_comHemSeries2("\\s?-?\\s?([Dd]el\\s+([0-9]+))"),
115  m_comHemTSub("\\s+-\\s+([^\\-]+)"),
116  m_mcaIncompleteTitle("(.*).\\.\\.\\.$"),
117  m_mcaCompleteTitlea("^'?("),
118  m_mcaCompleteTitleb("[^\\.\\?]+[^\\'])'?[\\.\\?]\\s+(.+)"),
119  m_mcaSubtitle("^'([^\\.]+)'\\.\\s+(.+)"),
120  m_mcaSeries("^S?(\\d+)\\/E?(\\d+)\\s-\\s(.*)$"),
121  m_mcaCredits("(.*)\\s\\((\\d{4})\\)\\s*([^\\.]+)\\.?\\s*$"),
122  m_mcaAvail("\\s(Only available on [^\\.]*bouquet|Not available in RSA [^\\.]*)\\.?"),
123  m_mcaActors("(.*\\.)\\s+([^\\.]+\\s[A-Z][^\\.]+)\\.\\s*"),
124  m_mcaActorsSeparator("(,\\s+)"),
125  m_mcaYear("(.*)\\s\\((\\d{4})\\)\\s*$"),
126  m_mcaCC(",?\\s(HI|English) Subtitles\\.?"),
127  m_mcaDD(",?\\sDD\\.?"),
128  m_RTLrepeat("(\\(|\\s)?Wiederholung.+vo[m|n].+((?:\\d{2}\\.\\d{2}\\.\\d{4})|(?:\\d{2}[:\\.]\\d{2}\\sUhr))\\)?"),
129  m_RTLSubtitle("^([^\\.]{3,})\\.\\s+(.+)"),
130  /* should be (?:\x{8a}|\\.\\s*|$) but 0x8A gets replaced with 0x20 */
131  m_RTLSubtitle1("^Folge\\s(\\d{1,4})\\s*:\\s+'(.*)'(?:\\s|\\.\\s*|$)"),
132  m_RTLSubtitle2("^Folge\\s(\\d{1,4})\\s+(.{,5}[^\\.]{,120})[\\?!\\.]\\s*"),
133  m_RTLSubtitle3("^(?:Folge\\s)?(\\d{1,4}(?:\\/[IVX]+)?)\\s+(.{,5}[^\\.]{,120})[\\?!\\.]\\s*"),
134  m_RTLSubtitle4("^Thema.{0,5}:\\s([^\\.]+)\\.\\s*"),
135  m_RTLSubtitle5("^'(.+)'\\.\\s*"),
136  m_PRO7Subtitle(",{0,1}([^,]*),([^,]+)\\s{0,1}(\\d{4})$"),
137  m_PRO7Crew("\n\n(Regie:.*)$"),
138  m_PRO7CrewOne("^(.*):\\s+(.*)$"),
139  m_PRO7Cast("\n\nDarsteller:\n(.*)$"),
140  m_PRO7CastOne("^([^\\(]*)\\((.*)\\)$"),
141  m_ATVSubtitle(",{0,1}\\sFolge\\s(\\d{1,3})$"),
142  m_DisneyChannelSubtitle(",([^,]+)\\s{0,1}(\\d{4})$"),
143  m_RTLEpisodeNo1("^(Folge\\s\\d{1,4})\\.*\\s*"),
144  m_RTLEpisodeNo2("^(\\d{1,2}\\/[IVX]+)\\.*\\s*"),
145  m_fiRerun("\\ ?Uusinta[a-zA-Z\\ ]*\\.?"),
146  m_fiRerun2("\\([Uu]\\)"),
147  m_fiAgeLimit("\\(((1?[0-9]?)|[ST])\\)$"),
148  m_fiFilm("^(Film|Elokuva): "),
149  m_dePremiereLength("\\s?[0-9]+\\sMin\\."),
150  m_dePremiereAirdate("\\s?([^\\s^\\.]+)\\s((?:1|2)[0-9]{3})\\."),
151  m_dePremiereCredits("\\sVon\\s([^,]+)(?:,|\\su\\.\\sa\\.)\\smit\\s([^\\.]*)\\."),
152  m_dePremiereOTitle("\\s*\\(([^\\)]*)\\)$"),
153  m_deSkyDescriptionSeasonEpisode("^(\\d{1,2}).\\sStaffel,\\sFolge\\s(\\d{1,2}):\\s"),
154  m_nlTxt("txt"),
155  m_nlWide("breedbeeld"),
156  m_nlRepeat("herh."),
157  m_nlHD("\\sHD$"),
158  m_nlSub("\\sAfl\\.:\\s([^\\.]+)\\."),
159  m_nlSub2("\\s\"([^\"]+)\""),
160  m_nlActors("\\sMet:\\s.+e\\.a\\."),
161  m_nlPres("\\sPresentatie:\\s([^\\.]+)\\."),
162  m_nlPersSeparator("(, |\\sen\\s)"),
163  m_nlRub("\\s?\\({1}\\W+\\){1}\\s?"),
164  m_nlYear1("(?=\\suit\\s)([1-2]{2}[0-9]{2})"),
165  m_nlYear2("([\\s]{1}[\\(]{1}[A-Z]{0,3}/?)([1-2]{2}[0-9]{2})([\\)]{1})"),
166  m_nlDirector("(?=\\svan\\s)(([A-Z]{1}[a-z]+\\s)|([A-Z]{1}\\.\\s))"),
167  m_nlCat("^(Amusement|Muziek|Informatief|Nieuws/actualiteiten|Jeugd|Animatie|Sport|Serie/soap|Kunst/Cultuur|Documentaire|Film|Natuur|Erotiek|Comedy|Misdaad|Religieus)\\.\\s"),
168  m_nlOmroep ("\\s\\(([A-Z]+/?)+\\)$"),
169  m_noRerun("\\(R\\)"),
170  m_noHD("[\\(\\[]HD[\\)\\]]"),
171  m_noColonSubtitle("^([^:]+): (.+)"),
172  m_noNRKCategories("^(Superstrek[ea]r|Supersomm[ea]r|Superjul|Barne-tv|Fantorangen|Kuraffen|Supermorg[eo]n|Julemorg[eo]n|Sommermorg[eo]n|"
173  "Kuraffen-TV|Sport i dag|NRKs sportsl.rdag|NRKs sportss.ndag|Dagens dokumentar|"
174  "NRK2s historiekveld|Detektimen|Nattkino|Filmklassiker|Film|Kortfilm|P.skemorg[eo]n|"
175  "Radioteatret|Opera|P2-Akademiet|Nyhetsmorg[eo]n i P2 og Alltid Nyheter:): (.+)"),
176  m_noPremiere("\\s+-\\s+(Sesongpremiere|Premiere|premiere)!?$"),
177  m_Stereo("\\b\\(?[sS]tereo\\)?\\b"),
178  m_dkEpisode("\\(([0-9]+)\\)"),
179  m_dkPart("\\(([0-9]+):([0-9]+)\\)"),
180  m_dkSubtitle1("^([^:]+): (.+)"),
181  m_dkSubtitle2("^([^:]+) - (.+)"),
182  m_dkSeason1("S\xE6son ([0-9]+)\\."),
183  m_dkSeason2("- \xE5r ([0-9]+)(?: :)"),
184  m_dkFeatures("Features:(.+)"),
185  m_dkWidescreen(" 16:9"),
186  m_dkDolby(" 5:1"),
187  m_dkSurround(" \\(\\(S\\)\\)"),
188  m_dkStereo(" S"),
189  m_dkReplay(" \\(G\\)"),
190  m_dkTxt(" TTV"),
191  m_dkHD(" HD"),
192  m_dkActors("(?:Medvirkende: |Medv\\.: )(.+)"),
193  m_dkPersonsSeparator("(, )|(og )"),
194  m_dkDirector("(?:Instr.: |Instrukt.r: )(.+)$"),
195  m_dkYear(" fra ([0-9]{4})[ \\.]"),
196  m_AUFreeviewSY("(.*) \\((.+)\\) \\(([12][0-9][0-9][0-9])\\)$"),
197  m_AUFreeviewY("(.*) \\(([12][0-9][0-9][0-9])\\)$"),
198  m_AUFreeviewYC("(.*) \\(([12][0-9][0-9][0-9])\\) \\((.+)\\)$"),
199  m_AUFreeviewSYC("(.*) \\((.+)\\) \\(([12][0-9][0-9][0-9])\\) \\((.+)\\)$"),
200  m_HTML("</?EM>", Qt::CaseInsensitive),
201  m_grReplay("\\([ΕE]\\)"),
202  m_grDescriptionFinale("\\s*Τελευταίο\\sΕπεισόδιο\\.\\s*"),
203  m_grActors("(?:[Ππ]α[ιί]ζουν:|[ΜMμ]ε τους:|Πρωταγωνιστο[υύ]ν:|Πρωταγωνιστε[ιί]:?)(?:\\s+στο ρόλο(?: του| της)?\\s(?:\\w+\\s[οη]\\s))?([-\\w\\s']+(?:,[-\\w\\s']+)*)(?:κ\\.[αά])?(?:\\W?)"),
204  // cap(1) actors, just names
205  m_grFixnofullstopActors("(\\w\\s(Παίζουν:|Πρωταγων))"),
206  m_grFixnofullstopDirectors("((\\w\\s(Σκηνοθ[εέ]))"),
207  m_grPeopleSeparator("([,-]\\s+)"),
208  m_grDirector("(?:Σκηνοθεσία: |Σκηνοθέτης: |Σκηνοθέτης - Επιμέλεια: )(\\w+\\s\\w+\\s?)(?:\\W?)"),
209  m_grPres("(?:Παρουσ[ιί]αση:(?:\\b)*|Παρουσι[αά]ζ(?:ουν|ει)(?::|\\sο|\\sη)|Παρουσι[αά]στ(?:[ηή]ς|ρια|ριες|[εέ]ς)(?::|\\sο|\\sη)|Με τ(?:ον |ην )(?:[\\s|:|ο|η])*(?:\\b)*)([-\\w\\s]+(?:,[-\\w\\s]+)*)(?:\\W?)"),
210  m_grYear("(?:\\W?)(?:\\s?παραγωγ[ηή]ς|\\s?-|,)\\s*([1-2]{1}[0-9]{3})(?:-\\d{1,4})?",Qt::CaseInsensitive),
211  m_grCountry("(?:\\W|\\b)(?:(ελλην|τουρκ|αμερικ[αά]ν|γαλλ|αγγλ|βρεττ?αν|γερμαν|ρωσσ?|ιταλ|ελβετ|σουηδ|ισπαν|πορτογαλ|μεξικ[αά]ν|κιν[εέ]ζικ|ιαπων|καναδ|βραζιλι[αά]ν)(ικ[ηή][ςσ]))",Qt::CaseInsensitive),
212  m_grlongEp("\\b(?:Επ.|επεισ[οό]διο:?)\\s*(\\d+)(?:\\W?)",Qt::CaseInsensitive),
213  m_grSeason_as_RomanNumerals(",\\s*([MDCLXVIΙΧ]+)$",Qt::CaseInsensitive),
214  m_grSeason("(?:\\W-?)*(?:\\(-\\s*)?\\b(([Α-Ω]{1,2})(?:'|΄)?|(\\d{1,2})(?:ος|ου|oς|os)?)(?:\\s*κ[υύ]κλο(?:[σς]|υ)){1}\\s?",Qt::CaseInsensitive),
215  m_grRealTitleinDescription("(?:^\\()([A-Za-z\\s\\d-]+)(?:\\))(?:\\s*)"),
216  // cap1 = real title
217  // cap0 = real title in parentheses.
218  m_grRealTitleinTitle("(?:\\()([A-Za-z\\s\\d-]+)(?:\\))(?:\\s*$)*"),
219  // cap1 = real title
220  // cap0 = real title in parentheses.
221  m_grCommentsinTitle("(?:\\()([Α-Ωα-ω\\s\\d-]+)(?:\\))(?:\\s*$)*"),
222  // cap1 = real title
223  // cap0 = real title in parentheses.
224  m_grNotPreviouslyShown("(?:\\W?)(?:-\\s*)*(?:\\b[Α1]['΄η]?\\s*(?:τηλεοπτικ[ηή]\\s*)?(?:μετ[αά]δοση|προβολ[ηή]))(?:\\W?)",Qt::CaseInsensitive),
225  // Try to exctract Greek categories from keywords in description.
226  m_grEpisodeAsSubtitle("(?:^Επεισ[οό]διο:\\s?)([\\w\\s-,']+)\\.(?:\\s)?"),
227  m_grCategFood("(?:\\W)?(?:εκπομπ[ηή]\\W)?(Γαστρονομ[ιί]α[σς]?|μαγειρικ[ηή][σς]?|chef|συνταγ[εέηή]|διατροφ|wine|μ[αά]γειρα[σς]?)(?:\\W)?",Qt::CaseInsensitive),
228  m_grCategDrama("(?:\\W)?(κοινωνικ[ηήό]|δραματικ[ηή]|δρ[αά]μα)(?:\\W)(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",Qt::CaseInsensitive),
229  m_grCategComedy("(?:\\W)?(κωμικ[ηήοό]|χιουμοριστικ[ηήοό]|κωμωδ[ιί]α)(?:\\W)(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",Qt::CaseInsensitive),
230  m_grCategChildren("(?:\\W)?(παιδικ[ηήοό]|κινο[υύ]μ[εέ]ν(ων|α)\\sσχ[εέ]δ[ιί](ων|α))(?:\\W)(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",Qt::CaseInsensitive),
231  m_grCategMystery("(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?(?:\\W)?(μυστηρ[ιί]ου)(?:\\W)?",Qt::CaseInsensitive),
232  m_grCategFantasy("(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?(?:\\W)?(φαντασ[ιί]ας)(?:\\W)?",Qt::CaseInsensitive),
233  m_grCategHistory("(?:\\W)?(ιστορικ[ηήοό])(?:\\W)?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",Qt::CaseInsensitive),
234  m_grCategTeleMag("(?:\\W)?(ενημερωτικ[ηή]|ψυχαγωγικ[ηή]|τηλεπεριοδικ[οό]|μαγκαζ[ιί]νο)(?:\\W)?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",Qt::CaseInsensitive),
235  m_grCategTeleShop("(?:\\W)?(οδηγ[οό][σς]?\\sαγορ[ωώ]ν|τηλεπ[ωώ]λ[ηή]σ|τηλεαγορ|τηλεμ[αά]ρκετ|telemarket)(?:\\W)?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",Qt::CaseInsensitive),
236  m_grCategGameShow("(?:\\W)?(τηλεπαιχν[ιί]δι|quiz)(?:\\W)?",Qt::CaseInsensitive),
237  m_grCategDocumentary("(?:\\W)?(ντοκ[ιυ]μαντ[εέ]ρ)(?:\\W)?",Qt::CaseInsensitive),
238  m_grCategBiography("(?:\\W)?(βιογραφ[ιί]α|βιογραφικ[οό][σς]?)(?:\\W)?",Qt::CaseInsensitive),
239  m_grCategNews("(?:\\W)?(δελτ[ιί]ο\\W?|ειδ[ηή]σε(ι[σς]|ων))(?:\\W)?",Qt::CaseInsensitive),
240  m_grCategSports("(?:\\W)?(champion|αθλητικ[αάοόηή]|πρωτ[αά]θλημα|ποδ[οό]σφαιρο(ου)?|κολ[υύ]μβηση|πατιν[αά]ζ|formula|μπ[αά]σκετ|β[οό]λε[ιϊ])(?:\\W)?",Qt::CaseInsensitive),
241  m_grCategMusic("(?:\\W)?(μουσικ[οόηή]|eurovision|τραγο[υύ]δι)(?:\\W)?",Qt::CaseInsensitive),
242  m_grCategReality("(?:\\W)?(ρι[αά]λιτι|reality)(?:\\W)?",Qt::CaseInsensitive),
243  m_grCategReligion("(?:\\W)?(θρησκε[ιί]α|θρησκευτικ|να[οό][σς]?|θε[ιί]α λειτουργ[ιί]α)(?:\\W)?",Qt::CaseInsensitive),
244  m_grCategCulture("(?:\\W)?(τ[εέ]χν(η|ε[σς])|πολιτισμ)(?:\\W)?",Qt::CaseInsensitive),
245  m_grCategNature("(?:\\W)?(φ[υύ]ση|περιβ[αά]λλο|κατασκευ|επιστ[ηή]μ(?!ονικ[ηή]ς φαντασ[ιί]ας))(?:\\W)?",Qt::CaseInsensitive),
246  m_grCategSciFi("(?:\\W)?(επιστ(.|ημονικ[ηή]ς)\\s?φαντασ[ιί]ας)(?:\\W)?",Qt::CaseInsensitive),
247  m_grCategHealth("(?:\\W)?(υγε[ιί]α|υγειιν|ιατρικ|διατροφ)(?:\\W)?",Qt::CaseInsensitive),
248  m_grCategSpecial("(?:\\W)?(αφι[εέ]ρωμα)(?:\\W)?",Qt::CaseInsensitive),
249  m_unitymediaImdbrating("\\s*IMDb Rating: (\\d\\.\\d)\\s?/10$")
250 {
251 }
252 
253 void EITFixUp::Fix(DBEventEIT &event) const
254 {
255  if (event.m_fixup)
256  {
257  if (event.m_subtitle == event.m_title)
258  event.m_subtitle = QString("");
259 
260  if (event.m_description.isEmpty() && !event.m_subtitle.isEmpty())
261  {
262  event.m_description = event.m_subtitle;
263  event.m_subtitle = QString("");
264  }
265  }
266 
267  if (kFixHTML & event.m_fixup)
268  FixStripHTML(event);
269 
270  if (kFixHDTV & event.m_fixup)
271  event.m_videoProps |= VID_HDTV;
272 
273  if (kFixBell & event.m_fixup)
274  FixBellExpressVu(event);
275 
276  if (kFixDish & event.m_fixup)
277  FixBellExpressVu(event);
278 
279  if (kFixUK & event.m_fixup)
280  FixUK(event);
281 
282  if (kFixPBS & event.m_fixup)
283  FixPBS(event);
284 
285  if (kFixComHem & event.m_fixup)
286  FixComHem(event, (kFixSubtitle & event.m_fixup) != 0U);
287 
288  if (kFixAUStar & event.m_fixup)
289  FixAUStar(event);
290 
291  if (kFixAUDescription & event.m_fixup)
292  FixAUDescription(event);
293 
294  if (kFixAUFreeview & event.m_fixup)
295  FixAUFreeview(event);
296 
297  if (kFixAUNine & event.m_fixup)
298  FixAUNine(event);
299 
300  if (kFixAUSeven & event.m_fixup)
301  FixAUSeven(event);
302 
303  if (kFixMCA & event.m_fixup)
304  FixMCA(event);
305 
306  if (kFixRTL & event.m_fixup)
307  FixRTL(event);
308 
309  if (kFixP7S1 & event.m_fixup)
310  FixPRO7(event);
311 
312  if (kFixATV & event.m_fixup)
313  FixATV(event);
314 
315  if (kFixDisneyChannel & event.m_fixup)
316  FixDisneyChannel(event);
317 
318  if (kFixFI & event.m_fixup)
319  FixFI(event);
320 
321  if (kFixPremiere & event.m_fixup)
322  FixPremiere(event);
323 
324  if (kFixNL & event.m_fixup)
325  FixNL(event);
326 
327  if (kFixNO & event.m_fixup)
328  FixNO(event);
329 
330  if (kFixNRK_DVBT & event.m_fixup)
331  FixNRK_DVBT(event);
332 
333  if (kFixDK & event.m_fixup)
334  FixDK(event);
335 
336  if (kFixCategory & event.m_fixup)
337  FixCategory(event);
338 
339  if (kFixGreekSubtitle & event.m_fixup)
340  FixGreekSubtitle(event);
341 
342  if (kFixGreekEIT & event.m_fixup)
343  FixGreekEIT(event);
344 
345  if (kFixGreekCategories & event.m_fixup)
346  FixGreekCategories(event);
347 
348  if (kFixUnitymedia & event.m_fixup)
349  FixUnitymedia(event);
350 
351  if (event.m_fixup)
352  {
353  if (!event.m_title.isEmpty())
354  {
355  event.m_title = event.m_title.replace(QChar('\0'), "");
356  event.m_title = event.m_title.trimmed();
357  }
358 
359  if (!event.m_subtitle.isEmpty())
360  {
361  event.m_subtitle = event.m_subtitle.replace(QChar('\0'), "");
362  event.m_subtitle = event.m_subtitle.trimmed();
363  }
364 
365  if (!event.m_description.isEmpty())
366  {
367  event.m_description = event.m_description.replace(QChar('\0'), "");
368  event.m_description = event.m_description.trimmed();
369  }
370  }
371 
372  if (kFixGenericDVB & event.m_fixup)
373  {
374  event.m_programId = AddDVBEITAuthority(event.m_chanid, event.m_programId);
375  event.m_seriesId = AddDVBEITAuthority(event.m_chanid, event.m_seriesId);
376  }
377 
378  // Are any items left unhandled? report them to allow fixups improvements
379  if (!event.m_items.empty())
380  {
381  QMap<QString,QString>::iterator i;
382  for (i = event.m_items.begin(); i != event.m_items.end(); ++i)
383  {
384  LOG(VB_EIT, LOG_DEBUG, QString("Unhandled item in EIT for"
385  " channel id \"%1\", \"%2\": %3").arg(event.m_chanid)
386  .arg(i.key()).arg(i.value()));
387  }
388  }
389 }
390 
406 QString EITFixUp::AddDVBEITAuthority(uint chanid, const QString &id)
407 {
408  if (id.isEmpty())
409  return id;
410 
411  // CRIDs are not case sensitive, so change all to lower case
412  QString crid = id.toLower();
413 
414  // remove "crid://"
415  if (crid.startsWith("crid://"))
416  crid.remove(0,7);
417 
418  // if id is a CRID with authority, return it
419  if (crid.length() >= 1 && crid[0] != '/')
420  return crid;
421 
422  QString authority = ChannelUtil::GetDefaultAuthority(chanid);
423  if (authority.isEmpty())
424  return ""; // no authority, not a valid CRID, return empty
425 
426  return authority + crid;
427 }
428 
434 {
435  // A 0x0D character is present between the content
436  // and the subtitle if its present
437  int position = event.m_description.indexOf(0x0D);
438 
439  if (position != -1)
440  {
441  // Subtitle present in the title, so get
442  // it and adjust the description
443  event.m_subtitle = event.m_description.left(position);
444  event.m_description = event.m_description.right(
445  event.m_description.length() - position - 2);
446  }
447 
448  // Take out the content description which is
449  // always next with a period after it
450  position = event.m_description.indexOf(".");
451  // Make sure they didn't leave it out and
452  // you come up with an odd category
453  if (position < 10)
454  {
455  }
456  else
457  {
458  event.m_category = "Unknown";
459  }
460 
461  // If the content descriptor didn't come up with anything, try parsing the category
462  // out of the description.
463  if (event.m_category.isEmpty())
464  {
465  // Take out the content description which is
466  // always next with a period after it
467  position = event.m_description.indexOf(".");
468  if ((position + 1) < event.m_description.length())
469  position = event.m_description.indexOf(". ");
470  // Make sure they didn't leave it out and
471  // you come up with an odd category
472  if ((position > -1) && position < 20)
473  {
474  const QString stmp = event.m_description;
475  event.m_description = stmp.right(stmp.length() - position - 2);
476  event.m_category = stmp.left(position);
477 
478  int position_p = event.m_category.indexOf("(");
479  if (position_p == -1)
480  event.m_description = stmp.right(stmp.length() - position - 2);
481  else
482  event.m_category = "Unknown";
483  }
484  else
485  {
486  event.m_category = "Unknown";
487  }
488 
489  // When a channel is off air the category is "-"
490  // so leave the category as blank
491  if (event.m_category == "-")
492  event.m_category = "OffAir";
493 
494  if (event.m_category.length() > 20)
495  event.m_category = "Unknown";
496  }
497  else if (event.m_categoryType)
498  {
499  QString theme = dish_theme_type_to_string(event.m_categoryType);
500  event.m_description = event.m_description.replace(theme, "");
501  if (event.m_description.startsWith("."))
502  event.m_description = event.m_description.right(event.m_description.length() - 1);
503  if (event.m_description.startsWith(" "))
504  event.m_description = event.m_description.right(event.m_description.length() - 1);
505  }
506 
507  // See if a year is present as (xxxx)
508  position = event.m_description.indexOf(m_bellYear);
509  if (position != -1 && !event.m_category.isEmpty())
510  {
511  // Parse out the year
512  bool ok;
513  uint y = event.m_description.mid(position + 1, 4).toUInt(&ok);
514  if (ok)
515  {
516  event.m_originalairdate = QDate(y, 1, 1);
517  event.m_airdate = y;
518  event.m_previouslyshown = true;
519  }
520 
521  // Get the actors if they exist
522  if (position > 3)
523  {
524  QString tmp = event.m_description.left(position-3);
525  QStringList actors =
526  tmp.split(m_bellActors, QString::SkipEmptyParts);
527  QStringList::const_iterator it = actors.begin();
528  for (; it != actors.end(); ++it)
529  event.AddPerson(DBPerson::kActor, *it);
530  }
531  // Remove the year and actors from the description
532  event.m_description = event.m_description.right(
533  event.m_description.length() - position - 7);
534  }
535 
536  // Check for (CC) in the decription and
537  // set the <subtitles type="teletext"> flag
538  position = event.m_description.indexOf("(CC)");
539  if (position != -1)
540  {
541  event.m_subtitleType |= SUB_HARDHEAR;
542  event.m_description = event.m_description.replace("(CC)", "");
543  }
544 
545  // Check for (Stereo) in the decription and set the <audio> tags
546  position = event.m_description.indexOf(m_Stereo);
547  if (position != -1)
548  {
549  event.m_audioProps |= AUD_STEREO;
550  event.m_description = event.m_description.replace(m_Stereo, "");
551  }
552 
553  // Check for "title (All Day, HD)" in the title
554  position = event.m_title.indexOf(m_bellPPVTitleAllDayHD);
555  if (position != -1)
556  {
557  event.m_title = event.m_title.replace(m_bellPPVTitleAllDayHD, "");
558  event.m_videoProps |= VID_HDTV;
559  }
560 
561  // Check for "title (All Day)" in the title
562  position = event.m_title.indexOf(m_bellPPVTitleAllDay);
563  if (position != -1)
564  {
565  event.m_title = event.m_title.replace(m_bellPPVTitleAllDay, "");
566  }
567 
568  // Check for "HD - title" in the title
569  position = event.m_title.indexOf(m_bellPPVTitleHD);
570  if (position != -1)
571  {
572  event.m_title = event.m_title.replace(m_bellPPVTitleHD, "");
573  event.m_videoProps |= VID_HDTV;
574  }
575 
576  // Check for (HD) in the decription
577  position = event.m_description.indexOf("(HD)");
578  if (position != -1)
579  {
580  event.m_description = event.m_description.replace("(HD)", "");
581  event.m_videoProps |= VID_HDTV;
582  }
583 
584  // Check for (HD) in the title
585  position = event.m_title.indexOf("(HD)");
586  if (position != -1)
587  {
588  event.m_description = event.m_title.replace("(HD)", "");
589  event.m_videoProps |= VID_HDTV;
590  }
591 
592  // Check for HD at the end of the title
593  position = event.m_title.indexOf(m_dishPPVTitleHD);
594  if (position != -1)
595  {
596  event.m_title = event.m_title.replace(m_dishPPVTitleHD, "");
597  event.m_videoProps |= VID_HDTV;
598  }
599 
600  // Check for (DD) at the end of the description
601  position = event.m_description.indexOf("(DD)");
602  if (position != -1)
603  {
604  event.m_description = event.m_description.replace("(DD)", "");
605  event.m_audioProps |= AUD_DOLBY;
606  event.m_audioProps |= AUD_STEREO;
607  }
608 
609  // Remove SAP from Dish descriptions
610  position = event.m_description.indexOf("(SAP)");
611  if (position != -1)
612  {
613  event.m_description = event.m_description.replace("(SAP", "");
614  event.m_subtitleType |= SUB_HARDHEAR;
615  }
616 
617  // Remove any trailing colon in title
618  position = event.m_title.indexOf(m_dishPPVTitleColon);
619  if (position != -1)
620  {
621  event.m_title = event.m_title.replace(m_dishPPVTitleColon, "");
622  }
623 
624  // Remove New at the end of the description
625  position = event.m_description.indexOf(m_dishDescriptionNew);
626  if (position != -1)
627  {
628  event.m_previouslyshown = false;
629  event.m_description = event.m_description.replace(m_dishDescriptionNew, "");
630  }
631 
632  // Remove Series Finale at the end of the desciption
633  position = event.m_description.indexOf(m_dishDescriptionFinale);
634  if (position != -1)
635  {
636  event.m_previouslyshown = false;
637  event.m_description = event.m_description.replace(m_dishDescriptionFinale, "");
638  }
639 
640  // Remove Series Finale at the end of the desciption
641  position = event.m_description.indexOf(m_dishDescriptionFinale2);
642  if (position != -1)
643  {
644  event.m_previouslyshown = false;
645  event.m_description = event.m_description.replace(m_dishDescriptionFinale2, "");
646  }
647 
648  // Remove Series Premiere at the end of the description
649  position = event.m_description.indexOf(m_dishDescriptionPremiere);
650  if (position != -1)
651  {
652  event.m_previouslyshown = false;
653  event.m_description = event.m_description.replace(m_dishDescriptionPremiere, "");
654  }
655 
656  // Remove Series Premiere at the end of the description
657  position = event.m_description.indexOf(m_dishDescriptionPremiere2);
658  if (position != -1)
659  {
660  event.m_previouslyshown = false;
661  event.m_description = event.m_description.replace(m_dishDescriptionPremiere2, "");
662  }
663 
664  // Remove Dish's PPV code at the end of the description
665  QRegExp ppvcode = m_dishPPVCode;
666  ppvcode.setCaseSensitivity(Qt::CaseInsensitive);
667  position = event.m_description.indexOf(ppvcode);
668  if (position != -1)
669  {
670  event.m_description = event.m_description.replace(ppvcode, "");
671  }
672 
673  // Remove trailing garbage
674  position = event.m_description.indexOf(m_dishPPVSpacePerenEnd);
675  if (position != -1)
676  {
677  event.m_description = event.m_description.replace(m_dishPPVSpacePerenEnd, "");
678  }
679 
680  // Check for subtitle "All Day (... Eastern)" in the subtitle
681  position = event.m_subtitle.indexOf(m_bellPPVSubtitleAllDay);
682  if (position != -1)
683  {
684  event.m_subtitle = event.m_subtitle.replace(m_bellPPVSubtitleAllDay, "");
685  }
686 
687  // Check for description "(... Eastern)" in the description
688  position = event.m_description.indexOf(m_bellPPVDescriptionAllDay);
689  if (position != -1)
690  {
691  event.m_description = event.m_description.replace(m_bellPPVDescriptionAllDay, "");
692  }
693 
694  // Check for description "(... ET)" in the description
695  position = event.m_description.indexOf(m_bellPPVDescriptionAllDay2);
696  if (position != -1)
697  {
698  event.m_description = event.m_description.replace(m_bellPPVDescriptionAllDay2, "");
699  }
700 
701  // Check for description "(nnnnn)" in the description
702  position = event.m_description.indexOf(m_bellPPVDescriptionEventId);
703  if (position != -1)
704  {
705  event.m_description = event.m_description.replace(m_bellPPVDescriptionEventId, "");
706  }
707 
708 }
709 
714 {
715  QStringList strListColon = event.m_description.split(":");
716  QStringList strListEnd;
717 
718  bool fColon = false, fQuotedSubtitle = false;
719  int nPosition1;
720  QString strEnd;
721  if (strListColon.count()>1)
722  {
723  bool fDoubleDot = false;
724  bool fSingleDot = true;
725  int nLength = strListColon[0].length();
726 
727  nPosition1 = event.m_description.indexOf("..");
728  if ((nPosition1 < nLength) && (nPosition1 >= 0))
729  fDoubleDot = true;
730  nPosition1 = event.m_description.indexOf(".");
731  if (nPosition1==-1)
732  fSingleDot = false;
733  if (nPosition1 > nLength)
734  fSingleDot = false;
735  else
736  {
737  QString strTmp = event.m_description.mid(nPosition1+1,
738  nLength-nPosition1);
739 
740  QStringList tmp = strTmp.split(" ");
741  if (((uint) tmp.size()) < kMaxDotToColon)
742  fSingleDot = false;
743  }
744 
745  if (fDoubleDot)
746  {
747  strListEnd = strListColon;
748  fColon = true;
749  }
750  else if (!fSingleDot)
751  {
752  QStringList strListTmp;
753  uint nTitle=0;
754  int nTitleMax=-1;
755  int i;
756  for (i =0; (i<strListColon.count()) && (nTitleMax==-1);i++)
757  {
758  const QStringList tmp = strListColon[i].split(" ");
759 
760  nTitle += tmp.size();
761 
762  if (nTitle < kMaxToTitle)
763  strListTmp.push_back(strListColon[i]);
764  else
765  nTitleMax=i;
766  }
767  QString strPartial;
768  for (i=0;i<(nTitleMax-1);i++)
769  strPartial+=strListTmp[i]+":";
770  if (nTitleMax>0)
771  {
772  strPartial+=strListTmp[nTitleMax-1];
773  strListEnd.push_back(strPartial);
774  }
775  for (i=nTitleMax+1;i<strListColon.count();i++)
776  strListEnd.push_back(strListColon[i]);
777  fColon = true;
778  }
779  }
780  QRegExp tmpQuotedSubtitle = m_ukQuotedSubtitle;
781  if (tmpQuotedSubtitle.indexIn(event.m_description) != -1)
782  {
783  event.m_subtitle = tmpQuotedSubtitle.cap(1);
784  event.m_description.remove(m_ukQuotedSubtitle);
785  fQuotedSubtitle = true;
786  }
787  QStringList strListPeriod;
788  QStringList strListQuestion;
789  QStringList strListExcl;
790  if (!(fColon || fQuotedSubtitle))
791  {
792  strListPeriod = event.m_description.split(".");
793  if (strListPeriod.count() >1)
794  {
795  nPosition1 = event.m_description.indexOf(".");
796  int nPosition2 = event.m_description.indexOf("..");
797  if ((nPosition1 < nPosition2) || (nPosition2==-1))
798  strListEnd = strListPeriod;
799  }
800 
801  strListQuestion = event.m_description.split("?");
802  strListExcl = event.m_description.split("!");
803  if ((strListQuestion.size() > 1) &&
804  ((uint)strListQuestion.size() <= kMaxQuestionExclamation))
805  {
806  strListEnd = strListQuestion;
807  strEnd = "?";
808  }
809  else if ((strListExcl.size() > 1) &&
810  ((uint)strListExcl.size() <= kMaxQuestionExclamation))
811  {
812  strListEnd = strListExcl;
813  strEnd = "!";
814  }
815  else
816  strEnd.clear();
817  }
818 
819  if (!strListEnd.empty())
820  {
821  QStringList strListSpace = strListEnd[0].split(
822  " ", QString::SkipEmptyParts);
823  if (fColon && ((uint)strListSpace.size() > kMaxToTitle))
824  return;
825  if ((uint)strListSpace.size() > kDotToTitle)
826  return;
827  if (strListSpace.filter(m_ukExclusionFromSubtitle).empty())
828  {
829  event.m_subtitle = strListEnd[0]+strEnd;
830  event.m_subtitle.remove(m_ukSpaceColonStart);
831  event.m_description=
832  event.m_description.mid(strListEnd[0].length()+1);
833  event.m_description.remove(m_ukSpaceColonStart);
834  }
835  }
836 }
837 
838 
842 void EITFixUp::FixUK(DBEventEIT &event) const
843 {
844  int position1;
845  int position2;
846  QString strFull;
847 
848  bool isMovie = event.m_category.startsWith("Movie",Qt::CaseInsensitive) ||
849  event.m_category.startsWith("Film",Qt::CaseInsensitive);
850  // BBC three case (could add another record here ?)
851  event.m_description = event.m_description.remove(m_ukThen);
852  event.m_description = event.m_description.remove(m_ukNew);
853  event.m_title = event.m_title.remove(m_ukNewTitle);
854 
855  // Removal of Class TV, CBBC and CBeebies etc..
856  event.m_title = event.m_title.remove(m_ukTitleRemove);
857  event.m_description = event.m_description.remove(m_ukDescriptionRemove);
858 
859  // Removal of BBC FOUR and BBC THREE
860  event.m_description = event.m_description.remove(m_ukBBC34);
861 
862  // BBC 7 [Rpt of ...] case.
863  event.m_description = event.m_description.remove(m_ukBBC7rpt);
864 
865  // "All New To 4Music!
866  event.m_description = event.m_description.remove(m_ukAllNew);
867 
868  // Removal of 'Also in HD' text
869  event.m_description = event.m_description.remove(m_ukAlsoInHD);
870 
871  // Remove [AD,S] etc.
872  bool ccMatched = false;
873  QRegExp tmpCC = m_ukCC;
874  position1 = 0;
875  while ((position1 = tmpCC.indexIn(event.m_description, position1)) != -1)
876  {
877  ccMatched = true;
878  position1 += tmpCC.matchedLength();
879 
880  QStringList tmpCCitems = tmpCC.cap(0).remove("[").remove("]").split(",");
881  if (tmpCCitems.contains("AD"))
883  if (tmpCCitems.contains("HD"))
884  event.m_videoProps |= VID_HDTV;
885  if (tmpCCitems.contains("S"))
886  event.m_subtitleType |= SUB_NORMAL;
887  if (tmpCCitems.contains("SL"))
888  event.m_subtitleType |= SUB_SIGNED;
889  if (tmpCCitems.contains("W"))
890  event.m_videoProps |= VID_WIDESCREEN;
891  }
892 
893  if(ccMatched)
894  event.m_description = event.m_description.remove(m_ukCC);
895 
896  event.m_title = event.m_title.trimmed();
897  event.m_description = event.m_description.trimmed();
898 
899  // Work out the season and episode numbers (if any)
900  // Matching pattern "Season 2 Episode|Ep 3 of 14|3/14" etc
901  bool series = false;
902  QRegExp tmpSeries = m_ukSeries;
903  if ((position1 = tmpSeries.indexIn(event.m_title)) != -1
904  || (position2 = tmpSeries.indexIn(event.m_description)) != -1)
905  {
906  if (!tmpSeries.cap(1).isEmpty())
907  {
908  event.m_season = tmpSeries.cap(1).toUInt();
909  series = true;
910  }
911 
912  if (!tmpSeries.cap(2).isEmpty())
913  {
914  event.m_episode = tmpSeries.cap(2).toUInt();
915  series = true;
916  }
917  else if (!tmpSeries.cap(5).isEmpty())
918  {
919  event.m_episode = tmpSeries.cap(5).toUInt();
920  series = true;
921  }
922 
923  if (!tmpSeries.cap(3).isEmpty())
924  {
925  event.m_totalepisodes = tmpSeries.cap(3).toUInt();
926  series = true;
927  }
928  else if (!tmpSeries.cap(6).isEmpty())
929  {
930  event.m_totalepisodes = tmpSeries.cap(6).toUInt();
931  series = true;
932  }
933 
934  // Remove long or short match. Short text doesn't start at position2
935  int form = tmpSeries.cap(4).isEmpty() ? 0 : 4;
936 
937  if (position1 != -1)
938  {
939  LOG(VB_EIT, LOG_DEBUG, QString("Extracted S%1E%2/%3 from title (%4) \"%5\"")
940  .arg(event.m_season).arg(event.m_episode).arg(event.m_totalepisodes)
941  .arg(event.m_title, event.m_description));
942 
943  event.m_title.remove(tmpSeries.cap(form));
944  }
945  else
946  {
947  LOG(VB_EIT, LOG_DEBUG, QString("Extracted S%1E%2/%3 from description (%4) \"%5\"")
948  .arg(event.m_season).arg(event.m_episode).arg(event.m_totalepisodes)
949  .arg(event.m_title, event.m_description));
950 
951  if (position2 == 0)
952  // Remove from the start of the description.
953  // Otherwise it ends up in the subtitle.
954  event.m_description.remove(tmpSeries.cap(form));
955  }
956  }
957 
958  if (isMovie)
959  event.m_categoryType = ProgramInfo::kCategoryMovie;
960  else if (series)
961  event.m_categoryType = ProgramInfo::kCategorySeries;
962 
963  // Multi-part episodes, or films (e.g. ITV film split by news)
964  // Matches Part 1, Pt 1/2, Part 1 of 2 etc.
965  QRegExp tmpPart = m_ukPart;
966  if ((position1 = tmpPart.indexIn(event.m_title)) != -1)
967  {
968  event.m_partnumber = tmpPart.cap(1).toUInt();
969  event.m_parttotal = tmpPart.cap(2).toUInt();
970 
971  LOG(VB_EIT, LOG_DEBUG, QString("Extracted Part %1/%2 from title (%3)")
972  .arg(event.m_partnumber).arg(event.m_parttotal).arg(event.m_title));
973 
974  // Remove from the title
975  event.m_title = event.m_title.remove(tmpPart.cap(0));
976  }
977  else if ((position1 = tmpPart.indexIn(event.m_description)) != -1)
978  {
979  event.m_partnumber = tmpPart.cap(1).toUInt();
980  event.m_parttotal = tmpPart.cap(2).toUInt();
981 
982  LOG(VB_EIT, LOG_DEBUG, QString("Extracted Part %1/%2 from description (%3) \"%4\"")
983  .arg(event.m_partnumber).arg(event.m_parttotal)
984  .arg(event.m_title, event.m_description));
985 
986  // Remove from the start of the description.
987  // Otherwise it ends up in the subtitle.
988  if (position1 == 0)
989  {
990  // Retain a single colon (subtitle separator) if we remove any
991  QString sub = tmpPart.cap(0).contains(":") ? ":" : "";
992  event.m_description = event.m_description.replace(tmpPart.cap(0), sub);
993  }
994  }
995 
996  QRegExp tmpStarring = m_ukStarring;
997  if (tmpStarring.indexIn(event.m_description) != -1)
998  {
999  // if we match this we've captured 2 actors and an (optional) airdate
1000  event.AddPerson(DBPerson::kActor, tmpStarring.cap(1));
1001  event.AddPerson(DBPerson::kActor, tmpStarring.cap(2));
1002  if (tmpStarring.cap(3).length() > 0)
1003  {
1004  bool ok;
1005  uint y = tmpStarring.cap(3).toUInt(&ok);
1006  if (ok)
1007  {
1008  event.m_airdate = y;
1009  event.m_originalairdate = QDate(y, 1, 1);
1010  }
1011  }
1012  }
1013 
1014  QRegExp tmp24ep = m_uk24ep;
1015  if (!event.m_title.startsWith("CSI:") && !event.m_title.startsWith("CD:") &&
1016  !event.m_title.contains(m_ukLaONoSplit) &&
1017  !event.m_title.startsWith("Mission: Impossible"))
1018  {
1019  if (((position1=event.m_title.indexOf(m_ukDoubleDotEnd)) != -1) &&
1020  ((position2=event.m_description.indexOf(m_ukDoubleDotStart)) != -1))
1021  {
1022  QString strPart=event.m_title.remove(m_ukDoubleDotEnd)+" ";
1023  strFull = strPart + event.m_description.remove(m_ukDoubleDotStart);
1024  if (isMovie &&
1025  ((position1 = strFull.indexOf(m_ukCEPQ,strPart.length())) != -1))
1026  {
1027  if (strFull[position1] == '!' || strFull[position1] == '?'
1028  || (position1>2 && strFull[position1] == '.' && strFull[position1-2] == '.'))
1029  position1++;
1030  event.m_title = strFull.left(position1);
1031  event.m_description = strFull.mid(position1 + 1);
1032  event.m_description.remove(m_ukSpaceStart);
1033  }
1034  else if ((position1 = strFull.indexOf(m_ukCEPQ)) != -1)
1035  {
1036  if (strFull[position1] == '!' || strFull[position1] == '?'
1037  || (position1>2 && strFull[position1] == '.' && strFull[position1-2] == '.'))
1038  position1++;
1039  event.m_title = strFull.left(position1);
1040  event.m_description = strFull.mid(position1 + 1);
1041  event.m_description.remove(m_ukSpaceStart);
1042  SetUKSubtitle(event);
1043  }
1044  if ((position1 = strFull.indexOf(m_ukYear)) != -1)
1045  {
1046  // Looks like they are using the airdate as a delimiter
1047  if ((uint)position1 < SUBTITLE_MAX_LEN)
1048  {
1049  event.m_description = event.m_title.mid(position1);
1050  event.m_title = event.m_title.left(position1);
1051  }
1052  }
1053  }
1054  else if ((position1 = tmp24ep.indexIn(event.m_description)) != -1)
1055  {
1056  // Special case for episodes of 24.
1057  // -2 from the length cause we don't want ": " on the end
1058  event.m_subtitle = event.m_description.mid(position1,
1059  tmp24ep.cap(0).length() - 2);
1060  event.m_description = event.m_description.remove(tmp24ep.cap(0));
1061  }
1062  else if ((position1 = event.m_description.indexOf(m_ukTime)) == -1)
1063  {
1064  if (!isMovie && (event.m_title.indexOf(m_ukYearColon) < 0))
1065  {
1066  if (((position1 = event.m_title.indexOf(":")) != -1) &&
1067  (event.m_description.indexOf(":") < 0 ))
1068  {
1069  if (event.m_title.mid(position1+1).indexOf(m_ukCompleteDots)==0)
1070  {
1071  SetUKSubtitle(event);
1072  QString strTmp = event.m_title.mid(position1+1);
1073  event.m_title.resize(position1);
1074  event.m_subtitle = strTmp+event.m_subtitle;
1075  }
1076  else if ((uint)position1 < SUBTITLE_MAX_LEN)
1077  {
1078  event.m_subtitle = event.m_title.mid(position1 + 1);
1079  event.m_title = event.m_title.left(position1);
1080  }
1081  }
1082  else
1083  SetUKSubtitle(event);
1084  }
1085  }
1086  }
1087 
1088  if (!isMovie && event.m_subtitle.isEmpty() &&
1089  !event.m_title.startsWith("The X-Files"))
1090  {
1091  if ((position1=event.m_description.indexOf(m_ukTime)) != -1)
1092  {
1093  position2 = event.m_description.indexOf(m_ukColonPeriod);
1094  if ((position2>=0) && (position2 < (position1-2)))
1095  SetUKSubtitle(event);
1096  }
1097  else if ((position1=event.m_title.indexOf("-")) != -1)
1098  {
1099  if ((uint)position1 < SUBTITLE_MAX_LEN)
1100  {
1101  event.m_subtitle = event.m_title.mid(position1 + 1);
1102  event.m_subtitle.remove(m_ukSpaceColonStart);
1103  event.m_title = event.m_title.left(position1);
1104  }
1105  }
1106  else
1107  SetUKSubtitle(event);
1108  }
1109 
1110  // Work out the year (if any)
1111  QRegExp tmpUKYear = m_ukYear;
1112  if ((position1 = tmpUKYear.indexIn(event.m_description)) != -1)
1113  {
1114  QString stmp = event.m_description;
1115  int itmp = position1 + tmpUKYear.cap(0).length();
1116  event.m_description = stmp.left(position1) + stmp.mid(itmp);
1117  bool ok;
1118  uint y = tmpUKYear.cap(1).toUInt(&ok);
1119  if (ok)
1120  {
1121  event.m_airdate = y;
1122  event.m_originalairdate = QDate(y, 1, 1);
1123  }
1124  }
1125 
1126  // Trim leading/trailing '.'
1127  event.m_subtitle.remove(m_ukDotSpaceStart);
1128  if (event.m_subtitle.lastIndexOf("..") != (event.m_subtitle.length()-2))
1129  event.m_subtitle.remove(m_ukDotEnd);
1130 
1131  // Reverse the subtitle and empty description
1132  if (event.m_description.isEmpty() && !event.m_subtitle.isEmpty())
1133  {
1134  event.m_description=event.m_subtitle;
1135  event.m_subtitle.clear();
1136  }
1137 }
1138 
1142 void EITFixUp::FixPBS(DBEventEIT &event) const
1143 {
1144  /* Used for PBS ATSC Subtitles are separated by a colon */
1145  int position = event.m_description.indexOf(':');
1146  if (position != -1)
1147  {
1148  const QString stmp = event.m_description;
1149  event.m_subtitle = stmp.left(position);
1150  event.m_description = stmp.right(stmp.length() - position - 2);
1151  }
1152 }
1153 
1157 void EITFixUp::FixComHem(DBEventEIT &event, bool process_subtitle) const
1158 {
1159  // Reverse what EITFixUp::Fix() did
1160  if (event.m_subtitle.isEmpty() && !event.m_description.isEmpty())
1161  {
1162  event.m_subtitle = event.m_description;
1163  event.m_description = "";
1164  }
1165 
1166  // Remove subtitle, it contains the category and we already know that
1167  event.m_subtitle = "";
1168 
1169  bool isSeries = false;
1170  // Try to find episode numbers
1171  int pos;
1172  QRegExp tmpSeries1 = m_comHemSeries1;
1173  QRegExp tmpSeries2 = m_comHemSeries2;
1174  if ((pos = tmpSeries2.indexIn(event.m_title)) != -1)
1175  {
1176  QStringList list = tmpSeries2.capturedTexts();
1177  event.m_partnumber = list[2].toUInt();
1178  event.m_title = event.m_title.replace(list[0],"");
1179  }
1180  else if ((pos = tmpSeries1.indexIn(event.m_description)) != -1)
1181  {
1182  QStringList list = tmpSeries1.capturedTexts();
1183  if (!list[1].isEmpty())
1184  {
1185  event.m_partnumber = list[1].toUInt();
1186  }
1187  if (!list[2].isEmpty())
1188  {
1189  event.m_parttotal = list[2].toUInt();
1190  }
1191 
1192  // Remove the episode numbers, but only if it's not at the begining
1193  // of the description (subtitle code might use it)
1194  if(pos > 0)
1195  event.m_description = event.m_description.replace(list[0],"");
1196  isSeries = true;
1197  }
1198 
1199  // Add partnumber/parttotal to subtitle
1200  // This will be overwritten if we find a better subtitle
1201  if (event.m_partnumber > 0)
1202  {
1203  event.m_subtitle = QString("Del %1").arg(event.m_partnumber);
1204  if (event.m_parttotal > 0)
1205  {
1206  event.m_subtitle += QString(" av %1").arg(event.m_parttotal);
1207  }
1208  }
1209 
1210  // Move subtitle info from title to subtitle
1211  QRegExp tmpTSub = m_comHemTSub;
1212  if (tmpTSub.indexIn(event.m_title) != -1)
1213  {
1214  event.m_subtitle = tmpTSub.cap(1);
1215  event.m_title = event.m_title.replace(tmpTSub.cap(0),"");
1216  }
1217 
1218  // No need to continue without a description.
1219  if (event.m_description.length() <= 0)
1220  return;
1221 
1222  // Try to find country category, year and possibly other information
1223  // from the begining of the description
1224  QRegExp tmpCountry = m_comHemCountry;
1225  pos = tmpCountry.indexIn(event.m_description);
1226  if (pos != -1)
1227  {
1228  QStringList list = tmpCountry.capturedTexts();
1229  QString replacement;
1230 
1231  // Original title, usually english title
1232  // note: list[1] contains extra () around the text that needs removing
1233  if (list[1].length() > 0)
1234  {
1235  replacement = list[1] + " ";
1236  //store it somewhere?
1237  }
1238 
1239  // Countr(y|ies)
1240  if (list[2].length() > 0)
1241  {
1242  replacement += list[2] + " ";
1243  //store it somewhere?
1244  }
1245 
1246  // Category
1247  if (list[3].length() > 0)
1248  {
1249  replacement += list[3] + ".";
1250  if(event.m_category.isEmpty())
1251  {
1252  event.m_category = list[3];
1253  }
1254 
1255  if(list[3].indexOf("serie")!=-1)
1256  {
1257  isSeries = true;
1258  }
1259  }
1260 
1261  // Year
1262  if (list[4].length() > 0)
1263  {
1264  bool ok;
1265  uint y = list[4].trimmed().toUInt(&ok);
1266  if (ok)
1267  event.m_airdate = y;
1268  }
1269 
1270  // Actors
1271  if (list[5].length() > 0)
1272  {
1273  const QStringList actors =
1274  list[5].split(m_comHemPersSeparator, QString::SkipEmptyParts);
1275  QStringList::const_iterator it = actors.begin();
1276  for (; it != actors.end(); ++it)
1277  event.AddPerson(DBPerson::kActor, *it);
1278  }
1279 
1280  // Remove year and actors.
1281  // The reason category is left in the description is because otherwise
1282  // the country would look wierd like "Amerikansk. Rest of description."
1283  event.m_description = event.m_description.replace(list[0],replacement);
1284  }
1285 
1286  if (isSeries)
1287  event.m_categoryType = ProgramInfo::kCategorySeries;
1288 
1289  // Look for additional persons in the description
1290  QRegExp tmpPersons = m_comHemPersons;
1291  while(pos = tmpPersons.indexIn(event.m_description),pos!=-1)
1292  {
1293  DBPerson::Role role;
1294  QStringList list = tmpPersons.capturedTexts();
1295 
1296  QRegExp tmpDirector = m_comHemDirector;
1297  QRegExp tmpActor = m_comHemActor;
1298  QRegExp tmpHost = m_comHemHost;
1299  if (tmpDirector.indexIn(list[1])!=-1)
1300  {
1301  role = DBPerson::kDirector;
1302  }
1303  else if(tmpActor.indexIn(list[1])!=-1)
1304  {
1305  role = DBPerson::kActor;
1306  }
1307  else if(tmpHost.indexIn(list[1])!=-1)
1308  {
1309  role = DBPerson::kHost;
1310  }
1311  else
1312  {
1313  event.m_description=event.m_description.replace(list[0],"");
1314  continue;
1315  }
1316 
1317  const QStringList actors =
1318  list[2].split(m_comHemPersSeparator, QString::SkipEmptyParts);
1319  QStringList::const_iterator it = actors.begin();
1320  for (; it != actors.end(); ++it)
1321  event.AddPerson(role, *it);
1322 
1323  // Remove it
1324  event.m_description=event.m_description.replace(list[0],"");
1325  }
1326 
1327  // Is this event on a channel we shoud look for a subtitle?
1328  // The subtitle is the first sentence in the description, but the
1329  // subtitle can't be the only thing in the description and it must be
1330  // shorter than 55 characters or we risk picking up the wrong thing.
1331  if (process_subtitle)
1332  {
1333  int pos2 = event.m_description.indexOf(m_comHemSub);
1334  bool pvalid = pos2 != -1 && pos2 <= 55;
1335  if (pvalid && (event.m_description.length() - (pos2 + 2)) > 0)
1336  {
1337  event.m_subtitle = event.m_description.left(
1338  pos2 + (event.m_description[pos2] == '?' ? 1 : 0));
1339  event.m_description = event.m_description.mid(pos2 + 2);
1340  }
1341  }
1342 
1343  // Teletext subtitles?
1344  int position = event.m_description.indexOf(m_comHemTT);
1345  if (position != -1)
1346  {
1347  event.m_subtitleType |= SUB_NORMAL;
1348  }
1349 
1350  // Try to findout if this is a rerun and if so the date.
1351  QRegExp tmpRerun1 = m_comHemRerun1;
1352  if (tmpRerun1.indexIn(event.m_description) == -1)
1353  return;
1354 
1355  // Rerun from today
1356  QStringList list = tmpRerun1.capturedTexts();
1357  if (list[1] == "i dag")
1358  {
1359  event.m_originalairdate = event.m_starttime.date();
1360  return;
1361  }
1362 
1363  // Rerun from yesterday afternoon
1364  if (list[1] == "eftermiddagen")
1365  {
1366  event.m_originalairdate = event.m_starttime.date().addDays(-1);
1367  return;
1368  }
1369 
1370  // Rerun with day, month and possibly year specified
1371  QRegExp tmpRerun2 = m_comHemRerun2;
1372  if (tmpRerun2.indexIn(list[1]) != -1)
1373  {
1374  QStringList datelist = tmpRerun2.capturedTexts();
1375  int day = datelist[1].toInt();
1376  int month = datelist[2].toInt();
1377  //int year;
1378 
1379  //if (datelist[3].length() > 0)
1380  // year = datelist[3].toInt();
1381  //else
1382  // year = event.m_starttime.date().year();
1383 
1384  if (day > 0 && month > 0)
1385  {
1386  QDate date(event.m_starttime.date().year(), month, day);
1387  // it's a rerun so it must be in the past
1388  if (date > event.m_starttime.date())
1389  date = date.addYears(-1);
1390  event.m_originalairdate = date;
1391  }
1392  return;
1393  }
1394 }
1395 
1400 {
1401  event.m_category = event.m_subtitle;
1402  /* Used for DVB-S Subtitles are separated by a colon */
1403  int position = event.m_description.indexOf(':');
1404  if (position != -1)
1405  {
1406  const QString stmp = event.m_description;
1407  event.m_subtitle = stmp.left(position);
1408  event.m_description = stmp.right(stmp.length() - position - 2);
1409  }
1410 }
1411 
1416 {
1417  if (event.m_description.startsWith("[Program data ") || event.m_description.startsWith("[Program info "))//TEN
1418  {
1419  event.m_description = "";//event.m_subtitle;
1420  }
1421  if (event.m_description.endsWith("Copyright West TV Ltd. 2011)"))
1422  event.m_description.resize(event.m_description.length()-40);
1423 
1424  if (event.m_description.isEmpty() && !event.m_subtitle.isEmpty())//due to ten's copyright info, this won't be caught before
1425  {
1426  event.m_description = event.m_subtitle;
1427  event.m_subtitle.clear();
1428  }
1429  if (event.m_description.startsWith(event.m_title+" - "))
1430  event.m_description.remove(0,event.m_title.length()+3);
1431  if (event.m_title.startsWith("LIVE: ", Qt::CaseInsensitive))
1432  {
1433  event.m_title.remove(0, 6);
1434  event.m_description.prepend("(Live) ");
1435  }
1436 }
1441 {
1442  QRegExp rating("\\((G|PG|M|MA)\\)");
1443  if (rating.indexIn(event.m_description) == 0)
1444  {
1445  EventRating prograting;
1446  prograting.m_system="AU"; prograting.m_rating = rating.cap(1);
1447  event.m_ratings.push_back(prograting);
1448  event.m_description.remove(0,rating.matchedLength()+1);
1449  }
1450  if (event.m_description.startsWith("[HD]"))
1451  {
1452  event.m_videoProps |= VID_HDTV;
1453  event.m_description.remove(0,5);
1454  }
1455  if (event.m_description.startsWith("[CC]"))
1456  {
1457  event.m_subtitleType |= SUB_NORMAL;
1458  event.m_description.remove(0,5);
1459  }
1460  if (event.m_subtitle == "Movie")
1461  {
1462  event.m_subtitle.clear();
1463  event.m_categoryType = ProgramInfo::kCategoryMovie;
1464  }
1465  if (event.m_description.startsWith(event.m_title))
1466  event.m_description.remove(0,event.m_title.length()+1);
1467 }
1472 {
1473  if (event.m_description.endsWith(" Rpt"))
1474  {
1475  event.m_previouslyshown = true;
1476  event.m_description.resize(event.m_description.size()-4);
1477  }
1478  QRegExp year("(\\d{4})$");
1479  if (year.indexIn(event.m_description) != -1)
1480  {
1481  event.m_airdate = year.cap(3).toUInt();
1482  event.m_description.resize(event.m_description.size()-5);
1483  }
1484  if (event.m_description.endsWith(" CC"))
1485  {
1486  event.m_subtitleType |= SUB_NORMAL;
1487  event.m_description.resize(event.m_description.size()-3);
1488  }
1489  QString advisories;//store the advisories to append later
1490  QRegExp adv("(\\([A-Z,]+\\))$");
1491  if (adv.indexIn(event.m_description) != -1)
1492  {
1493  advisories = adv.cap(1);
1494  event.m_description.resize(event.m_description.size()-(adv.matchedLength()+1));
1495  }
1496  QRegExp rating("(C|G|PG|M|MA)$");
1497  if (rating.indexIn(event.m_description) != -1)
1498  {
1499  EventRating prograting;
1500  prograting.m_system=""; prograting.m_rating = rating.cap(1);
1501  if (!advisories.isEmpty())
1502  prograting.m_rating.append(" ").append(advisories);
1503  event.m_ratings.push_back(prograting);
1504  event.m_description.resize(event.m_description.size()-(rating.matchedLength()+1));
1505  }
1506 }
1511 {
1512  if (event.m_description.endsWith(".."))//has been truncated to fit within the 'subtitle' eit field, so none of the following will work (ABC)
1513  return;
1514 
1515  if (m_AUFreeviewSY.indexIn(event.m_description.trimmed(), 0) != -1)
1516  {
1517  if (event.m_subtitle.isEmpty())//nine sometimes has an actual subtitle field and the brackets thingo)
1518  event.m_subtitle = m_AUFreeviewSY.cap(2);
1519  event.m_airdate = m_AUFreeviewSY.cap(3).toUInt();
1520  event.m_description = m_AUFreeviewSY.cap(1);
1521  }
1522  else if (m_AUFreeviewY.indexIn(event.m_description.trimmed(), 0) != -1)
1523  {
1524  event.m_airdate = m_AUFreeviewY.cap(2).toUInt();
1525  event.m_description = m_AUFreeviewY.cap(1);
1526  }
1527  else if (m_AUFreeviewSYC.indexIn(event.m_description.trimmed(), 0) != -1)
1528  {
1529  if (event.m_subtitle.isEmpty())
1530  event.m_subtitle = m_AUFreeviewSYC.cap(2);
1531  event.m_airdate = m_AUFreeviewSYC.cap(3).toUInt();
1532  QStringList actors = m_AUFreeviewSYC.cap(4).split("/");
1533  for (int i = 0; i < actors.size(); ++i)
1534  event.AddPerson(DBPerson::kActor, actors.at(i));
1535  event.m_description = m_AUFreeviewSYC.cap(1);
1536  }
1537  else if (m_AUFreeviewYC.indexIn(event.m_description.trimmed(), 0) != -1)
1538  {
1539  event.m_airdate = m_AUFreeviewYC.cap(2).toUInt();
1540  QStringList actors = m_AUFreeviewYC.cap(3).split("/");
1541  for (int i = 0; i < actors.size(); ++i)
1542  event.AddPerson(DBPerson::kActor, actors.at(i));
1543  event.m_description = m_AUFreeviewYC.cap(1);
1544  }
1545 }
1546 
1550 void EITFixUp::FixMCA(DBEventEIT &event) const
1551 {
1552  const uint SUBTITLE_PCT = 60; // % of description to allow subtitle to
1553  const uint lSUBTITLE_MAX_LEN = 128;// max length of subtitle field in db.
1554  int position;
1555  QRegExp tmpExp1;
1556 
1557  // Remove subtitle, it contains category information too specific to use
1558  event.m_subtitle = QString("");
1559 
1560  // No need to continue without a description.
1561  if (event.m_description.length() <= 0)
1562  return;
1563 
1564  // Replace incomplete title if the full one is in the description
1565  tmpExp1 = m_mcaIncompleteTitle;
1566  if (tmpExp1.indexIn(event.m_title) != -1)
1567  {
1568  tmpExp1 = QRegExp( m_mcaCompleteTitlea.pattern() + tmpExp1.cap(1) +
1569  m_mcaCompleteTitleb.pattern());
1570  tmpExp1.setCaseSensitivity(Qt::CaseInsensitive);
1571  if (tmpExp1.indexIn(event.m_description) != -1)
1572  {
1573  event.m_title = tmpExp1.cap(1).trimmed();
1574  event.m_description = tmpExp1.cap(2).trimmed();
1575  }
1576  tmpExp1.setCaseSensitivity(Qt::CaseSensitive);
1577  }
1578 
1579  // Try to find subtitle in description
1580  tmpExp1 = m_mcaSubtitle;
1581  if ((position = tmpExp1.indexIn(event.m_description)) != -1)
1582  {
1583  uint tmpExp1Len = tmpExp1.cap(1).length();
1584  uint evDescLen = max(event.m_description.length(), 1);
1585 
1586  if ((tmpExp1Len < lSUBTITLE_MAX_LEN) &&
1587  ((tmpExp1Len * 100 / evDescLen) < SUBTITLE_PCT))
1588  {
1589  event.m_subtitle = tmpExp1.cap(1);
1590  event.m_description = tmpExp1.cap(2);
1591  }
1592  }
1593 
1594  // Try to find episode numbers in subtitle
1595  tmpExp1 = m_mcaSeries;
1596  if ((position = tmpExp1.indexIn(event.m_subtitle)) != -1)
1597  {
1598  uint season = tmpExp1.cap(1).toUInt();
1599  uint episode = tmpExp1.cap(2).toUInt();
1600  event.m_subtitle = tmpExp1.cap(3).trimmed();
1601  event.m_syndicatedepisodenumber =
1602  QString("S%1E%2").arg(season).arg(episode);
1603  event.m_season = season;
1604  event.m_episode = episode;
1605  event.m_categoryType = ProgramInfo::kCategorySeries;
1606  }
1607 
1608  // Close captioned?
1609  position = event.m_description.indexOf(m_mcaCC);
1610  if (position > 0)
1611  {
1612  event.m_subtitleType |= SUB_HARDHEAR;
1613  event.m_description.replace(m_mcaCC, "");
1614  }
1615 
1616  // Dolby Digital 5.1?
1617  position = event.m_description.indexOf(m_mcaDD);
1618  if ((position > 0) && (position > event.m_description.length() - 7))
1619  {
1620  event.m_audioProps |= AUD_DOLBY;
1621  event.m_description.replace(m_mcaDD, "");
1622  }
1623 
1624  // Remove bouquet tags
1625  event.m_description.replace(m_mcaAvail, "");
1626 
1627  // Try to find year and director from the end of the description
1628  bool isMovie = false;
1629  tmpExp1 = m_mcaCredits;
1630  position = tmpExp1.indexIn(event.m_description);
1631  if (position != -1)
1632  {
1633  isMovie = true;
1634  event.m_description = tmpExp1.cap(1).trimmed();
1635  bool ok;
1636  uint y = tmpExp1.cap(2).trimmed().toUInt(&ok);
1637  if (ok)
1638  event.m_airdate = y;
1639  event.AddPerson(DBPerson::kDirector, tmpExp1.cap(3).trimmed());
1640  }
1641  else
1642  {
1643  // Try to find year only from the end of the description
1644  tmpExp1 = m_mcaYear;
1645  position = tmpExp1.indexIn(event.m_description);
1646  if (position != -1)
1647  {
1648  isMovie = true;
1649  event.m_description = tmpExp1.cap(1).trimmed();
1650  bool ok;
1651  uint y = tmpExp1.cap(2).trimmed().toUInt(&ok);
1652  if (ok)
1653  event.m_airdate = y;
1654  }
1655  }
1656 
1657  if (isMovie)
1658  {
1659  tmpExp1 = m_mcaActors;
1660  position = tmpExp1.indexIn(event.m_description);
1661  if (position != -1)
1662  {
1663  const QStringList actors = tmpExp1.cap(2).split(
1664  m_mcaActorsSeparator, QString::SkipEmptyParts);
1665  QStringList::const_iterator it = actors.begin();
1666  for (; it != actors.end(); ++it)
1667  event.AddPerson(DBPerson::kActor, (*it).trimmed());
1668  event.m_description = tmpExp1.cap(1).trimmed();
1669  }
1670  event.m_categoryType = ProgramInfo::kCategoryMovie;
1671  }
1672 
1673 }
1674 
1678 void EITFixUp::FixRTL(DBEventEIT &event) const
1679 {
1680  int pos;
1681 
1682  // No need to continue without a description or with an subtitle.
1683  if (event.m_description.length() <= 0 || event.m_subtitle.length() > 0)
1684  return;
1685 
1686  // Repeat
1687  QRegExp tmpExpRepeat = m_RTLrepeat;
1688  if ((pos = tmpExpRepeat.indexIn(event.m_description)) != -1)
1689  {
1690  // remove '.' if it matches at the beginning of the description
1691  int length = tmpExpRepeat.cap(0).length() + (pos ? 0 : 1);
1692  event.m_description = event.m_description.remove(pos, length).trimmed();
1693  }
1694 
1695  QRegExp tmpExp1 = m_RTLSubtitle;
1696  QRegExp tmpExpSubtitle1 = m_RTLSubtitle1;
1697  tmpExpSubtitle1.setMinimal(true);
1698  QRegExp tmpExpSubtitle2 = m_RTLSubtitle2;
1699  QRegExp tmpExpSubtitle3 = m_RTLSubtitle3;
1700  QRegExp tmpExpSubtitle4 = m_RTLSubtitle4;
1701  QRegExp tmpExpSubtitle5 = m_RTLSubtitle5;
1702  tmpExpSubtitle5.setMinimal(true);
1703  QRegExp tmpExpEpisodeNo1 = m_RTLEpisodeNo1;
1704  QRegExp tmpExpEpisodeNo2 = m_RTLEpisodeNo2;
1705 
1706  // subtitle with episode number: "Folge *: 'subtitle'. description
1707  if (tmpExpSubtitle1.indexIn(event.m_description) != -1)
1708  {
1709  event.m_syndicatedepisodenumber = tmpExpSubtitle1.cap(1);
1710  event.m_subtitle = tmpExpSubtitle1.cap(2);
1711  event.m_description =
1712  event.m_description.remove(0, tmpExpSubtitle1.matchedLength());
1713  }
1714  // episode number subtitle
1715  else if (tmpExpSubtitle2.indexIn(event.m_description) != -1)
1716  {
1717  event.m_syndicatedepisodenumber = tmpExpSubtitle2.cap(1);
1718  event.m_subtitle = tmpExpSubtitle2.cap(2);
1719  event.m_description =
1720  event.m_description.remove(0, tmpExpSubtitle2.matchedLength());
1721  }
1722  // episode number subtitle
1723  else if (tmpExpSubtitle3.indexIn(event.m_description) != -1)
1724  {
1725  event.m_syndicatedepisodenumber = tmpExpSubtitle3.cap(1);
1726  event.m_subtitle = tmpExpSubtitle3.cap(2);
1727  event.m_description =
1728  event.m_description.remove(0, tmpExpSubtitle3.matchedLength());
1729  }
1730  // "Thema..."
1731  else if (tmpExpSubtitle4.indexIn(event.m_description) != -1)
1732  {
1733  event.m_subtitle = tmpExpSubtitle4.cap(1);
1734  event.m_description =
1735  event.m_description.remove(0, tmpExpSubtitle4.matchedLength());
1736  }
1737  // "'...'"
1738  else if (tmpExpSubtitle5.indexIn(event.m_description) != -1)
1739  {
1740  event.m_subtitle = tmpExpSubtitle5.cap(1);
1741  event.m_description =
1742  event.m_description.remove(0, tmpExpSubtitle5.matchedLength());
1743  }
1744  // episode number
1745  else if (tmpExpEpisodeNo1.indexIn(event.m_description) != -1)
1746  {
1747  event.m_syndicatedepisodenumber = tmpExpEpisodeNo1.cap(2);
1748  event.m_subtitle = tmpExpEpisodeNo1.cap(1);
1749  event.m_description =
1750  event.m_description.remove(0, tmpExpEpisodeNo1.matchedLength());
1751  }
1752  // episode number
1753  else if (tmpExpEpisodeNo2.indexIn(event.m_description) != -1)
1754  {
1755  event.m_syndicatedepisodenumber = tmpExpEpisodeNo2.cap(2);
1756  event.m_subtitle = tmpExpEpisodeNo2.cap(1);
1757  event.m_description =
1758  event.m_description.remove(0, tmpExpEpisodeNo2.matchedLength());
1759  }
1760 
1761  /* got an episode title now? (we did not have one at the start of this function) */
1762  if (!event.m_subtitle.isEmpty())
1763  {
1764  event.m_categoryType = ProgramInfo::kCategorySeries;
1765  }
1766 
1767  /* if we do not have an episode title by now try some guessing as last resort */
1768  if (event.m_subtitle.length() == 0)
1769  {
1770  const uint SUBTITLE_PCT = 35; // % of description to allow subtitle up to
1771  const uint lSUBTITLE_MAX_LEN = 50; // max length of subtitle field in db
1772 
1773  if (tmpExp1.indexIn(event.m_description) != -1)
1774  {
1775  uint tmpExp1Len = tmpExp1.cap(1).length();
1776  uint evDescLen = max(event.m_description.length(), 1);
1777 
1778  if ((tmpExp1Len < lSUBTITLE_MAX_LEN) &&
1779  (tmpExp1Len * 100 / evDescLen < SUBTITLE_PCT))
1780  {
1781  event.m_subtitle = tmpExp1.cap(1);
1782  event.m_description = tmpExp1.cap(2);
1783  }
1784  }
1785  }
1786 }
1787 
1791 void EITFixUp::FixPRO7(DBEventEIT &event) const
1792 {
1793  QRegExp tmp = m_PRO7Subtitle;
1794 
1795  int pos = tmp.indexIn(event.m_subtitle);
1796  if (pos != -1)
1797  {
1798  if (event.m_airdate == 0)
1799  {
1800  event.m_airdate = tmp.cap(3).toUInt();
1801  }
1802  event.m_subtitle.replace(tmp, "");
1803  }
1804 
1805  /* handle cast, the very last in description */
1806  tmp = m_PRO7Cast;
1807  pos = tmp.indexIn(event.m_description);
1808  if (pos != -1)
1809  {
1810  QStringList cast = tmp.cap(1).split("\n");
1811  QRegExp tmpOne = m_PRO7CastOne;
1812  QStringListIterator i(cast);
1813  while (i.hasNext())
1814  {
1815  pos = tmpOne.indexIn (i.next());
1816  if (pos != -1)
1817  {
1818  event.AddPerson (DBPerson::kActor, tmpOne.cap(1).simplified());
1819  }
1820  }
1821  event.m_description.replace(tmp, "");
1822  }
1823 
1824  /* handle crew, the new very last in description
1825  * format: "Role: Name" or "Role: Name1, Name2"
1826  */
1827  tmp = m_PRO7Crew;
1828  pos = tmp.indexIn(event.m_description);
1829  if (pos != -1)
1830  {
1831  QStringList crew = tmp.cap(1).split("\n");
1832  QRegExp tmpOne = m_PRO7CrewOne;
1833  QStringListIterator i(crew);
1834  while (i.hasNext())
1835  {
1836  pos = tmpOne.indexIn (i.next());
1837  if (pos != -1)
1838  {
1840  if (QString::compare (tmpOne.cap(1), "Regie") == 0)
1841  {
1842  role = DBPerson::kDirector;
1843  }
1844  else if (QString::compare (tmpOne.cap(1), "Drehbuch") == 0)
1845  {
1846  role = DBPerson::kWriter;
1847  }
1848  else if (QString::compare (tmpOne.cap(1), "Autor") == 0)
1849  {
1850  role = DBPerson::kWriter;
1851  }
1852  // FIXME add more jobs
1853 
1854  QStringList names = tmpOne.cap(2).simplified().split("\\s*,\\s*");
1855  QStringListIterator j(names);
1856  while (j.hasNext())
1857  {
1858  event.AddPerson (role, j.next());
1859  }
1860  }
1861  }
1862  event.m_description.replace(tmp, "");
1863  }
1864 
1865  /* FIXME unless its Jamie Oliver, then there is neither Crew nor Cast only
1866  * \n\nKoch: Jamie Oliver
1867  */
1868 }
1869 
1874 {
1875  QRegExp tmp = m_DisneyChannelSubtitle;
1876  int pos = tmp.indexIn(event.m_subtitle);
1877  if (pos != -1)
1878  {
1879  if (event.m_airdate == 0)
1880  {
1881  event.m_airdate = tmp.cap(3).toUInt();
1882  }
1883  event.m_subtitle.replace(tmp, "");
1884  }
1885  tmp = QRegExp("\\s[^\\s]+-(Serie)");
1886  pos = tmp.indexIn(event.m_subtitle);
1887  if (pos != -1)
1888  {
1889  event.m_categoryType = ProgramInfo::kCategorySeries;
1890  event.m_category=tmp.cap(0).trimmed();
1891  event.m_subtitle.replace(tmp, "");
1892  }
1893 }
1894 
1898 void EITFixUp::FixATV(DBEventEIT &event) const
1899 {
1900  event.m_subtitle.replace(m_ATVSubtitle, "");
1901 }
1902 
1903 
1907 void EITFixUp::FixFI(DBEventEIT &event) const
1908 {
1909  int position = event.m_description.indexOf(m_fiRerun);
1910  if (position != -1)
1911  {
1912  event.m_previouslyshown = true;
1913  event.m_description = event.m_description.replace(m_fiRerun, "");
1914  }
1915 
1916  position = event.m_description.indexOf(m_fiRerun2);
1917  if (position != -1)
1918  {
1919  event.m_previouslyshown = true;
1920  event.m_description = event.m_description.replace(m_fiRerun2, "");
1921  }
1922 
1923  // Check for (Stereo) in the decription and set the <audio> tags
1924  position = event.m_description.indexOf(m_Stereo);
1925  if (position != -1)
1926  {
1927  event.m_audioProps |= AUD_STEREO;
1928  event.m_description = event.m_description.replace(m_Stereo, "");
1929  }
1930 
1931  // Remove age limit in parenthesis at end of title
1932  position = event.m_title.indexOf(m_fiAgeLimit);
1933  if (position != -1)
1934  {
1935  event.m_title = event.m_title.replace(m_fiAgeLimit, "");
1936  }
1937 
1938  // Remove Film or Elokuva at start of title
1939  position = event.m_title.indexOf(m_fiFilm);
1940  if (position != -1)
1941  {
1942  event.m_title = event.m_title.replace(m_fiFilm, "");
1943  }
1944 
1945 }
1946 
1952 {
1953  QString country = "";
1954 
1955  QRegExp tmplength = m_dePremiereLength;
1956  QRegExp tmpairdate = m_dePremiereAirdate;
1957  QRegExp tmpcredits = m_dePremiereCredits;
1958 
1959  event.m_description = event.m_description.replace(tmplength, "");
1960 
1961  if (tmpairdate.indexIn(event.m_description) != -1)
1962  {
1963  country = tmpairdate.cap(1).trimmed();
1964  bool ok;
1965  uint y = tmpairdate.cap(2).toUInt(&ok);
1966  if (ok)
1967  event.m_airdate = y;
1968  event.m_description = event.m_description.replace(tmpairdate, "");
1969  }
1970 
1971  if (tmpcredits.indexIn(event.m_description) != -1)
1972  {
1973  event.AddPerson(DBPerson::kDirector, tmpcredits.cap(1));
1974  const QStringList actors = tmpcredits.cap(2).split(
1975  ", ", QString::SkipEmptyParts);
1976  QStringList::const_iterator it = actors.begin();
1977  for (; it != actors.end(); ++it)
1978  event.AddPerson(DBPerson::kActor, *it);
1979  event.m_description = event.m_description.replace(tmpcredits, "");
1980  }
1981 
1982  event.m_description = event.m_description.replace("\u000A$", "");
1983  event.m_description = event.m_description.replace("\u000A", " ");
1984 
1985  // move the original titel from the title to subtitle
1986  QRegExp tmpOTitle = m_dePremiereOTitle;
1987  if (tmpOTitle.indexIn(event.m_title) != -1)
1988  {
1989  event.m_subtitle = QString("%1, %2").arg(tmpOTitle.cap(1)).arg(country);
1990  event.m_title = event.m_title.replace(tmpOTitle, "");
1991  }
1992 
1993  // Find infos about season and episode number
1994  QRegExp tmpSeasonEpisode = m_deSkyDescriptionSeasonEpisode;
1995  if (tmpSeasonEpisode.indexIn(event.m_description) != -1)
1996  {
1997  event.m_season = tmpSeasonEpisode.cap(1).trimmed().toUInt();
1998  event.m_episode = tmpSeasonEpisode.cap(2).trimmed().toUInt();
1999  event.m_description.replace(tmpSeasonEpisode, "");
2000  }
2001 }
2002 
2006 void EITFixUp::FixNL(DBEventEIT &event) const
2007 {
2008  QString fullinfo = "";
2009  fullinfo.append (event.m_subtitle);
2010  fullinfo.append (event.m_description);
2011  event.m_subtitle = "";
2012 
2013  // Convert categories to Dutch categories Myth knows.
2014  // nog invoegen: comedy, sport, misdaad
2015 
2016  if (event.m_category == "Documentary")
2017  {
2018  event.m_category = "Documentaire";
2019  event.m_categoryType = ProgramInfo::kCategoryNone;
2020  }
2021  if (event.m_category == "News")
2022  {
2023  event.m_category = "Nieuws/actualiteiten";
2024  event.m_categoryType = ProgramInfo::kCategoryNone;
2025  }
2026  if (event.m_category == "Kids")
2027  {
2028  event.m_category = "Jeugd";
2029  event.m_categoryType = ProgramInfo::kCategoryNone;
2030  }
2031  if (event.m_category == "Show/game Show")
2032  {
2033  event.m_category = "Amusement";
2034  event.m_categoryType = ProgramInfo::kCategoryTVShow;
2035  }
2036  if (event.m_category == "Music/Ballet/Dance")
2037  {
2038  event.m_category = "Muziek";
2039  event.m_categoryType = ProgramInfo::kCategoryNone;
2040  }
2041  if (event.m_category == "News magazine")
2042  {
2043  event.m_category = "Informatief";
2044  event.m_categoryType = ProgramInfo::kCategoryNone;
2045  }
2046  if (event.m_category == "Movie")
2047  {
2048  event.m_category = "Film";
2049  event.m_categoryType = ProgramInfo::kCategoryMovie;
2050  }
2051  if (event.m_category == "Nature/animals/Environment")
2052  {
2053  event.m_category = "Natuur";
2054  event.m_categoryType = ProgramInfo::kCategoryNone;
2055  }
2056  if (event.m_category == "Movie - Adult")
2057  {
2058  event.m_category = "Erotiek";
2059  event.m_categoryType = ProgramInfo::kCategoryNone;
2060  }
2061  if (event.m_category == "Movie - Soap/melodrama/folkloric")
2062  {
2063  event.m_category = "Serie/soap";
2064  event.m_categoryType = ProgramInfo::kCategorySeries;
2065  }
2066  if (event.m_category == "Arts/Culture")
2067  {
2068  event.m_category = "Kunst/Cultuur";
2069  event.m_categoryType = ProgramInfo::kCategoryNone;
2070  }
2071  if (event.m_category == "Sports")
2072  {
2073  event.m_category = "Sport";
2074  event.m_categoryType = ProgramInfo::kCategorySports;
2075  }
2076  if (event.m_category == "Cartoons/Puppets")
2077  {
2078  event.m_category = "Animatie";
2079  event.m_categoryType = ProgramInfo::kCategoryNone;
2080  }
2081  if (event.m_category == "Movie - Comedy")
2082  {
2083  event.m_category = "Comedy";
2084  event.m_categoryType = ProgramInfo::kCategorySeries;
2085  }
2086  if (event.m_category == "Movie - Detective/Thriller")
2087  {
2088  event.m_category = "Misdaad";
2089  event.m_categoryType = ProgramInfo::kCategoryNone;
2090  }
2091  if (event.m_category == "Social/Spiritual Sciences")
2092  {
2093  event.m_category = "Religieus";
2094  event.m_categoryType = ProgramInfo::kCategoryNone;
2095  }
2096 
2097  // Film - categories are usually not Films
2098  if (event.m_category.startsWith("Film -"))
2099  {
2100  event.m_categoryType = ProgramInfo::kCategorySeries;
2101  }
2102 
2103  // Get stereo info
2104  if (fullinfo.indexOf(m_Stereo) != -1)
2105  {
2106  event.m_audioProps |= AUD_STEREO;
2107  fullinfo = fullinfo.replace(m_Stereo, ".");
2108  }
2109 
2110  //Get widescreen info
2111  if (fullinfo.indexOf(m_nlWide) != -1)
2112  {
2113  fullinfo = fullinfo.replace("breedbeeld", ".");
2114  }
2115 
2116  // Get repeat info
2117  if (fullinfo.indexOf(m_nlRepeat) != -1)
2118  {
2119  fullinfo = fullinfo.replace("herh.", ".");
2120  }
2121 
2122  // Get teletext subtitle info
2123  if (fullinfo.indexOf(m_nlTxt) != -1)
2124  {
2125  event.m_subtitleType |= SUB_NORMAL;
2126  fullinfo = fullinfo.replace("txt", ".");
2127  }
2128 
2129  // Get HDTV information
2130  if (event.m_title.indexOf(m_nlHD) != -1)
2131  {
2132  event.m_videoProps |= VID_HDTV;
2133  event.m_title = event.m_title.replace(m_nlHD, "");
2134  }
2135 
2136  // Try to make subtitle from Afl.:
2137  QRegExp tmpSub = m_nlSub;
2138  QString tmpSubString;
2139  if (tmpSub.indexIn(fullinfo) != -1)
2140  {
2141  tmpSubString = tmpSub.cap(0);
2142  tmpSubString = tmpSubString.right(tmpSubString.length() - 7);
2143  event.m_subtitle = tmpSubString.left(tmpSubString.length() -1);
2144  fullinfo = fullinfo.replace(tmpSub.cap(0), "");
2145  }
2146 
2147  // Try to make subtitle from " "
2148  QRegExp tmpSub2 = m_nlSub2;
2149  //QString tmpSubString2;
2150  if (tmpSub2.indexIn(fullinfo) != -1)
2151  {
2152  tmpSubString = tmpSub2.cap(0);
2153  tmpSubString = tmpSubString.right(tmpSubString.length() - 2);
2154  event.m_subtitle = tmpSubString.left(tmpSubString.length() -1);
2155  fullinfo = fullinfo.replace(tmpSub2.cap(0), "");
2156  }
2157 
2158 
2159  // This is trying to catch the case where the subtitle is in the main title
2160  // but avoid cases where it isn't a subtitle e.g cd:uk
2161  int position;
2162  if (((position = event.m_title.indexOf(":")) != -1) &&
2163  (event.m_title[position + 1].toUpper() == event.m_title[position + 1]) &&
2164  (event.m_subtitle.isEmpty()))
2165  {
2166  event.m_subtitle = event.m_title.mid(position + 1);
2167  event.m_title = event.m_title.left(position);
2168  }
2169 
2170 
2171  // Get the actors
2172  QRegExp tmpActors = m_nlActors;
2173  if (tmpActors.indexIn(fullinfo) != -1)
2174  {
2175  QString tmpActorsString = tmpActors.cap(0);
2176  tmpActorsString = tmpActorsString.right(tmpActorsString.length() - 6);
2177  tmpActorsString = tmpActorsString.left(tmpActorsString.length() - 5);
2178  const QStringList actors =
2179  tmpActorsString.split(", ", QString::SkipEmptyParts);
2180  QStringList::const_iterator it = actors.begin();
2181  for (; it != actors.end(); ++it)
2182  event.AddPerson(DBPerson::kActor, *it);
2183  fullinfo = fullinfo.replace(tmpActors.cap(0), "");
2184  }
2185 
2186  // Try to find presenter
2187  QRegExp tmpPres = m_nlPres;
2188  if (tmpPres.indexIn(fullinfo) != -1)
2189  {
2190  QString tmpPresString = tmpPres.cap(0);
2191  tmpPresString = tmpPresString.right(tmpPresString.length() - 14);
2192  tmpPresString = tmpPresString.left(tmpPresString.length() -1);
2193  const QStringList host =
2194  tmpPresString.split(m_nlPersSeparator, QString::SkipEmptyParts);
2195  QStringList::const_iterator it = host.begin();
2196  for (; it != host.end(); ++it)
2197  event.AddPerson(DBPerson::kPresenter, *it);
2198  fullinfo = fullinfo.replace(tmpPres.cap(0), "");
2199  }
2200 
2201  // Try to find year
2202  QRegExp tmpYear1 = m_nlYear1;
2203  QRegExp tmpYear2 = m_nlYear2;
2204  if (tmpYear1.indexIn(fullinfo) != -1)
2205  {
2206  bool ok;
2207  uint y = tmpYear1.cap(0).toUInt(&ok);
2208  if (ok)
2209  event.m_originalairdate = QDate(y, 1, 1);
2210  }
2211 
2212  if (tmpYear2.indexIn(fullinfo) != -1)
2213  {
2214  bool ok;
2215  uint y = tmpYear2.cap(2).toUInt(&ok);
2216  if (ok)
2217  event.m_originalairdate = QDate(y, 1, 1);
2218  }
2219 
2220  // Try to find director
2221  QRegExp tmpDirector = m_nlDirector;
2222  QString tmpDirectorString;
2223  if (fullinfo.indexOf(m_nlDirector) != -1)
2224  {
2225  tmpDirectorString = tmpDirector.cap(0);
2226  event.AddPerson(DBPerson::kDirector, tmpDirectorString);
2227  }
2228 
2229  // Strip leftovers
2230  if (fullinfo.indexOf(m_nlRub) != -1)
2231  {
2232  fullinfo = fullinfo.replace(m_nlRub, "");
2233  }
2234 
2235  // Strip category info from description
2236  if (fullinfo.indexOf(m_nlCat) != -1)
2237  {
2238  fullinfo = fullinfo.replace(m_nlCat, "");
2239  }
2240 
2241  // Remove omroep from title
2242  if (event.m_title.indexOf(m_nlOmroep) != -1)
2243  {
2244  event.m_title = event.m_title.replace(m_nlOmroep, "");
2245  }
2246 
2247  // Put information back in description
2248 
2249  event.m_description = fullinfo;
2250  event.m_description = event.m_description.trimmed();
2251  event.m_title = event.m_title.trimmed();
2252  event.m_subtitle = event.m_subtitle.trimmed();
2253 
2254 }
2255 
2257 {
2258  // remove category movie from short events
2260  event.m_starttime.secsTo(event.m_endtime) < kMinMovieDuration)
2261  {
2262  /* default taken from ContentDescriptor::GetMythCategory */
2263  event.m_categoryType = ProgramInfo::kCategoryTVShow;
2264  }
2265 }
2266 
2270 void EITFixUp::FixNO(DBEventEIT &event) const
2271 {
2272  // Check for "title (R)" in the title
2273  int position = event.m_title.indexOf(m_noRerun);
2274  if (position != -1)
2275  {
2276  event.m_previouslyshown = true;
2277  event.m_title = event.m_title.replace(m_noRerun, "");
2278  }
2279  // Check for "subtitle (HD)" in the subtitle
2280  position = event.m_subtitle.indexOf(m_noHD);
2281  if (position != -1)
2282  {
2283  event.m_videoProps |= VID_HDTV;
2284  event.m_subtitle = event.m_subtitle.replace(m_noHD, "");
2285  }
2286  // Check for "description (HD)" in the description
2287  position = event.m_description.indexOf(m_noHD);
2288  if (position != -1)
2289  {
2290  event.m_videoProps |= VID_HDTV;
2291  event.m_description = event.m_description.replace(m_noHD, "");
2292  }
2293 }
2294 
2299 {
2300  QRegExp tmpExp1;
2301  // Check for "title (R)" in the title
2302  if (event.m_title.indexOf(m_noRerun) != -1)
2303  {
2304  event.m_previouslyshown = true;
2305  event.m_title = event.m_title.replace(m_noRerun, "");
2306  }
2307  // Check for "(R)" in the description
2308  if (event.m_description.indexOf(m_noRerun) != -1)
2309  {
2310  event.m_previouslyshown = true;
2311  }
2312  // Move colon separated category from program-titles into description
2313  // Have seen "NRK2s historiekveld: Film: bla-bla"
2314  tmpExp1 = m_noNRKCategories;
2315  while ((tmpExp1.indexIn(event.m_title) != -1) &&
2316  (tmpExp1.cap(2).length() > 1))
2317  {
2318  event.m_title = tmpExp1.cap(2);
2319  event.m_description = "(" + tmpExp1.cap(1) + ") " + event.m_description;
2320  }
2321  // Remove season premiere markings
2322  tmpExp1 = m_noPremiere;
2323  if (tmpExp1.indexIn(event.m_title) >= 3)
2324  {
2325  event.m_title.remove(m_noPremiere);
2326  }
2327  // Try to find colon-delimited subtitle in title, only tested for NRK channels
2328  tmpExp1 = m_noColonSubtitle;
2329  if (!event.m_title.startsWith("CSI:") &&
2330  !event.m_title.startsWith("CD:") &&
2331  !event.m_title.startsWith("Distriktsnyheter: fra"))
2332  {
2333  if (tmpExp1.indexIn(event.m_title) != -1)
2334  {
2335 
2336  if (event.m_subtitle.length() <= 0)
2337  {
2338  event.m_title = tmpExp1.cap(1);
2339  event.m_subtitle = tmpExp1.cap(2);
2340  }
2341  else if (event.m_subtitle == tmpExp1.cap(2))
2342  {
2343  event.m_title = tmpExp1.cap(1);
2344  }
2345  }
2346  }
2347 }
2348 
2352 void EITFixUp::FixDK(DBEventEIT &event) const
2353 {
2354  // Source: YouSee Rules of Operation v1.16
2355  // url: http://yousee.dk/~/media/pdf/CPE/Rules_Operation.ashx
2356  int episode = -1;
2357  int season = -1;
2358  QRegExp tmpRegEx;
2359  // Title search
2360  // episode and part/part total
2361  tmpRegEx = m_dkEpisode;
2362  int position = event.m_title.indexOf(tmpRegEx);
2363  if (position != -1)
2364  {
2365  episode = tmpRegEx.cap(1).toInt();
2366  event.m_partnumber = tmpRegEx.cap(1).toInt();
2367  event.m_title = event.m_title.replace(tmpRegEx, "");
2368  }
2369 
2370  tmpRegEx = m_dkPart;
2371  position = event.m_title.indexOf(tmpRegEx);
2372  if (position != -1)
2373  {
2374  episode = tmpRegEx.cap(1).toInt();
2375  event.m_partnumber = tmpRegEx.cap(1).toInt();
2376  event.m_parttotal = tmpRegEx.cap(2).toInt();
2377  event.m_title = event.m_title.replace(tmpRegEx, "");
2378  }
2379 
2380  // subtitle delimiters
2381  tmpRegEx = m_dkSubtitle1;
2382  position = event.m_title.indexOf(tmpRegEx);
2383  if (position != -1)
2384  {
2385  event.m_title = tmpRegEx.cap(1);
2386  event.m_subtitle = tmpRegEx.cap(2);
2387  }
2388  else
2389  {
2390  tmpRegEx = m_dkSubtitle2;
2391  if(event.m_title.indexOf(tmpRegEx) != -1)
2392  {
2393  event.m_title = tmpRegEx.cap(1);
2394  event.m_subtitle = tmpRegEx.cap(2);
2395  }
2396  }
2397  // Description search
2398  // Season (Sæson [:digit:]+.) => episode = season episode number
2399  // or year (- år [:digit:]+(\\)|:) ) => episode = total episode number
2400  tmpRegEx = m_dkSeason1;
2401  position = event.m_description.indexOf(tmpRegEx);
2402  if (position != -1)
2403  {
2404  season = tmpRegEx.cap(1).toInt();
2405  }
2406  else
2407  {
2408  tmpRegEx = m_dkSeason2;
2409  if(event.m_description.indexOf(tmpRegEx) != -1)
2410  {
2411  season = tmpRegEx.cap(1).toInt();
2412  }
2413  }
2414 
2415  if (episode > 0)
2416  event.m_episode = episode;
2417 
2418  if (season > 0)
2419  event.m_season = season;
2420 
2421  //Feature:
2422  tmpRegEx = m_dkFeatures;
2423  position = event.m_description.indexOf(tmpRegEx);
2424  if (position != -1)
2425  {
2426  QString features = tmpRegEx.cap(1);
2427  event.m_description = event.m_description.replace(tmpRegEx, "");
2428  // 16:9
2429  if (features.indexOf(m_dkWidescreen) != -1)
2430  event.m_videoProps |= VID_WIDESCREEN;
2431  // HDTV
2432  if (features.indexOf(m_dkHD) != -1)
2433  event.m_videoProps |= VID_HDTV;
2434  // Dolby Digital surround
2435  if (features.indexOf(m_dkDolby) != -1)
2436  event.m_audioProps |= AUD_DOLBY;
2437  // surround
2438  if (features.indexOf(m_dkSurround) != -1)
2439  event.m_audioProps |= AUD_SURROUND;
2440  // stereo
2441  if (features.indexOf(m_dkStereo) != -1)
2442  event.m_audioProps |= AUD_STEREO;
2443  // (G)
2444  if (features.indexOf(m_dkReplay) != -1)
2445  event.m_previouslyshown = true;
2446  // TTV
2447  if (features.indexOf(m_dkTxt) != -1)
2448  event.m_subtitleType |= SUB_NORMAL;
2449  }
2450 
2451  // Series and program id
2452  // programid is currently not transmitted
2453  // YouSee doesn't use a default authority but uses the first byte after
2454  // the / to indicate if the seriesid is global unique or unique on the
2455  // service id
2456  if (event.m_seriesId.length() >= 1 && event.m_seriesId[0] == '/')
2457  {
2458  QString newid;
2459  if (event.m_seriesId[1] == '1')
2460  newid = QString("%1%2").arg(event.m_chanid).
2461  arg(event.m_seriesId.mid(2,8));
2462  else
2463  newid = event.m_seriesId.mid(2,8);
2464  event.m_seriesId = newid;
2465  }
2466 
2467  if (event.m_programId.length() >= 1 && event.m_programId[0] == '/')
2468  event.m_programId[0]='_';
2469 
2470  // Add season and episode number to subtitle
2471  if (episode > 0)
2472  {
2473  event.m_subtitle = QString("%1 (%2").arg(event.m_subtitle).arg(episode);
2474  if (event.m_parttotal >0)
2475  event.m_subtitle = QString("%1:%2").arg(event.m_subtitle).
2476  arg(event.m_parttotal);
2477  if (season > 0)
2478  {
2479  event.m_season = season;
2480  event.m_episode = episode;
2481  event.m_syndicatedepisodenumber =
2482  QString("S%1E%2").arg(season).arg(episode);
2483  event.m_subtitle = QString("%1 S\xE6son %2").arg(event.m_subtitle).
2484  arg(season);
2485  }
2486  event.m_subtitle = QString("%1)").arg(event.m_subtitle);
2487  }
2488 
2489  // Find actors and director in description
2490  tmpRegEx = m_dkDirector;
2491  bool directorPresent = false;
2492  position = event.m_description.indexOf(tmpRegEx);
2493  if (position != -1)
2494  {
2495  QString tmpDirectorsString = tmpRegEx.cap(1);
2496  const QStringList directors =
2497  tmpDirectorsString.split(m_dkPersonsSeparator, QString::SkipEmptyParts);
2498  QStringList::const_iterator it = directors.begin();
2499  for (; it != directors.end(); ++it)
2500  {
2501  tmpDirectorsString = it->split(":").last().trimmed().
2502  remove(QRegExp("\\.$"));
2503  if (tmpDirectorsString != "")
2504  event.AddPerson(DBPerson::kDirector, tmpDirectorsString);
2505  }
2506  directorPresent = true;
2507  }
2508 
2509  tmpRegEx = m_dkActors;
2510  position = event.m_description.indexOf(tmpRegEx);
2511  if (position != -1)
2512  {
2513  QString tmpActorsString = tmpRegEx.cap(1);
2514  if (directorPresent)
2515  tmpActorsString = tmpActorsString.replace(m_dkDirector,"");
2516  const QStringList actors =
2517  tmpActorsString.split(m_dkPersonsSeparator, QString::SkipEmptyParts);
2518  QStringList::const_iterator it = actors.begin();
2519  for (; it != actors.end(); ++it)
2520  {
2521  tmpActorsString = it->split(":").last().trimmed().
2522  remove(QRegExp("\\.$"));
2523  if (tmpActorsString != "")
2524  event.AddPerson(DBPerson::kActor, tmpActorsString);
2525  }
2526  }
2527  //find year
2528  tmpRegEx = m_dkYear;
2529  position = event.m_description.indexOf(tmpRegEx);
2530  if (position != -1)
2531  {
2532  bool ok;
2533  uint y = tmpRegEx.cap(1).toUInt(&ok);
2534  if (ok)
2535  event.m_originalairdate = QDate(y, 1, 1);
2536  }
2537  // Remove white spaces
2538  event.m_description = event.m_description.trimmed();
2539  event.m_title = event.m_title.trimmed();
2540  event.m_subtitle = event.m_subtitle.trimmed();
2541 }
2542 
2547 {
2548  LOG(VB_EIT, LOG_INFO, QString("Applying html strip to %1").arg(event.m_title));
2549  event.m_title.remove(m_HTML);
2550 }
2551 
2552 // Moves the subtitle field into the description since it's just used
2553 // as more description field. All the sort-out will happen in the description
2554 // field. Also, sometimes the description is just a repeat of the title. If so,
2555 // we remove it.
2557 {
2558  if (event.m_title == event.m_description)
2559  {
2560  event.m_description = QString("");
2561  }
2562  if (!event.m_subtitle.isEmpty())
2563  {
2564  if (event.m_subtitle.trimmed().right(1) != ".'" )
2565  event.m_subtitle = event.m_subtitle.trimmed() + ".";
2566  event.m_description = event.m_subtitle.trimmed() + QString(" ") + event.m_description;
2567  event.m_subtitle = QString("");
2568  }
2569 }
2570 
2572 {
2573  //Live show
2574  int position;
2575  QRegExp tmpRegEx;
2576  position = event.m_title.indexOf("(Ζ)");
2577  if (position != -1)
2578  {
2579  event.m_title = event.m_title.replace("(Ζ)", "");
2580  event.m_description.prepend("Ζωντανή Μετάδοση. ");
2581  }
2582 
2583  // Greek not previously Shown
2584  position = event.m_title.indexOf(m_grNotPreviouslyShown);
2585  if (position != -1)
2586  {
2587  event.m_previouslyshown = false;
2588  event.m_title = event.m_title.replace(m_grNotPreviouslyShown, "");
2589  }
2590 
2591  // Greek Replay (Ε)
2592  // it might look redundant compared to previous check but at least it helps
2593  // remove the (Ε) From the title.
2594  tmpRegEx = m_grReplay;
2595  if (event.m_title.indexOf(tmpRegEx) != -1)
2596  {
2597  event.m_previouslyshown = true;
2598  event.m_title = event.m_title.replace(tmpRegEx, "");
2599  }
2600 
2601  // Check for (HD) in the decription
2602  position = event.m_description.indexOf("(HD)");
2603  if (position != -1)
2604  {
2605  event.m_description = event.m_description.replace("(HD)", "");
2606  event.m_videoProps |= VID_HDTV;
2607  }
2608 
2609  // Check for (Full HD) in the decription
2610  position = event.m_description.indexOf("(Full HD)");
2611  if (position != -1)
2612  {
2613  event.m_description = event.m_description.replace("(Full HD)", "");
2614  event.m_videoProps |= VID_HDTV;
2615  }
2616 
2617 
2618  tmpRegEx = m_grFixnofullstopActors;
2619  position = event.m_description.indexOf(tmpRegEx);
2620  if (position != -1)
2621  {
2622  event.m_description.insert(position + 1, ".");
2623  }
2624 
2625  // If they forgot the "." at the end of the sentence before the actors/directors begin, let's insert it.
2626  tmpRegEx = m_grFixnofullstopDirectors;
2627  position = event.m_description.indexOf(tmpRegEx);
2628  if (position != -1)
2629  {
2630  event.m_description.insert(position + 1, ".");
2631  }
2632 
2633  // Find actors and director in description
2634  // I am looking for actors first and then for directors/presenters because
2635  // sometimes punctuation is missing and the "Παίζουν:" label is mistaken
2636  // for a director's/presenter's surname (directors/presenters are shown
2637  // before actors in the description field.). So removing the text after
2638  // adding the actors AND THEN looking for dir/pres helps to clear things up.
2639  tmpRegEx = m_grActors;
2640  position = event.m_description.indexOf(tmpRegEx);
2641  if (position != -1)
2642  {
2643  QString tmpActorsString = tmpRegEx.cap(1);
2644  const QStringList actors =
2645  tmpActorsString.split(m_grPeopleSeparator, QString::SkipEmptyParts);
2646  QStringList::const_iterator it = actors.begin();
2647  for (; it != actors.end(); ++it)
2648  {
2649  tmpActorsString = it->split(":").last().trimmed().
2650  remove(QRegExp("\\.$"));
2651  if (tmpActorsString != "")
2652  event.AddPerson(DBPerson::kActor, tmpActorsString);
2653  }
2654  event.m_description.replace(tmpRegEx.cap(0), "");
2655  }
2656  // Director
2657  tmpRegEx = m_grDirector;
2658  position = event.m_description.indexOf(tmpRegEx);
2659  if (position != -1)
2660  {
2661  QString tmpDirectorsString = tmpRegEx.cap(1);
2662  const QStringList directors =
2663  tmpDirectorsString.split(m_grPeopleSeparator, QString::SkipEmptyParts);
2664  QStringList::const_iterator it = directors.begin();
2665  for (; it != directors.end(); ++it)
2666  {
2667  tmpDirectorsString = it->split(":").last().trimmed().
2668  remove(QRegExp("\\.$"));
2669  if (tmpDirectorsString != "")
2670  {
2671  event.AddPerson(DBPerson::kDirector, tmpDirectorsString);
2672  }
2673  }
2674  event.m_description.replace(tmpRegEx.cap(0), "");
2675  }
2676 
2677  //Try to find presenter
2678  tmpRegEx = m_grPres;
2679  position = event.m_description.indexOf(tmpRegEx);
2680  if (position != -1)
2681  {
2682  QString tmpPresentersString = tmpRegEx.cap(1);
2683  const QStringList presenters =
2684  tmpPresentersString.split(m_grPeopleSeparator, QString::SkipEmptyParts);
2685  QStringList::const_iterator it = presenters.begin();
2686  for (; it != presenters.end(); ++it)
2687  {
2688  tmpPresentersString = it->split(":").last().trimmed().
2689  remove(QRegExp("\\.$"));
2690  if (tmpPresentersString != "")
2691  {
2692  event.AddPerson(DBPerson::kPresenter, tmpPresentersString);
2693  }
2694  }
2695  event.m_description.replace(tmpRegEx.cap(0), "");
2696  }
2697 
2698  //find year e.g Παραγωγής 1966 ή ΝΤΟΚΙΜΑΝΤΕΡ - 1998 Κατάλληλο για όλους
2699  // Used in Private channels (not 'secret', just not owned by Government!)
2700  tmpRegEx = m_grYear;
2701  position = event.m_description.indexOf(tmpRegEx);
2702  if (position != -1)
2703  {
2704  bool ok;
2705  uint y = tmpRegEx.cap(1).toUInt(&ok);
2706  if (ok)
2707  {
2708  event.m_originalairdate = QDate(y, 1, 1);
2709  event.m_description.replace(tmpRegEx, "");
2710  }
2711  }
2712  // Remove white spaces
2713  event.m_description = event.m_description.trimmed();
2714  event.m_title = event.m_title.trimmed();
2715  event.m_subtitle = event.m_subtitle.trimmed();
2716  // Remove " ."
2717  event.m_description = event.m_description.replace(" .",".").trimmed();
2718 
2719  //find country of origin and remove it from description.
2720  tmpRegEx = m_grCountry;
2721  position = event.m_description.indexOf(tmpRegEx);
2722  if (position != -1)
2723  {
2724  event.m_description.replace(tmpRegEx, "");
2725  }
2726 
2727  // Work out the season and episode numbers (if any)
2728  // Matching pattern "Επεισ[όο]διο:?|Επ 3 από 14|3/14" etc
2729  bool series = false;
2730  QRegExp tmpSeries = m_grSeason;
2731  // cap(2) is the season for ΑΒΓΔ
2732  // cap(3) is the season for 1234
2733  int position1 = tmpSeries.indexIn(event.m_title);
2734  int position2 = tmpSeries.indexIn(event.m_description);
2735  if ((position1 != -1) || (position2 != -1))
2736  {
2737  if (!tmpSeries.cap(2).isEmpty()) // we found a letter representing a number
2738  {
2739  //sometimes Nat. TV writes numbers as letters, i.e Α=1, Β=2, Γ=3, etc
2740  //must convert them to numbers.
2741  int tmpinteger = tmpSeries.cap(2).toUInt();
2742  if (tmpinteger < 1)
2743  {
2744  if (tmpSeries.cap(2) == "ΣΤ") // 6, don't ask!
2745  event.m_season = 6;
2746  else
2747  {
2748  QString LettToNumber = "0ΑΒΓΔΕ6ΖΗΘΙΚΛΜΝ";
2749  tmpinteger = LettToNumber.indexOf(tmpSeries.cap(2));
2750  if (tmpinteger != -1)
2751  event.m_season = tmpinteger;
2752  }
2753  }
2754  }
2755  else if (!tmpSeries.cap(3).isEmpty()) //number
2756  {
2757  event.m_season = tmpSeries.cap(3).toUInt();
2758  }
2759  series = true;
2760  if (position1 != -1)
2761  event.m_title.replace(tmpSeries.cap(0),"");
2762  if (position2 != -1)
2763  event.m_description.replace(tmpSeries.cap(0),"");
2764  }
2765  // If Season is in Roman Numerals (I,II,etc)
2766  tmpSeries = m_grSeason_as_RomanNumerals;
2767  if ((position1 = tmpSeries.indexIn(event.m_title)) != -1
2768  || (position2 = tmpSeries.indexIn(event.m_description)) != -1)
2769  {
2770  if (!tmpSeries.isEmpty()) //number
2771  {
2772  // make sure I replace greek Ι with english I
2773  QString romanSeries = tmpSeries.cap(1).replace("Ι","I").toUpper();
2774  if (romanSeries == "I")
2775  event.m_season = 1;
2776  else if (romanSeries == "II")
2777  event.m_season = 2;
2778  else if (romanSeries== "III")
2779  event.m_season = 3;
2780  else if (romanSeries == "IV")
2781  event.m_season = 4;
2782  else if (romanSeries == "V")
2783  event.m_season = 5;
2784  else if (romanSeries== "VI")
2785  event.m_season = 6;
2786  else if (romanSeries == "VII")
2787  event.m_season = 7;
2788  else if (romanSeries == "VIII")
2789  event.m_season = 8;
2790  else if (romanSeries == "IX")
2791  event.m_season = 9;
2792  else if (romanSeries == "X")
2793  event.m_season = 10;
2794  else if (romanSeries == "XI")
2795  event.m_season = 11;
2796  else if (romanSeries == "XII")
2797  event.m_season = 12;
2798  else if (romanSeries == "XII")
2799  event.m_season = 13;
2800  else if (romanSeries == "XIV")
2801  event.m_season = 14;
2802  else if (romanSeries == "XV")
2803  event.m_season = 15;
2804  else if (romanSeries == "XVI")
2805  event.m_season = 16;
2806  else if (romanSeries == "XVII")
2807  event.m_season = 17;
2808  else if (romanSeries == "XIII")
2809  event.m_season = 18;
2810  else if (romanSeries == "XIX")
2811  event.m_season = 19;
2812  else if (romanSeries == "XX")
2813  event.m_season = 20;
2814  }
2815  series = true;
2816  if (position1 != -1)
2817  {
2818  event.m_title.replace(tmpSeries.cap(0),"");
2819  event.m_title = event.m_title.trimmed();
2820  if (event.m_title.right(1) == ",")
2821  event.m_title.chop(1);
2822  }
2823  if (position2 != -1)
2824  {
2825  event.m_description.replace(tmpSeries.cap(0),"");
2826  event.m_description = event.m_description.trimmed();
2827  if (event.m_description.right(1) == ",")
2828  event.m_description.chop(1);
2829  }
2830  }
2831 
2832 
2833  QRegExp tmpEpisode = m_grlongEp;
2834  //tmpEpisode.setMinimal(true);
2835  // cap(1) is the Episode No.
2836  if ((position1 = tmpEpisode.indexIn(event.m_title)) != -1
2837  || (position2 = tmpEpisode.indexIn(event.m_description)) != -1)
2838  {
2839  if (!tmpEpisode.cap(1).isEmpty())
2840  {
2841  event.m_episode = tmpEpisode.cap(1).toUInt();
2842  series = true;
2843  if (position1 != -1)
2844  event.m_title.replace(tmpEpisode.cap(0),"");
2845  if (position2 != -1)
2846  event.m_description.replace(tmpEpisode.cap(0),"");
2847  // Sometimes description omits Season if it's 1. We fix this
2848  if (0 == event.m_season)
2849  event.m_season = 1;
2850  }
2851  }
2852  // Sometimes, especially on greek national tv, they include comments in the
2853  // title, e.g "connection to ert1", "ert archives".
2854  // Because they obscure the real title, I'll isolate and remove them.
2855 
2856  QRegExp tmpComment = m_grCommentsinTitle;
2857  tmpComment.setMinimal(true);
2858  position = event.m_title.indexOf(tmpComment);
2859  if (position != -1)
2860  {
2861  event.m_title.replace(tmpComment.cap(0),"");
2862  }
2863 
2864  // Sometimes the real (mostly English) title of a movie or series is
2865  // enclosed in parentheses in the event title, subtitle or description.
2866  // Since the subtitle has been moved to the description field by
2867  // EITFixUp::FixGreekSubtitle, I will search for it only in the description.
2868  // It will replace the translated one to get better chances of metadata
2869  // retrieval. The old title will be moved in the description.
2870  QRegExp tmptitle = m_grRealTitleinDescription;
2871  tmptitle.setMinimal(true);
2872  position = event.m_description.indexOf(tmptitle);
2873  if (position != -1)
2874  {
2875  event.m_description = event.m_description.replace(tmptitle, "");
2876  if (tmptitle.cap(0) != event.m_title.trimmed())
2877  {
2878  event.m_description = "(" + event.m_title.trimmed() + "). " + event.m_description;
2879  }
2880  event.m_title = tmptitle.cap(1);
2881  // Remove the real title from the description
2882  }
2883  else // search in title
2884  {
2885  tmptitle = m_grRealTitleinTitle;
2886  position = event.m_title.indexOf(tmptitle);
2887  if (position != -1) // found in title instead
2888  {
2889  event.m_title.replace(tmptitle.cap(0),"");
2890  QString tmpTranslTitle = event.m_title;
2891  //QString tmpTranslTitle = event.m_title.replace(tmptitle.cap(0),"");
2892  event.m_title = tmptitle.cap(1);
2893  event.m_description = "(" + tmpTranslTitle.trimmed() + "). " + event.m_description;
2894  }
2895  }
2896 
2897  // Description field: "^Episode: Lion in the cage. (Description follows)"
2898  tmpRegEx = m_grEpisodeAsSubtitle;
2899  position = event.m_description.indexOf(tmpRegEx);
2900  if (position != -1)
2901  {
2902  event.m_subtitle = tmpRegEx.cap(1).trimmed();
2903  event.m_description.replace(tmpRegEx, "");
2904  }
2905  QRegExp m_grMovie("\\bταιν[ιί]α\\b",Qt::CaseInsensitive);
2906  bool isMovie = (event.m_description.indexOf(m_grMovie) !=-1) ;
2907  if (isMovie)
2908  {
2909  event.m_categoryType = ProgramInfo::kCategoryMovie;
2910  }
2911  else if (series)
2912  {
2913  event.m_categoryType = ProgramInfo::kCategorySeries;
2914  }
2915  // just for luck, retrim fields.
2916  event.m_description = event.m_description.trimmed();
2917  event.m_title = event.m_title.trimmed();
2918  event.m_subtitle = event.m_subtitle.trimmed();
2919 
2920 // να σβήσω τα κομμάτια που περισσεύουν από την περιγραφή πχ παραγωγής χχχχ
2921 }
2922 
2924 {
2925  if (event.m_description.indexOf(m_grCategComedy) != -1)
2926  {
2927  event.m_category = "Κωμωδία";
2928  }
2929  else if (event.m_description.indexOf(m_grCategTeleMag) != -1)
2930  {
2931  event.m_category = "Τηλεπεριοδικό";
2932  }
2933  else if (event.m_description.indexOf(m_grCategNature) != -1)
2934  {
2935  event.m_category = "Επιστήμη/Φύση";
2936  }
2937  else if (event.m_description.indexOf(m_grCategHealth) != -1)
2938  {
2939  event.m_category = "Υγεία";
2940  }
2941  else if (event.m_description.indexOf(m_grCategReality) != -1)
2942  {
2943  event.m_category = "Ριάλιτι";
2944  }
2945  else if (event.m_description.indexOf(m_grCategDrama) != -1)
2946  {
2947  event.m_category = "Κοινωνικό";
2948  }
2949  else if (event.m_description.indexOf(m_grCategChildren) != -1)
2950  {
2951  event.m_category = "Παιδικό";
2952  }
2953  else if (event.m_description.indexOf(m_grCategSciFi) != -1)
2954  {
2955  event.m_category = "Επιστ.Φαντασίας";
2956  }
2957  else if ((event.m_description.indexOf(m_grCategFantasy) != -1)
2958  && (event.m_description.indexOf(m_grCategMystery) != -1))
2959  {
2960  event.m_category = "Φαντασίας/Μυστηρίου";
2961  }
2962  else if (event.m_description.indexOf(m_grCategMystery) != -1)
2963  {
2964  event.m_category = "Μυστηρίου";
2965  }
2966  else if (event.m_description.indexOf(m_grCategFantasy) != -1)
2967  {
2968  event.m_category = "Φαντασίας";
2969  }
2970  else if (event.m_description.indexOf(m_grCategHistory) != -1)
2971  {
2972  event.m_category = "Ιστορικό";
2973  }
2974  else if (event.m_description.indexOf(m_grCategTeleShop) != -1
2975  || event.m_title.indexOf(m_grCategTeleShop) != -1)
2976  {
2977  event.m_category = "Τηλεπωλήσεις";
2978  }
2979  else if (event.m_description.indexOf(m_grCategFood) != -1)
2980  {
2981  event.m_category = "Γαστρονομία";
2982  }
2983  else if (event.m_description.indexOf(m_grCategGameShow) != -1
2984  || event.m_title.indexOf(m_grCategGameShow) != -1)
2985  {
2986  event.m_category = "Τηλεπαιχνίδι";
2987  }
2988  else if (event.m_description.indexOf(m_grCategBiography) != -1)
2989  {
2990  event.m_category = "Βιογραφία";
2991  }
2992  else if (event.m_title.indexOf(m_grCategNews) != -1)
2993  {
2994  event.m_category = "Ειδήσεις";
2995  }
2996  else if (event.m_description.indexOf(m_grCategSports) != -1)
2997  {
2998  event.m_category = "Αθλητικά";
2999  }
3000  else if (event.m_description.indexOf(m_grCategMusic) != -1
3001  || event.m_title.indexOf(m_grCategMusic) != -1)
3002  {
3003  event.m_category = "Μουσική";
3004  }
3005  else if (event.m_description.indexOf(m_grCategDocumentary) != -1)
3006  {
3007  event.m_category = "Ντοκιμαντέρ";
3008  }
3009  else if (event.m_description.indexOf(m_grCategReligion) != -1)
3010  {
3011  event.m_category = "Θρησκεία";
3012  }
3013  else if (event.m_description.indexOf(m_grCategCulture) != -1)
3014  {
3015  event.m_category = "Τέχνες/Πολιτισμός";
3016  }
3017  else if (event.m_description.indexOf(m_grCategSpecial) != -1)
3018  {
3019  event.m_category = "Αφιέρωμα";
3020  }
3021 
3022 }
3023 
3025 {
3026  // TODO handle scraping the category and category_type from localized text in the short/long description
3027  // TODO remove short description (stored as episode title) which is just the beginning of the long description (actual description)
3028 
3029  // drop the short description if its copy the start of the long description
3030  if (event.m_description.startsWith (event.m_subtitle))
3031  {
3032  event.m_subtitle = "";
3033  }
3034 
3035  // handle cast and crew in items in the DVB Extended Event Descriptor
3036  // remove handled items from the map, so the left overs can be reported
3037  QMap<QString,QString>::iterator i = event.m_items.begin();
3038  while (i != event.m_items.end())
3039  {
3040  if (QString::compare (i.key(), "Role Player") == 0)
3041  {
3042  event.AddPerson (DBPerson::kActor, i.value());
3043  i = event.m_items.erase (i);
3044  }
3045  else if (QString::compare (i.key(), "Director") == 0)
3046  {
3047  event.AddPerson (DBPerson::kDirector, i.value());
3048  i = event.m_items.erase (i);
3049  }
3050  else if (QString::compare (i.key(), "Commentary or Commentator") == 0)
3051  {
3052  event.AddPerson (DBPerson::kCommentator, i.value());
3053  i = event.m_items.erase (i);
3054  }
3055  else if (QString::compare (i.key(), "Performing Artist") == 0)
3056  {
3057  event.AddPerson (DBPerson::kActor, i.value());
3058  i = event.m_items.erase (i);
3059  }
3060  else if (QString::compare (i.key(), "Presenter") == 0)
3061  {
3062  event.AddPerson (DBPerson::kPresenter, i.value());
3063  i = event.m_items.erase (i);
3064  }
3065  else if (QString::compare (i.key(), "Producer") == 0)
3066  {
3067  event.AddPerson (DBPerson::kProducer, i.value());
3068  i = event.m_items.erase (i);
3069  }
3070  else if (QString::compare (i.key(), "Scriptwriter") == 0)
3071  {
3072  event.AddPerson (DBPerson::kWriter, i.value());
3073  i = event.m_items.erase (i);
3074  }
3075  else
3076  {
3077  ++i;
3078  }
3079  }
3080 
3081  // handle star rating in the description
3082  QRegExp tmp = m_unitymediaImdbrating;
3083  if (event.m_description.indexOf (tmp) != -1)
3084  {
3085  float stars = tmp.cap(1).toFloat();
3086  event.m_stars = stars / 10.0F;
3087  event.m_description.replace (m_unitymediaImdbrating, "");
3088  }
3089 }
const QRegExp m_RTLSubtitle
Definition: eitfixup.h:198
const QRegExp m_mcaDD
Definition: eitfixup.h:196
const QRegExp m_grCountry
Definition: eitfixup.h:275
void FixComHem(DBEventEIT &event, bool process_subtitle) const
Use this to standardize ComHem DVB-C service in Sweden.
Definition: eitfixup.cpp:1157
QDateTime m_endtime
Definition: programdata.h:138
const QRegExp m_grSeason
Definition: eitfixup.h:278
QString m_description
Definition: programdata.h:135
void FixAUNine(DBEventEIT &event) const
Use this to standardize DVB-T guide in Australia.
Definition: eitfixup.cpp:1440
const QRegExp m_noHD
Definition: eitfixup.h:238
const QRegExp m_comHemRerun2
Definition: eitfixup.h:177
const QRegExp m_bellPPVDescriptionEventId
Definition: eitfixup.h:132
const QRegExp m_dkWidescreen
Definition: eitfixup.h:250
const QRegExp m_dishPPVTitleColon
Definition: eitfixup.h:134
const QRegExp m_dePremiereCredits
Definition: eitfixup.h:219
const QString longEp
Definition: eitfixup.cpp:25
const QRegExp m_dishPPVSpacePerenEnd
Definition: eitfixup.h:135
const QRegExp m_dishPPVCode
Definition: eitfixup.h:141
const QRegExp m_PRO7CastOne
Definition: eitfixup.h:208
const QRegExp m_ukYearColon
Definition: eitfixup.h:165
QString dish_theme_type_to_string(uint theme_type)
uint16_t m_airdate
movie year / production year
Definition: programdata.h:139
const QRegExp m_dishDescriptionPremiere2
Definition: eitfixup.h:140
const QRegExp m_comHemSeries1
Definition: eitfixup.h:182
const QRegExp m_dkDirector
Definition: eitfixup.h:259
static const uint kMaxQuestionExclamation
Definition: eitfixup.h:23
QString m_category
Definition: programdata.h:136
void FixGreekEIT(DBEventEIT &event) const
Definition: eitfixup.cpp:2571
void FixNRK_DVBT(DBEventEIT &event) const
Use this to clean DVB-T guide in Norway (NRK)
Definition: eitfixup.cpp:2298
const QRegExp m_mcaSeries
Definition: eitfixup.h:189
const QRegExp m_noNRKCategories
Definition: eitfixup.h:240
const QRegExp m_grCategDrama
Definition: eitfixup.h:286
void FixGreekCategories(DBEventEIT &event) const
Definition: eitfixup.cpp:2923
const QRegExp m_dkPersonsSeparator
Definition: eitfixup.h:258
const QRegExp m_ukDotEnd
Definition: eitfixup.h:149
const QRegExp m_dkSurround
Definition: eitfixup.h:252
const QRegExp m_mcaIncompleteTitle
Definition: eitfixup.h:185
void FixPremiere(DBEventEIT &event) const
Use this to standardize DVB-C guide in Germany for the providers Kabel Deutschland and Premiere.
Definition: eitfixup.cpp:1951
const QRegExp m_bellPPVTitleAllDay
Definition: eitfixup.h:127
void FixAUFreeview(DBEventEIT &event) const
Use this to standardize DVB-T guide in Australia.
Definition: eitfixup.cpp:1510
const QRegExp m_dkSeason1
Definition: eitfixup.h:247
const QRegExp m_grCategHealth
Definition: eitfixup.h:305
const QRegExp m_dkSubtitle1
Definition: eitfixup.h:245
const QRegExp m_dkSeason2
Definition: eitfixup.h:248
QString m_title
Definition: programdata.h:133
const QString seasonStr
Definition: eitfixup.cpp:21
const QRegExp m_dkDolby
Definition: eitfixup.h:251
void FixCategory(DBEventEIT &event) const
Definition: eitfixup.cpp:2256
QString m_system
Definition: programdata.h:67
void FixUK(DBEventEIT &event) const
Use this in the United Kingdom to standardize DVB-T guide.
Definition: eitfixup.cpp:842
const QRegExp m_noPremiere
Definition: eitfixup.h:241
static const int kMinMovieDuration
Definition: eitfixup.h:27
const QRegExp m_ukSeries
Definition: eitfixup.h:153
const QRegExp m_ukSpaceStart
Definition: eitfixup.h:151
const QRegExp m_ukYear
Definition: eitfixup.h:155
const QRegExp m_grPeopleSeparator
Definition: eitfixup.h:271
const QRegExp m_AUFreeviewYC
Definition: eitfixup.h:263
const QRegExp m_grCategSpecial
Definition: eitfixup.h:306
const QRegExp m_AUFreeviewSY
Definition: eitfixup.h:261
const QRegExp m_mcaCredits
Definition: eitfixup.h:190
unsigned int uint
Definition: compat.h:140
const QRegExp m_comHemSeries2
Definition: eitfixup.h:183
const QRegExp m_ukAlsoInHD
Definition: eitfixup.h:145
const QRegExp m_mcaCC
Definition: eitfixup.h:195
static const uint kDotToTitle
Definition: eitfixup.h:21
const QRegExp m_dishDescriptionFinale2
Definition: eitfixup.h:138
const QRegExp m_AUFreeviewSYC
Definition: eitfixup.h:264
void FixUnitymedia(DBEventEIT &event) const
Definition: eitfixup.cpp:3024
void FixPBS(DBEventEIT &event) const
Use this to standardize PBS ATSC guide in the USA.
Definition: eitfixup.cpp:1142
const QString shortContext
Definition: eitfixup.cpp:44
void FixBellExpressVu(DBEventEIT &event) const
Use this for the Canadian BellExpressVu to standardize DVB-S guide.
Definition: eitfixup.cpp:433
static const uint kMaxToTitle
Definition: eitfixup.h:19
const QRegExp m_fiRerun2
Definition: eitfixup.h:214
static guint32 * tmp
Definition: goom_core.c:35
const QRegExp m_ukDoubleDotEnd
Definition: eitfixup.h:161
const QRegExp m_bellPPVTitleHD
Definition: eitfixup.h:128
QString m_subtitle
Definition: programdata.h:134
const QRegExp m_ukCC
Definition: eitfixup.h:154
const QRegExp m_HTML
Definition: eitfixup.h:265
const QRegExp m_dkSubtitle2
Definition: eitfixup.h:246
uint m_season
Definition: programdata.h:157
const QRegExp m_ukSpaceColonStart
Definition: eitfixup.h:150
const QRegExp m_grYear
Definition: eitfixup.h:274
const QRegExp m_unitymediaImdbrating
IMDb Rating.
Definition: eitfixup.h:307
const QRegExp m_grCategSports
Definition: eitfixup.h:298
const QRegExp m_mcaCompleteTitleb
Definition: eitfixup.h:187
const QRegExp m_grNotPreviouslyShown
Definition: eitfixup.h:283
void FixAUStar(DBEventEIT &event) const
Use this to standardize DVB-S guide in Australia.
Definition: eitfixup.cpp:1399
const QRegExp m_ukQuotedSubtitle
Definition: eitfixup.h:168
bool m_previouslyshown
Definition: programdata.h:153
const QString longSeasEp
Definition: eitfixup.cpp:29
const QRegExp m_ukPart
Definition: eitfixup.h:152
const QRegExp m_mcaYear
Definition: eitfixup.h:194
const QRegExp m_nlOmroep
Definition: eitfixup.h:236
const QRegExp m_grCategSciFi
Definition: eitfixup.h:304
const QRegExp m_nlActors
Definition: eitfixup.h:228
const QRegExp m_dkHD
Definition: eitfixup.h:256
const QRegExp m_mcaCompleteTitlea
Definition: eitfixup.h:186
const QRegExp m_comHemDirector
Definition: eitfixup.h:172
const QRegExp m_dkFeatures
Definition: eitfixup.h:249
const QString shortEp
Definition: eitfixup.cpp:37
const QRegExp m_PRO7CrewOne
Definition: eitfixup.h:206
const QRegExp m_dkPart
Definition: eitfixup.h:244
const QRegExp m_grCategTeleMag
Definition: eitfixup.h:292
const QRegExp m_ukCompleteDots
Definition: eitfixup.h:167
const QRegExp m_grActors
Definition: eitfixup.h:268
const QRegExp m_Stereo
Definition: eitfixup.h:242
def rating(profile, smoonURL, gate)
Definition: scan.py:25
const QRegExp m_grFixnofullstopActors
Definition: eitfixup.h:269
const QRegExp m_ukExclusionFromSubtitle
Definition: eitfixup.h:166
const QRegExp m_dePremiereAirdate
Definition: eitfixup.h:218
const QRegExp m_bellPPVDescriptionAllDay2
Definition: eitfixup.h:131
const QRegExp m_ATVSubtitle
Definition: eitfixup.h:209
const QRegExp m_nlHD
Definition: eitfixup.h:225
void FixNL(DBEventEIT &event) const
Use this to standardize @Home DVB-C guide in the Netherlands.
Definition: eitfixup.cpp:2006
unsigned char m_audioProps
Definition: programdata.h:146
const QRegExp m_dePremiereOTitle
Definition: eitfixup.h:220
const QRegExp m_dkEpisode
Definition: eitfixup.h:243
const QRegExp m_grDirector
Definition: eitfixup.h:272
static const uint kMaxDotToColon
Definition: eitfixup.h:25
void FixGreekSubtitle(DBEventEIT &event) const
Definition: eitfixup.cpp:2556
unsigned char m_subtitleType
Definition: programdata.h:145
const QRegExp m_nlWide
Definition: eitfixup.h:223
EITFixUp()
Definition: eitfixup.cpp:48
const QRegExp m_comHemSub
Definition: eitfixup.h:175
const QRegExp m_bellYear
Definition: eitfixup.h:124
const QRegExp m_ukNew
Definition: eitfixup.h:143
const QRegExp m_mcaSubtitle
Definition: eitfixup.h:188
QDateTime m_starttime
Definition: programdata.h:137
const QRegExp m_RTLrepeat
Definition: eitfixup.h:197
void FixNO(DBEventEIT &event) const
Use this to clean DVB-S guide in Norway.
Definition: eitfixup.cpp:2270
const QRegExp m_mcaAvail
Definition: eitfixup.h:191
const QRegExp m_ukColonPeriod
Definition: eitfixup.h:147
void FixDisneyChannel(DBEventEIT &event) const
Use this to standardise the Disney Channel guide in Germany.
Definition: eitfixup.cpp:1873
const QRegExp m_ukNewTitle
Definition: eitfixup.h:144
const QRegExp m_grCategComedy
Definition: eitfixup.h:287
const QRegExp m_comHemTSub
Definition: eitfixup.h:184
const QRegExp m_dkActors
Definition: eitfixup.h:257
const QRegExp m_comHemCountry
Definition: eitfixup.h:171
uint m_episode
Definition: programdata.h:158
const QRegExp m_ukDescriptionRemove
Definition: eitfixup.h:159
const QRegExp m_ukStarring
Definition: eitfixup.h:157
static QString AddDVBEITAuthority(uint chanid, const QString &id)
This adds a DVB EIT default authority to series id or program id if one exists in the DB for that cha...
Definition: eitfixup.cpp:406
const QRegExp m_ukBBC7rpt
Definition: eitfixup.h:158
void FixRTL(DBEventEIT &event) const
Use this to standardise the RTL group guide in Germany.
Definition: eitfixup.cpp:1678
const QRegExp m_mcaActorsSeparator
Definition: eitfixup.h:193
const QRegExp m_mcaActors
Definition: eitfixup.h:192
const QRegExp m_AUFreeviewY
Definition: eitfixup.h:262
const QRegExp m_dishDescriptionPremiere
Definition: eitfixup.h:139
void FixMCA(DBEventEIT &event) const
Use this to standardise the MultiChoice Africa DVB-S guide.
Definition: eitfixup.cpp:1550
const QRegExp m_RTLEpisodeNo1
Definition: eitfixup.h:211
QString m_seriesId
Definition: programdata.h:150
void FixAUDescription(DBEventEIT &event) const
Use this to standardize DVB-T guide in Australia.
Definition: eitfixup.cpp:1415
const QRegExp m_RTLSubtitle5
Definition: eitfixup.h:203
const QRegExp m_dkTxt
Definition: eitfixup.h:255
const QRegExp m_grCategFood
Definition: eitfixup.h:285
const QRegExp m_grCategNature
Definition: eitfixup.h:303
uint m_totalepisodes
Definition: programdata.h:159
const QRegExp m_grCategGameShow
Definition: eitfixup.h:294
const QRegExp m_nlCat
Definition: eitfixup.h:235
unsigned char m_videoProps
Definition: programdata.h:147
const QRegExp m_grCategReality
Definition: eitfixup.h:300
const QRegExp m_dishDescriptionNew
Definition: eitfixup.h:136
const QRegExp m_nlSub
Definition: eitfixup.h:226
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
const QRegExp m_dePremiereLength
Definition: eitfixup.h:217
const QRegExp m_bellActors
Definition: eitfixup.h:125
const QRegExp m_RTLSubtitle2
Definition: eitfixup.h:200
const QRegExp m_deSkyDescriptionSeasonEpisode
Definition: eitfixup.h:221
const QRegExp m_dkReplay
Definition: eitfixup.h:254
const QRegExp m_ukLaONoSplit
Definition: eitfixup.h:170
const QRegExp m_grCategMystery
Definition: eitfixup.h:289
ProgramInfo::CategoryType m_categoryType
Definition: programdata.h:149
const QRegExp m_nlRepeat
Definition: eitfixup.h:224
const QRegExp m_RTLSubtitle4
Definition: eitfixup.h:202
const QRegExp m_PRO7Subtitle
Definition: eitfixup.h:204
const QRegExp m_noColonSubtitle
Definition: eitfixup.h:239
const QRegExp m_nlYear2
Definition: eitfixup.h:233
const QRegExp m_ukCEPQ
Definition: eitfixup.h:146
const QRegExp m_comHemRerun1
Definition: eitfixup.h:176
const QRegExp m_RTLSubtitle3
Definition: eitfixup.h:201
const QRegExp m_ukBBC34
Definition: eitfixup.h:164
const QRegExp m_nlDirector
Definition: eitfixup.h:234
static QString GetDefaultAuthority(uint chanid)
Returns the DVB default authority for the chanid given.
const QRegExp m_grCategReligion
Definition: eitfixup.h:301
const QRegExp m_fiRerun
Definition: eitfixup.h:213
const QRegExp m_dishDescriptionFinale
Definition: eitfixup.h:137
const QRegExp m_nlYear1
Definition: eitfixup.h:232
void FixDK(DBEventEIT &event) const
Use this to clean YouSee's DVB-C guide in Denmark.
Definition: eitfixup.cpp:2352
void FixStripHTML(DBEventEIT &event) const
Use this to clean HTML Tags from EIT Data.
Definition: eitfixup.cpp:2546
const QRegExp m_grCategHistory
Definition: eitfixup.h:291
void SetUKSubtitle(DBEventEIT &event) const
Use this in the United Kingdom to standardize DVB-T guide.
Definition: eitfixup.cpp:713
const QRegExp m_bellPPVSubtitleAllDay
Definition: eitfixup.h:129
const QRegExp m_uk24ep
Definition: eitfixup.h:156
void FixATV(DBEventEIT &event) const
Use this to standardise the ATV/ATV2 guide in Germany.
Definition: eitfixup.cpp:1898
const QRegExp m_grReplay
Definition: eitfixup.h:266
const QRegExp m_comHemHost
Definition: eitfixup.h:174
const QRegExp m_dkYear
Definition: eitfixup.h:260
const QRegExp m_dkStereo
Definition: eitfixup.h:253
const QRegExp m_ukTitleRemove
Definition: eitfixup.h:160
const QRegExp m_grCategFantasy
Definition: eitfixup.h:290
void FixAUSeven(DBEventEIT &event) const
Use this to standardize DVB-T guide in Australia.
Definition: eitfixup.cpp:1471
const QRegExp m_noRerun
Definition: eitfixup.h:237
const QRegExp m_comHemPersSeparator
Definition: eitfixup.h:179
const QRegExp m_bellPPVTitleAllDayHD
Definition: eitfixup.h:126
FixupValue m_fixup
Definition: programdata.h:207
const QRegExp m_DisneyChannelSubtitle
Definition: eitfixup.h:210
static const uint SUBTITLE_MAX_LEN
Definition: eitfixup.h:17
const QRegExp m_grFixnofullstopDirectors
Definition: eitfixup.h:270
uint32_t m_chanid
Definition: programdata.h:206
const QRegExp m_grCategChildren
Definition: eitfixup.h:288
const QRegExp m_nlTxt
Definition: eitfixup.h:222
const QRegExp m_RTLEpisodeNo2
Definition: eitfixup.h:212
const QRegExp m_comHemTT
Definition: eitfixup.h:178
const QRegExp m_RTLSubtitle1
Definition: eitfixup.h:199
const QRegExp m_ukDotSpaceStart
Definition: eitfixup.h:148
const QRegExp m_fiFilm
Definition: eitfixup.h:216
const QString longContext
Definition: eitfixup.cpp:33
void FixPRO7(DBEventEIT &event) const
Use this to standardise the PRO7/Sat1 group guide in Germany.
Definition: eitfixup.cpp:1791
const QRegExp m_grCategTeleShop
Definition: eitfixup.h:293
const QRegExp m_PRO7Cast
Definition: eitfixup.h:207
const QRegExp m_nlSub2
Definition: eitfixup.h:227
const QRegExp m_grCategCulture
Definition: eitfixup.h:302
const QRegExp m_fiAgeLimit
Definition: eitfixup.h:215
const QRegExp m_nlRub
Definition: eitfixup.h:231
const QRegExp m_comHemActor
Definition: eitfixup.h:173
const QRegExp m_ukDoubleDotStart
Definition: eitfixup.h:162
const QRegExp m_PRO7Crew
Definition: eitfixup.h:205
uint16_t m_partnumber
Definition: programdata.h:142
const QRegExp m_ukThen
Definition: eitfixup.h:142
const QRegExp m_bellPPVDescriptionAllDay
Definition: eitfixup.h:130
const QRegExp m_dishPPVTitleHD
Definition: eitfixup.h:133
const QRegExp m_grPres
Definition: eitfixup.h:273
const QRegExp m_ukTime
Definition: eitfixup.h:163
void FixFI(DBEventEIT &event) const
Use this to clean DVB-T guide in Finland.
Definition: eitfixup.cpp:1907
const QRegExp m_nlPres
Definition: eitfixup.h:229
const QRegExp m_grCategNews
Definition: eitfixup.h:297
const QRegExp m_grCategBiography
Definition: eitfixup.h:296
const QRegExp m_ukAllNew
Definition: eitfixup.h:169
const QRegExp m_grCategDocumentary
Definition: eitfixup.h:295
void Fix(DBEventEIT &event) const
Definition: eitfixup.cpp:253
const QRegExp m_nlPersSeparator
Definition: eitfixup.h:230
QString m_rating
Definition: programdata.h:68
uint16_t m_parttotal
Definition: programdata.h:143
void AddPerson(DBPerson::Role, const QString &name)
QString m_programId
Definition: programdata.h:151
const QRegExp m_grCategMusic
Definition: eitfixup.h:299
QMap< QString, QString > m_items
Definition: programdata.h:208
const QRegExp m_comHemPersons
Definition: eitfixup.h:180