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