Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 andreas 1
/*
21 andreas 2
 * Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
2 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
#include <iostream>
19
#include <iomanip>
20
#include <string>
21
#include <vector>
22
#include <algorithm>
23
#include "tconfig.h"
24
#include "tsettings.h"
3 andreas 25
#include "tpagelist.h"
26
#include "tpage.h"
27
#include "tsubpage.h"
28
#include "tpagemanager.h"
2 andreas 29
#include "tqtmain.h"
30
 
22 andreas 31
#ifdef Q_OS_ANDROID
32
#include <QStandardPaths>
33
#endif
34
#ifdef __ANDROID__
35
#include <android/log.h>
36
#endif
37
 
2 andreas 38
using std::string;
39
using std::find;
40
using std::vector;
21 andreas 41
using std::cout;
42
using std::endl;
2 andreas 43
 
90 andreas 44
bool _restart_ = false;
91 andreas 45
#ifdef __ANDROID__
46
extern std::atomic<bool> killed;
47
extern std::atomic<bool> _netRunning;
48
#endif
90 andreas 49
 
21 andreas 50
/**
51
 * @class InputParser
52
 * @brief The InputParser class parses the command line.
53
 *
54
 * This class takes the command line arguments and parses them. It creates an
55
 * internal vector array to hold the parameters.
56
 */
2 andreas 57
class InputParser
58
{
3 andreas 59
    public:
21 andreas 60
        /**
61
         * @brief InputParser is the constructor.
62
         *
63
         * The constructor requires the command line parameters. It immediately
118 andreas 64
         * starts to parse each parameter. If it finds the string `--` it stops
21 andreas 65
         * and ignores the rest of parameters. \p argc contains the rest of
66
         * the parameters after `--`, if there are any.
67
         *
68
         * @param argc  A pointer to the numbers of command line parameters.
69
         *              This parameter must not be `NULL`.
70
         * @param argv  The 2 dimensional array of command line parameters.
71
         *              This parameter must not be `NULL`.
72
         */
3 andreas 73
        InputParser(int *argc, char **argv)
74
        {
75
            int i;
2 andreas 76
 
3 andreas 77
            for (i = 1; i < *argc; ++i)
78
            {
79
                if (string(argv[i]).compare("--") == 0)
80
                    break;
2 andreas 81
 
3 andreas 82
                this->tokens.push_back(string(argv[i]));
83
            }
2 andreas 84
 
3 andreas 85
            *argc -= i;
2 andreas 86
 
3 andreas 87
            if (*argc <= 1)
88
                *argc = 1;
89
            else
90
            {
91
                *argc = *argc + 1;
92
                *(argv + i - 1) = *argv;
93
            }
94
        }
21 andreas 95
        /**
96
         * @brief getCmdOption searches for the command line option \p option.
97
         * @author iain
98
         *
99
         * The method searches for the command line option \p option and
100
         * returns the parameter after the option, if there is one.
101
         *
102
         * @param option    The name of a command line option. This is any
103
         *                  name starting with 1 or 2 dash (-). The name in
104
         *                  the parameter must include the dash(es) in front
105
         *                  of the name.\n
106
         *                  If the option was found and the next parameter on
107
         *                  the command line doesn't start with a dash, the
108
         *                  parameter is returned.
109
         *
110
         * @return Tf the option was found and the parameter on the command
111
         * line following the option doesn't start with a dash, it is returned.
112
         * Otherwise an empty string is returned.
113
         */
3 andreas 114
        const string& getCmdOption(const string &option) const
115
        {
116
            vector<string>::const_iterator itr;
117
            itr = find(this->tokens.begin(), this->tokens.end(), option);
2 andreas 118
 
3 andreas 119
            if (itr != this->tokens.end() && ++itr != this->tokens.end())
120
                return *itr;
2 andreas 121
 
3 andreas 122
            static const string empty_string("");
123
            return empty_string;
124
        }
21 andreas 125
 
126
        /**
127
         * @brief cmdOptionExists tests for an existing option.
128
         * @author iain
129
         *
130
         * This function tests whether the option \p option exists or not. If
131
         * the option was found, it returnes `true`.
132
         *
133
         * @param option    The name of a command line option. This is any
134
         *                  name starting with 1 or 2 dash (-). The name in
135
         *                  the parameter must include the dash(es) in front
136
         *                  of the name.\n
137
         *
138
         * @return If the command line option was found in the internal vector
139
         * array `true` is returned. Otherwise it returnes `false`.
140
         */
3 andreas 141
        bool cmdOptionExists(const string &option) const
142
        {
143
            return find(this->tokens.begin(), this->tokens.end(), option) != this->tokens.end();
144
        }
2 andreas 145
 
3 andreas 146
    private:
147
        vector <string> tokens;
2 andreas 148
};
149
 
