1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-13 17:43:59 +02:00

* Fixed phonon branch.

This commit is contained in:
Christian Muehlhaeuser
2011-03-04 08:48:12 +01:00
52 changed files with 539 additions and 140 deletions

View File

@@ -1,6 +1,16 @@
PROJECT( tomahawk ) PROJECT( tomahawk )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
###
### Tomahawk application info
###
SET( ORGANIZATION_NAME "Tomahawk" )
SET( ORGANIZATION_DOMAIN "tomahawk-player.org" )
SET( APPLICATION_NAME "Player" )
SET( VERSION "0.0.0" )
# set paths
SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/CMakeModules" ) SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/CMakeModules" )
SET( THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty ) SET( THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty )

View File

@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>tomahawk</string> <string>tomahawk</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>org.tomahawk.Tomahawk</string> <string>org.tomahawk-player.org.Tomahawk</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>

View File

@@ -62,7 +62,7 @@ function deposx_change
function deplib_change function deplib_change
{ {
install_name_tool -change /usr/local/Cellar/liblastfm/0.3.1/lib/liblastfm.0.dylib @executable_path/liblastfm.0.dylib $1 install_name_tool -change /usr/local/Cellar/liblastfm/0.3.1/lib/liblastfm.0.dylib @executable_path/liblastfm.0.dylib $1
install_name_tool -change libqjson.0.dylib @executable_path/libqjson.0.dylib $1 install_name_tool -change /usr/local/Cellar/qjson/0.7.1/lib/libqjson.0.dylib @executable_path/libqjson.0.dylib $1
install_name_tool -change /usr/local/lib/libechonest.1.1.dylib @executable_path/libechonest.1.1.dylib $1 install_name_tool -change /usr/local/lib/libechonest.1.1.dylib @executable_path/libechonest.1.1.dylib $1
install_name_tool -change /usr/local/lib/libclucene-core.0.9.23.dylib @executable_path/libclucene-core.0.9.23.dylib $1 install_name_tool -change /usr/local/lib/libclucene-core.0.9.23.dylib @executable_path/libclucene-core.0.9.23.dylib $1
install_name_tool -change /usr/local/lib/libclucene-shared.0.9.23.dylib @executable_path/libclucene-shared.0.9.23.dylib $1 install_name_tool -change /usr/local/lib/libclucene-shared.0.9.23.dylib @executable_path/libclucene-shared.0.9.23.dylib $1
@@ -80,6 +80,11 @@ function deplib_change
install_name_tool -change $ORIGROOT/libsip_zeroconf.dylib @executable_path/libsip_zeroconf.dylib $1 install_name_tool -change $ORIGROOT/libsip_zeroconf.dylib @executable_path/libsip_zeroconf.dylib $1
install_name_tool -change $ORIGROOT/thirdparty/jdns/libtomahawk_jdns.dylib @executable_path/libtomahawk_jdns.dylib $1 install_name_tool -change $ORIGROOT/thirdparty/jdns/libtomahawk_jdns.dylib @executable_path/libtomahawk_jdns.dylib $1
install_name_tool -change $ORIGROOT/thirdparty/qtweetlib/libtomahawk_qtweetlib.dylib @executable_path/libtomahawk_qtweetlib.dylib $1 install_name_tool -change $ORIGROOT/thirdparty/qtweetlib/libtomahawk_qtweetlib.dylib @executable_path/libtomahawk_qtweetlib.dylib $1
install_name_tool -change libqjson.0.dylib @executable_path/libqjson.0.dylib $1
install_name_tool -change libechonest.1.1.dylib @executable_path/libechonest.1.1.dylib $1
install_name_tool -change libclucene-core.0.9.23.dylib @executable_path/libclucene-core.0.9.23.dylib $1
install_name_tool -change libclucene-shared.0.9.23.dylib @executable_path/libclucene-shared.0.9.23.dylib $1
} }
################################################################################ ################################################################################

View File

@@ -44,7 +44,7 @@
</head> </head>
<body> <body>
<a href="http://www.playdar.org/" title="Tomahawk - Powered by Playdar" id="head"> <a href="http://www.playdar.org/" title="Tomahawk - Powered by Playdar" id="head">
<img alt="Tomahawk - Powered by Playdar" src="/static/playdar_auth_logo.gif" width="233" height="68"/> <img alt="Tomahawk - Powered by Playdar" src="/staticdata/tomahawk_auth_logo.png" width="233" height="68"/>
</a> </a>
<div id="content"> <div id="content">

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -85,5 +85,6 @@
<file>./data/icons/audio-x-generic-16x16.png</file> <file>./data/icons/audio-x-generic-16x16.png</file>
<file>./data/www/auth.html</file> <file>./data/www/auth.html</file>
<file>./data/www/auth.na.html</file> <file>./data/www/auth.na.html</file>
<file>./data/www/tomahawk_banner_small.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -1,6 +1,12 @@
#ifndef CONFIG_H_IN #ifndef CONFIG_H_IN
#define CONFIG_H_IN #define CONFIG_H_IN
#cmakedefine ORGANIZATION_NAME "${ORGANIZATION_NAME}"
#cmakedefine ORGANIZATION_DOMAIN "${ORGANIZATION_DOMAIN}"
#cmakedefine APPLICATION_NAME "${APPLICATION_NAME}"
#cmakedefine VERSION "${VERSION}"
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" #define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#cmakedefine SNOW_LEOPARD #cmakedefine SNOW_LEOPARD

View File

