// case1: 当mediaSource为null,newPlayRange不为null时只改变入出点。 // case2: 当mediaSource不为null,newPlayRange为null时等长替换媒体源。 // case3: 当mediaSource不为null,newPlayRange不为null时变长替换媒体源。 private void ChangeMediaSourceInternal(IPlayItem playItem, IMediaSource mediaSource, PlayRange?newPlayRange) { //if (_playlist.IsLocked(playItem)) throw new PlayItemLockedException(); if (mediaSource == null && newPlayRange == null) { return; } if (mediaSource == null && newPlayRange.Value == playItem.PlayRange) { return; } if (newPlayRange != null && (playItem.ScheduleMode == PlayScheduleMode.Timing || playItem.ScheduleMode == PlayScheduleMode.TimingBreak)) { //_playlist.ValidateTimeRange(playItem.StartTime, newPlayRange.Value.Duration, playItem); ValidateTimeRange(playItem.StartTime, newPlayRange.Value.Duration, playItem); } PlayRange playRange = newPlayRange ?? new PlayRange(TimeSpan.Zero, playItem.CalculatedPlayDuration /*playItem.PlayRange.Duration*/); if (mediaSource == null) { mediaSource = playItem.MediaSource; //.Clone(); } var newPlaySource = new PlaySource(mediaSource, playRange, playItem.CGItems); IPlayItem newPlayItem = null; switch (playItem.ScheduleMode) { case PlayScheduleMode.Timing: newPlayItem = (IPlayItem)PlaybillItem.Timing(newPlaySource, playItem.StartTime); break; case PlayScheduleMode.TimingBreak: newPlayItem = (IPlayItem)PlaybillItem.TimingBreak(newPlaySource, playItem.StartTime); break; case PlayScheduleMode.Auto: newPlayItem = new AutoPlayItem(PlaybillItem.Auto(newPlaySource)); break; } var segment = this.FindSegment(playItem); DateTime startTime = segment.StartTime; int beginIndex = segment.BeginIndex; DateTime stopTime = segment.StopTime; int endIndex = segment.EndIndex; Rebuild(startTime, stopTime, beginIndex, endIndex, (items) => { var i = items.FindIndex(si => si.PlayItem == playItem); items[i] = new ScheduleItem(newPlayItem); }); }
/// <summary> /// 把定时播或定时插播改为顺播。 /// </summary> /// <param name="playItem"></param> private void ChangeToAutoScheduleInternal(IPlayItem playItem) { Debug.Assert(playItem.ScheduleMode == PlayScheduleMode.Timing || playItem.ScheduleMode == PlayScheduleMode.TimingBreak); //if (_playlist.IsLocked(playItem)) throw new PlayItemLockedException(); var prevTuple = this.FindLastTiming(i => i.StartTime < playItem.StartTime); DateTime startTime, stopTime; int beginIndex, endIndex; if (prevTuple.Item2 == -1) { startTime = _playlist[0].StartTime; beginIndex = 0; } else { startTime = prevTuple.Item1.CalculatedStopTime; beginIndex = prevTuple.Item2 + 1; } var nextTuple = this.FindFirstTiming(beginIndex, i => i.StartTime > playItem.StartTime); if (nextTuple.Item2 == -1) { stopTime = DateTime.MaxValue; endIndex = _playlist.Count - 1; } else { stopTime = nextTuple.Item1.StartTime; endIndex = nextTuple.Item2 - 1; } var playSource = ((PlaybillItem)playItem.PlaybillItem).PlaySource.Clone(); var newAutoItem = new AutoPlayItem(PlaybillItem.Auto(playSource)); Rebuild(startTime, stopTime, beginIndex, endIndex, (items) => { var i = items.FindIndex(si => si.PlayItem == playItem); items[i] = new ScheduleItem(newAutoItem); }); }
// case1: 修改定时播或定时插播的开始时间。 // case2: 定时播改为定时插播。 // case3: 定时插播改为定时播。 // case4: 顺播改为定时播或定时插播。 private void ChangeToTimingScheduleInternal(IPlayItem playItem, PlayScheduleMode?scheduleMode, DateTime?startTime) { var newScheduleMode = scheduleMode ?? playItem.ScheduleMode; Debug.Assert(newScheduleMode == PlayScheduleMode.Timing || newScheduleMode == PlayScheduleMode.TimingBreak); //if (_playlist.IsLocked(playItem)) throw new PlayItemLockedException(); var newStartTime = startTime ?? playItem.StartTime; if (playItem.ScheduleMode == newScheduleMode && playItem.StartTime == newStartTime) { return; } var playRange = playItem.PlayRange; //_playlist.ValidateTimeRange(newStartTime, playRange.Duration, playItem); ValidateTimeRange(newStartTime, playRange.Duration, playItem); // NOTE: 对于顺播PlayRange可能需要改变,因此不能简单的克隆PlaySource。 var playSource = new PlaySource(playItem.MediaSource /*.Clone()*/, playRange, playItem.CGItems); var newItem = newScheduleMode == PlayScheduleMode.Timing ? PlaybillItem.Timing(playSource, newStartTime) : PlaybillItem.TimingBreak(playSource, newStartTime); /* * 修改定时播开始时间。不能跨越前后定时播。 * 修改定时插播开始时间。不能向前跨越第一个定时播。 */ if (scheduleMode == null && startTime != null) { if (playItem.ScheduleMode == PlayScheduleMode.Timing) { // 查找前一个定时播。 var prevTuple = this.FindLastTiming(i => i.StartTime < playItem.StartTime /*startTime.Value*/); if (prevTuple.Item2 != -1) { // 如果前面有定时播,则开始时间不能小于前面定时播的结束时间。 if (startTime.Value < prevTuple.Item1.CalculatedStopTime) { throw new ArgumentException(); } } // 查找后一个定时播。 var nextTuple = this.FindFirstTiming(i => i.StartTime > playItem.StartTime /*startTime.Value*/); if (nextTuple.Item2 != -1) { // 如果后面有定时播,则结束时间不能大于后面定时播的开始时间。 if (startTime.Value.Add(playItem.PlayRange.Duration) > prevTuple.Item1.StartTime) { throw new ArgumentException(); } } var currentTuple = this.FindFirstTiming(i => i.PlayItem == playItem); if (currentTuple.Item2 != 0) { // 如果前面有片断,则更新前面片断。 var begin1 = prevTuple.Item2 == -1 ? 0 : prevTuple.Item2 + 1; this.Rebuild(_playlist[begin1].StartTime < startTime.Value ? _playlist[begin1].StartTime : startTime.Value, startTime.Value, begin1, currentTuple.Item2 - 1, null); } // 更新本片断。 var temp = (IPlayItem)newItem; _playlist[currentTuple.Item2] = new ScheduleItem(temp); this.Rebuild(temp.CalculatedStopTime, nextTuple.Item2 == -1 ? DateTime.MaxValue : nextTuple.Item1.StartTime /*stopTime*/, currentTuple.Item2 + 1, nextTuple.Item2 == -1 ? _playlist.Count - 1 : nextTuple.Item2 - 1, null); return; } else if (playItem.ScheduleMode == PlayScheduleMode.TimingBreak) { //var prevTuple = this.FindLastTiming(i => i.StartTime < startTime.Value); //if (prevTuple.Item2 == -1) //{ // if (startTime.Value < prevTuple.Item1.CalculatedStopTime) // { // throw new ArgumentException(); // } //} } else { } } this.Delete(playItem); this.AddTiming((IPlayItem)newItem); }
/// <summary> /// 把指定的顺播上移一个位置。 /// </summary> /// <param name="playItem"></param> public void MoveUp(IPlayItem playItem) { Debug.Assert(playItem.ScheduleMode == PlayScheduleMode.Auto); //if (_playlist.IsLocked(playItem)) throw new PlayItemLockedException(); if (_playlist[0] == playItem) { return; } //var index = _playlist.FindFirstIndex(i => i == playItem); var index = _playlist.FindIndex(i => i.PlayItem == playItem); if (index == -1) { throw new ArgumentException(); } if (index >= 2) { var newPrevItem = _playlist[index - 2]; //Reorder(newPrevItem, playItem); Reorder(newPrevItem.PlayItem, playItem); } else { Debug.Assert(index == 1); var oldPrevItem = _playlist[0]; if (oldPrevItem.ScheduleMode == PlayScheduleMode.Timing || oldPrevItem.ScheduleMode == PlayScheduleMode.TimingBreak) { return; } var playSource = new PlaySource(playItem.MediaSource /*.Clone()*/, playItem.PlayRange, playItem.CGItems); var newAutoItem = new AutoPlayItem(PlaybillItem.Auto(playSource)); var nextTuple = this.FindFirstTiming(index + 1, (i) => true); DateTime startTime = oldPrevItem.StartTime; int beginIndex = 0; DateTime stopTime; int endIndex; if (nextTuple.Item2 == -1) { stopTime = DateTime.MaxValue; endIndex = _playlist.Count - 1; } else { stopTime = nextTuple.Item1.StartTime; endIndex = nextTuple.Item2 - 1; } this.Rebuild(startTime, stopTime, beginIndex, endIndex, (items) => { items.RemoveAt(1); items.Insert(0, new ScheduleItem(newAutoItem)); }); } }