Change playlist to use Esperanza's playlistmodel

This commit is contained in:
Thomas Frauendorfer 2007-10-07 14:34:53 +02:00
parent 85cf6a8d1c
commit 503385309b
96 changed files with 2010 additions and 412 deletions

2
lib/TODO Normal file
View file

@ -0,0 +1,2 @@
Contains a copy of some of Esperanzas src/lib/ directory
Will have to be removed as soon as those files become a seperate lib

28
lib/debug.h Normal file
View file

@ -0,0 +1,28 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
// Usage: include it and then just do a DBGOUT("bla foo bar " << variable << " is awesome.");
// while in debug mode, it will all be print to console. In release mode, DBGOUT does nothing
#ifndef __DEBUG_H__
# define __DEBUG_H__
# ifdef _DEBUG
# include <QDebug>
# define DBGOUT(a) qDebug () << QString(__FILE__ ":%1").arg(__LINE__) << "[" << __func__ << "] -" << a
# else
# define DBGOUT(a)
# endif
#endif

35
lib/lib.pro Normal file
View file

@ -0,0 +1,35 @@
TEMPLATE = lib
CONFIG += static
include (../config.pri)
SOURCES += xclient.cpp \
xclientcache.cpp \
playlistmodel.cpp \
xmmsqt4.cpp
HEADERS += xclient.h \
xclientcache.h \
playlistmodel.h \
xmmsqt4.h \
debug.h
;RESOURCES = promoe.qrc
;macx:RC_FILE = promoe.icns
;macx:INCLUDEPATH = /sw/include
QT += network
;macx:QTPLUGIN += qjpeg
QMAKE_LFLAGS += -L$$[QT_INSTALL_PLUGINS]/imageformats
CONFIG += link_pkgconfig
QMAKE_CXXFLAGS += -g
;CONFIG += debug warn_on
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter
PKGCONFIG += xmms2-client xmms2-client-cpp
;CONFIG += avahi

516
lib/playlistmodel.cpp Normal file
View file

