xbmc: add PR4414

Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
Stephan Raue 2014-03-15 04:13:01 +01:00
parent a6e4c27029
commit 2bbee7ca90

View File

@ -0,0 +1,390 @@
From 794ebc00947bc208e6b377e5d69be6cfa85cf382 Mon Sep 17 00:00:00 2001
From: Memphiz <memphis@machzwo.de>
Date: Tue, 11 Mar 2014 20:30:19 +0100
Subject: [PATCH 1/3] [airplay] - ensure to announce airtunes before airplay
via zeroconf (makes it more likely that ios7 clients detect us correctly at
the first shot)
---
xbmc/network/NetworkServices.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/xbmc/network/NetworkServices.cpp b/xbmc/network/NetworkServices.cpp
index f1b82d7..66316b4 100644
--- a/xbmc/network/NetworkServices.cpp
+++ b/xbmc/network/NetworkServices.cpp
@@ -210,12 +210,6 @@ bool CNetworkServices::OnSettingChanging(const CSetting *setting)
}
#endif //HAS_ZEROCONF
- if (!StartAirPlayServer())
- {
- CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1273), "", g_localizeStrings.Get(33100), "");
- return false;
- }
-
#ifdef HAS_AIRTUNES
if (!StartAirTunesServer())
{
@@ -223,6 +217,12 @@ bool CNetworkServices::OnSettingChanging(const CSetting *setting)
return false;
}
#endif //HAS_AIRTUNES
+
+ if (!StartAirPlayServer())
+ {
+ CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1273), "", g_localizeStrings.Get(33100), "");
+ return false;
+ }
}
else
{
@@ -402,8 +402,8 @@ void CNetworkServices::Start()
CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33102), g_localizeStrings.Get(33100));
if (CSettings::Get().GetBool("services.esenabled") && !StartJSONRPCServer())
CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33103), g_localizeStrings.Get(33100));
- StartAirPlayServer();
StartAirTunesServer();
+ StartAirPlayServer();
StartRss();
}
--
1.8.5.5
From 9cfabede54d59aafff8aece7e4270f32422d03b3 Mon Sep 17 00:00:00 2001
From: Memphiz <memphis@machzwo.de>
Date: Tue, 11 Mar 2014 20:31:58 +0100
Subject: [PATCH 2/3] [zeroconf] - add method to reannounce already published
services
---
xbmc/network/Zeroconf.cpp | 11 +++++++++++
xbmc/network/Zeroconf.h | 15 ++++++++++++++-
xbmc/network/linux/ZeroconfAvahi.cpp | 20 ++++++++++++++++++++
xbmc/network/linux/ZeroconfAvahi.h | 1 +
xbmc/network/mdns/ZeroconfMDNS.cpp | 36 +++++++++++++++++++++++++++++++-----
xbmc/network/mdns/ZeroconfMDNS.h | 9 ++++++++-
xbmc/network/osx/ZeroconfOSX.cpp | 26 ++++++++++++++++++++++++++
xbmc/network/osx/ZeroconfOSX.h | 2 ++
8 files changed, 113 insertions(+), 7 deletions(-)
diff --git a/xbmc/network/Zeroconf.cpp b/xbmc/network/Zeroconf.cpp
index ac13ac4..1569ec4 100644
--- a/xbmc/network/Zeroconf.cpp
+++ b/xbmc/network/Zeroconf.cpp
@@ -45,6 +45,8 @@ class CZeroconfDummy : public CZeroconf
{
return false;
}
+
+ virtual bool doForceReAnnounceService(const std::string&){return false;}
virtual bool doRemoveService(const std::string& fcr_ident){return false;}
virtual void doStop(){}
};
@@ -93,6 +95,15 @@ bool CZeroconf::RemoveService(const std::string& fcr_identifier)
return true;
}
+bool CZeroconf::ForceReAnnounceService(const std::string& fcr_identifier)
+{
+ if (HasService(fcr_identifier) && m_started)
+ {
+ return doForceReAnnounceService(fcr_identifier);
+ }
+ return false;
+}
+
bool CZeroconf::HasService(const std::string& fcr_identifier) const
{
return (m_service_map.find(fcr_identifier) != m_service_map.end());
diff --git a/xbmc/network/Zeroconf.h b/xbmc/network/Zeroconf.h
index 441c0c1..d87e34c 100644
--- a/xbmc/network/Zeroconf.h
+++ b/xbmc/network/Zeroconf.h
@@ -40,7 +40,7 @@ class CZeroconf
public:
//tries to publish this service via zeroconf
- //fcr_identifier can be used to stop this service later
+ //fcr_identifier can be used to stop or reannounce this service later
//fcr_type is the zeroconf service type to publish (e.g. _http._tcp for webserver)
//fcr_name is the name of the service to publish. The hostname is currently automatically appended
// and used for name collisions. e.g. XBMC would get published as fcr_name@Martn or, after collision fcr_name@Martn-2
@@ -51,6 +51,14 @@ class CZeroconf
const std::string& fcr_name,
unsigned int f_port,
std::vector<std::pair<std::string, std::string> > txt /*= std::vector<std::pair<std::string, std::string> >()*/);
+
+ //tries to rebroadcast that service on the network without removing/readding
+ //this can be achieved by changing a fake txt record. Implementations should
+ //implement it by doing so.
+ //
+ //fcr_identifier - the identifier of the already published service which should be reannounced
+ // returns true on successfull reannonuce - false if this service isn't published yet
+ bool ForceReAnnounceService(const std::string& fcr_identifier);
///removes the specified service
///returns false if fcr_identifier does not exist
@@ -90,6 +98,11 @@ class CZeroconf
const std::string& fcr_name,
unsigned int f_port,
const std::vector<std::pair<std::string, std::string> >& txt) = 0;
+
+ //methods to implement for concrete implementations
+ //update this service
+ virtual bool doForceReAnnounceService(const std::string& fcr_identifier) = 0;
+
//removes the service if published
virtual bool doRemoveService(const std::string& fcr_ident) = 0;
diff --git a/xbmc/network/linux/ZeroconfAvahi.cpp b/xbmc/network/linux/ZeroconfAvahi.cpp
index 355b7ce..e9199b9 100644
--- a/xbmc/network/linux/ZeroconfAvahi.cpp
+++ b/xbmc/network/linux/ZeroconfAvahi.cpp
@@ -167,6 +167,26 @@ bool CZeroconfAvahi::doPublishService(const std::string& fcr_identifier,
return true;
}
+bool CZeroconfAvahi::doForceReAnnounceService(const std::string& fcr_identifier)
+{
+ bool ret = false;
+ ScopedEventLoopBlock l_block(mp_poll);
+ tServiceMap::iterator it = m_services.find(fcr_identifier);
+ if (it != m_services.end())
+ {
+ // to force a reannounce on avahi its enough to reverse the txtrecord list
+ it->second->mp_txt = avahi_string_list_reverse(it->second->mp_txt);
+
+ // this will trigger the reannouncement
+ if ((avahi_entry_group_update_service_txt_strlst(it->second->mp_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0),
+ it->second->m_name.c_str(),
+ it->second->m_type.c_str(), NULL, it->second->mp_txt)) >= 0)
+ ret = true;
+ }
+
+ return ret;
+}
+
bool CZeroconfAvahi::doRemoveService(const std::string& fcr_ident)
{
CLog::Log(LOGDEBUG, "CZeroconfAvahi::doRemoveService named: %s", fcr_ident.c_str());
diff --git a/xbmc/network/linux/ZeroconfAvahi.h b/xbmc/network/linux/ZeroconfAvahi.h
index 281dc21..e0b46b5 100644
--- a/xbmc/network/linux/ZeroconfAvahi.h
+++ b/xbmc/network/linux/ZeroconfAvahi.h
@@ -50,6 +50,7 @@ class CZeroconfAvahi : public CZeroconf
unsigned int f_port,
const std::vector<std::pair<std::string, std::string> >& txt);
+ virtual bool doForceReAnnounceService(const std::string& fcr_identifier);
virtual bool doRemoveService(const std::string& fcr_ident);
virtual void doStop();
diff --git a/xbmc/network/mdns/ZeroconfMDNS.cpp b/xbmc/network/mdns/ZeroconfMDNS.cpp
index b81ea11..00d02c5 100644
--- a/xbmc/network/mdns/ZeroconfMDNS.cpp
+++ b/xbmc/network/mdns/ZeroconfMDNS.cpp
@@ -144,21 +144,46 @@ bool CZeroconfMDNS::doPublishService(const std::string& fcr_identifier,
else
{
CSingleLock lock(m_data_guard);
- m_services.insert(make_pair(fcr_identifier, netService));
+ struct tServiceRef newService;
+ newService.serviceRef = netService;
+ newService.txtRecordRef = txtRecord;
+ newService.updateNumber = 0;
+ m_services.insert(make_pair(fcr_identifier, newService));
}
- TXTRecordDeallocate(&txtRecord);
-
return err == kDNSServiceErr_NoError;
}
+bool CZeroconfMDNS::doForceReAnnounceService(const std::string& fcr_identifier)
+{
+ bool ret = false;
+ CSingleLock lock(m_data_guard);
+ tServiceMap::iterator it = m_services.find(fcr_identifier);
+ if(it != m_services.end())
+ {
+ // for force announcing a service with mdns we need
+ // to change a txt record - so we diddle between
+ // even and odd dummy records here
+ if ( (it->second.updateNumber % 2) == 0)
+ TXTRecordSetValue(&it->second.txtRecordRef, "xbmcdummy", strlen("evendummy"), "evendummy");
+ else
+ TXTRecordSetValue(&it->second.txtRecordRef, "xbmcdummy", strlen("odddummy"), "odddummy");
+ it->second.updateNumber++;
+
+ if (DNSServiceUpdateRecord(it->second.serviceRef, NULL, 0, TXTRecordGetLength(&it->second.txtRecordRef), TXTRecordGetBytesPtr(&it->second.txtRecordRef), 0) == kDNSServiceErr_NoError)
+ ret = true;
+ }
+ return ret;
+}
+
bool CZeroconfMDNS::doRemoveService(const std::string& fcr_ident)
{
CSingleLock lock(m_data_guard);
tServiceMap::iterator it = m_services.find(fcr_ident);
if(it != m_services.end())
{
- DNSServiceRefDeallocate(it->second);
+ DNSServiceRefDeallocate(it->second.serviceRef);
+ TXTRecordDeallocate(&it->second.txtRecordRef);
m_services.erase(it);
CLog::Log(LOGDEBUG, "ZeroconfMDNS: Removed service %s", fcr_ident.c_str());
return true;
@@ -174,7 +199,8 @@ void CZeroconfMDNS::doStop()
CLog::Log(LOGDEBUG, "ZeroconfMDNS: Shutdown services");
for(tServiceMap::iterator it = m_services.begin(); it != m_services.end(); ++it)
{
- DNSServiceRefDeallocate(it->second);
+ DNSServiceRefDeallocate(it->second.serviceRef);
+ TXTRecordDeallocate(&it->second.txtRecordRef);
CLog::Log(LOGDEBUG, "ZeroconfMDNS: Removed service %s", it->first.c_str());
}
m_services.clear();
diff --git a/xbmc/network/mdns/ZeroconfMDNS.h b/xbmc/network/mdns/ZeroconfMDNS.h
index 075c22e..0156691 100644
--- a/xbmc/network/mdns/ZeroconfMDNS.h
+++ b/xbmc/network/mdns/ZeroconfMDNS.h
@@ -44,6 +44,7 @@ class CZeroconfMDNS : public CZeroconf,public CThread
unsigned int f_port,
const std::vector<std::pair<std::string, std::string> >& txt);
+ bool doForceReAnnounceService(const std::string& fcr_identifier);
bool doRemoveService(const std::string& fcr_ident);
virtual void doStop();
@@ -65,7 +66,13 @@ class CZeroconfMDNS : public CZeroconf,public CThread
//lock + data (accessed from runloop(main thread) + the rest)
CCriticalSection m_data_guard;
- typedef std::map<std::string, DNSServiceRef> tServiceMap;
+ struct tServiceRef
+ {
+ DNSServiceRef serviceRef;
+ TXTRecordRef txtRecordRef;
+ int updateNumber;
+ };
+ typedef std::map<std::string, struct tServiceRef> tServiceMap;
tServiceMap m_services;
DNSServiceRef m_service;
};
diff --git a/xbmc/network/osx/ZeroconfOSX.cpp b/xbmc/network/osx/ZeroconfOSX.cpp
index 298dea4..24ad68c 100644
--- a/xbmc/network/osx/ZeroconfOSX.cpp
+++ b/xbmc/network/osx/ZeroconfOSX.cpp
@@ -125,6 +125,32 @@ bool CZeroconfOSX::doPublishService(const std::string& fcr_identifier,
return result;
}
+bool CZeroconfOSX::doForceReAnnounceService(const std::string& fcr_identifier)
+{
+ bool ret = false;
+ CSingleLock lock(m_data_guard);
+ tServiceMap::iterator it = m_services.find(fcr_identifier);
+ if(it != m_services.end())
+ {
+ CFNetServiceRef service = it->second;
+
+ CFDataRef txtData = CFNetServiceGetTXTData(service);
+ // convert the txtdata back and forth is enough to trigger a reannounce later
+ CFDictionaryRef txtDict = CFNetServiceCreateDictionaryWithTXTData(NULL, txtData);
+ CFMutableDictionaryRef txtDictMutable =CFDictionaryCreateMutableCopy(NULL, 0, txtDict);
+ txtData = CFNetServiceCreateTXTDataWithDictionary(NULL, txtDictMutable);
+
+ // this triggers the reannounce
+ ret = CFNetServiceSetTXTData(service, txtData);
+
+ CFRelease(txtDictMutable);
+ CFRelease(txtDict);
+ CFRelease(txtData);
+ }
+ return ret;
+}
+
+
bool CZeroconfOSX::doRemoveService(const std::string& fcr_ident)
{
CSingleLock lock(m_data_guard);
diff --git a/xbmc/network/osx/ZeroconfOSX.h b/xbmc/network/osx/ZeroconfOSX.h
index 368c2d4..8952a96 100644
--- a/xbmc/network/osx/ZeroconfOSX.h
+++ b/xbmc/network/osx/ZeroconfOSX.h
@@ -45,6 +45,8 @@ class CZeroconfOSX : public CZeroconf
unsigned int f_port,
const std::vector<std::pair<std::string, std::string> >& txt);
+ bool doForceReAnnounceService(const std::string& fcr_identifier);
+
bool doRemoveService(const std::string& fcr_ident);
virtual void doStop();
--
1.8.5.5
From 16d31f8914520d89de53ae19ce7b4d5eb8f4fa29 Mon Sep 17 00:00:00 2001
From: Memphiz <memphis@machzwo.de>
Date: Tue, 11 Mar 2014 20:32:22 +0100
Subject: [PATCH 3/3] [airplay] - reannounce airplay service every 10 secs
(fixes ios7 clients not detecting us when their wlan was asleep or they saw
the airplay announcement before the airtunes annoncement)
---
xbmc/network/AirPlayServer.cpp | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp
index 7db6754..4c93368 100644
--- a/xbmc/network/AirPlayServer.cpp
+++ b/xbmc/network/AirPlayServer.cpp
@@ -43,6 +43,9 @@
#include "URL.h"
#include "cores/IPlayer.h"
#include "interfaces/AnnouncementManager.h"
+#ifdef HAS_ZEROCONF
+#include "network/Zeroconf.h"
+#endif // HAS_ZEROCONF
using namespace ANNOUNCEMENT;
@@ -277,6 +280,18 @@ void CAirPlayServer::AnnounceToClients(int state)
CAnnouncementManager::RemoveAnnouncer(this);
}
+void handleZeroconfAnnouncement()
+{
+#if defined(HAS_ZEROCONF)
+ static XbmcThreads::EndTime timeout(10000);
+ if(timeout.IsTimePast())
+ {
+ CZeroconf::GetInstance()->ForceReAnnounceService("servers.airplay");
+ timeout.Set(10000);
+ }
+#endif
+}
+
void CAirPlayServer::Process()
{
m_bStop = false;
@@ -357,6 +372,12 @@ void CAirPlayServer::Process()
}
}
}
+
+ // by reannouncing the zeroconf service
+ // we fix issues where xbmc is detected
+ // as audio-only target on devices with
+ // ios7 and later
+ handleZeroconfAnnouncement();
}
Deinitialize();
--
1.8.5.5