dbus support for kaffeine

View: New views
10 Messages — Rating Filter:   Alert me  

dbus support for kaffeine

by Pascal Pollet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I sent an email to this mailing list with a patch attached one hour ago,
but now I looked at the mailing list archive
(http://sourceforge.net/mailarchive/forum.php?forum_name=kaffeine-devel),
and it seems that only the patch reached the mailing list, and not the
body of the email. Is this maybe a sourceforge bug? So I send the mail
again, without the patch this time:


Hello guys,

I am since the very beginning of kaffeine a great fan of this
application and use it for watching movies and TV. In the new version, I
miss a dbus interface to be able to use my remote control for watching
TV. As I know a little bit of C++ and Qt, I decided to implement the
dbus features for kaffeine, btw. giving me the occasion to learn how to
do this. Here is a small patch which makes two functions of dvbtab.cpp
available for dbus: previousChannel() and nextChannel(). It is just a
minimal proof of principle, to show you how I would implement the dbus
functionality. I would be really happy to contribute to this cool
project, so if you are interested in my code, please tell me. I would
add dbus support for all functions which should be accessible from the
outside world.

For my developer background, I like to contribute with mostly small
patches to various open-source projects, and I am the guy from this
project: http://www.bongosoft.de (german page!).
Newly, I also started this one:
http://www.kde-look.org/content/show.php/Babeleo+translator?content=110491
In "real life" I am about to finalize a Ph.D. in bioinformatics in the
nice town of Freiburg/Germany...

I am both French and German, so you can talk to me in any of these
languages, naturally also in English.

The patch is against revision 1042616 of the SVN tree.

greetings,
Pascal





diff -Naur ../kaffeine_ori/src/CMakeLists.txt ./src/CMakeLists.txt
--- ../kaffeine_ori/src/CMakeLists.txt 2009-10-30 10:34:30.000000000 +0100
+++ ./src/CMakeLists.txt 2009-10-30 11:08:47.000000000 +0100
@@ -2,6 +2,7 @@
     dvb/dvbchannel.cpp
     dvb/dvbchannelui.cpp
     dvb/dvbconfigdialog.cpp
+    dvb/dvbdbusadaptor.cpp
     dvb/dvbdevice.cpp
     dvb/dvbepg.cpp
     dvb/dvbmanager.cpp
diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp ./src/dvb/dvbdbusadaptor.cpp
--- ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp 1970-01-01 01:00:00.000000000 +0100
+++ ./src/dvb/dvbdbusadaptor.cpp 2009-10-30 11:08:47.000000000 +0100
@@ -0,0 +1,19 @@
+#include "dvbdbusadaptor.h"
+#include "dvbtab.h"
+
+
+dvbdbusadaptor::dvbdbusadaptor(QWidget* dvbtab)
+: QDBusAbstractAdaptor(dvbtab)
+{
+ dtab = dynamic_cast<DvbTab*>(dvbtab);
+}
+
+Q_NOREPLY void dvbdbusadaptor::previousTvChannel()
+{
+ dtab->previousChannel();
+}
+
+Q_NOREPLY void dvbdbusadaptor::nextTvChannel()
+{
+ dtab->nextChannel();
+}
diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.h ./src/dvb/dvbdbusadaptor.h
--- ../kaffeine_ori/src/dvb/dvbdbusadaptor.h 1970-01-01 01:00:00.000000000 +0100
+++ ./src/dvb/dvbdbusadaptor.h 2009-10-30 11:08:47.000000000 +0100
@@ -0,0 +1,19 @@
+#include <QDBusAbstractAdaptor>
+
+class DvbTab;
+
+class dvbdbusadaptor: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.kde.kaffeine")
+
+private:
+ DvbTab* dtab;
+
+public:
+ dvbdbusadaptor(QWidget* dvbTab);
+  
+public slots:
+ void nextTvChannel();
+ void previousTvChannel();
+};
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.cpp ./src/dvb/dvbtab.cpp
--- ../kaffeine_ori/src/dvb/dvbtab.cpp 2009-10-30 10:34:30.000000000 +0100
+++ ./src/dvb/dvbtab.cpp 2009-10-30 11:08:47.000000000 +0100
@@ -21,6 +21,7 @@
 #include "dvbtab.h"
 
 #include <QBoxLayout>
+#include <QDBusConnection>
 #include <QDir>
 #include <QHeaderView>
 #include <QPainter>
@@ -37,6 +38,7 @@
 #include "../osdwidget.h"
 #include "dvbchannelui.h"
 #include "dvbconfigdialog.h"
+#include "dvbdbusadaptor.h"
 #include "dvbepg.h"
 #include "dvbmanager.h"
 #include "dvbrecording.h"
@@ -424,6 +426,10 @@
 
  dvbOsdTimer = new QTimer(this);
  connect(dvbOsdTimer, SIGNAL(timeout()), this, SLOT(osdTimeout()));
+
+ new dvbdbusadaptor(this);
+ QDBusConnection::sessionBus().registerObject("/DVB", this);
+ QDBusConnection::sessionBus().registerService("org.kde.kaffeine");
 }
 
 DvbTab::~DvbTab()
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.h ./src/dvb/dvbtab.h
--- ../kaffeine_ori/src/dvb/dvbtab.h 2009-10-30 10:34:30.000000000 +0100
+++ ./src/dvb/dvbtab.h 2009-10-30 11:08:47.000000000 +0100
@@ -42,6 +42,8 @@
 class DvbTab : public TabBase
 {
  Q_OBJECT
+ friend class dvbdbusadaptor;
+
 public:
  DvbTab(KMenu *menu, KActionCollection *collection, MediaWidget *mediaWidget_);
  ~DvbTab();

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Bugzilla from christophpfister@gmail.com :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/10/30 Pascal Pollet <pascal@...>:
> Hi,
>
> I sent an email to this mailing list with a patch attached one hour ago,
> but now I looked at the mailing list archive
> (http://sourceforge.net/mailarchive/forum.php?forum_name=kaffeine-devel),
> and it seems that only the patch reached the mailing list, and not the
> body of the email.

Right, there seems to be a problem (I'll take care of it).

> Is this maybe a sourceforge bug? So I send the mail
> again, without the patch this time:
>
>
> Hello guys,
>
> I am since the very beginning of kaffeine a great fan of this
> application and use it for watching movies and TV. In the new version, I
> miss a dbus interface to be able to use my remote control for watching
> TV. As I know a little bit of C++ and Qt, I decided to implement the
> dbus features for kaffeine, btw. giving me the occasion to learn how to
> do this. Here is a small patch which makes two functions of dvbtab.cpp
> available for dbus: previousChannel() and nextChannel(). It is just a
> minimal proof of principle, to show you how I would implement the dbus
> functionality. I would be really happy to contribute to this cool
> project, so if you are interested in my code, please tell me. I would
> add dbus support for all functions which should be accessible from the
> outside world.

I appreciate contributions (I have to code less; you learn something
;-). See below for a (short, I'm sorry) feedback.

> For my developer background, I like to contribute with mostly small
> patches to various open-source projects, and I am the guy from this
> project: http://www.bongosoft.de (german page!).
> Newly, I also started this one:
> http://www.kde-look.org/content/show.php/Babeleo+translator?content=110491
> In "real life" I am about to finalize a Ph.D. in bioinformatics in the
> nice town of Freiburg/Germany...
>
> I am both French and German, so you can talk to me in any of these
> languages, naturally also in English.
>
> The patch is against revision 1042616 of the SVN tree.
>
> greetings,
> Pascal

> diff -Naur ../kaffeine_ori/src/CMakeLists.txt ./src/CMakeLists.txt
> --- ../kaffeine_ori/src/CMakeLists.txt  2009-10-30 10:34:30.000000000 +0100
> +++ ./src/CMakeLists.txt        2009-10-30 11:08:47.000000000 +0100
> @@ -2,6 +2,7 @@
>     dvb/dvbchannel.cpp
>     dvb/dvbchannelui.cpp
>     dvb/dvbconfigdialog.cpp
> +    dvb/dvbdbusadaptor.cpp

please place the file in the src/ directory and call it dbusadaptor.cpp

>     dvb/dvbdevice.cpp
>     dvb/dvbepg.cpp
>     dvb/dvbmanager.cpp
> diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.h ./src/dvb/dvbdbusadaptor.h
> --- ../kaffeine_ori/src/dvb/dvbdbusadaptor.h    1970-01-01 01:00:00.000000000 +0100
> +++ ./src/dvb/dvbdbusadaptor.h  2009-10-30 11:08:47.000000000 +0100
> @@ -0,0 +1,19 @@

use a header include guard =
#ifndef DBUSADAPTOR_H
#define DBUSADAPTOR_H

...

#endif

> +#include <QDBusAbstractAdaptor>
> +
> +class DvbTab;
> +
> +class dvbdbusadaptor: public QDBusAbstractAdaptor
> +{
> +       Q_OBJECT
> +       Q_CLASSINFO("D-Bus Interface", "org.kde.kaffeine")
> +
> +private:
> +       DvbTab* dtab;
> +
> +public:
> +       dvbdbusadaptor(QWidget* dvbTab);
> +
> +public slots:
> +       void nextTvChannel();
> +       void previousTvChannel();

please call those slots previous() and next()

> +};
> diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp ./src/dvb/dvbdbusadaptor.cpp
> --- ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp  1970-01-01 01:00:00.000000000 +0100
> +++ ./src/dvb/dvbdbusadaptor.cpp        2009-10-30 11:08:47.000000000 +0100
> @@ -0,0 +1,19 @@
> +#include "dvbdbusadaptor.h"
> +#include "dvbtab.h"
> +
> +
> +dvbdbusadaptor::dvbdbusadaptor(QWidget* dvbtab)
> +: QDBusAbstractAdaptor(dvbtab)
> +{
> +       dtab = dynamic_cast<DvbTab*>(dvbtab);

avoid dynamic casts

> +}
> +
> +Q_NOREPLY void dvbdbusadaptor::previousTvChannel()
> +{
> +       dtab->previousChannel();

call mediaWidget->previous()

> +}
> +
> +Q_NOREPLY void dvbdbusadaptor::nextTvChannel()
> +{
> +       dtab->nextChannel();

call mediaWidget->next()

> +}
> diff -Naur ../kaffeine_ori/src/dvb/dvbtab.cpp ./src/dvb/dvbtab.cpp
> --- ../kaffeine_ori/src/dvb/dvbtab.cpp  2009-10-30 10:34:30.000000000 +0100
> +++ ./src/dvb/dvbtab.cpp        2009-10-30 11:08:47.000000000 +0100
> @@ -21,6 +21,7 @@
>  #include "dvbtab.h"
>
>  #include <QBoxLayout>
> +#include <QDBusConnection>
>  #include <QDir>
>  #include <QHeaderView>
>  #include <QPainter>
> @@ -37,6 +38,7 @@
>  #include "../osdwidget.h"
>  #include "dvbchannelui.h"
>  #include "dvbconfigdialog.h"
> +#include "dvbdbusadaptor.h"
>  #include "dvbepg.h"
>  #include "dvbmanager.h"
>  #include "dvbrecording.h"
> @@ -424,6 +426,10 @@
>
>        dvbOsdTimer = new QTimer(this);
>        connect(dvbOsdTimer, SIGNAL(timeout()), this, SLOT(osdTimeout()));
> +
> +       new dvbdbusadaptor(this);
> +       QDBusConnection::sessionBus().registerObject("/DVB", this);
> +       QDBusConnection::sessionBus().registerService("org.kde.kaffeine");

initialise the adapter from Kaffeine::Kaffeine()

>  }
>
>  DvbTab::~DvbTab()
> diff -Naur ../kaffeine_ori/src/dvb/dvbtab.h ./src/dvb/dvbtab.h
> --- ../kaffeine_ori/src/dvb/dvbtab.h    2009-10-30 10:34:30.000000000 +0100
> +++ ./src/dvb/dvbtab.h  2009-10-30 11:08:47.000000000 +0100
> @@ -42,6 +42,8 @@
>  class DvbTab : public TabBase
>  {
>        Q_OBJECT
> +       friend class dvbdbusadaptor;
> +
>  public:
>        DvbTab(KMenu *menu, KActionCollection *collection, MediaWidget *mediaWidget_);
>        ~DvbTab();

Thanks,

Christoph

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Pascal Pollet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thank you for your feedback Christoph, I'll consider the points you
mentioned and try to implement the complete dbus-functionality in the
very near future. Maybe I'll come up with some questions if things are
unclear, we'll see :)

cheers,
Pascal


Christoph Pfister schrieb:

> 2009/10/30 Pascal Pollet <pascal@...>:
>  
>> Hi,
>>
>> I sent an email to this mailing list with a patch attached one hour ago,
>> but now I looked at the mailing list archive
>> (http://sourceforge.net/mailarchive/forum.php?forum_name=kaffeine-devel),
>> and it seems that only the patch reached the mailing list, and not the
>> body of the email.
>>    
>
> Right, there seems to be a problem (I'll take care of it).
>
>  
>> Is this maybe a sourceforge bug? So I send the mail
>> again, without the patch this time:
>>
>>
>> Hello guys,
>>
>> I am since the very beginning of kaffeine a great fan of this
>> application and use it for watching movies and TV. In the new version, I
>> miss a dbus interface to be able to use my remote control for watching
>> TV. As I know a little bit of C++ and Qt, I decided to implement the
>> dbus features for kaffeine, btw. giving me the occasion to learn how to
>> do this. Here is a small patch which makes two functions of dvbtab.cpp
>> available for dbus: previousChannel() and nextChannel(). It is just a
>> minimal proof of principle, to show you how I would implement the dbus
>> functionality. I would be really happy to contribute to this cool
>> project, so if you are interested in my code, please tell me. I would
>> add dbus support for all functions which should be accessible from the
>> outside world.
>>    
>
> I appreciate contributions (I have to code less; you learn something
> ;-). See below for a (short, I'm sorry) feedback.
>
>  
>> For my developer background, I like to contribute with mostly small
>> patches to various open-source projects, and I am the guy from this
>> project: http://www.bongosoft.de (german page!).
>> Newly, I also started this one:
>> http://www.kde-look.org/content/show.php/Babeleo+translator?content=110491
>> In "real life" I am about to finalize a Ph.D. in bioinformatics in the
>> nice town of Freiburg/Germany...
>>
>> I am both French and German, so you can talk to me in any of these
>> languages, naturally also in English.
>>
>> The patch is against revision 1042616 of the SVN tree.
>>
>> greetings,
>> Pascal
>>    
>
>  
>> diff -Naur ../kaffeine_ori/src/CMakeLists.txt ./src/CMakeLists.txt
>> --- ../kaffeine_ori/src/CMakeLists.txt  2009-10-30 10:34:30.000000000 +0100
>> +++ ./src/CMakeLists.txt        2009-10-30 11:08:47.000000000 +0100
>> @@ -2,6 +2,7 @@
>>     dvb/dvbchannel.cpp
>>     dvb/dvbchannelui.cpp
>>     dvb/dvbconfigdialog.cpp
>> +    dvb/dvbdbusadaptor.cpp
>>    
>
> please place the file in the src/ directory and call it dbusadaptor.cpp
>
>  
>>     dvb/dvbdevice.cpp
>>     dvb/dvbepg.cpp
>>     dvb/dvbmanager.cpp
>> diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.h ./src/dvb/dvbdbusadaptor.h
>> --- ../kaffeine_ori/src/dvb/dvbdbusadaptor.h    1970-01-01 01:00:00.000000000 +0100
>> +++ ./src/dvb/dvbdbusadaptor.h  2009-10-30 11:08:47.000000000 +0100
>> @@ -0,0 +1,19 @@
>>    
>
> use a header include guard =
> #ifndef DBUSADAPTOR_H
> #define DBUSADAPTOR_H
>
> ...
>
> #endif
>
>  
>> +#include <QDBusAbstractAdaptor>
>> +
>> +class DvbTab;
>> +
>> +class dvbdbusadaptor: public QDBusAbstractAdaptor
>> +{
>> +       Q_OBJECT
>> +       Q_CLASSINFO("D-Bus Interface", "org.kde.kaffeine")
>> +
>> +private:
>> +       DvbTab* dtab;
>> +
>> +public:
>> +       dvbdbusadaptor(QWidget* dvbTab);
>> +
>> +public slots:
>> +       void nextTvChannel();
>> +       void previousTvChannel();
>>    
>
> please call those slots previous() and next()
>
>  
>> +};
>> diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp ./src/dvb/dvbdbusadaptor.cpp
>> --- ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp  1970-01-01 01:00:00.000000000 +0100
>> +++ ./src/dvb/dvbdbusadaptor.cpp        2009-10-30 11:08:47.000000000 +0100
>> @@ -0,0 +1,19 @@
>> +#include "dvbdbusadaptor.h"
>> +#include "dvbtab.h"
>> +
>> +
>> +dvbdbusadaptor::dvbdbusadaptor(QWidget* dvbtab)
>> +: QDBusAbstractAdaptor(dvbtab)
>> +{
>> +       dtab = dynamic_cast<DvbTab*>(dvbtab);
>>    
>
> avoid dynamic casts
>
>  
>> +}
>> +
>> +Q_NOREPLY void dvbdbusadaptor::previousTvChannel()
>> +{
>> +       dtab->previousChannel();
>>    
>
> call mediaWidget->previous()
>
>  
>> +}
>> +
>> +Q_NOREPLY void dvbdbusadaptor::nextTvChannel()
>> +{
>> +       dtab->nextChannel();
>>    
>
> call mediaWidget->next()
>
>  
>> +}
>> diff -Naur ../kaffeine_ori/src/dvb/dvbtab.cpp ./src/dvb/dvbtab.cpp
>> --- ../kaffeine_ori/src/dvb/dvbtab.cpp  2009-10-30 10:34:30.000000000 +0100
>> +++ ./src/dvb/dvbtab.cpp        2009-10-30 11:08:47.000000000 +0100
>> @@ -21,6 +21,7 @@
>>  #include "dvbtab.h"
>>
>>  #include <QBoxLayout>
>> +#include <QDBusConnection>
>>  #include <QDir>
>>  #include <QHeaderView>
>>  #include <QPainter>
>> @@ -37,6 +38,7 @@
>>  #include "../osdwidget.h"
>>  #include "dvbchannelui.h"
>>  #include "dvbconfigdialog.h"
>> +#include "dvbdbusadaptor.h"
>>  #include "dvbepg.h"
>>  #include "dvbmanager.h"
>>  #include "dvbrecording.h"
>> @@ -424,6 +426,10 @@
>>
>>        dvbOsdTimer = new QTimer(this);
>>        connect(dvbOsdTimer, SIGNAL(timeout()), this, SLOT(osdTimeout()));
>> +
>> +       new dvbdbusadaptor(this);
>> +       QDBusConnection::sessionBus().registerObject("/DVB", this);
>> +       QDBusConnection::sessionBus().registerService("org.kde.kaffeine");
>>    
>
> initialise the adapter from Kaffeine::Kaffeine()
>
>  
>>  }
>>
>>  DvbTab::~DvbTab()
>> diff -Naur ../kaffeine_ori/src/dvb/dvbtab.h ./src/dvb/dvbtab.h
>> --- ../kaffeine_ori/src/dvb/dvbtab.h    2009-10-30 10:34:30.000000000 +0100
>> +++ ./src/dvb/dvbtab.h  2009-10-30 11:08:47.000000000 +0100
>> @@ -42,6 +42,8 @@
>>  class DvbTab : public TabBase
>>  {
>>        Q_OBJECT
>> +       friend class dvbdbusadaptor;
>> +
>>  public:
>>        DvbTab(KMenu *menu, KActionCollection *collection, MediaWidget *mediaWidget_);
>>        ~DvbTab();
>>    
>
> Thanks,
>
> Christoph
>
>  

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Pascal Pollet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

here is what I've done so far, I think it should add enough d-bus to make most users happy, including me :) Please look at it and tell me what you think of it...

There is one problem left, when selecting a new DVB-channel directly by name or by number, with the (new) functions:

dvbTab::setChannel(const QString &name)
and
DvbTab::setChannel(int number)

changing the channel works, but I didn't manage to have the selection changed to the new channel in the DvbChannelView tree. I don't know how to get a valid QModelIndex that points to the correct DvbChannelModel. Please look at the code and at my comments in DvbTab::setChannel(int number). I tried almost everything and thereby learned a lot about the model / view concept of Qt, but it didn't help me to find the solution... Maybe you already know this probem Christoph, because there is the same issue when kaffeine gets started with the "--tv <channel>" flag: it simply calls DvbTab::playChannel(const QString &name), but it does not select the channel in the DvbChannelView. The problem is that afterwards, calls to MediaWidget::previous() and next() have no effect, because the currently selected channel is not known. I hope that someone more clever than me will solve this issue ;)

cheers,
Pascal







Pascal Pollet schrieb:
Thank you for your feedback Christoph, I'll consider the points you
mentioned and try to implement the complete dbus-functionality in the
very near future. Maybe I'll come up with some questions if things are
unclear, we'll see :)

cheers,
Pascal


Christoph Pfister schrieb:
  
2009/10/30 Pascal Pollet pascal@...:
  
    
Hi,

I sent an email to this mailing list with a patch attached one hour ago,
but now I looked at the mailing list archive
(http://sourceforge.net/mailarchive/forum.php?forum_name=kaffeine-devel),
and it seems that only the patch reached the mailing list, and not the
body of the email.
    
      
Right, there seems to be a problem (I'll take care of it).

  
    
Is this maybe a sourceforge bug? So I send the mail
again, without the patch this time:


Hello guys,

I am since the very beginning of kaffeine a great fan of this
application and use it for watching movies and TV. In the new version, I
miss a dbus interface to be able to use my remote control for watching
TV. As I know a little bit of C++ and Qt, I decided to implement the
dbus features for kaffeine, btw. giving me the occasion to learn how to
do this. Here is a small patch which makes two functions of dvbtab.cpp
available for dbus: previousChannel() and nextChannel(). It is just a
minimal proof of principle, to show you how I would implement the dbus
functionality. I would be really happy to contribute to this cool
project, so if you are interested in my code, please tell me. I would
add dbus support for all functions which should be accessible from the
outside world.
    
      
I appreciate contributions (I have to code less; you learn something
;-). See below for a (short, I'm sorry) feedback.

  
    
For my developer background, I like to contribute with mostly small
patches to various open-source projects, and I am the guy from this
project: http://www.bongosoft.de (german page!).
Newly, I also started this one:
http://www.kde-look.org/content/show.php/Babeleo+translator?content=110491
In "real life" I am about to finalize a Ph.D. in bioinformatics in the
nice town of Freiburg/Germany...

I am both French and German, so you can talk to me in any of these
languages, naturally also in English.

The patch is against revision 1042616 of the SVN tree.

greetings,
Pascal
    
      
  
    
diff -Naur ../kaffeine_ori/src/CMakeLists.txt ./src/CMakeLists.txt
--- ../kaffeine_ori/src/CMakeLists.txt  2009-10-30 10:34:30.000000000 +0100
+++ ./src/CMakeLists.txt        2009-10-30 11:08:47.000000000 +0100
@@ -2,6 +2,7 @@
    dvb/dvbchannel.cpp
    dvb/dvbchannelui.cpp
    dvb/dvbconfigdialog.cpp
+    dvb/dvbdbusadaptor.cpp
    
      
please place the file in the src/ directory and call it dbusadaptor.cpp

  
    
    dvb/dvbdevice.cpp
    dvb/dvbepg.cpp
    dvb/dvbmanager.cpp
diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.h ./src/dvb/dvbdbusadaptor.h
--- ../kaffeine_ori/src/dvb/dvbdbusadaptor.h    1970-01-01 01:00:00.000000000 +0100
+++ ./src/dvb/dvbdbusadaptor.h  2009-10-30 11:08:47.000000000 +0100
@@ -0,0 +1,19 @@
    
      
use a header include guard =
#ifndef DBUSADAPTOR_H
#define DBUSADAPTOR_H

...

#endif

  
    
+#include <QDBusAbstractAdaptor>
+
+class DvbTab;
+
+class dvbdbusadaptor: public QDBusAbstractAdaptor
+{
+       Q_OBJECT
+       Q_CLASSINFO("D-Bus Interface", "org.kde.kaffeine")
+
+private:
+       DvbTab* dtab;
+
+public:
+       dvbdbusadaptor(QWidget* dvbTab);
+
+public slots:
+       void nextTvChannel();
+       void previousTvChannel();
    
      
please call those slots previous() and next()

  
    
+};
diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp ./src/dvb/dvbdbusadaptor.cpp
--- ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp  1970-01-01 01:00:00.000000000 +0100
+++ ./src/dvb/dvbdbusadaptor.cpp        2009-10-30 11:08:47.000000000 +0100
@@ -0,0 +1,19 @@
+#include "dvbdbusadaptor.h"
+#include "dvbtab.h"
+
+
+dvbdbusadaptor::dvbdbusadaptor(QWidget* dvbtab)
+: QDBusAbstractAdaptor(dvbtab)
+{
+       dtab = dynamic_cast<DvbTab*>(dvbtab);
    
      
avoid dynamic casts

  
    
+}
+
+Q_NOREPLY void dvbdbusadaptor::previousTvChannel()
+{
+       dtab->previousChannel();
    
      
call mediaWidget->previous()

  
    
+}
+
+Q_NOREPLY void dvbdbusadaptor::nextTvChannel()
+{
+       dtab->nextChannel();
    
      
call mediaWidget->next()

  
    
+}
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.cpp ./src/dvb/dvbtab.cpp
--- ../kaffeine_ori/src/dvb/dvbtab.cpp  2009-10-30 10:34:30.000000000 +0100
+++ ./src/dvb/dvbtab.cpp        2009-10-30 11:08:47.000000000 +0100
@@ -21,6 +21,7 @@
 #include "dvbtab.h"

 #include <QBoxLayout>
+#include <QDBusConnection>
 #include <QDir>
 #include <QHeaderView>
 #include <QPainter>
@@ -37,6 +38,7 @@
 #include "../osdwidget.h"
 #include "dvbchannelui.h"
 #include "dvbconfigdialog.h"
+#include "dvbdbusadaptor.h"
 #include "dvbepg.h"
 #include "dvbmanager.h"
 #include "dvbrecording.h@.../DVB", this);
+       QDBusConnection::sessionBus().registerService("org.kde.kaffeine");
    
      
initialise the adapter from Kaffeine::Kaffeine()

  
    
 }

 DvbTab::~DvbTab()
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.h ./src/dvb/dvbtab.h
--- ../kaffeine_ori/src/dvb/dvbtab.h    2009-10-30 10:34:30.000000000 +0100
+++ ./src/dvb/dvbtab.h  2009-10-30 11:08:47.000000000 +0100
@@ -42,6 +42,8 @@
 class DvbTab : public TabBase
 {
       Q_OBJECT
+       friend class dvbdbusadaptor;
+
 public:
       DvbTab(KMenu *menu, KActionCollection *collection, MediaWidget *mediaWidget_);
       ~DvbTab();
    
      
Thanks,

Christoph

  
    

  

diff -Naur ../kaffeine_ori/src/CMakeLists.txt ./src/CMakeLists.txt
--- ../kaffeine_ori/src/CMakeLists.txt 2009-11-05 09:13:12.000000000 +0100
+++ ./src/CMakeLists.txt 2009-11-05 23:26:07.000000000 +0100
@@ -14,6 +14,7 @@
     playlist/playlistmodel.cpp
     playlist/playlisttab.cpp
     datetimeedit.cpp
+    dbusadaptor.cpp
     kaffeine.cpp
     main.cpp
     mediawidget.cpp
diff -Naur ../kaffeine_ori/src/dbusadaptor.cpp ./src/dbusadaptor.cpp
--- ../kaffeine_ori/src/dbusadaptor.cpp 1970-01-01 01:00:00.000000000 +0100
+++ ./src/dbusadaptor.cpp 2009-11-05 23:26:08.000000000 +0100
@@ -0,0 +1,171 @@
+#include "dbusadaptor.h"
+#include "mediawidget.h"
+
+#include <KUrl>
+
+
+DbusAdaptor::DbusAdaptor(MediaWidget *mediaWidget_)
+: QDBusAbstractAdaptor(mediaWidget_), mediaWidget(mediaWidget_)
+{ }
+
+DbusAdaptor::~DbusAdaptor() { }
+
+void DbusAdaptor::previous()
+{
+ mediaWidget->previous();
+}
+
+void DbusAdaptor::playPause()
+{
+ mediaWidget->playPause();
+}
+
+void DbusAdaptor::next()
+{
+ mediaWidget->next();
+}
+
+void DbusAdaptor::toggleMuted()
+{
+ mediaWidget->toggleMuted();
+}
+
+void DbusAdaptor::increaseVolume()
+{
+ mediaWidget->increaseVolume();
+}
+
+void DbusAdaptor::decreaseVolume()
+{
+ mediaWidget->decreaseVolume();
+}
+
+void  DbusAdaptor::changeAudioChannel(int index)
+{
+ mediaWidget->changeAudioChannel(index);
+}
+
+void  DbusAdaptor::changeSubtitle(int index)
+{
+ mediaWidget->changeSubtitle(index);
+}
+
+void  DbusAdaptor::changeVolume(int volume)
+{
+ if ( volume >= 0 && volume <= 100 ) {
+ mediaWidget->changeVolume(volume);
+ }
+}
+
+void DbusAdaptor::setDvbChannel(const QString &name)
+{
+ mediaWidget->setDvbChannel(name);
+}
+
+void DbusAdaptor::setDvbChannelNumber(int number)
+{
+ mediaWidget->setDvbChannel(number);
+}
+
+void DbusAdaptor::setDvbLastChannel()
+{
+ mediaWidget->setDvbLastChannel();
+}
+
+void DbusAdaptor::aspectRatioAuto()
+{
+ mediaWidget->aspectRatioAuto();
+}
+
+void DbusAdaptor::aspectRatio4_3()
+{
+ mediaWidget->aspectRatio4_3();
+}
+
+void DbusAdaptor::aspectRatio16_9()
+{
+ mediaWidget->aspectRatio16_9();
+}
+
+void DbusAdaptor::aspectRatioWidget()
+{
+ mediaWidget->aspectRatioWidget();
+}
+
+void DbusAdaptor::longSkipBackward()
+{
+ mediaWidget->longSkipBackward();
+}
+
+void DbusAdaptor::skipBackward()
+{
+ mediaWidget->skipBackward();
+}
+
+void DbusAdaptor::skipForward()
+{
+ mediaWidget->skipForward();
+}
+
+void DbusAdaptor::longSkipForward()
+{
+ mediaWidget->longSkipForward();
+}
+
+void DbusAdaptor::jumpToPosition()
+{
+ mediaWidget->jumpToPosition();
+}
+
+void DbusAdaptor::timeButtonClicked()
+{
+ mediaWidget->timeButtonClicked();
+}
+
+void DbusAdaptor::updateTimeButton()
+{
+ mediaWidget->updateTimeButton();
+}
+
+void DbusAdaptor::play(const QString &url)
+{
+ KUrl kurl(url);
+ if (kurl.isValid()) {
+ mediaWidget->play(kurl);
+ }
+}
+
+void DbusAdaptor::playAudioCd()
+{
+ mediaWidget->playAudioCd();
+}
+
+void DbusAdaptor::playVideoCd()
+{
+ mediaWidget->playVideoCd();
+}
+
+void DbusAdaptor::playDvd()
+{
+ mediaWidget->playDvd();
+}
+
+void DbusAdaptor::stop()
+{
+ mediaWidget->stop();
+}
+
+void DbusAdaptor::stopDvb()
+{
+ mediaWidget->stopDvb();
+}
+
+void DbusAdaptor::toggleFullScreen()
+{
+ mediaWidget->fullScreen();
+}
+
+void DbusAdaptor::toggleInstantRecord()
+{
+ mediaWidget->toggleInstantRecord();
+}
diff -Naur ../kaffeine_ori/src/dbusadaptor.h ./src/dbusadaptor.h
--- ../kaffeine_ori/src/dbusadaptor.h 1970-01-01 01:00:00.000000000 +0100
+++ ./src/dbusadaptor.h 2009-11-05 23:26:07.000000000 +0100
@@ -0,0 +1,56 @@
+#ifndef DBUSADAPTOR_H
+#define DBUSADAPTOR_H
+
+#include <QDBusAbstractAdaptor>
+#include <QString>
+
+class MediaWidget;
+//class KUrl;
+
+class DbusAdaptor: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.kde.kaffeine")
+
+private:
+ MediaWidget *mediaWidget;
+
+public:
+ DbusAdaptor(MediaWidget *mediaWidget_);
+ ~DbusAdaptor();
+  
+public slots:
+ void next();
+ void previous();
+ void playPause();
+ void changeAudioChannel(int index);
+ void changeSubtitle(int index);
+ void setDvbChannel(const QString &name);
+ void setDvbChannelNumber(int number);
+ void setDvbLastChannel();
+ void toggleMuted();
+ void changeVolume(int volume);
+ void increaseVolume();
+ void decreaseVolume();
+ void aspectRatioAuto();
+ void aspectRatio4_3();
+ void aspectRatio16_9();
+ void aspectRatioWidget();
+ void longSkipBackward();
+ void skipBackward();
+ void skipForward();
+ void longSkipForward();
+ void jumpToPosition();
+ void timeButtonClicked();
+ void updateTimeButton();
+ void play(const QString &url);
+ void playAudioCd();
+ void playVideoCd();
+ void playDvd();
+ void stop();
+ void stopDvb();
+ void toggleFullScreen();
+ void toggleInstantRecord();
+};
+
+#endif /* DBUSADAPTOR_H */
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.cpp ./src/dvb/dvbtab.cpp
--- ../kaffeine_ori/src/dvb/dvbtab.cpp 2009-11-05 09:13:12.000000000 +0100
+++ ./src/dvb/dvbtab.cpp 2009-11-05 23:26:07.000000000 +0100
@@ -117,6 +117,10 @@
 
  connect(mediaWidget, SIGNAL(previousDvbChannel()), this, SLOT(previousChannel()));
  connect(mediaWidget, SIGNAL(nextDvbChannel()), this, SLOT(nextChannel()));
+ connect(mediaWidget, SIGNAL(changeDvbChannel(const QString&)), this, SLOT(setChannel(const QString&)));
+ connect(mediaWidget, SIGNAL(changeDvbChannel(int)), this, SLOT(setChannel(int)));
+ connect(mediaWidget, SIGNAL(dvbLastChannel()), this, SLOT(setLastChannel()));
+ connect(mediaWidget, SIGNAL(toggleInstantRecord()), this, SLOT(toggleInstantRecord()));
 
  connect(manager->getRecordingModel(), SIGNAL(instantRecordingRemoved()),
  this, SLOT(instantRecordingRemoved()));
@@ -144,7 +148,7 @@
  channelView->setRootIsDecorated(false);
 
  if (!channelView->header()->restoreState(QByteArray::fromBase64(
-    KGlobal::config()->group("DVB").readEntry("ChannelViewState", QByteArray())))) {
+ KGlobal::config()->group("DVB").readEntry("ChannelViewState", QByteArray())))) {
  channelView->sortByColumn(0, Qt::AscendingOrder);
  }
 
@@ -210,6 +214,11 @@
  playChannel(manager->getChannelModel()->channelForName(name));
 }
 
+void DvbTab::playChannel(int number)
+{
+ playChannel(manager->getChannelModel()->channelForNumber(number));
+}
+
 void DvbTab::playLastChannel()
 {
  playChannel(KGlobal::config()->group("DVB").readEntry("LastChannel"));
@@ -245,6 +254,19 @@
  dialog.exec();
 }
 
+void DvbTab::toggleInstantRecord()
+{
+ if (instantRecordAction->isChecked()) {
+ instantRecordAction->setChecked(false);
+ instantRecord(false);
+ }
+ else {
+ instantRecordAction->setChecked(true);
+ instantRecord(true);
+ }
+}
+
+
 void DvbTab::instantRecord(bool checked)
 {
  if (checked) {
@@ -353,3 +375,35 @@
  manager->getLiveView()->playChannel(channel);
  }
 }
+
+void DvbTab::setChannel(const QString &name)
+{
+ playChannel(name);
+}
+
+void DvbTab::setChannel(int number)
+{
+ // with this way to get QModelIndex, the later setCurrentIndex(index) call does not work:
+ //QModelIndex index = manager->getChannelModel()->index(number, 0);
+
+ // another way to obtain the QModelIndex, but doesn't work too:
+ DvbChannelModel *channelModel = (DvbChannelModel*) channelView->getModel();
+ QModelIndex index = channelModel->index(number, 0);
+
+ // for testing purposes, returns this runtime error (why?):
+ // QSortFilterProxyModel: index from wrong model passed to mapToSource
+ channelView->mapToSource(index);
+
+ // Has no effect (index from wrong model?):
+ channelView->setCurrentIndex(index);
+
+ // at least this works
+ playChannel(number);
+
+}
+
+void DvbTab::setLastChannel()
+{
+ playLastChannel();
+}
+
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.h ./src/dvb/dvbtab.h
--- ../kaffeine_ori/src/dvb/dvbtab.h 2009-11-05 09:13:12.000000000 +0100
+++ ./src/dvb/dvbtab.h 2009-11-05 23:26:07.000000000 +0100
@@ -38,11 +38,13 @@
 class DvbTab : public TabBase
 {
  Q_OBJECT
+
 public:
  DvbTab(KMenu *menu, KActionCollection *collection, MediaWidget *mediaWidget_);
  ~DvbTab();
 
  void playChannel(const QString &name);
+ void playChannel(int number);
  void playLastChannel();
 
  void enableDvbDump();
@@ -52,12 +54,16 @@
  void showEpgDialog();
  void showRecordingDialog();
  void instantRecord(bool checked);
+ void toggleInstantRecord();
  void instantRecordingRemoved();
  void configureDvb();
  void playLive(const QModelIndex &index);
  void previousChannel();
  void nextChannel();
  void cleanTimeShiftFiles();
+ void setChannel(const QString &name);
+ void setChannel(int number);
+ void setLastChannel();
 
 private:
  void activate();
diff -Naur ../kaffeine_ori/src/kaffeine.cpp ./src/kaffeine.cpp
--- ../kaffeine_ori/src/kaffeine.cpp 2009-11-05 09:13:12.000000000 +0100
+++ ./src/kaffeine.cpp 2009-11-05 23:26:08.000000000 +0100
@@ -20,6 +20,7 @@
 
 #include "kaffeine.h"
 
+#include <QDBusConnection>
 #include <QHoverEvent>
 #include <QLabel>
 #include <QSpinBox>
@@ -38,6 +39,7 @@
 #include <KToolBar>
 #include "dvb/dvbtab.h"
 #include "playlist/playlisttab.h"
+#include "dbusadaptor.h"
 #include "mediawidget.h"
 
 class StartTab : public TabBase
@@ -322,6 +324,11 @@
  // initialize random number generator
  qsrand(QTime().msecsTo(QTime::currentTime()));
 
+ // initialize the dbus-adaptor
+ new DbusAdaptor(mediaWidget);
+ QDBusConnection::sessionBus().registerObject("/Player", mediaWidget);
+ QDBusConnection::sessionBus().registerService("org.kde.kaffeine");
+
  show();
 }
 
diff -Naur ../kaffeine_ori/src/mediawidget.cpp ./src/mediawidget.cpp
--- ../kaffeine_ori/src/mediawidget.cpp 2009-11-05 09:13:12.000000000 +0100
+++ ./src/mediawidget.cpp 2009-11-05 23:26:08.000000000 +0100
@@ -543,6 +543,32 @@
  }
 }
 
+void MediaWidget::setDvbChannel(int number)
+{
+ if (dvbFeed != NULL) {
+ emit changeDvbChannel(number);
+ }
+}
+
+void MediaWidget::setDvbChannel(const QString &name)
+{
+ if (dvbFeed != NULL) {
+ emit changeDvbChannel(name);
+ }
+}
+
+void MediaWidget::setDvbLastChannel()
+{
+ if (dvbFeed != NULL) {
+ emit dvbLastChannel();
+ }
+}
+
+void MediaWidget::fullScreen()
+{
+ emit toggleFullScreen();
+}
+
 void MediaWidget::stateChanged(Phonon::State state)
 {
  bool newPlaying = false;
@@ -655,6 +681,15 @@
  }
 }
 
+void MediaWidget::playPause() {
+ if (actionPlayPause->text() == textPlay) {
+ playPause(false);
+ }
+ else {
+ playPause(true);
+ }
+}
+
 void MediaWidget::stop()
 {
  mediaObject->stop();
@@ -679,7 +714,9 @@
  if ((dvbFeed != NULL) && !dvbFeed->audioChannels.isEmpty()) {
  emit changeDvbAudioChannel(index);
  } else {
- mediaController->setCurrentAudioChannel(audioChannels.at(index));
+ if ( index >= 0 && index < audioChannels.size() ) {
+ mediaController->setCurrentAudioChannel(audioChannels.at(index));
+ }
  }
  }
 }
@@ -690,7 +727,9 @@
  if ((dvbFeed != NULL) && !dvbFeed->subtitles.isEmpty()) {
  emit changeDvbSubtitle(index);
  } else {
- mediaController->setCurrentSubtitle(subtitles.at(index));
+ if ( index >= 0 && index < subtitles.size() ) {
+ mediaController->setCurrentSubtitle(subtitles.at(index));
+ }
  }
  }
 }