@ -0,0 +1,516 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <xmmsclient/xmmsclient++.h>
#include <QAbstractTableModel>
#include <QHash>
#include <QVariant>
#include <QMimeData>
#include <QSettings>
#include <QUrl>
#include <QFileInfo>
#include "playlistmodel.h"
PlaylistModel::PlaylistModel (QObject *parent, XClient *client, const QString &name) : QAbstractItemModel (parent)
{
// m_columns.append ("#");
m_columns.append ("Artist");
m_columns.append ("Title");
// m_colfallback.append ("");
m_colfallback.append ("");
m_colfallback.append ("url");
m_cached_size.append (QSize ());
m_cached_size.append (QSize ());
m_cached_size.append (QSize ());
connect (client, SIGNAL(gotConnection (XClient *)), this, SLOT (got_connection (XClient *)));
connect (client->cache (), SIGNAL(entryChanged (uint32_t)), this, SLOT (entry_changed (uint32_t)));
if (name == QLatin1String ("_active")) {
m_isactive = true;
}
m_name = name;
if (client->isConnected ()) {
got_connection (client);
}
}
void
PlaylistModel::set_playlist (const QString &name)
{
if (name == QLatin1String ("_active")) {
m_isactive = true;
m_client->playlist ()->currentActive () (Xmms::bind (&PlaylistModel::handle_current_pls, this));
} else {
m_isactive = false;
}
m_name = name;
m_client->playlist ()->listEntries (XClient::qToStd (name)) (Xmms::bind (&PlaylistModel::handle_list, this));
}
bool
PlaylistModel::handle_current_pls (const std::string &name)
{
if (m_name == QLatin1String ("_active")) {
m_name = XClient::stdToQ (name);
}
return true;
}
void
PlaylistModel::got_connection (XClient *client)
{
if (m_isactive) {
client->playlist ()->currentActive () (Xmms::bind (&PlaylistModel::handle_current_pls, this));
}
client->playlist ()->listEntries (XClient::qToStd (m_name)) (Xmms::bind (&PlaylistModel::handle_list, this));
client->playlist ()->currentPos () (Xmms::bind (&PlaylistModel::handle_update_pos, this));
client->playlist ()->broadcastChanged () (Xmms::bind (&PlaylistModel::handle_change, this));
client->playlist ()->broadcastCurrentPos () (Xmms::bind (&PlaylistModel::handle_update_pos, this));
client->playlist ()->broadcastLoaded () (Xmms::bind (&PlaylistModel::handle_pls_loaded, this));
m_client = client;
}
bool
PlaylistModel::handle_pls_loaded (const std::string &name)
{
if (m_isactive) {
m_client->playlist ()->listEntries (name)
(Xmms::bind (&PlaylistModel::handle_list, this));
m_name = XClient::stdToQ (name);
}
return true;
}
bool
PlaylistModel::handle_update_pos (const uint32_t &pos)
{
m_current_pos = pos;
emit dataChanged(index (pos, 0), index (pos, m_columns.size ()));
return true;
}
QList<QString>
PlaylistModel::columns () const
{
return m_columns;
}
void
PlaylistModel::setColumns (const QList<QString> &new_columns)
{
m_columns = new_columns;
reset ();
}
void
PlaylistModel::setColumnFallback (const QList<QString> &new_columns)
{
m_colfallback = new_columns;
reset ();
}
bool
PlaylistModel::handle_change (const Xmms::Dict &chg)
{
int32_t change = chg.get<int32_t> ("type");
int32_t pos = 0, npos = 0;
uint32_t id = 0;
QString s;
if (chg.contains ("position")) {
pos = chg.get<int32_t> ("position");
}
if (chg.contains ("id")) {
id = chg.get<uint32_t> ("id");
}
if (chg.contains ("name")) {
s = XClient::stdToQ (chg.get<std::string> ("name"));
}
if (s != m_name) {
return true;
}
QModelIndex idx = QModelIndex ();
switch (change) {
case XMMS_PLAYLIST_CHANGED_ADD:
beginInsertRows (idx, pos, pos);
m_plist.append (id);
endInsertRows ();
break;
case XMMS_PLAYLIST_CHANGED_INSERT:
beginInsertRows (idx, pos, pos);
m_plist.insert (pos, id);
endInsertRows ();
break;
case XMMS_PLAYLIST_CHANGED_MOVE:
npos = chg.get<int32_t> ("newposition");
beginRemoveRows (idx, pos, pos);
m_plist.removeAt (pos);
endRemoveRows ();
beginInsertRows (idx, npos, npos);
m_plist.insert (npos, id);
endInsertRows ();
if (pos < npos && pos)
pos --;
emit entryMoved (index (pos, 0), index (npos, 0));
break;
case XMMS_PLAYLIST_CHANGED_REMOVE:
m_client->cache ()->invalidate (m_plist[pos]);
beginRemoveRows (idx, pos, pos);
m_plist.removeAt (pos);
endRemoveRows ();
break;
case XMMS_PLAYLIST_CHANGED_SHUFFLE:
case XMMS_PLAYLIST_CHANGED_SORT:
case XMMS_PLAYLIST_CHANGED_CLEAR:
m_client->cache ()->invalidate_all ();
m_client->playlist ()->listEntries () (Xmms::bind (&PlaylistModel::handle_list, this));
break;
}
return true;
}
bool
PlaylistModel::handle_list (const Xmms::List< unsigned int > &list)
{
beginRemoveRows (QModelIndex (), 0, m_plist.size ());
m_plist.clear ();
endRemoveRows ();
int i = 0;
for (list.first (); list.isValid (); ++list) {
i ++;
}
beginInsertRows (QModelIndex (), 0, i);
for (list.first (); list.isValid (); ++list) {
m_plist.append (*list);
}
endInsertRows ();
return true;
}
QModelIndexList
PlaylistModel::get_idxlist_by_id (uint32_t id)
{
QModelIndexList ret;
QList<uint32_t> l = getPosById (id);
for (int i = 0; i < l.count (); i++) {
ret.append (index (l.at (i), 0));
}
return ret;
}
QList<uint32_t>
PlaylistModel::getPosById (uint32_t id)
{
QList<uint32_t> ret;
int32_t pos = m_plist.indexOf (id);
while (pos != -1) {
ret.append (pos);
pos = m_plist.indexOf (id, pos + 1);
}
return ret;
}
void
PlaylistModel::entry_changed (uint32_t id)
{
QList<uint32_t> pos = getPosById (id);
for (int i = 0; i < pos.size (); i ++) {
QModelIndex idx1 = index (pos.at (i), 0);
QModelIndex idx2 = index (pos.at (i), m_columns.size ());
emit dataChanged(idx1, idx2);
}
}
int
PlaylistModel::columnCount (const QModelIndex &parent) const
{
return m_columns.size ();
}
int
PlaylistModel::rowCount (const QModelIndex &parent) const
{
if (!parent.isValid ()) {
return m_plist.size ();
}
return 0;
}
QModelIndex
PlaylistModel::parent (const QModelIndex &idx) const
{
return QModelIndex ();
}
QModelIndex
PlaylistModel::index (int row, int column, const QModelIndex &parent) const
{
if (!parent.isValid ()) {
if (row > (m_plist.size () - 1))
return QModelIndex ();
if (row < 0)
return QModelIndex ();
return createIndex (row, column, -1);
}
return QModelIndex ();
}
QVariant
PlaylistModel::data (const QModelIndex &index, int role) const
{
if (!index.isValid ()) {
return QVariant ();
}
if (index.row () >= m_plist.size ()) {
return QVariant ();
}
if (role == MedialibIdRole) {
return QVariant (m_plist[index.row ()]);
}
if (role == Qt::SizeHintRole) {
if (m_cached_size[index.column ()].isValid ()) {
return QVariant (m_cached_size[index.column ()]);
}
return QVariant ();
}
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
QString key = m_columns[index.column ()].toLower ();
QString fallkey = m_colfallback[index.column ()].toLower ();
if (key == "#") {
return QVariant (index.row ());
} else {
unsigned int id = m_plist[index.row ()];
PlaylistModel *fake = const_cast<PlaylistModel*> (this);
QHash<QString, QVariant> d = fake->m_client->cache ()->get_info (id);
if (d.contains (key)) {
return QVariant (d[key]);
} else if (d.contains (fallkey)) {
return QVariant (d[fallkey]);
}
return QVariant ();
}
} else if (role == CurrentEntryRole) {
int i = m_current_pos;
if (index.row () == i)
return QVariant (true);
return QVariant (false);
}
return QVariant ();
}
QStringList
PlaylistModel::mimeTypes () const
{
QStringList l ("application/x-xmms2poslist");
l << "application/x-xmms2mlibid";
l << "text/uri-list";
return l;
}
QMimeData *
PlaylistModel::mimeData (const QModelIndexList &list) const
{
QMimeData *ret = new QMimeData ();
QByteArray ba;
QDataStream stream (&ba, QIODevice::WriteOnly);
QList<int> l;
for (int i = 0; i < list.size (); i ++) {
QModelIndex idx = list.at (i);
if (idx.column () != 0)
continue;
l.append (idx.row ());
}
stream << l;
ret->setData ("application/x-xmms2poslist", ba);
return ret;
}
bool
PlaylistModel::dropMimeData (const QMimeData *data,
Qt::DropAction action,
int row, int column,
const QModelIndex & parent)
{
if (parent.internalId () != -1 && parent.isValid ()) {
return false;
}
if (data->hasFormat ("application/x-xmms2poslist")) {
if (!parent.isValid ())
return false;
QByteArray ba = data->data ("application/x-xmms2poslist");
QDataStream stream (&ba, QIODevice::ReadOnly);
QList<int> l;
stream >> l;
qSort (l);
int target = parent.row ();
int mod = 0;
while (l.size ()) {
int orow = l.takeAt (0) - mod;
m_client->playlist ()->moveEntry (orow, target) ();
if (orow < target) {
mod ++;
} else {
target ++;
}
}
return true;
} else if (data->hasFormat ("application/x-xmms2mlibid")) {
QByteArray ba = data->data ("application/x-xmms2mlibid");
QDataStream stream (&ba, QIODevice::ReadOnly);
QList<int> l;
stream >> l;
int target;
if (parent.isValid ())
target = parent.row () + 1;
else
target = m_plist.size () + 1;
while (l.size ()) {
int id = l.takeAt (0);
if (target >= m_plist.size ()) {
m_client->playlist ()->addId (id) ();
} else {
m_client->playlist ()->insertId (target ++, id) ();
}
}
return true;
} else if (data->hasFormat ("text/uri-list")) {
int target;
if (parent.isValid ())
target = parent.row () + 1;
else
target = m_plist.size () + 1;
QList<QUrl> l = data->urls ();
qSort (l);
for (int i = 0; i < l.size (); i++) {
QFileInfo fi (l.at (i).toLocalFile ());
std::string s ("file:///");
s.append (fi.absoluteFilePath ().toLocal8Bit ());
if (fi.isFile ()) {
if (target >= m_plist.size ()) {
m_client->playlist ()->addUrl (s) ();
} else {
m_client->playlist ()->insertUrl (target ++, s) ();
}
} else if (fi.isDir ()) {
m_client->playlist ()->addRecursive (s) ();
}
}
return true;
}
return false;
}
Qt::DropActions
PlaylistModel::supportedDropActions () const
{
return Qt::CopyAction | Qt::MoveAction;
}
QVariant
PlaylistModel::headerData (int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole) {
return QVariant ();
}
if (orientation == Qt::Horizontal) {
if (section <= m_columns.size ())
return QVariant (m_columns[section]);
}
return QVariant ();
}
Qt::ItemFlags
PlaylistModel::flags (const QModelIndex &idx) const
{
unsigned int id = m_plist[idx.row ()];
PlaylistModel *fake = const_cast<PlaylistModel*> (this);
QHash<QString, QVariant> d = fake->m_client->cache ()->get_info (id);
Qt::ItemFlags f = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
if (idx.isValid ()) {
f |= Qt::ItemIsDropEnabled;
}
if (d.contains ("status") && d["status"] != XMMS_MEDIALIB_ENTRY_STATUS_NOT_AVAILABLE) {
f |= Qt::ItemIsEnabled;
}
return f;
}
QList<uint32_t>
PlaylistModel::get_all_id ()
{
return m_plist;
}

