[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: =?utf-8?q?=5Bkaffeine=5D_/=3A_switch_from_=28lib-=29xine_to_=28l?=
From: Christoph Pfister <christophpfister () gmail ! com>
Date: 2011-04-30 17:01:28
Message-ID: 20110430170128.3D132A60A4 () git ! kde ! org
[Download RAW message or body]
Git commit e31652b06cc46dde488804b09205487d8036114f by Christoph Pfister.
Committed on 30/04/2011 at 18:48.
Pushed by pfister into branch 'master'.
switch from (lib-)xine to (lib-)vlc
- many issues (esp. crashes) vanish / are easier to fix
- likely you need the 'full' vlc package (with X11 plugins)
- this commit introduces introduces various regressions ;-)
- big picture problems with libvlc:
- dvd navigation (likely solved with libvlc 1.2 once it's released)
- VDPAU
- make MediaWidget more state-orientated, i.e. separate between
- functions, which modify the state (e.g. a signal from the backend)
- functions, which rely on the state (e.g. ui updates)
M +1 -2 CMakeLists.txt
M +2 -2 README
M +2 -12 src/CMakeLists.txt
A +608 -0 src/backend-vlc/vlcmediawidget.cpp [License: GPL (v2+)]
A +77 -0 src/backend-vlc/vlcmediawidget.h [License: GPL (v2+)]
A +96 -0 src/backend-vlc/vlcmediawidget_p.h [License: GPL (v2+)]
D +0 -1008 src/backend-xine/xineapplication.cpp
D +0 -138 src/backend-xine/xineapplication.h
D +0 -303 src/backend-xine/xinecommands.cpp
D +0 -357 src/backend-xine/xinecommands.h
D +0 -1042 src/backend-xine/xinemediawidget.cpp
D +0 -186 src/backend-xine/xinemediawidget.h
D +0 -55 src/backend-xine/xinemediawidget_p.h
M +16 -6 src/dbusobjects.cpp
M +4 -0 src/dbusobjects.h
M +125 -24 src/dvb/dvbliveview.cpp
M +18 -3 src/dvb/dvbliveview_p.h
M +2 -2 src/dvb/dvbtab.cpp
M +19 -3 src/mainwindow.cpp
M +2 -1 src/mainwindow.h
M +543 -572 src/mediawidget.cpp
M +89 -53 src/mediawidget.h
M +0 -31 src/mediawidget_p.h
http://commits.kde.org/kaffeine/e31652b06cc46dde488804b09205487d8036114f
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3a1cf39..1bc7c4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,9 +2,8 @@ project(kaffeine)
find_package(KDE4 REQUIRED)
find_package(X11 REQUIRED)
-find_package(Xine REQUIRED)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_BINARY_DIR} \
${KDE4_INCLUDES}
- ${X11_INCLUDE_DIR} ${X11_Xscreensaver_INCLUDE_PATH} \
${XINE_INCLUDE_DIR}) + ${X11_Xscreensaver_INCLUDE_PATH})
add_definitions(${KDE4_DEFINITIONS})
if(STRICT_BUILD)
diff --git a/README b/README
index 6ec6cdc..3952f8a 100644
--- a/README
+++ b/README
@@ -5,9 +5,9 @@ Installing Kaffeine
The following development headers are needed (recommended versions):
* Qt >= 4.6
* KDE >= 4.4
-* xine-lib
-* libXss
+* libvlc >= 1.1.1
* libX11
+* libXss
For the translations you need:
* gettext
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2c00837..d50d9f0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,5 @@
set(kaffeine_SRCS
- backend-xine/xinecommands.cpp
- backend-xine/xinemediawidget.cpp
+ backend-vlc/vlcmediawidget.cpp
playlist/playlistmodel.cpp
playlist/playlisttab.cpp
configuration.cpp
@@ -37,20 +36,11 @@ if(HAVE_DVB)
dvb/dvbtransponder.cpp)
endif(HAVE_DVB)
-set(kaffeinexbu_SRCS
- backend-xine/xineapplication.cpp
- backend-xine/xinecommands.cpp
- log.cpp)
-
configure_file(config-kaffeine.h.cmake ${CMAKE_BINARY_DIR}/config-kaffeine.h)
kde4_add_executable(kaffeine ${kaffeinedvb_SRCS} ${kaffeine_SRCS})
target_link_libraries(kaffeine ${QT_QTSQL_LIBRARY} ${KDE4_KFILE_LIBS} \
${KDE4_KIO_LIBS}
- ${KDE4_SOLID_LIBS} ${X11_Xscreensaver_LIB})
+ ${KDE4_SOLID_LIBS} ${X11_Xscreensaver_LIB} vlc)
install(TARGETS kaffeine ${INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES scanfile.dvb DESTINATION ${DATA_INSTALL_DIR}/kaffeine)
install(PROGRAMS kaffeine.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
-
-kde4_add_executable(kaffeine-xbu ${kaffeinexbu_SRCS})
-target_link_libraries(kaffeine-xbu ${X11_X11_LIB} ${XINE_LIBRARY} \
${KDE4_KDEUI_LIBS})
-install(TARGETS kaffeine-xbu ${INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/src/backend-vlc/vlcmediawidget.cpp b/src/backend-vlc/vlcmediawidget.cpp
new file mode 100644
index 0000000..a86a304
--- /dev/null
+++ b/src/backend-vlc/vlcmediawidget.cpp
@@ -0,0 +1,608 @@
+/*
+ * vlcmediawidget.cpp
+ *
+ * Copyright (C) 2010-2011 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
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "vlcmediawidget.h"
+#include "vlcmediawidget_p.h"
+
+#include <QCoreApplication>
+#include <vlc/vlc.h>
+#include "../log.h"
+
+AbstractMediaWidget::AbstractMediaWidget(QWidget *parent) : QWidget(parent)
+{
+}
+
+AbstractMediaWidget::~AbstractMediaWidget()
+{
+}
+
+AbstractMediaWidget *AbstractMediaWidget::createVlcMediaWidget(QWidget *parent)
+{
+ AbstractMediaWidget *mediaWidget = VlcMediaWidget::createVlcMediaWidget(parent);
+
+ if (mediaWidget == NULL) {
+ mediaWidget = new AbstractMediaWidget(parent);
+ }
+
+ return mediaWidget;
+}
+
+void AbstractMediaWidget::setMuted(bool muted)
+{
+ Q_UNUSED(muted)
+}
+
+void AbstractMediaWidget::setVolume(int volume)
+{
+ Q_UNUSED(volume)
+}
+
+void AbstractMediaWidget::setAspectRatio(MediaWidget::AspectRatio aspectRatio)
+{
+ Q_UNUSED(aspectRatio)
+}
+
+void AbstractMediaWidget::setDeinterlacing(bool deinterlacing)
+{
+ Q_UNUSED(deinterlacing)
+}
+
+void AbstractMediaWidget::play(MediaWidget::Source source, const KUrl &url,
+ const KUrl &subtitleUrl)
+{
+ Q_UNUSED(source)
+ Q_UNUSED(url)
+ Q_UNUSED(subtitleUrl)
+}
+
+void AbstractMediaWidget::stop()
+{
+ emit updatePlaybackStatus(MediaWidget::Idle);
+}
+
+void AbstractMediaWidget::setPaused(bool paused)
+{
+ Q_UNUSED(paused)
+}
+
+void AbstractMediaWidget::seek(int time)
+{
+ Q_UNUSED(time)
+}
+
+void AbstractMediaWidget::setCurrentAudioChannel(int currentAudioChannel)
+{
+ Q_UNUSED(currentAudioChannel)
+}
+
+void AbstractMediaWidget::setCurrentSubtitle(int currentSubtitle)
+{
+ Q_UNUSED(currentSubtitle)
+}
+
+void AbstractMediaWidget::setExternalSubtitle(const KUrl &subtitleUrl)
+{
+ Q_UNUSED(subtitleUrl)
+}
+
+void AbstractMediaWidget::setCurrentTitle(int currentTitle)
+{
+ Q_UNUSED(currentTitle)
+}
+
+void AbstractMediaWidget::setCurrentChapter(int currentChapter)
+{
+ Q_UNUSED(currentChapter)
+}
+
+void AbstractMediaWidget::setCurrentAngle(int currentAngle)
+{
+ Q_UNUSED(currentAngle)
+}
+
+bool AbstractMediaWidget::jumpToPreviousChapter()
+{
+ return false;
+}
+
+bool AbstractMediaWidget::jumpToNextChapter()
+{
+ return false;
+}
+
+void AbstractMediaWidget::toggleMenu()
+{
+}
+
+VlcMediaWidget::VlcMediaWidget(QWidget *parent) : AbstractMediaWidget(parent), \
vlcInstance(NULL), + vlcMediaPlayer(NULL)
+{
+}
+
+bool VlcMediaWidget::init()
+{
+ const char *arguments[] = { "--no-video-title-show" };
+ vlcInstance = libvlc_new(sizeof(arguments) / sizeof(arguments[0]), arguments);
+
+ if (vlcInstance == NULL) {
+ Log("VlcMediaWidget::init: cannot create vlc instance") << libvlc_errmsg();
+ return false;
+ }
+
+ vlcMediaPlayer = libvlc_media_player_new(vlcInstance);
+
+ if (vlcMediaPlayer == NULL) {
+ Log("VlcMediaWidget::init: cannot create vlc media player") << libvlc_errmsg();
+ return false;
+ }
+
+ libvlc_event_manager_t *eventManager = \
libvlc_media_player_event_manager(vlcMediaPlayer); + libvlc_event_e eventTypes[] = { \
libvlc_MediaPlayerEncounteredError, + libvlc_MediaPlayerEndReached, \
libvlc_MediaPlayerLengthChanged, + libvlc_MediaPlayerSeekableChanged, \
libvlc_MediaPlayerStopped, + libvlc_MediaPlayerTimeChanged };
+
+ for (uint i = 0; i < (sizeof(eventTypes) / sizeof(eventTypes[0])); ++i) {
+ if (libvlc_event_attach(eventManager, eventTypes[i], eventHandler, this) != 0) {
+ Log("VlcMediaWidget::init: cannot attach event handler") << eventTypes[i];
+ return false;
+ }
+ }
+
+ libvlc_media_player_set_xwindow(vlcMediaPlayer, winId());
+ setAttribute(Qt::WA_NativeWindow);
+ setAttribute(Qt::WA_PaintOnScreen);
+ return true;
+}
+
+VlcMediaWidget::~VlcMediaWidget()
+{
+ if (vlcMediaPlayer != NULL) {
+ libvlc_media_player_release(vlcMediaPlayer);
+ }
+
+ if (vlcInstance != NULL) {
+ libvlc_release(vlcInstance);
+ }
+}
+
+VlcMediaWidget *VlcMediaWidget::createVlcMediaWidget(QWidget *parent)
+{
+ QScopedPointer<VlcMediaWidget> vlcMediaWidget(new VlcMediaWidget(parent));
+
+ if (!vlcMediaWidget->init()) {
+ return NULL;
+ }
+
+ return vlcMediaWidget.take();
+}
+
+void VlcMediaWidget::setMuted(bool muted)
+{
+ libvlc_audio_set_mute(vlcMediaPlayer, muted);
+}
+
+void VlcMediaWidget::setVolume(int volume)
+{
+ // 0 <= volume <= 200
+ if (libvlc_audio_set_volume(vlcMediaPlayer, volume) != 0) {
+ Log("VlcMediaWidget::setVolume: cannot set volume") << volume;
+ }
+}
+
+void VlcMediaWidget::setAspectRatio(MediaWidget::AspectRatio aspectRatio)
+{
+ // "", "1:1", "4:3", "5:4", 16:9", "16:10", "221:100", "235:100", "239:100"
+ const char *vlcAspectRatio = "";
+ int vlcScaleFactor = 1;
+
+ switch (aspectRatio) {
+ case MediaWidget::AspectRatioAuto:
+ break;
+ case MediaWidget::AspectRatio4_3:
+ vlcAspectRatio = "4:3";
+ break;
+ case MediaWidget::AspectRatio16_9:
+ vlcAspectRatio = "16:9";
+ break;
+ case MediaWidget::AspectRatioWidget:
+ // zero = adjust video to window
+ vlcScaleFactor = 0;
+ break;
+ }
+
+ libvlc_video_set_aspect_ratio(vlcMediaPlayer, vlcAspectRatio);
+ libvlc_video_set_scale(vlcMediaPlayer, vlcScaleFactor);
+}
+
+void VlcMediaWidget::setDeinterlacing(bool deinterlacing)
+{
+ // "", "blend", "bob", "discard", "ivtc", "linear",
+ // "mean", "phosphor", "x", "yadif", "yadif2x"
+ const char *vlcDeinterlaceMode = "";
+
+ if (deinterlacing) {
+ vlcDeinterlaceMode = "yadif";
+ }
+
+ libvlc_video_set_deinterlace(vlcMediaPlayer, vlcDeinterlaceMode);
+}
+
+void VlcMediaWidget::play(MediaWidget::Source source, const KUrl &url, const KUrl \
&subtitleUrl) +{
+ QByteArray encodedUrl = url.toEncoded();
+
+ switch (source) {
+ case MediaWidget::Playlist:
+ case MediaWidget::Dvb:
+ case MediaWidget::DvbTimeShift:
+ // FIXME how to treat ".iso" files?
+ break;
+ case MediaWidget::AudioCd:
+ encodedUrl.replace(0, 4, "cdda");
+ break;
+ case MediaWidget::VideoCd:
+ encodedUrl.replace(0, 4, "vcd");
+ break;
+ case MediaWidget::Dvd:
+ encodedUrl.replace(0, 4, "dvd");
+ break;
+ }
+
+ libvlc_media_t *vlcMedia = libvlc_media_new_location(vlcInstance, \
encodedUrl.constData()); +
+ if (vlcMedia == NULL) {
+ Log("VlcMediaWidget::play: cannot create media") << url.prettyUrl();
+ stop();
+ return;
+ }
+
+ libvlc_event_manager_t *eventManager = libvlc_media_event_manager(vlcMedia);
+ libvlc_event_e eventTypes[] = { libvlc_MediaMetaChanged };
+
+ for (uint i = 0; i < (sizeof(eventTypes) / sizeof(eventTypes[0])); ++i) {
+ if (libvlc_event_attach(eventManager, eventTypes[i], eventHandler, this) != 0) {
+ Log("VlcMediaWidget::play: cannot attach event handler") << eventTypes[i];
+ }
+ }
+
+ libvlc_media_player_set_media(vlcMediaPlayer, vlcMedia);
+ libvlc_media_release(vlcMedia);
+ setDirtyFlags(UpdatePlaybackStatus | UpdateTotalTime | UpdateCurrentTime | \
UpdateSeekable | + UpdateMetadata | UpdateAudioChannels | UpdateSubtitles | \
UpdateTitles | + UpdateChapters | UpdateAngles);
+
+ if (!subtitleUrl.isEmpty()) {
+ if (libvlc_video_set_subtitle_file(vlcMediaPlayer,
+ subtitleUrl.toEncoded().constData()) == 0) {
+ Log("VlcMediaWidget::play: cannot set subtitle file") <<
+ subtitleUrl.prettyUrl();
+ }
+ }
+
+ if (libvlc_media_player_play(vlcMediaPlayer) != 0) {
+ Log("VlcMediaWidget::play: cannot play media") << url.prettyUrl();
+ stop();
+ return;
+ }
+}
+
+void VlcMediaWidget::stop()
+{
+ libvlc_media_player_stop(vlcMediaPlayer);
+ setDirtyFlags(UpdatePlaybackStatus | UpdateTotalTime | UpdateCurrentTime | \
UpdateSeekable | + UpdateMetadata | UpdateAudioChannels | UpdateSubtitles | \
UpdateTitles | + UpdateChapters | UpdateAngles);
+}
+
+void VlcMediaWidget::setPaused(bool paused)
+{
+ libvlc_media_player_set_pause(vlcMediaPlayer, paused);
+ addDirtyFlags(UpdatePlaybackStatus);
+}
+
+void VlcMediaWidget::seek(int time)
+{
+ libvlc_media_player_set_time(vlcMediaPlayer, time);
+}
+
+void VlcMediaWidget::setCurrentAudioChannel(int currentAudioChannel)
+{
+ libvlc_audio_set_track(vlcMediaPlayer, currentAudioChannel);
+}
+
+void VlcMediaWidget::setCurrentSubtitle(int currentSubtitle)
+{
+ libvlc_video_set_spu(vlcMediaPlayer, currentSubtitle);
+}
+
+void VlcMediaWidget::setExternalSubtitle(const KUrl &subtitleUrl)
+{
+ if (libvlc_video_set_subtitle_file(vlcMediaPlayer,
+ subtitleUrl.toEncoded().constData()) == 0) {
+ Log("VlcMediaWidget::setExternalSubtitle: cannot set subtitle file") <<
+ subtitleUrl.prettyUrl();
+ }
+}
+
+void VlcMediaWidget::setCurrentTitle(int currentTitle)
+{
+ libvlc_media_player_set_title(vlcMediaPlayer, currentTitle);
+}
+
+void VlcMediaWidget::setCurrentChapter(int currentChapter)
+{
+ libvlc_media_player_set_chapter(vlcMediaPlayer, currentChapter);
+}
+
+void VlcMediaWidget::setCurrentAngle(int currentAngle)
+{
+ Q_UNUSED(currentAngle)
+ // FIXME
+}
+
+bool VlcMediaWidget::jumpToPreviousChapter()
+{
+ int currentTitle = libvlc_media_player_get_title(vlcMediaPlayer);
+ int currentChapter = libvlc_media_player_get_chapter(vlcMediaPlayer);
+ libvlc_media_player_previous_chapter(vlcMediaPlayer);
+
+ if ((libvlc_media_player_get_title(vlcMediaPlayer) != currentTitle) ||
+ (libvlc_media_player_get_chapter(vlcMediaPlayer) != currentChapter)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool VlcMediaWidget::jumpToNextChapter()
+{
+ int currentTitle = libvlc_media_player_get_title(vlcMediaPlayer);
+ int currentChapter = libvlc_media_player_get_chapter(vlcMediaPlayer);
+ libvlc_media_player_next_chapter(vlcMediaPlayer);
+
+ if ((libvlc_media_player_get_title(vlcMediaPlayer) != currentTitle) ||
+ (libvlc_media_player_get_chapter(vlcMediaPlayer) != currentChapter)) {
+ return true;
+ }
+
+ return false;
+}
+
+void VlcMediaWidget::toggleMenu()
+{
+ // FIXME
+}
+
+QSize VlcMediaWidget::sizeHint() const
+{
+ // FIXME
+ return QWidget::sizeHint();
+}
+
+void VlcMediaWidget::customEvent(QEvent *event)
+{
+ Q_UNUSED(event)
+
+ while (true) {
+ uint oldDirtyFlags = dirtyFlags;
+ uint lowestDirtyFlag = (oldDirtyFlags & (~(oldDirtyFlags - 1)));
+ uint newDirtyFlags = (oldDirtyFlags & (~lowestDirtyFlag));
+
+ if (oldDirtyFlags == newDirtyFlags) {
+ break;
+ }
+
+ if (!dirtyFlags.testAndSetRelaxed(oldDirtyFlags, newDirtyFlags)) {
+ continue;
+ }
+
+ switch (lowestDirtyFlag) {
+ case PlaybackFinished:
+ emit playbackFinished();
+ break;
+ case UpdatePlaybackStatus: {
+ MediaWidget::PlaybackStatus playbackStatus = MediaWidget::Playing;
+
+ switch (libvlc_media_player_get_state(vlcMediaPlayer)) {
+ case libvlc_NothingSpecial:
+ case libvlc_Stopped:
+ case libvlc_Ended:
+ case libvlc_Error:
+ playbackStatus = MediaWidget::Idle;
+ break;
+ case libvlc_Opening:
+ case libvlc_Buffering:
+ case libvlc_Playing:
+ playbackStatus = MediaWidget::Playing;
+ break;
+ case libvlc_Paused:
+ playbackStatus = MediaWidget::Paused;
+ break;
+ }
+
+ emit updatePlaybackStatus(playbackStatus);
+ break;
+ }
+ case UpdateTotalTime:
+ emit updateTotalTime(libvlc_media_player_get_length(vlcMediaPlayer));
+ break;
+ case UpdateCurrentTime:
+ emit updateCurrentTime(libvlc_media_player_get_time(vlcMediaPlayer));
+ break;
+ case UpdateSeekable:
+ emit updateSeekable(libvlc_media_player_is_seekable(vlcMediaPlayer));
+ break;
+ case UpdateMetadata: {
+ QMap<MediaWidget::MetadataType, QString> metadata;
+ libvlc_media_t *media = libvlc_media_player_get_media(vlcMediaPlayer);
+
+ if (media != NULL) {
+ metadata.insert(MediaWidget::Title, QString::fromUtf8(
+ libvlc_media_get_meta(media, libvlc_meta_Title)));
+ metadata.insert(MediaWidget::Artist, QString::fromUtf8(
+ libvlc_media_get_meta(media, libvlc_meta_Artist)));
+ metadata.insert(MediaWidget::Album, QString::fromUtf8(
+ libvlc_media_get_meta(media, libvlc_meta_Album)));
+ metadata.insert(MediaWidget::TrackNumber, QString::fromUtf8(
+ libvlc_media_get_meta(media, libvlc_meta_TrackNumber)));
+ }
+
+ emit updateMetadata(metadata);
+ break;
+ }
+ case UpdateAudioChannels: {
+ QStringList audioChannels;
+ libvlc_track_description_t *track =
+ libvlc_audio_get_track_description(vlcMediaPlayer);
+
+ while (track != NULL) {
+ QString audioChannel = QString::fromUtf8(track->psz_name);
+
+ if (audioChannel.isEmpty()) {
+ audioChannel = QString::number(audioChannels.size() + 1);
+ }
+
+ audioChannels.append(audioChannel);
+ track = track->p_next;
+ }
+
+ Log("VlcMediaWidget::customEvent: number of audio channels") << \
audioChannels.size(); + Log("XXX:") << \
libvlc_audio_get_track_count(vlcMediaPlayer); + int currentAudioChannel = \
libvlc_audio_get_track(vlcMediaPlayer); + emit updateAudioChannels(audioChannels, \
currentAudioChannel); + break;
+ }
+ case UpdateSubtitles: {
+ QStringList subtitles;
+ libvlc_track_description_t *track =
+ libvlc_video_get_spu_description(vlcMediaPlayer);
+
+ while (track != NULL) {
+ QString subtitle = QString::fromUtf8(track->psz_name);
+
+ if (subtitle.isEmpty()) {
+ subtitle = QString::number(subtitles.size() + 1);
+ }
+
+ subtitles.append(subtitle);
+ track = track->p_next;
+ }
+
+ int currentSubtitle = libvlc_video_get_spu(vlcMediaPlayer);
+ emit updateSubtitles(subtitles, currentSubtitle);
+ break;
+ }
+ case UpdateTitles: {
+ int titleCount = libvlc_media_player_get_title_count(vlcMediaPlayer);
+ int currentTitle = libvlc_media_player_get_title(vlcMediaPlayer);
+ emit updateTitles(titleCount, currentTitle);
+ break;
+ }
+ case UpdateChapters: {
+ int chapterCount = libvlc_media_player_get_chapter_count(vlcMediaPlayer);
+ int currentChapter = libvlc_media_player_get_chapter(vlcMediaPlayer);
+ emit updateChapters(chapterCount, currentChapter);
+ break;
+ }
+ case UpdateAngles: {
+ // FIXME
+ break;
+ }
+ case UpdateDvdPlayback: {
+ // FIXME
+ break;
+ }
+ case UpdateVideoSize: {
+ // FIXME
+ break;
+ }
+ default:
+ Log("VlcMediaWidget::customEvent: unknown dirty flag") << lowestDirtyFlag;
+ break;
+ }
+ }
+}
+
+void VlcMediaWidget::eventHandler(const libvlc_event_t *event, void *instance)
+{
+ uint changedDirtyFlags = 0;
+
+ switch (event->type) {
+ case libvlc_MediaMetaChanged:
+ Log("VlcMediaWidget::eventHandler: called");
+ changedDirtyFlags = (UpdateMetadata | UpdateAudioChannels | UpdateSubtitles |
+ UpdateTitles | UpdateChapters | UpdateAngles);
+ break;
+ case libvlc_MediaPlayerEncounteredError:
+ changedDirtyFlags = UpdatePlaybackStatus;
+ break;
+ case libvlc_MediaPlayerEndReached:
+ changedDirtyFlags = (PlaybackFinished | UpdatePlaybackStatus);
+ break;
+ case libvlc_MediaPlayerLengthChanged:
+ changedDirtyFlags = UpdateTotalTime;
+ break;
+ case libvlc_MediaPlayerSeekableChanged:
+ changedDirtyFlags = UpdateSeekable;
+ break;
+ case libvlc_MediaPlayerStopped:
+ changedDirtyFlags = UpdatePlaybackStatus;
+ break;
+ case libvlc_MediaPlayerTimeChanged:
+ changedDirtyFlags = UpdateCurrentTime;
+ break;
+ }
+
+ if (changedDirtyFlags != 0) {
+ reinterpret_cast<VlcMediaWidget *>(instance)->addDirtyFlags(changedDirtyFlags);
+ } else {
+ Log("VlcMediaWidget::eventHandler: unknown event type") << event->type;
+ }
+}
+
+void VlcMediaWidget::addDirtyFlags(uint changedDirtyFlags)
+{
+ while (true) {
+ uint oldDirtyFlags = dirtyFlags;
+ uint newDirtyFlags = (oldDirtyFlags | changedDirtyFlags);
+
+ if (oldDirtyFlags == newDirtyFlags) {
+ break;
+ }
+
+ if (!dirtyFlags.testAndSetRelaxed(oldDirtyFlags, newDirtyFlags)) {
+ continue;
+ }
+
+ if (oldDirtyFlags == 0) {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+
+ break;
+ }
+}
+
+void VlcMediaWidget::setDirtyFlags(uint newDirtyFlags)
+{
+ if (dirtyFlags.fetchAndStoreRelaxed(newDirtyFlags) == 0) {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+}
diff --git a/src/backend-vlc/vlcmediawidget.h b/src/backend-vlc/vlcmediawidget.h
new file mode 100644
index 0000000..b85b3da
--- /dev/null
+++ b/src/backend-vlc/vlcmediawidget.h
@@ -0,0 +1,77 @@
+/*
+ * vlcmediawidget.h
+ *
+ * Copyright (C) 2010-2011 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
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef VLCMEDIAWIDGET_H
+#define VLCMEDIAWIDGET_H
+
+#include "../mediawidget.h"
+
+class AbstractMediaWidget : public QWidget
+{
+ Q_OBJECT
+protected:
+ explicit AbstractMediaWidget(QWidget *parent);
+
+public:
+ ~AbstractMediaWidget();
+
+ static AbstractMediaWidget *createVlcMediaWidget(QWidget *parent);
+
+ virtual void setMuted(bool muted);
+ virtual void setVolume(int volume); // [0 - 100]
+ virtual void setAspectRatio(MediaWidget::AspectRatio aspectRatio);
+ virtual void setDeinterlacing(bool deinterlacing);
+
+ // it is guaranteed that updatePlaybackStatus() will
+ // be emitted after calling play() or stop()
+ virtual void play(MediaWidget::Source source, const KUrl &url, const KUrl \
&subtitleUrl); + virtual void stop();
+
+ virtual void setPaused(bool paused);
+ virtual void seek(int time);
+ virtual void setCurrentAudioChannel(int currentAudioChannel);
+ virtual void setCurrentSubtitle(int currentSubtitle);
+ virtual void setExternalSubtitle(const KUrl &subtitleUrl);
+ virtual void setCurrentTitle(int currentTitle); // first title = 0
+ virtual void setCurrentChapter(int currentChapter); // first chapter = 0
+ virtual void setCurrentAngle(int currentAngle); // first angle = 0
+ virtual bool jumpToPreviousChapter();
+ virtual bool jumpToNextChapter();
+ virtual void toggleMenu();
+
+signals:
+ void playbackFinished();
+ void updatePlaybackStatus(MediaWidget::PlaybackStatus playbackStatus);
+ void updateTotalTime(int totalTime); // milliseconds
+ void updateCurrentTime(int currentTime); // milliseconds
+ void updateMetadata(const QMap<MediaWidget::MetadataType, QString> &metadata);
+ void updateSeekable(bool seekable);
+ // first audio channel = 0
+ void updateAudioChannels(const QStringList &audioChannels, int \
currentAudioChannel); + // first subtitle = 0
+ void updateSubtitles(const QStringList &subtitles, int currentSubtitle);
+ void updateTitles(int titleCount, int currentTitle);
+ void updateChapters(int chapterCount, int currentChapter);
+ void updateAngles(int angleCount, int currentAngle);
+ void updateDvdPlayback(bool playingDvd);
+ void updateVideoSize();
+};
+
+#endif /* VLCMEDIAWIDGET_H */
diff --git a/src/backend-vlc/vlcmediawidget_p.h b/src/backend-vlc/vlcmediawidget_p.h
new file mode 100644
index 0000000..3dd3e20
--- /dev/null
+++ b/src/backend-vlc/vlcmediawidget_p.h
@@ -0,0 +1,96 @@
+/*
+ * vlcmediawidget_p.h
+ *
+ * Copyright (C) 2010-2011 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
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef VLCMEDIAWIDGET_P_H
+#define VLCMEDIAWIDGET_P_H
+
+#include "vlcmediawidget.h"
+
+class libvlc_event_t;
+class libvlc_instance_t;
+class libvlc_media_player_t;
+
+class VlcMediaWidget : public AbstractMediaWidget
+{
+private:
+ explicit VlcMediaWidget(QWidget *parent);
+ bool init();
+
+public:
+ ~VlcMediaWidget();
+
+ static VlcMediaWidget *createVlcMediaWidget(QWidget *parent);
+
+ void setMuted(bool muted);
+ void setVolume(int volume); // [0 - 100]
+ void setAspectRatio(MediaWidget::AspectRatio aspectRatio);
+ void setDeinterlacing(bool deinterlacing);
+
+ // it is guaranteed that updatePlaybackStatus() will
+ // be emitted after calling play() or stop()
+ void play(MediaWidget::Source source, const KUrl &url, const KUrl &subtitleUrl);
+ void stop();
+
+ void setPaused(bool paused);
+ void seek(int time);
+ void setCurrentAudioChannel(int currentAudioChannel);
+ void setCurrentSubtitle(int currentSubtitle);
+ void setExternalSubtitle(const KUrl &subtitleUrl);
+ void setCurrentTitle(int currentTitle); // first title = 0
+ void setCurrentChapter(int currentChapter); // first chapter = 0
+ void setCurrentAngle(int currentAngle); // first angle = 0
+ bool jumpToPreviousChapter();
+ bool jumpToNextChapter();
+ void toggleMenu();
+
+ QSize sizeHint() const;
+
+protected:
+ void customEvent(QEvent *event);
+
+private:
+ static void eventHandler(const libvlc_event_t *event, void *instance);
+
+ enum DirtyFlag
+ {
+ PlaybackFinished = (1 << 0),
+ UpdatePlaybackStatus = (1 << 1),
+ UpdateTotalTime = (1 << 2),
+ UpdateCurrentTime = (1 << 3),
+ UpdateSeekable = (1 << 4),
+ UpdateMetadata = (1 << 5),
+ UpdateAudioChannels = (1 << 6),
+ UpdateSubtitles = (1 << 7),
+ UpdateTitles = (1 << 8),
+ UpdateChapters = (1 << 9),
+ UpdateAngles = (1 << 10),
+ UpdateDvdPlayback = (1 << 11),
+ UpdateVideoSize = (1 << 12)
+ };
+
+ void addDirtyFlags(uint changedDirtyFlags);
+ void setDirtyFlags(uint newDirtyFlags);
+
+ libvlc_instance_t *vlcInstance;
+ libvlc_media_player_t *vlcMediaPlayer;
+ QAtomicInt dirtyFlags;
+};
+
+#endif /* VLCMEDIAWIDGET_P_H */
diff --git a/src/backend-xine/xineapplication.cpp \
b/src/backend-xine/xineapplication.cpp deleted file mode 100644
index 0e5fb3d..0000000
--- a/src/backend-xine/xineapplication.cpp
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
- * xineapplication.cpp
- *
- * Copyright (C) 2010-2011 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
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "xineapplication.h"
-
-#include <QFile>
-#include <QVector>
-#include <KAboutData>
-#include <KApplication>
-#include <KCmdLineArgs>
-#include <KStandardDirs>
-#include <X11/Xlib.h>
-#include "../log.h"
-#include "xinecommands.h"
-
-class XineParent : public XineParentMarshaller
-{
-public:
- XineParent(int fd, QObject *parent) : writer(fd, parent)
- {
- XineParentMarshaller::writer = &writer;
- }
-
- ~XineParent() { }
-
-private:
- XinePipeWriter writer;
-};
-
-XineObject::XineObject() : engine(NULL), audioOutput(NULL), videoOutput(NULL), \
stream(NULL),
- eventQueue(NULL), widgetSize(0), overrideTitleCount(0), overrideCurrentTitle(0),
- dirtyFlags(NotReady), aspectRatio(XineAspectRatioAuto), videoSize(0)
-{
- reader = new XinePipeReader(3, this);
- parentProcess = new XineParent(4, this);
- positionTimer.setInterval(500);
- connect(&positionTimer, SIGNAL(timeout()), this, SLOT(updatePosition()));
-}
-
-XineObject::~XineObject()
-{
- if (eventQueue != NULL) {
- xine_event_dispose_queue(eventQueue);
- }
-
- if (stream != NULL) {
- xine_dispose(stream);
- }
-
- if (deinterlacer != NULL) {
- xine_post_dispose(engine, deinterlacer);
- }
-
- if (visualization != NULL) {
- xine_post_dispose(engine, visualization);
- }
-
- if (videoOutput != NULL) {
- xine_close_video_driver(engine, videoOutput);
- }
-
- if (audioOutput != NULL) {
- xine_close_audio_driver(engine, audioOutput);
- }
-
- if (engine != NULL) {
- xine_config_save(engine, QFile::encodeName(
- KStandardDirs::locateLocal("data", "kaffeine/xine-config")).constData());
- xine_exit(engine);
- }
-
- delete reader;
- delete parentProcess;
-}
-
-const char *XineObject::version()
-{
- return xine_get_version_string();
-}
-
-void XineObject::readyRead()
-{
- reader->readyRead();
-
- while (true) {
- int command = reader->nextCommand();
-
- switch (command) {
- case -1:
- return;
- case XineCommands::Quit:
- kapp->quit();
- dirtyFlags |= Quit;
- return;
- case XineCommands::Init: {
- quint64 windowId = reader->readLongLong();
-
- if (reader->isValid()) {
- init(windowId);
- }
-
- break;
- }
- case XineCommands::Resize: {
- quint16 width = reader->readShort();
- quint16 height = reader->readShort();
-
- if (reader->isValid()) {
- widgetSize = ((width << 16) | height);
- }
-
- break;
- }
- case XineCommands::SetMuted: {
- bool muted_ = reader->readBool();
-
- if (reader->isValid()) {
- muted = muted_;
- dirtyFlags |= SetMuted;
- }
-
- break;
- }
- case XineCommands::SetVolume: {
- quint8 volume_ = reader->readChar();
-
- if (reader->isValid()) {
- volume = volume_;
- dirtyFlags |= SetVolume;
- }
-
- break;
- }
- case XineCommands::SetAspectRatio: {
- qint8 aspectRatio_ = reader->readChar();
-
- if (reader->isValid()) {
- aspectRatio = aspectRatio_;
- dirtyFlags |= SetAspectRatio;
- }
-
- break;
- }
- case XineCommands::SetDeinterlacing: {
- bool deinterlacing_ = reader->readBool();
-
- if (reader->isValid()) {
- deinterlacing = deinterlacing_;
- dirtyFlags |= SetDeinterlacing;
- }
-
- break;
- }
- case XineCommands::PlayUrl: {
- quint32 sequenceNumber_ = reader->readInt();
- QByteArray encodedUrl_ = reader->readByteArray();
-
- if (reader->isValid()) {
- sequenceNumber = sequenceNumber_;
- encodedUrl = encodedUrl_;
- dirtyFlags &= ~(PlayStream | SetPaused | Seek | Repaint |
- MouseMoved | MousePressed |
- SetCurrentAudioChannel | SetCurrentSubtitle |
- ToggleMenu);
- dirtyFlags |= OpenStream;
- }
-
- break;
- }
- case XineCommands::SetPaused: {
- bool paused_ = reader->readBool();
-
- if (reader->isValid()) {
- paused = paused_;
- dirtyFlags |= SetPaused;
- }
-
- break;
- }
- case XineCommands::Seek: {
- qint32 seekTime_ = reader->readInt();
-
- if (reader->isValid()) {
- seekTime = seekTime_;
- dirtyFlags |= Seek;
- }
-
- break;
- }
- case XineCommands::Repaint:
- dirtyFlags |= Repaint;
- break;
- case XineCommands::MouseMoved: {
- quint16 x = reader->readShort();
- quint16 y = reader->readShort();
-
- if (reader->isValid()) {
- mouseMovePosition = ((x << 16) | y);
- dirtyFlags |= MouseMoved;
- }
-
- break;
- }
- case XineCommands::MousePressed: {
- quint16 x = reader->readShort();
- quint16 y = reader->readShort();
-
- if (reader->isValid()) {
- mousePressPosition = ((x << 16) | y);
- dirtyFlags |= MousePressed;
- }
-
- break;
- }
- case XineCommands::SetCurrentAudioChannel: {
- qint8 currentAudioChannel_ = reader->readChar();
-
- if (reader->isValid()) {
- currentAudioChannel = currentAudioChannel_;
- dirtyFlags |= SetCurrentAudioChannel;
- }
-
- break;
- }
- case XineCommands::SetCurrentSubtitle: {
- qint8 currentSubtitle_ = reader->readChar();
-
- if (reader->isValid()) {
- currentSubtitle = currentSubtitle_;
- dirtyFlags |= SetCurrentSubtitle;
- }
-
- break;
- }
- case XineCommands::ToggleMenu:
- dirtyFlags |= ToggleMenu;
- break;
- default:
- Log("XineObject::readyRead: unknown command") << command;
- continue;
- }
-
- if (!reader->isValid()) {
- Log("XineObject::readyRead: wrong argument size for command") << command;
- }
-
- if (((dirtyFlags & (Quit | NotReady | ProcessEvent)) == 0) && (dirtyFlags != 0)) {
- QCoreApplication::postEvent(this, new QEvent(ReaderEvent));
- dirtyFlags |= ProcessEvent;
- }
- }
-}
-
-void XineObject::updatePosition()
-{
- int relativePosition;
- int currentTime;
- int totalTime;
-
- if (xine_get_pos_length(stream, &relativePosition, ¤tTime, &totalTime) == 1) \
{
- parentProcess->updateCurrentTotalTime(currentTime, totalTime);
- }
-}
-
-void XineObject::init(quint64 windowId)
-{
- if (engine != NULL) {
- Log("XineObject::init: xine engine is already initialised");
- return;
- }
-
- engine = xine_new();
-
- if (engine == NULL) {
- parentProcess->initFailed("Cannot create engine.");
- return;
- }
-
- xine_config_load(engine, QFile::encodeName(KStandardDirs::locateLocal("data",
- "kaffeine/xine-config")).constData());
- xine_init(engine);
-
- QVector<const char *> audioDrivers;
- audioDrivers.append("auto");
-
- for (const char *const *it = xine_list_audio_output_plugins(engine); *it != NULL; \
++it) {
- audioDrivers.append(*it);
- }
-
- audioDrivers.append(NULL);
- const char *audioDriver = audioDrivers.at(
- xine_config_register_enum(engine, "audio.driver", 0,
- const_cast<char **>(audioDrivers.constData()), "audio driver", NULL, 10,
- &audio_driver_cb, this));
- audioDrivers.clear();
-
- QVector<const char *> videoDrivers;
- videoDrivers.append("auto");
-
- for (const char *const *it = xine_list_video_output_plugins(engine); *it != NULL; \
++it) {
- videoDrivers.append(*it);
- }
-
- videoDrivers.append(NULL);
- const char *videoDriver = videoDrivers.at(
- xine_config_register_enum(engine, "video.driver", 0,
- const_cast<char **>(videoDrivers.constData()), "video driver", NULL, 10,
- &video_driver_cb, this));
- videoDrivers.clear();
-
- QLatin1String pixelAspectRatioString(xine_config_register_string(engine,
- "video.pixel_aspect_ratio", "", "override pixel aspect ratio", NULL, 10,
- &pixel_aspect_ratio_cb, this));
-
- bool ok;
- pixelAspectRatio = QString(pixelAspectRatioString).toDouble(&ok);
-
- if (!ok || (pixelAspectRatio < 0.1) || (pixelAspectRatio > 10)) {
- if (qstrlen(pixelAspectRatioString.latin1()) != 0) {
- Log("XineObject::init: invalid pixel aspect ratio") <<
- pixelAspectRatioString;
- }
-
- pixelAspectRatio = static_cast<double>(QX11Info::appDpiY()) / QX11Info::appDpiX();
-
- if ((pixelAspectRatio >= 0.96) || (pixelAspectRatio <= 1.04)) {
- pixelAspectRatio = 1;
- }
- }
-
- audioOutput = xine_open_audio_driver(engine, audioDriver, NULL);
-
- if (audioOutput == NULL) {
- Log("XineObject::init: cannot create audio output") << QLatin1String(audioDriver);
- audioOutput = xine_open_audio_driver(engine, NULL, NULL);
-
- if (audioOutput == NULL) {
- parentProcess->initFailed("Cannot create audio output.");
- return;
- }
- }
-
- x11_visual_t videoOutputData;
- memset(&videoOutputData, 0, sizeof(videoOutputData));
- videoOutputData.display = QX11Info::display();
- videoOutputData.screen = QX11Info::appScreen();
- videoOutputData.d = windowId;
- videoOutputData.user_data = this;
- videoOutputData.dest_size_cb = &dest_size_cb;
- videoOutputData.frame_output_cb = &frame_output_cb;
-
- videoOutput = xine_open_video_driver(engine, videoDriver, XINE_VISUAL_TYPE_X11,
- &videoOutputData);
-
- if (videoOutput == NULL) {
- Log("XineObject::init: cannot create video output") << QLatin1String(videoDriver);
- videoOutput = xine_open_video_driver(engine, NULL, XINE_VISUAL_TYPE_X11,
- &videoOutputData);
-
- if (videoOutput == NULL) {
- parentProcess->initFailed("Cannot create video output.");
- return;
- }
- }
-
- stream = xine_stream_new(engine, audioOutput, videoOutput);
-
- if (stream == NULL) {
- parentProcess->initFailed("Cannot create stream.");
- return;
- }
-
- eventQueue = xine_event_new_queue(stream);
-
- if (eventQueue == NULL) {
- parentProcess->initFailed("Cannot create event queue.");
- return;
- }
-
- xine_event_create_listener_thread(eventQueue, &event_listener_cb, this);
- dirtyFlags &= ~NotReady;
-
- visualization = NULL; // xine_post_init(engine, "goom", 0, &audioOutput, \
&videoOutput);
-
- if (visualization == NULL) {
- // kWarning() << "cannot create audio visualization plugin";
- } else {
- xine_post_in_t *input = xine_post_input(visualization, "audio in");
-
- if (input == NULL) {
- Log("XineObject::init: cannot connect audio visualization plugin");
- } else {
- xine_post_wire(xine_get_audio_source(stream), input);
- }
- }
-
- deinterlacer = xine_post_init(engine, "tvtime", 1, 0, &videoOutput);
-
- if (deinterlacer == NULL) {
- Log("XineObject::init: cannot create deinterlace plugin");
- return;
- }
-
- xine_post_in_t *input = xine_post_input(deinterlacer, "parameters");
-
- if (input == NULL) {
- Log("XineObject::init: cannot configure deinterlace plugin");
- return;
- }
-
- xine_post_api_t *deinterlacerApi = static_cast<xine_post_api_t *>(input->data);
-
- if (deinterlacerApi == NULL) {
- Log("XineObject::init: cannot configure deinterlace plugin");
- return;
- }
-
- xine_post_api_descr_t *deinterlacerParameters = deinterlacerApi->get_param_descr();
-
- if (deinterlacerParameters == NULL) {
- Log("XineObject::init: cannot configure deinterlace plugin");
- return;
- }
-
- for (int i = 0; deinterlacerParameters->parameter[i].type != POST_PARAM_TYPE_LAST; \
++i) {
- xine_post_api_parameter_t ¶meter = deinterlacerParameters->parameter[i];
-
- if ((parameter.type == POST_PARAM_TYPE_INT) &&
- (strcmp(parameter.name, "method") == 0)) {
- QByteArray parameterData;
- parameterData.resize(deinterlacerParameters->struct_size);
- char *data = parameterData.data();
- deinterlacerApi->get_parameters(deinterlacer, data);
- int *method = reinterpret_cast<int *>(data + parameter.offset);
-
- for (char **value = parameter.enum_values; *value != NULL; ++value) {
- if (strcmp(*value, "Greedy2Frame") == 0) {
- *method = value - parameter.enum_values;
- break;
- }
- }
-
- deinterlacerApi->set_parameters(deinterlacer, data);
- break;
- }
- }
-
- // FIXME gapless playback?
-}
-
-void XineObject::customEvent(QEvent *event)
-{
- if (event->type() == XineEvent) {
- QMutexLocker locker(&mutex);
-
- if ((dirtyFlags & (Quit | OpenStream)) != 0) {
- errorMessage.clear();
- xineDirtyFlags = 0;
- }
-
- while (xineDirtyFlags != 0) {
- int lowestDirtyFlag = xineDirtyFlags & (~(xineDirtyFlags - 1));
- xineDirtyFlags &= ~lowestDirtyFlag;
-
- switch (lowestDirtyFlag) {
- case PlaybackFailed:
- parentProcess->playbackFailed(errorMessage);
- errorMessage.clear();
- xineDirtyFlags = CloseStream;
- break;
- case PlaybackFinished:
- parentProcess->playbackFinished();
- xineDirtyFlags = CloseStream;
- break;
- case CloseStream:
- positionTimer.stop();
- xine_close(stream);
- break;
- case UpdateStreamInfo: {
- QString metadata;
- metadata.append(QChar(XineMetadataTitle));
- metadata.append(QString::fromUtf8(xine_get_meta_info(stream,
- XINE_META_INFO_TITLE)));
- metadata.append(QChar('\0'));
- metadata.append(QChar(XineMetadataArtist));
- metadata.append(QString::fromUtf8(xine_get_meta_info(stream,
- XINE_META_INFO_ARTIST)));
- metadata.append(QChar('\0'));
- metadata.append(QChar(XineMetadataAlbum));
- metadata.append(QString::fromUtf8(xine_get_meta_info(stream,
- XINE_META_INFO_ALBUM)));
- metadata.append(QChar('\0'));
- metadata.append(QChar(XineMetadataTrackNumber));
- metadata.append(QString::fromUtf8(xine_get_meta_info(stream,
- XINE_META_INFO_TRACK_NUMBER)));
- metadata.append(QChar('\0'));
- parentProcess->updateMetadata(metadata);
-
- bool seekable = (xine_get_stream_info(stream,
- XINE_STREAM_INFO_SEEKABLE) != 0);
- parentProcess->updateSeekable(seekable);
-
- QByteArray audioChannels;
- int audioChannelCount = xine_get_stream_info(stream,
- XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
- int currentAudioChannel = xine_get_param(stream,
- XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
-
- for (int i = 0; i < audioChannelCount; ++i) {
- char langBuffer[XINE_LANG_MAX];
-
- if (xine_get_audio_lang(stream, i, langBuffer) == 1) {
- audioChannels.append(langBuffer);
- }
-
- audioChannels.append('\0');
- }
-
- parentProcess->updateAudioChannels(audioChannels,
- currentAudioChannel);
-
- QByteArray subtitles;
- int subtitleCount = xine_get_stream_info(stream,
- XINE_STREAM_INFO_MAX_SPU_CHANNEL);
- int currentSubtitle = xine_get_param(stream,
- XINE_PARAM_SPU_CHANNEL);
-
- for (int i = 0; i < subtitleCount; ++i) {
- char langBuffer[XINE_LANG_MAX];
-
- if (xine_get_spu_lang(stream, i, langBuffer) == 1) {
- subtitles.append(langBuffer);
- }
-
- subtitles.append('\0');
- }
-
- parentProcess->updateSubtitles(subtitles, currentSubtitle);
-
- int titleCount = xine_get_stream_info(stream,
- XINE_STREAM_INFO_DVD_TITLE_COUNT);
- int currentTitle = xine_get_stream_info(stream,
- XINE_STREAM_INFO_DVD_TITLE_NUMBER);
-
- if ((titleCount <= 0) && (overrideTitleCount > 0)) {
- titleCount = overrideTitleCount;
- }
-
- if ((currentTitle <= 0) && (overrideCurrentTitle > 0)) {
- currentTitle = overrideCurrentTitle;
- }
-
- parentProcess->updateTitles(titleCount, currentTitle);
-
- int chapterCount = xine_get_stream_info(stream,
- XINE_STREAM_INFO_DVD_CHAPTER_COUNT);
- int currentChapter = xine_get_stream_info(stream,
- XINE_STREAM_INFO_DVD_CHAPTER_NUMBER);
- parentProcess->updateChapters(chapterCount, currentChapter);
-
- int angleCount = xine_get_stream_info(stream,
- XINE_STREAM_INFO_DVD_ANGLE_COUNT);
- int currentAngle = xine_get_stream_info(stream,
- XINE_STREAM_INFO_DVD_ANGLE_NUMBER);
- parentProcess->updateAngles(angleCount, currentAngle);
- break;
- }
- case UpdateMouseTracking:
- parentProcess->updateMouseTracking(mouseTrackingEnabled);
- break;
- case UpdateMouseCursor:
- parentProcess->updateMouseCursor(pointingMouseCursor);
- break;
- case UpdateVideoSize:
- parentProcess->updateVideoSize(videoSize);
- break;
- case ProcessXineEvent:
- break;
- default:
- Log("XineObject::customEvent: unknown flag") << lowestDirtyFlag;
- break;
- }
- }
-
- return;
- }
-
- while (dirtyFlags != 0) {
- QCoreApplication::processEvents();
- int lowestDirtyFlag = dirtyFlags & (~(dirtyFlags - 1));
- dirtyFlags &= ~lowestDirtyFlag;
-
- switch (lowestDirtyFlag) {
- case Quit:
- return;
- case SetMuted:
- xine_set_param(stream, XINE_PARAM_AUDIO_AMP_MUTE, muted);
- break;
- case SetVolume:
- xine_set_param(stream, XINE_PARAM_AUDIO_AMP_LEVEL, volume);
- break;
- case SetAspectRatio: {
- int xineAspectRatio;
-
- switch (aspectRatio) {
- case XineAspectRatioAuto:
- xineAspectRatio = XINE_VO_ASPECT_AUTO;
- break;
- case XineAspectRatio4_3:
- xineAspectRatio = XINE_VO_ASPECT_4_3;
- break;
- case XineAspectRatio16_9:
- xineAspectRatio = XINE_VO_ASPECT_ANAMORPHIC;
- break;
- case XineAspectRatioWidget:
- // this is solved via xine frame callbacks
- xineAspectRatio = XINE_VO_ASPECT_SQUARE;
- break;
- default:
- Log("XineObject::customEvent: unknown aspect ratio") <<
- aspectRatio;
- xineAspectRatio = XINE_VO_ASPECT_AUTO;
- break;
- }
-
- xine_set_param(stream, XINE_PARAM_VO_ASPECT_RATIO, xineAspectRatio);
- break;
- }
- case SetDeinterlacing:
- if (deinterlacing && (deinterlacer != NULL)) {
- xine_post_in_t *input = xine_post_input(deinterlacer, "video");
-
- if (input != NULL) {
- xine_post_wire(xine_get_video_source(stream), input);
- }
- } else {
- xine_post_wire_video_port(xine_get_video_source(stream),
- videoOutput);
- }
-
- break;
- case OpenStream:
- parentProcess->sync(sequenceNumber);
- overrideTitleCount = 0;
- overrideCurrentTitle = 0;
-
- if (encodedUrl.startsWith("cdda:")) {
- xine_get_autoplay_input_plugin_ids(engine);
- xine_get_autoplay_mrls(engine, "CD", &overrideTitleCount);
- overrideCurrentTitle =
- encodedUrl.mid(encodedUrl.lastIndexOf('/') + 1).toInt();
-
- if (overrideCurrentTitle < 1) {
- overrideCurrentTitle = 1;
- }
- }
-
- if (!encodedUrl.isEmpty()) {
- if (xine_open(stream, encodedUrl.constData()) == 1) {
- mutex.lock();
- errorMessage.clear();
- xineDirtyFlags &= ~(PlaybackFailed | PlaybackFinished);
- mutex.unlock();
- dirtyFlags |= PlayStream;
- } else {
- int errorCode = xine_get_error(stream);
- // xine_close is called when dealing with PlaybackFailed
- mutex.lock();
-
- if (errorMessage.isEmpty()) {
- errorMessage = xineErrorString(errorCode);
- }
-
- xineDirtyFlags |= PlaybackFailed;
- postXineEvent();
- mutex.unlock();
- }
-
- encodedUrl.clear();
- } else {
- // xine_close is called when dealing with PlaybackFinished
- mutex.lock();
- xineDirtyFlags |= PlaybackFinished;
- postXineEvent();
- mutex.unlock();
- }
-
- break;
- case PlayStream:
- if (xine_play(stream, 0, 0) == 1) {
- mutex.lock();
- xineDirtyFlags |= UpdateStreamInfo;
- postXineEvent();
- mutex.unlock();
- positionTimer.start();
- updatePosition();
- } else {
- int errorCode = xine_get_error(stream);
- // xine_close is called when dealing with PlaybackFailed
- mutex.lock();
-
- if (errorMessage.isEmpty()) {
- errorMessage = xineErrorString(errorCode);
- }
-
- xineDirtyFlags |= PlaybackFailed;
- postXineEvent();
- mutex.unlock();
- }
-
- break;
- case SetPaused:
- if (paused) {
- xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
- } else {
- xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
- }
-
- break;
- case Seek:
- xine_play(stream, 0, seekTime);
- break;
- case Repaint: {
- XEvent event;
- memset(&event, 0, sizeof(event));
- event.xexpose.type = Expose;
- event.xexpose.width = (widgetSize >> 16);
- event.xexpose.height = (widgetSize & 0xffff);
- xine_port_send_gui_data(videoOutput, XINE_GUI_SEND_EXPOSE_EVENT, &event);
- break;
- }
- case MouseMoved: {
- x11_rectangle_t rectangle;
- memset(&rectangle, 0, sizeof(rectangle));
- rectangle.x = (mouseMovePosition >> 16);
- rectangle.y = (mouseMovePosition & 0xffff);
- xine_port_send_gui_data(videoOutput, XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO,
- &rectangle);
- xine_input_data_t input;
- memset(&input, 0, sizeof(input));
- input.event.type = XINE_EVENT_INPUT_MOUSE_MOVE;
- input.event.data = &input;
- input.event.data_length = sizeof(input);
- input.x = rectangle.x;
- input.y = rectangle.y;
- xine_event_send(stream, &input.event);
- break;
- }
- case MousePressed: {
- x11_rectangle_t rectangle;
- memset(&rectangle, 0, sizeof(rectangle));
- rectangle.x = (mousePressPosition >> 16);
- rectangle.y = (mousePressPosition & 0xffff);
- xine_port_send_gui_data(videoOutput, XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO,
- &rectangle);
- xine_input_data_t input;
- memset(&input, 0, sizeof(input));
- input.event.type = XINE_EVENT_INPUT_MOUSE_BUTTON;
- input.event.data = &input;
- input.event.data_length = sizeof(input);
- input.button = 1;
- input.x = rectangle.x;
- input.y = rectangle.y;
- xine_event_send(stream, &input.event);
- break;
- }
- case SetCurrentAudioChannel:
- xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL,
- currentAudioChannel);
- break;
- case SetCurrentSubtitle:
- xine_set_param(stream, XINE_PARAM_SPU_CHANNEL, currentSubtitle);
- break;
- case ToggleMenu: {
- xine_event_t event;
- memset(&event, 0, sizeof(event));
- event.type = XINE_EVENT_INPUT_MENU1;
- xine_event_send(stream, &event);
- break;
- }
- case ProcessEvent:
- break;
- default:
- Log("XineObject::customEvent: unknown flag") << lowestDirtyFlag;
- break;
- }
- }
-}
-
-QString XineObject::xineErrorString(int errorCode) const
-{
- switch (errorCode) {
- case XINE_ERROR_NO_INPUT_PLUGIN:
- return QString("Cannot find input plugin for MRL \"") + encodedUrl + "\".";
- case XINE_ERROR_INPUT_FAILED:
- return QString("Cannot open input plugin for MRL \"") + encodedUrl + "\".";
- case XINE_ERROR_NO_DEMUX_PLUGIN:
- return QString("Cannot find demux plugin for MRL \"") + encodedUrl + "\".";
- case XINE_ERROR_DEMUX_FAILED:
- return QString("Cannot open demux plugin for MRL \"") + encodedUrl + "\".";
- case XINE_ERROR_MALFORMED_MRL:
- return QString("Cannot parse MRL \"") + encodedUrl + "\".";
- case XINE_ERROR_NONE:
- default:
- return QString("Cannot open MRL \"") + encodedUrl + "\".";
- }
-}
-
-void XineObject::postXineEvent()
-{
- if ((xineDirtyFlags & ProcessXineEvent) == 0) {
- QCoreApplication::postEvent(this, new QEvent(XineEvent));
- xineDirtyFlags |= ProcessXineEvent;
- }
-}
-
-void XineObject::audio_driver_cb(void *user_data, xine_cfg_entry_t *entry)
-{
- Q_UNUSED(user_data)
- Q_UNUSED(entry)
-}
-
-void XineObject::video_driver_cb(void *user_data, xine_cfg_entry_t *entry)
-{
- Q_UNUSED(user_data)
- Q_UNUSED(entry)
-}
-
-void XineObject::pixel_aspect_ratio_cb(void *user_data, xine_cfg_entry_t *entry)
-{
- Q_UNUSED(user_data)
- Q_UNUSED(entry)
-}
-
-void XineObject::dest_size_cb(void *user_data, int video_width, int video_height,
- double video_pixel_aspect, int *dest_width, int *dest_height, double \
*dest_pixel_aspect)
-{
- XineObject *instance = static_cast<XineObject *>(user_data);
- int widgetSize = instance->widgetSize;
- *dest_width = (widgetSize >> 16);
- *dest_height = (widgetSize & 0xffff);
-
- if (instance->aspectRatio != XineAspectRatioWidget) {
- *dest_pixel_aspect = instance->pixelAspectRatio;
- } else {
- *dest_pixel_aspect = video_pixel_aspect * video_width * (widgetSize & 0xffff) /
- (video_height * (widgetSize >> 16));
- }
-
- unsigned int videoSize = ((video_width << 16) | video_height);
-
- if (instance->videoSize != videoSize) {
- QMutexLocker locker(&instance->mutex);
- instance->videoSize = videoSize;
- instance->xineDirtyFlags |= UpdateVideoSize;
- instance->postXineEvent();
- }
-}
-
-void XineObject::frame_output_cb(void *user_data, int video_width, int video_height,
- double video_pixel_aspect, int *dest_x, int *dest_y, int *dest_width, int \
*dest_height,
- double *dest_pixel_aspect, int *win_x, int *win_y)
-{
- XineObject *instance = static_cast<XineObject *>(user_data);
- *dest_x = 0;
- *dest_y = 0;
- int widgetSize = instance->widgetSize;
- *dest_width = (widgetSize >> 16);
- *dest_height = (widgetSize & 0xffff);
- *win_x = 0;
- *win_y = 0;
-
- if (instance->aspectRatio != XineAspectRatioWidget) {
- *dest_pixel_aspect = instance->pixelAspectRatio;
- } else {
- *dest_pixel_aspect = video_pixel_aspect * video_width * (widgetSize & 0xffff) /
- (video_height * (widgetSize >> 16));
- }
-
- unsigned int videoSize = ((video_width << 16) | video_height);
-
- if (instance->videoSize != videoSize) {
- QMutexLocker locker(&instance->mutex);
- instance->videoSize = videoSize;
- instance->xineDirtyFlags |= UpdateVideoSize;
- instance->postXineEvent();
- }
-}
-
-void XineObject::event_listener_cb(void *user_data, const xine_event_t *event)
-{
- XineObject *instance = static_cast<XineObject *>(user_data);
-
- switch (event->type) {
- case XINE_EVENT_UI_PLAYBACK_FINISHED: {
- QMutexLocker locker(&instance->mutex);
- instance->xineDirtyFlags |= PlaybackFinished;
- instance->postXineEvent();
- break;
- }
- case XINE_EVENT_UI_CHANNELS_CHANGED: {
- QMutexLocker locker(&instance->mutex);
- instance->xineDirtyFlags |= UpdateStreamInfo;
- instance->postXineEvent();
- break;
- }
- case XINE_EVENT_UI_MESSAGE: {
- QMutexLocker locker(&instance->mutex);
- const xine_ui_message_data_t *messageData =
- static_cast<const xine_ui_message_data_t *>(event->data);
-
- if (messageData != NULL) {
- const char *data = messageData->messages;
- int size = 0;
-
- while (data[size + 1] != '\0') {
- ++size;
- size += qstrlen(data + size);
- }
-
- instance->errorMessage = QString::fromLocal8Bit(data, size);
- instance->errorMessage.replace('\0', '\n');
- } else {
- instance->errorMessage.clear();
- }
-
- instance->xineDirtyFlags |= PlaybackFailed;
- instance->postXineEvent();
- break;
- }
- case XINE_EVENT_UI_NUM_BUTTONS: {
- QMutexLocker locker(&instance->mutex);
- const xine_ui_data_t *uiData = static_cast<const xine_ui_data_t *>(event->data);
-
- if (uiData != NULL) {
- instance->mouseTrackingEnabled = (uiData->num_buttons != 0);
- } else {
- instance->mouseTrackingEnabled = false;
- }
-
- instance->xineDirtyFlags |= UpdateMouseTracking;
- instance->postXineEvent();
- break;
- }
- case XINE_EVENT_SPU_BUTTON: {
- QMutexLocker locker(&instance->mutex);
- const xine_spu_button_t *spu_event =
- static_cast<const xine_spu_button_t *>(event->data);
-
- if (spu_event != NULL) {
- instance->pointingMouseCursor = (spu_event->direction == 1);
- } else {
- instance->pointingMouseCursor = false;
- }
-
- instance->xineDirtyFlags |= UpdateMouseCursor;
- instance->postXineEvent();
- break;
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- XInitThreads();
-
- bool ok = false;
-
- if ((argc == 2) && (strcmp(argv[1], "fU4eT3iN") == 0)) {
- ok = true;
- argc = 1;
- }
-
- KAboutData aboutData("kaffeine-xbu", "kaffeine", ki18n("Kaffeine"),
- QByteArray("1.3-svn ").append(XineObject::version()),
- ki18nc("program description", "Internal utility for Kaffeine."),
- KAboutData::License_GPL_V2, ki18n("(C) 2007-2011 The Kaffeine Authors"),
- KLocalizedString(), "http://kaffeine.kde.org");
- aboutData.addAuthor(ki18n("Christoph Pfister"), ki18n("Maintainer"),
- "christophpfister@gmail.com");
- KCmdLineArgs::init(argc, argv, &aboutData);
-
- KApplication application;
-
- if (!ok) {
- return 0;
- }
-
- XineObject xineObject;
- return application.exec();
-}
diff --git a/src/backend-xine/xineapplication.h b/src/backend-xine/xineapplication.h
deleted file mode 100644
index 3fcccd4..0000000
--- a/src/backend-xine/xineapplication.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * xineapplication.h
- *
- * Copyright (C) 2010-2011 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
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef XINEAPPLICATION_H
-#define XINEAPPLICATION_H
-
-#include <QEvent>
-#include <QMutex>
-#include <QTimer>
-#include <xine.h>
-
-class XineParent;
-class XinePipeReader;
-
-class XineObject : public QObject
-{
- Q_OBJECT
-public:
- XineObject();
- ~XineObject();
-
- static const char *version();
-
-private slots:
- void readyRead();
- void updatePosition();
-
-private:
- enum DirtyFlag {
- Quit = (1 << 0),
- NotReady = (1 << 1),
- SetMuted = (1 << 2),
- SetVolume = (1 << 3),
- SetAspectRatio = (1 << 4),
- SetDeinterlacing = (1 << 5),
- OpenStream = (1 << 6),
- PlayStream = (1 << 7),
- SetPaused = (1 << 8),
- Seek = (1 << 9),
- Repaint = (1 << 10),
- MouseMoved = (1 << 11),
- MousePressed = (1 << 12),
- SetCurrentAudioChannel = (1 << 13),
- SetCurrentSubtitle = (1 << 14),
- ToggleMenu = (1 << 15),
- ProcessEvent = (1 << 30)
- };
-
- Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
-
- enum XineDirtyFlag {
- PlaybackFailed = (1 << 0),
- PlaybackFinished = (1 << 1),
- CloseStream = (1 << 2),
- UpdateStreamInfo = (1 << 3),
- UpdateMouseTracking = (1 << 4),
- UpdateMouseCursor = (1 << 5),
- UpdateVideoSize = (1 << 6),
- ProcessXineEvent = (1 << 30)
- };
-
- Q_DECLARE_FLAGS(XineDirtyFlags, XineDirtyFlag)
-
- static const QEvent::Type ReaderEvent = static_cast<QEvent::Type>(QEvent::User + \
1);
- static const QEvent::Type XineEvent = static_cast<QEvent::Type>(QEvent::User + 2);
-
- void init(quint64 windowId);
- void customEvent(QEvent *event);
- QString xineErrorString(int errorCode) const;
-
- void postXineEvent();
- static void audio_driver_cb(void *user_data, xine_cfg_entry_t *entry);
- static void video_driver_cb(void *user_data, xine_cfg_entry_t *entry);
- static void pixel_aspect_ratio_cb(void *user_data, xine_cfg_entry_t *entry);
- static void dest_size_cb(void *user_data, int video_width, int video_height,
- double video_pixel_aspect, int *dest_width, int *dest_height,
- double *dest_pixel_aspect);
- static void frame_output_cb(void *user_data, int video_width, int video_height,
- double video_pixel_aspect, int *dest_x, int *dest_y, int *dest_width,
- int *dest_height, double *dest_pixel_aspect, int *win_x, int *win_y);
- static void event_listener_cb(void *user_data, const xine_event_t *event);
-
- XinePipeReader *reader;
- XineParent *parentProcess;
-
- xine_t *engine;
- xine_audio_port_t *audioOutput;
- xine_video_port_t *videoOutput;
- xine_stream_t *stream;
- xine_event_queue_t *eventQueue;
- xine_post_t *visualization;
- xine_post_t *deinterlacer;
- double pixelAspectRatio;
- unsigned int widgetSize;
- QTimer positionTimer;
- int overrideTitleCount;
- int overrideCurrentTitle;
-
- DirtyFlags dirtyFlags;
- bool muted;
- bool deinterlacing;
- bool paused;
- int aspectRatio;
- int currentAudioChannel;
- int currentSubtitle;
- int seekTime;
- int volume;
- unsigned int mouseMovePosition;
- unsigned int mousePressPosition;
- unsigned int sequenceNumber;
- QByteArray encodedUrl;
-
- QMutex mutex;
- XineDirtyFlags xineDirtyFlags;
- bool mouseTrackingEnabled;
- bool pointingMouseCursor;
- unsigned int videoSize;
- QString errorMessage;
-};
-
-#endif /* XINEAPPLICATION_H */
diff --git a/src/backend-xine/xinecommands.cpp b/src/backend-xine/xinecommands.cpp
deleted file mode 100644
index 737ebb7..0000000
--- a/src/backend-xine/xinecommands.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * xinecommands.cpp
- *
- * Copyright (C) 2010-2011 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
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "xinecommands.h"
-
-#include <errno.h>
-#include <unistd.h>
-#include "../log.h"
-
-XinePipeReader::XinePipeReader(int fd_, QObject *parent) : fd(fd_),
- notifier(fd, QSocketNotifier::Read)
-{
- QObject::connect(¬ifier, SIGNAL(activated(int)), parent, SLOT(readyRead()));
-
- buffer.resize(4080);
- bufferPosition = 0;
- bufferSize = 0;
- currentData = NULL;
- currentSize = -1;
-}
-
-XinePipeReader::~XinePipeReader()
-{
-}
-
-void XinePipeReader::readyRead()
-{
- while (true) {
- int bytesRead = read(fd, buffer.data() + bufferSize, buffer.size() - bufferSize);
-
- if ((bytesRead < 0) && (errno == EINTR)) {
- continue;
- }
-
- if (bytesRead > 0) {
- bufferSize += bytesRead;
-
- if (bufferSize == buffer.size()) {
- buffer.resize(buffer.size() + 4096);
- continue;
- }
- }
-
- break;
- }
-
- currentSize = -1;
-}
-
-int XinePipeReader::nextCommand()
-{
- qint32 size = 5;
-
- if ((bufferSize - bufferPosition) >= 4) {
- memcpy(&size, buffer.constData() + bufferPosition, 4);
-
- if (size < 5) {
- Log("XinePipeReader::nextCommand: size too small");
- size = 5;
- }
- }
-
- if ((bufferSize - bufferPosition) < size) {
- if (bufferPosition == bufferSize) {
- if (buffer.size() != 4080) {
- buffer.clear();
- buffer.resize(4080);
- }
-
- bufferPosition = 0;
- bufferSize = 0;
- } else if (bufferPosition > 0) {
- memmove(buffer.data(), buffer.constData() + bufferPosition,
- bufferSize - bufferPosition);
- bufferSize -= bufferPosition;
- bufferPosition = 0;
-
- if (buffer.size() < size) {
- buffer.resize(4080 + ((size - 4080 + 4095) & (~4095)));
- } else if ((buffer.size() > 4080) && (size <= 4080)) {
- buffer.resize(4080);
- }
- }
-
- currentSize = -1;
- return -1;
- }
-
- currentData = buffer.constData() + bufferPosition + 5;
- currentSize = size - 5;
- bufferPosition += size;
- return *(currentData - 1);
-}
-
-bool XinePipeReader::isValid() const
-{
- return (currentSize == 0);
-}
-
-bool XinePipeReader::readBool()
-{
- bool value = false;
-
- if (currentSize >= 1) {
- value = (*currentData != 0);
- ++currentData;
- --currentSize;
- } else {
- currentSize = -1;
- }
-
- return value;
-}
-
-qint8 XinePipeReader::readChar()
-{
- qint8 value = 0;
-
- if (currentSize >= static_cast<int>(sizeof(value))) {
- memcpy(&value, currentData, sizeof(value));
- currentData += sizeof(value);
- currentSize -= sizeof(value);
- } else {
- currentSize = -1;
- }
-
- return value;
-}
-
-qint16 XinePipeReader::readShort()
-{
- qint16 value = 0;
-
- if (currentSize >= static_cast<int>(sizeof(value))) {
- memcpy(&value, currentData, sizeof(value));
- currentData += sizeof(value);
- currentSize -= sizeof(value);
- } else {
- currentSize = -1;
- }
-
- return value;
-}
-
-qint32 XinePipeReader::readInt()
-{
- qint32 value = 0;
-
- if (currentSize >= static_cast<int>(sizeof(value))) {
- memcpy(&value, currentData, sizeof(value));
- currentData += sizeof(value);
- currentSize -= sizeof(value);
- } else {
- currentSize = -1;
- }
-
- return value;
-}
-
-qint64 XinePipeReader::readLongLong()
-{
- qint64 value = 0;
-
- if (currentSize >= static_cast<int>(sizeof(value))) {
- memcpy(&value, currentData, sizeof(value));
- currentData += sizeof(value);
- currentSize -= sizeof(value);
- } else {
- currentSize = -1;
- }
-
- return value;
-}
-
-QByteArray XinePipeReader::readByteArray()
-{
- QByteArray byteArray;
-
- if (currentSize >= 0) {
- byteArray.resize(currentSize);
- memcpy(byteArray.data(), currentData, currentSize);
- currentSize = 0;
- }
-
- return byteArray;
-}
-
-QString XinePipeReader::readString()
-{
- QString string;
-
- if ((currentSize >= 0) && ((currentSize & 0x01) == 0)) {
- string.resize(currentSize / 2);
- memcpy(reinterpret_cast<char *>(string.data()), currentData, currentSize);
- currentSize = 0;
- } else {
- currentSize = -1;
- }
-
- return string;
-}
-
-void XinePipeWriterBase::write(qint8 command, const char *firstArg, unsigned int \
firstArgSize,
- const char *secondArg, unsigned int secondArgSize)
-{
- Q_UNUSED(command)
- Q_UNUSED(firstArg)
- Q_UNUSED(firstArgSize)
- Q_UNUSED(secondArg)
- Q_UNUSED(secondArgSize)
-}
-
-XinePipeWriter::XinePipeWriter(int fd_, QObject *parent) : QObject(parent), fd(fd_),
- notifier(fd, QSocketNotifier::Write)
-{
- notifier.setEnabled(false);
- connect(¬ifier, SIGNAL(activated(int)), this, SLOT(readyWrite()));
-
- buffer.resize(4080);
- bufferPosition = 0;
-}
-
-XinePipeWriter::~XinePipeWriter()
-{
-}
-
-void XinePipeWriter::readyWrite()
-{
- if (flush()) {
- notifier.setEnabled(false);
- }
-}
-
-void XinePipeWriter::write(qint8 command, const char *firstArg, unsigned int \
firstArgSize,
- const char *secondArg, unsigned int secondArgSize)
-{
- if ((firstArgSize >= 0x100000) || (secondArgSize >= 0x100000)) {
- Log("XinePipeWriter::write: monstrous big write") << command;
- firstArgSize = 0;
- secondArgSize = 0;
- }
-
- qint32 size = 5 + firstArgSize + secondArgSize;
-
- if (size > (buffer.size() - bufferPosition)) {
- buffer.resize(4080 + ((bufferPosition + size - 4080 + 4095) & (~4095)));
- }
-
- char *data = buffer.data() + bufferPosition;
- memcpy(data, &size, 4);
- data[4] = command;
- memcpy(data + 5, firstArg, firstArgSize);
- memcpy(data + 5 + firstArgSize, secondArg, secondArgSize);
- bufferPosition += size;
-
- if (!flush()) {
- notifier.setEnabled(true);
- }
-}
-
-bool XinePipeWriter::flush()
-{
- int bytesWritten;
-
- do {
- bytesWritten = ::write(fd, buffer.constData(), bufferPosition);
- } while ((bytesWritten < 0) && (errno == EINTR));
-
- if (bytesWritten > 0) {
- if (bytesWritten == bufferPosition) {
- if (buffer.size() != 4080) {
- buffer.clear();
- buffer.resize(4080);
- }
-
- bufferPosition = 0;
- return true;
- }
-
- memmove(buffer.data(), buffer.constData() + bytesWritten,
- bufferPosition - bytesWritten);
- bufferPosition -= bytesWritten;
- }
-
- return false;
-}
diff --git a/src/backend-xine/xinecommands.h b/src/backend-xine/xinecommands.h
deleted file mode 100644
index 25759cf..0000000
--- a/src/backend-xine/xinecommands.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * xinecommands.h
- *
- * Copyright (C) 2010-2011 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
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef XINECOMMANDS_H
-#define XINECOMMANDS_H
-
-#include <QSocketNotifier>
-
-namespace XineCommands
-{
- enum CommandToChild {
- Quit = 0,
- Init = 1,
- Resize = 2,
- SetMuted = 3,
- SetVolume = 4,
- SetAspectRatio = 5,
- SetDeinterlacing = 6,
- PlayUrl = 7,
- SetPaused = 8,
- Seek = 9,
- Repaint = 10,
- MouseMoved = 11,
- MousePressed = 12,
- SetCurrentAudioChannel = 13,
- SetCurrentSubtitle = 14,
- ToggleMenu = 15
- };
-
- enum CommandFromChild {
- InitFailed = 0,
- Sync = 1,
- PlaybackFailed = 2,
- PlaybackFinished = 3,
- UpdateCurrentTotalTime = 4,
- UpdateMetadata = 5,
- UpdateSeekable = 6,
- UpdateAudioChannels = 7,
- UpdateSubtitles = 8,
- UpdateTitles = 9,
- UpdateChapters = 10,
- UpdateAngles = 11,
- UpdateMouseTracking = 12,
- UpdateMouseCursor = 13,
- UpdateVideoSize = 14
- };
-}
-
-enum XineAspectRatio {
- XineAspectRatioAuto = 0,
- XineAspectRatio4_3 = 1,
- XineAspectRatio16_9 = 2,
- XineAspectRatioWidget = 3
-};
-
-enum XineMetadataType {
- XineMetadataTitle = 0,
- XineMetadataArtist = 1,
- XineMetadataAlbum = 2,
- XineMetadataTrackNumber = 3
-};
-
-class XinePipeReader
-{
-public:
- XinePipeReader(int fd_, QObject *parent);
- ~XinePipeReader();
-
- void readyRead();
- int nextCommand();
- bool isValid() const;
-
- bool readBool();
- qint8 readChar();
- qint16 readShort();
- qint32 readInt();
- qint64 readLongLong();
- QByteArray readByteArray();
- QString readString();
-
-private:
- int fd;
- QSocketNotifier notifier;
- QByteArray buffer;
- int bufferPosition;
- int bufferSize;
- const char *currentData;
- int currentSize;
-};
-
-class XinePipeWriterBase
-{
- friend class XineChildMarshaller;
- friend class XineParentMarshaller;
-public:
- XinePipeWriterBase() { }
- virtual ~XinePipeWriterBase() { }
-
-private:
- virtual void write(qint8 command,
- const char *firstArg = NULL, unsigned int firstArgSize = 0,
- const char *secondArg = NULL, unsigned int secondArgSize = 0);
-};
-
-class XinePipeWriter : public QObject, public XinePipeWriterBase
-{
- Q_OBJECT
-public:
- XinePipeWriter(int fd_, QObject *parent);
- ~XinePipeWriter();
-
-private slots:
- void readyWrite();
-
-private:
- void write(qint8 command, const char *firstArg, unsigned int firstArgSize,
- const char *secondArg, unsigned int secondArgSize);
- bool flush();
-
- int fd;
- QSocketNotifier notifier;
- QByteArray buffer;
- int bufferPosition;
-};
-
-class XineChildMarshaller
-{
-public:
- XineChildMarshaller() : writer(NULL) { }
- ~XineChildMarshaller() { }
-
- void quit()
- {
- writer->write(XineCommands::Quit);
- }
-
- void init(quint64 windowId)
- {
- writer->write(XineCommands::Init, reinterpret_cast<const char *>(&windowId),
- sizeof(windowId));
- }
-
- void resize(quint16 width, quint16 height)
- {
- writer->write(XineCommands::Resize, reinterpret_cast<const char *>(&width),
- sizeof(width), reinterpret_cast<const char *>(&height), sizeof(height));
- }
-
- void setMuted(bool muted)
- {
- writer->write(XineCommands::SetMuted, reinterpret_cast<const char *>(&muted),
- sizeof(muted));
- }
-
- void setVolume(quint8 volume)
- {
- writer->write(XineCommands::SetVolume, reinterpret_cast<const char *>(&volume),
- sizeof(volume));
- }
-
- void setAspectRatio(qint8 aspectRatio)
- {
- writer->write(XineCommands::SetAspectRatio,
- reinterpret_cast<const char *>(&aspectRatio), sizeof(aspectRatio));
- }
-
- void setDeinterlacing(bool deinterlacing)
- {
- writer->write(XineCommands::SetDeinterlacing,
- reinterpret_cast<const char *>(&deinterlacing), sizeof(deinterlacing));
- }
-
- void playUrl(quint32 sequenceNumber, const QByteArray &encodedUrl)
- {
- writer->write(XineCommands::PlayUrl,
- reinterpret_cast<const char *>(&sequenceNumber), sizeof(sequenceNumber),
- encodedUrl.constData(), encodedUrl.size());
- }
-
- void setPaused(bool paused)
- {
- writer->write(XineCommands::SetPaused, reinterpret_cast<const char *>(&paused),
- sizeof(paused));
- }
-
- void seek(qint32 time)
- {
- writer->write(XineCommands::Seek, reinterpret_cast<const char *>(&time),
- sizeof(time));
- }
-
- void repaint()
- {
- writer->write(XineCommands::Repaint);
- }
-
- void mouseMoved(quint16 x, quint16 y)
- {
- writer->write(XineCommands::MouseMoved, reinterpret_cast<const char *>(&x),
- sizeof(x), reinterpret_cast<const char *>(&y), sizeof(y));
- }
-
- void mousePressed(quint16 x, quint16 y)
- {
- writer->write(XineCommands::MousePressed, reinterpret_cast<const char *>(&x),
- sizeof(x), reinterpret_cast<const char *>(&y), sizeof(y));
- }
-
- void setCurrentAudioChannel(qint8 currentAudioChannel)
- {
- writer->write(XineCommands::SetCurrentAudioChannel,
- reinterpret_cast<const char *>(¤tAudioChannel),
- sizeof(currentAudioChannel));
- }
-
- void setCurrentSubtitle(qint8 currentSubtitle)
- {
- writer->write(XineCommands::SetCurrentSubtitle,
- reinterpret_cast<const char *>(¤tSubtitle), sizeof(currentSubtitle));
- }
-
- void toggleMenu()
- {
- writer->write(XineCommands::ToggleMenu);
- }
-
- XinePipeWriterBase *writer;
-};
-
-class XineParentMarshaller
-{
-public:
- XineParentMarshaller() : writer(NULL) { }
- ~XineParentMarshaller() { }
-
- void initFailed(const QString &errorMessage)
- {
- writer->write(XineCommands::InitFailed,
- reinterpret_cast<const char *>(errorMessage.constData()),
- static_cast<unsigned int>(errorMessage.size()) * sizeof(QChar));
- }
-
- void sync(quint32 sequenceNumber)
- {
- writer->write(XineCommands::Sync, reinterpret_cast<const char *>(&sequenceNumber),
- sizeof(sequenceNumber));
- }
-
- void playbackFailed(const QString &errorMessage)
- {
- writer->write(XineCommands::PlaybackFailed,
- reinterpret_cast<const char *>(errorMessage.constData()),
- static_cast<unsigned int>(errorMessage.size()) * sizeof(QChar));
- }
-
- void playbackFinished()
- {
- writer->write(XineCommands::PlaybackFinished);
- }
-
- void updateCurrentTotalTime(qint32 currentTime, qint32 totalTime)
- {
- writer->write(XineCommands::UpdateCurrentTotalTime,
- reinterpret_cast<const char *>(¤tTime), sizeof(currentTime),
- reinterpret_cast<const char *>(&totalTime), sizeof(totalTime));
- }
-
- void updateMetadata(const QString &metadata)
- {
- writer->write(XineCommands::UpdateMetadata,
- reinterpret_cast<const char *>(metadata.constData()),
- static_cast<unsigned int>(metadata.size()) * sizeof(QChar));
- }
-
- void updateSeekable(bool seekable)
- {
- writer->write(XineCommands::UpdateSeekable,
- reinterpret_cast<const char *>(&seekable), sizeof(seekable));
- }
-
- void updateAudioChannels(const QByteArray &audioChannels, qint8 \
currentAudioChannel)
- {
- writer->write(XineCommands::UpdateAudioChannels,
- reinterpret_cast<const char *>(¤tAudioChannel),
- sizeof(currentAudioChannel),
- audioChannels.constData(), audioChannels.size());
- }
-
- void updateSubtitles(const QByteArray &subtitles, qint8 currentSubtitle)
- {
- writer->write(XineCommands::UpdateSubtitles,
- reinterpret_cast<const char *>(¤tSubtitle), sizeof(currentSubtitle),
- subtitles.constData(), subtitles.size());
- }
-
- void updateTitles(qint8 titleCount, qint8 currentTitle)
- {
- writer->write(XineCommands::UpdateTitles,
- reinterpret_cast<const char *>(&titleCount), sizeof(titleCount),
- reinterpret_cast<const char *>(¤tTitle), sizeof(currentTitle));
- }
-
- void updateChapters(qint8 chapterCount, qint8 currentChapter)
- {
- writer->write(XineCommands::UpdateChapters,
- reinterpret_cast<const char *>(&chapterCount), sizeof(chapterCount),
- reinterpret_cast<const char *>(¤tChapter), sizeof(currentChapter));
- }
-
- void updateAngles(qint8 angleCount, qint8 currentAngle)
- {
- writer->write(XineCommands::UpdateAngles,
- reinterpret_cast<const char *>(&angleCount), sizeof(angleCount),
- reinterpret_cast<const char *>(¤tAngle), sizeof(currentAngle));
- }
-
- void updateMouseTracking(bool mouseTrackingEnabled)
- {
- writer->write(XineCommands::UpdateMouseTracking,
- reinterpret_cast<const char *>(&mouseTrackingEnabled),
- sizeof(mouseTrackingEnabled));
- }
-
- void updateMouseCursor(bool pointingMouseCursor)
- {
- writer->write(XineCommands::UpdateMouseCursor,
- reinterpret_cast<const char *>(&pointingMouseCursor),
- sizeof(pointingMouseCursor));
- }
-
- void updateVideoSize(quint32 videoSize)
- {
- writer->write(XineCommands::UpdateVideoSize,
- reinterpret_cast<const char *>(&videoSize), sizeof(videoSize));
- }
-
- XinePipeWriterBase *writer;
-};
-
-#endif /* XINECOMMANDS_H */
diff --git a/src/backend-xine/xinemediawidget.cpp \
b/src/backend-xine/xinemediawidget.cpp deleted file mode 100644
index 960073e..0000000
--- a/src/backend-xine/xinemediawidget.cpp
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * xinemediawidget.cpp
- *
- * Copyright (C) 2010-2011 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
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "xinemediawidget.h"
-#include "xinemediawidget_p.h"
-
-#include <QResizeEvent>
-#include <KMessageBox>
-#include <config-kaffeine.h>
-#include <errno.h>
-#include <unistd.h>
-#include "../log.h"
-
-static QString binInstallPath()
-{
- return QString::fromUtf8(KAFFEINE_BIN_INSTALL_DIR "/");
-}
-
-XineProcess::XineProcess(XineMediaWidget *parent_) : QProcess(parent_), \
parent(parent_)
-{
- memset(pipeToChild, 0, sizeof(pipeToChild));
- memset(pipeFromChild, 0, sizeof(pipeFromChild));
-
- if ((pipe(pipeToChild) != 0) || (pipe(pipeFromChild) != 0)) {
- Log("XineProcess::XineProcess: pipe failed");
- reader = NULL;
- writer = new XinePipeWriterBase();
- childProcess.writer = writer;
- return;
- }
-
- reader = new XinePipeReader(pipeFromChild[0], this);
- writer = new XinePipeWriter(pipeToChild[1], this);
- childProcess.writer = writer;
-
- setProcessChannelMode(ForwardedChannels);
- start(binInstallPath() + "kaffeine-xbu", QStringList() << "fU4eT3iN");
-}
-
-XineProcess::~XineProcess()
-{
- if (state() != QProcess::NotRunning) {
- childProcess.quit();
-
- if (!waitForFinished(3000)) {
- kill();
- }
- }
-
- delete reader;
- delete writer;
-}
-
-void XineProcess::readyRead()
-{
- reader->readyRead();
-
- while (true) {
- int command = reader->nextCommand();
-
- switch (command) {
- case -1:
- return;
- case XineCommands::InitFailed: {
- QString errorMessage = reader->readString();
-
- if (reader->isValid()) {
- parent->initFailed(errorMessage);
- }
-
- break;
- }
- case XineCommands::Sync: {
- quint32 sequenceNumber = reader->readInt();
-
- if (reader->isValid()) {
- parent->sync(sequenceNumber);
- }
-
- break;
- }
- case XineCommands::PlaybackFailed: {
- QString errorMessage = reader->readString();
-
- if (reader->isValid()) {
- parent->playbackFailed(errorMessage);
- }
-
- break;
- }
- case XineCommands::PlaybackFinished:
- parent->playbackFinishedInternal();
- break;
- case XineCommands::UpdateCurrentTotalTime: {
- qint32 currentTime = reader->readInt();
- qint32 totalTime = reader->readInt();
-
- if (reader->isValid()) {
- parent->updateCurrentTotalTime(currentTime, totalTime);
- }
-
- break;
- }
- case XineCommands::UpdateMetadata: {
- QString metadata = reader->readString();
-
- if (reader->isValid()) {
- parent->updateMetadata(metadata);
- }
-
- break;
- }
- case XineCommands::UpdateSeekable: {
- bool seekable = reader->readBool();
-
- if (reader->isValid()) {
- parent->updateSeekable(seekable);
- }
-
- break;
- }
- case XineCommands::UpdateAudioChannels: {
- qint8 currentAudioChannel = reader->readChar();
- QByteArray audioChannels = reader->readByteArray();
-
- if (reader->isValid()) {
- parent->updateAudioChannels(audioChannels, currentAudioChannel);
- }
-
- break;
- }
- case XineCommands::UpdateSubtitles: {
- qint8 currentSubtitle = reader->readChar();
- QByteArray subtitles = reader->readByteArray();
-
- if (reader->isValid()) {
- parent->updateSubtitles(subtitles, currentSubtitle);
- }
-
- break;
- }
- case XineCommands::UpdateTitles: {
- qint8 titleCount = reader->readChar();
- qint8 currentTitle = reader->readChar();
-
- if (reader->isValid()) {
- parent->updateTitles(titleCount, currentTitle);
- }
-
- break;
- }
- case XineCommands::UpdateChapters: {
- qint8 chapterCount = reader->readChar();
- qint8 currentChapter = reader->readChar();
-
- if (reader->isValid()) {
- parent->updateChapters(chapterCount, currentChapter);
- }
-
- break;
- }
- case XineCommands::UpdateAngles: {
- qint8 angleCount = reader->readChar();
- qint8 currentAngle = reader->readChar();
-
- if (reader->isValid()) {
- parent->updateAngles(angleCount, currentAngle);
- }
-
- break;
- }
- case XineCommands::UpdateMouseTracking: {
- bool mouseTrackingEnabled = reader->readBool();
-
- if (reader->isValid()) {
- parent->updateMouseTracking(mouseTrackingEnabled);
- }
-
- break;
- }
- case XineCommands::UpdateMouseCursor: {
- bool pointingMouseCursor = reader->readBool();
-
- if (reader->isValid()) {
- parent->updateMouseCursor(pointingMouseCursor);
- }
-
- break;
- }
- case XineCommands::UpdateVideoSize: {
- quint32 videoSize = reader->readInt();
-
- if (reader->isValid()) {
- parent->updateVideoSize(videoSize);
- }
-
- break;
- }
- default:
- Log("XineProcess::readyRead: unknown command") << command;
- continue;
- }
-
- if (!reader->isValid()) {
- Log("XineProcess::readyRead: wrong argument size for command") << command;
- }
- }
-}
-
-void XineProcess::setupChildProcess()
-{
- while (true) {
- if (dup2(pipeToChild[0], 3) < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- Log("XineProcess::setupChildProcess: dup2 failed");
- }
-
- break;
- }
-
- while (true) {
- if (dup2(pipeFromChild[1], 4) < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- Log("XineProcess::setupChildProcess: dup2 failed");
- }
-
- break;
- }
-}
-
-XineMediaWidget::XineMediaWidget(QWidget *parent) : QWidget(parent), \
sequenceNumber(0x71821680),
- currentTime(0), totalTime(0), seekable(false), currentAudioChannel(-1),
- currentSubtitle(-1), titleCount(0), currentTitle(0), chapterCount(0), \
currentChapter(0),
- angleCount(0), currentAngle(0), videoSize(0)
-{
- setAttribute(Qt::WA_NativeWindow);
- setAttribute(Qt::WA_PaintOnScreen);
-
- QPalette palette = QWidget::palette();
- palette.setColor(backgroundRole(), Qt::black);
- setPalette(palette);
- setAutoFillBackground(true);
-
- process = new XineProcess(this);
- childProcess = process->getChildProcess();
- childProcess->init(winId());
- hide();
-}
-
-XineMediaWidget::~XineMediaWidget()
-{
-}
-
-void XineMediaWidget::setMuted(bool muted)
-{
- childProcess->setMuted(muted);
-}
-
-void XineMediaWidget::setVolume(int volume)
-{
- childProcess->setVolume(volume);
-}
-
-void XineMediaWidget::setAspectRatio(MediaWidget::AspectRatio aspectRatio)
-{
- XineAspectRatio xineAspectRatio;
-
- switch (aspectRatio) {
- case MediaWidget::AspectRatioAuto:
- xineAspectRatio = XineAspectRatioAuto;
- break;
- case MediaWidget::AspectRatio4_3:
- xineAspectRatio = XineAspectRatio4_3;
- break;
- case MediaWidget::AspectRatio16_9:
- xineAspectRatio = XineAspectRatio16_9;
- break;
- case MediaWidget::AspectRatioWidget:
- xineAspectRatio = XineAspectRatioWidget;
- break;
- default:
- Log("XineMediaWidget::setAspectRatio: unknown aspect ratio") << aspectRatio;
- return;
- }
-
- childProcess->setAspectRatio(xineAspectRatio);
-}
-
-void XineMediaWidget::setDeinterlacing(bool deinterlacing)
-{
- childProcess->setDeinterlacing(deinterlacing);
-}
-
-void XineMediaWidget::playUrl(const KUrl &url, const KUrl &subtitleUrl)
-{
- if (url.toLocalFile().endsWith(QLatin1String(".iso"), Qt::CaseInsensitive)) {
- currentUrl = QByteArray("dvd://").append(url.encodedPath());
- playEncodedUrl(currentUrl, PlayingDvd);
- } else {
- currentUrl = url.toEncoded();
- QByteArray encodedUrl = currentUrl;
-
- if (subtitleUrl.isValid()) {
- encodedUrl.append("#subtitle:");
- encodedUrl.append(subtitleUrl.encodedPath());
- }
-
- playEncodedUrl(encodedUrl, EmitPlaybackFinished);
- }
-}
-
-void XineMediaWidget::playAudioCd(const QString &device)
-{
- currentUrl = QByteArray("cdda://").append(device.toUtf8().toPercentEncoding("/"));
- playEncodedUrl(currentUrl);
-}
-
-void XineMediaWidget::playVideoCd(const QString &device)
-{
- currentUrl = QByteArray("vcd://").append(device.toUtf8().toPercentEncoding("/"));
- playEncodedUrl(currentUrl);
-}
-
-void XineMediaWidget::playDvd(const QString &device)
-{
- currentUrl = QByteArray("dvd://").append(device.toUtf8().toPercentEncoding("/"));
- playEncodedUrl(currentUrl, PlayingDvd);
-}
-
-void XineMediaWidget::setExternalSubtitle(const KUrl &subtitleUrl)
-{
- QByteArray encodedUrl = currentUrl;
- int position = currentTime;
- int audioChannel = currentAudioChannel;
-
- if (subtitleUrl.isValid()) {
- encodedUrl.append("#subtitle:");
- encodedUrl.append(subtitleUrl.encodedPath());
- }
-
- playEncodedUrl(encodedUrl, EmitPlaybackFinished);
- seek(position);
- setCurrentAudioChannel(audioChannel);
-}
-
-void XineMediaWidget::stop()
-{
- currentUrl.clear();
- playEncodedUrl(QByteArray());
-}
-
-bool XineMediaWidget::isPlaying() const
-{
- return ((currentState & Playing) != 0);
-}
-
-bool XineMediaWidget::isSeekable() const
-{
- return seekable;
-}
-
-int XineMediaWidget::getCurrentTime() const
-{
- return currentTime;
-}
-
-int XineMediaWidget::getTotalTime() const
-{
- return totalTime;
-}
-
-QStringList XineMediaWidget::getAudioChannels() const
-{
- return audioChannels;
-}
-
-QStringList XineMediaWidget::getSubtitles() const
-{
- return subtitles;
-}
-
-int XineMediaWidget::getCurrentAudioChannel() const
-{
- return currentAudioChannel;
-}
-
-int XineMediaWidget::getCurrentSubtitle() const
-{
- return currentSubtitle;
-}
-
-void XineMediaWidget::setPaused(bool paused)
-{
- childProcess->setPaused(paused);
-}
-
-void XineMediaWidget::setCurrentAudioChannel(int currentAudioChannel_)
-{
- childProcess->setCurrentAudioChannel(currentAudioChannel_);
-}
-
-void XineMediaWidget::setCurrentSubtitle(int currentSubtitle_)
-{
- childProcess->setCurrentSubtitle(currentSubtitle_);
-}
-
-void XineMediaWidget::toggleMenu()
-{
- childProcess->toggleMenu();
-}
-
-void XineMediaWidget::setCurrentTitle(int currentTitle_)
-{
- if (currentUrl.startsWith("cdda:") || currentUrl.startsWith("dvd:")) {
- QByteArray encodedUrl = currentUrl;
-
- if (!encodedUrl.endsWith('/')) {
- encodedUrl.append('/');
- }
-
- encodedUrl.append(QByteArray::number(currentTitle_));
-
- if (currentUrl.startsWith("dvd:")) {
- playEncodedUrl(encodedUrl, PlayingDvd);
- } else {
- playEncodedUrl(encodedUrl);
- }
- } else if (currentUrl.startsWith("vcd:")) {
- playEncodedUrl(currentUrl + '@' + QByteArray::number(currentTitle_));
- }
-}
-
-void XineMediaWidget::setCurrentChapter(int currentChapter_)
-{
- if ((currentState & PlayingDvd) != 0) {
- if (!encodedDvdUrl.endsWith('/')) {
- encodedDvdUrl.append('/');
- }
-
- QByteArray encodedUrl = encodedDvdUrl;
- encodedUrl.append(QByteArray::number(currentTitle));
- encodedUrl.append('.');
- encodedUrl.append(QByteArray::number(currentChapter_));
- playEncodedUrl(encodedUrl, PlayingDvd);
- }
-}
-
-void XineMediaWidget::setCurrentAngle(int currentAngle_)
-{
- Q_UNUSED(currentAngle_) // not possible :-(
-}
-
-bool XineMediaWidget::playPreviousTitle()
-{
- if (currentTitle > 1) {
- setCurrentTitle(currentTitle - 1);
- return true;
- }
-
- return false;
-}
-
-bool XineMediaWidget::playNextTitle()
-{
- if (currentTitle < titleCount) {
- setCurrentTitle(currentTitle + 1);
- return true;
- }
-
- return false;
-}
-
-void XineMediaWidget::seek(int time)
-{
- if (isPlaying() && (time != currentTime)) {
- childProcess->seek(time);
- }
-}
-
-void XineMediaWidget::mouseMoveEvent(QMouseEvent *event)
-{
- QWidget::mouseMoveEvent(event);
- childProcess->mouseMoved(event->x(), event->y());
-}
-
-void XineMediaWidget::mousePressEvent(QMouseEvent *event)
-{
- QWidget::mousePressEvent(event);
-
- if (event->button() == Qt::LeftButton) {
- childProcess->mousePressed(event->x(), event->y());
- }
-}
-
-void XineMediaWidget::paintEvent(QPaintEvent *event)
-{
- QWidget::paintEvent(event);
- childProcess->repaint();
-}
-
-void XineMediaWidget::resizeEvent(QResizeEvent *event)
-{
- QWidget::resizeEvent(event);
- childProcess->resize(event->size().width(), event->size().height());
-}
-
-QSize XineMediaWidget::sizeHint() const
-{
- return QSize(videoSize >> 16, videoSize & 0xffff);
-}
-
-void XineMediaWidget::initFailed(const QString &errorMessage)
-{
- if ((currentState & NotReady) == 0) {
- currentUrl.clear();
- playEncodedUrl(QByteArray(), NotReady);
- KMessageBox::queuedMessageBox(this, KMessageBox::Sorry, errorMessage); // FIXME
- }
-}
-
-void XineMediaWidget::sync(unsigned int sequenceNumber_)
-{
- if ((sequenceNumber == sequenceNumber_) && isPlaying()) {
- currentState |= Synchronized;
- }
-}
-
-void XineMediaWidget::playbackFailed(const QString &errorMessage)
-{
- if ((currentState & Synchronized) != 0) {
- if ((currentState & PlayingDvd) != 0) {
- dirtyFlags |= PlayingDvdChanged;
- }
-
- currentState = 0;
- dirtyFlags |= (ResetState | PlaybackStopped | PlaybackChanged);
- stateChanged();
- KMessageBox::queuedMessageBox(this, KMessageBox::Sorry, errorMessage); // FIXME
- }
-}
-
-void XineMediaWidget::playbackFinishedInternal()
-{
- if ((currentState & Synchronized) != 0) {
- if (currentUrl.startsWith("cdda") && (currentTitle < titleCount)) {
- playNextTitle();
- return;
- }
-
- if ((currentState & PlayingDvd) != 0) {
- dirtyFlags |= PlayingDvdChanged;
- }
-
- if ((currentState & EmitPlaybackFinished) != 0) {
- dirtyFlags |= PlaybackFinished;
- } else {
- dirtyFlags |= PlaybackStopped;
- }
-
- currentState = 0;
- dirtyFlags |= (ResetState | PlaybackChanged);
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateCurrentTotalTime(int currentTime_, int totalTime_)
-{
- if ((currentState & Synchronized) != 0) {
- if (currentTime_ < 0) {
- currentTime_ = 0;
- }
-
- if (currentTime != currentTime_) {
- currentTime = currentTime_;
- dirtyFlags |= CurrentTimeChanged;
- }
-
- if (totalTime_ < currentTime) {
- totalTime_ = currentTime;
- }
-
- if (totalTime != totalTime_) {
- totalTime = totalTime_;
- dirtyFlags |= TotalTimeChanged;
- }
-
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateMetadata(const QString &metadata_)
-{
- if (((currentState & Synchronized) != 0) && (rawMetadata != metadata_)) {
- rawMetadata = metadata_;
- metadata.clear();
-
- for (int i = 0; i < rawMetadata.size(); ++i) {
- int type = rawMetadata.at(i).unicode();
- ++i;
- int end = i;
-
- while ((end < rawMetadata.size()) && (rawMetadata.at(end) != '\0')) {
- ++end;
- }
-
- if (i == end) {
- continue;
- }
-
- QString content = rawMetadata.mid(i, end - i);
- i = end;
-
- switch (type) {
- case XineMetadataTitle:
- metadata.insert(MediaWidget::Title, content);
- break;
- case XineMetadataArtist:
- metadata.insert(MediaWidget::Artist, content);
- break;
- case XineMetadataAlbum:
- metadata.insert(MediaWidget::Album, content);
- break;
- case XineMetadataTrackNumber:
- metadata.insert(MediaWidget::TrackNumber, content);
- break;
- default:
- Log("XineMediaWidget::updateMetadata: unknown metadata type") <<
- type;
- break;
- }
- }
-
- dirtyFlags |= MetadataChanged;
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateSeekable(bool seekable_)
-{
- if (((currentState & Synchronized) != 0) && (seekable != seekable_)) {
- seekable = seekable_;
- dirtyFlags |= SeekableChanged;
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateAudioChannels(const QByteArray &audioChannels_,
- int currentAudioChannel_)
-{
- if ((currentState & Synchronized) != 0) {
- if (rawAudioChannels != audioChannels_) {
- rawAudioChannels = audioChannels_;
- audioChannels.clear();
- const char *rawData = rawAudioChannels.constData();
-
- for (int i = 0; i < rawAudioChannels.size(); ++i) {
- QString audioChannel = QString::fromLatin1(rawData + i);
- i += audioChannel.size();
-
- if (audioChannel.isEmpty()) {
- audioChannel = QString::number(i + 1);
- }
-
- audioChannels.append(audioChannel);
- }
-
- dirtyFlags |= AudioChannelsChanged;
- }
-
- if ((currentAudioChannel_ < 0) || (currentAudioChannel_ >= audioChannels.size())) \
{
- currentAudioChannel_ = -1;
- }
-
- if (currentAudioChannel != currentAudioChannel_) {
- currentAudioChannel = currentAudioChannel_;
- dirtyFlags |= CurrentAudioChannelChanged;
- }
-
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateSubtitles(const QByteArray &subtitles_, int \
currentSubtitle_)
-{
- if ((currentState & Synchronized) != 0) {
- if (rawSubtitles != subtitles_) {
- rawSubtitles = subtitles_;
- subtitles.clear();
- const char *rawData = rawSubtitles.constData();
-
- for (int i = 0; i < rawSubtitles.size(); ++i) {
- QString subtitle = QString::fromLatin1(rawData + i);
- i += subtitle.size();
-
- if (subtitle.isEmpty()) {
- subtitle = QString::number(i + 1);
- }
-
- subtitles.append(subtitle);
- }
-
- dirtyFlags |= SubtitlesChanged;
- }
-
- if ((currentSubtitle_ < 0) || (currentSubtitle_ >= subtitles.size())) {
- currentSubtitle_ = -1;
- }
-
- if (currentSubtitle != currentSubtitle_) {
- currentSubtitle = currentSubtitle_;
- dirtyFlags |= CurrentSubtitleChanged;
- }
-
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateTitles(int titleCount_, int currentTitle_)
-{
- if ((currentState & Synchronized) != 0) {
- if (titleCount_ < 0) {
- titleCount_ = 0;
- }
-
- if (titleCount != titleCount_) {
- titleCount = titleCount_;
- dirtyFlags |= TitleCountChanged;
- }
-
- if ((currentTitle_ < 0) || (currentTitle_ > titleCount)) {
- currentTitle_ = 0;
- }
-
- if (currentTitle != currentTitle_) {
- currentTitle = currentTitle_;
- dirtyFlags |= CurrentTitleChanged;
- }
-
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateChapters(int chapterCount_, int currentChapter_)
-{
- if ((currentState & Synchronized) != 0) {
- if (chapterCount_ < 0) {
- chapterCount_ = 0;
- }
-
- if (chapterCount != chapterCount_) {
- chapterCount = chapterCount_;
- dirtyFlags |= ChapterCountChanged;
- }
-
- if ((currentChapter_ < 0) || (currentChapter_ > chapterCount)) {
- currentChapter_ = 0;
- }
-
- if (currentChapter != currentChapter_) {
- currentChapter = currentChapter_;
- dirtyFlags |= CurrentChapterChanged;
- }
-
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateAngles(int angleCount_, int currentAngle_)
-{
- if ((currentState & Synchronized) != 0) {
- if (angleCount_ < 0) {
- angleCount_ = 0;
- }
-
- if (angleCount != angleCount_) {
- angleCount = angleCount_;
- dirtyFlags |= AngleCountChanged;
- }
-
- if ((currentAngle_ < 0) || (currentAngle_ > angleCount)) {
- currentAngle_ = 0;
- }
-
- if (currentAngle != currentAngle_) {
- currentAngle = currentAngle_;
- dirtyFlags |= CurrentAngleChanged;
- }
-
- stateChanged();
- }
-}
-
-void XineMediaWidget::updateMouseTracking(bool mouseTrackingEnabled)
-{
- if ((currentState & Synchronized) != 0) {
- if (mouseTrackingEnabled) {
- setMouseTracking(true);
- } else {
- unsetCursor();
- setMouseTracking(false);
- }
- }
-}
-
-void XineMediaWidget::updateMouseCursor(bool pointingMouseCursor)
-{
- if ((currentState & Synchronized) != 0) {
- if (pointingMouseCursor && hasMouseTracking()) {
- setCursor(Qt::PointingHandCursor);
- } else {
- unsetCursor();
- }
- }
-}
-
-void XineMediaWidget::updateVideoSize(unsigned int videoSize_)
-{
- if (((currentState & Synchronized) != 0) && (videoSize != videoSize_)) {
- videoSize = videoSize_;
- dirtyFlags |= VideoSizeChanged;
- stateChanged();
- }
-}
-
-void XineMediaWidget::playEncodedUrl(const QByteArray &encodedUrl, StateFlags \
stateFlags)
-{
- ++sequenceNumber;
- childProcess->playUrl(sequenceNumber, encodedUrl);
-
- if (!encodedUrl.isEmpty() && ((currentState & NotReady) == 0)) {
- stateFlags |= Playing;
- dirtyFlags |= (SourceChanged | ResetState);
- } else {
- stateFlags = ((currentState | stateFlags) & NotReady);
- dirtyFlags |= (PlaybackStopped | ResetState);
- }
-
- StateFlags difference = currentState ^ stateFlags;
- currentState = stateFlags;
-
- if ((difference & Playing) != 0) {
- dirtyFlags |= PlaybackChanged;
- }
-
- if ((difference & PlayingDvd) != 0) {
- dirtyFlags |= PlayingDvdChanged;
- }
-
- stateChanged();
-}
-
-void XineMediaWidget::stateChanged()
-{
- while (dirtyFlags != 0) {
- int lowestDirtyFlag = dirtyFlags & (~(dirtyFlags - 1));
- dirtyFlags &= ~lowestDirtyFlag;
-
- switch (lowestDirtyFlag) {
- case ResetState:
- if (currentTime != 0) {
- currentTime = 0;
- dirtyFlags |= CurrentTimeChanged;
- }
-
- if (totalTime != 0) {
- totalTime = 0;
- dirtyFlags |= TotalTimeChanged;
- }
-
- if (!metadata.isEmpty()) {
- rawMetadata.clear();
- metadata.clear();
- dirtyFlags |= MetadataChanged;
- }
-
- if (seekable != isPlaying()) {
- seekable = isPlaying();
- dirtyFlags |= SeekableChanged;
- }
-
- if (!audioChannels.isEmpty()) {
- rawAudioChannels.clear();
- audioChannels.clear();
- dirtyFlags |= AudioChannelsChanged;
- }
-
- if (currentAudioChannel != -1) {
- currentAudioChannel = -1;
- dirtyFlags |= CurrentAudioChannelChanged;
- }
-
- if (!subtitles.isEmpty()) {
- rawSubtitles.clear();
- subtitles.clear();
- dirtyFlags |= SubtitlesChanged;
- }
-
- if (currentSubtitle != -1) {
- currentSubtitle = -1;
- dirtyFlags |= CurrentSubtitleChanged;
- }
-
- if ((currentState & PlayingDvd) == 0) {
- encodedDvdUrl.clear();
- }
-
- if (titleCount != 0) {
- titleCount = 0;
- dirtyFlags |= TitleCountChanged;
- }
-
- if (currentTitle != 0) {
- currentTitle = 0;
- dirtyFlags |= CurrentTitleChanged;
- }
-
- if (chapterCount != 0) {
- chapterCount = 0;
- dirtyFlags |= ChapterCountChanged;
- }
-
- if (currentChapter != 0) {
- currentChapter = 0;
- dirtyFlags |= CurrentChapterChanged;
- }
-
- if (angleCount != 0) {
- angleCount = 0;
- dirtyFlags |= AngleCountChanged;
- }
-
- if (currentAngle != 0) {
- currentAngle = 0;
- dirtyFlags |= CurrentAngleChanged;
- }
-
- unsetCursor();
- setMouseTracking(false);
- break;
- case SourceChanged:
- emit sourceChanged();
- break;
- case PlaybackFinished:
- emit playbackFinished();
- break;
- case PlaybackStopped:
- emit playbackStopped();
- break;
- case PlaybackChanged:
- if (isPlaying()) {
- show();
- emit playbackChanged(true);
- } else {
- hide();
- parentWidget()->update();
- emit playbackChanged(false);
- }
-
- break;
- case TotalTimeChanged:
- emit totalTimeChanged(totalTime);
- break;
- case CurrentTimeChanged:
- emit currentTimeChanged(currentTime);
- break;
- case MetadataChanged:
- emit metadataChanged(metadata);
- break;
- case SeekableChanged:
- emit seekableChanged(seekable);
- break;
- case AudioChannelsChanged:
- emit audioChannelsChanged(audioChannels, currentAudioChannel);
- dirtyFlags &= ~CurrentAudioChannelChanged;
- break;
- case CurrentAudioChannelChanged:
- emit currentAudioChannelChanged(currentAudioChannel);
- break;
- case SubtitlesChanged:
- emit subtitlesChanged(subtitles, currentSubtitle);
- dirtyFlags &= ~CurrentSubtitleChanged;
- break;
- case CurrentSubtitleChanged:
- emit currentSubtitleChanged(currentSubtitle);
- break;
- case PlayingDvdChanged:
- emit dvdPlaybackChanged((currentState & PlayingDvd) != 0);
- break;
- case TitleCountChanged:
- emit titlesChanged(titleCount, currentTitle);
- dirtyFlags &= ~CurrentTitleChanged;
- break;
- case CurrentTitleChanged:
- emit currentTitleChanged(currentTitle);
- break;
- case ChapterCountChanged:
- emit chaptersChanged(chapterCount, currentChapter);
- dirtyFlags &= ~CurrentChapterChanged;
- break;
- case CurrentChapterChanged:
- emit currentChapterChanged(currentChapter);
- break;
- case AngleCountChanged:
- emit anglesChanged(angleCount, currentAngle);
- dirtyFlags &= ~CurrentAngleChanged;
- break;
- case CurrentAngleChanged:
- emit currentAngleChanged(currentAngle);
- break;
- case VideoSizeChanged:
- updateGeometry();
- emit videoSizeChanged();
- break;
- default:
- Log("XineMediaWidget::stateChanged: unknown flag") << lowestDirtyFlag;
- break;
- }
- }
-}
diff --git a/src/backend-xine/xinemediawidget.h b/src/backend-xine/xinemediawidget.h
deleted file mode 100644
index d7423f2..0000000
--- a/src/backend-xine/xinemediawidget.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * xinemediawidget.h
- *
- * Copyright (C) 2010-2011 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
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef XINEMEDIAWIDGET_H
-#define XINEMEDIAWIDGET_H
-
-#include "../mediawidget.h"
-
-class XineChildMarshaller;
-class XineProcess;
-
-class XineMediaWidget : public QWidget
-{
- friend class XineProcess;
- Q_OBJECT
-public:
- explicit XineMediaWidget(QWidget *parent);
- ~XineMediaWidget();
-
- void setMuted(bool muted);
- void setVolume(int volume); // [0 - 100]
- void setAspectRatio(MediaWidget::AspectRatio aspectRatio);
- void setDeinterlacing(bool deinterlacing);
-
- void playUrl(const KUrl &url, const KUrl &subtitleUrl);
- void playAudioCd(const QString &device);
- void playVideoCd(const QString &device);
- void playDvd(const QString &device);
- void setExternalSubtitle(const KUrl &subtitleUrl);
- void stop();
-
- bool isPlaying() const;
- bool isSeekable() const;
- int getCurrentTime() const; // milliseconds
- int getTotalTime() const; // milliseconds
- QStringList getAudioChannels() const;
- QStringList getSubtitles() const;
- int getCurrentAudioChannel() const; // first audio channel = 0
- int getCurrentSubtitle() const; // first subtitle = 0
-
- void setPaused(bool paused);
- void setCurrentAudioChannel(int currentAudioChannel_);
- void setCurrentSubtitle(int currentSubtitle_);
- void toggleMenu();
- void setCurrentTitle(int currentTitle_); // first title = 1
- void setCurrentChapter(int currentChapter_); // first chapter = 1
- void setCurrentAngle(int currentAngle_); // first angle = 1
- bool playPreviousTitle();
- bool playNextTitle();
-
-public slots:
- void seek(int time);
-
-signals:
- void sourceChanged();
- void playbackFinished();
- void playbackStopped();
- void playbackChanged(bool playing);
- void totalTimeChanged(int totalTime);
- void currentTimeChanged(int currentTime);
- void metadataChanged(const QMap<MediaWidget::MetadataType, QString> &metadata);
- void seekableChanged(bool seekable);
- void audioChannelsChanged(const QStringList &audioChannels, int \
currentAudioChannel);
- void currentAudioChannelChanged(int currentAudioChannel);
- void subtitlesChanged(const QStringList &subtitles, int currentSubtitle);
- void currentSubtitleChanged(int currentSubtitle);
- void dvdPlaybackChanged(bool playingDvd);
- void titlesChanged(int titleCount, int currentTitle);
- void currentTitleChanged(int currentTitle);
- void chaptersChanged(int chapterCount, int currentChapter);
- void currentChapterChanged(int currentChapter);
- void anglesChanged(int angleCount, int currentAngle);
- void currentAngleChanged(int currentAngle);
- void videoSizeChanged();
-
-public:
- enum StateFlag {
- NotReady = (1 << 0),
- Playing = (1 << 1),
- PlayingDvd = (1 << 2),
- EmitPlaybackFinished = (1 << 3),
- Synchronized = (1 << 4)
- };
-
- Q_DECLARE_FLAGS(StateFlags, StateFlag)
-
- enum DirtyFlag {
- ResetState = (1 << 0),
- SourceChanged = (1 << 1),
- PlaybackFinished = (1 << 2),
- PlaybackStopped = (1 << 3),
- PlaybackChanged = (1 << 4),
- TotalTimeChanged = (1 << 5),
- CurrentTimeChanged = (1 << 6),
- MetadataChanged = (1 << 7),
- SeekableChanged = (1 << 8),
- AudioChannelsChanged = (1 << 9),
- CurrentAudioChannelChanged = (1 << 10),
- SubtitlesChanged = (1 << 11),
- CurrentSubtitleChanged = (1 << 12),
- PlayingDvdChanged = (1 << 13),
- TitleCountChanged = (1 << 14),
- CurrentTitleChanged = (1 << 15),
- ChapterCountChanged = (1 << 16),
- CurrentChapterChanged = (1 << 17),
- AngleCountChanged = (1 << 18),
- CurrentAngleChanged = (1 << 19),
- VideoSizeChanged = (1 << 20)
- };
-
- Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
-
-private:
- void mouseMoveEvent(QMouseEvent *event);
- void mousePressEvent(QMouseEvent *event);
- void paintEvent(QPaintEvent *event);
- void resizeEvent(QResizeEvent *event);
- QSize sizeHint() const;
-
- void initFailed(const QString &errorMessage);
- void sync(unsigned int sequenceNumber_);
- void playbackFailed(const QString &errorMessage);
- void playbackFinishedInternal();
- void updateCurrentTotalTime(int currentTime_, int totalTime_);
- void updateMetadata(const QString &metadata_);
- void updateSeekable(bool seekable_);
- void updateAudioChannels(const QByteArray &audioChannels_, int \
currentAudioChannel_);
- void updateSubtitles(const QByteArray &subtitles_, int currentSubtitle_);
- void updateTitles(int titleCount_, int currentTitle_);
- void updateChapters(int chapterCount_, int currentChapter_);
- void updateAngles(int angleCount_, int currentAngle_);
- void updateMouseTracking(bool mouseTrackingEnabled);
- void updateMouseCursor(bool pointingMouseCursor);
- void updateVideoSize(unsigned int videoSize_);
-
- void playEncodedUrl(const QByteArray &encodedUrl, StateFlags stateFlags = 0);
- void stateChanged();
-
- XineProcess *process;
- XineChildMarshaller *childProcess;
- StateFlags currentState;
- DirtyFlags dirtyFlags;
- QByteArray currentUrl;
- unsigned int sequenceNumber;
- int currentTime;
- int totalTime;
- QString rawMetadata;
- QMap<MediaWidget::MetadataType, QString> metadata;
- bool seekable;
- QByteArray rawAudioChannels;
- QStringList audioChannels;
- int currentAudioChannel;
- QByteArray rawSubtitles;
- QStringList subtitles;
- int currentSubtitle;
- QByteArray encodedDvdUrl;
- int titleCount;
- int currentTitle;
- int chapterCount;
- int currentChapter;
- int angleCount;
- int currentAngle;
- unsigned int videoSize;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(XineMediaWidget::StateFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(XineMediaWidget::DirtyFlags)
-
-#endif /* XINEMEDIAWIDGET_H */
diff --git a/src/backend-xine/xinemediawidget_p.h \
b/src/backend-xine/xinemediawidget_p.h deleted file mode 100644
index 5512779..0000000
--- a/src/backend-xine/xinemediawidget_p.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * xinemediawidget_p.h
- *
- * Copyright (C) 2010-2011 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
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef XINEMEDIAWIDGET_P_H
-#define XINEMEDIAWIDGET_P_H
-
-#include <QProcess>
-#include "xinecommands.h"
-
-class XineMediaWidget;
-
-class XineProcess : public QProcess
-{
- Q_OBJECT
-public:
- explicit XineProcess(XineMediaWidget *parent_);
- ~XineProcess();
-
- XineChildMarshaller *getChildProcess()
- {
- return &childProcess;
- }
-
-private slots:
- void readyRead();
-
-private:
- void setupChildProcess();
-
- XineMediaWidget *parent;
- int pipeToChild[2];
- int pipeFromChild[2];
- XinePipeReader *reader;
- XinePipeWriterBase *writer;
- XineChildMarshaller childProcess;
-};
-
-#endif /* XINEMEDIAWIDGET_P_H */
diff --git a/src/dbusobjects.cpp b/src/dbusobjects.cpp
index d6643b4..ba46b80 100644
--- a/src/dbusobjects.cpp
+++ b/src/dbusobjects.cpp
@@ -153,13 +153,18 @@ void MprisPlayerObject::Repeat(bool repeat)
MprisStatusStruct MprisPlayerObject::GetStatus()
{
MprisStatusStruct statusStruct;
+ statusStruct.state = 0;
- if (mediaWidget->isPaused()) {
- statusStruct.state = 1;
- } else if (mediaWidget->isPlaying()) {
- statusStruct.state = 0;
- } else {
+ switch (mediaWidget->getPlaybackStatus()) {
+ case MediaWidget::Idle:
statusStruct.state = 2;
+ break;
+ case MediaWidget::Playing:
+ statusStruct.state = 0;
+ break;
+ case MediaWidget::Paused:
+ statusStruct.state = 1;
+ break;
}
if (playlistTab->getRandom()) {
@@ -192,8 +197,13 @@ int MprisPlayerObject::GetCaps()
(1 << 4) | // CAN_SEEK // FIXME check availability
(1 << 6); // CAN_HAS_TRACKLIST
- if (mediaWidget->isPlaying()) {
+ switch (mediaWidget->getPlaybackStatus()) {
+ case MediaWidget::Idle:
+ break;
+ case MediaWidget::Playing:
+ case MediaWidget::Paused:
capabilities |= (1 << 2); // CAN_PAUSE
+ break;
}
return capabilities; // FIXME metadata handling not implemented yet
diff --git a/src/dbusobjects.h b/src/dbusobjects.h
index 1745e23..797ae3d 100644
--- a/src/dbusobjects.h
+++ b/src/dbusobjects.h
@@ -130,6 +130,10 @@ private:
PlaylistTab *playlistTab;
};
+#ifndef HAVE_DVB
+#error HAVE_DVB must be defined
+#endif /* HAVE_DVB */
+
#if HAVE_DVB == 1
class DBusTelevisionObject : public QObject
diff --git a/src/dvb/dvbliveview.cpp b/src/dvb/dvbliveview.cpp
index 3bec59e..5a63789 100644
--- a/src/dvb/dvbliveview.cpp
+++ b/src/dvb/dvbliveview.cpp
@@ -24,8 +24,15 @@
#include <QDir>
#include <QPainter>
#include <QSet>
+#include <QSocketNotifier>
#include <KLocale>
#include <KMessageBox>
+#include <KStandardDirs>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h> // bsd compatibility
+#include <sys/types.h> // bsd compatibility
+#include <unistd.h>
#include "../log.h"
#include "../mediawidget.h"
#include "dvbdevice.h"
@@ -127,24 +134,6 @@ QPixmap DvbOsd::paintOsd(QRect &rect, const QFont &font, \
Qt::LayoutDirection) return pixmap;
}
-void DvbLiveViewInternal::processData(const char data[188])
-{
- buffer.append(data, 188);
-
- if (buffer.size() < (87 * 188)) {
- return;
- }
-
- if (!timeShiftFile.isOpen()) {
- mediaWidget->writeDvbData(buffer);
- } else {
- timeShiftFile.write(buffer); // FIXME avoid buffer reallocation
- }
-
- buffer.clear();
- buffer.reserve(87 * 188);
-}
-
DvbLiveView::DvbLiveView(DvbManager *manager_, QObject *parent) : QObject(parent),
manager(manager_), device(NULL), videoPid(-1), audioPid(-1), subtitlePid(-1)
{
@@ -159,11 +148,11 @@ DvbLiveView::DvbLiveView(DvbManager *manager_, QObject *parent) \
: QObject(parent connect(&patPmtTimer, SIGNAL(timeout()), this, \
SLOT(insertPatPmt())); connect(&osdTimer, SIGNAL(timeout()), this, \
SLOT(osdTimeout()));
- connect(mediaWidget, SIGNAL(changeDvbAudioChannel(int)),
+ connect(mediaWidget, SIGNAL(dvbSetCurrentAudioChannel(int)),
this, SLOT(changeAudioStream(int)));
- connect(mediaWidget, SIGNAL(changeDvbSubtitle(int)), this, \
SLOT(changeSubtitle(int)));
- connect(mediaWidget, SIGNAL(prepareDvbTimeShift()), this, \
SLOT(prepareTimeShift()));
- connect(mediaWidget, SIGNAL(startDvbTimeShift()), this, SLOT(startTimeShift()));
+ connect(mediaWidget, SIGNAL(dvbSetCurrentSubtitle(int)), this, \
SLOT(changeSubtitle(int))); + connect(mediaWidget, SIGNAL(dvbPrepareTimeShift()), \
this, SLOT(prepareTimeShift())); + connect(mediaWidget, SIGNAL(dvbStartTimeShift()), \
this, SLOT(startTimeShift())); connect(mediaWidget, SIGNAL(dvbStopped()), this, \
SLOT(liveStopped())); }
@@ -216,7 +205,8 @@ void DvbLiveView::playChannel(const DvbSharedChannel &channel_)
return;
}
- mediaWidget->playDvb(channel->name);
+ internal->channelName = channel->name;
+ mediaWidget->playDvb(MediaWidget::Dvb, internal->setupPipe(), channel->name);
internal->pmtFilter.setProgramNumber(channel->serviceId);
startDevice();
@@ -416,7 +406,8 @@ void DvbLiveView::prepareTimeShift()
void DvbLiveView::startTimeShift()
{
- mediaWidget->play(internal->timeShiftFile.fileName());
+ mediaWidget->playDvb(MediaWidget::DvbTimeShift, internal->timeShiftFile.fileName(),
+ internal->channelName);
}
void DvbLiveView::showOsd()
@@ -544,3 +535,113 @@ void DvbLiveView::updatePids(bool forcePatPmtUpdate)
insertPatPmt();
}
}
+
+DvbLiveViewInternal::DvbLiveViewInternal() : mediaWidget(NULL), readFd(-1), \
writeFd(-1) +{
+ QString fileName = KStandardDirs::locateLocal("appdata", "dvbpipe.m2t");
+ QFile::remove(fileName);
+ url = KUrl::fromLocalFile(fileName);
+ url.setScheme("fifo");
+
+ if (mkfifo(QFile::encodeName(fileName).constData(), 0600) != 0) {
+ Log("timeShiftActive: mkfifo failed");
+ return;
+ }
+
+ readFd = open(QFile::encodeName(fileName).constData(), O_RDONLY | O_NONBLOCK);
+
+ if (readFd < 0) {
+ Log("timeShiftActive: open failed");
+ return;
+ }
+
+ writeFd = open(QFile::encodeName(fileName).constData(), O_WRONLY | O_NONBLOCK);
+
+ if (writeFd < 0) {
+ Log("timeShiftActive: open failed");
+ return;
+ }
+
+ notifier = new QSocketNotifier(writeFd, QSocketNotifier::Write, this);
+ notifier->setEnabled(false);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(writeToPipe()));
+}
+
+DvbLiveViewInternal::~DvbLiveViewInternal()
+{
+ if (writeFd >= 0) {
+ close(writeFd);
+ }
+
+ if (readFd >= 0) {
+ close(readFd);
+ }
+}
+
+KUrl DvbLiveViewInternal::setupPipe()
+{
+ if (!buffers.isEmpty()) {
+ buffer = buffers.at(0);
+ buffers.clear();
+ }
+
+ if (readFd >= 0) {
+ if (buffer.isEmpty()) {
+ buffer.resize(87 * 188);
+ }
+
+ while (read(readFd, buffer.data(), buffer.size()) != 0) {
+ }
+ }
+
+ buffer.clear();
+ return url;
+}
+
+void DvbLiveViewInternal::writeToPipe()
+{
+ while (!buffers.isEmpty()) {
+ const QByteArray &buffer = buffers.at(0);
+ int bytesWritten = write(writeFd, buffer.constData(), buffer.size());
+
+ if ((bytesWritten < 0) && (errno == EINTR)) {
+ continue;
+ }
+
+ if (bytesWritten == buffer.size()) {
+ buffers.removeFirst();
+ continue;
+ }
+
+ if (bytesWritten > 0) {
+ buffers.first().remove(0, bytesWritten);
+ }
+
+ break;
+ }
+
+ if (!buffers.isEmpty()) {
+ notifier->setEnabled(true);
+ }
+}
+
+void DvbLiveViewInternal::processData(const char data[188])
+{
+ buffer.append(data, 188);
+
+ if (buffer.size() < (87 * 188)) {
+ return;
+ }
+
+ if (!timeShiftFile.isOpen()) {
+ if (writeFd >= 0) {
+ buffers.append(buffer);
+ writeToPipe();
+ }
+ } else {
+ timeShiftFile.write(buffer); // FIXME avoid buffer reallocation
+ }
+
+ buffer.clear();
+ buffer.reserve(87 * 188);
+}
diff --git a/src/dvb/dvbliveview_p.h b/src/dvb/dvbliveview_p.h
index 9066b1c..0a52f76 100644
--- a/src/dvb/dvbliveview_p.h
+++ b/src/dvb/dvbliveview_p.h
@@ -22,10 +22,12 @@
#define DVBLIVEVIEW_P_H
#include <QFile>
+#include <KUrl>
#include "../osdwidget.h"
#include "dvbepg.h"
#include "dvbsi.h"
+class QSocketNotifier;
class MediaWidget;
class DvbOsd : public OsdObject
@@ -53,13 +55,17 @@ private:
DvbEpgEntry secondEntry;
};
-class DvbLiveViewInternal : public DvbPidFilter
+class DvbLiveViewInternal : public QObject, public DvbPidFilter
{
+ Q_OBJECT
public:
- DvbLiveViewInternal() : mediaWidget(NULL) { }
- ~DvbLiveViewInternal() { }
+ DvbLiveViewInternal();
+ ~DvbLiveViewInternal();
+
+ KUrl setupPipe();
MediaWidget *mediaWidget;
+ QString channelName;
DvbPmtFilter pmtFilter;
QByteArray pmtSectionData;
DvbSectionGenerator patGenerator;
@@ -68,8 +74,17 @@ public:
QFile timeShiftFile;
DvbOsd dvbOsd;
+private slots:
+ void writeToPipe();
+
private:
void processData(const char data[188]);
+
+ KUrl url;
+ int readFd;
+ int writeFd;
+ QSocketNotifier *notifier;
+ QList<QByteArray> buffers;
};
#endif /* DVBLIVEVIEW_P_H */
diff --git a/src/dvb/dvbtab.cpp b/src/dvb/dvbtab.cpp
index e07c318..0eb2ae6 100644
--- a/src/dvb/dvbtab.cpp
+++ b/src/dvb/dvbtab.cpp
@@ -119,8 +119,8 @@ DvbTab::DvbTab(KMenu *menu, KActionCollection *collection, \
MediaWidget *mediaWid connect(configureAction, SIGNAL(triggered()), this, \
SLOT(configureDvb())); menu->addAction(collection->addAction("settings_dvb", \
configureAction));
- connect(mediaWidget, SIGNAL(previousDvbChannel()), this, SLOT(previousChannel()));
- connect(mediaWidget, SIGNAL(nextDvbChannel()), this, SLOT(nextChannel()));
+ connect(mediaWidget, SIGNAL(dvbPreviousChannel()), this, SLOT(previousChannel()));
+ connect(mediaWidget, SIGNAL(dvbNextChannel()), this, SLOT(nextChannel()));
connect(manager->getRecordingModel(), SIGNAL(recordingRemoved(DvbSharedRecording)),
this, SLOT(recordingRemoved(DvbSharedRecording)));
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 43dd014..3e33456 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -253,7 +253,8 @@ MainWindow::MainWindow()
mediaWidget = new MediaWidget(playerMenu, controlBar, collection, widget);
connect(mediaWidget, SIGNAL(displayModeChanged()), this, \
SLOT(displayModeChanged())); connect(mediaWidget, SIGNAL(changeCaption(QString)), \
this, SLOT(setCaption(QString)));
- connect(mediaWidget, SIGNAL(resizeToVideo(int)), this, SLOT(resizeToVideo(int)));
+ connect(mediaWidget, SIGNAL(resizeToVideo(MediaWidget::ResizeFactor)),
+ this, SLOT(resizeToVideo(MediaWidget::ResizeFactor)));
// tabs - keep in sync with TabIndex enum!
@@ -590,14 +591,29 @@ void MainWindow::playDvb()
dvbTab->playLastChannel();
}
-void MainWindow::resizeToVideo(int factor)
+void MainWindow::resizeToVideo(MediaWidget::ResizeFactor resizeFactor)
{
if (!isFullScreen() && !mediaWidget->sizeHint().isEmpty()) {
if (isMaximized()) {
setWindowState(windowState() & ~Qt::WindowMaximized);
}
- resize(size() - centralWidget()->size() + factor * mediaWidget->sizeHint());
+ QSize videoSize;
+
+ switch (resizeFactor) {
+ case MediaWidget::ResizeOff:
+ break;
+ case MediaWidget::OriginalSize:
+ videoSize = mediaWidget->sizeHint();
+ break;
+ case MediaWidget::DoubleSize:
+ videoSize = (2 * mediaWidget->sizeHint());
+ break;
+ }
+
+ if (!videoSize.isEmpty()) {
+ resize(size() - centralWidget()->size() + videoSize);
+ }
}
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 87ccbd3..5bddb60 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -22,6 +22,7 @@
#define MAINWINDOW_H
#include <KMainWindow>
+#include "mediawidget.h"
class QStackedLayout;
class KActionCollection;
@@ -58,7 +59,7 @@ private slots:
void openDvd(const QString &device = QString());
void playDvdFolder();
void playDvb();
- void resizeToVideo(int factor);
+ void resizeToVideo(MediaWidget::ResizeFactor resizeFactor);
void configureKeys();
void configureKaffeine();
void navigationBarOrientationChanged(Qt::Orientation orientation);
diff --git a/src/mediawidget.cpp b/src/mediawidget.cpp
index f348a11..7a3bb43 100644
--- a/src/mediawidget.cpp
+++ b/src/mediawidget.cpp
@@ -24,10 +24,8 @@
#include <QBoxLayout>
#include <QContextMenuEvent>
#include <QDBusInterface>
-#include <QFile>
#include <QLabel>
#include <QPushButton>
-#include <QSocketNotifier>
#include <QTimeEdit>
#include <QTimer>
#include <QX11Info>
@@ -38,199 +36,46 @@
#include <KComboBox>
#include <KLocalizedString>
#include <KMenu>
-#include <KStandardDirs>
#include <KToolBar>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h> // bsd compatibility
-#include <sys/types.h> // bsd compatibility
-#include <unistd.h>
#include <X11/extensions/scrnsaver.h>
-#include "backend-xine/xinemediawidget.h"
+#include "backend-vlc/vlcmediawidget.h"
#include "configuration.h"
#include "log.h"
#include "osdwidget.h"
-DvbFeed::DvbFeed(QObject *parent) : QObject(parent), timeShiftPrepared(false),
- timeShiftActive(false), ignoreSourceChange(false), readFd(-1), writeFd(-1), \
notifier(NULL)
-{
- QString fileName = KStandardDirs::locateLocal("appdata", "dvbpipe.m2t");
- QFile::remove(fileName);
- url = KUrl::fromLocalFile(fileName);
- url.setScheme("fifo");
-
- if (mkfifo(QFile::encodeName(fileName).constData(), 0600) != 0) {
- Log("timeShiftActive: mkfifo failed");
- return;
- }
-
- readFd = open(QFile::encodeName(fileName).constData(), O_RDONLY | O_NONBLOCK);
-
- if (readFd < 0) {
- Log("timeShiftActive: open failed");
- return;
- }
-
- writeFd = open(QFile::encodeName(fileName).constData(), O_WRONLY | O_NONBLOCK);
-
- if (writeFd < 0) {
- Log("timeShiftActive: open failed");
- close(readFd);
- readFd = -1;
- }
-
- notifier = new QSocketNotifier(writeFd, QSocketNotifier::Write, this);
- notifier->setEnabled(false);
- connect(notifier, SIGNAL(activated(int)), this, SLOT(readyWrite()));
-}
-
-DvbFeed::~DvbFeed()
-{
- endOfData();
-}
-
-KUrl DvbFeed::getUrl() const
-{
- return url;
-}
-
-void DvbFeed::writeData(const QByteArray &data)
-{
- if (writeFd >= 0) {
- buffers.append(data);
-
- if (!flush()) {
- notifier->setEnabled(true);
- }
- }
-}
-
-void DvbFeed::endOfData()
-{
- if (writeFd >= 0) {
- notifier->setEnabled(false);
- close(writeFd);
- writeFd = -1;
- }
-
- if (readFd >= 0) {
- close(readFd);
- readFd = -1;
- }
-}
-
-void DvbFeed::readyWrite()
-{
- if (flush()) {
- notifier->setEnabled(false);
- }
-}
-
-bool DvbFeed::flush()
-{
- while (!buffers.isEmpty()) {
- const QByteArray &buffer = *buffers.constBegin();
- int bytesWritten = write(writeFd, buffer.constData(), buffer.size());
-
- if ((bytesWritten < 0) && (errno == EINTR)) {
- continue;
- }
-
- if (bytesWritten == buffer.size()) {
- buffers.removeFirst();
- continue;
- }
-
- if (bytesWritten > 0) {
- buffers.first().remove(0, bytesWritten);
- }
-
- break;
- }
-
- return buffers.isEmpty();
-}
-
-JumpToPositionDialog::JumpToPositionDialog(MediaWidget *mediaWidget_) : \
KDialog(mediaWidget_),
- mediaWidget(mediaWidget_)
-{
- setCaption(i18nc("@title:window", "Jump to Position"));
-
- QWidget *widget = new QWidget(this);
- QBoxLayout *layout = new QVBoxLayout(widget);
-
- layout->addWidget(new QLabel(i18n("Enter a position:")));
-
- timeEdit = new QTimeEdit(this);
- timeEdit->setDisplayFormat("hh:mm:ss");
- timeEdit->setTime(QTime().addSecs(mediaWidget->getPosition() / 1000));
- layout->addWidget(timeEdit);
-
- timeEdit->setFocus();
-
- setMainWidget(widget);
-}
-
-JumpToPositionDialog::~JumpToPositionDialog()
-{
-}
-
-void JumpToPositionDialog::accept()
-{
- mediaWidget->setPosition(QTime().msecsTo(timeEdit->time()));
- KDialog::accept();
-}
-
-void SeekSlider::mousePressEvent(QMouseEvent *event)
-{
- int buttons = style()->styleHint(QStyle::SH_Slider_AbsoluteSetButtons);
- Qt::MouseButton button = static_cast<Qt::MouseButton>(buttons & (~(buttons - 1)));
- QMouseEvent modifiedEvent(event->type(), event->pos(), event->globalPos(), button,
- event->buttons() ^ event->button() ^ button, event->modifiers());
- QSlider::mousePressEvent(&modifiedEvent);
-}
-
MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, KActionCollection \
*collection,
- QWidget *parent) : QWidget(parent), menu(menu_), dvbFeed(NULL), \
screenSaverSuspended(false) + QWidget *parent) : QWidget(parent), menu(menu_),
+ backendPlaybackStatus(Idle), displayMode(NormalMode), automaticResize(ResizeOff), \
source(Playlist), blockBackendUpdates(false), muted(false), \
screenSaverSuspended(false), backendTotalTime(0), backendCurrentTime(0), \
showElapsedTime(true), backendSeekable(false), currentBackendAudioChannel(-1), \
currentDvbAudioChannel(-1), currentBackendSubtitle(-1), currentDvbSubtitle(-1), \
currentExternalSubtitle(-1) {
QBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
- setAcceptDrops(true);
- setFocusPolicy(Qt::StrongFocus);
-
QPalette palette = QWidget::palette();
palette.setColor(backgroundRole(), Qt::black);
setPalette(palette);
setAutoFillBackground(true);
- backend = new XineMediaWidget(this);
- connect(backend, SIGNAL(sourceChanged()), this, SLOT(sourceChanged()));
+ setAcceptDrops(true);
+ setFocusPolicy(Qt::StrongFocus);
+
+ backend = AbstractMediaWidget::createVlcMediaWidget(this);
connect(backend, SIGNAL(playbackFinished()), this, SLOT(playbackFinished()));
- connect(backend, SIGNAL(playbackStopped()), this, SLOT(playbackStopped()));
- connect(backend, SIGNAL(playbackChanged(bool)), this, SLOT(playbackChanged(bool)));
- connect(backend, SIGNAL(totalTimeChanged(int)), this, SLOT(totalTimeChanged(int)));
- connect(backend, SIGNAL(currentTimeChanged(int)), this, \
SLOT(currentTimeChanged(int)));
- connect(backend, SIGNAL(metadataChanged(QMap<MediaWidget::MetadataType,QString>)),
- this, SLOT(setMetadata(QMap<MediaWidget::MetadataType,QString>)));
- connect(backend, SIGNAL(seekableChanged(bool)), this, SLOT(seekableChanged(bool)));
- connect(backend, SIGNAL(audioChannelsChanged(QStringList,int)),
- this, SLOT(audioChannelsChanged(QStringList,int)));
- connect(backend, SIGNAL(currentAudioChannelChanged(int)),
- this, SLOT(setCurrentAudioChannel(int)));
- connect(backend, SIGNAL(subtitlesChanged(QStringList,int)),
- this, SLOT(subtitlesChanged(QStringList,int)));
- connect(backend, SIGNAL(currentSubtitleChanged(int)),
- this, SLOT(setCurrentSubtitle(int)));
- connect(backend, SIGNAL(dvdPlaybackChanged(bool)), this, \
SLOT(dvdPlaybackChanged(bool)));
- connect(backend, SIGNAL(titlesChanged(int,int)), this, \
SLOT(titlesChanged(int,int)));
- connect(backend, SIGNAL(currentTitleChanged(int)), this, \
SLOT(setCurrentTitle(int)));
- connect(backend, SIGNAL(chaptersChanged(int,int)), this, \
SLOT(chaptersChanged(int,int)));
- connect(backend, SIGNAL(currentChapterChanged(int)),
- this, SLOT(setCurrentChapter(int)));
- connect(backend, SIGNAL(anglesChanged(int,int)), this, \
SLOT(anglesChanged(int,int)));
- connect(backend, SIGNAL(currentAngleChanged(int)), this, \
SLOT(setCurrentAngle(int)));
- connect(backend, SIGNAL(videoSizeChanged()), this, SLOT(videoSizeChanged()));
+ connect(backend, SIGNAL(updatePlaybackStatus(MediaWidget::PlaybackStatus)),
+ this, SLOT(updatePlaybackStatus(MediaWidget::PlaybackStatus)));
+ connect(backend, SIGNAL(updateTotalTime(int)), this, SLOT(updateTotalTime(int)));
+ connect(backend, SIGNAL(updateCurrentTime(int)), this, \
SLOT(updateCurrentTime(int))); + connect(backend, \
SIGNAL(updateMetadata(QMap<MediaWidget::MetadataType,QString>)), + this, \
SLOT(updateMetadata(QMap<MediaWidget::MetadataType,QString>))); + connect(backend, \
SIGNAL(updateSeekable(bool)), this, SLOT(updateSeekable(bool))); + connect(backend, \
SIGNAL(updateAudioChannels(QStringList,int)), + this, \
SLOT(updateAudioChannels(QStringList,int))); + connect(backend, \
SIGNAL(updateSubtitles(QStringList,int)), + this, \
SLOT(updateSubtitles(QStringList,int))); + connect(backend, \
SIGNAL(updateTitles(int,int)), this, SLOT(updateTitles(int,int))); + connect(backend, \
SIGNAL(updateChapters(int,int)), this, SLOT(updateChapters(int,int))); \
+ connect(backend, SIGNAL(updateAngles(int,int)), this, SLOT(updateAngles(int,int))); \
+ connect(backend, SIGNAL(updateDvdPlayback(bool)), this, \
SLOT(updateDvdPlayback(bool))); + connect(backend, SIGNAL(updateVideoSize()), this, \
SLOT(updateVideoSize())); layout->addWidget(backend);
osdWidget = new OsdWidget(this);
@@ -264,8 +109,6 @@ MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, \
KActionCollection *col menu->addAction(actionNext);
menu->addSeparator();
- displayMode = NormalMode;
-
fullScreenAction = new KAction(KIcon("view-fullscreen"),
i18nc("'Playback' menu", "Full Screen Mode"), this);
fullScreenAction->setShortcut(Qt::Key_F);
@@ -279,14 +122,12 @@ MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, \
KActionCollection *col menu->addAction(collection->addAction("view_minimal_mode", \
minimalModeAction));
audioChannelBox = new KComboBox(toolBar);
- audioChannelsReady = false;
connect(audioChannelBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(currentAudioChannelChanged(int)));
toolBar->addWidget(audioChannelBox);
subtitleBox = new KComboBox(toolBar);
textSubtitlesOff = i18nc("subtitle selection entry", "off");
- subtitlesReady = false;
connect(subtitleBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(currentSubtitleChanged(int)));
toolBar->addWidget(subtitleBox);
@@ -310,7 +151,6 @@ MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, \
KActionCollection *col unmutedIcon = KIcon("audio-volume-medium");
muteAction->setIcon(unmutedIcon);
muteAction->setShortcut(KShortcut(Qt::Key_M, Qt::Key_VolumeMute));
- isMuted = false;
connect(muteAction, SIGNAL(triggered()), this, SLOT(mutedChanged()));
toolBar->addAction(collection->addAction("controls_mute_volume", muteAction));
audioMenu->addAction(muteAction);
@@ -379,14 +219,24 @@ MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, \
KActionCollection *col action->setData(2);
autoResizeMenu->addAction(collection->addAction("controls_autoresize_double", \
action));
- autoResizeFactor =
+ int autoResizeFactor =
KGlobal::config()->group("MediaObject").readEntry("AutoResizeFactor", 0);
- if ((autoResizeFactor < 0) || (autoResizeFactor > 2)) {
- autoResizeFactor = 0;
+ switch (autoResizeFactor) {
+ case 1:
+ automaticResize = OriginalSize;
+ autoResizeGroup->actions().at(1)->setChecked(true);
+ break;
+ case 2:
+ automaticResize = DoubleSize;
+ autoResizeGroup->actions().at(2)->setChecked(true);
+ break;
+ default:
+ automaticResize = ResizeOff;
+ autoResizeGroup->actions().at(0)->setChecked(true);
+ break;
}
- autoResizeGroup->actions().at(autoResizeFactor)->setChecked(true);
videoMenu->addMenu(autoResizeMenu);
action = new KAction(i18n("Volume Slider"), this);
@@ -454,7 +304,7 @@ MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, \
KActionCollection *col seekSlider->setFocusPolicy(Qt::NoFocus);
seekSlider->setOrientation(Qt::Horizontal);
seekSlider->setToolTip(action->text());
- connect(seekSlider, SIGNAL(valueChanged(int)), backend, SLOT(seek(int)));
+ connect(seekSlider, SIGNAL(valueChanged(int)), this, SLOT(seek(int)));
action->setDefaultWidget(seekSlider);
toolBar->addAction(collection->addAction("controls_position_slider", action));
@@ -485,7 +335,6 @@ MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, \
KActionCollection *col timeButton = new QPushButton(toolBar);
timeButton->setFocusPolicy(Qt::NoFocus);
timeButton->setToolTip(action->text());
- showElapsedTime = true;
connect(timeButton, SIGNAL(clicked(bool)), this, SLOT(timeButtonClicked()));
action->setDefaultWidget(timeButton);
toolBar->addAction(collection->addAction("controls_time_button", action));
@@ -494,16 +343,16 @@ MediaWidget::MediaWidget(KMenu *menu_, KToolBar *toolBar, \
KActionCollection *col timer->start(50000);
connect(timer, SIGNAL(timeout()), this, SLOT(checkScreenSaver()));
- playbackChanged(false);
- seekableChanged(false);
- totalTimeChanged(0);
- currentTimeChanged(0);
- audioChannelsChanged(QStringList(), -1);
- subtitlesChanged(QStringList(), -1);
- dvdPlaybackChanged(false);
- titlesChanged(0, -1);
- chaptersChanged(0, -1);
- anglesChanged(0, -1);
+ updatePlaybackStatus(Idle);
+ updateSeekable(false);
+ updateTotalTime(0);
+ updateCurrentTime(0);
+ updateAudioChannels(QStringList(), -1);
+ updateSubtitles(QStringList(), -1);
+ updateDvdPlayback(false);
+ updateTitles(0, -1);
+ updateChapters(0, -1);
+ updateAngles(0, -1);
}
MediaWidget::~MediaWidget()
@@ -511,6 +360,21 @@ MediaWidget::~MediaWidget()
KGlobal::config()->group("MediaObject").writeEntry("Volume", \
volumeSlider->value()); \
KGlobal::config()->group("MediaObject").writeEntry("Deinterlace", \
deinterlaceAction->isChecked()); +
+ int autoResizeFactor = 0;
+
+ switch (automaticResize) {
+ case ResizeOff:
+ autoResizeFactor = 0;
+ break;
+ case OriginalSize:
+ autoResizeFactor = 1;
+ break;
+ case DoubleSize:
+ autoResizeFactor = 2;
+ break;
+ }
+
KGlobal::config()->group("MediaObject").writeEntry("AutoResizeFactor", \
autoResizeFactor); }
@@ -573,27 +437,50 @@ void MediaWidget::setDisplayMode(DisplayMode displayMode_)
}
}
-void MediaWidget::play(const KUrl &url, const KUrl &subtitleUrl)
+void MediaWidget::play(Source source_, const KUrl &url, const KUrl &subtitleUrl)
{
- currentSourceName = url.toLocalFile();
+ source = source_;
- if (currentSourceName.isEmpty()) {
- currentSourceName = url.fileName();
+ switch (source) {
+ case Playlist:
+ emit changeCaption(url.fileName());
+ break;
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ emit changeCaption(QString());
+ case Dvb:
+ case DvbTimeShift:
+ break;
}
+ dvbAudioChannels.clear();
+ currentDvbAudioChannel = -1;
+ dvbSubtitles.clear();
externalSubtitles.clear();
- currentExternalSubtitle = subtitleUrl;
- actionPlayPause->setText(textPause);
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setChecked(false);
- backend->playUrl(url, subtitleUrl);
+ currentDvbSubtitle = -1;
+ currentExternalSubtitle = -1;
+
+ if (subtitleUrl.isValid()) {
+ externalSubtitles.append(subtitleUrl);
+ currentExternalSubtitle = 0;
+ }
+
+ backend->play(source, url, subtitleUrl);
+}
+
+void MediaWidget::play(const KUrl &url, const KUrl &subtitleUrl)
+{
+ play(Playlist, url, subtitleUrl);
}
void MediaWidget::playAudioCd(const QString &device)
{
- QString deviceName = device;
+ KUrl devicePath;
- if (deviceName.isEmpty()) {
+ if (!device.isEmpty()) {
+ devicePath = QUrl::fromLocalFile(device);
+ } else {
QList<Solid::Device> devices =
Solid::Device::listFromQuery("OpticalDisc.availableContent & 'Audio'");
@@ -601,25 +488,21 @@ void MediaWidget::playAudioCd(const QString &device)
Solid::Block *block = devices.first().as<Solid::Block>();
if (block != NULL) {
- deviceName = block->device();
+ devicePath = QUrl::fromLocalFile(block->device());
}
}
}
- currentSourceName.clear();
- externalSubtitles.clear();
- currentExternalSubtitle.clear();
- actionPlayPause->setText(textPause);
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setChecked(false);
- backend->playAudioCd(deviceName);
+ play(AudioCd, devicePath, KUrl());
}
void MediaWidget::playVideoCd(const QString &device)
{
- QString deviceName = device;
+ KUrl devicePath;
- if (deviceName.isEmpty()) {
+ if (!device.isEmpty()) {
+ devicePath = QUrl::fromLocalFile(device);
+ } else {
QList<Solid::Device> devices = Solid::Device::listFromQuery(
"OpticalDisc.availableContent & 'VideoCd|SuperVideoCd'");
@@ -627,25 +510,21 @@ void MediaWidget::playVideoCd(const QString &device)
Solid::Block *block = devices.first().as<Solid::Block>();
if (block != NULL) {
- deviceName = block->device();
+ devicePath = QUrl::fromLocalFile(block->device());
}
}
}
- currentSourceName.clear();
- externalSubtitles.clear();
- currentExternalSubtitle.clear();
- actionPlayPause->setText(textPause);
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setChecked(false);
- backend->playVideoCd(deviceName);
+ play(VideoCd, devicePath, KUrl());
}
void MediaWidget::playDvd(const QString &device)
{
- QString deviceName = device;
+ KUrl devicePath;
- if (deviceName.isEmpty()) {
+ if (!device.isEmpty()) {
+ devicePath = QUrl::fromLocalFile(device);
+ } else {
QList<Solid::Device> devices =
Solid::Device::listFromQuery("OpticalDisc.availableContent & 'VideoDvd'");
@@ -653,123 +532,50 @@ void MediaWidget::playDvd(const QString &device)
Solid::Block *block = devices.first().as<Solid::Block>();
if (block != NULL) {
- deviceName = block->device();
+ devicePath = QUrl::fromLocalFile(block->device());
}
}
}
- currentSourceName.clear();
- externalSubtitles.clear();
- currentExternalSubtitle.clear();
- actionPlayPause->setText(textPause);
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setChecked(false);
- backend->playDvd(deviceName);
-}
-
-void MediaWidget::updateExternalSubtitles(const QList<KUrl> &subtitles, int \
currentSubtitle)
-{
- if (!currentSourceName.isEmpty()) {
- subtitlesReady = false;
- externalSubtitles = subtitles;
- int currentIndex;
- KUrl externalSubtitle;
-
- if (currentSubtitle < 0) {
- currentIndex = subtitleBox->currentIndex();
- } else {
- currentIndex = currentSubtitle + subtitleBox->count();
- externalSubtitle = subtitles.at(currentSubtitle);
- }
-
- if (currentExternalSubtitle != externalSubtitle) {
- currentExternalSubtitle = externalSubtitle;
- backend->setExternalSubtitle(currentExternalSubtitle);
- }
-
- foreach (const KUrl &subtitleUrl, subtitles) {
- subtitleBox->addItem(subtitleUrl.fileName());
- }
-
- subtitleBox->setCurrentIndex(currentIndex);
- subtitleBox->setEnabled(subtitleBox->count() > 1);
- subtitlesReady = true;
- }
-}
-
-OsdWidget *MediaWidget::getOsdWidget()
-{
- return osdWidget;
+ play(Dvd, devicePath, KUrl());
}
-void MediaWidget::playDvb(const QString &channelName)
+void MediaWidget::playDvb(Source source_, const KUrl &url, const QString \
&channelName) {
- delete dvbFeed;
- dvbFeed = NULL;
-
- seekableChanged(false);
- totalTimeChanged(0);
- currentTimeChanged(0);
-
- dvbFeed = new DvbFeed(this);
- dvbFeed->ignoreSourceChange = true;
emit changeCaption(channelName);
- externalSubtitles.clear();
- currentExternalSubtitle.clear();
- actionPlayPause->setText(textPause);
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setChecked(false);
- backend->playUrl(dvbFeed->getUrl(), KUrl());
- dvbFeed->ignoreSourceChange = false;
+ play(source_, url, KUrl());
}
-void MediaWidget::writeDvbData(const QByteArray &data)
+void MediaWidget::updateExternalSubtitles(const QList<KUrl> &subtitles, int \
currentSubtitle) {
- dvbFeed->writeData(data);
+ externalSubtitles = subtitles;
+ currentExternalSubtitle = currentSubtitle;
+ updateSubtitleUi();
}
-void MediaWidget::updateDvbAudioChannels(const QStringList &audioChannels, int \
currentAudioChannel) +OsdWidget *MediaWidget::getOsdWidget()
{
- dvbFeed->audioChannels = audioChannels;
-
- if (!audioChannels.isEmpty()) {
- audioChannelsReady = false;
- audioChannelBox->clear();
- audioChannelBox->addItems(audioChannels);
- audioChannelBox->setCurrentIndex(currentAudioChannel);
- audioChannelBox->setEnabled(audioChannelBox->count() > 1);
- audioChannelsReady = true;
- } else {
- audioChannelsChanged(backend->getAudioChannels(),
- backend->getCurrentAudioChannel());
- }
+ return osdWidget;
}
-void MediaWidget::updateDvbSubtitles(const QStringList &subtitles, int \
currentSubtitle) +void MediaWidget::updateDvbAudioChannels(const QStringList \
&dvbAudioChannels_, + int currentDvbAudioChannel_)
{
- dvbFeed->subtitles = subtitles;
-
- if (!subtitles.isEmpty()) {
- subtitlesReady = false;
- subtitleBox->clear();
- subtitleBox->addItem(textSubtitlesOff);
- subtitleBox->addItems(subtitles);
- subtitleBox->setCurrentIndex(currentSubtitle + 1);
- subtitleBox->setEnabled(subtitleBox->count() > 1);
- subtitlesReady = true;
- } else {
- subtitlesChanged(backend->getSubtitles(), backend->getCurrentSubtitle());
- }
+ dvbAudioChannels = dvbAudioChannels_;
+ currentDvbAudioChannel = currentDvbAudioChannel_;
+ updateAudioChannelUi();
}
-bool MediaWidget::isPlaying() const
+void MediaWidget::updateDvbSubtitles(const QStringList &dvbSubtitles_, int \
currentDvbSubtitle_) {
- return backend->isPlaying();
+ dvbSubtitles = dvbSubtitles_;
+ currentDvbSubtitle = currentDvbSubtitle_;
+ updateSubtitleUi();
}
-bool MediaWidget::isPaused() const
+MediaWidget::PlaybackStatus MediaWidget::getPlaybackStatus() const
{
- return actionPlayPause->isChecked();
+ return backendPlaybackStatus;
}
int MediaWidget::getVolume() const
@@ -779,15 +585,21 @@ int MediaWidget::getVolume() const
int MediaWidget::getPosition() const
{
- return backend->getCurrentTime();
+ return backendCurrentTime;
}
void MediaWidget::play()
{
- // FIXME not the best behaviour
-
- if (dvbFeed == NULL) {
+ switch (source) {
+ case Playlist:
emit playlistPlay();
+ break;
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ case Dvb:
+ case DvbTimeShift:
+ break;
}
}
@@ -814,34 +626,55 @@ void MediaWidget::toggleMuted()
void MediaWidget::previous()
{
- actionPlayPause->setText(textPause);
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setChecked(false);
+ switch (source) {
+ case Playlist:
+ if (!backend->jumpToPreviousChapter()) {
+ emit playlistPrevious();
+ }
- if (dvbFeed != NULL) {
- emit previousDvbChannel();
- } else if (!backend->playPreviousTitle()) {
- emit playlistPrevious();
+ break;
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ backend->jumpToPreviousChapter();
+ break;
+ case Dvb:
+ case DvbTimeShift:
+ emit dvbPreviousChannel();
+ break;
}
}
void MediaWidget::next()
{
- actionPlayPause->setText(textPause);
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setChecked(false);
+ switch (source) {
+ case Playlist:
+ if (!backend->jumpToNextChapter()) {
+ emit playlistNext();
+ }
- if (dvbFeed != NULL) {
- emit nextDvbChannel();
- } else if (!backend->playNextTitle()) {
- emit playlistNext();
+ break;
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ backend->jumpToNextChapter();
+ break;
+ case Dvb:
+ case DvbTimeShift:
+ emit dvbNextChannel();
+ break;
}
}
void MediaWidget::stop()
{
- if (backend->isPlaying()) {
+ switch (backendPlaybackStatus) {
+ case Idle:
+ break;
+ case Playing:
+ case Paused:
osdWidget->showText(i18nc("osd", "Stopped"), 1500);
+ break;
}
backend->stop();
@@ -859,47 +692,79 @@ void MediaWidget::decreaseVolume()
volumeSlider->setValue(volumeSlider->value() - 5);
}
-void MediaWidget::sourceChanged()
+void MediaWidget::playbackFinished()
{
- if ((dvbFeed != NULL) && !dvbFeed->ignoreSourceChange) {
- stopDvbPlayback();
- }
-
- setMetadata(QMap<MetadataType, QString>());
-
- if (autoResizeFactor > 0) {
- emit resizeToVideo(autoResizeFactor);
+ switch (source) {
+ case Playlist:
+ emit playlistNext();
+ break;
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ break;
+ case Dvb:
+ case DvbTimeShift:
+ emit dvbStartTimeShift();
+ break;
}
}
-void MediaWidget::playbackFinished()
+void MediaWidget::updatePlaybackStatus(PlaybackStatus playbackStatus)
{
- currentSourceName.clear();
+ backendPlaybackStatus = playbackStatus;
+ bool playing = true;
- if (dvbFeed != NULL) {
- dvbFeed->ignoreSourceChange = true;
- emit startDvbTimeShift();
- dvbFeed->ignoreSourceChange = false;
- } else {
+ switch (playbackStatus) {
+ case Idle:
emit changeCaption(QString());
- emit playlistNext();
- }
-}
+ actionPlayPause->setIcon(iconPlay);
+ actionPlayPause->setText(textPlay);
+ playing = false;
+ dvbAudioChannels.clear();
+ currentDvbAudioChannel = -1;
+ dvbSubtitles.clear();
+ externalSubtitles.clear();
+ currentDvbSubtitle = -1;
+ currentExternalSubtitle = -1;
+ break;
+ case Playing:
+ actionPlayPause->setIcon(iconPause);
+ actionPlayPause->setText(textPause);
+ osdWidget->showText(i18nc("osd", "Playing"), 1500);
+
+ switch (source) {
+ case Playlist:
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ case DvbTimeShift:
+ break;
+ case Dvb:
+ emit dvbStartTimeShift();
+ break;
+ }
-void MediaWidget::playbackStopped()
-{
- currentSourceName.clear();
- emit changeCaption(QString());
+ break;
+ case Paused:
+ actionPlayPause->setIcon(iconPlay);
+ actionPlayPause->setText(textPlay);
+ osdWidget->showText(i18nc("osd", "Paused"), 1500);
+
+ switch (source) {
+ case Playlist:
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ case DvbTimeShift:
+ break;
+ case Dvb:
+ emit dvbPrepareTimeShift();
+ break;
+ }
- if (dvbFeed != NULL) {
- stopDvbPlayback();
+ break;
}
-}
-void MediaWidget::playbackChanged(bool playing)
-{
- actionPlayPause->setText(playing ? textPause : textPlay);
- actionPlayPause->setIcon(playing ? iconPause : iconPlay);
actionPlayPause->setCheckable(playing);
actionPrevious->setEnabled(playing);
actionStop->setEnabled(playing);
@@ -907,28 +772,52 @@ void MediaWidget::playbackChanged(bool playing)
timeButton->setEnabled(playing);
}
-void MediaWidget::totalTimeChanged(int totalTime)
+void MediaWidget::updateTotalTime(int totalTime)
{
- if ((dvbFeed == NULL) || dvbFeed->timeShiftActive) {
- seekSlider->setRange(0, totalTime);
+ if (totalTime < 0) {
+ totalTime = 0;
}
- if (!currentSourceName.isEmpty() && (dvbFeed == NULL)) {
- emit playlistTrackLengthChanged(totalTime);
+ backendTotalTime = totalTime;
+
+ switch (source) {
+ case Playlist:
+ emit playlistTrackLengthChanged(backendTotalTime);
+ break;
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ case Dvb:
+ case DvbTimeShift:
+ break;
}
+
+ updateCurrentTotalTimeUi();
}
-void MediaWidget::currentTimeChanged(int currentTime)
+void MediaWidget::updateCurrentTime(int currentTime)
{
- if ((dvbFeed == NULL) || dvbFeed->timeShiftActive) {
- seekSlider->setValue(currentTime);
- updateTimeButton();
+ if (currentTime < 0) {
+ currentTime = 0;
+ }
+
+ if (currentTime > backendTotalTime) {
+ currentTime = backendTotalTime;
}
+
+ backendCurrentTime = currentTime;
+ updateCurrentTotalTimeUi();
}
-void MediaWidget::setMetadata(const QMap<MetadataType, QString> &metadata)
+void MediaWidget::updateMetadata(const QMap<MetadataType, QString> &metadata)
{
- if (dvbFeed == NULL) {
+ switch (source) {
+ case Playlist:
+ emit playlistTrackMetadataChanged(metadata);
+ // fall through
+ case AudioCd:
+ case VideoCd:
+ case Dvd: {
QString caption = metadata.value(Title);
QString artist = metadata.value(Artist);
@@ -942,93 +831,59 @@ void MediaWidget::setMetadata(const QMap<MetadataType, QString> \
&metadata) caption += ')';
}
- if (caption.isEmpty()) {
- caption = currentSourceName;
- }
-
if (!caption.isEmpty()) {
osdWidget->showText(caption, 2500);
+ emit changeCaption(caption);
}
- emit changeCaption(caption);
-
- if (!currentSourceName.isEmpty()) {
- emit playlistTrackMetadataChanged(metadata);
- }
- }
-}
-
-void MediaWidget::seekableChanged(bool seekable)
-{
- if ((dvbFeed == NULL) || dvbFeed->timeShiftActive) {
- seekSlider->setEnabled(seekable);
- navigationMenu->setEnabled(seekable);
- jumpToPositionAction->setEnabled(seekable);
+ break;
+ }
+ case Dvb:
+ case DvbTimeShift:
+ break;
}
}
-void MediaWidget::audioChannelsChanged(const QStringList &audioChannels, int \
currentAudioChannel) +void MediaWidget::updateSeekable(bool seekable)
{
- if ((dvbFeed == NULL) || dvbFeed->audioChannels.isEmpty()) {
- audioChannelsReady = false;
- audioChannelBox->clear();
- audioChannelBox->addItems(audioChannels);
- audioChannelBox->setCurrentIndex(currentAudioChannel);
- audioChannelBox->setEnabled(audioChannelBox->count() > 1);
- audioChannelsReady = true;
- }
+ backendSeekable = seekable;
+ updateSeekableUi();
}
-void MediaWidget::setCurrentAudioChannel(int currentAudioChannel)
+void MediaWidget::updateAudioChannels(const QStringList &audioChannels, int \
currentAudioChannel) {
- if ((dvbFeed == NULL) || dvbFeed->audioChannels.isEmpty()) {
- audioChannelBox->setCurrentIndex(currentAudioChannel);
- }
+ backendAudioChannels = audioChannels;
+ currentBackendAudioChannel = currentAudioChannel;
+ updateAudioChannelUi();
}
-void MediaWidget::subtitlesChanged(const QStringList &subtitles, int \
currentSubtitle) +void MediaWidget::updateSubtitles(const QStringList &subtitles, int \
currentSubtitle) {
- if ((dvbFeed == NULL) || dvbFeed->subtitles.isEmpty()) {
- subtitlesReady = false;
- subtitleBox->clear();
- subtitleBox->addItem(textSubtitlesOff);
- subtitleBox->addItems(subtitles);
- int currentIndex;
+ backendSubtitles = subtitles;
+ currentBackendSubtitle = currentSubtitle;
- if (currentExternalSubtitle.isValid()) {
- currentIndex = (externalSubtitles.indexOf(currentExternalSubtitle) +
- subtitleBox->count());
- } else {
- currentIndex = (currentSubtitle + 1);
- }
+ if (!dvbSubtitles.isEmpty()) {
+ // subtitles are overriden --> automatically choose appropriate subtitle
+ int selectedSubtitle = -1;
- foreach (const KUrl &subtitleUrl, externalSubtitles) {
- subtitleBox->addItem(subtitleUrl.fileName());
+ if (currentDvbSubtitle >= 0) {
+ selectedSubtitle = (backendSubtitles.size() - 1);
}
- subtitleBox->setCurrentIndex(currentIndex);
- subtitleBox->setEnabled(subtitleBox->count() > 1);
- subtitlesReady = true;
- } else {
- if (!subtitles.isEmpty()) {
- backend->setCurrentSubtitle(0);
+ if (currentBackendSubtitle != selectedSubtitle) {
+ backend->setCurrentSubtitle(selectedSubtitle);
}
}
-}
-void MediaWidget::setCurrentSubtitle(int currentSubtitle)
-{
- if ((dvbFeed == NULL) || dvbFeed->subtitles.isEmpty()) {
- subtitleBox->setCurrentIndex(currentSubtitle + 1);
- }
+ updateSubtitleUi();
}
-void MediaWidget::dvdPlaybackChanged(bool playingDvd)
+void MediaWidget::updateDvdPlayback(bool playingDvd)
{
menuAction->setEnabled(playingDvd);
}
-void MediaWidget::titlesChanged(int titleCount, int currentTitle)
+void MediaWidget::updateTitles(int titleCount, int currentTitle)
{
if (titleCount > 1) {
QList<QAction *> actions = titleGroup->actions();
@@ -1050,23 +905,19 @@ void MediaWidget::titlesChanged(int titleCount, int \
currentTitle) actions.at(i)->setVisible(i < titleCount);
}
- setCurrentTitle(currentTitle);
+ if ((currentTitle >= 1) && (currentTitle <= titleGroup->actions().count())) {
+ titleGroup->actions().at(currentTitle - 1)->setChecked(true);
+ } else if (titleGroup->checkedAction() != NULL) {
+ titleGroup->checkedAction()->setChecked(false);
+ }
+
titleMenu->setEnabled(true);
} else {
titleMenu->setEnabled(false);
}
}
-void MediaWidget::setCurrentTitle(int currentTitle)
-{
- if ((currentTitle >= 1) && (currentTitle <= titleGroup->actions().count())) {
- titleGroup->actions().at(currentTitle - 1)->setChecked(true);
- } else if (titleGroup->checkedAction() != NULL) {
- titleGroup->checkedAction()->setChecked(false);
- }
-}
-
-void MediaWidget::chaptersChanged(int chapterCount, int currentChapter)
+void MediaWidget::updateChapters(int chapterCount, int currentChapter)
{
if (chapterCount > 1) {
QList<QAction *> actions = chapterGroup->actions();
@@ -1088,23 +939,19 @@ void MediaWidget::chaptersChanged(int chapterCount, int \
currentChapter) actions.at(i)->setVisible(i < chapterCount);
}
- setCurrentChapter(currentChapter);
+ if ((currentChapter >= 1) && (currentChapter <= chapterGroup->actions().count())) \
{ + chapterGroup->actions().at(currentChapter - 1)->setChecked(true);
+ } else if (chapterGroup->checkedAction() != NULL) {
+ chapterGroup->checkedAction()->setChecked(false);
+ }
+
chapterMenu->setEnabled(true);
} else {
chapterMenu->setEnabled(false);
}
}
-void MediaWidget::setCurrentChapter(int currentChapter)
-{
- if ((currentChapter >= 1) && (currentChapter <= chapterGroup->actions().count())) {
- chapterGroup->actions().at(currentChapter - 1)->setChecked(true);
- } else if (chapterGroup->checkedAction() != NULL) {
- chapterGroup->checkedAction()->setChecked(false);
- }
-}
-
-void MediaWidget::anglesChanged(int angleCount, int currentAngle)
+void MediaWidget::updateAngles(int angleCount, int currentAngle)
{
if (angleCount > 1) {
QList<QAction *> actions = angleGroup->actions();
@@ -1126,32 +973,37 @@ void MediaWidget::anglesChanged(int angleCount, int \
currentAngle) actions.at(i)->setVisible(i < angleCount);
}
- setCurrentAngle(currentAngle);
+ if ((currentAngle >= 1) && (currentAngle <= angleGroup->actions().count())) {
+ angleGroup->actions().at(currentAngle - 1)->setChecked(true);
+ } else if (angleGroup->checkedAction() != NULL) {
+ angleGroup->checkedAction()->setChecked(false);
+ }
+
angleMenu->setEnabled(true);
} else {
angleMenu->setEnabled(false);
}
}
-void MediaWidget::setCurrentAngle(int currentAngle)
-{
- if ((currentAngle >= 1) && (currentAngle <= angleGroup->actions().count())) {
- angleGroup->actions().at(currentAngle - 1)->setChecked(true);
- } else if (angleGroup->checkedAction() != NULL) {
- angleGroup->checkedAction()->setChecked(false);
- }
-}
-
-void MediaWidget::videoSizeChanged()
+void MediaWidget::updateVideoSize()
{
- if (autoResizeFactor > 0) {
- emit resizeToVideo(autoResizeFactor);
+ if (automaticResize != ResizeOff) {
+ emit resizeToVideo(automaticResize);
}
}
void MediaWidget::checkScreenSaver()
{
- bool suspendScreenSaver = (backend->isPlaying() && !isPaused() && isVisible());
+ bool suspendScreenSaver = false;
+
+ switch (backendPlaybackStatus) {
+ case Idle:
+ case Paused:
+ break;
+ case Playing:
+ suspendScreenSaver = isVisible();
+ break;
+ }
if (suspendScreenSaver) {
// KDE - Inhibit doesn't inhibit "lock screen after inactivity"
@@ -1173,10 +1025,10 @@ void MediaWidget::checkScreenSaver()
void MediaWidget::mutedChanged()
{
- isMuted = !isMuted;
- backend->setMuted(isMuted);
+ muted = !muted;
+ backend->setMuted(muted);
- if (isMuted) {
+ if (muted) {
muteAction->setIcon(mutedIcon);
osdWidget->showText(i18nc("osd", "Mute On"), 1500);
} else {
@@ -1209,6 +1061,15 @@ void MediaWidget::toggleMinimalMode()
}
}
+void MediaWidget::seek(int position)
+{
+ if (blockBackendUpdates) {
+ return;
+ }
+
+ backend->seek(position);
+}
+
void MediaWidget::deinterlacingChanged(bool deinterlacing)
{
backend->setDeinterlacing(deinterlacing);
@@ -1239,17 +1100,23 @@ void MediaWidget::autoResizeTriggered(QAction *action)
autoResizeAction->setChecked(autoResizeAction == action);
}
- bool ok;
- unsigned int autoResizeFactor_ = action->data().toInt(&ok);
-
- if (ok && (autoResizeFactor_ <= 2)) {
- autoResizeFactor = autoResizeFactor_;
-
- if (autoResizeFactor > 0) {
- emit resizeToVideo(autoResizeFactor);
+ bool ok = false;
+ int autoResizeFactor = action->data().toInt(&ok);
+
+ if (ok) {
+ switch (autoResizeFactor) {
+ case 0:
+ automaticResize = ResizeOff;
+ return;
+ case 1:
+ automaticResize = OriginalSize;
+ emit(automaticResize);
+ return;
+ case 2:
+ automaticResize = DoubleSize;
+ emit(automaticResize);
+ return;
}
-
- return;
}
Log("MediaWidget::autoResizeTriggered: internal error");
@@ -1257,78 +1124,57 @@ void MediaWidget::autoResizeTriggered(QAction *action)
void MediaWidget::pausedChanged(bool paused)
{
- if (backend->isPlaying()) {
- if (paused) {
- actionPlayPause->setIcon(iconPlay);
- actionPlayPause->setText(textPlay);
- osdWidget->showText(i18nc("osd", "Paused"), 1500);
- backend->setPaused(true);
-
- if ((dvbFeed != NULL) && !dvbFeed->timeShiftPrepared) {
- dvbFeed->timeShiftPrepared = true;
- dvbFeed->endOfData();
- emit prepareDvbTimeShift();
- }
- } else {
- actionPlayPause->setIcon(iconPause);
- actionPlayPause->setText(textPause);
- osdWidget->showText(i18nc("osd", "Playing"), 1500);
-
- if ((dvbFeed != NULL) && !dvbFeed->timeShiftActive &&
- dvbFeed->timeShiftPrepared) {
- dvbFeed->timeShiftActive = true;
- dvbFeed->ignoreSourceChange = true;
- emit startDvbTimeShift();
- dvbFeed->ignoreSourceChange = false;
- } else {
- backend->setPaused(false);
- }
- }
- } else {
+ switch (backendPlaybackStatus) {
+ case Idle:
emit playlistPlay();
+ break;
+ case Playing:
+ case Paused:
+ backend->setPaused(paused);
+ break;
}
}
void MediaWidget::timeButtonClicked()
{
showElapsedTime = !showElapsedTime;
- updateTimeButton();
+ updateCurrentTotalTimeUi();
}
void MediaWidget::longSkipBackward()
{
int longSkipDuration = Configuration::instance()->getLongSkipDuration();
- int time = backend->getCurrentTime() - 1000 * longSkipDuration;
+ int currentTime = (backendCurrentTime - 1000 * longSkipDuration);
- if (time < 0) {
- time = 0;
+ if (currentTime < 0) {
+ currentTime = 0;
}
- backend->seek(time);
+ backend->seek(currentTime);
}
void MediaWidget::shortSkipBackward()
{
int shortSkipDuration = Configuration::instance()->getShortSkipDuration();
- int time = backend->getCurrentTime() - 1000 * shortSkipDuration;
+ int currentTime = (backendCurrentTime - 1000 * shortSkipDuration);
- if (time < 0) {
- time = 0;
+ if (currentTime < 0) {
+ currentTime = 0;
}
- backend->seek(time);
+ backend->seek(currentTime);
}
void MediaWidget::shortSkipForward()
{
int shortSkipDuration = Configuration::instance()->getShortSkipDuration();
- backend->seek(backend->getCurrentTime() + 1000 * shortSkipDuration);
+ backend->seek(backendCurrentTime + 1000 * shortSkipDuration);
}
void MediaWidget::longSkipForward()
{
int longSkipDuration = Configuration::instance()->getLongSkipDuration();
- backend->seek(backend->getCurrentTime() + 1000 * longSkipDuration);
+ backend->seek(backendCurrentTime + 1000 * longSkipDuration);
}
void MediaWidget::jumpToPosition()
@@ -1341,36 +1187,47 @@ void MediaWidget::jumpToPosition()
void MediaWidget::currentAudioChannelChanged(int currentAudioChannel)
{
- if (audioChannelsReady) {
- if ((dvbFeed == NULL) || dvbFeed->audioChannels.isEmpty()) {
- backend->setCurrentAudioChannel(currentAudioChannel);
- } else {
- emit changeDvbAudioChannel(currentAudioChannel);
- }
+ if (blockBackendUpdates) {
+ return;
+ }
+
+ if (dvbAudioChannels.isEmpty()) {
+ backend->setCurrentAudioChannel(currentAudioChannel);
+ } else {
+ emit dvbSetCurrentAudioChannel(currentAudioChannel);
}
}
void MediaWidget::currentSubtitleChanged(int currentSubtitle)
{
- if (subtitlesReady) {
- if ((dvbFeed == NULL) || dvbFeed->subtitles.isEmpty()) {
+ if (blockBackendUpdates) {
+ return;
+ }
+
+ --currentSubtitle;
+
+ if (dvbSubtitles.isEmpty()) {
+ int oldExternalSubtitle = currentExternalSubtitle;
+
+ if (currentSubtitle < backendSubtitles.size()) {
+ currentExternalSubtitle = -1;
+ backend->setCurrentSubtitle(currentSubtitle);
+ } else {
+ currentExternalSubtitle = (currentSubtitle - backendSubtitles.size());
+ }
+
+ if (currentExternalSubtitle != oldExternalSubtitle) {
KUrl externalSubtitle;
- if (currentSubtitle < (subtitleBox->count() - externalSubtitles.count())) {
- backend->setCurrentSubtitle(currentSubtitle - 1);
- } else {
- backend->setCurrentSubtitle(-1);
- externalSubtitle = externalSubtitles.at(currentSubtitle -
- (subtitleBox->count() - externalSubtitles.count()));
+ if ((currentExternalSubtitle >= 0) &&
+ (currentExternalSubtitle < externalSubtitles.size())) {
+ externalSubtitle = externalSubtitles.at(currentExternalSubtitle);
}
- if (currentExternalSubtitle != externalSubtitle) {
- currentExternalSubtitle = externalSubtitle;
- backend->setExternalSubtitle(currentExternalSubtitle);
- }
- } else {
- emit changeDvbSubtitle(currentSubtitle - 1);
+ backend->setExternalSubtitle(externalSubtitle);
}
+ } else {
+ emit dvbSetCurrentSubtitle(currentSubtitle);
}
}
@@ -1410,26 +1267,105 @@ void MediaWidget::longSkipDurationChanged(int \
longSkipDuration) longSkipDuration));
}
-void MediaWidget::updateTimeButton()
+void MediaWidget::updateAudioChannelUi()
{
+ blockBackendUpdates = true;
+ audioChannelBox->clear();
+
+ if (dvbAudioChannels.isEmpty()) {
+ audioChannelBox->addItems(backendAudioChannels);
+ audioChannelBox->setCurrentIndex(currentBackendAudioChannel);
+ } else {
+ audioChannelBox->addItems(dvbAudioChannels);
+ audioChannelBox->setCurrentIndex(currentDvbAudioChannel);
+ }
+
+ audioChannelBox->setEnabled(audioChannelBox->count() > 1);
+ blockBackendUpdates = false;
+}
+
+void MediaWidget::updateSubtitleUi()
+{
+ blockBackendUpdates = true;
+ subtitleBox->clear();
+ subtitleBox->addItem(textSubtitlesOff);
+
+ if (dvbSubtitles.isEmpty()) {
+ subtitleBox->addItems(backendSubtitles);
+
+ foreach (const KUrl &subtitleUrl, externalSubtitles) {
+ subtitleBox->addItem(subtitleUrl.fileName());
+ }
+
+ int currentIndex;
+
+ if (currentExternalSubtitle < 0) {
+ currentIndex = (currentBackendSubtitle + 1);
+ } else {
+ currentIndex = (currentExternalSubtitle + backendSubtitles.size() + 1);
+ }
+
+ subtitleBox->setCurrentIndex(currentIndex);
+ } else {
+ subtitleBox->addItems(dvbSubtitles);
+ subtitleBox->setCurrentIndex(currentDvbSubtitle + 1);
+ }
+
+ subtitleBox->setEnabled(subtitleBox->count() > 1);
+ blockBackendUpdates = false;
+}
+
+void MediaWidget::updateCurrentTotalTimeUi()
+{
+ int currentTime = backendCurrentTime;
+ int totalTime = backendTotalTime;
+
+ switch (source) {
+ case Playlist:
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ case DvbTimeShift:
+ break;
+ case Dvb:
+ currentTime = 0;
+ totalTime = 0;
+ break;
+ }
+
+ blockBackendUpdates = true;
+ seekSlider->setRange(0, totalTime);
+ seekSlider->setValue(currentTime);
+
if (showElapsedTime) {
- timeButton->setText(' ' + QTime(0, 0).addMSecs(seekSlider->value()).toString());
+ timeButton->setText(' ' + QTime(0, 0).addMSecs(currentTime).toString());
} else {
- int remainingTime = seekSlider->maximum() - seekSlider->value();
+ int remainingTime = (totalTime - currentTime);
timeButton->setText('-' + QTime(0, 0).addMSecs(remainingTime).toString());
}
+
+ blockBackendUpdates = false;
}
-void MediaWidget::stopDvbPlayback()
+void MediaWidget::updateSeekableUi()
{
- delete dvbFeed;
- dvbFeed = NULL;
- totalTimeChanged(backend->getTotalTime());
- currentTimeChanged(backend->getCurrentTime());
- seekableChanged(backend->isSeekable());
- audioChannelsChanged(QStringList(), -1);
- subtitlesChanged(QStringList(), -1);
- emit dvbStopped();
+ bool seekable = backendSeekable;
+
+ switch (source) {
+ case Playlist:
+ case AudioCd:
+ case VideoCd:
+ case Dvd:
+ case DvbTimeShift:
+ break;
+ case Dvb:
+ seekable = false;
+ break;
+ }
+
+ seekSlider->setEnabled(seekable);
+ navigationMenu->setEnabled(seekable);
+ jumpToPositionAction->setEnabled(seekable);
}
void MediaWidget::contextMenuEvent(QContextMenuEvent *event)
@@ -1480,15 +1416,50 @@ void MediaWidget::resizeEvent(QResizeEvent *event)
void MediaWidget::wheelEvent(QWheelEvent *event)
{
int shortSkipDuration = Configuration::instance()->getShortSkipDuration();
+ int currentTime = (backendCurrentTime - ((25 * shortSkipDuration * event->delta()) \
/ 3));
- if (backend->isSeekable()) {
- qint64 time = (backend->getCurrentTime() -
- (25 * shortSkipDuration * event->delta()) / 3);
+ if (currentTime < 0) {
+ currentTime = 0;
+ }
- if (time < 0) {
- time = 0;
- }
+ backend->seek(currentTime);
+}
- backend->seek(time);
- }
+JumpToPositionDialog::JumpToPositionDialog(MediaWidget *mediaWidget_) : \
KDialog(mediaWidget_), + mediaWidget(mediaWidget_)
+{
+ setCaption(i18nc("@title:window", "Jump to Position"));
+
+ QWidget *widget = new QWidget(this);
+ QBoxLayout *layout = new QVBoxLayout(widget);
+
+ layout->addWidget(new QLabel(i18n("Enter a position:")));
+
+ timeEdit = new QTimeEdit(this);
+ timeEdit->setDisplayFormat("hh:mm:ss");
+ timeEdit->setTime(QTime().addMSecs(mediaWidget->getPosition()));
+ layout->addWidget(timeEdit);
+
+ timeEdit->setFocus();
+
+ setMainWidget(widget);
+}
+
+JumpToPositionDialog::~JumpToPositionDialog()
+{
+}
+
+void JumpToPositionDialog::accept()
+{
+ mediaWidget->setPosition(QTime().msecsTo(timeEdit->time()));
+ KDialog::accept();
+}
+
+void SeekSlider::mousePressEvent(QMouseEvent *event)
+{
+ int buttons = style()->styleHint(QStyle::SH_Slider_AbsoluteSetButtons);
+ Qt::MouseButton button = static_cast<Qt::MouseButton>(buttons & (~(buttons - 1)));
+ QMouseEvent modifiedEvent(event->type(), event->pos(), event->globalPos(), button,
+ event->buttons() ^ event->button() ^ button, event->modifiers());
+ QSlider::mousePressEvent(&modifiedEvent);
}
diff --git a/src/mediawidget.h b/src/mediawidget.h
index 31bc030..a0e8661 100644
--- a/src/mediawidget.h
+++ b/src/mediawidget.h
@@ -33,10 +33,9 @@ class KActionCollection;
class KComboBox;
class KMenu;
class KToolBar;
-class DvbFeed;
+class AbstractMediaWidget;
class OsdWidget;
class SeekSlider;
-class XineMediaWidget;
class MediaWidget : public QWidget
{
@@ -48,26 +47,53 @@ public:
static QString extensionFilter(); // usable for KFileDialog::setFilter()
- enum AspectRatio {
+ enum AspectRatio
+ {
AspectRatioAuto,
AspectRatio4_3,
AspectRatio16_9,
AspectRatioWidget
};
- enum DisplayMode {
+ enum DisplayMode
+ {
NormalMode,
FullScreenMode,
MinimalMode
};
- enum MetadataType {
+ enum MetadataType
+ {
Title,
Artist,
Album,
TrackNumber
};
+ enum PlaybackStatus
+ {
+ Idle,
+ Playing,
+ Paused
+ };
+
+ enum ResizeFactor
+ {
+ ResizeOff,
+ OriginalSize,
+ DoubleSize
+ };
+
+ enum Source
+ {
+ Playlist,
+ AudioCd,
+ VideoCd,
+ Dvd,
+ Dvb,
+ DvbTimeShift
+ };
+
DisplayMode getDisplayMode() const;
void setDisplayMode(DisplayMode displayMode_);
@@ -75,7 +101,9 @@ public:
* loads the media and starts playback
*/
+ void play(Source source_, const KUrl &url, const KUrl &subtitleUrl);
void play(const KUrl &url, const KUrl &subtitleUrl = KUrl());
+ void playDvb(Source source_, const KUrl &url, const QString &channelName);
void playAudioCd(const QString &device);
void playVideoCd(const QString &device);
void playDvd(const QString &device);
@@ -83,15 +111,12 @@ public:
OsdWidget *getOsdWidget();
- void playDvb(const QString &channelName); // starts dvb mode
- void writeDvbData(const QByteArray &data);
-
- // empty list = use audio channels / subtitles provided by phonon
- void updateDvbAudioChannels(const QStringList &audioChannels, int \
currentAudioChannel);
- void updateDvbSubtitles(const QStringList &subtitles, int currentSubtitle);
+ // empty list = use audio channels / subtitles provided by the backend
+ void updateDvbAudioChannels(const QStringList &dvbAudioChannels_,
+ int currentDvbAudioChannel_);
+ void updateDvbSubtitles(const QStringList &dvbSubtitles_, int currentDvbSubtitle_);
- bool isPlaying() const;
- bool isPaused() const;
+ PlaybackStatus getPlaybackStatus() const;
int getPosition() const; // milliseconds
int getVolume() const; // 0 - 100
@@ -117,7 +142,7 @@ public slots:
signals:
void displayModeChanged();
void changeCaption(const QString &caption);
- void resizeToVideo(int factor);
+ void resizeToVideo(MediaWidget::ResizeFactor resizeFactor);
void playlistPrevious();
void playlistPlay();
@@ -127,40 +152,35 @@ signals:
void playlistTrackMetadataChanged(
const QMap<MediaWidget::MetadataType, QString> &metadata);
- void previousDvbChannel();
- void nextDvbChannel();
- void prepareDvbTimeShift();
- void startDvbTimeShift();
- void changeDvbAudioChannel(int index);
- void changeDvbSubtitle(int index);
- void dvbStopped();
void osdKeyPressed(int key);
+ void dvbStopped();
+ void dvbPrepareTimeShift();
+ void dvbStartTimeShift();
+ void dvbSetCurrentAudioChannel(int index);
+ void dvbSetCurrentSubtitle(int index);
+ void dvbPreviousChannel();
+ void dvbNextChannel();
private slots:
- void sourceChanged();
void playbackFinished();
- void playbackStopped();
- void playbackChanged(bool playing);
- void totalTimeChanged(int totalTime);
- void currentTimeChanged(int currentTime);
- void setMetadata(const QMap<MediaWidget::MetadataType, QString> &metadata);
- void seekableChanged(bool seekable);
- void audioChannelsChanged(const QStringList &audioChannels, int \
currentAudioChannel);
- void setCurrentAudioChannel(int currentAudioChannel);
- void subtitlesChanged(const QStringList &subtitles, int currentSubtitle);
- void setCurrentSubtitle(int currentSubtitle);
- void dvdPlaybackChanged(bool playingDvd);
- void titlesChanged(int titleCount, int currentTitle);
- void setCurrentTitle(int currentTitle);
- void chaptersChanged(int chapterCount, int currentChapter);
- void setCurrentChapter(int currentChapter);
- void anglesChanged(int angleCount, int currentAngle);
- void setCurrentAngle(int currentAngle);
- void videoSizeChanged();
+ void updatePlaybackStatus(MediaWidget::PlaybackStatus playbackStatus);
+ void updateTotalTime(int totalTime);
+ void updateCurrentTime(int currentTime);
+ void updateMetadata(const QMap<MediaWidget::MetadataType, QString> &metadata);
+ void updateSeekable(bool seekable);
+ void updateAudioChannels(const QStringList &audioChannels, int \
currentAudioChannel); + void updateSubtitles(const QStringList &subtitles, int \
currentSubtitle); + void updateTitles(int titleCount, int currentTitle);
+ void updateChapters(int chapterCount, int currentChapter);
+ void updateAngles(int angleCount, int currentAngle);
+ void updateDvdPlayback(bool playingDvd);
+ void updateVideoSize();
+
void checkScreenSaver();
void mutedChanged();
void volumeChanged(int volume);
+ void seek(int position);
void deinterlacingChanged(bool deinterlacing);
void aspectRatioChanged(QAction *action);
void autoResizeTriggered(QAction *action);
@@ -177,8 +197,10 @@ private slots:
void longSkipDurationChanged(int longSkipDuration);
private:
- void updateTimeButton();
- void stopDvbPlayback();
+ void updateCurrentTotalTimeUi();
+ void updateSeekableUi();
+ void updateAudioChannelUi();
+ void updateSubtitleUi();
void contextMenuEvent(QContextMenuEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
@@ -189,11 +211,9 @@ private:
void wheelEvent(QWheelEvent *event);
KMenu *menu;
- XineMediaWidget *backend;
+ AbstractMediaWidget *backend;
OsdWidget *osdWidget;
- DvbFeed *dvbFeed;
- QString currentSourceName;
KAction *actionPrevious;
KAction *actionPlayPause;
QString textPlay;
@@ -202,21 +222,14 @@ private:
KIcon iconPause;
KAction *actionStop;
KAction *actionNext;
- DisplayMode displayMode;
KAction *fullScreenAction;
KAction *minimalModeAction;
KComboBox *audioChannelBox;
KComboBox *subtitleBox;
QString textSubtitlesOff;
- QList<KUrl> externalSubtitles;
- KUrl currentExternalSubtitle;
- bool audioChannelsReady;
- bool subtitlesReady;
- int autoResizeFactor;
KAction *muteAction;
KIcon mutedIcon;
KIcon unmutedIcon;
- bool isMuted;
QSlider *volumeSlider;
SeekSlider *seekSlider;
KAction *longSkipBackwardAction;
@@ -234,8 +247,31 @@ private:
KMenu *navigationMenu;
KAction *jumpToPositionAction;
QPushButton *timeButton;
- bool showElapsedTime;
+
+ PlaybackStatus backendPlaybackStatus;
+ DisplayMode displayMode;
+ ResizeFactor automaticResize;
+ Source source;
+ bool blockBackendUpdates;
+ bool muted;
bool screenSaverSuspended;
+
+ int backendTotalTime; // milliseconds
+ int backendCurrentTime; // milliseconds
+ bool showElapsedTime;
+ bool backendSeekable;
+
+ QStringList backendAudioChannels;
+ QStringList dvbAudioChannels;
+ int currentBackendAudioChannel; // first audio channel = 0
+ int currentDvbAudioChannel; // first audio channel = 0
+
+ QStringList backendSubtitles;
+ QStringList dvbSubtitles;
+ QList<KUrl> externalSubtitles;
+ int currentBackendSubtitle; // first subtitle = 0
+ int currentDvbSubtitle; // first subtitle = 0
+ int currentExternalSubtitle; // first subtitle = 0
};
#endif /* MEDIAWIDGET_H */
diff --git a/src/mediawidget_p.h b/src/mediawidget_p.h
index 26a6b1b..ce4d168 100644
--- a/src/mediawidget_p.h
+++ b/src/mediawidget_p.h
@@ -24,40 +24,9 @@
#include <QSlider>
#include <KDialog>
-class QSocketNotifier;
class QTimeEdit;
class MediaWidget;
-class DvbFeed : public QObject
-{
- Q_OBJECT
-public:
- explicit DvbFeed(QObject *parent);
- ~DvbFeed();
-
- KUrl getUrl() const;
- void writeData(const QByteArray &data);
- void endOfData();
-
- bool timeShiftPrepared;
- bool timeShiftActive;
- bool ignoreSourceChange;
- QStringList audioChannels;
- QStringList subtitles;
-
-private slots:
- void readyWrite();
-
-private:
- bool flush();
-
- KUrl url;
- int readFd;
- int writeFd;
- QSocketNotifier *notifier;
- QList<QByteArray> buffers;
-};
-
class JumpToPositionDialog : public KDialog
{
public:
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic