remove quotation marks from the host in the 'welcome' message
[ncmpcpp.git] / src / ncmpcpp.cpp
blob7faf3488ce781cbc52730ae9383f4897541e9a7d
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 <cerrno>
22 #include <clocale>
23 #include <csignal>
24 #include <cstring>
26 #include <boost/locale.hpp>
27 #include <iostream>
28 #include <fstream>
29 #include <stdexcept>
31 #include "mpdpp.h"
33 #include "actions.h"
34 #include "bindings.h"
35 #include "browser.h"
36 #include "charset.h"
37 #include "configuration.h"
38 #include "global.h"
39 #include "error.h"
40 #include "helpers.h"
41 #include "lyrics.h"
42 #include "outputs.h"
43 #include "playlist.h"
44 #include "settings.h"
45 #include "status.h"
46 #include "statusbar.h"
47 #include "visualizer.h"
48 #include "title.h"
49 #include "utility/conversion.h"
51 namespace
53 std::ofstream errorlog;
54 std::streambuf *cerr_buffer;
55 bool run_resize_screen = false;
57 # if !defined(WIN32)
58 void sighandler(int sig)
60 if (sig == SIGPIPE)
62 Statusbar::print("SIGPIPE (broken pipe signal) received");
64 else if (sig == SIGWINCH)
66 run_resize_screen = true;
68 # if defined(__sun) && defined(__SVR4)
69 // in solaris it is needed to reinstall the handler each time it's executed
70 signal(sig, sighandler);
71 # endif // __sun && __SVR4
73 # endif // !WIN32
75 void do_at_exit()
77 // restore old cerr buffer
78 std::cerr.rdbuf(cerr_buffer);
79 errorlog.close();
80 Mpd.Disconnect();
81 # ifndef USE_PDCURSES // destroying screen somehow crashes pdcurses
82 NC::destroyScreen();
83 # endif // USE_PDCURSES
84 windowTitle("");
88 int main(int argc, char **argv)
90 using Global::myScreen;
91 using Global::myLockedScreen;
92 using Global::myInactiveScreen;
94 using Global::wHeader;
95 using Global::wFooter;
97 using Global::VolumeState;
98 using Global::Timer;
100 std::srand(std::time(0));
101 std::setlocale(LC_ALL, "");
102 std::locale::global(Charset::internalLocale());
104 if (!configure(argc, argv))
105 return 0;
107 // always execute these commands, even if ncmpcpp use exit function
108 atexit(do_at_exit);
110 // redirect std::cerr output to ~/.ncmpcpp/error.log file
111 errorlog.open((Config.ncmpcpp_directory + "error.log").c_str(), std::ios::app);
112 cerr_buffer = std::cerr.rdbuf();
113 std::cerr.rdbuf(errorlog.rdbuf());
115 NC::initScreen("ncmpcpp ver. " VERSION, Config.colors_enabled);
117 Actions::OriginalStatusbarVisibility = Config.statusbar_visibility;
119 // for column separators
120 attron(COLOR_PAIR(int(Config.main_color)));
122 if (Config.design == Design::Alternative)
123 Config.statusbar_visibility = 0;
125 Actions::setWindowsDimensions();
126 Actions::validateScreenSize();
127 Actions::initializeScreens();
129 wHeader = new NC::Window(0, 0, COLS, Actions::HeaderHeight, "", Config.header_color, NC::Border::None);
130 if (Config.header_visibility || Config.design == Design::Alternative)
131 wHeader->display();
133 wFooter = new NC::Window(0, Actions::FooterStartY, COLS, Actions::FooterHeight, "", Config.statusbar_color, NC::Border::None);
134 wFooter->setTimeout(500);
135 wFooter->setGetStringHelper(Statusbar::Helpers::getString);
137 // initialize global timer
138 Timer = boost::posix_time::microsec_clock::local_time();
140 // initialize playlist
141 myPlaylist->switchTo();
143 // local variables
144 Key input(0, Key::Standard);
145 auto past = boost::posix_time::from_time_t(0);
147 /// enable mouse
148 mouseinterval(0);
149 if (Config.mouse_support)
150 mousemask(ALL_MOUSE_EVENTS, 0);
152 # ifndef WIN32
153 signal(SIGPIPE, sighandler);
154 signal(SIGWINCH, sighandler);
155 # endif // !WIN32
157 while (!Actions::ExitMainLoop)
161 if (!Mpd.Connected())
163 wFooter->clearFDCallbacksList();
166 Mpd.Connect();
167 if (Mpd.Version() < 16)
169 Mpd.Disconnect();
170 throw MPD::ClientError(MPD_ERROR_STATE, "MPD < 0.16.0 is not supported", false);
172 wFooter->addFDCallback(Mpd.GetFD(), Statusbar::Helpers::mpd);
173 Status::update(-1); // we need info about new connection
175 if (Config.jump_to_now_playing_song_at_start)
177 int curr_pos = myPlaylist->currentSongPosition();
178 if (curr_pos >= 0)
179 myPlaylist->main().highlight(curr_pos);
182 // go to startup screen
183 if (Config.startup_screen_type != myScreen->type())
184 toScreen(Config.startup_screen_type)->switchTo();
186 myBrowser->fetchSupportedExtensions();
187 # ifdef ENABLE_OUTPUTS
188 myOutputs->FetchList();
189 # endif // ENABLE_OUTPUTS
190 # ifdef ENABLE_VISUALIZER
191 myVisualizer->ResetFD();
192 if (myScreen == myVisualizer)
193 myVisualizer->SetFD();
194 myVisualizer->FindOutputID();
195 # endif // ENABLE_VISUALIZER
197 Statusbar::printf("Connected to %1%", Mpd.GetHostname());
199 catch (MPD::ClientError &e)
201 Status::handleClientError(e);
205 Status::trace();
207 if (run_resize_screen)
209 Actions::resizeScreen(true);
210 run_resize_screen = false;
213 // header stuff
214 if ((myScreen == myPlaylist || myScreen == myBrowser || myScreen == myLyrics)
215 && (Timer - past > boost::posix_time::milliseconds(500))
218 drawHeader();
219 past = Timer;
222 if (input != Key::noOp)
223 myScreen->refreshWindow();
224 input = Key::read(*wFooter);
226 if (input == Key::noOp)
227 continue;
231 auto k = Bindings.get(input);
232 std::any_of(k.first, k.second, boost::bind(&Binding::execute, _1));
234 catch (ConversionError &e)
236 Statusbar::printf("Couldn't convert value \"%1%\" to target type", e.value());
238 catch (OutOfBounds &e)
240 Statusbar::printf("Error: %1%", e.errorMessage());
243 if (myScreen == myPlaylist)
244 myPlaylist->EnableHighlighting();
246 # ifdef ENABLE_VISUALIZER
247 // visualizer sets timeout to 40ms, but since only it needs such small
248 // value, we should restore default one after switching to another screen.
249 if (wFooter->getTimeout() < 500
250 && !(myScreen == myVisualizer || myLockedScreen == myVisualizer || myInactiveScreen == myVisualizer)
252 wFooter->setTimeout(500);
253 # endif // ENABLE_VISUALIZER
255 catch (MPD::ClientError &e)
257 Status::handleClientError(e);
259 catch (MPD::ServerError &e)
261 Status::handleServerError(e);
264 return 0;