Commit 2b3afab2 authored by Scott Wheeler's avatar Scott Wheeler

Move more stuff dealing with playing into the PlayerManager class and out

of the JuK class.  Also along the way, where possible, continued trying to
decouple the classes and their interactions more.

svn path=/trunk/kdemultimedia/juk/; revision=291742
parent 81780b47
......@@ -33,6 +33,7 @@
#include "keydialog.h"
#include "tagguesserconfigdlg.h"
#include "filerenamerconfigdlg.h"
#include "playermanager.h"
////////////////////////////////////////////////////////////////////////////////
// public members
......@@ -106,63 +107,18 @@ void JuK::slotGuessTagInfoFromInternet()
void JuK::play()
{
if(m_player->paused()) {
m_player->play();
m_statusLabel->setPlayingItemInfo(playingString(), m_splitter->playingList());
// Here, before doing anything, we want to make sure that the m_player did
// in fact start.
if(m_player->playing()) {
actionCollection()->action("pause")->setEnabled(true);
actionCollection()->action("stop")->setEnabled(true);
m_playTimer->start(m_pollInterval);
if(m_systemTray)
m_systemTray->slotPlay();
}
}
else if(m_player->playing())
m_player->seekPosition(0);
else
play(m_splitter->playNextFile(m_randomPlayAction->isChecked(),
m_loopPlaylistAction->isChecked()));
m_player->play();
}
void JuK::pause()
{
if(!m_player)
return;
m_playTimer->stop();
m_player->pause();
m_statusLabel->setPlayingItemInfo(playingString(), m_splitter->playingList());
actionCollection()->action("pause")->setEnabled(false);
if(m_systemTray)
m_systemTray->slotPause();
}
void JuK::stop()
{
if(!m_player || !m_sliderAction || !m_sliderAction->volumeSlider())
return;
m_playTimer->stop();
m_player->stop();
actionCollection()->action("pause")->setEnabled(false);
actionCollection()->action("stop")->setEnabled(false);
actionCollection()->action("back")->setEnabled(false);
actionCollection()->action("forward")->setEnabled(false);
m_sliderAction->trackPositionSlider()->setValue(0);
m_sliderAction->trackPositionSlider()->setEnabled(false);
m_splitter->stop();
m_statusLabel->clear();
if(m_systemTray)
m_systemTray->slotStop();
}
void JuK::back()
......@@ -206,9 +162,6 @@ void JuK::seekForward()
void JuK::playPause()
{
if(!m_player)
return;
if(m_player->playing())
pause();
else
......@@ -273,7 +226,9 @@ void JuK::setupLayout()
this, SLOT(startPlayingPlaylist()));
// create status bar
m_statusLabel = new StatusLabel(statusBar());
statusBar()->addWidget(m_statusLabel, 1);
connect(m_splitter, SIGNAL(signalSelectedPlaylistCountChanged(int)),
......@@ -283,6 +238,8 @@ void JuK::setupLayout()
connect(m_statusLabel, SIGNAL(jumpButtonClicked()),
m_splitter, SLOT(slotSelectPlaying()));
PlayerManager::instance()->setStatusLabel(m_statusLabel);
// Needs to be here because m_splitter is not called before setupActions
// (because PlaylistSplitter itself accesses the actionCollection)
......@@ -443,10 +400,8 @@ void JuK::setupActions()
m_outputSelectAction = Player::playerSelectAction(actionCollection());
if(m_outputSelectAction) {
if(m_outputSelectAction)
m_outputSelectAction->setCurrentItem(0);
connect(m_outputSelectAction, SIGNAL(activated(int)), this, SLOT(slotSetOutput(int)));
}
new KAction(i18n("&Tag Guesser..."), 0, 0, this, SLOT(slotConfigureTagGuesser()),
actionCollection(), "tagGuesserConfig");
......@@ -496,11 +451,6 @@ void JuK::setupSystemTray()
connect(this, SIGNAL(signalNewSong(const QString&)),
m_systemTray, SLOT(slotNewSong(const QString&)));
if(m_player && m_player->paused())
m_systemTray->slotPause();
else if(m_player && m_player->playing())
m_systemTray->slotPlay();
m_toggleDockOnCloseAction->setEnabled(true);
m_togglePopupsAction->setEnabled(true);
......@@ -515,46 +465,13 @@ void JuK::setupSystemTray()
void JuK::setupPlayer()
{
m_trackPositionDragging = false;
m_noSeek = false;
m_muted = false;
actionCollection()->action("pause")->setEnabled(false);
actionCollection()->action("stop")->setEnabled(false);
actionCollection()->action("back")->setEnabled(false);
actionCollection()->action("forward")->setEnabled(false);
m_playTimer = new QTimer(this);
connect(m_playTimer, SIGNAL(timeout()), this, SLOT(slotPollPlay()));
if(m_sliderAction &&
m_sliderAction->trackPositionSlider() &&
m_sliderAction->volumeSlider())
{
connect(m_sliderAction->trackPositionSlider(), SIGNAL(valueChanged(int)),
this, SLOT(slotTrackPositionSliderUpdate(int)));
connect(m_sliderAction->trackPositionSlider(), SIGNAL(sliderPressed()),
this, SLOT(slotTrackPositionSliderClicked()));
connect(m_sliderAction->trackPositionSlider(), SIGNAL(sliderReleased()),
this, SLOT(slotTrackPositionSliderReleased()));
m_sliderAction->trackPositionSlider()->setEnabled(false);
connect(m_sliderAction->volumeSlider(), SIGNAL(valueChanged(int)),
this, SLOT(slotSetVolume(int)));
}
int playerType = 0;
if(m_outputSelectAction) {
playerType = m_outputSelectAction->currentItem();
connect(m_outputSelectAction, SIGNAL(activated(int)), this, SLOT(slotSetOutput(int)));
if(m_sliderAction) {
}
m_player = Player::createPlayer(playerType);
float volume =
float(m_sliderAction->volumeSlider()->value()) /
float(m_sliderAction->volumeSlider()->maxValue());
m_player->setVolume(volume);
m_player = PlayerManager::instance();
PlayerManager::instance()->setPlaylistInterface(m_splitter);
}
......@@ -705,7 +622,6 @@ bool JuK::queryExit()
m_systemTray = 0;
stop();
delete m_player;
Cache::instance()->save();
saveConfig();
......@@ -754,36 +670,8 @@ void JuK::updatePlaylistInfo()
void JuK::play(const QString &file)
{
if(!m_player || !m_sliderAction || !m_sliderAction->volumeSlider())
return;
if(m_player->paused())
m_player->stop();
m_player->play(file);
// Make sure that the m_player actually starts before doing anything.
if(m_player->playing()) {
actionCollection()->action("pause")->setEnabled(true);
actionCollection()->action("stop")->setEnabled(true);
actionCollection()->action("forward")->setEnabled(true);
m_backAction->setEnabled(true);
m_sliderAction->trackPositionSlider()->setValue(0);
m_sliderAction->trackPositionSlider()->setEnabled(true);
m_playTimer->start(m_pollInterval);
m_statusLabel->setPlayingItemInfo(playingString(), m_splitter->playingList());
emit signalNewSong(playingString());
if(m_systemTray)
m_systemTray->slotPlay();
}
else
stop();
emit signalNewSong(playingString());
}
KAction *JuK::createSplitterAction(const QString &text, const char *slot,
......@@ -853,13 +741,6 @@ void JuK::slotToggleSystemTray(bool enabled)
}
}
void JuK::slotSetOutput(int output)
{
stop();
delete m_player;
m_player = Player::createPlayer(output);
}
void JuK::slotEditKeys()
{
KeyDialog::configure(m_accel, actionCollection(), this);
......@@ -869,79 +750,6 @@ void JuK::slotEditKeys()
// additional player slots
////////////////////////////////////////////////////////////////////////////////
void JuK::slotTrackPositionSliderClicked()
{
m_trackPositionDragging = true;
}
void JuK::slotTrackPositionSliderReleased()
{
if(!m_player)
return;
m_trackPositionDragging = false;
m_player->seekPosition(m_sliderAction->trackPositionSlider()->value());
}
void JuK::slotTrackPositionSliderUpdate(int position)
{
if(!m_player)
return;
if(m_player->playing() && !m_trackPositionDragging && !m_noSeek)
m_player->seekPosition(position);
// The dragging flag is set, so just update the status label, rather than seeking
if(m_player->playing() && m_trackPositionDragging && !m_noSeek) {
// position from 0 to 1
float positionFraction = float(position) /
m_sliderAction->trackPositionSlider()->maxValue();
float totalTime = float(m_player->totalTime());
long seekTime = long(positionFraction * totalTime + 0.5); // "+0.5" for rounding
m_statusLabel->setItemCurrentTime(seekTime);
}
}
// This method is called when the play timer has expired.
void JuK::slotPollPlay()
{
if(!m_player)
return;
// Our locking mechanism. Since this method adjusts the play slider, we
// want to make sure that our adjustments
m_noSeek = true;
if(!m_player->playing()) {
m_playTimer->stop();
play(m_splitter->playNextFile(m_randomPlayAction->isChecked(),
m_loopPlaylistAction->isChecked()));
}
else if(!m_trackPositionDragging) {
m_sliderAction->trackPositionSlider()->setValue(m_player->position());
m_statusLabel->setItemTotalTime(m_player->totalTime());
m_statusLabel->setItemCurrentTime(m_player->currentTime());
}
// 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.
if(m_player->playing() &&
m_player->totalTime() > 0 &&
float(m_player->totalTime() - m_player->currentTime()) < m_pollInterval * 2)
{
m_playTimer->changeInterval(50);
}
m_noSeek = false;
}
void JuK::slotPlaySelectedFile()
{
QString file = m_splitter->playSelectedFile();
......@@ -951,16 +759,7 @@ void JuK::slotPlaySelectedFile()
void JuK::slotSetVolume(int volume)
{
if(m_player &&
m_sliderAction &&
m_sliderAction->volumeSlider() &&
m_sliderAction->volumeSlider()->maxValue() > 0 &&
volume >= 0 &&
m_sliderAction->volumeSlider()->maxValue() >= volume)
{
m_player->setVolume(float(volume) /
float(m_sliderAction->volumeSlider()->maxValue()));
}
m_player->slotSetVolume(volume);
}
void JuK::slotConfigureTagGuesser()
......
......@@ -31,7 +31,7 @@
#include <qlabel.h>
#include "player.h"
#include "playermanager.h"
#include "playlistsplitter.h"
#include "jukIface.h"
......@@ -149,16 +149,10 @@ private slots:
// settings menu
void slotToggleSystemTray(bool enabled);
void slotSetOutput(int output);
void slotEditKeys();
void slotConfigureTagGuesser();
void slotConfigureFileRenamer();
// additional player slots
void slotTrackPositionSliderClicked();
void slotTrackPositionSliderReleased();
void slotTrackPositionSliderUpdate(int position);
/**
* This method is called by the slider to set the volume of the player. Its
* value is relative to the maxValue() of the volume slider.
......@@ -169,7 +163,6 @@ private slots:
* This method is called to check our progress in the playing file. It uses
* m_playTimer to know when to call itself again.
*/
void slotPollPlay();
void slotPlaySelectedFile();
void startPlayingPlaylist();
void slotToggleMenuBar() { menuBar()->isVisible() ? menuBar()->hide() : menuBar()->show(); }
......@@ -201,11 +194,9 @@ private:
KToolBarPopupAction *m_backAction;
KToggleAction *m_loopPlaylistAction;
QTimer *m_playTimer;
Player *m_player;
PlayerManager *m_player;
KGlobalAccel *m_accel;
bool m_trackPositionDragging;
bool m_noSeek;
bool m_startDocked;
bool m_showSplash;
......
......@@ -25,6 +25,7 @@
#include "playermanager.h"
#include "slideraction.h"
#include "statuslabel.h"
PlayerManager *PlayerManager::m_instance = 0;
......@@ -38,6 +39,7 @@ PlayerManager::PlayerManager() :
m_actionCollection(0),
m_sliderAction(0),
m_playlistInterface(0),
m_statusLabel(0),
m_player(0),
m_timer(0),
m_noSeek(false)
......@@ -63,83 +65,88 @@ PlayerManager *PlayerManager::instance() // static
bool PlayerManager::playing() const
{
if(!m_player)
if(!player())
return false;
return m_player->playing();
return player()->playing();
}
bool PlayerManager::paused() const
{
if(!m_player)
if(!player())
return false;
return m_player->paused();
return player()->paused();
}
float PlayerManager::volume() const
{
if(!m_player)
if(!player())
return 0;
return m_player->volume();
return player()->volume();
}
long PlayerManager::totalTime() const
{
if(!m_player)
if(!player())
return 0;
return m_player->totalTime();
return player()->totalTime();
}
long PlayerManager::currentTime() const
{
if(!m_player)
if(!player())
return 0;
return m_player->currentTime();
return player()->currentTime();
}
int PlayerManager::position() const
{
if(!m_player)
if(!player())
return 0;
return m_player->position();
return player()->position();
}
void PlayerManager::setPlaylistInterface(const PlaylistInterface *interface)
void PlayerManager::setPlaylistInterface(PlaylistInterface *interface)
{
m_playlistInterface = interface;
}
void PlayerManager::setStatusLabel(StatusLabel *label)
{
m_statusLabel = label;
}
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////
void PlayerManager::play(const QString &fileName)
{
if(!m_player || !m_playlistInterface)
if(!player() || !m_playlistInterface)
return;
if(fileName.isNull()) {
if(m_player->paused())
m_player->play();
if(m_player->playing())
m_player->seekPosition(0);
if(player()->paused())
player()->play();
if(player()->playing())
player()->seekPosition(0);
else
m_player->play(m_playlistInterface->nextFile());
player()->play(m_playlistInterface->nextFile());
}
else {
if(m_player->paused())
m_player->stop();
m_player->play(fileName);
if(player()->paused())
player()->stop();
player()->play(fileName);
}
// Make sure that the m_player actually starts before doing anything.
// Make sure that the player() actually starts before doing anything.
if(!m_player->playing()) {
if(!player()->playing()) {
stop();
return;
}
......@@ -157,42 +164,66 @@ void PlayerManager::play(const QString &fileName)
void PlayerManager::pause()
{
if(!m_player)
if(!player())
return;
m_player->pause();
if(player()->paused()) {
play();
return;
}
m_timer->stop();
m_actionCollection->action("pause")->setEnabled(false);
player()->pause();
}
void PlayerManager::stop()
{
if(!m_player)
if(!player())
return;
m_player->stop();
m_timer->stop();
m_actionCollection->action("pause")->setEnabled(false);
m_actionCollection->action("stop")->setEnabled(false);
m_actionCollection->action("back")->setEnabled(false);
m_actionCollection->action("forward")->setEnabled(false);
m_sliderAction->trackPositionSlider()->setValue(0);
m_sliderAction->trackPositionSlider()->setEnabled(false);
m_statusLabel->clear();
player()->stop();
}
void PlayerManager::setVolume(float volume)
{
if(!m_player)
if(!player())
return;
m_player->setVolume(volume);
player()->setVolume(volume);
}
void PlayerManager::seek(long seekTime)
{
if(!m_player)
if(!player())
return;
m_player->seek(seekTime);
player()->seek(seekTime);
}
void PlayerManager::seekPosition(int position)
{
if(!m_player)
if(!player())
return;
if(!player()->playing() || m_noSeek)
return;
m_player->seekPosition(position);
slotUpdateTime(position);
player()->seekPosition(position);
}
////////////////////////////////////////////////////////////////////////////////
......@@ -201,22 +232,22 @@ void PlayerManager::seekPosition(int position)
void PlayerManager::slotPollPlay()
{
if(!m_player || !m_playlistInterface)
if(!player() || !m_playlistInterface)
return;
m_noSeek = true;
if(!m_player->playing()) {
if(!player()->playing()) {
m_timer->stop();
play(m_playlistInterface->nextFile());
}
else if(!m_sliderAction->dragging()) {
m_sliderAction->trackPositionSlider()->setValue(m_player->position());
// TODO: figure out something to do with the status bar interface
m_sliderAction->trackPositionSlider()->setValue(player()->position());
// m_statusLabel->setItemTotalTime(m_player->totalTime());
// m_statusLabel->setItemCurrentTime(m_player->currentTime());
if(m_statusLabel) {
m_statusLabel->setItemTotalTime(player()->totalTime());
m_statusLabel->setItemCurrentTime(player()->currentTime());
}
}
// Ok, this is weird stuff, but it works pretty well. Ordinarily we don't
......@@ -224,9 +255,9 @@ void PlayerManager::slotPollPlay()
// last interval, we want to check a lot -- to figure out that we've hit the
// end of the song as soon as possible.
if(m_player->playing() &&
m_player->totalTime() > 0 &&
float(m_player->totalTime() - m_player->currentTime()) < m_pollInterval * 2)
if(player()->playing() &&
player()->totalTime() > 0 &&
float(player()->totalTime() - player()->currentTime()) < m_pollInterval * 2)
{
m_timer->changeInterval(50);
}
......@@ -234,10 +265,42 @@ void PlayerManager::slotPollPlay()
m_noSeek = false;
}
void PlayerManager::slotSetOutput(int system)
{
stop();
delete m_player;
m_player = Player::createPlayer(system);
}
void PlayerManager::slotSetVolume(int volume)
{
setVolume(float(volume) / float(m_sliderAction->volumeSlider()->maxValue()));
}
void PlayerManager::slotUpdateTime(int position)
{
if(!m_statusLabel)
return;
float positionFraction = float(position) / m_sliderAction->trackPositionSlider()->maxValue();
float totalTime = float(m_player->totalTime());
long seekTime = long(positionFraction * totalTime + 0.5); // "+0.5" for rounding
m_statusLabel->setItemCurrentTime(seekTime);
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
Player *PlayerManager::player() const
{
if(!m_player)
instance()->setup();
return m_player;
}
void PlayerManager::setup()
{
// Since we're doing a little wizardry to keep the interaction and API
......@@ -271,22 +334,40 @@ void PlayerManager::setup()
return;
}
// initialize action states
m_actionCollection->action("pause")->setEnabled(false);
m_actionCollection->action("stop")->setEnabled(false);
m_actionCollection->action("back")->setEnabled(false);
m_actionCollection->action("forward")->setEnabled(false);
// setup sliders
m_sliderAction = static_cast<SliderAction *>(m_actionCollection->action("trackPositionAction"));
connect(m_sliderAction, SIGNAL(signalPositionChanged(int)),
this, SLOT(seekPosition(int)));
connect(m_sliderAction->trackPositionSlider(), SIGNAL(valueChanged(int)),
this, SLOT(slotUpdateTime(int)));
connect(m_sliderAction->volumeSlider(), SIGNAL(valueChanged(int)),
this, SLOT(slotSetVolume(int)));
KAction *outputAction = m_actionCollection->action("outputSelect");
if(outputAction) {
int mediaSystem = static_cast<KSelectAction *>(outputAction)->currentItem();
m_player = Player::createPlayer(mediaSystem);
connect(outputAction, SIGNAL(activated(int)), this, SLOT(setOutputSystem(int)));
}
else
m_player = Player::createPlayer();
float volume =
float(m_sliderAction->volumeSlider()->value()) /
float(m_sliderAction->volumeSlider()->maxValue());
m_player->setVolume(volume);
m_timer = new QTimer(this, "play timer");
connect(m_timer, SIGNAL(timeout()), this, SLOT(slotPollPlay()));
}
......
......@@ -24,6 +24,7 @@
class QTimer;
class SliderAction;
class StatusLabel;
/**
* This is a simple interface that should be implemented by objects used by
......@@ -33,8 +34,8 @@ class SliderAction;
class PlaylistInterface
{
public:
virtual QString nextFile() const = 0;
virtual QString previousFile() const = 0;
virtual QString nextFile() = 0;
virtual QString previousFile() = 0;
};
/**
......@@ -60,7 +61,8 @@ public:
virtual long currentTime() const;
virtual int position() const;
void setPlaylistInterface(const PlaylistInterface *interface);
void setPlaylistInterface(PlaylistInterface *interface);
void setStatusLabel(StatusLabel *label);
public slots:
......@@ -71,18 +73,24 @@ public slots:
virtual void seek(long seekTime);
virtual void seekPosition(int position);
void slotSetVolume(int volume); // TODO: make private
private:
Player *player() const;
void setup();
private slots: