Commit b10c22ee authored by Scott Wheeler's avatar Scott Wheeler

Abstracted the Player interface and added aRts and GStreamer concrete

implementations

svn path=/trunk/kdemultimedia/juk/; revision=205818
parent e3c0c019
......@@ -3,12 +3,12 @@ bin_PROGRAMS = juk
## INCLUDES were found outside kdevelop specific part
juk_SOURCES = directorylist.cpp directorylistbase.ui stringhash.cpp sortedstringlist.cpp systemtray.cpp genrelisteditor.cpp genrelisteditorbase.ui splashscreen.cpp statuslabel.cpp cachedtag.cpp oggtag.cpp id3tag.cpp collectionlist.cpp playlistitem.cpp playlist.cpp playlistsplitter.cpp listboxpixmap.cpp playlistbox.cpp tageditor.cpp cache.cpp audiodata.cpp genrelistreader.cpp genrelistlist.cpp genrelist.cpp genre.cpp player.cpp tag.cpp customaction.cpp slideraction.cpp juk.cpp main.cpp
juk_SOURCES = gstreamerplayer.cpp artsplayer.cpp directorylist.cpp directorylistbase.ui stringhash.cpp sortedstringlist.cpp systemtray.cpp genrelisteditor.cpp genrelisteditorbase.ui splashscreen.cpp statuslabel.cpp cachedtag.cpp oggtag.cpp id3tag.cpp collectionlist.cpp playlistitem.cpp playlist.cpp playlistsplitter.cpp listboxpixmap.cpp playlistbox.cpp tageditor.cpp cache.cpp audiodata.cpp genrelistreader.cpp genrelistlist.cpp genrelist.cpp genre.cpp player.cpp tag.cpp customaction.cpp slideraction.cpp juk.cpp main.cpp
juk_LDADD = -lid3 -lsoundserver_idl $(LIB_KFILE) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) $(LIBSOCKET)
SUBDIRS = pics data
EXTRA_DIST = main.cpp juk.cpp juk.h juk.desktop jukui.rc slideraction.cpp slideraction.h customaction.h customaction.cpp tag.cpp tag.h player.cpp player.h genre.h genre.cpp hi16-app-juk.png hi32-app-juk.png hi48-app-juk.png genrelist.cpp genrelist.h genrelistlist.cpp genrelistlist.h genrelistreader.cpp genrelistreader.h audiodata.cpp audiodata.h cache.cpp cache.h tageditor.cpp tageditor.h playlistbox.cpp playlistbox.h listboxpixmap.cpp listboxpixmap.h playlistsplitter.cpp playlistsplitter.h playlist.cpp playlist.h playlistitem.cpp playlistitem.h collectionlist.cpp collectionlist.h id3tag.cpp id3tag.h oggtag.cpp oggtag.h cachedtag.cpp cachedtag.h statuslabel.cpp statuslabel.h splashscreen.cpp splashscreen.h genrelisteditorbase.ui genrelisteditor.cpp genrelisteditor.h systemtray.h systemtray.cpp sortedstringlist.cpp sortedstringlist.h stringhash.cpp stringhash.h directorylistbase.ui directorylist.cpp directorylist.h
EXTRA_DIST = main.cpp juk.cpp juk.h juk.desktop jukui.rc slideraction.cpp slideraction.h customaction.h customaction.cpp tag.cpp tag.h player.cpp player.h genre.h genre.cpp hi16-app-juk.png hi32-app-juk.png hi48-app-juk.png genrelist.cpp genrelist.h genrelistlist.cpp genrelistlist.h genrelistreader.cpp genrelistreader.h audiodata.cpp audiodata.h cache.cpp cache.h tageditor.cpp tageditor.h playlistbox.cpp playlistbox.h listboxpixmap.cpp listboxpixmap.h playlistsplitter.cpp playlistsplitter.h playlist.cpp playlist.h playlistitem.cpp playlistitem.h collectionlist.cpp collectionlist.h id3tag.cpp id3tag.h oggtag.cpp oggtag.h cachedtag.cpp cachedtag.h statuslabel.cpp statuslabel.h splashscreen.cpp splashscreen.h genrelisteditorbase.ui genrelisteditor.cpp genrelisteditor.h systemtray.h systemtray.cpp sortedstringlist.cpp sortedstringlist.h stringhash.cpp stringhash.h directorylistbase.ui directorylist.cpp directorylist.h artsplayer.cpp artsplayer.h gstreamerplayer.cpp gstreamerplayer.h
install-data-local:
$(mkinstalldirs) $(kde_appsdir)/Multimedia/
......
/***************************************************************************
player.cpp - description
-------------------
begin : Sun Feb 17 2002
copyright : (C) 2002 by Scott Wheeler
email : wheeler@kde.org
***************************************************************************/
/***************************************************************************
* *
* 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 <kdebug.h>
#include <qfile.h>
#include <connect.h>
#include <flowsystem.h>
#include "artsplayer.h"
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
ArtsPlayer::ArtsPlayer() : Player()
{
// set pointers to null
server = 0;
volumeControl = 0;
media = 0;
dispatcher = 0;
// startup volume of "full" volume
currentVolume = 1.0;
setupPlayer();
}
ArtsPlayer::~ArtsPlayer()
{
delete(volumeControl);
delete(media);
delete(server);
delete(dispatcher);
}
void ArtsPlayer::play(const QString &fileName, float volume)
{
currentFile = fileName;
play(volume);
}
void ArtsPlayer::play(float volume)
{
if(serverRunning()) {
if(media && media->state() == posPaused) {
media->play();
}
else {
if(media)
stop();
media = new PlayObject(server->createPlayObject(QFile::encodeName(currentFile).data()));
// media = new PlayObject(server->createPlayObject(currentFile.latin1()));
if(!media->isNull()) {
setVolume(volume);
media->play();
}
else {
kdDebug() << "Media did not initialize properly! (" << currentFile << ")" << endl;
delete(media);
media = 0;
}
}
}
}
void ArtsPlayer::pause()
{
if(serverRunning() && media)
media->pause();
}
void ArtsPlayer::stop()
{
if(serverRunning()) {
if(media) {
media->halt();
delete(media);
media = 0;
}
if(volumeControl) {
delete(volumeControl);
volumeControl = 0;
}
}
}
void ArtsPlayer::setVolume(float volume)
{
if(serverRunning() && media && !media->isNull()) {
if(!volumeControl)
setupVolumeControl();
if(volumeControl) {
currentVolume = volume;
volumeControl->scaleFactor(volume);
}
}
}
float ArtsPlayer::getVolume() const
{
return(currentVolume);
}
/////////////////////////////////////////////////////////////////////////////////
// player status functions
/////////////////////////////////////////////////////////////////////////////////
bool ArtsPlayer::playing() const
{
if(serverRunning() && media && media->state() == posPlaying)
return(true);
else
return(false);
}
bool ArtsPlayer::paused() const
{
if(serverRunning() && media && media->state() == posPaused)
return(true);
else
return(false);
}
long ArtsPlayer::totalTime() const
{
if(serverRunning() && media)
return(media->overallTime().seconds);
else
return(-1);
}
long ArtsPlayer::currentTime() const
{
if(serverRunning() && media && media->state() == posPlaying)
return(media->currentTime().seconds);
else
return(-1);
}
int ArtsPlayer::position() const
{
if(serverRunning() && media && media->state() == posPlaying) {
// long total=media->overallTime().ms;
// long current=media->currentTime().ms;
long total = media->overallTime().seconds * 1000 + media->overallTime().ms;
long current = media->currentTime().seconds * 1000 + media->currentTime().ms;
// add .5 to make rounding happen properly
return(int(double(current) * 1000 / total + .5));
}
else
return(-1);
}
/////////////////////////////////////////////////////////////////////////////////
// player seek functions
/////////////////////////////////////////////////////////////////////////////////
void ArtsPlayer::seek(long seekTime)
{
if(serverRunning() && media) {
poTime poSeekTime;
poSeekTime.seconds = seekTime;
media->seek(poSeekTime);
}
}
void ArtsPlayer::seekPosition(int position)
{
if(serverRunning() && media) {
poTime poSeekTime;
long total = media->overallTime().seconds;
poSeekTime.seconds = long(double(total) * position / 1000 + .5);
media->seek(poSeekTime);
}
}
/////////////////////////////////////////////////////////////////////////////////
// private
/////////////////////////////////////////////////////////////////////////////////
void ArtsPlayer::setupPlayer()
{
dispatcher = new Dispatcher;
server = new SimpleSoundServer(Reference("global:Arts_SimpleSoundServer"));
}
void ArtsPlayer::setupVolumeControl()
{
volumeControl = new StereoVolumeControl(DynamicCast(server->createObject("Arts::StereoVolumeControl")));
if(volumeControl && media && !volumeControl->isNull() && !media->isNull()) {
Synth_BUS_UPLINK uplink = Arts::DynamicCast(media->_getChild( "uplink" ));
uplink.stop();
Arts::disconnect(*media, "left", uplink, "left");
Arts::disconnect(*media, "right", uplink, "right");
volumeControl->start();
uplink.start();
media->_addChild(*volumeControl, "volume" );
Arts::connect(*media, "left", *volumeControl, "inleft");
Arts::connect(*media, "right", *volumeControl, "inright");
Arts::connect(*volumeControl, "outleft", uplink, "left");
Arts::connect(*volumeControl, "outright", uplink, "right");
}
else {
delete(volumeControl);
volumeControl = 0;
kdDebug() << "Could not initialize volume control!" << endl;
}
}
bool ArtsPlayer::serverRunning() const
{
if(server)
return(!(server->isNull()));
else
return(0);
}
/***************************************************************************
artsplayer.h - description
-------------------
begin : Sun Feb 17 2002
copyright : (C) 2002 by Scott Wheeler
email : wheeler@kde.org
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef ARTSPLAYER_H
#define ARTSPLAYER_H
#include <qstring.h>
#include <soundserver.h>
#include <arts/artsflow.h>
#include "player.h"
using namespace Arts;
class ArtsPlayer : public Player
{
public:
ArtsPlayer();
virtual ~ArtsPlayer();
virtual void play(const QString &fileName, float volume = 1.0);
virtual void play(float volume = 1.0);
virtual void pause();
virtual void stop();
virtual void setVolume(float volume = 1.0);
virtual float getVolume() const;
virtual bool playing() const;
virtual bool paused() const;
virtual long totalTime() const;
virtual long currentTime() const;
virtual int position() const; // in this case not really the percent
virtual void seek(long seekTime);
virtual void seekPosition(int position);
private:
void setupPlayer();
void setupVolumeControl();
bool serverRunning() const;
Dispatcher *dispatcher;
SimpleSoundServer *server;
PlayObject *media;
StereoVolumeControl *volumeControl;
QString currentFile;
float currentVolume;
};
#endif
/***************************************************************************
gstreamerplayer.cpp - description
-------------------
begin : Sat Feb 9 2003
copyright : (C) 2003 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#if 0
#include <kdebug.h>
#include <qfile.h>
#include <connect.h>
#include <flowsystem.h>
#include "gstreamerplayer.h"
using namespace QGst;
using namespace QGstPlay;
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
GStreamerPlayer::GStreamerPlayer() : QObject(0), Player()
{
currentVolume = 1.0;
positionNs = 0;
durationNs = 0;
setupPlayer();
}
GStreamerPlayer::~GStreamerPlayer()
{
delete(player);
}
void GStreamerPlayer::play(const QString &fileName, float volume)
{
currentFile = fileName;
if(!fileName.isNull())
player->setLocation(fileName);
play(volume);
}
void GStreamerPlayer::play(float volume)
{
// 1.0 is full volume
positionNs = 0;
durationNs = 0;
if (player->getState() != Element::STATE_PLAYING)
player->setState(Element::STATE_PLAYING);
}
void GStreamerPlayer::pause()
{
if(player->getState() != Element::STATE_PAUSED)
player->setState(Element::STATE_PAUSED);
}
void GStreamerPlayer::stop()
{
if(player->getState() != Element::STATE_READY)
player->setState(Element::STATE_READY);
}
void GStreamerPlayer::setVolume(float volume)
{
// 1.0 is full volume
player->setVolume(volume);
}
float GStreamerPlayer::getVolume() const
{
// 1.0 is full volume
// when is works in QGstPlay::Play, just call:
// return player->getVolume();
return 1.0;
}
/////////////////////////////////////////////////////////////////////////////////
// player status functions
/////////////////////////////////////////////////////////////////////////////////
bool GStreamerPlayer::playing() const
{
// true if playing
return player->getState() == Element::STATE_PLAYING;
}
bool GStreamerPlayer::paused() const
{
// true if paused
return player->getState() == Element::STATE_PAUSED;
}
long GStreamerPlayer::totalTime() const
{
return durationNs / 1000000000L;
}
long GStreamerPlayer::currentTime() const
{
return positionNs / 1000000000L;
}
int GStreamerPlayer::position() const
{
if (durationNs > 0)
return (int)((positionNs * 1000.0) / durationNs);
else
return 0;
}
/////////////////////////////////////////////////////////////////////////////////
// player seek functions
/////////////////////////////////////////////////////////////////////////////////
void GStreamerPlayer::seek(long seekTime)
{
// seek time in seconds?
player->seekToTime(seekTime*1000000000);
}
void GStreamerPlayer::seekPosition(int position)
{
// position unit is 1/1000th
if(durationNs > 0)
player->seekToTime(position * durationNs / 1000L);
else
player->seekToTime(0);
}
/////////////////////////////////////////////////////////////////////////////////
// private
/////////////////////////////////////////////////////////////////////////////////
void GStreamerPlayer::setDuration(long long d)
{
durationNs = d;
}
void GStreamerPlayer::setPosition(long long d)
{
positionNs = d;
}
void GStreamerPlayer::setupPlayer()
{
player = new Play(Play::PIPE_AUDIO_THREADED, this, "Play");
connect(player, SIGNAL(timeTick(long long)),
SLOT(setPosition(long long)));
connect(player, SIGNAL(streamLength(long long)),
SLOT(setDuration(long long)));
connect(player, SIGNAL(streamEnd()), SLOT(stop()));
}
void GStreamerPlayer::setupVolumeControl()
{
}
bool GStreamerPlayer::serverRunning() const
{
return true;
}
#include "gstreamerplayer.moc"
#endif
/***************************************************************************
gstreamerplayer.h - description
-------------------
begin : Sat Feb 9 2003
copyright : (C) 2003 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef GSTREAMERPLAYER_H
#define GSTREAMERPLAYER_H
#include <qgstplay/play.h>
#include <qobject.h>
#include <qstring.h>
#include "player.h"
class GStreamerPlayer : public QObject, public Player
{
Q_OBJECT
public:
GStreamerPlayer();
virtual ~GStreamerPlayer();
virtual void play(const QString &fileName, float volume = 1.0);
virtual void play(float volume = 1.0);
virtual void setVolume(float volume = 1.0);
virtual float getVolume() const;
virtual bool playing() const;
virtual bool paused() const;
virtual long totalTime() const;
virtual long currentTime() const;
virtual int position() const; // in this case not really the percent
virtual void seek(long seekTime);
virtual void seekPosition(int position);
public slots:
void pause();
void stop();
private slots:
void setPosition(long long d);
void setDuration(long long d);
private:
void setupGStreamerPlayer();
void setupVolumeControl();
bool serverRunning() const;
QGstPlay::Play *player;
unsigned long long duration;
long long positionNs; // in ns
long long durationNs; // in ns
QString currentFile;
float currentVolume;
};
#endif
......@@ -60,7 +60,7 @@ JuK::JuK(QWidget *parent, const char *name) : KMainWindow(parent, name, WDestruc
JuK::~JuK()
{
delete(player);
}
////////////////////////////////////////////////////////////////////////////////
......@@ -160,9 +160,9 @@ void JuK::setupSystemTray()
connect(systemTray, SIGNAL(back()), this, SLOT(backFile()));
connect(systemTray, SIGNAL(forward()), this, SLOT(forwardFile()));
if(player.paused())
if(player && player->paused())
systemTray->slotPause();
else if(player.playing())
else if(player && player->playing())
systemTray->slotPlay();
}
else
......@@ -171,6 +171,8 @@ void JuK::setupSystemTray()
void JuK::setupPlayer()
{
player = Player::createPlayer();
trackPositionDragging = false;
noSeek = false;
pauseAction->setEnabled(false);
......@@ -314,13 +316,16 @@ void JuK::updatePlaylistInfo()
void JuK::playFile()
{
if(player.paused()) {
player.play();
if(!player)
return;
if(player->paused()) {
player->play();
// Here, before doing anything, we want to make sure that the player did
// in fact start.
if(player.playing()) {
if(player->playing()) {
pauseAction->setEnabled(true);
stopAction->setEnabled(true);
playTimer->start(pollInterval);
......@@ -328,16 +333,19 @@ void JuK::playFile()
systemTray->slotPlay();
}
}
else if(player.playing())
player.seekPosition(0);
else if(player->playing())
player->seekPosition(0);
else
playFile(splitter->playNextFile(randomPlayAction->isChecked()));
}
void JuK::pauseFile()
{
if(!player)
return;
playTimer->stop();
player.pause();
player->pause();
pauseAction->setEnabled(false);
if(systemTray)
systemTray->slotPause();
......@@ -345,8 +353,11 @@ void JuK::pauseFile()
void JuK::stopFile()
{
if(!player)
return;
playTimer->stop();
player.stop();
player->stop();
pauseAction->setEnabled(false);
stopAction->setEnabled(false);
......@@ -405,36 +416,45 @@ void JuK::trackPositionSliderClick()