147
lib/playlistmodel.h Normal file
View file

@ -0,0 +1,147 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __PLAYLIST_MODEL_H__
#define __PLAYLIST_MODEL_H__
#include <xmmsclient/xmmsclient++.h>
#include <QAbstractTableModel>
#include <QVariant>
#include <QHash>
#include <QIcon>
#include "xclient.h"
/**
* @class PlaylistModel playlistmodel.h
* @brief A model that represents a playlist on the server
*
* This model will show the playlist and update it according to the
* changes from the server. This can be subclassed to be customized.
**/
class PlaylistModel : public QAbstractItemModel
{
Q_OBJECT
public:
/**
* The constructor for the PlaylistModel.
* @param parent The parent QObject for this model
* @param client The XClient object to be used in order to get the updates
* @param n The name of the playlist that this model should show
**/
PlaylistModel (QObject *parent, XClient *client, const QString &n = "_active");
enum {
DisplayRole = Qt::DisplayRole,
ToolTipRole = Qt::ToolTipRole,
CurrentEntryRole = 200,
MedialibIdRole,
AvailableRole
};
int rowCount (const QModelIndex &parent) const;
int columnCount (const QModelIndex &parent) const;
QVariant data (const QModelIndex &index, int role = DisplayRole) const;
QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags (const QModelIndex &) const;
QModelIndex parent (const QModelIndex &) const;
QModelIndex index (int row, int column, const QModelIndex &idx = QModelIndex ()) const;
QMimeData *mimeData (const QModelIndexList &list) const;
bool dropMimeData (const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent);
Qt::DropActions supportedDropActions () const;
QStringList mimeTypes () const;
/**
* Set the columns that should be shown in the view.
* @param columns A list of property keys. i.e. "artist", "album"
**/
void setColumns (const QList <QString> &columns);
/**
* Set fallback columns. A fallback column is what should be shown
* if the first column is not available for that entry.
* @param columns A list of property keys.
**/
void setColumnFallback (const QList <QString> &columns);
/**
* Return the current columns.
**/
QList<QString> columns () const;
/**
* Return a list of all entry ids that are currently in the list.
**/
QList<uint32_t> get_all_id ();
void set_cached_size (int i, const QSize &size) {
m_cached_size[i] = size;
};
QSize cached_size (int i) const {
return m_cached_size[i];
};
/**
* Return a list of QModelIndex for the entry. Since one
* entry can be in the Playlist multiple times we need to
* return a list of indexes.
* @
**/
QModelIndexList get_idxlist_by_id (uint32_t);
QModelIndex current_playlist_pos () const {
return index (m_current_pos, 0);
};
void set_playlist (const QString &);
protected:
XClient *m_client;
QList < unsigned int > m_plist;
QList < uint32_t > getPosById (uint32_t id);
QList < QString > m_columns;
QList < QString > m_colfallback;
signals:
void entryMoved (const QModelIndex &, const QModelIndex &);
public slots:
void got_connection (XClient *);
void entry_changed (uint32_t);
private:
bool handle_list (const Xmms::List< unsigned int > &list);
bool handle_change (const Xmms::Dict &chg);
bool handle_update_pos (const unsigned int &pos);
bool handle_pls_loaded (const std::string &);
bool handle_current_pls (const std::string &);
void getInfo (unsigned int id) const;
uint32_t m_current_pos;
bool m_isactive;
QList<QSize> m_cached_size;
QString m_name;
};
#endif