diff -Naur ../kaffeine_ori/src/mediawidget.h ./src/mediawidget.h
--- ../kaffeine_ori/src/mediawidget.h 2009-11-05 09:13:12.000000000 +0100
+++ ./src/mediawidget.h 2009-11-05 23:26:07.000000000 +0100
@@ -48,9 +48,11 @@
 class MediaWidget : public QWidget
 {
  Q_OBJECT
+ friend class DbusAdaptor;
+
 public:
  MediaWidget(KMenu *menu_, KAction *fullScreenAction, KToolBar *toolBar,
-    KActionCollection *collection, QWidget *parent);
+ KActionCollection *collection, QWidget *parent);
  ~MediaWidget();
 
  static QString extensionFilter(); // usable for KFileDialog::setFilter()
@@ -98,14 +100,19 @@
  void startDvbTimeShift();
  void changeDvbAudioChannel(int index);
  void changeDvbSubtitle(int index);
+ void changeDvbChannel(int number);
+ void changeDvbChannel(const QString &name);
  void dvbStopped();
  void osdKeyPressed(int key);
+ void dvbLastChannel();
+ void toggleInstantRecord();
 
 private slots:
  void stateChanged(Phonon::State state);
  void playbackFinished();
  void previous();
  void playPause(bool paused);
+ void playPause();
  void next();
  void changeAudioChannel(int index);
  void changeSubtitle(int index);
@@ -135,6 +142,11 @@
  void timeButtonClicked();
  void updateTimeButton();
  void updateCaption();
+ void setDvbChannel(int number);
+ void setDvbChannel(const QString &name);
+ void setDvbLastChannel();
+ void fullScreen();
+
 
  void titleCountChanged(int count);
  void chapterCountChanged(int count);
diff -Naur ../kaffeine_ori/src/proxytreeview.cpp ./src/proxytreeview.cpp
--- ../kaffeine_ori/src/proxytreeview.cpp 2009-11-05 09:13:12.000000000 +0100
+++ ./src/proxytreeview.cpp 2009-11-05 23:26:07.000000000 +0100
@@ -85,6 +85,11 @@
  proxyModel->setSourceModel(model);
 }
 
+QAbstractItemModel* ProxyTreeView::getModel()
+{
+ return proxyModel->sourceModel();
+}
+
 void ProxyTreeView::contextMenuEvent(QContextMenuEvent *event)
 {
  if (!currentIndex().isValid()) {
diff -Naur ../kaffeine_ori/src/proxytreeview.h ./src/proxytreeview.h
--- ../kaffeine_ori/src/proxytreeview.h 2009-11-05 09:13:12.000000000 +0100
+++ ./src/proxytreeview.h 2009-11-05 23:26:08.000000000 +0100
@@ -36,6 +36,7 @@
  QList<int> selectedRows() const;
 
  void setModel(QAbstractItemModel *model);
+ QAbstractItemModel* getModel();
 
 protected:
  void contextMenuEvent(QContextMenuEvent *event);

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Pascal Pollet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

sorry, in my 2 last mails I forgot to respond to this:

I sent an email to this mailing list with a patch attached one hour ago,
but now I looked at the mailing list archive
(http://sourceforge.net/mailarchive/forum.php?forum_name=kaffeine-devel),
and it seems that only the patch reached the mailing list, and not the
body of the email.
    
      
  
Right, there seems to be a problem (I'll take care of it).

I don't think you need to care about this Christoph, I already reported this bug to sourceforge : bug #6149

cheers,
Pascal


Pascal Pollet schrieb:
Hi,

here is what I've done so far, I think it should add enough d-bus to
make most users happy, including me :) Please look at it and tell me
what you think of it...

There is one problem left, when selecting a new DVB-channel directly by
name or by number, with the (new) functions:

dvbTab::setChannel(const QString &name)
and
DvbTab::setChannel(int number)

changing the channel works, but I didn't manage to have the selection
changed to the new channel in the DvbChannelView tree. I don't know how
to get a valid QModelIndex that points to the correct DvbChannelModel.
Please look at the code and at my comments in DvbTab::setChannel(int
number). I tried almost everything and thereby learned a lot about the
model / view concept of Qt, but it didn't help me to find the
solution... Maybe you already know this probem Christoph, because there
is the same issue when kaffeine gets started with the "--tv <channel>"
flag: it simply calls DvbTab::playChannel(const QString &name), but it
does not select the channel in the DvbChannelView. The problem is that
afterwards, calls to MediaWidget::previous() and next() have no effect,
because the currently selected channel is not known. I hope that someone
more clever than me will solve this issue ;)

cheers,
Pascal







Pascal Pollet schrieb:
  
Thank you for your feedback Christoph, I'll consider the points you
mentioned and try to implement the complete dbus-functionality in the
very near future. Maybe I'll come up with some questions if things are
unclear, we'll see :)

cheers,
Pascal


Christoph Pfister schrieb:
  
    
2009/10/30 Pascal Pollet pascal@...:
  
    
      
Hi,

I sent an email to this mailing list with a patch attached one hour ago,
but now I looked at the mailing list archive
(http://sourceforge.net/mailarchive/forum.php?forum_name=kaffeine-devel),
and it seems that only the patch reached the mailing list, and not the
body of the email.
    
      
        
Right, there seems to be a problem (I'll take care of it).

  
    
      
Is this maybe a sourceforge bug? So I send the mail
again, without the patch this time:


Hello guys,

I am since the very beginning of kaffeine a great fan of this
application and use it for watching movies and TV. In the new version, I
miss a dbus interface to be able to use my remote control for watching
TV. As I know a little bit of C++ and Qt, I decided to implement the
dbus features for kaffeine, btw. giving me the occasion to learn how to
do this. Here is a small patch which makes two functions of dvbtab.cpp
available for dbus: previousChannel() and nextChannel(). It is just a
minimal proof of principle, to show you how I would implement the dbus
functionality. I would be really happy to contribute to this cool
project, so if you are interested in my code, please tell me. I would
add dbus support for all functions which should be accessible from the
outside world.
    
      
        
I appreciate contributions (I have to code less; you learn something
;-). See below for a (short, I'm sorry) feedback.

  
    
      
For my developer background, I like to contribute with mostly small
patches to various open-source projects, and I am the guy from this
project: http://www.bongosoft.de (german page!).
Newly, I also started this one:
http://www.kde-look.org/content/show.php/Babeleo+translator?content=110491
In "real life" I am about to finalize a Ph.D. in bioinformatics in the
nice town of Freiburg/Germany...

I am both French and German, so you can talk to me in any of these
languages, naturally also in English.

The patch is against revision 1042616 of the SVN tree.

greetings,
Pascal
    
      
        
  
    
      
diff -Naur ../kaffeine_ori/src/CMakeLists.txt ./src/CMakeLists.txt
--- ../kaffeine_ori/src/CMakeLists.txt  2009-10-30 10:34:30.000000000 +0100
+++ ./src/CMakeLists.txt        2009-10-30 11:08:47.000000000 +0100
@@ -2,6 +2,7 @@
    dvb/dvbchannel.cpp
    dvb/dvbchannelui.cpp
    dvb/dvbconfigdialog.cpp
+    dvb/dvbdbusadaptor.cpp
    
      
        
please place the file in the src/ directory and call it dbusadaptor.cpp

  
    
      
    dvb/dvbdevice.cpp
    dvb/dvbepg.cpp
    dvb/dvbmanager.cpp
diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.h ./src/dvb/dvbdbusadaptor.h
--- ../kaffeine_ori/src/dvb/dvbdbusadaptor.h    1970-01-01 01:00:00.000000000 +0100
+++ ./src/dvb/dvbdbusadaptor.h  2009-10-30 11:08:47.000000000 +0100
@@ -0,0 +1,19 @@
    
      
        
use a header include guard =
#ifndef DBUSADAPTOR_H
#define DBUSADAPTOR_H

...

#endif

  
    
      
+#include <QDBusAbstractAdaptor>
+
+class DvbTab;
+
+class dvbdbusadaptor: public QDBusAbstractAdaptor
+{
+       Q_OBJECT
+       Q_CLASSINFO("D-Bus Interface", "org.kde.kaffeine")
+
+private:
+       DvbTab* dtab;
+
+public:
+       dvbdbusadaptor(QWidget* dvbTab);
+
+public slots:
+       void nextTvChannel();
+       void previousTvChannel();
    
      
        
please call those slots previous() and next()

  
    
      
+};
diff -Naur ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp ./src/dvb/dvbdbusadaptor.cpp
--- ../kaffeine_ori/src/dvb/dvbdbusadaptor.cpp  1970-01-01 01:00:00.000000000 +0100
+++ ./src/dvb/dvbdbusadaptor.cpp        2009-10-30 11:08:47.000000000 +0100
@@ -0,0 +1,19 @@
+#include "dvbdbusadaptor.h"
+#include "dvbtab.h"
+
+
+dvbdbusadaptor::dvbdbusadaptor(QWidget* dvbtab)
+: QDBusAbstractAdaptor(dvbtab)
+{
+       dtab = dynamic_cast<DvbTab*>(dvbtab);
    
      
        
avoid dynamic casts

  
    
      
+}
+
+Q_NOREPLY void dvbdbusadaptor::previousTvChannel()
+{
+       dtab->previousChannel();
    
      
        
call mediaWidget->previous()

  
    
      
+}
+
+Q_NOREPLY void dvbdbusadaptor::nextTvChannel()
+{
+       dtab->nextChannel();
    
      
        
call mediaWidget->next()

  
    
      
+}
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.cpp ./src/dvb/dvbtab.cpp
--- ../kaffeine_ori/src/dvb/dvbtab.cpp  2009-10-30 10:34:30.000000000 +0100
+++ ./src/dvb/dvbtab.cpp        2009-10-30 11:08:47.000000000 +0100
@@ -21,6 +21,7 @@
 #include "dvbtab.h"

 #include <QBoxLayout>
+#include <QDBusConnection>
 #include <QDir>
 #include <QHeaderView>
 #include <QPainter>
@@ -37,6 +38,7 @@
 #include "../osdwidget.h"
 #include "dvbchannelui.h"
 #include "dvbconfigdialog.h"
+#include "dvbdbusadaptor.h"
 #include "dvbepg.h"
 #include "dvbmanager.h"
 #include "dvbrecording.h@.../DVB", this);
+       QDBusConnection::sessionBus().registerService("org.kde.kaffeine");
    
      
        
initialise the adapter from Kaffeine::Kaffeine()

  
    
      
 }

 DvbTab::~DvbTab()
diff -Naur ../kaffeine_ori/src/dvb/dvbtab.h ./src/dvb/dvbtab.h
--- ../kaffeine_ori/src/dvb/dvbtab.h    2009-10-30 10:34:30.000000000 +0100
+++ ./src/dvb/dvbtab.h  2009-10-30 11:08:47.000000000 +0100
@@ -42,6 +42,8 @@
 class DvbTab : public TabBase
 {
       Q_OBJECT
+       friend class dvbdbusadaptor;
+
 public:
       DvbTab(KMenu *menu, KActionCollection *collection, MediaWidget *mediaWidget_);
       ~DvbTab();
    
      
        
Thanks,

Christoph

  
    
      
  
    

  

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Bugzilla from christophpfister@gmail.com :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/11/6 Pascal Pollet <pascal@...>:
<snip>
> I don't think you need to care about this Christoph, I already reported this
> bug to sourceforge : bug #6149

Thanks for the update.

> cheers,
> Pascal

Christoph

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Bugzilla from christophpfister@gmail.com :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

2009/11/6 Pascal Pollet <pascal@...>:
> Hi,
>
> here is what I've done so far, I think it should add enough d-bus to make
> most users happy, including me :) Please look at it and tell me what you
> think of it...

It's a very good starting point. There exists a mediaplayer dbus
specification MPRIS [1], which I consider worth to implement (so that
we don't add yet another dbus interface for common functionality).
I've committed preliminary support to svn (the "root" object). Could
you please adapt your patch to that concept (i.e. add a tracklist and
player object; in case of need just method stubs)? I'm aware of the
fact that the actions defined in that specification don't 100% map
Kaffeine's actions (e.g. Play() doing a rewind to the beginning of a
track), so you don't have to care about those details if you don't
want to do. I also know that not every mpris thing is possible
(especially the tracklist parts needs more work) and that there's not
a mpris thing for every action Kaffeine is able to perform (put them
in a separate object for now).

> There is one problem left, when selecting a new DVB-channel directly by name
> or by number, with the (new) functions:
>
> dvbTab::setChannel(const QString &name)
> and
> DvbTab::setChannel(int number)
>
> changing the channel works, but I didn't manage to have the selection
> changed to the new channel in the DvbChannelView tree. I don't know how to
> get a valid QModelIndex that points to the correct DvbChannelModel. Please
> look at the code and at my comments in DvbTab::setChannel(int number). I
> tried almost everything and thereby learned a lot about the model / view
> concept of Qt, but it didn't help me to find the solution... Maybe you
> already know this probem Christoph, because there is the same issue when
> kaffeine gets started with the "--tv <channel>" flag: it simply calls
> DvbTab::playChannel(const QString &name), but it does not select the channel
> in the DvbChannelView. The problem is that afterwards, calls to
> MediaWidget::previous() and next() have no effect, because the currently
> selected channel is not known. I hope that someone more clever than me will
> solve this issue ;)

Yes, this one is trickier. Note that there exists a similar problem
e.g. with playPause(): you also need to update the ui state.

> cheers,
> Pascal

Thanks,

Christoph


[1] http://wiki.xmms2.xmms.se/wiki/MPRIS

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Pascal Pollet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

> There exists a mediaplayer dbus
> specification MPRIS [1], which I consider worth to implement (so that
> we don't add yet another dbus interface for common functionality).

I fully agree, it' good to have standards.

> I've committed preliminary support to svn (the "root" object).

nice, I'll take it as a starting point.

> Could you please adapt your patch to that concept (i.e. add a tracklist and
> player object; in case of need just method stubs)?
ok, no problem :) Yes for the beginning I will for sure leave some stubs
for the more difficult functions, which can be implemented later...

> I'm aware of the
> fact that the actions defined in that specification don't 100% map
> Kaffeine's actions (e.g. Play() doing a rewind to the beginning of a
> track), so you don't have to care about those details if you don't
> want to do. I also know that not every mpris thing is possible
> (especially the tracklist parts needs more work) and that there's not
> a mpris thing for every action Kaffeine is able to perform (put them
> in a separate object for now).
I'll see what I can do, I already began to port my stuff yesterday... I
would put methods like playPause() or increaseVolume() into the /Player
object even if they are not included in the mpris-specs, because
everything else would be very confusing... All the methods related to
the display (fullscreen, aspect-ratio) could come into an object named
/Display, and all the DVB-related stuff into an object /DVB. This can be
changed very easily later anyway......

In my last patch I forgot a function like the setNumber() function in
kaffeine 0.8 (with a timer for the input of numbers with more than one
digit), which is very important for the use with a remote control. I
will add this, and also a dbus-function to show/hide EPG information,
which I forgot too...

I must say it's really nice to work on kaffeine, because it's codebase
is very well structured and comprehensible, I got into it very fast.
I'll try to not mess it up too much ;)


cheers,
Pascal


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Pascal Pollet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

this e-mail is just to say that I didn't forget what I promised to do, I
simply hadn't much time in the two last weeks. But I think that I will
be able to send you a new patch in the next few days, if nothing gets in
the way... Have a nice week-end!

cheers,
Pascal


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel

Re: dbus support for kaffeine

by Pascal Pollet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

ok, here is the actual state of things. The mpris methods are all implemented, with a few stubs left: a few /TrackList methods still need to be implemented, but I will try to do it soon. The /Player Repeat() function is also a stub, because the playlist does not allow to repeat a single track yet. Also the GetCaps () function is incomplete.

I put much methods into the /Player object which are not part of the mpris specs, because it wouldn't make much sense to make a separate object for them. I think it should be ok, but if you don't agree, please tell me, it' not difficult to change...

I made a DVB/ object for dvb-related stuff and a Display/ object for methods like toggleFullScreen, I'm not sure if "Display" is the best name for that...

There is still a need for a method that allows to enter channel numbers with more than one digit with a remote control (or with the keyboard), I will try to do this in the next time, as for me it's the most important feature which is still missing.

I changed all dbus functions to begin with a capital letter, to be consistent with the mpris methods.

All this isn't thoroughly tested at all and rather crude, and there should certainly be more error checking, but I think this is true for almost all the rest of the app also, so it should be ok for the beginning ;)

changing the channel works, but I didn't manage to have the selection
changed to the new channel in the DvbChannelView tree. I don't know how to
get a valid QModelIndex that points to the correct DvbChannelModel. Please
look at the code and at my comments in DvbTab::setChannel(int number). I
tried almost everything and thereby learned a lot about the model / view
concept of Qt, but it didn't help me to find the solution... Maybe you
already know this probem Christoph, because there is the same issue when
kaffeine gets started with the "--tv <channel>" flag: it simply calls
DvbTab::playChannel(const QString &name), but it does not select the channel
in the DvbChannelView. The problem is that afterwards, calls to
MediaWidget::previous() and next() have no effect, because the currently
selected channel is not known. I hope that someone more clever than me will
solve this issue ;)

Yes, this one is trickier. Note that there exists a similar problem
e.g. with playPause(): you also need to update the ui state.
  
I now found a solution (although I don't know if it's the best), but I don't recognize what should be updated when the playPause() method is called,  you have a better overview for sure...

ciao,
Pascal


Christoph Pfister schrieb:
Hi,

2009/11/6 Pascal Pollet pascal@...:
  
Hi,

here is what I've done so far, I think it should add enough d-bus to make
most users happy, including me :) Please look at it and tell me what you
think of it...
    

It's a very good starting point. There exists a mediaplayer dbus
specification MPRIS [1], which I consider worth to implement (so that
we don't add yet another dbus interface for common functionality).
I've committed preliminary support to svn (the "root" object). Could
you please adapt your patch to that concept (i.e. add a tracklist and
player object; in case of need just method stubs)? I'm aware of the
fact that the actions defined in that specification don't 100% map
Kaffeine's actions (e.g. Play() doing a rewind to the beginning of a
track), so you don't have to care about those details if you don't
want to do. I also know that not every mpris thing is possible
(especially the tracklist parts needs more work) and that there's not
a mpris thing for every action Kaffeine is able to perform (put them
in a separate object for now).

  
There is one problem left, when selecting a new DVB-channel directly by name
or by number, with the (new) functions:

dvbTab::setChannel(const QString &name)
and
DvbTab::setChannel(int number)

changing the channel works, but I didn't manage to have the selection
changed to the new channel in the DvbChannelView tree. I don't know how to
get a valid QModelIndex that points to the correct DvbChannelModel. Please
look at the code and at my comments in DvbTab::setChannel(int number). I
tried almost everything and thereby learned a lot about the model / view
concept of Qt, but it didn't help me to find the solution... Maybe you
already know this probem Christoph, because there is the same issue when
kaffeine gets started with the "--tv <channel>" flag: it simply calls
DvbTab::playChannel(const QString &name), but it does not select the channel
in the DvbChannelView. The problem is that afterwards, calls to
MediaWidget::previous() and next() have no effect, because the currently
selected channel is not known. I hope that someone more clever than me will
solve this issue ;)
    

Yes, this one is trickier. Note that there exists a similar problem
e.g. with playPause(): you also need to update the ui state.

  
cheers,
Pascal
    

Thanks,

Christoph


[1] http://wiki.xmms2.xmms.se/wiki/MPRIS

  

diff -Naur ../kaffeine/src/dbusobjects.cpp ./src/dbusobjects.cpp
--- ../kaffeine/src/dbusobjects.cpp 2009-11-21 23:11:28.000000000 +0100
+++ ./src/dbusobjects.cpp 2009-11-21 23:08:52.000000000 +0100
@@ -23,6 +23,9 @@
 #include <QDBusMetaType>
 #include <KAboutData>
 #include <KApplication>
+#include <KUrl>
+
+#include "mediawidget.h"
 
 QDBusArgument &operator<<(QDBusArgument &argument, const MprisVersionStruct &versionStruct)
 {
@@ -40,9 +43,27 @@
  return argument;
 }
 
+QDBusArgument &operator<<(QDBusArgument &argument, const MprisStatusStruct &statusStruct)
+{
+ argument.beginStructure();
+ argument << statusStruct.play << statusStruct.random << statusStruct.repeatTrack << statusStruct.repeatAll;
+ argument.endStructure();
+ return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, MprisStatusStruct &statusStruct)
+{
+ argument.beginStructure();
+ argument >> statusStruct.play >> statusStruct.random >> statusStruct.repeatTrack >> statusStruct.repeatAll;
+ argument.endStructure();
+ return argument;
+}
+
+
 MprisRootObject::MprisRootObject(QObject *parent) : QObject(parent)
 {
  qDBusRegisterMetaType<MprisVersionStruct>();
+ qDBusRegisterMetaType<MprisStatusStruct>();
 }
 
 MprisRootObject::~MprisRootObject()
@@ -67,3 +88,320 @@
  versionStruct.minor = 0;
  return versionStruct;
 }
+
+MprisPlayerObject::MprisPlayerObject(MediaWidget *mediaWidget_): mediaWidget(mediaWidget_)
+{ }
+
+MprisPlayerObject::~MprisPlayerObject()
+{ }
+
+void MprisPlayerObject::Next()
+{
+ mediaWidget->next();
+}
+
+void MprisPlayerObject::Prev()
+{
+ mediaWidget->previous();
+}
+
+void MprisPlayerObject::PlayPause()
+{
+ mediaWidget->playPause();
+}
+
+void MprisPlayerObject::Play()
+{
+ mediaWidget->play();
+}
+
+void MprisPlayerObject::Pause()
+{
+ mediaWidget->pause();
+}
+
+int MprisPlayerObject::VolumeGet()
+{
+ return mediaWidget->getVolume();
+}
+
+void MprisPlayerObject::VolumeSet(int volume)
+{
+ mediaWidget->changeVolume(volume);
+}
+
+void MprisPlayerObject::VolumeIncrease()
+{
+ mediaWidget->increaseVolume();
+}
+
+void MprisPlayerObject::VolumeDecrease()
+{
+ mediaWidget->decreaseVolume();
+}
+
+int MprisPlayerObject::PositionGet()
+{
+ return mediaWidget->getPosition();
+}
+
+
+void MprisPlayerObject::PositionSet(int position)
+{
+ mediaWidget->setPosition(position);
+}
+
+void MprisPlayerObject::Repeat()
+{
+ //TODO
+ //repeating a single track not implemented yet, only whole playlist
+}
+
+int MprisPlayerObject::GetCaps()
+{
+ int caps = NO_CAPS;
+
+ if ( mediaWidget->hasMedia() )
+ {
+ if ( mediaWidget->isPlaying() && ! mediaWidget->isPaused() )
+ {
+ caps |= CAN_PAUSE;
+ }
+ else
+ {
+ caps |= CAN_PLAY;
+ }
+ }
+
+ caps |= CAN_HAS_TRACKLIST;
+
+ //TODO: CAN_GO_NEXT & CAN_GO_PREV & CAN_PROVIDE_METADATA
+
+ return caps;
+}
+
+void MprisPlayerObject::Stop()
+{
+ mediaWidget->stop();
+}
+
+MprisStatusStruct MprisPlayerObject::GetStatus()
+{
+ MprisStatusStruct statusStruct;
+ if ( mediaWidget->isPaused() )
+ {
+ statusStruct.play = 1;
+ }
+ else if ( mediaWidget->isPlaying() )
+ {
+ statusStruct.play = 0;
+ }
+ else
+ {
+ statusStruct.play = 2;
+ }
+
+ if ( mediaWidget->isRepeat() )
+ {
+ statusStruct.repeatAll = 1;
+ }
+ else
+ {
+ statusStruct.repeatAll = 0;
+ }
+
+ statusStruct.random = 0;
+ statusStruct.repeatTrack = 0;
+
+ return statusStruct;
+}
+
+QVariantMap MprisPlayerObject::GetMetadata()
+{
+ return mediaWidget->getMetadata();
+}
+
+void MprisPlayerObject::Play(const QString &url)
+{
+ KUrl kurl(url);
+ if (kurl.isValid()) {
+ mediaWidget->play(kurl);
+ }
+}
+
+void MprisPlayerObject::PlayAudioCd()
+{
+ mediaWidget->playAudioCd();
+}
+
+void MprisPlayerObject::PlayVideoCd()
+{
+ mediaWidget->playVideoCd();
+}
+
+void MprisPlayerObject::PlayDvd()
+{
+ mediaWidget->playDvd();
+}
+
+void  MprisPlayerObject::ChangeAudioChannel(int index)
+{
+ mediaWidget->changeAudioChannel(index);
+}
+
+void  MprisPlayerObject::ChangeSubtitle(int index)
+{
+ mediaWidget->changeSubtitle(index);
+}
+
+void MprisPlayerObject::ToggleMuted()
+{
+ mediaWidget->toggleMuted();
+}
+
+void MprisPlayerObject::LongSkipBackward()
+{
+ mediaWidget->longSkipBackward();
+}
+
+void MprisPlayerObject::SkipBackward()
+{
+ mediaWidget->skipBackward();
+}
+
+void MprisPlayerObject::SkipForward()
+{
+ mediaWidget->skipForward();
+}
+
+void MprisPlayerObject::LongSkipForward()
+{
+ mediaWidget->longSkipForward();
+}
+
+void MprisPlayerObject::TimeButtonClicked()
+{
+ mediaWidget->timeButtonClicked();
+}
+
+void MprisPlayerObject::UpdateTimeButton()
+{
+ mediaWidget->updateTimeButton();
+}
+
+
+MprisTrackListObject::MprisTrackListObject(MediaWidget *mediaWidget_): mediaWidget(mediaWidget_)
+{ }
+
+MprisTrackListObject::~MprisTrackListObject()
+{ }
+
+QVariantMap MprisTrackListObject::GetMetadata()
+{
+ return mediaWidget->getMetadata();
+}
+
+int MprisTrackListObject::GetCurrentTrack()
+{
+ return mediaWidget->getCurrentTrack();
+}
+
+int MprisTrackListObject::GetLength()
+{
+ return mediaWidget->getLength();
+}
+
+int MprisTrackListObject::AddTrack(QString track, bool play)
+{
+ return mediaWidget->addTrack(track, play);
+}
+
+void MprisTrackListObject::DelTrack(int position)
+{
+ mediaWidget->delTrack(position);
+}
+
+void MprisTrackListObject::SetLoop(bool loop)
+{
+ mediaWidget->setLoop(loop);
+}
+
+void MprisTrackListObject::SetRandom(bool random)
+{
+ mediaWidget->setRandom(random);
+}
+
+
+
+MprisDvbObject::MprisDvbObject(MediaWidget *mediaWidget_): mediaWidget(mediaWidget_)
+{ }
+
+MprisDvbObject::~MprisDvbObject()
+{ }
+
+void MprisDvbObject::SetDvbChannel(const QString &name)
+{
+ mediaWidget->setDvbChannel(name);
+}
+
+void MprisDvbObject::SetDvbChannelNumber(int number)
+{
+ mediaWidget->setDvbChannel(number);
+}
+
+void MprisDvbObject::SetDvbLastChannel()
+{
+ mediaWidget->setDvbLastChannel();
+}
+
+void MprisDvbObject::StopDvb()
+{
+ mediaWidget->stopDvb();
+}
+
+void MprisDvbObject::ToggleInstantRecord()
+{
+ mediaWidget->toggleInstantRecord();
+}
+
+void MprisDvbObject::ToggleOsd()
+{
+ mediaWidget->toggleOsd();
+}
+
+
+
+MprisDisplayObject::MprisDisplayObject(MediaWidget *mediaWidget_): mediaWidget(mediaWidget_)
+{ }
+
+MprisDisplayObject::~MprisDisplayObject()
+{ }
+
+void MprisDisplayObject::ToggleFullScreen()
+{
+ mediaWidget->fullScreen();
+}
+
+void MprisDisplayObject::AspectRatioAuto()
+{
+ mediaWidget->aspectRatioAuto();
+}
+
+void MprisDisplayObject::AspectRatio4_3()
+{
+ mediaWidget->aspectRatio4_3();
+}
+
+void MprisDisplayObject::AspectRatio16_9()
+{
+ mediaWidget->aspectRatio16_9();
+}
+
+void MprisDisplayObject::AspectRatioWidget()
+{
+ mediaWidget->aspectRatioWidget();
+}
+
+
+
+
diff -Naur ../kaffeine/src/dbusobjects.h ./src/dbusobjects.h
--- ../kaffeine/src/dbusobjects.h 2009-11-21 23:11:28.000000000 +0100
+++ ./src/dbusobjects.h 2009-11-21 23:08:52.000000000 +0100
@@ -22,8 +22,12 @@
 #define DBUSOBJECTS_H
 
 #include <QMetaType>
+#include <QVariantMap>
 
 struct MprisVersionStruct;
+struct MprisStatusStruct;
+
+class MediaWidget;
 
 class MprisRootObject : public QObject
 {
@@ -39,6 +43,129 @@
  MprisVersionStruct MprisVersion();
 };
 
+
+class MprisPlayerObject : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.MediaPlayer")
+public:
+ explicit MprisPlayerObject(MediaWidget *mediaWidget_);
+ ~MprisPlayerObject();
+
+public slots:
+ void Next();
+ void Prev();
+ void Play();
+ void Pause();
+ void Stop();
+ int  VolumeGet();
+ void VolumeSet(int volume);
+ int  PositionGet();
+ void PositionSet(int position);
+ void Repeat();
+ MprisStatusStruct GetStatus();
+ QVariantMap GetMetadata();
+ int GetCaps();
+
+ // this functions are not part of the MPRIS specs
+ void PlayPause();
+ void VolumeIncrease();
+ void VolumeDecrease();
+ void Play(const QString &url);
+ void PlayAudioCd();
+ void PlayVideoCd();
+ void PlayDvd();
+ void ChangeAudioChannel(int index);
+ void ChangeSubtitle(int index);
+ void ToggleMuted();
+ void LongSkipBackward();
+ void SkipBackward();
+ void SkipForward();
+ void LongSkipForward();
+ void TimeButtonClicked();
+ void UpdateTimeButton();
+
+signals:
+ void CapsChange( int );
+ void StatusChange( MprisStatusStruct );
+ void TrackChange( QVariantMap );
+
+private:
+ MediaWidget *mediaWidget;
+
+};
+
+
+class MprisTrackListObject : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.MediaPlayer")
+public:
+ explicit MprisTrackListObject(MediaWidget *mediaWidget_);
+ ~MprisTrackListObject();
+
+public slots:
+ QVariantMap GetMetadata();
+ int GetCurrentTrack();
+ int GetLength();
+ int AddTrack(QString track, bool play);
+ void DelTrack(int position);
+ void SetLoop(bool loop);
+ void SetRandom(bool random);
+
+signals:
+ void TrackListChange(int);
+
+private:
+ MediaWidget *mediaWidget;
+
+};
+
+
+class MprisDvbObject : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.MediaPlayer")
+public:
+ explicit MprisDvbObject(MediaWidget *mediaWidget_);
+ ~MprisDvbObject();
+
+public slots:
+ void SetDvbChannel(const QString &name);
+ void SetDvbChannelNumber(int number);
+ void SetDvbLastChannel();
+ void StopDvb();
+ void ToggleInstantRecord();
+ void ToggleOsd();
+
+private:
+ MediaWidget *mediaWidget;
+
+};
+
+
+class MprisDisplayObject : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.MediaPlayer")
+public:
+ explicit MprisDisplayObject(MediaWidget *mediaWidget_);
+ ~MprisDisplayObject();
+
+public slots:
+ void AspectRatioAuto();
+ void AspectRatio4_3();
+ void AspectRatio16_9();
+ void AspectRatioWidget();
+ void ToggleFullScreen();
+
+
+private:
+ MediaWidget *mediaWidget;
+
+};
+
+
 struct MprisVersionStruct
 {
  quint16 major;
@@ -47,4 +174,30 @@
 
 Q_DECLARE_METATYPE(MprisVersionStruct)
 
+struct MprisStatusStruct
+{
+ quint16 play;
+ quint16 random;
+ quint16 repeatTrack;
+ quint16 repeatAll;
+};
+
+Q_DECLARE_METATYPE(MprisStatusStruct)
+
+/**
+* The bit values for the capabilities flags
+*/
+enum Cap {
+ NO_CAPS   = 0,
+ CAN_GO_NEXT   = 1 << 0,
+ CAN_GO_PREV   = 1 << 1,
+ CAN_PAUSE = 1 << 2,
+ CAN_PLAY  = 1 << 3,
+ CAN_SEEK  = 1 << 4,
+ CAN_PROVIDE_METADATA  = 1 << 5,
+ CAN_HAS_TRACKLIST = 1 << 6,
+ ALL_KNOWN_CAPS = (1 << 7) - 1
+};
+Q_DECLARE_FLAGS(Caps, Cap)
+
 #endif /* DBUSOBJECTS_H */
diff -Naur ../kaffeine/src/dvb/dvbliveview.cpp ./src/dvb/dvbliveview.cpp
--- ../kaffeine/src/dvb/dvbliveview.cpp 2009-11-21 23:11:27.000000000 +0100
+++ ./src/dvb/dvbliveview.cpp 2009-11-21 23:08:52.000000000 +0100
@@ -157,6 +157,7 @@
  connect(mediaWidget, SIGNAL(dvbStopped()), this, SLOT(liveStopped()));
 
  connect(mediaWidget, SIGNAL(osdKeyPressed(int)), this, SLOT(osdKeyPressed(int)));
+ connect(mediaWidget, SIGNAL(toggleOsd()), this, SLOT(toggleOsd()));
  connect(&osdChannelTimer, SIGNAL(timeout()), this, SLOT(tuneOsdChannel()));
 }
 
diff -Naur ../kaffeine/src/dvb/dvbtab.cpp ./src/dvb/dvbtab.cpp
--- ../kaffeine/src/dvb/dvbtab.cpp 2009-11-21 23:11:27.000000000 +0100
+++ ./src/dvb/dvbtab.cpp 2009-11-21 23:08:52.000000000 +0100
@@ -117,6 +117,10 @@
 
  connect(mediaWidget, SIGNAL(previousDvbChannel()), this, SLOT(previousChannel()));
  connect(mediaWidget, SIGNAL(nextDvbChannel()), this, SLOT(nextChannel()));
+ connect(mediaWidget, SIGNAL(changeDvbChannel(const QString&)), this, SLOT(setChannel(const QString&)));
+ connect(mediaWidget, SIGNAL(changeDvbChannel(int)), this, SLOT(setChannel(int)));
+ connect(mediaWidget, SIGNAL(dvbLastChannel()), this, SLOT(setLastChannel()));
+ connect(mediaWidget, SIGNAL(toggleInstantRecord()), this, SLOT(toggleInstantRecord()));
 
  connect(manager->getRecordingManager(), SIGNAL(instantRecordingRemoved()),
  this, SLOT(instantRecordingRemoved()));
@@ -144,7 +148,7 @@
  channelView->setRootIsDecorated(false);
 
  if (!channelView->header()->restoreState(QByteArray::fromBase64(
-    KGlobal::config()->group("DVB").readEntry("ChannelViewState", QByteArray())))) {
+ KGlobal::config()->group("DVB").readEntry("ChannelViewState", QByteArray())))) {
  channelView->sortByColumn(0, Qt::AscendingOrder);
  }
 
@@ -210,6 +214,11 @@
  playChannel(manager->getChannelModel()->channelForName(name));
 }
 
+void DvbTab::playChannel(int number)
+{
+ playChannel(manager->getChannelModel()->channelForNumber(number));
+}
+
 void DvbTab::playLastChannel()
 {
  playChannel(KGlobal::config()->group("DVB").readEntry("LastChannel"));
@@ -244,6 +253,19 @@
  dialog.exec();
 }
 
+void DvbTab::toggleInstantRecord()
+{
+ if (instantRecordAction->isChecked()) {
+ instantRecordAction->setChecked(false);
+ instantRecord(false);
+ }
+ else {
+ instantRecordAction->setChecked(true);
+ instantRecord(true);
+ }
+}
+
+
 void DvbTab::instantRecord(bool checked)
 {
  if (checked) {
@@ -351,4 +373,73 @@
  if (channel != NULL) {
  manager->getLiveView()->playChannel(channel);
  }
+
+ QModelIndex index = channelView->indexAt(QPoint(0,0));
+
+ if (!index.isValid()) {
+ return;
+ }
+
+ DvbChannelModel *channelModel = (DvbChannelModel*) index.model();
+
+ QModelIndexList list = channelModel->match(channelModel->index(0, 0), Qt::DisplayRole, channel->name, 1, Qt::MatchExactly);
+ QModelIndex index_new = list.value(0);
+
+ if (!index_new.isValid()) {
+ return;
+ }
+
+ channelView->setCurrentIndex(index_new);
+
 }
+
+void DvbTab::setChannel(const QString &name)
+{
+ QModelIndex index = channelView->indexAt(QPoint(0,0));
+
+ if (!index.isValid()) {
+ return;
+ }
+
+ DvbChannelModel *channelModel = (DvbChannelModel*) index.model();
+
+ QModelIndexList list = channelModel->match(channelModel->index(0, 0), Qt::DisplayRole, name, 1, Qt::MatchExactly);
+ QModelIndex index_new = list.value(0);
+
+ if (!index_new.isValid()) {
+ return;
+ }
+
+ channelView->setCurrentIndex(index_new);
+
+ playChannel(name);
+}
+
+void DvbTab::setChannel(int number)
+{
+
+ QModelIndex index = channelView->indexAt(QPoint(0,0));
+
+ if (!index.isValid()) {
+ return;
+ }
+
+ DvbChannelModel *channelModel = (DvbChannelModel*) index.model();
+
+ QModelIndexList list = channelModel->match(channelModel->index(0, 1), Qt::DisplayRole, number, 1, Qt::MatchExactly);
+ QModelIndex index_new = list.value(0);
+
+ if (!index_new.isValid()) {
+ return;
+ }
+
+ channelView->setCurrentIndex(index_new);
+ playChannel(number);
+
+}
+
+void DvbTab::setLastChannel()
+{
+ playLastChannel();
+}
+
diff -Naur ../kaffeine/src/dvb/dvbtab.h ./src/dvb/dvbtab.h
--- ../kaffeine/src/dvb/dvbtab.h 2009-11-21 23:11:27.000000000 +0100
+++ ./src/dvb/dvbtab.h 2009-11-21 23:08:52.000000000 +0100
@@ -38,11 +38,13 @@
 class DvbTab : public TabBase
 {
  Q_OBJECT
+
 public:
  DvbTab(KMenu *menu, KActionCollection *collection, MediaWidget *mediaWidget_);
  ~DvbTab();
 
  void playChannel(const QString &name);
+ void playChannel(int number);
  void playLastChannel();
 
  void enableDvbDump();
@@ -52,12 +54,16 @@
  void showEpgDialog();
  void showRecordingDialog();
  void instantRecord(bool checked);
+ void toggleInstantRecord();
  void instantRecordingRemoved();
  void configureDvb();
  void playLive(const QModelIndex &index);
  void previousChannel();
  void nextChannel();
  void cleanTimeShiftFiles();
+ void setChannel(const QString &name);
+ void setChannel(int number);
+ void setLastChannel();
 
 private:
  void activate();
diff -Naur ../kaffeine/src/kaffeine.cpp ./src/kaffeine.cpp
--- ../kaffeine/src/kaffeine.cpp 2009-11-21 23:11:28.000000000 +0100
+++ ./src/kaffeine.cpp 2009-11-21 23:08:52.000000000 +0100
@@ -327,6 +327,15 @@
  // initialize dbus objects
  QDBusConnection::sessionBus().registerObject("/", new MprisRootObject(this),
  QDBusConnection::ExportAllContents);
+ QDBusConnection::sessionBus().registerObject("/Player", new MprisPlayerObject(mediaWidget),
+    QDBusConnection::ExportAllContents);
+ QDBusConnection::sessionBus().registerObject("/TrackList", new MprisTrackListObject(mediaWidget),
+ QDBusConnection::ExportAllContents);
+ QDBusConnection::sessionBus().registerObject("/DVB", new MprisDvbObject(mediaWidget),
+ QDBusConnection::ExportAllContents);
+ QDBusConnection::sessionBus().registerObject("/Display", new MprisDisplayObject(mediaWidget),
+ QDBusConnection::ExportAllContents);
+
  QDBusConnection::sessionBus().registerService("org.mpris.kaffeine");
 
  show();
diff -Naur ../kaffeine/src/mediawidget.cpp ./src/mediawidget.cpp
--- ../kaffeine/src/mediawidget.cpp 2009-11-21 23:11:27.000000000 +0100
+++ ./src/mediawidget.cpp 2009-11-21 23:08:52.000000000 +0100
@@ -45,6 +45,8 @@
 #include <KToolBar>
 #include "osdwidget.h"
 
+#include <iostream>
+
 class DvbFeed : public Phonon::AbstractMediaStream
 {
 public:
@@ -374,6 +376,8 @@
  connect(timer, SIGNAL(timeout()), this, SLOT(checkScreenSaver()));
 
  stateChanged(Phonon::StoppedState);
+
+ setRepeat(false);
 }
 
 MediaWidget::~MediaWidget()
@@ -543,6 +547,69 @@
  }
 }
 
