//#define SQLLITE_CONNECTION_TEST using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SQLite; using System.Diagnostics; using Enterprise.Logging; using libxmltv; using libxmltv.Interfaces; using libxmltv.Core; namespace GBPVRProgramDatabaseFixer { public interface ISQLLITE { List Programs { get; } List Recordings { get; } List Channels { get; } IDateTimeRange GetProgramsDateRange(List programs); List CreateUpdatedProgramsList(List gbpvr_programs, List xmltv_programs, out List removed_programs); } public class SQLLITE : ISQLLITE { public static ISQLLITE Create(string database, EventHandler OnInstanceCreated) { return new SQLLITE(database, OnInstanceCreated); } #region DATABASE DEFINITIONS public interface ICHANNEL { Int64 oid { get; } String name { get; } String channelID { get; } Int64 channel_number { get; } String favourite_channel { get; } String display_name { get; } } private class CHANNEL : ICHANNEL { public CHANNEL() { BaseDatabaseDefinition.CreateDefault(this); } //public RECORDING_SCHEDULE(SQLiteDataReader r, int index) { BaseDatabaseDefinition.Create(this, r, index); } public static void Create(ref CHANNEL instance, SQLiteDataReader r, int index) { BaseDatabaseDefinition.Create(ref instance, r, index); } #region ICHANNEL members public Int64 oid { get; set; } public String name { get; set; } public String channelID { get; set; } public Int64 channel_number { get; set; } public String favourite_channel { get; set; } public String display_name { get; set; } #endregion } public interface IRECORDING_SCHEDULE { Int64 oid { get; } Int64 programme_oid { get; } Int64 capture_source_oid { get; } Int16 status { get; } String filename { get; } Int64 recording_type { get; } Int64 recording_group { get; } DateTime manual_start_time { get; } DateTime manual_end_time { get; } Int64 manual_channel_oid { get; } Int64 quality_level { get; } Int64 pre_pad_minutes { get; } Int64 post_pad_minutes { get;} Int32 priority { get; } String conversion_profile { get; } } private static class BaseDatabaseDefinition { public static void CreateDefault(T instance) { try { Type t = typeof(T); var props = t.GetProperties(); foreach (var prop in props) { Type prop_type = prop.PropertyType; object field_value = null; try { if (prop_type == typeof(string)) { field_value = string.Empty; } else { field_value = Activator.CreateInstance(prop_type); } } catch (Exception ex) { throw ex; } prop.SetValue(instance, field_value, null); } } catch (Exception ex) { throw ex; } } public static void Create(ref T instance, SQLiteDataReader r, int index) { string field_name = r.GetName(index); Type field_type = r.GetFieldType(index); object field_value = r.GetValue(index); //gLog.Verbose.Debug.WriteLine("Name: '{0}' Type: '{1}' Value: '{2}'", field_name, field_type.Name, field_value == null ? "null" : field_value.ToString()); Type t = typeof(T); var props = t.GetProperties(); foreach (var prop in props) { if (prop.Name.ToLower() == field_name.ToLower()) { if (prop.PropertyType == field_type) { Type db_type = field_value.GetType(); try { if (db_type == typeof(System.DBNull)) { prop.SetValue(instance, null, null); } else { prop.SetValue(instance, field_value, null); } } catch (Exception ex) { throw ex; } } else { gLog.Verbose.Debug.WriteLine("Found Property: {0} but there was a type mismatch. Property Type: '{1}' Expected: '{2}'", prop.Name, prop.PropertyType.Name, field_type.Name); throw new InvalidOperationException(string.Format("Found Property: {0} but there was a type mismatch. Property Type: '{1}' Expected: '{2}'", prop.Name, prop.PropertyType.Name, field_type.Name)); } } } } } private class RECORDING_SCHEDULE : IRECORDING_SCHEDULE { public RECORDING_SCHEDULE() { BaseDatabaseDefinition.CreateDefault(this); } //public RECORDING_SCHEDULE(SQLiteDataReader r, int index) { BaseDatabaseDefinition.Create(this, r, index); } public static void Create(ref RECORDING_SCHEDULE instance, SQLiteDataReader r, int index) { BaseDatabaseDefinition.Create(ref instance, r, index); } #region IRECORDING_SCHEDULE members public Int64 oid { get; set;} public Int64 programme_oid { get; set;} public Int64 capture_source_oid { get; set;} public Int16 status { get; set; } public String filename { get; set; } public Int64 recording_type { get;set; } public Int64 recording_group { get; set;} public DateTime manual_start_time { get; set;} public DateTime manual_end_time { get; set; } public Int64 manual_channel_oid { get; set; } public Int64 quality_level { get; set; } public Int64 pre_pad_minutes { get; set; } public Int64 post_pad_minutes { get; set; } public Int32 priority { get; set; } public String conversion_profile { get; set; } #endregion } public interface IPROGRAMME { Int64 oid { get; set; } String name { get; set; } String sub_title { get; set; } String description { get; set; } DateTime start_time { get; set; } DateTime end_time { get; set; } Int64 channel_oid { get; set; } String unique_identifier { get; set; } String rating { get; set; } IProgramDefinition AsXMLTVProgramDefinition(ISQLLITE sqllite); } private class PROGRAMME : IPROGRAMME { public PROGRAMME() { BaseDatabaseDefinition.CreateDefault(this); } //public PROGRAMME(SQLiteDataReader r, int index) : base(r, index) { } public static void Create(ref PROGRAMME instance, SQLiteDataReader r, int index) { BaseDatabaseDefinition.Create(ref instance, r, index); } #region IPROGRAMME members public Int64 oid { get; set; } public String name { get; set; } public String sub_title { get; set; } public String description { get; set; } public DateTime start_time { get; set; } public DateTime end_time { get; set; } public Int64 channel_oid { get; set; } public String unique_identifier { get; set; } public String rating { get; set; } public IProgramDefinition AsXMLTVProgramDefinition(ISQLLITE sqllite) { ProgramList.ProgramDefintion definition = new ProgramList.ProgramDefintion(); var channel = sqllite.Channels.Find(s => s.oid == this.channel_oid); definition.ChannelName = channel.display_name; definition.ChannelNumber = (int)channel.channel_number; definition.Description = this.description; definition.Start = this.start_time.ToDateTimeString(); definition.Stop = this.end_time.ToDateTimeString(); definition.SubTitle = this.sub_title; definition.Title = this.name; return definition; } #endregion } #endregion private static class TABLES { public const string RECORDING_SCHEDULE = "RECORDING_SCHEDULE"; public const string PROGRAMME = "PROGRAMME"; public const string CHANNEL = "CHANNEL"; } //public SQLLite() { } protected SQLLITE(string database, EventHandler OnInstanceCreated) { this.OnInstanceCreated = OnInstanceCreated; //CreateConnection(database); this.Database = database; if (!CreateDatabaseBackup()) { gLog.Error.WriteLine("Failed to backup database."); return; } ConnectionTest(); ReadChannelData(); ReadRecodringScheduleData(); ReadProgrammeData(); OnCreatedInstance(this, new EventArgs()); } [NonSerialized] private EventHandler _OnInstanceCreated; private EventHandler OnInstanceCreated { get { return _OnInstanceCreated; } set { _OnInstanceCreated = value; } } private void OnCreatedInstance(object sender, EventArgs e) { if (OnInstanceCreated != null) { OnInstanceCreated.Invoke(sender, e); } } private string Database; #region ISQLLITE members public List Programs { get; private set; } public List Recordings { get; private set; } public List Channels { get; private set; } public IDateTimeRange GetProgramsDateRange(List programs) { var list = new List(programs.ToArray()); DateTime first = new DateTime(); DateTime last = new DateTime(); first = list.OrderBy(s => s.start_time).ToList().First().start_time; last = list.OrderBy(s => s.start_time).ToList().Last().start_time; gLog.Verbose.Debug.WriteLine("\tFirst: {0} = ({1})", first.ToString("yyyy/MM/dd HH:mm:ss.fffffff"), first.ToDateTimeString()); gLog.Verbose.Debug.WriteLine("\tLast: {0} = ({1})", last.ToString("yyyy/MM/dd HH:mm:ss.fffffff"), last.ToDateTimeString()); var range = DateTimeRange.Create(first, last); return range; } public List CreateUpdatedProgramsList(List gbpvr_programs, List xmltv_programs, out List gbpvr_programs_not_found) { gbpvr_programs_not_found = new List(); gbpvr_programs = gbpvr_programs.OrderBy(s => s.start_time).ToList(); List source_valid = new List(); //if (range == null) //{ // gLog.Warn.WriteLine("The DateTimeRange passed in is null...returning the original program list"); // return list; //} //gLog.Warn.WriteLine("FilterProgramsByDateRange has not been implemented"); double total = gbpvr_programs.Count; double index = 0; double progress = 0; foreach (var program in gbpvr_programs) { ////if (program.start_time >= range.Start && //// program.start_time <= range.End) ////{ //// list2.Add(program); ////} ////else ////{ //// removed_programs.Add(program); ////} //progress = 100.0 * (index / total); //gLog.ReportProgress(this, new ReportProgressEventArgs((int)progress, string.Format("Filtering GBPVR Programs: {0:00}%", (int)progress))); //var xmltv_entry = program.AsXMLTVProgramDefinition(this); //if (xmltv_programs.Contains(xmltv_entry)) //{ // source_valid.Add(program); //} //else //{ // gbpvr_programs_not_found.Add(program); //} //index++; var channel_oid = program.channel_oid; var channel = this.Channels.Find(s => s.oid == channel_oid); var start_date = program.start_time; var xmltv_entry = xmltv_programs.Find(s => s.ChannelNumber == channel.channel_number && s.Start == start_date.ToDateTimeString()); if (xmltv_entry == null) { gbpvr_programs_not_found.Add(program); } else { var updated_program = program; updated_program.description = xmltv_entry.Description; updated_program.end_time = DateTime.Parse(xmltv_entry.Stop); updated_program.name = xmltv_entry.Title; updated_program.start_time = DateTime.Parse(xmltv_entry.Start); updated_program.sub_title = xmltv_entry.SubTitle; source_valid.Add(updated_program); } } //for (int i = 0; i < programs.Count(); i++) //{ // var gbpvr_entry = gbpvr[i]; // var xmltv_entry = gbpvr_entry.AsXMLTVProgramDefinition(sqlite); // if (!xmltv[i].Equals(xmltv_entry)) // { // gLog.Warn.WriteLine("Warning GBPVR Program oid: {0} might be invalid", gbpvr_entry.oid); // } //} source_valid = source_valid.OrderBy(s => s.channel_oid).ThenBy(s => s.start_time).ToList(); gbpvr_programs_not_found = gbpvr_programs_not_found.OrderBy(s => s.channel_oid).ThenBy(s => s.start_time).ToList(); gLog.Info.WriteLine("Total XMLTV Programs: 0x{0:x8}", xmltv_programs.Count); gLog.Info.WriteLine("Updated: 0x{0:x8} GB-PVR Programs", source_valid.Count); gLog.Info.WriteLine("Could not find: 0x{0:x8} GB-PVR Programs", gbpvr_programs_not_found.Count); gLog.Info.WriteLine("Total GB-PVR Programs: 0x{0:x8}", source_valid.Count + gbpvr_programs_not_found.Count); return source_valid; } #endregion private string CreateConnectionString() { string connection_string = string.Format("Data Source={0}", this.Database); return connection_string; } private SQLiteConnection CreateConnection() { SQLiteConnection connection = new SQLiteConnection(CreateConnectionString()); return connection; } [Conditional("SQLLITE_CONNECTION_TEST")] private void ConnectionTest() { try { using (SQLiteConnection con = CreateConnection()) { con.Open(); string command_text = string.Format("select * from {0};", TABLES.CHANNEL); gLog.Verbose.Debug.WriteLine("Executing Command: '{0}'", command_text); using (SQLiteCommand cmd = new SQLiteCommand(command_text, con)) { using (SQLiteDataReader r = cmd.ExecuteReader()) { if (!r.HasRows) { gLog.Warn.WriteLine("Query: '{0}' returned no rows.", cmd.CommandText); } else { while (r.Read()) { for (int i = 0; i < r.FieldCount; i++) { string field_name = r.GetName(i); Type field_type = r.GetFieldType(i); object field_value = r.GetValue(i); gLog.Verbose.Debug.WriteLine("Name: '{0}' Type: '{1}' Value: '{2}'", field_name, field_type.Name, field_value == null ? "null" : field_value.ToString()); } break; } } } } con.Clone(); } OnCreatedInstance(this, new EventArgs()); } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } private bool CreateDatabaseBackup() { try { string backup_file = string.Format("{0}.{1}", this.Database, DateTime.Now.ToString("yyyyMMddHHmmss")); gLog.Info.WriteLine("Creating Database backup..."); gLog.Info.WriteLine("\tSource: {0}", this.Database); gLog.Info.WriteLine("\tDestination: {0}", backup_file); System.IO.File.Copy(this.Database, backup_file); return true; } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); return false; } } private void ReadChannelData() { try { List channels = new List(); using (SQLiteConnection con = CreateConnection()) { con.Open(); string command_text = string.Format("select * from {0};", TABLES.CHANNEL); gLog.Verbose.Debug.WriteLine("Executing Command: '{0}'", command_text); using (SQLiteCommand cmd = new SQLiteCommand(command_text, con)) { using (SQLiteDataReader r = cmd.ExecuteReader()) { if (!r.HasRows) { gLog.Warn.WriteLine("Query: '{0}' returned no rows.", cmd.CommandText); } else { while (r.Read()) { CHANNEL channel = new CHANNEL(); for (int i = 0; i < r.FieldCount; i++) { CHANNEL.Create(ref channel, r, i); } channels.Add(channel); } } } } con.Clone(); } this.Channels = channels; } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } private void ReadProgrammeData() { try { List programs = new List(); using (SQLiteConnection con = CreateConnection()) { con.Open(); string command_text = string.Format("select * from {0};", TABLES.PROGRAMME); gLog.Verbose.Debug.WriteLine("Executing Command: '{0}'", command_text); using (SQLiteCommand cmd = new SQLiteCommand(command_text, con)) { using (SQLiteDataReader r = cmd.ExecuteReader()) { if (!r.HasRows) { gLog.Warn.WriteLine("Query: '{0}' returned no rows.", cmd.CommandText); } else { while (r.Read()) { PROGRAMME program = new PROGRAMME(); for (int i = 0; i < r.FieldCount; i++) { PROGRAMME.Create(ref program, r, i); } programs.Add(program); } } } } con.Clone(); } this.Programs = programs; } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } private void ReadRecodringScheduleData() { try { List recordings = new List(); using (SQLiteConnection con = CreateConnection()) { con.Open(); string command_text = string.Format("select * from {0};", TABLES.RECORDING_SCHEDULE); gLog.Verbose.Debug.WriteLine("Executing Command: '{0}'", command_text); using (SQLiteCommand cmd = new SQLiteCommand(command_text, con)) { using (SQLiteDataReader r = cmd.ExecuteReader()) { if (!r.HasRows) { gLog.Warn.WriteLine("Query: '{0}' returned no rows.", cmd.CommandText); } else { while (r.Read()) { RECORDING_SCHEDULE recording = new RECORDING_SCHEDULE(); for (int i = 0; i < r.FieldCount; i++) { RECORDING_SCHEDULE.Create(ref recording, r, i); } recordings.Add(recording); } } } } con.Clone(); } this.Recordings = recordings; } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } } }