]> git.vomp.tv Git - vompclient.git/blob - vconnect.cc
Convert VConnect to std::thread
[vompclient.git] / vconnect.cc
1 /*
2     Copyright 2004-2020 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "video.h"
21 #include "colour.h"
22 #include "command.h"
23 #include "i18n.h"
24 #include "boxstack.h"
25 #include "message.h"
26 #include "log.h"
27 #include "wol.h"
28 #include "vserverselect.h"
29 #include "messagequeue.h"
30
31 #include "vconnect.h"
32
33 VConnect::VConnect(char* tServer)
34 : server(tServer)
35 {
36   boxstack = BoxStack::getInstance();
37   vdr = VDR::getInstance();
38   logger = Log::getInstance();
39
40   setSize(400, 200);
41   createBuffer();
42   if (Video::getInstance()->getFormat() == Video::PAL)
43   {
44     setPosition(170, 200);
45   }
46   else
47   {
48     setPosition(160, 150);
49   }
50
51   exitable = 0;
52 }
53
54 VConnect::~VConnect()
55 {
56   threadReqQuit = true;
57   vdr->cancelFindingServer();
58   stop();
59 }
60
61 void VConnect::draw()
62 {
63   VInfo::draw();
64   logger->log("VConnect", Log::DEBUG, "Draw done");
65 }
66
67 int VConnect::handleCommand(int /* command */)
68 {
69   return 1;
70 }
71
72 void VConnect::run()
73 {
74   threadMutex.lock();
75   threadReqQuit = false;
76   connectThread = std::thread([this]
77   {
78     threadMutex.lock();
79     threadMutex.unlock();
80     threadMethod();
81   });
82   threadMutex.unlock();
83 }
84
85 void VConnect::stop()
86 {
87   threadMutex.lock();
88   threadReqQuit = true;
89   threadCond.notify_one();
90   threadMutex.unlock();
91   connectThread.join();
92 }
93
94 void VConnect::threadMethod()
95 {
96   ULONG delay = 0;
97   int success;
98
99   std::unique_lock<std::mutex> ul(threadMutex, std::defer_lock);
100
101   do
102   {
103     if (server) // Server is specified, fake a servers array
104     {
105       VDRServer vdrserver;
106       vdrserver.ip = new char[strlen(server)+1];
107       strcpy(vdrserver.ip, server);
108       vdrserver.name = new char[1];
109       vdrserver.name[0] = '\0';
110       vdrserver.port = 3024; // FIXME
111       servers.push_back(vdrserver);
112     }
113     else
114     {
115       setOneLiner(tr("Locating server"));
116       draw();
117       boxstack->update(this);
118
119       vdr->findServers(servers);
120       if (threadReqQuit)
121       {
122         for(UINT k = 0; k < servers.size(); k++)
123         {
124           delete[] servers[k].ip;
125           delete[] servers[k].name;
126         }
127         servers.clear();
128         return;
129       }
130     }
131
132     if (servers.size() == 1)
133     {
134       selectedServer = 0;
135     }
136     else
137     {
138       selectedServer = -1;
139       VServerSelect* vs = new VServerSelect(servers, this);
140       vs->draw();
141       boxstack->add(vs);
142       boxstack->update(vs);
143
144       ul.lock();
145       if (threadReqQuit) { ul.unlock(); return; }
146       threadCond.wait(ul);
147       ul.unlock();
148     }
149
150     if (threadReqQuit)
151     {
152       for(UINT k = 0; k < servers.size(); k++)
153       {
154         delete[] servers[k].ip;
155         delete[] servers[k].name;
156       }
157       servers.clear();
158       return;
159     }
160
161     logger->log("VConnect", Log::NOTICE, "Connecting to server at %s %u", servers[selectedServer].ip, servers[selectedServer].port);
162     Wol::getInstance()->setWakeUpIP(servers[selectedServer].ip);
163     vdr->setServerIP(servers[selectedServer].ip);
164     vdr->setServerPort(servers[selectedServer].port);
165
166     // Clear the serverIPs vector
167     for(UINT k = 0; k < servers.size(); k++)
168     {
169       delete[] servers[k].ip;
170       delete[] servers[k].name;
171     }
172     servers.clear();
173
174
175     setOneLiner(tr("Connecting to VDR"));
176     draw();
177     boxstack->update(this);
178
179     success = vdr->connect();
180     if (success)
181     {
182       logger->log("VConnect", Log::DEBUG, "Connected ok, doing login");
183       unsigned int version_server_min,version_server_max,version_client;
184       int subtitles;
185       success = vdr->doLogin(&version_server_min,&version_server_max,&version_client, Command::getInstance()->getASLList(), subtitles);
186       Command::getInstance()->setSubDefault(subtitles);
187
188       if (!success)
189       {
190         vdr->disconnect();
191         if (version_server_min >version_client || version_client > version_server_max) {
192                 char buffer[1024];
193                 sprintf(buffer,"Version error: s min: %x s max: %x c: %x",version_server_min,version_server_max,version_client);
194                 setOneLiner(buffer);
195         } else {
196                 setOneLiner(tr("Login failed"));
197         }
198         delay = 3000;
199       }
200     }
201     else
202     {
203       setOneLiner(tr("Connection failed"));
204       delay = 3000;
205     }
206
207     draw();
208     boxstack->update(this);
209     MILLISLEEP(delay);
210
211   } while(!success);
212
213   logger->log("VConnect", Log::INFO, "Send VDR connected message");
214   Message* m = new Message(); // Must be done after this thread ends
215   m->from = this;
216   m->to = Command::getInstance();
217   m->message = Message::VDR_CONNECTED;
218   MessageQueue::getInstance()->postMessage(m);
219 }
220
221 void VConnect::processMessage(Message* m)
222 {
223   if (m->message == Message::SERVER_SELECTED)
224   {
225     selectedServer = m->parameter;
226     threadCond.notify_one();
227   }
228 }