void DynamicModel::newTrackGenerated( const Tomahawk::query_ptr& query ) { if ( m_onDemandRunning ) { bool isDuplicate = false; for ( int i = 0; i < m_deduper.size(); i++ ) { if ( m_deduper[ i ].first == query->track()->track() && m_deduper[ i ].second == query->track()->artist() ) isDuplicate = true; } if ( isDuplicate ) { m_playlist->generator()->fetchNext(); return; } else { m_deduper.append( QPair< QString, QString >( query->track()->track(), query->track()->artist() ) ); } connect( query.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( trackResolveFinished( bool ) ) ); m_waitingFor << query.data(); appendQuery( query ); } }
void DatabaseCommand_LogPlayback::postCommitHook() { connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr ) ), source().data(), SLOT( onPlaybackStarted( Tomahawk::query_ptr ) ), Qt::QueuedConnection ); connect( this, SIGNAL( trackPlayed( Tomahawk::query_ptr ) ), source().data(), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection ); Tomahawk::query_ptr q; if ( !m_result.isNull() ) { q = m_result->toQuery(); } else { // do not auto resolve this track q = Tomahawk::Query::get( m_artist, m_track, QString() ); } q->setPlayedBy( source(), m_playtime ); if ( m_action == Finished ) { emit trackPlayed( q ); } // if the play time is more than 10 minutes in the past, ignore else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < STARTED_THRESHOLD ) { emit trackPlaying( q ); } if ( source()->isLocal() ) { Servent::instance()->triggerDBSync(); } }
void M3uLoader::getTags( const QFileInfo& info ) { QByteArray fileName = QFile::encodeName( info.canonicalFilePath() ); const char *encodedName = fileName.constData(); TagLib::FileRef f( encodedName ); TagLib::Tag *tag = f.tag(); QString artist = TStringToQString( tag->artist() ).trimmed(); QString album = TStringToQString( tag->album() ).trimmed(); QString track = TStringToQString( tag->title() ).trimmed(); if ( artist.isEmpty() || track.isEmpty() ) { qDebug() << "Error parsing" << info.fileName(); return; } else { qDebug() << Q_FUNC_INFO << artist << track << album; Tomahawk::query_ptr q = Tomahawk::Query::get( artist, track, album, uuid(), !m_createNewPlaylist ); if ( !q.isNull() ) m_tracks << q; } }
void AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::query_ptr& query ) { if ( query->resolvingFinished() ) { if ( query->numResults() && query->results().first()->isOnline() ) { playItem( playlist, query->results().first() ); return; } JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Sorry, Tomahawk couldn't find the track '%1' by %2" ).arg( query->track() ).arg( query->artist() ), 15 ) ); if ( isStopped() ) emit stopped(); // we do this so the original caller knows we couldn't find this track } else { Pipeline::instance()->resolve( query ); NewClosure( query.data(), SIGNAL( resolvingFinished( bool ) ), const_cast<AudioEngine*>(this), SLOT( playItem( Tomahawk::playlistinterface_ptr, Tomahawk::query_ptr ) ), playlist, query ); } }
void TrackModelItem::setupItem( const Tomahawk::query_ptr& query, TrackModelItem* parent, int row ) { this->parent = parent; if ( parent ) { if ( row < 0 ) { parent->children.append( this ); row = parent->children.count() - 1; } else { parent->children.insert( row, this ); } this->model = parent->model; } m_isPlaying = false; toberemoved = false; m_query = query; if ( !query->numResults() ) { connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ), SIGNAL( dataChanged() ) ); connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ), SIGNAL( dataChanged() ) ); connect( query.data(), SIGNAL( resultsChanged() ), SIGNAL( dataChanged() ) ); } }
TreeModelItem::TreeModelItem( const Tomahawk::query_ptr& query, TreeModelItem* parent, int row ) : QObject( parent ) , m_query( query ) { this->parent = parent; fetchingMore = false; m_isPlaying = false; if ( parent ) { if ( row < 0 ) { parent->children.append( this ); row = parent->children.count() - 1; } else { parent->children.insert( row, this ); } this->model = parent->model; } toberemoved = false; onResultsChanged(); connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ), SLOT( onResultsChanged() ) ); connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ), SLOT( onResultsChanged() ) ); connect( query.data(), SIGNAL( resultsChanged() ), SLOT( onResultsChanged() ) ); }
void DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi ) { TomahawkSqlQuery query = dbi->newquery(); QList<Tomahawk::query_ptr> ql; QString whereToken; if ( !source().isNull() ) { whereToken = QString( "WHERE source %1" ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ); } QString sql = QString( "SELECT track, playtime, secs_played, source " "FROM playback_log " "%1 " "ORDER BY playtime DESC " "%2" ).arg( whereToken ) .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() ); query.prepare( sql ); query.exec(); while( query.next() ) { TomahawkSqlQuery query_track = dbi->newquery(); QString sql = QString( "SELECT track.name, artist.name " "FROM track, artist " "WHERE artist.id = track.artist " "AND track.id = %1" ).arg( query.value( 0 ).toUInt() ); query_track.prepare( sql ); query_track.exec(); if ( query_track.next() ) { Tomahawk::query_ptr q = Tomahawk::Query::get( query_track.value( 1 ).toString(), query_track.value( 0 ).toString(), QString() ); if ( query.value( 3 ).toUInt() == 0 ) { q->setPlayedBy( SourceList::instance()->getLocal(), query.value( 1 ).toUInt() ); } else { q->setPlayedBy( SourceList::instance()->get( query.value( 3 ).toUInt() ), query.value( 1 ).toUInt() ); } ql << q; } } if ( ql.count() ) emit tracks( ql ); }
void DynamicModel::newTrackGenerated( const Tomahawk::query_ptr& query ) { if( m_onDemandRunning ) { connect( query.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( trackResolveFinished( bool ) ) ); m_waitingFor << query.data(); append( query ); } }
void PlaylistModel::append( const Tomahawk::query_ptr& query ) { if ( query.isNull() ) return; if ( !query->resolvingFinished() ) Pipeline::instance()->resolve( query ); TrackModel::append( query ); }
void PipelineStatusItem::resolving( const Tomahawk::query_ptr& query ) { if ( query->isFullTextQuery() ) m_latestQuery = query->fullTextQuery(); else m_latestQuery = QString( "%1 - %2" ).arg( query->queryTrack()->artist() ).arg( query->queryTrack()->track() ); Q_ASSERT( !m_latestQuery.isEmpty() ); emit statusChanged(); }
QMap< int, float > FuzzyIndex::searchAlbum( const Tomahawk::query_ptr& query ) { Q_ASSERT( query->isFullTextQuery() ); QMutexLocker lock( &m_mutex ); QMap< int, float > resultsmap; try { if ( !m_luceneReader ) { if ( !IndexReader::indexExists( m_luceneDir ) ) { tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "index didn't exist."; return resultsmap; } m_luceneReader = IndexReader::open( m_luceneDir ); m_luceneSearcher = newLucene<IndexSearcher>( m_luceneReader ); } QueryParserPtr parser = newLucene<QueryParser>( LuceneVersion::LUCENE_CURRENT, L"album", m_analyzer ); QString q = Tomahawk::DatabaseImpl::sortname( query->fullTextQuery() ); FuzzyQueryPtr qry = newLucene<FuzzyQuery>( newLucene<Term>( L"album", q.toStdWString() ) ); TopScoreDocCollectorPtr collector = TopScoreDocCollector::create( 99999, false ); m_luceneSearcher->search( boost::dynamic_pointer_cast<Query>( qry ), collector ); Collection<ScoreDocPtr> hits = collector->topDocs()->scoreDocs; for ( int i = 0; i < collector->getTotalHits(); i++ ) { DocumentPtr d = m_luceneSearcher->doc( hits[i]->doc ); float score = hits[i]->score; int id = QString::fromStdWString( d->get( L"albumid" ) ).toInt(); if ( score > 0.30 ) { resultsmap.insert( id, score ); // tDebug() << "Index hit:" << id << score; } } } catch( LuceneException& error ) { tDebug() << "Caught Lucene error:" << error.what(); QTimer::singleShot( 0, this, SLOT( wipeIndex() ) ); } return resultsmap; }
PlayableItem::PlayableItem( const Tomahawk::query_ptr& query, PlayableItem* parent, int row ) : QObject( parent ) , m_query( query ) { init( parent, row ); connect( query->track().data(), SIGNAL( socialActionsLoaded() ), SIGNAL( dataChanged() ) ); connect( query->track().data(), SIGNAL( updated() ), SIGNAL( dataChanged() ) ); connect( query.data(), SIGNAL( resultsChanged() ), SLOT( onResultsChanged() ) ); }
void SourceTreeView::dropEvent( QDropEvent* event ) { bool accept = false; const QPoint pos = event->pos(); const QModelIndex index = indexAt( pos ); if ( event->mimeData()->hasFormat( "application/tomahawk.query.list" ) ) { const QPoint pos = event->pos(); const QModelIndex index = indexAt( pos ); if ( index.isValid() ) { if ( SourcesModel::indexType( index ) == SourcesModel::PlaylistSource ) { playlist_ptr playlist = SourcesModel::indexToPlaylist( index ); if ( !playlist.isNull() && playlist->author()->isLocal() ) { accept = true; QByteArray itemData = event->mimeData()->data( "application/tomahawk.query.list" ); QDataStream stream( &itemData, QIODevice::ReadOnly ); QList<Tomahawk::query_ptr> queries; while ( !stream.atEnd() ) { qlonglong qptr; stream >> qptr; Tomahawk::query_ptr* query = reinterpret_cast<Tomahawk::query_ptr*>(qptr); if ( query && !query->isNull() ) { qDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track(); queries << *query; } } qDebug() << "on playlist:" << playlist->title() << playlist->guid(); SourceTreeItem* treeItem = SourcesModel::indexToTreeItem( index ); if ( treeItem ) { QString rev = treeItem->currentlyLoadedPlaylistRevision( playlist->guid() ); playlist->addEntries( queries, rev ); } } } }
void AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::result_ptr& result, const Tomahawk::query_ptr& fromQuery ) { tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() ); if ( !m_playlist.isNull() ) m_playlist.data()->reset(); setPlaylist( playlist ); if ( playlist.isNull() && !fromQuery.isNull() ) m_currentTrackPlaylist = playlistinterface_ptr( new SingleTrackPlaylistInterface( fromQuery ) ); else m_currentTrackPlaylist = playlist; if ( !result.isNull() ) { loadTrack( result ); } else if ( !m_playlist.isNull() && m_playlist.data()->retryMode() == PlaylistModes::Retry ) { m_waitingOnNewTrack = true; if ( isStopped() ) emit sendWaitingNotification(); else stop(); } }
void Source::onPlaybackStarted( const Tomahawk::query_ptr& query ) { qDebug() << Q_FUNC_INFO << query->toString(); m_currentTrack = query; emit playbackStarted( query ); }
void Source::onPlaybackFinished( const Tomahawk::query_ptr& query ) { qDebug() << Q_FUNC_INFO << query->toString(); emit playbackFinished( query ); m_currentTrackTimer.start(); }
void PlaylistEntry::setQuery( const Tomahawk::query_ptr& q ) { Q_D( PlaylistEntry ); d->query = q; connect( q.data(), SIGNAL( resolvingFinished( bool ) ), SLOT( onQueryResolved( bool ) ) ); }
void QueryLabel::setQuery( const Tomahawk::query_ptr& query ) { if ( query.isNull() ) return; setContentsMargins( BOXMARGIN * 2, BOXMARGIN / 2, BOXMARGIN * 2, BOXMARGIN / 2 ); if ( m_query.isNull() || m_query.data() != query.data() ) { m_query = query; m_result.clear(); updateLabel(); emit textChanged( text() ); emit queryChanged( m_query ); } }
void Source::onPlaybackFinished( const Tomahawk::query_ptr& query ) { tDebug() << Q_FUNC_INFO << query->toString(); emit playbackFinished( query ); m_currentTrack.clear(); emit stateChanged(); }
PipelineStatusItem::PipelineStatusItem( const Tomahawk::query_ptr& q ) : JobStatusItem() { connect( Tomahawk::Pipeline::instance(), SIGNAL( resolving( Tomahawk::query_ptr ) ), this, SLOT( resolving( Tomahawk::query_ptr ) ) ); connect( Tomahawk::Pipeline::instance(), SIGNAL( idle() ), this, SLOT( idle() ) ); if ( !q.isNull() ) resolving( q ); }
void TopTracksContext::setQuery( const Tomahawk::query_ptr& query ) { if ( !m_query.isNull() && query->artist() == m_query->artist() ) return; m_query = query; Tomahawk::InfoSystem::InfoStringHash artistInfo; artistInfo["artist"] = query->artist(); Tomahawk::InfoSystem::InfoRequestData requestData; requestData.caller = m_infoId; requestData.customData = QVariantMap(); requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( artistInfo ); requestData.type = Tomahawk::InfoSystem::InfoArtistSongs; Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); }
void Source::onPlaybackStarted( const Tomahawk::query_ptr& query, unsigned int duration ) { qDebug() << Q_FUNC_INFO << query->toString(); m_currentTrack = query; m_currentTrackTimer.start( duration * 1000 + 900000 ); // duration comes in seconds if ( m_playlistInterface.isNull() ) getPlaylistInterface(); emit playbackStarted( query ); }
void TrackModel::insert( const Tomahawk::query_ptr& query, int row ) { if ( query.isNull() ) return; QList< Tomahawk::query_ptr > ql; ql << query; insert( ql, row ); }
void SocialWidget::setQuery( const Tomahawk::query_ptr& query ) { m_query = query; ui->coverImage->setPixmap( TomahawkUtils::addDropShadow( query->cover( ui->coverImage->size() ), ui->coverImage->size() ) ); onShortLinkReady( QString(), QString(), QVariant() ); onChanged(); QUrl longUrl = GlobalActionManager::instance()->openLinkFromQuery( query ); GlobalActionManager::instance()->shortenLink( longUrl ); }
QMap< int, float > FuzzyIndex::searchAlbum( const Tomahawk::query_ptr& query ) { Q_ASSERT( query->isFullTextQuery() ); // QMutexLocker lock( &m_mutex ); QMap< int, float > resultsmap; if ( !m_luceneReader || !m_luceneSearcher ) return resultsmap; try { QueryParserPtr parser = newLucene<QueryParser>( LuceneVersion::LUCENE_CURRENT, L"album", m_analyzer ); const QString q = Tomahawk::DatabaseImpl::sortname( query->fullTextQuery() ); FuzzyQueryPtr qry = newLucene<FuzzyQuery>( newLucene<Term>( L"album", q.toStdWString() ) ); TopScoreDocCollectorPtr collector = TopScoreDocCollector::create( 99999, false ); m_luceneSearcher->search( boost::dynamic_pointer_cast<Query>( qry ), collector ); Collection<ScoreDocPtr> hits = collector->topDocs()->scoreDocs; for ( int i = 0; i < collector->getTotalHits(); i++ ) { DocumentPtr d = m_luceneSearcher->doc( hits[i]->doc ); float score = hits[i]->score; int id = QString::fromStdWString( d->get( L"albumid" ) ).toInt(); if ( score > 0.30 ) { resultsmap.insert( id, score ); // tDebug() << "Index hit:" << id << score; } } } catch( LuceneException& error ) { tDebug() << "Caught Lucene error:" << QString::fromWCharArray( error.getError().c_str() ); } return resultsmap; }
QMap< int, float > FuzzyIndex::searchAlbum( const Tomahawk::query_ptr& query ) { Q_ASSERT( query->isFullTextQuery() ); QMutexLocker lock( &m_mutex ); QMap< int, float > resultsmap; try { if ( !m_luceneReader ) { if ( !IndexReader::indexExists( TomahawkUtils::appDataDir().absoluteFilePath( "tomahawk.lucene" ).toStdString().c_str() ) ) { qDebug() << Q_FUNC_INFO << "index didn't exist."; return resultsmap; } m_luceneReader = IndexReader::open( m_luceneDir ); m_luceneSearcher = _CLNEW IndexSearcher( m_luceneReader ); } QueryParser parser( _T( "album" ), m_analyzer ); QString escapedName = QString::fromWCharArray( parser.escape( DatabaseImpl::sortname( query->fullTextQuery() ).toStdWString().c_str() ) ); Query* qry = _CLNEW FuzzyQuery( _CLNEW Term( _T( "album" ), escapedName.toStdWString().c_str() ) ); Hits* hits = m_luceneSearcher->search( qry ); for ( uint i = 0; i < hits->length(); i++ ) { Document* d = &hits->doc( i ); float score = hits->score( i ); int id = QString::fromWCharArray( d->get( _T( "albumid" ) ) ).toInt(); if ( score > 0.30 ) { resultsmap.insert( id, score ); // tDebug() << "Index hit:" << id << score; } } delete hits; delete qry; } catch( CLuceneError& error ) { tDebug() << "Caught CLucene error:" << error.what(); Q_ASSERT( false ); } return resultsmap; }
void ScriptEngine::resolve( const Tomahawk::query_ptr& query ) { qDebug() << Q_FUNC_INFO << query->toString(); QString eval = QString( "resolve( '%1', '%2', '%3', '%4' );" ) .arg( query->id().replace( "'", "\\'" ) ) .arg( query->artist().replace( "'", "\\'" ) ) .arg( query->album().replace( "'", "\\'" ) ) .arg( query->track().replace( "'", "\\'" ) ); QList< Tomahawk::result_ptr > results; QVariantMap m = mainFrame()->evaluateJavaScript( eval ).toMap(); qDebug() << "JavaScript Result:" << m; const QString qid = query->id(); const QVariantList reslist = m.value( "results" ).toList(); foreach( const QVariant& rv, reslist ) { QVariantMap m = rv.toMap(); qDebug() << "RES" << m; Tomahawk::result_ptr rp( new Tomahawk::Result() ); Tomahawk::artist_ptr ap = Tomahawk::Artist::get( 0, m.value( "artist" ).toString() ); rp->setArtist( ap ); rp->setAlbum( Tomahawk::Album::get( 0, m.value( "album" ).toString(), ap ) ); rp->setTrack( m.value( "track" ).toString() ); rp->setBitrate( m.value( "bitrate" ).toUInt() ); rp->setUrl( m.value( "url" ).toString() ); rp->setSize( m.value( "size" ).toUInt() ); rp->setScore( m.value( "score" ).toFloat() * ( (float)m_parent->weight() / 100.0 ) ); rp->setRID( uuid() ); rp->setFriendlySource( m_parent->name() ); if ( m.contains( "year" ) ) { QVariantMap attr; attr[ "releaseyear" ] = m.value( "year" ); rp->setAttributes( attr ); } rp->setDuration( m.value( "duration", 0 ).toUInt() ); if ( rp->duration() <= 0 && m.contains( "durationString" ) ) { QTime time = QTime::fromString( m.value( "durationString" ).toString(), "hh:mm:ss" ); rp->setDuration( time.secsTo( QTime( 0, 0 ) ) * -1 ); } rp->setMimetype( m.value( "mimetype" ).toString() ); if ( rp->mimetype().isEmpty() ) { rp->setMimetype( TomahawkUtils::extensionToMimetype( m.value( "extension" ).toString() ) ); Q_ASSERT( !rp->mimetype().isEmpty() ); } results << rp; }
Tomahawk::result_ptr PlaylistInterface::siblingResult( int itemsAway, qint64 rootIndex ) const { qint64 idx = siblingIndex( itemsAway, rootIndex ); QList< qint64 > safetyCheck; // If safetyCheck contains idx, this means the interface keeps returning the same items and we won't discover anything new - abort // This can happen in repeat / random mode e.g. while ( idx >= 0 && !safetyCheck.contains( idx ) ) { safetyCheck << idx; Tomahawk::query_ptr query = queryAt( idx ); if ( query && query->playable() ) { return query->results().first(); } idx = siblingIndex( itemsAway < 0 ? -1 : 1, idx ); } return Tomahawk::result_ptr(); }
void QtScriptResolver::resolve( const Tomahawk::query_ptr& query ) { if ( QThread::currentThread() != thread() ) { QMetaObject::invokeMethod( this, "resolve", Qt::QueuedConnection, Q_ARG(Tomahawk::query_ptr, query) ); return; } QString eval; if ( !query->isFullTextQuery() ) { eval = QString( RESOLVER_LEGACY_CODE2 "resolver.resolve( '%1', '%2', '%3', '%4' );" ) .arg( query->id().replace( "'", "\\'" ) ) .arg( query->artist().replace( "'", "\\'" ) ) .arg( query->album().replace( "'", "\\'" ) ) .arg( query->track().replace( "'", "\\'" ) ); } else { eval = QString( "if(Tomahawk.resolver.instance !== undefined) {" " resolver.search( '%1', '%2' );" "} else {" " resolve( '%1', '', '', '%2' );" "}" ) .arg( query->id().replace( "'", "\\'" ) ) .arg( query->fullTextQuery().replace( "'", "\\'" ) ); } QVariantMap m = m_engine->mainFrame()->evaluateJavaScript( eval ).toMap(); if( m.isEmpty() ) { // if the resolver doesn't return anything, async api is used return; } qDebug() << "JavaScript Result:" << m; const QString qid = query->id(); const QVariantList reslist = m.value( "results" ).toList(); QList< Tomahawk::result_ptr > results = parseResultVariantList( reslist ); Tomahawk::Pipeline::instance()->reportResults( qid, results ); }
// TODO make clever (ft. featuring live (stuff) etc) float DatabaseCommand_Resolve::how_similar( const Tomahawk::query_ptr& q, const Tomahawk::result_ptr& r ) { // query values const QString qArtistname = DatabaseImpl::sortname( q->artist() ); const QString qAlbumname = DatabaseImpl::sortname( q->album() ); const QString qTrackname = DatabaseImpl::sortname( q->track() ); // result values const QString rArtistname = DatabaseImpl::sortname( r->artist()->name() ); const QString rAlbumname = DatabaseImpl::sortname( r->album()->name() ); const QString rTrackname = DatabaseImpl::sortname( r->track() ); // normal edit distance int artdist = levenshtein( qArtistname, rArtistname ); int albdist = levenshtein( qAlbumname, rAlbumname ); int trkdist = levenshtein( qTrackname, rTrackname ); // max length of name int mlart = qMax( qArtistname.length(), rArtistname.length() ); int mlalb = qMax( qAlbumname.length(), rAlbumname.length() ); int mltrk = qMax( qTrackname.length(), rTrackname.length() ); // distance scores float dcart = (float)( mlart - artdist ) / mlart; float dcalb = (float)( mlalb - albdist ) / mlalb; float dctrk = (float)( mltrk - trkdist ) / mltrk; // don't penalize for missing album name if( qAlbumname.length() == 0 ) dcalb = 1.0; // weighted, so album match is worth less than track title float combined = ( dcart*4 + dcalb + dctrk*5 ) / 10; return combined; }