210
lib/xclient.cpp Normal file
View file

@ -0,0 +1,210 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <xmmsclient/xmmsclient++.h>
#include <QObject>
#include <QHash>
#include <QVariant>
#include <QErrorMessage>
#include <QSettings>
#include "xclient.h"
#include "xmmsqt4.h"
#include "debug.h"
XSettings::XSettings (QObject *parent) : QObject (parent)
{
/* dummy */
}
void
XSettings::change_settings ()
{
emit settingsChanged ();
}
QString
XClient::stdToQ (const std::string &str)
{
return QString::fromUtf8 (str.c_str ());
}
std::string
XClient::qToStd (const QString &str)
{
return std::string (str.toUtf8 ().data ());
}
QDir
XClient::esperanza_dir ()
{
QDir c (stdToQ (Xmms::getUserConfDir ()));
if (!c.cd ("clients/Esperanza")) {
c.mkpath ("clients/Esperanza");
if (!c.cd ("clients/Esperanza")) {
qDebug ("couldn't open dir");
}
return c;
} else {
return c;
}
return QDir ();
}
XClient::XClient (QObject *parent, const std::string &name) : QObject (parent), m_sync (name + "-sync")
{
m_client = NULL;
m_isconnected = false;
m_cache = new XClientCache (this, this);
m_settings = new XSettings (this);
m_name = name;
}
void XClient::disconnect ()
{
delete m_client;
m_client = NULL;
m_isconnected = false;
}
bool
XClient::connect (const char *ipcpath, const bool &sync, QWidget *parent)
{
bool tried_once = false;
try_again:
try {
delete m_client;
m_client = new Xmms::Client (m_name);
if (!ipcpath || ipcpath == "")
m_client->connect (NULL);
else
m_client->connect (ipcpath);
}
catch (Xmms::connection_error& e) {
if (ipcpath == NULL && !tried_once) {
QSettings s;
if (s.value ("core/autostart", true).toBool ()) {
if (!system ("xmms2-launcher")) {
tried_once = true;
goto try_again;
}
}
}
QErrorMessage *err = new QErrorMessage (parent);
err->showMessage ("Couldn't connect to XMMS2, please try again.");
err->exec ();
delete err;
return false;
}
m_client->setMainloop (new XmmsQT4 (m_client->getConnection ()));
if (sync) {
try {
m_sync.connect (ipcpath);
}
catch (Xmms::connection_error &e) {
qWarning ("Couldn't establish sync connection!");
}
}
m_isconnected = true;
emit gotConnection (this);
return true;
}
void
XClient::dictToQHash (const std::string &key,
const Xmms::Dict::Variant &value,
QHash<QString, QVariant> &hash)
{
if (value.type () == typeid (int32_t)) {
hash.insert (QString::fromLatin1 (key.c_str ()),
QVariant (boost::get< int32_t > (value)));
} else if (value.type () == typeid (uint32_t)) {
hash.insert (QString::fromLatin1 (key.c_str ()),
QVariant (boost::get< uint32_t > (value)));
} else {
QString val;
val = QString::fromUtf8 (boost::get< std::string > (value).c_str ());
hash.insert (stdToQ (key), QVariant (val));
}
}
/**
* convert a Xmms::Dict to a QHash<QString, QVariant>
**/
QHash<QString, QVariant>
XClient::convert_dict (const Xmms::Dict &dict)
{
QHash<QString, QVariant> hash;
dict.each (boost::bind (&XClient::dictToQHash,
_1, _2, boost::ref (hash)));
return hash;
}
void
XClient::propDictToQHash (const std::string &key,
const Xmms::Dict::Variant &value,
const std::string &source,
QHash<QString, QVariant> &hash)
{
if (value.type () == typeid (int32_t)) {
hash.insert (QString::fromLatin1 (key.c_str ()),
QVariant (boost::get< int32_t > (value)));
} else if (value.type () == typeid (uint32_t)) {
hash.insert (QString::fromLatin1 (key.c_str ()),
QVariant (boost::get< uint32_t > (value)));
} else {
QString val;
if (key == "url") {
/* This really is wrong ...*/
char *c = const_cast<char *>(xmmsc_result_decode_url (NULL, boost::get< std::string >(value).c_str ()));
val = QString::fromUtf8 (c);
val = val.mid (val.lastIndexOf ("/") + 1);
if (val.isEmpty ()) {
val = QString::fromUtf8 (c);
}
free (c);
} else {
val = QString::fromUtf8 (boost::get< std::string > (value).c_str ());
}
hash.insert (stdToQ (key), QVariant (val));
}
}
/**
* convert a Xmms::PropDict to a QHash<QString, QVariant>
**/
QHash<QString, QVariant>
XClient::convert_propdict (const Xmms::PropDict &dict)
{
QHash<QString, QVariant> hash;
dict.each (boost::bind (&XClient::propDictToQHash,
_1, _2, _3, boost::ref (hash)));
return hash;
}

