예제 #1
0
 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;
 }
예제 #2
0
 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 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);
 }
예제 #4
0
 /// <summary>
 /// Check if a channel was already allocated to a card.
 /// </summary>
 /// <param name="alreadyAllocated">The array of previously allocated cards.
 /// <param name="cardId">The ID of the card we want to check.
 /// <param name="channelId">The ID of the channel.
 /// <returns>True if the channel was already allocated to this card, false otherwise.</returns>
 protected bool ChannelAlreadyAllocatedOn(CardChannelAllocation[] alreadyAllocated, string cardId, Guid channelId)
 {
     foreach (CardChannelAllocation allocation in alreadyAllocated)
     {
         if (allocation.CardId == cardId
             && allocation.ChannelId == channelId)
         {
             return true;
         }
     }
     return false;
 }
예제 #5
0
 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;
 }
 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;
 }
예제 #7
0
 /// <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);
 }
예제 #8
0
 public abstract bool ValidateAndUpdateRecording(CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, DateTime stopTimeUtc);
예제 #9
0
 public abstract bool StartRecording(string schedulerBaseUrl, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName);
 /// <summary>
 /// Aktiviert den <i>LIVE</i> Modus.
 /// </summary>
 /// <param name="channel">Der gewünschte Sender.</param>
 /// <param name="upcomingRecordingAllocation">Beschreibung der Belegung.</param>
 /// <param name="liveStream">Die Daten zum Datenstrom.</param>
 /// <returns>Das Ergebnis der Operation.</returns>
 public LiveStreamResult TuneLiveStream( Channel channel, CardChannelAllocation upcomingRecordingAllocation, ref LiveStream liveStream )
 {
     // Report
     return LiveStreamResult.NotSupported;
 }
 /// <summary>
 /// Beginnt eine neue Aufzeichnung.
 /// </summary>
 /// <param name="serverHostName">Der Name des ArgusTV Steuerdienstes.</param>
 /// <param name="tcpPort">Die Adresse des Steuerdienstes.</param>
 /// <param name="channelAllocation">Das Gerät, auf dem die Aufzeichnung stattfinden soll.</param>
 /// <param name="startTimeUtc">Der Startzeitpunkt.</param>
 /// <param name="stopTimeUtc">Der Endzeitpunkt.</param>
 /// <param name="recordingProgram">Das aufzuzeichnende Programm.</param>
 /// <param name="suggestedBaseFileName">Ein Vorschlag für den Namen der Aufzeichnungsdatei.</param>
 /// <returns>Gesetzt, wenn der Start eingeleitet wurde.</returns>
 public bool StartRecording( string serverHostName, int tcpPort, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName )
 {
     // Enqueue
     return m_activities.GetOrCreate( recordingProgram.UpcomingProgramId, this ).Start( serverHostName, tcpPort, channelAllocation, startTimeUtc, stopTimeUtc, recordingProgram, suggestedBaseFileName );
 }
        /// <summary>
        /// Prüft, ob eine Ausführung möglich ist.
        /// </summary>
        /// <param name="channel">Der Sender, von dem aufgezeichnet werden soll.</param>
        /// <param name="alreadyAllocated">Alle bereits geplanten Aufzeichnungen.</param>
        /// <param name="useReversePriority">Gesetzt, um die Planungspriorität zu verändern (wird hier ignoriert).</param>
        /// <returns>Der eindeutige Name des Gerätes, auf dem eine Aufzeichnung stattfinden könnte.</returns>
        public string AllocateCard( Channel channel, CardChannelAllocation[] alreadyAllocated, bool useReversePriority )
        {
            // Find all devices which are able to handle the channel of interest
            var candidates =
                    Devices
                        .Where( d => d.Resolve( channel.DisplayName ) != null )
                        .ToDictionary( d => d.Name, Devices.NameComparer );

            // None left
            if (candidates.Count < 1)
                return null;

            // Check all allocations
            foreach (var allocation in alreadyAllocated)
            {
                // No longer a candidate
                if (!candidates.ContainsKey( allocation.CardId ))
                    continue;

                // Attach to the device
                var device = Devices[allocation.CardId];
                if (device == null)
                    continue;

                // If the channel name is the same guess we can do it
                if (StringComparer.Ordinal.Equals( channel.DisplayName, allocation.ChannelName ))
                    continue;

                // Now we have to check for the source group - we can record different sources if coming from the same group
                var allowedGroups = device.Resolve( channel.DisplayName );
                var allocatedGroups = device.Resolve( allocation.ChannelName );

                // Check for any match - actually this is fairly slow (ok for the given scenario) and not totally correct when using multiple sources with the same name (e.g. Channel 4)
                if (device.CheckForCommonSourceGroups( allowedGroups, allocatedGroups ))
                    continue;

                // Discard
                candidates.Remove( allocation.CardId );

                // Maybe we are done
                if (candidates.Count < 1)
                    return null;
            }

            // Get the best fit - we know the list is NOT empty
            return
                candidates
                    .Values
                    .Aggregate( default( RecordingDevice ), ( best, test ) => (best == null) ? test : ((test.Priority < best.Priority) ? test : best) )
                    .Name;
        }
 /// <summary>
 /// Count the number of times a card has been allocated.
 /// </summary>
 /// <param name="alreadyAllocated">The array of previously allocated cards.</param>
 /// <param name="cardId">The ID of the card we want to check.</param>
 /// <returns>The number of times this card has been allocated.</returns>
 protected int CountNumTimesAllocated(CardChannelAllocation[] alreadyAllocated, string cardId)
 {
     int count = 0;
     foreach (CardChannelAllocation allocation in alreadyAllocated)
     {
         if (allocation.CardId == cardId)
         {
             count++;
         }
     }
     return count;
 }
 public abstract bool StartRecording(string serverHostName, int tcpPort, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName);