+bool MediaWidget::isPaused()
+{
+ if (playing && mediaObject->state() == Phonon::PausedState)
+ {
+ return true;
+ }
+ return false;
+}
+
+// also returns true when paused
+bool MediaWidget::isPlaying()
+{
+ return playing;
+}
+
+void MediaWidget::setRepeat(bool repeat_)
+{
+ repeat = repeat_;
+}
+
+bool MediaWidget::isRepeat()
+{
+ return repeat;
+}
+
+bool MediaWidget::hasMedia()
+{
+ if ( mediaObject->currentSource().type() != Phonon::MediaSource::Invalid ) {
+ std::cout << "KAFFEINE: true" << std::endl;
+ return true;
+ }
+ else {
+ std::cout << "KAFFEINE: false" << std::endl;
+ return false;
+ }
+}
+
+void MediaWidget::setDvbChannel(int number)
+{
+ if (dvbFeed != NULL) {
+ emit changeDvbChannel(number);
+ }
+}
+
+void MediaWidget::setDvbChannel(const QString &name)
+{
+ if (dvbFeed != NULL) {
+ emit changeDvbChannel(name);
+ }
+}
+
+void MediaWidget::setDvbLastChannel()
+{
+ if (dvbFeed != NULL) {
+ emit dvbLastChannel();
+ }
+}
+
+void MediaWidget::fullScreen()
+{
+ emit toggleFullScreen();
+}
+
 void MediaWidget::stateChanged(Phonon::State state)
 {
  bool newPlaying = false;
@@ -551,6 +618,7 @@
  case Phonon::BufferingState:
  case Phonon::PlayingState:
  case Phonon::PausedState:
+ paused = true;
  newPlaying = true;
  break;
 
@@ -655,6 +723,31 @@
  }
 }
 
+void MediaWidget::playPause() {
+ //if (actionPlayPause->text() == textPlay) {
+ if (isPaused()) {
+ playPause(false);
+ }
+ else {
+ playPause(true);
+ }
+}
+
+void MediaWidget::play() {
+ if (playing && actionPlayPause->text() == textPlay) {
+ playPause(false);
+ }
+ else if (!playing) {
+ emit playlistPlay();
+ }
+}
+
+void MediaWidget::pause() {
+ if (playing && actionPlayPause->text() == textPause) {
+ playPause(true);
+ }
+}
+
 void MediaWidget::stop()
 {
  mediaObject->stop();
@@ -726,6 +819,17 @@
  }
 }
 
+int MediaWidget::getVolume()
+{
+ int volume = audioOutput->volume() * 100;
+
+ if ( volume >= 0 && volume <= 100 ) {
+ return volume;
+ }
+
+ return 0;
+}
+
 void MediaWidget::changeVolume(int volume)
 {
  audioOutput->setVolume(volume * qreal(0.01));
@@ -915,6 +1019,16 @@
  mediaObject->seek(mediaObject->currentTime() + 1000 * longSkipDuration);
 }
 
+void MediaWidget::setPosition(int position)
+{
+ mediaObject->seek(position);
+}
+
+int MediaWidget::getPosition()
+{
+ return mediaObject->currentTime();
+}
+
 void MediaWidget::jumpToPosition()
 {
  JumpToPositionDialog dialog(QTime().addMSecs(mediaObject->currentTime()), this);
@@ -1150,3 +1264,57 @@
  subtitleBox->setEnabled(false);
  }
 }
+
+QVariantMap MediaWidget::getMetadata()
+{
+ QVariantMap ret;
+ QMultiMap<QString, QString> multiMap = mediaObject->metaData();
+ QMultiMap<QString, QString>::const_iterator i = multiMap.constBegin();
+
+ while( i != multiMap.constEnd() )
+ {
+ ret[ i.key() ] = QVariant( i.value() );
+ i++;
+ }
+ return ret;
+}
+
+int getNumberOfTracks()
+{
+ //TODO
+ return 0;
+}
+
+int MediaWidget::getCurrentTrack()
+{
+ //TODO
+ return 0;
+}
+
+int MediaWidget::getLength()
+{
+ //TODO
+ return 0;
+}
+
+int MediaWidget::addTrack(QString track, bool play)
+{
+ //TODO
+ return 0;
+}
+
+void MediaWidget::delTrack(int position)
+{
+ //TODO
+}
+
+void MediaWidget::setLoop(bool loop)
+{
+ setRepeat(loop);
+}
+
+void MediaWidget::setRandom(bool random)
+{
+ //TODO
+}
+
diff -Naur ../kaffeine/src/mediawidget.h ./src/mediawidget.h
--- ../kaffeine/src/mediawidget.h 2009-11-21 23:11:27.000000000 +0100
+++ ./src/mediawidget.h 2009-11-21 23:08:52.000000000 +0100
@@ -21,6 +21,7 @@
 #ifndef MEDIAWIDGET_H
 #define MEDIAWIDGET_H
 
+#include <QVariantMap>
 #include <QWidget>
 #include <Phonon/Global>
 #include <Phonon/ObjectDescription>
@@ -48,9 +49,14 @@
 class MediaWidget : public QWidget
 {
  Q_OBJECT
+ friend class MprisPlayerObject;
+ friend class MprisTrackListObject;
+ friend class MprisDvbObject;
+ friend class MprisDisplayObject;
+
 public:
  MediaWidget(KMenu *menu_, KAction *fullScreenAction, KToolBar *toolBar,
-    KActionCollection *collection, QWidget *parent);
+ KActionCollection *collection, QWidget *parent);
  ~MediaWidget();
 
  static QString extensionFilter(); // usable for KFileDialog::setFilter()
@@ -78,6 +84,10 @@
  void setShortSkipDuration(int duration);
  void setLongSkipDuration(int duration);
 
+ void setRepeat(bool repeat_);
+ bool isRepeat();
+ bool hasMedia();
+
 public slots:
  void stop();
  void stopDvb();
@@ -98,14 +108,34 @@
  void startDvbTimeShift();
  void changeDvbAudioChannel(int index);
  void changeDvbSubtitle(int index);
+ void changeDvbChannel(int number);
+ void changeDvbChannel(const QString &name);
  void dvbStopped();
  void osdKeyPressed(int key);
+ void toggleOsd();
+
+ void dvbLastChannel();
+ void toggleInstantRecord();
 
 private slots:
+ bool isPlaying();
+ bool isPaused();
+
+ int getPosition();
+ int getCurrentTrack();
+ int getLength();
+ int addTrack(QString track, bool play);
+ int getVolume();
+
+ QVariantMap getMetadata();
+
  void stateChanged(Phonon::State state);
  void playbackFinished();
  void previous();
  void playPause(bool paused);
+ void playPause();
+ void play();
+ void pause();
  void next();
  void changeAudioChannel(int index);
  void changeSubtitle(int index);
@@ -132,6 +162,7 @@
  void skipForward();
  void longSkipForward();
  void jumpToPosition();
+ void setPosition(int position);
  void timeButtonClicked();
  void updateTimeButton();
  void updateCaption();
@@ -144,6 +175,16 @@
 
  void checkScreenSaver();
 
+ void setDvbChannel(int number);
+ void setDvbChannel(const QString &name);
+ void setDvbLastChannel();
+
+ void fullScreen();
+
+ void delTrack(int position);
+ void setLoop(bool loop);
+ void setRandom(bool random);
+
 private:
  void contextMenuEvent(QContextMenuEvent *event);
  void mouseDoubleClickEvent(QMouseEvent *);
@@ -164,6 +205,7 @@
  Phonon::MediaController *mediaController;
  DvbFeed *dvbFeed;
  bool playing;
+ bool paused;
 
  KAction *actionPrevious;
  KAction *actionPlayPause;
@@ -204,6 +246,7 @@
  KAction *jumpToPositionAction;
  QPushButton *timeButton;
  bool showElapsedTime;
+ bool repeat;
 };
 
 #endif /* MEDIAWIDGET_H */
diff -Naur ../kaffeine/src/playlist/playlistmodel.cpp ./src/playlist/playlistmodel.cpp
--- ../kaffeine/src/playlist/playlistmodel.cpp 2009-11-21 23:11:27.000000000 +0100
+++ ./src/playlist/playlistmodel.cpp 2009-11-21 23:08:52.000000000 +0100
@@ -48,6 +48,7 @@
  QAbstractTableModel(parent), mediaWidget(mediaWidget_), repeat(false)
 {
  setSupportedDragActions(Qt::MoveAction);
+ mediaWidget->setRepeat(false);
 
  connect(mediaWidget, SIGNAL(playlistPrevious()), this, SLOT(playPreviousTrack()));
  connect(mediaWidget, SIGNAL(playlistPlay()), this, SLOT(playCurrentTrack()));
@@ -351,6 +352,7 @@
 void PlaylistModel::repeatPlaylist(bool repeat_)
 {
  repeat = repeat_;
+ mediaWidget->setRepeat(repeat);
 }
 
 static bool playlistIndexLess(const PlaylistTrack &x, const PlaylistTrack &y)

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
kaffeine-devel mailing list
kaffeine-devel@...
https://lists.sourceforge.net/lists/listinfo/kaffeine-devel