1 |
#define OVERRIDE_COMMANDLINE_ARGUMENTS // when defined will override supplied commandline args |
2 |
//#define ENABLE_SCHEDULDED_RECORDINGS_FIXUP // when defined will enable calls to CheckScheduledRecordingsForDiscrepancies |
3 |
|
4 |
#if DEBUG |
5 |
//#define ENABLE_VERBOSE_DEBUG_WHEN_DEBUGGING // when defined and debugging will enable verbose debug log messages |
6 |
#endif |
7 |
using System; |
8 |
using System.Collections.Generic; |
9 |
using System.Text; |
10 |
using System.Linq; |
11 |
using Enterprise.Logging; |
12 |
using System.Windows.Forms; |
13 |
using System.Diagnostics; |
14 |
using System.IO; |
15 |
using libxmltv.Core; |
16 |
using libxmltv.Interfaces; |
17 |
using libxmltv; |
18 |
using GBPVR.Backend.Common; |
19 |
namespace GBPVRProgramDatabaseFixer |
20 |
{ |
21 |
class Program |
22 |
{ |
23 |
const long MAX_LOG_FILESIZE_IN_BYTES = 250000; //250kb max |
24 |
static void TruncateLogFile(FileInfo log_file) |
25 |
{ |
26 |
if (!log_file.Exists) |
27 |
{ |
28 |
gLog.CreateLog(log_file.FullName, false, LogLevel.kLogLevel_All, new LogWriter.LogStream()); |
29 |
} |
30 |
else |
31 |
{ |
32 |
if (log_file.Length > MAX_LOG_FILESIZE_IN_BYTES) |
33 |
{ |
34 |
string match = string.Format("{0}.*", log_file.Name); |
35 |
var files = Directory.GetFiles(log_file.Directory.FullName, match).ToList(); |
36 |
files.RemoveAt(0); |
37 |
files.TrimExcess(); |
38 |
int count = files.Count; |
39 |
if (log_file.Exists) |
40 |
{ |
41 |
File.Copy(log_file.FullName, string.Format("{0}.{1}", log_file.FullName, count)); |
42 |
} |
43 |
gLog.CreateLog(log_file.FullName, true, LogLevel.kLogLevel_All, new LogWriter.LogStream()); |
44 |
} |
45 |
else |
46 |
{ |
47 |
gLog.CreateLog(log_file.FullName, false, LogLevel.kLogLevel_All, new LogWriter.LogStream()); |
48 |
} |
49 |
} |
50 |
} |
51 |
|
52 |
static ISQLLITE sqlite; |
53 |
static string XMLTV_FILE = ""; |
54 |
static string GBPVR_DATABASE = ""; |
55 |
|
56 |
//static bool LOADING_XMLTV_FILE = false; |
57 |
static bool XMLTV_INSTANCE_CREATED = false; |
58 |
//static int LAST_REPORTED_XMLTV_PROGRESS = 0; |
59 |
|
60 |
|
61 |
//static bool LOADING_GBPVR_DATABASE = false; |
62 |
static bool SQLLIST_INSTANCE_CREATED = false; |
63 |
//static int LAST_REPORTED_SQLLITE_PROGRESS = 0; |
64 |
|
65 |
//static int LAST_REPORTED_PROGRESS = 0; |
66 |
|
67 |
static FileInfo fi_XMLTVFILE; |
68 |
static FileInfo fi_GBPVRDATABASE; |
69 |
static void CreateLog() |
70 |
{ |
71 |
string log_path = Application.StartupPath; |
72 |
string log_filename = string.Format("{0}.log", typeof(Program).Assembly.GetName().Name); |
73 |
FileInfo log_file = new FileInfo(string.Format(@"{0}\{1}", log_path, log_filename)); |
74 |
TruncateLogFile(log_file); |
75 |
#if DEBUG |
76 |
LogLevel gLevel = gLog.LogLevel; |
77 |
#if ENABLE_VERBOSE_DEBUG_WHEN_DEBUGGING |
78 |
gLevel |= LogLevel.kLogLevel_VerboseDebug; |
79 |
#else |
80 |
gLevel = gLevel & ~LogLevel.kLogLevel_VerboseDebug; |
81 |
#endif |
82 |
gLevel |= LogLevel.kLogLevel_Debug; |
83 |
gLog.SetLogLevel(gLevel); |
84 |
#else |
85 |
LogLevel gLevel = LogLevel.kLogLevel_Default; // set the default log level: Info, Warn, Error, Debug |
86 |
// it is OK for kLogLevel_Debug to be set in Release mode ... must of the chatty messages are from kLogLevel_VerboseDebug |
87 |
gLevel &= ~LogLevel.kLogLevel_Debug; // ensure this is not set, ever in release mode |
88 |
gLevel &= ~LogLevel.kLogLevel_VerboseDebug; // ensure this is not set, ever in release mode |
89 |
gLog.SetLogLevel(gLevel); |
90 |
#endif |
91 |
gLog.ReportProgressEvent += new EventHandler<ReportProgressEventArgs>(gLog_ReportProgress); |
92 |
} |
93 |
|
94 |
[Conditional("OVERRIDE_COMMANDLINE_ARGUMENTS")] |
95 |
static void CreateDebugCommandlineArgs(ref List<string> cargs) |
96 |
{ |
97 |
cargs = new List<string>(); |
98 |
cargs.Add(string.Format("--xmltv_file=\"{0}\"", @"c:\EPG Guide\Guide\tvguide.xml")); |
99 |
cargs.Add(string.Format("--gbprv_db=\"{0}\"", @"c:\Program Files (x86)\Devnz\GBPVR\gbpvr.db3")); |
100 |
} |
101 |
|
102 |
static List<string> CreateCommandlineArgs(string[] args) |
103 |
{ |
104 |
List<string> cargs = new List<string>(args); |
105 |
CreateDebugCommandlineArgs(ref cargs); |
106 |
return cargs; |
107 |
} |
108 |
|
109 |
static void Main(string[] args) |
110 |
{ |
111 |
CreateLog(); |
112 |
var cargs = CreateCommandlineArgs(args); |
113 |
foreach (var carg in cargs) |
114 |
{ |
115 |
if (carg.ToLower().Contains("--xmltv_file=")) |
116 |
{ |
117 |
XMLTV_FILE = carg.Replace("--xmltv_file=", "").Replace("\"",""); |
118 |
gLog.Info.WriteLine("XMLTV FILE: '{0}'", XMLTV_FILE); |
119 |
} |
120 |
else if (carg.ToLower().Contains("--gbprv_db=")) |
121 |
{ |
122 |
GBPVR_DATABASE = carg.Replace("--gbprv_db=", "").Replace("\"", ""); |
123 |
gLog.Info.WriteLine("GBPVR DATABASE: '{0}'", GBPVR_DATABASE); |
124 |
} |
125 |
else |
126 |
{ |
127 |
gLog.Warn.WriteLine("Unknown commandline option: {0}", carg); |
128 |
} |
129 |
} |
130 |
|
131 |
LoadXMLTVFile(); |
132 |
LoadGBPVRDatabase(); |
133 |
PerformDatabaseProcessing(); |
134 |
} |
135 |
|
136 |
static void ConsoleOverwritePreviosLine(string format, params object[] args) |
137 |
{ |
138 |
Console.WriteLine(format,args); |
139 |
Console.SetCursorPosition(0, Console.CursorTop - 1); |
140 |
} |
141 |
|
142 |
static void gLog_ReportProgress(object sender, ReportProgressEventArgs e) |
143 |
{ |
144 |
//object k = e.UserState; // we will assum that is a status message |
145 |
//if (k == null) // assume we do not have a user status message (ie: is only a progress message) |
146 |
//{ |
147 |
// if (sender == null) { ConsoleOverwritePreviosLine("Progress: {0} ", e.Progress); } |
148 |
// else { ConsoleOverwritePreviosLine("{0}: Progress: {1:00}%", sender.GetType().Name, e.Progress); } |
149 |
//} |
150 |
//else // assume we have a user status message |
151 |
//{ |
152 |
// if (sender == null) { ConsoleOverwritePreviosLine("{0} ", k.ToString()); } |
153 |
// else { ConsoleOverwritePreviosLine("{0}: {1}", sender.GetType().Name, k.ToString()); } |
154 |
//} |
155 |
} |
156 |
static void LoadXMLTVFile() |
157 |
{ |
158 |
//LOADING_XMLTV_FILE = true; |
159 |
if (string.IsNullOrEmpty(XMLTV_FILE)) |
160 |
{ |
161 |
gLog.Error.WriteLine("XMLTV File is either a null or empty string."); |
162 |
//LOADING_XMLTV_FILE = false; |
163 |
return; |
164 |
} |
165 |
fi_XMLTVFILE = new FileInfo(XMLTV_FILE); |
166 |
if (!fi_XMLTVFILE.Exists) |
167 |
{ |
168 |
gLog.Error.WriteLine("Could not find XMLTV File: {0}", fi_XMLTVFILE.FullName); |
169 |
//LOADING_XMLTV_FILE = false; |
170 |
return; |
171 |
} |
172 |
|
173 |
XMLTV.Create(fi_XMLTVFILE.FullName, new EventHandler<EventArgs>(XMLTV_OnInstanceCreated)); |
174 |
while (!XMLTV_INSTANCE_CREATED) { Application.DoEvents(); } |
175 |
//LOADING_XMLTV_FILE = false; |
176 |
} |
177 |
static void XMLTV_OnInstanceCreated(object sender, EventArgs e) { XMLTV_INSTANCE_CREATED = true; } |
178 |
|
179 |
static void LoadGBPVRDatabase() |
180 |
{ |
181 |
//LOADING_GBPVR_DATABASE = true; |
182 |
if (string.IsNullOrEmpty(GBPVR_DATABASE)) |
183 |
{ |
184 |
gLog.Error.WriteLine("GBPVR Datbase is either a null or empty string."); |
185 |
//LOADING_GBPVR_DATABASE = false; |
186 |
return; |
187 |
} |
188 |
fi_GBPVRDATABASE = new FileInfo(GBPVR_DATABASE); |
189 |
if (!fi_GBPVRDATABASE.Exists) |
190 |
{ |
191 |
gLog.Error.WriteLine("Could not find GBPVR Database: {0}", fi_GBPVRDATABASE.FullName); |
192 |
//LOADING_GBPVR_DATABASE = false; |
193 |
return; |
194 |
} |
195 |
sqlite = SQLLITE.Create(fi_GBPVRDATABASE.FullName, new EventHandler<EventArgs>(SQLLITE_OnInstanceCreated)); |
196 |
while (!SQLLIST_INSTANCE_CREATED) { Application.DoEvents(); } |
197 |
//LOADING_GBPVR_DATABASE = false; |
198 |
} |
199 |
static void SQLLITE_OnInstanceCreated(object sender, EventArgs e) { SQLLIST_INSTANCE_CREATED = true; } |
200 |
|
201 |
static void PerformDatabaseProcessing() |
202 |
{ |
203 |
var sqllite_channels = sqlite.Channels; |
204 |
var sqllite_recordings = sqlite.Recordings; |
205 |
var sqllite_programs = sqlite.Programs; |
206 |
Type datatype; |
207 |
var xmlt_raw_program_data = (IProgramDefinitionList)XMLTV.CreateBindingSourceFromData(XMLTV.GetPrograms(), out datatype); |
208 |
var xmltv_programs = xmlt_raw_program_data.ToList().OrderBy(p => DateTime.Parse(p.Start)).ToList(); |
209 |
var sqllite_programs_startdate_range = sqlite.GetProgramsDateRange(sqllite_programs); |
210 |
var xmltv_programs_startdate_range = GetXMLTVProgramStartDateRange(xmltv_programs); |
211 |
var gbpvr_invalid_programs = new List<SQLLITE.IPROGRAMME>(); |
212 |
var gbpvr_valid_programs = sqlite.FixGBPVRProgramsDatabase(sqllite_programs, xmltv_programs, out gbpvr_invalid_programs); |
213 |
sqlite.RemoveOldGBPVRPrograms(gbpvr_invalid_programs); |
214 |
sqlite.UpdateGBPVRPrograms(gbpvr_valid_programs); |
215 |
|
216 |
sqllite_programs.Clear(); |
217 |
gbpvr_valid_programs.ForEach(s=>sqllite_programs.Add(s.NewProgram)); |
218 |
|
219 |
CheckScheduledRecordingsForDiscrepancies(sqllite_recordings,sqllite_programs); |
220 |
} |
221 |
|
222 |
static IDateTimeRange GetXMLTVProgramStartDateRange(List<libxmltv.Interfaces.IProgramDefinition> programs) |
223 |
{ |
224 |
IDateTimeRange range = DateTimeRange.Create(); |
225 |
var list = new List<libxmltv.Interfaces.IProgramDefinition>(programs.ToArray()); |
226 |
DateTime first = new DateTime(); |
227 |
DateTime last = new DateTime(); |
228 |
first = DateTime.Parse(list.OrderBy(s => DateTime.Parse(s.Start)).ToList().First().Start); |
229 |
last = DateTime.Parse(list.OrderBy(s => DateTime.Parse(s.Start)).ToList().Last().Start); |
230 |
gLog.Verbose.Debug.WriteLine("\tFirst: {0} = ({1})", first.ToString("yyyy/MM/dd HH:mm:ss.fffffff"), first.ToDateTimeString()); |
231 |
gLog.Verbose.Debug.WriteLine("\tLast: {0} = ({1})", last.ToString("yyyy/MM/dd HH:mm:ss.fffffff"), last.ToDateTimeString()); |
232 |
range = DateTimeRange.Create(first, last); |
233 |
return range; |
234 |
} |
235 |
|
236 |
static void CheckScheduledRecordingsForDiscrepancies(List<SQLLITE.IRECORDING_SCHEDULE> recordings, List<SQLLITE.IPROGRAMME> programs) |
237 |
{ |
238 |
#if !ENABLE_SCHEDULDED_RECORDINGS_FIXUP |
239 |
gLog.Warn.WriteLine("WANRING: Checking scheduled recordings for errors (and then deleting them) has been disabled."); |
240 |
#else |
241 |
List<SQLLITE.IRECORDING_SCHEDULE> recordings_to_delete = new List<SQLLITE.IRECORDING_SCHEDULE>(); |
242 |
foreach (var recording in recordings) |
243 |
{ |
244 |
RecordingStatus status = (RecordingStatus)recording.status; |
245 |
RecordingType type = (RecordingType)recording.recording_type; |
246 |
|
247 |
// ignore any recording whose type is not: RecordingType.TYPE_RECORD_ONCE |
248 |
if (type != RecordingType.TYPE_RECORD_ONCE) { continue; } |
249 |
// ignore any recording whose status is not: RecordingStatus.STATUS_PENDING and not: RecordingStatus.STATUS_IN_PROGRESS |
250 |
if (status != RecordingStatus.STATUS_PENDING && status != RecordingStatus.STATUS_IN_PROGRESS) { continue; } |
251 |
// only fix recordings that have a recording group greater than 0 (zero) |
252 |
if (recording.recording_group == 0) { continue; } |
253 |
// verify data for this recording |
254 |
var recording_oid = recording.oid; |
255 |
var programme_oid = recording.programme_oid; |
256 |
var filename = recording.filename; |
257 |
var manual_start_time = recording.manual_start_time; |
258 |
var manual_end_time = recording.manual_end_time; |
259 |
var manual_channel_oid = recording.manual_channel_oid; |
260 |
|
261 |
// lookup program by oid |
262 |
var entry = programs.Find(s => s.oid == programme_oid); |
263 |
if (entry == null) |
264 |
{ |
265 |
gLog.Warn.WriteLine("Unable to find program with oid: '{0}' for recording with oid: '{1}' -- assuming it should be deleted", programme_oid, recording_oid); |
266 |
//throw new NullReferenceException(string.Format("Unable to find program with oid: '{0}' for recording with oid: '{1}'", programme_oid, recording_oid)); |
267 |
//deleted_recordings.Add(recording); |
268 |
} |
269 |
else |
270 |
{ |
271 |
recordings_to_delete.Add(recording); |
272 |
} |
273 |
} |
274 |
recordings_to_delete.TrimExcess(); |
275 |
if (recordings_to_delete.Count > 0) |
276 |
{ |
277 |
gLog.Info.WriteLine("Found {0} recordings to delete.", recordings_to_delete.Count); |
278 |
sqlite.DeleteGBPVRScheduledRecordings(recordings_to_delete); |
279 |
} |
280 |
try |
281 |
{ |
282 |
|
283 |
// taken from: Config.EpgUpdateProgress.method_1() |
284 |
//Zap2itEpgReader.smethod_0(); |
285 |
//GClass4.smethod_0().method_14(); |
286 |
Zap2itEpgReader.x9a6781c43845a63b(); |
287 |
x396614b3dae3b1da.x479a7b07c9d5bd70().xf03e555cf1814572(); |
288 |
} |
289 |
catch (Exception ex) |
290 |
{ |
291 |
gLog.Error.WriteLine(ex.ToString()); |
292 |
} |
293 |
#endif |
294 |
} |
295 |
} |
296 |
} |