public override LiveStream[] GetLiveStreams() { List <LiveStream> liveStreams = new List <LiveStream>(); lock (_liveStreamsLock) { try { // Get cards in reverse priority. List <TvDatabase.Card> cards = Utility.GetAllCards(); cards.Sort(delegate(TvDatabase.Card c1, TvDatabase.Card c2) { return(-c1.Priority.CompareTo(c2.Priority)); }); // Get the list of live streams from TV Server Dictionary <string, IUser> mpStreamUsers = new Dictionary <string, IUser>(); foreach (TvDatabase.Card card in cards) { IUser[] cardUsers = TvServerPlugin.TvController_GetUsersForCard(card.IdCard); if (cardUsers != null) { foreach (IUser user in cardUsers) { if (user.Name.StartsWith(_argusLiveUserName)) { IUser tve3User = user; if (TvServerPlugin.TvController_IsTimeShifting(ref tve3User)) { mpStreamUsers.Add(TvServerPlugin.TvController_GetStreamingUrl(tve3User), tve3User); } } } } } // Now loop our own list and check if all those streams are indeed still up. List <string> keysToRemove = new List <string>(); foreach (LiveStream stream in _liveStreams.Values) { if (mpStreamUsers.ContainsKey(stream.RtspUrl)) { liveStreams.Add(stream); } else { keysToRemove.Add(stream.RtspUrl); } } // Remove streams that no longer exist. foreach (string keyToRemove in keysToRemove) { _liveStreams.Remove(keyToRemove); _liveStreamUsers.Remove(keyToRemove); } // Check if there are any live streams within MP that we don't know about. // If so, stop those streams (they may be left-overs from client crashes). foreach (string rtspUrl in mpStreamUsers.Keys) { if (!_liveStreams.ContainsKey(rtspUrl)) { IUser tve3User = mpStreamUsers[rtspUrl]; TvServerPlugin.TvController_StopTimeShifting(ref tve3User, TvStoppedReason.KickedByAdmin); } } } catch (Exception ex) { Log(TraceEventType.Error, ex.Message); } } return(liveStreams.ToArray()); }
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); } }