21 andreas 150
/**
151
 * @brief usage displays on the standard output a small help.
152
 *
153
 * This function shows a short help with all available parameters and a brief
154
 * description of them.
155
 * \verbatim
156
 * NOTE: This function is not available on Android systems.
157
 * \endverbatim
158
 */
2 andreas 159
void usage()
160
{
21 andreas 161
#ifndef __ANDROID__
162
    cout << TConfig::getProgName() << " version " <<  V_MAJOR << "."  << V_MINOR << "." << V_PATCH << endl << endl;
163
    cout << "Usage: tpanel [-c <config file>]" << endl;
164
    cout << "-c | --config-file <file> The path and name of the configuration file." << endl;
165
    cout << "                          This parameter is optional. If it is omitted," << endl;
166
    cout << "                          The standard path is searched for the" << endl;
167
    cout << "                          configuration file." << endl << endl;
168
    cout << "-h | --help               This help." << endl << endl;
169
#endif
2 andreas 170
}
171
 
22 andreas 172
#ifndef __ANDROID__
21 andreas 173
/**
174
 * @brief banner displays a shor banner with informations about this application.
175
 *
176
 * This function shows a short information about this application. It prints
177
 * this on the standard output.
178
 * \verbatim
179
 * NOTE: This function is not available on Android systems.
180
 * \endverbatim
181
 *
182
 * @param pname The name of this application.
183
 */
2 andreas 184
void banner(const string& pname)
185
{
3 andreas 186
    if (!TConfig::showBanner())
187
        return;
2 andreas 188
 
21 andreas 189
    cout << pname << " v" << V_MAJOR << "."  << V_MINOR << "." << V_PATCH << endl;
190
    cout << "(C) Andreas Theofilu <andreas@theosys.at>" << endl;
191
    cout << "This program is under the terms of GPL version 3" << endl << endl;
22 andreas 192
}
21 andreas 193
#endif
2 andreas 194
 
21 andreas 195
/**
90 andreas 196
 * @brief Is called whenever the program starts up.
197
 *
198
 * This method is called to start up the program. It initializes the main
199
 * classes and waits until the main loop ends.
200
 * It is also called if the program have to start over. This happens when
201
 * the settings change the host, port or channel ID, or after receiving a new
202
 * surface.
203
 *
93 andreas 204
 * @param oldArgc   This is the previous parameter counter (only for desktop).
90 andreas 205
 * @param argc      This is the actual parameter counter.
206
 * @param argv      This is the pointer array to the environment.
207
 *
208
 * @return of success TRUE is returned. Otherwise FALSE.
209
 */
210
bool _startUp(int oldArgc, int argc, char *argv[])
211
{
92 andreas 212
    DECL_TRACER("_startUp(int oldArgc, int argc, char *argv[])");
90 andreas 213
 
92 andreas 214
    TPageManager *pageManager = new TPageManager;
215
 
90 andreas 216
    if (TError::isError())
92 andreas 217
    {
218
        delete pageManager;
119 andreas 219
        pageManager = nullptr;
90 andreas 220
        return false;
92 andreas 221
    }
90 andreas 222
 
223
    // Prepare command line stack
224
#ifndef __ANDROID__
225
    int pt = oldArgc - argc;
226
#else
227
    int pt = 0;
228
#endif
229
    // Start the graphical environment
230
    int ret = 0;
231
 
93 andreas 232
    // The _restart_ variable is reset in class initialization MainWindow.
92 andreas 233
    ret = qtmain(argc, &argv[pt], pageManager);
234
    delete pageManager;
119 andreas 235
    pageManager = nullptr;
90 andreas 236
 
237
    if (ret != 0)
238
        return false;
239
 
240
    return true;
241
}
242
 
