public void GetInfo() { // File exists? if (!File.Exists(Info.FileName)) { Info.ErrorText = "File not found."; return; } // OK let's try SendDebugMessage("MediaInfoGrabber: Setting up prober..."); FFMPGProber prober = new FFMPGProber(); string strTempDirName = "probe_results"; string OutputBasePath = Path.Combine(ProbeResultsFolderPath, strTempDirName); prober.DebugMessage += new EventHandler<GenericEventArgs<string>>(prober_DebugMessage); bool result = prober.Probe(PathToToolkit, Info.FileName, OutputBasePath); prober.DebugMessage -= new EventHandler<GenericEventArgs<string>>(prober_DebugMessage); if (!result) { Info.ErrorText = "FFProber Failed"; return; } Info.Streams = prober.AVAudioAndVideoStreams; Info.Success = true; }
public void GetInfo2(string ffmpegexe, string workdir) { // File exists? while (!File.Exists(Info.FileName)) { } // OK let's try bool result = false; SendDebugMessage("MediaInfoGrabber: Setting up prober..."); FFMPGProber prober = new FFMPGProber(); DateTime start = DateTime.Now; do { string strTempDirName = "probe_results"; string OutputBasePath = Path.Combine(ProbeResultsFolderPath, strTempDirName); prober.DebugMessage += new EventHandler<GenericEventArgs<string>>(prober_DebugMessage); result = prober.Probe(ffmpegexe, workdir, PathToToolkit, Info.FileName, OutputBasePath); prober.DebugMessage -= new EventHandler<GenericEventArgs<string>>(prober_DebugMessage); Info.NewLiveTVPartDuration = prober.duration; if (DateTime.Now.Ticks < (start.Ticks + 10000000 * 20)) // May take a small while, timeout after 20 seconds { //Debug.Print("Probing failed, trying again"); } else { break; } } while (!result); if (!result) { Info.ErrorText = "FFProber Failed"; return; } Info.Streams = prober.AVAudioAndVideoStreams; Info.Success = true; }
public List<AVStream> ProbeFile(string fileName) { FFMPGProber prober = new FFMPGProber(); string strTempDirName = "probe_results"; string OutputBasePath = Path.Combine(Functions.StreamBaseFolder, strTempDirName); prober.DebugMessage += new EventHandler<FatAttitude.GenericEventArgs<string>>(prober_DebugMessage); bool result = prober.Probe(Functions.ToolkitFolder, fileName, OutputBasePath); prober.DebugMessage -= new EventHandler<FatAttitude.GenericEventArgs<string>>(prober_DebugMessage); if (!result) return new List<AVStream>(); return prober.AVAudioAndVideoStreams; }
private void WebServiceProcess(string action, ref BrowserSender browserSender, ref string PostObjects) { if (Settings.Default.DebugFullAPI) { Functions.WriteLineToLogFile("\r\n\r\nAPI: Incoming API Call: " + action); if (PostObjects.Length > 0) Functions.WriteLineToLogFile("API: Post Object String: [" + PostObjects + "]"); else Functions.WriteLineToLogFile("API: Post Object String: Blank."); } try { // Pre-process, e.g. to correct '%2B replaced by + sign' bug action = preProcessActionString(action); // LOGIN - GET TOKEN if (action.StartsWith("xml/login")) { if ( (!qsParams.HasParameter("un")) && (!qsParams.HasParameter("hashedpw") || (!qsParams.HasParameter("pw"))) ) { // not enough params XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"NOT_ENOUGH_PARAMETERS\" />"; browserSender.SendXMLToBrowser(XMLresponse); return; } string UN = "", PW = "", HPW = "", client = ""; bool passwordIsHashed = qsParams.HasParameter("hashedpw"); // Client (optional) if (qsParams.HasParameter("client")) { client = qsParams["client"].Trim(); client = HttpUtility.UrlDecode(client); } UN = qsParams["un"].Trim(); UN = HttpUtility.UrlDecode(UN); if (passwordIsHashed) { HPW = qsParams["hashedpw"].Trim(); HPW = HttpUtility.UrlDecode(HPW); } else { PW = qsParams["pw"].Trim(); PW = HttpUtility.UrlDecode(PW); } if (action.StartsWith("xml/login64")) { UN = Functions.DecodeFromBase64(UN); if (passwordIsHashed) HPW = Functions.DecodeFromBase64(PW); else PW = Functions.DecodeFromBase64(PW); client = Functions.DecodeFromBase64(client); } if ((!UN.Equals(Settings.Default.UserName)) || (!Functions.StringHashesToPasswordHash(PW, passwordIsHashed)) ) { // incorrect credentials - always log Functions.WriteLineToLogFile("API: Failed login attempt from client " + client + " with username " + UN); XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"INCORRECT_CREDENTIALS\" />"; browserSender.SendXMLToBrowser(XMLresponse); return; } // Success! if (Settings.Default.DebugBasic) Functions.WriteLineToLogFile("API: User " + UN + " logged in OK using client " + client); string token = AuthSessionHelper.Default.AddClient(currentClientIP); // Store session, get token XMLresponse = "<?xml version=\"1.0\"?><loginresponse result=\"OK\" token=\"" + token + "\" />"; browserSender.SendXMLToBrowser(XMLresponse); return; } // ************ REMAINING METHODS MAY REQUIRE AUTHENTICATION if (!AuthenticatedByToken) { Functions.logAPIoutputString("ASending 403 Incorrect Authentication"); browserSender.SendGenericStatusCodePage("403", "Incorrect authentication"); spoolMessage("API: Must provide a valid authentication token. Use /xml/login first."); return; } // Should we zip up afterwards bool zipContent = false; if (action.EndsWith("/zip")) { zipContent = true; action = action.Replace("/zip", ""); } if (txtActionOriginalCase.EndsWith("/zip")) { txtActionOriginalCase = txtActionOriginalCase.Replace("/zip", ""); } if (action.StartsWith("xml/channels/setasfavorite/")) { string chanID = action.Replace("xml/channels/setasfavorite/", ""); string strResponse = (EPGManager.MakeChannelFavorite(chanID)) ? "OK" : "ERROR"; XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse); if (Settings.Default.DebugChannels) Functions.WriteLineToLogFile("API: Set channel " + chanID + " as favorite OK."); } else if (action.StartsWith("xml/channels/unsetasfavorite/")) { string chanID = action.Replace("xml/channels/unsetasfavorite/", ""); string strResponse = (EPGManager.MakeChannelNotFavorite(chanID)) ? "OK" : "ERROR"; XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse); if (Settings.Default.DebugChannels) Functions.WriteLineToLogFile("API: Unset channel " + chanID + " as not favorite OK."); } else if (action == "xml/channels/all") { // New 2011: Update channels first from media center (MediaCenter can randomly change internal IDs) EPGManager.UpdateTVChannels(); XMLresponse = EPGExporter.AllChannelsAsXML(); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all channels via XML web request..."); } else if (action.StartsWith("xml/programmes")) { string subAction = action.Replace("xml/programmes/", ""); // No description? (turbo mode) bool omitDescriptions = (subAction.StartsWith("nodescription")); if (omitDescriptions) { subAction = subAction.Replace("nodescription/", ""); } // If a programme type is specified, restrict to this type, otherwise use all TVProgrammeType restrictProgrammesToType = (qsParams.HasParameter("programmetype")) ? (TVProgrammeType)Enum.Parse(new TVProgrammeType().GetType(), qsParams["programmetype"], true) : TVProgrammeType.All; // 2. CHANNELS List<string> TVServiceIDs = new List<string>(); if (subAction.StartsWith("limitchannels/")) { subAction = subAction.Replace("limitchannels/", ""); TVServiceIDs = Functions.StringListFromXML(PostObjects); } else if (subAction.StartsWith("favoritechannels/")) { subAction = subAction.Replace("favoritechannels/", ""); TVServiceIDs = EPGManager.EPGDisplayedTVChannelsServiceIDs; } else if (subAction.StartsWith("byepgrequest")) { List<EPGRequest> EPGRequests = EPGRequest.ArrayFromXML(PostObjects); try { XMLresponse = EPGExporter.EPGwithEPGRequests(EPGRequests, omitDescriptions, restrictProgrammesToType); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes (using " + EPGRequests.Count.ToString() + " epg requests) via XML web request..."); } catch (Exception ex) { Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse array of EPG requests. Date passed was " + PostObjects); Functions.WriteExceptionToLogFile(ex); } } // 3. DATE / DAYRANGE if (subAction.StartsWith("date/")) { string strDate = subAction.Replace("date/", ""); DateTime localDate = new DateTime(); if (DateTime.TryParse(strDate, out localDate)) { XMLresponse = EPGExporter.EPGForLocalDate(localDate, TVServiceIDs, omitDescriptions, restrictProgrammesToType); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for date " + strDate + " via XML web request..."); } else { Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse local date to export shows. Date passed was " + strDate + "."); } } else if (subAction.StartsWith("daterange/")) { string strDate = subAction.Replace("daterange/", ""); string[] dateRanges = strDate.Split(new string[] { "/" }, StringSplitOptions.None); if (dateRanges.Count() > 1) { DateTime startDateTime, endDateTime; if (DateTime.TryParse(dateRanges[0], out startDateTime) && DateTime.TryParse(dateRanges[1], out endDateTime) ) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for date range " + strDate + " via XML web request..."); XMLresponse = EPGExporter.EPGForDateRange(startDateTime, endDateTime, TVServiceIDs, omitDescriptions, restrictProgrammesToType); } else { Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse day ranges."); } } } else if (subAction.StartsWith("dayrange/")) { string strDate = subAction.Replace("dayrange/", ""); string[] dayRanges = strDate.Split(new string[] { "/" }, StringSplitOptions.None); if (dayRanges.Count() > 1) { int startDaysAhead, numberOfDays; if (int.TryParse(dayRanges[0], out startDaysAhead) && int.TryParse(dayRanges[1], out numberOfDays) ) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting tv programmes on " + TVServiceIDs.Count.ToString() + " channels for day range " + strDate + " via XML web request..."); XMLresponse = EPGExporter.EPGForDaysRange(startDaysAhead, numberOfDays, TVServiceIDs, omitDescriptions, restrictProgrammesToType); } else { Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse day ranges."); } } } else if (subAction.StartsWith("search")) { EPGSearch theSearch = EPGSearch.FromXML(PostObjects); if (theSearch != null) { XMLresponse = EPGExporter.TVProgrammesMatchingSearch(theSearch); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all programmes matching search."); } else { Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse search request XML"); } } } else if (action.StartsWith("xml/programme/getinfo/")) { string strUID = action.Replace("xml/programme/getinfo/", ""); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting programme info blob for prog ID " + strUID + " via XML web request..."); XMLresponse = EPGExporter.TVProgrammeInfoBlobForProgID(strUID); } else if (action.StartsWith("xml/filebrowse/dir")) { FileBrowseRequest fbrequest = FileBrowseRequest.FromXML(PostObjects); if (fbrequest != null) { XMLresponse = FileBrowseExporter.FileBrowseUsingRequestAsXML(fbrequest); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting list of files matching request (path " + fbrequest.FullPath + ")"); } else { Functions.WriteLineToLogFile("CRITICAL ERROR - could not parse file browse request XML"); } } else if (action.StartsWith("xml/recordings")) { // FOR NOW.. ..refresh each time, although strictly may not be necessary if (Settings.Default.RecordingsRetrieveAsParanoid) EPGManager.ReloadAllRecordings(); XMLresponse = EPGExporter.RecordingsBlobAsXML(); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all recordings via XML web request..."); } else if (action.StartsWith("xml/settings")) { XMLresponse = EPGExporter.AllSettingsAsXML(); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all settings via XML web request..."); } else if (action.StartsWith("xml/record/byrecordingrequest")) { RecordingRequest tReq = RecordingRequest.FromXML(PostObjects); XMLresponse = EPGManager.ScheduleRecording(RecordingRequest.FromXML(PostObjects)).ToXML(); } else if (action.StartsWith("xml/recordedtv")) { /*if (action.Contains("refreshnow")) RecTV.Default.RefreshCache(); */ XMLresponse = EPGExporter.AllRecordedTVAsXML(); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all recorded TV via XML web request..."); } else if (action.StartsWith("xml/cancelrequest/")) { string txtID = action.Replace("xml/cancelrequest/", ""); XMLresponse = WebSvcCancelRequest(txtID); } else if (action.StartsWith("xml/sendremotekey/")) { string txtCmd = action.Replace("xml/sendremotekey/", ""); string strResponse = IRCommunicator.Default.SendIRCommand(txtCmd); // Returns OK or HELPER_NOT_RUNNING. Doesn't return socket errors (it's ASync) XMLresponse = XMLHelper.XMLReponseWithOutputString(strResponse); } else if (action.StartsWith("xml/showlog")) { XMLresponse = "<?xml version=\"1.0\"?><log "; if (Settings.Default.AllowRemoteLogRetrieval) { XMLresponse += "result=\"OK\" contents=\"" + FileCache.ReadTextFileFromDisk(Functions.DebugLogFileFN) + "\">"; } else { XMLresponse += "result=\"Error\" contents=\"RemoteLoggingDisabled\">"; } XMLresponse += "</log>"; } else if (action.StartsWith("xml/cancelrecording/")) { string txtID = action.Replace("xml/cancelrecording/", ""); XMLresponse = WebSvcCancelRecording(txtID); } else if (action.StartsWith("xml/realcancelrecording64/")) { string filePath = ""; if (PostObjects.Trim().Length > 0) { filePath = HttpUtility.UrlDecode(PostObjects); filePath = Functions.DecodeFromBase64(filePath, Encoding.UTF8); } XMLresponse = WebSvcRealCancelRecording64(filePath); } else if (action.StartsWith("xml/deletefile64")) { string filePath = ""; if (PostObjects.Trim().Length > 0) { filePath = HttpUtility.UrlDecode(PostObjects); filePath = Functions.DecodeFromBase64(filePath, Encoding.UTF8); } XMLresponse = WebSvcDeleteFileByFilePath(filePath); } else if (action.StartsWith("xml/deletefile")) { string filePath = ""; if (PostObjects.Trim().Length > 0) filePath = HttpUtility.UrlDecode(PostObjects); else { // LEGACY - use URL path filePath = action.Replace("xml/deletefile/", ""); } XMLresponse = WebSvcDeleteFileByFilePath(filePath); } else if (action.StartsWith("xml/deletebackgroundtranscoded")) { StreamingManager.Default.DeleteAllBackgroundTranscodedStreamingFiles(); } else if (action.StartsWith("xml/getmediastreamingrequest/")) { string strStreamerID = action.Replace("xml/getmediastreamingrequest/", ""); int streamerID = 0; try { if (int.TryParse(strStreamerID, out streamerID)) { } else { Functions.WriteLineToLogFile( "Warning in xml/getmediastreamingrequest/: Could not parse streamer ID " + strStreamerID); } } catch (Exception ex) { Functions.WriteExceptionToLogFileIfAdvanced(ex); } MediaStreamingRequest msr = StreamingManager.Default.GetMediaStreamingRequest(streamerID); if (msr == null) { XMLresponse = XMLHelper.XMLReponseWithOutputString("No Data"); } else { XMLresponse = XMLHelper.Serialize<MediaStreamingRequest>(msr); } } else if (action.StartsWith("xml/mediastream/start/bymediastreamingrequestgetid")) { MediaStreamingResult streamResult2 = new MediaStreamingResult(); MediaStreamingRequest streamRq = XMLHelper.Deserialize<MediaStreamingRequest>(PostObjects); bool foo; if (streamRq != null) streamResult2 = StreamingManager.Default.StartStreamer(streamRq, Request.UserHostName, false, out foo); else streamResult2 = new MediaStreamingResult(MediaStreamingResultCodes.NamedError, "Error in streaming request."); //if (streamRq != null) //{ // streamResult2.StreamerID = StreamingManager.Default.newUniqueID(streamRq, true); // streamResult2.LiveStreamingIndexPath = "/httplivestream/" + streamResult2.StreamerID + "/index.m3u8"; // streamResult2.Success = true; //} //else //{ // streamResult2.StreamerID = 0; // streamResult2.Success = false; //} XMLresponse = XMLHelper.Serialize<MediaStreamingResult>(streamResult2); } else if (action.StartsWith("xml/mediastream/start/bymediastreamingrequest")) { MediaStreamingResult streamResult; MediaStreamingRequest streamRq = XMLHelper.Deserialize<MediaStreamingRequest>(PostObjects); bool foo; if (streamRq != null) streamResult = StreamingManager.Default.StartStreamer(streamRq, Request.UserHostName, false, out foo); else streamResult = new MediaStreamingResult(MediaStreamingResultCodes.NamedError, "Error in streaming request."); XMLresponse = XMLHelper.Serialize<MediaStreamingResult>(streamResult); } else if (action.StartsWith("xml/restartrp")) { //88888 if (RestartRP != null) { RestartRP(this, e); XMLresponse = XMLHelper.Serialize<String>("success"); } else { XMLresponse = XMLHelper.Serialize<String>("failed"); } } else if (action.StartsWith("xml/killffmpeglatest")) { Process[] workers = Process.GetProcessesByName("ffmpeglatest"); foreach (Process worker in workers) { worker.Kill(); worker.WaitForExit(); worker.Dispose(); } } else if (action.StartsWith("xml/livetvstop")) { //foreach (string recTVFolder in Settings.Default.RecordedTVFolders) //{ // DirectoryInfo di = new DirectoryInfo(recTVFolder); // FileInfo[] files = null; // try // { // files = di.GetFiles("RMCLiveTV*.wtv"); // } // catch (Exception e) // { // if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("You probably have a path defined in Recorded TV (RP settings) that does not exist. Exception " + e.ToString()); // } // if (files != null) // { // for (int index = 0; index < files.Length; index++) // { // try // { // files[index].Delete(); // } // catch (Exception) // { // //file was currently being read or something, just ignore // } // } // } //} Int32 ID; action = action.Replace("xml/livetvstop/", ""); action = action.Replace("streamerid=", ""); Int32.TryParse(action, out ID); bool stopped; if (ID == 0) { stopped = false; } else { stopped = StreamingManager.Default.StopStreamer(ID, 4); } XMLresponse = XMLHelper.Serialize<string>("LiveTV does not always really stop, but stream " + ID + " is stopped=" + stopped); } else if (action.StartsWith("xml/getduration")) { action = action.Replace("xml/getduration/", ""); string filePath = ""; if (PostObjects.Trim().Length > 0) { filePath = HttpUtility.UrlDecode(PostObjects); filePath = Functions.DecodeFromBase64(filePath, Encoding.UTF8); } long duration = (long)FileBrowseExporter.DurationOfMediaFile_OSSpecific(filePath).TotalMilliseconds; XMLresponse = XMLHelper.Serialize<string>("" + duration); } else if (action.StartsWith("xml/getshowschedule")) //else if (action.StartsWith("livetv/getshowschedule")) //suggestion as new syntax { action = action.Replace("xml/getshowschedule/", ""); //action = action.Replace("livetv/getshowschedule/", ""); action = action.Replace("serviceid=", ""); string serviceID = action.Substring(0, action.IndexOf("starttime=")); action = action.Replace(serviceID, ""); action = action.Replace("starttime=", ""); long startTime = 0; long.TryParse(action.Substring(0, action.IndexOf("duration=")), out startTime); action = action.Replace("" + startTime, ""); action = action.Replace("duration=", ""); long duration = 0; long.TryParse(action, out duration); //ShowDebuggingInformationShowProgress: EPGRequest request = new EPGRequest(serviceID, startTime, (startTime + duration)); List<EPGRequest> requests = new List<EPGRequest>(); requests.Add(request); //TVService ds = new TVService(); //List<TVService> dss = new List<TVService>(); ////List<string> ServiceIDs = new List<string>(); ////List<string> _channels = new List<string>(); //TVProgramme progtvchannel = new TVProgramme(); //List<TVProgramme> progtvchannelz = new List<TVProgramme>(); //progtvchannelz.Add(progtvchannel); var tvProgs = EPGManager.mcData.GetTVProgrammes(requests, false, TVProgrammeType.All); List<string> scheduledshows = new List<string>(); string showinfo = ""; int firstshow = 0; foreach (var tvProg in tvProgs) { TimeZone localzone = TimeZone.CurrentTimeZone; var startingTime = localzone.ToLocalTime(new DateTime(tvProg.StartTime)); var endingTime = localzone.ToLocalTime(new DateTime(tvProg.StopTime)); if (firstshow == 0) { DateTime now = DateTime.Now; TimeSpan currShowTime = now.Subtract(startingTime); TimeSpan durationLeft = endingTime.Subtract(now); showinfo = "Show Title: " + tvProg.Title + " Start time: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", startingTime) + ". Ends at: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", endingTime) + ". Current time: " + String.Format("{0:O}", currShowTime) + ". Time left: " + String.Format("{0:c}", durationLeft) + ". Timezone " + localzone.StandardName; Functions.WriteLineToLogFile(showinfo); firstshow++; scheduledshows.Add(showinfo); } else { showinfo = "Show Title: " + tvProg.Title + ". Start time: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", startingTime) + ". Ends at: " + String.Format("{0:MMM dd yyyy hh:mm:ss tt}", endingTime); Functions.WriteLineToLogFile(showinfo); scheduledshows.Add(showinfo); } } XMLresponse = XMLHelper.Serialize<List<string>>(scheduledshows); } else if (action.StartsWith("xml/setstartsegment")) { action = action.Replace("xml/setstartsegment=", ""); List<string> parts = action.Split('*').ToList(); int startSegmentNr = 0; Int32.TryParse(parts[0], out startSegmentNr); int ID = 0; Int32.TryParse(parts[1], out ID); StreamingManager.Default.SetTimeForIndexFile(ID, startSegmentNr); } else if (action.StartsWith("xml/storestreaminfo")) { MediaStreamingResult msr = XMLHelper.Deserialize<MediaStreamingResult>(PostObjects); //if (msr == null) //{ // XMLresponse = XMLHelper.Serialize<string>("failure"); //} StreamingManager.Default.store(msr); } else if (action.StartsWith("xml/checkexists")) { Int32 ID; action = action.Replace("xml/checkexists/", ""); bool CheckInBackgroundTranscodedDirectory = action.Contains("streamtranscodedinbackground64"); if (CheckInBackgroundTranscodedDirectory) { int pos = action.IndexOf("streamtranscodedinbackground64", 0); string action2 = action.Replace(action.Substring(0, "streamtranscodedinbackground64".Length), ""); action2 = action2.Replace("/index.m3u8", ""); action2 = action2.Replace("/index2.m3u8", ""); string filePath = ""; if (PostObjects.Trim().Length > 0) { filePath = HttpUtility.UrlDecode(PostObjects); filePath = Functions.DecodeFromBase64(filePath, Encoding.UTF8); } ID = StreamingManager.Default.MediaStreamingResultsContains(filePath); // Int32.TryParse(action2, out ID); // action = "segment-0.ts"; string segmentfile = "segment-0.ts"; string direc = Functions.AppDataFolder; if (CheckInBackgroundTranscodedDirectory) { segmentfile = Path.Combine(direc, "static\\BackgroundTranscodedMediastreams\\" + ID + "\\" + segmentfile); } if (File.Exists(segmentfile)) { XMLresponse = XMLHelper.Serialize<string>("" + ID); } else { XMLresponse = XMLHelper.Serialize<string>("failure"); } } else { action = action.Replace("streamid=", ""); int pos = action.IndexOf("/segment=", 0); string action2 = action.Replace(action.Substring(pos, action.Length - pos), ""); Int32.TryParse(action2, out ID); action = action.Replace(ID + "/segment=", ""); string dir = Functions.AppDataFolder; string streamPath; if (CheckInBackgroundTranscodedDirectory) { streamPath = Path.Combine(dir, "static\\BackgroundTranscodedMediastreams\\"); } else { streamPath = Path.Combine(dir, "static\\mediastreams\\"); } DirectoryInfo di = new DirectoryInfo(streamPath + ID); FileInfo[] files = null; try { List<string> parts = action.Split('-').ToList(); List<string> parts2 = parts[1].Split('.').ToList(); //Hack: cuz all clients only ask for 2 segments, actually we need 3, so +1: // action = parts[0] + "-" + (Int32.Parse(parts2[0]) + 1) + ".ts"; action = parts[0] + "-" + Int32.Parse(parts2[0]) + ".ts"; files = di.GetFiles(action); try { if (files != null && files.Length > 0 && files[0].Exists) // && files[0].Length>1000) //also check if has grown a bit, needed for slow servers! { XMLresponse = XMLHelper.Serialize<string>("success"); } else { XMLresponse = XMLHelper.Serialize<string>("failure"); } } catch (Exception e) { XMLresponse = XMLHelper.Serialize<string>("failure"); } } catch (Exception e) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile(e.ToString()); XMLresponse = XMLHelper.Serialize<string>("failure"); } } } else if (action.StartsWith("xml/setrprecstreamid/")) { //ToDo: Have to define an API that conforms to the rest of the API! // // GET rprec ID and streamID action = action.Replace("xml/setrprecstreamid/", ""); long rprecId = 0; long.TryParse((action.Substring(0, action.IndexOf("streamid="))), out rprecId); action = action.Replace("" + rprecId, ""); action = action.Replace("streamid=", ""); long streamId = 0; long.TryParse(action, out streamId); EPGManager.setStreamID(rprecId, streamId); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Setting recording " + rprecId + " to streamID " + streamId); } //else if (action.StartWith("xml/startlivetv")) //suggestion else if (action.StartsWith("xml/livetv")) { //ToDo: Have to define an API that conforms to the rest of the API! // XMLresponse = ""; RecordingRequest newRR = null; bool failedValidation = false; string failedValidationReason = ""; string filenameId = "RMCLiveTV"; // GET SERVICE ID (Channel) and length action = action.Replace("xml/livetv/", ""); string serviceId; try { serviceId = action.Substring(0, action.IndexOf("uniqueandroid=")); } catch (Exception e) { serviceId = "unknown"; } action = action.Replace(serviceId, ""); action = action.Replace("uniqueandroid=", ""); string uniqueAndroidId; try { uniqueAndroidId = action.Substring(0, action.IndexOf("length=")); } catch (Exception e) { uniqueAndroidId = "unknown"; } // DURATION Int32 tryDuration; Int32.TryParse(action.Substring(action.IndexOf("length=") + 7), out tryDuration); DateTime tryStartTime = DateTime.Now; // Schedule manual recording // DATE TIME if ((tryDuration == 0) | (tryDuration > 720)) { failedValidation = true; failedValidationReason += "Invalid duration, must be between 1 and 720 minutes.<br>"; } // In the unliklely event a file already exist with a certain random nr, try again: bool randomFileAlreadyExists = false; do { Random r = new Random(); filenameId = filenameId + uniqueAndroidId + r.Next(0, int.MaxValue); string[] filePaths = null; foreach (string recTVFolder in Settings.Default.RecordedTVFolders) { try { filePaths = Directory.GetFiles(recTVFolder, filenameId + "*.wtv"); } catch (Exception e) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile( "You probably have a path defined in Recorded TV (RP settings) that does not exist. Exception " + e.ToString()); } if (filePaths.Length > 0) { randomFileAlreadyExists = true; break; } } } while (randomFileAlreadyExists); long servId; try { servId = long.Parse(serviceId); // Create a new recording request newRR = new RecordingRequest(tryStartTime.ToUniversalTime(), servId, tryDuration, filenameId); } catch (Exception e) { failedValidation = true; failedValidationReason = "Service id not valid: " + serviceId; } // Passed validation? if (failedValidation) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("FailedValidation"); txtResponse += "<p class='recorderror'>Error in recording request: " + failedValidationReason + "</p>"; XMLresponse = XMLHelper.Serialize<string>(txtResponse); } else { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Did not fail Validation"); qsParams.Add("queueid", RecordingQueue.AddToQueue(newRR)); string txtRecSummary2; if (RecordFromQueue(out txtRecSummary2)) { bool found = false; if (txtRecSummary2.Contains("The scheduling was successful")) { if (RecordFromQueueResult != null) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile(RecordFromQueueResult); if (!RecordFromQueueResult.StartsWith("Recording not scheduled")) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("RecordFromQueue=True"); int waittimeforfiletoappear = 20; // seconds //int waittimeforfiletoappear = 200; // seconds, testing whether setting needs high value for certain tv card like Ceton DateTime begin = DateTime.Now; string[] filepaths = null; int i = 0; do { foreach (string rectvfolder in Settings.Default.RecordedTVFolders) { if ((i % 1000 == 0) && (Settings.Default.DebugAdvanced)) Functions.WriteLineToLogFile("Checking " + rectvfolder + " for " + filenameId + "*.wtv"); i++; try { filepaths = Directory.GetFiles(rectvfolder, filenameId + "*.wtv"); } catch (Exception e) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile( "You probably have a path defined in Recorded TV (RP settings) that does not exist. Exception " + e.ToString()); } if (filepaths != null && filepaths.Length > 0) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Found recording tv folder..." + filepaths[0]); break; } } if (filepaths != null && filepaths.Length > 0) { XMLresponse = XMLHelper.Serialize<string>(filepaths[0]); found = true; break; } if ( DateTime.Compare(begin.AddSeconds(waittimeforfiletoappear), DateTime.Now) < 0) //not found after 20 seconds { if (Settings.Default.DebugAdvanced) { foreach (string rectvfolder in Settings.Default.RecordedTVFolders) { string[] filepaths2 = Directory.GetFiles(rectvfolder, "*.*"); foreach (string fp in filepaths2) { Functions.WriteLineToLogFile("However, this does exist :" + fp); } } } break; } } while (true); } } else { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("strange: RecordFromQueueResult is null"); } } if (!found) { List<string> errors = new List<string>(); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("All tuners are busy somewhere in between now and " + tryDuration + " minutes from now"); errors.Add("All tuners are busy somewhere in between now and " + tryDuration + " minutes from now"); DateRange dateRange = new DateRange(DateTime.UtcNow, DateTime.UtcNow.AddMinutes(tryDuration)); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Going to find conflicting recordings"); List<RPRecording> recsToday = EPGManager.AllRecordingsRunningInTimeFrame(dateRange, true); //List<RPRecording> oldLiveTVrecs = EPGManager.AllRecordingsContainsTitle("RMCLiveTV"); foreach (RPRecording rec in recsToday) { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Recording: not found!, conflicting: " + rec.Title + " Are your recording folders in Remote Potato RP server (the general tab click on \"recorded TV\") and Media Center (tasks/setings/TV/Recorder) the same?"); //if (rec.TVProgramme().StartTime <= (tryStartTime.Ticks + tryDuration * TimeSpan.TicksPerMinute)) { errors.Add(rec.Id.ToString()); errors.Add(rec.Title); errors.Add(rec.TVProgramme().TVService().Callsign); errors.Add(rec.TVProgramme().StartTime.ToString()); errors.Add(rec.TVProgramme().StopTime.ToString()); //errors.Add(rec.TVProgramme().Filename); } } if (Settings.Default.DebugAdvanced && errors.Count == 0) Functions.WriteLineToLogFile( "mmm, this is strange: no recordings in recording folder beginning with RMCLiveTV"); XMLresponse = XMLHelper.Serialize<List<string>>(errors); } //Could wait for event (for file to appear) instead... //WTVfse = new FileSystemEventHandler(OnChanged); //foreach (string location in Settings.Default.RecordedTVFolders) //{ // FileSystemWatcher w = new FileSystemWatcher(); // w.Path = location; // /* Watch for changes in LastAccess and LastWrite times, and // the renaming of files or directories. */ // w.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite // | NotifyFilters.FileName | NotifyFilters.DirectoryName; // // Only watch filter. // w.Filter = filenameID + "*.wtv"; // w.Created += WTVfse; // WTVwatcher.Add(w); //} //// Begin watching. //foreach (FileSystemWatcher w in WTVwatcher) //{ // w.EnableRaisingEvents = true; //} //do { } while (!LiveTVScheduled); //XMLresponse = XMLHelper.Serialize<string>(LiveTVFilename); } else { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("RecordFromQueue=False"); } } } else if (action.StartsWith("xml/mediastream/probe/byfilename")) { string strFileName = HttpUtility.UrlDecode(PostObjects); strFileName = strFileName.Trim(); if (action.StartsWith("xml/mediastream/probe/byfilename64")) strFileName = Functions.DecodeFromBase64(strFileName); List<AVStream> result; if (strFileName.Length > 0) result = StreamingManager.Default.ProbeFile(strFileName); else result = new List<AVStream>(); if (Settings.Default.DebugStreaming) Functions.WriteLineToLogFile("Probed file " + strFileName + ": sending back details of " + result.Count.ToString() + " AV streams."); XMLresponse = XMLHelper.Serialize<List<AVStream>>(result); } else if (action.StartsWith("xml/mediastream/keepalive/")) { string strStreamerID = action.Replace("xml/mediastream/keepalive/", ""); int streamerID; string strmStatus; if (int.TryParse(strStreamerID, out streamerID)) { strmStatus = StreamingManager.Default.KeepStreamerAliveAndReturnStatus(streamerID); } else { Functions.WriteLineToLogFile("Warning: Could not parse streamer ID " + strStreamerID); strmStatus = "invalid_id"; } //XMLresponse = XMLHelper.XMLReponseWithOutputString(strmStatus); XMLresponse = strmStatus; if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("MediaStreaming: GetStatus (" + strStreamerID + "): " + strmStatus); } else if (action.StartsWith("xml/islivetvstarted/")) { string strStreamerID = action.Replace("xml/islivetvstarted/", ""); int streamerID = 0; if (int.TryParse(strStreamerID, out streamerID)) { } else { Functions.WriteLineToLogFile("Warning: Could not parse streamer ID " + strStreamerID); } if (StreamingManager.Default.LiveTVStarted(streamerID)) { XMLresponse = XMLHelper.XMLReponseWithOutputString("started"); } else { XMLresponse = XMLHelper.XMLReponseWithOutputString("No Data"); } } else if (action.StartsWith("xml/getmappings")) { string WorkingDirectory = action.Replace("xml/getmappings/", ""); MediaStreamingRequest msr = XMLHelper.Deserialize<MediaStreamingRequest>(PostObjects); FFMPGProber prober = new FFMPGProber(); string mapping; while (true) { FFMPGProber prober2 = new FFMPGProber(); bool result = prober2.Probe("ffmpeglatest.exe", "", Functions.ToolkitFolder, msr.InputFile, WorkingDirectory, msr.UseAudioStreamIndex); mapping = prober2.mapArguments.ToString(); if (string.IsNullOrEmpty(mapping)) // May take a small while { Functions.WriteLineToLogFile("Probing failed, trying again"); } else { Functions.WriteLineToLogFile("Success! Mappings are :" + mapping); break; } } XMLresponse = XMLHelper.XMLReponseWithOutputString(mapping); } else if (action.StartsWith("xml/mediastream/stop/")) { string strStreamerID = action.Replace("xml/mediastream/stop/", ""); int streamerID; try { if (int.TryParse(strStreamerID, out streamerID)) { if (!StreamingManager.Default.StopStreamer(streamerID, 5)) Functions.WriteLineToLogFile( "Warning in stopping mediastream: Could not stop streamer ID " + strStreamerID); } else { Functions.WriteLineToLogFile( "Warningin stopping mediastream2: Could not parse streamer ID " + strStreamerID); } } catch (Exception ex) { Functions.WriteExceptionToLogFileIfAdvanced(ex); } XMLresponse = XMLHelper.XMLReponseWithOutputString("No Data"); } else if (action.StartsWith("xml/stream/start")) { WTVStreamingVideoResult streamResult; WTVStreamingVideoRequest streamRq = XMLHelper.Deserialize<WTVStreamingVideoRequest>(PostObjects); if (streamRq == null) { streamResult = new WTVStreamingVideoResult(DSStreamResultCodes.ErrorInStreamRequest); } else { try { streamResult = DSStreamingManager.Default.StartStreamer(streamRq); } catch (Exception e) { Functions.WriteLineToLogFile("Exception setting up streaming object:"); Functions.WriteExceptionToLogFile(e); streamResult = new WTVStreamingVideoResult(DSStreamResultCodes.ErrorExceptionOccurred, e.Message); } } XMLresponse = XMLHelper.Serialize<WTVStreamingVideoResult>(streamResult); } else if (action.StartsWith("xml/stream/stop")) { XMLresponse = XMLHelper.XMLReponseWithOutputString("ERROR (DEPRECATED)"); } else if (action.StartsWith("xml/picture/thumbnailzip/")) { FileBrowseRequest fbrequest = FileBrowseRequest.FromXML(PostObjects); if (fbrequest != null) { if (PictureExporter.SendThumbnailsAsZipFile(fbrequest, FatAttitude.ThumbnailSizes.Small, ref browserSender)) return; else { if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Could not export zip of thumbnails."); browserSender.Send404Page(); } } else { Functions.WriteLineToLogFile( "ThumbnailZip: Error in requestprocessor- could not parse file browse request XML"); } } else if (action.StartsWith("xml/picture/get")) // matches /xml/picture/getrequest too { string strSubAction = txtActionOriginalCase.Replace("xml/picture/", ""); // URL DECODE strSubAction = HttpUtility.UrlDecode(strSubAction); string strParams; string strFileName = ""; bool fileNameAtEndOfUri = false; bool fileNameAtEndOfUriIsBase64Encoded = false; if (strSubAction.StartsWith("getwithfilename")) // GET FILENAME FROM URL { fileNameAtEndOfUri = true; fileNameAtEndOfUriIsBase64Encoded = strSubAction.StartsWith("getwithfilename64"); if (fileNameAtEndOfUriIsBase64Encoded) strParams = strSubAction.Replace("getwithfilename64/", ""); else strParams = strSubAction.Replace("getwithfilename/", ""); } else // GET FILENAME FROM POST STRING { fileNameAtEndOfUri = false; strFileName = PostObjects; strParams = strSubAction.Replace("get/", ""); } string[] Params = strParams.Split(new string[] { "/" }, StringSplitOptions.None); bool haveFrameSizes = false; int frameWidth = 0; int frameHeight = 0; if (Params.Count() > 1) { if ((int.TryParse(Params[0], out frameWidth) && int.TryParse(Params[1], out frameHeight) )) haveFrameSizes = ((frameWidth > 0) && (frameHeight > 0)); else haveFrameSizes = false; } else // Send full picture haveFrameSizes = false; if (!haveFrameSizes) Functions.WriteLineToLogFile( "Xml/Picture: invalid frame size (or none supplied): using full picture"); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting picture " + strFileName + " resized to frame " + frameWidth.ToString() + "x" + frameHeight.ToString()); // Get Filename if not got already // File name from Uri ? if (fileNameAtEndOfUri) { if (fileNameAtEndOfUriIsBase64Encoded) { // Take final component and un-encode to produce filename strFileName = Params[Params.Count() - 1]; strFileName = HttpUtility.UrlDecode(strFileName); strFileName = Functions.DecodeFromBase64(strFileName); } else { // Reconstruct filename by putting /slashed/ components back together for (int pCount = 2; pCount < Params.Count(); pCount++) { strFileName = strFileName + Params[pCount]; if (pCount < (Params.Count() - 1)) strFileName = strFileName + "/"; strFileName = HttpUtility.UrlDecode(strFileName); } } } if (string.IsNullOrEmpty(strFileName)) { Functions.WriteLineToLogFile("Xml/Picture : No filename specified in POST request, sending 404"); browserSender.Send404Page(); return; } // Send if (haveFrameSizes) { byte[] resizedPictureData = new byte[] { }; if (ImageResizer.ResizePicture(strFileName, new Size(frameWidth, frameHeight), out resizedPictureData, ImageFormat.Jpeg, false)) { browserSender.SendDataToBrowser(Functions.MimeTypeForFileName(strFileName), resizedPictureData); return; } else { Functions.WriteLineToLogFile("Xml/Picture: Could not resize picture."); browserSender.Send404Page(); return; } } else // No frame sizes, send full image { browserSender.SendFileToBrowser(strFileName); return; } } else if (action.StartsWith("xml/music/framework")) { using (WMPManager manager = new WMPManager()) { XMLresponse = manager.MusicFrameworkAsXML(); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting music framework blob via XML web request..."); } } else if (action.StartsWith("xml/music/songs/artist")) { bool isBase64Encoded = (action.Contains("artist64/")); action = action.Replace("artist64", "artist"); txtActionOriginalCase = txtActionOriginalCase.Replace("artist64", "artist"); string strArtistID = txtActionOriginalCase.Replace("xml/music/songs/artist/", ""); strArtistID = HttpUtility.UrlDecode(strArtistID); if (isBase64Encoded) strArtistID = Functions.DecodeFromBase64(strArtistID); using (WMPManager manager = new WMPManager()) { XMLresponse = manager.GetSongsForArtistAsXML(strArtistID); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting songs for artist " + strArtistID + " via XML web request..."); } } else if (action.StartsWith("xml/music/songs/album")) { bool isBase64Encoded = (action.Contains("album64/")); action = action.Replace("album64", "album"); txtActionOriginalCase = txtActionOriginalCase.Replace("album64", "album"); // USE case sensitive action string for match string strAlbumID = txtActionOriginalCase.Replace("xml/music/songs/album/", ""); strAlbumID = HttpUtility.UrlDecode(strAlbumID); if (isBase64Encoded) strAlbumID = Functions.DecodeFromBase64(strAlbumID); using (WMPManager manager = new WMPManager()) { XMLresponse = manager.GetSongsForAlbumAsXML(strAlbumID); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting songs for album " + strAlbumID + " via XML web request..."); } } else if (action.StartsWith("xml/music/songs/genre")) { bool isBase64Encoded = (action.Contains("genre64/")); action = action.Replace("genre64", "genre"); txtActionOriginalCase = txtActionOriginalCase.Replace("genre64", "genre"); // USE case sensitive action string for match string strGenreID = txtActionOriginalCase.Replace("xml/music/songs/genre/", ""); strGenreID = HttpUtility.UrlDecode(strGenreID); if (isBase64Encoded) strGenreID = Functions.DecodeFromBase64(strGenreID); using (WMPManager manager = new WMPManager()) { XMLresponse = manager.GetSongsForGenreAsXML(strGenreID); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting songs for genre " + strGenreID + " via XML web request..."); } } else if (action.StartsWith("xml/music/songs/all")) { using (WMPManager manager = new WMPManager()) { XMLresponse = manager.GetAllSongsAsXML(); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting all songs in library via XML web request..."); } } else if (action.StartsWith("xml/music/songs/checkexists")) { bool isBase64Encoded = (action.Contains("checkexists64/")); action = action.Replace("checkexists64", "checkexists"); txtActionOriginalCase = txtActionOriginalCase.Replace("checkexists64", "checkexists"); // USE case sensitive action string for match string strSongID = txtActionOriginalCase.Replace("xml/music/songs/checkexists/", ""); strSongID = HttpUtility.UrlDecode(strSongID); if (isBase64Encoded) strSongID = Functions.DecodeFromBase64(strSongID); using (WMPManager manager = new WMPManager()) { XMLresponse = manager.WMPItemFileExistsAsXML(strSongID); if (Settings.Default.DebugAdvanced) Functions.WriteLineToLogFile("Exporting whether song exists... " + XMLresponse); } } //else if (action.StartsWith("xml/startrunners")) //{ // action = action.Replace("xml/startrunners/", ""); // int ID = 0; // try // { // Int32.TryParse(action, out ID); // } // catch (Exception e) // { // ID = 0; // } // byte[] TSdata = new byte[] { }; // string txtError = ""; // StreamingManager.Default.SegmentFromStreamer(0, ID, 1, ref TSdata, ref txtError, true); //start up the runners //} else { Functions.WriteLineToLogFile("XML: Unknown request : " + action); XMLresponse = ""; } if (String.IsNullOrEmpty(XMLresponse)) { Functions.WriteLineToLogFile("NULL xmlresponse - nothing to send out to Silverlight client. Sending error string."); browserSender.SendStringToBrowser(XMLHelper.XMLReponseWithOutputString("No Data")); return; } // Strip out any UTF-16 encoding XMLresponse = Functions.StripIllegalXmlCharacters(XMLresponse); // Zip up ? if (zipContent) { Functions.logAPIoutputString(XMLresponse); XMLresponse = ZipHelper.ZipString(XMLresponse); if (Settings.Default.DebugServer) Functions.WriteLineToLogFile("Zipped String to base64 string. Length:" + XMLresponse.Length.ToString() + " characters. "); browserSender.SendZipStringToBrowser(XMLresponse); } else browserSender.SendXMLToBrowser(XMLresponse); } catch (Exception e) { string errorResponse = XMLHelper.XMLReponseWithOutputString("An error occurred - " + e.Message + " - check the debug log on the server."); Functions.WriteLineToLogFile("Exception while processing XML request:"); Functions.WriteExceptionToLogFile(e); browserSender.SendXMLToBrowser(errorResponse); } }