110
lib/xclient.h Normal file
View file

@ -0,0 +1,110 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __XCLIENT_H__
#define __XCLIENT_H__
#include <xmmsclient/xmmsclient++.h>
class XClient;
#include <QObject>
#include <QHash>
#include <QVariant>
#include <QDir>
#include <QWidget>
#include "xclientcache.h"
class XSettings : public QObject
{
Q_OBJECT
public:
XSettings (QObject *);
void change_settings ();
signals:
void settingsChanged ();
};
class XClient : public QObject {
Q_OBJECT
public:
XClient (QObject *, const std::string &);
void disconnect ();
bool connect (const char *path = NULL, const bool &sync = false, QWidget* parent = NULL);
static void propDictToQHash (const std::string &key,
const Xmms::Dict::Variant &value,
const std::string &source,
QHash<QString, QVariant> &hash);
static void dictToQHash (const std::string &key,
const Xmms::Dict::Variant &value,
QHash<QString, QVariant> &hash);
static QHash<QString, QVariant> convert_propdict (const Xmms::PropDict &);
static QHash<QString, QVariant> convert_dict (const Xmms::Dict &);
XClientCache *cache () const {
return m_cache;
};
XSettings *settings () const {
return m_settings;
};
const Xmms::Client *sync () const {
return &m_sync;
};
static QString stdToQ (const std::string &);
static std::string qToStd (const QString &);
bool isConnected () const {
return m_isconnected;
};
static QDir esperanza_dir ();
void setDisconnectCallback (const Xmms::DisconnectCallback::slot_type &slot) { m_client->setDisconnectCallback (slot); }
const Xmms::Collection* collection () { if (m_client && m_client->isConnected ()) return &m_client->collection; else return NULL; }
const Xmms::Playlist* playlist () { if (m_client && m_client->isConnected ()) return &m_client->playlist; else return NULL; }
const Xmms::Playback* playback () { if (m_client && m_client->isConnected ()) return &m_client->playback; else return NULL; }
const Xmms::Medialib* medialib () { if (m_client && m_client->isConnected ()) return &m_client->medialib; else return NULL; }
const Xmms::Bindata* bindata () { if (m_client && m_client->isConnected ()) return &m_client->bindata; else return NULL; }
const Xmms::Config* config () { if (m_client && m_client->isConnected ()) return &m_client->config; else return NULL; }
const Xmms::Stats* stats () { if (m_client && m_client->isConnected ()) return &m_client->stats; else return NULL; }
signals:
void gotConnection (XClient *);
protected:
Xmms::Client *m_client;
private:
std::string m_name;
// Xmms::Client *m_client;
XClientCache *m_cache;
XSettings *m_settings;
bool m_isconnected;
Xmms::Client m_sync;
};
#endif