243
/**
21 andreas 244
 * @brief main is the main entry function.
245
 *
246
 * This is where the program starts.
247
 *
248
 * @param argc  The number of command line arguments.
249
 * @param argv  A pointer to a 2 dimensional array containing the command line
250
 *              parameters.
251
 *
252
 * @return 0 on success. This means that no errors occured.\n
253
 * In case of an error a number grater than 0 is returned.
254
 */
2 andreas 255
int main(int argc, char *argv[])
256
{
3 andreas 257
    string configFile;
91 andreas 258
    int oldArgc = argc;
22 andreas 259
#ifndef __ANDROID__
3 andreas 260
    string pname = *argv;
261
    size_t pos = pname.find_last_of("/");
2 andreas 262
 
3 andreas 263
    if (pos != string::npos)
264
        pname = pname.substr(pos + 1);
22 andreas 265
#else
266
    string pname = "tpanel";
91 andreas 267
    killed = false;
268
    _netRunning = false;
22 andreas 269
#endif
21 andreas 270
    TConfig::setProgName(pname);    // Remember the name of this application.
22 andreas 271
#ifndef Q_OS_ANDROID
21 andreas 272
    InputParser input(&argc, argv); // Parse the command line parameters.
2 andreas 273
 
21 andreas 274
    // Evaluate the command line parameters.
3 andreas 275
    if (input.cmdOptionExists("-h") || input.cmdOptionExists("--help"))
276
    {
277
        banner(pname);
278
        usage();
279
        return 0;
280
    }
2 andreas 281
 
3 andreas 282
    if (input.cmdOptionExists("-c") || input.cmdOptionExists("--config-file"))
283
    {
284
        configFile = input.getCmdOption("-c");
2 andreas 285
 
3 andreas 286
        if (configFile.empty())
287
            configFile = input.getCmdOption("--config-file");
2 andreas 288
 
3 andreas 289
        if (configFile.empty())
290
        {
291
            banner(pname);
292
            std::cerr << "Missing the path and name of the configuration file!" << std::endl;
293
            usage();
294
            return 1;
295
        }
296
    }
22 andreas 297
#endif
21 andreas 298
    TError::clear();                    // Clear all errors (initialize)
299
    TConfig config(configFile);         // Read the configuration file.
2 andreas 300
 
21 andreas 301
    if (TError::isError())              // Exit if the previous command failed.
22 andreas 302
    {
303
        TError::displayMessage(TError::getErrorMsg());
3 andreas 304
        return 1;
22 andreas 305
    }
306
#ifndef __ANDROID__
3 andreas 307
    banner(pname);
22 andreas 308
#endif
3 andreas 309
    TError::clear();
58 andreas 310
    // Start the page manager. This is the core class handling everything.
311
    try
312
    {
90 andreas 313
        bool ret;
2 andreas 314
 
90 andreas 315
        do
316
        {
317
            ret = _startUp(oldArgc, argc, argv);
2 andreas 318
 
90 andreas 319
            if (_restart_)
320
            {
321
                MSG_INFO("Starting over ...");
322
                prg_stopped = false;
323
                killed = false;
324
            }
325
        }
326
        while (_restart_);
21 andreas 327
 
90 andreas 328
        if (!ret)
329
        {
330
            MSG_ERROR("Terminating because of a previous fatal error!");
331
            return 1;
332
        }
58 andreas 333
    }
334
    catch (std::exception& e)
335
    {
336
        MSG_ERROR("Fatal: " << e.what());
337
        return 1;
338
    }
2 andreas 339
 
3 andreas 340
    return 0;
2 andreas 341
}