/xbmc/cores/paplayer/PAPlayer.cpp

http://github.com/xbmc/xbmc · C++ · 1164 lines · 925 code · 162 blank · 77 comment · 209 complexity · bfeac87057c3c87e8ff2ca6216380d36 MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2018 Team Kodi
  3. * This file is part of Kodi - https://kodi.tv
  4. *
  5. * SPDX-License-Identifier: GPL-2.0-or-later
  6. * See LICENSES/README.md for more information.
  7. */
  8. #include "PAPlayer.h"
  9. #include "CodecFactory.h"
  10. #include "ServiceBroker.h"
  11. #include "Util.h"
  12. #include "cores/AudioEngine/Interfaces/AE.h"
  13. #include "cores/AudioEngine/Interfaces/AEStream.h"
  14. #include "cores/AudioEngine/Utils/AEStreamData.h"
  15. #include "cores/AudioEngine/Utils/AEUtil.h"
  16. #include "cores/DataCacheCore.h"
  17. #include "cores/VideoPlayer/Process/ProcessInfo.h"
  18. #include "messaging/ApplicationMessenger.h"
  19. #include "music/tags/MusicInfoTag.h"
  20. #include "settings/AdvancedSettings.h"
  21. #include "settings/Settings.h"
  22. #include "settings/SettingsComponent.h"
  23. #include "utils/JobManager.h"
  24. #include "utils/log.h"
  25. #include "video/Bookmark.h"
  26. using namespace KODI::MESSAGING;
  27. #define TIME_TO_CACHE_NEXT_FILE 5000 /* 5 seconds before end of song, start caching the next song */
  28. #define FAST_XFADE_TIME 80 /* 80 milliseconds */
  29. #define MAX_SKIP_XFADE_TIME 2000 /* max 2 seconds crossfade on track skip */
  30. // PAP: Psycho-acoustic Audio Player
  31. // Supporting all open audio codec standards.
  32. // First one being nullsoft's nsv audio decoder format
  33. PAPlayer::PAPlayer(IPlayerCallback& callback) :
  34. IPlayer(callback),
  35. CThread("PAPlayer"),
  36. m_signalSpeedChange(false),
  37. m_playbackSpeed(1 ),
  38. m_isPlaying(false),
  39. m_isPaused(false),
  40. m_isFinished(false),
  41. m_defaultCrossfadeMS (0),
  42. m_upcomingCrossfadeMS(0),
  43. m_audioCallback(NULL ),
  44. m_jobCounter(0),
  45. m_newForcedPlayerTime(-1),
  46. m_newForcedTotalTime (-1)
  47. {
  48. memset(&m_playerGUIData, 0, sizeof(m_playerGUIData));
  49. m_processInfo.reset(CProcessInfo::CreateInstance());
  50. m_processInfo->SetDataCache(&CServiceBroker::GetDataCacheCore());
  51. }
  52. PAPlayer::~PAPlayer()
  53. {
  54. CloseFile();
  55. }
  56. bool PAPlayer::HandlesType(const std::string &type)
  57. {
  58. ICodec* codec = CodecFactory::CreateCodec(type);
  59. if (codec && codec->CanInit())
  60. {
  61. delete codec;
  62. return true;
  63. }
  64. return false;
  65. }
  66. void PAPlayer::SoftStart(bool wait/* = false */)
  67. {
  68. CSingleLock lock(m_streamsLock);
  69. for(StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
  70. {
  71. StreamInfo* si = *itt;
  72. if (si->m_fadeOutTriggered)
  73. continue;
  74. si->m_stream->Resume();
  75. si->m_stream->FadeVolume(0.0f, 1.0f, FAST_XFADE_TIME);
  76. }
  77. if (wait)
  78. {
  79. /* wait for them to fade in */
  80. lock.Leave();
  81. CThread::Sleep(FAST_XFADE_TIME);
  82. lock.Enter();
  83. /* be sure they have faded in */
  84. while(wait)
  85. {
  86. wait = false;
  87. for(StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
  88. {
  89. StreamInfo* si = *itt;
  90. if (si->m_stream->IsFading())
  91. {
  92. lock.Leave();
  93. wait = true;
  94. CThread::Sleep(1);
  95. lock.Enter();
  96. break;
  97. }
  98. }
  99. }
  100. }
  101. }
  102. void PAPlayer::SoftStop(bool wait/* = false */, bool close/* = true */)
  103. {
  104. /* fade all the streams out fast for a nice soft stop */
  105. CSingleLock lock(m_streamsLock);
  106. for(StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
  107. {
  108. StreamInfo* si = *itt;
  109. if (si->m_stream)
  110. si->m_stream->FadeVolume(1.0f, 0.0f, FAST_XFADE_TIME);
  111. if (close)
  112. {
  113. si->m_prepareTriggered = true;
  114. si->m_playNextTriggered = true;
  115. si->m_fadeOutTriggered = true;
  116. }
  117. }
  118. /* if we are going to wait for them to finish fading */
  119. if(wait)
  120. {
  121. // fail safe timer, do not wait longer than 1000ms
  122. XbmcThreads::EndTime timer(1000);
  123. /* wait for them to fade out */
  124. lock.Leave();
  125. CThread::Sleep(FAST_XFADE_TIME);
  126. lock.Enter();
  127. /* be sure they have faded out */
  128. while(wait && !CServiceBroker::GetActiveAE()->IsSuspended() && !timer.IsTimePast())
  129. {
  130. wait = false;
  131. for(StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
  132. {
  133. StreamInfo* si = *itt;
  134. if (si->m_stream && si->m_stream->IsFading())
  135. {
  136. lock.Leave();
  137. wait = true;
  138. CThread::Sleep(1);
  139. lock.Enter();
  140. break;
  141. }
  142. }
  143. }
  144. /* if we are not closing the streams, pause them */
  145. if (!close)
  146. {
  147. for(StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
  148. {
  149. StreamInfo* si = *itt;
  150. si->m_stream->Pause();
  151. }
  152. }
  153. }
  154. }
  155. void PAPlayer::CloseAllStreams(bool fade/* = true */)
  156. {
  157. if (!fade)
  158. {
  159. CSingleLock lock(m_streamsLock);
  160. while (!m_streams.empty())
  161. {
  162. StreamInfo* si = m_streams.front();
  163. m_streams.pop_front();
  164. if (si->m_stream)
  165. {
  166. CloseFileCB(*si);
  167. CServiceBroker::GetActiveAE()->FreeStream(si->m_stream, true);
  168. si->m_stream = NULL;
  169. }
  170. si->m_decoder.Destroy();
  171. delete si;
  172. }
  173. while (!m_finishing.empty())
  174. {
  175. StreamInfo* si = m_finishing.front();
  176. m_finishing.pop_front();
  177. if (si->m_stream)
  178. {
  179. CloseFileCB(*si);
  180. CServiceBroker::GetActiveAE()->FreeStream(si->m_stream, true);
  181. si->m_stream = nullptr;
  182. }
  183. si->m_decoder.Destroy();
  184. delete si;
  185. }
  186. m_currentStream = nullptr;
  187. }
  188. else
  189. {
  190. SoftStop(false, true);
  191. CSingleLock lock(m_streamsLock);
  192. m_currentStream = NULL;
  193. }
  194. }
  195. bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
  196. {
  197. m_defaultCrossfadeMS = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MUSICPLAYER_CROSSFADE) * 1000;
  198. m_fullScreen = options.fullscreen;
  199. if (m_streams.size() > 1 || !m_defaultCrossfadeMS || m_isPaused)
  200. {
  201. CloseAllStreams(!m_isPaused);
  202. StopThread();
  203. m_isPaused = false; // Make sure to reset the pause state
  204. }
  205. {
  206. CSingleLock lock(m_streamsLock);
  207. m_jobCounter++;
  208. }
  209. CJobManager::GetInstance().Submit(
  210. [=]() { QueueNextFileEx(file, false); },
  211. this,
  212. CJob::PRIORITY_NORMAL
  213. );
  214. CSingleLock lock(m_streamsLock);
  215. if (m_streams.size() == 2)
  216. {
  217. //do a short crossfade on trackskip, set to max 2 seconds for these prev/next transitions
  218. m_upcomingCrossfadeMS = std::min(m_defaultCrossfadeMS, (unsigned int)MAX_SKIP_XFADE_TIME);
  219. //start transition to next track
  220. StreamInfo* si = m_streams.front();
  221. si->m_playNextAtFrame = si->m_framesSent; //start next track at current frame
  222. si->m_prepareTriggered = true; //next track is ready to go
  223. }
  224. lock.Leave();
  225. if (!IsRunning())
  226. Create();
  227. /* trigger playback start */
  228. m_isPlaying = true;
  229. m_startEvent.Set();
  230. // OnPlayBackStarted to be made only once. Callback processing may be slower than player process
  231. // so clear signal flag first otherwise async stream processing could also make callback
  232. m_signalStarted = false;
  233. m_callback.OnPlayBackStarted(file);
  234. return true;
  235. }
  236. void PAPlayer::UpdateCrossfadeTime(const CFileItem& file)
  237. {
  238. // we explicitly disable crossfading for audio cds
  239. if (file.IsCDDA())
  240. m_upcomingCrossfadeMS = 0;
  241. else
  242. m_upcomingCrossfadeMS = m_defaultCrossfadeMS = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MUSICPLAYER_CROSSFADE) * 1000;
  243. if (m_upcomingCrossfadeMS)
  244. {
  245. if (!m_currentStream ||
  246. (file.HasMusicInfoTag() && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MUSICPLAYER_CROSSFADEALBUMTRACKS) &&
  247. m_currentStream->m_fileItem.HasMusicInfoTag() &&
  248. (m_currentStream->m_fileItem.GetMusicInfoTag()->GetAlbum() != "") &&
  249. (m_currentStream->m_fileItem.GetMusicInfoTag()->GetAlbum() == file.GetMusicInfoTag()->GetAlbum()) &&
  250. (m_currentStream->m_fileItem.GetMusicInfoTag()->GetDiscNumber() == file.GetMusicInfoTag()->GetDiscNumber()) &&
  251. (m_currentStream->m_fileItem.GetMusicInfoTag()->GetTrackNumber() == file.GetMusicInfoTag()->GetTrackNumber() - 1)))
  252. {
  253. //do not crossfade when playing consecutive albumtracks
  254. m_upcomingCrossfadeMS = 0;
  255. }
  256. }
  257. }
  258. bool PAPlayer::QueueNextFile(const CFileItem &file)
  259. {
  260. {
  261. CSingleLock lock(m_streamsLock);
  262. m_jobCounter++;
  263. }
  264. CJobManager::GetInstance().Submit([this, file]() {
  265. QueueNextFileEx(file, true);
  266. }, this, CJob::PRIORITY_NORMAL);
  267. return true;
  268. }
  269. bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn)
  270. {
  271. if (m_currentStream)
  272. {
  273. // check if we advance a track of a CUE sheet
  274. // if this is the case we don't need to open a new stream
  275. std::string newURL = file.GetDynURL().GetFileName();
  276. std::string oldURL = m_currentStream->m_fileItem.GetDynURL().GetFileName();
  277. if (newURL.compare(oldURL) == 0 &&
  278. file.m_lStartOffset &&
  279. file.m_lStartOffset == m_currentStream->m_fileItem.m_lEndOffset &&
  280. m_currentStream && m_currentStream->m_prepareTriggered)
  281. {
  282. m_currentStream->m_nextFileItem.reset(new CFileItem(file));
  283. m_upcomingCrossfadeMS = 0;
  284. return true;
  285. }
  286. m_currentStream->m_nextFileItem.reset();
  287. }
  288. StreamInfo *si = new StreamInfo();
  289. si->m_fileItem = file;
  290. if (!si->m_decoder.Create(file, si->m_fileItem.m_lStartOffset))
  291. {
  292. CLog::Log(LOGWARNING, "PAPlayer::QueueNextFileEx - Failed to create the decoder");
  293. // advance playlist
  294. AdvancePlaylistOnError(si->m_fileItem);
  295. m_callback.OnQueueNextItem();
  296. delete si;
  297. return false;
  298. }
  299. /* decode until there is data-available */
  300. si->m_decoder.Start();
  301. while (si->m_decoder.GetDataSize(true) == 0)
  302. {
  303. int status = si->m_decoder.GetStatus();
  304. if (status == STATUS_ENDED ||
  305. status == STATUS_NO_FILE ||
  306. si->m_decoder.ReadSamples(PACKET_SIZE) == RET_ERROR)
  307. {
  308. CLog::Log(LOGINFO, "PAPlayer::QueueNextFileEx - Error reading samples");
  309. si->m_decoder.Destroy();
  310. // advance playlist
  311. AdvancePlaylistOnError(si->m_fileItem);
  312. m_callback.OnQueueNextItem();
  313. delete si;
  314. return false;
  315. }
  316. /* yield our time so that the main PAP thread doesnt stall */
  317. CThread::Sleep(1);
  318. }
  319. // set m_upcomingCrossfadeMS depending on type of file and user settings
  320. UpdateCrossfadeTime(si->m_fileItem);
  321. /* init the streaminfo struct */
  322. si->m_audioFormat = si->m_decoder.GetFormat();
  323. si->m_startOffset = file.m_lStartOffset;
  324. si->m_endOffset = file.m_lEndOffset;
  325. si->m_bytesPerSample = CAEUtil::DataFormatToBits(si->m_audioFormat.m_dataFormat) >> 3;
  326. si->m_bytesPerFrame = si->m_bytesPerSample * si->m_audioFormat.m_channelLayout.Count();
  327. si->m_started = false;
  328. si->m_finishing = false;
  329. si->m_framesSent = 0;
  330. si->m_seekNextAtFrame = 0;
  331. if (si->m_fileItem.HasProperty("audiobook_bookmark"))
  332. si->m_seekFrame = si->m_audioFormat.m_sampleRate * CUtil::ConvertMilliSecsToSecs(si->m_fileItem.GetProperty("audiobook_bookmark").asInteger());
  333. else
  334. si->m_seekFrame = -1;
  335. si->m_stream = NULL;
  336. si->m_volume = (fadeIn && m_upcomingCrossfadeMS) ? 0.0f : 1.0f;
  337. si->m_fadeOutTriggered = false;
  338. si->m_isSlaved = false;
  339. si->m_decoderTotal = si->m_decoder.TotalTime();
  340. int64_t streamTotalTime = si->m_decoderTotal;
  341. if (si->m_endOffset)
  342. streamTotalTime = si->m_endOffset - si->m_startOffset;
  343. si->m_prepareNextAtFrame = 0;
  344. // cd drives don't really like it to be crossfaded or prepared
  345. if(!file.IsCDDA())
  346. {
  347. if (streamTotalTime >= TIME_TO_CACHE_NEXT_FILE + m_defaultCrossfadeMS)
  348. si->m_prepareNextAtFrame = (int)((streamTotalTime - TIME_TO_CACHE_NEXT_FILE - m_defaultCrossfadeMS) * si->m_audioFormat.m_sampleRate / 1000.0f);
  349. }
  350. if (m_currentStream && ((m_currentStream->m_audioFormat.m_dataFormat == AE_FMT_RAW) || (si->m_audioFormat.m_dataFormat == AE_FMT_RAW)))
  351. {
  352. m_currentStream->m_prepareTriggered = false;
  353. m_currentStream->m_waitOnDrain = true;
  354. m_currentStream->m_prepareNextAtFrame = 0;
  355. si->m_decoder.Destroy();
  356. delete si;
  357. return false;
  358. }
  359. si->m_prepareTriggered = false;
  360. si->m_playNextAtFrame = 0;
  361. si->m_playNextTriggered = false;
  362. si->m_waitOnDrain = false;
  363. if (!PrepareStream(si))
  364. {
  365. CLog::Log(LOGINFO, "PAPlayer::QueueNextFileEx - Error preparing stream");
  366. si->m_decoder.Destroy();
  367. // advance playlist
  368. AdvancePlaylistOnError(si->m_fileItem);
  369. m_callback.OnQueueNextItem();
  370. delete si;
  371. return false;
  372. }
  373. /* add the stream to the list */
  374. CSingleLock lock(m_streamsLock);
  375. m_streams.push_back(si);
  376. //update the current stream to start playing the next track at the correct frame.
  377. UpdateStreamInfoPlayNextAtFrame(m_currentStream, m_upcomingCrossfadeMS);
  378. return true;
  379. }
  380. void PAPlayer::UpdateStreamInfoPlayNextAtFrame(StreamInfo *si, unsigned int crossFadingTime)
  381. {
  382. // if no crossfading or cue sheet, wait for eof
  383. if (si && (crossFadingTime || si->m_endOffset))
  384. {
  385. int64_t streamTotalTime = si->m_decoder.TotalTime();
  386. if (si->m_endOffset)
  387. streamTotalTime = si->m_endOffset - si->m_startOffset;
  388. if (streamTotalTime < crossFadingTime)
  389. si->m_playNextAtFrame = (int)((streamTotalTime / 2) * si->m_audioFormat.m_sampleRate / 1000.0f);
  390. else
  391. si->m_playNextAtFrame = (int)((streamTotalTime - crossFadingTime) * si->m_audioFormat.m_sampleRate / 1000.0f);
  392. }
  393. }
  394. inline bool PAPlayer::PrepareStream(StreamInfo *si)
  395. {
  396. /* if we have a stream we are already prepared */
  397. if (si->m_stream)
  398. return true;
  399. /* get a paused stream */
  400. AEAudioFormat format = si->m_audioFormat;
  401. si->m_stream = CServiceBroker::GetActiveAE()->MakeStream(
  402. format,
  403. AESTREAM_PAUSED
  404. );
  405. if (!si->m_stream)
  406. {
  407. CLog::Log(LOGDEBUG, "PAPlayer::PrepareStream - Failed to get IAEStream");
  408. return false;
  409. }
  410. si->m_stream->SetVolume(si->m_volume);
  411. float peak = 1.0;
  412. float gain = si->m_decoder.GetReplayGain(peak);
  413. if (peak * gain <= 1.0)
  414. // No clipping protection needed
  415. si->m_stream->SetReplayGain(gain);
  416. else if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MUSICPLAYER_REPLAYGAINAVOIDCLIPPING))
  417. // Normalise volume reducing replaygain to avoid needing clipping protection, plays file at lower level
  418. si->m_stream->SetReplayGain(1.0f / fabs(peak));
  419. else
  420. // Clipping protection (when enabled in AE) by audio limiting, applied just where needed
  421. si->m_stream->SetAmplification(gain);
  422. /* if its not the first stream and crossfade is not enabled */
  423. if (m_currentStream && m_currentStream != si && !m_upcomingCrossfadeMS)
  424. {
  425. /* slave the stream for gapless */
  426. si->m_isSlaved = true;
  427. m_currentStream->m_stream->RegisterSlave(si->m_stream);
  428. }
  429. /* fill the stream's buffer */
  430. while(si->m_stream->IsBuffering())
  431. {
  432. int status = si->m_decoder.GetStatus();
  433. if (status == STATUS_ENDED ||
  434. status == STATUS_NO_FILE ||
  435. si->m_decoder.ReadSamples(PACKET_SIZE) == RET_ERROR)
  436. {
  437. CLog::Log(LOGINFO, "PAPlayer::PrepareStream - Stream Finished");
  438. break;
  439. }
  440. if (!QueueData(si))
  441. break;
  442. /* yield our time so that the main PAP thread doesnt stall */
  443. CThread::Sleep(1);
  444. }
  445. CLog::Log(LOGINFO, "PAPlayer::PrepareStream - Ready");
  446. return true;
  447. }
  448. bool PAPlayer::CloseFile(bool reopen)
  449. {
  450. if (reopen)
  451. CServiceBroker::GetActiveAE()->KeepConfiguration(3000);
  452. if (!m_isPaused)
  453. SoftStop(true, true);
  454. CloseAllStreams(false);
  455. /* wait for the thread to terminate */
  456. StopThread(true);//true - wait for end of thread
  457. // wait for any pending jobs to complete
  458. {
  459. CSingleLock lock(m_streamsLock);
  460. while (m_jobCounter > 0)
  461. {
  462. lock.Leave();
  463. m_jobEvent.WaitMSec(100);
  464. lock.Enter();
  465. }
  466. }
  467. return true;
  468. }
  469. void PAPlayer::Process()
  470. {
  471. if (!m_startEvent.WaitMSec(100))
  472. {
  473. CLog::Log(LOGDEBUG, "PAPlayer::Process - Failed to receive start event");
  474. return;
  475. }
  476. CLog::Log(LOGDEBUG, "PAPlayer::Process - Playback started");
  477. while(m_isPlaying && !m_bStop)
  478. {
  479. /* this needs to happen outside of any locks to prevent deadlocks */
  480. if (m_signalSpeedChange)
  481. {
  482. m_callback.OnPlayBackSpeedChanged(m_playbackSpeed);
  483. m_signalSpeedChange = false;
  484. }
  485. double freeBufferTime = 0.0;
  486. ProcessStreams(freeBufferTime);
  487. // if none of our streams wants at least 10ms of data, we sleep
  488. if (freeBufferTime < 0.01)
  489. {
  490. CThread::Sleep(10);
  491. }
  492. if (m_newForcedPlayerTime != -1)
  493. {
  494. if (SetTimeInternal(m_newForcedPlayerTime))
  495. {
  496. m_newForcedPlayerTime = -1;
  497. }
  498. }
  499. if (m_newForcedTotalTime != -1)
  500. {
  501. if (SetTotalTimeInternal(m_newForcedTotalTime))
  502. {
  503. m_newForcedTotalTime = -1;
  504. }
  505. }
  506. GetTimeInternal(); //update for GUI
  507. }
  508. m_isPlaying = false;
  509. }
  510. inline void PAPlayer::ProcessStreams(double &freeBufferTime)
  511. {
  512. CSingleLock sharedLock(m_streamsLock);
  513. if (m_isFinished && m_streams.empty() && m_finishing.empty())
  514. {
  515. m_isPlaying = false;
  516. freeBufferTime = 1.0;
  517. return;
  518. }
  519. /* destroy any drained streams */
  520. for (auto itt = m_finishing.begin(); itt != m_finishing.end();)
  521. {
  522. StreamInfo* si = *itt;
  523. if (si->m_stream->IsDrained())
  524. {
  525. itt = m_finishing.erase(itt);
  526. CloseFileCB(*si);
  527. CServiceBroker::GetActiveAE()->FreeStream(si->m_stream, true);
  528. delete si;
  529. CLog::Log(LOGDEBUG, "PAPlayer::ProcessStreams - Stream Freed");
  530. }
  531. else
  532. ++itt;
  533. }
  534. sharedLock.Leave();
  535. CSingleLock lock(m_streamsLock);
  536. for(StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
  537. {
  538. StreamInfo* si = *itt;
  539. if (!m_currentStream && !si->m_started)
  540. {
  541. m_currentStream = si;
  542. UpdateGUIData(si); //update for GUI
  543. }
  544. /* if the stream is finishing */
  545. if ((si->m_playNextTriggered && si->m_stream && !si->m_stream->IsFading()) || !ProcessStream(si, freeBufferTime))
  546. {
  547. if (!si->m_prepareTriggered)
  548. {
  549. if (si->m_waitOnDrain)
  550. {
  551. si->m_stream->Drain(true);
  552. si->m_waitOnDrain = false;
  553. }
  554. si->m_prepareTriggered = true;
  555. m_callback.OnQueueNextItem();
  556. }
  557. /* remove the stream */
  558. itt = m_streams.erase(itt);
  559. /* if its the current stream */
  560. if (si == m_currentStream)
  561. {
  562. /* if it was the last stream */
  563. if (itt == m_streams.end())
  564. {
  565. /* if it didnt trigger the next queue item */
  566. if (!si->m_prepareTriggered)
  567. {
  568. if (si->m_waitOnDrain)
  569. {
  570. si->m_stream->Drain(true);
  571. si->m_waitOnDrain = false;
  572. }
  573. m_callback.OnQueueNextItem();
  574. si->m_prepareTriggered = true;
  575. }
  576. m_currentStream = NULL;
  577. }
  578. else
  579. {
  580. m_currentStream = *itt;
  581. UpdateGUIData(*itt); //update for GUI
  582. }
  583. }
  584. /* unregister the audio callback */
  585. si->m_stream->UnRegisterAudioCallback();
  586. si->m_decoder.Destroy();
  587. si->m_stream->Drain(false);
  588. m_finishing.push_back(si);
  589. return;
  590. }
  591. if (!si->m_started)
  592. continue;
  593. // is it time to prepare the next stream?
  594. if (si->m_prepareNextAtFrame > 0 && !si->m_prepareTriggered && si->m_framesSent >= si->m_prepareNextAtFrame)
  595. {
  596. si->m_prepareTriggered = true;
  597. m_callback.OnQueueNextItem();
  598. }
  599. // it is time to start playing the next stream?
  600. if (si->m_playNextAtFrame > 0 && !si->m_playNextTriggered && !si->m_nextFileItem && si->m_framesSent >= si->m_playNextAtFrame)
  601. {
  602. if (!si->m_prepareTriggered)
  603. {
  604. si->m_prepareTriggered = true;
  605. m_callback.OnQueueNextItem();
  606. }
  607. if (!m_isFinished)
  608. {
  609. if (m_upcomingCrossfadeMS)
  610. {
  611. si->m_stream->FadeVolume(1.0f, 0.0f, m_upcomingCrossfadeMS);
  612. si->m_fadeOutTriggered = true;
  613. }
  614. m_currentStream = NULL;
  615. /* unregister the audio callback */
  616. si->m_stream->UnRegisterAudioCallback();
  617. }
  618. si->m_playNextTriggered = true;
  619. }
  620. }
  621. }
  622. inline bool PAPlayer::ProcessStream(StreamInfo *si, double &freeBufferTime)
  623. {
  624. /* if playback needs to start on this stream, do it */
  625. if (si == m_currentStream && !si->m_started)
  626. {
  627. si->m_started = true;
  628. si->m_stream->RegisterAudioCallback(m_audioCallback);
  629. if (!si->m_isSlaved)
  630. si->m_stream->Resume();
  631. si->m_stream->FadeVolume(0.0f, 1.0f, m_upcomingCrossfadeMS);
  632. if (m_signalStarted)
  633. m_callback.OnPlayBackStarted(si->m_fileItem);
  634. m_signalStarted = true;
  635. if (m_fullScreen)
  636. {
  637. CApplicationMessenger::GetInstance().PostMsg(TMSG_SWITCHTOFULLSCREEN);
  638. m_fullScreen = false;
  639. }
  640. m_callback.OnAVStarted(si->m_fileItem);
  641. }
  642. /* if we have not started yet and the stream has been primed */
  643. unsigned int space = si->m_stream->GetSpace();
  644. if (!si->m_started && !space)
  645. return true;
  646. /* see if it is time yet to FF/RW or a direct seek */
  647. if (!si->m_playNextTriggered && ((m_playbackSpeed != 1 && si->m_framesSent >= si->m_seekNextAtFrame) || si->m_seekFrame > -1))
  648. {
  649. int64_t time = (int64_t)0;
  650. /* if its a direct seek */
  651. if (si->m_seekFrame > -1)
  652. {
  653. time = (int64_t)((float)si->m_seekFrame / (float)si->m_audioFormat.m_sampleRate * 1000.0f);
  654. si->m_framesSent = (int)(si->m_seekFrame - ((float)si->m_startOffset * (float)si->m_audioFormat.m_sampleRate) / 1000.0f);
  655. si->m_seekFrame = -1;
  656. m_playerGUIData.m_time = time; //update for GUI
  657. si->m_seekNextAtFrame = 0;
  658. CDataCacheCore::GetInstance().SetPlayTimes(0, time, 0, m_playerGUIData.m_totalTime);
  659. }
  660. /* if its FF/RW */
  661. else
  662. {
  663. si->m_framesSent += si->m_audioFormat.m_sampleRate * (m_playbackSpeed - 1);
  664. si->m_seekNextAtFrame = si->m_framesSent + si->m_audioFormat.m_sampleRate / 2;
  665. time = (int64_t)(((float)si->m_framesSent / (float)si->m_audioFormat.m_sampleRate * 1000.0f) + (float)si->m_startOffset);
  666. }
  667. /* if we are seeking back before the start of the track start normal playback */
  668. if (time < si->m_startOffset || si->m_framesSent < 0)
  669. {
  670. time = si->m_startOffset;
  671. si->m_framesSent = 0;
  672. si->m_seekNextAtFrame = 0;
  673. SetSpeed(1);
  674. }
  675. si->m_decoder.Seek(time);
  676. }
  677. int status = si->m_decoder.GetStatus();
  678. if (status == STATUS_ENDED ||
  679. status == STATUS_NO_FILE ||
  680. si->m_decoder.ReadSamples(PACKET_SIZE) == RET_ERROR ||
  681. ((si->m_endOffset) && (si->m_framesSent / si->m_audioFormat.m_sampleRate >= (si->m_endOffset - si->m_startOffset) / 1000)))
  682. {
  683. if (si == m_currentStream && si->m_nextFileItem)
  684. {
  685. CloseFileCB(*si);
  686. // update current stream with info of next track
  687. si->m_startOffset = si->m_nextFileItem->m_lStartOffset;
  688. if (si->m_nextFileItem->m_lEndOffset)
  689. si->m_endOffset = si->m_nextFileItem->m_lEndOffset;
  690. else
  691. si->m_endOffset = 0;
  692. si->m_framesSent = 0;
  693. si->m_fileItem = *si->m_nextFileItem;
  694. si->m_nextFileItem.reset();
  695. int64_t streamTotalTime = si->m_decoder.TotalTime() - si->m_startOffset;
  696. if (si->m_endOffset)
  697. streamTotalTime = si->m_endOffset - si->m_startOffset;
  698. // calculate time when to prepare next stream
  699. si->m_prepareNextAtFrame = 0;
  700. if (streamTotalTime >= TIME_TO_CACHE_NEXT_FILE + m_defaultCrossfadeMS)
  701. si->m_prepareNextAtFrame = (int)((streamTotalTime - TIME_TO_CACHE_NEXT_FILE - m_defaultCrossfadeMS) * si->m_audioFormat.m_sampleRate / 1000.0f);
  702. si->m_prepareTriggered = false;
  703. si->m_playNextAtFrame = 0;
  704. si->m_playNextTriggered = false;
  705. si->m_seekNextAtFrame = 0;
  706. //update the current stream to start playing the next track at the correct frame.
  707. UpdateStreamInfoPlayNextAtFrame(m_currentStream, m_upcomingCrossfadeMS);
  708. UpdateGUIData(si);
  709. if (m_signalStarted)
  710. m_callback.OnPlayBackStarted(si->m_fileItem);
  711. m_signalStarted = true;
  712. m_callback.OnAVStarted(si->m_fileItem);
  713. }
  714. else
  715. {
  716. CLog::Log(LOGINFO, "PAPlayer::ProcessStream - Stream Finished");
  717. return false;
  718. }
  719. }
  720. if (!QueueData(si))
  721. return false;
  722. /* update free buffer time if we are running */
  723. if (si->m_started)
  724. {
  725. if (si->m_stream->IsBuffering())
  726. freeBufferTime = 1.0;
  727. else
  728. {
  729. double free_space;
  730. if (si->m_audioFormat.m_dataFormat != AE_FMT_RAW)
  731. free_space = (double)(si->m_stream->GetSpace() / si->m_bytesPerSample) / si->m_audioFormat.m_sampleRate;
  732. else
  733. free_space = (double) si->m_stream->GetSpace() * si->m_audioFormat.m_streamInfo.GetDuration() / 1000;
  734. freeBufferTime = std::max(freeBufferTime , free_space);
  735. }
  736. }
  737. return true;
  738. }
  739. bool PAPlayer::QueueData(StreamInfo *si)
  740. {
  741. unsigned int space = si->m_stream->GetSpace();
  742. if (si->m_audioFormat.m_dataFormat != AE_FMT_RAW)
  743. {
  744. unsigned int samples = std::min(si->m_decoder.GetDataSize(false), space / si->m_bytesPerSample);
  745. if (!samples)
  746. return true;
  747. // we want complete frames
  748. samples -= samples % si->m_audioFormat.m_channelLayout.Count();
  749. uint8_t* data = (uint8_t*)si->m_decoder.GetData(samples);
  750. if (!data)
  751. {
  752. CLog::Log(LOGERROR, "PAPlayer::QueueData - Failed to get data from the decoder");
  753. return false;
  754. }
  755. unsigned int frames = samples/si->m_audioFormat.m_channelLayout.Count();
  756. unsigned int added = si->m_stream->AddData(&data, 0, frames, nullptr);
  757. si->m_framesSent += added;
  758. }
  759. else
  760. {
  761. if (!space)
  762. return true;
  763. int size;
  764. uint8_t *data = si->m_decoder.GetRawData(size);
  765. if (data && size)
  766. {
  767. int added = si->m_stream->AddData(&data, 0, size, nullptr);
  768. if (added != size)
  769. {
  770. CLog::Log(LOGERROR, "PAPlayer::QueueData - unknown error");
  771. return false;
  772. }
  773. si->m_framesSent += si->m_audioFormat.m_streamInfo.GetDuration() / 1000 * si->m_audioFormat.m_streamInfo.m_sampleRate;
  774. }
  775. }
  776. const ICodec* codec = si->m_decoder.GetCodec();
  777. m_playerGUIData.m_cacheLevel = codec ? codec->GetCacheLevel() : 0; //update for GUI
  778. return true;
  779. }
  780. void PAPlayer::OnExit()
  781. {
  782. //@todo signal OnPlayBackError if there was an error on last stream
  783. if (m_isFinished && !m_bStop)
  784. m_callback.OnPlayBackEnded();
  785. else
  786. m_callback.OnPlayBackStopped();
  787. }
  788. void PAPlayer::OnNothingToQueueNotify()
  789. {
  790. m_isFinished = true;
  791. }
  792. bool PAPlayer::IsPlaying() const
  793. {
  794. return m_isPlaying;
  795. }
  796. void PAPlayer::Pause()
  797. {
  798. if (m_isPaused)
  799. {
  800. SetSpeed(1);
  801. }
  802. else
  803. {
  804. SetSpeed(0);
  805. }
  806. }
  807. void PAPlayer::SetVolume(float volume)
  808. {
  809. }
  810. void PAPlayer::SetDynamicRangeCompression(long drc)
  811. {
  812. }
  813. void PAPlayer::SetSpeed(float speed)
  814. {
  815. m_playbackSpeed = static_cast<int>(speed);
  816. CDataCacheCore::GetInstance().SetSpeed(1.0, speed);
  817. if (m_playbackSpeed != 0 && m_isPaused)
  818. {
  819. m_isPaused = false;
  820. SoftStart();
  821. m_callback.OnPlayBackResumed();
  822. }
  823. else if (m_playbackSpeed == 0 && !m_isPaused)
  824. {
  825. m_isPaused = true;
  826. SoftStop(true, false);
  827. m_callback.OnPlayBackPaused();
  828. }
  829. m_signalSpeedChange = true;
  830. }
  831. int64_t PAPlayer::GetTimeInternal()
  832. {
  833. CSingleLock lock(m_streamsLock);
  834. if (!m_currentStream)
  835. return 0;
  836. double time = ((double)m_currentStream->m_framesSent / (double)m_currentStream->m_audioFormat.m_sampleRate);
  837. if (m_currentStream->m_stream)
  838. time -= m_currentStream->m_stream->GetDelay();
  839. time = time * 1000.0;
  840. m_playerGUIData.m_time = (int64_t)time; //update for GUI
  841. CDataCacheCore::GetInstance().SetPlayTimes(0, time, 0, m_playerGUIData.m_totalTime);
  842. return (int64_t)time;
  843. }
  844. bool PAPlayer::SetTotalTimeInternal(int64_t time)
  845. {
  846. CSingleLock lock(m_streamsLock);
  847. if (!m_currentStream)
  848. {
  849. return false;
  850. }
  851. m_currentStream->m_decoder.SetTotalTime(time);
  852. UpdateGUIData(m_currentStream);
  853. return true;
  854. }
  855. bool PAPlayer::SetTimeInternal(int64_t time)
  856. {
  857. CSingleLock lock(m_streamsLock);
  858. if (!m_currentStream)
  859. return false;
  860. m_currentStream->m_framesSent = time / 1000 * m_currentStream->m_audioFormat.m_sampleRate;
  861. if (m_currentStream->m_stream)
  862. m_currentStream->m_framesSent += m_currentStream->m_stream->GetDelay() * m_currentStream->m_audioFormat.m_sampleRate;
  863. return true;
  864. }
  865. void PAPlayer::SetTime(int64_t time)
  866. {
  867. m_newForcedPlayerTime = time;
  868. }
  869. int64_t PAPlayer::GetTotalTime64()
  870. {
  871. CSingleLock lock(m_streamsLock);
  872. if (!m_currentStream)
  873. return 0;
  874. int64_t total = m_currentStream->m_decoder.TotalTime();
  875. if (m_currentStream->m_endOffset)
  876. total = m_currentStream->m_endOffset;
  877. total -= m_currentStream->m_startOffset;
  878. return total;
  879. }
  880. void PAPlayer::SetTotalTime(int64_t time)
  881. {
  882. m_newForcedTotalTime = time;
  883. }
  884. int PAPlayer::GetCacheLevel() const
  885. {
  886. return m_playerGUIData.m_cacheLevel;
  887. }
  888. void PAPlayer::GetAudioStreamInfo(int index, AudioStreamInfo &info)
  889. {
  890. info.bitrate = m_playerGUIData.m_audioBitrate;
  891. info.channels = m_playerGUIData.m_channelCount;
  892. info.codecName = m_playerGUIData.m_codec;
  893. info.samplerate = m_playerGUIData.m_sampleRate;
  894. info.bitspersample = m_playerGUIData.m_bitsPerSample;
  895. }
  896. bool PAPlayer::CanSeek()
  897. {
  898. return m_playerGUIData.m_canSeek;
  899. }
  900. void PAPlayer::Seek(bool bPlus, bool bLargeStep, bool bChapterOverride)
  901. {
  902. if (!CanSeek()) return;
  903. long long seek;
  904. const std::shared_ptr<CAdvancedSettings> advancedSettings = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings();
  905. if (advancedSettings->m_musicUseTimeSeeking && m_playerGUIData.m_totalTime > 2 * advancedSettings->m_musicTimeSeekForwardBig)
  906. {
  907. if (bLargeStep)
  908. seek = bPlus ? advancedSettings->m_musicTimeSeekForwardBig : advancedSettings->m_musicTimeSeekBackwardBig;
  909. else
  910. seek = bPlus ? advancedSettings->m_musicTimeSeekForward : advancedSettings->m_musicTimeSeekBackward;
  911. seek *= 1000;
  912. seek += m_playerGUIData.m_time;
  913. }
  914. else
  915. {
  916. float percent;
  917. if (bLargeStep)
  918. percent = bPlus ? static_cast<float>(advancedSettings->m_musicPercentSeekForwardBig) : static_cast<float>(advancedSettings->m_musicPercentSeekBackwardBig);
  919. else
  920. percent = bPlus ? static_cast<float>(advancedSettings->m_musicPercentSeekForward) : static_cast<float>(advancedSettings->m_musicPercentSeekBackward);
  921. seek = static_cast<long long>(GetTotalTime64() * (GetPercentage() + percent) / 100);
  922. }
  923. SeekTime(seek);
  924. }
  925. void PAPlayer::SeekTime(int64_t iTime /*=0*/)
  926. {
  927. if (!CanSeek()) return;
  928. CSingleLock lock(m_streamsLock);
  929. if (!m_currentStream)
  930. return;
  931. int64_t seekOffset = iTime - GetTimeInternal();
  932. if (m_playbackSpeed != 1)
  933. SetSpeed(1);
  934. m_currentStream->m_seekFrame = (int)((float)m_currentStream->m_audioFormat.m_sampleRate * ((float)iTime + (float)m_currentStream->m_startOffset) / 1000.0f);
  935. m_callback.OnPlayBackSeek(iTime, seekOffset);
  936. }
  937. void PAPlayer::SeekPercentage(float fPercent /*=0*/)
  938. {
  939. if (fPercent < 0.0f ) fPercent = 0.0f;
  940. if (fPercent > 100.0f) fPercent = 100.0f;
  941. SeekTime((int64_t)(fPercent * 0.01f * (float)GetTotalTime64()));
  942. }
  943. float PAPlayer::GetPercentage()
  944. {
  945. if (m_playerGUIData.m_totalTime > 0)
  946. return m_playerGUIData.m_time * 100.0f / m_playerGUIData.m_totalTime;
  947. return 0.0f;
  948. }
  949. void PAPlayer::UpdateGUIData(StreamInfo *si)
  950. {
  951. /* Store data need by external threads in member
  952. * structure to prevent locking conflicts when
  953. * data required by GUI and main application
  954. */
  955. CSingleLock lock(m_streamsLock);
  956. m_playerGUIData.m_sampleRate = si->m_audioFormat.m_sampleRate;
  957. m_playerGUIData.m_channelCount = si->m_audioFormat.m_channelLayout.Count();
  958. m_playerGUIData.m_canSeek = si->m_decoder.CanSeek();
  959. const ICodec* codec = si->m_decoder.GetCodec();
  960. m_playerGUIData.m_audioBitrate = codec ? codec->m_bitRate : 0;
  961. strncpy(m_playerGUIData.m_codec,codec ? codec->m_CodecName.c_str() : "",20);
  962. m_playerGUIData.m_cacheLevel = codec ? codec->GetCacheLevel() : 0;
  963. m_playerGUIData.m_bitsPerSample = (codec && codec->m_bitsPerCodedSample) ? codec->m_bitsPerCodedSample : si->m_bytesPerSample << 3;
  964. int64_t total = si->m_decoder.TotalTime();
  965. if (si->m_endOffset)
  966. total = m_currentStream->m_endOffset;
  967. total -= m_currentStream->m_startOffset;
  968. m_playerGUIData.m_totalTime = total;
  969. CServiceBroker::GetDataCacheCore().SignalAudioInfoChange();
  970. }
  971. void PAPlayer::OnJobComplete(unsigned int jobID, bool success, CJob *job)
  972. {
  973. CSingleLock lock(m_streamsLock);
  974. m_jobCounter--;
  975. m_jobEvent.Set();
  976. }
  977. void PAPlayer::CloseFileCB(StreamInfo &si)
  978. {
  979. IPlayerCallback *cb = &m_callback;
  980. CFileItem fileItem(si.m_fileItem);
  981. CBookmark bookmark;
  982. double total = si.m_decoderTotal;
  983. if (si.m_endOffset)
  984. total = si.m_endOffset;
  985. total -= si.m_startOffset;
  986. bookmark.totalTimeInSeconds = total / 1000;
  987. bookmark.timeInSeconds = (static_cast<double>(si.m_framesSent) /
  988. static_cast<double>(si.m_audioFormat.m_sampleRate));
  989. bookmark.timeInSeconds -= si.m_stream->GetDelay();
  990. bookmark.player = m_name;
  991. bookmark.playerState = GetPlayerState();
  992. CJobManager::GetInstance().Submit([=]() {
  993. cb->OnPlayerCloseFile(fileItem, bookmark);
  994. }, CJob::PRIORITY_NORMAL);
  995. }
  996. void PAPlayer::AdvancePlaylistOnError(CFileItem &fileItem)
  997. {
  998. if (m_signalStarted)
  999. m_callback.OnPlayBackStarted(fileItem);
  1000. m_signalStarted = true;
  1001. m_callback.OnAVStarted(fileItem);
  1002. }