]> git.vomp.tv Git - vompclient.git/blob - vconnect.cc
OSDOpenVG: Render on demand: Fix backing out of a view render race
[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 "video.h"
22 #include "colour.h"
23 #include "control.h"
24 #include "i18n.h"
25 #include "boxstack.h"
26 #include "message.h"
27 #include "log.h"
28 #include "vdr.h"
29 #include "wol.h"
30 #include "vserverselect.h"
31 #include "messagequeue.h"
32 #include "util.h"
33
34 #include "vconnect.h"
35
36 VConnect::VConnect()
37 {
38   boxstack = BoxStack::getInstance();
39   vdr = VDR::getInstance();
40   logger = Log::getInstance();
41
42   setSize(400, 200);
43   createBuffer();
44   if (Video::getInstance()->getFormat() == Video::PAL)
45   {
46     setPosition(170, 200);
47   }
48   else
49   {
50     setPosition(160, 150);
51   }
52
53   exitable = 0;
54 }
55
56 VConnect::~VConnect()
57 {
58   threadReqQuit = true;
59   vdpc.stop();
60   stop();
61 }
62
63 void VConnect::draw()
64 {
65   VInfo::draw();
66   logger->log("VConnect", Log::DEBUG, "Draw done");
67 }
68
69 int VConnect::handleCommand(int /* command */)
70 {
71   return 1;
72 }
73
74 void VConnect::run()
75 {
76   threadMutex.lock();
77   threadReqQuit = false;
78   connectThread = std::thread([this]
79   {
80     threadMutex.lock();
81     threadMutex.unlock();
82     threadMethod();
83   });
84   threadMutex.unlock();
85 }
86
87 void VConnect::stop()
88 {
89   threadMutex.lock();
90   threadReqQuit = true;
91   vdr->abortConnect(); // If this and vdr are connecting, cancel it
92   threadCond.notify_one();
93   threadMutex.unlock();
94   connectThread.join();
95 }
96
97 void VConnect::threadMethod()
98 {
99   logger->log("VConnect", Log::DEBUG, "start threadMethod");
100
101   ULONG delay = 0;
102   int success;
103
104   std::unique_lock<std::mutex> ul(threadMutex, std::defer_lock);
105
106   const std::string& commandLineServer = getCommandLineServer();
107
108   if (!vdpc.init())
109   {
110     logger->log("VConnect", Log::CRIT, "Failed to init VDPC");
111     return;
112   }
113
114   do
115   {
116     if (!commandLineServer.empty()) // Server is specified, fake a servers array
117     {
118       //servers.emplace_back(commandLineServer, "", 3024, 0);
119       vdpc.TEMPaddCLIServer(commandLineServer); // FIXME move to new config system NCONFIG
120     }
121     else
122     {
123       setOneLiner(tr("Locating server"));
124       draw();
125       boxstack->update(this);
126       vdpc.go();
127       if (threadReqQuit) return;
128     }
129
130     for (ULONG i = 0; i < vdpc.numServers(); i++)
131       logger->log("VConnect", Log::INFO, "Found server: %i %s %s %u", vdpc[i].ipVersion, vdpc[i].ip.c_str(), vdpc[i].name.c_str(), vdpc[i].port, vdpc[i].version);
132
133     if (vdpc.numServers() == 1)
134     {
135       selectedServer = 0;
136     }
137     else
138     {
139       selectedServer = -1;
140       VServerSelect* vs = new VServerSelect(vdpc, this);
141       vs->draw();
142       boxstack->add(vs);
143       boxstack->update(vs);
144
145       ul.lock();
146       if (threadReqQuit) { ul.unlock(); return; }
147       threadCond.wait(ul);
148       ul.unlock();
149     }
150
151     if (threadReqQuit) return;
152
153     logger->log("VConnect", Log::NOTICE, "Connecting to server at %s %u", vdpc[selectedServer].ip.c_str(), vdpc[selectedServer].port);
154     Wol::getInstance()->setWakeUpIP(vdpc[selectedServer].ip.c_str());
155     vdr->setServerIP(vdpc[selectedServer].ip.c_str());
156     vdr->setServerPort(vdpc[selectedServer].port);
157
158     setOneLiner(tr("Connecting to VDR"));
159     draw();
160     boxstack->update(this);
161
162     if (threadReqQuit) return;
163     success = vdr->connect();
164     if (threadReqQuit) return;
165
166     if (success)
167     {
168       logger->log("VConnect", Log::DEBUG, "Connected ok, doing login");
169       unsigned int version_server_min, version_server_max, version_client;
170       int subtitles;
171       success = vdr->doLogin(&version_server_min, &version_server_max, &version_client, Control::getInstance()->getASLList(), subtitles);
172       Control::getInstance()->setSubDefault(subtitles);
173
174       if (!success)
175       {
176         vdr->disconnect();
177         if (version_server_min >version_client || version_client > version_server_max) {
178                 char buffer[1024];
179                 sprintf(buffer,"Version error: s min: %x s max: %x c: %x",version_server_min,version_server_max,version_client);
180                 setOneLiner(buffer);
181         } else {
182                 setOneLiner(tr("Login failed"));
183         }
184         delay = 3000;
185       }
186     }
187     else
188     {
189       setOneLiner(tr("Connection failed"));
190       delay = 3000;
191     }
192
193     draw();
194     boxstack->update(this);
195
196     MILLISLEEP(delay); // FIXME wait on cond?
197     if (threadReqQuit) return;
198   } while(!success);
199
200   logger->log("VConnect", Log::INFO, "Send VDR connected message");
201   Message* m = new Message(); // Must be done after this thread ends
202   m->from = this;
203   m->p_to = Message::CONTROL;
204   m->message = Message::VDR_CONNECTED;
205   MessageQueue::getInstance()->postMessage(m);
206 }
207
208 void VConnect::processMessage(Message* m)
209 {
210   if (m->message == Message::SERVER_SELECTED)
211   {
212     selectedServer = m->parameter;
213     threadCond.notify_one();
214   }
215 }