Update NEWS for v0.9.0
[cclive.git] / src / cc / options.cpp
1 /* cclive
2  * Copyright (C) 2010-2013  Toni Gundogdu <legatvs@gmail.com>
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, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <ccinternal>
19
20 #include <iostream>
21 #include <fstream>
22 #include <cstring>
23
24 #include <boost/filesystem.hpp>
25 #include <boost/foreach.hpp>
26
27 #ifndef foreach
28 #define foreach BOOST_FOREACH
29 #endif
30
31 #include <ccre>
32 #include <ccoptions>
33
34 namespace cc
35 {
36
37 options opts;
38
39 namespace po = boost::program_options;
40 namespace fs = boost::filesystem;
41
42 typedef std::vector<std::string> vst;
43
44 void options::exec(int argc, char **argv)
45 {
46   memset(&flags, 0, sizeof(struct flags_s));
47
48   // Path to ccliverc.
49
50 #if BOOST_FILESYSTEM_VERSION > 2
51   fs::path conf_path(fs::current_path());
52 #else
53   fs::path conf_path(fs::current_path<fs::path>());
54 #endif
55
56   const char *home = getenv("HOME");
57
58   if (home && strlen(home) > 0)
59     conf_path = fs::system_complete(fs::path(home));
60
61   conf_path /=
62 #ifndef _WIN32
63     std::string(".") +
64 #endif
65     std::string("ccliverc");
66
67   // Construct options.
68
69   po::options_description generic;
70   std::string conf_file;
71
72   generic.add_options()
73   ("print-config,D",
74    po::value(&flags.print_config)->zero_tokens(),
75    "Print value of defined config options")
76   ("version,v",
77    po::value(&flags.version)->zero_tokens(),
78    "Print version and exit")
79   ("help,h",
80    po::value(&flags.help)->zero_tokens(),
81    "Print help and exit")
82   ("support",
83    po::value(&flags.support)->zero_tokens(),
84    "Print supported websites and exit")
85   ("verbose-libcurl,B",
86    po::value(&flags.verbose_libcurl)->zero_tokens()->default_value(false),
87    "Turn on libcurl verbose output")
88   ("quiet,q",
89    po::value(&flags.quiet)->zero_tokens()->default_value(false),
90    "Turn off all output, excl. errors")
91 #ifdef HAVE_FORK
92   ("background,b",
93    po::value(&flags.background)->zero_tokens()->default_value(false),
94    "Go to background")
95 #endif
96   ("print-streams,S",
97    po::value(&flags.print_streams)->zero_tokens(),
98    "Print available media streams")
99   ("stream,s",
100    po::value<std::string>(),
101    "Select media stream")
102   ("overwrite,W",
103    po::value(&flags.overwrite)->zero_tokens()->default_value(false),
104    "Overwrite existing media")
105   ("output-file,O",
106    po::value<std::string>(),
107    "Write media to arg")
108   ("no-download,n",
109    po::value(&flags.no_download)->zero_tokens()->default_value(false),
110    "Do not download media, print details")
111   ("no-proxy",
112    po::value(&flags.no_proxy)->zero_tokens()->default_value(false),
113    "Do not use HTTP proxy")
114   ("log-file",
115    po::value<std::string>()->default_value("cclive_log"),
116    "Write log output to arg")
117   ("config-file",
118    po::value<std::string>(&conf_file)->default_value(conf_path.string()),
119    "Read args from arg")
120   ;
121
122   // Config.
123
124   po::options_description config("Configuration");
125
126   config.add_options()
127   ("no-resolve,r",
128    po::value(&flags.no_resolve)->zero_tokens()->default_value(false),
129    "Do not resolve URL redirections")
130   ("continue,c",
131    po::value(&flags.cont)->zero_tokens()->default_value(false),
132    "Resume partially downloaded media")
133   ("prefer-format,p",
134    po::value<std::vector<std::string> >()->composing(),
135    "Preferred format [domain:format[,...]]")
136   ("progressbar",
137    po::value<std::string>()->default_value("normal"),
138    "Use progressbar arg")
139   ("update-interval",
140    po::value<double>()->default_value(1.0),
141    "Update interval of progressbar")
142   ("filename-format",
143    po::value<std::string>()->default_value("%t.%s"),
144    "Downloaded media filename format")
145   ("output-dir",
146    po::value<std::string>(),
147    "Write downloaded media to arg directory")
148   ("tr,t",
149    po::value<vst>()->composing(),
150    "Translate characters in media title")
151   ("exec", po::value<vst>()->composing(),
152    "Invoke arg after each finished download")
153   ("agent",
154    po::value<std::string>()->default_value("Mozilla/5.0"),
155    "Identify as arg to HTTP servers")
156   ("proxy", po::value<std::string>(),
157    "Use proxy for HTTP connections")
158   ("throttle", po::value<int>()->default_value(0),
159    "Do not exceed transfer rate arg KB/s")
160   ("connect-timeout", po::value<int>()->default_value(30),
161    "Seconds connecting allowed to take")
162   ("transfer-timeout", po::value<int>()->default_value(0),
163    "Seconds transfer allowed to take")
164   ("dns-cache-timeout", po::value<int>()->default_value(60),
165    "Seconds DNS resolves kept in memory")
166   ("max-retries", po::value<int>()->default_value(5),
167    "Max download attempts before giving up")
168   ("retry-wait", po::value<int>()->default_value(5),
169    "Time to wait before retrying")
170   ;
171
172   // Hidden.
173
174   po::options_description hidden;
175
176   hidden.add_options()
177   ("url", po::value<vst>(), "url");
178
179   // Visible.
180
181   _visible.add(generic).add(config);
182
183   // Command line options.
184
185   po::options_description cmdline_options;
186   cmdline_options.add(generic).add(config).add(hidden);
187
188   // Config file options.
189
190   po::options_description config_file_options;
191   config_file_options.add(config);
192
193   // Positional.
194
195   po::positional_options_description p;
196   p.add("url", -1);
197
198   // Parse.
199
200   store(po::command_line_parser(argc,argv)
201         .options(cmdline_options).positional(p).run(), _map);
202   notify(_map);
203
204   // Read config.
205
206   std::ifstream ifs(conf_file.c_str());
207
208   if (ifs)
209     {
210       store(parse_config_file(ifs, config_file_options), _map);
211       notify(_map);
212     }
213
214   _validate();
215 }
216
217 void options::_validate()
218 {
219   std::string empty;
220
221   if (_map.count("tr"))
222     {
223       vst v = _map["tr"].as<vst>();
224       foreach (const std::string s, v)
225       {
226         re::tr(s, empty);
227       }
228     }
229 }
230
231 void options::dump()
232 {
233   for (po::variables_map::iterator i = _map.begin(); i != _map.end(); ++i)
234     {
235       const po::variable_value &v = i->second;
236
237       if (v.empty())
238         continue;
239
240       const std::type_info &t = v.value().type();
241       bool nl = true;
242
243       if (t == typeid(bool))
244         std::cout << i->first << " is " << (v.as<bool>() ? "set" : "unset");
245       else if (t == typeid(vst))
246         {
247           const vst r = v.as<vst>();
248           foreach (const std::string s, r)
249           {
250             std::cout << i->first << "=" << s << "\n";
251           }
252           nl = false;
253         }
254       else
255         {
256           std::cout << i->first << "=";
257           if (t == typeid(std::string))
258             std::cout << v.as<std::string>();
259           else if (t == typeid(double))
260             std::cout << v.as<double>();
261           else if (t == typeid(int))
262             std::cout << v.as<int>();
263           else
264             std::cout << "<unsupported type error>";
265         }
266
267       if (!nl)
268         std::cout << std::flush;
269       else
270         std::cout << std::endl;
271     }
272 }
273
274 } // namespace cc
275
276 // vim: set ts=2 sw=2 tw=72 expandtab: