I'll give you an example. One of the series that is set to record is EastEnders (for my better half...honest! ;-) but only the omnibus episode on a Sunday should be recorded. Unfortunately there is no way to schedule this single day only. If one scheduled to record it as a series, it also records all the showings during the week which clogs up the recorded tv view. Otherwise one has to schedule manually each week as a single recording. Not ideal!
I'm currently working on a small app that will interface to the built-in scheduler and provide a bit more flexibility. To enable the scenario I mentioned above I'm creating a Windows service to run periodically and try to schedule any requests. By using the Media Center Click-to-record API one can choose specific days to record on. The recording request I've come up with is for the program name on a Sunday only. Submitting this to media center results in all instances of this show on that day of the week being recorded (for the data held in the guide - typically two weeks ahead).
(daysOfWeek is a Flag-ed enum so one can choose a combination of between 1 and 7 days)<?xml version="1.0"?>
<clickToRecord xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:schemas-microsoft-com:ehome:clicktorecord">
<body>
<metadata>
<description>Weekly Eastendersdescription>
</metadata>
<programRecord allowAlternateAirings="false" daysOfWeek="1">
<program>
<key field="urn:schemas-microsoft-com:ehome:epg:program#title" match="startswith">Eastenders</key>
</program>
</programRecord>
</body>
</clickToRecord>
Pretty smart, no? By submitting these requests periodically via a Windows Service (I could just use a scheduled task but would like to have a play with the services stuff too) this weekly omnibus should be recorded with no duplicates. Hurrah!
Now where I've been pulling my hair out is in submitting this request to the Media Center API programatically from .NET. I've written a console app to test this stuff and no matter what I did I couldn't get it working. The API call kept throwing back an error:
Invalid root element.
at Microsoft.MediaCenter.TV.Scheduling.Internal.CreateRequestHandler.ParseClickToRecordElement(XmlReader reader)
at Microsoft.MediaCenter.TV.Scheduling.Internal.CreateRequestHandler.ParseStream()
at Microsoft.MediaCenter.TV.Scheduling.Internal.CreateRequestHandler..ctor(XmlReader reader, Boolean semiTrustedSource)
at Microsoft.MediaCenter.TV.Scheduling.EventSchedule.CreateScheduleRequest(XmlReader requestConstraints, ConflictResolutionPolicy conflictPolicy, String orig
inatorDescription, ScheduleRequest& scheduleRequest)
Which was annoying! I knew the request worked as when writing the XML out to a text file (with a .c2r file suffix) and double-clicking the .c2r file on my media center machine the schedule request worked perfectly! So what was going on?
In the end it turns out that the "issue" was solved by writing the XML generated by my custom data entity to DISK first and then re-reading this data in via an XmlReader and passing this to the CreateScheduleRequest method:
ScheduleRequest result;Previously I was passing the MemoryStream object above into XmlReader.Create but the media center API didn't like this and kept giving me the error above!
MemoryStream xmlRequest = (MemoryStream) request.GetClickToRecordXml();
EventSchedule scheduleEvent = new EventSchedule();
string clickToRecordXml = Encoding.UTF8.GetString(xmlRequest.GetBuffer());
string logFolderFilePath = Path.Combine(_logFolderPath, "ScheduleRequest" + DateTime.Now.ToString("yyyyMMddTHHmmss") + ".c2r");
StreamWriter writer2 = null;
try
{
writer2 = new StreamWriter(logFolderFilePath);
writer2.Write(clickToRecordXml);
}
finally
{
if (writer2 != null) writer2.Close();
}
FileStream fsXml;
XmlReader readerXml;
fsXml = new FileStream(logFolderFilePath, FileMode.Open, FileAccess.Read);
readerXml = XmlReader.Create(fsXml);
Core.Enums.CreateScheduleRequestResult requestResult = (Core.Enums.CreateScheduleRequestResult) scheduleEvent.CreateScheduleRequest(readerXml, ConflictResolutionPolicy.AllowConflict, "SchedulerPlus", out result);
IScheduledProgramResult scheduledProgramResult = new ScheduledProgramResult(result.Id, requestResult);
Anyway although I'm glad I got this working I'd love to know why there is this issue. It almost seems like it couldn't read the xml properly when I was passing the XmlReader object created from the MemoryStream earlier but why is this an issue when effectively serialising the data to disk and then deserialising back is doing the same thing? The MemoryStream object is created by calling a method on my custom class that serialises a data entity that has been populated with the relevant data.
Any comments on the cause of this are most welcome!
UPDATE: After thinking about this some more it seemed fairly obvious that writing the XML to disk was a bit of a red herring - converting it to and from a string should also suffice, so that's what I tried. Unfortunately the call is now returning "ExceededMaxRequests" - although clicking the .c2r files in explorer still schedule the recording - arrrgh! Still, it appears to be some sort of encoding issue causing the original problem...
No comments:
Post a Comment