set SIGWINCH handler before initializing ncurses to avoid races
[ncmpcpp.git] / src / configuration.cpp
blobd44ba4fa2ce087a0b6fef91cd9971f327e29557e
1 /***************************************************************************
2 * Copyright (C) 2008-2014 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include <boost/filesystem/operations.hpp>
22 #include <boost/program_options.hpp>
23 #include <iostream>
25 #include "bindings.h"
26 #include "configuration.h"
27 #include "config.h"
28 #include "mpdpp.h"
29 #include "settings.h"
31 namespace po = boost::program_options;
33 using std::cerr;
34 using std::cout;
36 namespace {
38 const char *env_home;
42 void expand_home(std::string &path)
44 if (!path.empty() && path[0] == '~')
45 path.replace(0, 1, env_home);
48 bool configure(int argc, char **argv)
50 std::string bindings_path, config_path;
52 po::options_description options("Options");
53 options.add_options()
54 ("host,h", po::value<std::string>()->default_value("localhost"), "connect to server at host")
55 ("port,p", po::value<int>()->default_value(6600), "connect to server at port")
56 ("config,c", po::value<std::string>(&config_path)->default_value("~/.ncmpcpp/config"), "specify configuration file")
57 ("bindings,b", po::value<std::string>(&bindings_path)->default_value("~/.ncmpcpp/bindings"), "specify bindings file")
58 ("screen,s", po::value<std::string>(), "specify initial screen")
59 ("help,?", "show help message")
60 ("version,v", "display version information")
63 po::variables_map vm;
64 try
66 po::store(po::parse_command_line(argc, argv, options), vm);
68 if (vm.count("help"))
70 cout << "Usage: " << argv[0] << " [options]...\n" << options << "\n";
71 return false;
73 if (vm.count("version"))
75 std::cout << "ncmpcpp " << VERSION << "\n\n"
76 << "optional screens compiled-in:\n"
77 # ifdef HAVE_TAGLIB_H
78 << " - tag editor\n"
79 << " - tiny tag editor\n"
80 # endif
81 # ifdef HAVE_CURL_CURL_H
82 << " - artist info\n"
83 # endif
84 # ifdef ENABLE_OUTPUTS
85 << " - outputs\n"
86 # endif
87 # ifdef ENABLE_VISUALIZER
88 << " - visualizer\n"
89 # endif
90 # ifdef ENABLE_CLOCK
91 << " - clock\n"
92 # endif
93 << "\nencoding detection: "
94 # ifdef HAVE_LANGINFO_H
95 << "enabled"
96 # else
97 << "disabled"
98 # endif // HAVE_LANGINFO_H
99 << "\nbuilt with support for:"
100 # ifdef HAVE_CURL_CURL_H
101 << " curl"
102 # endif
103 # ifdef HAVE_FFTW3_H
104 << " fftw"
105 # endif
106 # ifdef USE_PDCURSES
107 << " pdcurses"
108 # else
109 << " ncurses"
110 # endif
111 # ifdef HAVE_TAGLIB_H
112 << " taglib"
113 # endif
114 # ifdef NCMPCPP_UNICODE
115 << " unicode"
116 # endif
117 << "\n";
118 return false;
121 po::notify(vm);
123 // get home directory
124 env_home = getenv("HOME");
125 if (env_home == nullptr)
127 cerr << "Fatal error: HOME environment variable is not defined\n";
128 return false;
131 // read configuration
132 expand_home(config_path);
133 if (Config.read(config_path) == false)
134 exit(1);
136 // if bindings file was not specified, use the one from main directory.
137 if (vm["bindings"].defaulted())
138 bindings_path = Config.ncmpcpp_directory + "bindings";
139 else
140 expand_home(bindings_path);
142 // read bindings
143 if (Bindings.read(bindings_path) == false)
144 exit(1);
145 Bindings.generateDefaults();
147 // create directories
148 boost::filesystem::create_directory(Config.ncmpcpp_directory);
149 boost::filesystem::create_directory(Config.lyrics_directory);
151 // try to get MPD connection details from environment variables
152 // as they take precedence over these from the configuration.
153 auto env_host = getenv("MPD_HOST");
154 auto env_port = getenv("MPD_PORT");
155 if (env_host != nullptr)
156 Mpd.SetHostname(env_host);
157 if (env_port != nullptr)
158 Mpd.SetPort(boost::lexical_cast<int>(env_port));
160 // if MPD connection details are provided as command line
161 // parameters, use them as their priority is the highest.
162 if (!vm["host"].defaulted())
163 Mpd.SetHostname(vm["host"].as<std::string>());
164 if (!vm["port"].defaulted())
165 Mpd.SetPort(vm["port"].as<int>());
166 Mpd.SetTimeout(Config.mpd_connection_timeout);
168 // custom startup screen
169 if (vm.count("screen"))
171 auto screen = vm["screen"].as<std::string>();
172 Config.startup_screen_type = stringtoStartupScreenType(screen);
173 if (Config.startup_screen_type == ScreenType::Unknown)
175 std::cerr << "Unknown screen: " << screen << "\n";
176 exit(1);
180 catch (std::exception &e)
182 cerr << "Error while processing configuration: " << e.what() << "\n";
183 exit(1);
185 return true;