From 24a6741648f79d148b30912666508c5359bd3b11 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 5 Apr 2013 11:56:50 +0200 Subject: [PATCH] xbmc: add various upstream patches Signed-off-by: Stephan Raue --- ...vicelist_change_callback_more_robust.patch | 52 +++ ...handle_empty_session_ids_from_itunes.patch | 26 ++ ...xbmc-990.30-airplay-fix_the_playtime.patch | 26 ++ ...-refactor_the_playstate_announcement.patch | 385 ++++++++++++++++++ ..._after_a_call_to_CAddon-SaveSettings.patch | 25 ++ .../xbmc/patches/xbmc-990.33-PR2392.patch | 43 ++ ...onger_played_since_the_Curl_seek_fix.patch | 39 ++ ...of_the_year_tag_its_stored_as_string.patch | 25 ++ ...990.36-Fix_parsing_of_the_artist_tag.patch | 27 ++ ...7-upnp-missing-info-for-music-videos.patch | 26 ++ ..._hide_unplayable_items_in_fiels_view.patch | 40 ++ ...o_retain_original_directory_ordering.patch | 31 ++ .../xbmc-990.40-fix_typo_in_ccdba4e.patch | 25 ++ 13 files changed, 770 insertions(+) create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.28-CA-AE-make_the_devicelist_change_callback_more_robust.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.29-airplay-handle_empty_session_ids_from_itunes.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.30-airplay-fix_the_playtime.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.31-airplay-refactor_the_playstate_announcement.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.32-CAddon-HasSettings_was_broken_after_a_call_to_CAddon-SaveSettings.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.33-PR2392.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.34-Some_streams_no_longer_played_since_the_Curl_seek_fix.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.35-Fix_parsing_of_the_year_tag_its_stored_as_string.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.36-Fix_parsing_of_the_artist_tag.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.37-upnp-missing-info-for-music-videos.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.38-upnp_hide_unplayable_items_in_fiels_view.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.39-upnp-use_a_better_way_to_retain_original_directory_ordering.patch create mode 100644 packages/mediacenter/xbmc/patches/xbmc-990.40-fix_typo_in_ccdba4e.patch diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.28-CA-AE-make_the_devicelist_change_callback_more_robust.patch b/packages/mediacenter/xbmc/patches/xbmc-990.28-CA-AE-make_the_devicelist_change_callback_more_robust.patch new file mode 100644 index 0000000000..2980d96771 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.28-CA-AE-make_the_devicelist_change_callback_more_robust.patch @@ -0,0 +1,52 @@ +From f6a002b0971138a785d03a934ad623b690a8becc Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Mon, 18 Mar 2013 22:30:19 +0100 +Subject: [PATCH] [CA/AE] - make the devicelist change callback more robust - + should fix crashes during shutdown on some system constellations (where + removing the callback seems to also triggers the callback at the same time) + +--- + xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp +index 2c1d4bb..a9302ac 100644 +--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp +@@ -51,8 +51,11 @@ OSStatus deviceChangedCB( AudioObjectID inObjectID, + void* inClientData) + { + CCoreAudioAE *pEngine = (CCoreAudioAE *)inClientData; +- pEngine->AudioDevicesChanged(); +- CLog::Log(LOGDEBUG, "CCoreAudioAE - audiodevicelist changed!"); ++ if (pEngine->GetHAL()) ++ { ++ pEngine->AudioDevicesChanged(); ++ CLog::Log(LOGDEBUG, "CCoreAudioAE - audiodevicelist changed!"); ++ } + return noErr; + } + +@@ -102,8 +105,8 @@ void RegisterDeviceChangedCB(bool bRegister, void *ref){} + + CCoreAudioAE::~CCoreAudioAE() + { +- RegisterDeviceChangedCB(false, this); + Shutdown(); ++ RegisterDeviceChangedCB(false, this); + } + + void CCoreAudioAE::Shutdown() +@@ -138,6 +141,9 @@ void CCoreAudioAE::Shutdown() + + void CCoreAudioAE::AudioDevicesChanged() + { ++ if (!m_Initialized) ++ return; ++ + // give CA a bit time to realise that maybe the + // default device might have changed now - else + // OpenCoreAudio might open the old default device +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.29-airplay-handle_empty_session_ids_from_itunes.patch b/packages/mediacenter/xbmc/patches/xbmc-990.29-airplay-handle_empty_session_ids_from_itunes.patch new file mode 100644 index 0000000000..1518d7c687 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.29-airplay-handle_empty_session_ids_from_itunes.patch @@ -0,0 +1,26 @@ +From b93a152c7c4dcdd2936711b59b5c209bc51d3f13 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Wed, 20 Mar 2013 22:22:47 +0100 +Subject: [PATCH] [airplay] - handle empty session ids from itunes + +--- + xbmc/network/AirPlayServer.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp +index 11daa97..5b64126 100644 +--- a/xbmc/network/AirPlayServer.cpp ++++ b/xbmc/network/AirPlayServer.cpp +@@ -645,6 +645,9 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, + CStdString authorization = m_httpParser->getValue("authorization"); + int status = AIRPLAY_STATUS_OK; + bool needAuth = false; ++ ++ if (m_sessionId.IsEmpty()) ++ m_sessionId = "00000000-0000-0000-0000-000000000000"; + + if (ServerInstance->m_usePassword && !m_bAuthenticated) + { +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.30-airplay-fix_the_playtime.patch b/packages/mediacenter/xbmc/patches/xbmc-990.30-airplay-fix_the_playtime.patch new file mode 100644 index 0000000000..93b01a023a --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.30-airplay-fix_the_playtime.patch @@ -0,0 +1,26 @@ +From 820b08c2520bbea89fb862c61f4dc5a6a63865df Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Wed, 20 Mar 2013 22:23:48 +0100 +Subject: [PATCH] [airplay] - fix the playtime - itunes is very picky about the + formatting here + +--- + xbmc/network/AirPlayServer.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp +index 5b64126..c4c4984 100644 +--- a/xbmc/network/AirPlayServer.cpp ++++ b/xbmc/network/AirPlayServer.cpp +@@ -840,7 +840,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, + if (g_application.m_pPlayer && g_application.m_pPlayer->GetTotalTime()) + { + float position = ((float) g_application.m_pPlayer->GetTime()) / 1000; +- responseBody.Format("duration: %d\r\nposition: %f", g_application.m_pPlayer->GetTotalTime() / 1000, position); ++ responseBody.Format("duration: %.6f\r\nposition: %.6f\r\n", (float)g_application.m_pPlayer->GetTotalTime() / 1000, position); + } + else + { +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.31-airplay-refactor_the_playstate_announcement.patch b/packages/mediacenter/xbmc/patches/xbmc-990.31-airplay-refactor_the_playstate_announcement.patch new file mode 100644 index 0000000000..09d27d3860 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.31-airplay-refactor_the_playstate_announcement.patch @@ -0,0 +1,385 @@ +From 7f0b5c61deb28bf7825a3504709be21fa37d95c1 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Wed, 20 Mar 2013 22:25:18 +0100 +Subject: [PATCH] [airplay] - refactor the playstate announcement by using the + IAnnouncer interface - also adapt to some new findings on revers engineering + itunes airplay traffic (add sessioncounter to reverse event and fix http + request formatting) - fixes #14191 + +--- + xbmc/network/AirPlayServer.cpp | 133 ++++++++++++++++++++++++++--------------- + xbmc/network/AirPlayServer.h | 19 ++++-- + 2 files changed, 97 insertions(+), 55 deletions(-) + +diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp +index c4c4984..28e8075 100644 +--- a/xbmc/network/AirPlayServer.cpp ++++ b/xbmc/network/AirPlayServer.cpp +@@ -38,6 +38,9 @@ + #include "utils/Variant.h" + #include "guilib/GUIWindowManager.h" + #include "URL.h" ++#include "interfaces/AnnouncementManager.h" ++ ++using namespace ANNOUNCEMENT; + + #ifdef TARGET_WINDOWS + #define close closesocket +@@ -134,6 +137,8 @@ + "\r\n"\ + "category\r\n"\ + "video\r\n"\ ++"sessionID\r\n"\ ++"%d\r\n"\ + "state\r\n"\ + "%s\r\n"\ + "\r\n"\ +@@ -142,6 +147,25 @@ + #define AUTH_REALM "AirPlay" + #define AUTH_REQUIRED "WWW-Authenticate: Digest realm=\"" AUTH_REALM "\", nonce=\"%s\"\r\n" + ++void CAirPlayServer::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) ++{ ++ if ( (flag & Player) && strcmp(sender, "xbmc") == 0 && ServerInstance) ++ { ++ if (strcmp(message, "OnStop") == 0) ++ { ++ ServerInstance->AnnounceToClients(EVENT_STOPPED); ++ } ++ else if (strcmp(message, "OnPlay") == 0) ++ { ++ ServerInstance->AnnounceToClients(EVENT_PLAYING); ++ } ++ else if (strcmp(message, "OnPause") == 0) ++ { ++ ServerInstance->AnnounceToClients(EVENT_PAUSED); ++ } ++ } ++} ++ + bool CAirPlayServer::StartServer(int port, bool nonlocal) + { + StopServer(true); +@@ -187,17 +211,62 @@ void CAirPlayServer::StopServer(bool bWait) + } + } + ++void CAirPlayServer::AnnounceToClients(int state) ++{ ++ CSingleLock lock (m_connectionLock); ++ ++ std::vector::iterator it; ++ for (it = m_connections.begin(); it != m_connections.end(); it++) ++ { ++ CStdString reverseHeader; ++ CStdString reverseBody; ++ CStdString response; ++ int reverseSocket = INVALID_SOCKET; ++ it->ComposeReverseEvent(reverseHeader, reverseBody, state); ++ ++ // Send event status per reverse http socket (play, loading, paused) ++ // if we have a reverse header and a reverse socket ++ if (reverseHeader.size() > 0 && m_reverseSockets.find(it->m_sessionId) != m_reverseSockets.end()) ++ { ++ //search the reverse socket to this sessionid ++ response.Format("POST /event HTTP/1.1\r\n"); ++ reverseSocket = m_reverseSockets[it->m_sessionId]; //that is our reverse socket ++ response += reverseHeader; ++ } ++ response += "\r\n"; ++ ++ if (reverseBody.size() > 0) ++ { ++ response += reverseBody; ++ } ++ ++ // don't send it to the connection object ++ // the reverse socket itself belongs to ++ if (reverseSocket != INVALID_SOCKET && reverseSocket != it->m_socket) ++ { ++ send(reverseSocket, response.c_str(), response.size(), 0);//send the event status on the eventSocket ++ } ++ } ++} ++ + CAirPlayServer::CAirPlayServer(int port, bool nonlocal) : CThread("AirPlayServer") + { + m_port = port; + m_nonlocal = nonlocal; + m_ServerSocket = INVALID_SOCKET; + m_usePassword = false; ++ CAnnouncementManager::AddAnnouncer(this); ++} ++ ++CAirPlayServer::~CAirPlayServer() ++{ ++ CAnnouncementManager::RemoveAnnouncer(this); + } + + void CAirPlayServer::Process() + { + m_bStop = false; ++ static int sessionCounter = 0; + + while (!m_bStop) + { +@@ -240,6 +309,7 @@ void CAirPlayServer::Process() + } + if (nread <= 0) + { ++ CSingleLock lock (m_connectionLock); + CLog::Log(LOGINFO, "AIRPLAY Server: Disconnection detected"); + m_connections[i].Disconnect(); + m_connections.erase(m_connections.begin() + i); +@@ -252,6 +322,8 @@ void CAirPlayServer::Process() + CLog::Log(LOGDEBUG, "AIRPLAY Server: New connection detected"); + CTCPClient newconnection; + newconnection.m_socket = accept(m_ServerSocket, &newconnection.m_cliaddr, &newconnection.m_addrlen); ++ sessionCounter++; ++ newconnection.m_sessionCounter = sessionCounter; + + if (newconnection.m_socket == INVALID_SOCKET) + { +@@ -265,6 +337,7 @@ void CAirPlayServer::Process() + } + else + { ++ CSingleLock lock (m_connectionLock); + CLog::Log(LOGINFO, "AIRPLAY Server: New connection added"); + m_connections.push_back(newconnection); + } +@@ -319,6 +392,7 @@ bool CAirPlayServer::Initialize() + + void CAirPlayServer::Deinitialize() + { ++ CSingleLock lock (m_connectionLock); + for (unsigned int i = 0; i < m_connections.size(); i++) + m_connections[i].Disconnect(); + +@@ -381,11 +455,9 @@ void CAirPlayServer::CTCPClient::PushBuffer(CAirPlayServer *host, const char *bu + // Parse the request + CStdString responseHeader; + CStdString responseBody; +- CStdString reverseHeader; +- CStdString reverseBody; +- int status = ProcessRequest(responseHeader, responseBody, reverseHeader, reverseBody, sessionId); ++ int status = ProcessRequest(responseHeader, responseBody); ++ sessionId = m_sessionId; + CStdString statusMsg = "OK"; +- int reverseSocket = INVALID_SOCKET; + + switch(status) + { +@@ -435,28 +507,6 @@ void CAirPlayServer::CTCPClient::PushBuffer(CAirPlayServer *host, const char *bu + { + send(m_socket, response.c_str(), response.size(), 0); + } +- +- // Send event status per reverse http socket (play, loading, paused) +- // if we have a reverse header and a reverse socket +- if (reverseHeader.size() > 0 && reverseSockets.find(sessionId) != reverseSockets.end()) +- { +- //search the reverse socket to this sessionid +- response.Format("POST /event HTTP/1.1\r\n"); +- reverseSocket = reverseSockets[sessionId]; //that is our reverse socket +- response += reverseHeader; +- } +- response += "\r\n"; +- +- if (reverseBody.size() > 0) +- { +- response += reverseBody; +- } +- +- if (reverseSocket != INVALID_SOCKET) +- { +- send(reverseSocket, response.c_str(), response.size(), 0);//send the event status on the eventSocket +- } +- + // We need a new parser... + delete m_httpParser; + m_httpParser = new HttpParser; +@@ -484,12 +534,12 @@ void CAirPlayServer::CTCPClient::Copy(const CTCPClient& client) + m_httpParser = client.m_httpParser; + m_authNonce = client.m_authNonce; + m_bAuthenticated = client.m_bAuthenticated; ++ m_sessionCounter = client.m_sessionCounter; + } + + + void CAirPlayServer::CTCPClient::ComposeReverseEvent( CStdString& reverseHeader, + CStdString& reverseBody, +- CStdString sessionId, + int state) + { + +@@ -501,13 +551,13 @@ void CAirPlayServer::CTCPClient::ComposeReverseEvent( CStdString& reverseHeader, + case EVENT_LOADING: + case EVENT_PAUSED: + case EVENT_STOPPED: +- reverseBody.Format(EVENT_INFO, eventStrings[state]); ++ reverseBody.Format(EVENT_INFO, m_sessionCounter, eventStrings[state]); + CLog::Log(LOGDEBUG, "AIRPLAY: sending event: %s", eventStrings[state]); + break; + } + reverseHeader = "Content-Type: text/x-apple-plist+xml\r\n"; +- reverseHeader.Format("%sContent-Length: %d",reverseHeader.c_str(),reverseBody.size()); +- reverseHeader.Format("%sx-apple-session-id: %s\r\n",reverseHeader.c_str(),sessionId.c_str()); ++ reverseHeader.Format("%sContent-Length: %d\r\n",reverseHeader.c_str(),reverseBody.size()); ++ reverseHeader.Format("%sx-apple-session-id: %s\r\n",reverseHeader.c_str(),m_sessionId.c_str()); + m_lastEvent = state; + } + } +@@ -631,17 +681,14 @@ bool CAirPlayServer::CTCPClient::checkAuthorization(const CStdString& authStr, + } + + int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, +- CStdString& responseBody, +- CStdString& reverseHeader, +- CStdString& reverseBody, +- CStdString& sessionId) ++ CStdString& responseBody) + { + CStdString method = m_httpParser->getMethod(); + CStdString uri = m_httpParser->getUri(); + CStdString queryString = m_httpParser->getQueryString(); + CStdString body = m_httpParser->getBody(); + CStdString contentType = m_httpParser->getValue("content-type"); +- sessionId = m_httpParser->getValue("x-apple-session-id"); ++ m_sessionId = m_httpParser->getValue("x-apple-session-id"); + CStdString authorization = m_httpParser->getValue("authorization"); + int status = AIRPLAY_STATUS_OK; + bool needAuth = false; +@@ -688,7 +735,6 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, + if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) + { + CApplicationMessenger::Get().MediaPause(); +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PAUSED); + } + } + else +@@ -696,7 +742,6 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, + if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && g_application.m_pPlayer->IsPaused()) + { + CApplicationMessenger::Get().MediaPause(); +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PLAYING); + } + } + } +@@ -820,8 +865,8 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, + + CFileItem fileToPlay(location, false); + fileToPlay.SetProperty("StartPercent", position*100.0f); ++ ServerInstance->AnnounceToClients(EVENT_LOADING); + CApplicationMessenger::Get().MediaPlay(fileToPlay); +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PLAYING); + } + } + +@@ -879,7 +924,6 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, + { + g_windowManager.PreviousWindow(); + } +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_STOPPED); + } + } + +@@ -950,22 +994,13 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, + + if (g_application.m_pPlayer->IsCaching()) + { +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_LOADING); +- } +- else if (playing) +- { +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PLAYING); +- } +- else +- { +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PAUSED); ++ CAirPlayServer::ServerInstance->AnnounceToClients(EVENT_LOADING); + } + } + else + { + responseBody.Format(PLAYBACK_INFO_NOT_READY, duration, cachePosition, position, (playing ? 1 : 0), duration); + responseHeader = "Content-Type: text/x-apple-plist+xml\r\n"; +- ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_STOPPED); + } + } + +diff --git a/xbmc/network/AirPlayServer.h b/xbmc/network/AirPlayServer.h +index 168a09f..6dcf741 100644 +--- a/xbmc/network/AirPlayServer.h ++++ b/xbmc/network/AirPlayServer.h +@@ -31,14 +31,19 @@ + #include "threads/CriticalSection.h" + #include "utils/HttpParser.h" + #include "utils/StdString.h" ++#include "interfaces/IAnnouncer.h" + + class DllLibPlist; + + #define AIRPLAY_SERVER_VERSION_STR "101.28" + +-class CAirPlayServer : public CThread ++class CAirPlayServer : public CThread, public ANNOUNCEMENT::IAnnouncer + { + public: ++ // IAnnouncer IF ++ virtual void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); ++ ++ //AirPlayServer impl. + static bool StartServer(int port, bool nonlocal); + static void StopServer(bool bWait); + static bool SetCredentials(bool usePassword, const CStdString& password); +@@ -50,9 +55,11 @@ class CAirPlayServer : public CThread + + private: + CAirPlayServer(int port, bool nonlocal); ++ ~CAirPlayServer(); + bool SetInternalCredentials(bool usePassword, const CStdString& password); + bool Initialize(); + void Deinitialize(); ++ void AnnounceToClients(int state); + + class CTCPClient + { +@@ -66,6 +73,7 @@ class CAirPlayServer : public CThread + void PushBuffer(CAirPlayServer *host, const char *buffer, + int length, CStdString &sessionId, + std::map &reverseSockets); ++ void ComposeReverseEvent(CStdString& reverseHeader, CStdString& reverseBody, int state); + + void Disconnect(); + +@@ -73,15 +81,13 @@ class CAirPlayServer : public CThread + struct sockaddr m_cliaddr; + socklen_t m_addrlen; + CCriticalSection m_critSection; ++ int m_sessionCounter; ++ CStdString m_sessionId; + + private: + int ProcessRequest( CStdString& responseHeader, +- CStdString& response, +- CStdString& reverseHeader, +- CStdString& reverseBody, +- CStdString& sessionId); ++ CStdString& response); + +- void ComposeReverseEvent(CStdString& reverseHeader, CStdString& reverseBody, CStdString sessionId, int state); + void ComposeAuthRequestAnswer(CStdString& responseHeader, CStdString& responseBody); + bool checkAuthorization(const CStdString& authStr, const CStdString& method, const CStdString& uri); + void Copy(const CTCPClient& client); +@@ -93,6 +99,7 @@ class CAirPlayServer : public CThread + CStdString m_authNonce; + }; + ++ CCriticalSection m_connectionLock; + std::vector m_connections; + std::map m_reverseSockets; + int m_ServerSocket; +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.32-CAddon-HasSettings_was_broken_after_a_call_to_CAddon-SaveSettings.patch b/packages/mediacenter/xbmc/patches/xbmc-990.32-CAddon-HasSettings_was_broken_after_a_call_to_CAddon-SaveSettings.patch new file mode 100644 index 0000000000..40e1b7d7af --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.32-CAddon-HasSettings_was_broken_after_a_call_to_CAddon-SaveSettings.patch @@ -0,0 +1,25 @@ +From 0fb38d80aabd1112b377760c509855bf529fb95f Mon Sep 17 00:00:00 2001 +From: Garrett Brown +Date: Sun, 24 Mar 2013 23:57:49 -0700 +Subject: [PATCH] Fixed: CAddon::HasSettings() was broken after a call to + CAddon::SaveSettings() on creation of user settings + +--- + xbmc/addons/Addon.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp +index 23f89b8..7315ab0 100644 +--- a/xbmc/addons/Addon.cpp ++++ b/xbmc/addons/Addon.cpp +@@ -512,6 +512,7 @@ void CAddon::SaveSettings(void) + CXBMCTinyXML doc; + SettingsToXML(doc); + doc.SaveFile(m_userSettingsPath); ++ m_userSettingsLoaded = true; + + CAddonMgr::Get().ReloadSettings(ID());//push the settings changes to the running addon instance + g_pythonParser.OnSettingsChanged(ID()); +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.33-PR2392.patch b/packages/mediacenter/xbmc/patches/xbmc-990.33-PR2392.patch new file mode 100644 index 0000000000..87878bd546 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.33-PR2392.patch @@ -0,0 +1,43 @@ +From 9db853e551f0380aac884fcb6c9564a725fcb966 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Fri, 8 Mar 2013 06:34:02 +0100 +Subject: [PATCH] fixed: We can only obtain the aspect & duration this way when + the Process() thread is running + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 0cd2510..8128197 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -4024,11 +4024,22 @@ bool CDVDPlayer::GetStreamDetails(CStreamDetails &details) + { + if (m_pDemuxer) + { +- bool result=CDVDFileInfo::DemuxerToStreamDetails(m_pInputStream, m_pDemuxer, details); ++ bool result = CDVDFileInfo::DemuxerToStreamDetails(m_pInputStream, m_pDemuxer, details); + if (result && details.GetStreamCount(CStreamDetail::VIDEO) > 0) // this is more correct (dvds in particular) + { +- GetVideoAspectRatio(((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_fAspect); +- ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_iDuration = GetTotalTime() / 1000; ++ /* ++ * We can only obtain the aspect & duration from dvdplayer when the Process() thread is running ++ * and UpdatePlayState() has been called at least once. In this case dvdplayer duration/AR will ++ * return 0 and we'll have to fallback to the (less accurate) info from the demuxer. ++ */ ++ float aspect; ++ GetVideoAspectRatio(aspect); ++ if (aspect > 0.0f) ++ ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_fAspect = aspect; ++ ++ int64_t duration = GetTotalTime() / 1000; ++ if (duration > 0) ++ ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_iDuration = duration; + } + return result; + } +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.34-Some_streams_no_longer_played_since_the_Curl_seek_fix.patch b/packages/mediacenter/xbmc/patches/xbmc-990.34-Some_streams_no_longer_played_since_the_Curl_seek_fix.patch new file mode 100644 index 0000000000..3e20d4d6f4 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.34-Some_streams_no_longer_played_since_the_Curl_seek_fix.patch @@ -0,0 +1,39 @@ +From 63a6dadd40815eb07ba940a60d012a23ce9a5eb4 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Fri, 29 Mar 2013 21:01:44 +0100 +Subject: [PATCH] fixed: Some (live) streams no longer played since the Curl + seek fix (fixes #14224) + +--- + xbmc/filesystem/CurlFile.cpp | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp +index 2c5da25..456f5f0 100644 +--- a/xbmc/filesystem/CurlFile.cpp ++++ b/xbmc/filesystem/CurlFile.cpp +@@ -291,14 +291,14 @@ bool CCurlFile::CReadState::Seek(int64_t pos) + void CCurlFile::CReadState::SetResume(void) + { + /* +- * Use RANGE method for resuming. We used to use RESUME_FROM_LARGE for this but some http servers +- * require us to always send the range request header. If we don't the server may provide different +- * content causing seeking to fail. Note that internally Curl will automatically handle this for FTP +- * so we don't need to worry about that here. ++ * Explicitly set RANGE header when filepos=0 as some http servers require us to always send the range ++ * request header. If we don't the server may provide different content causing seeking to fail. ++ * This only affects HTTP-like items, for FTP it's a null operation. + */ +- char str[21]; +- sprintf(str, "%"PRId64"-", m_filePos); +- g_curlInterface.easy_setopt(m_easyHandle, CURLOPT_RANGE, str); ++ if (m_filePos == 0) ++ g_curlInterface.easy_setopt(m_easyHandle, CURLOPT_RANGE, "0-"); ++ ++ g_curlInterface.easy_setopt(m_easyHandle, CURLOPT_RESUME_FROM_LARGE, m_filePos); + } + + long CCurlFile::CReadState::Connect(unsigned int size) +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.35-Fix_parsing_of_the_year_tag_its_stored_as_string.patch b/packages/mediacenter/xbmc/patches/xbmc-990.35-Fix_parsing_of_the_year_tag_its_stored_as_string.patch new file mode 100644 index 0000000000..c64a3c6ae3 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.35-Fix_parsing_of_the_year_tag_its_stored_as_string.patch @@ -0,0 +1,25 @@ +From 68cab251cbca58adaf7df698d8db11145ff0e27a Mon Sep 17 00:00:00 2001 +From: ace20022 +Date: Sat, 16 Mar 2013 14:53:33 +0100 +Subject: [PATCH] [ASF Tag] Fix parsing of the year tag, it's stored as string. + +--- + xbmc/music/tags/TagLoaderTagLib.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/music/tags/TagLoaderTagLib.cpp b/xbmc/music/tags/TagLoaderTagLib.cpp +index c6ac758..2f16d43 100644 +--- a/xbmc/music/tags/TagLoaderTagLib.cpp ++++ b/xbmc/music/tags/TagLoaderTagLib.cpp +@@ -262,7 +262,7 @@ bool CTagLoaderTagLib::ParseASF(ASF::Tag *asf, EmbeddedArt *art, CMusicInfoTag& + else if (it->first == "WM/AlbumArtistSortOrder") {} // Known unsupported, supress warnings + else if (it->first == "WM/ArtistSortOrder") {} // Known unsupported, supress warnings + else if (it->first == "WM/Script") {} // Known unsupported, supress warnings +- else if (it->first == "WM/Year") tag.SetYear(it->second.front().toUInt()); ++ else if (it->first == "WM/Year") tag.SetYear(atoi(it->second.front().toString().toCString(true))); + else if (it->first == "MusicBrainz/Artist Id") tag.SetMusicBrainzArtistID(it->second.front().toString().to8Bit(true)); + else if (it->first == "MusicBrainz/Album Id") tag.SetMusicBrainzAlbumID(it->second.front().toString().to8Bit(true)); + else if (it->first == "MusicBrainz/Album Artist Id") tag.SetMusicBrainzAlbumArtistID(it->second.front().toString().to8Bit(true)); +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.36-Fix_parsing_of_the_artist_tag.patch b/packages/mediacenter/xbmc/patches/xbmc-990.36-Fix_parsing_of_the_artist_tag.patch new file mode 100644 index 0000000000..bfcefaabca --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.36-Fix_parsing_of_the_artist_tag.patch @@ -0,0 +1,27 @@ +From b06e994c4acbf39ba0013ed48cbd9fbde2b05bde Mon Sep 17 00:00:00 2001 +From: ace20022 +Date: Sat, 16 Mar 2013 15:27:38 +0100 +Subject: [PATCH] [ASF Tag] Fix parsing of the artist tag. More precisely: fall + back to the built in artist method if there's no "author" field in the tag. + +--- + xbmc/music/tags/TagLoaderTagLib.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/music/tags/TagLoaderTagLib.cpp b/xbmc/music/tags/TagLoaderTagLib.cpp +index 2f16d43..6b88302 100644 +--- a/xbmc/music/tags/TagLoaderTagLib.cpp ++++ b/xbmc/music/tags/TagLoaderTagLib.cpp +@@ -284,6 +284,9 @@ bool CTagLoaderTagLib::ParseASF(ASF::Tag *asf, EmbeddedArt *art, CMusicInfoTag& + else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) + CLog::Log(LOGDEBUG, "unrecognized ASF tag name: %s", it->first.toCString(true)); + } ++ // artist may be specified in the ContentDescription block rather than using the 'Author' attribute. ++ if (tag.GetArtist().empty()) ++ tag.SetArtist(asf->artist().toCString(true)); + tag.SetLoaded(true); + return true; + } +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.37-upnp-missing-info-for-music-videos.patch b/packages/mediacenter/xbmc/patches/xbmc-990.37-upnp-missing-info-for-music-videos.patch new file mode 100644 index 0000000000..847ee56f84 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.37-upnp-missing-info-for-music-videos.patch @@ -0,0 +1,26 @@ +From ccdba4e2a281970c4b5a2b81a85831f5bd8cf61d Mon Sep 17 00:00:00 2001 +From: Alasdair Campbell +Date: Tue, 2 Apr 2013 19:39:22 +0100 +Subject: [PATCH] upnp: missing info for music videos, fixes #14239 thanks to + Pulfer + +--- + xbmc/network/upnp/UPnPServer.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp +index 0518d14..1b92f99 100644 +--- a/xbmc/network/upnp/UPnPServer.cpp ++++ b/xbmc/network/upnp/UPnPServer.cpp +@@ -308,6 +308,8 @@ NPT_String CUPnPServer::BuildSafeResourceUri(const NPT_HttpUrl &rooturi, + + if (params.GetMovieId() >= 0 ) + db.GetMovieInfo((const char*)path, *item->GetVideoInfoTag(), params.GetMovieId()); ++ if (params.GetMVideoId() >= 0 ) ++ db.GetMusicVideoInfo((const char*)path, *item->GetVideoInfoTag(), params.GetMVideoId()); + else if (params.GetEpisodeId() >= 0 ) + db.GetEpisodeInfo((const char*)path, *item->GetVideoInfoTag(), params.GetEpisodeId()); + else if (params.GetTvShowId() >= 0 ) +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.38-upnp_hide_unplayable_items_in_fiels_view.patch b/packages/mediacenter/xbmc/patches/xbmc-990.38-upnp_hide_unplayable_items_in_fiels_view.patch new file mode 100644 index 0000000000..a985c9533c --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.38-upnp_hide_unplayable_items_in_fiels_view.patch @@ -0,0 +1,40 @@ +From ec9129fe58614016d98af521471ff097171ae444 Mon Sep 17 00:00:00 2001 +From: Alasdair Campbell +Date: Tue, 2 Apr 2013 04:41:48 +0100 +Subject: [PATCH] upnp: hide unplayable items in fiels view fixes #13526 + +--- + xbmc/network/upnp/UPnPServer.cpp | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp +index 86f13eb..0518d14 100644 +--- a/xbmc/network/upnp/UPnPServer.cpp ++++ b/xbmc/network/upnp/UPnPServer.cpp +@@ -13,6 +13,7 @@ + #include "filesystem/VideoDatabaseDirectory.h" + #include "guilib/WindowIDs.h" + #include "music/tags/MusicInfoTag.h" ++#include "settings/Settings.h" + #include "settings/GUISettings.h" + #include "utils/log.h" + #include "utils/md5.h" +@@ -600,7 +601,14 @@ static NPT_String TranslateWMPObjectId(NPT_String id) + + items.Sort(SORT_METHOD_LABEL, SortOrderAscending); + } else { +- CDirectory::GetDirectory((const char*)parent_id, items); ++ // this is the only way to hide unplayable items in the 'files' ++ // view as we cannot tell what context (eg music vs video) the ++ // request came from ++ string supported = g_settings.m_pictureExtensions + "|" ++ + g_settings.m_videoExtensions + "|" ++ + g_settings.m_musicExtensions + "|" ++ + g_settings.m_discStubExtensions; ++ CDirectory::GetDirectory((const char*)parent_id, items, supported); + DefaultSortItems(items); + } + +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.39-upnp-use_a_better_way_to_retain_original_directory_ordering.patch b/packages/mediacenter/xbmc/patches/xbmc-990.39-upnp-use_a_better_way_to_retain_original_directory_ordering.patch new file mode 100644 index 0000000000..53ed6c085f --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.39-upnp-use_a_better_way_to_retain_original_directory_ordering.patch @@ -0,0 +1,31 @@ +From 87f4c493cab4f648ebd7ce4ee10dc6fc593f179f Mon Sep 17 00:00:00 2001 +From: Alasdair Campbell +Date: Tue, 2 Apr 2013 03:30:19 +0100 +Subject: [PATCH] upnp: use a better way to retain original directory ordering, + fixes #14235 + +--- + xbmc/filesystem/UPnPDirectory.cpp | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/xbmc/filesystem/UPnPDirectory.cpp b/xbmc/filesystem/UPnPDirectory.cpp +index 2a3c893..49c8449 100644 +--- a/xbmc/filesystem/UPnPDirectory.cpp ++++ b/xbmc/filesystem/UPnPDirectory.cpp +@@ -349,7 +349,12 @@ bool CUPnPDirectory::GetResource(const CURL& path, CFileItem &item) + std::string content = GetContentMapping(max_string); + items.SetContent(content); + if (content == "unknown") +- items.AddSortMethod(SORT_METHOD_NONE, 551, LABEL_MASKS("%L", "%I", "%L", "")); ++ { ++ items.AddSortMethod(SORT_METHOD_UNSORTED, 571, LABEL_MASKS("%L", "%I", "%L", "")); ++ items.AddSortMethod(SORT_METHOD_LABEL_IGNORE_FOLDERS, 551, LABEL_MASKS("%L", "%I", "%L", "")); ++ items.AddSortMethod(SORT_METHOD_SIZE, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); ++ items.AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J")); ++ } + } + + cleanup: +-- +1.8.1.5 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.40-fix_typo_in_ccdba4e.patch b/packages/mediacenter/xbmc/patches/xbmc-990.40-fix_typo_in_ccdba4e.patch new file mode 100644 index 0000000000..66f54f0833 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.40-fix_typo_in_ccdba4e.patch @@ -0,0 +1,25 @@ +From 4e8a5a0dbc3f8bb7815d699475e2afa25cb1ca2e Mon Sep 17 00:00:00 2001 +From: Alasdair Campbell +Date: Wed, 3 Apr 2013 12:51:13 +0100 +Subject: [PATCH] fix typo in ccdba4e + +--- + xbmc/network/upnp/UPnPServer.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp +index 1b92f99..bd618d8 100644 +--- a/xbmc/network/upnp/UPnPServer.cpp ++++ b/xbmc/network/upnp/UPnPServer.cpp +@@ -308,7 +308,7 @@ NPT_String CUPnPServer::BuildSafeResourceUri(const NPT_HttpUrl &rooturi, + + if (params.GetMovieId() >= 0 ) + db.GetMovieInfo((const char*)path, *item->GetVideoInfoTag(), params.GetMovieId()); +- if (params.GetMVideoId() >= 0 ) ++ else if (params.GetMVideoId() >= 0 ) + db.GetMusicVideoInfo((const char*)path, *item->GetVideoInfoTag(), params.GetMVideoId()); + else if (params.GetEpisodeId() >= 0 ) + db.GetEpisodeInfo((const char*)path, *item->GetVideoInfoTag(), params.GetEpisodeId()); +-- +1.8.1.5 +