bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn/* = true */) { StreamInfo *si = new StreamInfo(); if (!si->m_decoder.Create(file, (file.m_lStartOffset * 1000) / 75)) { CLog::Log(LOGWARNING, "PAPlayer::QueueNextFileEx - Failed to create the decoder"); delete si; m_callback.OnQueueNextItem(); return false; } /* decode until there is data-available */ si->m_decoder.Start(); while(si->m_decoder.GetDataSize() == 0) { int status = si->m_decoder.GetStatus(); if (status == STATUS_ENDED || status == STATUS_NO_FILE || si->m_decoder.ReadSamples(PACKET_SIZE) == RET_ERROR) { CLog::Log(LOGINFO, "PAPlayer::QueueNextFileEx - Error reading samples"); si->m_decoder.Destroy(); delete si; m_callback.OnQueueNextItem(); return false; } /* yield our time so that the main PAP thread doesnt stall */ CThread::Sleep(1); } UpdateCrossfadeTime(file); /* init the streaminfo struct */ si->m_decoder.GetDataFormat(&si->m_channelInfo, &si->m_sampleRate, &si->m_encodedSampleRate, &si->m_dataFormat); si->m_startOffset = file.m_lStartOffset * 1000 / 75; si->m_endOffset = file.m_lEndOffset * 1000 / 75; si->m_bytesPerSample = CAEUtil::DataFormatToBits(si->m_dataFormat) >> 3; si->m_bytesPerFrame = si->m_bytesPerSample * si->m_channelInfo.Count(); si->m_started = false; si->m_finishing = false; si->m_framesSent = 0; si->m_seekNextAtFrame = 0; si->m_seekFrame = -1; si->m_stream = NULL; si->m_volume = (fadeIn && m_upcomingCrossfadeMS) ? 0.0f : 1.0f; si->m_fadeOutTriggered = false; si->m_isSlaved = false; int64_t streamTotalTime = si->m_decoder.TotalTime(); if (si->m_endOffset) streamTotalTime = si->m_endOffset - si->m_startOffset; si->m_prepareNextAtFrame = 0; if (streamTotalTime >= TIME_TO_CACHE_NEXT_FILE + m_defaultCrossfadeMS) si->m_prepareNextAtFrame = (int)((streamTotalTime - TIME_TO_CACHE_NEXT_FILE - m_defaultCrossfadeMS) * si->m_sampleRate / 1000.0f); si->m_prepareTriggered = false; si->m_playNextAtFrame = 0; si->m_playNextTriggered = false; PrepareStream(si); /* add the stream to the list */ CExclusiveLock lock(m_streamsLock); m_streams.push_back(si); //update the current stream to start playing the next track at the correct frame. UpdateStreamInfoPlayNextAtFrame(m_currentStream, m_upcomingCrossfadeMS); *m_FileItem = file; return true; }
bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn/* = true */, bool job /* = false */) { // check if we advance a track of a CUE sheet // if this is the case we don't need to open a new stream std::string newURL = file.GetMusicInfoTag() ? file.GetMusicInfoTag()->GetURL() : file.GetPath(); std::string oldURL = m_FileItem->GetMusicInfoTag() ? m_FileItem->GetMusicInfoTag()->GetURL() : m_FileItem->GetPath(); if (newURL.compare(oldURL) == 0 && file.m_lStartOffset && file.m_lStartOffset == m_FileItem->m_lEndOffset && m_currentStream && m_currentStream->m_prepareTriggered) { m_continueStream = true; m_upcomingCrossfadeMS = 0; *m_FileItem = file; return true; } else { m_continueStream = false; } StreamInfo *si = new StreamInfo(); if (!si->m_decoder.Create(file, (file.m_lStartOffset * 1000) / 75)) { CLog::Log(LOGWARNING, "PAPlayer::QueueNextFileEx - Failed to create the decoder"); delete si; // advance playlist if (job) m_callback.OnPlayBackStarted(); m_callback.OnQueueNextItem(); return false; } /* decode until there is data-available */ si->m_decoder.Start(); while(si->m_decoder.GetDataSize() == 0) { int status = si->m_decoder.GetStatus(); if (status == STATUS_ENDED || status == STATUS_NO_FILE || si->m_decoder.ReadSamples(PACKET_SIZE) == RET_ERROR) { CLog::Log(LOGINFO, "PAPlayer::QueueNextFileEx - Error reading samples"); si->m_decoder.Destroy(); delete si; // advance playlist if (job) m_callback.OnPlayBackStarted(); m_callback.OnQueueNextItem(); return false; } /* yield our time so that the main PAP thread doesnt stall */ CThread::Sleep(1); } // set m_upcomingCrossfadeMS depending on type of file and user settings UpdateCrossfadeTime(file); /* init the streaminfo struct */ si->m_decoder.GetDataFormat(&si->m_channelInfo, &si->m_sampleRate, &si->m_encodedSampleRate, &si->m_dataFormat); si->m_startOffset = file.m_lStartOffset * 1000 / 75; si->m_endOffset = file.m_lEndOffset * 1000 / 75; si->m_bytesPerSample = CAEUtil::DataFormatToBits(si->m_dataFormat) >> 3; si->m_bytesPerFrame = si->m_bytesPerSample * si->m_channelInfo.Count(); si->m_started = false; si->m_finishing = false; si->m_framesSent = 0; si->m_seekNextAtFrame = 0; si->m_seekFrame = -1; si->m_stream = NULL; si->m_volume = (fadeIn && m_upcomingCrossfadeMS) ? 0.0f : 1.0f; si->m_fadeOutTriggered = false; si->m_isSlaved = false; int64_t streamTotalTime = si->m_decoder.TotalTime(); if (si->m_endOffset) streamTotalTime = si->m_endOffset - si->m_startOffset; si->m_prepareNextAtFrame = 0; // cd drives don't really like it to be crossfaded or prepared if(!file.IsCDDA()) { if (streamTotalTime >= TIME_TO_CACHE_NEXT_FILE + m_defaultCrossfadeMS) si->m_prepareNextAtFrame = (int)((streamTotalTime - TIME_TO_CACHE_NEXT_FILE - m_defaultCrossfadeMS) * si->m_sampleRate / 1000.0f); } if (m_currentStream && (AE_IS_RAW(m_currentStream->m_dataFormat) || AE_IS_RAW(si->m_dataFormat))) { m_currentStream->m_prepareTriggered = false; m_currentStream->m_waitOnDrain = true; m_currentStream->m_prepareNextAtFrame = 0; si->m_decoder.Destroy(); delete si; return false; } si->m_prepareTriggered = false; si->m_playNextAtFrame = 0; si->m_playNextTriggered = false; si->m_waitOnDrain = false; if (!PrepareStream(si)) { CLog::Log(LOGINFO, "PAPlayer::QueueNextFileEx - Error preparing stream"); si->m_decoder.Destroy(); delete si; // advance playlist if (job) m_callback.OnPlayBackStarted(); m_callback.OnQueueNextItem(); return false; } /* add the stream to the list */ CExclusiveLock lock(m_streamsLock); m_streams.push_back(si); //update the current stream to start playing the next track at the correct frame. UpdateStreamInfoPlayNextAtFrame(m_currentStream, m_upcomingCrossfadeMS); *m_FileItem = file; return true; }