mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
xbmc: add various upstream patches
Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
parent
229521b914
commit
24a6741648
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
43
packages/mediacenter/xbmc/patches/xbmc-990.33-PR2392.patch
Normal file
43
packages/mediacenter/xbmc/patches/xbmc-990.33-PR2392.patch
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user