Skip to content

Commit ee0460c

Browse files
Added support for reading a configuration file. All settings that are available on the command line may be specified in the config file. See the attached .conf.sample-file. The default name of the config file is the same as of the binary with the extension ".conf". The program will first look in the same folder as the binary is placed, if not found there it will try /etc/. The configuration file namd and location may be specified with the --config-file command line parameter. Any command line arguments will override those of the config file. Compilation now requires the libconfig++-dev package.
Removed the -g parameter from the Makefile.
1 parent 5165399 commit ee0460c

File tree

5 files changed

+201
-85
lines changed

5 files changed

+201
-85
lines changed

Exception.hh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,24 @@
22
#define EXCEPTION_HH__
33

44
#include <exception>
5+
#include <string>
56

67
class Exception : public std::exception
78
{
89
public:
910
Exception() {
1011
}
1112

12-
Exception(const char *whatString)
13+
Exception(const std::string& whatString)
1314
: m_whatString(whatString) {
1415
};
1516

1617
const char *what() const noexcept override {
17-
return m_whatString;
18+
return m_whatString.c_str();
1819
}
1920

2021
private:
21-
const char *m_whatString = "";
22+
std::string m_whatString;
2223
};
2324

2425
class HelpException : public Exception

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
CC = g++
2-
CFLAGS = -g -Wall -std=c++11 -O3 -DHAVE_LIBBCM_HOST -DUSE_EXTERNAL_LIBBCM_HOST -DUSE_VCHIQ_ARM
2+
CFLAGS = -Wall -std=c++11 -O3 -DHAVE_LIBBCM_HOST -DUSE_EXTERNAL_LIBBCM_HOST -DUSE_VCHIQ_ARM
33

44
INCLUDES = -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux
55
LIB_PATHS = -L/opt/vc/lib/
6-
LIBS = -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt -lvncserver
6+
LIBS = -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt -lvncserver -lconfig++
77

88
SOURCES = main.cpp \
99
UFile.cpp \

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ VNC Server for Raspberry PI using dispmanx
55

66
Compile with "make"
77

8-
you need to have installed libvncserver-dev and gcc/g++-4.7.
8+
you need to have installed libvncserver-dev, libconfig++-dev and gcc/g++-4.7.
99

1010
On raspbian you prepare using the following steps.
1111

12-
apt-get install gcc-4.7 g++-4.7 libvncserver-dev
12+
apt-get install gcc-4.7 g++-4.7 libvncserver-dev libconfig++-dev
1313

1414
Followed by
1515

dispmanx_vncserver.conf.sample

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
relative = false;
2+
port = 0;
3+
screen = 0;
4+
unsafe = false;
5+
fullscreen = false;
6+
multi-threaded = false;
7+
password = "";
8+
frame-rate = 15;

main.cpp

Lines changed: 185 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <string.h>
77

88
#include <iostream>
9+
#include <sstream>
910

1011
#include <errno.h>
1112
#include <sys/time.h>
@@ -14,6 +15,8 @@
1415
#include <assert.h>
1516
#include <getopt.h>
1617

18+
#include <libconfig.h++>
19+
1720
#include "Exception.hh"
1821
#include "UFile.hh"
1922
#include "DMXResource.hh"
@@ -23,6 +26,23 @@
2326

2427
extern bool terminate;
2528

29+
struct ConfigData
30+
{
31+
uint32_t screen = 0;
32+
bool relative = false;
33+
std::string password;
34+
int port = 0;
35+
bool unsafe = false;
36+
bool fullscreen = false;
37+
bool multiThreaded = false;
38+
int frameRate = 15;
39+
std::string configFile;
40+
};
41+
42+
void GetConfigData(int argc, char *argv[], ConfigData& configData);
43+
void GetCommandLineConfigData(int argc, char *argv[], ConfigData& configData);
44+
bool ReadConfigFile(const char *programName, const std::string& configFile, ConfigData& configData);
45+
bool TryReadConfigFile(libconfig::Config& config, const std::string& file);
2646
void usage(const char *programName);
2747

2848
void sig_handler(int signo)
@@ -36,90 +56,31 @@ int main(int argc, char *argv[])
3656

