diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/BUILDDATE kodi-20.0+git20230115.1026-389e701cb9/BUILDDATE --- kodi-20.0+git20230109.1027-bbdf5686e0/BUILDDATE 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/BUILDDATE 2013-05-12 08:41:54.000000000 +0000 @@ -1 +1 @@ -20230109 +20230115 diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/debian/changelog kodi-20.0+git20230115.1026-389e701cb9/debian/changelog --- kodi-20.0+git20230109.1027-bbdf5686e0/debian/changelog 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/debian/changelog 2013-05-12 08:41:54.000000000 +0000 @@ -1,4 +1,4 @@ -kodi (6:20.0+git20230109.1027-bbdf5686e0-0~jammy) jammy; urgency=medium +kodi (6:20.0+git20230115.1026-389e701cb9-0~jammy) jammy; urgency=medium [ kodi ] * autogenerated dummy changelog Binary files /tmp/tmpp4zi4qrv/ENCEWpbzZN/kodi-20.0+git20230109.1027-bbdf5686e0/media/splash.jpg and /tmp/tmpp4zi4qrv/UfoOHeXbHd/kodi-20.0+git20230115.1026-389e701cb9/media/splash.jpg differ diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/tools/Linux/kodi.metainfo.xml.in kodi-20.0+git20230115.1026-389e701cb9/tools/Linux/kodi.metainfo.xml.in --- kodi-20.0+git20230109.1027-bbdf5686e0/tools/Linux/kodi.metainfo.xml.in 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/tools/Linux/kodi.metainfo.xml.in 2013-05-12 08:41:54.000000000 +0000 @@ -78,6 +78,7 @@ + https://kodi.tv/article/kodi-20-0-nexus-release/ https://kodi.tv/article/kodi-nexus-rc-2/ https://kodi.tv/article/kodi-nexus-rc-1/ https://kodi.tv/article/kodi-nexus-beta-1/ diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/VERSION kodi-20.0+git20230115.1026-389e701cb9/VERSION --- kodi-20.0+git20230109.1027-bbdf5686e0/VERSION 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/VERSION 2013-05-12 08:41:54.000000000 +0000 @@ -1 +1 @@ -bbdf5686e0 +389e701cb9 diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/version.txt kodi-20.0+git20230115.1026-389e701cb9/version.txt --- kodi-20.0+git20230109.1027-bbdf5686e0/version.txt 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/version.txt 2013-05-12 08:41:54.000000000 +0000 @@ -4,9 +4,9 @@ WEBSITE http://kodi.tv VERSION_MAJOR 20 VERSION_MINOR 0 -VERSION_TAG RC2 -VERSION_CODE 19.90.905 -ADDON_API 19.90.905 +VERSION_TAG +VERSION_CODE 20.0.0 +ADDON_API 20.0.0 ADDON_REPOS repository.xbmc.org|https://mirrors.kodi.tv APP_PACKAGE org.xbmc.kodi PACKAGE_IDENTITY XBMCFoundation.Kodi diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/addons/kodi-dev-kit/include/kodi/c-api/addon_base.h kodi-20.0+git20230115.1026-389e701cb9/xbmc/addons/kodi-dev-kit/include/kodi/c-api/addon_base.h --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/addons/kodi-dev-kit/include/kodi/c-api/addon_base.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/addons/kodi-dev-kit/include/kodi/c-api/addon_base.h 2013-05-12 08:41:54.000000000 +0000 @@ -251,7 +251,7 @@ typedef int KODI_ADDON_INSTANCE_TYPE; - struct KODI_ADDON_INSTANCE_INFO + typedef struct KODI_ADDON_INSTANCE_INFO { KODI_ADDON_INSTANCE_TYPE type; uint32_t number; @@ -262,7 +262,7 @@ bool first_instance; struct KODI_ADDON_INSTANCE_FUNC_CB* functions; - }; + } KODI_ADDON_INSTANCE_INFO; typedef struct KODI_ADDON_INSTANCE_STRUCT { diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/RetroPlayer/guicontrols/GUIGameControl.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/RetroPlayer/guicontrols/GUIGameControl.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/RetroPlayer/guicontrols/GUIGameControl.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/RetroPlayer/guicontrols/GUIGameControl.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -126,10 +126,10 @@ void CGUIGameControl::UpdateInfo(const CGUIListItem* item /* = nullptr */) { - Reset(); - if (item) { + Reset(); + std::string strVideoFilter = m_videoFilterInfo.GetItemLabel(item); if (!strVideoFilter.empty()) { diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxCC.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxCC.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxCC.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxCC.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -319,7 +319,7 @@ stream.flags = FLAG_HEARING_IMPAIRED; stream.codec = AV_CODEC_ID_TEXT; stream.uniqueId = service; - ctx->m_streams.push_back(stream); + ctx->m_streams.push_back(std::move(stream)); streamdata data; data.streamIdx = idx; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -154,14 +154,12 @@ int len = stream->m_parser->parser->split(stream->m_context, pkt->pData, pkt->iSize); if (len > 0 && len < FF_MAX_EXTRADATA_SIZE) { - if (st->ExtraData) - delete[] st->ExtraData; st->changes++; st->disabled = false; st->ExtraSize = len; - st->ExtraData = new uint8_t[len+AV_INPUT_BUFFER_PADDING_SIZE]; - memcpy(st->ExtraData, pkt->pData, len); - memset(st->ExtraData + len, 0 , AV_INPUT_BUFFER_PADDING_SIZE); + st->ExtraData = std::make_unique(len + AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(st->ExtraData.get(), pkt->pData, len); + memset(st->ExtraData.get() + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); stream->m_parser_split = false; change = true; CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - split extradata"); @@ -435,8 +433,7 @@ streamAudio->iBitsPerSample = source->iBitsPerSample; if (source->ExtraSize > 0 && source->ExtraData) { - delete[] streamAudio->ExtraData; - streamAudio->ExtraData = new uint8_t[source->ExtraSize]; + streamAudio->ExtraData = std::make_unique(source->ExtraSize); streamAudio->ExtraSize = source->ExtraSize; for (unsigned int j=0; jExtraSize; j++) streamAudio->ExtraData[j] = source->ExtraData[j]; @@ -476,8 +473,7 @@ streamVideo->iBitRate = source->iBitRate; if (source->ExtraSize > 0 && source->ExtraData) { - delete[] streamVideo->ExtraData; - streamVideo->ExtraData = new uint8_t[source->ExtraSize]; + streamVideo->ExtraData = std::make_unique(source->ExtraSize); streamVideo->ExtraSize = source->ExtraSize; for (unsigned int j=0; jExtraSize; j++) streamVideo->ExtraData[j] = source->ExtraData[j]; @@ -519,8 +515,7 @@ if (source->ExtraSize == 4) { - delete[] streamSubtitle->ExtraData; - streamSubtitle->ExtraData = new uint8_t[4]; + streamSubtitle->ExtraData = std::make_unique(4); streamSubtitle->ExtraSize = 4; for (int j=0; j<4; j++) streamSubtitle->ExtraData[j] = source->ExtraData[j]; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -1880,8 +1880,9 @@ if (stream->type != STREAM_NONE && pStream->codecpar->extradata && pStream->codecpar->extradata_size > 0) { stream->ExtraSize = pStream->codecpar->extradata_size; - stream->ExtraData = new uint8_t[pStream->codecpar->extradata_size]; - memcpy(stream->ExtraData, pStream->codecpar->extradata, pStream->codecpar->extradata_size); + stream->ExtraData = std::make_unique(pStream->codecpar->extradata_size); + memcpy(stream->ExtraData.get(), pStream->codecpar->extradata, + pStream->codecpar->extradata_size); } #ifdef HAVE_LIBBLURAY diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h 2013-05-12 08:41:54.000000000 +0000 @@ -82,14 +82,14 @@ source = STREAM_SOURCE_NONE; iDuration = 0; pPrivate = NULL; - ExtraData = NULL; ExtraSize = 0; disabled = false; changes = 0; flags = StreamFlags::FLAG_NONE; } - virtual ~CDemuxStream() { delete[] ExtraData; } + virtual ~CDemuxStream() = default; + CDemuxStream(CDemuxStream&&) = default; virtual std::string GetStreamName(); @@ -105,7 +105,7 @@ int iDuration; // in mseconds void* pPrivate; // private pointer for the demuxer - uint8_t* ExtraData; // extra data for codec to use + std::unique_ptr ExtraData; // extra data for codec to use unsigned int ExtraSize; // size of extra data StreamFlags flags; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -114,8 +114,8 @@ for(unsigned i=0;iExtraSize = state.extra.length()+1; - m_Streams[i]->ExtraData = new uint8_t[m_Streams[i]->ExtraSize]; - strcpy((char*)m_Streams[i]->ExtraData, state.extra.c_str()); + m_Streams[i]->ExtraData = std::make_unique(m_Streams[i]->ExtraSize); + strcpy((char*)m_Streams[i]->ExtraData.get(), state.extra.c_str()); } return true; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -530,7 +530,7 @@ if (stream->m_ExtraData && stream->m_ExtraSize) { - demuxStream->ExtraData = new uint8_t[stream->m_ExtraSize]; + demuxStream->ExtraData = std::make_unique(stream->m_ExtraSize); demuxStream->ExtraSize = stream->m_ExtraSize; for (unsigned int j = 0; j < stream->m_ExtraSize; ++j) demuxStream->ExtraData[j] = stream->m_ExtraData[j]; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -322,7 +322,7 @@ if (stream.iSubtitleInfo) { - streamSubtitle->ExtraData = new uint8_t[4]; + streamSubtitle->ExtraData = std::make_unique(4); streamSubtitle->ExtraSize = 4; streamSubtitle->ExtraData[0] = (stream.iSubtitleInfo >> 8) & 0xff; streamSubtitle->ExtraData[1] = (stream.iSubtitleInfo >> 0) & 0xff; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -266,7 +266,7 @@ extradata = malloc(extrasize); if (!extradata) return; - memcpy(extradata, right.ExtraData, extrasize); + memcpy(extradata, right.ExtraData.get(), extrasize); } cryptoSession = right.cryptoSession; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/guilib/GUISliderControl.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/guilib/GUISliderControl.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/guilib/GUISliderControl.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/guilib/GUISliderControl.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -614,7 +614,7 @@ { case SLIDER_CONTROL_TYPE_FLOAT: { - float fValue = m_fStart + (m_fEnd - m_fStart) * fPercent + m_fInterval / 2; + float fValue = m_fStart + (m_fEnd - m_fStart) * fPercent; SetFloatValue(MathUtils::RoundF(fValue, m_fInterval), m_currentSelector, true); break; } diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/builtins/PlayerBuiltins.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/builtins/PlayerBuiltins.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/builtins/PlayerBuiltins.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/builtins/PlayerBuiltins.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -597,9 +597,16 @@ } if ((item.IsAudio() || item.IsVideo()) && !item.IsSmartPlayList()) + { + if (!item.HasProperty("playlist_type_hint")) + item.SetProperty("playlist_type_hint", PLAYLIST::TYPE_MUSIC); + CServiceBroker::GetPlaylistPlayer().Play(std::make_shared(item), ""); + } else + { g_application.PlayMedia(item, "", PLAYLIST::TYPE_NONE); + } } return 0; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -57,6 +57,8 @@ { "Player.PlayPause", CPlayerOperations::PlayPause }, { "Player.Stop", CPlayerOperations::Stop }, + { "Player.GetAudioDelay", CPlayerOperations::GetAudioDelay }, + { "Player.SetAudioDelay", CPlayerOperations::SetAudioDelay }, { "Player.SetSpeed", CPlayerOperations::SetSpeed }, { "Player.Seek", CPlayerOperations::Seek }, { "Player.Move", CPlayerOperations::Move }, diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/PlayerOperations.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/PlayerOperations.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/PlayerOperations.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/PlayerOperations.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -40,7 +40,12 @@ #include "pvr/guilib/PVRGUIActionsChannels.h" #include "pvr/guilib/PVRGUIActionsPlayback.h" #include "pvr/recordings/PVRRecordings.h" +#include "settings/AdvancedSettings.h" #include "settings/DisplaySettings.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/MathUtils.h" #include "utils/Variant.h" #include "video/VideoDatabase.h" @@ -358,6 +363,76 @@ case None: default: return FailedToExecute; + } +} + +JSONRPC_STATUS CPlayerOperations::GetAudioDelay(const std::string& method, + ITransportLayer* transport, + IClient* client, + const CVariant& parameterObject, + CVariant& result) +{ + auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent(); + result["offset"] = appPlayer->GetVideoSettings().m_AudioDelay; + return OK; +} + +JSONRPC_STATUS CPlayerOperations::SetAudioDelay(const std::string& method, + ITransportLayer* transport, + IClient* client, + const CVariant& parameterObject, + CVariant& result) +{ + switch (GetPlayer(parameterObject["playerid"])) + { + case Video: + { + auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent(); + float videoAudioDelayRange = + CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange; + + if (parameterObject["offset"].isDouble()) + { + float offset = static_cast(parameterObject["offset"].asDouble()); + offset = MathUtils::RoundF(offset, AUDIO_DELAY_STEP); + if (offset > videoAudioDelayRange) + offset = videoAudioDelayRange; + else if (offset < -videoAudioDelayRange) + offset = -videoAudioDelayRange; + + appPlayer->SetAVDelay(offset); + } + else if (parameterObject["offset"].isString()) + { + CVideoSettings vs = appPlayer->GetVideoSettings(); + if (parameterObject["offset"].asString().compare("increment") == 0) + { + vs.m_AudioDelay += AUDIO_DELAY_STEP; + if (vs.m_AudioDelay > videoAudioDelayRange) + vs.m_AudioDelay = videoAudioDelayRange; + appPlayer->SetAVDelay(vs.m_AudioDelay); + } + else + { + vs.m_AudioDelay -= AUDIO_DELAY_STEP; + if (vs.m_AudioDelay < -videoAudioDelayRange) + vs.m_AudioDelay = -videoAudioDelayRange; + appPlayer->SetAVDelay(vs.m_AudioDelay); + } + } + else + return InvalidParams; + + result["offset"] = appPlayer->GetVideoSettings().m_AudioDelay; + return OK; + } + case Audio: + case Picture: + case None: + default: + return FailedToExecute; } } diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/PlayerOperations.h kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/PlayerOperations.h --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/PlayerOperations.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/PlayerOperations.h 2013-05-12 08:41:54.000000000 +0000 @@ -51,6 +51,16 @@ static JSONRPC_STATUS PlayPause(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); static JSONRPC_STATUS Stop(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); + static JSONRPC_STATUS GetAudioDelay(const std::string& method, + ITransportLayer* transport, + IClient* client, + const CVariant& parameterObject, + CVariant& result); + static JSONRPC_STATUS SetAudioDelay(const std::string& method, + ITransportLayer* transport, + IClient* client, + const CVariant& parameterObject, + CVariant& result); static JSONRPC_STATUS SetSpeed(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); static JSONRPC_STATUS Seek(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/schema/methods.json kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/schema/methods.json --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/schema/methods.json 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/schema/methods.json 2013-05-12 08:41:54.000000000 +0000 @@ -271,6 +271,61 @@ ], "returns": "string" }, + "Player.GetAudioDelay": { + "type": "method", + "description": "Get the audio delay for the current playback", + "transport": "Response", + "permission": "ReadData", + "params": [], + "returns": { + "type": "object", + "properties": { + "offset": { + "type": "number", + "description": "The offset value used in the current playback.", + "required": true + } + } + } + }, + "Player.SetAudioDelay": { + "type": "method", + "description": "Set the audio delay for the current playback", + "transport": "Response", + "permission": "ControlPlayback", + "params": [ + { + "name": "playerid", + "$ref": "Player.Id", + "required": true + }, + { + "name": "offset", + "type": [ + { + "type": "number", + "description": "The value should be a multiple of 0.025 in a range of +/-10 (the default range can be overriden by advancedsettings.xml).", + "required": true + }, + { + "$ref": "Global.IncrementDecrement", + "required": true + } + ], + "required": true + } + ], + "returns": { + "type": "object", + "properties": { + "offset": { + "type": "number", + "description": "The offset value used in the current playback.", + "required": true + } + } + } + }, "Player.SetSpeed": { "type": "method", "description": "Set the speed of the current playback", diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/schema/version.txt kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/schema/version.txt --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/interfaces/json-rpc/schema/version.txt 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/interfaces/json-rpc/schema/version.txt 2013-05-12 08:41:54.000000000 +0000 @@ -1 +1 @@ -JSONRPC_VERSION 12.10.2 +JSONRPC_VERSION 13.0.0 diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/listproviders/DirectoryProvider.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/listproviders/DirectoryProvider.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/listproviders/DirectoryProvider.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/listproviders/DirectoryProvider.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -157,7 +157,6 @@ CDirectoryProvider::CDirectoryProvider(const TiXmlElement *element, int parentID) : IListProvider(parentID), m_updateState(OK), - m_isAnnounced(false), m_jobID(0), m_currentLimit(0) { @@ -187,7 +186,6 @@ CDirectoryProvider::CDirectoryProvider(const CDirectoryProvider& other) : IListProvider(other.m_parentID), m_updateState(INVALIDATED), - m_isAnnounced(false), m_jobID(0), m_url(other.m_url), m_target(other.m_target), @@ -352,22 +350,25 @@ void CDirectoryProvider::Reset() { - std::unique_lock lock(m_section); - if (m_jobID) - CServiceBroker::GetJobManager()->CancelJob(m_jobID); - m_jobID = 0; - m_items.clear(); - m_currentTarget.clear(); - m_currentUrl.clear(); - m_itemTypes.clear(); - m_currentSort.sortBy = SortByNone; - m_currentSort.sortOrder = SortOrderAscending; - m_currentLimit = 0; - m_updateState = OK; + { + std::unique_lock lock(m_section); + if (m_jobID) + CServiceBroker::GetJobManager()->CancelJob(m_jobID); + m_jobID = 0; + m_items.clear(); + m_currentTarget.clear(); + m_currentUrl.clear(); + m_itemTypes.clear(); + m_currentSort.sortBy = SortByNone; + m_currentSort.sortOrder = SortOrderAscending; + m_currentLimit = 0; + m_updateState = OK; + } - if (m_isAnnounced) + std::unique_lock subscriptionLock(m_subscriptionSection); + if (m_isSubscribed) { - m_isAnnounced = false; + m_isSubscribed = false; CServiceBroker::GetAnnouncementManager()->RemoveAnnouncer(this); CServiceBroker::GetFavouritesService().Events().Unsubscribe(this); CServiceBroker::GetRepositoryUpdater().Events().Unsubscribe(this); @@ -529,16 +530,19 @@ bool CDirectoryProvider::UpdateURL() { - std::unique_lock lock(m_section); - std::string value(m_url.GetLabel(m_parentID, false)); - if (value == m_currentUrl) - return false; + { + std::unique_lock lock(m_section); + std::string value(m_url.GetLabel(m_parentID, false)); + if (value == m_currentUrl) + return false; - m_currentUrl = value; + m_currentUrl = value; + } - if (!m_isAnnounced) + std::unique_lock subscriptionLock(m_subscriptionSection); + if (!m_isSubscribed) { - m_isAnnounced = true; + m_isSubscribed = true; CServiceBroker::GetAnnouncementManager()->AddAnnouncer(this); CServiceBroker::GetAddonMgr().Events().Subscribe(this, &CDirectoryProvider::OnAddonEvent); CServiceBroker::GetRepositoryUpdater().Events().Subscribe(this, &CDirectoryProvider::OnAddonRepositoryEvent); diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/listproviders/DirectoryProvider.h kodi-20.0+git20230115.1026-389e701cb9/xbmc/listproviders/DirectoryProvider.h --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/listproviders/DirectoryProvider.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/listproviders/DirectoryProvider.h 2013-05-12 08:41:54.000000000 +0000 @@ -74,7 +74,6 @@ void OnJobComplete(unsigned int jobID, bool success, CJob *job) override; private: UpdateState m_updateState; - bool m_isAnnounced; unsigned int m_jobID; KODI::GUILIB::GUIINFO::CGUIInfoLabel m_url; KODI::GUILIB::GUIINFO::CGUIInfoLabel m_target; @@ -97,4 +96,7 @@ void OnPVRManagerEvent(const PVR::PVREvent& event); void OnFavouritesEvent(const CFavouritesService::FavouritesUpdated& event); std::string GetTarget(const CFileItem& item) const; + + CCriticalSection m_subscriptionSection; + bool m_isSubscribed{false}; }; diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/music/MusicDatabase.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/music/MusicDatabase.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/music/MusicDatabase.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/music/MusicDatabase.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -5568,7 +5568,7 @@ if (nullptr == m_pDS) return false; - std::string strSQL = PrepareSQL("SELECT albumview.* FROM song" + std::string strSQL = PrepareSQL("SELECT albumview.* FROM song " "JOIN albumview on song.idAlbum = albumview.idAlbum " "WHERE song.idSong='%i'", idSong); diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/music/windows/GUIWindowMusicBase.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/music/windows/GUIWindowMusicBase.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/music/windows/GUIWindowMusicBase.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/music/windows/GUIWindowMusicBase.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -741,7 +741,7 @@ OnQueueItem(iItem); return true; } - pItem->SetProperty("playlist_type_hint", PLAYLIST::TYPE_MUSIC); + pItem->SetProperty("playlist_type_hint", m_guiState->GetPlaylist()); CServiceBroker::GetPlaylistPlayer().Play(pItem, player); return true; } Binary files /tmp/tmpp4zi4qrv/ENCEWpbzZN/kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/platform/darwin/tvos/Assets.xcassets/LaunchImage.launchimage/splash.jpg and /tmp/tmpp4zi4qrv/UfoOHeXbHd/kodi-20.0+git20230115.1026-389e701cb9/xbmc/platform/darwin/tvos/Assets.xcassets/LaunchImage.launchimage/splash.jpg differ diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/PlayListPlayer.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/PlayListPlayer.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/PlayListPlayer.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/PlayListPlayer.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -263,21 +263,31 @@ Id playlistId; bool isVideo{pItem->IsVideo()}; bool isAudio{pItem->IsAudio()}; - if (isVideo && isAudio && pItem->HasProperty("playlist_type_hint")) + + if (isAudio && !isVideo) + playlistId = TYPE_MUSIC; + else if (isVideo && !isAudio) + playlistId = TYPE_VIDEO; + else if (pItem->HasProperty("playlist_type_hint")) { - // If an extension is set in both audio / video lists (e.g. playlist .strm), - // is not possible detect the type of playlist then we rely on the hint + // There are two main cases that can fall here: + // - If an extension is set on both audio / video extension lists example .strm + // see GetFileExtensionProvider() -> GetVideoExtensions() / GetAudioExtensions() + // When you play the .strm containing single path, cause that + // IsVideo() and IsAudio() methods both return true + // + // - When you play a playlist (e.g. .m3u / .strm) containing multiple paths, + // and the path played is generic (e.g.without extension) and have no properties + // to detect the media type, IsVideo() / IsAudio() both return false + // + // for these cases the type is unknown so we rely on the hint playlistId = pItem->GetProperty("playlist_type_hint").asInteger32(TYPE_NONE); } - else if (isAudio) - playlistId = TYPE_MUSIC; - else if (isVideo) - playlistId = TYPE_VIDEO; else { - CLog::Log( - LOGWARNING, - "Playlist Player: ListItem type must be audio or video, use ListItem::setInfo to specify!"); + CLog::LogF(LOGWARNING, "ListItem type must be audio or video type. The type can be specified " + "by using ListItem::getVideoInfoTag or ListItem::getMusicInfoTag, in " + "the case of playlist entries by adding #KODIPROP mimetype value."); return false; } diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/settings/MediaSettings.h kodi-20.0+git20230115.1026-389e701cb9/xbmc/settings/MediaSettings.h --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/settings/MediaSettings.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/settings/MediaSettings.h 2013-05-12 08:41:54.000000000 +0000 @@ -24,6 +24,9 @@ class TiXmlNode; +// Step used to increase/decrease audio delay +static constexpr float AUDIO_DELAY_STEP = 0.025f; + typedef enum { WatchedModeAll = 0, WatchedModeUnwatched, diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/utils/MathUtils.h kodi-20.0+git20230115.1026-389e701cb9/xbmc/utils/MathUtils.h --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/utils/MathUtils.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/utils/MathUtils.h 2013-05-12 08:41:54.000000000 +0000 @@ -211,7 +211,11 @@ template::value, bool> = true> inline T RoundF(const T value, const T multiple) { - return value - std::fmod(value, multiple); + if (multiple == 0) + return value; + + return static_cast(std::round(static_cast(value) / static_cast(multiple)) * + static_cast(multiple)); } #if 0 diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/video/dialogs/GUIDialogAudioSettings.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/video/dialogs/GUIDialogAudioSettings.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/video/dialogs/GUIDialogAudioSettings.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/video/dialogs/GUIDialogAudioSettings.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -275,7 +275,12 @@ // audio delay setting if (SupportsAudioFeature(IPC_AUD_OFFSET)) { - std::shared_ptr settingAudioDelay = AddSlider(groupAudio, SETTING_AUDIO_DELAY, 297, SettingLevel::Basic, videoSettings.m_AudioDelay, 0, -CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange, 0.025f, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange, 297, usePopup); + std::shared_ptr settingAudioDelay = AddSlider( + groupAudio, SETTING_AUDIO_DELAY, 297, SettingLevel::Basic, videoSettings.m_AudioDelay, 0, + -CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange, + AUDIO_DELAY_STEP, + CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange, 297, + usePopup); std::static_pointer_cast(settingAudioDelay->GetControl())->SetFormatter(SettingFormatterDelay); } diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/video/PlayerController.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/video/PlayerController.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/video/PlayerController.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/video/PlayerController.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -179,7 +179,7 @@ { float videoAudioDelayRange = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange; ShowSlider(action.GetID(), 297, appPlayer->GetVideoSettings().m_AudioDelay, - -videoAudioDelayRange, 0.025f, videoAudioDelayRange, true); + -videoAudioDelayRange, AUDIO_DELAY_STEP, videoAudioDelayRange, true); return true; } @@ -187,13 +187,13 @@ { float videoAudioDelayRange = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange; CVideoSettings vs = appPlayer->GetVideoSettings(); - vs.m_AudioDelay -= 0.025f; + vs.m_AudioDelay -= AUDIO_DELAY_STEP; if (vs.m_AudioDelay < -videoAudioDelayRange) vs.m_AudioDelay = -videoAudioDelayRange; appPlayer->SetAVDelay(vs.m_AudioDelay); ShowSlider(action.GetID(), 297, appPlayer->GetVideoSettings().m_AudioDelay, - -videoAudioDelayRange, 0.025f, videoAudioDelayRange); + -videoAudioDelayRange, AUDIO_DELAY_STEP, videoAudioDelayRange); return true; } @@ -201,13 +201,13 @@ { float videoAudioDelayRange = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange; CVideoSettings vs = appPlayer->GetVideoSettings(); - vs.m_AudioDelay += 0.025f; + vs.m_AudioDelay += AUDIO_DELAY_STEP; if (vs.m_AudioDelay > videoAudioDelayRange) vs.m_AudioDelay = videoAudioDelayRange; appPlayer->SetAVDelay(vs.m_AudioDelay); ShowSlider(action.GetID(), 297, appPlayer->GetVideoSettings().m_AudioDelay, - -videoAudioDelayRange, 0.025f, videoAudioDelayRange); + -videoAudioDelayRange, AUDIO_DELAY_STEP, videoAudioDelayRange); return true; } @@ -558,7 +558,8 @@ m_sliderAction == ACTION_VOLAMP) slider->SetTextValue(CGUIDialogAudioSettings::FormatDecibel(slider->GetFloatValue())); else - slider->SetTextValue(CGUIDialogAudioSettings::FormatDelay(slider->GetFloatValue(), 0.025f)); + slider->SetTextValue( + CGUIDialogAudioSettings::FormatDelay(slider->GetFloatValue(), AUDIO_DELAY_STEP)); auto& components = CServiceBroker::GetAppComponents(); const auto appPlayer = components.GetComponent(); diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/video/windows/GUIWindowVideoBase.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/video/windows/GUIWindowVideoBase.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/video/windows/GUIWindowVideoBase.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/video/windows/GUIWindowVideoBase.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -1005,7 +1005,7 @@ } CLog::Log(LOGDEBUG, "{} {}", __FUNCTION__, CURL::GetRedacted(item.GetPath())); - item.SetProperty("playlist_type_hint", PLAYLIST::TYPE_VIDEO); + item.SetProperty("playlist_type_hint", m_guiState->GetPlaylist()); PlayMovie(&item, player); diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/windowing/wayland/Connection.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/windowing/wayland/Connection.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/windowing/wayland/Connection.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/windowing/wayland/Connection.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -8,17 +8,32 @@ #include "Connection.h" +#include "utils/log.h" + #include +#include using namespace KODI::WINDOWING::WAYLAND; CConnection::CConnection() { - m_display.reset(new wayland::display_t); + try + { + m_display = std::make_unique(); + } + catch (const std::exception& err) + { + CLog::Log(LOGERROR, "Wayland connection error: {}", err.what()); + } +} + +bool CConnection::HasDisplay() const +{ + return static_cast(m_display); } wayland::display_t& CConnection::GetDisplay() { assert(m_display); return *m_display; -} \ No newline at end of file +} diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/windowing/wayland/Connection.h kodi-20.0+git20230115.1026-389e701cb9/xbmc/windowing/wayland/Connection.h --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/windowing/wayland/Connection.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/windowing/wayland/Connection.h 2013-05-12 08:41:54.000000000 +0000 @@ -27,6 +27,7 @@ public: CConnection(); + bool HasDisplay() const; wayland::display_t& GetDisplay(); private: diff -Nru kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/windowing/wayland/WinSystemWayland.cpp kodi-20.0+git20230115.1026-389e701cb9/xbmc/windowing/wayland/WinSystemWayland.cpp --- kodi-20.0+git20230109.1027-bbdf5686e0/xbmc/windowing/wayland/WinSystemWayland.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-20.0+git20230115.1026-389e701cb9/xbmc/windowing/wayland/WinSystemWayland.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -158,11 +158,14 @@ wayland::set_log_handler([](const std::string& message) { CLog::Log(LOGWARNING, "wayland-client log message: {}", message); }); + CLog::LogF(LOGINFO, "Connecting to Wayland server"); + m_connection = std::make_unique(); + if (!m_connection->HasDisplay()) + return false; + VIDEOPLAYER::CProcessInfoWayland::Register(); RETRO::CRPProcessInfoWayland::Register(); - CLog::LogF(LOGINFO, "Connecting to Wayland server"); - m_connection.reset(new CConnection); m_registry.reset(new CRegistry{*m_connection}); m_registry->RequestSingleton(m_compositor, 1, 4);