@@ -43,6 +43,7 @@ set( libSources
database/databasecommand_allalbums.cpp database/databasecommand_allalbums.cpp
database/databasecommand_alltracks.cpp database/databasecommand_alltracks.cpp
database/databasecommand_addfiles.cpp database/databasecommand_addfiles.cpp
database/databasecommand_deletefiles.cpp
database/databasecommand_dirmtimes.cpp database/databasecommand_dirmtimes.cpp
database/databasecommand_loadfile.cpp database/databasecommand_loadfile.cpp
database/databasecommand_logplayback.cpp database/databasecommand_logplayback.cpp
@@ -181,6 +182,7 @@ set( libHeaders
database/databasecommand_allalbums.h database/databasecommand_allalbums.h
database/databasecommand_alltracks.h database/databasecommand_alltracks.h
database/databasecommand_addfiles.h database/databasecommand_addfiles.h
database/databasecommand_deletefiles.h
database/databasecommand_dirmtimes.h database/databasecommand_dirmtimes.h
database/databasecommand_loadfile.h database/databasecommand_loadfile.h
database/databasecommand_logplayback.h database/databasecommand_logplayback.h

View File

@@ -252,7 +252,7 @@ AudioEngine::playItem( PlaylistInterface* playlist, const Tomahawk::result_ptr&
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
m_playlist = playlist; setPlaylist( playlist );
m_currentTrackPlaylist = playlist; m_currentTrackPlaylist = playlist;
loadTrack( result ); loadTrack( result );
@@ -298,6 +298,14 @@ AudioEngine::timerTriggered( qint64 time )
} }
void
AudioEngine::setPlaylist( PlaylistInterface* playlist )
{
m_playlist = playlist;
emit playlistChanged( playlist );
}
void void
AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result ) AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
{ {

View File

@@ -53,7 +53,7 @@ public slots:
void mute(); void mute();
void playItem( PlaylistInterface* playlist, const Tomahawk::result_ptr& result ); void playItem( PlaylistInterface* playlist, const Tomahawk::result_ptr& result );
void setPlaylist( PlaylistInterface* playlist ) { m_playlist = playlist; } void setPlaylist( PlaylistInterface* playlist );
void setQueue( PlaylistInterface* queue ) { m_queue = queue; } void setQueue( PlaylistInterface* queue ) { m_queue = queue; }
void onTrackAboutToFinish(); void onTrackAboutToFinish();
@@ -72,6 +72,8 @@ signals:
void timerSeconds( unsigned int secondsElapsed ); void timerSeconds( unsigned int secondsElapsed );
void timerPercentage( unsigned int percentage ); void timerPercentage( unsigned int percentage );
void playlistChanged( PlaylistInterface* playlist );
void error( AudioErrorCode errorCode ); void error( AudioErrorCode errorCode );
private slots: private slots:

View File

@@ -153,10 +153,40 @@ Collection::setDynamicPlaylists( const QList< Tomahawk::dynplaylist_ptr >& plist
void void
Collection::setTracks( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::collection_ptr collection ) Collection::setTracks( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection )
{ {
qDebug() << Q_FUNC_INFO << tracks.count() << collection->name(); qDebug() << Q_FUNC_INFO << tracks.count() << collection->name();
m_tracks << tracks; m_tracks << tracks;
emit tracksAdded( tracks, collection ); emit tracksAdded( tracks, collection );
} }
void
Collection::delTracks( const QStringList& files, const Tomahawk::collection_ptr& collection )
{
qDebug() << Q_FUNC_INFO << files.count() << collection->name();
QList<Tomahawk::query_ptr> tracks;
int i = 0;
foreach ( const query_ptr& query, m_tracks )
{
foreach ( QString file, files )
{
foreach ( const result_ptr& result, query->results() )
{
if ( file == result->url() )
{
qDebug() << Q_FUNC_INFO << "Found deleted result:" << file;
tracks << query;
m_tracks.removeAt( i );
}
}
}
i++;
}
emit tracksRemoved( tracks, collection );
}

View File

@@ -9,6 +9,7 @@
#define TOMAHAWK_COLLECTION_H #define TOMAHAWK_COLLECTION_H
#include <QHash> #include <QHash>
#include <QDir>
#include <QList> #include <QList>
#include <QSharedPointer> #include <QSharedPointer>
#include <QDebug> #include <QDebug>
@@ -56,7 +57,7 @@ public:
signals: signals:
void tracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& ); void tracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& );
void tracksRemoved( const QList<QVariant>&, const Tomahawk::collection_ptr& ); void tracksRemoved( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& );
void tracksFinished( const Tomahawk::collection_ptr& ); void tracksFinished( const Tomahawk::collection_ptr& );
void playlistsAdded( const QList<Tomahawk::playlist_ptr>& ); void playlistsAdded( const QList<Tomahawk::playlist_ptr>& );
@@ -67,11 +68,13 @@ signals:
public slots: public slots:
virtual void addTracks( const QList<QVariant>& newitems ) = 0; virtual void addTracks( const QList<QVariant>& newitems ) = 0;
virtual void removeTracks( const QList<QVariant> &olditems ) = 0; virtual void removeTracks( const QDir& dir ) = 0;
void setPlaylists( const QList<Tomahawk::playlist_ptr>& plists ); void setPlaylists( const QList<Tomahawk::playlist_ptr>& plists );
void setDynamicPlaylists( const QList< Tomahawk::dynplaylist_ptr >& dynplists ); void setDynamicPlaylists( const QList< Tomahawk::dynplaylist_ptr >& dynplists );
void setTracks( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::collection_ptr collection ); void setTracks( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection );
void delTracks( const QStringList& files, const Tomahawk::collection_ptr& collection );
protected: protected:
QString m_name; QString m_name;
@@ -79,8 +82,8 @@ protected:
private: private:
source_ptr m_source; source_ptr m_source;
QList< Tomahawk::playlist_ptr > m_playlists;
QList< Tomahawk::query_ptr > m_tracks; QList< Tomahawk::query_ptr > m_tracks;
QList< Tomahawk::playlist_ptr > m_playlists;
QList< Tomahawk::dynplaylist_ptr > m_dynplaylists; QList< Tomahawk::dynplaylist_ptr > m_dynplaylists;
}; };

View File

@@ -3,6 +3,7 @@
#include "database/database.h" #include "database/database.h"
#include "databasecommand_alltracks.h" #include "databasecommand_alltracks.h"
#include "databasecommand_addfiles.h" #include "databasecommand_addfiles.h"
#include "databasecommand_deletefiles.h"
#include "databasecommand_loadallplaylists.h" #include "databasecommand_loadallplaylists.h"
#include "databasecommand_loadalldynamicplaylists.h" #include "databasecommand_loadalldynamicplaylists.h"
@@ -68,13 +69,12 @@ DatabaseCollection::addTracks( const QList<QVariant> &newitems )
void void
DatabaseCollection::removeTracks( const QList<QVariant> &olditems ) DatabaseCollection::removeTracks( const QDir& dir )
{ {
// FIXME qDebug() << Q_FUNC_INFO << dir;
Q_ASSERT( false ); DatabaseCommand_DeleteFiles* cmd = new DatabaseCommand_DeleteFiles( dir, source() );
// TODO RemoveTracks cmd, probably builds a temp table of all the URLs in Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
// olditems, then joins on that to batch-delete.
} }

View File

@@ -1,6 +1,8 @@
#ifndef DATABASECOLLECTION_H #ifndef DATABASECOLLECTION_H
#define DATABASECOLLECTION_H #define DATABASECOLLECTION_H
#include <QDir>
#include "collection.h" #include "collection.h"
#include "source.h" #include "source.h"
#include "typedefs.h" #include "typedefs.h"
@@ -28,7 +30,7 @@ public:
public slots: public slots:
virtual void addTracks( const QList<QVariant>& newitems ); virtual void addTracks( const QList<QVariant>& newitems );
virtual void removeTracks( const QList<QVariant> &olditems ); virtual void removeTracks( const QDir& dir );
private slots: private slots:
void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data ); void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data );

View File

