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 static bool CardFreeOrUsingSameTransponder(TvDatabase.Card card, TvDatabase.Channel channel, IUser userToIgnore) { IUser[] cardUsers = TvServerPlugin.TvController_GetUsersForCard(card.IdCard); if (cardUsers != null) { TvDatabase.TuningDetail tuning = Utility.FindTuningDetailOnCard(channel, card.IdCard); HashSet <int> activeChannels = new HashSet <int>(); foreach (IUser cardUser in cardUsers) { if (userToIgnore == null || cardUser.Name != userToIgnore.Name) { if (!cardUser.Name.Equals("epg", StringComparison.InvariantCultureIgnoreCase)) { activeChannels.Add(cardUser.IdChannel); if (!Utility.IsSameTransponder(card.IdCard, tuning, cardUser.IdChannel)) { return(false); } } } } return(activeChannels.Contains(channel.IdChannel) || card.DecryptLimit == 0 || activeChannels.Count < card.DecryptLimit); } return(true); }
public override string AllocateCard(Channel channel, CardChannelAllocation[] alreadyAllocated, bool useReversePriority) { try { // // Find the channel in MediaPortal (match by DisplayName) and get all the // cards this channel is mapped to. // TvDatabase.Channel mpChannel; List <TvDatabase.Card> availableCards = GetCardsForChannel(channel, out mpChannel); // Sort the cards by reverse(!) priority. int order = useReversePriority ? -1 : 1; availableCards.Sort(delegate(TvDatabase.Card c1, TvDatabase.Card c2) { return(order * c1.Priority.CompareTo(c2.Priority)); }); // // Now remove all cards that were previously allocated. // foreach (CardChannelAllocation allocation in alreadyAllocated) { TvDatabase.Card allocatedCard = GetCardByCardId(allocation.CardId); List <int> allocatedHybridGroupIds = Utility.GetHybridGroupIds(allocatedCard); List <TvDatabase.Card> cardsToRemove = new List <TvDatabase.Card>(); foreach (TvDatabase.Card card in availableCards) { bool isHybrid = (card.IdCard != allocatedCard.IdCard) && Utility.IsInSameHybridGroup(card, allocatedHybridGroupIds); if (isHybrid || !IsCardFreeOrSharedByAllocation(card, mpChannel, allocation, alreadyAllocated)) { cardsToRemove.Add(card); } } foreach (TvDatabase.Card cardToRemove in cardsToRemove) { availableCards.Remove(cardToRemove); } } // // If there's still at least one card available, return the card // with the highest priority. // foreach (TvDatabase.Card card in availableCards) { TvDatabase.TuningDetail tuning = Utility.FindTuningDetailOnCard(mpChannel, card.IdCard); if (tuning != null) { return(GetCardId(card)); } } } catch (Exception ex) { Log(TraceEventType.Error, ex.Message); } return(null); }
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 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 static bool IsInSameHybridGroup(TvDatabase.Card card, List <int> otherCardGroupIds) { if (otherCardGroupIds.Count > 0) { List <int> cardGroupIds = GetHybridGroupIds(card); foreach (int cardGroupId in cardGroupIds) { if (otherCardGroupIds.Contains(cardGroupId)) { return(true); } } } return(false); }
public static List <int> GetHybridGroupIds(TvDatabase.Card card) { List <int> groupIds = new List <int>(); if (card != null) { SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof(TvDatabase.CardGroupMap)); sb.AddConstraint(Operator.Equals, "idCard", card.IdCard); SqlResult result = Broker.Execute(sb.GetStatement()); List <TvDatabase.CardGroupMap> groupMaps = (List <TvDatabase.CardGroupMap>) ObjectFactory.GetCollection(typeof(TvDatabase.CardGroupMap), result, new List <TvDatabase.CardGroupMap>()); foreach (TvDatabase.CardGroupMap groupMap in groupMaps) { groupIds.Add(groupMap.IdCardGroup); } } return(groupIds); }
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 static bool CardFreeOrUsingSameTransponder(TvDatabase.Card card, TvDatabase.Channel channel) { return(CardFreeOrUsingSameTransponder(card, channel, null)); }
private static string GetCardId(TvDatabase.Card card) { return(card.IdCard.ToString(CultureInfo.InvariantCulture)); }
private LiveStreamResult StartTimeShifting(Channel channel, TvDatabase.Card card, TvDatabase.Channel mpChannel, ref IUser tve3User, ref LiveStream liveStream) { IChannel tuningChannel = Utility.FindTuningChannelOnCard(mpChannel, card.IdCard); if (tuningChannel != null) { if (TvServerPlugin.TvController_Tune(ref tve3User, tuningChannel, mpChannel.IdChannel) == TvResult.Succeeded) { string timeshiftFileName = Path.Combine(card.TimeShiftFolder, String.Format(CultureInfo.InvariantCulture, @"live{0}-{1}", tve3User.CardId, tve3User.SubChannel)); switch (TvServerPlugin.TvController_StartTimeShifting(ref tve3User, ref timeshiftFileName)) { case TvResult.Succeeded: if (liveStream == null) { string rtspUrl = TvServerPlugin.TvController_GetStreamingUrl(tve3User); string tsBufferFile = GetTsBufferFile(tve3User); liveStream = new LiveStream(channel, rtspUrl); liveStream.TimeshiftFile = tsBufferFile; #if USE_ARGUS_RTSP string rtspUrlSuffix = String.Format(_rtspUrlSuffixFormat, tve3User.CardId, tve3User.SubChannel); liveStream.RtspUrl = StartRtspStream(tsBufferFile, rtspUrlSuffix); #endif } liveStream.Channel = channel; liveStream.CardId = tve3User.CardId.ToString(CultureInfo.InvariantCulture); liveStream.StreamLastAliveTimeUtc = DateTime.UtcNow; lock (_liveStreamsLock) { _liveStreams[liveStream.RtspUrl] = liveStream; _liveStreamUsers[liveStream.RtspUrl] = tve3User; } return(LiveStreamResult.Succeeded); case TvResult.AllCardsBusy: return(LiveStreamResult.NoFreeCardFound); case TvResult.ChannelIsScrambled: return(LiveStreamResult.IsScrambled); case TvResult.ChannelNotMappedToAnyCard: case TvResult.NoSignalDetected: case TvResult.NoTuningDetails: case TvResult.NoVideoAudioDetected: case TvResult.UnknownChannel: return(LiveStreamResult.ChannelTuneFailed); default: return(LiveStreamResult.UnknownError); } } else { Log(TraceEventType.Error, "StartTimeShifting(): failed to tune to {0}", tuningChannel.Name); return(LiveStreamResult.ChannelTuneFailed); } } else { Log(TraceEventType.Error, "StartTimeShifting(): no tuning channel found for {0}", mpChannel.DisplayName); return(LiveStreamResult.ChannelTuneFailed); } }