예제 #1
0
파일: player.go 프로젝트: xfanity/pulsar
func (btp *BTPlayer) playerLoop() {
	defer btp.Close()

	start := time.Now()

	btp.log.Info("Buffer loop")

	buffered, bufferDone := btp.bufferEvents.Listen()
	defer close(bufferDone)

	go btp.bufferDialog()

	if err := <-buffered; err != nil {
		return
	}

	ga.TrackTiming("player", "buffer_time_real", int(time.Now().Sub(start).Seconds()*1000), "")

	btp.log.Info("Waiting for playback...")
	oneSecond := time.NewTicker(1 * time.Second)
	defer oneSecond.Stop()
	playbackTimeout := time.After(playbackMaxWait)
playbackWaitLoop:
	for {
		if xbmc.PlayerIsPlaying() {
			break playbackWaitLoop
		}
		select {
		case <-playbackTimeout:
			btp.log.Info("Playback was unable to start after %d seconds. Aborting...", playbackMaxWait)
			btp.bufferEvents.Broadcast(errors.New("Playback was unable to start before timeout."))
			return
		case <-oneSecond.C:
			ga.TrackEvent("player", "waiting_playback", btp.torrentName, -1)
		}
	}

	ga.TrackTiming("player", "buffer_time_perceived", int(time.Now().Sub(start).Seconds()*1000), "")

	btp.log.Info("Playback loop")
	playingTicker := time.NewTicker(60 * time.Second)
	defer playingTicker.Stop()
playbackLoop:
	for {
		if xbmc.PlayerIsPlaying() == false {
			break playbackLoop
		}
		select {
		case <-playingTicker.C:
			ga.TrackEvent("player", "playing", btp.torrentName, -1)
		case <-oneSecond.C:
		}
	}

	ga.TrackEvent("player", "stop", btp.torrentName, -1)
	ga.TrackTiming("player", "watched_time", int(time.Now().Sub(start).Seconds()*1000), "")
}
예제 #2
0
파일: player.go 프로젝트: xfanity/pulsar
func (btp *BTPlayer) bufferDialog() {
	halfSecond := time.NewTicker(500 * time.Millisecond)
	defer halfSecond.Stop()
	oneSecond := time.NewTicker(1 * time.Second)
	defer oneSecond.Stop()

	for {
		select {
		case <-halfSecond.C:
			if btp.dialogProgress.IsCanceled() {
				btp.log.Info("User cancelled the buffering")
				go ga.TrackEvent("player", "buffer_canceled", btp.torrentName, -1)
				btp.bufferEvents.Broadcast(errors.New("user canceled the buffering"))
				return
			}
		case <-oneSecond.C:
			bufferProgress := float64(0)
			btp.bufferPiecesProgressLock.Lock()
			if len(btp.bufferPiecesProgress) > 0 {
				totalProgress := float64(0)
				btp.piecesProgress(btp.bufferPiecesProgress)
				for _, v := range btp.bufferPiecesProgress {
					totalProgress += v
				}
				bufferProgress = totalProgress / float64(len(btp.bufferPiecesProgress))
			}
			btp.bufferPiecesProgressLock.Unlock()
			status := btp.torrentHandle.Status(uint(libtorrent.Torrent_handleQuery_name))
			line1, line2, line3 := btp.statusStrings(bufferProgress, status)
			btp.dialogProgress.Update(int(bufferProgress*100.0), line1, line2, line3)
			if bufferProgress >= 1 {
				btp.bufferEvents.Signal()
				return
			}
		}
	}
}
예제 #3
0
파일: player.go 프로젝트: xfanity/pulsar
func (btp *BTPlayer) onMetadataReceived() {
	btp.log.Info("Metadata received.")

	btp.torrentHandle.Pause()
	defer btp.torrentHandle.Resume()

	btp.torrentName = btp.torrentHandle.Status(uint(0)).GetName()
	go ga.TrackEvent("player", "metadata_received", btp.torrentName, -1)

	btp.torrentInfo = btp.torrentHandle.Torrent_file()

	if btp.diskStatus != nil {
		btp.log.Info("Checking for sufficient space on %s...", btp.bts.config.DownloadPath)
		torrentSize := btp.torrentInfo.Total_size()
		if btp.diskStatus.Free < torrentSize {
			btp.log.Info("Unsufficient free space on %s. Has %d, needs %d.", btp.bts.config.DownloadPath, btp.diskStatus.Free, torrentSize)
			xbmc.Notify("Pulsar", "Not enough space available on the download path.", config.AddonIcon())
			btp.bufferEvents.Broadcast(errors.New("Not enough space on download destination."))
			return
		}
	}

	btp.biggestFile = btp.findBiggestFile()
	btp.log.Info("Biggest file: %s", btp.biggestFile.GetPath())

	btp.log.Info("Setting piece priorities")

	pieceLength := float64(btp.torrentInfo.Piece_length())

	startPiece, endPiece, _ := btp.getFilePiecesAndOffset(btp.biggestFile)

	startLength := float64(endPiece-startPiece) * float64(pieceLength) * startBufferPercent
	if startLength < startBufferMinSize {
		startLength = startBufferMinSize
	}
	startBufferPieces := int(math.Ceil(startLength / pieceLength))

	// Prefer a fixed size, since metadata are very rarely over endPiecesSize=10MB
	// anyway.
	endBufferPieces := int(math.Ceil(float64(endBufferSize) / pieceLength))

	piecesPriorities := libtorrent.NewStd_vector_int()
	defer libtorrent.DeleteStd_vector_int(piecesPriorities)

	btp.bufferPiecesProgressLock.Lock()
	defer btp.bufferPiecesProgressLock.Unlock()

	// Properly set the pieces priority vector
	curPiece := 0
	for _ = 0; curPiece < startPiece; curPiece++ {
		piecesPriorities.Add(0)
	}
	for _ = 0; curPiece < startPiece+startBufferPieces; curPiece++ { // get this part
		piecesPriorities.Add(1)
		btp.bufferPiecesProgress[curPiece] = 0
		btp.torrentHandle.Set_piece_deadline(curPiece, 0, 0)
	}
	for _ = 0; curPiece < endPiece-endBufferPieces; curPiece++ {
		piecesPriorities.Add(1)
	}
	for _ = 0; curPiece <= endPiece; curPiece++ { // get this part
		piecesPriorities.Add(7)
		btp.bufferPiecesProgress[curPiece] = 0
		btp.torrentHandle.Set_piece_deadline(curPiece, 0, 0)
	}
	numPieces := btp.torrentInfo.Num_pieces()
	for _ = 0; curPiece < numPieces; curPiece++ {
		piecesPriorities.Add(0)
	}
	btp.torrentHandle.Prioritize_pieces(piecesPriorities)
}