~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/libtomahawk/Album.cpp

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
 
2
 *
 
3
 *   Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
 
4
 *   Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
 
5
 *
 
6
 *   Tomahawk is free software: you can redistribute it and/or modify
 
7
 *   it under the terms of the GNU General Public License as published by
 
8
 *   the Free Software Foundation, either version 3 of the License, or
 
9
 *   (at your option) any later version.
 
10
 *
 
11
 *   Tomahawk is distributed in the hope that it will be useful,
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
14
 *   GNU General Public License for more details.
 
15
 *
 
16
 *   You should have received a copy of the GNU General Public License
 
17
 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include "Album.h"
 
21
 
 
22
#include "Artist.h"
 
23
#include "AlbumPlaylistInterface.h"
 
24
#include "database/Database.h"
 
25
#include "database/DatabaseImpl.h"
 
26
#include "database/IdThreadWorker.h"
 
27
#include "Query.h"
 
28
#include "Source.h"
 
29
 
 
30
#include "utils/TomahawkUtilsGui.h"
 
31
#include "utils/Logger.h"
 
32
 
 
33
#include <QReadWriteLock>
 
34
 
 
35
using namespace Tomahawk;
 
36
 
 
37
QHash< QString, album_ptr > Album::s_albumsByName = QHash< QString, album_ptr >();
 
38
QHash< unsigned int, album_ptr > Album::s_albumsById = QHash< unsigned int, album_ptr >();
 
39
 
 
40
static QMutex s_nameCacheMutex;
 
41
static QMutex s_idCacheMutex;
 
42
static QReadWriteLock s_idMutex;
 
43
 
 
44
Album::~Album()
 
45
{
 
46
    m_ownRef.clear();
 
47
 
 
48
#ifndef ENABLE_HEADLESS
 
49
    delete m_cover;
 
50
#endif
 
51
}
 
52
 
 
53
inline QString
 
54
albumCacheKey( const Tomahawk::artist_ptr& artist, const QString& albumName )
 
55
{
 
56
    return QString( "%1\t\t%2" ).arg( artist->name().toLower() ).arg( albumName.toLower() );
 
57
}
 
58
 
 
59
 
 
60
album_ptr
 
61
Album::get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCreate )
 
62
{
 
63
    if ( !Database::instance() || !Database::instance()->impl() )
 
64
        return album_ptr();
 
65
 
 
66
    QMutexLocker l( &s_nameCacheMutex );
 
67
 
 
68
    const QString key = albumCacheKey( artist, name );
 
69
    if ( s_albumsByName.contains( key ) )
 
70
    {
 
71
        return s_albumsByName.value( key );
 
72
    }
 
73
 
 
74
    album_ptr album = album_ptr( new Album( name, artist ) );
 
75
    album->setWeakRef( album.toWeakRef() );
 
76
    album->loadId( autoCreate );
 
77
    s_albumsByName.insert( key, album );
 
78
 
 
79
    return album;
 
80
}
 
81
 
 
82
 
 
83
album_ptr
 
84
Album::get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& artist )
 
85
{
 
86
    static QHash< unsigned int, album_ptr > s_albums;
 
87
    static QMutex s_mutex;
 
88
 
 
89
    QMutexLocker lock( &s_idCacheMutex );
 
90
 
 
91
    const QString key = albumCacheKey( artist, name );
 
92
    if ( s_albumsByName.contains( key ) )
 
93
    {
 
94
        return s_albumsByName.value( key );
 
95
    }
 
96
    if ( s_albumsById.contains( id ) )
 
97
    {
 
98
        return s_albumsById.value( id );
 
99
    }
 
100
 
 
101
    album_ptr a = album_ptr( new Album( id, name, artist ), &QObject::deleteLater );
 
102
    a->setWeakRef( a.toWeakRef() );
 
103
    s_albumsByName.insert( key, a );
 
104
 
 
105
    if ( id > 0 )
 
106
    {
 
107
        s_albumsById.insert( id, a );
 
108
    }
 
109
 
 
110
    return a;
 
111
}
 