3757
try
3858
{
39-
uint32_t screen = 0;
40-
bool relativeMode = 0;
41-
std::string password;
42-
int port = 0;
43-
bool safeMode = true;
44-
bool bandwidthMode = true;
45-
bool multiThreaded = false;
46-
int frameRate = 15;
47-
48-
static struct option long_options[] = {
49-
{ "relative", no_argument, nullptr, 'r' },
50-
{ "absolute", no_argument, nullptr, 'a' },
51-
{ "unsafe", no_argument, nullptr, 'u' },
52-
{ "fullscreen", no_argument, nullptr, 'f' },
53-
{ "multi-threaded", no_argument, nullptr, 'm' },
54-
{ "password", required_argument, nullptr, 'P' },
55-
{ "port", required_argument, nullptr, 'p' },
56-
{ "screen", required_argument, nullptr, 's' },
57-
{ "frame-rate", required_argument, nullptr, 't' },
58-
{ "help", no_argument, nullptr, CHAR_MIN - 2 },
59-
{ nullptr, 0, nullptr, 0}
60-
};
61-
62-
int c;
63-
while (-1 != (c = getopt_long(argc, argv, "abfmP:p:rs:t:u", long_options, nullptr))) {
64-
switch (c) {
65-
case 'a':
66-
relativeMode = false;
67-
break;
68-
69-
case 'r':
70-
relativeMode = true;
71-
break;
72-
73-
case 'u':
74-
safeMode = false;
75-
break;
76-
77-
case 'f':
78-
bandwidthMode = false;
79-
break;
80-
81-
case 'm':
82-
multiThreaded = true;
83-
break;
84-
85-
case 'P':
86-
password = optarg;
87-
break;
88-
89-
case 'p':
90-
port = atoi(optarg);
91-
break;
92-
93-
case 's':
94-
screen = atoi(optarg);
95-
break;
96-
97-
case 't':
98-
frameRate = atoi(optarg);
99-
break;
100-
101-
case CHAR_MIN - 2:
102-
throw HelpException();
103-
104-
default:
105-
throw ParamException();
106-
}
107-
}
108-
109-
if (optind < argc) {
110-
std::cerr << "Unknown parameter: " << argv[optind] << '\n';
111-
throw ParamException();
112-
}
113-
11459
if (signal(SIGINT, sig_handler) == SIG_ERR) {
11560
throw Exception( "error setting sighandler");
11661
}
11762
if (signal(SIGTERM, sig_handler) == SIG_ERR) {
11863
throw Exception("error setting sighandler");
11964
}
12065

121-
DMXVNCServer vncServer(BPP, frameRate);
122-
vncServer.Run( argc, argv, port, password, screen, relativeMode, safeMode, bandwidthMode, multiThreaded);
66+
ConfigData configData;
67+
GetConfigData(argc, argv, configData);
68+
69+
std::cerr <<
70+
"Running vnc server with the following settings\n"
71+
" frame-rate = " << configData.frameRate << "\n"
72+
" fullscreen = " << (configData.fullscreen ? "true" : "false") << "\n"
73+
" multi-threaded = " << (configData.multiThreaded ? "true" : "false") << "\n"
74+
" password = " << (configData.password.length() ? "***" : "") << "\n"
75+
" port = " << configData.port << "\n"
76+
" relative = " << (configData.relative ? "true" : "false") << "\n"
77+
" screen = " << configData.screen << "\n"
78+
" unsafe = " << (configData.unsafe ? "true" : "false") << "\n";
79+
80+
DMXVNCServer vncServer(BPP, configData.frameRate);
81+
vncServer.Run(argc, argv, configData.port, configData.password, configData.screen,
82+
configData.relative, !configData.unsafe, !configData.fullscreen,
83+
configData.multiThreaded);
12384
}
12485
catch (HelpException) {
12586
usage(argv[0]);
@@ -129,19 +90,165 @@ int main(int argc, char *argv[])
12990
ret = EXIT_FAILURE;
13091
}
13192
catch (Exception& e) {
132-
std::cerr << "Exception caught: " << e.what() << "\n";
93+
std::cerr << "Exception: " << e.what() << "\n";
13394
ret = EXIT_FAILURE;
13495
}
13596

13697
return ret;
13798
}
13899

100+
void GetConfigData(int argc, char *argv[], ConfigData& configData)
101+
{
102+
ConfigData configDataTemp;
103+
GetCommandLineConfigData(argc, argv, configDataTemp);
104+
if (ReadConfigFile(argv[0], configDataTemp.configFile, configData))
105+
GetCommandLineConfigData(argc, argv, configData);
106+
else
107+
configData = configDataTemp;
108+
}
109+
110+
void GetCommandLineConfigData(int argc, char *argv[], ConfigData& configData)
111+
{
112+
static struct option long_options[] = {
113+
{ "relative", no_argument, nullptr, 'r' },
114+
{ "absolute", no_argument, nullptr, 'a' },
115+
{ "config-file", required_argument, nullptr, 'c' },
116+
{ "unsafe", no_argument, nullptr, 'u' },
117+
{ "fullscreen", no_argument, nullptr, 'f' },
118+
{ "multi-threaded", no_argument, nullptr, 'm' },
119+
{ "password", required_argument, nullptr, 'P' },
120+
{ "port", required_argument, nullptr, 'p' },
121+
{ "screen", required_argument, nullptr, 's' },
122+
{ "frame-rate", required_argument, nullptr, 't' },
123+
{ "help", no_argument, nullptr, CHAR_MIN - 2 },
124+
{ nullptr, 0, nullptr, 0 }
125+
};
126+
127+
int c;
128+
while (-1 != (c = getopt_long(argc, argv, "abc:fmP:p:rs:t:u", long_options, nullptr))) {
129+
switch (c) {
130+
case 'a':
131+
configData.relative = false;
132+
break;
133+
134+
case 'r':
135+
configData.relative = true;
136+
break;
137+
138+
case 'c':
139+
configData.configFile = optarg;
140+
break;
141+
142+
case 'u':
143+
configData.unsafe = true;
144+
break;
145+
146+
case 'f':
147+
configData.fullscreen = true;
148+
break;
149+
150+
case 'm':
151+
configData.multiThreaded = true;
152+
break;
153+
154+
case 'P':
155+
configData.password = optarg;
156+
break;
157+
158+
case 'p':
159+
configData.port = atoi(optarg);
160+
break;
161+
162+
case 's':
163+
configData.screen = atoi(optarg);
164+
break;
165+
166+
case 't':
167+
configData.frameRate = atoi(optarg);
168+
break;
169+
170+
case CHAR_MIN - 2:
171+
throw HelpException();
172+
173+
default:
174+
throw ParamException();
175+
}
176+
}
177+
178+
if (optind < argc) {
179+
std::cerr << "Unknown parameter: " << argv[optind] << '\n';
180+
throw ParamException();
181+
}
182+
}
183+
184+
bool ReadConfigFile(const char *programName, const std::string& configFile, ConfigData& configData)
185+
{
186+
std::string configFileTemp;
187+
libconfig::Config config;
188+
bool readConfig = false;
189+
190+
if (configFile.length()) {
191+
configFileTemp = configFile;
192+
readConfig = TryReadConfigFile(config, configFileTemp);
193+
if (!readConfig)
194+
throw Exception("Unable to read the specified configuration file");
195+
}
196+
else {
197+
configFileTemp = programName;
198+
configFileTemp += ".conf";
199+
readConfig = TryReadConfigFile(config, configFileTemp);
200+
if (!readConfig) {
201+
const char *baseName = basename(programName);
202+
configFileTemp = "/etc/";
203+
configFileTemp += baseName;
204+
configFileTemp += ".conf";
205+
std::cerr << "trying: " << configFileTemp << '\n';
206+
//configFileTemp = "/etc/dispmanx_vncserver.conf";
207+
readConfig = TryReadConfigFile(config, configFileTemp);
208+
}
209+
}
210+
211+
if (readConfig) {
212+
std::cerr << "Read config file: " << configFileTemp << '\n';
213+
214+
config.lookupValue("relative", configData.relative);
215+
config.lookupValue("unsafe", configData.unsafe);
216+
config.lookupValue("fullscreen", configData.fullscreen);
217+
config.lookupValue("multi-threaded", configData.multiThreaded);
218+
config.lookupValue("password", configData.password);
219+
config.lookupValue("port", configData.port);
220+
config.lookupValue("screen", configData.screen);
221+
config.lookupValue("frame-rate", configData.frameRate);
222+
}
223+
else
224+
std::cerr << "No config file found\n";
225+
226+
return readConfig;
227+
}
228+
229+
bool TryReadConfigFile(libconfig::Config& config, const std::string& file)
230+
{
231+
try{
232+
config.readFile(file.c_str());
233+
return true;
234+
}
235+
catch (libconfig::FileIOException) {
236+
return false;;
237+
}
238+
catch (libconfig::ParseException &e) {
239+
std::stringstream ss;
240+
ss << "Error: " << e.getError() << " on line " << e.getLine() << " while reading configuration file: " << file;
241+
throw Exception(ss.str());
242+
}
243+
}
244+
139245
void usage(const char *programName)
140246
{
141247
std::cout <<
142248
"Usage: " << programName << " [OPTION]...\n"
143249
"\n"
144250
" -a, --absolute absolute mouse movements\n"
251+
" -c, --config-file=FILE use the specified configuration file\n"
145252
" -f, --fullscreen always runs fullscreen mode\n"
146253
" -m, --multi-threaded runs vnc in a separate thread\n"
147254
" -p, --port=PORT makes vnc available on the speficied port\n"

0 commit comments

Comments
 (0)