Merge pull request #3157 from adamreeve/album_artist_fanart
[vuplus_xbmc] / xbmc / ApplicationPlayer.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "ApplicationPlayer.h"
22 #include "cores/IPlayer.h"
23
24 #define VOLUME_MINIMUM 0.0f        // -60dB
25 #define VOLUME_MAXIMUM 1.0f        // 0dB
26
27 CApplicationPlayer::CApplicationPlayer()
28 {
29   m_iPlayerOPSeq = 0;
30   m_eCurrentPlayer = EPC_NONE;
31 }
32
33 boost::shared_ptr<IPlayer> CApplicationPlayer::GetInternal() const
34 {
35   CSingleLock lock(m_player_lock);
36   return m_pPlayer;
37 }
38
39 void CApplicationPlayer::ClosePlayer()
40 {
41   boost::shared_ptr<IPlayer> player = GetInternal();
42   if (player)
43   {
44     CloseFile();
45     // we need to do this directly on the member
46     CSingleLock lock(m_player_lock);
47     m_pPlayer.reset();
48   }
49 }
50
51 void CApplicationPlayer::CloseFile()
52 {
53   boost::shared_ptr<IPlayer> player = GetInternal();
54   if (player)
55   {
56     ++m_iPlayerOPSeq;
57     player->CloseFile();
58   }
59 }
60
61 void CApplicationPlayer::ClosePlayerGapless(PLAYERCOREID newCore)
62 {
63   boost::shared_ptr<IPlayer> player = GetInternal();
64   if (!player)
65     return;
66
67   bool gaplessSupported = (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer == EPC_PAPLAYER);
68 #if defined(HAS_OMXPLAYER)
69   gaplessSupported = gaplessSupported || (m_eCurrentPlayer == EPC_OMXPLAYER);
70 #endif            
71   gaplessSupported = gaplessSupported && (m_eCurrentPlayer == newCore);
72   if (!gaplessSupported)
73   {
74     ClosePlayer();
75   }
76   else
77   {
78     // XXX: we had to stop the previous playing item, it was done in dvdplayer::OpenFile.
79     // but in paplayer::OpenFile, it sometimes just fade in without call CloseFile.
80     // but if we do not stop it, we can not distingush callbacks from previous
81     // item and current item, it will confused us then we can not make correct delay
82     // callback after the starting state.
83     CloseFile();
84   }
85 }
86
87 void CApplicationPlayer::CreatePlayer(PLAYERCOREID newCore, IPlayerCallback& callback)
88 {
89   CSingleLock lock(m_player_lock);
90   if (!m_pPlayer)
91   {
92     m_eCurrentPlayer = newCore;
93     m_pPlayer.reset(CPlayerCoreFactory::Get().CreatePlayer(newCore, callback));
94   }
95 }
96
97 PlayBackRet CApplicationPlayer::OpenFile(const CFileItem& item, const CPlayerOptions& options)
98 {
99   boost::shared_ptr<IPlayer> player = GetInternal();
100   PlayBackRet iResult = PLAYBACK_FAIL;
101   if (player)
102   {
103     // op seq for detect cancel (CloseFile be called or OpenFile be called again) during OpenFile.
104     unsigned int startingSeq = ++m_iPlayerOPSeq;
105
106     iResult = player->OpenFile(item, options) ? PLAYBACK_OK : PLAYBACK_FAIL;
107     // check whether the OpenFile was canceled by either CloseFile or another OpenFile.
108     if (m_iPlayerOPSeq != startingSeq)
109       iResult = PLAYBACK_CANCELED;
110   }
111   return iResult;
112 }
113
114 bool CApplicationPlayer::HasPlayer() const 
115
116   boost::shared_ptr<IPlayer> player = GetInternal();
117   return player != NULL; 
118 }
119
120 void CApplicationPlayer::RegisterAudioCallback(IAudioCallback* pCallback)
121 {
122   boost::shared_ptr<IPlayer> player = GetInternal();
123   if (player)
124     player->RegisterAudioCallback(pCallback);
125 }
126
127 void CApplicationPlayer::UnRegisterAudioCallback()
128 {
129   boost::shared_ptr<IPlayer> player = GetInternal();
130   if (player)
131     player->UnRegisterAudioCallback();
132 }
133
134 int CApplicationPlayer::GetChapter()
135 {
136   boost::shared_ptr<IPlayer> player = GetInternal();
137   if (player)
138     return player->GetChapter();
139   else 
140     return -1;
141 }
142
143 int CApplicationPlayer::GetChapterCount()
144 {
145   boost::shared_ptr<IPlayer> player = GetInternal();
146   if (player)
147     return player->GetChapterCount();
148   else 
149     return 0;
150 }
151
152 void CApplicationPlayer::GetChapterName(CStdString& strChapterName)
153 {
154   boost::shared_ptr<IPlayer> player = GetInternal();
155   if (player)
156     player->GetChapterName(strChapterName);
157 }
158
159 bool CApplicationPlayer::HasAudio() const
160 {
161   boost::shared_ptr<IPlayer> player = GetInternal();
162   return (player && player->HasAudio());
163 }
164
165 bool CApplicationPlayer::HasVideo() const
166 {
167   boost::shared_ptr<IPlayer> player = GetInternal();
168   return (player && player->HasVideo());
169 }
170
171 bool CApplicationPlayer::IsPaused() const
172 {
173   boost::shared_ptr<IPlayer> player = GetInternal();
174   return (player && player->IsPaused());
175 }
176
177 bool CApplicationPlayer::IsPlaying() const
178 {
179   boost::shared_ptr<IPlayer> player = GetInternal();
180   return (player && player->IsPlaying());
181 }
182
183 bool CApplicationPlayer::IsPausedPlayback() const
184 {
185   return (IsPlaying() && IsPaused());
186 }
187
188 bool CApplicationPlayer::IsPlayingAudio() const
189 {
190   return (IsPlaying() && !HasVideo() && HasAudio());
191 }
192
193 bool CApplicationPlayer::IsPlayingVideo() const
194 {
195   return (IsPlaying() && HasVideo());
196 }
197
198 void CApplicationPlayer::Pause()
199 {
200   boost::shared_ptr<IPlayer> player = GetInternal();
201   if (player)
202     player->Pause();
203 }
204
205 bool CApplicationPlayer::ControlsVolume() const
206 {
207   boost::shared_ptr<IPlayer> player = GetInternal();
208   return (player && player->ControlsVolume());
209 }
210
211 void CApplicationPlayer::SetMute(bool bOnOff)
212 {
213   boost::shared_ptr<IPlayer> player = GetInternal();
214   if (player)
215     player->SetMute(bOnOff);
216 }
217
218 void CApplicationPlayer::SetVolume(float volume)
219 {
220   boost::shared_ptr<IPlayer> player = GetInternal();
221   if (player)
222     player->SetVolume(volume);
223 }
224
225 void CApplicationPlayer::Seek(bool bPlus, bool bLargeStep, bool bChapterOverride)
226 {
227   boost::shared_ptr<IPlayer> player = GetInternal();
228   if (player)
229     player->Seek(bPlus, bLargeStep, bChapterOverride);
230 }
231
232 void CApplicationPlayer::SeekPercentage(float fPercent)
233 {
234   boost::shared_ptr<IPlayer> player = GetInternal();
235   if (player)
236     player->SeekPercentage(fPercent);
237 }
238
239 bool CApplicationPlayer::IsPassthrough() const
240 {
241   boost::shared_ptr<IPlayer> player = GetInternal();
242   return (player && player->IsPassthrough());
243 }
244
245 bool CApplicationPlayer::CanSeek()
246 {
247   boost::shared_ptr<IPlayer> player = GetInternal();
248   return (player && player->CanSeek());
249 }
250
251 bool CApplicationPlayer::SeekScene(bool bPlus)
252 {
253   boost::shared_ptr<IPlayer> player = GetInternal();
254   return (player && player->SeekScene(bPlus));
255 }
256
257 void CApplicationPlayer::SeekTime(int64_t iTime)
258 {
259   boost::shared_ptr<IPlayer> player = GetInternal();
260   if (player)
261     player->SeekTime(iTime);
262 }
263
264 CStdString CApplicationPlayer::GetPlayingTitle()
265 {
266   boost::shared_ptr<IPlayer> player = GetInternal();
267   if (player)
268     return player->GetPlayingTitle();
269   else
270     return "";
271 }
272
273 int64_t CApplicationPlayer::GetTime() const
274 {
275   boost::shared_ptr<IPlayer> player = GetInternal();
276   if (player)
277     return player->GetTime();
278   else
279     return 0;
280 }
281
282 int CApplicationPlayer::GetPictureHeight()
283 {
284   boost::shared_ptr<IPlayer> player = GetInternal();
285   if (player)
286     return player->GetPictureHeight();
287   else
288     return 0;
289 }
290
291 int CApplicationPlayer::GetPictureWidth()
292 {
293   boost::shared_ptr<IPlayer> player = GetInternal();
294   if (player)
295     return player->GetPictureWidth();
296   else
297     return 0;
298 }
299
300 int CApplicationPlayer::GetSampleRate()
301 {
302   boost::shared_ptr<IPlayer> player = GetInternal();
303   if (player)
304     return player->GetSampleRate();
305   else
306     return 0;
307 }
308
309 bool CApplicationPlayer::IsCaching() const
310 {
311   boost::shared_ptr<IPlayer> player = GetInternal();
312   return (player && player->IsCaching());
313 }
314
315 bool CApplicationPlayer::IsInMenu() const
316 {
317   boost::shared_ptr<IPlayer> player = GetInternal();
318   return (player && player->IsInMenu());
319 }
320
321 bool CApplicationPlayer::HasMenu() const
322 {
323   boost::shared_ptr<IPlayer> player = GetInternal();
324   return (player && player->HasMenu());
325 }
326
327 int CApplicationPlayer::GetCacheLevel() const
328 {
329   boost::shared_ptr<IPlayer> player = GetInternal();
330   if (player)
331     return player->GetCacheLevel();
332   else
333     return 0;
334 }
335
336 int CApplicationPlayer::GetSubtitleCount()
337 {
338   boost::shared_ptr<IPlayer> player = GetInternal();
339   if (player)
340     return player->GetSubtitleCount();
341   else
342     return 0;
343 }
344
345 int CApplicationPlayer::GetBitsPerSample()
346 {
347   boost::shared_ptr<IPlayer> player = GetInternal();
348   if (player)
349     return player->GetBitsPerSample();
350   else
351     return 0;
352 }
353
354 int CApplicationPlayer::GetAudioStream()
355 {
356   boost::shared_ptr<IPlayer> player = GetInternal();
357   if (player)
358     return player->GetAudioStream();
359   else
360     return 0;
361 }
362
363 int CApplicationPlayer::GetSubtitle()
364 {
365   boost::shared_ptr<IPlayer> player = GetInternal();
366   if (player)
367     return player->GetSubtitle();
368   else
369     return 0;
370 }
371
372 bool CApplicationPlayer::GetSubtitleVisible()
373 {
374   boost::shared_ptr<IPlayer> player = GetInternal();
375   return (player && player->GetSubtitleVisible());
376 }
377
378 bool CApplicationPlayer::CanRecord()
379 {
380   boost::shared_ptr<IPlayer> player = GetInternal();
381   return (player && player->CanRecord());
382 }
383
384 bool CApplicationPlayer::CanPause()
385 {
386   boost::shared_ptr<IPlayer> player = GetInternal();
387   return (player && player->CanPause());
388 }
389
390 bool CApplicationPlayer::IsRecording() const
391 {
392   boost::shared_ptr<IPlayer> player = GetInternal();
393   return (player && player->IsRecording());
394 }
395
396 TextCacheStruct_t* CApplicationPlayer::GetTeletextCache()
397 {
398   boost::shared_ptr<IPlayer> player = GetInternal();
399   if (player)
400     return player->GetTeletextCache();
401   else
402     return NULL;
403 }
404
405 int64_t CApplicationPlayer::GetTotalTime() const
406 {
407   boost::shared_ptr<IPlayer> player = GetInternal();
408   if (player)
409     return player->GetTotalTime();
410   else
411     return 0;
412 }
413
414 float CApplicationPlayer::GetPercentage() const
415 {
416   boost::shared_ptr<IPlayer> player = GetInternal();
417   if (player)
418     return player->GetPercentage();
419   else
420     return 0.0;
421 }
422
423 float CApplicationPlayer::GetCachePercentage() const
424 {
425   boost::shared_ptr<IPlayer> player = GetInternal();
426   if (player)
427     return player->GetCachePercentage();
428   else
429     return 0.0;
430 }
431
432 void CApplicationPlayer::ToFFRW(int iSpeed)
433 {
434   boost::shared_ptr<IPlayer> player = GetInternal();
435   if (player)
436     player->ToFFRW(iSpeed);
437 }
438
439 void CApplicationPlayer::DoAudioWork()
440 {
441   boost::shared_ptr<IPlayer> player = GetInternal();
442   if (player)
443     player->DoAudioWork();
444 }
445
446 CStdString CApplicationPlayer::GetPlayerState()
447 {
448   boost::shared_ptr<IPlayer> player = GetInternal();
449   if (player)
450     return player->GetPlayerState();
451   else
452     return "";
453 }
454
455 bool CApplicationPlayer::QueueNextFile(const CFileItem &file)
456 {
457   boost::shared_ptr<IPlayer> player = GetInternal();
458   return (player && player->QueueNextFile(file));
459 }
460
461 bool CApplicationPlayer::GetStreamDetails(CStreamDetails &details)
462 {
463   boost::shared_ptr<IPlayer> player = GetInternal();
464   return (player && player->GetStreamDetails(details));
465 }
466
467 bool CApplicationPlayer::SetPlayerState(CStdString state)
468 {
469   boost::shared_ptr<IPlayer> player = GetInternal();
470   return (player && player->SetPlayerState(state));
471 }
472
473 void CApplicationPlayer::OnNothingToQueueNotify()
474 {
475   boost::shared_ptr<IPlayer> player = GetInternal();
476   if (player)
477     player->OnNothingToQueueNotify();
478 }
479
480 void CApplicationPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info)
481 {
482   boost::shared_ptr<IPlayer> player = GetInternal();
483   if (player)
484     player->GetVideoStreamInfo(info);
485 }
486
487 void CApplicationPlayer::GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info)
488 {
489   boost::shared_ptr<IPlayer> player = GetInternal();
490   if (player)
491     player->GetAudioStreamInfo(index, info);
492 }
493
494 bool CApplicationPlayer::OnAction(const CAction &action)
495 {
496   boost::shared_ptr<IPlayer> player = GetInternal();
497   return (player && player->OnAction(action));
498 }
499
500 bool CApplicationPlayer::Record(bool bOnOff)
501 {
502   boost::shared_ptr<IPlayer> player = GetInternal();
503   return (player && player->Record(bOnOff));
504 }
505
506 int  CApplicationPlayer::GetAudioStreamCount()
507 {
508   boost::shared_ptr<IPlayer> player = GetInternal();
509   if (player)
510     return player->GetAudioStreamCount();
511   else
512     return 0;
513 }
514
515 void CApplicationPlayer::SetAudioStream(int iStream)
516 {
517   boost::shared_ptr<IPlayer> player = GetInternal();
518   if (player)
519     player->SetAudioStream(iStream);
520 }
521
522 void CApplicationPlayer::GetSubtitleStreamInfo(int index, SPlayerSubtitleStreamInfo &info)
523 {
524   boost::shared_ptr<IPlayer> player = GetInternal();
525   if (player)
526     player->GetSubtitleStreamInfo(index, info);
527 }
528
529 void CApplicationPlayer::SetSubtitle(int iStream)
530 {
531   boost::shared_ptr<IPlayer> player = GetInternal();
532   if (player)
533     player->SetSubtitle(iStream);
534 }
535
536 void CApplicationPlayer::SetSubtitleVisible(bool bVisible)
537 {
538   boost::shared_ptr<IPlayer> player = GetInternal();
539   if (player)
540     player->SetSubtitleVisible(bVisible);
541 }
542
543 int  CApplicationPlayer::AddSubtitle(const CStdString& strSubPath)
544 {
545   boost::shared_ptr<IPlayer> player = GetInternal();
546   if (player)
547     return player->AddSubtitle(strSubPath);
548   else
549     return 0;
550 }
551
552 void CApplicationPlayer::SetSubTitleDelay(float fValue)
553 {
554   boost::shared_ptr<IPlayer> player = GetInternal();
555   if (player)
556     player->SetSubTitleDelay(fValue);
557 }
558
559 void CApplicationPlayer::SetAVDelay(float fValue)
560 {
561   boost::shared_ptr<IPlayer> player = GetInternal();
562   if (player)
563     player->SetAVDelay(fValue);
564 }
565
566 void CApplicationPlayer::SetDynamicRangeCompression(long drc)
567 {
568   boost::shared_ptr<IPlayer> player = GetInternal();
569   if (player)
570     player->SetDynamicRangeCompression(drc);
571 }
572
573 bool CApplicationPlayer::SwitchChannel(const PVR::CPVRChannel &channel)
574 {
575   boost::shared_ptr<IPlayer> player = GetInternal();
576   return (player && player->SwitchChannel(channel));
577 }
578
579 void CApplicationPlayer::LoadPage(int p, int sp, unsigned char* buffer)
580 {
581   boost::shared_ptr<IPlayer> player = GetInternal();
582   if (player)
583     player->LoadPage(p, sp, buffer);
584 }
585
586 void CApplicationPlayer::GetAudioCapabilities(std::vector<int> &audioCaps)
587 {
588   boost::shared_ptr<IPlayer> player = GetInternal();
589   if (player)
590     player->GetAudioCapabilities(audioCaps);
591 }
592
593 void CApplicationPlayer::GetSubtitleCapabilities(std::vector<int> &subCaps)
594 {
595   boost::shared_ptr<IPlayer> player = GetInternal();
596   if (player)
597     player->GetSubtitleCapabilities(subCaps);
598 }
599
600 void CApplicationPlayer::GetAudioInfo( CStdString& strAudioInfo)
601 {
602   boost::shared_ptr<IPlayer> player = GetInternal();
603   if (player)
604     player->GetAudioInfo(strAudioInfo);
605 }
606
607 void CApplicationPlayer::GetVideoInfo( CStdString& strVideoInfo)
608 {
609   boost::shared_ptr<IPlayer> player = GetInternal();
610   if (player)
611     player->GetVideoInfo(strVideoInfo);
612 }
613
614 void CApplicationPlayer::GetGeneralInfo( CStdString& strVideoInfo)
615 {
616   boost::shared_ptr<IPlayer> player = GetInternal();
617   if (player)
618     player->GetGeneralInfo(strVideoInfo);
619 }
620
621 bool CApplicationPlayer::GetCurrentSubtitle(CStdString& strSubtitle)
622 {
623   boost::shared_ptr<IPlayer> player = GetInternal();
624   return (player && player->GetCurrentSubtitle(strSubtitle));
625 }
626
627 int  CApplicationPlayer::SeekChapter(int iChapter)
628 {
629   boost::shared_ptr<IPlayer> player = GetInternal();
630   if (player)
631     return player->SeekChapter(iChapter);
632   else
633     return 0;
634 }
635
636 void CApplicationPlayer::GetRenderFeatures(std::vector<int> &renderFeatures)
637 {
638   boost::shared_ptr<IPlayer> player = GetInternal();
639   if (player)
640     player->GetRenderFeatures(renderFeatures);
641 }
642
643 void CApplicationPlayer::GetDeinterlaceMethods(std::vector<int> &deinterlaceMethods)
644 {
645   boost::shared_ptr<IPlayer> player = GetInternal();
646   if (player)
647     player->GetDeinterlaceMethods(deinterlaceMethods);
648 }
649
650 void CApplicationPlayer::GetDeinterlaceModes(std::vector<int> &deinterlaceModes)
651 {
652   boost::shared_ptr<IPlayer> player = GetInternal();
653   if (player)
654     player->GetDeinterlaceModes(deinterlaceModes);
655 }
656
657 void CApplicationPlayer::GetScalingMethods(std::vector<int> &scalingMethods)
658 {
659   boost::shared_ptr<IPlayer> player = GetInternal();
660   if (player)
661     player->GetScalingMethods(scalingMethods);
662 }
663
664 void CApplicationPlayer::SetPlaySpeed(int iSpeed, bool bApplicationMuted)
665 {
666   boost::shared_ptr<IPlayer> player = GetInternal();
667   if (!player)
668     return;
669
670   if (!IsPlayingAudio() && !IsPlayingVideo())
671     return ;
672   if (m_iPlaySpeed == iSpeed)
673     return ;
674   if (!CanSeek())
675     return;
676   if (IsPaused())
677   {
678     if (
679       ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
680       ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
681     )
682     {
683       iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
684     }
685     Pause();
686   }
687   m_iPlaySpeed = iSpeed;
688
689   ToFFRW(m_iPlaySpeed);
690
691   // if player has volume control, set it.
692   if (ControlsVolume())
693   {
694     if (m_iPlaySpeed == 1)
695     { // restore volume
696       player->SetVolume(VOLUME_MAXIMUM);
697     }
698     else
699     { // mute volume
700       player->SetVolume(VOLUME_MINIMUM);
701     }
702     player->SetMute(bApplicationMuted);
703   }
704 }
705
706 int CApplicationPlayer::GetPlaySpeed() const
707 {
708   return m_iPlaySpeed;
709 }