juk.cpp 22.7 KB
Newer Older
1 2 3 4 5
/***************************************************************************
                          juk.cpp  -  description
                             -------------------
    begin                : Mon Feb  4 23:40:41 EST 2002
    copyright            : (C) 2002 by Scott Wheeler
6
    email                : wheeler@kde.org
7
***************************************************************************/
8 9 10 11 12 13 14 15 16 17

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

18
#include <kapplication.h>
19
#include <klocale.h>
20
#include <kiconloader.h>
21
#include <kcmdlineargs.h>
22
#include <kstatusbar.h>
23
#include <kconfig.h>
24
#include <kdebug.h>
25
#include <kmessagebox.h>
26

27 28
#include <qtimer.h>
#include <qlistview.h>
29
#include <qinputdialog.h>
30
#include <qslider.h>
31 32
#include <qstrlist.h>
#include <qmetaobject.h>
33

34
#include "juk.h"
35
#include "slideraction.h"
36
#include "cache.h"
37
#include "statuslabel.h"
38 39
#include "splashscreen.h"
#include "genrelisteditor.h"
40
#include "systemtray.h"
41
#include "keydialog.h"
42 43 44 45 46

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

47 48
JuK::JuK(QWidget *parent, const char *name) : KMainWindow(parent, name, WDestructiveClose),
					      m_shuttingDown(false)
49
{
50 51 52
    SplashScreen::instance()->show();
    kapp->processEvents();
 
53 54
    // Expect segfaults if you change this order.

55
    readSettings();
56
    setupLayout();
57
    setupActions();
58
    slotPlaylistChanged();
59
    readConfig();
60
    setupPlayer();
61
    setupSystemTray();
62
    setupGlobalAccels();
63
    processArgs();
64

65
    SplashScreen::finishedLoading();
Scott Wheeler's avatar
Scott Wheeler committed
66
    QTimer::singleShot(0, CollectionList::instance(), SLOT(slotCheckCache()));
67 68 69 70
}

JuK::~JuK()
{
71

72 73 74 75 76 77
}

////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

78 79
void JuK::setupLayout()
{
80 81
    m_splitter = new PlaylistSplitter(this, m_restore, "playlistSplitter");
    setCentralWidget(m_splitter);
82 83

    // playlist item activation connection
84 85
    connect(m_splitter, SIGNAL(signalDoubleClicked()), this, SLOT(slotPlaySelectedFile()));
    connect(m_splitter, SIGNAL(signalListBoxDoubleClicked()), this, SLOT(slotPlayFirstFile()));
86

87
    // create status bar
88 89
    m_statusLabel = new StatusLabel(statusBar());
    statusBar()->addWidget(m_statusLabel, 1);
90

91 92
    connect(m_splitter, SIGNAL(signalSelectedPlaylistCountChanged(int)), m_statusLabel, SLOT(setPlaylistCount(int)));
    connect(m_statusLabel, SIGNAL(jumpButtonClicked()), m_splitter, SLOT(slotSelectPlaying()));
93

94
    m_splitter->setFocus();
95

96
    resize(750, 500);
97 98
}

99 100
void JuK::setupActions()
{
101
    // file menu
102 103 104
    KStdAction::openNew(m_splitter, SLOT(slotCreatePlaylist()), actionCollection());
    KStdAction::open(m_splitter, SLOT(slotOpen()), actionCollection());
    new KAction(i18n("Open &Directory..."), "fileopen", 0, m_splitter, SLOT(slotOpenDirectory()), actionCollection(), "openDirectory");
105

106
    m_renamePlaylistAction = new KAction(i18n("Rename..."), 0, m_splitter, SLOT(slotRenamePlaylist()), 
107
					 actionCollection(), "renamePlaylist");
108
    new KAction(i18n("Duplicate..."), "editcopy", 0, m_splitter, SLOT(slotDuplicatePlaylist()), actionCollection(), "duplicatePlaylist");
109
    
110 111 112
    m_savePlaylistAction = KStdAction::save(m_splitter, SLOT(slotSavePlaylist()), actionCollection());
    m_saveAsPlaylistAction = KStdAction::saveAs(m_splitter, SLOT(slotSaveAsPlaylist()), actionCollection());
    m_deleteItemPlaylistAction = new KAction(i18n("Remove"), "edittrash", 0, m_splitter, SLOT(slotDeletePlaylist()), 
113
					     actionCollection(), "deleteItemPlaylist");
114

115
    KStdAction::quit(this, SLOT(slotQuit()), actionCollection());
116 117

    // edit menu
118
    KStdAction::cut(this, SLOT(cut()), actionCollection());
119 120 121 122
    KStdAction::copy(this, SLOT(copy()), actionCollection());
    KStdAction::paste(this, SLOT(paste()), actionCollection());
    new KAction(i18n("Clear"), "editclear", 0, this, SLOT(clear()), actionCollection(), "clear");
    KStdAction::selectAll(this, SLOT(selectAll()), actionCollection());
123

124
    // view menu
125 126 127 128
    m_showEditorAction = new KToggleAction(i18n("Show Tag Editor"), "edit", 0, actionCollection(), "showEditor");
    connect(m_showEditorAction, SIGNAL(toggled(bool)), m_splitter, SLOT(slotSetEditorVisible(bool)));
    KStdAction::redisplay(m_splitter, SLOT(slotRefresh()), actionCollection());
    actionCollection()->insert(m_splitter->columnVisibleAction());
129
    
130
    // play menu
131
    m_randomPlayAction = new KToggleAction(i18n("Random Play"), 0, actionCollection(), "randomPlay");
132 133 134 135 136
    m_playAction = new KAction(i18n("&Play"), "player_play", 0, this, SLOT(slotPlay()), actionCollection(), "play");
    m_pauseAction = new KAction(i18n("P&ause"), "player_pause", 0, this, SLOT(slotPause()), actionCollection(), "pause");
    m_stopAction = new KAction(i18n("&Stop"), "player_stop", 0, this, SLOT(slotStop()), actionCollection(), "stop");
    m_backAction = new KAction(i18n("Skip &Back"), "player_start", 0, this, SLOT(slotBack()), actionCollection(), "back");
    m_forwardAction = new KAction(i18n("Skip &Forward"), "player_end", 0, this, SLOT(slotForward()), actionCollection(), "forward");
137

138
    // tagger menu
139 140
    new KAction(i18n("Save"), "filesave", "CTRL+t", m_splitter, SLOT(slotSaveTag()), actionCollection(), "saveItem");
    new KAction(i18n("Delete"), "editdelete", 0, m_splitter, SLOT(slotDeleteSelectedItems()), actionCollection(), "removeItem");
141
    
142
    // settings menu
143 144 145
    new KToggleAction(i18n("Show Menu Bar"), "CTRL+m", this, SLOT(slotToggleMenuBar()), actionCollection(), "toggleMenuBar");
    new KToggleAction(i18n("Show Tool Bar"), "CTRL+b", this, SLOT(slotToggleToolBar()), actionCollection(), "toggleToolBar");

146
    m_restoreOnLoadAction = new KToggleAction(i18n("Restore Playlists on Load"),  0, actionCollection(), "restoreOnLoad");
147

148
    m_toggleSystemTrayAction = new KToggleAction(i18n("Dock in System Tray"), KShortcut(), actionCollection(), "toggleSystemTray");
149
    connect(m_toggleSystemTrayAction, SIGNAL(toggled(bool)), this, SLOT(slotToggleSystemTray(bool)));
150

151 152
    m_toggleDockOnCloseAction = new KToggleAction(i18n("Stay in System Tray on Close"), 0, actionCollection(), "dockOnClose");

153
    m_togglePopupsAction = new KToggleAction(i18n("Popup Track Announcement"), 0, this, 0, actionCollection(), "togglePopups");
154

155
    new KAction(i18n("Genre List Editor..."), 0, this, SLOT(slotShowGenreListEditor()), actionCollection(), "showGenreListEditor");
156

157
    m_outputSelectAction = Player::playerSelectAction(actionCollection());
158

159 160
    if(m_outputSelectAction) {
	m_outputSelectAction->setCurrentItem(0);
161
	connect(m_outputSelectAction, SIGNAL(activated(int)), this, SLOT(slotSetOutput(int)));
162
    }
163

164 165
    KStdAction::keyBindings(this, SLOT(slotEditKeys()), actionCollection());

166
    // just in the toolbar
167
    m_sliderAction = new SliderAction(i18n("Track Position"), actionCollection(), "trackPositionAction");
168 169

    createGUI();
170 171

    // set the slider to the proper orientation and make it stay that way
172 173
    m_sliderAction->slotUpdateOrientation();
    connect(this, SIGNAL(dockWindowPositionChanged(QDockWindow *)), m_sliderAction, SLOT(slotUpdateOrientation(QDockWindow *)));
174

175
    connect(m_splitter, SIGNAL(signalPlaylistChanged()), this, SLOT(slotPlaylistChanged()));
176 177
}

