You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeaddons/kicker-applets/mediacontrol/jukInterface.cpp

315 lines
7.8 KiB

/***************************************************************************
Interface to access JuK
-------------------
begin : Mon Jan 15 21:09:00 CEST 2001
copyright : (C) 2001-2002 by Stefan Gehn
email : metz {AT} gehn {DOT} 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. *
* *
***************************************************************************/
#include "jukInterface.h"
#include "jukInterface.moc"
#include <kapplication.h>
#include <kdebug.h>
#include <tqstringlist.h>
#include <tqstrlist.h>
#include <tqprocess.h>
#include <kurldrag.h>
#define TIMER_FAST 250
JuKInterface::JuKInterface() : PlayerInterface(), mProc(0)
{
mTimerValue = TIMER_FAST;
mJuKTimer = new TQTimer ( this, "mJukTimer" );
connect(mJuKTimer, TQT_SIGNAL(timeout()), TQT_SLOT(updateSlider()) );
kapp->dcopClient()->setNotifications ( true );
connect(kapp->dcopClient(), TQT_SIGNAL(applicationRegistered(const TQCString&)),
TQT_SLOT(appRegistered(const TQCString&)) );
connect(kapp->dcopClient(), TQT_SIGNAL(applicationRemoved(const TQCString&)),
TQT_SLOT(appRemoved(const TQCString&)));
TQTimer::singleShot(0, this, TQT_SLOT(myInit()));
}
JuKInterface::~JuKInterface()
{
kapp->dcopClient()->setNotifications(false);
delete mJuKTimer;
}
void JuKInterface::myInit()
{
// Start the timer if juk is already running
// Needed if user adds applet while running juk
if ( findRunningJuK() )
{
emit playerStarted();
mJuKTimer->start(mTimerValue);
}
else
{
emit playerStopped();
emit newSliderPosition(0,0);
}
}
void JuKInterface::appRegistered ( const TQCString &appId )
{
if(appId.contains("juk",false) )
{
mAppId = appId;
// BWAHAHAHA EVIL HACK
// JuK blocks DCOP signals on its startup, so if we try to
// ping it now, it'll simply cause us to block, which will
// cause kicker to block, which is bad, m'kay?
//
// So what we do is launch the dcop command instead, and let
// *it* block for us. As soon as the command exits, we know
// that JuK is ready to go (and so are we).
mProc = new TQProcess(this, "jukdcopCheckProc");
mProc->addArgument("dcop");
mProc->addArgument("juk");
mProc->addArgument("Player");
mProc->addArgument("status()");
connect(mProc, TQT_SIGNAL(processExited()), TQT_SLOT(jukIsReady()));
mProc->start();
}
}
void JuKInterface::appRemoved ( const TQCString &appId )
{
if ( appId.contains("juk",false) )
{
// is there still another juk alive?
if ( findRunningJuK() )
return;
mJuKTimer->stop();
emit playerStopped();
emit newSliderPosition(0,0);
}
}
/* Called when the dcop process we launch terminates */
void JuKInterface::jukIsReady()
{
emit playerStarted();
mJuKTimer->start(mTimerValue);
mProc->deleteLater();
mProc = 0;
}
void JuKInterface::updateSlider ()
{
// length/time in msecs, -1 means "no playobject in juk"
int len = -1;
int time = -1;
TQByteArray data, replyData;
TQCString replyType;
if (kapp->dcopClient()->call(mAppId, "Player", "totalTime()", data,
replyType, replyData))
{
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == "int")
reply >> len;
}
data = 0;
replyData = 0;
replyType = 0;
if (kapp->dcopClient()->call(mAppId, "Player", "currentTime()", data,
replyType, replyData))
{
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == "int")
reply >> time;
}
if ( (time < 0) || (len < 0)) // JuK isn't playing and thus returns -1
{
len = 0;
time = 0;
}
emit ( newSliderPosition(len,time) );
emit playingStatusChanged(playingStatus());
}
// Drag-n-Drop stuff =================================================================
void JuKInterface::dragEnterEvent(TQDragEnterEvent* event)
{
// kdDebug(90200) << "JuKInterface::dragEnterEvent()" << endl;
event->accept( KURLDrag::canDecode(event) );
}
void JuKInterface::dropEvent(TQDropEvent* event)
{
// kdDebug(90200) << "JuKInterface::dropEvent()" << endl;
KURL::List list;
if (KURLDrag::decode(event, list))
{
TQByteArray data, replyData;
TQStringList fileList;
TQCString replyType;
TQDataStream arg(data, IO_WriteOnly);
// Juk doesn't handle KURL's yet, so we need to form a list
// that contains the local paths.
for (KURL::List::ConstIterator it = list.begin(); it != list.end(); ++it)
fileList += (*it).path();
arg << fileList << false;
// Use call instead of send to make sure the files are added
// before we try to play.
if (!kapp->dcopClient()->call(mAppId, "Collection", "openFile(TQStringList)", data,
replyType, replyData, true))
{
kdDebug(90200) << "Couldn't send drop to juk" << endl;
}
// Apparently we should auto-play?
TQByteArray strData;
TQDataStream strArg(strData, IO_WriteOnly);
strArg << *fileList.begin();
if (!kapp->dcopClient()->send(mAppId, "Player", "play(TQString)", strData))
kdDebug(90200) << "Couldn't send play command to juk" << endl;
}
}
// ====================================================================================
void JuKInterface::sliderStartDrag()
{
mJuKTimer->stop();
}
void JuKInterface::sliderStopDrag()
{
mJuKTimer->start(mTimerValue);
}
void JuKInterface::jumpToTime( int sec )
{
TQByteArray data;
TQDataStream arg(data, IO_WriteOnly);
arg << sec;
// Used in JuK shipping with KDE < 3.3
//kapp->dcopClient()->send(mAppId, "Player", "setTime(int)", data);
kapp->dcopClient()->send(mAppId, "Player", "seek(int)", data);
}
void JuKInterface::playpause()
{
if (!findRunningJuK())
startPlayer("juk");
TQByteArray data;
kapp->dcopClient()->send(mAppId, "Player", "playPause()", data);
}
void JuKInterface::stop()
{
TQByteArray data;
kapp->dcopClient()->send(mAppId, "Player", "stop()", data);
}
void JuKInterface::next()
{
TQByteArray data;
kapp->dcopClient()->send(mAppId, "Player", "forward()", data);
}
void JuKInterface::prev()
{
TQByteArray data;
kapp->dcopClient()->send(mAppId, "Player", "back()", data);
}
void JuKInterface::volumeUp()
{
TQByteArray data;
kapp->dcopClient()->send(mAppId, "Player", "volumeUp()", data);
}
void JuKInterface::volumeDown()
{
TQByteArray data;
kapp->dcopClient()->send(mAppId, "Player", "volumeDown()", data);
}
const TQString JuKInterface::getTrackTitle() const
{
TQString title;
TQByteArray data, replyData;
TQCString replyType;
if (kapp->dcopClient()->call(mAppId, "Player", "playingString()",data,
replyType, replyData))
{
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == TQSTRING_OBJECT_NAME_STRING)
{
reply >> title;
return title;
}
}
return TQString("");
}
// FIXME: what if we have a dcop app named, let's say, 'jukfrontend'?
bool JuKInterface::findRunningJuK()
{
QCStringList allApps = kapp->dcopClient()->registeredApplications();
TQValueList<TQCString>::const_iterator iterator;
for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator)
{
if ((*iterator).contains("juk",false))
{
mAppId = *iterator;
return true;
}
}
return false;
}
int JuKInterface::playingStatus()
{
TQByteArray data, replyData;
TQCString replyType;
if (kapp->dcopClient()->call(mAppId, "Player", "status()", data, replyType,
replyData))
{
int status = 0;
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == "int")
reply >> status;
if (status == 2)
return Playing;
else if (status == 1)
return Paused;
}
return Stopped;
}