Commit 9b63934e authored by Christoph Pfister's avatar Christoph Pfister

properly handle vlc events: use thread-safe functions

parent 12e5eb8c
/*
* abstractmediawidget.cpp
*
* Copyright (C) 2010-2011 Christoph Pfister <christophpfister@gmail.com>
* Copyright (C) 2010-2012 Christoph Pfister <christophpfister@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
......@@ -24,33 +24,11 @@
AbstractMediaWidget::AbstractMediaWidget(QWidget *parent) : QWidget(parent), mediaWidget(NULL)
{
resetBaseState();
}
AbstractMediaWidget::~AbstractMediaWidget()
{
}
void AbstractMediaWidget::setMediaWidget(MediaWidget *mediaWidget_)
{
mediaWidget = mediaWidget_;
}
void AbstractMediaWidget::resetBaseState()
{
if (pendingUpdates == 0) {
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
pendingUpdates |= ResetState;
playbackStatus = MediaWidget::Idle;
currentTime = 0;
totalTime = 0;
seekable = false;
metadata.clear();
audioStreams.clear();
currentAudioStream = -1;
subtitles.clear();
currentSubtitle = -1;
titleCount = 0;
currentTitle = -1;
......@@ -59,181 +37,107 @@ void AbstractMediaWidget::resetBaseState()
angleCount = 0;
currentAngle = -1;
dvdMenu = false;
videoSize = QSize();
}
void AbstractMediaWidget::playbackFinished()
{
addPendingUpdate(PlaybackFinished);
}
void AbstractMediaWidget::updatePlaybackStatus(MediaWidget::PlaybackStatus playbackStatus_)
{
playbackStatus = playbackStatus_;
addPendingUpdate(PlaybackStatus);
}
void AbstractMediaWidget::updateCurrentTotalTime(int currentTime_, int totalTime_)
{
currentTime = currentTime_;
totalTime = totalTime_;
if (currentTime < 0) {
currentTime = 0;
}
if (totalTime < 0) {
totalTime = 0;
}
addPendingUpdate(CurrentTotalTime);
}
void AbstractMediaWidget::updateSeekable(bool seekable_)
{
seekable = seekable_;
addPendingUpdate(Seekable);
}
void AbstractMediaWidget::updateMetadata(const QMap<MediaWidget::MetadataType, QString> &metadata_)
{
metadata = metadata_;
addPendingUpdate(Metadata);
}
void AbstractMediaWidget::updateAudioStreams(const QStringList &audioStreams_)
{
audioStreams = audioStreams_;
addPendingUpdate(AudioStreams);
}
void AbstractMediaWidget::updateCurrentAudioStream(int currentAudioStream_)
{
currentAudioStream = currentAudioStream_;
addPendingUpdate(AudioStreams);
}
void AbstractMediaWidget::updateSubtitles(const QStringList &subtitles_)
{
subtitles = subtitles_;
addPendingUpdate(Subtitles);
}
void AbstractMediaWidget::updateCurrentSubtitle(int currentSubtitle_)
{
currentSubtitle = currentSubtitle_;
addPendingUpdate(Subtitles);
}
void AbstractMediaWidget::updateTitleCount(int titleCount_)
{
titleCount = titleCount_;
addPendingUpdate(Titles);
}
void AbstractMediaWidget::updateCurrentTitle(int currentTitle_)
{
currentTitle = currentTitle_;
addPendingUpdate(Titles);
}
void AbstractMediaWidget::updateChapterCount(int chapterCount_)
{
chapterCount = chapterCount_;
addPendingUpdate(Chapters);
}
void AbstractMediaWidget::updateCurrentChapter(int currentChapter_)
{
currentChapter = currentChapter_;
addPendingUpdate(Chapters);
}
void AbstractMediaWidget::updateAngleCount(int angleCount_)
AbstractMediaWidget::~AbstractMediaWidget()
{
angleCount = angleCount_;
addPendingUpdate(Angles);
}
void AbstractMediaWidget::updateCurrentAngle(int currentAngle_)
void AbstractMediaWidget::addPendingUpdates(PendingUpdates pendingUpdatesToBeAdded)
{
currentAngle = currentAngle_;
addPendingUpdate(Angles);
}
while (true) {
int oldValue = pendingUpdates;
int newValue = (oldValue | pendingUpdatesToBeAdded);
void AbstractMediaWidget::updateDvdMenu(bool dvdMenu_)
{
dvdMenu = dvdMenu_;
addPendingUpdate(DvdMenu);
}
if (!pendingUpdates.testAndSetRelaxed(oldValue, newValue)) {
continue;
}
void AbstractMediaWidget::updateVideoSize(const QSize &videoSize_)
{
videoSize = videoSize_;
addPendingUpdate(VideoSize);
}
if (oldValue == 0) {
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
void AbstractMediaWidget::addPendingUpdate(PendingUpdate pendingUpdate)
{
if (pendingUpdates == 0) {
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
break;
}
pendingUpdates |= pendingUpdate;
}
void AbstractMediaWidget::customEvent(QEvent *event)
{
Q_UNUSED(event)
while (pendingUpdates != 0) {
uint lowestPendingUpdate = (pendingUpdates & (~(pendingUpdates - 1)));
pendingUpdates &= ~lowestPendingUpdate;
while (true) {
int oldValue = pendingUpdates;
int lowestPendingUpdate = (oldValue & (~(oldValue - 1)));
int newValue = (oldValue & (~lowestPendingUpdate));
switch (static_cast<PendingUpdates>(lowestPendingUpdate)) {
if (!pendingUpdates.testAndSetRelaxed(oldValue, newValue)) {
continue;
}
switch (static_cast<PendingUpdate>(lowestPendingUpdate)) {
case PlaybackFinished:
mediaWidget->playbackFinished();
break;
case PlaybackStatus:
updatePlaybackStatus();
mediaWidget->playbackStatusChanged();
break;
case CurrentTotalTime:
updateCurrentTotalTime();
mediaWidget->currentTotalTimeChanged();
break;
case Seekable:
updateSeekable();
mediaWidget->seekableChanged();
break;
case Metadata:
updateMetadata();
mediaWidget->metadataChanged();
break;
case AudioStreams:
updateAudioStreams();
mediaWidget->audioStreamsChanged();
break;
case Subtitles:
updateSubtitles();
mediaWidget->subtitlesChanged();
break;
case Titles:
updateTitles();
mediaWidget->titlesChanged();
break;
case Chapters:
updateChapters();
mediaWidget->chaptersChanged();
break;
case Angles:
updateAngles();
mediaWidget->anglesChanged();
break;
case DvdMenu:
updateDvdMenu();
mediaWidget->dvdMenuChanged();
break;
case VideoSize:
updateVideoSize();
mediaWidget->videoSizeChanged();
break;
case ResetState:
// this is a combination of flags
}
if (newValue == 0) {
break;
}
}
}
DummyMediaWidget::DummyMediaWidget(QWidget *parent) : AbstractMediaWidget(parent)
{
}
DummyMediaWidget::~DummyMediaWidget()
{
}
void DummyMediaWidget::setMuted(bool muted)
{
Q_UNUSED(muted)
......@@ -257,12 +161,10 @@ void DummyMediaWidget::setDeinterlacing(bool deinterlacing)
void DummyMediaWidget::play(const MediaSource &source)
{
Q_UNUSED(source)
resetBaseState();
}
void DummyMediaWidget::stop()
{
resetBaseState();
}
void DummyMediaWidget::setPaused(bool paused)
......@@ -318,3 +220,47 @@ bool DummyMediaWidget::jumpToNextChapter()
void DummyMediaWidget::showDvdMenu()
{
}
void DummyMediaWidget::updatePlaybackStatus()
{
}
void DummyMediaWidget::updateCurrentTotalTime()
{
}
void DummyMediaWidget::updateSeekable()
{
}
void DummyMediaWidget::updateMetadata()
{
}
void DummyMediaWidget::updateAudioStreams()
{
}
void DummyMediaWidget::updateSubtitles()
{
}
void DummyMediaWidget::updateTitles()
{
}
void DummyMediaWidget::updateChapters()
{
}
void DummyMediaWidget::updateAngles()
{
}
void DummyMediaWidget::updateDvdMenu()
{
}
void DummyMediaWidget::updateVideoSize()
{
}
/*
* abstractmediawidget.h
*
* Copyright (C) 2010-2011 Christoph Pfister <christophpfister@gmail.com>
* Copyright (C) 2010-2012 Christoph Pfister <christophpfister@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
......@@ -29,7 +29,7 @@ public:
explicit AbstractMediaWidget(QWidget *parent);
virtual ~AbstractMediaWidget();
void setMediaWidget(MediaWidget *mediaWidget_);
void setMediaWidget(MediaWidget *mediaWidget_) { mediaWidget = mediaWidget_; }
// zero-based numbering is used everywhere (e.g. first audio channel = 0)
......@@ -69,27 +69,6 @@ public:
virtual bool jumpToNextChapter() = 0;
virtual void showDvdMenu() = 0;
protected:
void resetBaseState();
void playbackFinished();
void updatePlaybackStatus(MediaWidget::PlaybackStatus playbackStatus_);
void updateCurrentTotalTime(int currentTime_, int totalTime_);
void updateSeekable(bool seekable_);
void updateMetadata(const QMap<MediaWidget::MetadataType, QString> &metadata_);
void updateAudioStreams(const QStringList &audioStreams_);
void updateCurrentAudioStream(int currentAudioStream_);
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),
......@@ -103,19 +82,26 @@ private:
Chapters = (1 << 8),
Angles = (1 << 9),
DvdMenu = (1 << 10),
VideoSize = (1 << 11),
ResetState = (PlaybackStatus | CurrentTotalTime | Seekable | Metadata |
AudioStreams | Subtitles | Titles | Chapters | Angles | DvdMenu |
VideoSize)
VideoSize = (1 << 11)
};
Q_DECLARE_FLAGS(PendingUpdates, PendingUpdate)
void addPendingUpdate(PendingUpdate pendingUpdate);
void customEvent(QEvent *event);
protected:
void addPendingUpdates(PendingUpdates pendingUpdatesToBeAdded); // thread-safe
virtual void updatePlaybackStatus() = 0;
virtual void updateCurrentTotalTime() = 0;
virtual void updateSeekable() = 0;
virtual void updateMetadata() = 0;
virtual void updateAudioStreams() = 0;
virtual void updateSubtitles() = 0;
virtual void updateTitles() = 0;
virtual void updateChapters() = 0;
virtual void updateAngles() = 0;
virtual void updateDvdMenu() = 0;
virtual void updateVideoSize() = 0;
MediaWidget *mediaWidget;
PendingUpdates pendingUpdates;
MediaWidget::PlaybackStatus playbackStatus;
int currentTime;
int totalTime;
......@@ -133,15 +119,21 @@ private:
int currentAngle;
bool dvdMenu;
QSize videoSize;
private:
void customEvent(QEvent *event);
MediaWidget *mediaWidget;
QAtomicInt pendingUpdates;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMediaWidget::PendingUpdates)
class DummyMediaWidget : public AbstractMediaWidget
{
public:
explicit DummyMediaWidget(QWidget *parent) : AbstractMediaWidget(parent) { }
~DummyMediaWidget() { }
// zero-based numbering is used everywhere (e.g. first audio channel = 0)
explicit DummyMediaWidget(QWidget *parent);
~DummyMediaWidget();
void setMuted(bool muted);
void setVolume(int volume); // [0 - 200]
......@@ -160,6 +152,18 @@ public:
bool jumpToPreviousChapter();
bool jumpToNextChapter();
void showDvdMenu();
void updatePlaybackStatus();
void updateCurrentTotalTime();
void updateSeekable();
void updateMetadata();
void updateAudioStreams();
void updateSubtitles();
void updateTitles();
void updateChapters();
void updateAngles();
void updateDvdMenu();
void updateVideoSize();
};
#endif /* ABSTRACTMEDIAWIDGET_H */
This diff is collapsed.
/*
* vlcmediawidget.h
*
* Copyright (C) 2010-2011 Christoph Pfister <christophpfister@gmail.com>
* Copyright (C) 2010-2012 Christoph Pfister <christophpfister@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
......@@ -40,23 +40,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 getAudioStreams();
int getCurrentAudioStream();
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);
......@@ -75,10 +58,23 @@ public:
bool jumpToNextChapter();
void showDvdMenu();
void updatePlaybackStatus();
void updateCurrentTotalTime();
void updateSeekable();
void updateMetadata();
void updateAudioStreams();
void updateSubtitles();
void updateTitles();
void updateChapters();
void updateAngles();
void updateDvdMenu();
void updateVideoSize();
private:
void mousePressEvent(QMouseEvent *event);
void vlcEvent(const libvlc_event_t *event);
static void eventHandler(const libvlc_event_t *event, void *instance);
static void vlcEventHandler(const libvlc_event_t *event, void *instance);
libvlc_instance_t *vlcInstance;
libvlc_media_player_t *vlcMediaPlayer;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment