window: use readline for handling line input
[ncmpcpp.git] / src / statusbar.cpp
blobe1e7280fc5a651a4e729d06eedf1fc129d719b63
1 /***************************************************************************
2 * Copyright (C) 2008-2013 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 "global.h"
22 #include "settings.h"
23 #include "status.h"
24 #include "statusbar.h"
25 #include "bindings.h"
26 #include "playlist.h"
27 #include "utility/wide_string.h"
29 using Global::wFooter;
31 namespace {//
33 timeval statusbarLockTime;
34 int statusbarLockDelay = -1;
36 bool statusbarBlockUpdate = false;
37 bool progressbarBlockUpdate = false;
38 bool statusbarAllowUnlock = true;
40 void showMessage(int time, const char *format, va_list list)
42 if (statusbarAllowUnlock)
44 statusbarLockTime = Global::Timer;
45 statusbarLockDelay = time;
46 if (Config.statusbar_visibility)
47 statusbarBlockUpdate = true;
48 else
49 progressbarBlockUpdate = true;
50 wFooter->goToXY(0, Config.statusbar_visibility);
51 *wFooter << NC::Format::NoBold;
52 wmove(wFooter->raw(), Config.statusbar_visibility, 0);
53 vw_printw(wFooter->raw(), format, list);
54 wclrtoeol(wFooter->raw());
55 wFooter->refresh();
61 void Progressbar::lock()
63 progressbarBlockUpdate = true;
66 void Progressbar::unlock()
68 progressbarBlockUpdate = false;
71 bool Progressbar::isUnlocked()
73 return !progressbarBlockUpdate;
76 void Progressbar::draw(unsigned int elapsed, unsigned int time)
78 unsigned pb_width = wFooter->getWidth();
79 unsigned howlong = time ? pb_width*elapsed/time : 0;
80 if (Config.progressbar_boldness)
81 *wFooter << NC::Format::Bold;
82 *wFooter << Config.progressbar_color;
83 if (Config.progressbar[2] != '\0')
85 wFooter->goToXY(0, 0);
86 for (unsigned i = 0; i < pb_width; ++i)
87 *wFooter << Config.progressbar[2];
88 wFooter->goToXY(0, 0);
90 else
91 mvwhline(wFooter->raw(), 0, 0, 0, pb_width);
92 if (time)
94 *wFooter << Config.progressbar_elapsed_color;
95 pb_width = std::min(size_t(howlong), wFooter->getWidth());
96 for (unsigned i = 0; i < pb_width; ++i)
97 *wFooter << Config.progressbar[0];
98 if (howlong < wFooter->getWidth())
99 *wFooter << Config.progressbar[1];
100 *wFooter << NC::Color::End;
102 *wFooter << NC::Color::End;
103 if (Config.progressbar_boldness)
104 *wFooter << NC::Format::NoBold;
107 void Statusbar::lock()
109 if (Config.statusbar_visibility)
110 statusbarBlockUpdate = true;
111 else
112 progressbarBlockUpdate = true;
113 statusbarAllowUnlock = false;
116 void Statusbar::unlock()
118 statusbarAllowUnlock = true;
119 if (statusbarLockDelay < 0)
121 if (Config.statusbar_visibility)
122 statusbarBlockUpdate = false;
123 else
124 progressbarBlockUpdate = false;
126 if (Status::State::player() == MPD::psStop)
128 if (Config.new_design)
129 Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength());
130 else
131 put() << wclrtoeol;
132 wFooter->refresh();
136 bool Statusbar::isUnlocked()
138 return !statusbarBlockUpdate;
141 void Statusbar::tryRedraw()
143 using Global::Timer;
144 if (statusbarLockDelay > 0
145 && Timer.tv_sec >= statusbarLockTime.tv_sec+statusbarLockDelay)
147 statusbarLockDelay = -1;
149 if (Config.statusbar_visibility)
150 statusbarBlockUpdate = !statusbarAllowUnlock;
151 else
152 progressbarBlockUpdate = !statusbarAllowUnlock;
154 if (Status::State::player() != MPD::psStop && !statusbarBlockUpdate && !progressbarBlockUpdate)
156 if (Config.new_design)
157 Progressbar::draw(Status::State::elapsedTime(), myPlaylist->currentSongLength());
158 else
159 Status::Changes::elapsedTime(false);
160 wFooter->refresh();
165 NC::Window &Statusbar::put()
167 *wFooter << NC::XY(0, Config.statusbar_visibility ? 1 : 0) << wclrtoeol;
168 return *wFooter;
171 void Statusbar::msg(const char *format, ...)
173 va_list list;
174 va_start(list, format);
175 showMessage(Config.message_delay_time, format, list);
176 va_end(list);
179 void Statusbar::msg(int time, const char *format, ...)
181 va_list list;
182 va_start(list, format);
183 showMessage(time, format, list);
184 va_end(list);
187 void Statusbar::Helpers::mpd()
189 Status::update(Mpd.noidle());
192 bool Statusbar::Helpers::getString(const char *)
194 Status::trace();
195 return true;
198 bool Statusbar::Helpers::ApplyFilterImmediately::operator()(const char *s)
200 using Global::myScreen;
201 // if input queue is not empty, we don't want to update filter since next
202 // character will be taken from queue immediately, trigering this function
203 // again and thus making it inefficient, so let's apply filter only if
204 // "real" user input arrived. however, we want to apply filter if ENTER
205 // is next in queue, so its effects will be seen.
206 if (wFooter->inputQueue().empty() || wFooter->inputQueue().front() == KEY_ENTER)
208 if (m_s != s)
210 m_s = s;
211 m_f->applyFilter(m_s);
212 myScreen->refreshWindow();
214 Status::trace();
216 return true;
219 bool Statusbar::Helpers::TryExecuteImmediateCommand::operator()(const char *s)
221 bool continue_ = true;
222 if (m_s != s)
224 m_s = s;
225 auto cmd = Bindings.findCommand(m_s);
226 if (cmd && cmd->immediate())
227 continue_ = false;
229 Status::trace();
230 return continue_;