diff options
36 files changed, 264 insertions, 95 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 28732719f2..0dc08a7caf 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -71,7 +71,7 @@ Used Operating system: - [ ] iOS - [ ] Linux - [ ] OSX - - [ ] Raspberri-Pi + - [ ] Raspberry-Pi - [ ] Windows - [ ] Windows UWP diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 28732719f2..0dc08a7caf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -71,7 +71,7 @@ Used Operating system: - [ ] iOS - [ ] Linux - [ ] OSX - - [ ] Raspberri-Pi + - [ ] Raspberry-Pi - [ ] Windows - [ ] Windows UWP diff --git a/addons/screensaver.xbmc.builtin.dim/addon.xml b/addons/screensaver.xbmc.builtin.dim/addon.xml index 365125ff97..8ded4db399 100644 --- a/addons/screensaver.xbmc.builtin.dim/addon.xml +++ b/addons/screensaver.xbmc.builtin.dim/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="screensaver.xbmc.builtin.dim" name="Dim" - version="1.0.50" + version="1.0.51" provider-name="Team Kodi"> <extension point="xbmc.ui.screensaver" library=""/> <extension point="xbmc.addon.metadata"> diff --git a/addons/skin.estuary/addon.xml b/addons/skin.estuary/addon.xml index 206afa8314..034c174dfc 100644 --- a/addons/skin.estuary/addon.xml +++ b/addons/skin.estuary/addon.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<addon id="skin.estuary" version="2.0.18" name="Estuary" provider-name="phil65, Ichabod Fletchman"> +<addon id="skin.estuary" version="2.0.19" name="Estuary" provider-name="phil65, Ichabod Fletchman"> <requires> <import addon="xbmc.gui" version="5.14.0"/> </requires> diff --git a/addons/skin.estuary/language/resource.language.cs_cz/strings.po b/addons/skin.estuary/language/resource.language.cs_cz/strings.po index 31d32581f7..607cb16ed4 100644 --- a/addons/skin.estuary/language/resource.language.cs_cz/strings.po +++ b/addons/skin.estuary/language/resource.language.cs_cz/strings.po @@ -230,7 +230,7 @@ msgstr "Položky hlavní nabídky" msgctxt "#31062" msgid "Choose weather fanart pack" -msgstr "Zvolte balíček fanatrů počasí" +msgstr "Zvolte balíček fanartů počasí" msgctxt "#31063" msgid "Sections" @@ -442,7 +442,7 @@ msgstr "Nastavení související s hlavní nabídkou: Konfigurujte domovskou obr msgctxt "#31131" msgid "Choose skin fanart pack" -msgstr "Zvolte balíček fanatrů vzhledu" +msgstr "Zvolte balíček fanartů vzhledu" msgctxt "#31132" msgid "Select Program" @@ -502,7 +502,7 @@ msgstr "Kategorie" msgctxt "#31149" msgid "Select genre fanart pack" -msgstr "Zvolte balíček fanatrů žánru" +msgstr "Zvolte balíček fanartů žánru" msgctxt "#31150" msgid "Repository" diff --git a/addons/skin.estuary/language/resource.language.ro_ro/strings.po b/addons/skin.estuary/language/resource.language.ro_ro/strings.po index 4391cd7ba7..ba217ea0dc 100644 --- a/addons/skin.estuary/language/resource.language.ro_ro/strings.po +++ b/addons/skin.estuary/language/resource.language.ro_ro/strings.po @@ -556,6 +556,14 @@ msgctxt "#31163" msgid "Show Fanart background" msgstr "Arată decorul media ca fundal" +msgctxt "#31164" +msgid "Choose kind of profile identification" +msgstr "Alegeți tipul de identificare profil" + msgctxt "#31165" msgid "Profile name" msgstr "Nume profil" + +msgctxt "#31166" +msgid "Profile avatar" +msgstr "Avatar profil" diff --git a/addons/skin.estuary/xml/DialogSeekBar.xml b/addons/skin.estuary/xml/DialogSeekBar.xml index 5588529fd3..1350ebf3ac 100644 --- a/addons/skin.estuary/xml/DialogSeekBar.xml +++ b/addons/skin.estuary/xml/DialogSeekBar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <window> - <visible>Player.Seeking | Player.DisplayAfterSeek | [Player.Paused + !Player.Caching] | Player.Forwarding | Player.Rewinding | Player.ShowInfo | Window.IsActive(videoosd) | Window.IsActive(musicosd) | Window.IsActive(playerprocessinfo) | !String.IsEmpty(Player.SeekNumeric) | !String.IsEmpty(PVR.ChannelNumberInput)</visible> + <visible>Player.Seeking | Player.DisplayAfterSeek | [Player.Paused + !Player.Caching] | Player.Forwarding | Player.Rewinding | Player.ShowInfo | Player.ShowTime | Window.IsActive(videoosd) | Window.IsActive(musicosd) | Window.IsActive(playerprocessinfo) | !String.IsEmpty(Player.SeekNumeric) | !String.IsEmpty(PVR.ChannelNumberInput)</visible> <visible>![Window.IsActive(sliderdialog) | Window.IsActive(pvrosdchannels)]</visible> <visible>Window.IsActive(fullscreenvideo) | Window.IsActive(visualisation)</visible> <include>Animation_BottomSlide</include> diff --git a/tools/android/packaging/xbmc/res/layout/activity_main.xml b/tools/android/packaging/xbmc/res/layout/activity_main.xml index f8f9865de0..18fcfc3e6e 100644 --- a/tools/android/packaging/xbmc/res/layout/activity_main.xml +++ b/tools/android/packaging/xbmc/res/layout/activity_main.xml @@ -2,8 +2,6 @@ android:id="@+id/VideoLayout" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@android:color/black" > - > - + android:background="@android:color/transparent"> </RelativeLayout> diff --git a/tools/android/packaging/xbmc/src/Main.java.in b/tools/android/packaging/xbmc/src/Main.java.in index d5e6c88381..cc0cd68722 100644 --- a/tools/android/packaging/xbmc/src/Main.java.in +++ b/tools/android/packaging/xbmc/src/Main.java.in @@ -197,6 +197,7 @@ public class Main extends NativeActivity implements Choreographer.FrameCallback public void onStart() { super.onStart(); + mDecorView.setBackgroundColor(Color.TRANSPARENT); Choreographer.getInstance().removeFrameCallback(this); Choreographer.getInstance().postFrameCallback(this); diff --git a/tools/android/packaging/xbmc/src/XBMCMainView.java.in b/tools/android/packaging/xbmc/src/XBMCMainView.java.in index 6ca1f7bb20..43d6e976ed 100644 --- a/tools/android/packaging/xbmc/src/XBMCMainView.java.in +++ b/tools/android/packaging/xbmc/src/XBMCMainView.java.in @@ -27,7 +27,7 @@ public class XBMCMainView extends SurfaceView implements SurfaceHolder.Callback super(context); setZOrderOnTop(true); getHolder().addCallback(this); - getHolder().setFormat(PixelFormat.TRANSLUCENT); + getHolder().setFormat(PixelFormat.TRANSPARENT); Log.d(TAG, "Created"); } @@ -37,7 +37,7 @@ public class XBMCMainView extends SurfaceView implements SurfaceHolder.Callback super(context, attrs, defStyle); setZOrderOnTop(true); getHolder().addCallback(this); - getHolder().setFormat(PixelFormat.TRANSLUCENT); + getHolder().setFormat(PixelFormat.TRANSPARENT); Log.d(TAG, "Created"); } diff --git a/tools/android/packaging/xbmc/src/XBMCVideoView.java.in b/tools/android/packaging/xbmc/src/XBMCVideoView.java.in index b80c98420f..c3fc5fcdea 100644 --- a/tools/android/packaging/xbmc/src/XBMCVideoView.java.in +++ b/tools/android/packaging/xbmc/src/XBMCVideoView.java.in @@ -59,7 +59,7 @@ public class XBMCVideoView extends SurfaceView implements super(context); setZOrderMediaOverlay(true); getHolder().addCallback(this); - getHolder().setFormat(PixelFormat.TRANSLUCENT); + getHolder().setFormat(PixelFormat.TRANSPARENT); mVideoLayout = (RelativeLayout) Main.MainActivity.findViewById(R.id.VideoLayout); } diff --git a/tools/depends/target/libshairplay/0001-configure-fix-dns-sd-check.patch b/tools/depends/target/libshairplay/0001-configure-fix-dns-sd-check.patch new file mode 100644 index 0000000000..5aa5c5300a --- /dev/null +++ b/tools/depends/target/libshairplay/0001-configure-fix-dns-sd-check.patch @@ -0,0 +1,26 @@ +From 031c3d802e51bbc233b1044f812402a66bfcf237 Mon Sep 17 00:00:00 2001 +From: Memphiz <memphis@machzwo.de> +Date: Fri, 21 Dec 2018 20:39:11 +0100 +Subject: [PATCH] [configure] - only check for dns_sd.h in case libdl was not + found + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 5a4b8ad..682d74b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -19,7 +19,7 @@ LT_LIB_DLLOAD + + # Checks for header files. + AC_HEADER_STDC +-if test yes = "$libltdl_cv_func_dlopen" || test yes = "$libltdl_cv_lib_dl_dlopen" ++if test no = "$libltdl_cv_func_dlopen" && test no = "$libltdl_cv_lib_dl_dlopen" + then + AC_CHECK_HEADERS([dns_sd.h], [], + [AC_MSG_ERROR([Could not find dns_sd.h header, please install libavahi-compat-libdnssd-dev or equivalent.])]) +-- +2.17.1 + diff --git a/tools/depends/target/libshairplay/Makefile b/tools/depends/target/libshairplay/Makefile index ecfffc5302..30d12164bf 100644 --- a/tools/depends/target/libshairplay/Makefile +++ b/tools/depends/target/libshairplay/Makefile @@ -1,9 +1,9 @@ include ../../Makefile.include -DEPS= ../../Makefile.include Makefile +DEPS= ../../Makefile.include Makefile 0001-configure-fix-dns-sd-check.patch # lib name, version LIBNAME=shairplay -VERSION=498bc5b +VERSION=096b61a SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.bz2 @@ -21,6 +21,7 @@ $(TARBALLS_LOCATION)/$(ARCHIVE): $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) rm -rf $(PLATFORM); mkdir -p $(PLATFORM) cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../0001-configure-fix-dns-sd-check.patch cd $(PLATFORM); $(AUTORECONF) -vif cd $(PLATFORM); $(CONFIGURE) diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index cef49b8641..dd092f512d 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -1599,6 +1599,7 @@ void CFileItem::UpdateInfo(const CFileItem &item, bool replaceLabels /*=true*/) *GetGameInfoTag() = *item.GetGameInfoTag(); SetInvalid(); } + SetDynPath(item.GetDynPath()); if (replaceLabels && !item.GetLabel().empty()) SetLabel(item.GetLabel()); if (replaceLabels && !item.GetLabel2().empty()) diff --git a/xbmc/GUIUserMessages.h b/xbmc/GUIUserMessages.h index 3d1e8ee7c5..a3335eaff9 100644 --- a/xbmc/GUIUserMessages.h +++ b/xbmc/GUIUserMessages.h @@ -103,6 +103,10 @@ // Message sent to tell the GUI to update a single item #define GUI_MSG_UPDATE_ITEM GUI_MSG_USER + 29 +// Flags for GUI_MSG_UPDATE_ITEM message +constexpr int GUI_MSG_FLAG_UPDATE_LIST = 0x00000001; +constexpr int GUI_MSG_FLAG_FORCE_UPDATE = 0x00000002; + // Message sent to tell the GUI to change view mode #define GUI_MSG_CHANGE_VIEW_MODE GUI_MSG_USER + 30 diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp index 200b53c100..eb84f45af8 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp @@ -4619,7 +4619,7 @@ int CVideoPlayer::AddSubtitleFile(const std::string& filename, const std::string return -1; m_SelectionStreams.Update(NULL, v.get(), vobsubfile); - ExternalStreamInfo info = CUtil::GetExternalStreamDetailsFromFilename(m_item.GetPath(), vobsubfile); + ExternalStreamInfo info = CUtil::GetExternalStreamDetailsFromFilename(m_item.GetDynPath(), vobsubfile); for (auto sub : v->GetStreams()) { @@ -4658,7 +4658,7 @@ int CVideoPlayer::AddSubtitleFile(const std::string& filename, const std::string s.type = STREAM_SUBTITLE; s.id = 0; s.filename = filename; - ExternalStreamInfo info = CUtil::GetExternalStreamDetailsFromFilename(m_item.GetPath(), filename); + ExternalStreamInfo info = CUtil::GetExternalStreamDetailsFromFilename(m_item.GetDynPath(), filename); s.name = info.name; s.language = info.language; if (static_cast<StreamFlags>(info.flag) != StreamFlags::FLAG_NONE) diff --git a/xbmc/cores/paplayer/PAPlayer.cpp b/xbmc/cores/paplayer/PAPlayer.cpp index 7af07c2af6..8f598394fb 100644 --- a/xbmc/cores/paplayer/PAPlayer.cpp +++ b/xbmc/cores/paplayer/PAPlayer.cpp @@ -562,14 +562,18 @@ void PAPlayer::Process() if (m_newForcedPlayerTime != -1) { - SetTimeInternal(m_newForcedPlayerTime); - m_newForcedPlayerTime = -1; + if (SetTimeInternal(m_newForcedPlayerTime)) + { + m_newForcedPlayerTime = -1; + } } if (m_newForcedTotalTime != -1) { - SetTotalTimeInternal(m_newForcedTotalTime); - m_newForcedTotalTime = -1; + if (SetTotalTimeInternal(m_newForcedTotalTime)) + { + m_newForcedTotalTime = -1; + } } GetTimeInternal(); //update for GUI @@ -956,26 +960,32 @@ int64_t PAPlayer::GetTimeInternal() return (int64_t)time; } -void PAPlayer::SetTotalTimeInternal(int64_t time) +bool PAPlayer::SetTotalTimeInternal(int64_t time) { CSingleLock lock(m_streamsLock); if (!m_currentStream) - return; + { + return false; + } m_currentStream->m_decoder.SetTotalTime(time); UpdateGUIData(m_currentStream); + + return true; } -void PAPlayer::SetTimeInternal(int64_t time) +bool PAPlayer::SetTimeInternal(int64_t time) { CSingleLock lock(m_streamsLock); if (!m_currentStream) - return; + return false; m_currentStream->m_framesSent = time / 1000 * m_currentStream->m_audioFormat.m_sampleRate; if (m_currentStream->m_stream) m_currentStream->m_framesSent += m_currentStream->m_stream->GetDelay() * m_currentStream->m_audioFormat.m_sampleRate; + + return true; } void PAPlayer::SetTime(int64_t time) diff --git a/xbmc/cores/paplayer/PAPlayer.h b/xbmc/cores/paplayer/PAPlayer.h index ccebbc5470..8aed4f8a74 100644 --- a/xbmc/cores/paplayer/PAPlayer.h +++ b/xbmc/cores/paplayer/PAPlayer.h @@ -145,8 +145,8 @@ private: void UpdateStreamInfoPlayNextAtFrame(StreamInfo *si, unsigned int crossFadingTime); void UpdateGUIData(StreamInfo *si); int64_t GetTimeInternal(); - void SetTimeInternal(int64_t time); - void SetTotalTimeInternal(int64_t time); + bool SetTimeInternal(int64_t time); + bool SetTotalTimeInternal(int64_t time); void CloseFileCB(StreamInfo &si); void AdvancePlaylistOnError(CFileItem &fileItem); }; diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index f6334bd635..fcc3a15e1f 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -59,7 +59,8 @@ void CPluginDirectory::CScriptObserver::Process() void CPluginDirectory::CScriptObserver::Abort() { - m_bStop = true; + // will wait until thread exits + StopThread(); } CPluginDirectory::CPluginDirectory() diff --git a/xbmc/interfaces/legacy/ModuleXbmcplugin.h b/xbmc/interfaces/legacy/ModuleXbmcplugin.h index d8b6f13129..e7386feb6d 100644 --- a/xbmc/interfaces/legacy/ModuleXbmcplugin.h +++ b/xbmc/interfaces/legacy/ModuleXbmcplugin.h @@ -325,16 +325,17 @@ namespace XBMCAddon /// @param content string - content type (eg. movies) /// /// @par Available content strings - /// | | | | | - /// |:--------:|:--------:|:--------:|:--------:| - /// | files | songs | artists | albums - /// | movies | tvshows | episodes | musicvideos - /// | videos | images | games | + /// | | | | | + /// |:--------:|:--------:|:--------:|:-----------:| + /// | files | songs | artists | albums | + /// | movies | tvshows | episodes | musicvideos | + /// | videos | images | games | -- | /// /// @remark Use **videos** for all videos which do not apply to the /// more specific mentioned ones like "movies", "episodes" etc. /// A good example is youtube. /// + /// /// ------------------------------------------------------------------------ /// @python_v18 Added new **games** content /// diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index 96035f7542..5e48e68f9b 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -10708,11 +10708,16 @@ void CMusicDatabase::UpdateFileDateAdded(int songId, const std::string& strFileN bool CMusicDatabase::AddAudioBook(const CFileItem& item) { - std::string strSQL = PrepareSQL("INSERT INTO audiobook (idBook,strBook,strAuthor,bookmark,file,dateAdded) VALUES (NULL,'%s','%s',%i,'%s','%s')", - item.GetMusicInfoTag()->GetAlbum().c_str(), - item.GetMusicInfoTag()->GetArtist()[0].c_str(), 0, - item.GetPath().c_str(), - CDateTime::GetCurrentDateTime().GetAsDBDateTime().c_str()); + auto const& artists = item.GetMusicInfoTag()->GetArtist(); + std::string strSQL = PrepareSQL( + "INSERT INTO audiobook (idBook,strBook,strAuthor,bookmark,file,dateAdded) " + "VALUES (NULL,'%s','%s',%i,'%s','%s')", + item.GetMusicInfoTag()->GetAlbum().c_str(), + artists.empty() ? "" : artists[0].c_str(), + 0, + item.GetPath().c_str(), + CDateTime::GetCurrentDateTime().GetAsDBDateTime().c_str() + ); return ExecuteQuery(strSQL); } diff --git a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp index 9448324714..72f52fe658 100644 --- a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp @@ -398,11 +398,14 @@ bool CGUIDialogMusicInfo::OnMessage(CGUIMessage& message) CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControl); CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); int iItem = msg.GetParam1(); - if (iItem < 0 || iItem >= m_albumSongs->Size()) - break; - OnAlbumInfo(m_albumSongs->Get(iItem)->GetMusicInfoTag()->GetDatabaseId()); - - return true; + int id = -1; + if (iItem >= 0 && iItem < m_albumSongs->Size()) + id = m_albumSongs->Get(iItem)->GetMusicInfoTag()->GetDatabaseId(); + if (id > 0) + { + OnAlbumInfo(id); + return true; + } } } } @@ -1010,10 +1013,12 @@ void CGUIDialogMusicInfo::ShowFor(CFileItem* pItem) // Maybe only path is set, then set MusicInfoTag CQueryParams params; CDirectoryNode::GetDatabaseInfo(pItem->GetPath(), params); - if (params.GetAlbumId() == -1) + if (params.GetArtistId() > 0) pItem->GetMusicInfoTag()->SetDatabaseId(params.GetArtistId(), MediaTypeArtist); - else + else if (params.GetAlbumId() > 0) pItem->GetMusicInfoTag()->SetDatabaseId(params.GetAlbumId(), MediaTypeAlbum); + else + return; // nothing to do } CGUIDialogMusicInfo *pDlgMusicInfo = CServiceBroker::GetGUI()->GetWindowManager(). GetWindow<CGUIDialogMusicInfo>(WINDOW_DIALOG_MUSIC_INFO); diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index cb27b0c6a3..d0b7650c16 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -62,6 +62,8 @@ #include "platform/linux/XTimeUtils.h" #endif +#include <algorithm> + using namespace XFILE; using namespace MUSICDATABASEDIRECTORY; using namespace PLAYLIST; @@ -690,12 +692,20 @@ bool CGUIWindowMusicBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button) Update(item->GetPath()); int bookmark; m_musicdatabase.GetResumeBookmarkForAudioBook(item->GetPath(), bookmark); - int i=0; - while (i < m_vecItems->Size() && bookmark > m_vecItems->Get(i)->m_lEndOffset) - ++i; - CFileItem resItem(*m_vecItems->Get(i)); - resItem.SetProperty("StartPercent", ((double)bookmark-resItem.m_lStartOffset)/(resItem.m_lEndOffset-resItem.m_lStartOffset)*100); - g_application.PlayFile(resItem, "", false); + + auto itemIt = std::find_if( + m_vecItems->cbegin(), + m_vecItems->cend(), + [&](const CFileItemPtr& item) { return bookmark <= item->m_lEndOffset; } + ); + if (itemIt != m_vecItems->cend()) + { + CFileItem resItem(**itemIt); + resItem.SetProperty("StartPercent", + 100.0 * (bookmark - resItem.m_lStartOffset) / (resItem.m_lEndOffset - resItem.m_lStartOffset) + ); + g_application.PlayFile(resItem, "", false); + } } default: diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp index ef8bd4136c..38edc521eb 100644 --- a/xbmc/network/AirTunesServer.cpp +++ b/xbmc/network/AirTunesServer.cpp @@ -72,6 +72,10 @@ std::list<CAction> CAirTunesServer::m_actionQueue; CEvent CAirTunesServer::m_processActions; int CAirTunesServer::m_sampleRate = 44100; +unsigned int CAirTunesServer::m_cachedStartTime = 0; +unsigned int CAirTunesServer::m_cachedEndTime = 0; +unsigned int CAirTunesServer::m_cachedCurrentTime = 0; + //parse daap metadata - thx to project MythTV std::map<std::string, std::string> decodeDMAP(const char *buffer, unsigned int size) @@ -398,15 +402,39 @@ void CAirTunesServer::AudioOutputFunctions::audio_remote_control_id(void *cls, c } } -void CAirTunesServer::AudioOutputFunctions::audio_set_progress(void *cls, void *session, unsigned int start, unsigned int curr, unsigned int end) +void CAirTunesServer::InformPlayerAboutPlayTimes() { - unsigned int duration = end - start; - unsigned int position = curr - start; - duration /= m_sampleRate; - position /= m_sampleRate; + if (m_cachedEndTime > 0) + { + unsigned int duration = m_cachedEndTime - m_cachedStartTime; + unsigned int position = m_cachedCurrentTime - m_cachedStartTime; + duration /= m_sampleRate; + position /= m_sampleRate; + + if (g_application.GetAppPlayer().IsPlaying()) + { + g_application.GetAppPlayer().SetTime(position * 1000); + g_application.GetAppPlayer().SetTotalTime(duration * 1000); + + // reset play times now that we have informed the player + m_cachedEndTime = 0; + m_cachedCurrentTime = 0; + m_cachedStartTime = 0; + + } + } +} - g_application.GetAppPlayer().SetTime(position * 1000); - g_application.GetAppPlayer().SetTotalTime(duration * 1000); +void CAirTunesServer::AudioOutputFunctions::audio_set_progress(void *cls, void *session, unsigned int start, unsigned int curr, unsigned int end) +{ + m_cachedStartTime = start; + m_cachedCurrentTime = curr; + m_cachedEndTime = end; + if (g_application.GetAppPlayer().IsPlaying()) + { + // player is there - directly inform him about play times + InformPlayerAboutPlayTimes(); + } } void CAirTunesServer::SetupRemoteControl() @@ -462,6 +490,9 @@ void CAirTunesServer::AudioOutputFunctions::audio_process(void *cls, void *sess { XFILE::CPipeFile *pipe=(XFILE::CPipeFile *)cls; pipe->Write(buffer, buflen); + + // in case there are some play times cached that are not yet sent to the player - do it here + InformPlayerAboutPlayTimes(); } void CAirTunesServer::AudioOutputFunctions::audio_destroy(void *cls, void *session) diff --git a/xbmc/network/AirTunesServer.h b/xbmc/network/AirTunesServer.h index 5c5b8e7b0b..aafe64150b 100644 --- a/xbmc/network/AirTunesServer.h +++ b/xbmc/network/AirTunesServer.h @@ -59,6 +59,7 @@ private: static void RefreshCoverArt(const char *outputFilename = NULL); static void RefreshMetadata(); static void ResetMetadata(); + static void InformPlayerAboutPlayTimes(); int m_port; static DllLibShairplay *m_pLibShairplay;//the lib @@ -77,6 +78,9 @@ private: static std::list<CAction> m_actionQueue; static CEvent m_processActions; static int m_sampleRate; + static unsigned int m_cachedStartTime; + static unsigned int m_cachedEndTime; + static unsigned int m_cachedCurrentTime; class AudioOutputFunctions { diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp index 39712ccded..d31adec553 100644 --- a/xbmc/network/upnp/UPnPServer.cpp +++ b/xbmc/network/upnp/UPnPServer.cpp @@ -1113,7 +1113,7 @@ CUPnPServer::OnUpdateObject(PLT_ActionReference& action, CUtil::DeleteMusicDatabaseDirectoryCache(); CFileItemPtr msgItem(new CFileItem(updated)); - CGUIMessage message(GUI_MSG_NOTIFY_ALL, CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(), 0, GUI_MSG_UPDATE_ITEM, 1, msgItem); + CGUIMessage message(GUI_MSG_NOTIFY_ALL, CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(), 0, GUI_MSG_UPDATE_ITEM, GUI_MSG_FLAG_UPDATE_LIST, msgItem); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message); } diff --git a/xbmc/platform/linux/network/ZeroconfAvahi.cpp b/xbmc/platform/linux/network/ZeroconfAvahi.cpp index c3ba719f5e..8e28e54ea6 100644 --- a/xbmc/platform/linux/network/ZeroconfAvahi.cpp +++ b/xbmc/platform/linux/network/ZeroconfAvahi.cpp @@ -355,10 +355,15 @@ bool CZeroconfAvahi::createClient() { avahi_client_free(mp_client); } + + int error = 0; mp_client = avahi_client_new(avahi_threaded_poll_get(mp_poll), - AVAHI_CLIENT_NO_FAIL, &clientCallback,this,0); + AVAHI_CLIENT_NO_FAIL, &clientCallback,this,&error); if (!mp_client) + { + CLog::Log(LOGERROR, "CZeroconfAvahi::createClient() failed with %d", error); return false; + } return true; } diff --git a/xbmc/pvr/PVRGUITimesInfo.cpp b/xbmc/pvr/PVRGUITimesInfo.cpp index 402b390237..365458164c 100644 --- a/xbmc/pvr/PVRGUITimesInfo.cpp +++ b/xbmc/pvr/PVRGUITimesInfo.cpp @@ -43,6 +43,7 @@ void CPVRGUITimesInfo::Reset() m_iTimeshiftProgressDuration = 0; m_playingEpgTag.reset(); + m_playingChannel.reset(); } void CPVRGUITimesInfo::UpdatePlayingTag() @@ -52,7 +53,7 @@ void CPVRGUITimesInfo::UpdatePlayingTag() if (currentChannel || currentTag) { - if (!currentTag) + if (currentChannel && !currentTag) currentTag = currentChannel->GetEPGNow(); CSingleLock lock(m_critSection); @@ -104,9 +105,18 @@ void CPVRGUITimesInfo::UpdateTimeshiftData() int64_t iPlayTime, iMinTime, iMaxTime; CServiceBroker::GetDataCacheCore().GetPlayTimes(iStartTime, iPlayTime, iMinTime, iMaxTime); bool bPlaying = CServiceBroker::GetDataCacheCore().GetSpeed() == 1.0; + const CPVRChannelPtr playingChannel = CServiceBroker::GetPVRManager().GetPlayingChannel(); CSingleLock lock(m_critSection); + if (playingChannel != m_playingChannel) + { + // playing channel changed. we need to reset offset and playtime. + m_iTimeshiftOffset = 0; + m_iTimeshiftPlayTime = 0; + m_playingChannel = playingChannel; + } + if (!iStartTime) { if (m_iStartTime == 0) diff --git a/xbmc/pvr/PVRGUITimesInfo.h b/xbmc/pvr/PVRGUITimesInfo.h index 479bdce5f9..f61d70227d 100644 --- a/xbmc/pvr/PVRGUITimesInfo.h +++ b/xbmc/pvr/PVRGUITimesInfo.h @@ -67,6 +67,7 @@ namespace PVR mutable CCriticalSection m_critSection; CPVREpgInfoTagPtr m_playingEpgTag; + CPVRChannelPtr m_playingChannel; time_t m_iStartTime; unsigned int m_iDuration; diff --git a/xbmc/video/Teletext.cpp b/xbmc/video/Teletext.cpp index 4055df6198..fd40314eb3 100644 --- a/xbmc/video/Teletext.cpp +++ b/xbmc/video/Teletext.cpp @@ -105,8 +105,8 @@ TextPageAttr_t Text_AtrTable[] = { TXT_ColorWhite , TXT_ColorBlack , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_WB */ { TXT_ColorWhite , TXT_ColorBlack , C_G0P, 0, 0, 1 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_PassiveDefault */ { TXT_ColorWhite , TXT_ColorRed , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L250 */ - { TXT_ColorBlack , TXT_ColorYellow, C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L252 */ { TXT_ColorBlack , TXT_ColorGreen , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L251 */ + { TXT_ColorBlack , TXT_ColorYellow, C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L252 */ { TXT_ColorWhite , TXT_ColorBlue , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L253 */ { TXT_ColorMagenta, TXT_ColorBlack , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU0 */ { TXT_ColorGreen , TXT_ColorBlack , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU1 */ diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index 8c5a6c60a3..a924a263c0 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -394,7 +394,7 @@ void CVideoDatabase::CreateViews() " episode.idShow=tvshow.idShow" " LEFT JOIN files ON" " files.idFile=episode.idFile " - " GROUP BY tvshow.idShow"); + "GROUP BY tvshow.idShow"); m_pDS->exec(tvshowcounts); CLog::Log(LOGINFO, "create tvshow_view"); @@ -410,7 +410,9 @@ void CVideoDatabase::CreateViews() " uniqueid.value AS uniqueid_value, " " uniqueid.type AS uniqueid_type " "FROM tvshow" - " LEFT JOIN tvshowlinkpath ON" + " LEFT JOIN (SELECT idShow, MAX(idPath) as idPath " + " FROM tvshowlinkpath " + " GROUP BY tvshowlinkpath.idShow) AS tvshowlinkpath ON " " tvshowlinkpath.idShow=tvshow.idShow" " LEFT JOIN path ON" " path.idPath=tvshowlinkpath.idPath" @@ -419,13 +421,17 @@ void CVideoDatabase::CreateViews() " LEFT JOIN rating ON" " rating.rating_id=tvshow.c%02d " " LEFT JOIN uniqueid ON" - " uniqueid.uniqueid_id=tvshow.c%02d " - "GROUP BY tvshow.idShow", + " uniqueid.uniqueid_id=tvshow.c%02d ", VIDEODB_ID_TV_RATING_ID, VIDEODB_ID_TV_IDENT_ID); m_pDS->exec(tvshowview); + CLog::Log(LOGINFO, "create season_view"); std::string seasonview = PrepareSQL("CREATE VIEW season_view AS SELECT " - " seasons.*, " + " seasons.idSeason AS idSeason," + " seasons.idShow AS idShow," + " seasons.season AS season," + " seasons.name AS name," + " seasons.userrating AS userrating," " tvshow_view.strPath AS strPath," " tvshow_view.c%02d AS showTitle," " tvshow_view.c%02d AS plot," @@ -443,10 +449,23 @@ void CVideoDatabase::CreateViews() " episode.idShow = seasons.idShow AND episode.c%02d = seasons.season" " JOIN files ON" " files.idFile = episode.idFile " - "GROUP BY seasons.idSeason", + "GROUP BY seasons.idSeason," + " seasons.idShow," + " seasons.season," + " seasons.name," + " seasons.userrating," + " tvshow_view.strPath," + " tvshow_view.c%02d," + " tvshow_view.c%02d," + " tvshow_view.c%02d," + " tvshow_view.c%02d," + " tvshow_view.c%02d," + " tvshow_view.c%02d ", VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_PLOT, VIDEODB_ID_TV_PREMIERED, VIDEODB_ID_TV_GENRE, VIDEODB_ID_TV_STUDIOS, VIDEODB_ID_TV_MPAA, - VIDEODB_ID_EPISODE_AIRED, VIDEODB_ID_EPISODE_SEASON); + VIDEODB_ID_EPISODE_AIRED, VIDEODB_ID_EPISODE_SEASON, + VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_PLOT, VIDEODB_ID_TV_PREMIERED, + VIDEODB_ID_TV_GENRE, VIDEODB_ID_TV_STUDIOS, VIDEODB_ID_TV_MPAA); m_pDS->exec(seasonview); CLog::Log(LOGINFO, "create musicvideo_view"); @@ -4882,6 +4901,8 @@ public: void CVideoDatabase::UpdateTables(int iVersion) { + // Important: DO NOT use CREATE TABLE [...] AS SELECT [...] - it does not work on MySQL with GTID consistency enforced + if (iVersion < 76) { m_pDS->exec("ALTER TABLE settings ADD StereoMode integer"); @@ -5363,9 +5384,15 @@ void CVideoDatabase::UpdateTables(int iVersion) if (iVersion < 109) { - m_pDS->exec("CREATE TABLE settingsnew AS SELECT idFile, Deinterlace, ViewMode, ZoomAmount, PixelRatio, VerticalShift, AudioStream, SubtitleStream, SubtitleDelay, SubtitlesOn, Brightness, Contrast, Gamma, VolumeAmplification, AudioDelay, ResumeTime, Sharpness, NoiseReduction, NonLinStretch, PostProcess, ScalingMethod, DeinterlaceMode, StereoMode, StereoInvert, VideoStream FROM settings"); - m_pDS->exec("DROP TABLE settings"); - m_pDS->exec("ALTER TABLE settingsnew RENAME TO settings"); + m_pDS->exec("ALTER TABLE settings RENAME TO settingsold"); + m_pDS->exec("CREATE TABLE settings ( idFile integer, Deinterlace bool," + "ViewMode integer,ZoomAmount float, PixelRatio float, VerticalShift float, AudioStream integer, SubtitleStream integer," + "SubtitleDelay float, SubtitlesOn bool, Brightness float, Contrast float, Gamma float," + "VolumeAmplification float, AudioDelay float, ResumeTime integer," + "Sharpness float, NoiseReduction float, NonLinStretch bool, PostProcess bool," + "ScalingMethod integer, DeinterlaceMode integer, StereoMode integer, StereoInvert bool, VideoStream integer)"); + m_pDS->exec("INSERT INTO settings SELECT idFile, Deinterlace, ViewMode, ZoomAmount, PixelRatio, VerticalShift, AudioStream, SubtitleStream, SubtitleDelay, SubtitlesOn, Brightness, Contrast, Gamma, VolumeAmplification, AudioDelay, ResumeTime, Sharpness, NoiseReduction, NonLinStretch, PostProcess, ScalingMethod, DeinterlaceMode, StereoMode, StereoInvert, VideoStream FROM settingsold"); + m_pDS->exec("DROP TABLE settingsold"); } if (iVersion < 110) @@ -5428,7 +5455,7 @@ void CVideoDatabase::UpdateTables(int iVersion) int CVideoDatabase::GetSchemaVersion() const { - return 113; + return 115; } bool CVideoDatabase::LookupByFolders(const std::string &path, bool shows) @@ -7013,6 +7040,7 @@ bool CVideoDatabase::GetMoviesByWhere(const std::string& strBaseDir, const Filte std::string path = StringUtils::Format("%i", movie.m_iDbId); itemUrl.AppendPath(path); pItem->SetPath(itemUrl.ToString()); + pItem->SetDynPath(movie.m_strFileNameAndPath); pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED,movie.GetPlayCount() > 0); items.Add(pItem); @@ -7237,12 +7265,12 @@ bool CVideoDatabase::GetEpisodesByWhere(const std::string& strBaseDir, const Fil unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger(); const dbiplus::sql_record* const record = data.at(targetRow); - CVideoInfoTag movie = GetDetailsForEpisode(record, getDetails); + CVideoInfoTag episode = GetDetailsForEpisode(record, getDetails); if (m_profileManager.GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE || g_passwordManager.bMasterUser || - g_passwordManager.IsDatabasePathUnlocked(movie.m_strPath, *CMediaSourceSettings::GetInstance().GetSources("video"))) + g_passwordManager.IsDatabasePathUnlocked(episode.m_strPath, *CMediaSourceSettings::GetInstance().GetSources("video"))) { - CFileItemPtr pItem(new CFileItem(movie)); + CFileItemPtr pItem(new CFileItem(episode)); formatter.FormatLabel(pItem.get()); int idEpisode = record->at(0).get_asInt(); @@ -7250,14 +7278,15 @@ bool CVideoDatabase::GetEpisodesByWhere(const std::string& strBaseDir, const Fil CVideoDbUrl itemUrl = videoUrl; std::string path; if (appendFullShowPath && videoUrl.GetItemType() != "episodes") - path = StringUtils::Format("%i/%i/%i", record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt(), movie.m_iSeason, idEpisode); + path = StringUtils::Format("%i/%i/%i", record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt(), episode.m_iSeason, idEpisode); else path = StringUtils::Format("%i", idEpisode); itemUrl.AppendPath(path); pItem->SetPath(itemUrl.ToString()); + pItem->SetDynPath(episode.m_strFileNameAndPath); - pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, movie.GetPlayCount() > 0); - pItem->m_dateTime = movie.m_firstAired; + pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, episode.GetPlayCount() > 0); + pItem->m_dateTime = episode.m_firstAired; items.Add(pItem); } } diff --git a/xbmc/view/ViewDatabase.cpp b/xbmc/view/ViewDatabase.cpp index ae669d94db..c4ee44fb5f 100644 --- a/xbmc/view/ViewDatabase.cpp +++ b/xbmc/view/ViewDatabase.cpp @@ -84,8 +84,7 @@ void CViewDatabase::UpdateTables(int version) if (version < 6) { // convert the "path" table - m_pDS->exec("CREATE TABLE tmp_view AS SELECT * FROM view"); - m_pDS->exec("DROP TABLE view"); + m_pDS->exec("ALTER TABLE view RENAME TO tmp_view"); m_pDS->exec("CREATE TABLE view (" "idView integer primary key," diff --git a/xbmc/windowing/Resolution.cpp b/xbmc/windowing/Resolution.cpp index d17caf0f6a..53427f965e 100644 --- a/xbmc/windowing/Resolution.cpp +++ b/xbmc/windowing/Resolution.cpp @@ -88,8 +88,15 @@ void CResolutionUtils::FindResolutionFromWhitelist(float fps, int width, int hei if (info.iScreenHeight >= curr.iScreenHeight && info.iScreenWidth >= curr.iScreenWidth && (info.dwFlags & D3DPRESENTFLAG_MODEMASK) == (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)) { - resString = CDisplaySettings::GetInstance().GetStringFromRes(c); - indexList.push_back(resString); + // do not add half refreshrates (25, 29.97 by default) as kodi cannot cope with + // them on playback start. Especially interlaced content is not properly detected + // and this causes ugly double switching. + // This won't allow 25p / 30p playback on native refreshrate by default + if ((info.fRefreshRate > 30) || (MathUtils::FloatEquals(info.fRefreshRate, 24.0f, 0.1f))) + { + resString = CDisplaySettings::GetInstance().GetStringFromRes(c); + indexList.push_back(resString); + } } } } diff --git a/xbmc/windowing/osx/WinEventsSDL.cpp b/xbmc/windowing/osx/WinEventsSDL.cpp index 745292814d..34bcdf4ecc 100644 --- a/xbmc/windowing/osx/WinEventsSDL.cpp +++ b/xbmc/windowing/osx/WinEventsSDL.cpp @@ -51,8 +51,8 @@ bool CWinEventsSDL::MessagePump() { g_application.m_AppFocused = event.active.gain != 0; std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort(); - if (appPort) - appPort->SetRenderGUI(event.active.gain != 0); + if (appPort && g_application.m_AppFocused) + appPort->SetRenderGUI(g_application.m_AppFocused); CServiceBroker::GetWinSystem()->NotifyAppFocusChange(g_application.m_AppFocused); } break; diff --git a/xbmc/windowing/wayland/WinSystemWayland.cpp b/xbmc/windowing/wayland/WinSystemWayland.cpp index 23f34906af..72337ffccf 100644 --- a/xbmc/windowing/wayland/WinSystemWayland.cpp +++ b/xbmc/windowing/wayland/WinSystemWayland.cpp @@ -1385,16 +1385,24 @@ void CWinSystemWayland::PrepareFramePresentation() // while it is minimized (since the wait needs to be interrupted for that). // -> Use Wait with timeout here so we can maintain a reasonable frame rate // even when the window is not visible and we do not get any frame callbacks. - m_frameCallbackEvent.WaitMSec(50); - m_frameCallbackEvent.Reset(); + if (m_frameCallbackEvent.WaitMSec(50)) + { + // Only reset frame callback object a callback was received so a + // new one is not requested continuously + m_frameCallback = {}; + m_frameCallbackEvent.Reset(); + } } - // Get frame callback event for checking in the next call to this function - m_frameCallback = m_surface.frame(); - m_frameCallback.on_done() = [this](std::uint32_t) + if (!m_frameCallback) { - m_frameCallbackEvent.Set(); - }; + // Get frame callback event for checking in the next call to this function + m_frameCallback = m_surface.frame(); + m_frameCallback.on_done() = [this](std::uint32_t) + { + m_frameCallbackEvent.Set(); + }; + } } void CWinSystemWayland::FinishFramePresentation() diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index 01f4e2e883..45e935cd9f 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -411,10 +411,14 @@ bool CGUIMediaWindow::OnMessage(CGUIMessage& message) } else if (message.GetParam1()==GUI_MSG_UPDATE_ITEM && message.GetItem()) { + int flag = message.GetParam2(); CFileItemPtr newItem = std::static_pointer_cast<CFileItem>(message.GetItem()); - if (IsActive()) + + if (IsActive() || (flag & GUI_MSG_FLAG_FORCE_UPDATE)) { - if (m_vecItems->UpdateItem(newItem.get()) && message.GetParam2() == 1) + m_vecItems->UpdateItem(newItem.get()); + + if (flag & GUI_MSG_FLAG_UPDATE_LIST) { // need the list updated as well UpdateFileList(); } |