summaryrefslogtreecommitdiffstats
path: root/kaffeine/src/player-parts
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-10 00:59:09 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-10 00:59:09 +0000
commit7f66b9e8ba186fb14a2db598a87dfa8de7b5a47b (patch)
treeb5e07812e82f00c780d2c035dca102b8e364f447 /kaffeine/src/player-parts
downloadkaffeine-7f66b9e8ba186fb14a2db598a87dfa8de7b5a47b.tar.gz
kaffeine-7f66b9e8ba186fb14a2db598a87dfa8de7b5a47b.zip
Added old abandoned KDE3 version of Kaffeine
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kaffeine@1088031 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kaffeine/src/player-parts')
-rw-r--r--kaffeine/src/player-parts/Makefile.am5
-rw-r--r--kaffeine/src/player-parts/README17
-rw-r--r--kaffeine/src/player-parts/dummy-part/Makefile.am20
-rw-r--r--kaffeine/src/player-parts/dummy-part/README6
-rw-r--r--kaffeine/src/player-parts/dummy-part/dummy_part.cpp120
-rw-r--r--kaffeine/src/player-parts/dummy-part/dummy_part.desktop23
-rw-r--r--kaffeine/src/player-parts/dummy-part/dummy_part.h72
-rw-r--r--kaffeine/src/player-parts/dummy-part/dummy_part.rc10
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/Makefile.am22
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/gstreamer.pngbin0 -> 231 bytes
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/gstreamer_part.cpp1082
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/gstreamer_part.desktop45
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/gstreamer_part.h154
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/gstreamer_part.rc105
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.cpp117
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.h56
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/timer.cpp197
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/timer.h77
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/video.cpp332
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/video.h95
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/videosettings.cpp95
-rw-r--r--kaffeine/src/player-parts/gstreamer-part/videosettings.h58
-rw-r--r--kaffeine/src/player-parts/kaffeine-part/Makefile.am12
-rw-r--r--kaffeine/src/player-parts/kaffeine-part/kaffeinepart.cpp58
-rw-r--r--kaffeine/src/player-parts/kaffeine-part/kaffeinepart.h222
-rw-r--r--kaffeine/src/player-parts/kaffeine-part/mrl.cpp47
-rw-r--r--kaffeine/src/player-parts/kaffeine-part/mrl.h96
-rw-r--r--kaffeine/src/player-parts/kaffeine-part/playlistimport.cpp685
-rw-r--r--kaffeine/src/player-parts/kaffeine-part/playlistimport.h50
-rw-r--r--kaffeine/src/player-parts/xine-part/Makefile.am26
-rw-r--r--kaffeine/src/player-parts/xine-part/README81
-rw-r--r--kaffeine/src/player-parts/xine-part/deinterlacequality.cpp137
-rw-r--r--kaffeine/src/player-parts/xine-part/deinterlacequality.h78
-rw-r--r--kaffeine/src/player-parts/xine-part/equalizer.cpp245
-rw-r--r--kaffeine/src/player-parts/xine-part/equalizer.h79
-rw-r--r--kaffeine/src/player-parts/xine-part/filterdialog.cpp135
-rw-r--r--kaffeine/src/player-parts/xine-part/filterdialog.h68
-rw-r--r--kaffeine/src/player-parts/xine-part/kxinewidget.cpp4117
-rw-r--r--kaffeine/src/player-parts/xine-part/kxinewidget.h518
-rw-r--r--kaffeine/src/player-parts/xine-part/positionslider.cpp113
-rw-r--r--kaffeine/src/player-parts/xine-part/positionslider.h55
-rw-r--r--kaffeine/src/player-parts/xine-part/postfilter.cpp398
-rw-r--r--kaffeine/src/player-parts/xine-part/postfilter.h229
-rw-r--r--kaffeine/src/player-parts/xine-part/screenshotpreview.cpp70
-rw-r--r--kaffeine/src/player-parts/xine-part/screenshotpreview.h52
-rw-r--r--kaffeine/src/player-parts/xine-part/videosettings.cpp129
-rw-r--r--kaffeine/src/player-parts/xine-part/videosettings.h65
-rw-r--r--kaffeine/src/player-parts/xine-part/xine_part.cpp2111
-rw-r--r--kaffeine/src/player-parts/xine-part/xine_part.desktop43
-rw-r--r--kaffeine/src/player-parts/xine-part/xine_part.h276
-rw-r--r--kaffeine/src/player-parts/xine-part/xine_part.rc347
-rw-r--r--kaffeine/src/player-parts/xine-part/xine_part_iface.h135
-rw-r--r--kaffeine/src/player-parts/xine-part/xineconfig.cpp404
-rw-r--r--kaffeine/src/player-parts/xine-part/xineconfig.h96
54 files changed, 13885 insertions, 0 deletions
diff --git a/kaffeine/src/player-parts/Makefile.am b/kaffeine/src/player-parts/Makefile.am
new file mode 100644
index 0000000..81311d2
--- /dev/null
+++ b/kaffeine/src/player-parts/Makefile.am
@@ -0,0 +1,5 @@
+if with_gstreamer
+ GST_SUBDIR = gstreamer-part
+endif
+
+SUBDIRS = kaffeine-part xine-part $(GST_SUBDIR)
diff --git a/kaffeine/src/player-parts/README b/kaffeine/src/player-parts/README
new file mode 100644
index 0000000..53aa664
--- /dev/null
+++ b/kaffeine/src/player-parts/README
@@ -0,0 +1,17 @@
+This directory contains the player parts (aka backends) for kaffeine.
+
+It consists of the following subdirectories:
+
+- kaffeine-part
+ The base for all player parts. Every player part is derived from the
+ "KaffeinePart" class and reimplements functions. Additionally kaffeine-part
+ provides functions for embedding the player part e.g. into browsers.
+
+- dummy-part
+ An empty part which you can use to create a new player part.
+
+- xine-part
+ This is the default (and recommended) player part for kaffeine using xine-lib.
+
+- gstreamer-part
+ This is an experimental player part using GStreamer.
diff --git a/kaffeine/src/player-parts/dummy-part/Makefile.am b/kaffeine/src/player-parts/dummy-part/Makefile.am
new file mode 100644
index 0000000..106d07a
--- /dev/null
+++ b/kaffeine/src/player-parts/dummy-part/Makefile.am
@@ -0,0 +1,20 @@
+
+kde_module_LTLIBRARIES = libdummypart.la
+
+INCLUDES = -I$(top_srcdir)/kaffeine/src/player-parts/ $(all_includes)
+
+METASOURCES = AUTO
+
+noinst_HEADERS = dummy_part.h
+
+libdummypart_la_SOURCES = dummy_part.cpp
+libdummypart_la_LIBADD = $(LIB_KPARTS) $(LIB_KFILE) ../libkaffeinepart.la
+libdummypart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -avoid-version -no-undefined
+
+# this is where the desktop file will go
+partdesktopdir = $(kde_servicesdir)
+partdesktop_DATA = dummy_part.desktop
+
+# this is where the part's XML-GUI resource file goes
+partrcdir = $(kde_datadir)/dummypart
+partrc_DATA = dummy_part.rc \ No newline at end of file
diff --git a/kaffeine/src/player-parts/dummy-part/README b/kaffeine/src/player-parts/dummy-part/README
new file mode 100644
index 0000000..a569c62
--- /dev/null
+++ b/kaffeine/src/player-parts/dummy-part/README
@@ -0,0 +1,6 @@
+
+**************
+* DUMMY PART *
+**************
+
+You can use this files as templates for your own player-part. \ No newline at end of file
diff --git a/kaffeine/src/player-parts/dummy-part/dummy_part.cpp b/kaffeine/src/player-parts/dummy-part/dummy_part.cpp
new file mode 100644
index 0000000..7c52cf7
--- /dev/null
+++ b/kaffeine/src/player-parts/dummy-part/dummy_part.cpp
@@ -0,0 +1,120 @@
+/*
+ * dummy_part.cpp
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <kparts/genericfactory.h>
+#include <kaction.h>
+
+#include "dummy_part.h"
+
+typedef KParts::GenericFactory<DummyPart> DummyPartFactory;
+K_EXPORT_COMPONENT_FACTORY (libdummypart, DummyPartFactory);
+
+
+DummyPart::DummyPart(QWidget* parentWidget, const char* widgetName, QObject* parent, const char* name, const QStringList& /*args*/)
+: KaffeinePart(parent, name ? name : "DummyPart")
+{
+ // we need an instance
+ setInstance(DummyPartFactory::instance());
+
+ // m_player = new Player(this);
+ // m_player->setFocusPolicy(QWidget::ClickFocus);
+ // setWidget(m_player);
+
+ setXMLFile("dummy_part.rc");
+ initActions();
+}
+
+
+DummyPart::~DummyPart()
+{
+}
+
+bool DummyPart::isPlaying()
+{
+ return false;
+}
+
+uint DummyPart::volume() const
+{
+ return 0;
+}
+
+uint DummyPart::position() const
+{
+ return 0;
+}
+
+bool DummyPart::closeURL()
+{
+ return true;
+}
+
+KAboutData *DummyPart::createAboutData()
+{
+ KAboutData* aboutData = new KAboutData( "dummypart", I18N_NOOP("DummyPart"),
+ "0.1", "Description...",
+ KAboutData::License_GPL,
+ "(c) 2004, Jürgen Kofler.", 0, "http://kaffeine.sourceforge.net");
+ aboutData->addAuthor("Jürgen Kofler.",0, "kaffeine@gmx.net");
+
+ return aboutData;
+}
+
+bool DummyPart::openURL(const MRL& mrl)
+{
+ // m_player->setLocation(mrl.url());
+}
+
+void DummyPart::slotPlay()
+{
+ // m_player->play();
+}
+
+void DummyPart::slotTogglePause()
+{
+
+}
+
+void DummyPart::slotSetVolume(uint)
+{
+
+}
+
+void DummyPart::slotSetPosition(uint)
+{
+
+}
+
+void DummyPart::slotStop()
+{
+ // m_player->stop();
+}
+
+void DummyPart::slotMute()
+{
+
+}
+
+void DummyPart::initActions()
+{
+ new KAction(i18n("Play"), "player_play", 0, this, SLOT(slotPlay()), actionCollection(), "player_play");
+ new KAction(i18n("Pause"), "player_pause", Key_Space, this, SLOT(slotTogglePause()), actionCollection(), "player_pause");
+ new KAction(i18n("Stop"), "player_stop", Key_Backspace, this, SLOT(slotStop()), actionCollection(), "player_stop");
+}
diff --git a/kaffeine/src/player-parts/dummy-part/dummy_part.desktop b/kaffeine/src/player-parts/dummy-part/dummy_part.desktop
new file mode 100644
index 0000000..de51e00
--- /dev/null
+++ b/kaffeine/src/player-parts/dummy-part/dummy_part.desktop
@@ -0,0 +1,23 @@
+[Desktop Entry]
+Encoding=UTF-8
+Icon=gear
+Name=DummyPart
+Name[bn]=ডামি-পার্ট
+Name[ca]=Part inútil
+Name[da]=Tom program-part
+Name[et]=Libakomponent
+Name[fr]=Partie factice
+Name[ja]=ダミーパート
+Name[nb]=Tullemodul
+Name[nn]=Eksempel-del
+Name[se]=Fillenoassi
+Name[sv]=Tom programdel
+Name[tg]=Қисми амсила
+Name[tr]=Kukla Kısım
+Name[uk]=Порожній компонент
+Name[xx]=xxDummyPartxx
+Name[zh_CN]=伪部件
+MimeType=audio/x-mp3
+ServiceTypes=KaffeinePart
+Type=Service
+X-KDE-Library=libdummypart
diff --git a/kaffeine/src/player-parts/dummy-part/dummy_part.h b/kaffeine/src/player-parts/dummy-part/dummy_part.h
new file mode 100644
index 0000000..8f9a568
--- /dev/null
+++ b/kaffeine/src/player-parts/dummy-part/dummy_part.h
@@ -0,0 +1,72 @@
+/*
+ * dummy_part.h
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 DUMMYPART_H
+#define DUMMYPART_H
+
+#include <kparts/factory.h>
+
+#include "kaffeinepart.h"
+
+/**
+ * DummyPart - use this as template for own player parts
+ * @author Jürgen Kofler <kaffeine@gmx.net>
+ *
+ */
+
+
+class DummyPart : public KaffeinePart
+{
+ Q_OBJECT
+public:
+ DummyPart(QWidget*, const char*, QObject*, const char*, const QStringList&);
+ virtual ~DummyPart();
+
+ /*
+ *Reimplement from KaffeinePart
+ */
+ bool isPlaying();
+ uint volume() const; /* percent */
+ uint position() const; /* percent */
+
+ bool closeURL();
+ static KAboutData* createAboutData();
+
+public slots:
+ /*
+ * Reimplement from KaffeinePart
+ */
+ bool openURL(const MRL& mrl);
+ void slotPlay();
+ void slotTogglePause();
+ void slotSetVolume(uint); /* percent */
+ void slotSetPosition(uint); /* percent */
+ void slotStop();
+ void slotMute();
+
+private:
+ void initActions();
+
+private:
+ // Player* m_play;
+
+};
+
+#endif /* DUMMYPART_H */
diff --git a/kaffeine/src/player-parts/dummy-part/dummy_part.rc b/kaffeine/src/player-parts/dummy-part/dummy_part.rc
new file mode 100644
index 0000000..d58b2aa
--- /dev/null
+++ b/kaffeine/src/player-parts/dummy-part/dummy_part.rc
@@ -0,0 +1,10 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="dummy_part" version="1">
+<MenuBar>
+ <Menu name="player"><text>&amp;Player</text>
+ <Action name="player_play"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ </Menu>
+</MenuBar>
+</kpartgui> \ No newline at end of file
diff --git a/kaffeine/src/player-parts/gstreamer-part/Makefile.am b/kaffeine/src/player-parts/gstreamer-part/Makefile.am
new file mode 100644
index 0000000..3d058be
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/Makefile.am
@@ -0,0 +1,22 @@
+kde_module_LTLIBRARIES = libgstreamerpart.la
+
+INCLUDES = -I$(top_srcdir)/kaffeine/src/player-parts/kaffeine-part -I$(top_srcdir)/kaffeine/src/ $(all_includes) $(CFLAGS_GSTREAMER)
+
+METASOURCES = AUTO
+
+noinst_HEADERS = gstreamer_part.h timer.h video.h videosettings.h gstreamerconfig.h
+
+libgstreamerpart_la_SOURCES = gstreamer_part.cpp video.cpp timer.cpp videosettings.cpp gstreamerconfig.cpp
+libgstreamerpart_la_LIBADD = $(LIB_KPARTS) $(LIB_KFILE) ../kaffeine-part/libkaffeinepart.la
+libgstreamerpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(LIB_GSTREAMER) -lgstinterfaces-0.10 $(all_libraries) -avoid-version -no-undefined
+
+# this is where the desktop file will go
+partdesktopdir = $(kde_servicesdir)
+partdesktop_DATA = gstreamer_part.desktop
+
+# this is where the part's XML-GUI resource file goes
+partrcdir = $(kde_datadir)/gstreamerpart
+partrc_DATA = gstreamer_part.rc
+
+icondir = $(kde_icondir)/hicolor/16x16/apps/
+icon_DATA = gstreamer.png
diff --git a/kaffeine/src/player-parts/gstreamer-part/gstreamer.png b/kaffeine/src/player-parts/gstreamer-part/gstreamer.png
new file mode 100644
index 0000000..1a73f7b
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/gstreamer.png
Binary files differ
diff --git a/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.cpp b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.cpp
new file mode 100644
index 0000000..22e747a
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.cpp
@@ -0,0 +1,1082 @@
+/*
+ * gstreamer_part.cpp
+ *
+ * Copyright (C) 2006 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * based on kiss by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * 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 <kparts/genericfactory.h>
+#include <kaction.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kxmlguifactory.h>
+#include <ktoolbar.h>
+#include <kio/netaccess.h>
+#include <kmimetype.h>
+#include <kpopupmenu.h>
+
+#include <qtimer.h>
+#include <qslider.h>
+#include <qfile.h>
+#include <qtooltip.h>
+
+#include "gstreamer_part.h"
+#include "gstreamer_part.moc"
+#include "playlistimport.h"
+
+#define TIMER_EVENT_PLAYBACK_FINISHED 100
+#define TIMER_EVENT_ERROR 102
+#define TIMER_EVENT_NEW_STATE 103
+#define TIMER_EVENT_FOUND_TAG 104
+
+
+
+typedef KParts::GenericFactory<GStreamerPart> GStreamerPartFactory;
+K_EXPORT_COMPONENT_FACTORY (libgstreamerpart, GStreamerPartFactory);
+
+
+GStreamerPart::GStreamerPart( QWidget* parentWidget, const char* /*widgetName*/, QObject* parent, const char* name,
+ const QStringList& /*args*/ )
+ : KaffeinePart( parent, name ? name : "GStreamerPart" ),
+ m_play(NULL), m_videosink(NULL), m_audiosink(NULL), m_visual(NULL), m_videoSettings(NULL),
+ m_gstConfig(NULL), m_mute(false), m_logoPath(QString::null), m_posToolbar(NULL)
+{
+ // we need an instance
+ setInstance( GStreamerPartFactory::instance() );
+ parentWidget->setPaletteBackgroundColor( QColor(0,0,0) ); //black
+
+ bus = NULL;
+
+ loadConfig();
+
+ if ( !initGStreamer() )
+ {
+ kdError() << "GStreamerPart: Initializing of GStreamer failed!" << endl;
+ emit canceled( i18n("GStreamer initializing failed!") );
+ return;
+ }
+
+ m_status = GST_STATE_NULL;
+
+ kdDebug() << "GStreamerPart: Creating video window" << endl;
+ m_video = new VideoWindow( parentWidget, m_videosink );
+ connect( m_video, SIGNAL(signalNewFrameSize(const QSize&)), this, SIGNAL(signalNewFrameSize(const QSize&)) );
+ m_video->setFocusPolicy( QWidget::ClickFocus );
+ setWidget( m_video );
+
+ setXMLFile( "gstreamer_part.rc" );
+ initActions();
+ stateChanged( "disable_all" );
+
+ emit setStatusBarText( i18n("Ready") );
+
+ // be careful - we may be embedded
+ m_logoPath = locate( "data", "kaffeine/logo" );
+ kdDebug() << "GStreamerPart: Found logo animation: " << m_logoPath << endl;
+
+ connect( &busTimer, SIGNAL(timeout()), this, SLOT(slotReadBus()) );
+}
+
+
+
+GStreamerPart::~GStreamerPart()
+{
+ deletePlaybin();
+ saveConfig();
+ delete m_timer;
+ kdDebug() << "GStreamerPart: destructed" << endl;
+}
+
+
+
+bool GStreamerPart::isPlaying()
+{
+ return ( (m_status==GST_STATE_PLAYING) && m_url != m_logoPath );
+}
+
+
+
+bool GStreamerPart::isPaused()
+{
+ if ( !m_play )
+ return false;
+ return ( GST_STATE(m_play)==GST_STATE_PAUSED );
+}
+
+
+
+bool GStreamerPart::hasVideo()
+{
+ //FIXME: don't work with all video codecs
+ return ( !m_videoCodec.isNull() );
+}
+
+
+
+uint GStreamerPart::position() const
+{
+ return (uint)((1.0 / m_timer->getTotalTimeMS()) * m_timer->getCurrentTimeMS() * 100);
+}
+
+
+
+bool GStreamerPart::closeURL()
+{
+ slotStop();
+ return true;
+}
+
+
+
+KAboutData *GStreamerPart::createAboutData()
+{
+ KAboutData* aboutData = new KAboutData( "gstreamerpart", I18N_NOOP("GStreamerPart"),
+ "0.1", "GStreamer based player part for Kaffeine.",
+ KAboutData::License_GPL,
+ "(c) 2005, Jürgen Kofler.", 0, "http://kaffeine.sourceforge.net");
+ aboutData->addAuthor("Jürgen Kofler.",0, "kaffeine@gmx.net");
+
+ return aboutData;
+}
+
+
+
+bool GStreamerPart::openURL(const MRL& mrl)
+{
+ kdDebug() << "GStreamerPart::openURL(): " << mrl.url() << endl;
+
+ // FIXME: thats not the right place for that
+ if ( !m_posToolbar ) {
+ m_posToolbar = (KToolBar*)factory()->container( "gstPositionToolBar", this );
+ if ( m_posToolbar ) {
+ m_posToolbar->setItemAutoSized( m_posToolbar->idAt(0), true ); //set position slider to maximum width
+ }
+ }
+
+ m_mrl = mrl;
+ m_playlist.clear();
+ m_current = 0;
+ bool playlist = false;
+
+ currentDevice = "";
+
+ QString ext = m_mrl.kurl().fileName();
+ ext = ext.remove( 0 , ext.findRev('.')+1 ).lower();
+
+ if ( m_mrl.mime().isNull() ) {
+ KMimeType::Ptr mime = KMimeType::findByURL( m_mrl.kurl().path() );
+ m_mrl.setMime( mime->name() );
+ }
+
+ /* is m_mrl a playlist? */
+ if ( (m_mrl.mime() == "text/plain") || (m_mrl.mime() == "text/xml") || (m_mrl.mime() == "application/x-kaffeine")
+ || (m_mrl.mime() == "audio/x-scpls") || (m_mrl.mime() == "audio/x-mpegurl") || (m_mrl.mime() == "audio/mpegurl")
+ || (ext == "asx") || (ext == "asf") || (ext == "wvx") || (ext == "wax") ) /* windows meta files */
+ {
+ kdDebug() << "GStreamerPart: Check for kaffeine/noatun/m3u/pls/asx playlist\n";
+ QString localFile;
+ if ( KIO::NetAccess::download(m_mrl.kurl(), localFile, widget()) ) {
+ QFile file( localFile );
+ file.open( IO_ReadOnly );
+ QTextStream stream( &file );
+ QString firstLine = stream.readLine();
+ QString secondLine = stream.readLine();
+ file.close();
+
+ if ( secondLine.contains("kaffeine", false) ) {
+ kdDebug() << "GStreamerPart: Try loading kaffeine playlist\n";
+ playlist = PlaylistImport::kaffeine( localFile, m_playlist );
+ }
+ if ( secondLine.contains("noatun", false) ) {
+ kdDebug() << "GStreamerPart: Try loading noatun playlist\n";
+ playlist = PlaylistImport::noatun( localFile, m_playlist);
+ }
+ if ( firstLine.contains("asx", false) ) {
+ kdDebug() << "GStreamerPart: Try loading asx playlist\n";
+ playlist = PlaylistImport::asx( localFile, m_playlist );
+ }
+ if ( firstLine.contains("[playlist]", false) ) {
+ kdDebug() << "GStreamerPart: Try loading pls playlist\n";
+ playlist = PlaylistImport::pls( localFile, m_playlist );
+ }
+ if (ext == "m3u") { //indentify by extension
+ kdDebug() << "GStreamerPart: Try loading m3u playlist\n";
+ playlist = PlaylistImport::m3u( localFile, m_playlist );
+ }
+ }
+ else
+ kdError() << "GStreamerPart: " << KIO::NetAccess::lastErrorString() << endl;
+ }
+ /* check for ram playlist */
+ if ( (ext == "ra") || (ext == "rm") || (ext == "ram") || (ext == "lsc") || (ext == "pl") ) {
+ kdDebug() << "GStreamerPart: Try loading ram playlist\n";
+ playlist = PlaylistImport::ram( m_mrl, m_playlist, widget() );
+ }
+
+ int pos;
+ QString s = mrl.url();
+ if ( s.startsWith("cdda://") ) {
+ s = s.remove("cdda://");
+ if ( (pos=s.findRev("/"))>-1 ) {
+ currentDevice=s.left( pos );
+ s = s.right( s.length()-pos-1 );
+ }
+ else
+ currentDevice=m_device;
+ m_mrl.setURL( "cdda://"+s );
+ }
+ else if ( s.startsWith("dvd://") ) {
+ s = s.remove("dvd://");
+ if ( s.startsWith("/") )
+ currentDevice=s;
+ else
+ currentDevice=m_device;
+ m_mrl.setURL( "dvd://" );
+ }
+ else if ( s.startsWith("vcd://") ) {
+ s = s.remove("vcd://");
+ if ( s.startsWith("/") )
+ currentDevice=s;
+ else
+ currentDevice=m_device;
+ m_mrl.setURL( "vcd://" );
+ }
+
+ if (!playlist)
+ {
+ kdDebug() << "GStreamerPart: Got single track" << endl;
+ m_playlist.append( m_mrl );
+ }
+
+ QTimer::singleShot(0, this, SLOT(slotPlay()));
+ return true;
+}
+
+
+
+void GStreamerPart::slotPlay()
+{
+ if ( (m_play) && (GST_STATE(m_play)==GST_STATE_PAUSED) ) {
+ gst_element_set_state( m_play, GST_STATE_PLAYING );
+ return;
+ }
+
+ if ( m_playlist.count() > 0 ) {
+ emit setStatusBarText( i18n("Opening...") );
+ MRL curMRL = m_playlist[m_current];
+ m_url = curMRL.url();
+ QString subUrl = QString::null;
+ if ( (!curMRL.subtitleFiles().isEmpty()) && (curMRL.currentSubtitle() > -1) )
+ subUrl = curMRL.subtitleFiles()[curMRL.currentSubtitle()];
+
+ gstPlay(m_url, subUrl);
+ }
+ else {
+ emit signalRequestCurrentTrack();
+ }
+}
+
+
+
+void GStreamerPart::slotNext()
+{
+ if ( (m_playlist.count() > 0) && (m_current < m_playlist.count()-1) )
+ {
+ m_current++;
+ slotPlay();
+ }
+ else {
+ emit signalRequestNextTrack();
+ }
+}
+
+
+
+void GStreamerPart::slotPrevious()
+{
+ if ( m_current > 0 ) {
+ m_current--;
+ slotPlay();
+ }
+ else {
+ emit signalRequestPreviousTrack();
+ }
+}
+
+
+
+void GStreamerPart::setDevice( QString device )
+{
+ if ( !m_play )
+ return;
+
+ GObject *source=NULL;
+ g_object_get( m_play, "source", &source, NULL );
+ if ( !source ) {
+ kdDebug() << "GStreamer: NO source for 'device' " << device << endl;
+ return;
+ }
+
+ GObjectClass *klass = G_OBJECT_GET_CLASS( source );
+ if ( g_object_class_find_property( klass, "device" ) ) {
+ kdDebug() << "GStreamer: Set source sink property 'device' to " << device << endl;
+ g_object_set(source, "device", device.ascii(), NULL);
+ }
+ g_object_unref (source);
+}
+
+
+
+void GStreamerPart::slotTogglePause( bool )
+{
+ if ( !m_play )
+ return;
+
+ if ( GST_STATE(m_play)==GST_STATE_PAUSED )
+ gst_element_set_state( m_play, GST_STATE_PLAYING );
+ else
+ gst_element_set_state( m_play, GST_STATE_PAUSED );
+}
+
+
+
+void GStreamerPart::slotSetPosition( uint percent )
+{
+ if ( !m_play )
+ return;
+ m_timer->seekPercent( percent );
+}
+
+
+
+void GStreamerPart::slotStop()
+{
+ if ( !m_play )
+ return;
+
+ gst_element_set_state( m_play, GST_STATE_READY );
+ if ( !m_logoPath.isNull() ) {
+ m_url = m_logoPath;
+ gstPlay( m_logoPath, QString::null );
+ }
+}
+
+
+
+void GStreamerPart::slotVolume( int vol )
+{
+ if ( !m_play )
+ return;
+
+ emit setStatusBarText(i18n("Volume") + ": " + QString::number(vol) + "%");
+ double v = vol * 0.01;
+ kdDebug() << "GStreamerPart: Set volume to " << v << endl;
+ g_object_set( G_OBJECT(m_play), "volume", v, NULL );
+}
+
+
+
+void GStreamerPart::slotSetVolume( uint vol )
+{
+ m_volume->setValue( vol );
+}
+
+
+
+uint GStreamerPart::volume() const
+{
+ if ( !m_play )
+ return m_volume->value();
+
+ double v;
+ g_object_get( G_OBJECT(m_play), "volume", &v, NULL );
+
+ return (uint)(v*100 );
+}
+
+
+
+void GStreamerPart::slotMute()
+{
+ m_mute = !m_mute;
+ if ( m_mute ) {
+ muteVolume = m_volume->value();
+ m_volume->setValue( 0 );
+ emit setStatusBarText( i18n("Mute") + ": " + i18n("On") );
+ }
+ else {
+ m_volume->setValue( muteVolume );
+ emit setStatusBarText( i18n("Mute") + ": " + i18n("Off") );
+ }
+}
+
+
+
+void GStreamerPart::slotSaturation( int sat )
+{
+ emit setStatusBarText( i18n("Saturation") + ": " + QString::number(sat) );
+ g_object_set( G_OBJECT(m_videosink), "saturation", sat, NULL );
+}
+
+
+
+void GStreamerPart::slotHue( int hue )
+{
+ emit setStatusBarText( i18n("Hue") + ": " + QString::number(hue) );
+ g_object_set( G_OBJECT(m_videosink), "hue", hue, NULL );
+}
+
+
+
+void GStreamerPart::slotContrast( int contrast )
+{
+ emit setStatusBarText( i18n("Contrast") + ": " + QString::number(contrast) );
+ g_object_set( G_OBJECT(m_videosink), "contrast", contrast, NULL );
+}
+
+
+
+void GStreamerPart::slotBrightness( int brightness )
+{
+ emit setStatusBarText( i18n("Brightness") + ": " + QString::number(brightness) );
+ g_object_set( G_OBJECT(m_videosink), "brightness", brightness, NULL );
+}
+
+
+
+void GStreamerPart::gstStateChanged()
+{
+ if ( m_status == GST_STATE_PAUSED ) {
+ kdDebug() << "GStreamerPart: New gstreamer state: PAUSE" << endl;
+ emit setStatusBarText( i18n("Pause") );
+ }
+ else if ( m_status == GST_STATE_PLAYING ) {
+ kdDebug() << "GStreamerPart: New gstreamer state: PLAYING" << endl;
+ if ( m_url != m_logoPath )
+ stateChanged("playing");
+ else
+ stateChanged("not_playing");
+ QString caption = m_mrl.title();
+ if ( !m_mrl.artist().isEmpty() )
+ caption.append( QString(" (") + m_mrl.artist() + ")" );
+ emit setWindowCaption(caption);
+ emit setStatusBarText(i18n("Playing"));
+ }
+ else if ( m_status == GST_STATE_READY ) {
+ kdDebug() << "GStreamerPart: New gstreamer state: READY" << endl;
+ if ( m_playlist.count() )
+ stateChanged( "not_playing" );
+ else
+ stateChanged( "disable_all" );
+ emit setWindowCaption("");
+ emit setStatusBarText( i18n("Stop") );
+ }
+ m_video->newState();
+}
+
+
+
+void GStreamerPart::slotVideoSettings()
+{
+ if ( !m_videoSettings ) {
+ int hue = 0, sat = 0, contr = 0, bright = 0;
+ g_object_get( G_OBJECT(m_videosink), "hue", &hue, NULL );
+ g_object_get( G_OBJECT(m_videosink), "saturation", &sat, NULL );
+ g_object_get( G_OBJECT(m_videosink), "contrast", &contr, NULL );
+ g_object_get( G_OBJECT(m_videosink), "brightness", &bright, NULL );
+
+ m_videoSettings = new VideoSettings( hue, sat, contr, bright );
+ connect( m_videoSettings, SIGNAL(signalNewBrightness(int)), this, SLOT(slotBrightness(int)) );
+ connect( m_videoSettings, SIGNAL(signalNewContrast(int)), this, SLOT(slotContrast(int)) );
+ connect( m_videoSettings, SIGNAL(signalNewHue(int)), this, SLOT(slotHue(int)) );
+ connect( m_videoSettings, SIGNAL(signalNewSaturation(int)), this, SLOT(slotSaturation(int)) );
+ }
+
+ m_videoSettings->show();
+}
+
+
+
+void GStreamerPart::slotConfigDialog()
+{
+ if ( m_gstConfig == NULL ) {
+ m_gstConfig = new GStreamerConfig( m_audioPluginList, m_videoPluginList );
+ }
+
+ m_gstConfig->setAudioDriver( m_audioSinkName );
+ m_gstConfig->setVideoDriver( m_videoSinkName );
+ m_gstConfig->setDrive( m_device );
+ if ( m_gstConfig->exec() == KDialogBase::Accepted ) {
+ kdDebug() << "GStreamerPart: Apply new configuration" << endl;
+ if ( m_audioSinkName != m_gstConfig->getAudioDriver() )
+ setAudioSink( m_gstConfig->getAudioDriver() );
+ m_videoSinkName = m_gstConfig->getVideoDriver();
+ m_device = m_gstConfig->getDrive();
+ }
+}
+
+
+
+void GStreamerPart::processMetaInfo()
+{
+ kdDebug() << "GStreamerPart: Processing meta info" << endl;
+
+ MRL mrl = m_playlist[m_current];
+
+ if ( (mrl.title().contains("/") || mrl.title().contains(".") || (mrl.title().isEmpty()))
+ && !m_title.stripWhiteSpace().isEmpty() && m_title.length() > 1 )
+ mrl.setTitle( m_title );
+ if (mrl.artist().isEmpty() && !m_artist.stripWhiteSpace().isEmpty())
+ mrl.setArtist(m_artist);
+ if (mrl.album().isEmpty() && !m_album.stripWhiteSpace().isEmpty())
+ mrl.setAlbum(m_album);
+ if (mrl.genre().isEmpty() && !m_genre.stripWhiteSpace().isEmpty())
+ mrl.setGenre(m_genre);
+ if (mrl.track().isEmpty() && !m_track.stripWhiteSpace().isEmpty())
+ mrl.setTrack(m_track);
+ if (mrl.comment().isEmpty() && !m_comment.stripWhiteSpace().isEmpty())
+ mrl.setComment(m_comment);
+ if (mrl.length().isNull()) {
+ QTime length = QTime().addMSecs(m_timer->getTotalTimeMS());
+ if (!length.isNull())
+ mrl.setLength(length);
+ }
+ m_playlist[m_current] = mrl;
+
+ QString caption = mrl.title();
+ if (!mrl.artist().isEmpty())
+ caption.append(QString(" (") + mrl.artist() + ")");
+ emit setWindowCaption(caption);
+ /* if we don't have a playlist emit signalNewMeta() */
+ if (mrl.url() == m_mrl.url()) {
+ m_mrl = mrl;
+ emit signalNewMeta(m_mrl);
+ }
+}
+
+
+
+void GStreamerPart::slotInfo()
+{
+ QString info;
+ QTextStream ts(&info, IO_WriteOnly);
+ ts << "<qt><table width=\"90%\">";
+ ts << "<tr><td colspan=\"2\"><center><b>" << m_title << "</b></center></td></tr>";
+ if (!m_artist.isNull())
+ ts << "<tr><td><b>" << i18n("Artist") << ":</b></td><td> " << m_artist << "</td></tr>";
+ if (!m_album.isNull())
+ ts << "<tr><td><b>" << i18n("Album") << ":</b></td><td> " << m_album << "</td></tr>";
+ if (!m_track.isNull())
+ ts << "<tr><td><b>" << i18n("Track") << ":</b></td><td> " << m_track << "</td></tr>";
+ if (!m_year.isNull())
+ ts << "<tr><td><b>" << i18n("Year") << ":</b></td><td> " << m_year << "</td></tr>";
+ if (!m_genre.isNull())
+ ts << "<tr><td><b>" << i18n("Genre") << ":</b></td><td> " << m_genre << "</td></tr>";
+ if (!m_comment.isNull())
+ ts << "<tr><td><b>" << i18n("Comment") << ":</b></td><td> " << m_comment << "</td></tr>";
+
+ QTime length = QTime().addMSecs(m_timer->getTotalTimeMS());
+ if (!length.isNull())
+ ts << "<tr><td><b>" << i18n("Length") << ":</b></td><td> " << length.toString("h:mm:ss") << "</td></tr>";
+
+ ts << "<br><br>";
+
+ ts << "<tr><td><b>" << i18n("Audio") << ":</b></td><td> " << m_audioCodec << "</td></tr>";
+ int width = m_video->getFrameSize().width();
+ int height = m_video->getFrameSize().height();
+ if (width > 0 && height > 0)
+ ts << "<tr><td><b>" << i18n("Video") << ":</b></td><td> " << m_videoCodec << " " << width << "x" << height << "</td></tr>";
+
+ ts << "</table></qt>";
+
+ KMessageBox::information(0, info);
+}
+
+
+
+void GStreamerPart::slotSetVisualPlugin( const QString& name )
+{
+ if ( name != "none" ) {
+ GstElement* visual = gst_element_factory_make( name.ascii(), "visualization" );
+ if ( visual ) {
+ g_object_set( G_OBJECT(m_play), "vis-plugin", visual, NULL );
+ if ( m_visual )
+ g_object_unref( m_visual );
+ m_visual = visual;
+ m_visualPluginName = name;
+ }
+ else
+ kdWarning() << "GStreamer: Initialization of visualization plugin failed (" << name << ")" << endl;
+ }
+ else {
+ if (m_visual) {
+ g_object_set(G_OBJECT (m_play), "vis-plugin", NULL, NULL);
+ g_object_unref(m_visual);
+ m_visual = NULL;
+ m_visualPluginName = "none";
+ }
+ }
+}
+
+
+
+void GStreamerPart::slotContextMenu( const QPoint& pos )
+{
+ if (factory()) {
+ KPopupMenu *pop = (KPopupMenu*)factory()->container("context_menu", this);
+ if ( pop )
+ pop->popup(pos);
+ }
+}
+
+
+
+void GStreamerPart::loadConfig()
+{
+ kdDebug() << "GStreamerPart: Load config" << endl;
+ KConfig* config = instance()->config();
+ config->setGroup("General Options");
+
+ m_audioSinkName = config->readEntry("Audio Sink", "alsasink");
+ m_videoSinkName = config->readEntry("Video Sink", "xvimagesink");
+ m_visualPluginName = config->readEntry("Visual Plugin", "goom");
+ m_savedVolume = config->readNumEntry("Volume", 25);
+ m_device = config->readEntry("CD Device", "/dev/dvd");
+}
+
+
+
+void GStreamerPart::saveConfig()
+{
+ kdDebug() << "GStreamerPart: Save config" << endl;
+
+ KConfig* config = instance()->config();
+ config->setGroup("General Options");
+
+ config->writeEntry( "Audio Sink", m_audioSinkName );
+ config->writeEntry( "Video Sink", m_videoSinkName );
+ config->writeEntry( "Visual Plugin", m_visualPluginName );
+ config->writeEntry( "Volume", m_volume->value() );
+ config->writeEntry( "CD Device", m_device );
+}
+
+
+
+void GStreamerPart::slotPrepareForFullscreen( bool fullscreen )
+{
+ if ( fullscreen )
+ m_video->startMouseHideTimer();
+ else
+ m_video->stopMouseHideTimer();
+}
+
+
+
+void GStreamerPart::initActions()
+{
+ new KAction(i18n("Toggle Minimal Mode"), 0, 0, this, SIGNAL(signalToggleMinimalMode()), actionCollection(), "player_minimal_mode");
+ new KAction(i18n("Play"), "player_play", 0, this, SLOT(slotPlay()), actionCollection(), "player_play");
+ new KAction(i18n("Pause"), "player_pause", Key_Space, this, SLOT(slotTogglePause()), actionCollection(), "player_pause");
+ new KAction(i18n("Stop"), "player_stop", Key_Backspace, this, SLOT(slotStop()), actionCollection(), "player_stop");
+ new KAction(i18n("&Next"), "player_end", Key_PageDown, this, SLOT(slotNext()), actionCollection(), "player_next");
+ new KAction(i18n("&Previous"), "player_start", Key_PageUp, this, SLOT(slotPrevious()), actionCollection(), "player_previous");
+
+ m_timer = new Timer();
+ new KWidgetAction(m_timer->getSlider(), i18n("Position"), 0, 0, 0, actionCollection(), "player_position");
+ new KWidgetAction((QWidget*)m_timer->getLabel(), i18n("Playtime"), 0, 0, 0, actionCollection(), "player_playtime");
+
+ m_audioVisual = new KSelectAction(i18n("Audio &Visualization"), 0, actionCollection(), "audio_visual");
+ connect(m_audioVisual, SIGNAL(activated(const QString&)), this, SLOT(slotSetVisualPlugin(const QString&)));
+ m_audioVisualPluginList.prepend("none");
+ m_audioVisual->setItems(m_audioVisualPluginList);
+ m_audioVisual->setCurrentItem(m_audioVisual->items().findIndex(m_visualPluginName));
+
+ new KAction(i18n("&Mute"), "player_mute", Key_U, this, SLOT(slotMute()), actionCollection(), "audio_mute");
+ new KAction(i18n("&Auto"), "viewmagfit", Key_F5, m_video, SLOT(slotAspectRatioAuto()), actionCollection(), "aspect_auto");
+ new KAction(i18n("&4:3"), "viewmagfit", Key_F6, m_video, SLOT(slotAspectRatio4_3()), actionCollection(), "aspect_43");
+ new KAction(i18n("A&namorphic"), "viewmagfit", Key_F7, m_video, SLOT(slotAspectRatioAnamorphic()), actionCollection(), "aspect_anamorphic");
+ new KAction(i18n("&DVB"), "viewmagfit", Key_F8, m_video, SLOT(slotAspectRatioDVB()), actionCollection(), "aspect_dvb");
+ new KAction(i18n("&Square"), "viewmagfit", Key_F9, m_video, SLOT(slotAspectRatioSquare()), actionCollection(), "aspect_square");
+ new KAction(i18n("&Video Settings"), "configure", Key_V, this, SLOT(slotVideoSettings()), actionCollection(), "video_settings");
+ new KAction(i18n("Track &Info"), "info", 0 , this, SLOT(slotInfo()), actionCollection(), "player_track_info");
+
+ m_volume = new QSlider(Horizontal, 0);
+ QToolTip::add(m_volume, i18n("Volume"));
+ m_volume->setRange(0, 100);
+ m_volume->setSteps(1, 5);
+ m_volume->setFixedWidth(75);
+ connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(slotVolume(int)));
+ slotSetVolume(m_savedVolume);
+ new KWidgetAction(m_volume, i18n("Volume"), 0, 0, 0, actionCollection(), "audio_volume");
+ new KAction(i18n("&GStreamer Engine Parameters"), "edit", 0, this, SLOT(slotConfigDialog()), actionCollection(), "settings_gst_parameter");
+
+ connect(m_video, SIGNAL(signalRightClick(const QPoint&)), this, SLOT(slotContextMenu(const QPoint&)));
+}
+
+
+//Change audio sink on the fly
+void GStreamerPart::setAudioSink( QString sinkName )
+{
+ GstElement* sink = gst_element_factory_make(sinkName.ascii(), "audiosink");
+ if ( !sink ) {
+ KMessageBox::error(0, i18n("Error: Can't init new Audio Driver %1 - using %2!").arg(sinkName).arg(m_audioSinkName));
+ return;
+ }
+
+ if ( m_play )
+ g_object_set( G_OBJECT(m_play), "audio-sink", sink, NULL );
+ m_audiosink = sink;
+ m_audioSinkName = sinkName;
+ kdDebug() << "GStreamerPart: Using audio driver: " << m_audioSinkName << endl;
+}
+
+/**
+ * Initialize GStreamer
+ */
+bool GStreamerPart::initGStreamer()
+{
+ if ( !gst_init_check(NULL, NULL,NULL) ) {
+ KMessageBox::error(0, i18n("GStreamer could not be initialized!"));
+ return false;
+ }
+
+ /* check GStreamer version */
+ guint maj, min, mic, nan;
+ gst_version(&maj, &min, &mic, &nan);
+ kdDebug() << "GStreamerPart: Found GStreamer version "<<maj<<"."<<min<<"."<<mic<<"."<< nan <<endl<<endl;
+
+ /* check for visualization plugins */
+ GList* factories = gst_registry_get_feature_list(gst_registry_get_default (), GST_TYPE_ELEMENT_FACTORY);
+ QString name, cat;
+ while ( factories ) {
+ name = GST_PLUGIN_FEATURE_NAME(factories->data);
+ cat = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factories->data));
+ // kdDebug() << "GStreamerPart: Found plugin: " << name << " - Category: " << cat << endl;
+ if ( cat == "Visualization" )
+ m_audioVisualPluginList.append(name);
+ else if ( cat == "Sink/Audio" )
+ m_audioPluginList.append(name);
+ else if ( cat == "Sink/Video" )
+ m_videoPluginList.append(name);
+ factories = g_list_next(factories);
+ }
+ g_list_free( factories );
+
+ /*
+ * Init audio driver
+ */
+ m_audiosink = gst_element_factory_make( m_audioSinkName.ascii(), "audiosink" );
+ if ( !m_audiosink ) {
+ KMessageBox::error(0, i18n("Can't init Audio Driver '%1' - trying another one...").arg(m_audioSinkName));
+ if ( (m_audiosink = gst_element_factory_make("alsasink", "audiosink")) != NULL )
+ kdDebug() << "GStreamerPart: Using audio-driver: alsasink" << endl;
+ else {
+ if ( (m_audiosink = gst_element_factory_make("osssink", "audiosink")) != NULL )
+ kdDebug() << "GStreamerPart: Using audio-driver: osssink" << endl;
+ else {
+ if ( (m_audiosink = gst_element_factory_make("artsdsink", "audiosink")) != NULL )
+ kdDebug() << "GStreamerPart: Using audio-driver: artsdsink" << endl;
+ else {
+ KMessageBox::error(0, i18n("No useable audio-driver found!") + " (" + m_audioSinkName + ")");
+ return false;
+ }
+ }
+ }
+ }
+ else
+ kdDebug() << "GStreamerPart: Using audio driver: " << m_audioSinkName << endl;
+ gst_element_set_state( m_audiosink, GST_STATE_READY );
+ /*
+ * Init video driver...
+ */
+ m_videosink = gst_element_factory_make( m_videoSinkName.ascii(), "videosink" );
+ if ( !m_videosink ) {
+ KMessageBox::error(0, i18n("Can't init Video Driver '%1' - trying another one...").arg(m_videoSinkName));
+ if ((m_videosink = gst_element_factory_make("xvimagesink", "videosink")) != NULL)
+ kdDebug() << "GStreamerPart: Using video-driver: xvimagesink" << endl;
+ else {
+ if ( (m_videosink = gst_element_factory_make( "ximagesink", "videosink") ) != NULL)
+ kdDebug() << "GStreamerPart: Using video-driver: ximagesink" << endl;
+ else {
+ KMessageBox::error(0, i18n("No useable video-driver found!") + " (" + m_videoSinkName + ")");
+ return false;
+ }
+ }
+ }
+ else
+ kdDebug() << "GStreamerPart: Using video driver: " << m_videoSinkName << endl;
+ gst_element_set_state( m_videosink, GST_STATE_READY );
+
+ /*
+ * Visualization
+ */
+ kdDebug() << "GStreamerPart: Using visualization plugin: " << m_visualPluginName << endl;
+ if ( m_visualPluginName != "none" ) {
+ m_visual = gst_element_factory_make( m_visualPluginName.ascii(), "visualization" );
+ if ( !m_visual )
+ kdWarning() << "GStreamer: Initialization of visualization plugin failed" << endl;
+ }
+
+ return true;
+}
+
+
+
+bool GStreamerPart::createPlaybin()
+{
+ m_play = gst_element_factory_make( "playbin", "play" );
+ if ( !m_play ) {
+ KMessageBox::error( 0, i18n("GStreamer playbin could not be initialized!") );
+ return false;
+ }
+ if ( !m_videosink || !m_audiosink ) {
+ KMessageBox::error( 0, i18n("GStreamer sink(s) missing, playbin could not be initialized!") );
+ gst_object_unref( GST_OBJECT(m_play) );
+ return false;
+ }
+
+ g_object_set( G_OBJECT(m_play), "video-sink", m_videosink, NULL );
+ g_object_set( G_OBJECT(m_play), "audio-sink", m_audiosink, NULL );
+ g_object_set( G_OBJECT(m_play), "vis-plugin", m_visual, NULL );
+ gst_element_set_state( m_play, GST_STATE_READY );
+ slotVolume( m_volume->value() );
+ m_video->setPlaybin( m_play );
+ m_timer->setPlaybin( m_play );
+
+ bus = gst_pipeline_get_bus( GST_PIPELINE(m_play) );
+ busTimer.start( 5 );
+ return true;
+}
+
+
+
+void GStreamerPart::deletePlaybin()
+{
+ if ( bus ) {
+ busTimer.stop();
+ gst_object_unref( GST_OBJECT(bus) );
+ bus = NULL;
+ }
+ if ( m_play ) {
+ m_video->setPlaybin( NULL );
+ m_timer->setPlaybin( NULL );
+ gst_element_set_state( m_play, GST_STATE_NULL );
+ gst_object_unref( GST_OBJECT(m_play) );
+ m_play = NULL;
+ }
+}
+
+
+
+void GStreamerPart::gstPlay( const QString& trackUrl, const QString& subtitleUrl )
+{
+ if ( !m_play && !createPlaybin() )
+ return;
+
+ m_title = QString::null;
+ m_artist = QString::null;
+ m_album = QString::null;
+ m_year = QString::null;
+ m_genre = QString::null;
+ m_track = QString::null;
+ m_comment = QString::null;
+ m_audioCodec = QString::null;
+ m_videoCodec = QString::null;
+ QString url = trackUrl;
+
+ if ( GST_STATE(m_play)!=GST_STATE_READY )
+ gst_element_set_state( m_play, GST_STATE_READY );
+
+ /* make sure the xoverlay know the winId */
+ m_video->refresh();
+
+ /* KDE has the habit to do "file:/location", whereas we
+ expect "file:///location" */
+ if (url.left(7).lower() == "file://") {
+ url.insert(6, "/");
+ }
+ else if (url[0] == '/') {
+ url.prepend("file://");
+ }
+ gchar *uri = g_strdup( url.local8Bit() );
+ kdDebug() << "GStreamerPart: play URL: " << uri << endl;
+ g_object_set( G_OBJECT(m_play), "uri", uri, NULL );
+ g_free( uri );
+
+ //process subtitle url
+ if ( !subtitleUrl.isNull() ) {
+ QString sub = subtitleUrl;
+ if ( sub.left(7).lower() == "file://" ) {
+ sub.insert(6, "/");
+ }
+ else if (sub[0] == '/') {
+ sub.prepend("file://");
+ }
+ // set sub font
+ g_object_set( G_OBJECT(m_play), "subtitle-font-desc", "sans bold 18", NULL );
+
+ gchar* suburi = g_strdup( sub.local8Bit() );
+ kdDebug() << "GStreamerPart: Setting subtitle URL to " << suburi << endl;
+ g_object_set( G_OBJECT(m_play), "suburi", suburi, NULL );
+ g_free( suburi );
+ }
+ else {
+ g_object_set( G_OBJECT(m_play), "suburi", NULL, NULL );
+ }
+
+ if ( !currentDevice.isEmpty() )
+ setDevice( currentDevice );
+ gst_element_set_state( m_play, GST_STATE_PLAYING );
+
+ m_timer->start();
+}
+
+
+
+void GStreamerPart::slotReadBus()
+{
+ //kdDebug() << "readBus : " << QTime::currentTime().toString("hh:mm:ss:zzz") << endl;
+ if ( !bus )
+ return;
+
+ GstMessage *msg = gst_bus_pop( bus );
+ if ( !msg )
+ return;
+
+ gchar *debug = NULL;
+ GError *error = NULL;
+ GstState old, cur, pending;
+
+ GstElement *src = (GstElement*)GST_MESSAGE_SRC( msg );
+ switch( GST_MESSAGE_TYPE( msg ) ) {
+ case GST_MESSAGE_STATE_CHANGED:
+ if ( src==m_play ) {
+ gst_message_parse_state_changed( msg, &old, &cur, &pending );
+ if ( cur==old )
+ kdDebug() << "GST_MESSAGE_STATE_UNCHANGED" << endl;
+ else {
+ kdDebug() << "GST_MESSAGE_STATE_CHANGED" << endl;
+ m_status = cur;
+ gstStateChanged();
+ }
+ }
+ break;
+ case GST_MESSAGE_ERROR:
+ gst_message_parse_error( msg, &error, &debug );
+ emit setStatusBarText(i18n("Error"));
+ if (m_url != m_logoPath) {
+ errorMessage = error->message;
+ errorDetails = debug;
+ QTimer::singleShot( 0, this, SLOT(slotEngineError()) );
+ }
+ g_error_free( error );
+ g_free( debug );
+ gst_element_set_state( m_play, GST_STATE_NULL );
+ //gst_element_set_state( m_play, GST_STATE_READY );
+ break;
+ case GST_MESSAGE_EOS:
+ if ( m_current < m_playlist.count()-1 ) {
+ m_current ++;
+ slotPlay();
+ }
+ else {
+ kdDebug() << "GStreamerPart: Playback finished" << endl;
+ m_timer->stop();
+ //m_status = GST_STATE_READY;
+ if (m_url != m_logoPath)
+ emit signalTrackFinished();
+ }
+ break;
+ case GST_MESSAGE_TAG:
+ GstTagList *tagList;
+ gst_message_parse_tag( msg, &tagList );
+ foundTag( tagList );
+ break;
+ case GST_MESSAGE_WARNING: kdDebug() << "GST_MESSAGE_WARNING" << endl; break;
+ case GST_MESSAGE_INFO: kdDebug() << "GST_MESSAGE_INFO" << endl; break;
+ case GST_MESSAGE_BUFFERING: kdDebug() << "GST_MESSAGE_BUFFERING" << endl; break;
+ case GST_MESSAGE_STATE_DIRTY: kdDebug() << "GST_MESSAGE_STATE_DIRTY" << endl; break;
+ case GST_MESSAGE_STEP_DONE: kdDebug() << "GST_MESSAGE_STEP_DONE" << endl; break;
+ case GST_MESSAGE_CLOCK_PROVIDE: kdDebug() << "GST_MESSAGE_CLOCK_PROVIDE" << endl; break;
+ case GST_MESSAGE_CLOCK_LOST: kdDebug() << "GST_MESSAGE_CLOCK_LOST" << endl; break;
+ case GST_MESSAGE_NEW_CLOCK: kdDebug() << "GST_MESSAGE_NEW_CLOCK" << endl; break;
+ case GST_MESSAGE_STRUCTURE_CHANGE: kdDebug() << "GST_MESSAGE_STRUCTURE_CHANGE" << endl; break;
+ case GST_MESSAGE_STREAM_STATUS: kdDebug() << "GST_MESSAGE_STREAM_STATUS" << endl; break;
+ case GST_MESSAGE_APPLICATION: kdDebug() << "GST_MESSAGE_APPLICATION" << endl; break;
+ case GST_MESSAGE_ELEMENT: kdDebug() << "GST_MESSAGE_ELEMENT" << endl; break;
+ case GST_MESSAGE_SEGMENT_START: kdDebug() << "GST_MESSAGE_SEGMENT_START" << endl; break;
+ case GST_MESSAGE_SEGMENT_DONE: kdDebug() << "GST_MESSAGE_SEGMENT_DONE" << endl; break;
+ case GST_MESSAGE_DURATION: kdDebug() << "GST_MESSAGE_DURATION" << endl; break;
+ default:
+ kdDebug() << "GST_MESSAGE_OTHER" << endl;
+ }
+ gst_message_unref( msg );
+}
+
+
+
+void GStreamerPart::slotEngineError()
+{
+ KMessageBox::detailedError( NULL, errorMessage, errorDetails );
+}
+
+
+
+void GStreamerPart::foundTag( GstTagList *taglist )
+{
+ kdDebug() << " Received meta tags..." << endl;
+
+ char* string;
+ guint intVal = 0;
+ bool success = false;
+
+ if ( gst_tag_list_get_string(taglist, GST_TAG_TITLE, &string) && string ) {
+ m_title = string;
+ success = true;
+ }
+ if ( gst_tag_list_get_string( taglist, GST_TAG_ARTIST, &string) && string ) {
+ m_artist = string;
+ success = true;
+ }
+ if ( gst_tag_list_get_string(taglist, GST_TAG_ALBUM, &string) && string ) {
+ m_album = string;
+ success = true;
+ }
+ if ( gst_tag_list_get_string(taglist, GST_TAG_GENRE, &string) && string ) {
+ m_genre = string;
+ success = true;
+ }
+ if ( gst_tag_list_get_uint(taglist, GST_TAG_TRACK_NUMBER, &intVal) && intVal > 0 ) {
+ m_track = QString::number(intVal);
+ success = true;
+ }
+ if ( gst_tag_list_get_string(taglist, GST_TAG_COMMENT, &string) && string ) {
+ m_comment = string;
+ success = true;
+ }
+ if ( gst_tag_list_get_string(taglist, GST_TAG_AUDIO_CODEC, &string) && string )
+ m_audioCodec = string;
+ if ( gst_tag_list_get_string(taglist, GST_TAG_VIDEO_CODEC, &string) && string )
+ m_videoCodec = string;
+
+ if (success)
+ processMetaInfo();
+}
diff --git a/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.desktop b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.desktop
new file mode 100644
index 0000000..8a2015a
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.desktop
@@ -0,0 +1,45 @@
+[Desktop Entry]
+Encoding=UTF-8
+Icon=gstreamer
+Name=Kaffeine-GStreamer
+Name[af]=Kaffeine=GStremer
+Name[nb]=Kaffeine GStreamer
+Name[pa]=ਕੈਫ਼ੀਨ-ਜੀਸਟਰੀਮਰ
+Name[se]=Kaffeine GStreamer
+Name[sv]=Kaffeine-Gstreamer
+Name[xx]=xxKaffeine-GStreamerxx
+Comment=A Kaffeine engine based on GStreamer.
+Comment[af]='n Kaffeine enjin wat op GStreamer gebaseer is.
+Comment[bg]=Ядро за Kaffeine, базирано върху GStreamer.
+Comment[ca]=Una part de reproductor basada en GStreamer.
+Comment[cs]=Část přehrávače založená na GStreameru.
+Comment[da]=En Kaffeine-grænseflade baseret på Gstreamer.
+Comment[de]=Ein auf GStreamer basierendes Programmmodul.
+Comment[el]=Μία μηχανή του Kaffeine βασισμένη στο GStreamer.
+Comment[et]=Kaffeine mootor GStreameri põhjal.
+Comment[ga]=Inneall Kaffeine bunaithe ar GStreamer.
+Comment[gl]=Un motor para Kaffeine baseado en GStreamer.
+Comment[hu]=GStreamer-alapú Kaffeine-alrendszer.
+Comment[it]=Un motore di Kaffeine basato su GStreamer.
+Comment[ja]=GStreamer に基づく Kaffeine エンジン
+Comment[lt]=Kaffeine variklis, paremtas GStreamer.
+Comment[nb]=En spillermotor basert på GStreamer.
+Comment[nl]=Een Kaffeine-engine gebaseerd op GStreamer.
+Comment[pa]=ਜੀਸਟੀਮਰ ਅਧਾਰਤ ਇੱਕ ਕੈਫ਼ੀਨ ਇੰਜਣ ਹੈ।
+Comment[pl]=Moduł odtwarzacza do Kaffeine bazujący na GStreamer.
+Comment[pt]=Um motor Kaffeine no GStreamer.
+Comment[pt_BR]=Um componente de reprodução Kaffeine baseado no GStreamer.
+Comment[se]=Čuojanmohtor vuođđoduvvon GStreameris.
+Comment[sr]=Кафеинов мотор заснован на GStreamer-у.
+Comment[sr@Latn]=Кафеинов мотор заснован на GStreamer-у.
+Comment[sv]=Ett Kaffeine-gränssnitt baserad på Gstreamer.
+Comment[tg]=Барномаи Kaffeine дар асоси GStreamer.
+Comment[th]=โปรแกรมประมวลผลของ Kaffeine โดยใช้ GStreamer
+Comment[tr]=GStreamer tabanlı bir Kaffeine motoru.
+Comment[uk]=Рушій Kaffeine, оснований на GStreamer.
+Comment[xx]=xxA Kaffeine engine based on GStreamer.xx
+MimeType=application/x-ogg;video/x-matroska;audio/x-matroska;video/mpeg;video/msvideo;video/quicktime;video/vnd.rn-realvideo;video/x-avi;video/x-fli;video/x-flic;video/x-ms-asf;video/x-ms-wmv;video/x-msvideo;application/x-mplayer2;application/smil;application/x-kaffeine;audio/x-musepack;
+ServiceTypes=KParts/ReadOnlyPart,KaffeinePart
+Type=Service
+X-KDE-Library=libgstreamerpart
+InitialPreference=1
diff --git a/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.h b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.h
new file mode 100644
index 0000000..0f5c276
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.h
@@ -0,0 +1,154 @@
+/*
+ * gstreamer_part.h
+ *
+ * Copyright (C) 2006 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 GSTREAMER_PART_H
+#define GSTREAMER_PART_H
+
+#include <kparts/factory.h>
+
+#include <gst/gst.h>
+
+#include "kaffeinepart.h"
+
+#include "timer.h"
+#include "video.h"
+#include "videosettings.h"
+#include "gstreamerconfig.h"
+
+
+
+class GStreamerPart : public KaffeinePart
+{
+ Q_OBJECT
+public:
+ GStreamerPart( QWidget*, const char*, QObject*, const char*, const QStringList& );
+ virtual ~GStreamerPart();
+
+ /*
+ *Reimplement from KaffeinePart
+ */
+ bool isPlaying();
+ bool isPaused();
+ uint volume() const; /* percent */
+ uint position() const; /* percent */
+ bool hasVideo();
+
+ bool closeURL();
+ static KAboutData* createAboutData();
+
+public slots:
+ /*
+ * Reimplement from KaffeinePart
+ */
+ bool openURL( const MRL& mrl );
+ void slotPlay();
+ void slotTogglePause( bool );
+ void slotSetVolume( uint ); /* percent */
+ void slotSetPosition( uint ); /* percent */
+ void slotStop();
+ void slotMute();
+ void slotPrepareForFullscreen( bool fullscreen );
+
+private slots:
+ void slotNext();
+ void slotPrevious();
+ void slotVolume( int );
+ void slotSaturation( int ); /* -1000...1000 */
+ void slotHue( int ); /* -1000...1000 */
+ void slotContrast( int ); /* -1000...1000 */
+ void slotBrightness( int ); /* -1000...1000 */
+ void slotContextMenu( const QPoint& pos );
+ void slotInfo();
+ void slotSetVisualPlugin( const QString& );
+ void slotVideoSettings();
+ void slotConfigDialog();
+ void slotEngineError();
+
+ void slotReadBus();
+
+private:
+ bool initGStreamer();
+ bool createPlaybin();
+ void deletePlaybin();
+ void loadConfig();
+ void saveConfig();
+ void gstPlay( const QString& trackUrl, const QString& subtitleUrl );
+ void initActions();
+ void showError();
+ void gstStateChanged();
+ void foundTag( GstTagList *taglist );
+ void processMetaInfo();
+ void setAudioSink( QString sinkName );
+ void setDevice( QString device );
+
+private:
+ GstElement *m_play;
+ GstElement *m_videosink;
+ GstElement *m_audiosink;
+ GstElement *m_visual;
+ GstBus *bus;
+ GstState m_status;
+
+ QTimer busTimer;
+
+ VideoWindow* m_video;
+ Timer* m_timer;
+ VideoSettings* m_videoSettings;
+ GStreamerConfig* m_gstConfig;
+ QSlider* m_volume;
+ KSelectAction* m_audioVisual;
+
+ MRL m_mrl;
+ QValueList<MRL> m_playlist;
+ uint m_current;
+ bool m_mute;
+ QString m_logoPath;
+
+ QString m_errorMsg;
+ QString m_errorDetails;
+
+ QString m_url;
+ QString m_title;
+ QString m_artist;
+ QString m_album;
+ QString m_track;
+ QString m_year;
+ QString m_genre;
+ QString m_comment;
+ QString m_audioCodec;
+ QString m_videoCodec;
+ QString errorMessage;
+ QString errorDetails;
+
+ QString m_audioSinkName;
+ QString m_videoSinkName;
+ QString m_visualPluginName;
+ QStringList m_audioVisualPluginList;
+ QStringList m_audioPluginList;
+ QStringList m_videoPluginList;
+ QString m_device, currentDevice;
+ int m_savedVolume;
+ int muteVolume;
+
+ KToolBar* m_posToolbar;
+};
+
+#endif /* GSTREAMER_PART_H */
diff --git a/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.rc b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.rc
new file mode 100644
index 0000000..2dcfc56
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/gstreamer_part.rc
@@ -0,0 +1,105 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="gstreamer_part" version="5">
+<MenuBar>
+ <Menu name="player"><text>&amp;Player</text>
+ <Action name="player_play"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ <Separator/>
+ <Action name="audio_visual"/>
+ <Action name="audio_mute"/>
+ <Separator/>
+ <Menu name="video_aspect"><text>&amp;Aspect Ratio</text>
+ <Action name="aspect_auto"/>
+ <Action name="aspect_43"/>
+ <Action name="aspect_anamorphic"/>
+ <Action name="aspect_dvb"/>
+ <Action name="aspect_square"/>
+ </Menu>
+ <Action name="video_settings"/>
+ <Action name="player_track_info"/>
+ </Menu>
+ <Menu name="settings">
+ <Action name="settings_gst_parameter"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="gstControlsToolBar" position="Bottom"><text>Controls Toolbar</text>
+ <Action name="player_previous"/>
+ <Action name="player_play"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+</ToolBar>
+<ToolBar name="gstVolumeToolBar"><text>Volume Toolbar</text>
+ <Action name="audio_volume"/>
+ <Action name="audio_mute"/>
+</ToolBar>
+<ToolBar name="gstPositionToolBar" fullWidth="true" position="Bottom"><text>Position Toolbar</text>
+ <Action name="player_position"/>
+ <Separator/>
+ <Action name="player_playtime"/>
+</ToolBar>
+<Menu name="context_menu">
+ <Action name="player_minimal_mode"/>
+ <Separator/>
+ <Action name="player_play"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ <Separator/>
+ <Action name="audio_visual"/>
+ <Action name="audio_mute"/>
+ <Separator/>
+ <Menu name="video_aspect"><text>&amp;Aspect Ratio</text>
+ <Action name="aspect_auto"/>
+ <Action name="aspect_43"/>
+ <Action name="aspect_anamorphic"/>
+ <Action name="aspect_dvb"/>
+ <Action name="aspect_square"/>
+ </Menu>
+ <Action name="video_settings"/>
+ <Action name="player_track_info"/>
+</Menu>
+<State name="disable_all">
+ <enable>
+ <Action name="player_play"/>
+ </enable>
+ <disable>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_position"/>
+ <Action name="player_playtime"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ </disable>
+</State>
+<State name="not_playing">
+ <enable>
+ <Action name="player_play"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ </enable>
+ <disable>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_position"/>
+ <Action name="player_playtime"/>
+ </disable>
+</State>
+<State name="playing">
+ <enable>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_position"/>
+ <Action name="player_playtime"/>
+ </enable>
+ <disable>
+ <Action name="player_play"/>
+ </disable>
+</State>
+</kpartgui> \ No newline at end of file
diff --git a/kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.cpp b/kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.cpp
new file mode 100644
index 0000000..19025bc
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.cpp
@@ -0,0 +1,117 @@
+/*
+ * gstreamerconfig.cpp - config dialog for gstreamer parameters
+ *
+ * Copyright (C) 2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <kcombobox.h>
+#include <klineedit.h>
+#include <kseparator.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include "gstreamerconfig.h"
+#include "gstreamerconfig.moc"
+
+
+GStreamerConfig::GStreamerConfig(const QStringList& audioDrivers, const QStringList& videoDrivers) :
+ KDialogBase(KDialogBase::IconList, i18n("GStreamer Engine Parameters"), KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel)
+
+{
+ setInitialSize(QSize(400,300), true);
+
+ QFrame* frame = NULL;
+ QGridLayout* layout = NULL;
+ QLabel* label = NULL;
+
+ //Audio Page
+ frame = addPage(i18n("Audio"), i18n("Audio Options"), KGlobal::iconLoader()->loadIcon("sound", KIcon::Panel,
+ KIcon::SizeMedium));
+ layout = new QGridLayout(frame, 10, 2);
+ layout->setMargin(10);
+ layout->setSpacing(10);
+ m_audioDriverBox = new KComboBox(frame);
+ m_audioDriverBox->insertStringList(audioDrivers);
+ label = new QLabel(i18n("Prefered audio driver"), frame);
+ layout->addWidget(label, 1, 0);
+ layout->addWidget(m_audioDriverBox, 1, 1);
+ layout->addMultiCellWidget(new KSeparator(KSeparator::Horizontal, frame), 2, 2, 0, 1);
+
+ //Video Page
+ frame = addPage(i18n("Video"), i18n("Video Options"), KGlobal::iconLoader()->loadIcon("video", KIcon::Panel,
+ KIcon::SizeMedium));
+ layout = new QGridLayout(frame, 10, 2);
+ layout->setMargin(10);
+ layout->setSpacing(10);
+ m_videoDriverBox = new KComboBox(frame);
+ m_videoDriverBox->insertStringList(videoDrivers);
+ label = new QLabel(i18n("Prefered video driver")+ "*", frame);
+ layout->addWidget(label, 1, 0);
+ layout->addWidget(m_videoDriverBox, 1, 1);
+ layout->addMultiCellWidget(new KSeparator(KSeparator::Horizontal, frame), 2, 2, 0, 1);
+ layout->addWidget(new QLabel(QString("<small>") + i18n("* Restart required!") + "</small>", frame), 10, 1);
+
+ //Media page
+ frame = addPage(i18n("Media"), i18n("Media Options"), KGlobal::iconLoader()->loadIcon("cdrom_unmount", KIcon::Panel,
+ KIcon::SizeMedium));
+ layout = new QGridLayout(frame, 10, 2);
+ layout->setMargin(10);
+ layout->setSpacing(10);
+ m_driveEdit = new KLineEdit(frame);
+ label = new QLabel(i18n("CD, VCD, DVD drive"), frame);
+ layout->addWidget(label, 1, 0);
+ layout->addWidget(m_driveEdit, 1, 1);
+ layout->addMultiCellWidget(new KSeparator(KSeparator::Horizontal, frame), 2, 2, 0, 1);
+}
+
+GStreamerConfig::~GStreamerConfig()
+{}
+
+QString GStreamerConfig::getAudioDriver() const
+{
+ return m_audioDriverBox->currentText();
+}
+
+QString GStreamerConfig::getVideoDriver() const
+{
+ return m_videoDriverBox->currentText();
+}
+
+QString GStreamerConfig::getDrive() const
+{
+ return m_driveEdit->text();
+}
+
+void GStreamerConfig::setDrive(const QString& drive)
+{
+ m_driveEdit->setText(drive);
+}
+
+void GStreamerConfig::setAudioDriver(const QString& name)
+{
+ m_audioDriverBox->setCurrentText(name);
+}
+
+void GStreamerConfig::setVideoDriver(const QString& name)
+{
+ m_videoDriverBox->setCurrentText(name);
+}
diff --git a/kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.h b/kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.h
new file mode 100644
index 0000000..f85d882
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/gstreamerconfig.h
@@ -0,0 +1,56 @@
+/*
+ * gstreamerconfig.h - config dialog for gstreamer parameters
+ *
+ * Copyright (C) 2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 GSTREAMERCONFIG_H
+#define GSTREAMERCONFIG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+
+class QString;
+class QStringList;
+class KComboBox;
+class KLineEdit;
+
+class GStreamerConfig : public KDialogBase
+{
+ Q_OBJECT
+public:
+ GStreamerConfig(const QStringList& audioDrivers, const QStringList& videoDrivers);
+ ~GStreamerConfig();
+
+ QString getAudioDriver() const;
+ QString getVideoDriver() const;
+ QString getDrive() const;
+
+ void setDrive(const QString& drive);
+ void setAudioDriver(const QString& name);
+ void setVideoDriver(const QString& name);
+
+private:
+ KComboBox* m_audioDriverBox;
+ KComboBox* m_videoDriverBox;
+ KLineEdit* m_driveEdit;
+};
+
+#endif /* GSTREAMERCONFIG_H */
diff --git a/kaffeine/src/player-parts/gstreamer-part/timer.cpp b/kaffeine/src/player-parts/gstreamer-part/timer.cpp
new file mode 100644
index 0000000..93d0116
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/timer.cpp
@@ -0,0 +1,197 @@
+/*
+ * timer.cpp
+ *
+ * Copyright (C) 2006 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * heavily based on kiss by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qslider.h>
+#include <qlabel.h>
+#include <qtimer.h>
+
+#include "timer.h"
+
+#include "timer.moc"
+
+
+
+Timer::Timer() : QObject()
+{
+ m_label = new QLabel( "0:00 / 0:00", 0 );
+ m_slider = new QSlider( Qt::Horizontal, 0 );
+ m_slider->setMinValue( 0 );
+ m_slider->setEnabled( false );
+
+ connect( &updateTimer, SIGNAL(timeout()), SLOT(slotUpdate()) );
+
+ m_pos = GST_CLOCK_TIME_NONE;
+ m_len = GST_CLOCK_TIME_NONE;
+
+ m_play = NULL;
+ seeking = false;
+
+ connect( m_slider, SIGNAL(sliderPressed()), this, SLOT(slotSeekStart()) );
+ connect( m_slider, SIGNAL(sliderReleased()), this, SLOT(slotSeek()) );
+}
+
+
+
+void Timer::setPlaybin( GstElement *play )
+{
+ m_play = play;
+ m_slider->setEnabled( false );
+ m_slider->setValue( 0 );
+}
+
+
+
+Timer::~Timer()
+{
+}
+
+
+
+static char *niceTime( guint64 t )
+{
+ if ( t >= GST_SECOND*60*60 ) {
+ return g_strdup_printf("%d:%02d:%02d",
+ (int) (t / (GST_SECOND * 60 * 60)),
+ (int) ((t / (GST_SECOND * 60)) % 60),
+ (int) ((t / GST_SECOND) % 60));
+ }
+ else {
+ return g_strdup_printf("%d:%02d",
+ (int) ((t / (GST_SECOND * 60)) % 60),
+ (int) ((t / GST_SECOND) % 60));
+ }
+}
+
+
+
+void Timer::slotSeekStart()
+{
+ seeking = true;
+}
+
+
+
+void Timer::slotSeek()
+{
+ if ( !m_play )
+ return;
+
+ gint64 gval = m_slider->value();
+ GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_KEY_UNIT);
+ gst_element_seek( m_play, 1.0, GST_FORMAT_TIME, flags,
+ GST_SEEK_TYPE_SET, gval*GST_SECOND, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+ gst_element_get_state( m_play, NULL, NULL, 100*GST_MSECOND);
+ seeking = false;
+}
+
+
+
+void Timer::seekPercent( uint percent )
+{
+ //slotSeek( (m_slider->maxValue() * percent) / 100 );
+}
+
+
+
+void Timer::slotUpdate()
+{
+ gint64 t;
+ GstFormat fmt = GST_FORMAT_TIME;
+ char *txt;
+
+ if ( seeking )
+ return;
+
+ if ( !m_play )
+ return;
+
+ if ( gst_element_query_duration( m_play, &fmt, &t ) ) {
+ m_len = t;
+ m_slider->setMaxValue( m_len / GST_SECOND );
+ }
+
+ if ( !gst_element_query_position( m_play, &fmt, &t ) )
+ return;
+
+ m_pos = t;
+
+ m_currentTimeMS = m_pos/1000000;
+ m_totalTimeMS = m_len/1000000;
+
+ if ( GST_CLOCK_TIME_IS_VALID (m_len) ) {
+ gchar *t1 = niceTime( m_pos ), *t2 = niceTime( m_len );
+ txt = g_strdup_printf( "%s / %s", t1, t2) ;
+ g_free(t1);
+ g_free(t2);
+ }
+ else {
+ txt = niceTime( m_pos );
+ }
+ m_label->setText( txt );
+ g_free( txt );
+
+ m_slider->setValue( m_pos / GST_SECOND );
+}
+
+
+
+void Timer::start()
+{
+ if ( updateTimer.isActive() )
+ return;
+ m_slider->setEnabled( true);
+ seeking = false;
+ updateTimer.start( 1000 );
+}
+
+
+
+void Timer::stop()
+{
+ if ( !updateTimer.isActive() )
+ return;
+ updateTimer.stop();
+ m_slider->setEnabled( false );
+ m_slider->setValue(0);
+}
+
+
+
+QLabel* Timer::getLabel() const
+{
+ return m_label;
+}
+
+
+
+QSlider* Timer::getSlider() const
+{
+ return m_slider;
+}
diff --git a/kaffeine/src/player-parts/gstreamer-part/timer.h b/kaffeine/src/player-parts/gstreamer-part/timer.h
new file mode 100644
index 0000000..9ee5bff
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/timer.h
@@ -0,0 +1,77 @@
+/*
+ * timer.h
+ *
+ * Copyright (C) 2006 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * heavily based on kiss by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * 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 TIMER_H
+#define TIMER_H
+
+#include <qobject.h>
+
+#include <gst/gst.h>
+
+class QSlider;
+class QLabel;
+class QTimer;
+class QTime;
+
+
+
+class Timer : public QObject
+{
+ Q_OBJECT
+
+public:
+ Timer();
+ ~Timer ();
+
+ void start();
+ void stop();
+ void setPlaybin( GstElement *play );
+
+ long getTotalTimeMS() { return m_totalTimeMS; }
+ long getCurrentTimeMS() { return m_currentTimeMS; }
+
+ void seekPercent(uint percent);
+
+ QLabel* getLabel() const;
+ QSlider* getSlider() const;
+
+public slots:
+ void slotSeekStart();
+ void slotSeek();
+
+private slots:
+ void slotUpdate();
+
+private:
+ QTimer updateTimer;
+ QLabel *m_label;
+ QSlider *m_slider;
+ GstElement *m_play;
+ bool seeking;
+
+ long m_currentTimeMS;
+ long m_totalTimeMS;
+ guint64 m_len, m_pos;
+};
+
+#endif /* TIMER_H */
diff --git a/kaffeine/src/player-parts/gstreamer-part/video.cpp b/kaffeine/src/player-parts/gstreamer-part/video.cpp
new file mode 100644
index 0000000..0fc76cd
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/video.cpp
@@ -0,0 +1,332 @@
+/*
+ * video.cpp
+ *
+ * Copyright (C) 2006 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * heavily based on kiss by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qcursor.h>
+
+#include <kstatusbar.h>
+#include <ktoolbar.h>
+#include <kmenubar.h>
+#include <kdebug.h>
+
+#include <gst/interfaces/xoverlay.h>
+
+#include "video.h"
+
+#include "video.moc"
+
+
+
+VideoWindow::VideoWindow( QWidget *parent, GstElement *_element )
+ : QWidget (parent), m_width(0), m_height(0), m_aspectRatio(AUTO)
+{
+ m_play = NULL;
+
+ gst_object_ref( GST_OBJECT (_element) );
+ m_element = _element;
+
+ setPaletteBackgroundColor(QColor(0,0,0)); //black
+ setUpdatesEnabled(false);
+
+ connect( &m_mouseHideTimer, SIGNAL(timeout()), this, SLOT(slotHideMouse()) );
+}
+
+
+
+void VideoWindow::setPlaybin( GstElement *play )
+{
+ m_play = play;
+}
+
+
+
+VideoWindow::~VideoWindow()
+{
+ if ( m_element && GST_IS_X_OVERLAY(m_element) ) {
+ gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(m_element), 0 );
+ }
+
+ gst_object_unref( GST_OBJECT(m_element) );
+ kdDebug() << "VideoWindow: destructed" << endl;
+}
+
+
+
+void VideoWindow::refresh()
+{
+ /* expose overlay */
+ if ( m_element && GST_IS_X_OVERLAY(m_element) ) {
+ gst_x_overlay_set_xwindow_id( GST_X_OVERLAY (m_element), winId() );
+ gst_x_overlay_expose( GST_X_OVERLAY (m_element) );
+ }
+}
+
+
+
+void VideoWindow::paintEvent(QPaintEvent */*event*/)
+{
+ refresh();
+}
+
+
+
+void VideoWindow::mousePressEvent(QMouseEvent* mev)
+{
+ if ( mev->button()==Qt::RightButton ) {
+ emit signalRightClick( mev->globalPos() );
+ mev->accept();
+ }
+ else {
+ mev->ignore();
+ }
+}
+
+
+
+void VideoWindow::newCapsset( const GstCaps *caps )
+{
+ const GstStructure *s;
+ m_width = 0;
+ m_height = 0;
+
+ s = gst_caps_get_structure(caps, 0);
+ if (s) {
+ const GValue *par;
+
+ gst_structure_get_int(s, "width", &m_width);
+ gst_structure_get_int(s, "height", &m_height);
+ if ( (par = gst_structure_get_value (s, "pixel-aspect-ratio")) ) {
+ int num = gst_value_get_fraction_numerator(par),
+ den = gst_value_get_fraction_denominator(par);
+
+ if (num > den)
+ m_width = (int) ((float) num * m_width / den);
+ else
+ m_height = (int) ((float) den * m_height / num);
+ }
+ }
+
+ QSize frame = getFrameSize();
+ correctByAspectRatio( frame );
+ emit signalNewFrameSize( frame );
+ //set correct geometry
+ setGeometry();
+}
+
+
+
+void VideoWindow::newState()
+{
+ if ( !m_play )
+ return;
+
+ const GList *list = NULL;
+
+ g_object_get( G_OBJECT(m_play), "stream-info", &list, NULL );
+ for ( ; list != NULL; list = list->next ) {
+ GObject *info = (GObject *)list->data;
+ gint type;
+ GParamSpec *pspec;
+ GEnumValue *val;
+ GstPad *pad = NULL;
+
+ if ( !info )
+ continue;
+
+ g_object_get( info, "type", &type, NULL );
+ pspec = g_object_class_find_property( G_OBJECT_GET_CLASS (info), "type" );
+ val = g_enum_get_value( G_PARAM_SPEC_ENUM(pspec)->enum_class, type );
+
+ if ( !g_strcasecmp(val->value_nick, "video") ) {
+ GstCaps *caps;
+ g_object_get( info, "object", &pad, NULL );
+ if ( (caps=gst_pad_get_negotiated_caps(pad)) ) {
+ newCapsset( caps );
+ gst_caps_unref (caps);
+ return;
+ }
+ }
+ }
+ m_width = 0;
+ m_height = 0;
+ QSize frame = getFrameSize();
+ correctByAspectRatio( frame );
+ emit signalNewFrameSize( frame );
+ //set correct geometry
+ setGeometry();
+}
+
+
+
+void VideoWindow::setGeometry( int, int, int, int )
+{
+ QSize frame = getFrameSize();
+ QSize window = parentWidget()->size();
+ int x = 0, y = 0, width = 0, height = 0;
+
+ if ( frame.width() == 0 || frame.height() == 0 ) {
+ QWidget::setGeometry(0, 0, window.width(), window.height());
+ return;
+ }
+
+ correctByAspectRatio( frame );
+
+ float frameAspect = (float)frame.width() / (float)frame.height();
+ float windowAspect = (float)window.width() / (float)window.height();
+
+ if ( frameAspect >= windowAspect ) {
+ width = window.width();
+ height = (int)((float)width / frameAspect);
+ y = (window.height() - height) / 2;
+ }
+ else {
+ height = window.height();
+ width = (int)((float)height * frameAspect);
+ x = (window.width() - width) / 2;
+ }
+
+ //kdDebug() << "VideoWindow::setGeometry: " << x << " : " << y << " : " << width << " : " << height << endl;
+ QWidget::setGeometry( x, y, width, height );
+}
+
+
+
+void VideoWindow::setGeometry()
+{
+ setGeometry(0, 0, 0, 0);
+}
+
+
+
+void VideoWindow::correctByAspectRatio( QSize& frame )
+{
+ float factor = 0;
+
+ switch ( m_aspectRatio ) {
+ case AUTO: return;
+ case FOURBYTHREE: factor = 4.0 / 3.0; break;
+ case ANAMORPHIC: factor = 16.0 / 9.0; break;
+ case DVB: factor = 2.11; break;
+ case SQUARE: factor = 1.0; break;
+ }
+
+ float frameAspect = (float)frame.width() / (float)frame.height();
+ factor = factor / frameAspect;
+ if ( factor > 1.0 )
+ frame.setWidth((int)((float)frame.width() * factor));
+ else
+ frame.setHeight((int)((float)frame.height() / factor));
+}
+
+
+
+void VideoWindow::slotAspectRatioAuto()
+{
+ m_aspectRatio = AUTO;
+ QSize frame = getFrameSize();
+ correctByAspectRatio( frame );
+ emit signalNewFrameSize( frame );
+ setGeometry();
+}
+
+
+
+void VideoWindow::slotAspectRatio4_3()
+{
+ m_aspectRatio = FOURBYTHREE;
+ QSize frame = getFrameSize();
+ correctByAspectRatio( frame );
+ emit signalNewFrameSize( frame );
+ setGeometry();
+}
+
+
+
+void VideoWindow::slotAspectRatioAnamorphic()
+{
+ m_aspectRatio = ANAMORPHIC;
+ QSize frame = getFrameSize();
+ correctByAspectRatio( frame );
+ emit signalNewFrameSize( frame );
+ setGeometry();
+}
+
+
+
+void VideoWindow::slotAspectRatioDVB()
+{
+ m_aspectRatio = DVB;
+ QSize frame = getFrameSize();
+ correctByAspectRatio( frame );
+ emit signalNewFrameSize( frame );
+ setGeometry();
+}
+
+
+
+void VideoWindow::slotAspectRatioSquare()
+{
+ m_aspectRatio = SQUARE;
+ QSize frame = getFrameSize();
+ correctByAspectRatio( frame );
+ emit signalNewFrameSize( frame );
+ setGeometry();
+}
+
+/******** mouse cursor hiding on fullscreen ****/
+
+void VideoWindow::startMouseHideTimer()
+{
+ m_mouseHideTimer.start( 5000 );
+ setMouseTracking( true );
+}
+
+
+
+void VideoWindow::stopMouseHideTimer()
+{
+ m_mouseHideTimer.stop();
+ setMouseTracking( false );
+ setCursor( QCursor(Qt::ArrowCursor) );
+}
+
+
+
+void VideoWindow::slotHideMouse()
+{
+ setCursor( QCursor(Qt::BlankCursor) );
+}
+
+
+
+void VideoWindow::mouseMoveEvent( QMouseEvent *mev )
+{
+ if ( cursor().shape() == Qt::BlankCursor )
+ setCursor( QCursor(Qt::ArrowCursor) );
+ mev->ignore();
+}
diff --git a/kaffeine/src/player-parts/gstreamer-part/video.h b/kaffeine/src/player-parts/gstreamer-part/video.h
new file mode 100644
index 0000000..5878066
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/video.h
@@ -0,0 +1,95 @@
+/*
+ * video.h
+ *
+ * Copyright (C) 2006 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * heavily based on kiss by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * 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 VIDEO_H
+#define VIDEO_H
+
+#include <qwidget.h>
+#include <kapplication.h>
+
+#include <qsize.h>
+
+#include <gst/gst.h>
+
+
+
+class VideoWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ VideoWindow( QWidget *parent, GstElement *element );
+ ~VideoWindow ();
+
+ enum AspectRatio {
+ AUTO,
+ FOURBYTHREE,
+ ANAMORPHIC,
+ DVB,
+ SQUARE
+ };
+
+ void newState();
+ void newCapsset( const GstCaps *caps );
+ void setPlaybin( GstElement *play );
+
+ void refresh();
+
+ QSize getFrameSize() { return QSize(m_width, m_height); }
+
+ void startMouseHideTimer();
+ void stopMouseHideTimer();
+
+signals:
+ void signalNewFrameSize( const QSize& );
+ void signalRightClick( const QPoint& );
+
+public slots:
+// void setGeometry(const QRect&);
+ void setGeometry();
+ void setGeometry( int x, int y, int width, int heigth );
+ void slotAspectRatioAuto();
+ void slotAspectRatio4_3();
+ void slotAspectRatioAnamorphic();
+ void slotAspectRatioDVB();
+ void slotAspectRatioSquare();
+
+private slots:
+ void slotHideMouse();
+
+protected:
+ void paintEvent( QPaintEvent *event );
+ void mousePressEvent( QMouseEvent* );
+ void mouseMoveEvent( QMouseEvent* );
+
+private:
+ void correctByAspectRatio( QSize &frame );
+
+private:
+ GstElement *m_element, *m_play;
+ int m_width, m_height;
+ AspectRatio m_aspectRatio;
+ QTimer m_mouseHideTimer;
+};
+
+#endif /* VIDEO_H */
diff --git a/kaffeine/src/player-parts/gstreamer-part/videosettings.cpp b/kaffeine/src/player-parts/gstreamer-part/videosettings.cpp
new file mode 100644
index 0000000..2e59359
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/videosettings.cpp
@@ -0,0 +1,95 @@
+/*
+ * videosettings.cpp
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <klocale.h>
+
+#include <qslider.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qnamespace.h>
+
+#include "videosettings.h"
+#include "videosettings.moc"
+
+
+VideoSettings::VideoSettings(int hue, int sat, int contr, int bright, QWidget *parent, const char *name)
+ : KDialogBase(KDialogBase::Plain, i18n("Video Settings"), KDialogBase::Default | KDialogBase::Close, KDialogBase::Close, parent, name, false)
+{
+ setInitialSize(QSize(450,200), true);
+ QWidget* page = plainPage();
+
+ QGridLayout* grid = new QGridLayout(page, 4, 2);
+ grid->setSpacing(5);
+
+ QLabel* hueText = new QLabel(i18n("Hue"), page);
+ hueText->setAlignment(AlignRight);
+ m_hueSlider = new QSlider(Qt::Horizontal, page);
+ m_hueSlider->setRange(-1000, 1000);
+ m_hueSlider->setSteps(10, 100);
+ m_hueSlider->setValue(hue);
+ connect(m_hueSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewHue(int)));
+ grid->addWidget(hueText, 0, 0);
+ grid->addWidget(m_hueSlider, 0, 1);
+
+ QLabel* satText = new QLabel(i18n("Saturation"), page);
+ satText->setAlignment(AlignRight);
+ m_satSlider = new QSlider(Qt::Horizontal, page);
+ m_satSlider->setRange(-1000, 1000);
+ m_satSlider->setSteps(10, 100);
+ m_satSlider->setValue(sat);
+ connect(m_satSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewSaturation(int)));
+ grid->addWidget(satText, 1, 0);
+ grid->addWidget(m_satSlider, 1, 1);
+
+ QLabel* contrastText = new QLabel(i18n("Contrast"), page);
+ contrastText->setAlignment(AlignRight);
+ m_contrastSlider = new QSlider(Qt::Horizontal, page);
+ m_contrastSlider->setRange(-1000, 1000);
+ m_contrastSlider->setSteps(10, 100);
+ m_contrastSlider->setValue(contr);
+ connect(m_contrastSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewContrast(int)));
+ grid->addWidget(contrastText, 2, 0);
+ grid->addWidget(m_contrastSlider, 2, 1);
+
+ QLabel* brightText = new QLabel(i18n("Brightness"), page);
+ brightText->setAlignment(AlignRight);
+ m_brightSlider = new QSlider(Qt::Horizontal, page);
+ m_brightSlider->setRange(-1000, 1000);
+ m_brightSlider->setSteps(10, 100);
+ m_brightSlider->setValue(bright);
+ connect(m_brightSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewBrightness(int)));
+ grid->addWidget(brightText, 3, 0);
+ grid->addWidget(m_brightSlider, 3, 1);
+
+ connect(this, SIGNAL(defaultClicked()), this, SLOT(slotSetDefaultValues()));
+}
+
+VideoSettings::~VideoSettings()
+{
+
+}
+
+void VideoSettings::slotSetDefaultValues()
+{
+ m_hueSlider->setValue(1000);
+ m_satSlider->setValue(0);
+ m_contrastSlider->setValue(0);
+ m_brightSlider->setValue(0);
+}
diff --git a/kaffeine/src/player-parts/gstreamer-part/videosettings.h b/kaffeine/src/player-parts/gstreamer-part/videosettings.h
new file mode 100644
index 0000000..62be08e
--- /dev/null
+++ b/kaffeine/src/player-parts/gstreamer-part/videosettings.h
@@ -0,0 +1,58 @@
+/*
+ * videosettings.h
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 VIDEOSETTINGS_H
+#define VIDEOSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+
+class QSlider;
+
+class VideoSettings : public KDialogBase
+{
+
+ Q_OBJECT
+
+public:
+ VideoSettings(int hue, int sat, int contr, int bright, QWidget *parent=0, const char *name=0);
+ ~VideoSettings();
+
+signals:
+ void signalNewHue(int);
+ void signalNewSaturation(int);
+ void signalNewContrast(int);
+ void signalNewBrightness(int);
+
+private slots:
+
+ void slotSetDefaultValues();
+
+private:
+ QSlider* m_hueSlider;
+ QSlider* m_satSlider;
+ QSlider* m_contrastSlider;
+ QSlider* m_brightSlider;
+};
+
+#endif /* VIDEOSETTINGS_H */
diff --git a/kaffeine/src/player-parts/kaffeine-part/Makefile.am b/kaffeine/src/player-parts/kaffeine-part/Makefile.am
new file mode 100644
index 0000000..7202c10
--- /dev/null
+++ b/kaffeine/src/player-parts/kaffeine-part/Makefile.am
@@ -0,0 +1,12 @@
+lib_LTLIBRARIES = libkaffeinepart.la
+
+INCLUDES = $(all_includes)
+
+kaffeineincludedir = $(includedir)/kaffeine
+kaffeineinclude_HEADERS = kaffeinepart.h mrl.h
+
+METASOURCES = AUTO
+
+libkaffeinepart_la_SOURCES = kaffeinepart.cpp mrl.cpp playlistimport.cpp
+libkaffeinepart_la_LIBADD = $(LIB_KPARTS) $(all_libraries)
+libkaffeinepart_la_LDFLAGS = -no-undefined -avoid-version
diff --git a/kaffeine/src/player-parts/kaffeine-part/kaffeinepart.cpp b/kaffeine/src/player-parts/kaffeine-part/kaffeinepart.cpp
new file mode 100644
index 0000000..4be8b73
--- /dev/null
+++ b/kaffeine/src/player-parts/kaffeine-part/kaffeinepart.cpp
@@ -0,0 +1,58 @@
+/*
+ * kaffeinepart.cpp
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 "kaffeinepart.h"
+#include <kapplication.h>
+#include <kservice.h>
+#include <ktrader.h>
+#include <kmessagebox.h>
+#include <krun.h>
+#include <klocale.h>
+
+#include "kaffeinepart.moc"
+
+KaffeinePart::KaffeinePart(QObject* parent, const char* name)
+ : KParts::ReadOnlyPart(parent, name)
+{
+}
+
+KaffeinePart::~KaffeinePart()
+{
+}
+
+bool KaffeinePart::installDistroCodec(QWidget* parent, const QString& engine, const QString& codec)
+{
+ QString query = QString("[X-KDE-Kaffeine-codec] == '%1' and \
+ [X-KDE-Kaffeine-engine] == '%2'").arg(codec).arg(engine);
+
+ KService::Ptr service = KTrader::self()->query( "Kaffeine/CodecInstall", query).first();
+
+ if (!service)
+ return false;
+
+ QString installScript = service->exec();
+
+ if (installScript.isNull())
+ return false;
+
+ KRun::runCommand(installScript);
+ return true;
+}
+
diff --git a/kaffeine/src/player-parts/kaffeine-part/kaffeinepart.h b/kaffeine/src/player-parts/kaffeine-part/kaffeinepart.h
new file mode 100644
index 0000000..e569ead
--- /dev/null
+++ b/kaffeine/src/player-parts/kaffeine-part/kaffeinepart.h
@@ -0,0 +1,222 @@
+/*
+ * kaffeinepart.h
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 KAFFEINEPART_H
+#define KAFFEINEPART_H
+
+#include <kparts/part.h>
+
+#include "mrl.h"
+
+/*
+ * Base-Class for Kaffeine-Parts. Derive from this class if you want to develop a player part for Kaffeine.
+ * At least you have to reimplement openURL(const MRL&) and to emit signalTrackFinished()!
+ *
+ * IMPORTANT: Forward the double-click, middle-click and wheel mouse-events to the parent widget (don't use
+ * QMouseEvent::accept())!
+ *
+ * @author Jürgen Kofler
+ */
+
+class KDE_EXPORT KaffeinePart : public KParts::ReadOnlyPart
+{
+ Q_OBJECT
+public:
+ KaffeinePart(QObject* parent, const char* name);
+ virtual ~KaffeinePart();
+
+ /*
+ * Playback in progress?
+ */
+ virtual bool isPlaying()
+ {
+ return false;
+ }
+
+ /*
+ * Playback paused?
+ */
+ virtual bool isPaused()
+ {
+ return false;
+ }
+
+ /*
+ * Should look like "*.mp3 *.MP3 *.avi *.AVI", used as file filter for directory import
+ */
+ virtual QString supportedExtensions()
+ {
+ return QString::null;
+ }
+
+ /*
+ * Current volume. In percent.
+ */
+ virtual uint volume() const
+ {
+ return 0;
+ }
+ /*
+ * Current position. In percent.
+ */
+ virtual uint position() const
+ {
+ return 0;
+ }
+
+ /*
+ * DVD etc.
+ */
+ virtual bool hasChapters()
+ {
+ return false;
+ }
+
+ virtual void setDVDChapter(uint) {}
+
+ /*
+ * Contain the stream video?
+ */
+ virtual bool hasVideo()
+ {
+ return false;
+ }
+
+signals:
+ /*
+ * Frame size of video changed
+ */
+ void signalNewFrameSize(const QSize& frame);
+
+ /*
+ * New meta information available
+ */
+ void signalNewMeta(const MRL &mrl);
+
+ /*
+ * Playback of current track finished
+ */
+ void signalTrackFinished();
+
+ /*
+ * Playback failed
+ */
+ void signalPlaybackFailed();
+
+ /*
+ * User pressed play button but queue is empty
+ */
+ void signalRequestCurrentTrack();
+
+ /*
+ * User pressed next button but no track left in queue
+ */
+ void signalRequestNextTrack();
+
+ /*
+ * User pressed previous button but queue is empty
+ */
+ void signalRequestPreviousTrack();
+
+ void signalToggleMinimalMode();
+
+public slots:
+ /*
+ * You have to reimplement this! Opens an url and plays it.
+ */
+ virtual bool openURL(const MRL &mrl) = 0;
+
+ /*
+ * Tells the player we go fullscreen now. Hide controls etc.
+ */
+ virtual void slotPrepareForFullscreen(bool)
+ {}
+
+ /*
+ * DVD etc.
+ */
+ virtual void playNextChapter()
+ {}
+
+ /*
+ * DVD etc.
+ */
+ virtual void playPreviousChapter()
+ {}
+
+ /*
+ * Toggle play/pause
+ */
+ virtual void slotTogglePause(bool pauseLive = true)
+ {
+ pauseLive = true;
+ }
+
+ /*
+ * Stop playback
+ */
+ virtual void slotStop()
+ {}
+
+ /*
+ * Sets Volume. In percent.
+ */
+ virtual void slotSetVolume(uint)
+ {}
+
+ /*
+ * Sets Position. In percent.
+ */
+ virtual void slotSetPosition(uint)
+ {}
+
+ virtual void slotPosPlusSmall()
+ {}
+
+ virtual void slotPosMinusSmall()
+ {}
+
+ /*
+ * Turn mute on/off
+ */
+ virtual void slotMute()
+ {}
+
+ /*
+ * Execute distro-dependent actions to install codecs
+ */
+ static bool installDistroCodec(QWidget* parent, const QString& engine, const QString& codec);
+
+private:
+ /*
+ * Don't reimplement this, a player should be able to stream media
+ */
+ bool openFile()
+ {
+ return false;
+ }
+
+ bool openURL(const KURL &url)
+ {
+ return openURL(MRL(url));
+ }
+};
+
+#endif /* KAFFEINEPART_H */
diff --git a/kaffeine/src/player-parts/kaffeine-part/mrl.cpp b/kaffeine/src/player-parts/kaffeine-part/mrl.cpp
new file mode 100644
index 0000000..9ab6e52
--- /dev/null
+++ b/kaffeine/src/player-parts/kaffeine-part/mrl.cpp
@@ -0,0 +1,47 @@
+/*
+ * mrl.cpp
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 "mrl.h"
+
+MRL::MRL()
+{
+ reset();
+}
+
+MRL::MRL(const KURL& url, const QString& title, const QTime& length, const QString& mime,
+ const QString& artist, const QString& album, const QString& track,
+ const QString& year, const QString& genre, const QString& comment,
+ const QStringList& subtitleFiles, const int currentSubtitle) :
+ m_url(url.prettyURL()), m_kurl(url), m_title(title), m_artist(artist), m_album(album), m_track(track), m_year(year), m_genre(genre), m_comment(comment),
+ m_mime(mime), m_length(length), m_subtitleFiles(subtitleFiles), m_currentSubtitle(currentSubtitle)
+{}
+
+MRL::MRL(const QString& url, const QString& title, const QTime& length, const QString& mime,
+ const QString& artist, const QString& album, const QString& track,
+ const QString& year, const QString& genre, const QString& comment,
+ const QStringList& subtitleFiles, const int currentSubtitle) :
+ m_url(url), m_kurl(KURL::fromPathOrURL(url)), m_title(title), m_artist(artist),
+ m_album(album), m_track(track), m_year(year), m_genre(genre), m_comment(comment),
+ m_mime(mime), m_length(length), m_subtitleFiles(subtitleFiles), m_currentSubtitle(currentSubtitle)
+{}
+
+MRL::~MRL()
+{
+}
diff --git a/kaffeine/src/player-parts/kaffeine-part/mrl.h b/kaffeine/src/player-parts/kaffeine-part/mrl.h
new file mode 100644
index 0000000..04c6d27
--- /dev/null
+++ b/kaffeine/src/player-parts/kaffeine-part/mrl.h
@@ -0,0 +1,96 @@
+/*
+ * mrl.h
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 MRL_H
+#define MRL_H
+
+#include <qdatetime.h>
+#include <qstringlist.h>
+
+#include <kurl.h>
+
+/*
+ * media resource locator
+ * holds url and meta info
+ */
+
+class KDE_EXPORT MRL
+{
+public:
+ MRL();
+ /* don't use this constructor to prevent encoding problems */
+ MRL(const KURL& url, const QString& title = QString::null, const QTime& length = QTime(), const QString& mime = QString::null,
+ const QString& artist = QString::null, const QString& album = QString::null, const QString& track = QString::null,
+ const QString& year = QString::null, const QString& genre = QString::null, const QString& comment = QString::null,
+ const QStringList& subtitleFiles = QStringList(), const int currentSubtitle = -1);
+ MRL(const QString& url, const QString& title = QString::null, const QTime& length = QTime(), const QString& mime = QString::null,
+ const QString& artist = QString::null, const QString& album = QString::null, const QString& track = QString::null,
+ const QString& year = QString::null, const QString& genre = QString::null, const QString& comment = QString::null,
+ const QStringList& subtitleFiles = QStringList(), const int currentSubtitle = -1);
+ virtual ~MRL();
+
+ void reset() { m_url = QString::null; m_kurl = KURL(); }
+ bool isEmpty() { return (m_url == QString::null); }
+
+ const QString& url() const { return m_url; }
+ const KURL& kurl() const { return m_kurl; }
+ const QString& title() const { return m_title; }
+ const QString& artist() const { return m_artist; }
+ const QString& album() const { return m_album; }
+ const QString& track() const { return m_track; }
+ const QString& year() const { return m_year; }
+ const QString& genre() const { return m_genre; }
+ const QString& comment() const { return m_comment; }
+ const QString& mime() const { return m_mime; }
+ const QTime& length() const { return m_length; }
+ const QStringList& subtitleFiles() const { return m_subtitleFiles; }
+ int currentSubtitle() const { return m_currentSubtitle; }
+
+ void setURL(const QString& url) { m_url = url; m_kurl = KURL(url); }
+ void setTitle(const QString& title) { m_title = title; }
+ void setArtist(const QString& artist) { m_artist = artist; }
+ void setAlbum(const QString& album) { m_album = album; }
+ void setTrack(const QString& track) { m_track = track; }
+ void setYear(const QString& year) { m_year = year; }
+ void setGenre(const QString& genre) { m_genre = genre; }
+ void setComment(const QString& comment) { m_comment = comment; }
+ void setMime(const QString& mime) { m_mime = mime; }
+ void setLength(const QTime& length) { m_length = length; }
+ void setSubtitleFiles(const QStringList& urls) { m_subtitleFiles = urls; }
+ void addSubtitleFile(const QString& url) { m_subtitleFiles.append(url); }
+ void setCurrentSubtitle(int sub) { m_currentSubtitle = sub; }
+
+private:
+ QString m_url;
+ KURL m_kurl;
+ QString m_title;
+ QString m_artist;
+ QString m_album;
+ QString m_track;
+ QString m_year;
+ QString m_genre;
+ QString m_comment;
+ QString m_mime;
+ QTime m_length;
+ QStringList m_subtitleFiles;
+ int m_currentSubtitle; /* -1 -> off */
+};
+
+#endif /* MRL_H */
diff --git a/kaffeine/src/player-parts/kaffeine-part/playlistimport.cpp b/kaffeine/src/player-parts/kaffeine-part/playlistimport.cpp
new file mode 100644
index 0000000..13b5d63
--- /dev/null
+++ b/kaffeine/src/player-parts/kaffeine-part/playlistimport.cpp
@@ -0,0 +1,685 @@
+/*
+ * playlistimport.cpp
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <qdom.h>
+#include <qregexp.h>
+#include <qxml.h>
+
+#include <kdebug.h>
+#include <kio/netaccess.h>
+
+#include "playlistimport.h"
+
+class MyXMLParser : public QXmlDefaultHandler
+{
+
+public:
+ QValueList<MRL> mrls;
+ bool isKaffeinePlaylist;
+
+
+ MyXMLParser() : isKaffeinePlaylist(false)
+ {}
+
+ bool startElement(const QString&, const QString&,
+ const QString &qname, const QXmlAttributes &att)
+ {
+
+ if (qname == "playlist")
+ if (att.value("client") == "kaffeine")
+ {
+ isKaffeinePlaylist = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+ if (qname != "entry") return true;
+
+ QStringList subs = QStringList();
+ int currentSub = -1;
+
+ if ((!att.value("subs").isNull()) && (!att.value("subs").isEmpty()))
+ subs = QStringList::split("&",att.value("subs"),false);
+ if ((!att.value("subs").isNull()) && (!att.value("subs").isEmpty()))
+ {
+ bool ok;
+ currentSub = att.value("currentSub").toInt(&ok);
+ if (!ok)
+ currentSub = -1;
+ }
+
+ // kdDebug() << "PlaylistImport: kaffeine import url: " << att.value("url") << endl;
+ mrls.append(MRL(att.value("url"), att.value("title"), PlaylistImport::stringToTime(att.value("length")),
+ att.value("mime"), att.value("artist"), att.value("album"), att.value("track"),
+ att.value("year"), att.value("genre"), QString::null, subs, currentSub));
+ return true;
+ }
+
+};
+
+bool PlaylistImport::kaffeine(const QString& playlist, QValueList<MRL>& mrls)
+{
+ kdDebug() << "PlaylistImport: kaffeine: " << playlist << endl;
+ QFile file(playlist);
+ if (!file.open(IO_ReadOnly)) return false;
+
+ QXmlInputSource source(&file);
+ QXmlSimpleReader reader;
+
+ MyXMLParser parser;
+ reader.setContentHandler(&parser);
+ reader.parse(source);
+ file.close();
+
+ if (!parser.isKaffeinePlaylist)
+ {
+ return false;
+ }
+ else
+ {
+ QValueList<MRL>::ConstIterator end(parser.mrls.end());
+ for (QValueList<MRL>::ConstIterator it = parser.mrls.begin(); it != end; ++it)
+ mrls.append(*it);
+ return true;
+ }
+}
+
+class NoatunXMLParser : public QXmlDefaultHandler
+{
+
+public:
+ QValueList<MRL> mrls;
+ bool isNoatunPlaylist;
+
+ NoatunXMLParser(): isNoatunPlaylist(false)
+ {}
+
+ bool startElement(const QString&, const QString &,
+ const QString &qname, const QXmlAttributes &att)
+ {
+
+ if (qname == "playlist")
+ if (att.value("client") == "noatun")
+ {
+ isNoatunPlaylist = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+ if (qname != "item") return true;
+
+ QString title = att.value("title");
+
+ if (title.isNull())
+ title = att.value("url");
+
+ bool ok;
+ QTime length;
+ int time = att.value("length").toInt(&ok);
+ if ((ok) && (time > 0))
+ {
+ length = QTime().addMSecs(time);
+ }
+
+ kdDebug() << "PlaylistImport: noatun import url: " << att.value("url") << endl;
+ mrls.append(MRL(att.value("url"), title, length, QString::null, att.value("author"),
+ att.value("album"), att.value("track")));
+
+ return true;
+ }
+
+};
+
+bool PlaylistImport::noatun(const QString& playlist, QValueList<MRL>& mrls)
+{
+ kdDebug() << "PlaylistImport: noatun: " << playlist << endl;
+ QFile file(playlist);
+ if (!file.open(IO_ReadOnly)) return false;
+
+ QXmlInputSource source(&file);
+ QXmlSimpleReader reader;
+
+ NoatunXMLParser parser;
+ reader.setContentHandler(&parser);
+ reader.parse(source);
+ file.close();
+
+ if (!parser.isNoatunPlaylist)
+ {
+ return false;
+ }
+ else
+ {
+ QValueList<MRL>::ConstIterator end(parser.mrls.end());
+ for (QValueList<MRL>::ConstIterator it = parser.mrls.begin(); it != end; ++it)
+ mrls.append(*it);
+ return true;
+ }
+}
+
+bool PlaylistImport::m3u(const QString& playlist , QValueList<MRL>& mrls)
+{
+ kdDebug() << "PlaylistImport: m3u: " << playlist << endl;
+ QFile file(playlist);
+ if (!file.open(IO_ReadOnly)) return false;
+ QTextStream stream(&file);
+
+ // if (stream.readLine().upper() != "#EXTM3U") return false;
+ QString url;
+ int time;
+ bool ok;
+ QTime length;
+ QString title;
+ KURL kUrl;
+ bool foundAnyUrl = false;
+ KURL plurl(playlist);
+ plurl.setFileName ("");
+
+ while (!stream.eof())
+ {
+ url = stream.readLine();
+ time = 0;
+ title = QString::null;
+ length = QTime();
+ if (url.left(1) == "#")
+ {
+ if (url.left(7).upper() == "#EXTINF")
+ {
+ url = url.remove(0,8);
+ time = url.section(",", 0,0).toInt(&ok);
+ if ((ok) && (time > 0))
+ {
+ length = QTime().addSecs(time);
+ }
+
+ title = url.section(",",1,1);
+ url = stream.readLine();
+ }
+ else
+ {
+ continue;
+ }
+ }
+ url.replace ('\\', '/'); /* for windows styled urls */
+ kUrl = KURL (plurl, url); /* maybe a relative url */
+ if (kUrl.isValid())
+ {
+ kdDebug() << "PlaylistImport: m3u import url: " << kUrl.prettyURL() << endl;
+
+ MRL mrl;
+ if (kUrl.isLocalFile())
+ mrl.setURL(kUrl.path());
+ else
+ mrl.setURL(kUrl.prettyURL());
+ if (title.isNull())
+ title = kUrl.fileName();
+ mrl.setTitle(title);
+ mrl.setLength(length);
+
+ mrls.append(mrl);
+
+ foundAnyUrl = true;
+ }
+ else
+ kdDebug() << "PlaylistImport: M3U: Not valid: " << kUrl.prettyURL() << endl;
+ }
+ file.close();
+ if (foundAnyUrl)
+ return true;
+ else
+ return false;
+}
+
+bool PlaylistImport::pls(const QString& playlist, QValueList<MRL>& mrls)
+{
+ kdDebug() << "PlaylistImport: pls: " << playlist << endl;
+ QFile file(playlist);
+ if (!file.open(IO_ReadOnly)) return false;
+
+ QTextStream stream(&file);
+
+ //if (stream.readLine().upper() != "[PLAYLIST]") return false;
+
+ // Better Handling of pls playlists - Taken from amaroK - amarok.kde.org
+ // Counted number of "File#=" lines.
+ uint entryCnt = 0;
+ // Value of the "NumberOfEntries=#" line.
+ uint numberOfEntries = 0;
+ bool havePlaylistSection = false;
+ QString tmp;
+ QStringList lines;
+
+ // set Regexp keywords, Be case insensitive
+ const QRegExp regExp_NumberOfEntries("^NumberOfEntries\\s*=\\s*\\d+$", false);
+ const QRegExp regExp_File("^File\\d+\\s*=", false);
+ const QRegExp regExp_Title("^Title\\d+\\s*=", false);
+ const QRegExp regExp_Length("^Length\\d+\\s*=\\s*-?\\d+$", false);
+ const QRegExp regExp_Version("^Version\\s*=\\s*\\d+$", false);
+ const QString section_playlist("[playlist]");
+
+ /* Preprocess the input data.
+ * Read the lines into a buffer; Cleanup the line strings;
+ * Count the entries manually and read "NumberOfEntries".
+ */
+ while (!stream.atEnd()) {
+ tmp = stream.readLine();
+ tmp = tmp.stripWhiteSpace();
+ if (tmp.isEmpty())
+ continue;
+ lines.append(tmp);
+
+ if (tmp == section_playlist) {
+ havePlaylistSection = true;
+ continue;
+ }
+
+ if (tmp.contains(regExp_File)) {
+ entryCnt++;
+ continue;
+ }
+
+ if (tmp.contains(regExp_NumberOfEntries)) {
+ numberOfEntries = tmp.section('=', -1).stripWhiteSpace().toUInt();
+ continue;
+ }
+ }
+
+ file.close();
+
+ if (numberOfEntries != entryCnt) {
+ kdError() << "PlaylistImport: Invalid \"NumberOfEntries\" value in .pls playlist. "
+ << "NumberOfEntries=" << numberOfEntries << " counted="
+ << entryCnt << endl;
+ /* Corrupt file. The "NumberOfEntries" value is
+ * not correct. Fix it by setting it to the manually
+ * counted number and go on parsing.
+ */
+ numberOfEntries = entryCnt;
+ }
+ // If we have no Entries, return
+ if (!numberOfEntries)
+ return true;
+
+ int time;
+ bool ok;
+ uint index;
+ bool inPlaylistSection = false;
+ QString* titles = new QString[entryCnt];
+ QString* files = new QString[entryCnt];
+ QTime* length = new QTime[entryCnt];
+
+ QStringList::const_iterator i = lines.begin(), end = lines.end();
+ for ( ; i != end; ++i) {
+ if (!inPlaylistSection && havePlaylistSection) {
+ /* The playlist begins with the "[playlist]" tag.
+ * Skip everything before this.
+ */
+ if ((*i) == section_playlist)
+ inPlaylistSection = true;
+ continue;
+ }
+ if ((*i).contains(regExp_File)) {
+ // Have a "File#=XYZ" line.
+ index = extractIndex(*i);
+ if (index > numberOfEntries || index == 0)
+ continue;
+ files[index-1] = (*i).section('=', 1).stripWhiteSpace();
+ continue;
+ }
+ if ((*i).contains(regExp_Title)) {
+ // Have a "Title#=XYZ" line.
+ index = extractIndex(*i);
+ if (index > numberOfEntries || index == 0)
+ continue;
+ titles[index-1] = (*i).section('=', 1).stripWhiteSpace();
+ continue;
+ }
+ if ((*i).contains(regExp_Length)) {
+ // Have a "Length#=XYZ" line.
+ index = extractIndex(*i);
+ if (index > numberOfEntries || index == 0)
+ continue;
+ tmp = (*i).section('=', 1).stripWhiteSpace();
+ time = tmp.toInt(&ok);
+ if ( !(ok) || !(time > 0) ) continue;
+ length[index-1] = QTime().addSecs(time);
+ continue;
+ }
+ if ((*i).contains(regExp_NumberOfEntries)) {
+ // Have the "NumberOfEntries=#" line.
+ continue;
+ }
+ if ((*i).contains(regExp_Version)) {
+ // Have the "Version=#" line.
+ tmp = (*i).section('=', 1).stripWhiteSpace();
+ // We only support Version=2
+ if (tmp.toUInt(&ok) != 2)
+ kdWarning() << "PlaylistImport: pls: Unsupported version." << endl;
+ continue;
+ }
+ kdWarning() << "PlaylistImport: pls: Unrecognized line: \"" << *i << "\"" << endl;
+ }
+
+ for (uint i=0; i<entryCnt; i++)
+ {
+ if (files[i].isNull()) continue;
+ kdDebug() << "PlaylistImport: pls import url: " << files[i] << endl;
+ if (titles[i].isNull())
+ titles[i] = files[i];
+ mrls.append(MRL(files[i], titles[i], length[i]));
+ }
+
+ delete [] titles;
+ delete [] files;
+ delete [] length;
+
+ return true;
+}
+
+// Helper for pls import
+uint PlaylistImport::extractIndex( const QString &str )
+{
+ /* Extract the index number out of a .pls line.
+ * Example:
+ * extractIndex("File2=foobar") == 2
+ */
+ bool ok = false;
+ unsigned int ret;
+ QString tmp(str.section('=', 0, 0));
+ tmp.remove(QRegExp("^\\D*"));
+ ret = tmp.stripWhiteSpace().toUInt(&ok);
+ if (!ok)
+ kdError() << "PlaylistImport: pls: Corrupt pls file, Error extracting index." << endl;
+ return ret;
+}
+
+bool PlaylistImport::ram(const MRL& playlist, QValueList<MRL>& mrls, QWidget* parent)
+{
+ Q_ULONG result;
+ char buf[10];
+
+ kdDebug() << "PlaylistImport: ram: " << playlist.url() << endl;
+ memset( buf, 0, 10 );
+
+ if (playlist.kurl().isLocalFile()) {
+ QFile file(playlist.kurl().path());
+ if (!file.open(IO_ReadOnly)) {
+ kdError() << "PlaylistImport: Can't open " << playlist.url() << endl;
+ return false;
+ }
+ result = file.readBlock(buf, 4);
+ file.close();
+ if (result != 4) {
+ kdError() << "PlaylistImport: Can't read " << playlist.url() << endl;
+ return false;
+ }
+ if (buf[0]=='.' && buf[1]=='R' && buf[2]=='M' && buf[3]=='F') {
+ kdDebug() << "PlaylistImport: Seems to be a real media file" << endl;
+ return false;
+ }
+ }
+ else if (!playlist.kurl().protocol().startsWith("http")) {
+ kdError() << "PlaylistImport: ram: Download via " << playlist.kurl().protocol() << " protocol not supported." << endl;
+ return false;
+ }
+
+ kdDebug() << "PlaylistImport: Seems to be a ram playlist!" << endl;
+
+ QString localFile, url;
+ if (KIO::NetAccess::mimetype(playlist.kurl(), parent) == "application/vnd.rn-realmedia") {
+ kdDebug() << "PlaylistImport: Seems to be a real media file" << endl;
+ return false;
+ }
+
+ if (KIO::NetAccess::download(playlist.kurl(), localFile, parent))
+ {
+ QFile plFile(localFile);
+ if (!plFile.open(IO_ReadOnly)) return false;
+ QTextStream stream( &plFile );
+
+ while (!stream.eof())
+ {
+ url = stream.readLine();
+
+ if (url[0] == '#') continue; /* ignore comments */
+ if (url == "--stop--") break; /* stop line */
+
+ if ((url.left(7) == "rtsp://") || (url.left(6) == "pnm://") || (url.left(7) == "http://"))
+ {
+ kdDebug() << "PlaylistImport: ram import url: " << url << endl;
+ mrls.append(MRL(url, url));
+ }
+ }
+ }
+ else {
+ kdError() << "PlaylistImport: " << KIO::NetAccess::lastErrorString() << endl;
+ return false;
+ }
+
+ return true;
+}
+
+/**********************************************************************************
+ * load asx playlist *
+ * spec: http://msdn.microsoft.com/library/en-us/wmplay/mmp_sdk/asxelement.asp *
+ **********************************************************************************/
+
+bool PlaylistImport::asx(const QString& playlist, QValueList<MRL>& mrls)
+{
+ kdDebug() << "PlaylistImport: asx: " << playlist << endl;
+ QFile file(playlist);
+ if (!file.open(IO_ReadOnly)) return false;
+
+ QDomDocument doc;
+ QString errorMsg;
+ int errorLine, errorColumn;
+ if (!doc.setContent(&file, &errorMsg, &errorLine, &errorColumn))
+ {
+ kdError() << "PlaylistImport: XML parse error: " << errorMsg
+ << " (line: " << errorLine << ", column: " << errorColumn << ")" << endl;
+ return false;
+ }
+
+ QDomElement root = doc.documentElement();
+
+ QString url;
+ QString title;
+ QString author;
+ QTime length;
+ QString duration;
+
+ if (root.nodeName().lower() != "asx") return false;
+
+ QDomNode node = root.firstChild();
+ QDomNode subNode;
+ QDomElement element;
+
+ while (!node.isNull())
+ {
+ url = QString::null;
+ title = QString::null;
+ author = QString::null;
+ length = QTime();
+ if (node.nodeName().lower() == "entry")
+ {
+ subNode = node.firstChild();
+ while (!subNode.isNull())
+ {
+ if ((subNode.nodeName().lower() == "ref") && (subNode.isElement()) && (url.isNull()))
+ {
+ element = subNode.toElement();
+ if (element.hasAttribute("href"))
+ url = element.attribute("href");
+ if (element.hasAttribute("HREF"))
+ url = element.attribute("HREF");
+ if (element.hasAttribute("Href"))
+ url = element.attribute("Href");
+ if (element.hasAttribute("HRef"))
+ url = element.attribute("HRef");
+
+ }
+
+ if ((subNode.nodeName().lower() == "duration") && (subNode.isElement()))
+ {
+ duration = QString::null;
+ element = subNode.toElement();
+ if (element.hasAttribute("value"))
+ duration = element.attribute("value");
+ if (element.hasAttribute("Value"))
+ duration = element.attribute("Value");
+ if (element.hasAttribute("VALUE"))
+ duration = element.attribute("VALUE");
+
+ if (!duration.isNull())
+ length = PlaylistImport::stringToTime(duration);
+ }
+
+ if ((subNode.nodeName().lower() == "title") && (subNode.isElement()))
+ {
+ title = subNode.toElement().text();
+ }
+ if ((subNode.nodeName().lower() == "author") && (subNode.isElement()))
+ {
+ author = subNode.toElement().text();
+ }
+
+ /* possible nodes we ignore: ABSTRACT, BANNER, BASE, COPYRIGHT, ENDMARKER, MOREINFO, PARAM,
+ * PREVIEWDURATION, STARTMARKER, STARTTIME
+ */
+ subNode = subNode.nextSibling();
+ }
+
+ if (!url.isNull())
+ {
+ if (title.isNull())
+ title = url;
+ kdDebug() << "PlaylistImport: asx import url: " << url << endl;
+ mrls.append(MRL(url, title, length, QString::null, author));
+ }
+ }
+ node = node.nextSibling();
+ }
+
+ file.close();
+
+ return true;
+}
+
+/****************************************************************
+ * Full SMIL support seems to be impossible at the moment... *
+ * spec: http://www.w3.org/TR/REC-smil/ *
+ ****************************************************************/
+
+bool PlaylistImport::smil(const QString& playlist, const MRL& baseMRL, QValueList<MRL>& mrls)
+{
+ kdDebug() << "PlaylistImport: smil: " << playlist << endl;
+ QFile file(playlist);
+ if (!file.open(IO_ReadOnly)) return false;
+
+ QDomDocument doc;
+ doc.setContent(&file);
+ QDomElement root = doc.documentElement();
+
+ if (root.nodeName().lower() != "smil") return false;
+
+ bool anyURL = false;
+ KURL kurl;
+ QString url;
+ QDomNodeList nodeList;
+ QDomNode node;
+ QDomElement element;
+
+ //video sources...
+ nodeList = doc.elementsByTagName("video");
+ kdDebug() << "PlaylistImport: smil: " << nodeList.count() << " 'video' tags found" << endl;
+ for (uint i = 0; i < nodeList.count(); i++)
+ {
+ node = nodeList.item(i);
+ url = QString::null;
+ if ((node.nodeName().lower() == "video") && (node.isElement()))
+ {
+ element = node.toElement();
+ if (element.hasAttribute("src"))
+ url = element.attribute("src");
+ if (element.hasAttribute("Src"))
+ url = element.attribute("Src");
+ if (element.hasAttribute("SRC"))
+ url = element.attribute("SRC");
+ }
+ if (!url.isNull())
+ {
+ kurl = KURL(baseMRL.kurl(), url);
+ kdDebug() << "PlaylistImport: smil: found video source: " << kurl.url() << endl;
+ mrls.append(kurl);
+ anyURL = true;
+ }
+ }
+
+ //audio sources...
+ nodeList = doc.elementsByTagName("audio");
+ kdDebug() << "PlaylistImport: smil: " << nodeList.count() << " 'audio' tags found" << endl;
+ for (uint i = 0; i < nodeList.count(); i++)
+ {
+ node = nodeList.item(i);
+ url = QString::null;
+ if ((node.nodeName().lower() == "audio") && (node.isElement()))
+ {
+ element = node.toElement();
+ if (element.hasAttribute("src"))
+ url = element.attribute("src");
+ if (element.hasAttribute("Src"))
+ url = element.attribute("Src");
+ if (element.hasAttribute("SRC"))
+ url = element.attribute("SRC");
+ }
+ if (!url.isNull())
+ {
+ kurl = KURL(baseMRL.kurl(), url);
+ kdDebug() << "PlaylistImport: smil: found audio source: " << kurl.url() << endl;
+ mrls.append(kurl);
+ anyURL = true;
+ }
+ }
+
+ file.close();
+ return anyURL;
+}
+
+QTime PlaylistImport::stringToTime(const QString& timeString)
+{
+ int sec = 0;
+ bool ok = false;
+ QStringList tokens = QStringList::split(':',timeString);
+
+ sec += tokens[0].toInt(&ok)*3600; //hours
+ sec += tokens[1].toInt(&ok)*60; //minutes
+ sec += tokens[2].toInt(&ok); //secs
+
+ if (ok)
+ return QTime().addSecs(sec);
+ else
+ return QTime();
+}
diff --git a/kaffeine/src/player-parts/kaffeine-part/playlistimport.h b/kaffeine/src/player-parts/kaffeine-part/playlistimport.h
new file mode 100644
index 0000000..16420eb
--- /dev/null
+++ b/kaffeine/src/player-parts/kaffeine-part/playlistimport.h
@@ -0,0 +1,50 @@
+/*
+ * playlistimport.h
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 PLAYLISTIMPORT_H
+#define PLAYLISTIMPORT_H
+
+#include "mrl.h"
+
+class QWidget;
+
+/*
+ * static methods for playlist import
+ */
+
+class KDE_EXPORT PlaylistImport
+{
+public:
+
+ static bool kaffeine(const QString&, QValueList<MRL>&);
+ static bool noatun(const QString&, QValueList<MRL>&);
+ static bool m3u(const QString&, QValueList<MRL>&);
+ static bool pls(const QString&, QValueList<MRL>&);
+ static bool ram(const MRL&, QValueList<MRL>&, QWidget*);
+ static bool asx(const QString&, QValueList<MRL>&);
+ static bool smil(const QString&, const MRL&, QValueList<MRL>&);
+ /* helper */
+ static QTime stringToTime(const QString&);
+
+private:
+ static uint extractIndex(const QString&);
+};
+
+#endif /* PLAYLISTIMPORT_H */
diff --git a/kaffeine/src/player-parts/xine-part/Makefile.am b/kaffeine/src/player-parts/xine-part/Makefile.am
new file mode 100644
index 0000000..0325e1d
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/Makefile.am
@@ -0,0 +1,26 @@
+kde_module_LTLIBRARIES = libxinepart.la
+
+INCLUDES = -I$(top_srcdir)/kaffeine/src/ -I$(top_srcdir)/kaffeine/src/player-parts/kaffeine-part $(all_includes) $(CFLAGS_XINERAMA) $(CFLAGS_XINE) $(CFLAGS_XCB)
+
+METASOURCES = AUTO
+
+kaffeineincludedir = $(includedir)/kaffeine
+kaffeineinclude_HEADERS = xine_part.h xine_part_iface.h
+
+noinst_HEADERS = xine_part_iface.h kxinewidget.h postfilter.h deinterlacequality.h videosettings.h \
+ filterdialog.h screenshotpreview.h xineconfig.h positionslider.h equalizer.h
+
+libxinepart_la_SOURCES = xine_part.cpp kxinewidget.cpp postfilter.cpp deinterlacequality.cpp \
+ videosettings.cpp filterdialog.cpp screenshotpreview.cpp xineconfig.cpp positionslider.cpp \
+ equalizer.cpp xine_part_iface.skel
+libxinepart_la_LIBADD = $(LIB_XINERAMA) $(LIB_XINE) $(LIB_XCB) ../kaffeine-part/libkaffeinepart.la
+libxinepart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -avoid-version -no-undefined
+
+
+# this is where the desktop file will go
+partdesktopdir = $(kde_servicesdir)
+partdesktop_DATA = xine_part.desktop
+
+# this is where the part's XML-GUI resource file goes
+partrcdir = $(kde_datadir)/kaffeine
+partrc_DATA = xine_part.rc
diff --git a/kaffeine/src/player-parts/xine-part/README b/kaffeine/src/player-parts/xine-part/README
new file mode 100644
index 0000000..b97bb38
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/README
@@ -0,0 +1,81 @@
+********************
+* XINE-PART *
+********************
+
+The xine-based default player-part of Kaffeine.
+
+
+*** IMPORTANT ***
+The following example is outdated and unlikely to work.
+*** IMPORTANT ***
+
+
+You can use this part in your Application like this:
+----------------------------------------------------
+
+*** myplayer.h: ***
+
+#include <kmainwindow.h>
+
+class KaffeinePart;
+
+class MyPlayer : public MainWindow
+{
+ public:
+ MyPlayer();
+ ~MyPlayer();
+
+ void loadURL(const QString&);
+
+ //...
+ private:
+ KaffeinePart* m_player;
+};
+
+*** myplayer.cpp: ***
+
+#include <kaffeine/xine_part.h>
+
+MyPlayer::MyPlayer() : KMainWindow(0)
+{
+ initMyActions();
+ createGUI();
+
+ //...
+
+ m_player = new XinePart(this, "my_player", this, 0, QStringList());
+ guiFactory()->addClient(m_player);
+ setCentralWidget(m_player->widget());
+
+ //..
+}
+
+void MyPlayer::loadURL(const QString& url)
+{
+ m_player->openURL(url);
+}
+
+*** Makefile.am ***
+
+bin_PROGRAMS = myplayer
+
+INCLUDES = $(all_includes)
+
+noinst_HEADERS = myplayer.h
+
+METASOURCES = AUTO
+
+myplayer_SOURCES = myplayer.cpp
+myplayer_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+myplayer_LDADD = $(LIB_KPARTS) -lxinepart
+
+
+*******************
+
+Thats it. If you need to implement your own UI, check kxinewidget.h
+
+
+
+
+
+
diff --git a/kaffeine/src/player-parts/xine-part/deinterlacequality.cpp b/kaffeine/src/player-parts/xine-part/deinterlacequality.cpp
new file mode 100644
index 0000000..70ca01d
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/deinterlacequality.cpp
@@ -0,0 +1,137 @@
+/*
+ * deinterlacequality.cpp - dialog for selecting the quality of deinterlacing
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <kdebug.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+
+#include <qcheckbox.h>
+#include <qslider.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include "deinterlacequality.h"
+#include "deinterlacequality.moc"
+
+
+DeinterlaceQuality::DeinterlaceQuality(QWidget* filterDialog, QWidget *parent, const char *name)
+:KDialogBase(parent, name, true, i18n("Deinterlace Quality"), KDialogBase::Close)
+{
+ m_configStrings << "tvtime:method=Greedy2Frame,enabled=1,pulldown=vektor,framerate_mode=full,judder_correction=1,use_progressive_frame_flag=1,chroma_filter=1,cheap_mode=0";
+ m_configStrings << "tvtime:method=Greedy2Frame,enabled=1,pulldown=vektor,framerate_mode=full,judder_correction=0,use_progressive_frame_flag=1,chroma_filter=0,cheap_mode=0";
+ m_configStrings << "tvtime:method=Greedy,enabled=1,pulldown=none,framerate_mode=half_top,judder_correction=0,use_progressive_frame_flag=1,chroma_filter=0,cheap_mode=0";
+ m_configStrings << "tvtime:method=Greedy,enabled=1,pulldown=none,framerate_mode=half_top,judder_correction=0,use_progressive_frame_flag=1,chroma_filter=0,cheap_mode=1";
+ m_configStrings << "tvtime:method=LinearBlend,enabled=1,pulldown=none,framerate_mode=half_top,judder_correction=0,use_progressive_frame_flag=1,chroma_filter=0,cheap_mode=1";
+ m_configStrings << "tvtime:method=LineDoubler,enabled=1,pulldown=none,framerate_mode=half_top,judder_correction=0,use_progressive_frame_flag=1,chroma_filter=0,cheap_mode=1";
+
+ setInitialSize(QSize(680, 480));
+ QWidget* mainWidget = makeMainWidget();
+ QGridLayout* grid = new QGridLayout( mainWidget, 9, 2 );
+ grid->setSpacing(5);
+ grid->setMargin(5);
+
+ m_qualitySlider = new QSlider( QSlider::Vertical, mainWidget );
+ m_qualitySlider->setRange(0, 5);
+ m_qualitySlider->setSteps(1, 1);
+ m_qualitySlider->setTickmarks(QSlider::Right);
+ grid->addMultiCellWidget(m_qualitySlider, 0, 5, 0, 0);
+
+ QLabel* level0Descr = new QLabel(i18n("<b>Very low cpu usage, worst quality.</b><br>Half of vertical resolution is lost. For some systems (with PCI video cards) this might decrease the cpu usage when compared to plain video playback (no deinterlacing)."), mainWidget);
+ grid->addWidget(level0Descr, 5, 1);
+
+ QLabel* level1Descr = new QLabel(i18n("<b>Low cpu usage, poor quality.</b><br>Image is blurred vertically so interlacing effects are removed."), mainWidget);
+ grid->addWidget(level1Descr, 4, 1);
+
+ QLabel* level2Descr = new QLabel(i18n("<b>Medium cpu usage, medium quality.</b><br>Image is analysed and areas showing interlacing artifacts are fixed (interpolated)."), mainWidget);
+ grid->addWidget(level2Descr, 3, 1);
+
+ QLabel* level3Descr = new QLabel(i18n("<b>High cpu usage, good quality.</b><br>Conversion of dvd image format improves quality and fixes chroma upsampling bug."), mainWidget);
+ grid->addWidget(level3Descr, 2, 1);
+
+ QLabel* level4Descr = new QLabel(i18n("<b>Very high cpu usage, great quality.</b><br>Besides using smart deinterlacing algorithms it will also double the frame rate (30->60fps) to match the field rate of TVs. Detects and reverts 3-2 pulldown. *"), mainWidget);
+ grid->addWidget(level4Descr, 1, 1);
+
+ QLabel* level5Descr = new QLabel(i18n("<b>Very very high cpu usage, great quality with (experimental) improvements.</b><br>Enables judder correction (play films at their original 24 fps speed) and vertical color smoothing (fixes small color stripes seen in some dvds). *"), mainWidget);
+ grid->addWidget(level5Descr, 0, 1);
+
+ m_customBox = new QCheckBox(i18n("User defined"), mainWidget);
+ grid->addMultiCellWidget(m_customBox, 6, 6, 0, 1);
+ connect(m_customBox, SIGNAL(toggled(bool)), this, SLOT(slotCustomBoxToggled(bool)));
+
+ m_customConfigButton = new KPushButton(i18n("Configure tvtime Deinterlace Plugin..."), mainWidget);
+ m_customConfigButton->setSizePolicy(QSizePolicy (QSizePolicy::Minimum, QSizePolicy::Fixed));
+ grid->addWidget(m_customConfigButton, 7, 1);
+ connect(m_customConfigButton, SIGNAL(clicked()), filterDialog, SLOT(show()));
+
+ QLabel* note = new QLabel(i18n("* <i>May require a patched 2.4 kernel (like RedHat one) or 2.6 kernel.</i>"), mainWidget);
+ note->setAlignment(QLabel::WordBreak | QLabel::AlignVCenter);
+ grid->addMultiCellWidget(note, 9, 9, 0, 1);
+}
+
+DeinterlaceQuality::~DeinterlaceQuality()
+{
+ kdDebug() << "DeinterlaceQuality: destructed" << endl;
+}
+
+void DeinterlaceQuality::slotLevelChanged( int level )
+{
+ // kdDebug() << "DeinterlaceQuality: Change to quality " << level << endl;
+ emit signalSetDeinterlaceConfig(m_configStrings[level]);
+}
+
+void DeinterlaceQuality::slotCustomBoxToggled(bool on)
+{
+ if (on)
+ {
+ m_customConfigButton->setEnabled(true);
+ m_qualitySlider->setEnabled(false);
+ }
+ else
+ {
+ m_customConfigButton->setEnabled(false);
+ m_qualitySlider->setEnabled(true);
+ }
+}
+
+void DeinterlaceQuality::setQuality(uint qu)
+{
+ if (qu < 10)
+ {
+ m_qualitySlider->setValue(qu);
+ m_customBox->setChecked(false);
+ slotCustomBoxToggled(false);
+ }
+ else
+ {
+ m_qualitySlider->setValue(qu-10);
+ m_customBox->setChecked(true);
+ }
+ connect(m_qualitySlider, SIGNAL(valueChanged(int)), this, SLOT(slotLevelChanged(int)));
+}
+
+uint DeinterlaceQuality::getQuality() const
+{
+ if (m_customBox->isChecked())
+ return m_qualitySlider->value()+10;
+ else
+ return m_qualitySlider->value();
+}
diff --git a/kaffeine/src/player-parts/xine-part/deinterlacequality.h b/kaffeine/src/player-parts/xine-part/deinterlacequality.h
new file mode 100644
index 0000000..5a91ad4
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/deinterlacequality.h
@@ -0,0 +1,78 @@
+/*
+ * deinterlacequality.h - dialog for selecting the quality of deinterlacing
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 DEINTERLACEQUALITY_H
+#define DEINTERLACEQUALITY_H
+
+#include <kdialogbase.h>
+
+/**
+ *@author Juergen Kofler
+ */
+
+class QCheckBox;
+class QSlider;
+class QString;
+class QStringList;
+class KPushButton;
+
+class DeinterlacerConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ DeinterlacerConfigDialog(QWidget *parent=0, const char *name=0)
+ : KDialogBase( parent, name, true, i18n("Configure tvtime Deinterlace Plugin"), KDialogBase::Close )
+ {
+ setInitialSize(QSize(450,400), true);
+
+ mainWidget = makeVBoxMainWidget();
+ }
+
+ ~DeinterlacerConfigDialog() {}
+ QWidget* getMainWidget() const { return (QWidget*)mainWidget; }
+
+private:
+ QVBox* mainWidget;
+};
+
+class DeinterlaceQuality : public KDialogBase {
+ Q_OBJECT
+public:
+ DeinterlaceQuality(QWidget* filterDialog, QWidget *parent=0, const char *name=0);
+ ~DeinterlaceQuality();
+
+ void setQuality(uint);
+ uint getQuality() const;
+
+signals:
+ void signalSetDeinterlaceConfig(const QString&);
+
+private slots:
+ void slotLevelChanged(int);
+ void slotCustomBoxToggled(bool);
+
+private:
+ QStringList m_configStrings;
+ QSlider* m_qualitySlider;
+ QCheckBox* m_customBox;
+ KPushButton* m_customConfigButton;
+};
+
+#endif /* DEINTERLACEQUALITY_H */
diff --git a/kaffeine/src/player-parts/xine-part/equalizer.cpp b/kaffeine/src/player-parts/xine-part/equalizer.cpp
new file mode 100644
index 0000000..12e5f92
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/equalizer.cpp
@@ -0,0 +1,245 @@
+/*
+ * equalizer.cpp
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <klocale.h>
+#include <kdebug.h>
+
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qlabel.h>
+
+#include "equalizer.h"
+#include "equalizer.moc"
+
+Equalizer::Equalizer(QWidget *parent, const char *name)
+ : KDialogBase(KDialogBase::Plain, i18n("Equalizer Settings"), KDialogBase::Default | KDialogBase::Close, KDialogBase::Close, parent, name, false)
+{
+ setInitialSize(QSize(450,250), true);
+ reparent(parent, pos(), false);
+ QWidget* page = plainPage();
+
+ QGridLayout* mainGrid = new QGridLayout( page, 3, 1 );
+
+ on = new QCheckBox( i18n("On"), page );
+ mainGrid->addWidget( on, 0, 0 );
+ connect(on, SIGNAL(toggled(bool)), this, SLOT(slotSetEnabled(bool)));
+
+ volumeGain = new QCheckBox( i18n("Volume gain"), page );
+ QToolTip::add(volumeGain, i18n("Volume Gain for Equalizer - If the sound becomes noisy disable this"));
+ mainGrid->addWidget( volumeGain, 1, 0 );
+ connect(volumeGain, SIGNAL(toggled(bool)), this, SIGNAL(signalSetVolumeGain(bool)));
+
+ equalGroup = new QGroupBox( QString::null, page );
+ mainGrid->addWidget( equalGroup, 2, 0 );
+
+ QGridLayout* equalGrid = new QGridLayout(equalGroup, 2, 10);
+ equalGrid->setSpacing(5);
+ equalGrid->setMargin(10);
+
+ QLabel* eq30Text = new QLabel("30Hz", equalGroup);
+ eq30Slider = new QSlider(Qt::Vertical, equalGroup);
+ eq30Slider->setRange(-100, -1);
+ eq30Slider->setSteps(1, 10);
+ eq30Slider->setTickInterval(50);
+ eq30Slider->setTickmarks(QSlider::Right);
+ connect(eq30Slider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq30(int)));
+ equalGrid->addWidget(eq30Text, 1, 0);
+ equalGrid->addWidget(eq30Slider, 0, 0);
+
+ QLabel* eq60Text = new QLabel("60Hz", equalGroup);
+ eq60Slider = new QSlider(Qt::Vertical, equalGroup);
+ eq60Slider->setRange(-100, -1);
+ eq60Slider->setSteps(1, 10);
+ connect(eq60Slider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq60(int)));
+ equalGrid->addWidget(eq60Text, 1, 1);
+ equalGrid->addWidget(eq60Slider, 0, 1);
+
+ QLabel* eq125Text = new QLabel("125Hz", equalGroup);
+ eq125Slider = new QSlider(Qt::Vertical, equalGroup);
+ eq125Slider->setRange(-100, -1);
+ eq125Slider->setSteps(1, 10);
+ connect(eq125Slider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq125(int)));
+ equalGrid->addWidget(eq125Text, 1, 2);
+ equalGrid->addWidget(eq125Slider, 0, 2);
+
+ QLabel* eq250Text = new QLabel("250Hz", equalGroup);
+ eq250Slider = new QSlider(Qt::Vertical, equalGroup);
+ eq250Slider->setRange(-100, -1);
+ eq250Slider->setSteps(1, 10);
+ connect(eq250Slider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq250(int)));
+ equalGrid->addWidget(eq250Text, 1, 3);
+ equalGrid->addWidget(eq250Slider, 0, 3);
+
+ QLabel* eq500Text = new QLabel("500Hz", equalGroup);
+ eq500Slider = new QSlider(Qt::Vertical, equalGroup);
+ eq500Slider->setRange(-100, -1);
+ eq500Slider->setSteps(1, 10);
+ connect(eq500Slider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq500(int)));
+ equalGrid->addWidget(eq500Text, 1, 4);
+ equalGrid->addWidget(eq500Slider, 0, 4);
+
+ QLabel* eq1kText = new QLabel("1kHz", equalGroup);
+ eq1kSlider = new QSlider(Qt::Vertical, equalGroup);
+ eq1kSlider->setRange(-100, -1);
+ eq1kSlider->setSteps(1, 10);
+ connect(eq1kSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq1k(int)));
+ equalGrid->addWidget(eq1kText, 1, 5);
+ equalGrid->addWidget(eq1kSlider, 0, 5);
+
+ QLabel* eq2kText = new QLabel("2kHz", equalGroup);
+ eq2kSlider = new QSlider(Qt::Vertical, equalGroup);
+ eq2kSlider->setRange(-100, -1);
+ eq2kSlider->setSteps(1, 10);
+ connect(eq2kSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq2k(int)));
+ equalGrid->addWidget(eq2kText, 1, 6);
+ equalGrid->addWidget(eq2kSlider, 0, 6);
+
+ QLabel* eq4kText = new QLabel("4kHz", equalGroup);
+ eq4kSlider = new QSlider(Qt::Vertical, equalGroup);
+ eq4kSlider->setRange(-100, -1);
+ eq4kSlider->setSteps(1, 10);
+ connect(eq4kSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq4k(int)));
+ equalGrid->addWidget(eq4kText, 1, 7);
+ equalGrid->addWidget(eq4kSlider, 0, 7);
+
+ QLabel* eq8kText = new QLabel("8kHz", equalGroup);
+ eq8kSlider = new QSlider(Qt::Vertical, equalGroup);
+ eq8kSlider->setRange(-100, -1);
+ eq8kSlider->setSteps(1, 10);
+ connect(eq8kSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq8k(int)));
+ equalGrid->addWidget(eq8kText, 1, 8);
+ equalGrid->addWidget(eq8kSlider, 0, 8);
+
+ QLabel* eq16kText = new QLabel("16kHz", equalGroup);
+ eq16kSlider = new QSlider(Qt::Vertical, equalGroup);
+ eq16kSlider->setRange(-100, -1);
+ eq16kSlider->setSteps(1, 10);
+ eq16kSlider->setTickInterval(50);
+ eq16kSlider->setTickmarks(QSlider::Left);
+ connect(eq16kSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewEq16k(int)));
+ equalGrid->addWidget(eq16kText, 1, 9);
+ equalGrid->addWidget(eq16kSlider, 0, 9);
+
+ connect(this, SIGNAL(defaultClicked()), this, SLOT(slotSetDefaultValues()));
+}
+
+
+Equalizer::~Equalizer()
+{
+}
+
+
+void Equalizer::slotSetEnabled( bool enabled )
+{
+ equalGroup->setEnabled( enabled );
+ volumeGain->setEnabled( enabled );
+ enableButton( KDialogBase::Default, enabled );
+
+ if (enabled)
+ {
+ emit signalSetVolumeGain( volumeGain->isChecked() );
+ emit signalNewEq30( eq30Slider->value() );
+ emit signalNewEq60( eq60Slider->value() );
+ emit signalNewEq125( eq125Slider->value() );
+ emit signalNewEq250( eq250Slider->value() );
+ emit signalNewEq500( eq500Slider->value() );
+ emit signalNewEq1k( eq1kSlider->value() );
+ emit signalNewEq2k( eq2kSlider->value() );
+ emit signalNewEq4k( eq4kSlider->value() );
+ emit signalNewEq8k( eq8kSlider->value() );
+ emit signalNewEq16k( eq16kSlider->value() );
+ }
+ else
+ {
+ emit signalSetVolumeGain( false );
+ emit signalNewEq30( 0 );
+ emit signalNewEq60( 0 );
+ emit signalNewEq125( 0 );
+ emit signalNewEq250( 0 );
+ emit signalNewEq500( 0 );
+ emit signalNewEq1k( 0 );
+ emit signalNewEq2k( 0 );
+ emit signalNewEq4k( 0 );
+ emit signalNewEq8k( 0 );
+ emit signalNewEq16k( 0 );
+ }
+}
+
+
+void Equalizer::slotSetDefaultValues()
+{
+ eq30Slider->setValue(-50);
+ eq60Slider->setValue(-50);
+ eq125Slider->setValue(-50);
+ eq250Slider->setValue(-50);
+ eq500Slider->setValue(-50);
+ eq1kSlider->setValue(-50);
+ eq2kSlider->setValue(-50);
+ eq4kSlider->setValue(-50);
+ eq8kSlider->setValue(-50);
+ eq16kSlider->setValue(-50);
+}
+
+
+/******* read from config-file ********/
+void Equalizer::ReadValues(KConfig* config)
+{
+ config->setGroup("Equalizer");
+
+ bool enabled = config->readBoolEntry( "Enabled", false );
+ on->setChecked( enabled );
+
+ bool gain = config->readBoolEntry( "Volume Gain", true );
+ volumeGain->setChecked( gain );
+
+ eq30Slider->setValue( config->readNumEntry("30Hz", -50) );
+ eq60Slider->setValue( config->readNumEntry("60Hz", -50) );
+ eq125Slider->setValue( config->readNumEntry("125Hz", -50) );
+ eq250Slider->setValue( config->readNumEntry("250Hz", -50) );
+ eq500Slider->setValue( config->readNumEntry("500Hz", -50) );
+ eq1kSlider->setValue( config->readNumEntry("1kHz", -50) );
+ eq2kSlider->setValue( config->readNumEntry("2kHz", -50) );
+ eq4kSlider->setValue( config->readNumEntry("4kHz", -50) );
+ eq8kSlider->setValue( config->readNumEntry("8kHz", -50) );
+ eq16kSlider->setValue( config->readNumEntry("16kHz", -50) );
+
+ if (!enabled)
+ slotSetEnabled( false );
+}
+
+
+/************** save in config file *************/
+void Equalizer::SaveValues(KConfig* config)
+{
+ config->setGroup("Equalizer");
+
+ config->writeEntry( "Enabled", on->isChecked());
+ config->writeEntry( "Volume Gain", volumeGain->isChecked());
+ config->writeEntry("30Hz", eq30Slider->value());
+ config->writeEntry("60Hz", eq60Slider->value());
+ config->writeEntry("125Hz", eq125Slider->value());
+ config->writeEntry("250Hz", eq250Slider->value());
+ config->writeEntry("500Hz", eq500Slider->value());
+ config->writeEntry("1kHz", eq1kSlider->value());
+ config->writeEntry("2kHz", eq2kSlider->value());
+ config->writeEntry("4kHz", eq4kSlider->value());
+ config->writeEntry("8kHz", eq8kSlider->value());
+ config->writeEntry("16kHz", eq16kSlider->value());
+}
diff --git a/kaffeine/src/player-parts/xine-part/equalizer.h b/kaffeine/src/player-parts/xine-part/equalizer.h
new file mode 100644
index 0000000..e912dcc
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/equalizer.h
@@ -0,0 +1,79 @@
+/*
+ * equalizer.h
+ *
+ * Copyright (C) 2003-2004 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 EQUALIZER_H
+#define EQUALIZER_H
+
+#include <kdialogbase.h>
+#include <kconfig.h>
+
+#include <qwidget.h>
+#include <qslider.h>
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+
+/**equalizer widget
+ *@author Juergen Kofler
+ */
+
+class Equalizer : public KDialogBase {
+ Q_OBJECT
+public:
+ Equalizer(QWidget *parent=0, const char *name=0);
+ ~Equalizer();
+
+ void ReadValues(KConfig* config);
+ void SaveValues(KConfig* config);
+
+signals:
+ void signalNewEq30(int);
+ void signalNewEq60(int);
+ void signalNewEq125(int);
+ void signalNewEq250(int);
+ void signalNewEq500(int);
+ void signalNewEq1k(int);
+ void signalNewEq2k(int);
+ void signalNewEq4k(int);
+ void signalNewEq8k(int);
+ void signalNewEq16k(int);
+ void signalSetVolumeGain(bool);
+
+
+private slots:
+ void slotSetDefaultValues();
+ void slotSetEnabled( bool );
+
+private:
+ QCheckBox* on;
+ QCheckBox* volumeGain;
+ QGroupBox* equalGroup;
+ QSlider* eq30Slider;
+ QSlider* eq60Slider;
+ QSlider* eq125Slider;
+ QSlider* eq250Slider;
+ QSlider* eq500Slider;
+ QSlider* eq1kSlider;
+ QSlider* eq2kSlider;
+ QSlider* eq4kSlider;
+ QSlider* eq8kSlider;
+ QSlider* eq16kSlider;
+};
+
+#endif /* EQUALIZER_H */
diff --git a/kaffeine/src/player-parts/xine-part/filterdialog.cpp b/kaffeine/src/player-parts/xine-part/filterdialog.cpp
new file mode 100644
index 0000000..4468b31
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/filterdialog.cpp
@@ -0,0 +1,135 @@
+/*
+ * filterdialog.cpp - config dialog for postprocessing filters
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <klocale.h>
+#include <kdebug.h>
+#include <kpushbutton.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kcombobox.h>
+
+#include <qvbox.h>
+#include <qstringlist.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qscrollview.h>
+
+#include "filterdialog.h"
+#include "filterdialog.moc"
+
+
+FilterDialog::FilterDialog(const QStringList& audioFilters, const QStringList& videoFilters, QWidget *parent, const char *name) :
+ KDialogBase(KDialogBase::IconList, i18n("Effect Plugins"), KDialogBase::Ok, KDialogBase::Ok, parent, name, false)
+{
+ reparent(parent, pos(), false);
+ setInitialSize(QSize(400,350), true);
+
+/****** Audio Filters ******/
+ QWidget* audioPage = addPage(i18n("Audio"), i18n("Audio Filters"),
+ KGlobal::iconLoader()->loadIcon("sound", KIcon::Panel, KIcon::SizeMedium));
+ QGridLayout* audioGrid = new QGridLayout( audioPage, 3, 3 );
+ audioGrid->setSpacing( 5 );
+
+ QCheckBox* useAudioFiltersCB = new QCheckBox( audioPage );
+ useAudioFiltersCB->setText( i18n("Enable audio filters") );
+ useAudioFiltersCB->setChecked( true );
+ connect( useAudioFiltersCB, SIGNAL(toggled(bool)), this, SLOT(slotUseAudioFilters(bool)));
+
+ audioGrid->addMultiCellWidget( useAudioFiltersCB, 0, 0, 0, 2 );
+
+ m_audioFilterCombo = new KComboBox( audioPage );
+ m_audioFilterCombo->insertStringList( audioFilters );
+
+ m_addAudioButton = new KPushButton( i18n("Add Filter"), audioPage );
+ connect( m_addAudioButton, SIGNAL( clicked() ), this, SLOT( slotAddAudioClicked() ));
+ m_removeAudioButton = new KPushButton( i18n("Remove All Filters"), audioPage );
+ connect( m_removeAudioButton, SIGNAL( clicked() ), this, SIGNAL( signalRemoveAllAudioFilters() ));
+
+ audioGrid->addWidget( m_audioFilterCombo, 1, 0 );
+ audioGrid->addWidget( m_removeAudioButton, 1, 2 );
+ audioGrid->addWidget( m_addAudioButton, 1, 1 );
+
+ QScrollView* audioSv = new QScrollView( audioPage );
+ audioSv->setResizePolicy(QScrollView::AutoOneFit);
+ m_audioFilterPage = new QVBox(audioSv->viewport());
+ m_audioFilterPage->setMargin( 5 );
+ audioSv->addChild(m_audioFilterPage);
+
+ audioGrid->addMultiCellWidget( audioSv, 2, 2, 0, 2 );
+
+/****** Video Filters ******/
+ QWidget* videoPage = addPage(i18n("Video"), i18n("Video Filters"),
+ KGlobal::iconLoader()->loadIcon("video", KIcon::Panel, KIcon::SizeMedium));
+ QGridLayout* videoGrid = new QGridLayout( videoPage, 3, 3 );
+ videoGrid->setSpacing( 5 );
+
+ QCheckBox* useVideoFiltersCB = new QCheckBox( videoPage );
+ useVideoFiltersCB->setText( i18n("Enable video filters") );
+ useVideoFiltersCB->setChecked( true );
+ connect( useVideoFiltersCB, SIGNAL(toggled(bool)), this, SLOT(slotUseVideoFilters(bool)));
+
+ videoGrid->addMultiCellWidget( useVideoFiltersCB, 0, 0, 0, 2 );
+
+ m_videoFilterCombo = new KComboBox( videoPage );
+ m_videoFilterCombo->insertStringList( videoFilters );
+
+ m_addVideoButton = new KPushButton( i18n("Add Filter"), videoPage );
+ connect( m_addVideoButton, SIGNAL( clicked() ), this, SLOT( slotAddVideoClicked() ));
+ m_removeVideoButton = new KPushButton( i18n("Remove All Filters"), videoPage );
+ connect( m_removeVideoButton, SIGNAL( clicked() ), this, SIGNAL( signalRemoveAllVideoFilters() ));
+
+ videoGrid->addWidget( m_videoFilterCombo, 1, 0 );
+ videoGrid->addWidget( m_removeVideoButton, 1, 2 );
+ videoGrid->addWidget( m_addVideoButton, 1, 1 );
+
+ QScrollView* videoSv = new QScrollView( videoPage );
+ videoSv->setResizePolicy(QScrollView::AutoOneFit);
+ m_videoFilterPage = new QVBox(videoSv->viewport());
+ m_videoFilterPage->setMargin( 5 );
+ videoSv->addChild(m_videoFilterPage);
+
+ videoGrid->addMultiCellWidget( videoSv, 2, 2, 0, 2 );
+}
+
+
+FilterDialog::~FilterDialog()
+{
+ kdDebug() << "FilterDialog: destructor" << endl;
+}
+
+
+void FilterDialog::slotUseAudioFilters( bool on )
+{
+ m_audioFilterCombo->setEnabled( on );
+ m_removeAudioButton->setEnabled( on );
+ m_addAudioButton->setEnabled( on );
+ m_audioFilterPage->setEnabled( on );
+ emit signalUseAudioFilters( on );
+}
+
+
+void FilterDialog::slotUseVideoFilters( bool on )
+{
+ m_videoFilterCombo->setEnabled( on );
+ m_removeVideoButton->setEnabled( on );
+ m_addVideoButton->setEnabled( on );
+ m_videoFilterPage->setEnabled( on );
+ emit signalUseVideoFilters( on );
+}
diff --git a/kaffeine/src/player-parts/xine-part/filterdialog.h b/kaffeine/src/player-parts/xine-part/filterdialog.h
new file mode 100644
index 0000000..c730f69
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/filterdialog.h
@@ -0,0 +1,68 @@
+/*
+ * filterdialog.h - config dialog for postprocessing filters
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 FILTERDIALOG_H
+#define FILTERDIALOG_H
+
+#include <kdialogbase.h>
+
+class KComboBox;
+class QVBox;
+class QString;
+class QStringList;
+
+/**
+ *@author Juergen Kofler
+ */
+
+class FilterDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ FilterDialog(const QStringList& audiofilters, const QStringList& videofilters, QWidget *parent=0, const char *name=0);
+ ~FilterDialog();
+
+signals:
+ void signalCreateAudioFilter(const QString& name, QWidget* parent);
+ void signalRemoveAllAudioFilters();
+ void signalUseAudioFilters(bool);
+ void signalCreateVideoFilter(const QString& name, QWidget* parent);
+ void signalRemoveAllVideoFilters();
+ void signalUseVideoFilters(bool);
+
+private slots:
+ void slotAddAudioClicked() { emit signalCreateAudioFilter(m_audioFilterCombo->currentText(), (QWidget*)m_audioFilterPage); }
+ void slotUseAudioFilters(bool on);
+ void slotAddVideoClicked() { emit signalCreateVideoFilter(m_videoFilterCombo->currentText(), (QWidget*)m_videoFilterPage); }
+ void slotUseVideoFilters(bool on);
+
+private:
+ KComboBox* m_audioFilterCombo;
+ QVBox* m_audioFilterPage;
+ KPushButton* m_addAudioButton;
+ KPushButton* m_removeAudioButton;
+
+ KComboBox* m_videoFilterCombo;
+ QVBox* m_videoFilterPage;
+ KPushButton* m_addVideoButton;
+ KPushButton* m_removeVideoButton;
+};
+
+#endif /* FILTERDIALOG_H */
diff --git a/kaffeine/src/player-parts/xine-part/kxinewidget.cpp b/kaffeine/src/player-parts/xine-part/kxinewidget.cpp
new file mode 100644
index 0000000..77f26e2
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/kxinewidget.cpp
@@ -0,0 +1,4117 @@
+/*
+ * kxinewidget.cpp - a kde / qt api for xine-lib
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ * Copyright (C) 2005-2006 Christophe Thommeret <hftom@free.fr>
+ *
+ * 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 <qapplication.h>
+#include <qwidget.h>
+#include <qstringlist.h>
+
+#include <qtimer.h>
+#include <qevent.h>
+#include <qdir.h>
+#include <qcursor.h>
+#include <qimage.h>
+#include <qdatetime.h>
+#include <qtextcodec.h>
+
+#include <xine/xineutils.h>
+
+#include <cmath>
+
+#include "kxinewidget.h"
+#include "kaffeinepart.h"
+
+#ifdef HAVE_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+
+#ifndef USE_QT_ONLY
+#include "kxinewidget.moc"
+#include <klocale.h>
+#include <kdebug.h>
+#endif
+
+#define TIMER_EVENT_PLAYBACK_FINISHED 100
+#define TIMER_EVENT_NEW_CHANNELS 101
+#define TIMER_EVENT_NEW_TITLE 102
+#define TIMER_EVENT_NEW_STATUS 103
+#define TIMER_EVENT_CHANGE_CURSOR 104
+#define TIMER_EVENT_NEW_MRL_REFERENCE 105
+#define TIMER_EVENT_NEW_XINE_MESSAGE 106
+#define TIMER_EVENT_NEW_XINE_ERROR 107
+#define TIMER_EVENT_FRAME_FORMAT_CHANGE 108
+#define TIMER_EVENT_NEW_VOLUME_LEVEL 109
+#define TIMER_EVENT_RESTART_PLAYBACK 200
+#define TIMER_EVENT_RESIZE_PARENT 300
+
+
+KXineWidget::KXineWidget(QWidget* parent, const char* name,
+ const QString& pathToConfigFile, const QString& pathToLogoFile,
+ const QString& audioDriver, const QString& videoDriver,
+ bool startManual, bool verbose)
+ : QWidget(parent,name), m_startXineManual(startManual), m_xineReady(false),
+ m_logoFile(pathToLogoFile), m_preferedAudio(audioDriver), m_preferedVideo(videoDriver), m_xineVerbose(verbose),
+ m_xineEngine(NULL), m_audioDriver(NULL), m_videoDriver(NULL), m_xineStream(NULL), connection(NULL),
+ m_eventQueue(NULL), m_osd(NULL), m_osdUnscaled(false), m_osdShow(false), m_osdSize(0), m_osdFont(NULL),
+ m_audioChoices(NULL), m_audioInfo(NULL), m_videoChoices(NULL), m_videoInfo(NULL), m_mixerInfo(NULL),
+ m_osdShowInfo(NULL),
+ m_osdSizeOptions(NULL), m_osdSizeInfo(NULL), m_osdFontInfo(NULL),
+#ifndef USE_QT_ONLY
+ m_videoFiltersEnabled(true), m_audioFiltersEnabled(true), m_deinterlaceFilter(NULL),
+ m_deinterlaceEnabled(false),
+ m_visualPlugin(NULL),
+#else
+ m_xinePost(NULL), m_postAudioSource(NULL), m_postInput(NULL),
+#endif
+ m_visualPluginName(QString::null), m_currentSpeed(Normal), m_softwareMixer(false), m_volumeGain(false),
+ m_currentZoom(100), m_currentZoomX(100), m_currentZoomY(100), m_currentAudio(0), m_currentSub(0), m_savedPos(0), m_autoresizeEnabled(false)
+{
+ setMinimumSize(QSize(20,20)); // set a size hint
+ setPaletteBackgroundColor(QColor(0,0,0)); //black
+
+ /* dvb */
+ TimeShiftFilename = "";
+ dvbHaveVideo = 0;
+ dvbOSD = 0;
+ dvbColor[0] = 0;
+ connect( &dvbOSDHideTimer, SIGNAL(timeout()), this, SLOT(dvbHideOSD()) );
+
+ if (pathToConfigFile.isNull())
+ {
+ debugOut("Using default config file ~/.xine/config");
+ m_configFilePath = QDir::homeDirPath();
+ m_configFilePath.append("/.xine/config");
+ }
+ else
+ m_configFilePath = pathToConfigFile;
+
+ if (!m_logoFile.isNull())
+ appendToQueue(m_logoFile);
+
+#ifndef USE_QT_ONLY
+ m_videoFilterList.setAutoDelete(true); /*** delete post plugin on removing from list ***/
+ m_audioFilterList.setAutoDelete(true); /*** delete post plugin on removing from list ***/
+#endif
+
+ connect(&m_posTimer, SIGNAL(timeout()), this, SLOT(slotSendPosition()));
+ connect(&m_lengthInfoTimer, SIGNAL(timeout()), this, SLOT(slotEmitLengthInfo()));
+ connect(&m_mouseHideTimer, SIGNAL(timeout()), this, SLOT(slotHideMouse()));
+ connect(&m_osdTimer, SIGNAL(timeout()), this, SLOT(slotOSDHide()));
+ connect(&m_recentMessagesTimer, SIGNAL(timeout()), this, SLOT(slotNoRecentMessage()));
+
+ setUpdatesEnabled(false);
+ setMouseTracking(true);
+}
+
+
+KXineWidget::~KXineWidget()
+{
+ /* "careful" shutdown, maybe xine initialization was not successful */
+ m_xineReady = false;
+
+ /* stop all timers */
+ m_posTimer.stop();
+ m_mouseHideTimer.stop();
+
+#ifndef USE_QT_ONLY
+ slotRemoveAllAudioFilters();
+ slotRemoveAllVideoFilters();
+#endif
+ if (m_osd)
+ xine_osd_free(m_osd);
+
+ if (m_xineStream)
+ xine_close(m_xineStream);
+
+ debugOut("Shut down xine engine");
+
+#ifndef USE_QT_ONLY
+ if (m_deinterlaceFilter)
+ {
+ debugOut("Unwire video filters");
+ unwireVideoFilters();
+ delete m_deinterlaceFilter;
+ m_deinterlaceFilter = NULL;
+ }
+ if (m_visualPlugin)
+ {
+ debugOut("Unwire audio filters");
+ unwireAudioFilters();
+ debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName ));
+ delete m_visualPlugin;
+ m_visualPlugin = NULL;
+ }
+#else
+ if (m_xinePost)
+ {
+ debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName));
+ m_postAudioSource = xine_get_audio_source(m_xineStream);
+ xine_post_wire_audio_port(m_postAudioSource, m_audioDriver);
+ xine_post_dispose(m_xineEngine, m_xinePost);
+ }
+#endif
+ if (m_eventQueue)
+ {
+ debugOut("Dispose event queue");
+ xine_event_dispose_queue(m_eventQueue);
+ }
+ if (m_xineStream)
+ {
+ debugOut("Dispose stream");
+ xine_dispose(m_xineStream);
+ }
+ if (m_audioDriver)
+ {
+ debugOut("Close audio driver");
+ xine_close_audio_driver(m_xineEngine, m_audioDriver);
+ }
+ if (m_videoDriver)
+ {
+ debugOut("Close video driver");
+ xine_close_video_driver(m_xineEngine, m_videoDriver);
+ }
+ if (m_xineEngine)
+ {
+ saveXineConfig();
+ debugOut("Close xine engine");
+ xine_exit(m_xineEngine);
+ }
+ m_xineEngine = NULL;
+
+ /* free xine config strings */
+ if (m_osdShowInfo) free(m_osdShowInfo);
+
+ if (m_osdFontInfo) free(m_osdFontInfo);
+ if (m_osdFont) free(m_osdFont);
+
+ if (m_osdSizeInfo) free(m_osdSizeInfo);
+ if (m_osdSizeOptions)
+ {
+ int i=0;
+ while (m_osdSizeOptions[i])
+ {
+ free(m_osdSizeOptions[i]);
+ i++;
+ }
+ delete [] m_osdSizeOptions;
+ }
+
+ if (m_mixerInfo) free(m_mixerInfo);
+
+ if (m_videoInfo) free(m_videoInfo);
+ if (m_videoChoices)
+ {
+ int i=0;
+ while (m_videoChoices[i])
+ {
+ free(m_videoChoices[i]);
+ i++;
+ }
+ delete [] m_videoChoices;
+ }
+
+ if (m_audioInfo) free(m_audioInfo);
+ if (m_audioChoices)
+ {
+ int i=0;
+ while (m_audioChoices[i])
+ {
+ free(m_audioChoices[i]);
+ i++;
+ }
+ delete [] m_audioChoices;
+ }
+
+ if (connection)
+ {
+ debugOut("Close xine display");
+#ifndef HAVE_XCB
+ XCloseDisplay(connection); /* close xine display */
+#else
+ xcb_disconnect(connection); /* close xine display */
+#endif
+ }
+ connection = NULL;
+
+ debugOut("xine closed");
+}
+
+
+void KXineWidget::saveXineConfig()
+{
+ debugOut("Set CD/VCD/DVD path back");
+ xine_cfg_entry_t config;
+
+ if (!m_cachedCDPath.isNull())
+ {
+ xine_config_lookup_entry (m_xineEngine, "input.cdda_device", &config);
+ config.str_value = (char*)m_cachedCDPath.latin1();
+ xine_config_update_entry (m_xineEngine, &config);
+ }
+
+ if (!m_cachedVCDPath.isNull())
+ {
+ xine_config_lookup_entry (m_xineEngine, "input.vcd_device", &config);
+ config.str_value = (char*)m_cachedVCDPath.latin1();
+ xine_config_update_entry (m_xineEngine, &config);
+ }
+
+ if (!m_cachedDVDPath.isNull())
+ {
+ xine_config_lookup_entry (m_xineEngine, "input.dvd_device", &config);
+ config.str_value = (char*)m_cachedDVDPath.latin1();
+ xine_config_update_entry (m_xineEngine, &config);
+ }
+
+ debugOut(QString("Save xine config to: %1").arg(m_configFilePath));
+ xine_config_save(m_xineEngine, m_configFilePath.ascii());
+}
+
+
+/***************************************************
+ * CALLBACKS
+ ***************************************************/
+
+void KXineWidget::destSizeCallback(void* p, int /*video_width*/, int /*video_height*/, double /*video_aspect*/,
+ int* dest_width, int* dest_height, double* dest_aspect)
+
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ *dest_width = vw->width();
+ *dest_height = vw->height();
+ *dest_aspect = vw->m_displayRatio;
+}
+
+
+void KXineWidget::frameOutputCallback(void* p, int video_width, int video_height, double video_aspect,
+ int* dest_x, int* dest_y, int* dest_width, int* dest_height,
+ double* dest_aspect, int* win_x, int* win_y)
+
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ *dest_x = 0;
+ *dest_y = 0 ;
+ *dest_width = vw->width();
+ *dest_height = vw->height();
+ *win_x = vw->m_globalX;
+ *win_y = vw->m_globalY;
+ *dest_aspect = vw->m_displayRatio;
+
+ /* give false aspect for audio visualization*/
+ if ( !vw->hasVideo() ) {
+ *dest_aspect = (video_width*video_aspect)/((vw->width()*video_height/vw->height())-0.5);
+ }
+
+ /* correct size with video aspect */
+ if (video_aspect >= vw->m_displayRatio)
+ video_width = (int) ( (double) (video_width * video_aspect / vw->m_displayRatio + 0.5) );
+ else
+ video_height = (int) ( (double) (video_height * vw->m_displayRatio / video_aspect) + 0.5);
+
+ /* frame size changed */
+ if ( (video_width != vw->m_videoFrameWidth) || (video_height != vw->m_videoFrameHeight) )
+ {
+ debugOut(QString("New video frame size: %1x%2 - aspect ratio: %3").arg(video_width).arg(video_height).arg(video_aspect));
+ vw->m_videoFrameWidth = video_width;
+ vw->m_videoFrameHeight = video_height;
+ vw->m_videoAspect = video_aspect;
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_FRAME_FORMAT_CHANGE));
+
+ /* auto-resize parent widget */
+ if ((vw->m_autoresizeEnabled) && (vw->parentWidget()) && (vw->m_posTimer.isActive()) && (!vw->parentWidget()->isFullScreen())
+ && (video_width > 0) && (video_height > 0))
+ {
+ vw->m_newParentSize = vw->parentWidget()->size() - QSize((vw->width() - video_width), vw->height() - video_height);
+
+ debugOut(QString("Resize video window to: %1x%2").arg(vw->m_newParentSize.width()).arg(vw->m_newParentSize.height()));
+
+ /* we should not do a resize() inside a xine thread,
+ but post an event to the main thread */
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_RESIZE_PARENT));
+ }
+ }
+}
+
+
+/*
+ * XINE EVENT THREAD
+ * only the QT event thread should do GUI operations,
+ * we use QApplication::postEvent() and a reimplementation of QObject::timerEvent() to
+ * make sure all critical jobs are done within the QT main thread context
+ *
+ * for more information see http://doc.trolltech.com/3.1/threads.html
+ */
+
+void KXineWidget::xineEventListener(void *p, const xine_event_t* xineEvent)
+{
+
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ switch (xineEvent->type)
+ {
+ case XINE_EVENT_UI_PLAYBACK_FINISHED:
+ {
+ debugOut("xine event: playback finished");
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_PLAYBACK_FINISHED ));
+ break;
+ }
+ case XINE_EVENT_UI_CHANNELS_CHANGED: /* new channel informations */
+ {
+ debugOut("xine event: channels changed");
+ int i,channels;
+ char* lang = new char[128];
+ QString slang;
+ int num;
+ QStringList tmp;
+ bool update=false, sk;
+
+ /*** get audio channels ***/
+ tmp.append(i18n("auto"));
+ channels = xine_get_stream_info(vw->m_xineStream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
+ for(i = 0; i < channels; i++)
+ {
+ slang = QString("%1.").arg(i+1);
+ if (xine_get_audio_lang(vw->m_xineStream, i, lang))
+ slang += lang;
+ tmp << slang;
+ }
+ if ( tmp!=vw->m_audioCh ) {
+ update = true;
+ vw->m_audioCh = tmp;
+ }
+ num = xine_get_param(vw->m_xineStream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
+ if ( vw->m_currentAudio!=num ) {
+ update = true;
+ if ( num>channels )
+ vw->m_currentAudio = -1;
+ else
+ vw->m_currentAudio = num;
+ }
+
+ /*** get subtitle channels ***/
+ tmp.clear();
+ tmp.append(i18n("off"));
+ channels = xine_get_stream_info(vw->m_xineStream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
+ for(i = 0; i<channels; i++)
+ {
+ slang = QString("%1.").arg(i+1);
+ if (xine_get_spu_lang(vw->m_xineStream, i, lang))
+ slang += lang;
+ tmp << slang;
+ }
+ if ( tmp!=vw->m_subCh ) {
+ update = true;
+ vw->m_subCh = tmp;
+ }
+ num = xine_get_param(vw->m_xineStream, XINE_PARAM_SPU_CHANNEL);
+ if ( vw->m_currentSub!=num ) {
+ update = true;
+ if ( num>channels )
+ vw->m_currentSub = -1;
+ else
+ vw->m_currentSub = num;
+ }
+
+ delete [] lang;
+
+ //check if stream is seekable
+ sk = (bool)xine_get_stream_info(vw->m_xineStream, XINE_STREAM_INFO_SEEKABLE);
+ if ( vw->m_trackIsSeekable!=sk ) {
+ update = true;
+ vw->m_trackIsSeekable = sk;
+ }
+
+ if ( update )
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_CHANNELS));
+ break;
+ }
+ case XINE_EVENT_UI_SET_TITLE: /* set new title */
+ {
+ debugOut("xine event: ui set title");
+ xine_ui_data_t* xd = (xine_ui_data_t*)xineEvent->data;
+ vw->m_trackTitle = QString::fromLocal8Bit( (char*)xd->str );
+
+ vw->m_lengthInfoTries = 0;
+ vw->m_lengthInfoTimer.start(1000); /* May be new Length on Changing DVD/VCD titles */
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_TITLE));
+ break;
+ }
+ case XINE_EVENT_PROGRESS:
+ {
+ debugOut("xine event: progress info");
+ xine_progress_data_t* pd = (xine_progress_data_t*)xineEvent->data;
+
+ vw->m_statusString = QString::fromLocal8Bit(pd->description) + " " + QString::number(pd->percent) + "%";
+
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_STATUS));
+ break;
+ }
+ case XINE_EVENT_DROPPED_FRAMES:
+ {
+ debugOut("xine event: dropped frames");
+ xine_dropped_frames_t* dropped = (xine_dropped_frames_t*)xineEvent->data;
+
+ warningOut(QString("Skipped frames: %1 - discarded frames: %2").arg(dropped->skipped_frames/10).arg(dropped->discarded_frames/10));
+
+ break;
+ }
+ case XINE_EVENT_SPU_BUTTON:
+ {
+ debugOut("xine event: spu button");
+ xine_spu_button_t* button = (xine_spu_button_t*)xineEvent->data;
+
+ if (button->direction == 1) /* enter a button */
+ {
+ debugOut("DVD Menu: Mouse entered button");
+ vw->m_DVDButtonEntered = true;
+ }
+ else
+ {
+ debugOut("DVD Menu: Mouse left button");
+ vw->m_DVDButtonEntered = false;
+ }
+
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_CHANGE_CURSOR));
+ break;
+ }
+ case XINE_EVENT_UI_NUM_BUTTONS:
+ {
+ debugOut("xine event: ui num buttons");
+
+ break;
+ }
+ case XINE_EVENT_MRL_REFERENCE:
+ {
+ debugOut("xine event: mrl reference");
+ xine_mrl_reference_data_t* mrldata = (xine_mrl_reference_data_t*)xineEvent->data;
+ vw->m_newMRLReference = mrldata->mrl;
+
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_MRL_REFERENCE));
+ break;
+ }
+ case XINE_EVENT_FRAME_FORMAT_CHANGE:
+ {
+ // debugOut("xine event: frame format change");
+
+ // QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_FRAME_FORMAT_CHANGE));
+ break;
+ }
+ case XINE_EVENT_AUDIO_LEVEL:
+ {
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_VOLUME_LEVEL));
+ break;
+ }
+ case XINE_EVENT_UI_MESSAGE:
+ {
+ debugOut("xine event: xine message");
+
+ xine_ui_message_data_t *data = (xine_ui_message_data_t *)xineEvent->data;
+ QString message;
+
+ switch(data->type)
+ {
+ case XINE_MSG_NO_ERROR:
+ {
+ /* copy strings, and replace '\0' separators by '\n' */
+ char* s = data->messages;
+ char* d = new char[2000];
+
+ while(s && (*s != '\0') && ((*s + 1) != '\0'))
+ {
+ switch(*s)
+ {
+ case '\0':
+ {
+ *d = '\n';
+ break;
+ }
+ default:
+ {
+ *d = *s;
+ break;
+ }
+ }
+ s++;
+ d++;
+ }
+ *++d = '\0';
+
+ message = d;
+ delete [] d;
+ break;
+ }
+ case XINE_MSG_GENERAL_WARNING:
+ {
+ message = i18n("General Warning: \n");
+
+ if(data->explanation)
+ message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
+ else
+ message = message + i18n("No Informations available.");
+
+ break;
+ }
+ case XINE_MSG_SECURITY:
+ {
+ message = i18n("Security Warning: \n");
+
+ if(data->explanation)
+ message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
+
+ break;
+ }
+ case XINE_MSG_UNKNOWN_HOST:
+ {
+ message = i18n("The host you're trying to connect is unknown.\nCheck the validity of the specified hostname. ");
+ if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ break;
+ }
+ case XINE_MSG_UNKNOWN_DEVICE:
+ {
+ message = i18n("The device name you specified seems invalid. ");
+ if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ break;
+ }
+ case XINE_MSG_NETWORK_UNREACHABLE:
+ {
+ message = i18n("The network looks unreachable.\nCheck your network setup and the server name. ");
+ if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ break;
+ }
+ case XINE_MSG_AUDIO_OUT_UNAVAILABLE:
+ {
+ message = i18n("Audio output unavailable. Device is busy. ");
+ if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ break;
+ }
+ case XINE_MSG_CONNECTION_REFUSED:
+ {
+ message = i18n("The connection was refused.\nCheck the host name. ");
+ if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ break;
+ }
+ case XINE_MSG_FILE_NOT_FOUND:
+ {
+ message = "@"+i18n("The specified file or url was not found. Please check it. ");
+ if(data->explanation)
+ message = message + "(" + QString::fromLocal8Bit((char *) data + data->parameters) + ")";
+ break;
+ }
+ case XINE_MSG_PERMISSION_ERROR:
+ {
+ message = i18n("Permission to this source was denied. ");
+ // if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ break;
+ }
+ case XINE_MSG_READ_ERROR:
+ {
+ message = i18n("The source can't be read.\nMaybe you don't have enough rights for this, or source doesn't contain data (e.g: no disc in drive). ");
+ if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ debugOut(message);
+ return; // This error is handled by autoinstallation
+ }
+ case XINE_MSG_LIBRARY_LOAD_ERROR:
+ {
+ message = i18n("A problem occur while loading a library or a decoder: ");
+ if(data->explanation)
+ message = message + ((char *) data + data->parameters);
+ break;
+ }
+ case XINE_MSG_ENCRYPTED_SOURCE:
+ {
+ message = i18n("The source seems encrypted, and can't be read. ");
+ if (vw->m_trackURL.contains("dvd:/"))
+ {
+ if (KaffeinePart::installDistroCodec(vw, "xine-engine", "dvdcss"))
+ return;
+ message = message + i18n("\nYour DVD is probably crypted. According to your country laws, you can or can't use libdvdcss to be able to read this disc. ");
+ }
+ if(data->explanation)
+ message = message + "(" + ((char *) data + data->parameters) + ")";
+ break;
+ }
+ default:
+ {
+ message = i18n("Unknown error: \n");
+ if(data->explanation)
+ message = message + ((char *) data + data->explanation) + " " + ((char *) data + data->parameters);
+ break;
+ }
+ }
+
+ vw->m_xineMessage = message;
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_XINE_MESSAGE));
+ break;
+ }
+ default:
+ {
+ //debugOut("xine event: unhandled type ");
+ break;
+ }
+ }
+}
+
+void KXineWidget::timerEvent( QTimerEvent* tevent )
+{
+ switch ( tevent->timerId() )
+ {
+ case TIMER_EVENT_PLAYBACK_FINISHED:
+ {
+ if ( !TimeShiftFilename.isEmpty() )
+ {
+ QTimer::singleShot(0, this, SLOT(slotPlayTimeShift()));
+ break;
+ }
+ if ( m_trackURL=="DVB" || m_trackURL.contains(".kaxtv") )
+ break;
+
+#ifdef XINE_PARAM_GAPLESS_SWITCH
+ if ( xine_check_version(1,1,1) )
+ xine_set_param( m_xineStream, XINE_PARAM_GAPLESS_SWITCH, 1);
+#endif
+ if (isQueueEmpty())
+ {
+ if (m_trackURL != m_logoFile)
+ emit signalPlaybackFinished();
+ else
+ xine_stop(m_xineStream);
+ }
+ else
+ QTimer::singleShot(0, this, SLOT(slotPlay()));
+ break;
+ }
+ case TIMER_EVENT_NEW_CHANNELS:
+ {
+ emit signalNewChannels(m_audioCh, m_subCh, m_currentAudio, m_currentSub);
+ break;
+ }
+ case TIMER_EVENT_NEW_TITLE:
+ {
+ emit signalTitleChanged();
+ break;
+ }
+ case TIMER_EVENT_FRAME_FORMAT_CHANGE:
+ {
+ if ((m_trackHasVideo) && (m_trackURL != m_logoFile))
+ emit signalVideoSizeChanged();
+ break;
+ }
+ case TIMER_EVENT_NEW_STATUS:
+ {
+ emit signalXineStatus(m_statusString);
+ break;
+ }
+ case TIMER_EVENT_CHANGE_CURSOR:
+ {
+ if (m_DVDButtonEntered)
+ setCursor(QCursor(Qt::PointingHandCursor));
+ else
+ setCursor(QCursor(Qt::ArrowCursor));
+ break;
+ }
+ case TIMER_EVENT_NEW_MRL_REFERENCE:
+ {
+ m_queue.prepend(m_newMRLReference );
+ break;
+ }
+ case TIMER_EVENT_NEW_VOLUME_LEVEL:
+ {
+ emit signalSyncVolume();
+ break;
+ }
+ case TIMER_EVENT_NEW_XINE_MESSAGE:
+ {
+ if (!m_recentMessagesTimer.isActive())
+ {
+ m_recentMessagesTimer.start(1500);
+ emit signalXineMessage(m_xineMessage);
+ }
+ else
+ {
+ //restart
+ warningOut(QString("Message: '%1' was blocked!").arg(m_xineMessage));
+ m_recentMessagesTimer.start(1500);
+ }
+ break;
+ }
+ case TIMER_EVENT_NEW_XINE_ERROR:
+ {
+ emit signalXineError(m_xineError);
+ break;
+ }
+ case TIMER_EVENT_RESTART_PLAYBACK:
+ {
+ appendToQueue(m_trackURL);
+ slotPlay();
+ break;
+ }
+ case TIMER_EVENT_RESIZE_PARENT:
+ {
+ parentWidget()->resize(m_newParentSize);
+ break;
+ }
+ default: break;
+ }
+}
+
+void KXineWidget::slotNoRecentMessage()
+{
+ m_recentMessagesTimer.stop();
+}
+
+/******************* new video driver *********************/
+
+void KXineWidget::videoDriverChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ if (entry == NULL) return;
+#ifndef USE_QT_ONLY
+ KXineWidget* vw = (KXineWidget*) p;
+ xine_video_port_t* oldVideoDriver = vw->m_videoDriver;
+ xine_video_port_t* noneVideoDriver;
+
+ int pos, time, length;
+
+ debugOut(QString("New video driver: %1").arg(entry->enum_values[entry->num_value]));
+
+ if (vw->m_osd)
+ {
+ xine_osd_free(vw->m_osd);
+ vw->m_osd = NULL;
+ }
+
+ noneVideoDriver = xine_open_video_driver(vw->m_xineEngine, "none",
+ XINE_VISUAL_TYPE_NONE, NULL);
+ if (!noneVideoDriver)
+ {
+ errorOut("Can't init Video Driver 'none', operation aborted.");
+ return;
+ }
+
+ bool playing = false;
+ if (vw->isPlaying())
+ {
+ playing = true;
+ vw->m_savedPos = 0;
+
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(vw->m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+
+ if ( ret != 0 )
+ vw->m_savedPos = pos;
+ }
+
+ xine_close(vw->m_xineStream);
+
+ /* wire filters to "none" driver so the old one can be safely disposed */
+ vw->m_videoDriver = noneVideoDriver;
+ vw->unwireVideoFilters();
+ vw->wireVideoFilters();
+
+ vw->unwireAudioFilters();
+ if (vw->m_visualPlugin)
+ {
+ debugOut(QString("Dispose visual plugin: %1").arg(vw->m_visualPluginName));
+ delete vw->m_visualPlugin;
+ vw->m_visualPlugin = NULL;
+ }
+
+ xine_event_dispose_queue(vw->m_eventQueue);
+ xine_dispose(vw->m_xineStream);
+
+ xine_close_video_driver(vw->m_xineEngine, oldVideoDriver);
+
+ vw->m_videoDriver = xine_open_video_driver(vw->m_xineEngine,
+#ifndef HAVE_XCB
+ entry->enum_values[entry->num_value], XINE_VISUAL_TYPE_X11,
+#else
+ entry->enum_values[entry->num_value], XINE_VISUAL_TYPE_XCB,
+#endif
+ (void *) &(vw->m_x11Visual));
+
+ if (!vw->m_videoDriver)
+ {
+ vw->m_xineError = i18n("Error: Can't init new Video Driver %1 - using %2!").arg(entry->enum_values[entry->num_value]).arg(vw->m_videoDriverName);
+ QApplication::postEvent(vw, new QTimerEvent( TIMER_EVENT_NEW_XINE_ERROR));
+ playing = false;
+ vw->m_videoDriver = xine_open_video_driver(vw->m_xineEngine,
+#ifndef HAVE_XCB
+ vw->m_videoDriverName.ascii(), XINE_VISUAL_TYPE_X11,
+#else
+ vw->m_videoDriverName.ascii(), XINE_VISUAL_TYPE_XCB,
+#endif
+ (void *) &(vw->m_x11Visual));
+ }
+ else
+ {
+ vw->m_videoDriverName = entry->enum_values[entry->num_value];
+ vw->m_statusString = i18n("Using Video Driver: %1").arg(vw->m_videoDriverName);
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_STATUS));
+ }
+
+ vw->m_xineStream = xine_stream_new(vw->m_xineEngine, vw->m_audioDriver, vw->m_videoDriver);
+ vw->m_eventQueue = xine_event_new_queue (vw->m_xineStream);
+ xine_event_create_listener_thread(vw->m_eventQueue, &KXineWidget::xineEventListener, p);
+
+ /* rewire filters to the new driver */
+ vw->unwireVideoFilters();
+ vw->wireVideoFilters();
+
+ /* "none" can now be disposed too */
+ xine_close_video_driver(vw->m_xineEngine, noneVideoDriver);
+
+ vw->initOSD();
+
+ if (playing)
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_RESTART_PLAYBACK));
+#endif
+}
+
+/*********************** new audio driver *************************/
+
+void KXineWidget::audioDriverChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ if (entry == NULL) return;
+#ifndef USE_QT_ONLY
+ KXineWidget* vw = (KXineWidget*) p;
+
+ int pos, time, length;
+
+ debugOut(QString("New audio driver: %1").arg(entry->enum_values[entry->num_value]));
+
+ if (vw->m_osd)
+ {
+ xine_osd_free(vw->m_osd);
+ vw->m_osd = NULL;
+ }
+
+ vw->unwireVideoFilters();
+
+ bool playing = false;
+ if (vw->isPlaying())
+ {
+ playing = true;
+ vw->m_savedPos = 0;
+
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(vw->m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+
+ if ( ret != 0 )
+ vw->m_savedPos = pos;
+ }
+
+ xine_close(vw->m_xineStream);
+
+ vw->unwireAudioFilters();
+ if (vw->m_visualPlugin)
+ {
+ debugOut(QString("Dispose visual plugin: %1").arg(vw->m_visualPluginName));
+ delete vw->m_visualPlugin;
+ vw->m_visualPlugin = NULL;
+ }
+
+ xine_event_dispose_queue(vw->m_eventQueue);
+ xine_dispose(vw->m_xineStream);
+ xine_close_audio_driver(vw->m_xineEngine, vw->m_audioDriver);
+ vw->m_audioDriver = NULL;
+
+ vw->m_audioDriver = xine_open_audio_driver(vw->m_xineEngine, entry->enum_values[entry->num_value], NULL);
+
+ if (!vw->m_audioDriver)
+ {
+ vw->m_xineError = i18n("Error: Can't init new Audio Driver %1 - using %2!").arg(entry->enum_values[entry->num_value]).arg(vw->m_audioDriverName);
+ QApplication::postEvent(vw, new QTimerEvent( TIMER_EVENT_NEW_XINE_ERROR));
+ playing = false;
+ vw->m_audioDriver = xine_open_audio_driver(vw->m_xineEngine, vw->m_audioDriverName.ascii(), NULL);
+ }
+ else
+ {
+ vw->m_audioDriverName = entry->enum_values[entry->num_value];
+ vw->m_statusString = i18n("Using Audio Driver: %1").arg(vw->m_audioDriverName);
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_NEW_STATUS));
+ }
+
+ vw->m_xineStream = xine_stream_new(vw->m_xineEngine, vw->m_audioDriver, vw->m_videoDriver);
+ vw->m_eventQueue = xine_event_new_queue (vw->m_xineStream);
+ xine_event_create_listener_thread(vw->m_eventQueue, &KXineWidget::xineEventListener, p);
+
+ vw->wireVideoFilters();
+
+ vw->initOSD();
+
+ if (playing)
+ QApplication::postEvent(vw, new QTimerEvent(TIMER_EVENT_RESTART_PLAYBACK));
+#endif
+}
+
+/******** change audio mixer method ****************/
+void KXineWidget::audioMixerMethodChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ vw->m_softwareMixer = (bool)entry->num_value;
+}
+
+/******** Callback for OSD configuration ****************/
+void KXineWidget::showOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ if (vw->m_osd)
+ vw->m_osdShow = (bool)entry->num_value;
+}
+
+void KXineWidget::sizeForOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ const int fontsizetable[] = { 16,20,24,32,48,64 };
+
+ if (entry->num_value >= 6)
+ {
+ debugOut("Font size not defined: Shouldn't have happened");
+ return;
+ }
+
+ if (vw->m_osd)
+ {
+ vw->m_osdSize = entry->num_value;
+ xine_osd_set_font(vw->m_osd, vw->m_osdFont, fontsizetable[vw->m_osdSize]);
+ }
+}
+
+void KXineWidget::fontForOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ const int fontsizetable[] = { 16,20,24,32,48,64 };
+
+ if (vw->m_osd)
+ if (entry->str_value)
+ {
+ free(vw->m_osdFont);
+ vw->m_osdFont = strdup(entry->str_value);
+ if (!xine_osd_set_font(vw->m_osd, vw->m_osdFont, fontsizetable[vw->m_osdSize]))
+ {
+ free(vw->m_osdFont);
+ vw->m_osdFont = strdup("sans");
+ if (!xine_osd_set_font(vw->m_osd, vw->m_osdFont, fontsizetable[vw->m_osdSize]))
+ warningOut("Default SANS font not found: shouldn't have happened.");
+ }
+ }
+}
+
+void KXineWidget::monitorXResChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ vw->monitorXRes = (double)entry->num_value;
+ double m_displayRatio = vw->monitorYRes / vw->monitorXRes;
+ if ((m_displayRatio >= 0.98) && (m_displayRatio <= 1.02))
+ m_displayRatio = 1;
+ vw->m_displayRatio = m_displayRatio;
+}
+
+void KXineWidget::monitorYResChangedCallback(void* p, xine_cfg_entry_t* entry)
+{
+ if (p == NULL) return;
+ KXineWidget* vw = (KXineWidget*) p;
+
+ vw->monitorYRes = (double)entry->num_value;
+ double m_displayRatio = vw->monitorYRes / vw->monitorXRes;
+ if ((m_displayRatio >= 0.98) && (m_displayRatio <= 1.02))
+ m_displayRatio = 1;
+ vw->m_displayRatio = m_displayRatio;
+}
+
+/**********************************************
+ * EVENT LOOP
+ *********************************************/
+
+#ifndef HAVE_XCB
+bool KXineWidget::x11Event(XEvent *event)
+{
+ if (isXineReady())
+ if (event->type == Expose)
+ if (event->xexpose.count == 0)
+ xine_port_send_gui_data(m_videoDriver, XINE_GUI_SEND_EXPOSE_EVENT, event);
+
+ return false;
+}
+#else
+void KXineWidget::paintEvent(QPaintEvent *event)
+{
+ if (isXineReady()) {
+ const QRect &rect = event->rect();
+
+ xcb_expose_event_t xcb_event;
+ memset(&xcb_event, 0, sizeof(xcb_event));
+
+ xcb_event.window = winId();
+ xcb_event.x = rect.x();
+ xcb_event.y = rect.y();
+ xcb_event.width = rect.width();
+ xcb_event.height = rect.height();
+ xcb_event.count = 0;
+
+ xine_port_send_gui_data(m_videoDriver, XINE_GUI_SEND_EXPOSE_EVENT, &xcb_event);
+ }
+
+ QWidget::paintEvent(event);
+}
+#endif
+
+/**********************************************************
+ * INIT XINE ENGINE
+ *********************************************************/
+
+void KXineWidget::polish()
+{
+ if ((!m_startXineManual) && (!isXineReady())) /* start xine engine automatically? */
+ {
+ initXine();
+ }
+}
+
+bool KXineWidget::initXine()
+{
+ if (isXineReady())
+ return true;
+
+ emit signalXineStatus(i18n("Init xine..."));
+ globalPosChanged(); /* get global pos of the window */
+
+ /**** INIT XINE DISPLAY ****/
+
+#ifndef HAVE_XCB
+ XInitThreads();
+
+ connection = XOpenDisplay(NULL);
+#else
+ int screen_nbr = 0;
+ connection = xcb_connect(NULL, &screen_nbr);
+#endif
+
+ if (!connection)
+ {
+ emit signalXineFatal(i18n("Failed to connect to X-Server!"));
+ return false;
+ }
+
+ int m_xineWindow = winId();
+
+/* // determine display aspect ratio
+ double resHor = ((double) DisplayWidth(x11Display(), x11Screen())) / DisplayWidthMM(x11Display(), x11Screen());
+ double resVer = ((double) DisplayHeight(x11Display(), x11Screen())) / DisplayHeightMM(x11Display(), x11Screen());
+
+ m_displayRatio = resVer / resHor;
+
+ if ((m_displayRatio >= 0.98) && (m_displayRatio <= 1.02))
+ m_displayRatio = 1;
+
+#ifdef HAVE_XINERAMA
+ int dummy_event, dummy_error;
+
+ if (XineramaQueryExtension(x11Display(), &dummy_event, &dummy_error))
+ {
+ int count = 1;
+ debugOut("Xinerama extension present");
+ XineramaQueryScreens(x11Display(), &count);
+ debugOut(QString("%1 screens detected").arg(count));
+ if (count > 1)
+ // multihead -> assuming square pixels
+ m_displayRatio = 1.0;
+ }
+#endif
+
+ debugOut(QString("Display aspect ratio (v/h): %1").arg(m_displayRatio));*/
+
+ /**** INIT XINE ENGINE ****/
+
+ debugOut(QString("Using xine version %1").arg(xine_get_version_string()));
+
+ m_xineEngine = xine_new();
+ if (!m_xineEngine)
+ {
+ emit signalXineFatal(i18n("Can't init xine Engine!"));
+ return false;
+ }
+
+ if (m_xineVerbose)
+ xine_engine_set_param(m_xineEngine, XINE_ENGINE_PARAM_VERBOSITY, 99);
+
+ /* load configuration */
+
+ if (!QFile::exists(m_configFilePath))
+ warningOut("No config file found, will create one...");
+ else
+ xine_config_load(m_xineEngine, QFile::encodeName(m_configFilePath));
+
+
+ debugOut("Post-init xine engine");
+ xine_init(m_xineEngine);
+
+ /** set xine parameters **/
+
+ const char* const* drivers = NULL;
+ drivers = xine_list_audio_output_plugins(m_xineEngine);
+ int i = 0;
+ while (drivers[i] != NULL) i++;
+ m_audioChoices = new char*[i+2];
+ m_audioChoices[0] = strdup("auto");
+ m_audioDriverList << m_audioChoices[0];
+ i = 0;
+ while(drivers[i])
+ {
+ m_audioChoices[i+1] = strdup(drivers[i]);
+ m_audioDriverList << m_audioChoices[i+1];
+ i++;
+ }
+ m_audioChoices[i+1] = NULL;
+
+ m_audioInfo = strdup(i18n("Audiodriver to use (default: auto)").local8Bit());
+ i = xine_config_register_enum(m_xineEngine, "audio.driver", 0,
+ m_audioChoices, m_audioInfo, NULL, 10, &KXineWidget::audioDriverChangedCallback, this);
+
+ if (m_audioDriverList.contains(m_preferedAudio))
+ m_audioDriverName = m_preferedAudio;
+ else
+ m_audioDriverName = m_audioChoices[i];
+
+ debugOut(QString("Use audio driver %1").arg(m_audioDriverName));
+
+ drivers = xine_list_video_output_plugins(m_xineEngine);
+ i = 0;
+ while (drivers[i] != NULL) i++;
+ m_videoChoices = new char*[i+2];
+ m_videoChoices[0] = strdup("auto");
+ m_videoDriverList << m_videoChoices[0];
+ i = 0;
+ while(drivers[i])
+ {
+ m_videoChoices[i+1] = strdup(drivers[i]);
+ m_videoDriverList << m_videoChoices[i+1];
+ i++;
+ }
+ m_videoChoices[i+1] = NULL;
+
+ m_videoInfo = strdup(i18n("Videodriver to use (default: auto)").local8Bit());
+ i = xine_config_register_enum(m_xineEngine, "video.driver", 0,
+ m_videoChoices, m_videoInfo, NULL, 10, &KXineWidget::videoDriverChangedCallback, this);
+
+ if (m_videoDriverList.contains(m_preferedVideo))
+ m_videoDriverName = m_preferedVideo;
+ else
+ m_videoDriverName = m_videoChoices[i];
+
+ debugOut(QString("Use video driver %1").arg(m_videoDriverName));
+
+ m_mixerInfo = strdup(i18n("Use software audio mixer").local8Bit());
+ m_softwareMixer = (bool)xine_config_register_bool(m_xineEngine, "audio.mixer_software", 1, m_mixerInfo,
+ NULL, 10, &KXineWidget::audioMixerMethodChangedCallback, this);
+
+ m_osdShowInfo = strdup(i18n("Show OSD Messages").local8Bit());
+ m_osdShow = (bool)xine_config_register_bool(m_xineEngine, "osd.osd_messages", 1, m_osdShowInfo,
+ NULL, 10, &KXineWidget::showOSDMessagesChangedCallback, this);
+
+ m_osdSizeOptions = new char*[7];
+ m_osdSizeOptions[0] = strdup("tiny");
+ m_osdSizeOptions[1] = strdup("small");
+ m_osdSizeOptions[2] = strdup("medium");
+ m_osdSizeOptions[3] = strdup("large");
+ m_osdSizeOptions[4] = strdup("very large");
+ m_osdSizeOptions[5] = strdup("huge");
+ m_osdSizeOptions[6] = NULL;
+
+ m_osdSizeInfo = strdup(i18n("Size of OSD text").local8Bit());
+ m_osdSize = (int)xine_config_register_enum(m_xineEngine, "osd.osd_size", 1 /*small - 20P*/, m_osdSizeOptions, m_osdSizeInfo,
+ NULL, 10, &KXineWidget::sizeForOSDMessagesChangedCallback, this);
+
+ m_osdFontInfo = strdup(i18n("Font for OSD Messages").local8Bit());
+ m_osdFont = strdup((char*)xine_config_register_string(m_xineEngine, "osd.osd_font", "sans", m_osdFontInfo,
+ NULL, 10, &KXineWidget::fontForOSDMessagesChangedCallback, this));
+
+ xResInfo = strdup(i18n("Monitor horizontal resolution (dpi).").local8Bit());
+ monitorXRes = (bool)xine_config_register_range(m_xineEngine, "video.screen_x_res", 78, 1, 200, xResInfo,
+ NULL, 10, &KXineWidget::monitorXResChangedCallback, this);
+ yResInfo = strdup(i18n("Monitor vertical resolution (dpi).").local8Bit());
+ monitorYRes = (bool)xine_config_register_range(m_xineEngine, "video.screen_y_res", 78, 1, 200, yResInfo,
+ NULL, 10, &KXineWidget::monitorYResChangedCallback, this);
+
+ double resHor = (double)monitorXRes;
+ double resVer = (double)monitorYRes;
+ m_displayRatio = resVer / resHor;
+ if ((m_displayRatio >= 0.98) && (m_displayRatio <= 1.02))
+ m_displayRatio = 1;
+
+ /* init video driver */
+ debugOut("Init video driver");
+
+#ifndef HAVE_XCB
+ m_x11Visual.display = connection;
+ m_x11Visual.screen = DefaultScreen(connection);
+ m_x11Visual.d = m_xineWindow;
+#else
+ xcb_screen_iterator_t screen_it = xcb_setup_roots_iterator(xcb_get_setup(connection));
+ while ((screen_it.rem > 1) && (screen_nbr > 0)) {
+ xcb_screen_next(&screen_it);
+ --screen_nbr;
+ }
+
+ m_x11Visual.connection = connection;
+ m_x11Visual.screen = screen_it.data;
+ m_x11Visual.window = m_xineWindow;
+#endif
+ m_x11Visual.dest_size_cb = &KXineWidget::destSizeCallback;
+ m_x11Visual.frame_output_cb = &KXineWidget::frameOutputCallback;
+ m_x11Visual.user_data = (void*)this;
+
+ m_videoDriver = xine_open_video_driver(m_xineEngine,
+#ifndef HAVE_XCB
+ m_videoDriverName.ascii(), XINE_VISUAL_TYPE_X11,
+#else
+ m_videoDriverName.ascii(), XINE_VISUAL_TYPE_XCB,
+#endif
+ (void *) &(m_x11Visual));
+
+ if (!m_videoDriver && m_videoDriverName != "auto")
+ {
+ emit signalXineError(i18n("Can't init Video Driver '%1' - trying 'auto'...").arg(m_videoDriverName));
+ m_videoDriverName = "auto";
+ m_videoDriver = xine_open_video_driver(m_xineEngine,
+#ifndef HAVE_XCB
+ m_videoDriverName.ascii(), XINE_VISUAL_TYPE_X11,
+#else
+ m_videoDriverName.ascii(), XINE_VISUAL_TYPE_XCB,
+#endif
+ (void *) &(m_x11Visual));
+ }
+
+ if (!m_videoDriver)
+ {
+ emit signalXineFatal(i18n("All Video Drivers failed to initialize!"));
+ return false;
+ }
+
+ /* init audio driver */
+ debugOut("Init audio driver");
+
+ m_audioDriver = xine_open_audio_driver(m_xineEngine, m_audioDriverName.ascii(), NULL);
+
+ if (!m_audioDriver && m_audioDriverName != "auto")
+ {
+ emit signalXineError(i18n("Can't init Audio Driver '%1' - trying 'auto'...").arg(m_audioDriverName));
+ m_audioDriverName = "auto";
+ m_audioDriver = xine_open_audio_driver (m_xineEngine, m_audioDriverName.ascii(), NULL);
+ }
+
+ if (!m_audioDriver)
+ {
+ emit signalXineFatal(i18n("All Audio Drivers failed to initialize!"));
+ return false;
+ }
+
+ //debugOut("Open xine stream");
+
+ m_xineStream = xine_stream_new(m_xineEngine, m_audioDriver, m_videoDriver);
+ if (!m_xineStream)
+ {
+ emit signalXineFatal(i18n("Can't create a new xine Stream!"));
+ return false;
+ }
+
+#ifdef XINE_PARAM_EARLY_FINISHED_EVENT
+ if ( xine_check_version(1,1,1) ) {
+ // enable gapless playback
+ xine_set_param(m_xineStream, XINE_PARAM_EARLY_FINISHED_EVENT, 1 );
+ }
+#endif
+
+ /*** OSD ***/
+
+ initOSD();
+
+ /** event handling **/
+
+ m_eventQueue = xine_event_new_queue (m_xineStream);
+ xine_event_create_listener_thread(m_eventQueue, &KXineWidget::xineEventListener, (void*)this);
+
+ //maybe user closed player in muted state
+ if (m_softwareMixer)
+ xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_MUTE, 0);
+ else
+ xine_set_param(m_xineStream, XINE_PARAM_AUDIO_MUTE, 0);
+
+ m_xineReady = true;
+
+ debugOut("xine init successful");
+
+ emit signalXineStatus(i18n("Ready"));
+ emit signalXineReady();
+
+ /** something to play? **/
+ slotPlay();
+
+ return true;
+}
+
+void KXineWidget::initOSD()
+{
+ debugOut("Init OSD");
+ const int fontsizetable[] = { 16,20,24,32,48,64 };
+ m_osd = xine_osd_new(m_xineStream, 10, 10, 1000, 200);
+ if (m_osd)
+ {
+ if (!xine_osd_set_font(m_osd, m_osdFont, fontsizetable[m_osdSize]))
+ {
+ debugOut(QString("Font ->%1<- specified for OSD doesn't exists.").arg(m_osdFont));
+ free(m_osdFont);
+ m_osdFont = strdup("sans");
+ xine_osd_set_font(m_osd, m_osdFont, fontsizetable[m_osdSize]);
+ }
+ debugOut(QString("Font for OSD: %1").arg(m_osdFont));
+ xine_osd_set_text_palette(m_osd, XINE_TEXTPALETTE_WHITE_BLACK_TRANSPARENT, XINE_OSD_TEXT1);
+ m_osdUnscaled = (xine_osd_get_capabilities(m_osd) & XINE_OSD_CAP_UNSCALED);
+ if (m_osdUnscaled)
+ debugOut("Unscaled OSD available");
+ }
+ else
+ warningOut("Initialisation of xine OSD failed.");
+}
+
+/************************************************
+ * PLAY MRL
+ ************************************************/
+
+bool KXineWidget::playDvb()
+{
+#ifndef USE_QT_ONLY
+ unwireAudioFilters();
+
+ QPtrList<PostFilter> activeList;
+
+ if (m_audioFilterList.count() && m_audioFiltersEnabled)
+ activeList = m_audioFilterList;
+
+ if ( !dvbHaveVideo )
+ {
+ if (!m_visualPlugin)
+ {
+ debugOut(QString("Init visual plugin: %1").arg(m_visualPluginName));
+ m_visualPlugin = new PostFilter(m_visualPluginName, m_xineEngine, m_audioDriver, m_videoDriver, NULL);
+ }
+
+ activeList.insert (0, m_visualPlugin);
+ }
+ else
+ {
+ if (m_visualPlugin)
+ {
+ debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName));
+ delete m_visualPlugin;
+ m_visualPlugin = NULL;
+ }
+ }
+
+ if (activeList.count())
+ {
+ xine_post_wire_audio_port(activeList.at(activeList.count()-1)->getOutput(), m_audioDriver);
+
+ for (uint i = activeList.count()-1; i >0; i--)
+ {
+ xine_post_wire(activeList.at(i-1)->getOutput(), activeList.at(i)->getInput());
+ }
+
+ xine_post_wire( xine_get_audio_source(m_xineStream), activeList.at(0)->getInput());
+ }
+#endif
+
+ if (!xine_play(m_xineStream, 0,0))
+ {
+ sendXineError();
+ return false;
+ }
+
+ m_currentSpeed = Normal;
+ m_trackHasChapters = false;
+ m_trackArtist = QString::null;
+ m_trackAlbum = QString::null;
+ m_trackNumber = QString::null;
+ m_trackYear = QString::null;
+ m_trackComment = QString::null;
+
+ m_trackIsSeekable = false;
+
+ if ( !dvbHaveVideo ) m_trackHasVideo = false;
+ else m_trackHasVideo = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO);
+ if (m_trackHasVideo)
+ {
+ m_trackVideoCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_VIDEOCODEC);
+ m_videoFrameWidth = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_WIDTH);
+ m_videoFrameHeight = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_HEIGHT);
+ m_trackVideoBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_BITRATE);
+ }
+ else
+ {
+ m_trackVideoCodec = QString::null;
+ m_videoFrameWidth = 0;
+ m_videoFrameHeight = 0;
+ m_trackVideoBitrate = 0;
+ }
+
+ m_trackHasAudio = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_AUDIO);
+ if (m_trackHasAudio)
+ {
+ m_trackAudioCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_AUDIOCODEC);
+ m_trackAudioBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_AUDIO_BITRATE);
+ }
+ else
+ {
+ m_trackAudioCodec = QString::null;
+ m_trackAudioBitrate = 0;
+ }
+
+ m_trackLength = getLengthInfo();
+
+ slotSetAudioChannel(0); //refresh channel info
+ m_posTimer.start(1000);
+
+ emit signalXinePlaying();
+ emit signalXineStatus(i18n("Playing"));
+
+ return true;
+}
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+#define rgb2yuv(R,G,B) ((((((66*R+129*G+25*B+128)>>8)+16)<<8)|(((112*R-94*G-18*B+128)>>8)+128))<<8|(((-38*R-74*G+112*B+128)>>8)+128))
+#else
+#define rgb2yuv(R,G,B) (((((((-38*R-74*G+112*B+128)>>8)+128)<<8)|(((112*R-94*G-18*B+128)>>8)+128))<<8|(((66*R+129*G+25*B+128)>>8)+16))<<8)
+#endif
+
+void KXineWidget::initDvbPalette()
+{
+ if ( dvbColor[0] ) return;
+
+ memset( dvbColor, 0, sizeof(dvbColor) );
+ memset( dvbTrans, 0, sizeof(dvbTrans) );
+ dvbColor[0]=1;
+
+ unsigned int blueText[11] = {
+ rgb2yuv(0,0,0), /* 0 : not used */
+ rgb2yuv(0,0,0), /* 1 : font bg */
+ rgb2yuv(10,50,40), /* 2 : transition bg->border */
+ rgb2yuv(30,100,85), /* 3 */
+ rgb2yuv(50,150,130), /* 4 */
+ rgb2yuv(70,200,175), /* 5 */
+ rgb2yuv(90,255,220), /* 6 : border */
+ rgb2yuv(90,255,220), /* 7 : transition border->fg */
+ rgb2yuv(90,255,220), /* 8 */
+ rgb2yuv(90,255,220), /* 9 */
+ rgb2yuv(90,255,220), /* 10 : font fg */
+ };
+ unsigned int whiteText[11] = {
+ rgb2yuv(0,0,0),
+ rgb2yuv(0,0,0),
+ rgb2yuv(50,50,50),
+ rgb2yuv(100,100,100),
+ rgb2yuv(150,150,150),
+ rgb2yuv(200,200,200),
+ rgb2yuv(255,255,255),
+ rgb2yuv(255,255,255),
+ rgb2yuv(255,255,255),
+ rgb2yuv(255,255,255),
+ rgb2yuv(255,255,255),
+ };
+ unsigned int greenText[11] = {
+ rgb2yuv(0,0,0),
+ rgb2yuv(0,0,0),
+ rgb2yuv(30,50,30),
+ rgb2yuv(60,100,30),
+ rgb2yuv(90,150,90),
+ rgb2yuv(120,200,120),
+ rgb2yuv(150,255,150),
+ rgb2yuv(150,255,150),
+ rgb2yuv(150,255,150),
+ rgb2yuv(150,255,150),
+ rgb2yuv(150,255,150),
+ };
+ unsigned char textAlpha[11] = { 0, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, };
+#define DVB_TEXT_WHITE 100
+#define DVB_TEXT_BLUE 111
+#define DVB_TEXT_GREEN 122
+ int a;
+ for ( a=DVB_TEXT_BLUE; a<DVB_TEXT_BLUE+11; a++ )
+ {
+ dvbColor[a]=blueText[a-DVB_TEXT_BLUE];
+ dvbTrans[a]=textAlpha[a-DVB_TEXT_BLUE];
+ }
+ for ( a=DVB_TEXT_GREEN; a<DVB_TEXT_GREEN+11; a++ )
+ {
+ dvbColor[a]=greenText[a-DVB_TEXT_GREEN];
+ dvbTrans[a]=textAlpha[a-DVB_TEXT_GREEN];
+ }
+ for ( a=DVB_TEXT_WHITE; a<DVB_TEXT_WHITE+11; a++ )
+ {
+ dvbColor[a]=whiteText[a-DVB_TEXT_WHITE];
+ dvbTrans[a]=textAlpha[a-DVB_TEXT_WHITE];
+ }
+#define DVB_COLOR_RED 200
+ dvbColor[DVB_COLOR_RED] = rgb2yuv(255,0,0); dvbTrans[DVB_COLOR_RED] = 15;
+#define DVB_COLOR_GREEN 201
+ dvbColor[DVB_COLOR_GREEN] = rgb2yuv(0,255,0); dvbTrans[DVB_COLOR_GREEN] = 15;
+#define DVB_COLOR_MAGENTA 202
+ dvbColor[DVB_COLOR_MAGENTA] = rgb2yuv(255,128,255); dvbTrans[DVB_COLOR_MAGENTA] = 15;
+#define DVB_COLOR_BAR 203
+ dvbColor[DVB_COLOR_BAR] = rgb2yuv(255,128,0); dvbTrans[DVB_COLOR_BAR] = 8;
+}
+
+void getOSDLine( xine_osd_t *osd, int w, QCString &dest, QCString &source )
+{
+ int prevPos, pos, tw, th;
+ bool wrap=false;
+
+ pos = source.find(" ");
+ if ( pos==-1 ) {
+ dest = source;
+ source = "";
+ return;
+ }
+ prevPos = pos;
+ dest = source.left( pos );
+ while ( !wrap ) {
+ xine_osd_get_text_size( osd, dest, &tw, &th );
+ if ( tw>w ) {
+ wrap = true;
+ break;
+ }
+ if ( pos==-1 )
+ break;
+ prevPos = pos;
+ pos = source.find(" ",pos+1);
+ dest = source.left( pos );
+ }
+ if ( wrap ) {
+ dest = source.left( prevPos );
+ source = source.right( source.length()-dest.length()-1 );
+ }
+ else {
+ dest = source;
+ source = "";
+ }
+}
+
+void KXineWidget::dvbShowOSD()
+{
+ if ( m_trackURL!="DVB" )
+ return;
+
+ if ( xine_get_status(m_xineStream)!=XINE_STATUS_PLAY )
+ return;
+
+ if ( !dvbHaveVideo )
+ m_trackHasVideo = false;
+ else
+ m_trackHasVideo = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO);
+
+ if (m_trackHasVideo) {
+ m_trackVideoCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_VIDEOCODEC);
+ m_videoFrameWidth = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_WIDTH);
+ m_videoFrameHeight = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_HEIGHT);
+ m_trackVideoBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_BITRATE);
+ }
+ else {
+ m_trackVideoCodec = QString::null;
+ m_videoFrameWidth = 0;
+ m_videoFrameHeight = 0;
+ m_trackVideoBitrate = 0;
+ }
+
+ m_trackHasAudio = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_AUDIO);
+ if (m_trackHasAudio) {
+ m_trackAudioCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_AUDIOCODEC);
+ m_trackAudioBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_AUDIO_BITRATE);
+ }
+ else {
+ m_trackAudioCodec = QString::null;
+ m_trackAudioBitrate = 0;
+ }
+
+ if ( dvbOSD ) {
+ xine_osd_free( dvbOSD );
+ dvbOSD = 0;
+ }
+
+ int border=40;
+ int w = m_videoFrameWidth;
+ int h = m_videoFrameHeight;
+ if ( !w || !h )
+ return;
+ if ( w<800 ) {
+ if ( dvbCurrentNext[0]=="E" ) {
+ dvbOSDHideTimer.stop();
+ dvbOSD = xine_osd_new( m_xineStream, border, border, w-(2*border), h-(2/border) );
+ }
+ else
+ dvbOSD = xine_osd_new( m_xineStream, border, h-border-100, w-(2*border), 100 );
+ }
+ if ( dvbOSD ) {
+ QCString ct, cs;
+ if ( !dvbColor[0] ) initDvbPalette();
+ xine_osd_set_palette( dvbOSD, dvbColor, dvbTrans );
+ xine_osd_set_font( dvbOSD, m_osdFont, 16 );
+ xine_osd_set_encoding( dvbOSD, "utf-8" );
+ if ( dvbCurrentNext[0]=="E" )
+ xine_osd_draw_rect( dvbOSD, 0, 0, w-(2*border), h-(2*border), DVB_TEXT_WHITE+1, 1 );
+ else
+ xine_osd_draw_rect( dvbOSD, 0, 0, w-(2*border), 100, DVB_TEXT_WHITE+1, 1 );
+ QString t = QTime::currentTime().toString( "hh:mm" );
+ int tw, th, len;
+ xine_osd_get_text_size(dvbOSD, t.utf8(), &tw, &th);
+ len = tw;
+ int offset = 5;
+ xine_osd_draw_text( dvbOSD, w-(2*border)-tw-offset, 5, t.utf8(), DVB_TEXT_BLUE );
+ int i;
+ for ( i=0; i<(int)dvbCurrentNext.count(); i++ ) {
+ if ( dvbCurrentNext[i]=="R" ) {
+ xine_osd_draw_rect( dvbOSD, offset, 5, offset+16, 21, DVB_COLOR_RED, 1 );
+ offset+=21;
+ }
+ else if ( dvbCurrentNext[i]=="T" ) {
+ xine_osd_draw_rect( dvbOSD, offset, 5, offset+16, 21, DVB_COLOR_GREEN, 1 );
+ offset+=21;
+ }
+ }
+ if (m_dvbChannelName == "")
+ t = m_trackTitle;
+ else
+ t = m_dvbChannelName;
+
+ i=0;
+ ct = t.utf8();
+ while ( i<(int)t.length() ) {
+ xine_osd_get_text_size( dvbOSD, ct, &tw, &th );
+ if ( tw<=(w-(2*border)-offset-5-len) ) break;
+ ct = ct.remove( ct.length()-1, ct.length() );
+ i++;
+ }
+ xine_osd_draw_text( dvbOSD, offset, 5, ct, DVB_TEXT_BLUE );
+ xine_osd_draw_line( dvbOSD, 5, 10+18, w-(2*border)-5, 10+18, DVB_COLOR_MAGENTA );
+
+ QString s, c;
+ int y=43;
+ int pos;
+ if ( dvbCurrentNext[0]=="E" ) {
+ if ( dvbCurrentNext.count()<2 ) {
+ xine_osd_show( dvbOSD, 0 );
+ return;
+ }
+ if ( !dvbCurrentNext[1].isEmpty() ) {
+ s = dvbCurrentNext[1];
+ pos = s.find("-");
+ c = s.left( pos+1 );
+ s = s.right( s.length()-pos-1 );
+ t = s;
+ xine_osd_draw_text( dvbOSD, 10, y, c.utf8(), DVB_TEXT_GREEN );
+ xine_osd_get_text_size( dvbOSD, c.utf8(), &offset, &th );
+ i=0;
+ cs = s.utf8();
+ while ( i<(int)t.length() ) {
+ ct = cs.remove( cs.length()-i, cs.length() );
+ xine_osd_get_text_size( dvbOSD, ct, &tw, &th );
+ if ( tw<=(w-(2*border)-20-offset) ) break;
+ i++;
+ }
+ xine_osd_draw_text( dvbOSD, 10+offset, y, ct, DVB_TEXT_WHITE );
+ y+= 40;
+ }
+ if ( !dvbCurrentNext[2].isEmpty() ) {
+ cs = dvbCurrentNext[2].utf8();
+ while ( y<(h-(2*border)-23) ) {
+ getOSDLine( dvbOSD, (w-(2*border)-20), ct, cs );
+ xine_osd_draw_text( dvbOSD, 10, y, ct, DVB_TEXT_BLUE );
+ y+= 28;
+ if ( !cs.length() )
+ break;
+ }
+ y+= 40;
+ }
+ if ( !dvbCurrentNext[3].isEmpty() ) {
+ cs = dvbCurrentNext[3].utf8();
+ while ( y<(h-(2*border)-23) ) {
+ getOSDLine( dvbOSD, (w-(2*border)-20), ct, cs );
+ xine_osd_draw_text( dvbOSD, 10, y, ct, DVB_TEXT_WHITE );
+ y+= 28;
+ if ( !cs.length() )
+ break;
+ }
+ }
+ xine_osd_show( dvbOSD, 0 );
+ return;
+ }
+ int bar=-1;
+ int barOffset=0;
+ for ( int j=0; j<(int)dvbCurrentNext.count(); j++ ) {
+ if ( (dvbCurrentNext[ j ]=="T") || (dvbCurrentNext[ j ]=="R") ) continue;
+ if ( dvbCurrentNext[ j ].startsWith("BAR") ) {
+ s = dvbCurrentNext[ j ];
+ s = s.remove("BAR");
+ bar = s.toInt();
+ //fprintf( stderr, "BAR : %d\n", bar );
+ continue;
+ }
+ s = dvbCurrentNext[ j ];
+ pos = s.find("-");
+ c = s.left( pos+1 );
+ s = s.right( s.length()-pos-1 );
+ ct = cs = s.utf8();
+ xine_osd_draw_text( dvbOSD, 10, y, c.utf8(), DVB_TEXT_GREEN );
+ xine_osd_get_text_size( dvbOSD, c.utf8(), &offset, &th );
+ i=0;
+ while ( i<(int)t.length() ) {
+ ct = cs.remove( cs.length()-i, cs.length() );
+ xine_osd_get_text_size( dvbOSD, ct, &tw, &th );
+ if ( tw<=(w-(2*border)-20-offset-35) ) break;
+ i++;
+ }
+ if ( !barOffset )
+ barOffset = tw;
+ xine_osd_draw_text( dvbOSD, 10+offset, y, ct, DVB_TEXT_WHITE );
+ y+= 28;
+ if ( bar>-1 ) {
+ int x1=10+offset+barOffset+10;
+ int x2=w-(2*border)-5;
+ if ( (x1+30)>x2 )
+ x1 = x2 - 30;
+ int x3=x1+((bar*(x2-x1))/100);
+ //fprintf( stderr, "x1=%d - x2=%d - x3=%d\n", x1, x2, x3 );
+ int y1=46;
+ int y2=60;
+ xine_osd_draw_line( dvbOSD, x1, y1, x2, y1, DVB_COLOR_BAR );
+ xine_osd_draw_line( dvbOSD, x1, y2, x2, y2, DVB_COLOR_BAR );
+ xine_osd_draw_line( dvbOSD, x1, y1, x1, y2, DVB_COLOR_BAR );
+ xine_osd_draw_line( dvbOSD, x2, y1, x2, y2, DVB_COLOR_BAR );
+ xine_osd_draw_rect( dvbOSD, x1, y1, x3, y2, DVB_COLOR_BAR, 1 );
+ }
+ }
+ xine_osd_show( dvbOSD, 0 );
+ dvbOSDHideTimer.start( 5000, true );
+ }
+}
+
+void KXineWidget::dvbHideOSD()
+{
+ if ( dvbOSD ) {
+ xine_osd_hide( dvbOSD, 0 );
+ xine_osd_free( dvbOSD );
+ dvbOSD = 0;
+
+ if (m_dvbChannelName != "")
+ m_dvbChannelName = "";
+
+ emit signalDvbOSDHidden();
+ }
+}
+
+void KXineWidget::setDvbCurrentNext( const QString &channelName, const QStringList &list )
+{
+ if ( list[0]=="STOP" ) {
+ dvbHideOSD();
+ return;
+ }
+ dvbCurrentNext = list;
+
+ m_dvbChannelName = channelName;
+
+ QTimer::singleShot( 0, this, SLOT(dvbShowOSD()) );
+}
+
+void KXineWidget::setDvb( const QString &pipeName, const QString &chanName, int haveVideo )
+{
+ m_trackURL = pipeName;
+ m_trackTitle = chanName;
+ dvbHaveVideo = haveVideo;
+}
+
+bool KXineWidget::openDvb()
+{
+ if ( dvbOSD ) {
+ dvbOSDHideTimer.stop();
+ xine_osd_hide( dvbOSD, 0 );
+ xine_osd_free( dvbOSD );
+ dvbOSD = 0;
+ }
+
+ clearQueue();
+ m_lengthInfoTimer.stop();
+ m_posTimer.stop();
+ xine_set_param( m_xineStream, XINE_PARAM_METRONOM_PREBUFFER, 180000);
+ if (!xine_open(m_xineStream, QFile::encodeName(m_trackURL))) {
+ sendXineError();
+ return false;
+ }
+ else fprintf(stderr,"xine pipe opened %s\n", m_trackURL.ascii());
+ m_trackURL = "DVB";
+ emit signalXineStatus(i18n("DVB: opening..."));
+ QTimer::singleShot( 0, this, SLOT(playDvb()) );
+
+ return true;
+}
+
+void KXineWidget::slotPlayTimeShift()
+{
+ m_lengthInfoTimer.stop();
+ m_posTimer.stop();
+ xine_set_param( m_xineStream, XINE_PARAM_METRONOM_PREBUFFER, 0);
+ if (!xine_open(m_xineStream, QFile::encodeName(TimeShiftFilename))) {
+ sendXineError();
+#ifdef XINE_PARAM_GAPLESS_SWITCH
+ if ( xine_check_version(1,1,1) )
+ xine_set_param( m_xineStream, XINE_PARAM_GAPLESS_SWITCH, 0);
+#endif
+ return;
+ }
+ if (!xine_play(m_xineStream, 0,0)) {
+ sendXineError();
+ return;
+ }
+ m_trackIsSeekable = true;
+ m_lengthInfoTimer.start(1000);
+ m_posTimer.start(1000);
+}
+
+bool KXineWidget::unhandledStreamsPresent()
+{
+ unsigned int hasAudio = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_AUDIO);
+ unsigned int hasVideo = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO);
+
+ return (hasAudio && !xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_AUDIO_HANDLED)) ||
+ (hasVideo && !xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_HANDLED));
+}
+
+void KXineWidget::slotPlay()
+{
+ if ((!isXineReady()) || (isQueueEmpty()))
+ return;
+
+ if (m_logoFile != NULL && m_trackURL == m_logoFile && isPlaying())
+ return;
+
+ /* dvb */
+ if ( dvbOSD ) {
+ dvbOSDHideTimer.stop();
+ xine_osd_hide( dvbOSD, 0 );
+ xine_osd_free( dvbOSD );
+ dvbOSD = 0;
+ }
+
+ m_lengthInfoTimer.stop();
+ m_posTimer.stop();
+ m_currentSpeed = Normal;
+
+ setCursor(QCursor(Qt::WaitCursor));
+
+ m_trackURL = m_queue.first();
+ m_queue.remove(m_queue.find(m_trackURL));
+
+ if (m_trackURL != m_logoFile)
+ emit signalXineStatus(i18n("Opening..."));
+
+ /* check for external subtitle file or save url */
+ m_trackSubtitleURL = QString::null;
+ m_trackSaveURL = QString::null;
+
+ /*for (int i = 1; i <= m_trackURL.contains('#'); i++) {
+ ref = m_trackURL.section('#', i, i);
+ if (ref.section(':', 0, 0) == "subtitle")
+ m_trackSubtitleURL = ref.section(':', 1);
+ if (ref.section(':', 0, 0) == "save")
+ m_trackSaveURL = ref.section(':', 1);
+ }*/
+
+ QString turl;
+ int pos;
+
+ if ( (pos=m_trackURL.find("#subtitle:"))>-1 ) {
+ turl = m_trackURL.left(pos);
+ m_trackSubtitleURL = m_trackURL.right( m_trackURL.length()-pos );
+ if ( (pos=m_trackSubtitleURL.find("#save:"))>-1 ) {
+ m_trackSaveURL = m_trackSubtitleURL.right( m_trackSubtitleURL.length()-pos );
+ m_trackSubtitleURL = m_trackSubtitleURL.left(pos);
+ }
+ }
+ else if ( (pos=m_trackURL.find("#save:"))>-1 ) {
+ turl = m_trackURL.left(pos);
+ m_trackSaveURL = m_trackURL.right( m_trackURL.length()-pos );
+ }
+ else turl = m_trackURL;
+
+ m_trackSubtitleURL.remove("#subtitle:");
+ m_trackSaveURL.remove("#save:");
+
+ turl = turl.replace( "%", "%25" ).replace( "#", "%23" ).replace( ";", "%3b" ).replace( " ", "%20" );
+ if ( !m_trackSubtitleURL.isEmpty() )
+ turl = turl + "#subtitle:" + m_trackSubtitleURL.replace( "%", "%25" ).replace( "#", "%23" ).replace( ";", "%3b" ).replace( " ", "%20" );
+ if ( !m_trackSaveURL.isEmpty() )
+ turl = turl + "#save:" + m_trackSaveURL.replace( "%", "%25" ).replace( "#", "%23" ).replace( ";", "%3b" ).replace( " ", "%20" );
+ if ( turl.startsWith("/") )
+ turl.prepend("file://");
+
+ debugOut(QString("Playing: %1").arg(turl.local8Bit()));
+
+ xine_set_param( m_xineStream, XINE_PARAM_METRONOM_PREBUFFER, 12000 );
+ if (!xine_open(m_xineStream, QFile::encodeName(turl))) {
+
+ sendXineError();
+ setCursor(QCursor(Qt::ArrowCursor));
+#ifdef XINE_PARAM_GAPLESS_SWITCH
+ if ( xine_check_version(1,1,1) )
+ xine_set_param( m_xineStream, XINE_PARAM_GAPLESS_SWITCH, 0);
+#endif
+ return;
+ }
+
+ if (unhandledStreamsPresent())
+ {
+ errorOut("No codecs to handle media");
+ sendXineError();
+ return;
+ }
+
+ /**** use visualization ? ****/
+#ifndef USE_QT_ONLY
+ unwireAudioFilters();
+ wireAudioFilters();
+#else
+ if ((xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_AUDIO)) &&
+ (!xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO)))
+ {
+ if (m_visualPluginName && (!m_xinePost))
+ {
+ debugOut(QString("Init visual plugin: %1").arg(m_visualPluginName));
+ m_xinePost = xine_post_init(m_xineEngine, m_visualPluginName, 0,
+ &m_audioDriver,
+ &m_videoDriver);
+
+ m_postAudioSource = xine_get_audio_source(m_xineStream);
+ m_postInput = (xine_post_in_t*)xine_post_input (m_xinePost, const_cast<char*>("audio in"));
+ xine_post_wire(m_postAudioSource, m_postInput);
+ }
+ }
+ else
+ {
+ if (m_xinePost)
+ {
+ debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName));
+ m_postAudioSource = xine_get_audio_source(m_xineStream);
+ xine_post_wire_audio_port(m_postAudioSource, m_audioDriver);
+ xine_post_dispose(m_xineEngine, m_xinePost);
+ m_xinePost = NULL;
+ }
+ }
+#endif
+
+ /*** play ***/
+ int savedPos = m_savedPos;
+ m_savedPos = 0;
+ if (!xine_play(m_xineStream, savedPos, 0))
+ {
+ sendXineError();
+ setCursor(QCursor(Qt::ArrowCursor));
+ return;
+ }
+
+ /* do the stream have chapters ? */
+ m_trackHasChapters = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_CHAPTERS);
+
+ /** information requirement **/
+
+ m_trackTitle = QString::null;
+
+ bool currentUtf8Locale;
+ QTextCodec* testUtf8Local = QTextCodec::codecForLocale();
+ if (!strcmp(testUtf8Local->name(),"UTF-8"))
+ currentUtf8Locale = true;
+ else
+ currentUtf8Locale = false;
+
+ QTextCodec *CodecUtf8;
+ CodecUtf8 = QTextCodec::codecForName("UTF-8");
+
+ QString infotag;
+ infotag = QString::fromLatin1(xine_get_meta_info(m_xineStream, XINE_META_INFO_TITLE));
+
+ if (currentUtf8Locale)
+ m_trackTitle = infotag;
+ else
+ m_trackTitle = QString::fromLocal8Bit(infotag.ascii());
+
+ if (CodecUtf8->heuristicContentMatch(infotag.ascii(), infotag.length()) >= 0)
+ m_trackTitle = QString::fromUtf8(infotag.ascii());
+
+ if ((!m_trackTitle.isNull()) && (!m_trackTitle.isEmpty())) /* no meta? */
+ {
+ QString trackArtist=NULL;
+ QString trackAlbum=NULL;
+ QString trackComment=NULL;
+ trackArtist = QString::fromLatin1(xine_get_meta_info(m_xineStream, XINE_META_INFO_ARTIST));
+ trackAlbum = QString::fromLatin1(xine_get_meta_info(m_xineStream, XINE_META_INFO_ALBUM));
+ trackComment = QString::fromLatin1(xine_get_meta_info(m_xineStream, XINE_META_INFO_COMMENT));
+ if (currentUtf8Locale)
+ {
+ m_trackArtist = trackArtist;
+ m_trackAlbum = trackAlbum;
+ m_trackComment = trackComment;
+ }
+ else
+ {
+ m_trackArtist = QString::fromLocal8Bit(trackArtist.ascii());
+ m_trackAlbum = QString::fromLocal8Bit(trackAlbum.ascii());
+ m_trackComment = QString::fromLocal8Bit(trackComment.ascii());
+ }
+ if (CodecUtf8->heuristicContentMatch(trackArtist.ascii(), trackArtist.length()) >= 0)
+ m_trackArtist = QString::fromUtf8(trackArtist.ascii());
+ if (CodecUtf8->heuristicContentMatch(trackAlbum.ascii(), trackAlbum.length()) >= 0)
+ m_trackAlbum = QString::fromUtf8(trackAlbum.ascii());
+ if (CodecUtf8->heuristicContentMatch(trackComment.ascii(), trackComment.length()) >= 0)
+ m_trackComment = QString::fromUtf8(trackComment.ascii());
+
+ m_trackYear = xine_get_meta_info(m_xineStream, XINE_META_INFO_YEAR);
+ m_trackNumber = xine_get_meta_info(m_xineStream, XINE_META_INFO_TRACK_NUMBER);
+ }
+ else
+ {
+ m_trackArtist = QString::null;
+ m_trackAlbum = QString::null;
+ m_trackNumber = QString::null;
+ m_trackYear = QString::null;
+ m_trackComment = QString::null;
+ }
+
+ m_trackHasVideo = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO);
+ if (m_trackHasVideo)
+ {
+ m_trackVideoCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_VIDEOCODEC);
+ m_videoFrameWidth = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_WIDTH);
+ m_videoFrameHeight = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_HEIGHT);
+ m_trackVideoBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_BITRATE);
+ }
+ else
+ {
+ m_trackVideoCodec = QString::null;
+ m_videoFrameWidth = 0;
+ m_videoFrameHeight = 0;
+ m_trackVideoBitrate = 0;
+ }
+
+ m_trackHasAudio = (bool)xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_AUDIO);
+ if (m_trackHasAudio)
+ {
+ m_trackAudioCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_AUDIOCODEC);
+ m_trackAudioBitrate = xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_AUDIO_BITRATE);
+ }
+ else
+ {
+ m_trackAudioCodec = QString::null;
+ m_trackAudioBitrate = 0;
+ }
+
+ /*** we need a little delay for some meta info ***/
+ QTimer::singleShot(1000, this, SLOT(slotGetInfoDelayed()));
+
+
+ m_trackLength = getLengthInfo();
+ if ((m_trackLength.isNull()) && (m_trackURL != m_logoFile))
+ {
+ debugOut("Wait for valid length information");
+ m_lengthInfoTries = 0;
+ m_lengthInfoTimer.start(1000); /* wait for available track length info */
+ }
+
+ if (m_trackTitle.isNull() || m_trackTitle.isEmpty())
+ {
+ /* no meta info */
+ m_trackTitle = m_trackURL;
+ }
+
+ slotSetAudioChannel(0); //refresh channel info
+ if (m_trackURL != m_logoFile)
+ m_posTimer.start(200);
+ setCursor(QCursor(Qt::ArrowCursor));
+
+ if (m_trackURL != m_logoFile)
+ {
+ emit signalXinePlaying();
+ if (hasSaveURL())
+ emit signalXineStatus(i18n("Recording"));
+ else
+ emit signalXineStatus(i18n("Playing"));
+ }
+}
+
+int KXineWidget::getVideoWidth()
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_WIDTH);
+}
+
+int KXineWidget::getVideoHeight()
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_VIDEO_HEIGHT);
+}
+
+void KXineWidget::slotGetInfoDelayed()
+{
+ if (!m_xineStream)
+ return;
+
+ if (m_trackHasVideo)
+ m_trackVideoCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_VIDEOCODEC);
+ if (m_trackHasAudio)
+ m_trackAudioCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_AUDIOCODEC);
+}
+
+
+/****** error processing ****/
+
+void KXineWidget::sendXineError()
+{
+ QString error;
+ int errCode = xine_get_error(m_xineStream);
+
+ QString addInfo;
+ QString audioCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_AUDIOCODEC);
+ QString videoCodec = xine_get_meta_info(m_xineStream, XINE_META_INFO_VIDEOCODEC);
+ if ((!audioCodec.isEmpty()) || (!videoCodec.isEmpty()))
+ {
+ if (!audioCodec.isEmpty())
+ addInfo.append(QString("(") + i18n("Audio Codec") + ": " + audioCodec + ")");
+ if (!videoCodec.isEmpty())
+ addInfo.append(QString("(") + i18n("Video Codec") + ": " + videoCodec + ")");
+ }
+ else
+ addInfo.append(QString("(") + m_trackURL + ")");
+
+ switch (errCode)
+ {
+ case XINE_ERROR_NO_INPUT_PLUGIN:
+ case XINE_ERROR_NO_DEMUX_PLUGIN:
+ {
+ if (m_trackURL.startsWith("dvd:/"))
+ {
+ if (KaffeinePart::installDistroCodec(this, "xine-engine", "dvdcss"))
+ return;
+ }
+ else
+ {
+ if (KaffeinePart::installDistroCodec(this, "xine-engine", "ffmpeg"))
+ return;
+ }
+
+ error = i18n("No plugin found to handle this resource") + " " + addInfo;
+ break;
+ }
+ case XINE_ERROR_DEMUX_FAILED:
+ {
+ error = i18n("Resource seems to be broken") + " (" + m_trackURL + ")";
+ break;
+ }
+ case XINE_ERROR_MALFORMED_MRL:
+ {
+ error = i18n("Requested resource does not exist") + " (" + m_trackURL + ")";
+ break;
+ }
+ case XINE_ERROR_INPUT_FAILED:
+ {
+ error = i18n("Resource can not be opened") + " (" + m_trackURL + ")";
+ break;
+ }
+ default:
+ {
+ if (unhandledStreamsPresent() && KaffeinePart::installDistroCodec(this, "xine-engine", "ffmpeg"))
+ return;
+
+ error = i18n("Generic error") + " (" + m_trackURL + ")";
+ break;
+ }
+ }
+
+ if (isQueueEmpty())
+ {
+ if (m_trackURL != m_logoFile)
+ {
+ emit signalXineStatus(i18n("Error"));
+ emit signalXineError(error);
+ }
+ else
+ errorOut("Can't find/play logo file!");
+ }
+ else
+ {
+ errorOut(error);
+ errorOut(QString("Can't play: %1 - trying next").arg(m_trackURL));
+ QTimer::singleShot(0, this, SLOT(slotPlay()));
+ }
+}
+
+bool KXineWidget::isPlaying() const
+{
+ if (isXineReady())
+ return ((xine_get_status(m_xineStream) == XINE_STATUS_PLAY) && (m_trackURL != m_logoFile));
+ else
+ return false;
+}
+
+QString KXineWidget::getXineLog() const
+{
+ QString logStr;
+ int i = 0;
+ QTextStream ts(&logStr, IO_WriteOnly);
+
+ const char* const* log = xine_get_log(m_xineEngine, /* XINE_LOG_MSG*/ 0);
+ if (log == NULL)
+ return QString();
+
+ while(log[i])
+ {
+ ts << QString::fromLocal8Bit(log[i]);
+ i++;
+ }
+
+ return logStr;
+}
+
+void KXineWidget::showOSDMessage(const QString& message, uint duration, int priority)
+{
+ if ((!m_osd) || (!m_osdShow) || (isHidden()))
+ return;
+
+ static int prevOsdPriority = 0;
+ if (m_osdTimer.isActive() && prevOsdPriority > priority)
+ return;
+ prevOsdPriority = priority;
+
+ //debugOut(QString("OSD: draw text: %1").arg(message));
+ xine_osd_clear(m_osd);
+ xine_osd_draw_text(m_osd, 0, 0, message.local8Bit(), XINE_OSD_TEXT1);
+
+ if (m_osdUnscaled)
+ xine_osd_show_unscaled(m_osd, 0);
+ else
+ xine_osd_show(m_osd, 0);
+
+ m_osdTimer.start(duration);
+}
+
+void KXineWidget::slotOSDHide()
+{
+ xine_osd_hide(m_osd, 0);
+ m_osdTimer.stop();
+}
+
+#ifndef USE_QT_ONLY
+/****************** postprocessing filter management ****************/
+
+QStringList KXineWidget::getVideoFilterNames() const
+{
+ QStringList filters;
+ const char* const* plugins = xine_list_post_plugins_typed(m_xineEngine, XINE_POST_TYPE_VIDEO_FILTER);
+
+ for (int i = 0; plugins[i]; i++)
+ {
+ filters << plugins[i];
+ }
+ return filters;
+}
+
+QStringList KXineWidget::getAudioFilterNames() const
+{
+ QStringList filters;
+ const char* const* plugins = xine_list_post_plugins_typed(m_xineEngine, XINE_POST_TYPE_AUDIO_FILTER);
+
+ for (int i = 0; plugins[i]; i++)
+ {
+ filters << plugins[i];
+ }
+ return filters;
+}
+#endif
+
+void KXineWidget::slotCreateVideoFilter(const QString& name, QWidget* parent)
+{
+#ifndef USE_QT_ONLY
+ unwireVideoFilters();
+
+ PostFilter* filter = new PostFilter(name, m_xineEngine, m_audioDriver, m_videoDriver, parent);
+ connect(filter, SIGNAL(signalDeleteMe(PostFilter*)), this, SLOT(slotDeleteVideoFilter(PostFilter*)));
+ m_videoFilterList.append(filter);
+
+ wireVideoFilters();
+#else
+ parent = parent;
+ warningOut(QString("Not implemented [CreateVideoFilter %1]").arg(name));
+#endif
+}
+
+void KXineWidget::slotCreateAudioFilter(const QString& name, QWidget* parent)
+{
+#ifndef USE_QT_ONLY
+ unwireAudioFilters();
+
+ PostFilter* filter = new PostFilter(name, m_xineEngine, m_audioDriver, m_videoDriver, parent);
+ connect(filter, SIGNAL(signalDeleteMe(PostFilter*)), this, SLOT(slotDeleteAudioFilter(PostFilter*)));
+ m_audioFilterList.append(filter);
+
+ wireAudioFilters();
+#else
+ parent = parent;
+ warningOut(QString("Not implemented [CreateAudioFilter %1]").arg(name));
+#endif
+}
+
+
+void KXineWidget::slotRemoveAllVideoFilters()
+{
+#ifndef USE_QT_ONLY
+ unwireVideoFilters();
+ while (m_videoFilterList.count())
+ m_videoFilterList.removeLast();
+ wireVideoFilters();
+#else
+ warningOut("Not implemented!");
+#endif
+}
+
+void KXineWidget::slotRemoveAllAudioFilters()
+{
+#ifndef USE_QT_ONLY
+ unwireAudioFilters();
+ while (m_audioFilterList.count())
+ m_audioFilterList.removeLast();
+ wireAudioFilters();
+#else
+ warningOut("Not implemented!");
+#endif
+}
+
+void KXineWidget::slotDeleteVideoFilter(PostFilter* filter)
+{
+#ifndef USE_QT_ONLY
+ unwireVideoFilters();
+ m_videoFilterList.remove(filter);
+ wireVideoFilters();
+#else
+ filter = filter;
+ warningOut("Not implemented!");
+#endif
+}
+
+void KXineWidget::slotDeleteAudioFilter(PostFilter* filter)
+{
+#ifndef USE_QT_ONLY
+ unwireAudioFilters();
+ m_audioFilterList.remove(filter);
+ wireAudioFilters();
+#else
+ filter = filter;
+ warningOut("Not implemented!");
+#endif
+}
+
+#ifndef USE_QT_ONLY
+void KXineWidget::unwireVideoFilters()
+{
+ if (m_xineStream && m_videoDriver)
+ xine_post_wire_video_port(xine_get_video_source(m_xineStream), m_videoDriver);
+}
+
+void KXineWidget::wireVideoFilters()
+{
+ if (!m_xineStream)
+ {
+ debugOut("wireVideoFilters() - xine stream not initialized, nothing happend.");
+ return;
+ }
+
+ QPtrList<PostFilter> activeList;
+
+ if (m_videoFilterList.count() && m_videoFiltersEnabled)
+ activeList = m_videoFilterList;
+
+ if (m_deinterlaceFilter && m_deinterlaceEnabled )
+ activeList.insert (0, m_deinterlaceFilter);
+
+ if (activeList.count())
+ {
+ xine_post_wire_video_port(activeList.at(activeList.count()-1)->getOutput(), m_videoDriver);
+
+ for (uint i = activeList.count()-1; i >0; i--)
+ {
+ xine_post_wire(activeList.at( i-1 )->getOutput(), activeList.at(i)->getInput());
+ }
+
+ xine_post_wire( xine_get_video_source(m_xineStream), activeList.at(0)->getInput());
+ }
+}
+
+void KXineWidget::unwireAudioFilters()
+{
+ if (m_xineStream && m_audioDriver)
+ xine_post_wire_audio_port( xine_get_audio_source (m_xineStream), m_audioDriver);
+}
+
+void KXineWidget::wireAudioFilters()
+{
+ if (!m_xineStream)
+ {
+ debugOut("wireAudioFilters() - xine stream not initialized, nothing happend.");
+ return;
+ }
+
+ QPtrList<PostFilter> activeList;
+
+ if (m_audioFilterList.count() && m_audioFiltersEnabled)
+ activeList = m_audioFilterList;
+
+ if ((xine_get_stream_info (m_xineStream, XINE_STREAM_INFO_HAS_AUDIO)) &&
+ (!xine_get_stream_info (m_xineStream, XINE_STREAM_INFO_HAS_VIDEO)) &&
+ m_visualPluginName.ascii())
+ {
+ if (!m_visualPlugin)
+ {
+ debugOut(QString("Init visual plugin: %1").arg(m_visualPluginName));
+ m_visualPlugin = new PostFilter(m_visualPluginName, m_xineEngine, m_audioDriver, m_videoDriver, NULL);
+ }
+
+ activeList.insert (0, m_visualPlugin);
+ }
+ else
+ {
+ if (m_visualPlugin)
+ {
+ debugOut(QString("Dispose visual plugin: %1").arg(m_visualPluginName));
+ delete m_visualPlugin;
+ m_visualPlugin = NULL;
+ }
+ }
+
+ if (activeList.count())
+ {
+ xine_post_wire_audio_port(activeList.at(activeList.count()-1)->getOutput(), m_audioDriver);
+
+ for (uint i = activeList.count()-1; i >0; i--)
+ {
+ xine_post_wire(activeList.at(i-1)->getOutput(), activeList.at(i)->getInput());
+ }
+
+ xine_post_wire( xine_get_audio_source(m_xineStream), activeList.at(0)->getInput());
+ }
+}
+#endif
+
+void KXineWidget::slotEnableVideoFilters(bool enable)
+{
+#ifndef USE_QT_ONLY
+ m_videoFiltersEnabled = enable;
+
+ unwireVideoFilters();
+ wireVideoFilters();
+#else
+ enable = enable;
+ warningOut("Not implemented!");
+#endif
+}
+
+void KXineWidget::slotEnableAudioFilters(bool enable)
+{
+#ifndef USE_QT_ONLY
+ m_audioFiltersEnabled = enable;
+
+ unwireAudioFilters();
+ wireAudioFilters();
+#else
+ enable = enable;
+ warningOut("Not implemented!");
+#endif
+}
+
+#ifndef USE_QT_ONLY
+QStringList KXineWidget::getAudioFilterConfig()
+{
+ QStringList configStrings;
+ for (uint i=0; i<m_audioFilterList.count(); i++)
+ configStrings << m_audioFilterList.at(i)->getConfig();
+ return configStrings;
+}
+
+QStringList KXineWidget::getVideoFilterConfig()
+{
+ QStringList configStrings;
+ for (uint i=0; i<m_videoFilterList.count(); i++)
+ configStrings << m_videoFilterList.at(i)->getConfig();
+ return configStrings;
+}
+#endif
+
+/**** visual plugin **********/
+
+QStringList KXineWidget::getVisualPlugins() const
+{
+ QStringList visuals;
+ const char* const* plugins = xine_list_post_plugins_typed(m_xineEngine, XINE_POST_TYPE_AUDIO_VISUALIZATION);
+
+ for (int i = 0; plugins[i]; i++)
+ {
+ visuals << plugins[i];
+ }
+ return visuals;
+}
+
+/**************** change visualization plugin *****************/
+
+void KXineWidget::slotSetVisualPlugin(const QString& visual)
+{
+ if (m_visualPluginName == visual) return;
+ debugOut(QString("New visualization plugin: %1").arg(visual));
+
+#ifndef USE_QT_ONLY
+ unwireAudioFilters();
+ if(m_visualPlugin)
+ {
+ delete m_visualPlugin;
+ m_visualPlugin = NULL;
+ }
+
+ if (visual == "none")
+ m_visualPluginName = QString::null;
+ else
+ m_visualPluginName = visual;
+
+ wireAudioFilters();
+#else
+ if (visual == "none")
+ m_visualPluginName = QString::null;
+ else
+ m_visualPluginName = visual;
+
+ if (m_xinePost)
+ {
+ xine_post_out_t *pp;
+
+ pp = xine_get_audio_source(m_xineStream);
+ xine_post_wire_audio_port(pp, m_audioDriver);
+ xine_post_dispose(m_xineEngine, m_xinePost);
+ m_xinePost = NULL;
+ }
+
+ if ( (xine_get_status(m_xineStream ) == XINE_STATUS_PLAY)
+ && (!xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_HAS_VIDEO)) && (m_visualPluginName) )
+ {
+ m_xinePost = xine_post_init(m_xineEngine, m_visualPluginName, 0, &m_audioDriver, &m_videoDriver);
+ m_postAudioSource = xine_get_audio_source(m_xineStream);
+ m_postInput = (xine_post_in_t*)xine_post_input(m_xinePost, const_cast<char*>("audio in"));
+ xine_post_wire(m_postAudioSource, m_postInput);
+ }
+#endif
+}
+
+/*****/
+
+void KXineWidget::getAutoplayPlugins(QStringList& autoPlayList) const
+{
+ char** pluginIds = NULL;
+ int i = 0;
+
+ pluginIds = (char**)xine_get_autoplay_input_plugin_ids(m_xineEngine);
+
+ while(pluginIds[i])
+ {
+ autoPlayList << pluginIds[i];
+
+ autoPlayList << xine_get_input_plugin_description(m_xineEngine, pluginIds[i]);
+ i++;
+ }
+}
+
+bool KXineWidget::getAutoplayPluginURLS(const QString& plugin, QStringList& list)
+{
+ char** urls = NULL;
+ int num;
+ int i = 0;
+
+ urls = xine_get_autoplay_mrls(m_xineEngine, plugin.ascii(), &num);
+
+ if (urls)
+ {
+ while (urls[i])
+ {
+ list << urls[i];
+ i++;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void KXineWidget::slotSetVolume(int vol)
+{
+ if (!isXineReady()) return;
+ if (m_softwareMixer)
+ {
+ //debugOut(QString("Set software amplification level: %1").arg(vol));
+ if (m_volumeGain)
+ xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, vol*2);
+ else
+ xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, vol);
+ }
+ else
+ {
+ //debugOut(QString("Set audio mixer volume: %1").arg(vol));
+ xine_set_param(m_xineStream, XINE_PARAM_AUDIO_VOLUME, vol);
+ }
+ emit signalXineStatus(i18n("Volume") + ": " + QString::number(vol) +"%");
+}
+
+uint KXineWidget::getVolume() const
+{
+ if (!isXineReady()) return 0;
+ uint vol;
+ if (m_softwareMixer)
+ {
+ vol = xine_get_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL);
+ if (vol > 200)
+ {
+ // when amp is high > 100, xine_get_param sometimes returns incorrect amp level
+ errorOut("Amp level returned weird results, set Amp to 100");
+ vol = 100;
+ }
+ if (m_volumeGain) vol = vol/2;
+ }
+ else
+ {
+ vol = xine_get_param(m_xineStream, XINE_PARAM_AUDIO_VOLUME);
+ }
+ return vol;
+}
+
+void KXineWidget::slotToggleMute()
+{
+ int muteParam;
+ if (m_softwareMixer)
+ muteParam = XINE_PARAM_AUDIO_AMP_MUTE;
+ else
+ muteParam = XINE_PARAM_AUDIO_MUTE;
+
+ if (xine_get_param(m_xineStream, muteParam))
+ {
+ xine_set_param(m_xineStream, muteParam, 0); /* mute off */
+ emit signalXineStatus(i18n("Mute Off"));
+ }
+ else
+ {
+ xine_set_param(m_xineStream, muteParam, 1); /* mute on */
+ emit signalXineStatus(i18n("Mute On"));
+ }
+}
+
+bool KXineWidget::SoftwareMixing() const
+{
+ if (m_softwareMixer)
+ return true;
+ else
+ return false;
+}
+
+void KXineWidget::mouseMoveEvent(QMouseEvent* mev)
+{
+ if (!m_xineReady) return;
+
+ if (cursor().shape() == Qt::BlankCursor)
+ {
+ setCursor(QCursor(Qt::ArrowCursor));
+ }
+
+ x11_rectangle_t rect;
+ xine_event_t event;
+ xine_input_data_t input;
+
+ rect.x = mev->x();
+ rect.y = mev->y();
+ rect.w = 0;
+ rect.h = 0;
+
+ xine_port_send_gui_data (m_videoDriver, XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO, (void*)&rect);
+
+ event.type = XINE_EVENT_INPUT_MOUSE_MOVE;
+ event.data = &input;
+ event.data_length = sizeof(input);
+ input.button = 0;
+ input.x = rect.x;
+ input.y = rect.y;
+ xine_event_send(m_xineStream, &event);
+ mev->ignore();
+}
+
+
+void KXineWidget::mousePressEvent(QMouseEvent* mev)
+{
+ if (!m_xineReady) return;
+ int cur = cursor().shape();
+
+ if (mev->button() == Qt::MidButton)
+ {
+ emit signalMiddleClick();
+ mev->ignore();
+ return;
+ }
+
+ if (mev->button() == Qt::RightButton)
+ {
+ if ( (cur == Qt::ArrowCursor) || (cur == Qt::BlankCursor) )
+ {
+ emit signalRightClick(mev->globalPos());
+ mev->accept();
+ return;
+ }
+ }
+
+ if (mev->button() == Qt::LeftButton)
+ {
+ if ( (cur == Qt::ArrowCursor) || (cur == Qt::BlankCursor) )
+ {
+ emit signalLeftClick(mev->globalPos());
+ mev->ignore();
+ return;
+ }
+
+ x11_rectangle_t rect;
+ xine_event_t event;
+ xine_input_data_t input;
+
+ rect.x = mev->x();
+ rect.y = mev->y();
+ rect.w = 0;
+ rect.h = 0;
+
+ xine_port_send_gui_data(m_videoDriver, XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO, (void*)&rect);
+
+ event.type = XINE_EVENT_INPUT_MOUSE_BUTTON;
+ event.data = &input;
+ event.data_length = sizeof(input);
+ input.button = 1;
+ input.x = rect.x;
+ input.y = rect.y;
+ xine_event_send (m_xineStream, &event);
+ mev->accept(); /* don't send event to parent */
+ }
+}
+
+void KXineWidget::mouseDoubleClickEvent(QMouseEvent* mev)
+{
+ emit signalDoubleClick();
+ mev->ignore();
+}
+
+void KXineWidget::wheelEvent(QWheelEvent* e)
+{
+ int oldVal = getPosition();
+ if (oldVal == 0) // no valid position
+ return;
+
+ float offset = log10( QABS(e->delta()) ) / 0.002;
+ int newVal = 0;
+ if (e->delta()>0)
+ newVal = oldVal - int(offset);
+ else
+ newVal = oldVal + int(offset);
+ if (newVal < 0) newVal = 0;
+ slotSeekToPosition(newVal);
+ e->accept();
+}
+
+void KXineWidget::playNextChapter() const
+{
+ xine_event_t xev;
+
+ xev.type = XINE_EVENT_INPUT_NEXT;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::playPreviousChapter() const
+{
+ xine_event_t xev;
+
+ xev.type = XINE_EVENT_INPUT_PREVIOUS;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotStop()
+{
+ m_posTimer.stop();
+ if ( m_lengthInfoTimer.isActive() ) m_lengthInfoTimer.stop();
+ //emit signalNewPosition(0, QTime());
+
+ xine_stop(m_xineStream);
+
+ emit signalXineStatus(i18n("Stop"));
+}
+
+void KXineWidget::slotSetAudiocdDevice(const QString& device)
+{
+ debugOut(QString("Set AudioCD device to %1").arg(device));
+
+ xine_cfg_entry_t config;
+ xine_config_lookup_entry(m_xineEngine, "input.cdda_device", &config);
+ if (m_cachedCDPath.isNull())
+ m_cachedCDPath = config.str_value;
+ config.str_value = QFile::encodeName(device).data();
+ xine_config_update_entry (m_xineEngine, &config);
+}
+
+void KXineWidget::slotSetVcdDevice(const QString& device)
+{
+ debugOut(QString("Set VCD device to %1").arg(device));
+
+ xine_cfg_entry_t config;
+ xine_config_lookup_entry(m_xineEngine, "input.vcd_device", &config);
+ if (m_cachedVCDPath.isNull())
+ m_cachedVCDPath = config.str_value;
+ config.str_value = QFile::encodeName(device).data();
+ xine_config_update_entry (m_xineEngine, &config);
+}
+
+void KXineWidget::slotSetDvdDevice(const QString& device)
+{
+ debugOut(QString("Set DVD device to %1").arg(device));
+
+ xine_cfg_entry_t config;
+ xine_config_lookup_entry(m_xineEngine, "input.dvd_device", &config);
+ if (m_cachedDVDPath.isNull())
+ m_cachedDVDPath = config.str_value;
+ config.str_value = QFile::encodeName(device).data();
+ xine_config_update_entry (m_xineEngine, &config);
+}
+
+QString KXineWidget::audiocdDevice() const
+{
+ xine_cfg_entry_t config;
+ xine_config_lookup_entry(m_xineEngine, "input.cdda_device", &config);
+
+ return QFile::decodeName(config.str_value);
+}
+
+QString KXineWidget::vcdDevice() const
+{
+ xine_cfg_entry_t config;
+ xine_config_lookup_entry(m_xineEngine, "input.vcd_device", &config);
+
+ return QFile::decodeName(config.str_value);
+}
+
+QString KXineWidget::dvdDevice() const
+{
+ xine_cfg_entry_t config;
+ xine_config_lookup_entry(m_xineEngine, "input.dvd_device", &config);
+
+ return QFile::decodeName(config.str_value);
+}
+
+uint KXineWidget::currentDVDTitleNumber() const
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_DVD_TITLE_NUMBER);
+}
+
+uint KXineWidget::getDVDTitleCount() const
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_DVD_TITLE_COUNT);
+}
+
+uint KXineWidget::currentDVDChapterNumber() const
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER);
+}
+
+uint KXineWidget::getDVDChapterCount() const
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_DVD_CHAPTER_COUNT);
+}
+
+uint KXineWidget::currentDVDAngleNumber() const
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER);
+}
+
+uint KXineWidget::getDVDAngleCount() const
+{
+ return xine_get_stream_info(m_xineStream, XINE_STREAM_INFO_DVD_ANGLE_COUNT);
+}
+
+void KXineWidget::setStreamSaveDir(const QString& dir)
+{
+ xine_cfg_entry_t config;
+
+ if (!xine_config_lookup_entry(m_xineEngine, "misc.save_dir", &config)) return; /* older xine-lib */
+
+ debugOut(QString("Set misc.save_dir to: %1").arg(dir));
+ config.str_value = QFile::encodeName(dir).data();
+ xine_config_update_entry (m_xineEngine, &config);
+}
+
+const QString KXineWidget::getStreamSaveDir()
+{
+ xine_cfg_entry_t config;
+
+ if (!xine_config_lookup_entry(m_xineEngine, "misc.save_dir", &config)) return QString::null; /* older xine-lib */
+
+ return QFile::decodeName(config.str_value);
+}
+
+void KXineWidget::setBroadcasterPort(const uint port)
+{
+ debugOut(QString("Set broadcaster port to %1").arg(port));
+ xine_set_param(m_xineStream, XINE_PARAM_BROADCASTER_PORT, port);
+}
+
+void KXineWidget::slotSpeedPause()
+{
+ if (m_currentSpeed == Pause)
+ {
+ slotSpeedNormal();
+ }
+ else if (m_trackURL != m_logoFile) // don't pause logo
+ {
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
+ m_posTimer.stop();
+ if (m_currentSpeed != Undefined)
+ emit signalXineStatus(i18n("Pause"));
+ m_currentSpeed = Pause;
+ }
+}
+
+void KXineWidget::slotSpeedNormal()
+{
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
+ m_posTimer.start(200);
+ m_currentSpeed = Normal;
+ emit signalXineStatus(i18n("Playing") + " ");
+}
+
+void KXineWidget::slotSpeedFaster()
+{
+ switch (m_currentSpeed)
+ {
+ case Fast1:
+ {
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_FAST_4);
+ m_currentSpeed = Fast2;
+ emit signalXineStatus(i18n("Fast Forward %1").arg("x2"));
+ break;
+ }
+ case Fast2:
+ {
+ slotSpeedNormal();
+ break;
+ }
+ case Slow1:
+ {
+ slotSpeedNormal();
+ break;
+ }
+ case Slow2:
+ {
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_2);
+ m_currentSpeed = Slow1;
+ emit signalXineStatus(i18n("Slow Motion %1").arg("x1"));
+ break;
+ }
+ default:
+ {
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_FAST_2);
+ m_currentSpeed = Fast1;
+ emit signalXineStatus(i18n("Fast Forward %1").arg("x1"));
+ break;
+ }
+ }
+}
+
+void KXineWidget::slotSpeedSlower()
+{
+ switch (m_currentSpeed)
+ {
+ case Slow1:
+ {
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_4);
+ m_currentSpeed = Slow2;
+ emit signalXineStatus(i18n("Slow Motion %1").arg("x2"));
+ break;
+ }
+ case Slow2:
+ {
+ slotSpeedNormal();
+ break;
+ }
+ case Fast1:
+ {
+ slotSpeedNormal();
+ break;
+ }
+ case Fast2:
+ {
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_FAST_2);
+ m_currentSpeed = Fast1;
+ emit signalXineStatus(i18n("Fast Forward %1").arg("x1"));
+ break;
+ }
+ default:
+ {
+ xine_set_param(m_xineStream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_2);
+ m_currentSpeed = Slow1;
+ emit signalXineStatus(i18n("Slow Motion %1").arg("x1"));
+ break;
+ }
+ }
+}
+
+QString KXineWidget::getSupportedExtensions() const
+{
+ return xine_get_file_extensions(m_xineEngine);
+}
+
+void KXineWidget::slotSetAudioChannel(int ch)
+{
+ debugOut(QString("Switch to audio channel %1").arg(ch-1));
+ xine_set_param(m_xineStream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, ch-1);
+}
+
+
+void KXineWidget::slotSetSubtitleChannel(int ch)
+{
+ debugOut(QString("Switch to subtitle channel %1").arg(ch-1));
+ xine_set_param(m_xineStream, XINE_PARAM_SPU_CHANNEL, ch-1);
+}
+
+
+void KXineWidget::slotSetFileSubtitles(QString url)
+{
+ int pos;
+ int time;
+ int length;
+
+ m_queue.prepend(url);
+
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+
+ if ( ret == 0 )
+ {
+ debugOut("No valid stream position information");
+ return;
+ }
+
+ if (isPlaying())
+ xine_stop(m_xineStream);
+ m_posTimer.stop();
+
+ slotPlay();
+ slotSeekToPosition(pos);
+}
+
+
+
+uint KXineWidget::getPosition() const
+{
+ if (!m_xineReady) return 0;
+
+ int pos, time, length;
+
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+
+ if ( ret == 0 )
+ {
+ debugOut("No valid stream position information");
+ return 0;
+ }
+
+ return (uint)pos;
+}
+
+QTime KXineWidget::getPlaytime() const
+{
+ if (!m_xineReady) return QTime();
+
+ int pos, time, length;
+
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+
+ if ( ret == 0 )
+ {
+ debugOut("No valid stream position information");
+ return QTime();
+ }
+
+ return msToTime(time);
+}
+
+void KXineWidget::slotSendPosition()
+{
+ if (!m_xineReady) return;
+
+ int pos, time, length;
+
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+
+ if ( ret == 0 )
+ {
+ debugOut("No valid stream position information");
+ return;
+ }
+
+ emit signalNewPosition(pos, msToTime(time));
+}
+
+void KXineWidget::slotStartSeeking()
+{
+ debugOut("Seeking started");
+ m_posTimer.stop();
+}
+
+void KXineWidget::run()
+{
+ if ( seekThreadPos )
+ xine_play(m_xineStream, seekThreadPos, 0);
+ else if ( seekThreadTime )
+ xine_play(m_xineStream, 0, seekThreadTime);
+ else
+ xine_play(m_xineStream, seekThreadPos, 0);
+
+ if ( seekThreadPause ) {
+ m_currentSpeed = Undefined;
+ slotSpeedPause();
+ }
+}
+
+void KXineWidget::slotSeekToPositionBlocking(int pos)
+{
+ while ( running() )
+ usleep( 1000 );
+ if ( pos!=seekThreadPos )
+ slotSeekToPosition(pos);
+}
+
+
+void KXineWidget::slotSeekToPosition(int pos)
+{
+ if ( running() ) {
+ return;
+ }
+
+ if ((!isXineReady()) || (!isPlaying()) || (!isSeekable()))
+ return;
+
+ seekThreadPause = false;
+ if (m_currentSpeed == Pause)
+ seekThreadPause = true;
+ seekThreadPos = pos;
+ seekThreadTime = 0;
+ start();
+}
+
+void KXineWidget::slotSeekToTime(const QTime& postime)
+{
+ if ( running() )
+ return;
+
+ if ((!isXineReady()) || (!isPlaying()) || (!isSeekable()))
+ return;
+
+ seekThreadPause = false;
+ if (m_currentSpeed == Pause)
+ seekThreadPause = true;
+ seekThreadPos = 0;
+ seekThreadTime = QTime().msecsTo(postime);
+ start();
+}
+
+void KXineWidget::slotStopSeeking()
+{
+ debugOut("Seeking stopped");
+ m_posTimer.start(200, false);
+}
+
+void KXineWidget::slotEject()
+{
+ xine_eject(m_xineStream);
+}
+
+void KXineWidget::slotEnableAutoresize(bool enable)
+{
+ m_autoresizeEnabled = enable;
+ if (!m_autoresizeEnabled)
+ {
+ m_videoFrameHeight = 0;
+ m_videoFrameWidth = 0;
+ }
+}
+
+/***************************************
+ * tvtime deinterlacer plugin *
+ ***************************************/
+
+#ifndef USE_QT_ONLY
+void KXineWidget::createDeinterlacePlugin(const QString& config, QWidget* parent)
+{
+ m_deinterlaceFilter = new PostFilter(config.section(':',0,0), m_xineEngine, m_audioDriver, m_videoDriver, parent);
+ if( !m_deinterlaceFilter->getInput() || !m_deinterlaceFilter->getOutput() )
+ {
+ delete m_deinterlaceFilter;
+ m_deinterlaceFilter = NULL;
+ }
+
+ slotSetDeinterlaceConfig(config);
+}
+
+const QString KXineWidget::getDeinterlaceConfig() const
+{
+ if (m_deinterlaceFilter)
+ return m_deinterlaceFilter->getConfig();
+
+ return DEFAULT_TVTIME_CONFIG;
+}
+#endif
+
+void KXineWidget::slotSetDeinterlaceConfig(const QString& config)
+{
+#ifndef USE_QT_ONLY
+ if (m_deinterlaceFilter)
+ m_deinterlaceFilter->setConfig(config);
+#else
+ warningOut(QString ("Not implemented [SetDeinterlaceConfig %1]").arg(config));
+#endif
+}
+
+void KXineWidget::slotToggleDeinterlace()
+{
+#ifndef USE_QT_ONLY
+ QString s;
+
+ if (m_deinterlaceFilter)
+ {
+ m_deinterlaceEnabled = !m_deinterlaceEnabled;
+ debugOut(QString("Deinterlace enabled: %1").arg(m_deinterlaceEnabled));
+ if ( m_deinterlaceEnabled ) s = i18n("Deinterlace: on");
+ else s = i18n("Deinterlace: off");
+ showOSDMessage( s, 2000 );
+ unwireVideoFilters();
+ wireVideoFilters();
+ }
+ else
+ {
+ /* fallback - this method is deprecated */
+ if (xine_get_param(m_xineStream, XINE_PARAM_VO_DEINTERLACE))
+ xine_set_param(m_xineStream, XINE_PARAM_VO_DEINTERLACE, false);
+ else
+ xine_set_param(m_xineStream, XINE_PARAM_VO_DEINTERLACE, true);
+ }
+#else
+ warningOut("Not implemented!");
+#endif
+}
+
+/**************************/
+
+void KXineWidget::slotAspectRatioAuto()
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_AUTO);
+ emit signalXineStatus(i18n("Aspect Ratio") + ": " + i18n("Auto"));
+}
+
+void KXineWidget::slotAspectRatio4_3()
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_4_3);
+ emit signalXineStatus(i18n("Aspect Ratio") + ": " + i18n("4:3"));
+}
+
+void KXineWidget::slotAspectRatioAnamorphic()
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_ANAMORPHIC);
+ emit signalXineStatus(i18n("Aspect Ratio") + ": " + i18n("16:9"));
+}
+
+void KXineWidget::slotAspectRatioSquare()
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_SQUARE);
+ emit signalXineStatus(i18n("Aspect Ratio") + ": " + i18n("1:1"));
+}
+
+void KXineWidget::slotAspectRatioDVB()
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ASPECT_RATIO, XINE_VO_ASPECT_DVB);
+ emit signalXineStatus(i18n("Aspect Ratio") + ": " + i18n("2.11:1"));
+}
+
+void KXineWidget::slotZoomOutX()
+{
+ if ((m_currentZoomX - 5) >= 100)
+ {
+ m_currentZoomX -= 5;
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_X, m_currentZoomX);
+ emit signalXineStatus(i18n("Zoom X") + ": " + QString::number(m_currentZoomX) + "%");
+ }
+}
+
+void KXineWidget::slotZoomInX()
+{
+ if ((m_currentZoomX + 5) <= XINE_VO_ZOOM_MAX)
+ {
+ m_currentZoomX += 5;
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_X, m_currentZoomX);
+ emit signalXineStatus(i18n("Zoom X") + ": " + QString::number(m_currentZoomX) + "%");
+ }
+}
+
+void KXineWidget::slotZoomOutY()
+{
+ if ((m_currentZoomY - 5) >= 100)
+ {
+ m_currentZoomY -= 5;
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_Y, m_currentZoomY);
+ emit signalXineStatus(i18n("Zoom Y") + ": " + QString::number(m_currentZoomY) + "%");
+ }
+}
+
+void KXineWidget::slotZoomInY()
+{
+ if ((m_currentZoomY + 5) <= XINE_VO_ZOOM_MAX)
+ {
+ m_currentZoomY += 5;
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_Y, m_currentZoomY);
+ emit signalXineStatus(i18n("Zoom Y") + ": " + QString::number(m_currentZoomY) + "%");
+ }
+}
+
+void KXineWidget::slotZoomOut()
+{
+ if ((m_currentZoom - 5) >= 100)
+ {
+ m_currentZoom -= 5;
+ m_currentZoomX = m_currentZoomY = m_currentZoom;
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_X, m_currentZoom);
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_Y, m_currentZoom);
+ emit signalXineStatus(i18n("Zoom") + ": " + QString::number(m_currentZoom) + "%");
+ }
+}
+
+void KXineWidget::slotZoomIn()
+{
+ if ((m_currentZoom + 5) <= XINE_VO_ZOOM_MAX)
+ {
+ m_currentZoom += 5;
+ m_currentZoomX = m_currentZoomY = m_currentZoom;
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_X, m_currentZoom);
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_Y, m_currentZoom);
+ emit signalXineStatus(i18n("Zoom") + ": " + QString::number(m_currentZoom) + "%");
+ }
+}
+
+void KXineWidget::slotZoomOff()
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_X, 100);
+ xine_set_param(m_xineStream, XINE_PARAM_VO_ZOOM_Y, 100);
+ m_currentZoom = 100;
+ m_currentZoomX = m_currentZoomY = m_currentZoom;
+ emit signalXineStatus(i18n("Zoom") + ": " + QString::number(m_currentZoom) + "%");
+}
+
+QTime KXineWidget::getLengthInfo()
+{
+ int pos, time, length;
+
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(m_xineStream, &pos, &time, &length)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+
+ if ( (ret != 0) && (length > 0) )
+ {
+ return msToTime(length);
+ }
+
+ return QTime();
+}
+
+void KXineWidget::slotEmitLengthInfo()
+{
+ QTime length = getLengthInfo();
+ if (!(length.isNull()))
+ {
+ if ( m_trackURL!="DVB" ) m_lengthInfoTimer.stop();
+ m_trackLength = length;
+ emit signalLengthChanged();
+ }
+ else
+ {
+ if (m_lengthInfoTries > 10) // wait 10 seconds
+ m_lengthInfoTimer.stop();
+ else
+ {
+ debugOut("Wait for valid length information");
+ m_lengthInfoTries ++;
+ }
+ }
+}
+
+void KXineWidget::globalPosChanged()
+{
+ QPoint g = mapToGlobal(QPoint(0,0));
+ m_globalX = g.x();
+ m_globalY = g.y();
+}
+
+const xine_t* const KXineWidget::getXineEngine()const
+{
+ return m_xineEngine;
+}
+
+/************ video settings ****************/
+
+void KXineWidget::getVideoSettings(int& hue, int& sat, int& contrast, int& bright,
+ int& avOffset, int& spuOffset) const
+{
+ hue = xine_get_param(m_xineStream, XINE_PARAM_VO_HUE);
+ sat = xine_get_param(m_xineStream, XINE_PARAM_VO_SATURATION);
+ contrast = xine_get_param(m_xineStream, XINE_PARAM_VO_CONTRAST);
+ bright = xine_get_param(m_xineStream, XINE_PARAM_VO_BRIGHTNESS);
+ avOffset = xine_get_param(m_xineStream, XINE_PARAM_AV_OFFSET);
+ spuOffset = xine_get_param(m_xineStream, XINE_PARAM_SPU_OFFSET);
+}
+
+void KXineWidget::getspuOffset(int& spuOffset) const
+{
+ spuOffset = xine_get_param(m_xineStream, XINE_PARAM_SPU_OFFSET);
+}
+
+void KXineWidget::slotSetHue(int hue)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_HUE, hue);
+ emit signalXineStatus(i18n("Hue") + ": " + QString::number((hue*100)/65535) + "%");
+}
+
+void KXineWidget::slotSetSaturation(int sat)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_SATURATION, sat);
+ emit signalXineStatus(i18n("Saturation") + ": " + QString::number((sat*100)/65535) + "%");
+}
+
+void KXineWidget::slotSetContrast(int contrast)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_CONTRAST, contrast);
+ emit signalXineStatus(i18n("Contrast") + ": " + QString::number((contrast*100)/65535) + "%");
+}
+
+void KXineWidget::slotSetBrightness(int bright)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_VO_BRIGHTNESS, bright);
+ emit signalXineStatus(i18n("Brightness") + ": " + QString::number((bright*100)/65535) + "%");
+}
+
+void KXineWidget::slotSetAVOffset(int av)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_AV_OFFSET, av);
+ emit signalXineStatus(i18n("Audio/Video Offset") + ": " + QString::number(av/90) + i18n("msec"));
+}
+
+void KXineWidget::slotSetSpuOffset(int spu)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_SPU_OFFSET, spu);
+ emit signalXineStatus(i18n("Subtitle Offset") + ": " + QString::number(spu/90) + i18n("msec"));
+}
+
+
+/**************** equalizer *****************/
+
+void KXineWidget::slotSetEq30(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_30HZ, -val);
+}
+
+void KXineWidget::slotSetEq60(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_60HZ, -val);
+}
+
+void KXineWidget::slotSetEq125(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_125HZ, -val);
+}
+
+void KXineWidget::slotSetEq250(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_250HZ, -val);
+}
+
+void KXineWidget::slotSetEq500(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_500HZ, -val);
+}
+
+void KXineWidget::slotSetEq1k(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_1000HZ, -val);
+}
+
+void KXineWidget::slotSetEq2k(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_2000HZ, -val);
+}
+
+void KXineWidget::slotSetEq4k(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_4000HZ, -val);
+}
+
+void KXineWidget::slotSetEq8k(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_8000HZ, -val);
+}
+
+void KXineWidget::slotSetEq16k(int val)
+{
+ xine_set_param(m_xineStream, XINE_PARAM_EQ_16000HZ, -val);
+}
+
+void KXineWidget::slotSetVolumeGain(bool gain)
+{
+ int amp = 0;
+
+ if (gain)
+ {
+ if (m_softwareMixer)
+ amp = getVolume()*2;
+ else
+ amp = 200;
+ }
+ else
+ {
+ if (m_softwareMixer)
+ amp = getVolume();
+ else
+ amp = 100;
+ }
+ xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, amp);
+
+ m_volumeGain = gain;
+}
+
+/*************** dvd menus ******************/
+
+void KXineWidget::slotMenuToggle()
+{
+ xine_event_t xev;
+ xev.type = XINE_EVENT_INPUT_MENU1;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotMenuTitle()
+{
+ xine_event_t xev;
+ xev.type = XINE_EVENT_INPUT_MENU2;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotMenuRoot()
+{
+ xine_event_t xev;
+ xev.type = XINE_EVENT_INPUT_MENU3;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotMenuSubpicture()
+{
+ xine_event_t xev;
+ xev.type = XINE_EVENT_INPUT_MENU4;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotMenuAudio()
+{
+ xine_event_t xev;
+ xev.type = XINE_EVENT_INPUT_MENU5;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotMenuAngle()
+{
+ xine_event_t xev;
+ xev.type = XINE_EVENT_INPUT_MENU6;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotMenuPart()
+{
+ xine_event_t xev;
+ xev.type = XINE_EVENT_INPUT_MENU7;
+ xev.data = NULL;
+ xev.data_length = 0;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotDVDMenuLeft()
+{
+ xine_event_t xev;
+ xev.data = NULL;
+ xev.data_length = 0;
+ xev.type = XINE_EVENT_INPUT_LEFT;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotDVDMenuRight()
+{
+ xine_event_t xev;
+ xev.data = NULL;
+ xev.data_length = 0;
+ xev.type = XINE_EVENT_INPUT_RIGHT;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotDVDMenuUp()
+{
+ xine_event_t xev;
+ xev.data = NULL;
+ xev.data_length = 0;
+ xev.type = XINE_EVENT_INPUT_UP;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotDVDMenuDown()
+{
+ xine_event_t xev;
+ xev.data = NULL;
+ xev.data_length = 0;
+ xev.type = XINE_EVENT_INPUT_DOWN;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+void KXineWidget::slotDVDMenuSelect()
+{
+ xine_event_t xev;
+ xev.data = NULL;
+ xev.data_length = 0;
+ xev.type = XINE_EVENT_INPUT_SELECT;
+
+ xine_event_send(m_xineStream, &xev);
+}
+
+
+/******** mouse hideing at fullscreen ****/
+
+void KXineWidget::startMouseHideTimer()
+{
+ m_mouseHideTimer.start(5000);
+}
+
+void KXineWidget::stopMouseHideTimer()
+{
+ m_mouseHideTimer.stop();
+}
+
+void KXineWidget::slotHideMouse()
+{
+ if (cursor().shape() == Qt::ArrowCursor)
+ {
+ setCursor(QCursor(Qt::BlankCursor));
+ }
+}
+
+
+/************************************************************
+ * Take a Screenshot *
+ ************************************************************/
+
+QImage KXineWidget::getScreenshot() const
+{
+ uchar *rgbPile = NULL;
+ int width, height;
+ double scaleFactor;
+
+ getScreenshot(rgbPile, width, height, scaleFactor);
+
+ if (!rgbPile) return QImage();
+
+ QImage screenShot(rgbPile, width, height, 32, 0, 0, QImage::IgnoreEndian);
+ if (scaleFactor >= 1.0)
+ width = (int)((double) width * scaleFactor + 0.5);
+ else
+ height = (int)((double) height / scaleFactor + 0.5);
+
+ debugOut(QString("Screenshot: scale picture from %1x%2 to %3x%4").arg(screenShot.width()).arg(screenShot.height()).arg(width).arg(height));
+ screenShot = screenShot.smoothScale(width, height);
+
+ delete []rgbPile;
+ return screenShot;
+}
+
+void KXineWidget::getScreenshot(uchar*& rgb32BitData, int& videoWidth, int& videoHeight, double& scaleFactor) const
+{
+
+ uint8_t *yuv = NULL, *y = NULL, *u = NULL, *v =NULL;
+
+ int width, height, ratio, format;
+ // double desired_ratio, image_ratio;
+
+ if (!xine_get_current_frame(m_xineStream, &width, &height, &ratio, &format, NULL))
+ return;
+
+ yuv = new uint8_t[((width+8) * (height+1) * 2)];
+ if (yuv == NULL)
+ {
+ errorOut("Not enough memory to make screenshot!");
+ return;
+ }
+
+ xine_get_current_frame(m_xineStream, &width, &height, &ratio, &format, yuv);
+
+ videoWidth = width;
+ videoHeight = height;
+
+ /*
+ * convert to yv12 if necessary
+ */
+
+ switch (format)
+ {
+ case XINE_IMGFMT_YUY2:
+ {
+ uint8_t *yuy2 = yuv;
+
+ yuv = new uint8_t[(width * height * 2)];
+ if (yuv == NULL)
+ {
+ errorOut("Not enough memory to make screenshot!");
+ return;
+ }
+ y = yuv;
+ u = yuv + width * height;
+ v = yuv + width * height * 5 / 4;
+
+ yuy2Toyv12 (y, u, v, yuy2, width, height);
+
+ delete [] yuy2;
+ }
+ break;
+ case XINE_IMGFMT_YV12:
+ y = yuv;
+ u = yuv + width * height;
+ v = yuv + width * height * 5 / 4;
+
+ break;
+ default:
+ {
+ warningOut(QString("Screenshot: Format %1 not supportet!").arg((char*)&format));
+ delete [] yuv;
+ return;
+ }
+ }
+
+ /*
+ * convert to rgb
+ */
+
+ rgb32BitData = yv12ToRgb (y, u, v, width, height);
+
+
+ // image_ratio = (double) height / (double) width;
+
+ /*
+ switch (ratio)
+ {
+ case XINE_VO_ASPECT_ANAMORPHIC:
+ debugOut("Screenshot: got video aspect: anamorphic");
+ desired_ratio = 16.0 /9.0;
+ break;
+ case XINE_VO_ASPECT_DVB:
+ debugOut("Screenshot: got video aspect: 2.11:1");
+ desired_ratio = 2.11/1.0;
+ break;
+ case XINE_VO_ASPECT_4_3:
+ debugOut("Screenshot: got video aspect: 4:3");
+ desired_ratio = 4.0 / 3.0;
+ break;
+ default:
+ warningOut(QString("Screenshot: Unknown aspect ratio: %1 - using 4:3").arg(ratio));
+ case XINE_VO_ASPECT_SQUARE:
+ debugOut("Screenshot: got video aspect: 1:1");
+ desired_ratio = image_ratio;
+ break;
+ }
+ */
+
+ debugOut(QString("Screenshot: using scale factor: %1").arg(m_videoAspect));
+ scaleFactor = m_videoAspect;
+
+ delete [] yuv;
+}
+
+
+/************************************************
+ * HELPER FUNCTIONS *
+ ************************************************/
+
+QTime KXineWidget::msToTime(int msec)
+{
+ QTime t;
+ t = t.addMSecs(msec);
+ return t;
+}
+
+#ifdef USE_QT_ONLY
+QString KXineWidget::i18n(const char *text)
+{
+ return QApplication::tr(text);
+}
+#endif
+
+void KXineWidget::debugOut (QString qsDebug)
+{
+#ifdef USE_QT_ONLY
+ QString qsDebugging = QString ("Debug: ") + qsDebug +"\n";
+ printf ((const char *)qsDebugging);
+#else
+ kdDebug() << "KXineWidget: " << (const char *)qsDebug.ascii() << "\n";
+#endif
+}
+void KXineWidget::errorOut (QString qsError)
+{
+#ifdef USE_QT_ONLY
+ QString qsErroring = QString ("Error: ") + qsError+ "\n";
+ printf ((const char *)qsErroring);
+#else
+ kdError() << "KXineWidget: " << (const char *)qsError.ascii() << "\n";
+#endif
+}
+void KXineWidget::warningOut (QString qsWarning)
+{
+#ifdef USE_QT_ONLY
+ QString qsWarninging = QString ("Warning: ") + qsWarning + "\n";
+ printf ((const char *)qsWarninging);
+#else
+ kdWarning() << "KXineWidget: " << (const char *)qsWarning.ascii() << "\n";
+#endif
+}
+
+
+/************************************************************
+ * Helpers to convert yuy and yv12 frames to rgb *
+ * code from gxine modified for 32bit output *
+ * Copyright (C) 2000-2003 the xine project *
+ ************************************************************/
+
+void KXineWidget::yuy2Toyv12 (uint8_t *y, uint8_t *u, uint8_t *v, uint8_t *input, int width, int height)
+{
+
+ int i, j, w2;
+
+ w2 = width / 2;
+
+ for (i = 0; i < height; i += 2)
+ {
+ for (j = 0; j < w2; j++)
+ {
+ /*
+ * packed YUV 422 is: Y[i] U[i] Y[i+1] V[i]
+ */
+ *(y++) = *(input++);
+ *(u++) = *(input++);
+ *(y++) = *(input++);
+ *(v++) = *(input++);
+ }
+
+ /*
+ * down sampling
+ */
+
+ for (j = 0; j < w2; j++)
+ {
+ /*
+ * skip every second line for U and V
+ */
+ *(y++) = *(input++);
+ input++;
+ *(y++) = *(input++);
+ input++;
+ }
+ }
+}
+
+
+uchar* KXineWidget::yv12ToRgb (uint8_t *src_y, uint8_t *src_u, uint8_t *src_v, int width, int height)
+{
+ /*
+ * Create rgb data from yv12
+ */
+
+#define clip_8_bit(val) \
+{ \
+ if (val < 0) \
+ val = 0; \
+ else \
+ if (val > 255) val = 255; \
+}
+
+ int i, j;
+
+ int y, u, v;
+ int r, g, b;
+
+ int sub_i_uv;
+ int sub_j_uv;
+
+ int uv_width, uv_height;
+
+ uchar *rgb;
+
+ uv_width = width / 2;
+ uv_height = height / 2;
+
+ rgb = new uchar[(width * height * 4)]; //qt needs a 32bit align
+ if (!rgb)
+ {
+ // kdError(555) << "Not enough memory!" << endl;
+ return NULL;
+ }
+
+ for (i = 0; i < height; ++i)
+ {
+ /*
+ * calculate u & v rows
+ */
+ sub_i_uv = ((i * uv_height) / height);
+
+ for (j = 0; j < width; ++j)
+ {
+ /*
+ * calculate u & v columns
+ */
+ sub_j_uv = ((j * uv_width) / width);
+
+ /***************************************************
+ *
+ * Colour conversion from
+ * http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
+ *
+ * Thanks to Billy Biggs <vektor@dumbterm.net>
+ * for the pointer and the following conversion.
+ *
+ * R' = [ 1.1644 0 1.5960 ] ([ Y' ] [ 16 ])
+ * G' = [ 1.1644 -0.3918 -0.8130 ] * ([ Cb ] - [ 128 ])
+ * B' = [ 1.1644 2.0172 0 ] ([ Cr ] [ 128 ])
+ *
+ * Where in xine the above values are represented as
+ *
+ * Y' == image->y
+ * Cb == image->u
+ * Cr == image->v
+ *
+ ***************************************************/
+
+ y = src_y[(i * width) + j] - 16;
+ u = src_u[(sub_i_uv * uv_width) + sub_j_uv] - 128;
+ v = src_v[(sub_i_uv * uv_width) + sub_j_uv] - 128;
+
+ r = (int)((1.1644 * (double)y) + (1.5960 * (double)v));
+ g = (int)((1.1644 * (double)y) - (0.3918 * (double)u) - (0.8130 * (double)v));
+ b = (int)((1.1644 * (double)y) + (2.0172 * (double)u));
+
+ clip_8_bit (r);
+ clip_8_bit (g);
+ clip_8_bit (b);
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ rgb[(i * width + j) * 4 + 0] = b;
+ rgb[(i * width + j) * 4 + 1] = g;
+ rgb[(i * width + j) * 4 + 2] = r;
+ rgb[(i * width + j) * 4 + 3] = 0;
+#else
+ rgb[(i * width + j) * 4 + 3] = b;
+ rgb[(i * width + j) * 4 + 2] = g;
+ rgb[(i * width + j) * 4 + 1] = r;
+ rgb[(i * width + j) * 4 + 0] = 0;
+#endif
+
+ }
+ }
+
+ return rgb;
+}
diff --git a/kaffeine/src/player-parts/xine-part/kxinewidget.h b/kaffeine/src/player-parts/xine-part/kxinewidget.h
new file mode 100644
index 0000000..aac81b4
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/kxinewidget.h
@@ -0,0 +1,518 @@
+/*
+ * kxinewidget.h - a kde / qt api for xine-lib
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ * Copyright (C) 2005-2006 Christophe Thommeret <hftom@free.fr>
+ *
+ * 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 KXINEWIDGET_H
+#define KXINEWIDGET_H
+
+/* define this if you want to use QT only - disables post plugin support (except visualization)! */
+//#define USE_QT_ONLY 1
+
+/* Usage:
+ *
+ * KXineWidget m_xine = new KXineWidget(parent);
+ * m_xine->appendToQueue("the_best_song_of_the_world.mp3");
+ *
+ * You should at least connect to signalXineFatal(const QString&)!
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* forward declaration */
+class QWidget;
+class QString;
+class QStringList;
+class QMouseEvent;
+class QTimerEvent;
+class QTime;
+
+#include <qtimer.h>
+#include <qptrlist.h>
+#include <qthread.h>
+#include <X11/Xlib.h>
+#include <xine.h>
+
+
+#ifndef USE_QT_ONLY
+#include "postfilter.h"
+#else
+typedef int PostFilter; /* dummy type */
+#endif
+
+#ifdef HAVE_XCB
+#include <xcb/xcb.h>
+#endif
+
+#define SUPPORTED_PROTOCOLS "file,http,mms,mmst,rtsp,rtp,tcp,pnm,cdda,vcd,vcdo,dvd,dvb,pvr,v4l,net,vdr,smb"
+
+#define DEFAULT_TVTIME_CONFIG "tvtime:method=LinearBlend,enabled=1,pulldown=none,framerate_mode=half_top,judder_correction=0,use_progressive_frame_flag=1,chroma_filter=0,cheap_mode=1"
+
+#define DEFAULT_OSD_FONT_SIZE 18
+#define DEFAULT_OSD_DURATION 5000
+#define OSD_MESSAGE_LOW_PRIORITY 1
+#define OSD_MESSAGE_NORMAL_PRIORITY 2
+
+class KXineWidget : public QWidget, public QThread
+{
+
+ Q_OBJECT
+
+public:
+ KXineWidget(QWidget *parent=0, const char *name=0,
+ const QString& pathToConfigFile = QString::null, const QString& pathToLogoFile = QString::null,
+ const QString& audioDriver = QString::null, const QString& videoDriver = QString::null,
+ bool startManual = false, bool verbose = false);
+ ~KXineWidget();
+
+ enum Speed { Normal = 0, Pause, Fast1, Fast2, Slow1, Slow2, Undefined };
+
+ bool initXine(); /* call this only if you set startManual = true in the constructor */
+ bool isXineReady() const { return m_xineReady; }
+ bool isPlaying() const;
+ Speed getSpeed() const { return m_currentSpeed; }
+ QString getXineLog() const;
+
+ void setQueue(const QStringList& urls) { m_queue = urls; }
+ void appendToQueue(const QString& url) { m_queue.append(url); } /* file to play; call slotPlay() to play queue... */
+ void clearQueue() { m_queue.clear(); }
+ bool isQueueEmpty() const { return m_queue.empty(); }
+
+ void showOSDMessage(const QString& message, uint duration = DEFAULT_OSD_DURATION /* ms */, int priority = OSD_MESSAGE_NORMAL_PRIORITY);
+
+ /* stream info */
+ const QString& getURL() const { return m_trackURL; }
+ const QString& getTitle() const { return m_trackTitle; }
+ const QString& getArtist() const { return m_trackArtist; }
+ const QString& getAlbum() const { return m_trackAlbum; }
+ const QString& getTrackNumber() const { return m_trackNumber; } //may return an empty string with xine-lib 1.0
+ const QString& getGenre() const { return m_trackGenre; }
+ const QString& getYear() const { return m_trackYear; }
+ const QString& getComment() const { return m_trackComment; }
+ const QTime& getLength() const { return m_trackLength; }
+ const QString& getVideoCodec() const { return m_trackVideoCodec; }
+ QSize getVideoSize() const { return QSize(m_videoFrameWidth, m_videoFrameHeight); }
+ int getVideoWidth();
+ int getVideoHeight();
+ uint getVideoBitrate() const { return m_trackVideoBitrate; }
+ const QString& getAudioCodec() const { return m_trackAudioCodec; }
+ uint getAudioBitrate() const { return m_trackAudioBitrate; }
+ const QString& getSubtitleURL() const { return m_trackSubtitleURL; }
+ const QString& getSaveURL() const { return m_trackSaveURL; }
+ bool hasVideo() const { return m_trackHasVideo; }
+ bool hasAudio() const { return m_trackHasAudio; }
+ bool hasChapters() const { return m_trackHasChapters; }
+ bool hasSubtitleURL() const { return !m_trackSubtitleURL.isNull(); }
+ bool hasSaveURL() const { return !m_trackSaveURL.isNull(); }
+ bool isSeekable() const { return m_trackIsSeekable; }
+
+ uint getVolume() const; /* percent */
+ bool SoftwareMixing() const;
+ QTime getPlaytime() const;
+ uint getPosition() const; /* 0..65535 */
+
+ void savePosition(const int pos) { (pos > 0) ? m_savedPos = pos : m_savedPos = 0; }
+
+ /* plugin handling */
+ QStringList getAudioDrivers() const { return m_audioDriverList; }
+ QStringList getVideoDrivers() const { return m_videoDriverList; }
+ void getAutoplayPlugins(QStringList& pluginNames) const;
+ bool getAutoplayPluginURLS(const QString& name, QStringList& urls);
+ QStringList getVisualPlugins() const;
+
+#ifndef USE_QT_ONLY
+ void createDeinterlacePlugin(const QString& configString, QWidget* parent);
+ const QString getDeinterlaceConfig() const;
+ QStringList getVideoFilterNames() const;
+ QStringList getAudioFilterNames() const;
+ QStringList getAudioFilterConfig();
+ QStringList getVideoFilterConfig();
+#endif
+
+ QString getSupportedExtensions() const; /* get mime types xine can play */
+
+ void playNextChapter() const;
+ void playPreviousChapter() const;
+
+ /* config stuff */
+ void setStreamSaveDir(const QString& dir);
+ const QString getStreamSaveDir();
+ void setBroadcasterPort(const uint port);
+ void getVideoSettings(int& hue, int& sat, int& contrast, int& bright,
+ int& avOffset, int& spuOffset) const;
+ void getspuOffset(int& spuOffset) const;
+ /* disc drives devices*/
+ QString audiocdDevice() const;
+ QString vcdDevice() const;
+ QString dvdDevice() const;
+
+ /* dvd stuff */
+ uint currentDVDTitleNumber() const;
+ uint getDVDTitleCount() const;
+ uint currentDVDChapterNumber() const;
+ uint getDVDChapterCount() const;
+ uint currentDVDAngleNumber() const;
+ uint getDVDAngleCount() const;
+
+ /* take a screenshot */
+ QImage getScreenshot() const;
+ void getScreenshot(uchar*& rgb32BitData, int& videoWidth, int& videoHeight, double& scaleFactor) const;
+
+ /* get the xine engine, needed by the xine configuration dialog */
+ const xine_t* const getXineEngine() const;
+ void saveXineConfig();
+
+ /* for fullscreen */
+ void startMouseHideTimer();
+ void stopMouseHideTimer();
+
+ void globalPosChanged(); /* call this if global pos of parent was changed */
+
+signals:
+ void signalXineFatal(const QString& message); /** initXine() not successfull! **/
+ void signalXineError(const QString& message);
+ void signalXineMessage(const QString& message);
+ void signalXineStatus(const QString& status);
+ void signalXineReady();
+ void signalXinePlaying();
+
+ void signalHasChapters(bool);
+ void signalPlaybackFinished();
+ void signalNewChannels(const QStringList& audio, const QStringList& sub, int currentAudio, int currentSub);
+ void signalNewPosition(int, const QTime&);
+
+ void signalTitleChanged();
+ void signalVideoSizeChanged();
+ void signalLengthChanged();
+
+ void signalRightClick(const QPoint&); /* right-click on video window */
+ void signalLeftClick(const QPoint&);
+ void signalMiddleClick();
+ void signalDoubleClick();
+ void signalSyncVolume();
+
+ void signalDvbOSDHidden();
+
+public slots:
+ virtual void polish();
+
+ void slotPlay();
+ void slotStop();
+
+ void slotSetVolume(int);
+ void slotToggleMute();
+ void slotSpeedPause();
+ void slotSpeedNormal();
+ void slotSpeedFaster();
+ void slotSpeedSlower();
+ void slotSetVisualPlugin(const QString& name);
+ void slotSetAudioChannel(int);
+ void slotSetSubtitleChannel(int);
+ void slotSetFileSubtitles(QString);
+ void slotStartSeeking();
+ void slotSeekToPosition(int pos);
+ void slotSeekToPositionBlocking(int pos);
+ void slotSeekToTime(const QTime&);
+ void slotStopSeeking();
+ void slotEnableVideoFilters(bool enable);
+ void slotEnableAudioFilters(bool enable);
+ void slotEject();
+ void slotEnableAutoresize(bool enable);
+ void slotAspectRatioAuto();
+ void slotAspectRatio4_3();
+ void slotAspectRatioAnamorphic(); /* 16:9 */
+ void slotAspectRatioSquare(); /* 1:1 */
+ void slotAspectRatioDVB(); /* 2.11:1 */
+ void slotZoomIn();
+ void slotZoomOut();
+ void slotZoomOff();
+ void slotZoomOutX();
+ void slotZoomInX();
+ void slotZoomOutY();
+ void slotZoomInY();
+ void slotToggleDeinterlace();
+ void slotSetDeinterlaceConfig(const QString&);
+ void slotGetInfoDelayed();
+
+ /* disc drive devices */
+ void slotSetAudiocdDevice(const QString&);
+ void slotSetVcdDevice(const QString&);
+ void slotSetDvdDevice(const QString&);
+
+ void slotSetHue(int hue);
+ void slotSetSaturation(int sat);
+ void slotSetContrast(int contrast);
+ void slotSetBrightness(int bright);
+ void slotSetAVOffset(int av);
+ void slotSetSpuOffset(int spu);
+
+ void slotSetEq30(int val);
+ void slotSetEq60(int val);
+ void slotSetEq125(int val);
+ void slotSetEq250(int val);
+ void slotSetEq500(int val);
+ void slotSetEq1k(int val);
+ void slotSetEq2k(int val);
+ void slotSetEq4k(int val);
+ void slotSetEq8k(int val);
+ void slotSetEq16k(int val);
+ void slotSetVolumeGain(bool gain);
+
+ /* DVD Menus */
+ void slotMenuToggle();
+ void slotMenuTitle();
+ void slotMenuRoot();
+ void slotMenuSubpicture();
+ void slotMenuAudio();
+ void slotMenuAngle();
+ void slotMenuPart();
+ void slotDVDMenuLeft();
+ void slotDVDMenuRight();
+ void slotDVDMenuUp();
+ void slotDVDMenuDown();
+ void slotDVDMenuSelect();
+
+ /***** postprocess filters ****/
+ void slotCreateVideoFilter(const QString& name, QWidget* parent);
+ void slotCreateAudioFilter(const QString& name, QWidget* parent);
+ void slotDeleteVideoFilter(PostFilter* filter);
+ void slotDeleteAudioFilter(PostFilter* filter);
+ void slotRemoveAllVideoFilters();
+ void slotRemoveAllAudioFilters();
+
+protected slots:
+ void slotSendPosition();
+ void slotEmitLengthInfo();
+ void slotHideMouse();
+ void slotOSDHide();
+ void slotNoRecentMessage();
+
+protected:
+ void mouseMoveEvent(QMouseEvent*);
+ void mousePressEvent(QMouseEvent*);
+ void timerEvent(QTimerEvent*);
+ void mouseDoubleClickEvent(QMouseEvent*);
+ void wheelEvent(QWheelEvent*);
+ void initOSD();
+ virtual void run();
+
+private:
+#ifndef HAVE_XCB
+ bool x11Event(XEvent *);
+#else
+ void paintEvent(QPaintEvent *);
+#endif
+ bool unhandledStreamsPresent();
+
+ /********* callbacks and threads ************/
+ static void destSizeCallback(void* p, int video_width, int video_height, double video_aspect,
+ int* dest_width, int* dest_height, double* dest_aspect);
+
+ static void frameOutputCallback(void* p, int video_width, int video_height, double video_aspect,
+ int* dest_x, int* dest_y, int* dest_width, int* dest_height,
+ double* dest_aspect, int* win_x, int* win_y);
+
+ static void videoDriverChangedCallback(void* p, xine_cfg_entry_t* entry);
+ static void audioDriverChangedCallback(void* p, xine_cfg_entry_t* entry);
+ static void audioMixerMethodChangedCallback(void* p, xine_cfg_entry_t* entry);
+ static void showOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry);
+ static void sizeForOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry);
+ static void fontForOSDMessagesChangedCallback(void* p, xine_cfg_entry_t* entry);
+ static void monitorXResChangedCallback(void* p, xine_cfg_entry_t* entry);
+ static void monitorYResChangedCallback(void* p, xine_cfg_entry_t* entry);
+
+ static void xineEventListener(void* p, const xine_event_t*);
+
+protected:
+ void sendXineError();
+ QTime getLengthInfo();
+#ifndef USE_QT_ONLY
+ void wireVideoFilters();
+ void unwireVideoFilters();
+ void wireAudioFilters();
+ void unwireAudioFilters();
+#endif
+
+ /* HELPER FUNCTIONS */
+public:
+#ifdef USE_QT_ONLY
+ static QString i18n(const char *text);
+#endif
+ static void debugOut(QString);
+ static void errorOut(QString);
+ static void warningOut(QString);
+ static QTime msToTime(int msec);
+ static void yuy2Toyv12(uint8_t *y, uint8_t *u, uint8_t *v, uint8_t *input, int width, int height);
+ static uchar *yv12ToRgb(uint8_t *src_y, uint8_t *src_u, uint8_t *src_v, int width, int height);
+
+protected:
+ QStringList m_queue;
+
+ int seekThreadPos;
+ int seekThreadTime;
+ bool seekThreadPause;
+ bool m_startXineManual;
+ bool m_xineReady;
+ QString m_logoFile;
+ QString m_preferedAudio;
+ QString m_preferedVideo;
+ bool m_xineVerbose;
+ QString m_configFilePath;
+ QStringList m_audioDriverList;
+ QStringList m_videoDriverList;
+
+ /*x11*/
+#ifndef HAVE_XCB
+ Display *connection;
+#else
+ xcb_connection_t *connection;
+#endif
+
+ /*xine*/
+#ifndef HAVE_XCB
+ x11_visual_t m_x11Visual;
+#else
+ xcb_visual_t m_x11Visual;
+#endif
+ xine_t* m_xineEngine;
+ xine_audio_port_t* m_audioDriver;
+ xine_video_port_t* m_videoDriver;
+ xine_stream_t* m_xineStream;
+ xine_event_queue_t* m_eventQueue;
+ xine_osd_t* m_osd;
+ bool m_osdUnscaled;
+ bool m_osdShow;
+ int m_osdSize;
+ char* m_osdFont;
+ char** m_audioChoices;
+ char* m_audioInfo;
+ char** m_videoChoices;
+ char* m_videoInfo;
+ char* m_mixerInfo;
+ char* m_osdShowInfo;
+ char** m_osdSizeOptions;
+ char* m_osdSizeInfo;
+ char* m_osdFontInfo;
+ double monitorXRes, monitorYRes;
+ char *xResInfo;
+ char *yResInfo;
+
+#ifndef USE_QT_ONLY
+ /*postfilter*/
+ QPtrList<PostFilter> m_videoFilterList;
+ bool m_videoFiltersEnabled;
+ QPtrList<PostFilter> m_audioFilterList;
+ bool m_audioFiltersEnabled;
+ PostFilter* m_deinterlaceFilter;
+ bool m_deinterlaceEnabled;
+ PostFilter* m_visualPlugin;
+#else
+ xine_post_t* m_xinePost;
+ xine_post_out_t* m_postAudioSource;
+ xine_post_in_t* m_postInput;
+#endif
+
+ QString m_audioDriverName;
+ QString m_videoDriverName;
+ QString m_visualPluginName;
+
+ int m_videoFrameWidth;
+ int m_videoFrameHeight;
+ double m_videoAspect;
+ int m_globalX;
+ int m_globalY;
+
+ Speed m_currentSpeed;
+ QString m_xineMessage;
+ QString m_xineError;
+ QString m_statusString;
+ bool m_softwareMixer;
+ bool m_volumeGain;
+ double m_displayRatio;
+ QString m_cachedCDPath, m_cachedVCDPath, m_cachedDVDPath;
+ QSize m_newParentSize;
+ int m_currentZoom;
+ int m_currentZoomX, m_currentZoomY;
+ QStringList m_audioCh;
+ QStringList m_subCh;
+ int m_currentAudio, m_currentSub;
+ int m_savedPos;
+ bool m_autoresizeEnabled;
+ bool m_DVDButtonEntered;
+ QString m_newMRLReference;
+
+ QTimer m_posTimer;
+ QTimer m_lengthInfoTimer;
+ uint m_lengthInfoTries;
+ QTimer m_mouseHideTimer;
+ QTimer m_osdTimer;
+ QTimer m_recentMessagesTimer;
+
+ QString m_trackURL;
+ QString m_trackTitle;
+ QString m_trackArtist;
+ QString m_trackAlbum;
+ QString m_trackNumber;
+ QString m_trackGenre;
+ QString m_trackYear;
+ QString m_trackComment;
+ QTime m_trackLength;
+ QString m_trackVideoCodec;
+ uint m_trackVideoBitrate;
+ QString m_trackAudioCodec;
+ uint m_trackAudioBitrate;
+ QString m_trackSubtitleURL;
+ QString m_trackSaveURL;
+ bool m_trackHasVideo;
+ bool m_trackHasAudio;
+ bool m_trackHasChapters;
+ bool m_trackIsSeekable;
+
+ /* dvb */
+signals:
+ void stopDvb();
+
+public:
+ QString TimeShiftFilename;
+
+public slots:
+ void setDvb( const QString &pipeName, const QString &chanName, int haveVideo );
+ void setDvbCurrentNext( const QString &channelName, const QStringList &list );
+ bool openDvb();
+ bool playDvb();
+ void slotPlayTimeShift();
+ void dvbShowOSD();
+ void dvbHideOSD();
+
+private:
+ QString m_dvbChannelName;
+ bool m_dvbSaveTitle;
+ int dvbHaveVideo;
+ QTimer dvbOSDHideTimer;
+ xine_osd_t *dvbOSD;
+ QStringList dvbCurrentNext;
+ unsigned int dvbColor[256];
+ unsigned char dvbTrans[256];
+ void initDvbPalette();
+};
+
+#endif /* KXINEWIDGET_H */
diff --git a/kaffeine/src/player-parts/xine-part/positionslider.cpp b/kaffeine/src/player-parts/xine-part/positionslider.cpp
new file mode 100644
index 0000000..9091dbe
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/positionslider.cpp
@@ -0,0 +1,113 @@
+/*
+ * positionslider.cpp
+ *
+ * Copyright (C) 2004-2005 Giorgos Gousios
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ * Copyright (C) 2004-2005 Miguel Freitas
+ *
+ * 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 <math.h>
+
+#include "positionslider.h"
+#include "positionslider.moc"
+
+
+PositionSlider::PositionSlider(Qt::Orientation o, QWidget *parent, const char* name) :
+ QSlider(o, parent, name), m_userChange(false)
+{
+ connect(this, SIGNAL(sliderPressed()), this ,SLOT(slotSliderPressed()));
+ connect(this, SIGNAL(sliderReleased()), this, SLOT(slotSliderReleased()));
+ installEventFilter(this);
+}
+
+
+
+PositionSlider::~PositionSlider()
+{
+}
+
+
+
+void PositionSlider::setPosition(int val, bool changePosition)
+{
+ if(!m_userChange)
+ setValue(val);
+ if(changePosition) {
+ setValue(val);
+ emit sliderMoved(val);
+ }
+}
+
+
+
+void PositionSlider::slotSliderPressed()
+{
+ m_userChange = true;
+ emit signalStartSeeking();
+}
+
+
+
+void PositionSlider::slotSliderReleased()
+{
+ emit sliderLastMove(this->value());
+ emit signalStopSeeking();
+ m_userChange = false;
+}
+
+
+
+void PositionSlider::wheelEvent(QWheelEvent* e)
+{
+ float offset = log10( QABS(e->delta()) ) / 0.002;
+ int newVal = 0;
+ if (e->delta()>0)
+ newVal = value() - int(offset);
+ else
+ newVal = value() + int(offset);
+ if (newVal < 0) newVal = 0;
+ //setPosition(newVal, true);
+ emit sliderLastMove( newVal );
+ e->accept();
+}
+
+
+
+bool PositionSlider::eventFilter(QObject *obj, QEvent *ev)
+{
+ if( obj == this && (ev->type() == QEvent::MouseButtonPress || ev->type() == QEvent::MouseButtonDblClick) ) {
+ QMouseEvent *e = (QMouseEvent *)ev;
+ QRect r = sliderRect();
+
+ if( r.contains( e->pos() ) || e->button() != LeftButton )
+ return false;
+
+ int range = maxValue() - minValue();
+ int pos = (orientation() == Horizontal) ? e->pos().x() : e->pos().y();
+ int maxpos = (orientation() == Horizontal) ? width() : height();
+ int value = pos * range / maxpos + minValue();
+
+ if (QApplication::reverseLayout())
+ value = maxValue() - (value - minValue());
+
+ setPosition(value, true);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
diff --git a/kaffeine/src/player-parts/xine-part/positionslider.h b/kaffeine/src/player-parts/xine-part/positionslider.h
new file mode 100644
index 0000000..34c78e6
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/positionslider.h
@@ -0,0 +1,55 @@
+/*
+ * positionslider.h
+ *
+ * Copyright (C) 2004-2005 Giorgos Gousios
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ * Copyright (C) 2004-2005 Miguel Freitas
+ *
+ * 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 POSITIONSLIDER_H
+#define POSITIONSLIDER_H
+
+#include <qslider.h>
+
+class PositionSlider : public QSlider
+{
+ Q_OBJECT
+
+ public:
+ PositionSlider(Qt::Orientation, QWidget * parent = 0, const char* name = 0);
+ virtual ~PositionSlider();
+
+ void setPosition(int, bool);
+
+signals:
+ void signalStartSeeking();
+ void signalStopSeeking();
+ void sliderLastMove(int);
+
+ protected:
+ virtual void wheelEvent(QWheelEvent* e);
+ bool eventFilter(QObject *obj, QEvent *ev);
+
+ private slots:
+ void slotSliderPressed();
+ void slotSliderReleased();
+
+ private:
+ bool m_userChange;
+};
+
+#endif /* POSITIONSLIDER_H */
diff --git a/kaffeine/src/player-parts/xine-part/postfilter.cpp b/kaffeine/src/player-parts/xine-part/postfilter.cpp
new file mode 100644
index 0000000..32c898c
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/postfilter.cpp
@@ -0,0 +1,398 @@
+/*
+ * postfilter.cpp - wrapper for xine's postprocessing filters
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ * Copyright (C) 2003-2005 Miguel Freitas
+ *
+ * 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 <kpushbutton.h>
+#include <kseparator.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwidget.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <qgroupbox.h>
+#include <qtextedit.h>
+
+#include <stdio.h>
+
+#include "postfilter.h"
+
+PostFilter::PostFilter(const QString& name, xine_t* engine, xine_audio_port_t* audioDriver,
+ xine_video_port_t* videoDriver, QWidget *parent) : QObject(parent), m_data(NULL), m_groupBox(NULL)
+{
+ m_filterName = name;
+ kdDebug() << "PostFilter: Create Postprocessing Filter: " << m_filterName << endl;
+
+ m_xineEngine = engine;
+
+ m_xinePost = xine_post_init(m_xineEngine, m_filterName.ascii(), 0, &audioDriver, &videoDriver );
+ if(m_xinePost)
+ {
+ xine_post_in_t* inputAPI = NULL;
+
+ m_groupBox = new QGroupBox(name, parent);
+ m_groupBox->setSizePolicy(QSizePolicy (QSizePolicy::Minimum, QSizePolicy::Fixed));
+ QGridLayout* grid = new QGridLayout(m_groupBox, 2, 2);
+ grid->setMargin( 20 );
+ grid->setSpacing( 5 );
+ int row = 0;
+
+ if ((inputAPI = (xine_post_in_t*)xine_post_input(m_xinePost, const_cast<char*>("parameters"))))
+ {
+ m_xinePostAPI = (xine_post_api_t*)inputAPI->data;
+ m_xinePostDescr = m_xinePostAPI->get_param_descr();
+ m_xinePostParameter = m_xinePostDescr->parameter;
+
+ m_data = new char[m_xinePostDescr->struct_size];
+ m_xinePostAPI->get_parameters(m_xinePost, m_data);
+
+ QLabel* descr;
+
+ while (m_xinePostParameter->type != POST_PARAM_TYPE_LAST)
+ {
+ kdDebug() << "PostFilter: Parameter: " << m_xinePostParameter->name << endl;
+ if (m_xinePostParameter->readonly) continue;
+
+ switch (m_xinePostParameter->type)
+ {
+ case POST_PARAM_TYPE_INT:
+ {
+ if (m_xinePostParameter->enum_values)
+ {
+ PostFilterParameterCombo* parameter = new
+ PostFilterParameterCombo(m_xinePostParameter->name, m_xinePostParameter->offset,
+ *(int*)(m_data+m_xinePostParameter->offset),
+ m_xinePostParameter->enum_values, m_groupBox );
+ connect(parameter, SIGNAL(signalIntValue(int, int)), this, SLOT(slotApplyIntValue(int, int)));
+ m_parameterList.append(parameter);
+
+ grid->addWidget(parameter->getWidget(), row, 0);
+ }
+ else
+ {
+ PostFilterParameterInt* parameter = new
+ PostFilterParameterInt(m_xinePostParameter->name, m_xinePostParameter->offset,
+ *(int*)(m_data+m_xinePostParameter->offset),
+ (int)m_xinePostParameter->range_min, (int)m_xinePostParameter->range_max,
+ m_groupBox);
+
+ connect(parameter, SIGNAL( signalIntValue(int, int)), this, SLOT( slotApplyIntValue(int, int)));
+ m_parameterList.append(parameter);
+
+ grid->addWidget(parameter->getWidget(), row, 0);
+ }
+ break;
+ }
+ case POST_PARAM_TYPE_DOUBLE:
+ {
+ PostFilterParameterDouble* parameter = new
+ PostFilterParameterDouble(m_xinePostParameter->name, m_xinePostParameter->offset,
+ *(double*)(m_data+m_xinePostParameter->offset),
+ (double)m_xinePostParameter->range_min, (double)m_xinePostParameter->range_max,
+ m_groupBox);
+
+ connect(parameter, SIGNAL(signalDoubleValue(int, double)), this, SLOT(slotApplyDoubleValue(int, double)));
+ m_parameterList.append(parameter);
+
+ grid->addWidget(parameter->getWidget(), row, 0);
+ break;
+ }
+ case POST_PARAM_TYPE_CHAR:
+ {
+ PostFilterParameterChar* parameter = new
+ PostFilterParameterChar(m_xinePostParameter->name, m_xinePostParameter->offset,
+ (char*)(m_data+m_xinePostParameter->offset), m_xinePostParameter->size,
+ m_groupBox);
+
+ connect( parameter, SIGNAL(signalCharValue(int, const QString&)), this, SLOT(slotApplyCharValue(int, const QString&)));
+ m_parameterList.append(parameter);
+
+ grid->addWidget(parameter->getWidget(), row, 0);
+ break;
+ }
+ case POST_PARAM_TYPE_STRING:
+ case POST_PARAM_TYPE_STRINGLIST: break; /* not implemented */
+ case POST_PARAM_TYPE_BOOL:
+ {
+ PostFilterParameterBool* parameter = new
+ PostFilterParameterBool(m_xinePostParameter->name, m_xinePostParameter->offset,
+ (bool) *(int*)(m_data+m_xinePostParameter->offset), m_groupBox);
+
+ connect(parameter, SIGNAL(signalIntValue(int, int)), this, SLOT(slotApplyIntValue(int, int)));
+ m_parameterList.append(parameter);
+
+ grid->addWidget(parameter->getWidget(), row, 0);
+ break;
+ }
+ default: break;
+ }
+
+ descr = new QLabel(QString::fromUtf8(m_xinePostParameter->description ), m_groupBox);
+ descr->setAlignment(QLabel::WordBreak | QLabel::AlignVCenter);
+ grid->addWidget(descr, row, 1);
+ row++;
+ m_xinePostParameter++;
+ }
+ }
+ KSeparator* sep = new KSeparator(KSeparator::Horizontal, m_groupBox);
+ grid->addMultiCellWidget(sep, row, row, 0, 1);
+ row++;
+ KPushButton* deleteButton = new KPushButton(i18n("Delete Filter"), m_groupBox);
+ deleteButton->setSizePolicy (QSizePolicy (QSizePolicy::Minimum, QSizePolicy::Fixed));
+ connect(deleteButton, SIGNAL(clicked()), this, SLOT( slotDeletePressed()));
+ grid->addWidget(deleteButton, row, 0);
+
+ if(inputAPI)
+ {
+ KPushButton* helpButton = new KPushButton(i18n("Help"), m_groupBox);
+ helpButton->setSizePolicy(QSizePolicy (QSizePolicy::Minimum, QSizePolicy::Fixed));
+ connect(helpButton, SIGNAL(clicked()), this, SLOT(slotHelpPressed()));
+ grid->addWidget(helpButton, row, 1);
+ }
+
+ if (parent)
+ m_groupBox->show();
+ }
+}
+
+PostFilter::~PostFilter()
+{
+ kdDebug() << "PostFilter: Delete Postprocessing Filter: " << m_filterName << endl;
+ if(m_xinePost)
+ {
+ delete m_groupBox;
+ delete [] m_data;
+ xine_post_dispose(m_xineEngine, m_xinePost);
+ }
+}
+
+void PostFilter::slotApplyIntValue(int offset, int val)
+{
+ kdDebug() << "PostFilter: " << m_filterName << " Apply integer value " << val << " on offset " << offset << endl;
+ *(int*)(m_data+offset) = val;
+ m_xinePostAPI->set_parameters(m_xinePost, m_data);
+}
+
+void PostFilter::slotApplyDoubleValue(int offset, double val)
+{
+ kdDebug() << "PostFilter: " << m_filterName << " Apply double value " << val << " on offset " << offset << endl;
+ *(double*)(m_data+offset) = val;
+ m_xinePostAPI->set_parameters(m_xinePost, m_data);
+}
+
+void PostFilter::slotApplyCharValue(int offset, const QString& val)
+{
+ kdDebug() << "PostFilter: " << m_filterName << " Apply char value '" << val << "' on offset " << offset << endl;
+ sprintf((char *)(m_data+offset), "%s", val.latin1());
+ m_xinePostAPI->set_parameters(m_xinePost, m_data);
+}
+
+xine_post_in_t* PostFilter::getInput() const
+{
+ xine_post_in_t* input = NULL;
+
+ kdDebug() << "PostFilter: Get input" << endl;
+ if(m_xinePost)
+ {
+ /* look for known input ports */
+ input = xine_post_input(m_xinePost, const_cast<char*>("video"));
+ if( !input )
+ input = xine_post_input(m_xinePost, const_cast<char*>("video in") );
+ if( !input )
+ input = xine_post_input(m_xinePost, const_cast<char*>("audio"));
+ if( !input )
+ input = xine_post_input(m_xinePost, const_cast<char*>("audio in"));
+ }
+ return input;
+}
+
+
+xine_post_out_t* PostFilter::getOutput() const
+{
+ xine_post_out_t* output = NULL;
+
+ kdDebug() << "PostFilter: Get output" << endl;
+
+ if(m_xinePost)
+ {
+ /* look for known output ports */
+ output = xine_post_output(m_xinePost, const_cast<char*>("video"));
+ if( !output )
+ output = xine_post_output(m_xinePost, const_cast<char*>("video out"));
+ if( !output )
+ output = xine_post_output(m_xinePost, const_cast<char*>("audio"));
+ if( !output )
+ output = xine_post_output(m_xinePost, const_cast<char*>("audio out"));
+
+ if(!output)
+ {
+ /* fallback to the first available output port.
+ * some video plugins have funky port names :)
+ */
+ const char *const *outs = xine_post_list_outputs(m_xinePost);
+ return (xine_post_out_t*)xine_post_output(m_xinePost, (char *) *outs);
+ }
+ }
+
+ return output;
+}
+
+
+void PostFilter::slotHelpPressed()
+{
+ kdDebug() << "PostFilter: Help pressed" << endl;
+
+ PostFilterHelp* filterHelp = new PostFilterHelp(NULL, m_filterName.ascii(), QString::fromUtf8(m_xinePostAPI->get_help()));
+ filterHelp->exec();
+
+ delete filterHelp;
+}
+
+
+QString PostFilter::getConfig()
+{
+ /*
+ * returns a string like "filtername:parameter=value,parameter=value,..."
+ */
+
+ QString configString;
+ QTextOStream configStream(&configString);
+
+ configStream << m_filterName << ":";
+ for (uint i = 0; i < m_parameterList.count(); i++)
+ {
+ configStream << m_parameterList.at( i )->name() << "=" << m_parameterList.at( i )->getValue();
+ if( i != m_parameterList.count()-1 )
+ configStream << ",";
+ }
+
+ kdDebug() << "PostFilter: GetConfig " << configString << endl;
+
+ return configString;
+}
+
+void PostFilter::setConfig(const QString &configString)
+{
+ /*
+ * expects a string like filtername:parameter=value,parameter=value,...
+ * or filtername:parameter="value",parameter="value",...
+ */
+
+ kdDebug() << "PostFilter: SetConfig " << configString << endl;
+
+ QString configStr;
+ if (configString.section(':',0,0) == m_filterName)
+ {
+ configStr = configString.section(':',1,1);
+ }
+ else
+ {
+ kdWarning() << "PostFilter: Config string doesn't match filter name " << m_filterName << endl;
+ kdDebug() << "PostFilter: Don't apply new configuration" << endl;
+ return;
+ }
+
+ for( int i = 0; i < configStr.contains(',') + 1; i++ )
+ {
+ QString parameterConfig = configStr.section(',', i, i);
+ QString parameterName = parameterConfig.section('=', 0, 0);
+ QString parameterValue = parameterConfig.section('=', 1, 1);
+ parameterValue = parameterValue.remove('"');
+
+ for (uint j = 0; j < m_parameterList.count(); j++)
+ {
+ if(parameterName == m_parameterList.at(j)->name())
+ {
+ kdDebug() << "PostFilter: Set parameter '" << parameterName << "' to value '" << parameterValue << "'" << endl;
+ m_parameterList.at(j)->setValue(parameterValue);
+ }
+ }
+ }
+}
+
+PostFilterParameterInt::PostFilterParameterInt(const QString& name, int offset, int value, int min, int max, QWidget* parent)
+ : PostFilterParameter (name, offset, parent )
+{
+ m_numInput = new KIntNumInput(value, parent);
+ m_numInput->setRange( min, max, 1, false);
+ connect(m_numInput, SIGNAL(valueChanged(int)), this, SLOT(slotIntValue(int)));
+}
+
+PostFilterParameterDouble::PostFilterParameterDouble(const QString& name, int offset, double value, double min, double max, QWidget* parent)
+ : PostFilterParameter (name, offset, parent )
+{
+ m_numInput = new KDoubleNumInput(parent);
+ m_numInput->setValue(value);
+ m_numInput->setRange(min, max, 0.01, false);
+ connect(m_numInput, SIGNAL(valueChanged( double)), this, SLOT(slotDoubleValue( double)));
+}
+
+PostFilterParameterChar::PostFilterParameterChar(const QString& name, int offset, char *value, int size, QWidget* parent)
+ : PostFilterParameter (name, offset, parent )
+{
+ m_charInput = new KLineEdit(value, parent);
+ m_charInput->setMaxLength(size);
+ connect(m_charInput, SIGNAL(returnPressed(const QString&)), this, SLOT(slotCharValue(const QString&)));
+}
+
+PostFilterParameterCombo::PostFilterParameterCombo(const QString& name, int offset, int value, char **enums, QWidget* parent)
+ : PostFilterParameter (name, offset, parent)
+{
+ m_comboBox = new KComboBox(parent);
+ for (int i = 0; enums[i]; i++)
+ {
+ m_comboBox->insertItem(enums[i]);
+ }
+ m_comboBox->setCurrentItem(value);
+ connect(m_comboBox, SIGNAL( activated(int)), this, SLOT( slotIntValue(int)));
+}
+
+PostFilterParameterBool::PostFilterParameterBool(const QString& name, int offset, bool value, QWidget* parent)
+ : PostFilterParameter (name, offset, parent )
+{
+ m_checkBox = new QCheckBox(parent);
+ m_checkBox->setChecked(value);
+ connect(m_checkBox, SIGNAL(toggled(bool)), this, SLOT(slotBoolValue( bool)));
+}
+
+PostFilterHelp::PostFilterHelp(QWidget *parent, const char *name, const QString& text)
+ : KDialogBase( parent, name, true, QString(name) + " - " + i18n("Help"), KDialogBase::Close )
+{
+ setInitialSize( QSize(500,500) );
+
+ QWidget* mainWidget = makeMainWidget();
+ QGridLayout* grid = new QGridLayout( mainWidget, 1, 1 );
+ grid->setSpacing( 5 );
+
+ //QString help = QString::fromUtf8(text);
+ m_textEdit = new QTextEdit(text, QString::null, mainWidget, name);
+ m_textEdit->setReadOnly(true);
+ grid->addWidget(m_textEdit, 0, 0);
+}
+
+
+PostFilterHelp::~PostFilterHelp()
+{
+ delete m_textEdit;
+}
+
+#include "postfilter.moc"
diff --git a/kaffeine/src/player-parts/xine-part/postfilter.h b/kaffeine/src/player-parts/xine-part/postfilter.h
new file mode 100644
index 0000000..ce04359
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/postfilter.h
@@ -0,0 +1,229 @@
+/*
+ * postfilter.h - wrapper for xine's postprocessing filters
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ * Copyright (C) 2003-2005 Miguel Freitas
+ *
+ * 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 POSTFILTER_H
+#define POSTFILTER_H
+
+/* forward declaration */
+class QWidget;
+class QObject;
+class QString;
+class QGroupBox;
+class QTextEdit;
+class KPushButton;
+
+#include <klineedit.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+#include <kdialogbase.h>
+
+#include <qcheckbox.h>
+
+#include <xine.h>
+
+
+class PostFilterParameter : public QObject
+{
+ Q_OBJECT
+public:
+ PostFilterParameter(const QString& name, int offset, QWidget* parent)
+ : QObject(parent, name.ascii()), m_offset(offset)
+ {}
+ ~PostFilterParameter() {};
+
+ virtual void setValue( const QString& ) = 0;
+ virtual QString getValue() = 0;
+ virtual QWidget *getWidget() = 0;
+
+protected:
+ int m_offset;
+};
+
+
+class PostFilterParameterInt : public PostFilterParameter
+{
+ Q_OBJECT
+public:
+ PostFilterParameterInt(const QString& name, int offset, int value, int min, int max, QWidget* parent);
+ ~PostFilterParameterInt() {};
+
+ void setValue( const QString &value )
+ { int i = value.toInt(); m_numInput->setValue(i); slotIntValue(i); }
+ QString getValue()
+ { QString s; s.sprintf("%d", m_numInput->value()); return s; }
+ QWidget *getWidget() { return m_numInput; }
+
+signals:
+ void signalIntValue( int, int );
+
+public slots:
+ void slotIntValue(int val) { emit signalIntValue(m_offset, val); }
+
+private:
+ KIntNumInput* m_numInput;
+};
+
+
+class PostFilterParameterDouble : public PostFilterParameter
+{
+ Q_OBJECT
+public:
+ PostFilterParameterDouble(const QString& name, int offset, double value, double min, double max, QWidget* parent);
+ ~PostFilterParameterDouble() {};
+
+ void setValue( const QString &value )
+ { double d = value.toDouble(); m_numInput->setValue(d); slotDoubleValue(d); }
+ QString getValue()
+ { QString s; s.sprintf("%lf",m_numInput->value()); return s; }
+ QWidget *getWidget() { return m_numInput; }
+
+signals:
+ void signalDoubleValue(int, double);
+
+public slots:
+ void slotDoubleValue(double val) { emit signalDoubleValue(m_offset, val); }
+
+private:
+ KDoubleNumInput* m_numInput;
+};
+
+
+class PostFilterParameterChar : public PostFilterParameter
+{
+ Q_OBJECT
+public:
+ PostFilterParameterChar(const QString& name, int offset, char *value, int size, QWidget* parent);
+ ~PostFilterParameterChar() {};
+
+ void setValue(const QString &value)
+ { m_charInput->setText(value); slotCharValue(value); }
+ QString getValue() { return m_charInput->text(); }
+ QWidget *getWidget() { return m_charInput; }
+
+signals:
+ void signalCharValue(int, const QString&);
+
+public slots:
+ void slotCharValue(const QString& val) { emit signalCharValue(m_offset, val); }
+
+private:
+ KLineEdit* m_charInput;
+};
+
+
+class PostFilterParameterCombo : public PostFilterParameter
+{
+ Q_OBJECT
+public:
+ PostFilterParameterCombo(const QString& name, int offset, int value, char **enums, QWidget* parent);
+ ~PostFilterParameterCombo() {};
+
+ void setValue(const QString &value) { m_comboBox->setCurrentItem(value); slotIntValue(m_comboBox->currentItem()); }
+ QString getValue() { return m_comboBox->currentText(); }
+ QWidget *getWidget() { return m_comboBox; }
+
+signals:
+ void signalIntValue(int, int);
+
+public slots:
+ void slotIntValue(int val) { emit signalIntValue(m_offset, val); }
+
+private:
+ KComboBox* m_comboBox;
+};
+
+
+class PostFilterParameterBool : public PostFilterParameter
+{
+ Q_OBJECT
+public:
+ PostFilterParameterBool(const QString& name, int offset, bool value, QWidget* parent);
+ ~PostFilterParameterBool() {};
+
+ void setValue(const QString &value)
+ { bool b = (bool)value.toInt(); m_checkBox->setChecked(b); slotBoolValue(b); }
+ QString getValue()
+ { QString s; s.sprintf("%d",(int)m_checkBox->isOn()); return s; }
+ QWidget *getWidget() { return m_checkBox; }
+
+signals:
+ void signalIntValue(int, int);
+
+public slots:
+ void slotBoolValue(bool val) { emit signalIntValue(m_offset, (int)val); }
+
+private:
+ QCheckBox* m_checkBox;
+};
+
+
+class PostFilterHelp : public KDialogBase
+{
+ Q_OBJECT
+public:
+ PostFilterHelp(QWidget *parent=0, const char *name=0, const QString& text = QString::null);
+ ~PostFilterHelp();
+
+private:
+ QTextEdit *m_textEdit;
+};
+
+
+class PostFilter : public QObject
+{
+ Q_OBJECT
+public:
+ PostFilter(const QString& name, xine_t* engine, xine_audio_port_t* audioDriver,
+ xine_video_port_t* videoDriver, QWidget *parent);
+ ~PostFilter();
+
+ xine_post_in_t* getInput() const;
+ xine_post_out_t* getOutput() const;
+ void setConfig(const QString &);
+ QString getConfig();
+
+
+signals:
+ void signalDeleteMe( PostFilter* me );
+
+
+private slots:
+ void slotDeletePressed() { emit signalDeleteMe(this); }
+ void slotApplyIntValue(int offset, int val);
+ void slotApplyDoubleValue(int offset, double val);
+ void slotApplyCharValue(int offset, const QString& val);
+ void slotHelpPressed();
+
+private:
+ xine_t* m_xineEngine;
+ xine_post_t* m_xinePost;
+ xine_post_api_t* m_xinePostAPI;
+ xine_post_api_descr_t* m_xinePostDescr;
+ xine_post_api_parameter_t* m_xinePostParameter;
+ char* m_data;
+
+ QGroupBox* m_groupBox;
+ QString m_filterName;
+
+ QPtrList<PostFilterParameter> m_parameterList;
+};
+
+#endif /* POSTFILTER_H */
diff --git a/kaffeine/src/player-parts/xine-part/screenshotpreview.cpp b/kaffeine/src/player-parts/xine-part/screenshotpreview.cpp
new file mode 100644
index 0000000..300ff83
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/screenshotpreview.cpp
@@ -0,0 +1,70 @@
+/*
+ * screenshotpreview.cpp
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <kglobalsettings.h>
+
+#include <qpainter.h>
+#include <qwidget.h>
+#include <qimage.h>
+
+#include "screenshotpreview.h"
+#include "screenshotpreview.moc"
+
+
+ScreenshotPreview::ScreenshotPreview(const QImage& img, QWidget *parent, const char *name )
+ : KPreviewWidgetBase(parent,name)
+{
+ setMinimumWidth(200);
+ m_previewImg = img.copy(); /* deep copy */
+}
+
+ScreenshotPreview::~ScreenshotPreview()
+{
+}
+
+void ScreenshotPreview::showPreview(const KURL&) /* reimplemented to do nothing */
+{
+}
+
+void ScreenshotPreview::clearPreview() /* reimplemented to do nothing */
+{
+}
+
+/* show preview picture */
+
+void ScreenshotPreview::paintEvent(QPaintEvent*)
+{
+ int imgHeight, posy;
+
+ imgHeight = (int)((double) m_previewImg.height() / m_previewImg.width() * (width()-5));
+ posy = (height() - imgHeight) / 2;
+
+ QString info = QString::number(m_previewImg.width()) + "x" + QString::number(m_previewImg.height());
+
+ QFont font = KGlobalSettings::generalFont();
+ font.setPointSize(10);
+ QFontMetrics met(font);
+
+ QPainter painter(this);
+ painter.drawImage(QRect(5, posy, width(), imgHeight), m_previewImg);
+
+ painter.setFont(font);
+ painter.drawText((width()-met.width(info))/2, posy + imgHeight + 20, info);
+}
diff --git a/kaffeine/src/player-parts/xine-part/screenshotpreview.h b/kaffeine/src/player-parts/xine-part/screenshotpreview.h
new file mode 100644
index 0000000..d3a62de
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/screenshotpreview.h
@@ -0,0 +1,52 @@
+/*
+ * screenshotpreview.h
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 SCREENSHOTPREVIEW_H
+#define SCREENSHOTPREVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kpreviewwidgetbase.h>
+
+class QImage;
+class QWidget;
+
+class ScreenshotPreview : public KPreviewWidgetBase
+{
+ Q_OBJECT
+public:
+ ScreenshotPreview(const QImage& img, QWidget *parent=0, const char *name=0);
+ ~ScreenshotPreview();
+
+public slots:
+ virtual void showPreview(const KURL&);
+ virtual void clearPreview();
+
+protected:
+ virtual void paintEvent(QPaintEvent*);
+
+private:
+ QImage m_previewImg;
+
+};
+
+#endif /* SCREENSHOTPREVIEW_H */
diff --git a/kaffeine/src/player-parts/xine-part/videosettings.cpp b/kaffeine/src/player-parts/xine-part/videosettings.cpp
new file mode 100644
index 0000000..e552df7
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/videosettings.cpp
@@ -0,0 +1,129 @@
+/*
+ * videosettings.cpp
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <klocale.h>
+
+#include <qslider.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qnamespace.h>
+#include <qgroupbox.h>
+
+#include "videosettings.h"
+#include "videosettings.moc"
+
+
+VideoSettings::VideoSettings(int hue, int sat, int contrast, int bright,
+ int avOffset, int spuOffset, QWidget *parent, const char *name)
+ : KDialogBase(KDialogBase::Plain, i18n("Video Settings"), KDialogBase::Default | KDialogBase::Close, KDialogBase::Close, parent, name, false)
+{
+ reparent(parent, pos(), false);
+ setInitialSize(QSize(450,250), true);
+ QWidget* page = plainPage();
+
+ QVBoxLayout* b = new QVBoxLayout(page);
+
+ QGroupBox *videoGroup = new QGroupBox(QString::null, page);
+ b->addWidget(videoGroup);
+
+ QGridLayout* videoGrid = new QGridLayout(videoGroup, 6, 2);
+ videoGrid->setSpacing(5);
+ videoGrid->setMargin(10);
+
+ QLabel* hueText = new QLabel(i18n("Hue"), videoGroup);
+ hueText->setAlignment(AlignRight);
+ m_hueSlider = new QSlider(Qt::Horizontal, videoGroup);
+ m_hueSlider->setRange(0, 65535);
+ m_hueSlider->setSteps(10, 1000);
+ m_hueSlider->setValue(hue);
+ connect(m_hueSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewHue(int)));
+ videoGrid->addWidget(hueText, 0, 0);
+ videoGrid->addWidget(m_hueSlider, 0, 1);
+
+ QLabel* satText = new QLabel(i18n("Saturation"), videoGroup);
+ satText->setAlignment(AlignRight);
+ m_satSlider = new QSlider(Qt::Horizontal, videoGroup);
+ m_satSlider->setRange(0, 65535);
+ m_satSlider->setSteps(10, 1000);
+ m_satSlider->setValue(sat);
+ connect(m_satSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewSaturation(int)));
+ videoGrid->addWidget(satText, 1, 0);
+ videoGrid->addWidget(m_satSlider, 1, 1);
+
+ QLabel* contrastText = new QLabel(i18n("Contrast"), videoGroup);
+ contrastText->setAlignment(AlignRight);
+ m_contrastSlider = new QSlider(Qt::Horizontal, videoGroup);
+ m_contrastSlider->setRange(0, 65535);
+ m_contrastSlider->setSteps(10, 1000);
+ m_contrastSlider->setValue(contrast);
+ connect(m_contrastSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewContrast(int)));
+ videoGrid->addWidget(contrastText, 2, 0);
+ videoGrid->addWidget(m_contrastSlider, 2, 1);
+
+ QLabel* brightText = new QLabel(i18n("Brightness"), videoGroup);
+ brightText->setAlignment(AlignRight);
+ m_brightSlider = new QSlider(Qt::Horizontal, videoGroup);
+ m_brightSlider->setRange(0, 65535);
+ m_brightSlider->setSteps(10, 1000);
+ m_brightSlider->setValue(bright);
+ connect(m_brightSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewBrightness(int)));
+ videoGrid->addWidget(brightText, 3, 0);
+ videoGrid->addWidget(m_brightSlider, 3, 1);
+
+ QLabel* avOffsetText = new QLabel(i18n("Audio/Video Offset"), videoGroup);
+ avOffsetText->setAlignment(AlignRight);
+ m_avOffsetSlider = new QSlider(Qt::Horizontal, videoGroup);
+ m_avOffsetSlider->setRange(-90000, 90000); // +/- 1 sec
+ m_avOffsetSlider->setSteps(100, 10000);
+ m_avOffsetSlider->setValue(avOffset);
+ connect(m_avOffsetSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewAVOffset(int)));
+ videoGrid->addWidget(avOffsetText, 4, 0);
+ videoGrid->addWidget(m_avOffsetSlider, 4, 1);
+
+ QLabel* spuOffsetText = new QLabel(i18n("Subtitle Offset"), videoGroup);
+ spuOffsetText->setAlignment(AlignRight);
+ m_spuOffsetSlider = new QSlider(Qt::Horizontal, videoGroup);
+ m_spuOffsetSlider->setRange(-90000, 90000); // +/- 1 sec
+ m_spuOffsetSlider->setSteps(100, 10000);
+ m_spuOffsetSlider->setValue(spuOffset);
+ connect(m_spuOffsetSlider, SIGNAL(valueChanged(int)), this, SIGNAL(signalNewSpuOffset(int)));
+ videoGrid->addWidget(spuOffsetText, 5, 0);
+ videoGrid->addWidget(m_spuOffsetSlider, 5, 1);
+
+ connect(this, SIGNAL(defaultClicked()), this, SLOT(slotSetDefaultValues()));
+}
+
+
+
+VideoSettings::~VideoSettings()
+{
+
+}
+
+
+void VideoSettings::slotSetDefaultValues()
+{
+ m_hueSlider->setValue(32768);
+ m_satSlider->setValue(32768);
+ m_contrastSlider->setValue(32768);
+ m_brightSlider->setValue(32768);
+ m_avOffsetSlider->setValue(0);
+ m_spuOffsetSlider->setValue(0);
+}
diff --git a/kaffeine/src/player-parts/xine-part/videosettings.h b/kaffeine/src/player-parts/xine-part/videosettings.h
new file mode 100644
index 0000000..7641bf8
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/videosettings.h
@@ -0,0 +1,65 @@
+/*
+ * videosettings.h
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 VIDEOSETTINGS_H
+#define VIDEOSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+
+class QSlider;
+
+class VideoSettings : public KDialogBase
+{
+
+ Q_OBJECT
+
+public:
+ VideoSettings(int hue, int sat, int contrast, int bright, int avOffset,
+ int spuOffset, QWidget *parent=0, const char *name=0);
+ ~VideoSettings();
+
+signals:
+ void signalNewHue(int);
+ void signalNewSaturation(int);
+ void signalNewContrast(int);
+ void signalNewBrightness(int);
+ void signalNewAVOffset(int);
+ void signalNewSpuOffset(int);
+
+private slots:
+
+ void slotSetDefaultValues();
+
+
+private:
+ QSlider* m_hueSlider;
+ QSlider* m_satSlider;
+ QSlider* m_contrastSlider;
+ QSlider* m_brightSlider;
+ QSlider* m_avOffsetSlider;
+ QSlider* m_spuOffsetSlider;
+
+};
+
+#endif /* VIDEOSETTINGS_H */
diff --git a/kaffeine/src/player-parts/xine-part/xine_part.cpp b/kaffeine/src/player-parts/xine-part/xine_part.cpp
new file mode 100644
index 0000000..920a2ac
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/xine_part.cpp
@@ -0,0 +1,2111 @@
+/*
+ * xine_part.cpp
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 "xine_part.h"
+
+#include <kapplication.h>
+#include <kinstance.h>
+#include <kiconloader.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <kxmlguifactory.h>
+#include <kpopupmenu.h>
+#include <kparts/genericfactory.h>
+#include <kprogress.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <dcopclient.h>
+#include <kprocess.h>
+#include <kprotocolinfo.h>
+#include <ktoolbar.h>
+
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qimage.h>
+#include <qfontmetrics.h>
+#include <qregexp.h>
+#include <qtooltip.h>
+#include <qdatetimeedit.h>
+
+#include <xine/xineutils.h>
+
+#include "mrl.h"
+#include "kxinewidget.h"
+#include "videosettings.h"
+#include "equalizer.h"
+#include "deinterlacequality.h"
+#include "filterdialog.h"
+#include "screenshotpreview.h"
+#include "xineconfig.h"
+#include "positionslider.h"
+#include "playlistimport.h"
+#include "version.h"
+
+typedef KParts::GenericFactory<XinePart> XinePartFactory;
+K_EXPORT_COMPONENT_FACTORY (libxinepart, XinePartFactory)
+
+
+XinePart::XinePart(QWidget* parentWidget, const char* widgetName, QObject* parent, const char* name, const QStringList& args)
+ : DCOPObject("XinePartIface"),
+ KaffeinePart(parent, name ? name : "XinePart"),
+ m_current(0), m_xine(NULL), m_pictureSettings(NULL), m_deinterlacerConfigWidget(NULL),
+ m_filterDialog(NULL), m_embeddedContext(NULL)
+{
+ kdDebug() << "XinePart: Creating new XinePart..." << endl;
+
+ /*
+ * Parsing parameter given by kaffeine (audiodriver, videodriver, verbose)
+ * or parameters of <embed>...</embed>
+ *
+ * format: param="value"
+ */
+ QString audioDriver = QString::null;
+ QString videoDriver = QString::null;
+ bool verbose = false;
+ TimeShiftFilename = "";
+
+ for (uint i=0; i<args.count(); i++)
+ {
+ kdDebug() << "XinePart: Argument: " << args[i] << endl;
+ if (args[i].left(11).lower() == "audiodriver")
+ {
+ audioDriver = args[i].section( '"',1, 1 );
+ kdDebug() << "XinePart: Found audiodriver parameter, value: " << audioDriver << endl;
+
+ }
+ if (args[i].left(11).lower() == "videodriver")
+ {
+ videoDriver = args[i].section( '"',1, 1 );
+ kdDebug() << "XinePart: Found videodriver parameter, value: " << videoDriver << endl;
+ }
+ if (args[i].left(7).lower() == "verbose")
+ {
+ if (args[i].section( '"', 1, 1 ).lower() == "true")
+ {
+ kdDebug() << "XinePart: Found parameter verbose, set xine engine verbosity to max..." << endl;
+ verbose = true;
+ }
+ }
+ }
+
+ // we need an instance
+ setInstance(XinePartFactory::instance());
+
+ // be careful - we may be embedded
+ QString configPath = locate("data", "kaffeine/xine-config");
+ QString logoPath = locate("data", "kaffeine/logo");
+
+ kdDebug() << "XinePart: Using xine-config file: " << configPath << endl;
+
+ m_xine = new KXineWidget(parentWidget, widgetName, configPath, logoPath,
+ audioDriver, videoDriver, /* start xine manual*/true, verbose);
+ connect(m_xine, SIGNAL(signalXineFatal(const QString&)), this, SIGNAL(canceled(const QString&)));
+ connect(m_xine, SIGNAL(stopDvb()), this, SIGNAL(stopDvb()));
+ connect(m_xine, SIGNAL(signalDvbOSDHidden()), this, SIGNAL(dvbOSDHide()));
+ m_xine->setFocusPolicy(QWidget::ClickFocus);
+ setWidget(m_xine);
+
+ // set our XML-UI resource file
+ setXMLFile("xine_part.rc");
+ initActions();
+ initConnections();
+
+ QTimer::singleShot(0, this, SLOT(slotDisableAllActions()));
+ m_oldPosition = m_xine->mapToGlobal(QPoint(0,0));
+ m_posCheckTimer.start(333);
+}
+
+XinePart::~XinePart()
+{
+ kdDebug() << "XinePart: destructor" << endl;
+ kdDebug() << "XinePart destructor: calling saveConfig()" << endl;
+ saveConfig();
+ if (m_embeddedContext)
+ delete m_embeddedContext;
+}
+
+KAboutData *XinePart::createAboutData()
+{
+ KAboutData* aboutData = new KAboutData( "kaffeine", I18N_NOOP("XinePart"),
+ KAFFEINE_VERSION, I18N_NOOP("A xine based player part for Kaffeine."),
+ KAboutData::License_GPL,
+ "(c) 2003-2004, Jürgen Kofler.", 0, "http://kaffeine.sourceforge.net");
+ aboutData->addAuthor("Jürgen Kofler.",0, "kaffeine@gmx.net");
+
+ return aboutData;
+}
+
+bool XinePart::openURL(const MRL& mrl)
+{
+ kdDebug() << "XinePart::openURL(): " << mrl.url() << endl;
+
+ // if (!mrl.kurl().isValid())
+ // return false;
+
+ m_mrl = mrl;
+ m_playlist.clear();
+ m_current = 0;
+ bool playlist = false;
+
+ QString ext = m_mrl.kurl().fileName();
+ ext = ext.remove( 0 , ext.findRev('.')+1 ).lower();
+
+ if (!m_mrl.mime().isNull())
+ {
+ KMimeType::Ptr mime = KMimeType::findByURL(m_mrl.kurl().path());
+ m_mrl.setMime(mime->name());
+ }
+
+ /* is m_mrl a playlist? */
+ if ((m_mrl.mime() == "text/plain") || (m_mrl.mime() == "text/xml") || (m_mrl.mime() == "application/x-kaffeine")
+ || (m_mrl.mime() == "audio/x-scpls") || (m_mrl.mime() == "audio/x-mpegurl") || (m_mrl.mime() == "audio/mpegurl")
+ || (m_mrl.mime() == "application/smil")
+ || (ext == "asx") || (ext == "asf") || (ext == "wvx") || (ext == "wax")) /* windows meta files */
+ {
+ kdDebug() << "XinePart: Check for kaffeine/noatun/m3u/pls/asx playlist\n";
+ QString localFile;
+ if (KIO::NetAccess::download(m_mrl.kurl(), localFile, widget()))
+ {
+ QFile file(localFile);
+ file.open(IO_ReadOnly);
+ QTextStream stream(&file);
+ QString firstLine = stream.readLine();
+ QString secondLine = stream.readLine();
+ file.close();
+
+ if (secondLine.contains("kaffeine", false))
+ {
+ kdDebug() << "KafeinePart: Try loading kaffeine playlist\n";
+ playlist = PlaylistImport::kaffeine(localFile, m_playlist);
+ }
+ if (secondLine.contains("noatun", false))
+ {
+ kdDebug() << "XinePart: Try loading noatun playlist\n";
+ playlist = PlaylistImport::noatun(localFile, m_playlist);
+ }
+ if (firstLine.contains("asx", false))
+ {
+ kdDebug() << "XinePart: Try loading asx playlist\n";
+ playlist = PlaylistImport::asx(localFile, m_playlist);
+ }
+ if (firstLine.contains("smil", false))
+ {
+ kdDebug() << "XinePart: Try loading smil playlist\n";
+ if (KMessageBox::warningYesNo(0, i18n("SMIL (Synchronized Multimedia Integration Language) support is rudimentary!\nXinePart can now try to playback contained video sources without any layout. Proceed?"), QString::null, KStdGuiItem::yes(), KStdGuiItem::no(), "smil_warning") == KMessageBox::Yes)
+ {
+ if (!PlaylistImport::smil(localFile, m_mrl, m_playlist))
+ {
+ emit signalTrackFinished();
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+ if (firstLine.contains("[playlist]", false))
+ {
+ kdDebug() << "XinePart: Try loading pls playlist\n";
+ playlist = PlaylistImport::pls(localFile, m_playlist);
+ }
+ if (ext == "m3u") //indentify by extension
+ {
+ kdDebug() << "XinePart: Try loading m3u playlist\n";
+ playlist = PlaylistImport::m3u(localFile, m_playlist);
+ }
+ }
+ else
+ kdError() << "XinePart: " << KIO::NetAccess::lastErrorString() << endl;
+ }
+ /* check for ram playlist */
+ if ( (ext == "ra") || (ext == "rm") || (ext == "ram") || (ext == "lsc") || (ext == "pl") )
+ {
+ kdDebug() << "XinePart: Try loading ram playlist\n";
+ playlist = PlaylistImport::ram(m_mrl, m_playlist, widget());
+ }
+ /* urls from audiocd kio-slave */
+ if (m_mrl.kurl().protocol() == "audiocd")
+ {
+ QString audioTrack = QString::number(m_mrl.kurl().fileName().remove( QRegExp("\\D" ) ).left(2).toUInt());
+ m_mrl = MRL(audioTrack.prepend( "cdda:/" ));
+ }
+
+ if (!playlist)
+ {
+ kdDebug() << "XinePart: Got single track\n";
+ m_playlist.append(m_mrl);
+ }
+
+ slotPlay(true);
+
+ return true;
+}
+
+bool XinePart::closeURL()
+{
+ kdDebug() << "XinePart::closeURL()" << endl;
+ // m_playlist.clear();
+ // m_mrl = MRL();
+ slotStop();
+
+ return true;
+}
+
+void XinePart::slotPlay(bool forcePlay)
+{
+ kdDebug() << "XinePart::slotPlay()" << endl;
+
+ m_pauseButton->setChecked(false);
+ if (m_xine->isPlaying())
+ {
+ if ( (m_xine->getSpeed() != KXineWidget::Normal) && !forcePlay )
+ {
+ m_xine->slotSpeedNormal();
+ slotEnablePlayActions();
+ return;
+ }
+ else
+ emit stopDvb();
+ }
+
+ if (m_playlist.count() == 0)
+ {
+ emit signalRequestCurrentTrack();
+ return;
+ }
+
+ MRL mrl = m_playlist[m_current];
+
+ /*
+ * is protocol supported by xine or not known by KIO?
+ */
+ if ((QString(SUPPORTED_PROTOCOLS).contains(mrl.kurl().protocol()))
+ || (!KProtocolInfo::isKnownProtocol(mrl.kurl())))
+ {
+ QString sub;
+ if ((!mrl.subtitleFiles().isEmpty()) && (mrl.currentSubtitle() > -1))
+ sub = QString("#subtitle:%1").arg(mrl.subtitleFiles()[mrl.currentSubtitle()]);
+
+ m_xine->clearQueue();
+ m_xine->appendToQueue(mrl.url() + sub );
+ if (!m_xine->isXineReady())
+ {
+ if (!m_xine->initXine())
+ return;
+ }
+ else
+ QTimer::singleShot(0, m_xine, SLOT(slotPlay()));
+ }
+ else
+ {
+ kdDebug() << "XinePart: Protocol not supported by xine, try to download it..." << endl;
+
+ QString localFile;
+ if (KIO::NetAccess::download(mrl.kurl(), localFile, widget()))
+ {
+ m_xine->clearQueue();
+ m_xine->appendToQueue(localFile);
+ if (!m_xine->isXineReady())
+ {
+ if (!m_xine->initXine())
+ return;
+ }
+ else
+ QTimer::singleShot(0, m_xine, SLOT(slotPlay()));
+ }
+ else
+ kdError() << "XinePart: " << KIO::NetAccess::lastErrorString() << endl;
+ }
+}
+
+void XinePart::slotStop()
+{
+ if (!m_xine->isXineReady())
+ return;
+
+ emit stopDvb();
+
+ /* if we play a DVD we cache current title and chapter */
+ if (m_playlist[m_current].url().startsWith("dvd:/"))
+ {
+ uint title = m_xine->currentDVDTitleNumber();
+ uint chapter = m_xine->currentDVDChapterNumber();
+
+ m_playlist[m_current] = MRL("dvd://" + QString::number(title) + "." + QString::number(chapter));
+ }
+
+ QTimer::singleShot(0, m_xine, SLOT(slotStop()));
+ stateChanged("not_playing");
+ m_pauseButton->setChecked(false);
+ m_playTime->setText("0:00:00");
+ emit setWindowCaption("");
+}
+
+void XinePart::slotNext()
+{
+ if (m_xine->hasChapters())
+ {
+ m_xine->playNextChapter();
+ return;
+ }
+
+ if ((m_playlist.count() > 0) && (m_current < m_playlist.count()-1))
+ {
+ m_current++;
+ slotPlay();
+ }
+ else
+ {
+ emit signalRequestNextTrack();
+ }
+}
+
+void XinePart::slotPrevious()
+{
+ if (m_xine->hasChapters())
+ {
+ m_xine->playPreviousChapter();
+ return;
+ }
+
+ if (m_current > 0)
+ {
+ m_current--;
+ slotPlay();
+ }
+ else
+ {
+ emit signalRequestPreviousTrack();
+ }
+}
+
+void XinePart::requestForOSD( const QString &text, int duration, int priority )
+{
+ m_xine->showOSDMessage( text, duration, priority );
+}
+
+void XinePart::setDvbCurrentNext( const QString &channelName, const QStringList &list )
+{
+ m_xine->setDvbCurrentNext( channelName, list );
+}
+
+void XinePart::slotDvbOpen( const QString &filename, const QString &chanName, int haveVideo )
+{
+ if (!m_xine->isXineReady())
+ if (!m_xine->initXine())
+ return;
+ m_playlist.clear();
+ m_xine->setDvb( filename, chanName, haveVideo );
+ QTimer::singleShot(0, m_xine, SLOT(openDvb()));
+ //m_xine->openDvb( filename, chanName, haveVideo );
+}
+
+void XinePart::getTimeShiftFilename( const QString &filename )
+{
+ TimeShiftFilename = filename;
+ m_xine->TimeShiftFilename = TimeShiftFilename;
+}
+
+void XinePart::slotTogglePause( bool pauseLive )
+{
+ kdDebug() << "slotSpeedPause()" << endl;
+ if (!m_xine->isXineReady())
+ return;
+
+ if (m_xine->getSpeed() == KXineWidget::Pause)
+ {
+ m_xine->slotSpeedNormal();
+ slotEnablePlayActions();
+ m_pauseButton->setChecked(false);
+ }
+ else
+ {
+ if ( pauseLive )
+ emit playerPause();
+ m_xine->slotSpeedPause();
+ // kdDebug() << "XinePart: Set state to paused" << endl;
+ stateChanged("paused");
+ m_pauseButton->setChecked(true);
+ }
+}
+
+void XinePart::speedFaster()
+{
+ slotFastForward();
+}
+
+void XinePart::slotFastForward()
+{
+ if (m_xine->getSpeed() == KXineWidget::Pause)
+ {
+ m_pauseButton->setChecked(false);
+ slotEnablePlayActions();
+ }
+ m_xine->slotSpeedFaster();
+}
+
+void XinePart::speedSlower()
+{
+ slotSlowMotion();
+}
+
+void XinePart::slotSlowMotion()
+{
+ if (m_xine->getSpeed() == KXineWidget::Pause)
+ {
+ m_pauseButton->setChecked(false);
+ slotEnablePlayActions();
+ }
+
+ m_xine->slotSpeedSlower();
+}
+
+void XinePart::slotMute()
+{
+ if (!m_xine->isXineReady())
+ return;
+
+ m_xine->slotToggleMute();
+}
+
+void XinePart::slotVolumeUp()
+{
+ int newVol = volume() + 5;
+ if (newVol >100)
+ newVol = 100;
+ slotSetVolume(newVol);
+}
+
+void XinePart::slotVolumeDown()
+{
+ int newVol = volume() - 5;
+ if (newVol <0)
+ newVol = 0;
+ slotSetVolume(newVol);
+}
+
+void XinePart::slotPosPlusSmall()
+{
+ slotJumpIncrement( 20 );
+}
+
+void XinePart::slotPosMinusSmall()
+{
+ slotJumpIncrement( -20 );
+}
+
+void XinePart::slotPosPlusMedium()
+{
+ slotJumpIncrement( 60 );
+}
+
+void XinePart::slotPosMinusMedium()
+{
+ slotJumpIncrement( -60 );
+}
+
+void XinePart::slotPosPlusLarge()
+{
+ slotJumpIncrement( 600 );
+}
+
+void XinePart::slotPosMinusLarge()
+{
+ slotJumpIncrement( -600 );
+}
+
+void XinePart::slotJumpIncrement(int increment)
+{
+ if (!m_xine->isSeekable())
+ return;
+
+ QTime timeNow;
+ QTime projectedTime;
+ QTime startTime;
+
+ if (!m_xine->getLength().isNull())
+ {
+ timeNow = m_xine->getPlaytime();
+ if ( increment < 0 && timeNow.msecsTo(startTime) > increment * 1000 )
+ {
+ m_xine->slotSeekToTime(startTime);
+ }
+ else
+ {
+ projectedTime = timeNow.addSecs(increment);
+ m_xine->slotSeekToTime(projectedTime);
+ }
+ }
+}
+
+void XinePart::slotAdvanceSubTitle()
+{
+ int spuOffset;
+ m_xine->getspuOffset(spuOffset);
+ m_xine->slotSetSpuOffset(spuOffset+45000);
+}
+
+void XinePart::slotDelaySubTitle()
+{
+ int spuOffset;
+ m_xine->getspuOffset(spuOffset);
+ m_xine->slotSetSpuOffset(spuOffset-45000);
+}
+
+void XinePart::slotSaveStream()
+{
+ if (m_mrl.isEmpty())
+ return;
+
+ QString saveDir = m_xine->getStreamSaveDir();
+
+ KURL kurl = KFileDialog::getSaveURL(saveDir + "/" + m_playlist[m_current].kurl().fileName(), QString::null, 0, i18n("Save Stream As"));
+ if (!kurl.isValid())
+ return;
+
+ if ( saveDir != kurl.directory() )
+ m_xine->setStreamSaveDir(kurl.directory());
+
+ m_xine->clearQueue();
+ m_xine->appendToQueue(m_playlist[m_current].url() + "#save:" + kurl.path());
+ QTimer::singleShot(0, m_xine, SLOT(slotPlay()));
+ m_pauseButton->setChecked(false);
+}
+
+void XinePart::slotSetSubtitle(int channel)
+{
+ if (m_playlist[m_current].subtitleFiles().isEmpty())
+ {
+ m_xine->slotSetSubtitleChannel(channel);
+ }
+ else
+ {
+ m_playlist[m_current].setCurrentSubtitle(channel - 1);
+ emit signalNewMeta(m_mrl);
+ m_xine->savePosition(m_xine->getPosition()-200);
+ slotPlay(true); //force load of new subtitle
+ }
+ emit setStatusBarText(i18n("Subtitle") + ": " + m_subtitles->items()[channel]);
+ m_xine->showOSDMessage(i18n("Subtitle") + ": " + m_subtitles->items()[channel], DEFAULT_OSD_DURATION);
+}
+
+void XinePart::slotAddSubtitle(void)
+{
+ QString subtitleURL = KFileDialog::getOpenURL(m_mrl.kurl().directory(),
+ i18n("*.smi *.srt *.sub *.txt *.ssa *.asc|Subtitle Files\n*.*|All Files"),
+ 0, i18n("Select Subtitle File")).path();
+
+ if (!(subtitleURL.isEmpty()))
+ {
+ if (!m_playlist[m_current].subtitleFiles().contains(subtitleURL))
+ {
+ m_playlist[m_current].addSubtitleFile(subtitleURL);
+ }
+
+ int subchannel = m_playlist[m_current].subtitleFiles().size() - 1;
+ m_playlist[m_current].setCurrentSubtitle(subchannel);
+ emit signalNewMeta(m_mrl);
+ m_xine->savePosition(m_xine->getPosition()-200);
+ slotPlay(true); //force load of new subtitle
+
+ emit setStatusBarText(i18n("Subtitle") + ": " + m_subtitles->items()[subchannel]);
+ m_xine->showOSDMessage(i18n("Subtitle") + ": " + m_subtitles->items()[subchannel], DEFAULT_OSD_DURATION);
+ }
+
+}
+
+void XinePart::slotSetAudioChannel(int channel)
+{
+ m_xine->slotSetAudioChannel(channel);
+ emit setStatusBarText(i18n("Audiochannel") + ": " + m_audioChannels->items()[channel]);
+ m_xine->showOSDMessage(i18n("Audiochannel") + ": " + m_audioChannels->items()[channel], DEFAULT_OSD_DURATION);
+}
+
+void XinePart::slotSetDVDTitle(const QString& titleStr)
+{
+ bool ok;
+ uint title = titleStr.toInt(&ok);
+ if (ok && title > 0 && title <= m_xine->getDVDTitleCount())
+ {
+ KURL url = m_mrl.kurl();
+ url.addPath(QString::number(title));
+ m_playlist[m_current] = MRL(url);
+ slotPlay(true);
+ }
+}
+
+void XinePart::slotSetDVDChapter(const QString& chapterStr)
+{
+ bool ok;
+ uint chapter = chapterStr.toInt(&ok);
+ if (ok)
+ setDVDChapter(chapter);
+}
+
+void XinePart::slotSetDVDAngle(const QString& angleStr)
+{
+ bool ok;
+ uint angle = angleStr.toInt(&ok);
+ if (ok && angle > 0 && angle <= m_xine->getDVDAngleCount())
+ {
+ uint title = m_xine->currentDVDTitleNumber();
+ uint chapter = m_xine->currentDVDChapterNumber();
+ KURL url = m_mrl.kurl();
+
+ url.addPath(QString::number(title) + "." + QString::number(chapter) + "." + QString::number(angle));
+ m_playlist[m_current] = MRL(url);
+ slotPlay(true);
+ }
+}
+
+void XinePart::setDVDChapter(uint chapter)
+{
+ if (chapter > 0 && chapter <= m_xine->getDVDChapterCount())
+ {
+ uint title = m_xine->currentDVDTitleNumber();
+ KURL url = m_mrl.kurl();
+
+ url.addPath(QString::number(title) + "." + QString::number(chapter));
+ m_playlist[m_current] = MRL(url);
+ slotPlay(true);
+ }
+}
+
+void XinePart::slotChannelInfo(const QStringList& audio, const QStringList& sub, int currentAudio, int currentSub)
+{
+ kdDebug() << "XinePart: slotChannelInfo: currentAudio="<<currentAudio<< " currentSub="<<currentSub<<"\n";
+ m_audioChannels->setItems(audio);
+ m_audioChannels->setCurrentItem(currentAudio+1);
+
+ if (m_playlist[m_current].subtitleFiles().isEmpty())
+ {
+ m_subtitles->setItems(sub);
+ m_subtitles->setCurrentItem(currentSub+1);
+ }
+ else
+ {
+ QStringList subFiles = m_playlist[m_current].subtitleFiles();
+ QStringList subs(i18n("off"));
+ QString sub;
+ QStringList::ConstIterator end(subFiles.end());
+ for (QStringList::ConstIterator it = subFiles.begin(); it != end; ++it)
+ {
+ sub = (*it);
+ sub = sub.remove(0 , sub.findRev('/')+1);
+ subs.append(sub);
+ }
+ m_subtitles->setItems(subs);
+ m_subtitles->setCurrentItem(m_playlist[m_current].currentSubtitle() + 1);
+ }
+
+ /* if we play a DVD enable and fill menus */
+ if (m_playlist[m_current].url().startsWith("dvd:/"))
+ {
+ QStringList titles;
+ QStringList chapters;
+ QStringList angles;
+ uint titlesCount = m_xine->getDVDTitleCount();
+ uint chaptersCount = m_xine->getDVDChapterCount();
+ uint anglesCount = m_xine->getDVDAngleCount();
+
+ for (uint i = 1; i <= titlesCount; i++)
+ titles.append(QString::number(i));
+ for (uint i = 1; i <= chaptersCount; i++)
+ chapters.append(QString::number(i));
+ for (uint i = 1; i <= anglesCount; i++)
+ angles.append(QString::number(i));
+
+ m_dvdTitles->setItems(titles);
+ m_dvdTitles->setCurrentItem(m_xine->currentDVDTitleNumber() - 1);
+ m_dvdChapters->setItems(chapters);
+ m_dvdChapters->setCurrentItem(m_xine->currentDVDChapterNumber() - 1);
+ m_dvdAngles->setItems(angles);
+ m_dvdAngles->setCurrentItem(m_xine->currentDVDAngleNumber() - 1);
+ stateChanged("dvd_playback");
+ }
+ else
+ {
+ stateChanged("dvd_playback", StateReverse);
+ }
+}
+
+void XinePart::slotNewPosition(int pos, const QTime& playtime)
+{
+ QTime length = m_xine->getLength();
+ QTime calcLength;
+
+ //if (!m_xine->isSeekable() || length.isNull() || length < playtime)
+ if (!m_xine->isSeekable() )
+ {
+ m_position->setPosition(0,false);
+ m_position->setEnabled(false);
+ }
+ else
+ {
+ m_position->setPosition(pos, false);
+ m_position->setEnabled(true);
+ }
+
+ if (m_timerDirection == BACKWARD_TIMER && !length.isNull() && length >= playtime)
+ calcLength = length.addSecs(-playtime.second()-playtime.minute()*60-playtime.hour()*60*60);
+ else
+ calcLength = playtime;
+
+ if (m_timerDirection == BACKWARD_TIMER)
+ m_playTime->setText("-" + calcLength.toString("h:mm:ss"));
+ else
+ m_playTime->setText(calcLength.toString("h:mm:ss"));
+
+ QString timeMessage;
+ if (m_isOsdTimer)
+ {
+ if (m_timerDirection == BACKWARD_TIMER || length.isNull() || length < playtime)
+ {
+ timeMessage = calcLength.toString("h:mm:ss");
+ m_xine->showOSDMessage("-" + timeMessage, 600, OSD_MESSAGE_LOW_PRIORITY);
+ }
+ else
+ {
+ timeMessage = i18n("%1 of %2").arg(calcLength.toString("h:mm:ss")).arg(length.toString("h:mm:ss"));
+ m_xine->showOSDMessage(timeMessage, 600, OSD_MESSAGE_LOW_PRIORITY);
+ }
+ }
+ currentPosition = (playtime.hour()*3600)+(playtime.minute()*60)+playtime.second();
+}
+
+QString XinePart::screenShot()
+{
+ QString filename = QDir::homeDirPath()+"/kaffeinedcopshot.jpg";
+ QImage shot = m_xine->getScreenshot();
+ if ( shot.save( filename, "JPEG" ) )
+ return filename;
+ else
+ return "";
+}
+
+void XinePart::slotScreenshot()
+{
+ QImage shot = m_xine->getScreenshot();
+
+ KFileDialog dlg(":kaffeineMain_Screenshot", i18n("*.png|PNG-File\n*.bmp|BMP-File\n*.xbm|XBM-File"),
+ 0, "save screenshot", true);
+ dlg.setOperationMode(KFileDialog::Saving);
+ dlg.setCaption(i18n("Save Screenshot As"));
+ dlg.setSelection("screenshot.png");
+
+ ScreenshotPreview* prev = new ScreenshotPreview(shot, &dlg);
+ dlg.setPreviewWidget(prev);
+
+ dlg.exec();
+ QString fileName = dlg.selectedFile();
+
+ if (fileName.isEmpty())
+ return;
+
+ QString type = dlg.currentFilter();
+ type = (type.remove(0,2)).upper();
+
+ kdDebug() << "XinePart: Save screenshot as " << type << "\n";
+ if (!shot.save(fileName, type.ascii()))
+ kdError() << "XinePart: Screenshot not saved successfully!" << endl;
+}
+
+void XinePart::slotFilterDialog()
+{
+ if (!m_filterDialog)
+ {
+ m_filterDialog = new FilterDialog(m_xine->getAudioFilterNames(), m_xine->getVideoFilterNames());
+ connect(m_filterDialog, SIGNAL(signalCreateAudioFilter(const QString&, QWidget*)),
+ m_xine, SLOT(slotCreateAudioFilter(const QString&, QWidget*)));
+ connect(m_filterDialog, SIGNAL(signalCreateVideoFilter(const QString&, QWidget*)),
+ m_xine, SLOT(slotCreateVideoFilter(const QString&, QWidget*)));
+ connect(m_filterDialog, SIGNAL(signalRemoveAllAudioFilters()), m_xine, SLOT(slotRemoveAllAudioFilters()));
+ connect(m_filterDialog, SIGNAL(signalRemoveAllVideoFilters()), m_xine, SLOT(slotRemoveAllVideoFilters()));
+ connect(m_filterDialog, SIGNAL(signalUseAudioFilters(bool)), m_xine, SLOT(slotEnableAudioFilters(bool)));
+ connect(m_filterDialog, SIGNAL(signalUseVideoFilters(bool)), m_xine, SLOT(slotEnableVideoFilters(bool)));
+ }
+ m_filterDialog->show();
+ m_filterDialog->raise();
+}
+
+void XinePart::slotDeinterlaceQuality()
+{
+ if (!m_deinterlacerConfigWidget)
+ return;
+ DeinterlaceQuality* deinterlaceQuality = new DeinterlaceQuality((QWidget*)m_deinterlacerConfigWidget);
+ deinterlaceQuality->setQuality(m_lastDeinterlaceQuality);
+ connect(deinterlaceQuality, SIGNAL(signalSetDeinterlaceConfig(const QString&)),
+ m_xine, SLOT(slotSetDeinterlaceConfig(const QString&)));
+
+ deinterlaceQuality->exec();
+
+ m_lastDeinterlaceQuality = deinterlaceQuality->getQuality();
+ m_lastDeinterlacerConfig = m_xine->getDeinterlaceConfig();
+ delete deinterlaceQuality;
+}
+
+void XinePart::slotSetHue( int i )
+{
+ m_hue = i;
+ if ( i==-1 )
+ return;
+ m_xine->slotSetHue( i );
+}
+
+void XinePart::slotSetSaturation( int i )
+{
+ m_saturation = i;
+ if ( i==-1 )
+ return;
+ m_xine->slotSetSaturation( i );
+}
+
+void XinePart::slotSetContrast( int i )
+{
+ m_contrast = i;
+ if ( i==-1 )
+ return;
+ m_xine->slotSetContrast( i );
+}
+
+void XinePart::slotSetBrightness( int i )
+{
+ m_brightness = i;
+ if ( i==-1 )
+ return;
+ m_xine->slotSetBrightness( i );
+}
+
+void XinePart::slotPictureSettings()
+{
+ if (!m_pictureSettings)
+ {
+ int hue, sat, contrast, bright, avOffset, spuOffset;
+ m_xine->getVideoSettings(hue, sat, contrast, bright, avOffset, spuOffset);
+ m_pictureSettings = new VideoSettings(hue, sat, contrast, bright, avOffset, spuOffset);
+ connect(m_pictureSettings, SIGNAL(signalNewHue(int)), this, SLOT(slotSetHue(int)));
+ connect(m_pictureSettings, SIGNAL(signalNewSaturation(int)), this, SLOT(slotSetSaturation(int)));
+ connect(m_pictureSettings, SIGNAL(signalNewContrast(int)), this, SLOT(slotSetContrast(int)));
+ connect(m_pictureSettings, SIGNAL(signalNewBrightness(int)), this, SLOT(slotSetBrightness(int)));
+ connect(m_pictureSettings, SIGNAL(signalNewAVOffset(int)), m_xine, SLOT(slotSetAVOffset(int)));
+ connect(m_pictureSettings, SIGNAL(signalNewSpuOffset(int)), m_xine, SLOT(slotSetSpuOffset(int)));
+ }
+ m_pictureSettings->show();
+ m_pictureSettings->raise();
+}
+
+void XinePart::slotEqualizer()
+{
+ m_equalizer->show();
+ m_equalizer->raise();
+}
+
+void XinePart::slotToggleBroadcastSend()
+{
+ bool ok = false;
+
+ if (m_broadcastSend->isChecked())
+ {
+ m_broadcastPort = (uint)KInputDialog::getInteger( QString::null, i18n("Broadcasting port:"), m_broadcastPort, 0, 1000000, 1, &ok);
+ if (!ok)
+ {
+ m_broadcastSend->setChecked(false);
+ return;
+ }
+ m_xine->setBroadcasterPort(m_broadcastPort);
+ }
+ else
+ {
+ m_xine->setBroadcasterPort(0); /* disable */
+ }
+}
+
+void XinePart::slotBroadcastReceive()
+{
+ if (!m_xine->isXineReady())
+ {
+ if (!m_xine->initXine())
+ return;
+ }
+
+ KDialogBase* dialog = new KDialogBase(0, "configmaster", true, i18n("Configure Receive Broadcast Stream"), KDialogBase::Ok|KDialogBase::Cancel);
+ QVBox* page = dialog->makeVBoxMainWidget();
+ new QLabel(i18n("Sender address:"), page);
+ KLineEdit* address = new KLineEdit(m_broadcastAddress, page);
+ new QLabel(i18n("Port:"), page);
+ QSpinBox* port = new QSpinBox(0, 1000000, 1, page);
+ port->setValue(m_broadcastPort);
+
+ if (dialog->exec() == KDialogBase::Accepted)
+ {
+ m_broadcastPort = port->value();
+ m_broadcastAddress = address->text();
+ openURL(MRL(QString("slave://") + m_broadcastAddress + ":" + QString::number(m_broadcastPort)));
+ }
+ delete dialog;
+}
+
+void XinePart::slotJumpToPosition()
+{
+ if (!m_xine->isSeekable())
+ return;
+
+ KDialogBase* dialog = new KDialogBase( 0, "configmaster", true, QString::null, KDialogBase::Ok|KDialogBase::Cancel );
+ QVBox* page = dialog->makeVBoxMainWidget();
+ page->setMargin(5);
+ page->setSpacing(5);
+ dialog->disableResize();
+ new QLabel(i18n("Jump to position:"), page);
+ QTimeEdit* timeEdit = new QTimeEdit(page);
+ if (!m_xine->getLength().isNull())
+ {
+ timeEdit->setMaxValue(m_xine->getLength());
+ timeEdit->setTime(m_xine->getPlaytime());
+ }
+
+ if (dialog->exec() == KDialogBase::Accepted)
+ {
+ m_xine->slotSeekToTime(timeEdit->time());
+ }
+ delete dialog;
+}
+
+void XinePart::slotButtonTimerPressed()
+{
+ m_osdTimerEnabler.start(500, true); /* Long Click is 500ms */
+}
+
+void XinePart::slotButtonTimerReleased()
+{
+ if (!m_osdTimerEnabler.isActive())
+ return; /* If short click toggle timer Mode*/
+ m_osdTimerEnabler.stop();
+ //kdDebug() << "XinePart: Toggling forward/backward Timer." << endl;
+ QTime length = m_xine->getLength();
+
+ if (!length.isNull()) /* if length not available counting backwards has no meaning */
+ {
+ if (m_timerDirection == FORWARD_TIMER)
+ m_timerDirection = BACKWARD_TIMER;
+ else
+ m_timerDirection = FORWARD_TIMER;
+ slotNewPosition(m_xine->getPosition(),m_xine->getPlaytime());
+ }
+}
+
+void XinePart::slotToggleOsdTimer()
+{
+ kdDebug() << "XinePart: Toggling Osd Timer." << endl;
+ m_isOsdTimer = !m_isOsdTimer;
+}
+
+void XinePart::slotConfigXine()
+{
+ if (!m_xine->isXineReady())
+ {
+ if (!m_xine->initXine())
+ return;
+ }
+
+ XineConfig* xineConfigDialog = new XineConfig(m_xine->getXineEngine());
+ xineConfigDialog->exec();
+ delete xineConfigDialog;
+}
+
+void XinePart::slotError(const QString& errMessage)
+{
+ if ((m_playlist.count() > 0) && (m_current < m_playlist.count() - 1))
+ {
+ slotNext(); // try next before aborting playback; e.g. we play a PLS playlist, primary server is full, now try secondary
+ }
+ else
+ {
+ //KMessageBox::detailedError(0, errMessage, m_xine->getXineLog(), i18n("xine Error"));
+ stateChanged("not_playing");
+ KMessageBox::detailedError(0, errMessage, m_xine->getXineLog(), i18n("xine Error"));
+ emit signalPlaybackFailed();
+ }
+}
+
+void XinePart::slotMessage(const QString& message)
+{
+ QString msg = message;
+ if ( msg.startsWith("@") ) {
+ if ( m_xine->isPlaying() && m_xine->getURL().contains("#") ) // do not warn for url containing #
+ return;
+ msg.remove(0,1);
+ }
+ KMessageBox::information(0, msg, i18n("xine Message"));
+}
+
+void XinePart::slotStatus(const QString& status)
+{
+ emit setStatusBarText(status);
+ if ((status != i18n("Ready")) && (status != i18n("Playing")))
+ {
+ m_xine->showOSDMessage(status, DEFAULT_OSD_DURATION);
+ }
+}
+
+void XinePart::slotTrackPlaying()
+{
+ QString caption;
+
+ kdDebug() << "XinePart: xine is playing" << endl;
+ m_pauseButton->setChecked(false);
+ QTimer::singleShot(100, this, SLOT(slotEnablePlayActions()));
+
+ if ( m_xine->getURL()=="DVB" )
+ {
+ caption = m_xine->getTitle();
+ emit setWindowCaption(caption);
+ m_xine->showOSDMessage(caption, DEFAULT_OSD_DURATION);
+ return;
+ }
+
+ /* fill current mrl with meta info */
+ MRL mrl = m_playlist[m_current];
+
+ if (mrl.length().isNull()) /* no meta */
+ {
+ if ((!m_xine->getTitle().isEmpty()) && (!m_xine->getTitle().contains('/'))
+ && (m_xine->getTitle().contains(QRegExp("\\w")) > 2) && (m_xine->getTitle().left(5).lower() != "track"))
+ mrl.setTitle(m_xine->getTitle());
+ if ((mrl.artist().isEmpty()) && (!m_xine->getArtist().isEmpty()))
+ mrl.setArtist(m_xine->getArtist());
+ if ((mrl.album().isEmpty()) && (!m_xine->getAlbum().isEmpty()))
+ mrl.setAlbum(m_xine->getAlbum());
+ if ((mrl.year().isEmpty()) && (!m_xine->getYear().isEmpty()))
+ mrl.setYear(m_xine->getYear());
+ if ((mrl.genre().isEmpty()) && (!m_xine->getGenre().isEmpty()))
+ mrl.setGenre(m_xine->getGenre());
+ if ((mrl.comment().isEmpty()) && (!m_xine->getComment().isEmpty()))
+ mrl.setComment(m_xine->getComment());
+ mrl.setLength(m_xine->getLength());
+ m_playlist[m_current] = mrl;
+ }
+ /* if we don't have a playlist emit signalNewMeta() */
+ if (mrl.url() == m_mrl.url())
+ {
+ m_mrl = mrl;
+ emit signalNewMeta(m_mrl);
+ }
+
+ caption = mrl.title();
+ if (!mrl.artist().isEmpty())
+ caption.append(QString(" (") + mrl.artist() + ")");
+ emit setWindowCaption(caption);
+ m_xine->showOSDMessage(caption, DEFAULT_OSD_DURATION);
+ //emit signalNewFrameSize(m_xine->getVideoSize());
+}
+
+void XinePart::slotPlaybackFinished()
+{
+ if ((m_playlist.count() > 0) && (m_current < m_playlist.count()-1))
+ {
+ slotNext();
+ }
+ else
+ {
+ stateChanged("not_playing");
+ emit signalTrackFinished();
+ }
+}
+
+void XinePart::slotNewLength()
+{
+ m_mrl.setLength(m_xine->getLength());
+ emit signalNewMeta(m_mrl);
+}
+
+void XinePart::slotNewTitle()
+{
+ m_mrl.setTitle(m_xine->getTitle());
+ emit signalNewMeta(m_mrl);
+ emit setWindowCaption(m_mrl.title());
+}
+
+void XinePart::slotNewFrameSize()
+{
+ kdDebug() << "XinePart: got new frame size from xine" << endl;
+ emit signalNewFrameSize(m_xine->getVideoSize());
+}
+
+void XinePart::slotContextMenu(const QPoint& pos)
+{
+ if (factory())
+ {
+ KPopupMenu *pop = (KPopupMenu*)factory()->container("context_menu", this);
+ if (pop)
+ pop->popup(pos);
+ }
+ else
+ {
+ if (m_embeddedContext)
+ m_embeddedContext->popup(pos);
+ }
+}
+
+void XinePart::slotDVDMenuLeft()
+{
+ if (m_xine)
+ m_xine->slotDVDMenuLeft();
+}
+
+void XinePart::slotDVDMenuRight()
+{
+ if (m_xine)
+ m_xine->slotDVDMenuRight();
+}
+
+void XinePart::slotDVDMenuUp()
+{
+ if (m_xine)
+ m_xine->slotDVDMenuUp();
+}
+
+void XinePart::slotDVDMenuDown()
+{
+ if (m_xine)
+ m_xine->slotDVDMenuDown();
+}
+
+void XinePart::slotDVDMenuSelect()
+{
+ if (m_xine)
+ m_xine->slotDVDMenuSelect();
+}
+
+void XinePart::slotInfo()
+{
+ MRL mrl;
+ if ( m_xine->getURL()=="DVB" )
+ mrl=MRL( QString("DVB"), m_xine->getTitle() );
+ else
+ {
+ if ((m_mrl.isEmpty()) || (m_xine->getTitle().isNull()))
+ return;
+ mrl = m_playlist[m_current];
+ }
+
+ QString info;
+ QTextStream ts(&info, IO_WriteOnly);
+ ts << "<qt><table width=\"90%\">";
+ ts << "<tr><td colspan=\"2\"><center><b>" << mrl.title() << "</b></center></td></tr>";
+ if (!mrl.artist().isNull())
+ ts << "<tr><td><b>" << i18n("Artist") << ":</b></td><td> " << mrl.artist() << "</td></tr>";
+ if (!mrl.album().isNull())
+ ts << "<tr><td><b>" << i18n("Album") << ":</b></td><td> " << mrl.album() << "</td></tr>";
+ if (!mrl.track().isNull())
+ ts << "<tr><td><b>" << i18n("Track") << ":</b></td><td> " << mrl.track() << "</td></tr>";
+ if (!mrl.year().isNull())
+ ts << "<tr><td><b>" << i18n("Year") << ":</b></td><td> " << mrl.year() << "</td></tr>";
+ if (!mrl.genre().isNull())
+ ts << "<tr><td><b>" << i18n("Genre") << ":</b></td><td> " << mrl.genre() << "</td></tr>";
+ if (!(mrl.length().isNull()))
+ ts << "<tr><td><b>" << i18n("Length") << ":</b></td><td> " << mrl.length().toString("h:mm:ss") << "</td></tr>";
+
+ ts << "<br>";
+ ts << "<tr><td><b>" << i18n("Mime") << ":</b></td><td> " << mrl.mime() << "</td></tr>";
+ if (m_xine->hasAudio())
+ ts << "<tr><td><b>" << i18n("Audio") << ":</b></td><td> " << m_xine->getAudioCodec() << " " << QString::number(m_xine->getAudioBitrate()/1000)
+ << "kb/s</td></tr>";
+ if (m_xine->hasVideo())
+ ts << "<tr><td><b>" << i18n("Video") << ":</b></td><td> " << m_xine->getVideoCodec() << " " << m_xine->getVideoSize().width() << "x"
+ << m_xine->getVideoSize().height() << "(" << m_xine->getVideoWidth() << "x" << m_xine->getVideoHeight() << ")"<< "</td></tr>";
+
+ ts << "<br>";
+ if (m_xine->hasSubtitleURL())
+ ts << "<tr><td><b>" << i18n("Subtitle File") << ":</b></td><td> " << m_xine->getSubtitleURL() << "</td></tr>";
+ if (m_xine->hasSaveURL())
+ ts << "<tr><td><b>" << i18n("Save Stream as") << ":</b></td><td> " << m_xine->getSaveURL() << "</td></tr>";
+
+ ts << "<tr><td></td><td></td></tr>"; // added for better layout
+ ts << "</table></qt>";
+ KMessageBox::information(0, info, i18n("Track info") );
+}
+
+void XinePart::slotFinalize()
+{
+ if (factory())
+ {
+ KToolBar *pos = (KToolBar*)factory()->container("positionToolBar", this);
+ if (pos)
+ {
+ // pos->alignItemRight(pos->idAt(1), true); //align time widget right
+ pos->setItemAutoSized(pos->idAt(0), true); //set position slider to maximum width
+ }
+ else
+ kdWarning("Position toolbar not found");
+ }
+ else
+ {
+ kdDebug() << "XinePart: no xmlguifactory, will create a simple context menu..." << endl;
+ KAction* action = NULL;
+ m_embeddedContext = new KPopupMenu(0);
+ m_embeddedContext->insertTitle(instance()->iconLoader()->loadIcon("kaffeine", KIcon::Small), i18n("Kaffeine Player"));
+ actionCollection()->action("player_play")->plug(m_embeddedContext);
+ actionCollection()->action("player_pause")->plug(m_embeddedContext);
+ actionCollection()->action("player_stop")->plug(m_embeddedContext);
+ actionCollection()->action("volume_increase")->plug(m_embeddedContext);
+ actionCollection()->action("volume_decrease")->plug(m_embeddedContext);
+ actionCollection()->action("audio_mute")->plug(m_embeddedContext);
+ m_embeddedContext->insertSeparator();
+ actionCollection()->action("player_track_info")->plug(m_embeddedContext);
+ m_embeddedContext->insertSeparator();
+ actionCollection()->action("file_save_screenshot")->plug(m_embeddedContext);
+ actionCollection()->action("file_save_stream")->plug(m_embeddedContext);
+ m_embeddedContext->insertSeparator();
+ action = new KAction(i18n("Copy URL to Clipboard"), "editcopy", 0, this, SLOT(slotCopyToClipboard()), actionCollection(), "copy_to_clipboard");
+ action->plug(m_embeddedContext);
+ action = new KAction(i18n("Play in Kaffeine Externally"), "gear", 0, this, SLOT(slotLaunchExternally()), actionCollection(), "play_externally");
+ action->plug(m_embeddedContext);
+ }
+
+ QStringList visuals = m_xine->getVisualPlugins();
+ visuals.prepend("none");
+ m_audioVisual->setItems(visuals);
+
+ loadConfig();
+ QTimer::singleShot(0, this, SLOT(slotEnableAllActions()));
+}
+
+void XinePart::slotCopyToClipboard()
+{
+ kdDebug() << "XinePart: Send URL to klipper: " << m_mrl.url() << endl;
+ DCOPClient* client = KApplication::dcopClient();
+ if (!client->send("klipper", "klipper", "setClipboardContents(QString)", m_mrl.url()))
+ kdError() << "Can't send current URL to klipper" << endl;
+}
+
+void XinePart::slotLaunchExternally()
+{
+ slotStop();
+
+ QTimer::singleShot(1000, this, SLOT(slotLaunchDelayed()));
+}
+
+void XinePart::slotLaunchDelayed()
+{
+ kdDebug() << "XinePart: Start Kaffeine with argument: " << m_mrl.url() << endl;
+ KProcess process;
+ process << "kaffeine" << m_mrl.url();
+ kdDebug() << "XinePart: Launching Kaffeine externaly..." << endl;
+ process.start(KProcess::DontCare);
+ process.detach();
+}
+
+void XinePart::initActions()
+{
+ KAction* action = NULL;
+ /* file menu */
+ m_broadcastSend = new KToggleAction(i18n("&Send Broadcast Stream..."), 0, 0, this, SLOT(slotToggleBroadcastSend()), actionCollection(), "network_send");
+ new KAction(i18n("&Receive Broadcast Stream..."), "network", 0, this, SLOT(slotBroadcastReceive()), actionCollection(), "network_receive");
+ new KAction(i18n("&Save Screenshot..."), "frame_image", CTRL|Key_S, this, SLOT(slotScreenshot()), actionCollection(), "file_save_screenshot");
+ action = new KAction(i18n("Save Stream..."), "player_record", Key_R, this, SLOT(slotSaveStream()), actionCollection(), "file_save_stream");
+ action->setWhatsThis(i18n("Saves current stream to harddisc. This feature was disabled for some formats (e.g. Real Media) to prevent potential legal problems."));
+
+ /* player menu */
+
+ new KAction(i18n("Toggle Minimal Mode"), 0, 0, this, SIGNAL(signalToggleMinimalMode()), actionCollection(), "player_minimal_mode");
+
+ new KAction(i18n("Play"), "player_play", 0, this, SLOT(slotPlay()), actionCollection(), "player_play");
+ m_pauseButton = new KToggleAction(i18n("Pause"), "player_pause", Key_Space, this, SLOT(slotTogglePause()), actionCollection(), "player_pause");
+ new KAction(i18n("&Next"), "player_end", Key_PageDown, this, SLOT(slotNext()), actionCollection(), "player_next");
+ new KAction(i18n("&Previous"), "player_start", Key_PageUp, this, SLOT(slotPrevious()), actionCollection(), "player_previous");
+ new KAction(i18n("Stop"), "player_stop", Key_Backspace, this, SLOT(slotStop()), actionCollection(), "player_stop");
+
+ new KAction(i18n("&Fast Forward"), "player_fwd", ALT|Key_Right, this, SLOT(slotFastForward()), actionCollection(), "player_ff");
+ new KAction(i18n("Slow &Motion"), 0, ALT|Key_Left, this, SLOT(slotSlowMotion()), actionCollection(), "player_slowmotion");
+
+ new KAction(i18n("Skip Forward (20s)"), NULL, Key_Right, this, SLOT(slotPosPlusSmall()), actionCollection(), "player_posplus_small");
+ new KAction(i18n("Skip Backward (20s)"), NULL, Key_Left, this, SLOT(slotPosMinusSmall()), actionCollection(), "player_posminus_small");
+ new KAction(i18n("Skip Forward (1m)"), NULL, CTRL|Key_PageUp, this, SLOT(slotPosPlusMedium()), actionCollection(), "player_posplus_medium");
+ new KAction(i18n("Skip Backward (1m)"), NULL, CTRL|Key_PageDown, this, SLOT(slotPosMinusMedium()), actionCollection(), "player_posminus_medium");
+ new KAction(i18n("Skip Forward (10m)"), NULL, ALT|Key_PageUp, this, SLOT(slotPosPlusLarge()), actionCollection(), "player_posplus_large");
+ new KAction(i18n("Skip Backward (10m)"), NULL, ALT|Key_PageDown, this, SLOT(slotPosMinusLarge()), actionCollection(), "player_posminus_large");
+ new KAction(i18n("Jump to Position..."), "goto", CTRL|Key_J, this, SLOT(slotJumpToPosition()), actionCollection(), "player_jump_to");
+
+ new KAction(i18n("DVD Menu Left"), 0, CTRL|Key_Left, this, SLOT(slotDVDMenuLeft()), actionCollection(), "dvdmenuleft");
+ new KAction(i18n("DVD Menu Right"), 0, CTRL|Key_Right, this, SLOT(slotDVDMenuRight()), actionCollection(), "dvdmenuright");
+ new KAction(i18n("DVD Menu Up"), 0, CTRL|Key_Up, this, SLOT(slotDVDMenuUp()), actionCollection(), "dvdmenuup");
+ new KAction(i18n("DVD Menu Down"), 0, CTRL|Key_Down, this, SLOT(slotDVDMenuDown()), actionCollection(), "dvdmenudown");
+ new KAction(i18n("DVD Menu Select"), 0, CTRL|Key_Return, this, SLOT(slotDVDMenuSelect()), actionCollection(), "dvdmenuselect");
+
+ m_audioChannels = new KSelectAction(i18n("Audio Channel"), 0, actionCollection(), "audio_channels");
+ m_audioChannels->setToolTip(i18n("Select audio channel"));
+ m_audioChannels->setComboWidth( 50 );
+ connect(m_audioChannels, SIGNAL(activated(int)), this, SLOT(slotSetAudioChannel(int )));
+ new KAction(i18n("&Next Audio Channel"), 0, 0, this, SLOT(slotNextAudioChannel()), actionCollection(), "next_audio_channels");
+ m_audioVisual = new KSelectAction(i18n("Audio &Visualization"), 0, actionCollection(), "audio_visualization");
+ connect(m_audioVisual, SIGNAL(activated(const QString&)), m_xine, SLOT(slotSetVisualPlugin(const QString&)));
+ new KAction(i18n("&Mute"), "player_mute", Key_U, this, SLOT(slotMute()), actionCollection(), "audio_mute");
+ new KAction(i18n("Volume Up"), NULL, Key_Plus, this, SLOT(slotVolumeUp()), actionCollection(), "volume_increase");
+ new KAction(i18n("Volume Down"), NULL, Key_Minus, this, SLOT(slotVolumeDown()), actionCollection(), "volume_decrease");
+
+ m_deinterlaceEnabled = new KToggleAction(i18n("&Deinterlace"), 0, Key_I, m_xine, SLOT(slotToggleDeinterlace()), actionCollection(), "video_deinterlace");
+ m_deinterlaceEnabled->setWhatsThis(i18n("Activate this for interlaced streams, some DVD's for example."));
+ new KAction(i18n("&Auto"), "viewmagfit", Key_F5, m_xine, SLOT(slotAspectRatioAuto()), actionCollection(), "aspect_auto");
+ new KAction(i18n("&4:3"), "viewmagfit", Key_F6, m_xine, SLOT(slotAspectRatio4_3()), actionCollection(), "aspect_43");
+ new KAction(i18n("A&namorphic"), "viewmagfit", Key_F7, m_xine, SLOT(slotAspectRatioAnamorphic()), actionCollection(), "aspect_anamorphic");
+ new KAction(i18n("&DVB"), "viewmagfit", Key_F8, m_xine, SLOT(slotAspectRatioDVB()), actionCollection(), "aspect_dvb");
+ new KAction(i18n("&Square"), "viewmagfit", Key_F9, m_xine, SLOT(slotAspectRatioSquare()), actionCollection(), "aspect_square");
+ KStdAction::zoomIn(m_xine, SLOT(slotZoomIn()), actionCollection(), "zoom_in");
+ KStdAction::zoomOut(m_xine, SLOT(slotZoomOut()), actionCollection(), "zoom_out");
+ KStdAction::fitToPage(m_xine, SLOT(slotZoomOff()), actionCollection(), "zoom_off");
+ new KAction(i18n("Zoom In Horizontal"), NULL, CTRL|Key_H, m_xine, SLOT(slotZoomInX()), actionCollection(), "zoom_in_x");
+ new KAction(i18n("Zoom Out Horizontal"), NULL, CTRL|SHIFT|Key_H, m_xine, SLOT(slotZoomOutX()), actionCollection(), "zoom_out_x");
+ new KAction(i18n("Zoom In Vertical"), NULL, CTRL|Key_V, m_xine, SLOT(slotZoomInY()), actionCollection(), "zoom_in_y");
+ new KAction(i18n("Zoom Out Vertical"), NULL, CTRL|SHIFT|Key_V, m_xine, SLOT(slotZoomOutY()), actionCollection(), "zoom_out_y");
+ new KAction(i18n("Deinterlace &Quality"), "blend", CTRL|Key_I, this, SLOT(slotDeinterlaceQuality()), actionCollection(), "video_deinterlace_quality");
+ new KAction(i18n("&Video Settings"), "configure", Key_V, this, SLOT(slotPictureSettings()), actionCollection(), "video_picture");
+ new KAction(i18n("&Equalizer"), NULL, Key_E, this, SLOT(slotEqualizer()), actionCollection(), "equalizer");
+
+
+ m_subtitles = new KSelectAction(i18n("Subtitle"), 0, actionCollection(), "player_subtitles");
+ m_subtitles->setToolTip(i18n("Select Subtitle"));
+ m_subtitles->setComboWidth( 50 );
+ connect(m_subtitles, SIGNAL(activated(int)), this, SLOT(slotSetSubtitle(int)));
+ new KAction(i18n("&Next Subtitle Channel"), 0, 0, this, SLOT(slotNextSubtitleChannel()), actionCollection(), "next_player_subtitles");
+ new KAction(i18n("Delay Subtitle"), 0, CTRL|ALT|Key_Left, this, SLOT(slotDelaySubTitle()), actionCollection(), "adv_sub");
+ new KAction(i18n("Advance Subtitle"), 0, CTRL|ALT|Key_Right, this, SLOT(slotAdvanceSubTitle()), actionCollection(), "delay_sub");
+ new KAction(i18n("Add subtitle..."), 0, 0, this, SLOT(slotAddSubtitle()), actionCollection(), "add_subtitle");
+
+ new KAction(i18n("&Menu Toggle"), "view_detailed", Key_D, m_xine, SLOT(slotMenuToggle()), actionCollection(), "dvd_toggle");
+ new KAction(i18n("&Title"), NULL, 0, m_xine, SLOT(slotMenuTitle()), actionCollection(), "dvd_title");
+ new KAction(i18n("&Root"), NULL, 0, m_xine, SLOT(slotMenuRoot()), actionCollection(), "dvd_root");
+ new KAction(i18n("&Subpicture"), NULL, 0, m_xine, SLOT(slotMenuSubpicture()), actionCollection(), "dvd_subpicture");
+ new KAction(i18n("&Audio"), NULL, 0, m_xine, SLOT(slotMenuAudio()), actionCollection(), "dvd_audio");
+ new KAction(i18n("An&gle"), NULL, 0, m_xine, SLOT(slotMenuAngle()), actionCollection(), "dvd_angle");
+ new KAction(i18n("&Part"), NULL, 0, m_xine, SLOT(slotMenuPart()), actionCollection(), "dvd_part");
+
+ m_dvdTitles = new KSelectAction(i18n("Titles"), 0, actionCollection(), "dvd_title_menu");
+ connect(m_dvdTitles, SIGNAL(activated(const QString&)), this, SLOT(slotSetDVDTitle(const QString&)));
+ m_dvdChapters = new KSelectAction(i18n("Chapters"), 0, actionCollection(), "dvd_chapter_menu");
+ connect(m_dvdChapters, SIGNAL(activated(const QString&)), this, SLOT(slotSetDVDChapter(const QString&)));
+ m_dvdAngles = new KSelectAction(i18n("Angles"), 0, actionCollection(), "dvd_angle_menu");
+ connect(m_dvdAngles, SIGNAL(activated(const QString&)), this, SLOT(slotSetDVDAngle(const QString&)));
+
+ new KAction(i18n("Track &Info"), "info", 0 , this, SLOT(slotInfo()), actionCollection(), "player_track_info");
+ new KAction(i18n("Effect &Plugins..."), "filter", Key_X, this, SLOT(slotFilterDialog()), actionCollection(), "player_post_filters");
+
+ /* settings menu */
+ new KAction(i18n("&xine Engine Parameters"), "edit", 0, this, SLOT(slotConfigXine()), actionCollection(), "settings_xine_parameter");
+
+ m_volume = new VolumeSlider();
+ QToolTip::add
+ (m_volume, i18n("Volume"));
+ m_volume->setRange(0, 100);
+ m_volume->setSteps(1, 10);
+ m_volume->setFocusPolicy(QWidget::NoFocus);
+ m_volume->setFixedWidth(75);
+ connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(slotVolumeChanged(int)));
+ connect(m_xine, SIGNAL(signalSyncVolume()), this, SLOT(slotSyncVolume()));
+ new KWidgetAction(m_volume, i18n("Volume"), 0, 0, 0, actionCollection(), "audio_volume");
+
+ m_position = new PositionSlider(Horizontal);
+ QToolTip::add
+ (m_position, i18n("Position"));
+ m_position->setRange(0, 65535);
+ m_position->setSteps(100, 1000);
+ m_position->setTracking(false);
+ m_position->setFocusPolicy(QWidget::NoFocus);
+ m_position->setMinimumWidth(180);
+ connect(m_position, SIGNAL(sliderMoved(int)), m_xine, SLOT(slotSeekToPosition(int)));
+ connect(m_position, SIGNAL(sliderLastMove(int)), m_xine, SLOT(slotSeekToPositionBlocking(int)));
+ connect(m_position, SIGNAL(signalStartSeeking()), m_xine, SLOT(slotStartSeeking()));
+ connect(m_position, SIGNAL(signalStopSeeking()), m_xine, SLOT(slotStopSeeking()));
+ new KWidgetAction(m_position, i18n("Position"), 0, 0, 0, actionCollection(), "player_position");
+
+ m_playTime = new QPushButton(0);
+ QToolTip::add
+ (m_playTime, i18n("Short click: Toggle Timer Forward/Backward\nLong click: Toggle Timer OSD"));
+ QFontMetrics met(KGlobalSettings::generalFont());
+ m_playTime->setFixedWidth(met.width("-55:55:55") + 6);
+ m_playTime->setSizePolicy(QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
+ m_playTime->setFocusPolicy(QWidget::NoFocus);
+ new KWidgetAction(m_playTime, i18n("Playtime"), 0, 0, 0, actionCollection(), "player_playtime");
+ connect(m_playTime, SIGNAL(pressed()), this, SLOT(slotButtonTimerPressed()));
+ connect(m_playTime, SIGNAL(released()), this, SLOT(slotButtonTimerReleased()));
+ m_playTime->setText("0:00:00");
+
+ m_equalizer = new Equalizer();
+ connect(m_equalizer, SIGNAL(signalNewEq30(int)), m_xine, SLOT(slotSetEq30(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq60(int)), m_xine, SLOT(slotSetEq60(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq125(int)), m_xine, SLOT(slotSetEq125(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq250(int)), m_xine, SLOT(slotSetEq250(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq500(int)), m_xine, SLOT(slotSetEq500(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq1k(int)), m_xine, SLOT(slotSetEq1k(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq2k(int)), m_xine, SLOT(slotSetEq2k(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq4k(int)), m_xine, SLOT(slotSetEq4k(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq8k(int)), m_xine, SLOT(slotSetEq8k(int)));
+ connect(m_equalizer, SIGNAL(signalNewEq16k(int)), m_xine, SLOT(slotSetEq16k(int)));
+ connect(m_equalizer, SIGNAL(signalSetVolumeGain(bool)), m_xine, SLOT(slotSetVolumeGain(bool)));
+
+}
+
+void XinePart::initConnections()
+{
+ connect(&m_posCheckTimer, SIGNAL(timeout()), this, SLOT(slotCheckMoved()));
+ connect(&m_osdTimerEnabler, SIGNAL(timeout()), this, SLOT(slotToggleOsdTimer()));
+ connect(m_xine, SIGNAL(signalXineReady()), this, SLOT(slotFinalize()));
+ connect(m_xine, SIGNAL(signalNewChannels(const QStringList&, const QStringList&, int, int )),
+ this, SLOT(slotChannelInfo(const QStringList&, const QStringList&, int, int )));
+ connect(m_xine, SIGNAL(signalXinePlaying()), this, SLOT(slotTrackPlaying()));
+ connect(m_xine, SIGNAL(signalNewPosition(int, const QTime&)), this, SLOT(slotNewPosition(int, const QTime&)));
+ connect(m_xine, SIGNAL(signalXineStatus(const QString&)), this, SLOT(slotStatus(const QString&)));
+ connect(m_xine, SIGNAL(signalXineError(const QString&)), this, SLOT(slotError(const QString&)));
+ connect(m_xine, SIGNAL(signalXineMessage(const QString&)), this, SLOT(slotMessage(const QString&)));
+ connect(m_xine, SIGNAL(signalPlaybackFinished()), this, SLOT(slotPlaybackFinished()));
+ connect(m_xine, SIGNAL(signalTitleChanged()), this, SLOT(slotNewTitle()));
+ connect(m_xine, SIGNAL(signalLengthChanged()), this, SLOT(slotNewLength()));
+ connect(m_xine, SIGNAL(signalVideoSizeChanged()), this, SLOT(slotNewFrameSize()));
+ connect(m_xine, SIGNAL(signalRightClick(const QPoint&)), this, SLOT(slotContextMenu(const QPoint&)));
+}
+
+void XinePart::loadConfig()
+{
+ kdDebug() << "XinePart: load config" << endl;
+
+ KConfig* config = instance()->config();
+
+ config->setGroup("General Options");
+ if (m_xine->SoftwareMixing())
+ {
+ int vol = config->readNumEntry("Volume", 70);
+ slotSetVolume(vol);
+ }
+ else
+ slotSyncVolume();
+ m_timerDirection = config->readNumEntry("Timer Direction", FORWARD_TIMER);
+ m_isOsdTimer = config->readBoolEntry("Osd Timer", false);
+
+ config->setGroup("Visualization");
+ QString visual = config->readEntry("Visual Plugin", "goom");
+ m_audioVisual->setCurrentItem(m_audioVisual->items().findIndex(visual));
+ m_xine->slotSetVisualPlugin(visual);
+
+ config->setGroup("Deinterlace");
+ m_lastDeinterlaceQuality = config->readNumEntry("Quality Level", 4);
+ m_lastDeinterlacerConfig = config->readEntry("Config String", DEFAULT_TVTIME_CONFIG);
+ DeinterlacerConfigDialog* deinterlacerConfigDialog = new DeinterlacerConfigDialog();
+ m_xine->createDeinterlacePlugin(m_lastDeinterlacerConfig, deinterlacerConfigDialog->getMainWidget());
+ m_deinterlacerConfigWidget = (QWidget*)deinterlacerConfigDialog;
+ bool deinterlaceEnabled = config->readBoolEntry("Enabled", true);
+ if (deinterlaceEnabled)
+ {
+ m_deinterlaceEnabled->setChecked(deinterlaceEnabled);
+ m_xine->slotToggleDeinterlace();
+ }
+
+ config->setGroup("Broadcasting Options");
+ m_broadcastPort = config->readNumEntry("Port", 8080);
+ m_broadcastAddress = config->readEntry("Master Address", "localhost");
+
+ config->setGroup( "Video Settings" );
+ slotSetHue(config->readNumEntry( "Hue", -1));
+ slotSetSaturation(config->readNumEntry( "Saturation", -1));
+ slotSetContrast(config->readNumEntry( "Contrast", -1));
+ slotSetBrightness(config->readNumEntry( "Brigthness", -1));
+
+ m_equalizer->ReadValues(config);
+}
+
+void XinePart::saveConfig()
+{
+ if (!m_audioVisual->items().count()) // no config loaded
+ return;
+
+ kdDebug() << "XinePart: save config" << endl;
+
+ KConfig* config = instance()->config();
+
+ config->setGroup("General Options");
+ config->writeEntry("Volume", m_volume->value());
+ config->writeEntry("Timer Direction", m_timerDirection);
+ config->writeEntry("Osd Timer", m_isOsdTimer);
+
+ config->setGroup("Visualization");
+ config->writeEntry("Visual Plugin", m_audioVisual->currentText());
+
+ config->setGroup("Deinterlace");
+ config->writeEntry("Quality Level", m_lastDeinterlaceQuality);
+ config->writeEntry("Config String", m_lastDeinterlacerConfig);
+ config->writeEntry("Enabled", m_deinterlaceEnabled->isChecked());
+
+ config->setGroup("Broadcasting Options");
+ config->writeEntry("Port", m_broadcastPort);
+ config->writeEntry("Master Address", m_broadcastAddress);
+
+ config->setGroup( "Video Settings" );
+ config->writeEntry( "Hue", m_hue );
+ config->writeEntry( "Saturation", m_saturation );
+ config->writeEntry( "Contrast", m_contrast );
+ config->writeEntry( "Brigthness", m_brightness );
+
+ m_equalizer->SaveValues(config);
+}
+
+/* check if shell was moved, send new global position
+ of the part to xine */
+void XinePart::slotCheckMoved()
+{
+ QPoint newPos = m_xine->mapToGlobal(QPoint(0,0));
+ if (newPos != m_oldPosition)
+ {
+ m_xine->globalPosChanged();
+ m_oldPosition = newPos;
+ }
+}
+
+bool XinePart::isPlaying()
+{
+ return m_xine->isPlaying();
+}
+
+bool XinePart::isPaused()
+{
+ return (m_xine->getSpeed() == KXineWidget::Pause);
+}
+
+#if 0
+void XinePart::audiocdMRLS(MRL::List& mrls, bool& ok, bool& supported, const QString& device)
+{
+ if (!m_xine->isXineReady())
+ {
+ if (!m_xine->initXine())
+ {
+ supported = false;
+ return;
+ }
+ }
+ supported = true;
+
+ if (!device.isNull())
+ m_xine->slotSetAudiocdDevice(device);
+
+ QStringList list;
+ if (!m_xine->getAutoplayPluginURLS("CD", list))
+ {
+ ok = false;
+ return;
+ }
+
+ MRL mrl;
+ /* use xine to connect to CDDB */
+ xine_stream_t* xineStreamForMeta = xine_stream_new((xine_t*)m_xine->getXineEngine(), NULL, NULL);
+
+ KProgressDialog* progress = new KProgressDialog(0, "cddbprogress", QString::null, i18n("Looking for CDDB entries..."));
+ progress->progressBar()->setTotalSteps(list.count());
+ progress->show();
+ QString title;
+ bool cddb = true;
+ for (uint i = 0; i < list.count(); i++)
+ {
+ mrl = MRL(list[i]);
+ mrl.setTitle(i18n("AudioCD Track %1").arg(i+1));
+ mrl.setTrack(QString::number(i+1));
+ if (xine_open(xineStreamForMeta, QFile::encodeName(mrl.url())))
+ {
+ if (cddb)
+ {
+ title = QString::fromUtf8(xine_get_meta_info(xineStreamForMeta, XINE_META_INFO_TITLE));
+ if ((!title.isNull()) && (!title.isEmpty()) ) //no meta info
+ {
+ mrl.setTitle(title);
+ mrl.setArtist(QString::fromUtf8(xine_get_meta_info(xineStreamForMeta, XINE_META_INFO_ARTIST)));
+ mrl.setAlbum(QString::fromUtf8(xine_get_meta_info(xineStreamForMeta, XINE_META_INFO_ALBUM)));
+ mrl.setYear(QString::fromUtf8(xine_get_meta_info(xineStreamForMeta, XINE_META_INFO_YEAR)));
+ mrl.setGenre(QString::fromUtf8(xine_get_meta_info(xineStreamForMeta, XINE_META_INFO_GENRE)));
+ mrl.setTrack(QString::number(i+1));
+ }
+ else
+ cddb = false;
+ }
+
+ int pos, time, len;
+ int t = 0, ret = 0;
+ while(((ret = xine_get_pos_length(xineStreamForMeta, &pos, &time, &len)) == 0) && (++t < 5))
+ xine_usec_sleep(100000);
+ if ( ( ret != 0 ) && (len > 0) )
+ mrl.setLength(QTime().addMSecs(len));
+
+ xine_close( xineStreamForMeta );
+ }
+
+ mrl.setMime("audio/cd");
+ mrls.append(mrl);
+ if (progress->wasCancelled())
+ break;
+ progress->progressBar()->setProgress(i+1);
+ KApplication::kApplication()->processEvents();
+ }
+
+ xine_dispose(xineStreamForMeta);
+ delete progress;
+ if (mrls.count())
+ ok = true;
+}
+
+void XinePart::vcdMRLS(MRL::List& mrls, bool& ok, bool& supported, const QString& device)
+{
+ if (!m_xine->isXineReady())
+ {
+ if (!m_xine->initXine())
+ {
+ supported = false;
+ return;
+ }
+ }
+ supported = true;
+
+ if (!device.isNull())
+ m_xine->slotSetVcdDevice(device);
+
+ QStringList list;
+ if (!m_xine->getAutoplayPluginURLS("VCD", list))
+ {
+ if (!m_xine->getAutoplayPluginURLS("VCDO", list))
+ {
+ ok = false;
+ return;
+ }
+ }
+
+ MRL mrl;
+ for (uint i = 0; i < list.count(); i++)
+ {
+ mrl = MRL(list[i]);
+ mrl.setMime("video/vcd");
+ mrl.setTrack(QString::number(i+1));
+ mrl.setTitle(i18n("VCD Track %1").arg(i+1));
+ mrls.append(mrl);
+ }
+ if (mrls.count())
+ ok = true;
+}
+
+void XinePart::dvdMRLS(MRL::List& mrls, bool& ok, bool& supported, const QString& device)
+{
+ if (!m_xine->isXineReady())
+ {
+ if (!m_xine->initXine())
+ {
+ supported = false;
+ return;
+ }
+ }
+ supported = true;
+
+ if (!device.isNull())
+ m_xine->slotSetDvdDevice(device);
+
+ QStringList list;
+ if (!m_xine->getAutoplayPluginURLS("DVD", list))
+ {
+ ok = false;
+ return;
+ }
+
+ MRL mrl;
+ for (uint i = 0; i < list.count(); i++)
+ {
+ mrl = MRL(list[i]);
+ mrl.setMime("video/dvd");
+ mrl.setTitle("DVD");
+ mrl.setTrack(QString::number(i+1));
+ mrls.append(mrl);
+ }
+ if (mrls.count())
+ ok = true;
+}
+#endif
+
+bool XinePart::hasChapters()
+{
+ if (m_xine->isXineReady())
+ return m_xine->hasChapters();
+ else
+ return false;
+}
+
+bool XinePart::hasVideo()
+{
+ return m_xine->hasVideo();
+}
+
+void XinePart::playNextChapter()
+{
+ if (m_xine->isXineReady())
+ m_xine->playNextChapter();
+}
+
+void XinePart::playPreviousChapter()
+{
+ if (m_xine->isXineReady())
+ m_xine->playPreviousChapter();
+}
+
+void XinePart::slotPrepareForFullscreen(bool fullscreen)
+{
+ if (fullscreen)
+ m_xine->startMouseHideTimer();
+ else
+ m_xine->stopMouseHideTimer();
+}
+
+uint XinePart::volume() const
+{
+ if (!m_xine->isXineReady())
+ return 0;
+
+ return m_xine->getVolume();
+}
+
+uint XinePart::position() const
+{
+ if (!m_xine->isXineReady())
+ return 0;
+
+ if ( m_xine->isPlaying() )
+ return currentPosition;
+ else
+ return 0;
+}
+
+void XinePart::slotSetVolume(uint vol)
+{
+ if (!m_xine->isXineReady())
+ return;
+
+ kdDebug() << "Set volume to: " << vol << endl;
+ m_volume->setValue(vol);
+}
+
+void XinePart::slotVolumeChanged(int vol)
+{
+ m_xine->slotSetVolume(vol);
+}
+
+void XinePart::slotSyncVolume()
+{
+ if (!m_xine->isXineReady())
+ return;
+
+ uint vol = volume();
+ slotSetVolume(vol);
+}
+
+void XinePart::slotSetPosition(uint pos)
+{
+ if (!m_xine->isXineReady())
+ return;
+
+ m_xine->slotSeekToPosition((int)(pos * 655.35));
+}
+
+QString XinePart::supportedExtensions()
+{
+ if (!m_xine->isXineReady())
+ return QString::null;
+
+ QString ext = m_xine->getSupportedExtensions();
+ ext = ext.remove("txt");
+ ext = "*." + ext;
+ ext.append(" smil");
+ ext = ext.replace( ' ', " *." );
+ ext = ext + " " + ext.upper();
+
+ return ext;
+}
+
+void* XinePart::engine()
+{
+ if (!m_xine->isXineReady())
+ return NULL;
+
+ return (void*)m_xine->getXineEngine();
+}
+
+void XinePart::slotDisableAllActions()
+{
+ stateChanged("xine_not_ready");
+}
+
+void XinePart::slotEnableAllActions()
+{
+ stateChanged("xine_not_ready", StateReverse);
+ stateChanged("not_playing");
+}
+
+void XinePart::slotEnablePlayActions()
+{
+ if ((m_playlist.count() > 1) || (m_xine->hasChapters())) // we need next/previous buttons
+ stateChanged("play_multiple_tracks");
+ else
+ stateChanged("play_single_track");
+}
+
+void XinePart::slotNextAudioChannel()
+{
+ nextAudioChannel();
+}
+
+void XinePart::slotNextSubtitleChannel()
+{
+ nextSubtitleChannel();
+}
+
+/********* DCOP INTERFACE *********/
+
+void XinePart::nextAudioChannel()
+{
+ int num = m_audioChannels->items().count();
+ int index = m_audioChannels->currentItem()+1;
+ if ( index>=num )
+ index = 0;
+ m_audioChannels->setCurrentItem( index );
+ slotSetAudioChannel( index );
+}
+
+void XinePart::nextSubtitleChannel()
+{
+ int num = m_subtitles->items().count();
+ int index = m_subtitles->currentItem()+1;
+ if ( index>=num )
+ index = 0;
+ m_subtitles->setCurrentItem( index );
+ slotSetSubtitle( index );
+}
+
+int XinePart::getContrast()
+{
+ int hue, sat, contrast, bright, avOffset, spuOffset;
+ if (!m_xine->isXineReady())
+ return -1;
+ m_xine->getVideoSettings(hue, sat, contrast, bright, avOffset, spuOffset);
+ return contrast;
+}
+
+void XinePart::setContrast(int c)
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotSetContrast(c);
+}
+
+int XinePart::getBrightness()
+{
+ int hue, sat, contrast, bright, avOffset, spuOffset;
+ if (!m_xine->isXineReady())
+ return -1;
+ m_xine->getVideoSettings(hue, sat, contrast, bright, avOffset, spuOffset);
+ return bright;
+}
+
+void XinePart::setBrightness(int b)
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotSetBrightness(b);
+}
+
+void XinePart::dvdMenuUp()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotDVDMenuUp();
+}
+
+void XinePart::dvdMenuDown()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotDVDMenuDown();
+}
+
+void XinePart::dvdMenuLeft()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotDVDMenuLeft();
+}
+
+void XinePart::dvdMenuRight()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotDVDMenuRight();
+}
+
+void XinePart::dvdMenuSelect()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotDVDMenuSelect();
+}
+
+void XinePart::dvdMenuToggle()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotMenuToggle();
+}
+
+void XinePart::aspectRatioAuto()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotAspectRatioAuto();
+}
+
+void XinePart::aspectRatio4_3()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotAspectRatio4_3();
+}
+
+void XinePart::aspectRatioAnamorphic()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotAspectRatioAnamorphic();
+}
+
+void XinePart::aspectRatioSquare()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotAspectRatioSquare();
+}
+
+void XinePart::aspectRatioDVB()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotAspectRatioDVB();
+}
+
+void XinePart::zoomInX()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotZoomInX();
+}
+
+void XinePart::zoomOutX()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotZoomOutX();
+}
+
+void XinePart::zoomInY()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotZoomInY();
+}
+
+void XinePart::zoomOutY()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotZoomOutY();
+}
+
+void XinePart::zoomIn()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotZoomIn();
+}
+
+void XinePart::zoomOut()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotZoomOut();
+}
+
+void XinePart::zoomOff()
+{
+ if (!m_xine->isXineReady())
+ return;
+ m_xine->slotZoomOff();
+}
+
+
+
+/********** volume slider ****************/
+
+
+VolumeSlider::VolumeSlider() : QSlider(Horizontal, 0)
+{
+ installEventFilter(this);
+}
+
+VolumeSlider::~VolumeSlider()
+{}
+
+void VolumeSlider::wheelEvent(QWheelEvent* e)
+{
+ int newVal = value();
+ if (e->delta() > 0)
+ newVal -= 5;
+ else if (e->delta() < 0)
+ newVal += 5;
+ setValue(newVal);
+ e->accept();
+}
+
+/*bool VolumeSlider::eventFilter(QObject *obj, QEvent *ev)
+{
+ if( obj == this && (ev->type() == QEvent::MouseButtonPress ||
+ ev->type() == QEvent::MouseButtonDblClick) )
+ {
+ QMouseEvent *e = (QMouseEvent *)ev;
+ QRect r = sliderRect();
+
+ if( r.contains( e->pos() ) || e->button() != LeftButton )
+ return FALSE;
+
+ int range = maxValue() - minValue();
+ int pos = (orientation() == Horizontal) ? e->pos().x() : e->pos().y();
+ int maxpos = (orientation() == Horizontal) ? width() : height();
+ int value = pos * range / maxpos + minValue();
+
+ if (QApplication::reverseLayout())
+ value = maxValue() - (value - minValue());
+
+ setValue(value);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}*/
+
+#include "xine_part.moc"
diff --git a/kaffeine/src/player-parts/xine-part/xine_part.desktop b/kaffeine/src/player-parts/xine-part/xine_part.desktop
new file mode 100644
index 0000000..ce9f2ab
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/xine_part.desktop
@@ -0,0 +1,43 @@
+[Desktop Entry]
+Encoding=UTF-8
+Icon=kaffeine
+MimeType=application/x-ogg;video/x-matroska;audio/x-matroska;video/mpeg;video/msvideo;video/quicktime;video/vnd.rn-realvideo;video/x-avi;video/x-fli;video/x-flic;video/x-ms-asf;video/x-ms-wmv;video/x-msvideo;application/x-mplayer2;application/smil;application/x-kaffeine;audio/x-musepack;
+Name=Kaffeine-Xine
+Name[nb]=Kaffeine Xine
+Name[pa]=ਕੈਫੀਨ-ਜ਼ਾਇਨ
+Name[se]=Kaffeine Xine
+Name[xx]=xxKaffeine-Xinexx
+Comment=A Kaffeine engine based on xine.
+Comment[af]='n Kaffeine enjin wat op Xine gebaseer is.
+Comment[bg]=Ядро за Kaffeine, базирано на xine.
+Comment[ca]=Una part de reproductor basada en xine.
+Comment[cs]=Část přehrávače založená na xine.
+Comment[da]=En Kaffeine-grænseflade baseret på Xine.
+Comment[de]=Ein auf Xine basierendes Programmmodul.
+Comment[el]=Μία μηχανή του Kaffeine βασισμένη στο xine.
+Comment[et]=Kaffeine mootor xine põhjal.
+Comment[ga]=Inneall Kaffeine bunaithe ar xine.
+Comment[gl]=Un motor para Kaffeine baseado en Xine.
+Comment[hu]=Xine-alapú Kaffeine-alrendszer.
+Comment[it]=Un motore di Kaffeine basato su xine.
+Comment[ja]=xine に基づく Kaffeine エンジン
+Comment[lt]=Kaffeine variklis, paremtas Xine.
+Comment[nb]=En spillermotor basert på xine.
+Comment[nl]=Een Kaffeine-engine gebaseerd op xine.
+Comment[pa]=ਜ਼ਾਈਨ ਅਧਾਰਤ ਇੱਕ ਕੈਫ਼ੀਨ ਇੰਜਣ ਹੈ।
+Comment[pl]=Moduł odtwarzacza do Kaffeine bazujący na xine.
+Comment[pt]=Um motor Kaffeine no xine.
+Comment[pt_BR]=Um componente de reprodução Kaffeine baseado no xine.
+Comment[se]=Čuojanmohtor vuođđoduvvon xineáis.
+Comment[sr]=Кафеинов мотор заснован на Xine-у.
+Comment[sr@Latn]=Кафеинов мотор заснован на Xine-у.
+Comment[sv]=En Kaffeine-gränssnitt baserad på Xine.
+Comment[tg]=Барномаи Kaffeine дар асоси xine.
+Comment[th]=โปรแกรมประมวลผลของ Kaffeine โดยใช้ xine
+Comment[tr]=xine tabanlı bir Kaffeine motoru.
+Comment[uk]=Рушій Kaffeine, оснований на xine.
+Comment[xx]=xxA Kaffeine engine based on xine.xx
+ServiceTypes=KParts/ReadOnlyPart,KaffeinePart
+Type=Service
+X-KDE-Library=libxinepart
+InitialPreference=9
diff --git a/kaffeine/src/player-parts/xine-part/xine_part.h b/kaffeine/src/player-parts/xine-part/xine_part.h
new file mode 100644
index 0000000..71769d3
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/xine_part.h
@@ -0,0 +1,276 @@
+/*
+ * xine_part.h
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 XINEPART_H
+#define XINEPART_H
+
+
+#include <kparts/factory.h>
+
+#include <qtimer.h>
+
+#include "kaffeinepart.h"
+#include "xine_part_iface.h"
+
+#define FORWARD_TIMER 0
+#define BACKWARD_TIMER 1
+
+class QWidget;
+class QSlider;
+class QLabel;
+class QPushButton;
+class MRL;
+class KXineWidget;
+class QPoint;
+class KSelectAction;
+class KToggleAction;
+class Equalizer;
+class VideoSettings;
+class FilterDialog;
+class PositionSlider;
+class KProgressDialog;
+class KPopupMenu;
+
+/**
+ * Kaffeine Part - xine based player part
+ * @author Jürgen Kofler <kaffeine@gmx.net>
+ *
+ */
+class XinePart : public KaffeinePart, public XinePartIface
+{
+ Q_OBJECT
+public:
+ XinePart(QWidget*, const char*, QObject*, const char*, const QStringList&);
+ virtual ~XinePart();
+
+ /*
+ *Reimplemented from KaffeinePart
+ */
+ bool isPlaying();
+ bool isPaused();
+
+ bool hasChapters(); /* e.g. DVD */
+ void playNextChapter();
+ void playPreviousChapter();
+ void setDVDChapter(uint chapter);
+
+ bool hasVideo();
+ QString supportedExtensions();
+ void* engine();
+ uint volume() const; /* percent */
+ uint position() const; /* percent */
+
+ bool closeURL(); /* stops playback and shows kaffeine logo */
+ static KAboutData* createAboutData();
+
+ /*
+ * DCOP functions...
+ */
+ int getContrast();
+ void setContrast(int c);
+ int getBrightness();
+ void setBrightness(int b);
+ void dvdMenuUp();
+ void dvdMenuDown();
+ void dvdMenuLeft();
+ void dvdMenuRight();
+ void dvdMenuSelect();
+ void dvdMenuToggle();
+ void aspectRatioAuto();
+ void aspectRatio4_3();
+ void aspectRatioAnamorphic();
+ void aspectRatioSquare();
+ void aspectRatioDVB();
+ void zoomInX();
+ void zoomOutX();
+ void zoomInY();
+ void zoomOutY();
+ void zoomIn();
+ void zoomOut();
+ void zoomOff();
+ QString screenShot();
+ void nextAudioChannel();
+ void nextSubtitleChannel();
+ void speedFaster();
+ void speedSlower();
+
+public slots:
+ /*
+ * Reimplemented from KaffeinePart
+ */
+ bool openURL(const MRL& mrl);
+ void slotPrepareForFullscreen(bool);
+ void slotPlay(bool forcePlay=false);
+ void slotTogglePause(bool pauseLive=true);
+ void slotSetVolume(uint); /* percent */
+ void slotSetPosition(uint); /* percent */
+ void slotPosPlusSmall();
+ void slotPosMinusSmall();
+ void slotSyncVolume();
+ void slotStop();
+ void slotMute(); /* toggle mute */
+
+ void slotVolumeUp();
+ void slotVolumeDown();
+ void slotPosPlusMedium();
+ void slotPosMinusMedium();
+ void slotPosPlusLarge();
+ void slotPosMinusLarge();
+ void slotJumpIncrement(int);
+ void slotDelaySubTitle();
+ void slotAdvanceSubTitle();
+ void slotAddSubtitle();
+ void slotNextAudioChannel();
+ void slotNextSubtitleChannel();
+ /***************** Private ********************/
+
+private slots:
+ void slotFinalize();
+ void slotTrackPlaying();
+ void slotCheckMoved();
+ void slotNext();
+ void slotPrevious();
+ void slotSaveStream();
+ void slotChannelInfo(const QStringList&, const QStringList&, int, int);
+ void slotSetSubtitle(int);
+ void slotSetAudioChannel(int);
+ void slotNewPosition(int, const QTime&);
+ void slotVolumeChanged(int);
+ void slotPictureSettings();
+ void slotEqualizer();
+ void slotDeinterlaceQuality();
+ void slotFilterDialog();
+ void slotInfo();
+ void slotToggleBroadcastSend();
+ void slotBroadcastReceive();
+ void slotJumpToPosition();
+ void slotButtonTimerPressed();
+ void slotButtonTimerReleased();
+ void slotToggleOsdTimer();
+ void slotScreenshot();
+ void slotConfigXine();
+ void slotError(const QString&);
+ void slotMessage(const QString&);
+ void slotStatus(const QString&);
+ void slotNewTitle();
+ void slotNewLength();
+ void slotNewFrameSize();
+ void slotPlaybackFinished();
+ void slotContextMenu(const QPoint&);
+ void slotDisableAllActions();
+ void slotEnableAllActions();
+ void slotEnablePlayActions();
+ void slotCopyToClipboard();
+ void slotLaunchExternally();
+ void slotLaunchDelayed();
+ void slotFastForward();
+ void slotSlowMotion();
+ void slotSetDVDTitle(const QString&);
+ void slotSetDVDChapter(const QString&);
+ void slotSetDVDAngle(const QString&);
+ void slotDVDMenuLeft();
+ void slotDVDMenuRight();
+ void slotDVDMenuUp();
+ void slotDVDMenuDown();
+ void slotDVDMenuSelect();
+ void slotSetHue(int);
+ void slotSetSaturation(int);
+ void slotSetContrast(int);
+ void slotSetBrightness(int);
+
+private:
+ void initActions();
+ void initConnections();
+ void loadConfig();
+ void saveConfig();
+
+private:
+ QPoint m_oldPosition;
+ QTimer m_posCheckTimer;
+ QTimer m_osdTimerEnabler; /* Provide Long click on timer button */
+ bool m_isOsdTimer; /* Status of Osd Timer (on/off) */
+ int m_timerDirection; /* Counting Up or Down */
+ int m_brightness, m_hue, m_contrast, m_saturation;
+
+ MRL m_mrl;
+ QValueList<MRL> m_playlist;
+ uint m_current;
+ uint m_lastDeinterlaceQuality;
+ QString m_lastDeinterlacerConfig;
+ uint m_broadcastPort;
+ QString m_broadcastAddress;
+
+ QSlider* m_volume;
+ PositionSlider* m_position;
+ QPushButton* m_playTime;
+ uint currentPosition;
+
+ KSelectAction* m_audioChannels;
+ KSelectAction* m_audioVisual;
+ KSelectAction* m_subtitles;
+ KSelectAction* m_dvdChapters;
+ KSelectAction* m_dvdTitles;
+ KSelectAction* m_dvdAngles;
+ KToggleAction* m_deinterlaceEnabled;
+ KToggleAction* m_broadcastSend;
+ KToggleAction* m_pauseButton;
+
+ KXineWidget* m_xine;
+ VideoSettings* m_pictureSettings;
+ Equalizer* m_equalizer;
+ QWidget* m_deinterlacerConfigWidget;
+ FilterDialog* m_filterDialog;
+
+ KPopupMenu* m_embeddedContext;
+
+ /* dvb */
+public:
+ QString TimeShiftFilename;
+
+public slots:
+ void slotDvbOpen( const QString &filename, const QString &chanName, int haveVideo );
+ void getTimeShiftFilename( const QString &filename );
+ void requestForOSD( const QString &text, int duration, int priority );
+ void setDvbCurrentNext( const QString &channelname, const QStringList &list );
+
+signals:
+ void stopDvb();
+ void playerPause();
+ void dvbOSDHide();
+};
+
+
+#include <qslider.h>
+
+class VolumeSlider : public QSlider
+{
+
+public:
+
+ VolumeSlider();
+ ~VolumeSlider();
+
+protected:
+
+ void wheelEvent(QWheelEvent* e);
+ //bool eventFilter(QObject *obj, QEvent *ev);
+};
+
+#endif /* XINEPART_H */
diff --git a/kaffeine/src/player-parts/xine-part/xine_part.rc b/kaffeine/src/player-parts/xine-part/xine_part.rc
new file mode 100644
index 0000000..8d4c1a7
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/xine_part.rc
@@ -0,0 +1,347 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="xine_part" version="21">
+<MenuBar>
+ <Menu name="file">
+ <Menu name="network_broadcasting"><text>&amp;Network Broadcasting</text>
+ <Action name="network_send"/>
+ <Action name="network_receive"/>
+ </Menu>
+ <Separator/>
+ <Action name="file_save_stream"/>
+ <Action name="file_save_screenshot"/>
+ </Menu>
+ <Menu name="player"><text>&amp;Player</text>
+ <Action name="player_play"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ <Separator/>
+ <Action name="player_ff"/>
+ <Action name="player_slowmotion"/>
+ <Separator/>
+ <Action name="player_jump_to"/>
+ <Menu name="navigation"><text>&amp;Navigation</text>
+ <Action name="player_posplus_small"/>
+ <Action name="player_posminus_small"/>
+ <Action name="player_posplus_medium"/>
+ <Action name="player_posminus_medium"/>
+ <Action name="player_posplus_large"/>
+ <Action name="player_posminus_large"/>
+ </Menu>
+ <Separator/>
+ <Menu name="dvd"><text>&amp;DVD</text>
+ <Menu name="dvdnav"><text>&amp;Navigation</text>
+ <Action name="dvdmenuleft"/>
+ <Action name="dvdmenuright"/>
+ <Action name="dvdmenuup"/>
+ <Action name="dvdmenudown"/>
+ <Action name="dvdmenuselect"/>
+ </Menu>
+ <Menu name="dvdmenus"><text>&amp;DVD Menus</text>
+ <Action name="dvd_toggle"/>
+ <Separator/>
+ <Action name="dvd_title"/>
+ <Action name="dvd_root"/>
+ <Action name="dvd_subpicture"/>
+ <Action name="dvd_audio"/>
+ <Action name="dvd_angle"/>
+ <Action name="dvd_part"/>
+ </Menu>
+ <Action name="dvd_title_menu"/>
+ <Action name="dvd_chapter_menu"/>
+ <Action name="dvd_angle_menu"/>
+ </Menu>
+ <Separator/>
+ <Menu name="audio"><text>&amp;Audio</text>
+ <Action name="audio_channels"/>
+ <Action name="next_audio_channels"/>
+ <Action name="audio_visualization"/>
+ <Action name="equalizer"/>
+ <Action name="audio_mute"/>
+ <Action name="volume_increase"/>
+ <Action name="volume_decrease"/>
+ </Menu>
+ <Menu name="video"><text>&amp;Video</text>
+ <Action name="video_deinterlace"/>
+ <Menu name="video_aspect"><text>&amp;Aspect Ratio</text>
+ <Action name="aspect_auto"/>
+ <Action name="aspect_43"/>
+ <Action name="aspect_anamorphic"/>
+ <Action name="aspect_dvb"/>
+ <Action name="aspect_square"/>
+ </Menu>
+ <Menu name="video_zoom"><text>&amp;Zoom</text>
+ <Action name="zoom_off"/>
+ <Action name="zoom_in"/>
+ <Action name="zoom_out"/>
+ <Action name="zoom_in_x"/>
+ <Action name="zoom_out_x"/>
+ <Action name="zoom_in_y"/>
+ <Action name="zoom_out_y"/>
+ </Menu>
+ <Separator/>
+ <Action name="video_deinterlace_quality"/>
+ <Action name="video_picture"/>
+ </Menu>
+ <Menu name="subtitles"><text>&amp;Subtitles</text>
+ <Action name="adv_sub"/>
+ <Action name="delay_sub"/>
+ <Action name="player_subtitles"/>
+ <Action name="next_player_subtitles"/>
+ <Action name="add_subtitle"/>
+ </Menu>
+ <Separator/>
+ <Action name="player_track_info"/>
+ <Action name="player_post_filters"/>
+ </Menu>
+ <Menu name="settings">
+ <Action name="settings_xine_parameter"/>
+ </Menu>
+</MenuBar>
+
+<ToolBar name="snapshotToolBar" hidden="true"><text>Screenshot Toolbar</text>
+ <Action name="file_save_screenshot"/>
+</ToolBar>
+<ToolBar name="controlsToolBar" position="Bottom"><text>Controls Toolbar</text>
+ <Action name="player_previous"/>
+ <Action name="player_play"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+ <Action name="audio_channels"/>
+ <Action name="player_subtitles"/>
+</ToolBar>
+<ToolBar name="volumeToolBar" position="Bottom"><text>Volume Toolbar</text>
+ <Action name="audio_volume"/>
+ <Action name="audio_mute"/>
+</ToolBar>
+<ToolBar name="positionToolBar" fullWidth="true" position="Bottom"><text>Position Toolbar</text>
+ <Action name="player_position"/>
+ <Separator/>
+ <Action name="player_playtime"/>
+</ToolBar>
+
+<Menu name="context_menu">
+ <Action name="player_minimal_mode"/>
+ <Separator/>
+ <Action name="player_play"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ <Action name="file_save_stream"/>
+ <Separator/>
+ <Action name="player_ff"/>
+ <Action name="player_slowmotion"/>
+ <Separator/>
+ <Action name="player_jump_to"/>
+ <Menu name="navigation"><text>&amp;Navigation</text>
+ <Action name="player_posplus_small"/>
+ <Action name="player_posminus_small"/>
+ <Action name="player_posplus_medium"/>
+ <Action name="player_posminus_medium"/>
+ <Action name="player_posplus_large"/>
+ <Action name="player_posminus_large"/>
+ </Menu>
+ <Separator/>
+ <Menu name="dvd"><text>&amp;DVD</text>
+ <Menu name="dvdmenus"><text>&amp;DVD Menus</text>
+ <Action name="dvd_toggle"/>
+ <Separator/>
+ <Action name="dvd_title"/>
+ <Action name="dvd_root"/>
+ <Action name="dvd_subpicture"/>
+ <Action name="dvd_audio"/>
+ <Action name="dvd_angle"/>
+ <Action name="dvd_part"/>
+ </Menu>
+ <Action name="dvd_title_menu"/>
+ <Action name="dvd_chapter_menu"/>
+ <Action name="dvd_angle_menu"/>
+ </Menu>
+ <Separator/>
+ <Action name="audio_channels"/>
+ <Action name="audio_visualization"/>
+ <Action name="audio_mute"/>
+ <Separator/>
+ <Menu name="subtitles"><text>&amp;Subtitles</text>
+    <Action name="adv_sub"/>
+    <Action name="delay_sub"/>
+    <Action name="player_subtitles"/>
+    <Action name="add_subtitle"/>
+   </Menu>
+ <Separator/>
+ <Action name="player_track_info"/>
+</Menu>
+
+<State name="xine_not_ready">
+ <enable>
+ <Action name="player_play"/>
+ </enable>
+ <disable>
+ <Action name="network_send"/>
+ <Action name="file_save_stream"/>
+ <Action name="file_save_screenshot"/>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ <Action name="player_ff"/>
+ <Action name="player_slowmotion"/>
+ <Action name="audio_channels"/>
+ <Action name="audio_visualization"/>
+ <Action name="audio_volume"/>
+ <Action name="audio_mute"/>
+ <Action name="player_position"/>
+ <Action name="player_posplus_small"/>
+ <Action name="player_posminus_small"/>
+ <Action name="player_posplus_medium"/>
+ <Action name="player_posminus_medium"/>
+ <Action name="player_posplus_large"/>
+ <Action name="player_posminus_large"/>
+ <Action name="player_jump_to"/>
+ <Action name="player_playtime"/>
+ <Action name="aspect_auto"/>
+ <Action name="aspect_43"/>
+ <Action name="aspect_anamorphic"/>
+ <Action name="aspect_dvb"/>
+ <Action name="aspect_square"/>
+ <Action name="zoom_off"/>
+ <Action name="zoom_in"/>
+ <Action name="zoom_out"/>
+ <Action name="zoom_in_x"/>
+ <Action name="zoom_out_x"/>
+ <Action name="zoom_in_y"/>
+ <Action name="zoom_out_y"/>
+ <Action name="video_deinterlace"/>
+ <Action name="video_deinterlace_quality"/>
+ <Action name="video_picture"/>
+ <Action name="equalizer"/>
+ <Action name="player_subtitles"/>
+ <Action name="add_subtitle"/>
+ <Action name="dvd_toggle"/>
+ <Action name="dvd_title"/>
+ <Action name="dvd_root"/>
+ <Action name="dvd_subpicture"/>
+ <Action name="dvd_audio"/>
+ <Action name="dvd_angle"/>
+ <Action name="dvd_part"/>
+ <Action name="dvd_title_menu"/>
+ <Action name="dvd_chapter_menu"/>
+ <Action name="dvd_angle_menu"/>
+ <Action name="dvdmenuleft"/>
+ <Action name="dvdmenuright"/>
+ <Action name="dvdmenuup"/>
+ <Action name="dvdmenudown"/>
+ <Action name="dvdmenuselect"/>
+ <Action name="player_track_info"/>
+ <Action name="player_post_filters"/>
+ </disable>
+</State>
+<State name="not_playing">
+ <enable>
+ <Action name="player_play"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ </enable>
+ <disable>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_ff"/>
+ <Action name="player_slowmotion"/>
+ <Action name="player_position"/>
+ <Action name="player_posplus_small"/>
+ <Action name="player_posminus_small"/>
+ <Action name="player_posplus_medium"/>
+ <Action name="player_posminus_medium"/>
+ <Action name="player_posplus_large"/>
+ <Action name="player_posminus_large"/>
+ <Action name="player_jump_to"/>
+ <Action name="player_playtime"/>
+ <Action name="dvd_toggle"/>
+ <Action name="dvd_title"/>
+ <Action name="dvd_root"/>
+ <Action name="dvd_subpicture"/>
+ <Action name="dvd_audio"/>
+ <Action name="dvd_angle"/>
+ <Action name="dvd_part"/>
+ <Action name="dvd_title_menu"/>
+ <Action name="dvd_chapter_menu"/>
+ <Action name="dvd_angle_menu"/>
+ <Action name="dvdmenuleft"/>
+ <Action name="dvdmenuright"/>
+ <Action name="dvdmenuup"/>
+ <Action name="dvdmenudown"/>
+ <Action name="dvdmenuselect"/>
+ </disable>
+</State>
+<State name="play_single_track">
+ <enable>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_ff"/>
+ <Action name="player_slowmotion"/>
+ <Action name="player_position"/>
+ <Action name="player_posplus_small"/>
+ <Action name="player_posminus_small"/>
+ <Action name="player_posplus_medium"/>
+ <Action name="player_posminus_medium"/>
+ <Action name="player_posplus_large"/>
+ <Action name="player_posminus_large"/>
+ <Action name="player_jump_to"/>
+ <Action name="player_playtime"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ </enable>
+ <disable>
+ <Action name="player_play"/>
+ </disable>
+</State>
+<State name="play_multiple_tracks">
+ <enable>
+ <Action name="player_pause"/>
+ <Action name="player_stop"/>
+ <Action name="player_next"/>
+ <Action name="player_previous"/>
+ <Action name="player_ff"/>
+ <Action name="player_slowmotion"/>
+ <Action name="player_position"/>
+ <Action name="player_posplus_small"/>
+ <Action name="player_posminus_small"/>
+ <Action name="player_posplus_medium"/>
+ <Action name="player_posminus_medium"/>
+ <Action name="player_posplus_large"/>
+ <Action name="player_posminus_large"/>
+ <Action name="player_jump_to"/>
+ <Action name="player_playtime"/>
+ </enable>
+ <disable>
+ <Action name="player_play"/>
+ </disable>
+</State>
+<State name="paused">
+ <enable>
+ <Action name="player_play"/>
+ </enable>
+</State>
+<State name="dvd_playback">
+ <enable>
+ <Action name="dvd_toggle"/>
+ <Action name="dvd_title"/>
+ <Action name="dvd_root"/>
+ <Action name="dvd_subpicture"/>
+ <Action name="dvd_audio"/>
+ <Action name="dvd_angle"/>
+ <Action name="dvd_part"/>
+ <Action name="dvd_title_menu"/>
+ <Action name="dvd_chapter_menu"/>
+ <Action name="dvd_angle_menu"/>
+ <Action name="dvdmenuleft"/>
+ <Action name="dvdmenuright"/>
+ <Action name="dvdmenuup"/>
+ <Action name="dvdmenudown"/>
+ <Action name="dvdmenuselect"/>
+ </enable>
+</State>
+</kpartgui>
diff --git a/kaffeine/src/player-parts/xine-part/xine_part_iface.h b/kaffeine/src/player-parts/xine-part/xine_part_iface.h
new file mode 100644
index 0000000..4380a84
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/xine_part_iface.h
@@ -0,0 +1,135 @@
+/*
+ * xine_part_iface.h
+ *
+ * Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 XINE_PART_IFACE_H
+#define XINE_PART_IFACE_H
+
+#include <dcopobject.h>
+
+class XinePartIface : virtual public DCOPObject
+{
+ K_DCOP
+public:
+
+k_dcop:
+ /*
+ * Returns the contrast value (0 - 65535).
+ */
+ virtual int getContrast() = 0;
+
+ /*
+ * Set the contrast (0 - 65535).
+ */
+ virtual void setContrast(int c) = 0;
+
+ /*
+ * Returns the brightness value (0 - 65535).
+ */
+ virtual int getBrightness() = 0;
+
+ /*
+ * Set the brightness (0 - 65535).
+ */
+ virtual void setBrightness(int b) = 0;
+
+ /*
+ * Move the menu cursor upwards.
+ */
+ virtual void dvdMenuUp() = 0;
+
+ /*
+ * Move the menu cursor downwards.
+ */
+ virtual void dvdMenuDown() = 0;
+
+ /*
+ * Move the menu cursor to the left.
+ */
+ virtual void dvdMenuLeft() = 0;
+
+ /*
+ * Move the menu cursor to the right.
+ */
+ virtual void dvdMenuRight() = 0;
+
+ /*
+ * Select the menu item pointed by the cursor.
+ */
+ virtual void dvdMenuSelect() = 0;
+
+ /*
+ *Toggle DVD menu on/off
+ */
+ virtual void dvdMenuToggle() = 0;
+
+ /*
+ * Set the aspect ratio automatically.
+ */
+ virtual void aspectRatioAuto() = 0;
+
+ /*
+ * Set the aspect ratio to 4:3.
+ */
+ virtual void aspectRatio4_3() = 0;
+
+ /*
+ * Set the aspect ration to 16:9.
+ */
+ virtual void aspectRatioAnamorphic() = 0;
+
+ /*
+ * Set the aspect ratio to 1:1.
+ */
+ virtual void aspectRatioSquare() = 0;
+
+ /*
+ * Set the aspect ratio to 2.11:1.
+ */
+ virtual void aspectRatioDVB() = 0;
+
+ /*
+ * Zoom in.
+ */
+ virtual void zoomIn() = 0;
+
+ /*
+ * Zoom out.
+ */
+ virtual void zoomOut() = 0;
+
+ /*
+ * Zoom off.
+ */
+ virtual void zoomOff() = 0;
+
+ virtual void zoomInX() = 0;
+ virtual void zoomOutX() = 0;
+ virtual void zoomInY() = 0;
+ virtual void zoomOutY() = 0;
+
+ virtual QString screenShot() = 0;
+
+ virtual void nextAudioChannel() = 0;
+ virtual void nextSubtitleChannel() = 0;
+ virtual void speedFaster() = 0;
+ virtual void speedSlower() = 0;
+};
+
+#endif /* XINE_PART_IFACE_H */
diff --git a/kaffeine/src/player-parts/xine-part/xineconfig.cpp b/kaffeine/src/player-parts/xine-part/xineconfig.cpp
new file mode 100644
index 0000000..55ec752
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/xineconfig.cpp
@@ -0,0 +1,404 @@
+/*
+ * xineconfig.cpp - config dialog for xine parameters
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 <kglobal.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <kpushbutton.h>
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kseparator.h>
+
+#include <qcolor.h>
+#include <qfont.h>
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qtabwidget.h>
+#include <qvbox.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qlabel.h>
+#include <qscrollview.h>
+#include <qsignalmapper.h>
+
+#include "xineconfig.h"
+#include "xineconfig.moc"
+
+#define NON_EXPERT_OPTIONS_DEPRECATED "audio.speaker_arrangement;audio.driver;audio.mixer_software;video.driver;dxr3.device_number;dxr3.enc_add_bars;dxr3.enc_alt_play_mode;input.dvd_language;input.dvd_region;input.cdda_device;input.cdda_use_cddb;input.drive_slowdown;input.dvd_device;input.vcd_device;input.http_no_proxy;input.http_proxy_host;input.http_proxy_password;input.http_proxy_port;input.http_proxy_user;codec.real_codecs_path;codec.win32_path;post.goom_fps;post.goom_height;post.goom_width;misc.spu_subtitle_size;misc.spu_vertical_offset;misc.spu_src_encoding;misc.sub_timeout;osd.osd_messages;vcd.default_device;"
+
+#define NON_EXPERT_OPTIONS_NEW "audio.output.speaker_arrangement;audio.driver;audio.mixer_software;video.driver;dxr3.device_number;dxr3.encoding.add_bars;dxr3.encoding.alt_play_mode;media.dvd.language;media.dvd.region;media.audio_cd.device;media.audio_cd.use_cddb;media.audio_cd.drive_slowdown;media.dvd.device;media.vcd.device;media.network.http_no_proxy;media.network.http_proxy_host;media.network.http_proxy_password;media.network.http_proxy_port;media.network.http_proxy_user;decoder.external.real_codecs_path;decoder.external.win32_codecs_path;effects.goom.csc_method;effects.goom.fps;effects.goom.height;effects.goom.width;subtitles.separate.subtitle_size;subtitles.separate.vertical_offset;subtitles.separate.src_encoding;subtitles.separate.timeout;media.vcd.device;osd.osd_messages;osd.osd_size"
+
+#define NON_EXPERT_OPTIONS NON_EXPERT_OPTIONS_NEW NON_EXPERT_OPTIONS_DEPRECATED
+
+XineConfigEntry::XineConfigEntry(QWidget* parent, QGridLayout* grid, int row, xine_cfg_entry_t* entry) :
+ m_valueChanged(false), m_key(QString(entry->key)), m_numValue(entry->num_value),
+ m_numDefault(entry->num_default), m_stringValue(entry->str_value), m_stringDefault(entry->str_default),
+ m_stringEdit(NULL), m_enumEdit(NULL), m_numEdit(NULL), m_boolEdit(NULL)
+{
+ switch (entry->type)
+ {
+ case XINE_CONFIG_TYPE_UNKNOWN:
+ break;
+ case XINE_CONFIG_TYPE_STRING:
+ {
+ m_stringEdit = new KLineEdit(entry->str_value, parent);
+ if (!strcmp(entry->str_value,entry->str_default))
+ m_stringEdit->setPaletteForegroundColor(QColor(darkMagenta));
+ else
+ m_stringEdit->setPaletteForegroundColor(QColor(black));
+ grid->addWidget(m_stringEdit, row ,0);
+ connect(m_stringEdit, SIGNAL(textChanged(const QString&)), this, SLOT(slotStringChanged(const QString&)));
+ break;
+ }
+ case XINE_CONFIG_TYPE_ENUM:
+ {
+ m_enumEdit = new KComboBox(parent);
+ int i = 0;
+ while (entry->enum_values[i])
+ {
+ m_enumEdit->insertItem(entry->enum_values[i]);
+ i++;
+ }
+ m_enumEdit->setCurrentItem(entry->num_value);
+ if (entry->num_value == entry->num_default)
+ m_enumEdit->setPaletteForegroundColor(QColor(darkMagenta));
+ else
+ m_enumEdit->setPaletteForegroundColor(QColor(black));
+ grid->addWidget(m_enumEdit, row, 0);
+ connect(m_enumEdit, SIGNAL(activated(int)), this, SLOT(slotNumChanged(int)));
+ break;
+ }
+ case XINE_CONFIG_TYPE_NUM:
+ {
+ m_numEdit = new QSpinBox(-999999, 999999, 1, parent);
+ m_numEdit->setValue(entry->num_value);
+ if (entry->num_value == entry->num_default)
+ m_numEdit->setPaletteForegroundColor(QColor(darkMagenta));
+ else
+ m_numEdit->setPaletteForegroundColor(QColor(black));
+ grid->addWidget(m_numEdit, row, 0);
+ connect(m_numEdit, SIGNAL(valueChanged(int)), this, SLOT(slotNumChanged(int)));
+ break;
+ }
+ case XINE_CONFIG_TYPE_RANGE:
+ {
+ m_numEdit = new QSpinBox(parent);
+ m_numEdit->setValue(entry->num_value);
+ m_numEdit->setRange(entry->range_min, entry->range_max);
+ if (entry->num_value == entry->num_default)
+ m_numEdit->setPaletteForegroundColor(QColor(darkMagenta));
+ else
+ m_numEdit->setPaletteForegroundColor(QColor(black));
+ grid->addWidget(m_numEdit, row, 0);
+ connect(m_numEdit, SIGNAL(valueChanged(int)), this, SLOT(slotNumChanged(int)));
+ break;
+ }
+ case XINE_CONFIG_TYPE_BOOL:
+ {
+ m_boolEdit = new QCheckBox(parent);
+ m_boolEdit->setChecked(entry->num_value);
+ if (entry->num_value == entry->num_default)
+ m_boolEdit->setPaletteForegroundColor(QColor(darkMagenta));
+ else
+ m_boolEdit->setPaletteForegroundColor(QColor(black));
+ grid->addWidget(m_boolEdit, row, 0);
+ connect(m_boolEdit, SIGNAL(toggled(bool)), this, SLOT(slotBoolChanged(bool)));
+ break;
+ }
+ }
+
+ QString m_keyName(entry->key);
+ m_keyName.remove( 0, m_keyName.find(".") + 1 );
+
+ QLabel* description = new QLabel(m_keyName + "\n" + QString::fromLocal8Bit(entry->description), parent);
+ description->setAlignment( QLabel::WordBreak | QLabel::AlignVCenter );
+ grid->addWidget(description, row, 1);
+
+ KSeparator* separator = new KSeparator(KSeparator::Horizontal, parent);
+ grid->addMultiCellWidget(separator, row+1, row+1, 0, 1);
+}
+
+XineConfigEntry::~XineConfigEntry()
+{}
+
+void XineConfigEntry::slotNumChanged(int val)
+{
+ m_numValue = val;
+ m_valueChanged = true;
+
+ if (m_numValue == m_numDefault)
+ {
+ if (m_numEdit)
+ {
+ m_numEdit->setPaletteForegroundColor(darkMagenta);
+ m_numEdit->update();
+ }
+ else
+ {
+ m_enumEdit->setPaletteForegroundColor(darkMagenta);
+ m_enumEdit->update();
+ }
+ }
+ else
+ {
+ if (m_numEdit)
+ {
+ m_numEdit->setPaletteForegroundColor(black);
+ m_numEdit->update();
+ }
+ else
+ {
+ m_enumEdit->setPaletteForegroundColor(black);
+ m_enumEdit->update();
+ }
+ }
+}
+
+void XineConfigEntry::slotBoolChanged(bool val)
+{
+ m_numValue = val;
+ m_valueChanged = true;
+ if (m_numValue == m_numDefault)
+ {
+ m_boolEdit->setPaletteForegroundColor(QColor(darkMagenta));
+ m_boolEdit->update();
+ }
+ else
+ {
+ m_boolEdit->setPaletteForegroundColor(QColor(black));
+ m_boolEdit->update();
+ }
+}
+
+void XineConfigEntry::slotStringChanged(const QString& val)
+{
+ m_stringValue = val;
+ m_valueChanged = true;
+ if (m_stringValue == m_stringDefault)
+ {
+ m_stringEdit->setPaletteForegroundColor(QColor(darkMagenta));
+ m_stringEdit->update();
+ }
+ else
+ {
+ m_stringEdit->setPaletteForegroundColor(QColor(black));
+ m_stringEdit->update();
+ }
+}
+
+bool XineConfigEntry::valueChanged() const
+{
+ return m_valueChanged;
+}
+
+const QString& XineConfigEntry::getKey() const
+{
+ return m_key;
+}
+
+int XineConfigEntry::getNumValue() const
+{
+ return m_numValue;
+}
+
+const QString& XineConfigEntry::getStringValue() const
+{
+ return m_stringValue;
+}
+
+
+/************** XINE CONFIG CLASS **************************/
+
+XineConfig::XineConfig(const xine_t* const xine) :
+ KDialogBase(KDialogBase::IconList, i18n("xine Engine Parameters"),
+ KDialogBase::Ok|KDialogBase::Apply|KDialogBase::Cancel, KDialogBase::Cancel)
+
+{
+ setInitialSize(QSize(650,500), true);
+
+ m_xine = (xine_t*)xine;
+
+ QStringList cats = getCategories();
+ QTabWidget* tabWidget = NULL;
+ QFrame* xineFrame = NULL;
+ QVBoxLayout* xineLayout = NULL;
+ QVBox* xineBeginnerPage = NULL;
+ QVBox* xineExpertPage = NULL;
+ QString icon;
+
+ QStringList::ConstIterator end ( cats.end());
+ for (QStringList::ConstIterator it = cats.begin(); it != end; ++it)
+ {
+ // kdDebug() << "XineConfig: add page: " << *it << endl;
+ if (*it == "audio")
+ icon = "sound";
+ else if (*it == "video")
+ icon = "video";
+ else if (*it == "vcd")
+ icon = "cdrom_unmount";
+ else if (*it == "input")
+ icon = "connect_established";
+ else if (*it == "effects")
+ icon = "wizard";
+ else if (*it == "media")
+ icon = "cdrom_unmount";
+ else if (*it == "subtitles")
+ icon = "font_bitmap";
+ else if (*it == "osd")
+ icon = "font_bitmap";
+ else if (*it == "engine")
+ icon = "exec";
+ else
+ icon = "edit";
+
+ xineFrame = addPage(*it, i18n("%1 Options").arg(*it), KGlobal::iconLoader()->loadIcon(icon, KIcon::Panel,
+ KIcon::SizeMedium));
+ xineLayout = new QVBoxLayout(xineFrame, marginHint(), spacingHint());
+ tabWidget = new QTabWidget(xineFrame);
+ xineLayout->addWidget(tabWidget);
+ xineBeginnerPage = new QVBox(tabWidget);
+ xineBeginnerPage->setMargin(5);
+ tabWidget->addTab(xineBeginnerPage, i18n("Beginner Options"));
+ createPage(*it, false, xineBeginnerPage);
+ xineExpertPage = new QVBox(tabWidget);
+ xineExpertPage->setMargin(5);
+ tabWidget->addTab(xineExpertPage, i18n("Expert Options"));
+ createPage(*it, true, xineExpertPage);
+ }
+
+ connect(this, SIGNAL(okClicked()), SLOT(slotOkPressed()));
+ connect(this, SIGNAL(applyClicked()), SLOT(slotApplyPressed()));
+}
+
+XineConfig::~XineConfig()
+{
+ m_entries.setAutoDelete(true);
+ m_entries.clear();
+ kdDebug() << "XineConfig: destructed" << endl;
+}
+
+void XineConfig::createPage(const QString& cat, bool expert, QWidget* parent)
+{
+ xine_cfg_entry_t* ent;
+
+ QScrollView* sv = new QScrollView(parent);
+ sv->setResizePolicy(QScrollView::AutoOneFit);
+ parent = new QWidget(sv->viewport());
+ sv->addChild(parent);
+
+ QGridLayout* grid = new QGridLayout(parent, 20 ,2);
+ grid->setColStretch(1,8);
+ grid->setSpacing(10);
+ grid->setMargin(10);
+
+ uint row = 0;
+ QString entCat;
+
+ /*********** read in xine config entries ***********/
+ ent = new xine_cfg_entry_t;
+ xine_config_get_first_entry(m_xine, ent);
+
+ do
+ {
+ entCat = QString(ent->key);
+ entCat = entCat.left(entCat.find("."));
+ if (entCat == cat)
+ {
+ if (((!expert) && (QString(NON_EXPERT_OPTIONS).contains(ent->key))) ||
+ ((expert) && (!QString(NON_EXPERT_OPTIONS).contains(ent->key))))
+ {
+ m_entries.append(new XineConfigEntry(parent, grid, row, ent));
+ delete ent;
+ ent = new xine_cfg_entry_t;
+ row += 2;
+ }
+ }
+ }
+ while(xine_config_get_next_entry(m_xine, ent));
+
+ delete ent;
+}
+
+const QStringList XineConfig::getCategories()
+{
+ QStringList cats;
+ xine_cfg_entry_t* ent = new xine_cfg_entry_t;
+ if (!xine_config_get_first_entry(m_xine, ent))
+ return cats;
+ QString entCat;
+
+ do
+ {
+ entCat = QString(ent->key);
+ entCat = entCat.left(entCat.find("."));
+ if (cats.findIndex(entCat) == -1)
+ {
+ // kdDebug() << "XineConfig: new category: " << entCat << endl;
+ cats.append(entCat);
+ }
+ delete ent;
+ ent = new xine_cfg_entry_t;
+
+ }
+ while(xine_config_get_next_entry(m_xine, ent));
+
+ delete ent;
+ return cats;
+}
+
+void XineConfig::slotOkPressed()
+{
+ slotApplyPressed();
+ QDialog::close();
+}
+
+/*************** apply changed entries *****************/
+
+void XineConfig::slotApplyPressed()
+{
+ xine_cfg_entry_t *entry;
+
+
+ for(uint i = 0; i < m_entries.count(); i++) /* check all entries */
+ {
+ if (m_entries.at(i)->valueChanged()) /* changed? */
+ {
+ entry = new xine_cfg_entry_t;
+ if (xine_config_lookup_entry(m_xine, m_entries.at(i)->getKey().ascii(), entry))
+ {
+ kdDebug() << "XineConfig: Apply: " << m_entries.at(i)->getKey() << "\n";
+
+ entry->num_value = m_entries.at(i)->getNumValue();
+
+ if (m_entries.at(i)->getStringValue().ascii())
+ entry->str_value = (char*) (const char*)m_entries.at(i)->getStringValue().latin1();
+
+ xine_config_update_entry(m_xine, entry);
+ delete entry;
+
+ m_entries.at(i)->setValueUnchanged();
+ }
+ }
+ }
+}
diff --git a/kaffeine/src/player-parts/xine-part/xineconfig.h b/kaffeine/src/player-parts/xine-part/xineconfig.h
new file mode 100644
index 0000000..c3c7532
--- /dev/null
+++ b/kaffeine/src/player-parts/xine-part/xineconfig.h
@@ -0,0 +1,96 @@
+/*
+ * xineconfig.h - config dialog for xine parameters
+ *
+ * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
+ *
+ * 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 XINECONFIG_H
+#define XINECONFIG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+class KLineEdit;
+class KComboBox;
+class QWidget;
+class QHBox;
+class QCheckBox;
+class QSpinBox;
+class QStringList;
+class QGridLayout;
+
+#include <xine.h>
+
+/* stores a single config entry of the config file */
+class XineConfigEntry : public QHBox
+{
+ Q_OBJECT
+public:
+ XineConfigEntry(QWidget* parent, QGridLayout* grid, int row, xine_cfg_entry_t* entry);
+ ~XineConfigEntry();
+
+ bool valueChanged() const; /* was the value changed by user? */
+ const QString& getKey() const; /* the key (name) of the entry */
+ int getNumValue() const;
+ const QString& getStringValue() const;
+ void setValueUnchanged()
+ {
+ m_valueChanged = false;
+ }
+
+private slots:
+ void slotNumChanged(int);
+ void slotBoolChanged(bool);
+ void slotStringChanged(const QString&);
+
+private:
+ bool m_valueChanged;
+ QString m_key;
+ int m_numValue;
+ int m_numDefault;
+ QString m_stringValue;
+ QString m_stringDefault;
+
+ KLineEdit* m_stringEdit;
+ KComboBox* m_enumEdit;
+ QSpinBox* m_numEdit;
+ QCheckBox* m_boolEdit;
+};
+
+
+class XineConfig : public KDialogBase
+{
+ Q_OBJECT
+public:
+ XineConfig(const xine_t* const xine);
+ ~XineConfig();
+
+private slots:
+ void slotOkPressed();
+ void slotApplyPressed();
+
+private:
+ void createPage(const QString& cat, bool expert, QWidget* parent);
+ const QStringList getCategories();
+
+private:
+ QPtrList<XineConfigEntry> m_entries;
+ xine_t* m_xine;
+};
+
+#endif /* XINECONFIG_H */