178
void JuK::setupSystemTray()
179
{
180 181 182
    if(m_toggleSystemTrayAction && m_toggleSystemTrayAction->isChecked()) {
	m_systemTray = new SystemTray(this, "systemTray");
	m_systemTray->show();
183
	
184 185 186 187 188
	connect(m_systemTray, SIGNAL(signalPlay()),    this, SLOT(slotPlay()));
	connect(m_systemTray, SIGNAL(signalStop()),    this, SLOT(slotStop()));
	connect(m_systemTray, SIGNAL(signalPause()),   this, SLOT(slotPause()));
	connect(m_systemTray, SIGNAL(signalBack()),    this, SLOT(slotBack()));
	connect(m_systemTray, SIGNAL(signalForward()), this, SLOT(slotForward()));
189

190
	connect(this, SIGNAL(signalNewSong(const QString&)), m_systemTray, SLOT(slotNewSong(const QString&)));
191
	
192 193 194 195
	if(m_player && m_player->paused())
	    m_systemTray->slotPause();
	else if(m_player && m_player->playing())
	    m_systemTray->slotPlay();
196 197
	
	m_toggleDockOnCloseAction->setEnabled(true);
198 199

	connect(m_systemTray, SIGNAL(quitSelected()), this, SLOT(slotQuit()));
200
    }
201
    else {
202
	m_systemTray = 0;
203 204
	m_toggleDockOnCloseAction->setEnabled(false);
    }
205 206
}

207 208
void JuK::setupPlayer()
{
209 210
    m_trackPositionDragging = false;
    m_noSeek = false;
211
    m_volmute = false;
212 213 214 215
    m_pauseAction->setEnabled(false);
    m_stopAction->setEnabled(false);
    m_backAction->setEnabled(false);
    m_forwardAction->setEnabled(false);
216

217
    m_playTimer = new QTimer(this);
218
    connect(m_playTimer, SIGNAL(timeout()), this, SLOT(slotPollPlay()));
219

220
    if(m_sliderAction && m_sliderAction->getTrackPositionSlider() && m_sliderAction->getVolumeSlider()) {
221 222 223
        connect(m_sliderAction->getTrackPositionSlider(), SIGNAL(valueChanged(int)), this, SLOT(slotTrackPositionSliderUpdate(int)));
        connect(m_sliderAction->getTrackPositionSlider(), SIGNAL(sliderPressed()), this, SLOT(slotTrackPositionSliderClicked()));
        connect(m_sliderAction->getTrackPositionSlider(), SIGNAL(sliderReleased()), this, SLOT(slotTrackPositionSliderReleased()));
224
        m_sliderAction->getTrackPositionSlider()->setEnabled(false);
225

226
        connect(m_sliderAction->getVolumeSlider(), SIGNAL(valueChanged(int)), this, SLOT(slotSetVolume(int)));
227
    }
228 229
    
    int playerType = 0;
230 231
    if(m_outputSelectAction) {
	playerType = m_outputSelectAction->currentItem();
232
	connect(m_outputSelectAction, SIGNAL(activated(int)), this, SLOT(slotSetOutput(int)));
233 234
    }

235
    m_player = Player::createPlayer(playerType);
236 237
}

238

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
void JuK::setupGlobalAccels()
{
    m_accel = new KGlobalAccel(this);
    KeyDialog::insert(m_accel, "PlayPause",  i18n("Play/Pause"),   this, SLOT(slotPlayPause()));
    KeyDialog::insert(m_accel, "Stop",       i18n("Stop Playing"), this, SLOT(slotStop()));
    KeyDialog::insert(m_accel, "Back",       i18n("Back"),         this, SLOT(slotBack()));
    KeyDialog::insert(m_accel, "Forward",    i18n("Forward"),      this, SLOT(slotForward()));
    KeyDialog::insert(m_accel, "VolumeUp",   i18n("Volume Up"),    this, SLOT(slotVolumeUp()));
    KeyDialog::insert(m_accel, "VolumeDown", i18n("Volume Down"),  this, SLOT(slotVolumeDown()));
    KeyDialog::insert(m_accel, "Mute",       i18n("Mute"),         this, SLOT(slotVolumeMute()));
    m_accel->setConfigGroup("Shortcuts");
    m_accel->readSettings();
    m_accel->updateConnections();
}

254 255 256 257 258 259 260 261
void JuK::processArgs()
{
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    QStringList files;
    
    for(int i = 0; i < args->count(); i++)
	files.append(args->arg(i));

262
    m_splitter->open(files);
263 264
}

265 266 267 268 269 270 271
void JuK::keyPressEvent(QKeyEvent *e)
{
    if (e->key() >= Qt::Key_Back && e->key() <= Qt::Key_MediaLast)
	e->accept();
    KMainWindow::keyPressEvent(e);
}

272 273 274 275 276 277 278 279 280
/**
 * These are settings that need to be know before setting up the GUI.
 */

void JuK::readSettings()
{
    KConfig *config = KGlobal::config();
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
281
	m_restore = config->readBoolEntry("RestoreOnLoad", true);
282 283 284
    }
}

285 286
void JuK::readConfig()
{
287
    // Automagically save and m_restore many window settings.
288 289
    setAutoSaveSettings();

290
    KConfig *config = KGlobal::config();
291
    { // m_player settings
292
        KConfigGroupSaver saver(config, "Player");
293
        if(m_sliderAction->getVolumeSlider()) {
294 295
            int volume = config->readNumEntry("Volume", m_sliderAction->getVolumeSlider()->maxValue());
            m_sliderAction->getVolumeSlider()->setValue(volume);
296
        }
297 298
	bool randomPlay = config->readBoolEntry("RandomPlay", false);
	m_randomPlayAction->setChecked(randomPlay);
299
    }
300
    { // view settings
301
        KConfigGroupSaver saver(config, "View");
302
	bool showEditor = config->readBoolEntry("ShowEditor", false);
303 304
	m_showEditorAction->setChecked(showEditor);
	m_splitter->slotSetEditorVisible(showEditor);
305
    }
306 307
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
308

309
	bool dockInSystemTray = config->readBoolEntry("DockInSystemTray", true);
310
	m_toggleSystemTrayAction->setChecked(dockInSystemTray);
311
	
312 313 314
	bool dockOnClose = config->readBoolEntry("DockOnClose", true);
	m_toggleDockOnCloseAction->setChecked(dockOnClose);

315 316 317
	bool showPopups = config->readBoolEntry("TrackPopup", false);
	m_togglePopupsAction->setChecked(showPopups);

318 319
	if(m_outputSelectAction)
	    m_outputSelectAction->setCurrentItem(config->readNumEntry("MediaSystem", 0));
320
	
321
    }
322

323
    m_restoreOnLoadAction->setChecked(m_restore);
324
    
325 326 327 328
}

