private static bool BuildLineupServices() { // build a comparison dictionary to determine service id for each channel from XMLTV Dictionary <string, string> displayNameChannelIDs = new Dictionary <string, string>(); foreach (XmltvChannel channel in xmltv.Channels) { foreach (XmltvText displayName in channel.DisplayNames) { try { displayNameChannelIDs.Add(displayName.Text.ToUpper(), channel.Id); } catch { } } } // find the stationid for each tuner channel for the MXF foreach (MxfLineup lineup in Common.mxf.With[0].Lineups) { foreach (MxfChannel channel in lineup.channels) { string match = string.Format("{0}{1} {2}", channel.Number, (channel.SubNumber > 0) ? "." + channel.SubNumber.ToString() : string.Empty, channel.MatchName.ToUpper()); if (displayNameChannelIDs.TryGetValue(match, out string serviceid) || displayNameChannelIDs.TryGetValue(match.Split(' ')[0], out serviceid)) { channel.stationId = GetStationIdFromChannelId(serviceid); MxfService service = Common.mxf.With[0].getService(channel.stationId); channel.Service = service.Id; service.Name = channel.MatchName; service.mxfScheduleEntries.Service = service.Id; service.isHD = channel.isHD; } } } // complete the service information foreach (XmltvChannel channel in xmltv.Channels) { MxfService service = Common.mxf.With[0].getService(GetStationIdFromChannelId(channel.Id)); // add guide image if available if (channel.Icons != null && channel.Icons.Count > 0) { service.LogoImage = Common.mxf.With[0].getGuideImage(channel.Icons[0].src).Id; } // this makes the assumption that the callsign will be first service.CallSign = channel.DisplayNames.First().Text; //// this makes the assumption that the affiliate will be last //string text = channel.DisplayNames.Last().Text.Split(' ')[0]; //if (!int.TryParse(text, out int dummy1) && !double.TryParse(text, out double dummy2)) //{ // service.Affiliate = Common.mxf.With[0].getAffiliateId(channel.DisplayNames.Last().Text); //} } // clean up the channels foreach (MxfLineup lineup in Common.mxf.With[0].Lineups) { List <MxfChannel> channelsToRemove = new List <MxfChannel>(); foreach (MxfChannel channel in lineup.channels) { if (!string.IsNullOrEmpty(channel.match)) { channel.MatchName = channel.match; } if (string.IsNullOrEmpty(channel.Service)) { channelsToRemove.Add(channel); } } if (channelsToRemove.Count > 0) { foreach (MxfChannel channel in channelsToRemove) { lineup.channels.Remove(channel); } } } return(true); }
private static bool BuildScheduleEntries() { foreach (XmltvProgramme program in xmltv.Programs) { // determine which service the schedule entry is for MxfService mxfService = Common.mxf.With[0].getService(GetStationIdFromChannelId(program.Channel)); // determine start time DateTime dtStart = DateTime.ParseExact(program.Start, "yyyyMMddHHmmss zzz", CultureInfo.InvariantCulture).ToUniversalTime(); DateTime dtStop = DateTime.ParseExact(program.Stop, "yyyyMMddHHmmss zzz", CultureInfo.InvariantCulture).ToUniversalTime(); string startTime = dtStart.ToString("yyyy-MM-ddTHH:mm:ss"); if (dtStart == mxfService.mxfScheduleEntries.endTime) { startTime = null; } // prepopulate some of the program MxfProgram mxfProgram = new MxfProgram() { index = Common.mxf.With[0].Programs.Count + 1, episodeInfo = GetProgramEpisodeInformation(program.EpisodeNums), IsPremiere = (program.Premiere != null) ? "true" : null, IsSeasonPremiere = (program.Premiere?.Text != null && program.Premiere.Text.ToLower().Equals("season premiere")) ? "true" : null, IsSeriesPremiere = (program.Premiere?.Text != null && program.Premiere.Text.ToLower().Equals("series premiere")) ? "true" : null, _newDate = (program.New != null) ? dtStart.ToLocalTime().ToString("yyyy-MM-dd") : null, ActorRole = new List <MxfPersonRank>(), WriterRole = new List <MxfPersonRank>(), GuestActorRole = new List <MxfPersonRank>(), HostRole = new List <MxfPersonRank>(), ProducerRole = new List <MxfPersonRank>(), DirectorRole = new List <MxfPersonRank>() //IsSeasonFinale = , //IsSeriesFinale = , }; // if dd_progid is not valid, don't add it if (string.IsNullOrEmpty(mxfProgram.episodeInfo.TMSID)) { continue; } // populate the schedule entry and create program entry as required mxfService.mxfScheduleEntries.ScheduleEntry.Add(new MxfScheduleEntry() { AudioFormat = GetAudioFormat(program.Audio), Duration = (int)((dtStop - dtStart).TotalSeconds), IsCC = program.Subtitles.Count > 0 ? "true" : null, IsHdtv = (program.Video?.Quality != null && program.Video.Quality.ToLower().Equals("hdtv")) ? "true" : mxfService.isHD ? "true" : null, IsLive = (program.Live != null) ? "true" : null, IsPremiere = (program.Premiere != null) ? "true" : null, IsRepeat = (program.New == null && !mxfProgram.episodeInfo.Type.Equals("MV")) ? "true" : null, Part = (mxfProgram.episodeInfo.NumberOfParts > 1) ? mxfProgram.episodeInfo.PartNumber.ToString() : null, Parts = (mxfProgram.episodeInfo.NumberOfParts > 1) ? mxfProgram.episodeInfo.NumberOfParts.ToString() : null, Program = Common.mxf.With[0].getProgram(mxfProgram.episodeInfo.TMSID, mxfProgram).Id, StartTime = startTime, TvRating = GetUsTvRating(program.Rating) //Is3D = , //IsBlackout = , //IsClassroom = , //IsDelay = , //IsDvs = , //IsEnhanced = , //IsFinale = , //IsHdtvSimulCast = , //IsInProgress = , //IsLetterbox = , //IsLiveSports = , //IsSap = , //IsSubtitled = , //IsTape = , //IsSigned = }); BuildProgram(mxfProgram.episodeInfo.TMSID, program); } return(true); }
public static XmltvChannel BuildXmltvChannel(MxfService mxfService) { // initialize the return channel var ret = new XmltvChannel { Id = $"EPG123.{mxfService.StationId}.schedulesdirect.org", DisplayNames = new List <XmltvText>() }; // minimum display names // 5MAXHD // 5 StarMAX HD East ret.DisplayNames.Add(new XmltvText { Text = mxfService.CallSign }); if (!mxfService.Name.Equals(mxfService.CallSign)) { ret.DisplayNames.Add(new XmltvText { Text = mxfService.Name }); } // add channel number if requested if (config.XmltvIncludeChannelNumbers) { var numbers = new HashSet <string>(); foreach (var mxfLineup in SdMxf.With.Lineups) { foreach (var mxfChannel in mxfLineup.channels) { if (mxfChannel.Service != mxfService.Id || mxfChannel.Number <= 0) { continue; } var num = $"{mxfChannel.Number}" + (mxfChannel.SubNumber > 0 ? $".{mxfChannel.SubNumber}" : ""); if (!numbers.Add(num)) { continue; } ret.DisplayNames.Add(new XmltvText { Text = num + " " + mxfService.CallSign }); ret.DisplayNames.Add(new XmltvText { Text = num }); } } } // add affiliate if present var affiliate = mxfService.mxfAffiliate?.Name; if (!string.IsNullOrEmpty(affiliate) && !mxfService.Name.Equals(affiliate)) { ret.DisplayNames.Add(new XmltvText { Text = affiliate }); } // add logo if available if (mxfService.extras.ContainsKey("logo")) { ret.Icons = new List <XmltvIcon> { new XmltvIcon { Src = mxfService.extras["logo"].Url, Height = mxfService.extras["logo"].Height, Width = mxfService.extras["logo"].Width } }; } return(ret); }
private static bool buildLineupServices() { // query what lineups client is subscribed to SdLineupResponse clientLineups = sdAPI.sdGetLineups(); if (clientLineups == null) { return(false); } // determine if there are custom lineups to consider if (File.Exists(Helper.Epg123CustomLineupsXmlPath)) { CustomLineups customLineups = new CustomLineups(); using (StreamReader stream = new StreamReader(Helper.Epg123CustomLineupsXmlPath, Encoding.Default)) { XmlSerializer serializer = new XmlSerializer(typeof(CustomLineups)); TextReader reader = new StringReader(stream.ReadToEnd()); customLineups = (CustomLineups)serializer.Deserialize(reader); reader.Close(); } foreach (CustomLineup lineup in customLineups.CustomLineup) { if (!config.IncludedLineup.Contains(lineup.Lineup)) { continue; } customLineup = lineup; clientLineups.Lineups.Add(new SdLineup() { Lineup = lineup.Lineup, Name = lineup.Name, Transport = string.Empty, Location = lineup.Location, Uri = "CUSTOM", IsDeleted = false }); customMap = new SdStationMapResponse(); customMap.Map = new List <SdLineupMap>(); customMap.Stations = new List <SdLineupStation>(); customMap.Metadata = new sdMetadata() { Lineup = lineup.Lineup }; } } // reset counters processedObjects = 0; totalObjects = clientLineups.Lineups.Count; reportProgress(); // process lineups Logger.WriteMessage(string.Format("Entering buildLineupServices() for {0} lineups.", clientLineups.Lineups.Count)); foreach (SdLineup clientLineup in clientLineups.Lineups) { bool flagCustom = (!string.IsNullOrEmpty(clientLineup.Uri) && clientLineup.Uri.Equals("CUSTOM")); ++processedObjects; reportProgress(); // request the lineup's station maps SdStationMapResponse lineupMap = null; if (!flagCustom) { lineupMap = sdAPI.sdGetStationMaps(clientLineup.Lineup); if (lineupMap == null) { continue; } foreach (SdLineupStation station in lineupMap.Stations) { if (!allStations.ContainsKey(station.StationID)) { allStations.Add(station.StationID, station); } } } if (!config.IncludedLineup.Contains(clientLineup.Lineup)) { Logger.WriteVerbose(string.Format("Subscribed lineup {0} has been EXCLUDED from download and processing.", clientLineup.Lineup)); continue; } else if (clientLineup.IsDeleted) { Logger.WriteWarning(string.Format("Subscribed lineup {0} has been DELETED at the headend.", clientLineup.Lineup)); continue; } else if (flagCustom) { foreach (CustomStation station in customLineup.Station) { SdLineupStation lineupStation; if (allStations.TryGetValue(station.StationId, out lineupStation)) { customMap.Map.Add(new SdLineupMap() { StationID = station.StationId, AtscMajor = int.Parse(station.Number), AtscMinor = int.Parse(station.Subnumber) }); customStations.Add(station.StationId); customMap.Stations.Add(lineupStation); } else if (!string.IsNullOrEmpty(station.Alternate) && allStations.TryGetValue(station.Alternate, out lineupStation)) { customMap.Map.Add(new SdLineupMap() { StationID = station.Alternate, AtscMajor = int.Parse(station.Number), AtscMinor = int.Parse(station.Subnumber) }); customStations.Add(station.Alternate); customMap.Stations.Add(lineupStation); } } lineupMap = customMap; Logger.WriteVerbose(string.Format("Successfully retrieved the station mapping for lineup {0}.", clientLineup.Lineup)); } if (lineupMap == null) { return(false); } int lineupIndex = sdMxf.With[0].Lineups.Count; sdMxf.With[0].Lineups.Add(new MxfLineup() { index = lineupIndex + 1, Uid = clientLineup.Lineup, Name = "EPG123 " + clientLineup.Name + " (" + clientLineup.Location + ")", channels = new List <MxfChannel>() }); // build the services and lineup foreach (SdLineupStation station in lineupMap.Stations) { // check if station should be downloaded and processed if (!flagCustom) { if ((station == null) || (excludedStations.Contains(station.StationID) && !customStations.Contains(station.StationID))) { continue; } if (!includedStations.Contains(station.StationID) && !config.AutoAddNew) { Logger.WriteWarning(string.Format("**** Lineup {0} ({1}) has added station {2} ({3}). ****", clientLineup.Name, clientLineup.Location, station.StationID, station.Callsign)); continue; } } // build the service if necessary MxfService mxfService = sdMxf.With[0].getService(station.StationID); if (string.IsNullOrEmpty(mxfService.CallSign)) { // add callsign and station name mxfService.CallSign = station.Callsign; mxfService.Name = station.Name; // add affiliate if available if (!string.IsNullOrEmpty(station.Affiliate)) { mxfService.Affiliate = sdMxf.With[0].getAffiliateId(station.Affiliate); } // set the ScheduleEntries service id mxfService.mxfScheduleEntries.Service = mxfService.Id; // add station logo if available and allowed string logoPath = string.Format("{0}\\{1}.png", Helper.Epg123LogosFolder, station.Callsign); if (config.IncludeSDLogos) { // make sure logos directory exists if (!Directory.Exists(Helper.Epg123LogosFolder)) { Directory.CreateDirectory(Helper.Epg123LogosFolder); } // add the existing logo or download the new logo if available if (File.Exists(logoPath)) { mxfService.LogoImage = sdMxf.With[0].getGuideImage("file://" + logoPath, getStringEncodedImage(logoPath)).Id; } else { string url = string.Empty; if ((station.StationLogos != null) && (station.StationLogos.Count > 0)) { // the second station logo is typically the best contrast url = station.StationLogos[Math.Min(station.StationLogos.Count - 1, 1)].URL; } else if (station.Logo != null) { url = station.Logo.URL; } // download, crop & resize logo image, save and add if (!string.IsNullOrEmpty(url)) { stationLogosToDownload.Add(new KeyValuePair <MxfService, string>(mxfService, url)); } } } // handle xmltv logos SdStationImage logoImage = (station.StationLogos != null) ? station.StationLogos[station.StationLogos.Count - 1] : station.Logo; if (config.XmltvIncludeChannelLogos.ToLower().Equals("url") && (logoImage != null)) { mxfService.logoImage = logoImage; } else if (config.XmltvIncludeChannelLogos.ToLower().Equals("local") && File.Exists(logoPath)) { Image image = Image.FromFile(logoPath); mxfService.logoImage = new SdStationImage() { URL = logoPath, Height = image.Height, Width = image.Width }; } else if (config.XmltvIncludeChannelLogos.ToLower().Equals("substitute") && File.Exists(logoPath)) { Image image = Image.FromFile(logoPath); mxfService.logoImage = new SdStationImage() { URL = string.Format("{0}\\{1}.png", config.XmltvLogoSubstitutePath.TrimEnd('\\'), station.Callsign), Height = image.Height, Width = image.Width }; } } // use hashset to make sure we don't duplicate channel entries for this station HashSet <string> channelNumbers = new HashSet <string>(); // match station with mapping for lineup number and subnumbers foreach (SdLineupMap map in lineupMap.Map) { int number = -1; int subnumber = 0; if (map.StationID.Equals(station.StationID)) { // QAM if (map.ChannelMajor > 0) { number = map.ChannelMajor; subnumber = map.ChannelMinor; } // ATSC or NTSC else if (map.AtscMajor > 0) { number = map.AtscMajor; subnumber = map.AtscMinor; } else if (map.UhfVhf > 0) { number = map.UhfVhf; } // Cable or Satellite else if (!string.IsNullOrEmpty(map.Channel)) { subnumber = 0; if (Regex.Match(map.Channel, @"[A-Za-z]{1}[\d]{4}").Length > 0) { // 4dtv has channels starting with 2 character satellite identifier number = int.Parse(map.Channel.Substring(2)); } else if (!int.TryParse(Regex.Replace(map.Channel, "[^0-9.]", ""), out number)) { // if channel number is not a whole number, must be a decimal number string[] numbers = Regex.Replace(map.Channel, "[^0-9.]", "").Replace('_', '.').Replace('-', '.').Split('.'); if (numbers.Length == 2) { number = int.Parse(numbers[0]); subnumber = int.Parse(numbers[1]); } } } string channelNumber = number.ToString() + ((subnumber > 0) ? "." + subnumber.ToString() : null); if (channelNumbers.Add(channelNumber + ":" + station.StationID)) { addLineupChannel(lineupMap.Metadata.Lineup, mxfService.StationID, mxfService.Id, number, subnumber, lineupIndex); } } } } } if (stationLogosToDownload.Count > 0) { stationLogosDownloadComplete = false; Logger.WriteInformation(string.Format("Kicking off background worker to download and process {0} station logos.", stationLogosToDownload.Count)); backgroundDownloader = new System.ComponentModel.BackgroundWorker(); backgroundDownloader.DoWork += BackgroundDownloader_DoWork; backgroundDownloader.RunWorkerCompleted += BackgroundDownloader_RunWorkerCompleted; backgroundDownloader.WorkerSupportsCancellation = true; backgroundDownloader.RunWorkerAsync(); } if (sdMxf.With[0].Services.Count > 0) { Logger.WriteMessage("Exiting buildLineupServices(). SUCCESS."); return(true); } else { Logger.WriteError(string.Format("There are 0 stations queued for download from {0} subscribed lineups. Exiting.", clientLineups.Lineups.Count)); Logger.WriteError("Check that lineups are 'INCLUDED' and stations are selected in the EPG123 GUI."); return(false); } }
public static XmltvChannel buildXmltvChannel(MxfChannel mxfChannel) { // determine what service this channel belongs to MxfService mxfService = sdMxf.With[0].Services.Where(arg => arg.Id.Equals(mxfChannel.Service)).Single(); // initialize the return channel XmltvChannel ret = new XmltvChannel() { Id = mxfService.xmltvChannelID, DisplayNames = new List <XmltvText>() }; // minimum display names // 5MAXHD // 5 StarMAX HD East ret.DisplayNames.Add(new XmltvText() { Text = mxfService.CallSign }); if (!mxfService.Name.Equals(mxfService.CallSign)) { ret.DisplayNames.Add(new XmltvText() { Text = mxfService.Name }); } // add channel number if requested if (config.XmltvIncludeChannelNumbers) { if (mxfChannel.Number > 0) { string num = mxfChannel.Number.ToString(); num += (mxfChannel.SubNumber > 0) ? "." + mxfChannel.SubNumber.ToString() : string.Empty; ret.DisplayNames.Add(new XmltvText() { Text = num + " " + mxfService.CallSign }); ret.DisplayNames.Add(new XmltvText() { Text = num }); } } // add affiliate if present if (!string.IsNullOrEmpty(mxfService.Affiliate)) { ret.DisplayNames.Add(new XmltvText() { Text = mxfService.Affiliate.Substring(11) }); } // add logo if available if (mxfService.logoImage != null) { ret.Icons = new List <XmltvIcon>() { new XmltvIcon() { src = mxfService.logoImage.URL, height = mxfService.logoImage.Height.ToString(), width = mxfService.logoImage.Width.ToString() } }; } return(ret); }
private static bool getMd5ScheduleEntries(string[] dates, int start) { // build request for station schedules sdScheduleRequest[] requests = new sdScheduleRequest[Math.Min(sdMxf.With[0].Services.Count - start, MAXQUERIES / dates.Length)]; for (int i = 0; i < requests.Length; ++i) { requests[i] = new sdScheduleRequest() { StationID = sdMxf.With[0].Services[start + i].StationID, Date = dates }; } // request schedule md5s from Schedules Direct Dictionary <string, Dictionary <string, sdScheduleMd5DateResponse> > stationResponses = sdAPI.sdGetScheduleMd5s(requests); if (stationResponses == null) { return(false); } // build request of daily schedules not downloaded yet IList <sdScheduleRequest> newRequests = new List <sdScheduleRequest>(); foreach (sdScheduleRequest request in requests) { Dictionary <string, sdScheduleMd5DateResponse> stationResponse; if (stationResponses.TryGetValue(request.StationID, out stationResponse)) { // if the station return is empty, go to next station if (stationResponse.Count == 0) { MxfService mxfService = sdMxf.With[0].getService(request.StationID); string comment = string.Format("Failed to parse the schedule Md5 return for stationId {0} ({1}) on {2} and after.", mxfService.StationID, mxfService.CallSign, dates[0]); if (checkSuppressWarnings(mxfService.CallSign)) { Logger.WriteInformation(comment); } else { Logger.WriteWarning(comment); } processedObjects += dates.Length; reportProgress(); continue; } // scan through all the dates returned for the station and request dates that are not cached IList <string> newDateRequests = new List <string>(); foreach (string day in dates) { sdScheduleMd5DateResponse dayResponse; if (stationResponse.TryGetValue(day, out dayResponse) && (dayResponse.Code == 0) && !string.IsNullOrEmpty(dayResponse.Md5)) { FileInfo file = new FileInfo(string.Format("{0}\\{1}", Helper.Epg123CacheFolder, safeFilename(dayResponse.Md5))); if (!file.Exists || (file.Length == 0)) { newDateRequests.Add(day); } else { ++processedObjects; reportProgress(); ++cachedSchedules; } scheduleEntries.Add(dayResponse.Md5, new string[] { request.StationID, day }); } } // create the new request for the station if (newDateRequests.Count > 0) { newRequests.Add(new sdScheduleRequest() { StationID = request.StationID, Date = newDateRequests.ToArray() }); } } else { // requested station was not in response MxfService mxfService = sdMxf.With[0].getService(request.StationID); Logger.WriteWarning(string.Format("Requested stationId {0} ({1}) was not present in schedule Md5 response.", mxfService.StationID, mxfService.CallSign)); processedObjects += dates.Length; reportProgress(); continue; } } reportProgress(); // download the remaining daily schedules to the cache directory if (newRequests.Count > 0) { // request daily schedules from Schedules Direct IList <sdScheduleResponse> responses = sdAPI.sdGetScheduleListings(newRequests.ToArray()); if (responses == null) { return(false); } // process the responses foreach (sdScheduleResponse response in responses) { ++processedObjects; reportProgress(); if (response == null || response.Programs == null) { continue; } ++downloadedSchedules; // serialize JSON directly to a file if (scheduleEntries.TryGetValue(response.Metadata.Md5, out string[] serviceDate))
public static bool BuildMxfFromSliceGuide(List <HDHRDiscover> homeruns) { // scan each device for tuned channels and associated programs foreach (HDHRDiscover homerun in homeruns) { HDHRDevice device = Common.api.ConnectDevice(homerun.DiscoverURL); if (device == null || string.IsNullOrEmpty(device.LineupURL)) { continue; } else { Console.WriteLine(string.Format("Processing {0} {1} ({2}) with firmware {3}.", device.FriendlyName, device.ModelNumber, device.DeviceID, device.FirmwareVersion)); } // get channels List <HDHRChannel> channels = Common.api.GetDeviceChannels(device.LineupURL); if (channels == null) { continue; } // determine lineup string model = device.ModelNumber.Split('-')[1]; string deviceModel = model.Substring(model.Length - 2); MxfLineup mxfLineup = Common.mxf.With[0].getLineup(deviceModel); foreach (HDHRChannel channel in channels) { int startTime = 0; List <HDHRChannelGuide> programs = Common.api.GetChannelGuide(device.DeviceAuth, channel.GuideNumber, startTime); if (programs == null) { continue; } // build the service MxfService mxfService = Common.mxf.With[0].getService(programs[0].GuideName); if (string.IsNullOrEmpty(mxfService.CallSign)) { mxfService.CallSign = programs[0].GuideName; mxfService.Name = channel.GuideName; mxfService.Affiliate = (!string.IsNullOrEmpty(programs[0].Affiliate)) ? Common.mxf.With[0].getAffiliateId(programs[0].Affiliate) : null; mxfService.LogoImage = (!Common.noLogos && !string.IsNullOrEmpty(programs[0].ImageURL)) ? Common.mxf.With[0].getGuideImage(programs[0].ImageURL).Id : null; mxfService.mxfScheduleEntries.Service = mxfService.Id; } // add channel to the lineup if (int.TryParse(channel.GuideNumber, out int iChannel) || double.TryParse(channel.GuideNumber, out double dChannel)) { string[] digits = channel.GuideNumber.Split('.'); int number = int.Parse(digits[0]); int subnumber = 0; if (digits.Length > 1) { subnumber = int.Parse(digits[1]); } // add the channel to the lineup and make sure we don't duplicate channels var vchan = mxfLineup.channels.Where(arg => arg.Service == mxfService.Id) .Where(arg => arg.Number == number) .Where(arg => arg.SubNumber == subnumber) .SingleOrDefault(); if (vchan == null) { string matchname = null; switch (deviceModel) { case "US": // ATSC matchname = string.Format("OC:{0}:{1}", number, subnumber); break; case "DT": // DVB-T matchname = string.Format("DVBT:{0}:{1}:{2}", channel.OriginalNetworkID, channel.TransportStreamID, channel.ProgramNumber); break; case "CC": // US CableCARD matchname = mxfService.Name; break; case "IS": // ISDB case "DC": // DVB-C default: matchname = mxfService.Name; break; } mxfLineup.channels.Add(new MxfChannel() { Lineup = mxfLineup.Id, lineupUid = mxfLineup.Uid, stationId = mxfService.CallSign, Service = mxfService.Id, Number = number, SubNumber = subnumber, MatchName = matchname }); Console.WriteLine(string.Format("--Processing station {0} on channel {1}{2}.", mxfService.CallSign, number, (subnumber > 0) ? "." + subnumber.ToString() : string.Empty)); } } // if this channel's listings are already done, stop here if (!Common.channelsDone.Add(mxfService.CallSign)) { continue; } // build the programs do { foreach (HDHRProgram program in programs[0].Guide) { // establish the program ID string programID = program.SeriesID; if (!string.IsNullOrEmpty(program.EpisodeNumber)) { programID += "_" + program.EpisodeNumber; } else if (!programID.StartsWith("MV")) { programID += "_" + program.GetHashCode().ToString(); } // create an mxf program MxfProgram mxfProgram = new MxfProgram() { index = Common.mxf.With[0].Programs.Count + 1 }; mxfProgram.programId = programID; // create the schedule entry and program if needed string start = program.StartDateTime.ToString("yyyy-MM-ddTHH:mm:ss"); if (program.StartDateTime == mxfService.mxfScheduleEntries.endTime) { start = null; } mxfService.mxfScheduleEntries.ScheduleEntry.Add(new MxfScheduleEntry() { Duration = program.EndTime - program.StartTime, IsHdtv = channel.HD ? "true" : null, Program = Common.mxf.With[0].getProgram(programID, mxfProgram).Id, StartTime = start }); // build the program BuildProgram(programID, program); startTime = program.EndTime; } } while ((programs = Common.api.GetChannelGuide(device.DeviceAuth, channel.GuideNumber, startTime)) != null); } } return(true); }