示例#1
0
func runCurrentProgram(s *datastore.Schedule) error {
	cp, err := s.CurrentProgram()
	if err != nil {
		log.Println("Error fetching current program:", s.Id, err)
		return err
	}

	// Rewrite the start_at parameter to resume position from playback counter
	params := cp.Parameters
	pc := cp.PlaybackCounter(s.Id)
	startAt, _ := params["start_at"]
	startParam, parseErr := strconv.ParseInt(startAt, 10, 64)
	if parseErr != nil {
		startParam = 0
	}

	newStart := startParam + pc
	params["start_at"] = fmt.Sprintf("%d", newStart)

	// now we run the function
	pipeline := RunPipe(cp.FunctionId, cp.UUID, params)
	checkTicker := time.Tick(100 * time.Millisecond)
	pipeline.Close()

	cancelStillPlaying := make(chan int, 3)
	go func() {
		timeout := time.Tick(1 * time.Second)
		s.StillPlaying() // lock schedule playback
		for {
			select {
			case <-cancelStillPlaying:
				return
			case <-timeout:
				s.StillPlaying()
			}
		}
	}()
	cancelPlayingMarker := func() { cancelStillPlaying <- 0 }
	defer cancelPlayingMarker()

	startDiscontinuityWritten := false // always write discontinuity when starting
	segmentTimer := time.After(1 * time.Nanosecond)

	for pipeout := pipeline.MediaChannel(); true; {
		select {
		case <-segmentTimer: // if it's time to send the next segment
			v, more := <-pipeout
			segment := v.Segment
			segmentDuration := time.Duration(segment.TargetDuration * 1000000)
			segmentTimer = time.After(segmentDuration * time.Microsecond)
			cp.IncrementPlaybackCounter(s.Id)
			if !more {
				cp.ResetPlaybackCounter(s.Id)
				return nil
			}

			if !startDiscontinuityWritten {
				segment.Discontinuity = true
				startDiscontinuityWritten = true
			}

			if err := AddSegmentToSchedule(s, segment); err != nil {
				log.Println("Error adding new segment to schedule:", err)
			}
		case <-checkTicker: // if it's time to check for the next program
			nextProgramStart, err := s.NextProgramStart()
			if err == nil && time.Now().After(nextProgramStart) {
				s.PopCurrentProgram()
				cp.ResetPlaybackCounter(s.Id)
				return nil
			}
		}
	}

	return nil
}