@@ -4,6 +4,7 @@
#include "databasecommand_addfiles.h" #include "databasecommand_addfiles.h"
#include "databasecommand_createplaylist.h" #include "databasecommand_createplaylist.h"
#include "databasecommand_deletefiles.h"
#include "databasecommand_deleteplaylist.h" #include "databasecommand_deleteplaylist.h"
#include "databasecommand_logplayback.h" #include "databasecommand_logplayback.h"
#include "databasecommand_renameplaylist.h" #include "databasecommand_renameplaylist.h"
@@ -60,6 +61,13 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd ); QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return cmd; return cmd;
} }
else if( name == "deletefiles" )
{
DatabaseCommand_DeleteFiles * cmd = new DatabaseCommand_DeleteFiles;
cmd->setSource( source );
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return cmd;
}
else if( name == "createplaylist" ) else if( name == "createplaylist" )
{ {
DatabaseCommand_CreatePlaylist * cmd = new DatabaseCommand_CreatePlaylist; DatabaseCommand_CreatePlaylist * cmd = new DatabaseCommand_CreatePlaylist;

View File

@@ -73,19 +73,14 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
TomahawkSqlQuery query_trackattr = dbi->newquery(); TomahawkSqlQuery query_trackattr = dbi->newquery();
TomahawkSqlQuery query_file_del = dbi->newquery(); TomahawkSqlQuery query_file_del = dbi->newquery();
query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) " query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" );
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)" ); query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) VALUES (?, ?, ?, ?, ?)" );
query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) " query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) VALUES (?, ?, ?)" );
"VALUES (?,?,?,?,?)" );
query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) "
"VALUES (?,?,?)" );
query_file_del.prepare( QString( "DELETE FROM file WHERE source %1 AND url = ?" ) query_file_del.prepare( QString( "DELETE FROM file WHERE source %1 AND url = ?" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) ); .arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
int added = 0; int added = 0;
QVariant srcid = source()->isLocal() ? QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
QVariant( QVariant::Int ) : source()->id();
qDebug() << "Adding" << m_files.length() << "files to db for source" << srcid; qDebug() << "Adding" << m_files.length() << "files to db for source" << srcid;
QList<QVariant>::iterator it; QList<QVariant>::iterator it;
@@ -96,15 +91,15 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
QString url = m.value( "url" ).toString(); QString url = m.value( "url" ).toString();
int mtime = m.value( "mtime" ).toInt(); int mtime = m.value( "mtime" ).toInt();
int size = m.value( "size" ).toInt(); uint size = m.value( "size" ).toUInt();
QString hash = m.value( "hash" ).toString(); QString hash = m.value( "hash" ).toString();
QString mimetype = m.value( "mimetype" ).toString(); QString mimetype = m.value( "mimetype" ).toString();
int duration = m.value( "duration" ).toInt(); uint duration = m.value( "duration" ).toUInt();
int bitrate = m.value( "bitrate" ).toInt(); uint bitrate = m.value( "bitrate" ).toUInt();
QString artist = m.value( "artist" ).toString(); QString artist = m.value( "artist" ).toString();
QString album = m.value( "album" ).toString(); QString album = m.value( "album" ).toString();
QString track = m.value( "track" ).toString(); QString track = m.value( "track" ).toString();
int albumpos = m.value( "albumpos" ).toInt(); uint albumpos = m.value( "albumpos" ).toUInt();
int year = m.value( "year" ).toInt(); int year = m.value( "year" ).toInt();
int fileid = 0, artistid = 0, albumid = 0, trackid = 0; int fileid = 0, artistid = 0, albumid = 0, trackid = 0;
@@ -139,9 +134,7 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
v = m; v = m;
if( !source()->isLocal() ) if( !source()->isLocal() )
url = QString( "servent://%1\t%2" ) url = QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( url );
.arg( source()->userName() )
.arg( url );
bool isnew; bool isnew;
artistid = dbi->artistId( artist, isnew ); artistid = dbi->artistId( artist, isnew );

View File

@@ -36,8 +36,8 @@ public:
void setFiles( const QVariantList& f ) { m_files = f; } void setFiles( const QVariantList& f ) { m_files = f; }
signals: signals:
void done( const QList<QVariant>&, Tomahawk::collection_ptr ); void done( const QList<QVariant>&, const Tomahawk::collection_ptr& );
void notify( const QList<Tomahawk::query_ptr>&, Tomahawk::collection_ptr ); void notify( const QList<Tomahawk::query_ptr>&, const Tomahawk::collection_ptr& );
private: private:
QVariantList m_files; QVariantList m_files;

View File

@@ -0,0 +1,122 @@
#include "databasecommand_deletefiles.h"
#include <QSqlQuery>
#include "artist.h"
#include "album.h"
#include "collection.h"
#include "database/database.h"
#include "databasecommand_collectionstats.h"
#include "databaseimpl.h"
#include "network/controlconnection.h"
using namespace Tomahawk;
// After changing a collection, we need to tell other bits of the system:
void
DatabaseCommand_DeleteFiles::postCommitHook()
{
qDebug() << Q_FUNC_INFO;
// make the collection object emit its tracksAdded signal, so the
// collection browser will update/fade in etc.
Collection* coll = source()->collection().data();
connect( this, SIGNAL( notify( QStringList, Tomahawk::collection_ptr ) ),
coll, SLOT( delTracks( QStringList, Tomahawk::collection_ptr ) ), Qt::QueuedConnection );
emit notify( m_files, source()->collection() );
// also re-calc the collection stats, to updates the "X tracks" in the sidebar etc:
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( source() );
connect( cmd, SIGNAL( done( QVariantMap ) ),
source().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
if( source()->isLocal() )
Servent::instance()->triggerDBSync();
}
void
DatabaseCommand_DeleteFiles::exec( DatabaseImpl* dbi )
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT( !source().isNull() );
int deleted = 0;
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
TomahawkSqlQuery delquery = dbi->newquery();
if ( !m_dir.path().isEmpty() && source()->isLocal() )
{
qDebug() << "Deleting" << m_dir.path() << "from db for localsource" << srcid;
TomahawkSqlQuery dirquery = dbi->newquery();
dirquery.prepare( QString( "SELECT id, url FROM file WHERE source %1 AND url LIKE ?" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND id = ?" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
dirquery.bindValue( 0, "file://" + m_dir.absolutePath() + "/%" );
dirquery.exec();
while ( dirquery.next() )
{
QFileInfo fi( dirquery.value( 1 ).toString().mid( 7 ) ); // remove file://
if ( fi.absolutePath() != m_dir.absolutePath() )
{
qDebug() << "Skipping subdir:" << fi.absolutePath();
continue;
}
m_ids << dirquery.value( 0 ).toUInt();
m_files << dirquery.value( 1 ).toString();
}
foreach ( const QVariant& id, m_ids )
{
delquery.bindValue( 0, id.toUInt() );
if( !delquery.exec() )
{
qDebug() << "Failed to delete file:"
<< delquery.lastError().databaseText()
<< delquery.lastError().driverText()
<< delquery.boundValues();
continue;
}
deleted++;
}
}
else
{
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND url = ?" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
foreach( const QVariant& id, m_ids )
{
qDebug() << "Deleting" << id.toUInt() << "from db for source" << srcid;
const QString url = QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( id.toString() );
m_files << url;
delquery.bindValue( 0, id.toUInt() );
if( !delquery.exec() )
{
qDebug() << "Failed to delete file:"
<< delquery.lastError().databaseText()
<< delquery.lastError().driverText()
<< delquery.boundValues();
continue;
}
deleted++;
}
}
qDebug() << "Deleted" << deleted << m_ids << m_files;
emit done( m_files, source()->collection() );
}

View File

@@ -0,0 +1,52 @@
#ifndef DATABASECOMMAND_DELETEFILES_H
#define DATABASECOMMAND_DELETEFILES_H
#include <QObject>
#include <QDir>
#include <QVariantMap>
#include "database/databasecommandloggable.h"
#include "typedefs.h"
#include "query.h"
#include "dllmacro.h"
class DLLEXPORT DatabaseCommand_DeleteFiles : public DatabaseCommandLoggable
{
Q_OBJECT
Q_PROPERTY( QVariantList ids READ ids WRITE setIds )
public:
explicit DatabaseCommand_DeleteFiles( QObject* parent = 0 )
: DatabaseCommandLoggable( parent )
{}
explicit DatabaseCommand_DeleteFiles( const QDir& dir, const Tomahawk::source_ptr& source, QObject* parent = 0 )
: DatabaseCommandLoggable( parent ), m_dir( dir )
{
setSource( source );
}
virtual QString commandname() const { return "deletefiles"; }
virtual void exec( DatabaseImpl* );
virtual bool doesMutates() const { return true; }
virtual void postCommitHook();
QStringList files() const { return m_files; }
void setFiles( const QStringList& f ) { m_files = f; }
QVariantList ids() const { return m_ids; }
void setIds( const QVariantList& i ) { m_ids = i; }
signals:
void done( const QStringList&, const Tomahawk::collection_ptr& );
void notify( const QStringList&, const Tomahawk::collection_ptr& );
private:
QDir m_dir;
QStringList m_files;
QVariantList m_ids;
};
#endif // DATABASECOMMAND_DELETEFILES_H

View File

@@ -56,7 +56,7 @@ void DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
e->setLastmodified( 0 ); // TODO e->lastmodified = query.value(6).toInt(); e->setLastmodified( 0 ); // TODO e->lastmodified = query.value(6).toInt();
e->setResultHint( query.value( 8 ).toString() ); e->setResultHint( query.value( 8 ).toString() );
Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString(), false ); Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() );
q->setResultHint( query.value( 8 ).toString() ); q->setResultHint( query.value( 8 ).toString() );
e->setQuery( q ); e->setQuery( q );

View File

@@ -19,7 +19,7 @@
*/ */
#include "schema.sql.h" #include "schema.sql.h"
#define CURRENT_SCHEMA_VERSION 21 #define CURRENT_SCHEMA_VERSION 22
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent ) DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )

View File

@@ -219,7 +219,7 @@ CREATE INDEX artist_tags_tag ON artist_tags(tag);
-- so that we can always do range queries. -- so that we can always do range queries.
CREATE TABLE IF NOT EXISTS track_attributes ( CREATE TABLE IF NOT EXISTS track_attributes (
id INTEGER NOT NULL, -- track id id INTEGER REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, -- track id
k TEXT NOT NULL, k TEXT NOT NULL,
v TEXT NOT NULL v TEXT NOT NULL
); );
@@ -241,6 +241,8 @@ CREATE TABLE IF NOT EXISTS playback_log (
CREATE INDEX playback_log_source ON playback_log(source); CREATE INDEX playback_log_source ON playback_log(source);
CREATE INDEX playback_log_track ON playback_log(track); CREATE INDEX playback_log_track ON playback_log(track);
-- auth information for http clients -- auth information for http clients
CREATE TABLE IF NOT EXISTS http_client_auth ( CREATE TABLE IF NOT EXISTS http_client_auth (
@@ -253,6 +255,7 @@ CREATE TABLE IF NOT EXISTS http_client_auth (
); );
-- Schema version, and misc tomahawk settings relating to the collection db -- Schema version, and misc tomahawk settings relating to the collection db
CREATE TABLE IF NOT EXISTS settings ( CREATE TABLE IF NOT EXISTS settings (
@@ -260,4 +263,4 @@ CREATE TABLE IF NOT EXISTS settings (
v TEXT NOT NULL DEFAULT '' v TEXT NOT NULL DEFAULT ''
); );
INSERT INTO settings(k,v) VALUES('schema_version', '21'); INSERT INTO settings(k,v) VALUES('schema_version', '22');

View File

@@ -1,5 +1,5 @@
/* /*
This file was automatically generated from schema.sql on Thu Feb 24 19:05:46 EST 2011. This file was automatically generated from ./schema.sql on Wed Mar 2 01:40:39 CET 2011.
*/ */
static const char * tomahawk_schema_sql = static const char * tomahawk_schema_sql =
@@ -146,7 +146,7 @@ static const char * tomahawk_schema_sql =
");" ");"
"CREATE INDEX artist_tags_tag ON artist_tags(tag);" "CREATE INDEX artist_tags_tag ON artist_tags(tag);"
"CREATE TABLE IF NOT EXISTS track_attributes (" "CREATE TABLE IF NOT EXISTS track_attributes ("
" id INTEGER NOT NULL, " " id INTEGER REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, "
" k TEXT NOT NULL," " k TEXT NOT NULL,"
" v TEXT NOT NULL" " v TEXT NOT NULL"
");" ");"
@@ -173,7 +173,7 @@ static const char * tomahawk_schema_sql =
" k TEXT NOT NULL PRIMARY KEY," " k TEXT NOT NULL PRIMARY KEY,"
" v TEXT NOT NULL DEFAULT ''" " v TEXT NOT NULL DEFAULT ''"
");" ");"
"INSERT INTO settings(k,v) VALUES('schema_version', '21');" "INSERT INTO settings(k,v) VALUES('schema_version', '22');"
; ;
const char * get_tomahawk_sql() const char * get_tomahawk_sql()

View File

@@ -91,7 +91,7 @@ ControlConnection::setup()
void void
ControlConnection::registerSource() ControlConnection::registerSource()
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO << m_source->id();
Source* source = (Source*) sender(); Source* source = (Source*) sender();
Q_ASSERT( source == m_source.data() ); Q_ASSERT( source == m_source.data() );
// .. but we'll use the shared pointer we've already made: // .. but we'll use the shared pointer we've already made:
@@ -105,10 +105,11 @@ ControlConnection::registerSource()
void void
ControlConnection::setupDbSyncConnection( bool ondemand ) ControlConnection::setupDbSyncConnection( bool ondemand )
{ {
qDebug() << Q_FUNC_INFO << ondemand << m_source->id() << ondemand << m_dbconnkey << m_dbsyncconn << m_registered;
if ( m_dbsyncconn || !m_registered ) if ( m_dbsyncconn || !m_registered )
return; return;
qDebug() << Q_FUNC_INFO << ondemand << m_source->id();
Q_ASSERT( m_source->id() > 0 ); Q_ASSERT( m_source->id() > 0 );
if( !m_dbconnkey.isEmpty() ) if( !m_dbconnkey.isEmpty() )

View File

@@ -18,7 +18,7 @@ void RemoteCollection::addTracks( const QList<QVariant> &newitems )
} }
void RemoteCollection::removeTracks( const QList<QVariant> &olditems ) void RemoteCollection::removeTracks( const QDir& dir )
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
Q_ASSERT( false ); Q_ASSERT( false );

View File

@@ -21,7 +21,7 @@ public:
public slots: public slots:
virtual void addTracks( const QList<QVariant>& newitems ); virtual void addTracks( const QList<QVariant>& newitems );
virtual void removeTracks( const QList<QVariant> &olditems ); virtual void removeTracks( const QDir& dir );
}; };
#endif // REMOTECOLLECTION_H #endif // REMOTECOLLECTION_H

View File

@@ -152,7 +152,6 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
} }
state = m_qidsState.value( qid ) - 1; state = m_qidsState.value( qid ) - 1;
if ( state ) if ( state )
{ {
qDebug() << Q_FUNC_INFO << "replacing" << qid << state; qDebug() << Q_FUNC_INFO << "replacing" << qid << state;

View File

@@ -28,7 +28,7 @@ PlaylistEntry::setQueryVariant( const QVariant& v )
QString artist = m.value( "artist" ).toString(); QString artist = m.value( "artist" ).toString();
QString album = m.value( "album" ).toString(); QString album = m.value( "album" ).toString();
QString track = m.value( "track" ).toString(); QString track = m.value( "track" ).toString();
m_query = Tomahawk::Query::get( artist, track, album, false ); m_query = Tomahawk::Query::get( artist, track, album );
} }

View File

@@ -60,6 +60,8 @@ CollectionFlatModel::addCollection( const collection_ptr& collection )
SLOT( onTracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ) ); SLOT( onTracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ) );
connect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ), connect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) ); SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
connect( collection.data(), SIGNAL( tracksRemoved( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ),
SLOT( onTracksRemoved( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ) );
if ( collection->source()->isLocal() ) if ( collection->source()->isLocal() )
setTitle( tr( "Your Collection" ) ); setTitle( tr( "Your Collection" ) );
@@ -93,6 +95,8 @@ CollectionFlatModel::addFilteredCollection( const collection_ptr& collection, un
void void
CollectionFlatModel::removeCollection( const collection_ptr& collection ) CollectionFlatModel::removeCollection( const collection_ptr& collection )
{ {
return; // FIXME
disconnect( collection.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ), disconnect( collection.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ),
this, SLOT( onTracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ) ); this, SLOT( onTracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ) );
disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ), disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
@@ -163,6 +167,8 @@ CollectionFlatModel::removeCollection( const collection_ptr& collection )
void void
CollectionFlatModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection ) CollectionFlatModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection )
{ {
qDebug() << Q_FUNC_INFO;
if ( !tracks.count() ) if ( !tracks.count() )
{ {
emit trackCountChanged( rowCount( QModelIndex() ) ); emit trackCountChanged( rowCount( QModelIndex() ) );
@@ -202,6 +208,39 @@ CollectionFlatModel::onTracksAddingFinished( const Tomahawk::collection_ptr& col
} }
void
CollectionFlatModel::onTracksRemoved( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection )
{
QList<Tomahawk::query_ptr> t = tracks;
for ( int i = rowCount( QModelIndex() ); i >= 0 && t.count(); i-- )
{
PlItem* item = itemFromIndex( index( i, 0, QModelIndex() ) );
if ( !item )
continue;
int j = 0;
foreach ( const query_ptr& query, t )
{
if ( item->query().data() == query.data() )
{
qDebug() << "Removing row:" << i << query->toString();
emit beginRemoveRows( QModelIndex(), i, i );
delete item;
emit endRemoveRows();
t.removeAt( j );
break;
}
j++;
}
}
emit trackCountChanged( rowCount( QModelIndex() ) );
qDebug() << Q_FUNC_INFO << rowCount( QModelIndex() );
}
void void
CollectionFlatModel::onDataChanged() CollectionFlatModel::onDataChanged()
{ {

View File

@@ -54,6 +54,8 @@ private slots:
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection ); void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection );
void onTracksAddingFinished( const Tomahawk::collection_ptr& collection ); void onTracksAddingFinished( const Tomahawk::collection_ptr& collection );
void onTracksRemoved( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection );
void onSourceOffline( const Tomahawk::source_ptr& src ); void onSourceOffline( const Tomahawk::source_ptr& src );
private: private:

View File

@@ -18,7 +18,7 @@
#include "dynamic/echonest/EchonestControl.h" #include "dynamic/echonest/EchonestControl.h"
#include "dynamic/echonest/EchonestSteerer.h" #include "dynamic/echonest/EchonestSteerer.h"
#include "query.h" #include "query.h"
#include "tomahawk/tomahawkapp.h" #include "utils/tomahawkutils.h"
using namespace Tomahawk; using namespace Tomahawk;
@@ -285,7 +285,7 @@ query_ptr
EchonestGenerator::queryFromSong(const Echonest::Song& song) EchonestGenerator::queryFromSong(const Echonest::Song& song)
{ {
// track[ "album" ] = song.release(); // TODO should we include it? can be quite specific // track[ "album" ] = song.release(); // TODO should we include it? can be quite specific
return Query::get( song.artistName(), song.title(), QString() ); return Query::get( song.artistName(), song.title(), QString(), uuid() );
} }
QWidget* QWidget*

View File

@@ -92,6 +92,7 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget
connect( PlaylistManager::instance(), SIGNAL( playClicked() ), this, SLOT( playPressed() ) ); connect( PlaylistManager::instance(), SIGNAL( playClicked() ), this, SLOT( playPressed() ) );
connect( PlaylistManager::instance(), SIGNAL( pauseClicked() ), this, SLOT( pausePressed() ) ); connect( PlaylistManager::instance(), SIGNAL( pauseClicked() ), this, SLOT( pausePressed() ) );
connect( AudioEngine::instance(), SIGNAL( playlistChanged( PlaylistInterface* ) ), this, SLOT( playlistStopped( PlaylistInterface* ) ) );
} }
DynamicWidget::~DynamicWidget() DynamicWidget::~DynamicWidget()
@@ -207,18 +208,22 @@ DynamicWidget::layoutFloatingWidgets()
} }
void void
DynamicWidget::hideEvent( QHideEvent* ev ) DynamicWidget::playlistStopped( PlaylistInterface* pl )
{ {
if( pl == static_cast< PlaylistInterface* >( m_view->proxyModel() ) ) // same playlist, so don't stop
return;
// user started playing something somewhere else, so give it a rest
if( m_runningOnDemand ) { if( m_runningOnDemand ) {
stopStation( false ); stopStation( false );
m_model->clear();
} }
QWidget::hideEvent( ev );
} }
void void
DynamicWidget::showEvent(QShowEvent* ) DynamicWidget::showEvent(QShowEvent* )
{ {
if( !m_playlist.isNull() ) { if( !m_playlist.isNull() && !m_runningOnDemand ) {
m_setup->fadeIn(); m_setup->fadeIn();
} }
} }

View File

@@ -67,7 +67,6 @@ public:
virtual QSize sizeHint() const; virtual QSize sizeHint() const;
virtual void resizeEvent( QResizeEvent* ); virtual void resizeEvent( QResizeEvent* );
virtual void hideEvent(QHideEvent* );
virtual void showEvent(QShowEvent* ); virtual void showEvent(QShowEvent* );
static void paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qreal opacity = .95 ); static void paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qreal opacity = .95 );
@@ -90,6 +89,8 @@ public slots:
void pausePressed(); void pausePressed();
void stationFailed( const QString& ); void stationFailed( const QString& );
void playlistStopped( PlaylistInterface* );
private slots: private slots:
void generate( int = -1 ); void generate( int = -1 );
void tracksGenerated( const QList< Tomahawk::query_ptr>& queries ); void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );

View File

@@ -79,6 +79,10 @@ Source::friendlyName() const
if ( m_friendlyname.isEmpty() ) if ( m_friendlyname.isEmpty() )
return m_username; return m_username;
//TODO: this is a terrible assumption, help me clean this up, mighty muesli!
if ( m_friendlyname.contains( "@conference.") )
return QString(m_friendlyname).remove( 0, m_friendlyname.lastIndexOf( "/" )+1 ).append(" via MUC");
if ( m_friendlyname.contains( "/tomahawk" ) ) if ( m_friendlyname.contains( "/tomahawk" ) )
return m_friendlyname.left( m_friendlyname.indexOf( "/tomahawk" ) ); return m_friendlyname.left( m_friendlyname.indexOf( "/tomahawk" ) );

View File

@@ -116,6 +116,17 @@ appDataDir()
} }
QDir
appLogDir()
{
#ifndef Q_WS_MAC
return appDataDir();
#else
return QDir( QDir::homePath() + "/Library/Logs" );
#endif
}
QString QString
timeToString( int seconds ) timeToString( int seconds )
{ {

View File

@@ -27,6 +27,7 @@ namespace TomahawkUtils
class DLLEXPORT DNSResolver : public QObject class DLLEXPORT DNSResolver : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DNSResolver(); explicit DNSResolver();
~DNSResolver() {} ~DNSResolver() {}
@@ -63,6 +64,7 @@ namespace TomahawkUtils
DLLEXPORT QDir appConfigDir(); DLLEXPORT QDir appConfigDir();
DLLEXPORT QDir appDataDir(); DLLEXPORT QDir appDataDir();
DLLEXPORT QDir appLogDir();
DLLEXPORT QString timeToString( int seconds ); DLLEXPORT QString timeToString( int seconds );
DLLEXPORT QString ageToString( const QDateTime& time ); DLLEXPORT QString ageToString( const QDateTime& time );

View File

@@ -104,7 +104,7 @@ XSPFLoader::gotBody()
album = e.firstChildElement( "album" ).text(); album = e.firstChildElement( "album" ).text();
track = e.firstChildElement( "title" ).text(); track = e.firstChildElement( "title" ).text();
p->setQuery( Tomahawk::Query::get( artist, track, album ) ); p->setQuery( Tomahawk::Query::get( artist, track, album, uuid() ) );
p->query()->setDuration( e.firstChildElement( "duration" ).text().toInt() / 1000 ); p->query()->setDuration( e.firstChildElement( "duration" ).text().toInt() / 1000 );
m_entries << p; m_entries << p;
} }

