diff -Nru kodi-18.0+git20180904.0201-5d7e1db/addons/skin.estuary/xml/Includes.xml kodi-18.0+git20180906.0201-b69ac07/addons/skin.estuary/xml/Includes.xml --- kodi-18.0+git20180904.0201-5d7e1db/addons/skin.estuary/xml/Includes.xml 2018-07-31 18:47:37.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/addons/skin.estuary/xml/Includes.xml 2018-09-06 00:01:15.000000000 +0000 @@ -290,8 +290,7 @@ true 150 - -5 - String.IsEqual($PARAM[infolabel_prefix]ListItem.DBtype,tvshow) + System.HasAddon(resource.images.studios.white) + String.IsEqual($PARAM[infolabel_prefix]ListItem.DBtype,tvshow) diff -Nru kodi-18.0+git20180904.0201-5d7e1db/addons/skin.estuary/xml/MusicOSD.xml kodi-18.0+git20180906.0201-b69ac07/addons/skin.estuary/xml/MusicOSD.xml --- kodi-18.0+git20180904.0201-5d7e1db/addons/skin.estuary/xml/MusicOSD.xml 2018-09-04 00:01:11.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/addons/skin.estuary/xml/MusicOSD.xml 2018-09-06 00:01:15.000000000 +0000 @@ -44,7 +44,7 @@ PlayerControl(Previous) - [MusicPlayer.HasPrevious | Player.SeekEnabled] + !MusicPlayer.Content(livetv) + MusicPlayer.HasPrevious | Player.SeekEnabled osd/fullscreen/buttons/play.png @@ -76,7 +76,7 @@ PlayerControl(Next) - MusicPlayer.HasNext + !MusicPlayer.Content(livetv) + MusicPlayer.HasNext | [MusicPlayer.Content(LiveTV) + Player.SeekEnabled] osd/fullscreen/buttons/record-white.png diff -Nru kodi-18.0+git20180904.0201-5d7e1db/addons/skin.estuary/xml/VideoOSD.xml kodi-18.0+git20180906.0201-b69ac07/addons/skin.estuary/xml/VideoOSD.xml --- kodi-18.0+git20180904.0201-5d7e1db/addons/skin.estuary/xml/VideoOSD.xml 2018-08-29 00:00:19.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/addons/skin.estuary/xml/VideoOSD.xml 2018-09-06 00:01:15.000000000 +0000 @@ -49,7 +49,7 @@ PlayerControl(Previous) - !VideoPlayer.Content(livetv) + [Player.ChapterCount | Integer.IsGreater(Playlist.Length(video),1) | Player.SeekEnabled] + Player.ChapterCount | Integer.IsGreater(Playlist.Length(video),1) | Player.SeekEnabled osd/fullscreen/buttons/play.png @@ -81,7 +81,7 @@ PlayerControl(Next) - !VideoPlayer.Content(livetv) + [Player.ChapterCount | Integer.IsGreater(Playlist.Length(video),1)] + Player.ChapterCount | Integer.IsGreater(Playlist.Length(video),1) | [VideoPlayer.Content(LiveTV) + Player.SeekEnabled] diff -Nru kodi-18.0+git20180904.0201-5d7e1db/BUILDDATE kodi-18.0+git20180906.0201-b69ac07/BUILDDATE --- kodi-18.0+git20180904.0201-5d7e1db/BUILDDATE 2018-09-04 00:01:27.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/BUILDDATE 2018-09-06 00:01:29.000000000 +0000 @@ -1 +1 @@ -20180904 +20180906 diff -Nru kodi-18.0+git20180904.0201-5d7e1db/debian/changelog kodi-18.0+git20180906.0201-b69ac07/debian/changelog --- kodi-18.0+git20180904.0201-5d7e1db/debian/changelog 2018-09-04 00:06:58.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/debian/changelog 2018-09-06 00:06:43.000000000 +0000 @@ -1,4 +1,27 @@ -kodi (2:18.0+git20180904.0201-5d7e1db-0xenial) xenial; urgency=high +kodi (2:18.0+git20180906.0201-b69ac07-0xenial) xenial; urgency=high + + [Kai Sommerfeld] + * [pvr] Some CPVRChannelGroup cleanup: remove unused method. + + [Kai Sommerfeld] + * [PVR][Estuary] Add support for ACTION_(PREV + + [Memphiz] + * [windowing/osx] - fix double release of nsstring when no displayname can be queried (initwithformat is a convenience ctor which already is autoreleasing the sting - use alloc/init instead so the return autorelease does its job) - fixes #17942 + + [Kai Sommerfeld] + * [application] Get rid of magic number to control ACTION_PREV_ITEM behavior. + + [Kai Sommerfeld] + * [messaging][playlistplayer] Add TMSG_MEDIA_SEEK_TIME, add support to CPlayListPlayer. + + [Kai Sommerfeld] + * [messaging] Add int64_t param3 to ThreadMessage, extend ApplicationMessenger. + + [ronie] + * [Estuary] studio icon fixes + + [Rechi] * [cleanup] silence class memaccess warning diff -Nru kodi-18.0+git20180904.0201-5d7e1db/debian/changelog.tmp kodi-18.0+git20180906.0201-b69ac07/debian/changelog.tmp --- kodi-18.0+git20180904.0201-5d7e1db/debian/changelog.tmp 2018-09-04 00:02:17.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/debian/changelog.tmp 2018-09-06 00:02:04.000000000 +0000 @@ -1,4 +1,27 @@ -kodi (2:18.0+git20180904.0201-5d7e1db-0dist) dist; urgency=high +kodi (2:18.0+git20180906.0201-b69ac07-0dist) dist; urgency=high + + [Kai Sommerfeld] + * [pvr] Some CPVRChannelGroup cleanup: remove unused method. + + [Kai Sommerfeld] + * [PVR][Estuary] Add support for ACTION_(PREV + + [Memphiz] + * [windowing/osx] - fix double release of nsstring when no displayname can be queried (initwithformat is a convenience ctor which already is autoreleasing the sting - use alloc/init instead so the return autorelease does its job) - fixes #17942 + + [Kai Sommerfeld] + * [application] Get rid of magic number to control ACTION_PREV_ITEM behavior. + + [Kai Sommerfeld] + * [messaging][playlistplayer] Add TMSG_MEDIA_SEEK_TIME, add support to CPlayListPlayer. + + [Kai Sommerfeld] + * [messaging] Add int64_t param3 to ThreadMessage, extend ApplicationMessenger. + + [ronie] + * [Estuary] studio icon fixes + + [Rechi] * [cleanup] silence class memaccess warning diff -Nru kodi-18.0+git20180904.0201-5d7e1db/debian/changelog.tmp.old kodi-18.0+git20180906.0201-b69ac07/debian/changelog.tmp.old --- kodi-18.0+git20180904.0201-5d7e1db/debian/changelog.tmp.old 2018-09-04 00:01:27.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/debian/changelog.tmp.old 2018-09-06 00:01:29.000000000 +0000 @@ -1,6 +1,38 @@ kodi (2:18.0+git20180719.0202-3231481-0dist) dist; urgency=high + [Rechi] + * [cleanup] silence class memaccess warning + + [Rechi] + * [modernize] use default member initializers for SZipEntry + + [Lukas Rusak] + * LinuxRendererGLES: cleanup logging + + [Lukas Rusak] + * guilib: do not log empty compile info of pixel shaders + + [Kai Sommerfeld] + * [PVR] Simple timeshift OSD (optional). + + [Lukas Rusak] + * RenderSystemGLES: remove logging of extension test + + [Lukas Rusak] + * RenderSystemGLES: remove unused extension test + + [Kai Sommerfeld] + * [Estuary] Music OSD: Remove 'Previous' button for non-seekable streams and if player has no previous item. + + [Kai Sommerfeld] + * [PVR] Channel groups: simplify channel number setting logic. + + [Kai Sommerfeld] + * [PVR] PVRChannelGroup::ResetChannelnumberCache - numbers must be reset for all groups, not only for the currently selected. + + + [Mario Franco] * Show EPG image on the Dialog Seek Bar during video playback and MyPVRChannels screen diff -Nru kodi-18.0+git20180904.0201-5d7e1db/VERSION kodi-18.0+git20180906.0201-b69ac07/VERSION --- kodi-18.0+git20180904.0201-5d7e1db/VERSION 2018-09-04 00:01:27.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/VERSION 2018-09-06 00:01:29.000000000 +0000 @@ -1 +1 @@ -5d7e1db +b69ac07 diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/Application.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/Application.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/Application.cpp 2018-08-31 00:01:49.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/Application.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -2010,8 +2010,8 @@ } // Now check with the playlist player if action can be handled. - // In case of the action PREV_ITEM, we only allow the playlist player to take it if we're less than 3 seconds into playback. - if (!(action.GetID() == ACTION_PREV_ITEM && m_appPlayer.CanSeek() && GetTime() > 3) ) + // In case of ACTION_PREV_ITEM, we only allow the playlist player to take it if we're less than ACTION_PREV_ITEM_THRESHOLD seconds into playback. + if (!(action.GetID() == ACTION_PREV_ITEM && m_appPlayer.CanSeek() && GetTime() > ACTION_PREV_ITEM_THRESHOLD) ) { if (CServiceBroker::GetPlaylistPlayer().OnAction(action)) return true; @@ -2059,7 +2059,7 @@ return true; } - // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit. + // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the ACTION_PREV_ITEM_THRESHOLD secs limit. // If so, we just jump to the start of the track. if (action.GetID() == ACTION_PREV_ITEM && m_appPlayer.CanSeek()) { diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/Application.h kodi-18.0+git20180906.0201-b69ac07/xbmc/Application.h --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/Application.h 2018-08-26 13:40:15.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/Application.h 2018-09-06 00:01:15.000000000 +0000 @@ -123,6 +123,10 @@ public: + // If playback time of current item is greater than this value, ACTION_PREV_ITEM will seek to start + // of currently playing item, otherwise it will seek to start of the previous item in playlist + static const unsigned int ACTION_PREV_ITEM_THRESHOLD = 3; // seconds; + enum ESERVERS { ES_WEBSERVER = 1, diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/messaging/ApplicationMessenger.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/messaging/ApplicationMessenger.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/messaging/ApplicationMessenger.cpp 2018-07-31 18:47:39.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/messaging/ApplicationMessenger.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -169,6 +169,11 @@ SendMsg(ThreadMessage{ messageId }, false); } +void CApplicationMessenger::PostMsg(uint32_t messageId, int64_t param3) +{ + SendMsg(ThreadMessage{ messageId, param3 }, false); +} + void CApplicationMessenger::PostMsg(uint32_t messageId, int param1, int param2, void* payload) { SendMsg(ThreadMessage{ messageId, param1, param2, payload }, false); diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/messaging/ApplicationMessenger.h kodi-18.0+git20180906.0201-b69ac07/xbmc/messaging/ApplicationMessenger.h --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/messaging/ApplicationMessenger.h 2018-07-31 18:47:39.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/messaging/ApplicationMessenger.h 2018-09-06 00:01:15.000000000 +0000 @@ -45,8 +45,7 @@ #define TMSG_MEDIA_RESTART TMSG_MASK_PLAYLISTPLAYER + 15 #define TMSG_MEDIA_UNPAUSE TMSG_MASK_PLAYLISTPLAYER + 16 #define TMSG_MEDIA_PAUSE_IF_PLAYING TMSG_MASK_PLAYLISTPLAYER + 17 - - +#define TMSG_MEDIA_SEEK_TIME TMSG_MASK_PLAYLISTPLAYER + 18 #define TMSG_SHUTDOWN TMSG_MASK_APPLICATION + 0 #define TMSG_POWERDOWN TMSG_MASK_APPLICATION + 1 @@ -86,14 +85,10 @@ #define TMSG_GUI_INFOBOOL TMSG_MASK_GUIINFOMANAGER + 1 #define TMSG_UPDATE_CURRENT_ITEM TMSG_MASK_GUIINFOMANAGER + 2 - #define TMSG_CECTOGGLESTATE TMSG_MASK_PERIPHERALS + 1 #define TMSG_CECACTIVATESOURCE TMSG_MASK_PERIPHERALS + 2 #define TMSG_CECSTANDBY TMSG_MASK_PERIPHERALS + 3 - - - #define TMSG_GUI_DIALOG_OPEN TMSG_MASK_WINDOWMANAGER + 1 #define TMSG_GUI_ACTIVATE_WINDOW TMSG_MASK_WINDOWMANAGER + 2 #define TMSG_GUI_PYTHON_DIALOG TMSG_MASK_WINDOWMANAGER + 3 @@ -320,6 +315,17 @@ /*! * \brief Send a non-blocking message and return immediately + * + * If and what the response is depends entirely on the message being sent and + * should be documented on the message. + * + * \param [in] messageId defined further up in this file + * \param [in] param3 value depends on the message being sent + */ + void PostMsg(uint32_t messageId, int64_t param3); + + /*! + * \brief Send a non-blocking message and return immediately * * If and what the response is depends entirely on the message being sent and * should be documented on the message. diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/messaging/ThreadMessage.h kodi-18.0+git20180906.0201-b69ac07/xbmc/messaging/ThreadMessage.h --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/messaging/ThreadMessage.h 2018-07-31 18:47:39.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/messaging/ThreadMessage.h 2018-09-06 00:01:15.000000000 +0000 @@ -35,10 +35,16 @@ { } - ThreadMessage(uint32_t messageId, int p1, int p2, void* payload) + ThreadMessage(uint32_t messageId, int64_t p3) + : ThreadMessage{ messageId, -1, -1, nullptr, p3 } + { + } + + ThreadMessage(uint32_t messageId, int p1, int p2, void* payload, int64_t p3 = 0) : dwMessage{ messageId } , param1{ p1 } , param2{ p2 } + , param3{ p3 } , lpVoid{ payload } { } @@ -57,6 +63,7 @@ : dwMessage(other.dwMessage), param1(other.param1), param2(other.param2), + param3(other.param3), lpVoid(other.lpVoid), strParam(other.strParam), params(other.params), @@ -69,6 +76,7 @@ : dwMessage(other.dwMessage), param1(other.param1), param2(other.param2), + param3(other.param3), lpVoid(other.lpVoid), strParam(std::move(other.strParam)), params(std::move(other.params)), @@ -84,6 +92,7 @@ dwMessage = other.dwMessage; param1 = other.param1; param2 = other.param2; + param3 = other.param3; lpVoid = other.lpVoid; strParam = other.strParam; params = other.params; @@ -99,6 +108,7 @@ dwMessage = other.dwMessage; param1 = other.param1; param2 = other.param2; + param3 = other.param3; lpVoid = other.lpVoid; strParam = std::move(other.strParam); params = std::move(other.params); @@ -110,6 +120,7 @@ uint32_t dwMessage; int param1; int param2; + int64_t param3; void* lpVoid; std::string strParam; std::vector params; diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/PlayListPlayer.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/PlayListPlayer.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/PlayListPlayer.cpp 2018-08-26 13:40:15.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/PlayListPlayer.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -924,7 +924,8 @@ g_application.WakeUpScreenSaverAndDPMS(); // stop playing file - if (g_application.GetAppPlayer().IsPlaying()) g_application.StopPlaying(); + if (g_application.GetAppPlayer().IsPlaying()) + g_application.StopPlaying(); } break; @@ -954,9 +955,16 @@ g_application.GetAppPlayer().Pause(); } break; + + case TMSG_MEDIA_SEEK_TIME: + { + CApplicationPlayer& player = g_application.GetAppPlayer(); + if (player.IsPlaying() || player.IsPaused()) + player.SeekTime(pMsg->param3); + + break; + } default: break; } } - - diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannel.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannel.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannel.cpp 2018-07-31 18:47:40.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannel.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -556,12 +556,20 @@ CPVREpgInfoTagPtr CPVRChannel::GetEPGNext() const { - CPVREpgPtr epg = GetEPG(); + const CPVREpgPtr epg = GetEPG(); if (epg) return epg->GetTagNext(); - CPVREpgInfoTagPtr empty; - return empty; + return CPVREpgInfoTagPtr(); +} + +CPVREpgInfoTagPtr CPVRChannel::GetEPGPrevious() const +{ + const CPVREpgPtr epg = GetEPG(); + if (epg) + return epg->GetTagPrevious(); + + return CPVREpgInfoTagPtr(); } bool CPVRChannel::SetEPGEnabled(bool bEPGEnabled) diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannelGroup.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannelGroup.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannelGroup.cpp 2018-09-04 00:01:11.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannelGroup.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -921,34 +921,6 @@ } } -int CPVRChannelGroup::GetEPGNowOrNext(CFileItemList &results, bool bGetNext) const -{ - int iInitialSize = results.Size(); - CPVREpgInfoTagPtr epgNext; - CPVRChannelPtr channel; - CSingleLock lock(m_critSection); - - for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::const_iterator it = m_sortedMembers.begin(); it != m_sortedMembers.end(); ++it) - { - channel = (*it).channel; - CPVREpgPtr epg = channel->GetEPG(); - if (epg && !channel->IsHidden()) - { - epgNext = bGetNext ? epg->GetTagNext() : epg->GetTagNow(); - if (epgNext) - { - CFileItemPtr entry(new CFileItem(epgNext)); - entry->SetLabel2(epgNext->StartAsLocalTime().GetAsLocalizedTime("", false)); - entry->SetPath(channel->Path()); - entry->SetArt("thumb", channel->IconPath()); - results.Add(entry); - } - } - } - - return results.Size() - iInitialSize; -} - int CPVRChannelGroup::GetEPGAll(CFileItemList &results, bool bIncludeChannelsWithoutEPG /* = false */) const { int iInitialSize = results.Size(); diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannelGroup.h kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannelGroup.h --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannelGroup.h 2018-09-04 00:01:11.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannelGroup.h 2018-09-06 00:01:15.000000000 +0000 @@ -388,20 +388,6 @@ int GetEPGAll(CFileItemList &results, bool bIncludeChannelsWithoutEPG = false) const; /*! - * @brief Get all entries that are active now. - * @param results The fileitem list to store the results in. - * @return The amount of entries that were added. - */ - int GetEPGNow(CFileItemList &results) const { return GetEPGNowOrNext(results, false); } - - /*! - * @brief Get all entries that will be active next. - * @param results The fileitem list to store the results in. - * @return The amount of entries that were added. - */ - int GetEPGNext(CFileItemList &results) const { return GetEPGNowOrNext(results, true); } - - /*! * @brief Get the start time of the first entry. * @return The start time. */ @@ -536,12 +522,5 @@ private: CDateTime GetEPGDate(EpgDateType epgDateType) const; - /*! - * @brief Get all entries that will be active next. - * @param results The fileitem list to store the results in. - * @param bGetNext True to get the next item, false to get the current one - * @return The amount of entries that were added. - */ - int GetEPGNowOrNext(CFileItemList &results, bool bGetNext) const; }; } diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannel.h kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannel.h --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/channels/PVRChannel.h 2018-07-31 18:47:40.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/channels/PVRChannel.h 2018-09-06 00:01:15.000000000 +0000 @@ -357,22 +357,32 @@ bool ClearEPG(void) const; /*! - * @brief Get the EPG tag that is active on this channel now. + * @brief Get the EPG tag that is now active on this channel. * - * Get the EPG tag that is active on this channel now. + * Get the EPG tag that is now active on this channel. * Will return an empty tag if there is none. * - * @return The EPG tag that is active on this channel now. + * @return The EPG tag that is now active. */ CPVREpgInfoTagPtr GetEPGNow() const; /*! - * @brief Get the EPG tag that is active on this channel next. + * @brief Get the EPG tag that was previously active on this channel. * - * Get the EPG tag that is active on this channel next. + * Get the EPG tag that was previously active on this channel. * Will return an empty tag if there is none. * - * @return The EPG tag that is active on this channel next. + * @return The EPG tag that was previously activ. + */ + CPVREpgInfoTagPtr GetEPGPrevious() const; + + /*! + * @brief Get the EPG tag that will be next active on this channel. + * + * Get the EPG tag that will be next active on this channel. + * Will return an empty tag if there is none. + * + * @return The EPG tag that will be next active. */ CPVREpgInfoTagPtr GetEPGNext() const; diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/epg/Epg.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/epg/Epg.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/epg/Epg.cpp 2018-08-27 00:01:45.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/epg/Epg.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -199,6 +199,32 @@ return CPVREpgInfoTagPtr(); } +CPVREpgInfoTagPtr CPVREpg::GetTagPrevious() const +{ + CPVREpgInfoTagPtr nowTag(GetTagNow()); + if (nowTag) + { + CSingleLock lock(m_critSection); + std::map::const_iterator it = m_tags.find(nowTag->StartAsUTC()); + if (it != m_tags.end() && it != m_tags.begin()) + { + --it; + return it->second; + } + } + else if (Size() > 0) + { + /* return the first event that is in the past */ + for (std::map::const_reverse_iterator it = m_tags.rbegin(); it != m_tags.rend(); ++it) + { + if (it->second->WasActive()) + return it->second; + } + } + + return CPVREpgInfoTagPtr(); +} + bool CPVREpg::CheckPlayingEvent(void) { CPVREpgInfoTagPtr previousTag(GetTagNow(false)); diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/epg/Epg.h kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/epg/Epg.h --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/epg/Epg.h 2018-07-31 18:47:40.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/epg/Epg.h 2018-09-06 00:01:15.000000000 +0000 @@ -152,6 +152,12 @@ CPVREpgInfoTagPtr GetTagNext() const; /*! + * @brief Get the event that occured previously + * @return The previous event or NULL if it wasn't found. + */ + CPVREpgInfoTagPtr GetTagPrevious() const; + + /*! * Get the event that occurs between the given begin and end time. * @param beginTime Minimum start time in UTC of the event. * @param endTime Maximum end time in UTC of the event. diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/PVRActionListener.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/PVRActionListener.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/PVRActionListener.cpp 2018-07-31 18:47:40.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/PVRActionListener.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -168,8 +168,25 @@ return false; } - case ACTION_MOVE_UP: case ACTION_NEXT_ITEM: + { + if (!bIsPlayingPVR) + return false; + + CServiceBroker::GetPVRManager().GUIActions()->SeekForward(); + return true; + } + + case ACTION_PREV_ITEM: + { + if (!bIsPlayingPVR) + return false; + + CServiceBroker::GetPVRManager().GUIActions()->SeekBackward(CApplication::ACTION_PREV_ITEM_THRESHOLD); + return true; + } + + case ACTION_MOVE_UP: case ACTION_CHANNEL_UP: { if (!bIsPlayingPVR) @@ -180,7 +197,6 @@ } case ACTION_MOVE_DOWN: - case ACTION_PREV_ITEM: case ACTION_CHANNEL_DOWN: { if (!bIsPlayingPVR) diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/PVRGUIActions.cpp kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/PVRGUIActions.cpp --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/PVRGUIActions.cpp 2018-07-31 18:47:40.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/PVRGUIActions.cpp 2018-09-06 00:01:15.000000000 +0000 @@ -12,6 +12,7 @@ #include "FileItem.h" #include "ServiceBroker.h" #include "addons/PVRClient.h" +#include "cores/DataCacheCore.h" #include "dialogs/GUIDialogBusy.h" #include "dialogs/GUIDialogKaiToast.h" #include "dialogs/GUIDialogNumeric.h" @@ -1822,6 +1823,84 @@ return bRadio ? m_selectedItemPathRadio : m_selectedItemPathTV; } + void CPVRGUIActions::SeekForward() + { + time_t playbackStartTime = CServiceBroker::GetDataCacheCore().GetStartTime(); + if (playbackStartTime > 0) + { + const CPVRChannelPtr playingChannel = CServiceBroker::GetPVRManager().GetPlayingChannel(); + if (playingChannel) + { + time_t nextTime = 0; + CPVREpgInfoTagPtr next = playingChannel->GetEPGNext(); + if (next) + { + next->StartAsUTC().GetAsTime(nextTime); + } + else + { + // if there is no next event, jump to end of currently playing event + next = playingChannel->GetEPGNow(); + if (next) + next->EndAsUTC().GetAsTime(nextTime); + } + + int64_t seekTime = 0; + if (nextTime != 0) + { + seekTime = (nextTime - playbackStartTime) * 1000; + } + else + { + // no epg; jump to end of buffer + seekTime = CServiceBroker::GetDataCacheCore().GetMaxTime(); + } + CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_SEEK_TIME, seekTime); + } + } + } + + void CPVRGUIActions::SeekBackward(unsigned int iThreshold) + { + time_t playbackStartTime = CServiceBroker::GetDataCacheCore().GetStartTime(); + if (playbackStartTime > 0) + { + const CPVRChannelPtr playingChannel = CServiceBroker::GetPVRManager().GetPlayingChannel(); + if (playingChannel) + { + time_t prevTime = 0; + CPVREpgInfoTagPtr prev = playingChannel->GetEPGNow(); + if (prev) + { + prev->StartAsUTC().GetAsTime(prevTime); + + // if playback time of current event is above threshold jump to start of current event + int64_t playTime = CServiceBroker::GetDataCacheCore().GetPlayTime() / 1000; + if ((playbackStartTime + playTime - prevTime) <= iThreshold) + { + // jump to start of previous event + prevTime = 0; + prev = playingChannel->GetEPGPrevious(); + if (prev) + prev->StartAsUTC().GetAsTime(prevTime); + } + } + + int64_t seekTime = 0; + if (prevTime != 0) + { + seekTime = (prevTime - playbackStartTime) * 1000; + } + else + { + // no epg; jump to begin of buffer + seekTime = CServiceBroker::GetDataCacheCore().GetMinTime(); + } + CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_SEEK_TIME, seekTime); + } + } + } + CPVRChannelNumberInputHandler &CPVRGUIActions::GetChannelNumberInputHandler() { // window/dialog specific input handler diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/PVRGUIActions.h kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/PVRGUIActions.h --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/pvr/PVRGUIActions.h 2018-07-31 18:47:40.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/pvr/PVRGUIActions.h 2018-09-06 00:01:15.000000000 +0000 @@ -359,6 +359,20 @@ void SetSelectedItemPath(bool bRadio, const std::string &path); /*! + * @brief Seek to the start of the next epg event in timeshift buffer, relative to the currently playing event. + * If there is no next event, seek to the end of the currently playing event (to the 'live' position). + */ + void SeekForward(); + + /*! + * @brief Seek to the start of the previous epg event in timeshift buffer, relative to the currently playing event + * or if there is no previous event or if playback time is greater than given threshold, seek to the start + * of the playing event. + * @param iThreshold the value in seconds to trigger seek to start of current event instead of start of previous event. + */ + void SeekBackward(unsigned int iThreshold); + + /*! * @brief Get the currently active channel number input handler. * @return the handler. */ diff -Nru kodi-18.0+git20180904.0201-5d7e1db/xbmc/windowing/osx/WinSystemOSX.mm kodi-18.0+git20180906.0201-b69ac07/xbmc/windowing/osx/WinSystemOSX.mm --- kodi-18.0+git20180904.0201-5d7e1db/xbmc/windowing/osx/WinSystemOSX.mm 2018-08-26 13:40:16.000000000 +0000 +++ kodi-18.0+git20180906.0201-b69ac07/xbmc/windowing/osx/WinSystemOSX.mm 2018-09-06 00:01:15.000000000 +0000 @@ -386,7 +386,7 @@ if (screenName == nil) { - screenName = [NSString stringWithFormat:@"%i", displayID]; + screenName = [[NSString alloc] initWithFormat:@"%i", displayID]; } return [screenName autorelease]; }