void JuK::saveConfig()
{
329
    KConfig *config = KGlobal::config();
330
    { // m_player settings
331
        KConfigGroupSaver saver(config, "Player");
332 333 334 335
        if(m_sliderAction && m_sliderAction->getVolumeSlider())
            config->writeEntry("Volume", m_sliderAction->getVolumeSlider()->value());
	if(m_randomPlayAction)
	    config->writeEntry("RandomPlay", m_randomPlayAction->isChecked());
336
    }
337 338
    { // view settings
        KConfigGroupSaver saver(config, "View");
339
	config->writeEntry("ShowEditor", m_showEditorAction->isChecked());
340
    }
341 342
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
343 344 345 346
	config->writeEntry("RestoreOnLoad", m_restoreOnLoadAction->isChecked());
	config->writeEntry("DockInSystemTray", m_toggleSystemTrayAction->isChecked());
	config->writeEntry("DockOnClose", m_toggleDockOnCloseAction->isChecked());
	config->writeEntry("TrackPopup", m_togglePopupsAction->isChecked());
347 348
	if(m_outputSelectAction)
	    config->writeEntry("MediaSystem", m_outputSelectAction->currentItem());
349
    }
350 351
}

352
bool JuK::queryExit()
353
{
354
    slotStop();
355
    delete m_player;
356
    Cache::instance()->save();
357
    saveConfig();
358
    delete m_splitter;
359
    return true;
360 361
}

362 363
bool JuK::queryClose()
{
364
    if(!m_shuttingDown && m_systemTray && m_toggleDockOnCloseAction->isChecked()) {
365 366 367 368 369 370 371 372 373 374 375
	KMessageBox::information(this,
				 i18n("<qt>Closing the main window will keep JuK running in the system tray. "
				      "Use Quit from the File menu to quit the application.</qt>"), 
				 i18n("Docking in System Tray"), "hideOnCloseInfo");
	hide();
	return false;
    }
    else
	return true;
}

376 377 378 379 380 381 382 383 384 385 386 387 388
void JuK::invokeEditSlot( const char *slotName, const char *slot )
{
    QObject *object = focusWidget();
    
    if(!object || !slotName || !slot)
	return;
    
    QMetaObject *meta = object->metaObject();
    QStrList l = meta->slotNames(true);
  
    if(l.find(slotName) == -1)
	return;
    
389 390 391
    connect(this, SIGNAL(signalEdit()), object, slot);
    emit signalEdit();
    disconnect(this, SIGNAL(signalEdit()), object, slot);
392 393
}

394 395 396 397
QString JuK::playingString() const
{
    QString s;
    
398 399
    if(m_splitter->playingArtist().isEmpty())
	s = m_splitter->playingTrack().simplifyWhiteSpace();
400
    else
401
	s = m_splitter->playingArtist().simplifyWhiteSpace() + " - " + m_splitter->playingTrack().simplifyWhiteSpace();
402 403 404 405

    return s;
}

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
void JuK::updatePlaylistInfo()
{
    m_statusLabel->setPlaylistInfo(m_splitter->selectedPlaylistName(), m_splitter->selectedPlaylistCount());
}

void JuK::play(const QString &file)
{
    if(!m_player)
	return;

    float volume = float(m_sliderAction->getVolumeSlider()->value()) / float(m_sliderAction->getVolumeSlider()->maxValue());

    if(m_player->paused())
	m_player->stop();
    
    m_player->play(file, volume);

    // Make sure that the m_player actually starts before doing anything.

    if(m_player->playing()) {
	m_pauseAction->setEnabled(true);
	m_stopAction->setEnabled(true);
	
	m_backAction->setEnabled(true);
	m_forwardAction->setEnabled(true);
	
	m_sliderAction->getTrackPositionSlider()->setValue(0);
	m_sliderAction->getTrackPositionSlider()->setEnabled(true);
	m_playTimer->start(m_pollInterval);

	m_statusLabel->setPlayingItemInfo(playingString(), m_splitter->playingList());

	emit signalNewSong(playingString());

	if(m_systemTray)
	    m_systemTray->slotPlay();
    }
    else
	slotStop();
}

447 448 449 450
////////////////////////////////////////////////////////////////////////////////
// private slot definitions
////////////////////////////////////////////////////////////////////////////////

451
void JuK::slotPlaylistChanged()
452
{
453 454 455 456 457
    if(m_splitter->collectionListSelected()) {
	m_savePlaylistAction->setEnabled(false);
	m_saveAsPlaylistAction->setEnabled(false);
	m_renamePlaylistAction->setEnabled(false);
	m_deleteItemPlaylistAction->setEnabled(false);	
458 459
    }
    else {
460 461 462 463
	m_savePlaylistAction->setEnabled(true);
	m_saveAsPlaylistAction->setEnabled(true);
	m_renamePlaylistAction->setEnabled(true);
	m_deleteItemPlaylistAction->setEnabled(true);
464
    }
465 466 467 468

    updatePlaylistInfo();
}

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
////////////////////////////////////////////////////////////////////////////////
// edit menu
////////////////////////////////////////////////////////////////////////////////

void JuK::cut()
{
    invokeEditSlot("cut()", SLOT(cut()));
}

void JuK::copy()
{
    invokeEditSlot("copy()", SLOT(copy()));
}

void JuK::paste()
{
    invokeEditSlot("paste()", SLOT(paste()));
}

void JuK::clear()
{
    invokeEditSlot("clear()", SLOT(clear()));
}

void JuK::selectAll()
{
    invokeEditSlot("selectAll()", SLOT(selectAll()));
}

498
////////////////////////////////////////////////////////////////////////////////
499
// player menu
500 501
////////////////////////////////////////////////////////////////////////////////

502
void JuK::slotPlay()
503
{
504
    if(!m_player)
505 506
	return;

507 508
    if(m_player->paused()) {
        m_player->play();
509

510
	// Here, before doing anything, we want to make sure that the m_player did
511 512
	// in fact start.

513 514 515
        if(m_player->playing()) {
            m_pauseAction->setEnabled(true);
            m_stopAction->setEnabled(true);
516
            m_playTimer->start(m_pollInterval);
517 518
	    if(m_systemTray)
		m_systemTray->slotPlay();
519 520
        }
    }
521 522
    else if(m_player->playing())
	m_player->seekPosition(0);
523
    else
524
	play(m_splitter->playNextFile(m_randomPlayAction->isChecked()));
525 526
}

527
void JuK::slotPause()
528
{
529
    if(!m_player)
530 531
	return;

532 533 534 535 536
    m_playTimer->stop();
    m_player->pause();
    m_pauseAction->setEnabled(false);
    if(m_systemTray)
	m_systemTray->slotPause();
537 538
}

539
void JuK::slotStop()
540
{
541
    if(!m_player)
542 543
	return;

544 545
    m_playTimer->stop();
    m_player->stop();
546

547 548 549 550
    m_pauseAction->setEnabled(false);
    m_stopAction->setEnabled(false);
    m_backAction->setEnabled(false);
    m_forwardAction->setEnabled(false);
551

552 553
    m_sliderAction->getTrackPositionSlider()->setValue(0);
    m_sliderAction->getTrackPositionSlider()->setEnabled(false);
554

555
    m_splitter->stop();
556

557
    m_statusLabel->clear();
558
    
559 560
    if(m_systemTray)
	m_systemTray->slotStop();
561 562
}

563
void JuK::slotBack()
564
{
565
    play(m_splitter->playPreviousFile(m_randomPlayAction->isChecked()));
566 567
}

568
void JuK::slotForward()
569
{
570
    play(m_splitter->playNextFile(m_randomPlayAction->isChecked()));
571 572
}

573 574 575 576
////////////////////////////////////////////////////////////////////////////////
// settings menu
////////////////////////////////////////////////////////////////////////////////

577
void JuK::slotShowGenreListEditor()
578 579 580 581
{
    GenreListEditor * editor = new GenreListEditor();
    editor->exec();
}
582

583
void JuK::slotToggleSystemTray(bool enabled)
584
{
585
    if(enabled && !m_systemTray)
586
	setupSystemTray();
587 588 589
    else if(!enabled && m_systemTray) {
	delete m_systemTray;
	m_systemTray = 0;
590
	m_toggleDockOnCloseAction->setEnabled(false);
591 592 593
    }
}

594
void JuK::slotSetOutput(int output)
595
{
596
    slotStop();
597 598
    delete m_player;
    m_player = Player::createPlayer(output);
599 600
}