167
lib/xclientcache.cpp Normal file
View file

@ -0,0 +1,167 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "xclientcache.h"
#include <QObject>
#include <QIcon>
#include <QPixmap>
#include <QHash>
#include <QList>
#include <QVariant>
#include <QPixmapCache>
#include <QSettings>
XClientCache::XClientCache (QObject *parent, XClient *client) : QObject (parent)
{
QSettings s;
connect (client, SIGNAL (gotConnection (XClient *)), this, SLOT (got_connection (XClient *)));
QPixmapCache::setCacheLimit (s.value ("core/pixmapcache").toInt ());
}
void
XClientCache::got_connection (XClient *client)
{
m_client = client;
client->playback ()->signalPlaytime () (Xmms::bind (&XClientCache::handle_playtime, this));
client->playback ()->getPlaytime () (Xmms::bind (&XClientCache::handle_playtime, this));
client->medialib ()->broadcastEntryChanged () (Xmms::bind (&XClientCache::handle_mlib_entry_changed, this));
}
bool
XClientCache::handle_medialib_info_error (const std::string &error, uint32_t id)
{
/* we probably couldn't find that entry, let's remove it */
m_info.remove (id);
emit entryRemoved (id);
return true;
}
bool
XClientCache::handle_medialib_info (const Xmms::PropDict &info)
{
int32_t id = info.get<int32_t> ("id");
QHash<QString, QVariant> hash = XClient::convert_propdict (info);
m_info.insert (id, hash);
emit entryChanged (id);
return true;
}
void
XClientCache::extra_info_set (uint32_t id, const QString &name,
const QVariant &value)
{
m_extra_info[id][name] = value;
}
QVariant
XClientCache::extra_info_get (uint32_t id, const QString &name)
{
return m_extra_info[id][name];
}
void
XClientCache::invalidate (uint32_t id)
{
m_info.remove (id);
}
void
XClientCache::invalidate_all ()
{
m_info.clear ();
}
bool
XClientCache::handle_bindata (const Xmms::bin &data, const QString &id)
{
QPixmap i;
i.loadFromData (data.c_str (), data.size());
if (i.isNull ()) {
return true;
}
/* conserve memory client side */
if (i.width () < 300) {
i = i.scaledToWidth (300, Qt::SmoothTransformation);
}
QPixmapCache::insert (id, i);
QList<uint32_t> ids = m_icon_map[id];
for (int i = 0; i < ids.size (); i++) {
emit entryChanged (ids.at (i));
}
return true;
}
QIcon
XClientCache::get_icon (uint32_t id)
{
return QIcon (get_pixmap (id));
}
QPixmap
XClientCache::get_pixmap (uint32_t id)
{
if (m_info[id].contains ("picture_front")) {
QString hash = m_info[id]["picture_front"].toString ();
QPixmap p;
if (!QPixmapCache::find (hash, p)) {
m_client->bindata ()->retrieve (hash.toStdString ()) (
boost::bind (&XClientCache::handle_bindata, this, _1, hash));
QPixmapCache::insert (hash, QPixmap ());
m_icon_map[hash].append (id);
}
return p;
}
return QPixmap ();
}
QHash<QString, QVariant>
XClientCache::get_info (uint32_t id)
{
if (!m_info.contains (id)) {
m_client->medialib ()->getInfo (id) (Xmms::bind (&XClientCache::handle_medialib_info, this),
boost::bind (&XClientCache::handle_medialib_info_error, this, _1, id));
m_info[id] = QHash<QString, QVariant> ();
}
return m_info[id];
}
bool
XClientCache::handle_mlib_entry_changed (const uint32_t &id)
{
m_client->medialib ()->getInfo (id) (Xmms::bind (&XClientCache::handle_medialib_info, this));
return true;
}
bool
XClientCache::handle_playtime (const unsigned int &tme)
{
emit playtime(tme);
return true;
}

