summaryrefslogtreecommitdiffstats
path: root/noatun/library/player.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'noatun/library/player.cpp')
-rw-r--r--noatun/library/player.cpp379
1 files changed, 379 insertions, 0 deletions
diff --git a/noatun/library/player.cpp b/noatun/library/player.cpp
new file mode 100644
index 00000000..7760d9a8
--- /dev/null
+++ b/noatun/library/player.cpp
@@ -0,0 +1,379 @@
+#include "player.h"
+
+#include <noatun/playlist.h>
+#include "engine.h"
+#include "app.h"
+#include "titleproxy.h"
+
+#include <klibloader.h>
+#include <knotifyclient.h>
+#include <klocale.h>
+#include <qfile.h>
+
+enum ArtsPOS { posIdle=0, posPlaying, posPaused };
+
+
+
+Player::Player(QObject *parent) : QObject(parent, "Player"),
+ position(-1), mLoopStyle(None), firstTimeout(true)
+{
+ mEngine=new Engine;
+ connect(&filePos, SIGNAL(timeout()), SLOT(posTimeout()));
+ connect(mEngine, SIGNAL(aboutToPlay()), this, SLOT(aboutToPlay()));
+ connect(mEngine,
+ SIGNAL(receivedStreamMeta(const QString &, const QString &,
+ const QString &, const QString &,
+ const QString &, const QString &)),
+ this, SLOT(
+ slotUpdateStreamMeta(const QString &, const QString &,
+ const QString &, const QString &,
+ const QString &, const QString &))
+ );
+ connect(mEngine, SIGNAL(playingFailed()), this, SLOT(forward()));
+
+ handleButtons();
+}
+
+Player::~Player()
+{
+ delete mEngine;
+}
+
+bool Player::isPlaying()
+{
+ return mEngine->state()==posPlaying;
+}
+
+bool Player::isPaused()
+{
+ return mEngine->state()==posPaused;
+}
+
+bool Player::isStopped()
+{
+ return mEngine->state()==posIdle;
+}
+
+void Player::toggleListView()
+{
+ napp->playlist()->toggleList();
+}
+
+void Player::handleButtons()
+{
+ switch (mEngine->state())
+ {
+ case (posPlaying):
+ emit playing();
+ break;
+ case (posPaused):
+ emit paused();
+ break;
+ case (posIdle):
+ emit stopped();
+ }
+}
+
+void Player::back()
+{
+ if (napp->playlist()->previous())
+ {
+ stop();
+ play();
+ }
+}
+
+void Player::stop()
+{
+ filePos.stop();
+ position=0;
+ mEngine->stop();
+ emit stopped();
+ mCurrent=0;
+}
+
+void Player::play()
+{
+ napp->processEvents();
+ bool work=false;
+ firstTimeout=true;
+
+ if (mEngine->state()==posPlaying) // do nothing if already playing
+ return;
+
+ if (mEngine->state()==posPaused)
+ {
+ work=mEngine->play();
+ }
+ else
+ {
+ stop();
+ mCurrent = napp->playlist()->current();
+ if (!mCurrent)
+ {
+ work=false;
+ }
+ else
+ {
+ mEngine->blockSignals(true);
+ work=mEngine->open(mCurrent);
+ mEngine->blockSignals(false);
+ }
+ }
+
+ if (!work)
+ {
+ forward(false);
+ }
+ else
+ {
+ filePos.start(500);
+ emit changed();
+ mEngine->play();
+ }
+
+ handleButtons();
+}
+
+void Player::play(const PlaylistItem &item)
+{
+ napp->playlist()->setCurrent(item);
+}
+
+void Player::playpause()
+{
+ if (mEngine->state()==posPlaying)
+ {
+ filePos.stop();
+ mEngine->pause();
+// emit paused(); NOT necessary because emitted in handleButtons() (mETz)
+ handleButtons();
+ }
+ else
+ play();
+}
+
+void Player::forward(bool allowLoop)
+{
+ stop();
+ if (napp->playlist()->next())
+ play();
+ else if (allowLoop && napp->loopList())
+ if (napp->playlist()->reset(), napp->playlist()->current())
+ play();
+}
+
+void Player::skipTo(int msec) // skip to a certain time in the track
+{
+ if( (current()) && (msec>=0) )
+ {
+ mEngine->seek(msec);
+ position = mEngine->position(); // make sure position is recent
+ emit timeout(); // update the UI
+ emit skipped(msec);
+ emit skipped();
+ }
+}
+
+void Player::playCurrent()
+{
+ if (!mEngine->initialized()) return;
+ stop();
+ mCurrent=0;
+ if (napp->playlist()->current())
+ play();
+}
+
+void Player::newCurrent()
+{
+ // the second half of the following
+ if (!napp->playlist() || !mEngine->initialized())
+ return; // no playlist, or squelch playing as an optimization
+ if ((mEngine->state()!=posPlaying) && napp->autoPlay())
+ playCurrent();
+}
+
+void Player::posTimeout()
+{
+ if (mEngine->state()==posIdle)
+ {
+ stop();
+ handleButtons();
+ // If you're supposed to loop the song, don't go next
+ // otherwise, do go next
+ if (loopStyle()==Song || napp->playlist()->next())
+ play();
+ else if (loopStyle()==Playlist)
+ {
+ napp->playlist()->reset();
+ play();
+ }
+ else if (napp->loopList())
+ napp->playlist()->reset();
+
+ return;
+ }
+ position = mEngine->position();
+
+ if (current())
+ {
+ current().setLength(mEngine->length());
+ if (current().length() && firstTimeout)
+ {
+ int minutes = (int) ( current().length() / 60 );
+ int seconds = current().length() - minutes * 60;
+ emit newSongLen ( minutes, seconds );
+ firstTimeout = false;
+ emit newSong();
+ }
+ }
+
+ emit timeout();
+}
+
+QString Player::lengthString(int _position)
+{
+ if (!current())
+ return QString("--:--/--:--");
+
+ QString posString;
+ QString lenString;
+ int secs, seconds, minutes;
+
+ if (_position < 0)
+ _position = position;
+
+ if (_position<0)
+ {
+ posString="--:--/";
+ }
+ else
+ { // get the position
+ bool remain = napp->displayRemaining() && current();
+ if (remain && current().length()<0)
+ {
+ remain = false;
+ }
+
+ if (remain)
+ {
+ _position = current().length() - _position;
+ }
+
+ secs = _position / 1000; // convert milliseconds -> seconds
+ seconds = secs % 60;
+ minutes = (secs - seconds) / 60;
+
+ // the string has to look like '00:00/00:00'
+ posString.sprintf("%.2d:%.2d/", minutes, seconds);
+ if (remain) posString.prepend('-');
+ }
+
+ if (!current() || current().length()<0)
+ {
+ posString+="--:--";
+ }
+ else
+ { // get the length
+ secs = current().length() / 1000; // convert milliseconds -> seconds
+ seconds = secs % 60;
+ minutes = (secs - seconds) / 60;
+
+ // the string has to look like '00:00/00:00'
+ lenString.sprintf("%.2d:%.2d", minutes, seconds);
+ posString += lenString;
+ }
+
+ return posString;
+}
+
+int Player::getLength()
+{
+ if (!current())
+ return -1;
+ return current().length(); // return track-length in milliseconds
+}
+
+void Player::openFile(const KURL &f, bool purge, bool autoplay)
+{
+ if (purge)
+ napp->playlist()->clear();
+ napp->playlist()->addFile(f, autoplay);
+}
+
+void Player::openFile(const KURL::List &f, bool purge, bool autoplay)
+{
+ if (purge)
+ napp->playlist()->clear();
+ for (KURL::List::ConstIterator i(f.begin()); i != f.end(); ++i)
+ {
+ napp->playlist()->addFile(*i, autoplay);
+ autoplay=false;
+ }
+}
+
+
+void Player::loop()
+{
+ mLoopStyle++;
+ if (mLoopStyle>Random)
+ mLoopStyle=None;
+ emit loopTypeChange(mLoopStyle);
+}
+void Player::loop(int i)
+{
+ mLoopStyle=i;
+ emit loopTypeChange(mLoopStyle);
+}
+
+void Player::removeCurrent()
+{
+ if (napp->playlist()->current())
+ napp->playlist()->current().remove();
+}
+
+void Player::setVolume(int v)
+{
+ if (v<0) v=0;
+ if (v>100) v=100;
+ mEngine->setVolume(v);
+ emit timeout();
+ emit volumeChanged(v);
+}
+
+int Player::volume() const
+{
+ return mEngine->volume();
+}
+
+void Player::aboutToPlay()
+{
+ emit aboutToOpen( mCurrent );
+}
+
+void Player::slotUpdateStreamMeta(
+ const QString &streamName, const QString &streamGenre,
+ const QString &streamUrl, const QString &streamBitrate,
+ const QString &trackTitle, const QString &trackUrl)
+{
+ PlaylistItem currentItem = napp->playlist()->current();
+ if(currentItem)
+ {
+ currentItem.setProperty("title", trackTitle);
+ currentItem.setProperty("bitrate", streamBitrate);
+
+ if(!streamName.isEmpty())
+ currentItem.setProperty("author", streamName);
+ if(!streamGenre.isEmpty())
+ currentItem.setProperty("genre", streamGenre);
+ if(!trackUrl.isEmpty())
+ currentItem.setProperty("comment", trackUrl);
+ else if(!streamUrl.isEmpty())
+ currentItem.setProperty("comment", streamUrl);
+ else
+ currentItem.clearProperty("comment");
+ emit changed();
+ }
+}
+
+#include "player.moc"