601 602 603 604 605
void JuK::slotEditKeys()
{
    KeyDialog::configure(m_accel, actionCollection(), this);
}

606
////////////////////////////////////////////////////////////////////////////////
607
// additional player slots
608 609
////////////////////////////////////////////////////////////////////////////////

610
void JuK::slotTrackPositionSliderClicked()
611
{
612
    m_trackPositionDragging = true;
613 614
}

615
void JuK::slotTrackPositionSliderReleased()
616
{
617
    if(!m_player)
618 619
	return;

620 621
    m_trackPositionDragging = false;
    m_player->seekPosition(m_sliderAction->getTrackPositionSlider()->value());
622 623
}

624
void JuK::slotTrackPositionSliderUpdate(int position)
625
{
626
    if(!m_player)
627 628
	return;

629 630
    if(m_player->playing() && !m_trackPositionDragging && !m_noSeek)
        m_player->seekPosition(position);
631 632
}

633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
void JuK::slotPlayPause()
{
    if(!m_player)
	return;

    if(m_player->playing())
	slotPause();
    else
	slotPlay();
}

void JuK::slotVolumeUp()
{
    if(m_sliderAction && m_sliderAction->getVolumeSlider()) {
	int volume = m_sliderAction->getVolumeSlider()->value() +
	  m_sliderAction->getVolumeSlider()->maxValue() / 25; // 4% up
	slotSetVolume(volume);
	m_sliderAction->getVolumeSlider()->setValue(volume);
    }
}

void JuK::slotVolumeDown()
{
    if(m_sliderAction && m_sliderAction->getVolumeSlider()) {
	int volume = m_sliderAction->getVolumeSlider()->value() -
	  m_sliderAction->getVolumeSlider()->maxValue() / 25; // 4% down
	slotSetVolume(volume);
	m_sliderAction->getVolumeSlider()->setValue(volume);
    }
}

void JuK::slotVolumeMute()
{
    if(m_sliderAction && m_sliderAction->getVolumeSlider()) {
	if(m_volmute)
	    slotSetVolume(m_sliderAction->getVolumeSlider()->value());
	else
	    slotSetVolume(0);
	m_volmute = !m_volmute;
    }
}

675 676
// This method is called when the play timer has expired.

677
void JuK::slotPollPlay()
678
{
679
    if(!m_player)
680 681
	return;

682 683
    // Our locking mechanism.  Since this method adjusts the play slider, we 
    // want to make sure that our adjustments
684
    m_noSeek = true;
685

686
    if(!m_player->playing()) {
687

688
        m_playTimer->stop();
689

690 691
	if(!m_player->paused())
	    play(m_splitter->playNextFile(m_randomPlayAction->isChecked()));
692

693
    }
694 695 696 697
    else if(!m_trackPositionDragging) {
        m_sliderAction->getTrackPositionSlider()->setValue(m_player->position());
	m_statusLabel->setItemTotalTime(m_player->totalTime());
	m_statusLabel->setItemCurrentTime(m_player->currentTime());
698 699 700 701 702 703
    }

    // Ok, this is weird stuff, but it works pretty well.  Ordinarily we don't
    // need to check up on our playing time very often, but in the span of the 
    // last interval, we want to check a lot -- to figure out that we've hit the
    // end of the song as soon as possible.
704

705
    if(m_player->playing() && m_player->totalTime() > 0 && float(m_player->totalTime() - m_player->currentTime()) < m_pollInterval * 2)
706
        m_playTimer->changeInterval(50);
707

708
    m_noSeek = false;
709 710
}

711
void JuK::slotSetVolume(int volume)
712
{
713 714 715
    if(m_player && m_sliderAction && m_sliderAction->getVolumeSlider() &&
       m_sliderAction->getVolumeSlider()->maxValue() > 0 &&
       volume >= 0 && m_sliderAction->getVolumeSlider()->maxValue() >= volume)
716
    {
717
        m_player->setVolume(float(volume) / float(m_sliderAction->getVolumeSlider()->maxValue()));
718 719
    }
}
720

721
#include "juk.moc"