80
lib/xclientcache.h Normal file
View file

@ -0,0 +1,80 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __XCLIENTCACHE_H__
#define __XCLIENTCACHE_H__
class XClientCache;
#include "xclient.h"
#include <QObject>
#include <QIcon>
#include <QPixmap>
#include <QHash>
#include <QList>
#include <QVariant>
#include <QPixmapCache>
class XClientCache : public QObject
{
Q_OBJECT
public:
XClientCache (QObject *, XClient *);
QHash<QString, QVariant> get_info (uint32_t id);
QIcon get_icon (uint32_t id);
QPixmap get_pixmap (uint32_t id);
QVariant extra_info_get (uint32_t, const QString &);
void extra_info_set (uint32_t, const QString &, const QVariant &);
void invalidate (uint32_t);
void invalidate_all ();
bool extra_info_has (uint32_t id, const QString &s) {
if (m_extra_info.contains (id))
if (m_extra_info[id].contains (s))
return true;
return false;
};
signals:
void entryChanged (uint32_t);
void entryRemoved (uint32_t);
void playtime (uint32_t);
public slots:
void got_connection (XClient *);
private:
bool handle_medialib_info (const Xmms::PropDict &info);
bool handle_medialib_info_error (const std::string &, uint32_t);
bool handle_mlib_entry_changed (const uint32_t &id);
bool handle_bindata (const Xmms::bin &, const QString &);
bool handle_playtime (const unsigned int &tme);
QHash< uint32_t, QHash<QString, QVariant> > m_info;
QHash < QString, QList <uint32_t> > m_icon_map;
QHash < int, QHash < QString, QVariant > > m_extra_info;
XClient *m_client;
};
#endif

