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() && m_deduper[ i ].second == query->artist() ) isDuplicate = true; } if ( isDuplicate ) { m_playlist->generator()->fetchNext(); return; } else { m_deduper.append( QPair< QString, QString >( query->track(), query->artist() ) ); } connect( query.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( trackResolveFinished( bool ) ) ); m_waitingFor << query.data(); appendQuery( query ); } }
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; }
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 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; }
QMap< int, float > FuzzyIndex::search( const Tomahawk::query_ptr& query ) { 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 ); } float minScore; const TCHAR** fields = 0; MultiFieldQueryParser parser( fields, m_analyzer ); BooleanQuery* qry = _CLNEW BooleanQuery(); if ( query->isFullTextQuery() ) { QString escapedQuery = QString::fromWCharArray( parser.escape( DatabaseImpl::sortname( query->fullTextQuery() ).toStdWString().c_str() ) ); Term* term = _CLNEW Term( _T( "track" ), escapedQuery.toStdWString().c_str() ); Query* fqry = _CLNEW FuzzyQuery( term ); qry->add( fqry, true, BooleanClause::SHOULD ); term = _CLNEW Term( _T( "artist" ), escapedQuery.toStdWString().c_str() ); fqry = _CLNEW FuzzyQuery( term ); qry->add( fqry, true, BooleanClause::SHOULD ); term = _CLNEW Term( _T( "fulltext" ), escapedQuery.toStdWString().c_str() ); fqry = _CLNEW FuzzyQuery( term ); qry->add( fqry, true, BooleanClause::SHOULD ); minScore = 0.00; } else { QString track = QString::fromWCharArray( parser.escape( DatabaseImpl::sortname( query->track() ).toStdWString().c_str() ) ); QString artist = QString::fromWCharArray( parser.escape( DatabaseImpl::sortname( query->artist() ).toStdWString().c_str() ) ); // QString album = QString::fromWCharArray( parser.escape( query->album().toStdWString().c_str() ) ); Term* term = _CLNEW Term( _T( "track" ), track.toStdWString().c_str() ); Query* fqry = _CLNEW FuzzyQuery( term ); qry->add( fqry, true, BooleanClause::MUST ); term = _CLNEW Term( _T( "artist" ), artist.toStdWString().c_str() ); fqry = _CLNEW FuzzyQuery( term ); qry->add( fqry, true, BooleanClause::MUST ); minScore = 0.00; } 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( "trackid" ) ) ).toInt(); if ( score > minScore ) { resultsmap.insert( id, score ); // tDebug() << "Index hit:" << id << score << QString::fromWCharArray( ((Query*)qry)->toString() ); } } delete hits; delete qry; } catch( CLuceneError& error ) { tDebug() << "Caught CLucene error:" << error.what(); Q_ASSERT( false ); } return resultsmap; }
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 ); } }