2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
20 #include "system.h" //HAS_ZEROCONF define
23 #include "settings/Settings.h"
25 #if defined(HAS_AVAHI)
26 #include "linux/ZeroconfAvahi.h"
27 #elif defined(TARGET_DARWIN)
28 //on osx use the native implementation
29 #include "osx/ZeroconfOSX.h"
30 #elif defined(HAS_MDNS)
31 #include "mdns/ZeroconfMDNS.h"
34 #include "threads/CriticalSection.h"
35 #include "threads/SingleLock.h"
36 #include "threads/Atomics.h"
37 #include "utils/JobManager.h"
40 //dummy implementation used if no zeroconf is present
41 //should be optimized away
42 class CZeroconfDummy : public CZeroconf
44 virtual bool doPublishService(const std::string&, const std::string&, const std::string&, unsigned int, const std::vector<std::pair<std::string, std::string> >&)
49 virtual bool doForceReAnnounceService(const std::string&){return false;}
50 virtual bool doRemoveService(const std::string& fcr_ident){return false;}
51 virtual void doStop(){}
55 long CZeroconf::sm_singleton_guard = 0;
56 CZeroconf* CZeroconf::smp_instance = 0;
58 CZeroconf::CZeroconf():mp_crit_sec(new CCriticalSection),m_started(false)
62 CZeroconf::~CZeroconf()
67 bool CZeroconf::PublishService(const std::string& fcr_identifier,
68 const std::string& fcr_type,
69 const std::string& fcr_name,
71 std::vector<std::pair<std::string, std::string> > txt /* = std::vector<std::pair<std::string, std::string> >() */)
73 CSingleLock lock(*mp_crit_sec);
74 CZeroconf::PublishInfo info = {fcr_type, fcr_name, f_port, txt};
75 std::pair<tServiceMap::const_iterator, bool> ret = m_service_map.insert(std::make_pair(fcr_identifier, info));
76 if(!ret.second) //identifier exists
79 CJobManager::GetInstance().AddJob(new CPublish(fcr_identifier, info), NULL);
81 //not yet started, so its just queued
85 bool CZeroconf::RemoveService(const std::string& fcr_identifier)
87 CSingleLock lock(*mp_crit_sec);
88 tServiceMap::iterator it = m_service_map.find(fcr_identifier);
89 if(it == m_service_map.end())
91 m_service_map.erase(it);
93 return doRemoveService(fcr_identifier);
98 bool CZeroconf::ForceReAnnounceService(const std::string& fcr_identifier)
100 if (HasService(fcr_identifier) && m_started)
102 return doForceReAnnounceService(fcr_identifier);
107 bool CZeroconf::HasService(const std::string& fcr_identifier) const
109 return (m_service_map.find(fcr_identifier) != m_service_map.end());
112 bool CZeroconf::Start()
114 CSingleLock lock(*mp_crit_sec);
115 if(!IsZCdaemonRunning())
117 CSettings::Get().SetBool("services.zeroconf", false);
118 if (CSettings::Get().GetBool("services.airplay"))
119 CSettings::Get().SetBool("services.airplay", false);
126 CJobManager::GetInstance().AddJob(new CPublish(m_service_map), NULL);
130 void CZeroconf::Stop()
132 CSingleLock lock(*mp_crit_sec);
139 CZeroconf* CZeroconf::GetInstance()
141 CAtomicSpinLock lock(sm_singleton_guard);
145 smp_instance = new CZeroconfDummy;
147 #if defined(TARGET_DARWIN)
148 smp_instance = new CZeroconfOSX;
149 #elif defined(HAS_AVAHI)
150 smp_instance = new CZeroconfAvahi;
151 #elif defined(HAS_MDNS)
152 smp_instance = new CZeroconfMDNS;
156 assert(smp_instance);
160 void CZeroconf::ReleaseInstance()
162 CAtomicSpinLock lock(sm_singleton_guard);
167 CZeroconf::CPublish::CPublish(const std::string& fcr_identifier, const PublishInfo& pubinfo)
169 m_servmap.insert(std::make_pair(fcr_identifier, pubinfo));
172 CZeroconf::CPublish::CPublish(const tServiceMap& servmap)
177 bool CZeroconf::CPublish::DoWork()
179 for(tServiceMap::const_iterator it = m_servmap.begin(); it != m_servmap.end(); ++it)
180 CZeroconf::GetInstance()->doPublishService(it->first, it->second.type, it->second.name, it->second.port, it->second.txt);