1 /*
2 * Copyright (C) 2012-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
9 #include "guilib/guiinfo/PlayerGUIInfo.h"
10
11 #include "Application.h"
12 #include "FileItem.h"
13 #include "PlayListPlayer.h"
14 #include "ServiceBroker.h"
15 #include "URL.h"
16 #include "cores/AudioEngine/Utils/AEUtil.h"
17 #include "cores/Cut.h"
18 #include "cores/DataCacheCore.h"
19 #include "guilib/GUIComponent.h"
20 #include "guilib/GUIDialog.h"
21 #include "guilib/GUIWindowManager.h"
22 #include "guilib/guiinfo/GUIInfo.h"
23 #include "guilib/guiinfo/GUIInfoHelper.h"
24 #include "guilib/guiinfo/GUIInfoLabels.h"
25 #include "utils/StringUtils.h"
26 #include "utils/TimeUtils.h"
27 #include "utils/URIUtils.h"
28 #include "utils/Variant.h"
29 #include "utils/log.h"
30
31 #include <cmath>
32
33 using namespace KODI::GUILIB::GUIINFO;
34
CPlayerGUIInfo()35 CPlayerGUIInfo::CPlayerGUIInfo()
36 : m_playerShowTime(false),
37 m_playerShowInfo(false)
38 {
39 }
40
41 CPlayerGUIInfo::~CPlayerGUIInfo() = default;
42
GetTotalPlayTime() const43 int CPlayerGUIInfo::GetTotalPlayTime() const
44 {
45 return std::lrint(g_application.GetTotalTime());
46 }
47
GetPlayTime() const48 int CPlayerGUIInfo::GetPlayTime() const
49 {
50 return std::lrint(g_application.GetTime());
51 }
52
GetPlayTimeRemaining() const53 int CPlayerGUIInfo::GetPlayTimeRemaining() const
54 {
55 int iReverse = GetTotalPlayTime() - std::lrint(g_application.GetTime());
56 return iReverse > 0 ? iReverse : 0;
57 }
58
GetSeekPercent() const59 float CPlayerGUIInfo::GetSeekPercent() const
60 {
61 int iTotal = GetTotalPlayTime();
62 if (iTotal == 0)
63 return 0.0f;
64
65 float fPercentPlayTime = static_cast<float>(GetPlayTime() * 1000) / iTotal * 0.1f;
66 float fPercentPerSecond = 100.0f / static_cast<float>(iTotal);
67 float fPercent = fPercentPlayTime + fPercentPerSecond * g_application.GetAppPlayer().GetSeekHandler().GetSeekSize();
68 fPercent = std::max(0.0f, std::min(fPercent, 100.0f));
69 return fPercent;
70 }
71
GetCurrentPlayTime(TIME_FORMAT format) const72 std::string CPlayerGUIInfo::GetCurrentPlayTime(TIME_FORMAT format) const
73 {
74 if (format == TIME_FORMAT_GUESS && GetTotalPlayTime() >= 3600)
75 format = TIME_FORMAT_HH_MM_SS;
76
77 return StringUtils::SecondsToTimeString(std::lrint(GetPlayTime()), format);
78 }
79
GetCurrentPlayTimeRemaining(TIME_FORMAT format) const80 std::string CPlayerGUIInfo::GetCurrentPlayTimeRemaining(TIME_FORMAT format) const
81 {
82 if (format == TIME_FORMAT_GUESS && GetTotalPlayTime() >= 3600)
83 format = TIME_FORMAT_HH_MM_SS;
84
85 int iTimeRemaining = GetPlayTimeRemaining();
86 if (iTimeRemaining)
87 return StringUtils::SecondsToTimeString(iTimeRemaining, format);
88
89 return std::string();
90 }
91
GetDuration(TIME_FORMAT format) const92 std::string CPlayerGUIInfo::GetDuration(TIME_FORMAT format) const
93 {
94 int iTotal = GetTotalPlayTime();
95 if (iTotal > 0)
96 {
97 if (format == TIME_FORMAT_GUESS && iTotal >= 3600)
98 format = TIME_FORMAT_HH_MM_SS;
99 return StringUtils::SecondsToTimeString(iTotal, format);
100 }
101 return std::string();
102 }
103
GetCurrentSeekTime(TIME_FORMAT format) const104 std::string CPlayerGUIInfo::GetCurrentSeekTime(TIME_FORMAT format) const
105 {
106 if (format == TIME_FORMAT_GUESS && GetTotalPlayTime() >= 3600)
107 format = TIME_FORMAT_HH_MM_SS;
108
109 return StringUtils::SecondsToTimeString(g_application.GetTime() + g_application.GetAppPlayer().GetSeekHandler().GetSeekSize(), format);
110 }
111
GetSeekTime(TIME_FORMAT format) const112 std::string CPlayerGUIInfo::GetSeekTime(TIME_FORMAT format) const
113 {
114 if (!g_application.GetAppPlayer().GetSeekHandler().HasTimeCode())
115 return std::string();
116
117 int iSeekTimeCode = g_application.GetAppPlayer().GetSeekHandler().GetTimeCodeSeconds();
118 if (format == TIME_FORMAT_GUESS && iSeekTimeCode >= 3600)
119 format = TIME_FORMAT_HH_MM_SS;
120
121 return StringUtils::SecondsToTimeString(iSeekTimeCode, format);
122 }
123
SetDisplayAfterSeek(unsigned int timeOut,int seekOffset)124 void CPlayerGUIInfo::SetDisplayAfterSeek(unsigned int timeOut, int seekOffset)
125 {
126 if (timeOut > 0)
127 {
128 m_AfterSeekTimeout = CTimeUtils::GetFrameTime() + timeOut;
129 if (seekOffset)
130 m_seekOffset = seekOffset;
131 }
132 else
133 m_AfterSeekTimeout = 0;
134 }
135
GetDisplayAfterSeek() const136 bool CPlayerGUIInfo::GetDisplayAfterSeek() const
137 {
138 if (CTimeUtils::GetFrameTime() < m_AfterSeekTimeout)
139 return true;
140 m_seekOffset = 0;
141 return false;
142 }
143
SetShowInfo(bool showinfo)144 void CPlayerGUIInfo::SetShowInfo(bool showinfo)
145 {
146 m_playerShowInfo = showinfo;
147 }
148
ToggleShowInfo()149 bool CPlayerGUIInfo::ToggleShowInfo()
150 {
151 SetShowInfo(!m_playerShowInfo);
152 return m_playerShowInfo;
153 }
154
InitCurrentItem(CFileItem * item)155 bool CPlayerGUIInfo::InitCurrentItem(CFileItem *item)
156 {
157 if (item && g_application.GetAppPlayer().IsPlaying())
158 {
159 CLog::Log(LOGDEBUG, "CPlayerGUIInfo::InitCurrentItem(%s)", CURL::GetRedacted(item->GetPath()).c_str());
160 m_currentItem.reset(new CFileItem(*item));
161 }
162 else
163 {
164 m_currentItem.reset();
165 }
166 return false;
167 }
168
GetLabel(std::string & value,const CFileItem * item,int contextWindow,const CGUIInfo & info,std::string * fallback) const169 bool CPlayerGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const
170 {
171 switch (info.m_info)
172 {
173 ///////////////////////////////////////////////////////////////////////////////////////////////
174 // PLAYER_*
175 ///////////////////////////////////////////////////////////////////////////////////////////////
176 case PLAYER_SEEKOFFSET:
177 {
178 std::string seekOffset = StringUtils::SecondsToTimeString(std::abs(m_seekOffset / 1000), static_cast<TIME_FORMAT>(info.GetData1()));
179 if (m_seekOffset < 0)
180 value = "-" + seekOffset;
181 else if (m_seekOffset > 0)
182 value = "+" + seekOffset;
183 return true;
184 }
185 case PLAYER_PROGRESS:
186 value = std::to_string(std::lrintf(g_application.GetPercentage()));
187 return true;
188 case PLAYER_PROGRESS_CACHE:
189 value = std::to_string(std::lrintf(g_application.GetCachePercentage()));
190 return true;
191 case PLAYER_VOLUME:
192 value = StringUtils::Format("%2.1f dB", CAEUtil::PercentToGain(g_application.GetVolumeRatio()));
193 return true;
194 case PLAYER_SUBTITLE_DELAY:
195 value = StringUtils::Format("%2.3f s", g_application.GetAppPlayer().GetVideoSettings().m_SubtitleDelay);
196 return true;
197 case PLAYER_AUDIO_DELAY:
198 value = StringUtils::Format("%2.3f s", g_application.GetAppPlayer().GetVideoSettings().m_AudioDelay);
199 return true;
200 case PLAYER_CHAPTER:
201 value = StringUtils::Format("%02d", g_application.GetAppPlayer().GetChapter());
202 return true;
203 case PLAYER_CHAPTERCOUNT:
204 value = StringUtils::Format("%02d", g_application.GetAppPlayer().GetChapterCount());
205 return true;
206 case PLAYER_CHAPTERNAME:
207 g_application.GetAppPlayer().GetChapterName(value);
208 return true;
209 case PLAYER_PATH:
210 case PLAYER_FILENAME:
211 case PLAYER_FILEPATH:
212 value = GUIINFO::GetFileInfoLabelValueFromPath(info.m_info, item->GetPath());
213 return true;
214 case PLAYER_TITLE:
215 // use label or drop down to title from path
216 value = item->GetLabel();
217 if (value.empty())
218 value = CUtil::GetTitleFromPath(item->GetPath());
219 return true;
220 case PLAYER_PLAYSPEED:
221 {
222 float speed = g_application.GetAppPlayer().GetPlaySpeed();
223 if (speed == 1.0)
224 speed = g_application.GetAppPlayer().GetPlayTempo();
225 value = StringUtils::Format("%.2f", speed);
226 return true;
227 }
228 case PLAYER_TIME:
229 value = GetCurrentPlayTime(static_cast<TIME_FORMAT>(info.GetData1()));
230 return true;
231 case PLAYER_START_TIME:
232 {
233 const CDateTime time(g_application.GetAppPlayer().GetStartTime());
234 value = time.GetAsLocalizedTime(static_cast<TIME_FORMAT>(info.GetData1()));
235 return true;
236 }
237 case PLAYER_DURATION:
238 value = GetDuration(static_cast<TIME_FORMAT>(info.GetData1()));
239 return true;
240 case PLAYER_TIME_REMAINING:
241 value = GetCurrentPlayTimeRemaining(static_cast<TIME_FORMAT>(info.GetData1()));
242 return true;
243 case PLAYER_FINISH_TIME:
244 {
245 CDateTime time(CDateTime::GetCurrentDateTime());
246 int playTimeRemaining = GetPlayTimeRemaining();
247 float speed = g_application.GetAppPlayer().GetPlaySpeed();
248 float tempo = g_application.GetAppPlayer().GetPlayTempo();
249 if (speed == 1.0)
250 playTimeRemaining /= tempo;
251 time += CDateTimeSpan(0, 0, 0, playTimeRemaining);
252 value = time.GetAsLocalizedTime(static_cast<TIME_FORMAT>(info.GetData1()));
253 return true;
254 }
255 case PLAYER_TIME_SPEED:
256 {
257 float speed = g_application.GetAppPlayer().GetPlaySpeed();
258 if (speed != 1.0)
259 value = StringUtils::Format("%s (%ix)", GetCurrentPlayTime(static_cast<TIME_FORMAT>(info.GetData1())).c_str(), static_cast<int>(speed));
260 else
261 value = GetCurrentPlayTime(TIME_FORMAT_GUESS);
262 return true;
263 }
264 case PLAYER_SEEKTIME:
265 value = GetCurrentSeekTime(static_cast<TIME_FORMAT>(info.GetData1()));
266 return true;
267 case PLAYER_SEEKSTEPSIZE:
268 {
269 int seekSize = g_application.GetAppPlayer().GetSeekHandler().GetSeekSize();
270 std::string strSeekSize = StringUtils::SecondsToTimeString(abs(seekSize), static_cast<TIME_FORMAT>(info.GetData1()));
271 if (seekSize < 0)
272 value = "-" + strSeekSize;
273 if (seekSize > 0)
274 value = "+" + strSeekSize;
275 return true;
276 }
277 case PLAYER_SEEKNUMERIC:
278 value = GetSeekTime(static_cast<TIME_FORMAT>(info.GetData1()));
279 return !value.empty();
280 case PLAYER_CACHELEVEL:
281 {
282 int iLevel = g_application.GetAppPlayer().GetCacheLevel();
283 if (iLevel >= 0)
284 {
285 value = StringUtils::Format("%i", iLevel);
286 return true;
287 }
288 break;
289 }
290 case PLAYER_ITEM_ART:
291 value = item->GetArt(info.GetData3());
292 return true;
293 case PLAYER_ICON:
294 value = item->GetArt("thumb");
295 if (value.empty())
296 value = item->GetArt("icon");
297 if (fallback)
298 *fallback = item->GetArt("icon");
299 return true;
300 case PLAYER_CUTLIST:
301 case PLAYER_CHAPTERS:
302 value = GetContentRanges(info.m_info);
303 return true;
304
305 ///////////////////////////////////////////////////////////////////////////////////////////////
306 // PLAYER_PROCESS_*
307 ///////////////////////////////////////////////////////////////////////////////////////////////
308 case PLAYER_PROCESS_VIDEODECODER:
309 value = CServiceBroker::GetDataCacheCore().GetVideoDecoderName();
310 return true;
311 case PLAYER_PROCESS_DEINTMETHOD:
312 value = CServiceBroker::GetDataCacheCore().GetVideoDeintMethod();
313 return true;
314 case PLAYER_PROCESS_PIXELFORMAT:
315 value = CServiceBroker::GetDataCacheCore().GetVideoPixelFormat();
316 return true;
317 case PLAYER_PROCESS_VIDEOFPS:
318 value = StringUtils::Format("%.3f", CServiceBroker::GetDataCacheCore().GetVideoFps());
319 return true;
320 case PLAYER_PROCESS_VIDEODAR:
321 value = StringUtils::Format("%.2f", CServiceBroker::GetDataCacheCore().GetVideoDAR());
322 return true;
323 case PLAYER_PROCESS_VIDEOWIDTH:
324 value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetVideoWidth());
325 return true;
326 case PLAYER_PROCESS_VIDEOHEIGHT:
327 value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetVideoHeight());
328 return true;
329 case PLAYER_PROCESS_AUDIODECODER:
330 value = CServiceBroker::GetDataCacheCore().GetAudioDecoderName();
331 return true;
332 case PLAYER_PROCESS_AUDIOCHANNELS:
333 value = CServiceBroker::GetDataCacheCore().GetAudioChannels();
334 return true;
335 case PLAYER_PROCESS_AUDIOSAMPLERATE:
336 value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetAudioSampleRate());
337 return true;
338 case PLAYER_PROCESS_AUDIOBITSPERSAMPLE:
339 value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetAudioBitsPerSample());
340 return true;
341
342 ///////////////////////////////////////////////////////////////////////////////////////////////
343 // PLAYLIST_*
344 ///////////////////////////////////////////////////////////////////////////////////////////////
345 case PLAYLIST_LENGTH:
346 case PLAYLIST_POSITION:
347 case PLAYLIST_RANDOM:
348 case PLAYLIST_REPEAT:
349 value = GUIINFO::GetPlaylistLabel(info.m_info, info.GetData1());
350 return true;
351 }
352
353 return false;
354 }
355
GetInt(int & value,const CGUIListItem * gitem,int contextWindow,const CGUIInfo & info) const356 bool CPlayerGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const
357 {
358 switch (info.m_info)
359 {
360 ///////////////////////////////////////////////////////////////////////////////////////////////
361 // PLAYER_*
362 ///////////////////////////////////////////////////////////////////////////////////////////////
363 case PLAYER_VOLUME:
364 value = static_cast<int>(g_application.GetVolumePercent());
365 return true;
366 case PLAYER_SUBTITLE_DELAY:
367 value = g_application.GetSubtitleDelay();
368 return true;
369 case PLAYER_AUDIO_DELAY:
370 value = g_application.GetAudioDelay();
371 return true;
372 case PLAYER_PROGRESS:
373 value = std::lrintf(g_application.GetPercentage());
374 return true;
375 case PLAYER_PROGRESS_CACHE:
376 value = std::lrintf(g_application.GetCachePercentage());
377 return true;
378 case PLAYER_CACHELEVEL:
379 value = g_application.GetAppPlayer().GetCacheLevel();
380 return true;
381 case PLAYER_CHAPTER:
382 value = g_application.GetAppPlayer().GetChapter();
383 return true;
384 case PLAYER_CHAPTERCOUNT:
385 value = g_application.GetAppPlayer().GetChapterCount();
386 return true;
387 case PLAYER_SEEKBAR:
388 value = std::lrintf(GetSeekPercent());
389 return true;
390 }
391
392 return false;
393 }
394
GetBool(bool & value,const CGUIListItem * gitem,int contextWindow,const CGUIInfo & info) const395 bool CPlayerGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const
396 {
397 const CFileItem *item = nullptr;
398 if (gitem->IsFileItem())
399 item = static_cast<const CFileItem*>(gitem);
400
401 switch (info.m_info)
402 {
403 ///////////////////////////////////////////////////////////////////////////////////////////////
404 // PLAYER_*
405 ///////////////////////////////////////////////////////////////////////////////////////////////
406 case PLAYER_SHOWINFO:
407 value = m_playerShowInfo;
408 return true;
409 case PLAYER_DISPLAY_AFTER_SEEK:
410 value = GetDisplayAfterSeek();
411 return true;
412 case PLAYER_SHOWTIME:
413 value = m_playerShowTime;
414 return true;
415 case PLAYER_MUTED:
416 value = (g_application.IsMuted() || g_application.GetVolumeRatio() <= VOLUME_MINIMUM);
417 return true;
418 case PLAYER_HAS_MEDIA:
419 value = g_application.GetAppPlayer().IsPlaying();
420 return true;
421 case PLAYER_HAS_AUDIO:
422 value = g_application.GetAppPlayer().IsPlayingAudio();
423 return true;
424 case PLAYER_HAS_VIDEO:
425 value = g_application.GetAppPlayer().IsPlayingVideo();
426 return true;
427 case PLAYER_HAS_GAME:
428 value = g_application.GetAppPlayer().IsPlayingGame();
429 return true;
430 case PLAYER_PLAYING:
431 value = g_application.GetAppPlayer().GetPlaySpeed() == 1.0;
432 return true;
433 case PLAYER_PAUSED:
434 value = g_application.GetAppPlayer().IsPausedPlayback();
435 return true;
436 case PLAYER_REWINDING:
437 value = g_application.GetAppPlayer().GetPlaySpeed() < 0;
438 return true;
439 case PLAYER_FORWARDING:
440 value = g_application.GetAppPlayer().GetPlaySpeed() > 1.5;
441 return true;
442 case PLAYER_REWINDING_2x:
443 value = g_application.GetAppPlayer().GetPlaySpeed() == -2;
444 return true;
445 case PLAYER_REWINDING_4x:
446 value = g_application.GetAppPlayer().GetPlaySpeed() == -4;
447 return true;
448 case PLAYER_REWINDING_8x:
449 value = g_application.GetAppPlayer().GetPlaySpeed() == -8;
450 return true;
451 case PLAYER_REWINDING_16x:
452 value = g_application.GetAppPlayer().GetPlaySpeed() == -16;
453 return true;
454 case PLAYER_REWINDING_32x:
455 value = g_application.GetAppPlayer().GetPlaySpeed() == -32;
456 return true;
457 case PLAYER_FORWARDING_2x:
458 value = g_application.GetAppPlayer().GetPlaySpeed() == 2;
459 return true;
460 case PLAYER_FORWARDING_4x:
461 value = g_application.GetAppPlayer().GetPlaySpeed() == 4;
462 return true;
463 case PLAYER_FORWARDING_8x:
464 value = g_application.GetAppPlayer().GetPlaySpeed() == 8;
465 return true;
466 case PLAYER_FORWARDING_16x:
467 value = g_application.GetAppPlayer().GetPlaySpeed() == 16;
468 return true;
469 case PLAYER_FORWARDING_32x:
470 value = g_application.GetAppPlayer().GetPlaySpeed() == 32;
471 return true;
472 case PLAYER_CAN_PAUSE:
473 value = g_application.GetAppPlayer().CanPause();
474 return true;
475 case PLAYER_CAN_SEEK:
476 value = g_application.GetAppPlayer().CanSeek();
477 return true;
478 case PLAYER_SUPPORTS_TEMPO:
479 value = g_application.GetAppPlayer().SupportsTempo();
480 return true;
481 case PLAYER_IS_TEMPO:
482 {
483 value = (g_application.GetAppPlayer().GetPlayTempo() != 1.0 &&
484 g_application.GetAppPlayer().GetPlaySpeed() == 1.0);
485 return true;
486 }
487 case PLAYER_CACHING:
488 value = g_application.GetAppPlayer().IsCaching();
489 return true;
490 case PLAYER_SEEKBAR:
491 {
492 CGUIDialog *seekBar = CServiceBroker::GetGUI()->GetWindowManager().GetDialog(WINDOW_DIALOG_SEEK_BAR);
493 value = seekBar ? seekBar->IsDialogRunning() : false;
494 return true;
495 }
496 case PLAYER_SEEKING:
497 value = g_application.GetAppPlayer().GetSeekHandler().InProgress();
498 return true;
499 case PLAYER_PASSTHROUGH:
500 value = g_application.GetAppPlayer().IsPassthrough();
501 return true;
502 case PLAYER_ISINTERNETSTREAM:
503 if (item)
504 {
505 value = URIUtils::IsInternetStream(item->GetDynPath());
506 return true;
507 }
508 break;
509 case PLAYER_HAS_PROGRAMS:
510 value = (g_application.GetAppPlayer().GetProgramsCount() > 1) ? true : false;
511 return true;
512 case PLAYER_HAS_RESOLUTIONS:
513 value = CServiceBroker::GetWinSystem()->GetGfxContext().IsFullScreenRoot() &&
514 CResolutionUtils::HasWhitelist();
515 return true;
516 case PLAYER_HASDURATION:
517 value = g_application.GetTotalTime() > 0;
518 return true;
519 case PLAYER_FRAMEADVANCE:
520 value = CServiceBroker::GetDataCacheCore().IsFrameAdvance();
521 return true;
522
523 ///////////////////////////////////////////////////////////////////////////////////////////////
524 // PLAYLIST_*
525 ///////////////////////////////////////////////////////////////////////////////////////////////
526 case PLAYLIST_ISRANDOM:
527 {
528 PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer();
529 int playlistid = info.GetData1();
530 if (info.GetData2() > 0 && playlistid > PLAYLIST_NONE)
531 value = player.IsShuffled(playlistid);
532 else
533 value = player.IsShuffled(player.GetCurrentPlaylist());
534 return true;
535 }
536 case PLAYLIST_ISREPEAT:
537 {
538 PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer();
539 int playlistid = info.GetData1();
540 if (info.GetData2() > 0 && playlistid > PLAYLIST_NONE)
541 value = (player.GetRepeat(playlistid) == PLAYLIST::REPEAT_ALL);
542 else
543 value = player.GetRepeat(player.GetCurrentPlaylist()) == PLAYLIST::REPEAT_ALL;
544 return true;
545 }
546 case PLAYLIST_ISREPEATONE:
547 {
548 PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer();
549 int playlistid = info.GetData1();
550 if (info.GetData2() > 0 && playlistid > PLAYLIST_NONE)
551 value = (player.GetRepeat(playlistid) == PLAYLIST::REPEAT_ONE);
552 else
553 value = player.GetRepeat(player.GetCurrentPlaylist()) == PLAYLIST::REPEAT_ONE;
554 return true;
555 }
556
557 ///////////////////////////////////////////////////////////////////////////////////////////////
558 // PLAYER_PROCESS_*
559 ///////////////////////////////////////////////////////////////////////////////////////////////
560 case PLAYER_PROCESS_VIDEOHWDECODER:
561 value = CServiceBroker::GetDataCacheCore().IsVideoHwDecoder();
562 return true;
563
564 ///////////////////////////////////////////////////////////////////////////////////////////////
565 // LISTITEM_*
566 ///////////////////////////////////////////////////////////////////////////////////////////////
567 case LISTITEM_ISPLAYING:
568 {
569 if (item)
570 {
571 if (item->HasProperty("playlistposition"))
572 {
573 value = static_cast<int>(item->GetProperty("playlisttype").asInteger()) == CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() &&
574 static_cast<int>(item->GetProperty("playlistposition").asInteger()) == CServiceBroker::GetPlaylistPlayer().GetCurrentSong();
575 return true;
576 }
577 else if (m_currentItem && !m_currentItem->GetPath().empty())
578 {
579 if (!g_application.m_strPlayListFile.empty())
580 {
581 //playlist file that is currently playing or the playlistitem that is currently playing.
582 value = item->IsPath(g_application.m_strPlayListFile) || m_currentItem->IsSamePath(item);
583 }
584 else
585 {
586 value = m_currentItem->IsSamePath(item);
587 }
588 return true;
589 }
590 }
591 break;
592 }
593 }
594
595 return false;
596 }
597
GetContentRanges(int iInfo) const598 std::string CPlayerGUIInfo::GetContentRanges(int iInfo) const
599 {
600 std::string values;
601
602 CDataCacheCore& data = CServiceBroker::GetDataCacheCore();
603 std::vector<std::pair<float, float>> ranges;
604
605 time_t start;
606 int64_t current;
607 int64_t min;
608 int64_t max;
609 data.GetPlayTimes(start, current, min, max);
610
611 time_t duration = max - start * 1000;
612 if (duration > 0)
613 {
614 switch (iInfo)
615 {
616 case PLAYER_CUTLIST:
617 ranges = GetCutList(data, duration);
618 break;
619 case PLAYER_CHAPTERS:
620 ranges = GetChapters(data, duration);
621 break;
622 default:
623 CLog::Log(LOGERROR, "CPlayerGUIInfo::GetContentRanges(%i) - unhandled guiinfo", iInfo);
624 break;
625 }
626
627 // create csv string from ranges
628 for (const auto& range : ranges)
629 values += StringUtils::Format("%.5f,%.5f,", range.first, range.second);
630
631 if (!values.empty())
632 values.pop_back(); // remove trailing comma
633 }
634
635 return values;
636 }
637
GetCutList(CDataCacheCore & data,time_t duration) const638 std::vector<std::pair<float, float>> CPlayerGUIInfo::GetCutList(CDataCacheCore& data, time_t duration) const
639 {
640 std::vector<std::pair<float, float>> ranges;
641
642 const std::vector<EDL::Cut> cuts = data.GetCutList();
643 for (const auto& cut : cuts)
644 {
645 if (cut.action != EDL::Action::CUT &&
646 cut.action != EDL::Action::COMM_BREAK)
647 continue;
648
649 float cutStart = cut.start * 100.0f / duration;
650 float cutEnd = cut.end * 100.0f / duration;
651 ranges.emplace_back(std::make_pair(cutStart, cutEnd));
652 }
653 return ranges;
654 }
655
GetChapters(CDataCacheCore & data,time_t duration) const656 std::vector<std::pair<float, float>> CPlayerGUIInfo::GetChapters(CDataCacheCore& data, time_t duration) const
657 {
658 std::vector<std::pair<float, float>> ranges;
659
660 const std::vector<std::pair<std::string, int64_t>> chapters = data.GetChapters();
661 float lastMarker = 0.0f;
662 for (const auto& chapter : chapters)
663 {
664 float marker = chapter.second * 1000 * 100.0f / duration;
665 if (marker != 0)
666 ranges.emplace_back(std::make_pair(lastMarker, marker));
667
668 lastMarker = marker;
669 }
670 return ranges;
671 }
672