View File

@@ -7,7 +7,8 @@ static pascal OSErr appleEventHandler( const AppleEvent*, AppleEvent*, long );
#endif #endif
#include <exception> #include <exception>
int main( int argc, char *argv[] ) int
main( int argc, char *argv[] )
{ {
#ifdef Q_WS_MAC #ifdef Q_WS_MAC
// Do Mac specific startup to get media keys working. // Do Mac specific startup to get media keys working.
@@ -19,16 +20,20 @@ int main( int argc, char *argv[] )
AEInstallEventHandler( 'GURL', 'GURL', h, 0, false ); AEInstallEventHandler( 'GURL', 'GURL', h, 0, false );
#endif #endif
try { try
{
TomahawkApp a( argc, argv ); TomahawkApp a( argc, argv );
return a.exec(); return a.exec();
} catch( const std::runtime_error& e ) { }
catch( const std::runtime_error& e )
{
return 0; return 0;
} }
} }
#ifdef Q_WS_MAC #ifdef Q_WS_MAC
static pascal OSErr appleEventHandler( const AppleEvent* e, AppleEvent*, long ) static pascal OSErr
appleEventHandler( const AppleEvent* e, AppleEvent*, long )
{ {
OSType id = typeWildCard; OSType id = typeWildCard;
AEGetAttributePtr( e, keyEventIDAttr, typeType, 0, &id, sizeof( id ), 0 ); AEGetAttributePtr( e, keyEventIDAttr, typeType, 0, &id, sizeof( id ), 0 );

View File

@@ -5,10 +5,19 @@
#include "database/database.h" #include "database/database.h"
#include "database/databasecommand_dirmtimes.h" #include "database/databasecommand_dirmtimes.h"
#include "database/databasecommand_addfiles.h" #include "database/databasecommand_addfiles.h"
#include "database/databasecommand_deletefiles.h"
using namespace Tomahawk; using namespace Tomahawk;
void
DirLister::go()
{
scanDir( m_dir, 0 );
emit finished( m_newdirmtimes );
}
void void
DirLister::scanDir( QDir dir, int depth ) DirLister::scanDir( QDir dir, int depth )
{ {
@@ -16,13 +25,15 @@ DirLister::scanDir( QDir dir, int depth )
const uint mtime = QFileInfo( dir.absolutePath() ).lastModified().toUTC().toTime_t(); const uint mtime = QFileInfo( dir.absolutePath() ).lastModified().toUTC().toTime_t();
m_newdirmtimes.insert( dir.absolutePath(), mtime ); m_newdirmtimes.insert( dir.absolutePath(), mtime );
if ( m_dirmtimes.contains( dir.absolutePath() ) && if ( m_dirmtimes.contains( dir.absolutePath() ) && mtime == m_dirmtimes.value( dir.absolutePath() ) )
mtime == m_dirmtimes.value( dir.absolutePath() ) )
{ {
// dont scan this dir, unchanged since last time. // dont scan this dir, unchanged since last time.
} }
else else
{ {
if ( m_dirmtimes.contains( dir.absolutePath() ) )
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( new DatabaseCommand_DeleteFiles( dir, SourceList::instance()->getLocal() ) ) );
dir.setFilter( QDir::Files | QDir::Readable | QDir::NoDotAndDotDot ); dir.setFilter( QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
dir.setSorting( QDir::Name ); dir.setSorting( QDir::Name );
dirs = dir.entryInfoList(); dirs = dir.entryInfoList();
@@ -138,6 +149,7 @@ void
MusicScanner::listerFinished( const QMap<QString, unsigned int>& newmtimes ) MusicScanner::listerFinished( const QMap<QString, unsigned int>& newmtimes )
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
// any remaining stuff that wasnt emitted as a batch: // any remaining stuff that wasnt emitted as a batch:
if( m_scannedfiles.length() ) if( m_scannedfiles.length() )
{ {
@@ -145,6 +157,16 @@ MusicScanner::listerFinished( const QMap<QString, unsigned int>& newmtimes )
commitBatch( m_scannedfiles ); commitBatch( m_scannedfiles );
} }
// remove obsolete / stale files
foreach ( const QString& path, m_dirmtimes.keys() )
{
if ( !newmtimes.keys().contains( path ) )
{
qDebug() << "Removing stale dir:" << path;
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( new DatabaseCommand_DeleteFiles( path, SourceList::instance()->getLocal() ) ) );
}
}
// save mtimes, then quit thread // save mtimes, then quit thread
DatabaseCommand_DirMtimes* cmd = new DatabaseCommand_DirMtimes( newmtimes ); DatabaseCommand_DirMtimes* cmd = new DatabaseCommand_DirMtimes( newmtimes );
connect( cmd, SIGNAL( finished() ), SLOT( deleteLister() ) ); connect( cmd, SIGNAL( finished() ), SLOT( deleteLister() ) );
@@ -222,7 +244,9 @@ MusicScanner::scanFile( const QFileInfo& fi )
QVariant QVariant
MusicScanner::readFile( const QFileInfo& fi ) MusicScanner::readFile( const QFileInfo& fi )
{ {
if ( ! m_ext2mime.contains( fi.suffix().toLower() ) ) const QString suffix = fi.suffix().toLower();
if ( ! m_ext2mime.contains( suffix ) )
{ {
m_skipped++; m_skipped++;
return QVariantMap(); // invalid extension return QVariantMap(); // invalid extension
@@ -272,14 +296,13 @@ MusicScanner::readFile( const QFileInfo& fi )
return QVariantMap(); return QVariantMap();
} }
QString mimetype = m_ext2mime.value( fi.suffix().toLower() ); QString mimetype = m_ext2mime.value( suffix );
QString url( "file://%1" ); QString url( "file://%1" );
QVariantMap m; QVariantMap m;
m["url"] = url.arg( fi.absoluteFilePath() ); m["url"] = url.arg( fi.absoluteFilePath() );
m["mtime"] = fi.lastModified().toUTC().toTime_t(); m["mtime"] = fi.lastModified().toUTC().toTime_t();
m["size"] = (unsigned int)fi.size(); m["size"] = (unsigned int)fi.size();
m["hash"] = ""; // TODO
m["mimetype"] = mimetype; m["mimetype"] = mimetype;
m["duration"] = duration; m["duration"] = duration;
m["bitrate"] = bitrate; m["bitrate"] = bitrate;
@@ -288,6 +311,7 @@ MusicScanner::readFile( const QFileInfo& fi )
m["track"] = track; m["track"] = track;
m["albumpos"] = tag->track(); m["albumpos"] = tag->track();
m["year"] = tag->year(); m["year"] = tag->year();
m["hash"] = ""; // TODO
m_scanned++; m_scanned++;
return m; return m;

View File

@@ -36,12 +36,7 @@ signals:
void finished( const QMap<QString, unsigned int>& ); void finished( const QMap<QString, unsigned int>& );
private slots: private slots:
void go() void go();
{
scanDir( m_dir, 0 );
emit finished( m_newdirmtimes );
}
void scanDir( QDir dir, int depth ); void scanDir( QDir dir, int depth );
private: private:

View File

@@ -23,7 +23,7 @@
<item> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="tabJabber"> <widget class="QWidget" name="tabJabber">
<attribute name="title"> <attribute name="title">
@@ -382,10 +382,10 @@
<enum>Qt::RightToLeft</enum> <enum>Qt::RightToLeft</enum>
</property> </property>
<property name="text"> <property name="text">
<string>Playdar HTTP API - NO AUTH</string> <string>Playdar HTTP API</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>false</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>

View File

@@ -27,6 +27,7 @@ SipHandler::~SipHandler()
disconnectPlugins(); disconnectPlugins();
} }
QList< SipPlugin* > QList< SipPlugin* >
SipHandler::plugins() const SipHandler::plugins() const
{ {
@@ -189,7 +190,13 @@ SipHandler::onPeerOnline( const QString& jid )
ControlConnection* conn = new ControlConnection( Servent::instance() ); ControlConnection* conn = new ControlConnection( Servent::instance() );
const QString& nodeid = Database::instance()->dbid(); const QString& nodeid = Database::instance()->dbid();
//TODO: this is a terrible assumption, help me clean this up, mighty muesli!
if ( jid.contains( "@conference.") )
conn->setName( jid );
else
conn->setName( jid.left( jid.indexOf( "/" ) ) ); conn->setName( jid.left( jid.indexOf( "/" ) ) );
conn->setId( nodeid ); conn->setId( nodeid );
Servent::instance()->registerOffer( key, conn ); Servent::instance()->registerOffer( key, conn );

View File

@@ -150,8 +150,9 @@ Jabber_p::addContact( const QString& jid, const QString& msg )
return; return;
} }
//FIXME: implement it when I dont suck that much :-) // Add contact to the Tomahawk group on the roster
//handleSubscription(Subscription()); m_roster->add( jid, jid, QStringList() << "Tomahawk" );
return; return;
} }
@@ -175,45 +176,77 @@ Jabber_p::onConnect()
m_client->setPresence(jreen::Presence::Available, "Tomahawk-JREEN available", 1); m_client->setPresence(jreen::Presence::Available, "Tomahawk-JREEN available", 1);
m_client->disco()->setSoftwareVersion( "Tomahawk JREEN", "0.0.0.0", "Foobar" ); m_client->disco()->setSoftwareVersion( "Tomahawk JREEN", "0.0.0.0", "Foobar" );
m_client->setPingInterval(60000); m_client->setPingInterval(60000);
jreen::AbstractRoster *roster = new jreen::AbstractRoster( m_client ); m_roster = new jreen::SimpleRoster( m_client );
roster->load(); m_roster->load();
// join MUC with bare jid as nickname
//TODO: make the room a list of rooms and make that configurable
QString bare(m_jid.bare());
m_room = new jreen::MUCRoom(m_client, jreen::JID(QString("tomahawk@conference.qutim.org/").append(bare.replace("@", "-"))));
m_room->setHistorySeconds(0);
m_room->join();
// treat muc participiants like contacts
connect(m_room, SIGNAL(messageReceived(jreen::Message, bool)), this, SLOT(onNewMessage(jreen::Message)));
connect(m_room, SIGNAL(presenceReceived(jreen::Presence,const jreen::MUCRoom::Participant*)), this, SLOT(onNewPresence(jreen::Presence)));
} }
void void
Jabber_p::onDisconnect( jreen::Client::DisconnectReason reason ) Jabber_p::onDisconnect( jreen::Client::DisconnectReason reason )
{ {
qDebug() << Q_FUNC_INFO << reason;
QString error; QString error;
bool reconnect = false;
int reconnectInSeconds = 0;
switch( reason ) switch( reason )
{ {
case jreen::Client::User: case jreen::Client::User:
error = "User Interaction";
break; break;
case jreen::Client::HostUnknown: case jreen::Client::HostUnknown:
error = "Host is unknown";
break; break;
case jreen::Client::ItemNotFound: case jreen::Client::ItemNotFound:
error = "Item not found";
break; break;
case jreen::Client::AuthorizationError: case jreen::Client::AuthorizationError:
error = "Authorization Error";
break; break;
case jreen::Client::RemoteStreamError: case jreen::Client::RemoteStreamError:
error = "Remote Stream Error";
reconnect = true;
break; break;
case jreen::Client::RemoteConnectionFailed: case jreen::Client::RemoteConnectionFailed:
error = "Remote Connection failed";
break; break;
case jreen::Client::InternalServerError: case jreen::Client::InternalServerError:
error = "Internal Server Error";
reconnect = true;
break; break;
case jreen::Client::SystemShutdown: case jreen::Client::SystemShutdown:
error = "System shutdown";
reconnect = true;
reconnectInSeconds = 60;
break; break;
case jreen::Client::Conflict: case jreen::Client::Conflict:
error = "Conflict";
break; break;
case jreen::Client::Unknown: case jreen::Client::Unknown:
error = "Unknown";
break;
default: default:
qDebug() << "Not all Client::DisconnectReasons checked";
Q_ASSERT(false);
break; break;
} }
qDebug() << "Connection error msg:" << error; qDebug() << "Disconnected from server:" << error;
if(reconnect)
QTimer::singleShot(reconnectInSeconds*1000, m_client, SLOT(connectToServer()));
emit disconnected(); emit disconnected();
} }

View File

@@ -31,6 +31,7 @@
#include "../sipdllmacro.h" #include "../sipdllmacro.h"
#include <jreen/connection.h> #include <jreen/connection.h>
#include <jreen/mucroom.h>
class SIPDLLEXPORT Jabber_p : class SIPDLLEXPORT Jabber_p :
public QObject public QObject
@@ -72,6 +73,8 @@ private slots:
private: private:
bool presenceMeansOnline( jreen::Presence::Type p ); bool presenceMeansOnline( jreen::Presence::Type p );
jreen::Client *m_client; jreen::Client *m_client;
jreen::MUCRoom *m_room;
jreen::SimpleRoster *m_roster;
jreen::JID m_jid; jreen::JID m_jid;
QMap<jreen::Presence::Type, QString> m_presences; QMap<jreen::Presence::Type, QString> m_presences;
QMap<QString, jreen::Presence::Type> m_peers; QMap<QString, jreen::Presence::Type> m_peers;

View File

@@ -61,10 +61,16 @@ public:
TomahawkZeroconf( int port, QObject* parent = 0 ) TomahawkZeroconf( int port, QObject* parent = 0 )
: QObject( parent ), m_sock( this ), m_port( port ) : QObject( parent ), m_sock( this ), m_port( port )
{ {
qDebug() << Q_FUNC_INFO;
m_sock.bind( ZCONF_PORT, QUdpSocket::ShareAddress ); m_sock.bind( ZCONF_PORT, QUdpSocket::ShareAddress );
connect( &m_sock, SIGNAL( readyRead() ), this, SLOT( readPacket() ) ); connect( &m_sock, SIGNAL( readyRead() ), this, SLOT( readPacket() ) );
} }
virtual ~TomahawkZeroconf()
{
qDebug() << Q_FUNC_INFO;
}
public slots: public slots:
void advertise() void advertise()
{ {
@@ -107,8 +113,8 @@ private slots:
{ {
qDebug() << "ADVERT received:" << sender << port; qDebug() << "ADVERT received:" << sender << port;
Node *n = new Node( sender.toString(), parts.at( 2 ), port ); Node *n = new Node( sender.toString(), parts.at( 2 ), port );
connect( n, SIGNAL( tomahawkHostFound( const QString&, int, const QString&, const QString& ) ), connect( n, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ),
this, SIGNAL( tomahawkHostFound( const QString&, int, const QString&, const QString& ) ) ); this, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ) );
n->resolve(); n->resolve();
} }
} }

