Logging improvements to allow prettier displays in the server GUI.
[dcpomatic.git] / src / lib / server_finder.cc
index bef00702f800c8ae7d503304b058d6ee746d6b43..642767e8bdda60f1c5e2f751619015da886c4382 100644 (file)
 #include "util.h"
 #include "config.h"
 #include "cross.h"
-#include "ui_signaller.h"
+#include "server_description.h"
 #include "dcpomatic_socket.h"
+#include "raw_convert.h"
 #include <libcxml/cxml.h>
-#include <dcp/raw_convert.h>
 #include <boost/lambda/lambda.hpp>
+#include <iostream>
 
 #include "i18n.h"
 
@@ -37,17 +38,22 @@ using std::cout;
 using boost::shared_ptr;
 using boost::scoped_array;
 using boost::weak_ptr;
-using dcp::raw_convert;
 
 ServerFinder* ServerFinder::_instance = 0;
 
 ServerFinder::ServerFinder ()
        : _disabled (false)
-       , _broadcast_thread (0)
+       , _search_thread (0)
        , _listen_thread (0)
        , _stop (false)
 {
-       _broadcast_thread = new boost::thread (boost::bind (&ServerFinder::broadcast_thread, this));
+       Config::instance()->Changed.connect (boost::bind (&ServerFinder::config_changed, this, _1));
+}
+
+void
+ServerFinder::start ()
+{
+       _search_thread = new boost::thread (boost::bind (&ServerFinder::search_thread, this));
        _listen_thread = new boost::thread (boost::bind (&ServerFinder::listen_thread, this));
 }
 
@@ -55,15 +61,21 @@ ServerFinder::~ServerFinder ()
 {
        _stop = true;
 
-       _broadcast_thread->interrupt ();
-       _broadcast_thread->join ();
+       _search_condition.notify_all ();
+       if (_search_thread) {
+               DCPOMATIC_ASSERT (_search_thread->joinable ());
+               _search_thread->join ();
+       }
 
        _listen_io_service.stop ();
-       _listen_thread->join ();
+       if (_listen_thread) {
+               DCPOMATIC_ASSERT (_listen_thread->joinable ());
+               _listen_thread->join ();
+       }
 }
 
 void
-ServerFinder::broadcast_thread ()
+ServerFinder::search_thread ()
 try
 {
        boost::system::error_code error;
@@ -78,7 +90,7 @@ try
         socket.set_option (boost::asio::socket_base::broadcast (true));
 
        string const data = DCPOMATIC_HELLO;
-       
+
        while (!_stop) {
                if (Config::instance()->use_any_servers ()) {
                        /* Broadcast to look for servers */
@@ -107,11 +119,8 @@ try
                        }
                }
 
-               try {
-                       boost::thread::sleep (boost::get_system_time() + boost::posix_time::seconds (10));
-               } catch (boost::thread_interrupted& e) {
-                       return;
-               }
+               boost::mutex::scoped_lock lm (_search_condition_mutex);
+               _search_condition.timed_wait (lm, boost::get_system_time() + boost::posix_time::seconds (10));
        }
 }
 catch (...)
@@ -155,26 +164,26 @@ ServerFinder::handle_accept (boost::system::error_code ec, shared_ptr<Socket> so
                start_accept ();
                return;
        }
-       
+
        uint32_t length;
        socket->read (reinterpret_cast<uint8_t*> (&length), sizeof (uint32_t));
        length = ntohl (length);
-       
+
        scoped_array<char> buffer (new char[length]);
        socket->read (reinterpret_cast<uint8_t*> (buffer.get()), length);
-       
+
        string s (buffer.get());
        shared_ptr<cxml::Document> xml (new cxml::Document ("ServerAvailable"));
        xml->read_string (s);
-       
+
        string const ip = socket->socket().remote_endpoint().address().to_string ();
-       if (!server_found (ip)) {
+       if (!server_found (ip) && xml->optional_number_child<int>("Version").get_value_or (0) == SERVER_LINK_VERSION) {
                ServerDescription sd (ip, xml->number_child<int> ("Threads"));
                {
-                       boost::mutex::scoped_lock lm (_mutex);
+                       boost::mutex::scoped_lock lm (_servers_mutex);
                        _servers.push_back (sd);
                }
-               ui_signaller->emit (boost::bind (boost::ref (ServerFound), sd));
+               emit (boost::bind (boost::ref (ServersListChanged)));
        }
 
        start_accept ();
@@ -183,7 +192,7 @@ ServerFinder::handle_accept (boost::system::error_code ec, shared_ptr<Socket> so
 bool
 ServerFinder::server_found (string ip) const
 {
-       boost::mutex::scoped_lock lm (_mutex);
+       boost::mutex::scoped_lock lm (_servers_mutex);
        list<ServerDescription>::const_iterator i = _servers.begin();
        while (i != _servers.end() && i->host_name() != ip) {
                ++i;
@@ -192,28 +201,12 @@ ServerFinder::server_found (string ip) const
        return i != _servers.end ();
 }
 
-void
-ServerFinder::connect (boost::function<void (ServerDescription)> fn)
-{
-       if (_disabled) {
-               return;
-       }
-       
-       boost::mutex::scoped_lock lm (_mutex);
-
-       /* Emit the current list of servers */
-       for (list<ServerDescription>::iterator i = _servers.begin(); i != _servers.end(); ++i) {
-               fn (*i);
-       }
-
-       ServerFound.connect (fn);
-}
-
 ServerFinder*
 ServerFinder::instance ()
 {
        if (!_instance) {
                _instance = new ServerFinder ();
+               _instance->start ();
        }
 
        return _instance;
@@ -225,3 +218,29 @@ ServerFinder::drop ()
        delete _instance;
        _instance = 0;
 }
+
+list<ServerDescription>
+ServerFinder::servers () const
+{
+       boost::mutex::scoped_lock lm (_servers_mutex);
+       return _servers;
+}
+
+void
+ServerFinder::config_changed (Config::Property what)
+{
+       if (what == Config::USE_ANY_SERVERS || what == Config::SERVERS) {
+               {
+                       boost::mutex::scoped_lock lm (_servers_mutex);
+                       _servers.clear ();
+               }
+               ServersListChanged ();
+               search_now ();
+       }
+}
+
+void
+ServerFinder::search_now ()
+{
+       _search_condition.notify_all ();
+}