Commit 7dd66e97 authored by Christoph Pfister's avatar Christoph Pfister

move state handling code into AbstractMediaWidget

parent 847cfedb
......@@ -5,7 +5,6 @@ Installing Kaffeine
The following development headers are needed (recommended versions):
* Qt >= 4.6
* KDE >= 4.4
* libvlc >= 1.1.1
* libX11
* libXss
......
......@@ -22,189 +22,220 @@
#include <QCoreApplication>
void AbstractMediaWidget::setMediaWidget(MediaWidget *mediaWidget_)
AbstractMediaWidget::AbstractMediaWidget(QWidget *parent) : QWidget(parent), mediaWidget(NULL)
{
mediaWidget = mediaWidget_;
resetState();
}
void AbstractMediaWidget::invalidateState()
AbstractMediaWidget::~AbstractMediaWidget()
{
if (dirtyFlags.fetchAndStoreRelaxed(InvalidateState) == 0) {
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
}
void AbstractMediaWidget::addDirtyFlags(DirtyFlags additionalDirtyFlags)
void AbstractMediaWidget::setMediaWidget(MediaWidget *mediaWidget_)
{
while (true) {
uint oldDirtyFlags = dirtyFlags;
uint newDirtyFlags = (oldDirtyFlags | additionalDirtyFlags);
mediaWidget = mediaWidget_;
}
if (oldDirtyFlags == newDirtyFlags) {
break;
}
void AbstractMediaWidget::resetState()
{
if (pendingUpdates == 0) {
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
if (!dirtyFlags.testAndSetRelaxed(oldDirtyFlags, newDirtyFlags)) {
continue;
}
pendingUpdates = ResetState;
playbackStatus = MediaWidget::Idle;
totalTime = 0;
currentTime = 0;
seekable = false;
metadata.clear();
audioChannels.clear();
currentAudioChannel = -1;
subtitles.clear();
currentSubtitle = -1;
titleCount = 0;
currentTitle = -1;
chapterCount = 0;
currentChapter = -1;
angleCount = 0;
currentAngle = -1;
dvdMenu = false;
videoSize = QSize();
}
void AbstractMediaWidget::addPendingUpdate(PendingUpdate pendingUpdate)
{
if (pendingUpdates == 0) {
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
if (oldDirtyFlags == 0) {
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
pendingUpdates |= pendingUpdate;
}
break;
}
void AbstractMediaWidget::updatePlaybackStatus(MediaWidget::PlaybackStatus playbackStatus_)
{
playbackStatus = playbackStatus_;
addPendingUpdate(UpdatePlaybackStatus);
}
void AbstractMediaWidget::customEvent(QEvent *event)
void AbstractMediaWidget::updateTotalTime(int totalTime_)
{
Q_UNUSED(event)
totalTime = totalTime_;
while (true) {
uint oldDirtyFlags = dirtyFlags;
uint lowestDirtyFlag = (oldDirtyFlags & (~(oldDirtyFlags - 1)));
uint newDirtyFlags = (oldDirtyFlags & (~lowestDirtyFlag));
if (totalTime < 0) {
totalTime = 0;
}
if (oldDirtyFlags == newDirtyFlags) {
break;
}
addPendingUpdate(UpdateTotalTime);
}
if (!dirtyFlags.testAndSetRelaxed(oldDirtyFlags, newDirtyFlags)) {
continue;
}
void AbstractMediaWidget::updateCurrentTime(int currentTime_)
{
currentTime = currentTime_;
switch (static_cast<DirtyFlag>(lowestDirtyFlag)) {
case PlaybackFinished:
mediaWidget->playbackFinished();
break;
case UpdatePlaybackStatus:
mediaWidget->updatePlaybackStatus(getPlaybackStatus());
break;
case UpdateTotalTime:
mediaWidget->updateTotalTime(getTotalTime());
break;
case UpdateCurrentTime:
mediaWidget->updateCurrentTime(getCurrentTime());
break;
case UpdateSeekable:
mediaWidget->updateSeekable(isSeekable());
break;
case UpdateMetadata:
mediaWidget->updateMetadata(getMetadata());
break;
case UpdateAudioChannels:
mediaWidget->updateAudioChannels(getAudioChannels(),
getCurrentAudioChannel());
break;
case UpdateSubtitles:
mediaWidget->updateSubtitles(getSubtitles(), getCurrentSubtitle());
break;
case UpdateTitles:
mediaWidget->updateTitles(getTitleCount(), getCurrentTitle());
break;
case UpdateChapters:
mediaWidget->updateChapters(getChapterCount(), getCurrentChapter());
break;
case UpdateAngles:
mediaWidget->updateAngles(getAngleCount(), getCurrentAngle());
break;
case UpdateDvdPlayback:
mediaWidget->updateDvdPlayback(hasMenu());
break;
case UpdateVideoSize:
// FIXME
mediaWidget->updateVideoSize();
break;
case InvalidateState:
// this is a combination of flags
break;
}
if (currentTime < 0) {
currentTime = 0;
}
}
MediaWidget::PlaybackStatus DummyMediaWidget::getPlaybackStatus()
{
return MediaWidget::Idle;
addPendingUpdate(UpdateCurrentTime);
}
int DummyMediaWidget::getCurrentTime()
void AbstractMediaWidget::updateSeekable(bool seekable_)
{
return 0;
seekable = seekable_;
addPendingUpdate(UpdateSeekable);
}
int DummyMediaWidget::getTotalTime()
void AbstractMediaWidget::updateMetadata(const QMap<MediaWidget::MetadataType, QString> &metadata_)
{
return 0;
metadata = metadata_;
addPendingUpdate(UpdateMetadata);
}
bool DummyMediaWidget::isSeekable()
void AbstractMediaWidget::updateAudioChannels(const QStringList &audioChannels_)
{
return false;
audioChannels = audioChannels_;
addPendingUpdate(UpdateAudioChannels);
}
QMap<MediaWidget::MetadataType, QString> DummyMediaWidget::getMetadata()
void AbstractMediaWidget::updateCurrentAudioChannel(int currentAudioChannel_)
{
return QMap<MediaWidget::MetadataType, QString>();
currentAudioChannel = currentAudioChannel_;
addPendingUpdate(UpdateAudioChannels);
}
QStringList DummyMediaWidget::getAudioChannels()
void AbstractMediaWidget::updateSubtitles(const QStringList &subtitles_)
{
return QStringList();
subtitles = subtitles_;
addPendingUpdate(UpdateSubtitles);
}
int DummyMediaWidget::getCurrentAudioChannel()
void AbstractMediaWidget::updateCurrentSubtitle(int currentSubtitle_)
{
return -1;
currentSubtitle = currentSubtitle_;
addPendingUpdate(UpdateSubtitles);
}
QStringList DummyMediaWidget::getSubtitles()
void AbstractMediaWidget::updateTitleCount(int titleCount_)
{
return QStringList();
titleCount = titleCount_;
addPendingUpdate(UpdateTitles);
}
int DummyMediaWidget::getCurrentSubtitle()
void AbstractMediaWidget::updateCurrentTitle(int currentTitle_)
{
return -1;
currentTitle = currentTitle_;
addPendingUpdate(UpdateTitles);
}
int DummyMediaWidget::getTitleCount()
void AbstractMediaWidget::updateChapterCount(int chapterCount_)
{
return 0;
chapterCount = chapterCount_;
addPendingUpdate(UpdateChapters);
}
int DummyMediaWidget::getCurrentTitle()
void AbstractMediaWidget::updateCurrentChapter(int currentChapter_)
{
return -1;
currentChapter = currentChapter_;
addPendingUpdate(UpdateChapters);
}
int DummyMediaWidget::getChapterCount()
void AbstractMediaWidget::updateAngleCount(int angleCount_)
{
return 0;
angleCount = angleCount_;
addPendingUpdate(UpdateAngles);
}
int DummyMediaWidget::getCurrentChapter()
void AbstractMediaWidget::updateCurrentAngle(int currentAngle_)
{
return -1;
currentAngle = currentAngle_;
addPendingUpdate(UpdateAngles);
}
int DummyMediaWidget::getAngleCount()
void AbstractMediaWidget::updateDvdMenu(bool dvdMenu_)
{
return 0;
dvdMenu = dvdMenu_;
addPendingUpdate(UpdateDvdMenu);
}
int DummyMediaWidget::getCurrentAngle()
void AbstractMediaWidget::updateVideoSize(const QSize &videoSize_)
{
return -1;
videoSize = videoSize_;
addPendingUpdate(UpdateVideoSize);
}
bool DummyMediaWidget::hasMenu()
void AbstractMediaWidget::customEvent(QEvent *event)
{
return false;
}
Q_UNUSED(event)
QSize DummyMediaWidget::getVideoSize()
{
return QSize();
while (pendingUpdates != 0) {
uint lowestPendingUpdate = (pendingUpdates & (~(pendingUpdates - 1)));
pendingUpdates &= ~lowestPendingUpdate;
switch (static_cast<PendingUpdates>(lowestPendingUpdate)) {
case PlaybackFinished:
mediaWidget->playbackFinished();
break;
case UpdatePlaybackStatus:
mediaWidget->updatePlaybackStatus();
break;
case UpdateTotalTime:
mediaWidget->updateTotalTime();
break;
case UpdateCurrentTime:
mediaWidget->updateCurrentTime();
break;
case UpdateSeekable:
mediaWidget->updateSeekable();
break;
case UpdateMetadata:
mediaWidget->updateMetadata();
break;
case UpdateAudioChannels:
mediaWidget->updateAudioChannels();
break;
case UpdateSubtitles:
mediaWidget->updateSubtitles();
break;
case UpdateTitles:
mediaWidget->updateTitles();
break;
case UpdateChapters:
mediaWidget->updateChapters();
break;
case UpdateAngles:
mediaWidget->updateAngles();
break;
case UpdateDvdMenu:
mediaWidget->updateDvdMenu();
break;
case UpdateVideoSize:
mediaWidget->updateVideoSize();
break;
case ResetState:
// this is a combination of flags
break;
}
}
}
void DummyMediaWidget::setMuted(bool muted)
......@@ -230,10 +261,12 @@ void DummyMediaWidget::setDeinterlacing(bool deinterlacing)
void DummyMediaWidget::play(const MediaSource &source)
{
Q_UNUSED(source)
resetState();
}
void DummyMediaWidget::stop()
{
resetState();
}
void DummyMediaWidget::setPaused(bool paused)
......
......@@ -26,31 +26,31 @@
class AbstractMediaWidget : public QWidget
{
public:
explicit AbstractMediaWidget(QWidget *parent) : QWidget(parent), mediaWidget(NULL) { }
virtual ~AbstractMediaWidget() { }
explicit AbstractMediaWidget(QWidget *parent);
virtual ~AbstractMediaWidget();
void setMediaWidget(MediaWidget *mediaWidget_);
void invalidateState(); // re-emit signals
// zero-based numbering is used everywhere (e.g. first audio channel = 0)
virtual MediaWidget::PlaybackStatus getPlaybackStatus() = 0;
virtual int getTotalTime() = 0; // milliseconds
virtual int getCurrentTime() = 0; // milliseconds
virtual bool isSeekable() = 0;
virtual QMap<MediaWidget::MetadataType, QString> getMetadata() = 0;
virtual QStringList getAudioChannels() = 0;
virtual int getCurrentAudioChannel() = 0;
virtual QStringList getSubtitles() = 0;
virtual int getCurrentSubtitle() = 0;
virtual int getTitleCount() = 0;
virtual int getCurrentTitle() = 0;
virtual int getChapterCount() = 0;
virtual int getCurrentChapter() = 0;
virtual int getAngleCount() = 0;
virtual int getCurrentAngle() = 0;
virtual bool hasMenu() = 0;
virtual QSize getVideoSize() = 0;
MediaWidget::PlaybackStatus getPlaybackStatus() const { return playbackStatus; }
int getTotalTime() const { return totalTime; } // milliseconds
int getCurrentTime() const { return currentTime; } // milliseconds
bool isSeekable() const { return seekable; }
QMap<MediaWidget::MetadataType, QString> getMetadata() const { return metadata; }
QStringList getAudioChannels() const { return audioChannels; }
int getCurrentAudioChannel() const { return currentAudioChannel; }
QStringList getSubtitles() const { return subtitles; }
int getCurrentSubtitle() const { return currentSubtitle; }
int getTitleCount() const { return titleCount; }
int getCurrentTitle() const { return currentTitle; }
int getChapterCount() const { return chapterCount; }
int getCurrentChapter() const { return currentChapter; }
int getAngleCount() const { return angleCount; }
int getCurrentAngle() const { return currentAngle; }
bool hasDvdMenu() const { return dvdMenu; }
QSize getVideoSize() const { return videoSize; }
virtual void setMuted(bool muted) = 0;
virtual void setVolume(int volume) = 0; // [0 - 200]
virtual void setAspectRatio(MediaWidget::AspectRatio aspectRatio) = 0;
......@@ -69,7 +69,28 @@ public:
virtual bool jumpToNextChapter() = 0;
virtual void toggleMenu() = 0;
enum DirtyFlag
protected:
void resetState();
void updatePlaybackStatus(MediaWidget::PlaybackStatus playbackStatus_);
void updateTotalTime(int totalTime_);
void updateCurrentTime(int currentTime_);
void updateSeekable(bool seekable_);
void updateMetadata(const QMap<MediaWidget::MetadataType, QString> &metadata_);
void updateAudioChannels(const QStringList &audioChannels_);
void updateCurrentAudioChannel(int currentAudioChannel_);
void updateSubtitles(const QStringList &subtitles_);
void updateCurrentSubtitle(int currentSubtitle_);
void updateTitleCount(int titleCount_);
void updateCurrentTitle(int currentTitle_);
void updateChapterCount(int chapterCount_);
void updateCurrentChapter(int currentChapter_);
void updateAngleCount(int angleCount_);
void updateCurrentAngle(int currentAngle_);
void updateDvdMenu(bool dvdMenu_);
void updateVideoSize(const QSize &videoSize_);
private:
enum PendingUpdate
{
PlaybackFinished = (1 << 0),
UpdatePlaybackStatus = (1 << 1),
......@@ -82,28 +103,40 @@ public:
UpdateTitles = (1 << 8),
UpdateChapters = (1 << 9),
UpdateAngles = (1 << 10),
UpdateDvdPlayback = (1 << 11),
UpdateDvdMenu = (1 << 11),
UpdateVideoSize = (1 << 12),
InvalidateState = (UpdatePlaybackStatus | UpdateTotalTime | UpdateCurrentTime |
ResetState = (UpdatePlaybackStatus | UpdateTotalTime | UpdateCurrentTime |
UpdateSeekable | UpdateMetadata | UpdateAudioChannels | UpdateSubtitles |
UpdateTitles | UpdateChapters | UpdateAngles | UpdateDvdPlayback |
UpdateTitles | UpdateChapters | UpdateAngles | UpdateDvdMenu |
UpdateVideoSize)
};
Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
Q_DECLARE_FLAGS(PendingUpdates, PendingUpdate)
protected:
void addDirtyFlags(DirtyFlags additionalDirtyFlags);
private:
void addPendingUpdate(PendingUpdate pendingUpdate);
void customEvent(QEvent *event);
QAtomicInt dirtyFlags;
MediaWidget *mediaWidget;
PendingUpdates pendingUpdates;
MediaWidget::PlaybackStatus playbackStatus;
int totalTime;
int currentTime;
bool seekable;
QMap<MediaWidget::MetadataType, QString> metadata;
QStringList audioChannels;
int currentAudioChannel;
QStringList subtitles;
int currentSubtitle;
int titleCount;
int currentTitle;
int chapterCount;
int currentChapter;
int angleCount;
int currentAngle;
bool dvdMenu;
QSize videoSize;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMediaWidget::DirtyFlags)
class DummyMediaWidget : public AbstractMediaWidget
{
public:
......@@ -112,23 +145,6 @@ public:
// zero-based numbering is used everywhere (e.g. first audio channel = 0)
MediaWidget::PlaybackStatus getPlaybackStatus();
int getTotalTime(); // milliseconds
int getCurrentTime(); // milliseconds
bool isSeekable();
QMap<MediaWidget::MetadataType, QString> getMetadata();
QStringList getAudioChannels();
int getCurrentAudioChannel();
QStringList getSubtitles();
int getCurrentSubtitle();
int getTitleCount();
int getCurrentTitle();
int getChapterCount();
int getCurrentChapter();
int getAngleCount();
int getCurrentAngle();
bool hasMenu();
QSize getVideoSize();
void setMuted(bool muted);
void setVolume(int volume); // [0 - 200]
void setAspectRatio(MediaWidget::AspectRatio aspectRatio);
......
......@@ -26,10 +26,9 @@
#include "../log.h"
#include "mplayervideowidget.h"
MPlayerMediaWidget::MPlayerMediaWidget(QWidget *parent) : AbstractMediaWidget(parent), volume(0),
muted(false), aspectRatio(MediaWidget::AspectRatioAuto), playbackStatus(MediaWidget::Idle),
playingDvd(false), totalTime(0), currentTime(0), videoWidth(0), videoHeight(0),
videoAspectRatio(1)
MPlayerMediaWidget::MPlayerMediaWidget(QWidget *parent) : AbstractMediaWidget(parent),
muted(false), volume(0), aspectRatio(MediaWidget::AspectRatioAuto), videoWidth(0),
videoHeight(0), videoAspectRatio(1)
{
videoWidget = new MPlayerVideoWidget(this);
standardError.open(stderr, QIODevice::WriteOnly);
......@@ -51,107 +50,6 @@ MPlayerMediaWidget *MPlayerMediaWidget::createMPlayerMediaWidget(QWidget *parent
return new MPlayerMediaWidget(parent);
}
MediaWidget::PlaybackStatus MPlayerMediaWidget::getPlaybackStatus()
{
return playbackStatus;
}
int MPlayerMediaWidget::getTotalTime()
{
return totalTime;
}
int MPlayerMediaWidget::getCurrentTime()
{
return currentTime;
}
bool MPlayerMediaWidget::isSeekable()
{
return false;
// FIXME
}
QMap<MediaWidget::MetadataType, QString> MPlayerMediaWidget::getMetadata()
{
QMap<MediaWidget::MetadataType, QString> metadata;
return metadata;
// FIXME
}
QStringList MPlayerMediaWidget::getAudioChannels()
{
QStringList audioChannels;
return audioChannels;
// FIXME
}
int MPlayerMediaWidget::getCurrentAudioChannel()
{
return 0;
// FIXME
}
QStringList MPlayerMediaWidget::getSubtitles()
{
QStringList subtitles;
return subtitles;
// FIXME
}
int MPlayerMediaWidget::getCurrentSubtitle()
{
return 0;
// FIXME
}
int MPlayerMediaWidget::getTitleCount()
{
return 0;
// FIXME
}
int MPlayerMediaWidget::getCurrentTitle()
{
return -1;
// FIXME
}
int MPlayerMediaWidget::getChapterCount()
{
return 0;
// FIXME
}
int MPlayerMediaWidget::getCurrentChapter()
{
return -1;
// FIXME
}
int MPlayerMediaWidget::getAngleCount()
{
return 0;
// FIXME
}
int MPlayerMediaWidget::getCurrentAngle()
{
return -1;
// FIXME
}
bool MPlayerMediaWidget::hasMenu()
{
return playingDvd;
}
QSize MPlayerMediaWidget::getVideoSize()
{
return QSize();
// FIXME
}
void MPlayerMediaWidget::setMuted(bool muted_)
{
muted = muted_;
......@@ -178,19 +76,17 @@ void MPlayerMediaWidget::setDeinterlacing(bool deinterlacing)
void MPlayerMediaWidget::play(const MediaSource &source)
{
QByteArray url = source.url.toEncoded();
playbackStatus = MediaWidget::Playing;
playingDvd = false;
totalTime = 0;
currentTime = 0;
resetState();
videoWidth = 0;
videoHeight = 0;
videoAspectRatio = 1;
updateVideoWidgetGeometry();
QByteArray url = source.url.toEncoded();
switch (source.type) {
case MediaSource::Url:
if (url.endsWith(".iso")) {
playingDvd = true;
updateDvdMenu(true);
}
break;
......@@ -217,41 +113,41 @@ void MPlayerMediaWidget::play(const MediaSource &source)
url = "dvdnav:///";
}
playingDvd = true;
updateDvdMenu(true);
break;
}
updatePlaybackStatus(MediaWidget::Playing);
process.write("loadfile " + url + '\n');
process.write("pausing_keep_force get_property path\n");
sendCommand(SetVolume);
}
void MPlayerMediaWidget::stop()
{
playbackStatus = MediaWidget::Idle;
playingDvd = false;
totalTime = 0;