View File

@@ -25,11 +25,10 @@ ZeroconfPlugin::connectPlugin( bool /*startup*/ )
{ {
delete m_zeroconf; delete m_zeroconf;
m_zeroconf = new TomahawkZeroconf( Servent::instance()->port(), this ); m_zeroconf = new TomahawkZeroconf( Servent::instance()->port(), this );
QObject::connect( m_zeroconf, SIGNAL( tomahawkHostFound( const QString&, int, const QString&, const QString& ) ), QObject::connect( m_zeroconf, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ),
SLOT( lanHostFound( const QString&, int, const QString&, const QString& ) ) ); SLOT( lanHostFound( QString, int, QString, QString ) ) );
m_zeroconf->advertise(); m_zeroconf->advertise();
m_isOnline = true; m_isOnline = true;
foreach( QStringList *currNode, m_cachedNodes ) foreach( QStringList *currNode, m_cachedNodes )
@@ -37,9 +36,9 @@ ZeroconfPlugin::connectPlugin( bool /*startup*/ )
QStringList nodeSet = *currNode; QStringList nodeSet = *currNode;
if ( !Servent::instance()->connectedToSession( nodeSet[3] ) ) if ( !Servent::instance()->connectedToSession( nodeSet[3] ) )
Servent::instance()->connectToPeer( nodeSet[0], nodeSet[1].toInt(), "whitelist", nodeSet[2], nodeSet[3] ); Servent::instance()->connectToPeer( nodeSet[0], nodeSet[1].toInt(), "whitelist", nodeSet[2], nodeSet[3] );
delete currNode; delete currNode;
} }
m_cachedNodes.empty();
return true; return true;
} }
@@ -48,6 +47,7 @@ void
ZeroconfPlugin::disconnectPlugin() ZeroconfPlugin::disconnectPlugin()
{ {
m_isOnline = false; m_isOnline = false;
delete m_zeroconf; delete m_zeroconf;
m_zeroconf = 0; m_zeroconf = 0;
} }
@@ -55,12 +55,14 @@ ZeroconfPlugin::disconnectPlugin()
void void
ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid ) ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid )
{ {
if ( sender() != m_zeroconf )
return;
qDebug() << "Found LAN host:" << host << port << nodeid; qDebug() << "Found LAN host:" << host << port << nodeid;
//FIXME: This doesn't work...why? I never see Found LAN host in debug either, but somehow nodes are being connected...
if ( !m_isOnline ) if ( !m_isOnline )
{ {
qDebug() << "Not online, so not connecting"; qDebug() << "Not online, so not connecting.";
QStringList *nodeSet = new QStringList(); QStringList *nodeSet = new QStringList();
*nodeSet << host << QString::number( port ) << name << nodeid; *nodeSet << host << QString::number( port ) << name << nodeid;
m_cachedNodes.insert( nodeSet ); m_cachedNodes.insert( nodeSet );
@@ -69,6 +71,8 @@ ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name
if ( !Servent::instance()->connectedToSession( nodeid ) ) if ( !Servent::instance()->connectedToSession( nodeid ) )
Servent::instance()->connectToPeer( host, port, "whitelist", name, nodeid ); Servent::instance()->connectToPeer( host, port, "whitelist", name, nodeid );
else
qDebug() << "Already connected to" << host;
} }
Q_EXPORT_PLUGIN2( sip, ZeroconfPlugin ) Q_EXPORT_PLUGIN2( sip, ZeroconfPlugin )

View File

@@ -18,9 +18,14 @@ public:
: m_zeroconf( 0 ) : m_zeroconf( 0 )
, m_isOnline( false ) , m_isOnline( false )
, m_cachedNodes() , m_cachedNodes()
{} {
qDebug() << Q_FUNC_INFO;
}
virtual ~ZeroconfPlugin() {} virtual ~ZeroconfPlugin()
{
qDebug() << Q_FUNC_INFO;
}
virtual bool isValid() { return true; } virtual bool isValid() { return true; }
virtual const QString name(); virtual const QString name();

View File

@@ -51,7 +51,7 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#define LOGFILE TomahawkUtils::appDataDir().filePath( "tomahawk.log" ).toLocal8Bit() #define LOGFILE TomahawkUtils::appLogDir().filePath( "Tomahawk.log" ).toLocal8Bit()
#define LOGFILE_SIZE 1024 * 512 #define LOGFILE_SIZE 1024 * 512
using namespace std; using namespace std;
@@ -146,10 +146,10 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
#endif #endif
qDebug() << "TomahawkApp thread:" << this->thread(); qDebug() << "TomahawkApp thread:" << this->thread();
setOrganizationName( "Tomahawk" ); setOrganizationName( QLatin1String( ORGANIZATION_NAME ) );
setOrganizationDomain( "tomahawk.org" ); setOrganizationDomain( QLatin1String( ORGANIZATION_DOMAIN ) );
setApplicationName( "Player" ); setApplicationName( QLatin1String( APPLICATION_NAME ) );
setApplicationVersion( "0.0.0" ); setApplicationVersion( QLatin1String( VERSION ) );
registerMetaTypes(); registerMetaTypes();
setupLogfile(); setupLogfile();

View File

@@ -165,7 +165,7 @@ Api_v1::stat( QxtWebRequestEvent* event )
if( event->url.hasQueryItem( "auth" ) ) if( event->url.hasQueryItem( "auth" ) )
{ {
// check for auth status // check for auth status
DatabaseCommand_ClientAuthValid* dbcmd = new DatabaseCommand_ClientAuthValid( event->url.queryItemValue( "auth" ), this ); DatabaseCommand_ClientAuthValid* dbcmd = new DatabaseCommand_ClientAuthValid( event->url.queryItemValue( "auth" ) );
connect( dbcmd, SIGNAL( authValid( QString, QString, bool ) ), this, SLOT( statResult( QString, QString, bool ) ) ); connect( dbcmd, SIGNAL( authValid( QString, QString, bool ) ), this, SLOT( statResult( QString, QString, bool ) ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(dbcmd) ); Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(dbcmd) );
} }
@@ -215,11 +215,17 @@ Api_v1::resolve( QxtWebRequestEvent* event )
void void
Api_v1::staticdata( QxtWebRequestEvent* event ) Api_v1::staticdata( QxtWebRequestEvent* event, const QString& str )
{ {
if( event->url.path().contains( "playdar_auth_logo.gif" ) ) qDebug() << "STATIC request:" << event << str;
if( str.contains( "tomahawk_auth_logo.png" ) )
{ {
// TODO handle QFile f( RESPATH "www/tomahawk_banner_small.png" );
f.open( QIODevice::ReadOnly );
QByteArray data = f.readAll();
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, data );
e->contentType = "image/png";
postEvent( e );
} }
} }

View File

@@ -53,7 +53,7 @@ public slots:
void stat( QxtWebRequestEvent* event ); void stat( QxtWebRequestEvent* event );
void statResult( const QString& clientToken, const QString& name, bool valid ); void statResult( const QString& clientToken, const QString& name, bool valid );
void resolve( QxtWebRequestEvent* event ); void resolve( QxtWebRequestEvent* event );
void staticdata( QxtWebRequestEvent* event ); void staticdata( QxtWebRequestEvent* event,const QString& );
void get_results( QxtWebRequestEvent* event ); void get_results( QxtWebRequestEvent* event );
void sendJSON( const QVariantMap& m, QxtWebRequestEvent* event ); void sendJSON( const QVariantMap& m, QxtWebRequestEvent* event );