112
 
 
113
 
 
114
Album::Album( unsigned int id, const QString& name, const Tomahawk::artist_ptr& artist )
 
115
    : QObject()
 
116
    , m_waitingForId( false )
 
117
    , m_id( id )
 
118
    , m_name( name )
 
119
    , m_artist( artist )
 
120
    , m_coverLoaded( false )
 
121
    , m_coverLoading( false )
 
122
#ifndef ENABLE_HEADLESS
 
123
    , m_cover( 0 )
 
124
#endif
 
125
{
 
126
    m_sortname = DatabaseImpl::sortname( name );
 
127
}
 
128
 
 
129
 
 
130
Album::Album( const QString& name, const Tomahawk::artist_ptr& artist )
 
131
    : QObject()
 
132
    , m_waitingForId( true )
 
133
    , m_name( name )
 
134
    , m_artist( artist )
 
135
    , m_coverLoaded( false )
 
136
    , m_coverLoading( false )
 
137
#ifndef ENABLE_HEADLESS
 
138
    , m_cover( 0 )
 
139
#endif
 
140
{
 
141
    m_sortname = DatabaseImpl::sortname( name );
 
142
}
 
143
 
 
144
void
 
145
Album::onTracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection )
 
146
{
 
147
    emit tracksAdded( playlistInterface( mode, collection )->tracks(), mode, collection );
 
148
}
 
149
 
 
150
 
 
151
artist_ptr
 
152
Album::artist() const
 
153
{
 
154
    return m_artist;
 
155
}
 
156
 
 
157
 
 
158
void
 
159
Album::loadId( bool autoCreate )
 
160
{
 
161
    Q_ASSERT( m_waitingForId );
 
162
    IdThreadWorker::getAlbumId( m_ownRef.toStrongRef(), autoCreate );
 
163
}
 
164
 
 
165
 
 
166
void
 
167
Album::setIdFuture( QFuture<unsigned int> future )
 
168
{
 
169
    m_idFuture = future;
 
170
}
 
171
 
 
172
 
 
173
unsigned int
 
174
Album::id() const
 
175
{
 
176
    s_idMutex.lockForRead();
 
177
    const bool waiting = m_waitingForId;
 
178
    unsigned int finalId = m_id;
 
179
    s_idMutex.unlock();
 
180
 
 
181
    if ( waiting )
 
182
    {
 
183
        finalId = m_idFuture.result();
 
184
 
 
185
        s_idMutex.lockForWrite();
 
186
        m_id = finalId;
 
187
        m_waitingForId = false;
 
188
 
 
189
        if ( m_id > 0 )
 
190
            s_albumsById[ m_id ] = m_ownRef.toStrongRef();
 
191
 
 
192
        s_idMutex.unlock();
 
193
    }
 
194
 
 
195
    return finalId;
 
196
}
 
197
 
 
198
 
 
199
#ifndef ENABLE_HEADLESS
 
200
QPixmap
 
201
Album::cover( const QSize& size, bool forceLoad ) const
 
202
{
 
203
    if ( name().isEmpty() )
 
204
    {
 
205
        m_coverLoaded = true;
 
206
        return QPixmap();
 
207
    }
 
208
 
 
209
    if ( !m_coverLoaded && !m_coverLoading )
 
210
    {
 
211
        if ( !forceLoad )
 
212
            return QPixmap();
 
213
 
 
214
        Tomahawk::InfoSystem::InfoStringHash trackInfo;
 
215
        trackInfo["artist"] = artist()->name();
 
216
        trackInfo["album"] = name();
 
217
 
 
218
        Tomahawk::InfoSystem::InfoRequestData requestData;
 
219
        requestData.caller = infoid();
 
220
        requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
 
221
        requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
 
222
        requestData.customData = QVariantMap();
 
223
 
 
224
        connect( Tomahawk::InfoSystem::InfoSystem::instance(),
 
225
                SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
 
226
                SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
 
227
 
 
228
        connect( Tomahawk::InfoSystem::InfoSystem::instance(),
 
229
                SIGNAL( finished( QString ) ),
 
230
                SLOT( infoSystemFinished( QString ) ) );
 
231
 
 
232
        Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
 
233
 
 
234
        m_coverLoading = true;
 
235
    }
 
236
 
 
237
    if ( !m_cover && !m_coverBuffer.isEmpty() )
 
238
    {
 
239
        QPixmap cover;
 
240
        cover.loadFromData( m_coverBuffer );
 
241
        m_coverBuffer.clear();
 
242
 
 
243
        m_cover = new QPixmap( TomahawkUtils::squareCenterPixmap( cover ) );
 
244
    }
 
245
 
 
246
    if ( m_cover && !m_cover->isNull() && !size.isEmpty() )
 
247
    {
 
248
        if ( m_coverCache.contains( size.width() ) )
 
249
        {
 
250
            return m_coverCache.value( size.width() );
 
251
        }
 
252
 
 
253
        QPixmap scaledCover;
 
254
        scaledCover = m_cover->scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
 
255
        m_coverCache.insert( size.width(), scaledCover );
 
256
        return scaledCover;
 
257
    }
 
258
 
 
259
    if ( m_cover )
 
260
        return *m_cover;
 
261
    else
 
262
        return QPixmap();
 
263
}
 
264
#endif
 
265
 
 
266
 
 
267
void
 
268
Album::infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData, const QVariant& output )
 
269
{
 
270
    if ( requestData.caller != infoid() ||
 
271
         requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
 
272
    {
 
273
        return;
 
274
    }
 
275
 
 
276
    if ( output.isNull() )
 
277
    {
 
278
        m_coverLoaded = true;
 
279
    }
 
280
    else if ( output.isValid() )
 
281
    {
 
282
        QVariantMap returnedData = output.value< QVariantMap >();
 
283
        const QByteArray ba = returnedData["imgbytes"].toByteArray();
 
284
        if ( ba.length() )
 
285
        {
 
286
            m_coverBuffer = ba;
 
287
        }
 
288
 
 
289
        m_coverLoaded = true;
 
290
        emit coverChanged();
 
291
    }
 
292
}
 
293
 
 
294
 
 
295
void
 
296
Album::infoSystemFinished( const QString& target )
 
297
{
 
298
    if ( target != infoid() )
 
299
        return;
 
300
 
 
301
    disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
 
302
                this, SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
 
303
 
 
304
    disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ),
 
305
                this, SLOT( infoSystemFinished( QString ) ) );
 
306
 
 
307
    m_coverLoading = false;
 
308
    emit updated();
 
309
}
 
310
 
 
311
 
 
312
Tomahawk::playlistinterface_ptr
 
313
Album::playlistInterface( ModelMode mode, const Tomahawk::collection_ptr& collection )
 
314
{
 
315
    playlistinterface_ptr pli = m_playlistInterface[ mode ][ collection ];
 
316
 
 
317
    if ( pli.isNull() )
 
318
    {
 
319
        pli = Tomahawk::playlistinterface_ptr( new Tomahawk::AlbumPlaylistInterface( this, mode, collection ) );
 
320
        connect( pli.data(), SIGNAL( tracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
 
321
                               SLOT( onTracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
 
322
 
 
323
        m_playlistInterface[ mode ][ collection ] = pli;
 
324
    }
 
325
 
 
326
    return pli;
 
327
}
 
328
 
 
329
 
 
330
QList<Tomahawk::query_ptr>
 
331
Album::tracks( ModelMode mode, const Tomahawk::collection_ptr& collection )
 
332
{
 
333
    return playlistInterface( mode, collection )->tracks();
 
334
}
 
335
 
 
336
 
 
337
QString
 
338
Album::infoid() const
 
339
{
 
340
    if ( m_uuid.isEmpty() )
 
341
        m_uuid = uuid();
 
342
 
 
343
    return m_uuid;
 
344
}