91
lib/xmmsqt4.cpp Normal file
View file

@ -0,0 +1,91 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <xmmsclient/xmmsclient++/mainloop.h>
#include <xmmsclient/xmmsclient.h>
#include "xmmsqt4.h"
#include <QApplication>
#include <QObject>
#include <QSocketNotifier>
static void CheckWrite (int i, void *userdata);
XmmsQT4::XmmsQT4 (xmmsc_connection_t *xmmsc) :
QObject (), Xmms::MainloopInterface (xmmsc),
m_fd (0), m_rsock (0), m_wsock (0), m_xmmsc (xmmsc)
{
m_fd = xmmsc_io_fd_get (xmmsc);
xmmsc_io_need_out_callback_set (xmmsc, CheckWrite, this);
m_rsock = new QSocketNotifier (m_fd, QSocketNotifier::Read, this);
connect (m_rsock, SIGNAL (activated (int)), SLOT (OnRead ()));
m_rsock->setEnabled (true);
m_wsock = new QSocketNotifier (m_fd, QSocketNotifier::Write, this);
connect (m_wsock, SIGNAL (activated (int)), SLOT (OnWrite ()));
m_wsock->setEnabled (false);
running_ = true;
}
XmmsQT4::~XmmsQT4 ()
{
delete m_rsock;
delete m_wsock;
}
void XmmsQT4::run ()
{
}
xmmsc_connection_t *XmmsQT4::GetXmmsConnection ()
{
return m_xmmsc;
}
void XmmsQT4::OnRead ()
{
if (!xmmsc_io_in_handle (m_xmmsc)) {
return; /* exception? */
}
}
void XmmsQT4::OnWrite ()
{
if (!xmmsc_io_out_handle (m_xmmsc)) {
return; /* exception? */
}
}
void XmmsQT4::ToggleWrite (bool toggle)
{
m_wsock->setEnabled (toggle);
}
static void CheckWrite (int i, void *userdata)
{
XmmsQT4 *obj = static_cast< XmmsQT4* > (userdata);
if (xmmsc_io_want_out (obj->GetXmmsConnection ())) {
obj->ToggleWrite (true);
} else {
obj->ToggleWrite (false);
}
}

50
lib/xmmsqt4.h Normal file
View file

@ -0,0 +1,50 @@
/**
* This file is a part of Esperanza, an XMMS2 Client.
*
* Copyright (C) 2005-2007 XMMS2 Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __XMMSQT4_H__
#define __XMMSQT4_H__
#include <xmmsclient/xmmsclient++/mainloop.h>
#include <QApplication>
#include <QObject>
#include <QSocketNotifier>
class XmmsQT4 : public QObject, public Xmms::MainloopInterface
{
Q_OBJECT
public:
XmmsQT4(xmmsc_connection_t *xmmsc);
~XmmsQT4();
void run ();
void ToggleWrite(bool toggle);
xmmsc_connection_t *GetXmmsConnection();
public slots:
void OnRead ();
void OnWrite ();
private:
int m_fd;
QSocketNotifier *m_rsock;
QSocketNotifier *m_wsock;
xmmsc_connection_t *m_xmmsc;
};
#endif