Commit 5487fcaa authored by Scott Wheeler's avatar Scott Wheeler

Switch to Amarok's volume / track polition sliders.

There's a lot that still seems wonky, but it seems to all be Phonon
breakage that I can reproduce with the version pre-changeset.

Specifically Phonon (or its backends) seem quite fickle about when
they've decided that seeking is enabled.  The crossfading code seems
to compound this, but again, this does not seem to be a regression
from the previous code.

svn path=/trunk/KDE/kdemultimedia/juk/; revision=1231011
parent e43aa99e
......@@ -34,6 +34,9 @@ endif(TUNEPIMP_FOUND)
set(juk_SRCS ${tunepimp_SRCS}
advancedsearchdialog.cpp
slider.cpp
svghandler.cpp
volumepopupbutton.cpp
actioncollection.cpp
cache.cpp
categoryreaderinterface.cpp
......
......@@ -313,8 +313,10 @@ void JuK::setupActions()
// just in the toolbar
//////////////////////////////////////////////////
m_sliderAction = new SliderAction(i18n("Track Position"), this);
collection->addAction("trackPositionAction", m_sliderAction);
collection->addAction("trackPositionAction",
new TrackPositionAction(i18n("Track Position"), this));
collection->addAction("volumeAction",
new VolumeAction(i18n("Track Position"), this));
ActionCollection::actions()->addAssociatedWidget(this);
foreach (QAction* action, ActionCollection::actions()->actions())
......@@ -393,6 +395,7 @@ void JuK::readConfig()
const int maxVolume = 100;
const int volume = playerConfig.readEntry("Volume", maxVolume);
m_player->setVolume(volume * 0.01);
ActionCollection::action<VolumeAction>("volumeAction")->button()->refresh();
bool enableCrossfade = playerConfig.readEntry("CrossfadeTracks", true);
m_player->setCrossfadeEnabled(enableCrossfade);
......
......@@ -84,7 +84,6 @@ private:
StatusLabel *m_statusLabel;
SystemTray *m_systemTray;
SliderAction *m_sliderAction;
KToggleAction *m_randomPlayAction;
KToggleAction *m_toggleSystemTrayAction;
KToggleAction *m_toggleDockOnCloseAction;
......
......@@ -106,5 +106,6 @@
<Action name="back"/>
<Action name="forward"/>
<Action name="trackPositionAction"/>
<Action name="volumeAction"/>
</ToolBar>
</kpartgui>
......@@ -57,10 +57,8 @@ enum PlayerManagerStatus { StatusStopped = -1, StatusPaused = 1, StatusPlaying =
PlayerManager::PlayerManager() :
QObject(),
m_sliderAction(0),
m_playlistInterface(0),
m_statusLabel(0),
m_muted(false),
m_setup(false),
m_crossfadeTracks(true),
m_curOutputPath(0)
......@@ -75,8 +73,7 @@ PlayerManager::PlayerManager() :
PlayerManager::~PlayerManager()
{
delete m_sliderAction;
m_sliderAction = 0;
}
////////////////////////////////////////////////////////////////////////////////
......@@ -100,6 +97,14 @@ bool PlayerManager::paused() const
return m_media[m_curOutputPath]->state() == Phonon::PausedState;
}
bool PlayerManager::muted() const
{
if(!m_setup)
return false;
return m_output[m_curOutputPath]->isMuted();
}
float PlayerManager::volume() const
{
if(!m_setup)
......@@ -138,6 +143,14 @@ int PlayerManager::currentTime() const
return m_media[m_curOutputPath]->currentTime() / 1000;
}
bool PlayerManager::seekable() const
{
if(!m_setup)
return false;
return m_media[m_curOutputPath]->isSeekable();
}
QStringList PlayerManager::trackProperties()
{
return FileHandle::properties();
......@@ -373,12 +386,22 @@ void PlayerManager::volumeDown()
setVolume(volume() - 0.04); // 4% down
}
void PlayerManager::mute()
void PlayerManager::setMuted(bool m)
{
if(!m_setup)
return;
m_output[m_curOutputPath]->setMuted(!m_output[m_curOutputPath]->isMuted());
m_output[m_curOutputPath]->setMuted(m);
}
bool PlayerManager::mute()
{
if(!m_setup)
return false;
bool newState = !muted();
setMuted(newState);
return newState;
}
////////////////////////////////////////////////////////////////////////////////
......@@ -428,6 +451,7 @@ void PlayerManager::slotFinished()
void PlayerManager::slotLength(qint64 msec)
{
m_statusLabel->setItemTotalTime(msec / 1000);
emit totalTimeChanged(msec);
}
void PlayerManager::slotTick(qint64 msec)
......@@ -437,6 +461,8 @@ void PlayerManager::slotTick(qint64 msec)
if(m_statusLabel)
m_statusLabel->setItemCurrentTime(msec / 1000);
emit tick(msec);
}
void PlayerManager::slotStateChanged(Phonon::State newstate, Phonon::State oldstate)
......@@ -555,28 +581,9 @@ void PlayerManager::setup()
action("forward")->setEnabled(false);
action("forwardAlbum")->setEnabled(false);
// setup sliders (a separate slot is used to switch as needed)
m_sliderAction = action<SliderAction>("trackPositionAction");
if(m_sliderAction->trackPositionSlider())
m_sliderAction->trackPositionSlider()->setMediaObject(m_media[0]);
if(m_sliderAction->volumeSlider())
m_sliderAction->volumeSlider()->setAudioOutput(m_output[0]);
QDBusConnection::sessionBus().registerObject("/Player", this);
}
void PlayerManager::slotUpdateSliders()
{
m_sliderAction->trackPositionSlider()->setMediaObject(m_media[m_curOutputPath]);
m_sliderAction->volumeSlider()->setAudioOutput(m_output[m_curOutputPath]);
disconnect(m_media[1 - m_curOutputPath], 0, this, SLOT(slotUpdateSliders()));
connect(m_media[1 - m_curOutputPath], SIGNAL(finished()), SLOT(slotFinished()));
}
void PlayerManager::slotUpdateGuiIfStopped()
{
if(m_media[0]->state() == Phonon::StoppedState && m_media[1]->state() == Phonon::StoppedState)
......@@ -591,10 +598,6 @@ void PlayerManager::crossfadeToFile(const FileHandle &newFile)
disconnect(m_media[m_curOutputPath], SIGNAL(finished()), this, 0);
connect(m_media[nextOutputPath], SIGNAL(finished()), SLOT(slotFinished()));
// Wait a couple of seconds and switch slider objects. (We would simply
// handle this when finished() is emitted but phonon-gst is buggy).
QTimer::singleShot(2000, this, SLOT(slotUpdateSliders()));
m_fader[nextOutputPath]->setVolume(0.0f);
emit signalItemChanged(newFile);
......
......@@ -30,7 +30,6 @@
#include <Phonon/Path>
class KSelectAction;
class SliderAction;
class StatusLabel;
class PlaylistInterface;
class QPixmap;
......@@ -57,10 +56,12 @@ public:
bool playing() const;
bool paused() const;
bool muted() const;
float volume() const;
int status() const;
int totalTime() const;
int currentTime() const;
bool seekable() const;
//int position() const;
QStringList trackProperties();
......@@ -78,7 +79,6 @@ public:
QString randomPlayMode() const;
public slots:
void play(const FileHandle &file);
void play(const QString &file);
void play();
......@@ -94,12 +94,16 @@ public slots:
void back();
void volumeUp();
void volumeDown();
void mute();
void setMuted(bool m);
bool mute();
void setRandomPlayMode(const QString &randomMode);
void setCrossfadeEnabled(bool enableCrossfade);
signals:
void tick(int time);
void totalTimeChanged(int time);
void signalPlay();
void signalPause();
void signalStop();
......@@ -116,13 +120,11 @@ private slots:
void slotLength(qint64);
void slotTick(qint64);
void slotStateChanged(Phonon::State, Phonon::State);
void slotUpdateSliders();
/// Updates the GUI to reflect stopped playback if we're stopped at this point.
void slotUpdateGuiIfStopped();
private:
FileHandle m_file;
SliderAction *m_sliderAction;
PlaylistInterface *m_playlistInterface;
StatusLabel *m_statusLabel;
bool m_muted;
......
This diff is collapsed.
/****************************************************************************************
* Copyright (c) 2003-2009 Mark Kretschmann <kretschmann@kde.org> *
* Copyright (c) 2005 Gabor Lehel <illissius@gmail.com> *
* Copyright (c) 2008 Dan Meltzer <parallelgrapefruit@gmail.com> *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
#ifndef SLIDERWIDGET_H
#define SLIDERWIDGET_H
#include <QList>
#include <QPixmap>
#include <QSlider>
#include <QVector>
class QPalette;
class QTimer;
class Slider : public QSlider
{
Q_OBJECT
public:
explicit Slider( Qt::Orientation, uint max = 0, QWidget* parent = 0 );
virtual void setValue( int );
signals:
//we emit this when the user has specifically changed the slider
//so connect to it if valueChanged() is too generic
//Qt also emits valueChanged( int )
void sliderReleased( int );
protected:
virtual void wheelEvent( QWheelEvent* );
virtual void mouseMoveEvent( QMouseEvent* );
virtual void mouseReleaseEvent( QMouseEvent* );
virtual void mousePressEvent( QMouseEvent* );
virtual void slideEvent( QMouseEvent* );
QRect sliderHandleRect( const QRect &slider, qreal percent ) const;
void paintCustomSlider( QPainter *p );
bool m_sliding;
bool m_usingCustomStyle;
static const int s_borderWidth = 6;
static const int s_borderHeight = 6;
static const int s_sliderInsertX = 5;
static const int s_sliderInsertY = 5;
private:
bool m_outside;
int m_prevValue;
bool m_needsResize;
QPixmap m_topLeft;
QPixmap m_topRight;
QPixmap m_top;
QPixmap m_bottomRight;
QPixmap m_right;
QPixmap m_bottomLeft;
QPixmap m_bottom;
QPixmap m_left;
Q_DISABLE_COPY( Slider )
};
class VolumeSlider : public Slider
{
Q_OBJECT
public:
explicit VolumeSlider( uint max, QWidget *parent, bool customStyle = true );
// VolumePopupButton needs to access this
virtual void wheelEvent( QWheelEvent *e );
protected:
virtual void paintEvent( QPaintEvent* );
virtual void mousePressEvent( QMouseEvent* );
virtual void contextMenuEvent( QContextMenuEvent* );
signals:
void volumeChanged( float );
private slots:
void emitVolumeChanged( int );
private:
Q_DISABLE_COPY( VolumeSlider )
};
class TimeSlider : public Slider
{
Q_OBJECT
public:
TimeSlider( QWidget *parent );
void setSliderValue( int value );
protected:
virtual void paintEvent( QPaintEvent* );
virtual void mousePressEvent( QMouseEvent* );
virtual void sliderChange( SliderChange change );
virtual bool event( QEvent * event );
private:
Q_DISABLE_COPY( TimeSlider )
int m_knobX; // The position of the current indicator.
};
#endif
......@@ -26,195 +26,52 @@
#include <QFocusEvent>
#include <QBoxLayout>
////////////////////////////////////////////////////////////////////////////////
// VolumeSlider implementation
////////////////////////////////////////////////////////////////////////////////
VolumeSlider::VolumeSlider(QWidget *parent) :
Phonon::VolumeSlider(parent)
{
setOrientation(Qt::Horizontal);
setMinimumWidth(70);
}
void VolumeSlider::focusInEvent(QFocusEvent *)
{
clearFocus();
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
SliderAction::SliderAction(const QString &text, QObject* parent)
: KAction(text, parent),
m_toolBar(0),
m_widget(0),
m_layout(0),
m_trackPositionSlider(0),
m_volumeSlider(0)
{
}
SliderAction::~SliderAction()
#include "volumepopupbutton.h"
#include "slider.h"
#include "playermanager.h"
#include "juk.h"
TrackPositionAction::TrackPositionAction(const QString &text, QObject *parent) :
KAction(text, parent),
m_slider(0)
{
}
int SliderAction::plug(QWidget *parent, int index)
QWidget *TrackPositionAction::createWidget(QWidget *parent)
{
Q_UNUSED(index)
m_widget = createWidget(parent);
if(!m_widget)
return -1;
m_slider = new TimeSlider(parent);
// the check for null makes sure that there is only one toolbar that this is
// "plugged" in to
PlayerManager *player = JuK::JuKInstance()->playerManager();
if(!m_toolBar && qobject_cast<KToolBar *>(parent)) {
m_toolBar = static_cast<KToolBar *>(parent);
m_toolBar->addWidget(m_widget);
connect(m_toolBar, SIGNAL(destroyed()), this, SLOT(slotToolbarDestroyed()));
return (associatedWidgets().count() - 1);
}
connect(player, SIGNAL(tick(int)), m_slider, SLOT(setValue(int)));
connect(player, SIGNAL(totalTimeChanged(int)), this, SLOT(totalTimeChanged(int)));
connect(m_slider, SIGNAL(sliderMoved(int)), player, SLOT(seek(int)));
return -1;
return m_slider;
}
void SliderAction::unplug(QWidget *parent)
void TrackPositionAction::totalTimeChanged(int ms)
{
if (parent->inherits("KToolBar")) {
delete m_widget;
m_widget = 0;
m_toolBar = 0;
}
m_slider->setRange(0, ms);
bool seekable = JuK::JuKInstance()->playerManager()->seekable();
m_slider->setEnabled(seekable);
m_slider->setToolTip(seekable ?
QString() :
i18n("Seeking is not supported in this file with your audio settings."));
}
QWidget *SliderAction::createToolBarWidget(QToolBar *parent)
VolumeAction::VolumeAction(const QString &text, QObject *parent) :
KAction(text, parent),
m_button(0)
{
if(parent) {
QWidget *base = new QWidget(parent);
base->setBackgroundRole(parent->backgroundRole());
base->setObjectName(QLatin1String("kde toolbar widget"));
m_layout = new QHBoxLayout(base);
//m_layout->setDirection(QBoxLayout::TopToBottom);
m_layout->setMargin(5);
m_layout->setSpacing(5);
m_layout->addItem(new QSpacerItem(20, 1));
m_trackPositionSlider = new Phonon::SeekSlider(base);
m_trackPositionSlider->setObjectName(QLatin1String("trackPositionSlider"));
m_trackPositionSlider->setOrientation(Qt::Horizontal);
//m_trackPositionSlider->setToolTip( i18n("Track position"));
m_layout->addWidget(m_trackPositionSlider);
m_layout->addItem(new QSpacerItem(10, 1));
m_volumeSlider = new VolumeSlider(base);
m_volumeSlider->setObjectName(QLatin1String("volumeSlider"));
m_layout->addWidget(m_volumeSlider);
connect(parent, SIGNAL(iconSizeChanged(QSize)), m_volumeSlider,
SLOT(setIconSize(QSize)));
m_volumeSlider->setObjectName(QLatin1String("kde toolbar widget"));
m_trackPositionSlider->setObjectName(QLatin1String("kde toolbar widget"));
m_layout->setStretchFactor(m_trackPositionSlider, 4);
m_layout->setStretchFactor(m_volumeSlider, 1);
connect(parent, SIGNAL(modechange()), this, SLOT(slotUpdateSize()));
return base;
}
else
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
QWidget *SliderAction::createWidget(QWidget *parent) // virtual -- used by base class
{
if(parent) {
QWidget *base = new QWidget(parent);
base->setBackgroundRole(parent->backgroundRole());
base->setObjectName( QLatin1String("kde toolbar widget" ));
m_layout = new QHBoxLayout(base);
m_layout->setMargin(5);
m_layout->setSpacing(5);
m_layout->addItem(new QSpacerItem(20, 1));
m_trackPositionSlider = new Phonon::SeekSlider(base);
m_trackPositionSlider->setObjectName(QLatin1String("trackPositionSlider"));
//m_trackPositionSlider->setToolTip(i18n("Track position"));
m_layout->addWidget(m_trackPositionSlider);
m_layout->addItem(new QSpacerItem(10, 1));
m_volumeSlider = new VolumeSlider(base);
m_volumeSlider->setObjectName(QLatin1String("volumeSlider"));
m_layout->addWidget(m_volumeSlider);
m_volumeSlider->setObjectName(QLatin1String("kde toolbar widget"));
m_trackPositionSlider->setObjectName(QLatin1String("kde toolbar widget"));
m_layout->setStretchFactor(m_trackPositionSlider, 4);
m_layout->setStretchFactor(m_volumeSlider, 1);
return base;
}
else
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// private slots
////////////////////////////////////////////////////////////////////////////////
void SliderAction::slotUpdateSize()
QWidget *VolumeAction::createWidget(QWidget *parent)
{
static const int offset = 3;
static const int absoluteMax = 10000;
if(!m_toolBar)
return;
if(m_toolBar->orientation() == Qt::Vertical) {
m_volumeSlider->setMaximumWidth(m_toolBar->iconSize().width() - offset);
m_volumeSlider->setMaximumHeight(volumeMax);
m_trackPositionSlider->setMaximumWidth(m_toolBar->iconSize().width() - offset);
m_trackPositionSlider->setMaximumHeight(absoluteMax);
}
else {
m_volumeSlider->setMaximumHeight(m_toolBar->iconSize().height() - offset);
m_volumeSlider->setMaximumWidth(volumeMax);
m_trackPositionSlider->setMaximumHeight(m_toolBar->iconSize().height() - offset);
m_trackPositionSlider->setMaximumWidth(absoluteMax);
}
}
void SliderAction::slotToolbarDestroyed()
{
#if 0 // what's going on here?
int index = findContainer(m_toolBar);
if(index != -1)
removeContainer(index);
#endif
m_toolBar = 0;
// This is probably a leak, but this code path hardly ever occurs, and it's
// too hard to debug correctly.
m_trackPositionSlider = 0;
m_volumeSlider = 0;
m_button = new VolumePopupButton(parent);
return m_button;
}
#include "slideraction.moc"
......
......@@ -17,56 +17,36 @@
#define SLIDERACTION_H
#include <kaction.h>
//Added by qt3to4:
#include <QWheelEvent>
#include <QFocusEvent>
#include <QBoxLayout>
#include <ktoolbar.h>
#include <phonon/volumeslider.h>
#include <phonon/seekslider.h>
class QBoxLayout;
#include "volumepopupbutton.h"
class VolumeSlider : public Phonon::VolumeSlider
class Slider;
class TrackPositionAction : public KAction
{
Q_OBJECT
public:
VolumeSlider(QWidget *parent);
TrackPositionAction(const QString &text, QObject *parent);
Slider *slider() const { return m_slider; }
protected:
virtual void focusInEvent(QFocusEvent *);
virtual QWidget *createWidget(QWidget *parent);
private slots:
void totalTimeChanged(int ms);
private:
Slider *m_slider;
};
class SliderAction : public KAction
class VolumeAction : public KAction
{
Q_OBJECT
public:
SliderAction(const QString &text, QObject* parent);
virtual ~SliderAction();
VolumeSlider *volumeSlider() const { return m_volumeSlider; }
Phonon::SeekSlider *trackPositionSlider() const { return m_trackPositionSlider; }
virtual int plug(QWidget *parent, int index = -1);
virtual void unplug(QWidget *widget);
virtual QWidget* createToolBarWidget(QToolBar* parent);
private:
QWidget *createWidget(QWidget *parent);
private slots:
void slotUpdateSize();
void slotToolbarDestroyed();
VolumeAction(const QString &text, QObject *parent);
VolumePopupButton *button() const { return m_button; }
protected:
virtual QWidget *createWidget(QWidget *parent);
private:
KToolBar *m_toolBar;
QWidget *m_widget;
QBoxLayout *m_layout;
Phonon::SeekSlider *m_trackPositionSlider;
VolumeSlider *m_volumeSlider;
static const int volumeMax = 50;
VolumePopupButton *m_button;
};
#endif
......
/****************************************************************************************
* Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org> *
* Copyright (c) 2008 Jeff Mitchell <kde-dev@emailgoeshere.com> *
* Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org> *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
#include "svghandler.h"
#include <KColorScheme>
#include <KColorUtils>
#include <KStandardDirs>
#include <KDebug>
#include <QHash>
#include <QPainter>
#include <QPalette>
#include <QReadLocker>
#include <QStyleOptionSlider>
#include <QWriteLocker>
namespace The {
static SvgHandler* s_SvgHandler_instance = 0;
SvgHandler* svgHandler()
{
if( !s_SvgHandler_instance )
s_SvgHandler_instance = new SvgHandler();
return s_SvgHandler_instance;
}
}
SvgHandler::SvgHandler( QObject* parent )
: QObject( parent )
, m_cache( new KPixmapCache( "JuK-pixmaps" ) )
{
m_cache->setCacheLimit( 10 * 1024 );
}
SvgHandler::~SvgHandler()
{
delete m_cache;
qDeleteAll( m_renderers );
m_renderers.clear();
The::s_SvgHandler_instance = 0;
}
bool SvgHandler::loadSvg( const QString& name )
{
const QString &svgFilename = name;
QSvgRenderer *renderer = new QSvgRenderer( svgFilename );
if ( !renderer->isValid() )
{
delete renderer;
return false;
}
QWriteLocker writeLocker( &m_lock );
if( m_renderers[name] )
delete m_renderers[name];
m_renderers[name] = renderer;
return true;
}
QPixmap SvgHandler::renderSvg( const QString& keyname,
int width,
int height,
const QString& element,
bool skipCache )
{
QString key;
QString name;
if( !skipCache )