xbmc: add various upstream patches

Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
Stephan Raue 2013-04-05 11:56:50 +02:00
parent 229521b914
commit 24a6741648
13 changed files with 770 additions and 0 deletions

View File

@ -0,0 +1,52 @@
From f6a002b0971138a785d03a934ad623b690a8becc Mon Sep 17 00:00:00 2001
From: Memphiz <memphis@machzwo.de>
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

View File

@ -0,0 +1,26 @@
From b93a152c7c4dcdd2936711b59b5c209bc51d3f13 Mon Sep 17 00:00:00 2001
From: Memphiz <memphis@machzwo.de>
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

View File

@ -0,0 +1,26 @@
From 820b08c2520bbea89fb862c61f4dc5a6a63865df Mon Sep 17 00:00:00 2001
From: Memphiz <memphis@machzwo.de>
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

View File

@ -0,0 +1,385 @@
From 7f0b5c61deb28bf7825a3504709be21fa37d95c1 Mon Sep 17 00:00:00 2001
From: Memphiz <memphis@machzwo.de>
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 @@
"<dict>\r\n"\
"<key>category</key>\r\n"\
"<string>video</string>\r\n"\
+"<key>sessionID</key>\r\n"\
+"<integer>%d</integer>\r\n"\
"<key>state</key>\r\n"\
"<string>%s</string>\r\n"\
"</dict>\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<CTCPClient>::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<CStdString, int> &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<CTCPClient> m_connections;
std::map<CStdString, int> m_reverseSockets;
int m_ServerSocket;
--
1.8.1.5

View File

@ -0,0 +1,25 @@
From 0fb38d80aabd1112b377760c509855bf529fb95f Mon Sep 17 00:00:00 2001
From: Garrett Brown <garbearucla@gmail.com>
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

View File

@ -0,0 +1,43 @@
From 9db853e551f0380aac884fcb6c9564a725fcb966 Mon Sep 17 00:00:00 2001
From: arnova <arnova@void.org>
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

View File

@ -0,0 +1,39 @@
From 63a6dadd40815eb07ba940a60d012a23ce9a5eb4 Mon Sep 17 00:00:00 2001
From: arnova <arnova@void.org>
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

View File

@ -0,0 +1,25 @@
From 68cab251cbca58adaf7df698d8db11145ff0e27a Mon Sep 17 00:00:00 2001
From: ace20022 <ace20022@ymail.com>
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

View File

@ -0,0 +1,27 @@
From b06e994c4acbf39ba0013ed48cbd9fbde2b05bde Mon Sep 17 00:00:00 2001
From: ace20022 <ace20022@ymail.com>
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

View File

@ -0,0 +1,26 @@
From ccdba4e2a281970c4b5a2b81a85831f5bd8cf61d Mon Sep 17 00:00:00 2001
From: Alasdair Campbell <alcoheca@gmail.com>
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

View File

@ -0,0 +1,40 @@
From ec9129fe58614016d98af521471ff097171ae444 Mon Sep 17 00:00:00 2001
From: Alasdair Campbell <alcoheca@gmail.com>
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

View File

@ -0,0 +1,31 @@
From 87f4c493cab4f648ebd7ce4ee10dc6fc593f179f Mon Sep 17 00:00:00 2001
From: Alasdair Campbell <alcoheca@gmail.com>
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

View File

@ -0,0 +1,25 @@
From 4e8a5a0dbc3f8bb7815d699475e2afa25cb1ca2e Mon Sep 17 00:00:00 2001
From: Alasdair Campbell <alcoheca@gmail.com>
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