1 /***************************************************************************
2 * Copyright (C) 2006-2021 by Ilya Kotov *
3 * forkotov02@ya.ru *
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 Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21 #include <QApplication>
22 #include <QSettings>
23 #include <QMenu>
24 #include <qmmp/soundcore.h>
25 #include <qmmpui/mediaplayer.h>
26 #include <qmmpui/playlistmanager.h>
27 #include <qmmpui/qmmpuisettings.h>
28 #include "skin.h"
29 #include "mainvisual.h"
30 #include "button.h"
31 #include "titlebar.h"
32 #include "positionbar.h"
33 #include "number.h"
34 #include "togglebutton.h"
35 #include "symboldisplay.h"
36 #include "textscroller.h"
37 #include "monostereo.h"
38 #include "playstatus.h"
39 #include "volumebar.h"
40 #include "balancebar.h"
41 #include "mainwindow.h"
42 #include "timeindicator.h"
43 #include "actionmanager.h"
44 #include "display.h"
45
MainDisplay(MainWindow * parent)46 MainDisplay::MainDisplay (MainWindow *parent)
47 : PixmapWidget (parent)
48 {
49 m_skin = Skin::instance();
50 setPixmap (m_skin->getMain());
51 setCursor(m_skin->getCursor(Skin::CUR_NORMAL));
52 m_mw = parent;
53
54 m_timeIndicatorModel = new TimeIndicatorModel(this);
55 m_titlebar = new TitleBar(m_timeIndicatorModel, this);
56 m_titlebar->move(0,0);
57 m_titlebar->setActive(true);
58 m_previous = new Button (this, Skin::BT_PREVIOUS_N, Skin::BT_PREVIOUS_P, Skin::CUR_NORMAL);
59 m_previous->setToolTip(tr("Previous"));
60 connect (m_previous, SIGNAL (clicked()), parent, SLOT (previous()));
61
62 m_play = new Button (this, Skin::BT_PLAY_N, Skin::BT_PLAY_P, Skin::CUR_NORMAL);
63 m_play->setToolTip(tr("Play"));
64 connect (m_play, SIGNAL (clicked()),parent,SLOT (play()));
65 m_pause = new Button (this, Skin::BT_PAUSE_N,Skin::BT_PAUSE_P, Skin::CUR_NORMAL);
66 m_pause->setToolTip(tr("Pause"));
67 connect (m_pause,SIGNAL (clicked()),parent,SLOT (pause()));
68 m_stop = new Button (this, Skin::BT_STOP_N,Skin::BT_STOP_P, Skin::CUR_NORMAL);
69 m_stop->setToolTip(tr("Stop"));
70 connect (m_stop,SIGNAL (clicked()),parent,SLOT (stop()));
71 m_next = new Button (this, Skin::BT_NEXT_N,Skin::BT_NEXT_P, Skin::CUR_NORMAL);
72 m_next->setToolTip(tr("Next"));
73 connect (m_next,SIGNAL (clicked()),parent,SLOT (next()));
74 m_eject = new Button (this, Skin::BT_EJECT_N,Skin::BT_EJECT_P, Skin::CUR_NORMAL);
75 m_eject->setToolTip(tr("Play files"));
76 connect (m_eject,SIGNAL (clicked()),parent, SLOT(playFiles()));
77 connect (m_skin, SIGNAL (skinChanged()), this, SLOT (updateSkin()));
78 m_vis = new MainVisual (this);
79
80 m_eqButton = new ToggleButton (this,Skin::BT_EQ_ON_N,Skin::BT_EQ_ON_P,
81 Skin::BT_EQ_OFF_N,Skin::BT_EQ_OFF_P);
82 m_eqButton->setToolTip(tr("Equalizer"));
83 m_plButton = new ToggleButton (this,Skin::BT_PL_ON_N,Skin::BT_PL_ON_P,
84 Skin::BT_PL_OFF_N,Skin::BT_PL_OFF_P);
85 m_plButton->setToolTip(tr("Playlist"));
86
87 m_repeatButton = new ToggleButton (this,Skin::REPEAT_ON_N,Skin::REPEAT_ON_P,
88 Skin::REPEAT_OFF_N,Skin::REPEAT_OFF_P);
89 connect(m_repeatButton,SIGNAL(clicked(bool)),this,SIGNAL(repeatableToggled(bool)));
90 m_repeatButton->setToolTip(tr("Repeat playlist"));
91 m_shuffleButton = new ToggleButton (this,Skin::SHUFFLE_ON_N,Skin::SHUFFLE_ON_P,
92 Skin::SHUFFLE_OFF_N,Skin::SHUFFLE_OFF_P);
93 m_shuffleButton->setToolTip(tr("Shuffle"));
94 connect(m_shuffleButton,SIGNAL(clicked(bool)),this,SIGNAL(shuffleToggled(bool)));
95
96 m_kbps = new SymbolDisplay(this,3);
97 m_freq = new SymbolDisplay(this,2);
98 m_text = new TextScroller (this);
99 m_monoster = new MonoStereo (this);
100 m_playstatus = new PlayStatus(this);
101
102 m_volumeBar = new VolumeBar(this);
103 m_volumeBar->setToolTip(tr("Volume"));
104 connect(m_volumeBar, SIGNAL(sliderMoved(int)),SLOT(displayVolume()));
105 connect(m_volumeBar, SIGNAL(sliderPressed()),SLOT(displayVolume()));
106 connect(m_volumeBar, SIGNAL(sliderReleased()),m_text,SLOT(clear()));
107
108 m_balanceBar = new BalanceBar(this);
109 m_balanceBar->setToolTip(tr("Balance"));
110 connect(m_balanceBar, SIGNAL(sliderMoved(int)),SLOT(displayVolume()));
111 connect(m_balanceBar, SIGNAL(sliderPressed()),SLOT(displayVolume()));
112 connect(m_balanceBar, SIGNAL(sliderReleased()),m_text,SLOT(clear()));
113
114 m_posbar = new PositionBar(this);
115 connect(m_posbar, SIGNAL(sliderPressed()),SLOT(showPosition()));
116 connect(m_posbar, SIGNAL(sliderMoved(qint64)),SLOT(showPosition()));
117 connect(m_posbar, SIGNAL(sliderReleased()),SLOT(updatePosition()));
118
119 m_timeIndicator = new TimeIndicator(m_timeIndicatorModel, this);
120 m_aboutWidget = new QWidget(this);
121 m_core = SoundCore::instance();
122 connect(m_core, SIGNAL(elapsedChanged(qint64)), SLOT(setTime(qint64)));
123 connect(m_core, SIGNAL(bitrateChanged(int)), m_kbps, SLOT(display(int)));
124 connect(m_core, SIGNAL(audioParametersChanged(AudioParameters)), SLOT(onAudioPatametersChanged(AudioParameters)));
125 connect(m_core, SIGNAL(stateChanged(Qmmp::State)), SLOT(setState(Qmmp::State)));
126 connect(m_core, SIGNAL(volumeChanged(int)), m_volumeBar, SLOT(setValue(int)));
127 connect(m_core, SIGNAL(balanceChanged(int)), m_balanceBar, SLOT(setValue(int)));
128 connect(m_balanceBar, SIGNAL(sliderMoved(int)), m_core, SLOT(setBalance(int)));
129 connect(m_volumeBar, SIGNAL(sliderMoved(int)), m_core, SLOT(setVolume(int)));
130 m_volumeBar->setValue(m_core->volume());
131 m_balanceBar->setValue(m_core->balance());
132
133 QmmpUiSettings *ui_settings = QmmpUiSettings::instance();
134 connect(ui_settings, SIGNAL(repeatableListChanged(bool)), m_repeatButton, SLOT(setChecked(bool)));
135 connect(ui_settings, SIGNAL(shuffleChanged(bool)), m_shuffleButton, SLOT(setChecked(bool)));
136 updatePositions();
137 updateMask();
138 }
139
~MainDisplay()140 MainDisplay::~MainDisplay()
141 {
142 QSettings settings (Qmmp::configFile(), QSettings::IniFormat);
143 settings.setValue ("Skinned/pl_visible",m_plButton->isChecked());
144 settings.setValue ("Skinned/eq_visible",m_eqButton->isChecked());
145 }
146
updatePositions()147 void MainDisplay::updatePositions()
148 {
149 int r = m_skin->ratio();
150 m_previous->move (r*16, r*88);
151 m_play->move (r*39, r*88);
152 m_pause->move (r*62, r*88);
153 m_vis->move(r*24, r*43);
154 m_stop->move (r*85, r*88);
155 m_next->move (r*108, r*88);
156 m_eject->move (r*136, r*89);
157 m_posbar->move (r*16, r*72);
158 m_eqButton->move (r*219, r*58);
159 m_plButton->move (r*241, r*58);
160 m_repeatButton->move (r*210, r*89);
161 m_shuffleButton->move (r*164, r*89);
162 m_kbps->move (r*111, r*43);
163 m_freq->move (r*156, r*43);
164 m_text->resize (r*154, r*16);
165 m_text->move (r*109, r*23);
166 m_monoster->move (r*212, r*41);
167 m_playstatus->move(r*24, r*28);
168 m_volumeBar->move(r*107, r*57);
169 m_balanceBar->move(r*177, r*57);
170 m_timeIndicator->move(r*34, r*26);
171 m_aboutWidget->setGeometry(r*247,r*83,r*20,r*25);
172 }
173
setTime(qint64 t)174 void MainDisplay::setTime (qint64 t)
175 {
176 m_posbar->setValue (t);
177 m_timeIndicatorModel->setPosition(t/1000);
178 }
setDuration(qint64 t)179 void MainDisplay::setDuration(qint64 t)
180 {
181 m_posbar->setMaximum (t);
182 m_timeIndicatorModel->setDuration(t/1000);
183 }
184
setState(Qmmp::State state)185 void MainDisplay::setState(Qmmp::State state)
186 {
187 switch ((int) state)
188 {
189 case Qmmp::Playing:
190 m_playstatus->setStatus(PlayStatus::PLAY);
191 m_timeIndicatorModel->setVisible(true);
192 setDuration(m_core->duration());
193 break;
194 case Qmmp::Paused:
195 m_playstatus->setStatus(PlayStatus::PAUSE);
196 break;
197 case Qmmp::Stopped:
198 m_playstatus->setStatus(PlayStatus::STOP);
199 m_monoster->setChannels (0);
200 m_timeIndicatorModel->setVisible(false);
201 m_posbar->setValue (0);
202 m_posbar->setMaximum (0);
203 }
204 }
205
onAudioPatametersChanged(const AudioParameters & p)206 void MainDisplay::onAudioPatametersChanged(const AudioParameters &p)
207 {
208 m_monoster->setChannels(p.channels());
209 m_freq->display(int(p.sampleRate()) / 1000);
210 }
211
updateSkin()212 void MainDisplay::updateSkin()
213 {
214 setPixmap (m_skin->getMain());
215 m_mw->resize(size());
216 setCursor(m_skin->getCursor(Skin::CUR_NORMAL));
217 setMinimalMode(m_shaded);
218 updatePositions();
219 }
220
updateMask()221 void MainDisplay::updateMask()
222 {
223 m_mw->clearMask();
224 m_mw->setMask(QRegion(0,0,m_mw->width(),m_mw->height()));
225 QRegion region = m_skin->getRegion(m_shaded? Skin::WINDOW_SHADE : Skin::NORMAL);
226 if (!region.isEmpty())
227 m_mw->setMask(region);
228 }
229
setMinimalMode(bool b)230 void MainDisplay::setMinimalMode(bool b)
231 {
232 m_shaded = b;
233 int r = m_skin->ratio();
234
235 if(m_shaded)
236 m_mw->setFixedSize(r*275,r*14);
237 else
238 m_mw->setFixedSize(r*275,r*116);
239 updateMask();
240 }
241
setActive(bool b)242 void MainDisplay::setActive(bool b)
243 {
244 m_titlebar->setActive(b);
245 }
246
247 //TODO optimize this connections
setEQ(QWidget * w)248 void MainDisplay::setEQ (QWidget* w)
249 {
250 m_equlizer = w;
251 m_eqButton->setChecked (m_equlizer->isVisible());
252 ACTION(ActionManager::SHOW_EQUALIZER)->setChecked(m_equlizer->isVisible());
253
254 connect (ACTION(ActionManager::SHOW_EQUALIZER), SIGNAL(triggered(bool)),
255 m_equlizer, SLOT (setVisible (bool)));
256 connect (ACTION(ActionManager::SHOW_EQUALIZER), SIGNAL(triggered(bool)),
257 m_eqButton, SLOT (setChecked (bool)));
258
259 connect (m_eqButton, SIGNAL(clicked(bool)),
260 ACTION(ActionManager::SHOW_EQUALIZER), SLOT(setChecked (bool)));
261 connect (m_eqButton, SIGNAL(clicked(bool)), m_equlizer, SLOT (setVisible (bool)));
262 connect (m_equlizer, SIGNAL(closed ()), m_eqButton, SLOT (click()));
263 }
264
setPL(QWidget * w)265 void MainDisplay::setPL (QWidget* w)
266 {
267 m_playlist = w;
268 m_plButton->setChecked (m_playlist->isVisible());
269 ACTION(ActionManager::SHOW_PLAYLIST)->setChecked(m_playlist->isVisible());
270
271 connect (ACTION(ActionManager::SHOW_PLAYLIST), SIGNAL(triggered(bool)),
272 m_playlist, SLOT (setVisible (bool)));
273 connect (ACTION(ActionManager::SHOW_PLAYLIST), SIGNAL(triggered(bool)),
274 m_plButton, SLOT (setChecked (bool)));
275
276 connect (m_plButton, SIGNAL(clicked(bool)),
277 ACTION(ActionManager::SHOW_PLAYLIST), SLOT(setChecked (bool)));
278 connect (m_plButton, SIGNAL (clicked (bool)), m_playlist, SLOT (setVisible (bool)));
279 connect (m_playlist, SIGNAL (closed ()), m_plButton, SLOT (click()));
280 }
281
isPlaylistVisible() const282 bool MainDisplay::isPlaylistVisible() const
283 {
284 return m_plButton->isChecked();
285 }
286
isEqualizerVisible() const287 bool MainDisplay::isEqualizerVisible() const
288 {
289 return m_eqButton->isChecked();
290 }
291
displayVolume()292 void MainDisplay::displayVolume()
293 {
294 if(sender() == m_volumeBar)
295 m_text->setText(tr("Volume: %1%").arg(m_volumeBar->value()));
296 if(sender() == m_balanceBar)
297 {
298 if(m_balanceBar->value() > 0)
299 m_text->setText(tr("Balance: %1% right").arg(m_balanceBar->value()));
300 else if(m_balanceBar->value() < 0)
301 m_text->setText(tr("Balance: %1% left").arg(-m_balanceBar->value()));
302 else
303 m_text->setText(tr("Balance: center"));
304 }
305 }
306
showPosition()307 void MainDisplay::showPosition()
308 {
309 m_text->setText(tr("Seek to: %1").arg(MetaDataFormatter::formatDuration(m_posbar->value(), false)));
310 }
311
updatePosition()312 void MainDisplay::updatePosition()
313 {
314 m_text->clear();
315 m_core->seek(m_posbar->value());
316 }
317
wheelEvent(QWheelEvent * e)318 void MainDisplay::wheelEvent (QWheelEvent *e)
319 {
320 m_core->changeVolume(e->delta()/10);
321 }
322
isRepeatable() const323 bool MainDisplay::isRepeatable() const
324 {
325 return m_repeatButton->isChecked();
326 }
327
isShuffle() const328 bool MainDisplay::isShuffle() const
329 {
330 return m_shuffleButton->isChecked();
331 }
332
setIsRepeatable(bool yes)333 void MainDisplay::setIsRepeatable(bool yes)
334 {
335 m_repeatButton->setChecked(yes);
336 }
337
setIsShuffle(bool yes)338 void MainDisplay::setIsShuffle(bool yes)
339 {
340 m_shuffleButton->setChecked(yes);
341 }
342
mousePressEvent(QMouseEvent * e)343 void MainDisplay::mousePressEvent(QMouseEvent *e)
344 {
345 if (e->button() == Qt::RightButton)
346 m_mw->menu()->exec(e->globalPos());
347 else if(e->button() == Qt::LeftButton && m_aboutWidget->underMouse())
348 m_mw->about();
349 PixmapWidget::mousePressEvent(e);
350 }
351