223 lines
8.3 KiB
C#

//////////////////////////////////////////////////////////////////////////////////
// //
// Copyright © 2005-2020 nzsjb //
// //
// This Program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2, or (at your option) //
// any later version. //
// //
// This Program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with GNU Make; see the file COPYING. If not, write to //
// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
// http://www.gnu.org/copyleft/gpl.html //
// //
//////////////////////////////////////////////////////////////////////////////////
using System;
using DomainObjects;
namespace DVBServices
{
/// <summary>
/// The class that describes MediaHighway2 title data.
/// </summary>
public class MediaHighway2TitleData
{
/// <summary>
/// Get the channel identification.
/// </summary>
public int ChannelID { get { return (channelID); } }
/// <summary>
/// Get the event identification.
/// </summary>
public int EventID { get { return (eventID); } }
/// <summary>
/// Get the start time of the event.
/// </summary>
public DateTime StartTime { get { return (baseDate + new TimeSpan(hours, minutes, 0)); }}
/// <summary>
/// Get the duration of the event.
/// </summary>
public TimeSpan Duration { get { return (duration); } }
/// <summary>
/// Get the theme identification of the event.
/// </summary>
public int CategoryID { get { return ((mainCategory << 6) + subCategory); } }
/// <summary>
/// Get the theme group of the event.
/// </summary>
public int MainCategory { get { return (mainCategory); } }
/// <summary>
/// Get the theme subgroup of the event.
/// </summary>
public int SubCategory { get { return (subCategory); } }
/// <summary>
/// Get the name of the event.
/// </summary>
public string EventName { get { return (eventName); } }
/// <summary>
/// Get the unknown data.
/// </summary>
public byte[] Unknown
{
get
{
byte[] outputBytes = new byte[unknown0.Length + unknown1.Length + unknown2.Length];
unknown0.CopyTo(outputBytes, 0);
unknown1.CopyTo(outputBytes, unknown0.Length);
unknown2.CopyTo(outputBytes, unknown0.Length + unknown1.Length);
return (outputBytes);
}
}
/// <summary>
/// Get the index of the next byte in the MPEG2 section following the title data.
/// </summary>
/// <exception cref="InvalidOperationException">
/// The title data has not been processed.
/// </exception>
public int Index
{
get
{
if (lastIndex == -1)
throw (new InvalidOperationException("MediaHighway2TitleData: Index requested before block processed"));
return (lastIndex);
}
}
private byte[] unknown0;
private int channelID;
private byte[] unknown1;
private int mainCategory;
private DateTime baseDate;
private int hours;
private int minutes;
private byte[] unknown2;
private TimeSpan duration;
private string eventName;
private int subCategory;
private int eventID;
private int lastIndex = -1;
/// <summary>
/// Initialize a new instance of the MediaHighway2TitleData class.
/// </summary>
public MediaHighway2TitleData() { }
/// <summary>
/// Parse the title data.
/// </summary>
/// <param name="byteData">The MPEG2 section containing the title data.</param>
/// <param name="index">Index of the first byte of the title data in the MPEG2 section.</param>
internal void Process(byte[] byteData, int index)
{
lastIndex = index;
try
{
unknown0 = Utils.GetBytes(byteData, 3, 15);
channelID = (int)byteData[lastIndex];
lastIndex++;
unknown1 = Utils.GetBytes(byteData, lastIndex, 10);
lastIndex += unknown1.Length;
mainCategory = byteData[7] & 0x0f;
baseDate = getDate(Utils.Convert2BytesToInt(byteData, lastIndex));
lastIndex += 2;
hours = ((byteData[lastIndex] >> 4) * 10) + (byteData[lastIndex] & 0x0f);
lastIndex++;
minutes = ((byteData[lastIndex] >> 4) * 10) + (byteData[lastIndex] & 0x0f);
lastIndex++;
unknown2 = Utils.GetBytes(byteData, lastIndex, 1);
lastIndex += unknown2.Length;
int durationMinutes = (byteData[lastIndex] << 4) + (byteData[lastIndex + 1] >> 4);
duration = new TimeSpan(durationMinutes / 60, durationMinutes % 60, 0);
lastIndex += 2;
int eventNameLength = byteData[lastIndex] & 0x3f;
lastIndex++;
eventName = Utils.GetString(byteData, lastIndex, eventNameLength, ReplaceMode.TransferUnchanged);
lastIndex += eventNameLength;
subCategory = byteData[lastIndex] & 0x3f;
lastIndex++;
eventID = Utils.Convert2BytesToInt(byteData, lastIndex);
lastIndex += 2;
Validate();
}
catch (IndexOutOfRangeException)
{
throw (new ArgumentOutOfRangeException("lastIndex = " + lastIndex));
}
}
private DateTime getDate(int mjd)
{
int j = mjd + 2400001 + 68569;
int c = 4 * j / 146097;
j = j - (146097 * c + 3) / 4;
int y = 4000 * (j + 1) / 1461001;
j = j - 1461 * y / 4 + 31;
int m = 80 * j / 2447;
int day = j - 2447 * m / 80;
j = m / 11;
int month = m + 2 - (12 * j);
int year = 100 * (c - 49) + y + j;
return (new DateTime(year, month, day));
}
/// <summary>
/// Validate the title data fields.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">
/// A title data field is not valid.
/// </exception>
public void Validate() { }
/// <summary>
/// Log the title data fields.
/// </summary>
public void LogMessage()
{
if (Logger.ProtocolLogger == null)
return;
Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "MHW2 TITLE DATA: Channel ID: " + channelID +
" Unknown0: " + Utils.ConvertToHex(unknown0) +
" Unknown1: " + Utils.ConvertToHex(unknown1) +
" Main cat: " + mainCategory +
" Base date: " + baseDate +
" Hours: " + hours +
" Minutes: " + minutes +
" Unknown2: " + Utils.ConvertToHex(unknown2) +
" Duration: " + duration +
" Event name: " + eventName +
" Sub cat: " + mainCategory +
" Event ID: " + eventID);
}
}
}