예제 #15
0
 /// <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);
 }
        /// <summary>
        /// Prüft eine Aufzeichnung und verändert optional den Endzeitpunkt.
        /// </summary>
        /// <param name="channelAllocation">Informationen zur Aufzeichnung.</param>
        /// <param name="recordingProgram">Das betroffene Programm.</param>
        /// <param name="stopTimeUtc">Der neue Endzeitpunkt.</param>
        /// <returns>Gesetzt, wenn die Änderung erfolgreich war.</returns>
        public bool ValidateAndUpdateRecording( CardChannelAllocation channelAllocation, UpcomingProgram recordingProgram, DateTime stopTimeUtc )
        {
            // Locate
            var activity = m_activities.Get( recordingProgram.UpcomingProgramId );
            if (activity == null)
                return false;

            // Forward
            return activity.SetNewStopTime( stopTimeUtc );
        }
예제 #17
0
 /// <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
     };
 }
        /// <summary>
        /// Beginnt eine neue Aufzeichnung.
        /// </summary>
        /// <param name="serverHostName">Der Name des ArgusTV Steuerdienstes.</param>
        /// <param name="tcpPort">Die Adresse des Steuerdienstes.</param>
        /// <param name="channelAllocation">Das Gerät, auf dem die Aufzeichnung stattfinden soll.</param>
        /// <param name="startTimeUtc">Der Startzeitpunkt.</param>
        /// <param name="stopTimeUtc">Der Endzeitpunkt.</param>
        /// <param name="recordingProgram">Das aufzuzeichnende Programm.</param>
        /// <param name="suggestedBaseFileName">Ein Vorschlag für den Namen der Aufzeichnungsdatei.</param>
        /// <returns>Gesetzt, wenn der Start eingeleitet wurde.</returns>
        public bool Start( string serverHostName, int tcpPort, CardChannelAllocation channelAllocation, DateTime startTimeUtc, DateTime stopTimeUtc, UpcomingProgram recordingProgram, string suggestedBaseFileName )
        {
            // Synchronize
            lock (m_synchronizer)
            {
                // Already active
                if (m_isRunning)
                    return false;

                // Get the first recording path in local notation
                var recordingDir =
                    m_service
                        .Configuration
                        .Directories
                        .Where( d => (d.Usage & RecordingDirectoryUsage.Recording) != 0 )
                        .Select( d => d.LocalPath )
                        .First();

                // Copy anything we need to us as the current state
                m_recordingPath = Path.Combine( recordingDir, (string.IsNullOrEmpty( suggestedBaseFileName ) ? Guid.NewGuid().ToString( "N" ) : suggestedBaseFileName) + ".ts" );
                m_allocation = channelAllocation;
                m_schedulerHost = serverHostName;
                m_originalEndTime = stopTimeUtc;
                m_program = recordingProgram;
                CurrentEndTime = stopTimeUtc;
                m_startTime = startTimeUtc;
                m_schedulerPort = tcpPort;
                m_isRunning = true;

                // Do asynchronous validation
                m_run = Validate;

                // Fire as soon as possible on the dedicated timer thread
                NextTime = DateTime.UtcNow;

                // Did it - remote call will now end
                return true;
            }
        }
예제 #19
0
 public virtual LiveStreamResult TuneLiveStream(Channel channel, CardChannelAllocation upcomingRecordingAllocation, ref LiveStream liveStream)
 {
     liveStream = null;
     return LiveStreamResult.NotSupported;
 }
예제 #20
0
 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";
 }
예제 #21
0
 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;
 }
예제 #22
0
 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);
 }