Пример #1
0
double
ConstraintTypes::TagMatch::satisfaction( const Meta::TrackList& tl ) const
{
    double satisfaction = 0.0;
    foreach( Meta::TrackPtr t, tl ) {
        if ( matches( t ) ) {
            satisfaction += 1.0;
        }
    }
    satisfaction /= ( double )tl.size();
    return satisfaction;
}
Пример #2
0
void
APG::ConstraintSolver::mutate_population( APG::ConstraintSolver::Population& population )
{
    if ( population.size() < 1 )
        return;
    
    const double mutantPercentage = 0.35; // TODO: tune this parameter
    
    QList<Meta::TrackList*> parents( population.keys() );
    int maxMutants = (int)( mutantPercentage * (double)(m_populationSize) );
    for ( int i = parents.size(); i < maxMutants; i++ ) {
        int idx = KRandom::random() % parents.size();
        Meta::TrackList* child = new Meta::TrackList( *(parents.at( idx )) );
        int op = KRandom::random() % 5;
        int s = child->size();
        switch (op) {
            case 0:
                child->removeAt( KRandom::random() % s );
            case 1:
                child->insert( KRandom::random() % ( s + 1 ), random_track_from_domain() );
            case 2:
                child->replace( KRandom::random() % s, random_track_from_domain() );
            case 3:
                child->swap( KRandom::random() % s, KRandom::random() % s );
            case 4:
                child = crossover( child, parents.at( KRandom::random() % parents.size() ) );
            default:
                (void)0; // effectively a no-op. the default is here so that the compiler doesn't complain about missing default in switch
        }
        population.insert( child, m_constraintTreeRoot->satisfaction( *child ) );
    }
    return;
}
Пример #3
0
Dynamic::TrackSet
Dynamic::AlbumPlayBias::matchingTracks( int position,
                                       const Meta::TrackList& playlist, int contextCount,
                                       Dynamic::TrackCollectionPtr universe ) const
{
    Q_UNUSED( contextCount );

    if( position < 1 || position >= playlist.count() )
        return Dynamic::TrackSet( universe, false );

    Meta::TrackPtr track = playlist[position-1];
    Meta::AlbumPtr album = track->album();

    if( !album )
        return Dynamic::TrackSet( universe, false );

    Meta::TrackList albumTracks = album->tracks();
    if( albumTracks.count() == 1 ||
        (track == albumTracks.last() && m_follow != DontCare) )
        return Dynamic::TrackSet( universe, false );

    // we assume that the album tracks are sorted by cd and track number which
    // is at least true for the SqlCollection
    TrackSet result( universe, false );
    if( m_follow == DirectlyFollow )
    {
        for( int i = 1; i < albumTracks.count(); i++ )
            if( albumTracks[i-1] == track )
                result.unite( albumTracks[i] );
    }
    else if( m_follow == Follow )
    {
        bool found = false;
        for( int i = 0; i < albumTracks.count(); i++ )
        {
            if( found )
                result.unite( albumTracks[i] );
            if( albumTracks[i] == track )
                found = true;
        }
    }
    else if( m_follow == DontCare )
    {
        for( int i = 0; i < albumTracks.count(); i++ )
        {
            if( albumTracks[i] != track )
                result.unite( albumTracks[i] );
        }
    }

    return result;
}
Пример #4
0
bool
Dynamic::LastFmBias::trackMatches( int position,
                                   const Meta::TrackList& playlist,
                                   int contextCount ) const
{
    Q_UNUSED( contextCount );

    if( position <= 0 || position >= playlist.count())
        return false;

    // determine the last track and artist
    Meta::TrackPtr lastTrack = playlist[position-1];
    Meta::ArtistPtr lastArtist = lastTrack->artist();
    QString lastTrackName = lastTrack->name();
    QString lastArtistName = lastArtist ? lastArtist->name() : QString();

    Meta::TrackPtr currentTrack = playlist[position-1];
    Meta::ArtistPtr currentArtist = currentTrack->artist();
    QString currentTrackName = currentTrack->name();
    QString currentArtistName = currentArtist ? currentArtist->name() : QString();

    {
        QMutexLocker locker( &m_mutex );

        if( m_match == SimilarArtist )
        {
            if( lastArtistName.isEmpty() )
                return true;
            if( currentArtistName.isEmpty() )
                return false;
            if( m_similarArtistMap.contains( lastArtistName ) )
                return m_similarArtistMap.value( lastArtistName ).contains( currentArtistName );
        }
        else if( m_match == SimilarTrack )
        {
            if( lastTrackName.isEmpty() )
                return true;
            if( currentTrackName.isEmpty() )
                return false;
            TitleArtistPair lastKey( lastTrackName, lastArtistName );
            TitleArtistPair currentKey( currentTrackName, currentArtistName );
            if( m_similarTrackMap.contains( lastKey ) )
                return m_similarTrackMap.value( lastKey ).contains( currentKey );
        }
    }

    warning() << "didn't have a cached suggestions for track:" << lastTrackName;
    return false;
}
Пример #5
0
double
ConstraintTypes::PlaylistLength::satisfaction( const Meta::TrackList& tl ) const
{
    quint32 l = static_cast<quint32>( tl.size() );
    if ( m_comparison == CompareNumEquals ) {
        if ( l > m_length )
            return ( l == m_length ) ? 1.0 : transformLength( l - m_length );
        else
            return ( l == m_length ) ? 1.0 : transformLength( m_length - l );
    } else if ( m_comparison == CompareNumGreaterThan ) {
        return ( l > m_length ) ? 1.0 : transformLength( m_length - l );
    } else if ( m_comparison == CompareNumLessThan ) {
        return ( l < m_length ) ? 1.0 : transformLength( l - m_length );
    } else {
        return 0.0;
    }
}
Пример #6
0
bool
Dynamic::WeeklyTopBias::trackMatches( int position,
                                   const Meta::TrackList& playlist,
                                   int contextCount ) const
{
    Q_UNUSED( contextCount );

    if( position < 0 || position >= playlist.count())
        return false;

    // - determine the current artist
    Meta::TrackPtr currentTrack = playlist[position-1];
    Meta::ArtistPtr currentArtist = currentTrack->artist();
    QString currentArtistName = currentArtist ? currentArtist->name() : QString();

    // - collect all the artists
    QStringList artists;
    bool weeksMissing = false;

    uint fromTime = m_range.from.toTime_t();
    uint toTime   = m_range.to.toTime_t();
    uint lastWeekTime = 0;
    foreach( uint weekTime, m_weeklyFromTimes )
    {
        if( weekTime > fromTime && weekTime < toTime && lastWeekTime )
        {
            if( m_weeklyArtistMap.contains( lastWeekTime ) )
            {
                artists.append( m_weeklyArtistMap.value( lastWeekTime ) );
                // debug() << "found already-saved data for week:" << lastWeekTime << m_weeklyArtistMap.value( lastWeekTime );
            }
            else
            {
                weeksMissing = true;
            }
        }

       lastWeekTime = weekTime;
    }

    if( weeksMissing )
        warning() << "didn't have a cached suggestions for weeks:" << m_range.from << "to" << m_range.to;

    return artists.contains( currentArtistName );
}
Пример #7
0
Dynamic::TrackSet
Dynamic::LastFmBias::matchingTracks( int position,
                                       const Meta::TrackList& playlist,
                                       int contextCount,
                                       Dynamic::TrackCollectionPtr universe ) const
{
    Q_UNUSED( contextCount );

    if( position <= 0 || position > playlist.count())
        return Dynamic::TrackSet( universe, true );

    // determine the last track and artist
    Meta::TrackPtr lastTrack = playlist[position-1];
    Meta::ArtistPtr lastArtist = lastTrack->artist();

    m_currentTrack = lastTrack->name();
    m_currentArtist = lastArtist ? lastArtist->name() : QString();

    {
        QMutexLocker locker( &m_mutex );

        if( m_match == SimilarArtist )
        {
            if( m_currentArtist.isEmpty() )
                return Dynamic::TrackSet( universe, true );
            if( m_tracksValid && m_tracksMap.contains( m_currentArtist ) )
                return m_tracksMap.value( m_currentArtist );
        }
        else if( m_match == SimilarTrack )
        {
            if( m_currentTrack.isEmpty() )
                return Dynamic::TrackSet( universe, true );
            QString key = m_currentTrack + '|' + m_currentArtist;
            if( m_tracksValid && m_tracksMap.contains( key ) )
                return m_tracksMap.value( key );
        }
    }

    m_tracks = Dynamic::TrackSet( universe, false );
    QTimer::singleShot(0,
                       const_cast<LastFmBias*>(this),
                       SLOT(newQuery())); // create the new query from my parent thread

    return Dynamic::TrackSet();
}
Пример #8
0
bool
Dynamic::QuizPlayBias::trackMatches( int position,
                                     const Meta::TrackList& playlist,
                                     int contextCount ) const
{
    Q_UNUSED( contextCount );

    if( position <= 0 || position >= playlist.count())
        return true;

    // -- determine the last character we need to quiz
    Meta::TrackPtr lastTrack = playlist[position-1];
    Meta::DataPtr lastData;
    if( m_follow == TitleToTitle )
        lastData = Meta::DataPtr::staticCast<Meta::Track>(lastTrack);
    else if( m_follow == ArtistToArtist )
        lastData = Meta::DataPtr::staticCast<Meta::Artist>(lastTrack->artist());
    else if( m_follow == AlbumToAlbum )
        lastData = Meta::DataPtr::staticCast<Meta::Album>(lastTrack->album());

    if( !lastData || lastData->name().isEmpty() )
        return true;

    // -- determine the first character
    Meta::TrackPtr track = playlist[position];
    Meta::DataPtr data;
    if( m_follow == TitleToTitle )
        data = Meta::DataPtr::staticCast<Meta::Track>(track);
    else if( m_follow == ArtistToArtist )
        data = Meta::DataPtr::staticCast<Meta::Artist>(track->artist());
    else if( m_follow == AlbumToAlbum )
        data = Meta::DataPtr::staticCast<Meta::Album>(track->album());

    if( !data || data->name().isEmpty() )
        return false;

    // -- now compare
    QString lastName = lastData->name();
    QString name = data->name();
    return lastChar( lastName ).toLower() == name[0].toLower();
}
Пример #9
0
Dynamic::TrackSet
Dynamic::QuizPlayBias::matchingTracks( int position,
                                       const Meta::TrackList& playlist, int contextCount,
                                       Dynamic::TrackCollectionPtr universe ) const
{
    Q_UNUSED( contextCount );

    if( position <= 0 || position > playlist.count())
        return Dynamic::TrackSet( universe, true );

    // determine the last character we need to quiz
    Meta::TrackPtr lastTrack = playlist[position-1];
    Meta::DataPtr lastData;
    if( m_follow == TitleToTitle )
        lastData = Meta::DataPtr::staticCast<Meta::Track>(lastTrack);
    else if( m_follow == ArtistToArtist )
        lastData = Meta::DataPtr::staticCast<Meta::Artist>(lastTrack->artist());
    else if( m_follow == AlbumToAlbum )
        lastData = Meta::DataPtr::staticCast<Meta::Album>(lastTrack->album());

    if( !lastData || lastData->name().isEmpty() )
    {
        // debug() << "QuizPlay: no data for"<<lastTrack->name();
        return Dynamic::TrackSet( universe, true );
    }

    m_currentCharacter = lastChar(lastData->name()).toLower();
    // debug() << "QuizPlay: data for"<<lastTrack->name()<<"is"<<m_currentCharacter;

    // -- look if we already buffered it
    if( m_tracksValid && m_characterTrackMap.contains( m_currentCharacter ) )
        return m_characterTrackMap.value( m_currentCharacter );

    // -- start a new query
    m_tracks = Dynamic::TrackSet( universe, false );
    QTimer::singleShot(0,
                       const_cast<QuizPlayBias*>(this),
                       SLOT(newQuery())); // create the new query from my parent thread

    return Dynamic::TrackSet();
}
Пример #10
0
OrganizeCollectionDialog::OrganizeCollectionDialog( const Meta::TrackList &tracks,
                                                    const QStringList &folders,
                                                    const QString &targetExtension,
                                                    QWidget *parent,
                                                    const char *name,
                                                    bool modal,
                                                    const QString &caption,
                                                    QFlags<KDialog::ButtonCode> buttonMask )
    : KDialog( parent )
    , ui( new Ui::OrganizeCollectionDialogBase )
    , m_detailed( true )
    , m_schemeModified( false )
    , m_conflict( false )
{
    Q_UNUSED( name )

    setCaption( caption );
    setModal( modal );
    setButtons( buttonMask );
    showButtonSeparator( true );
    m_targetFileExtension = targetExtension;

    if( tracks.size() > 0 )
        m_allTracks = tracks;

    KVBox *mainVBox = new KVBox( this );
    setMainWidget( mainVBox );
    QWidget *mainContainer = new QWidget( mainVBox );

    ui->setupUi( mainContainer );

    m_trackOrganizer = new TrackOrganizer( m_allTracks, this );

    ui->folderCombo->insertItems( 0, folders );
    if( ui->folderCombo->contains( AmarokConfig::organizeDirectory() ) )
        ui->folderCombo->setCurrentItem( AmarokConfig::organizeDirectory() );
    else
        ui->folderCombo->setCurrentIndex( 0 ); //TODO possible bug: assumes folder list is not empty.

    ui->overwriteCheck->setChecked( AmarokConfig::overwriteFiles() );

    ui->optionsWidget->setReplaceSpaces( AmarokConfig::replaceSpace() );
    ui->optionsWidget->setPostfixThe( AmarokConfig::ignoreThe() );
    ui->optionsWidget->setVfatCompatible( AmarokConfig::vfatCompatible() );
    ui->optionsWidget->setAsciiOnly( AmarokConfig::asciiOnly() );
    ui->optionsWidget->setRegexpText( AmarokConfig::replacementRegexp() );
    ui->optionsWidget->setReplaceText( AmarokConfig::replacementString() );

    ui->previewTableWidget->horizontalHeader()->setResizeMode( QHeaderView::ResizeToContents );
    ui->conflictLabel->setText("");
    QPalette p = ui->conflictLabel->palette();
    KColorScheme::adjustForeground( p, KColorScheme::NegativeText ); // TODO this isn't working, the color is still normal
    ui->conflictLabel->setPalette( p );
    ui->previewTableWidget->sortItems( 0, Qt::AscendingOrder );

    // only show the options when the Options button is checked
    connect( ui->optionsButton, SIGNAL(toggled(bool)), ui->organizeCollectionWidget, SLOT(setVisible(bool)) );
    connect( ui->optionsButton, SIGNAL(toggled(bool)), ui->optionsWidget, SLOT(setVisible(bool)) );
    ui->organizeCollectionWidget->hide();
    ui->optionsWidget->hide();

    connect( ui->folderCombo, SIGNAL(currentIndexChanged(QString)), SLOT(slotUpdatePreview()) );
    connect( ui->organizeCollectionWidget, SIGNAL(schemeChanged()), SLOT(slotUpdatePreview()) );
    connect( ui->optionsWidget, SIGNAL(optionsChanged()), SLOT(slotUpdatePreview()));
    // to show the conflict error
    connect( ui->overwriteCheck, SIGNAL(stateChanged(int)), SLOT(slotOverwriteModeChanged()) );

    connect( this, SIGNAL(finished(int)), ui->organizeCollectionWidget, SLOT(slotSaveFormatList()) );
    connect( this, SIGNAL(accepted()), ui->organizeCollectionWidget, SLOT(onAccept()) );
    connect( this, SIGNAL(accepted()), SLOT(slotDialogAccepted()) );
    connect( ui->folderCombo, SIGNAL(currentIndexChanged(QString)),
             SLOT(slotEnableOk(QString)) );

    slotEnableOk( ui->folderCombo->currentText() );
    restoreDialogSize( Amarok::config( "OrganizeCollectionDialog" ) );

    QTimer::singleShot( 0, this, SLOT(slotUpdatePreview()) );
}
Пример #11
0
Meta::TrackList
APG::ConstraintSolver::sample( Meta::TrackList domain, const int sampleSize ) const
{
    std::random_shuffle( domain.begin(), domain.end() );
    return domain.mid( 0, sampleSize );
}
Пример #12
0
void Albums::dataUpdated( const QString &name, const Plasma::DataEngine::Data &data )
{
    if( name != QLatin1String("albums") )
        return;

    Meta::AlbumList albums = data[ "albums" ].value<Meta::AlbumList>();
    Meta::TrackPtr track = data[ "currentTrack" ].value<Meta::TrackPtr>();
    QString headerText = data[ "headerText" ].toString();
    setHeaderText( headerText.isEmpty() ? i18n("Albums") : headerText );

    //Don't keep showing the albums for the artist of the last track that had album in the collection
    if( (m_currentTrack == track) && (m_albums == albums) )
        return;

    if( albums.isEmpty() )
    {
        debug() << "received albums is empty";
        setCollapseOn();
        m_albums.clear();
        m_albumsView->clear();
        return;
    }

    setCollapseOff();

    m_albums = albums;
    m_currentTrack = track;
    m_albumsView->clear();
    m_albumsView->setMode( track ? AlbumsProxyModel::SortByYear : AlbumsProxyModel::SortByCreateDate );
    QStandardItem *currentItem( 0 );

    foreach( Meta::AlbumPtr albumPtr, albums )
    {
        // do not show all tracks without an album from the collection, this takes ages
        // TODO: show all tracks from this artist that are not part of an album
        if( albumPtr->name().isEmpty() )
            continue;

        Meta::TrackList tracks = albumPtr->tracks();
        if( tracks.isEmpty() )
            continue;

        AlbumItem *albumItem = new AlbumItem();
        albumItem->setIconSize( 50 );
        albumItem->setAlbum( albumPtr );
        albumItem->setShowArtist( !m_currentTrack );

        int numberOfDiscs = 0;
        int childRow = 0;

        qStableSort( tracks.begin(), tracks.end(), Meta::Track::lessThan );

        QMultiHash< int, TrackItem* > trackItems; // hash of tracks items for each disc
        foreach( Meta::TrackPtr trackPtr, tracks )
        {
            if( numberOfDiscs < trackPtr->discNumber() )
                numberOfDiscs = trackPtr->discNumber();

            TrackItem *trackItem = new TrackItem();
            trackItem->setTrack( trackPtr );

            // bold the current track to make it more visible
            if( m_currentTrack && *m_currentTrack == *trackPtr )
            {
                currentItem = trackItem;
                trackItem->bold();
            }

            // If compilation and same artist, then highlight, but only if there's a current track
            if( m_currentTrack
                && m_currentTrack->artist() && trackPtr->artist()
                && (*m_currentTrack->artist() == *trackPtr->artist())
                && albumPtr->isCompilation() )
            {
                trackItem->italicise();
            }
            trackItems.insert( trackPtr->discNumber(), trackItem );
        }

        for( int i = 0; i <= numberOfDiscs; ++i )
        {
            QList<TrackItem*> items = trackItems.values( i );
            if( !items.isEmpty() )
            {
                const TrackItem *item = items.first();
                QStandardItem *discItem( 0 );
                if( numberOfDiscs > 1 )
                {
                    discItem = new QStandardItem( i18n("Disc %1", item->track()->discNumber()) );
                    albumItem->setChild( childRow++, discItem );
                    int discChildRow = 0;
                    foreach( TrackItem *trackItem, items )
                        discItem->setChild( discChildRow++, trackItem );
                }
                else
                {
                    foreach( TrackItem *trackItem, items )
                        albumItem->setChild( childRow++, trackItem );
                }
            }
        }
        m_albumsView->appendAlbum( albumItem );
    }

    m_albumsView->sort();
    if( currentItem )
    {
        m_albumsView->setRecursiveExpanded( currentItem, true );
        m_albumsView->scrollTo( currentItem );
    }

    updateConstraints();
}