]> git.vomp.tv Git - vompclient.git/blob - vconnect.cc
Server address/port to config. Clean up VConnect
[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 "defines.h"
21 #include "config.h"
22 #include "video.h"
23 #include "colour.h"
24 #include "control.h"
25 #include "i18n.h"
26 #include "boxstack.h"
27 #include "message.h"
28 #include "log.h"
29 #include "vdr.h"
30 #include "wol.h"
31 #include "vserverselect.h"
32 #include "messagequeue.h"
33 #include "util.h"
34
35 #include "vconnect.h"
36
37 static const char* TAG = "VConnect";
38
39 VConnect::VConnect()
40 {
41   boxstack = BoxStack::getInstance();
42   vdr = VDR::getInstance();
43   logger = LogNT::getInstance();
44
45   setSize(400, 200);
46   createBuffer();
47   if (Video::getInstance()->getFormat() == Video::PAL)
48   {
49     setPosition(170, 200);
50   }
51   else
52   {
53     setPosition(160, 150);
54   }
55
56   exitable = 0;
57 }
58
59 VConnect::~VConnect()
60 {
61   threadReqQuit = true;
62   vdpc.stop();
63   stop();
64 }
65
66 void VConnect::draw()
67 {
68   VInfo::draw();
69   logger->debug(TAG, "Draw done");
70 }
71
72 int VConnect::handleCommand(int /* command */)
73 {
74   return 1;
75 }
76
77 void VConnect::run()
78 {
79   threadMutex.lock();
80   threadReqQuit = false;
81   connectThread = std::thread([this]
82   {
83     threadMutex.lock();
84     threadMutex.unlock();
85     threadMethod();
86   });
87   threadMutex.unlock();
88 }
89
90 void VConnect::stop()
91 {
92   threadMutex.lock();
93   threadReqQuit = true;
94   vdr->abortConnect(); // If this and vdr are connecting, cancel it
95   threadCond.notify_one();
96   threadMutex.unlock();
97   connectThread.join();
98 }
99
100 void VConnect::threadMethod()
101 {
102   logger->debug(TAG, "start threadMethod");
103
104   ULONG delay = 0;
105   int success;
106
107   std::unique_lock<std::mutex> ul(threadMutex, std::defer_lock);
108
109   VDRServer configServerStr;
110   const VDRServer* selectedServerStr = NULL;
111
112   bool serverFromConfig{}; // FIXME Redesign all this.
113
114   if (Config::getInstance()->getString("server", "address", configServerStr.ip))
115   {
116     configServerStr.port = 3024;
117     int newPort;
118     if (Config::getInstance()->getInt("server", "port", newPort))
119     {
120       configServerStr.port = newPort;
121     }
122
123     selectedServerStr = &configServerStr;
124     serverFromConfig = true;
125   }
126   else // No server specified in config. Start VDPC
127   {
128     if (!vdpc.init())
129     {
130       logger->crit(TAG, "Failed to init VDPC");
131       return;
132     }
133   }
134
135
136   do
137   {
138     if (!selectedServerStr)
139     {
140       setOneLiner(tr("Locating server"));
141       draw();
142       boxstack->update(this);
143       vdpc.go();
144       if (threadReqQuit) return;
145
146       for (ULONG i = 0; i < vdpc.numServers(); i++)
147         logger->info(TAG, "Found server: {} {} {} {}", vdpc[i].ipVersion, vdpc[i].ip.c_str(), vdpc[i].name.c_str(), vdpc[i].port, vdpc[i].version);
148
149       if (vdpc.numServers() == 1)
150       {
151         selectedServer = 0;
152         selectedServerStr = &vdpc[0];
153       }
154       else
155       {
156         selectedServer = -1;
157         VServerSelect* vs = new VServerSelect(vdpc, this); // FIXME is this deleted?
158         vs->draw();
159         boxstack->add(vs);
160         boxstack->update(vs);
161
162         ul.lock();
163         if (threadReqQuit) { ul.unlock(); return; }
164         threadCond.wait(ul);
165
166         // This thread has been notified by VServerSelect. selectedServer is now an index into vdpc of the chosen server
167
168         selectedServerStr = &vdpc[selectedServer];
169
170         ul.unlock();
171       }
172
173       if (threadReqQuit) return;
174     }
175
176
177     logger->info(TAG, "Connecting to server at {} {}", selectedServerStr->ip, selectedServerStr->port);
178     Wol::getInstance()->setWakeUpIP(selectedServerStr->ip.c_str());
179     vdr->setServerIP(selectedServerStr->ip.c_str());
180     vdr->setServerPort(selectedServerStr->port);
181
182     // In case of go around, clear selectedServerStr here if it was discovered
183     if (!serverFromConfig) selectedServerStr = NULL;
184
185
186     setOneLiner(tr("Connecting to VDR"));
187     draw();
188     boxstack->update(this);
189
190     if (threadReqQuit) return;
191     success = vdr->connect();
192     if (threadReqQuit) return;
193
194     if (success)
195     {
196       logger->debug(TAG, "Connected ok, doing login");
197       unsigned int version_server_min, version_server_max, version_client;
198       int subtitles;
199       success = vdr->doLogin(&version_server_min, &version_server_max, &version_client, Control::getInstance()->getASLList(), subtitles);
200       Control::getInstance()->setSubDefault(subtitles);
201
202       if (!success)
203       {
204         vdr->disconnect();
205         if (version_server_min >version_client || version_client > version_server_max) {
206                 char buffer[1024];
207                 sprintf(buffer,"Version error: s min: %x s max: %x c: %x",version_server_min,version_server_max,version_client);
208                 setOneLiner(buffer);
209         } else {
210                 setOneLiner(tr("Login failed"));
211         }
212         delay = 3000;
213       }
214     }
215     else
216     {
217       setOneLiner(tr("Connection failed"));
218       delay = 3000;
219     }
220
221     draw();
222     boxstack->update(this);
223
224     MILLISLEEP(delay); // FIXME wait on cond?
225     if (threadReqQuit) return;
226   } while(!success);
227
228   logger->info(TAG, "Send VDR connected message");
229   Message* m = new Message(); // Must be done after this thread ends
230   m->from = this;
231   m->p_to = Message::CONTROL;
232   m->message = Message::VDR_CONNECTED;
233   MessageQueue::getInstance()->postMessage(m);
234 }
235
236 void VConnect::processMessage(Message* m)
237 {
238   if (m->message == Message::SERVER_SELECTED)
239   {
240     selectedServer = m->parameter;
241     threadCond.notify_one();
242   }
243 }