public override bool StartRecording(string serverHostName, int tcpPort, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName) { bool result = false; TvDatabase.Card recordOnCard = GetCardByCardId(channelAllocation.CardId); if (recordOnCard != null) { TvDatabase.Channel channel = GetLinkedMediaPortalChannel(channelAllocation.ChannelType, channelAllocation.ChannelId, channelAllocation.ChannelName); if (channel != null) { result = this.RecordingThreads.StartNewThread(new RecordingThread(this.RecorderTunerId, serverHostName, tcpPort, channelAllocation, startTimeUtc, stopTimeUtc, recordingProgram, suggestedBaseFileName, recordOnCard, channel)); if (!result) { Log(TraceEventType.Error, "{0} - Already recording {1}", this.Name, recordingProgram.CreateProgramTitle()); } } else { Log(TraceEventType.Error, "{0} - Channel {1} not found", this.Name, channelAllocation.ChannelName); } } else { Log(TraceEventType.Error, "{0} - Card {1} not found", this.Name, channelAllocation.CardId); } return(result); }
public RecordingThread(Guid recorderId, string schedulerBaseUrl, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName, TvDatabase.Card recordOnCard, TvDatabase.Channel channel) : base(recorderId, schedulerBaseUrl, channelAllocation, startTimeUtc, stopTimeUtc, recordingProgram, true) { _suggestedBaseFileName = suggestedBaseFileName; _recordOnCard = recordOnCard; _channel = channel; }
public override bool ValidateAndUpdateRecording(CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, DateTime stopTimeUtc) { bool threadNotFound; bool result = _recordingThreads.ValidateAndUpdateRecording(recordingProgram, stopTimeUtc, out threadNotFound); if (threadNotFound) { Log(TraceEventType.Warning, "{0} - ValidateAndUpdateRecording called on unknown recording {1}", this.Name, recordingProgram.CreateProgramTitle()); } return(result); }
public RecordingThreadBase(Guid recorderId, string schedulerBaseUrl, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, bool okToRenameRecordedFiles) : base("Record") { _recorderId = recorderId; _schedulerBaseUrl = schedulerBaseUrl; _channelAllocation = channelAllocation; _startTimeUtc = startTimeUtc; _stopTimeUtc = stopTimeUtc; _recordingProgram = recordingProgram; _okToRenameRecordedFiles = okToRenameRecordedFiles; }
/// <summary> /// Validate a recording is still running, and update its actual stop time. /// </summary> /// <param name="channelAllocation">The card allocation for the channel.</param> /// <param name="recordingProgram">The program being recorded.</param> /// <param name="stopTimeUtc">The up-to-date stop time (UTC).</param> /// <returns>True if the recording was still running (and its stop time was succesfully updated), false if there was a problem or the recording is not running.</returns> public async Task <bool> ValidateAndUpdateRecording(CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, DateTime stopTimeUtc) { var request = NewRequest(HttpMethod.Put, "Recording/ValidateAndUpdate"); request.AddBody(new { channelAllocation = channelAllocation, recordingProgram = recordingProgram, stopTimeUtc = stopTimeUtc }); return(await ExecuteResult <bool>(request).ConfigureAwait(false)); }
public void StartRecordingFailed(CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, string reason) { var request = NewRequest("/RecorderCallback/Recording/StartFailed", Method.PUT); request.AddBody(new { Allocation = channelAllocation, RecordingProgram = recordingProgram, Reason = reason }); Execute(request); }
/// <summary> /// Validate a recording is still running, and update its actual stop time. /// </summary> /// <param name="channelAllocation">The card allocation for the channel.</param> /// <param name="recordingProgram">The program being recorded.</param> /// <param name="stopTimeUtc">The up-to-date stop time (UTC).</param> /// <returns>True if the recording was still running (and its stop time was succesfully updated), false if there was a problem or the recording is not running.</returns> public bool ValidateAndUpdateRecording(CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, DateTime stopTimeUtc) { var request = NewRequest("/Recording/ValidateAndUpdate", Method.PUT); request.AddBody(new { channelAllocation = channelAllocation, recordingProgram = recordingProgram, stopTimeUtc = stopTimeUtc }); return(ExecuteResult <bool>(request)); }
public async Task StartRecordingFailed(CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, string reason) { var request = NewRequest(HttpMethod.Put, "RecorderCallback/Recording/StartFailed"); request.AddBody(new { Allocation = channelAllocation, RecordingProgram = recordingProgram, Reason = reason }); await ExecuteAsync(request).ConfigureAwait(false); }
public RecordingThreadBase(Guid recorderTunerId, string serverHostName, int serverTcpPort, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, bool okToRenameRecordedFiles) : base("Record") { _recorderTunerId = recorderTunerId; _serverHostName = serverHostName; _serverTcpPort = serverTcpPort; _channelAllocation = channelAllocation; _startTimeUtc = startTimeUtc; _stopTimeUtc = stopTimeUtc; _recordingProgram = recordingProgram; _okToRenameRecordedFiles = okToRenameRecordedFiles; }
/// <summary> /// Tell the recorder to actually start a recording on the given card. The implementation /// must call /Recording/New on the Recorder callback service when the recording actually /// starts. If the recording can't start for some reason, StartRecordingFailed() must be called. /// In case the recording ends (prematurely or on time) /Recording/End must be called. IMPORTANT: /// If the suggested relative path and filename was used the recorder should /// return 'false' to /Recording/End's 'okToMoveFile'! /// </summary> /// <param name="schedulerBaseUrl">The callback URL for the Recorder to communicate with the Scheduler.</param> /// <param name="channelAllocation">The card allocation for the channel.</param> /// <param name="startTimeUtc">The actual time to start the recording (UTC).</param> /// <param name="stopTimeUtc">The actual time to stop the recording (UTC).</param> /// <param name="recordingProgram">The program to record.</param> /// <param name="suggestedBaseFileName">The suggested relative path and filename (without extension) of the recording file.</param> /// <returns>A boolean indicating the recording was initiated succesfully.</returns> public async Task <bool> StartRecording(string schedulerBaseUrl, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName) { var request = NewRequest(HttpMethod.Post, "Recording/Start"); request.AddBody(new { schedulerBaseUrl = schedulerBaseUrl, channelAllocation = channelAllocation, startTimeUtc = startTimeUtc, stopTimeUtc = stopTimeUtc, recordingProgram = recordingProgram, suggestedBaseFileName = suggestedBaseFileName }); return(await ExecuteResult <bool>(request).ConfigureAwait(false)); }
/// <summary> /// Tune to a channel, and get a live stream to that channel. /// </summary> /// <param name="channel">The channel to tune to.</param> /// <param name="upcomingRecordingAllocation">The allocation if the next upcoming recording, or null if there isn't one.</param> /// <param name="liveStream">Reference to a live stream that is either existing or null for a new one.</param> /// <returns>A LiveStreamResult value to indicate success or failure.</returns> public LiveStreamResult TuneLiveStream(Channel channel, CardChannelAllocation upcomingRecordingAllocation, ref LiveStream liveStream) { var request = NewRequest("/Live/Tune", Method.POST); request.AddBody(new { channel = channel, upcomingRecordingAllocation = upcomingRecordingAllocation, stream = liveStream }); var data = Execute <TuneLiveStreamResult>(request); liveStream = data.stream; return(data.result); }
/// <summary> /// Tell the recorder to actually start a recording on the given card. The implementation /// must call /Recording/New on the Recorder callback service when the recording actually /// starts. If the recording can't start for some reason, StartRecordingFailed() must be called. /// In case the recording ends (prematurely or on time) /Recording/End must be called. IMPORTANT: /// If the suggested relative path and filename was used the recorder should /// return 'false' to /Recording/End's 'okToMoveFile'! /// </summary> /// <param name="schedulerBaseUrl">The callback URL for the Recorder to communicate with the Scheduler.</param> /// <param name="channelAllocation">The card allocation for the channel.</param> /// <param name="startTimeUtc">The actual time to start the recording (UTC).</param> /// <param name="stopTimeUtc">The actual time to stop the recording (UTC).</param> /// <param name="recordingProgram">The program to record.</param> /// <param name="suggestedBaseFileName">The suggested relative path and filename (without extension) of the recording file.</param> /// <returns>A boolean indicating the recording was initiated succesfully.</returns> public bool StartRecording(string schedulerBaseUrl, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName) { var request = NewRequest("/Recording/Start", Method.POST); request.AddBody(new { schedulerBaseUrl = schedulerBaseUrl, channelAllocation = channelAllocation, startTimeUtc = startTimeUtc, stopTimeUtc = stopTimeUtc, recordingProgram = recordingProgram, suggestedBaseFileName = suggestedBaseFileName }); return(ExecuteResult <bool>(request)); }
/// <summary> /// Tune to a channel, and get a live stream to that channel. /// </summary> /// <param name="channel">The channel to tune to.</param> /// <param name="upcomingRecordingAllocation">The allocation if the next upcoming recording, or null if there isn't one.</param> /// <param name="liveStream">A live stream that is either existing or null for a new one.</param> /// <returns>A LiveStreamResult value to indicate success or failure, and a new or updated live stream.</returns> public async Task <TuneLiveStreamResult> TuneLiveStream(Channel channel, CardChannelAllocation upcomingRecordingAllocation, LiveStream liveStream) { var request = NewRequest(HttpMethod.Post, "Live/Tune"); request.AddBody(new { channel = channel, upcomingRecordingAllocation = upcomingRecordingAllocation, stream = liveStream }); var data = await ExecuteAsync <InternalTuneLiveStreamResult>(request).ConfigureAwait(false); return(new TuneLiveStreamResult { Result = data.result, Stream = data.stream }); }
private static string BuildRecordingInfoToolTip(DateTime actualStartTime, DateTime actualStopTime, CardChannelAllocation allocation, string onText) { if (allocation != null) { PluginService pluginService = RecorderTunersCache.GetRecorderTunerById(allocation.RecorderTunerId); if (pluginService != null) { return(String.Format(CultureInfo.CurrentCulture, "{0} - {1} {2} {3} ({4})", actualStartTime.ToShortTimeString(), actualStopTime.ToShortTimeString(), onText, pluginService.Name, allocation.CardId)); } else { return(String.Format(CultureInfo.CurrentCulture, "{0} - {1} on ?", actualStartTime.ToShortTimeString(), actualStopTime.ToShortTimeString())); } } return(null); }
private static string GetIconImageFileName(ScheduleType scheduleType, bool isPartOfSeries, UpcomingCancellationReason cancellationReason, bool isRecording, CardChannelAllocation cardChannelAllocation, List <Guid> conflictingPrograms) { string suffix = String.Empty; if (isPartOfSeries) { suffix += "Series"; } if (cancellationReason != UpcomingCancellationReason.None) { suffix += "Cancelled"; if (cancellationReason == UpcomingCancellationReason.PreviouslyRecorded || cancellationReason == UpcomingCancellationReason.AlreadyQueued) { suffix += "History"; } } else { if (isRecording) { if (cardChannelAllocation == null) { suffix += "InConflict"; //toolTip = ProcessUtility.CreateConflictingProgramsToolTip(_model.UpcomingRecordings, // upcoming.UpcomingRecording.ConflictingPrograms, Utility.GetLocalizedText(TextId.ConflictsHeader), // Utility.GetLocalizedText(TextId.NoCardFoundForRecording)); } else if (conflictingPrograms.Count > 0) { suffix += "WithWarning"; //toolTip = ProcessUtility.CreateConflictingProgramsToolTip(_model.UpcomingRecordings, // upcoming.UpcomingRecording.ConflictingPrograms, Utility.GetLocalizedText(TextId.ConflictsHeader), // Utility.GetLocalizedText((TextId.NoCardFoundForRecording)); } } } return(GUIGraphicsContext.Skin + @"\Media\ARGUS_" + scheduleType.ToString() + suffix + ".png"); }
public abstract bool StartRecording(string schedulerBaseUrl, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName);
public abstract bool ValidateAndUpdateRecording(CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, DateTime stopTimeUtc);
public override LiveStreamResult TuneLiveStream(Channel channel, CardChannelAllocation upcomingRecordingAllocation, ref LiveStream liveStream) { try { TvDatabase.Channel mpChannel; List <TvDatabase.Card> availableCards = GetCardsForChannel(channel, out mpChannel); // Sort the cards by priority. availableCards.Sort(delegate(TvDatabase.Card c1, TvDatabase.Card c2) { return(c1.Priority.CompareTo(c2.Priority)); }); if (liveStream != null && _liveStreamUsers.ContainsKey(liveStream.RtspUrl)) { IUser tve3User = _liveStreamUsers[liveStream.RtspUrl]; foreach (TvDatabase.Card card in availableCards) { if (card.IdCard == tve3User.CardId) { if (Utility.CardFreeOrUsingSameTransponder(card, mpChannel, tve3User)) { Log("TuneLiveTvStream(): tuning on card {0} {1}", card.IdCard, card.Name); lock (_liveStreamsLock) { _liveStreams[liveStream.RtspUrl].StreamLastAliveTimeUtc = DateTime.UtcNow; } LiveStreamResult result = StartTimeShifting(channel, card, mpChannel, ref tve3User, ref liveStream); if (result != LiveStreamResult.NoFreeCardFound) { return(result); } } } } return(LiveStreamResult.NoRetunePossible); } else { if (liveStream != null) { StopLiveStream(liveStream); liveStream = null; } List <int> inUseHybridGroups = new List <int>(); foreach (TvDatabase.Card card in availableCards) { if (!Utility.IsInSameHybridGroup(card, inUseHybridGroups) && Utility.CardFreeOrUsingSameTransponder(card, mpChannel)) { string userName = String.Format(CultureInfo.InvariantCulture, "{0}{1}", _argusLiveUserName, Guid.NewGuid()); IUser tve3User = new User(userName, true, card.IdCard); tve3User.IdChannel = mpChannel.IdChannel; tve3User.SubChannel = -1; Log("TuneLiveTvStream(): tuning on card {0} {1}", card.IdCard, card.Name); LiveStreamResult result = StartTimeShifting(channel, card, mpChannel, ref tve3User, ref liveStream); if (result != LiveStreamResult.NoFreeCardFound) { return(result); } } // For hybrid cards, keep track of the groups that are in use. inUseHybridGroups.AddRange(Utility.GetHybridGroupIds(card)); } return(LiveStreamResult.NoFreeCardFound); } } catch (Exception ex) { Log(TraceEventType.Error, ex.Message); return(LiveStreamResult.UnknownError); } }
private bool IsCardFreeOrSharedByAllocation(TvDatabase.Card card, TvDatabase.Channel mpChannel, CardChannelAllocation allocation, CardChannelAllocation[] alreadyAllocated) { TvDatabase.TuningDetail tuning = Utility.FindTuningDetailOnCard(mpChannel, card.IdCard); if (GetCardId(card) == allocation.CardId && tuning != null) { // // The card is allocated by this allocation, but may be able to reuse the card. So let's // check if the if the card (and CAM) allow this. // // Note: "!ChannelAlreadyAllocatedOn(alreadyAllocated, allocation.CardId, channelId)" was // not added since TV Server can record the same channel several times on the same transponder. if (card.DecryptLimit == 0 || CountNumTimesAllocated(alreadyAllocated, allocation.CardId) < card.DecryptLimit) { // Get the previously allocated channel and its tuning details and let's check if the // channel we want is on the same transponder as that channel. TvDatabase.Channel allocatedChannel = GetLinkedMediaPortalChannel(allocation.ChannelType, allocation.ChannelId, allocation.ChannelName); TvDatabase.Card allocatedCard = GetCardByCardId(allocation.CardId); if (allocatedChannel != null && allocatedCard != null && Utility.IsSameTransponder(allocatedCard.IdCard, tuning, allocatedChannel)) { // Same transponder, so we can actually re-use this card and consider it free. return(true); } } // The card is allocated by this allocation, and it's not for a channel on the same // transponder, so it's not free. return(false); } // The card is not allocated by this allocation, so it's free. return(true); }
public RecordingThread(Guid recorderTunerId, string serverHostName, int tcpPort, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName, TvDatabase.Card recordOnCard, TvDatabase.Channel channel) : base(recorderTunerId, serverHostName, tcpPort, channelAllocation, startTimeUtc, stopTimeUtc, recordingProgram, true) { _suggestedBaseFileName = suggestedBaseFileName; _recordOnCard = recordOnCard; _channel = channel; }
public virtual LiveStreamResult TuneLiveStream(Channel channel, CardChannelAllocation upcomingRecordingAllocation, ref LiveStream liveStream) { liveStream = null; return(LiveStreamResult.NotSupported); }
public abstract bool StartRecording(string serverHostName, int tcpPort, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName);