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

« back to all changes in this revision

Viewing changes to src/libtomahawk/infosystem/InfoSystem.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 2012       Leo Franchi            <lfranchi@kde.org>
 
5
 *   Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
 
6
 *
 
7
 *   Tomahawk is free software: you can redistribute it and/or modify
 
8
 *   it under the terms of the GNU General Public License as published by
 
9
 *   the Free Software Foundation, either version 3 of the License, or
 
10
 *   (at your option) any later version.
 
11
 *
 
12
 *   Tomahawk is distributed in the hope that it will be useful,
 
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
15
 *   GNU General Public License for more details.
 
16
 *
 
17
 *   You should have received a copy of the GNU General Public License
 
18
 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#include <QCoreApplication>
 
22
 
 
23
#include "InfoSystem.h"
 
24
#include "TomahawkSettings.h"
 
25
#include "InfoSystemCache.h"
 
26
#include "InfoSystemWorker.h"
 
27
#include "utils/TomahawkUtils.h"
 
28
#include "utils/Logger.h"
 
29
#include "Source.h"
 
30
 
 
31
namespace Tomahawk
 
32
{
 
33
 
 
34
namespace InfoSystem
 
35
{
 
36
 
 
37
static const int DEFAULT_TIMEOUT_MILLIS = 10000;
 
38
 
 
39
InfoRequestData::InfoRequestData()
 
40
    : requestId( TomahawkUtils::infosystemRequestId() )
 
41
{
 
42
    init( QString() , Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariantMap() );
 
43
}
 
44
 
 
45
 
 
46
InfoRequestData::InfoRequestData( const quint64 rId, const QString& callr, const InfoType typ, const QVariant& inputvar, const QVariantMap& custom )
 
47
    : requestId( rId )
 
48
{
 
49
    init( callr, typ, inputvar, custom );
 
50
}
 
51
 
 
52
 
 
53
void
 
54
InfoRequestData::init( const QString& callr, const InfoType typ, const QVariant& inputvar, const QVariantMap& custom )
 
55
{
 
56
    internalId = TomahawkUtils::infosystemRequestId();
 
57
    caller = callr;
 
58
    type = typ;
 
59
    input = inputvar;
 
60
    customData = custom;
 
61
    timeoutMillis = DEFAULT_TIMEOUT_MILLIS;
 
62
    allSources = false;
 
63
}
 
64
 
 
65
 
 
66
InfoPlugin::InfoPlugin()
 
67
    : QObject()
 
68
{
 
69
}
 
70
 
 
71
InfoPlugin::~InfoPlugin()
 
72
{
 
73
}
 
74
 
 
75
InfoSystem* InfoSystem::s_instance = 0;
 
76
 
 
77
InfoSystem*
 
78
InfoSystem::instance()
 
79
{
 
80
    if ( !s_instance )
 
81
        s_instance = new InfoSystem( 0 );
 
82
 
 
83
    return s_instance;
 
84
}
 
85
 
 
86
 
 
87
InfoSystem::InfoSystem( QObject *parent )
 
88
    : QObject( parent )
 
89
    , m_inited( false )
 
90
    , m_infoSystemCacheThreadController( 0 )
 
91
    , m_infoSystemWorkerThreadController( 0 )
 
92
{
 
93
    s_instance = this;
 
94
 
 
95
    qDebug() << Q_FUNC_INFO;
 
96
 
 
97
    m_infoSystemCacheThreadController = new InfoSystemCacheThread( this );
 
98
    m_infoSystemCacheThreadController->start( QThread::IdlePriority );
 
99
 
 
100
    m_infoSystemWorkerThreadController = new InfoSystemWorkerThread( this );
 
101
    m_infoSystemWorkerThreadController->start();
 
102
 
 
103
    QTimer::singleShot( 0, this, SLOT( init() ) );
 
104
}
 
105
 
 
106
 
 
107
InfoSystem::~InfoSystem()
 
108
{
 
109
    tDebug() << Q_FUNC_INFO << " beginning";
 
110
 
 
111
    if ( m_infoSystemWorkerThreadController )
 
112
    {
 
113
        m_infoSystemWorkerThreadController->quit();
 
114
        m_infoSystemWorkerThreadController->wait( 60000 );
 
115
 
 
116
        delete m_infoSystemWorkerThreadController;
 
117
        m_infoSystemWorkerThreadController = 0;
 
118
    }
 
119
    tDebug() << Q_FUNC_INFO << " done deleting worker";
 
120
 
 
121
    if( m_infoSystemCacheThreadController )
 
122
    {
 
123
        m_infoSystemCacheThreadController->quit();
 
124
        m_infoSystemCacheThreadController->wait( 60000 );
 
125
 
 
126
        delete m_infoSystemCacheThreadController;
 
127
        m_infoSystemCacheThreadController = 0;
 
128
    }
 
129
 
 
130
    tDebug() << Q_FUNC_INFO << " done deleting cache";
 
131
}
 
132
 
 
133
 
 
134
void
 
135
InfoSystem::init()
 
136
{
 
137
    tDebug() << Q_FUNC_INFO;
 
138
    if ( m_inited )
 
139
        return;
 
140
 
 
141
    if ( !m_infoSystemCacheThreadController->cache() || !m_infoSystemWorkerThreadController->worker() )
 
142
    {
 
143
        QTimer::singleShot( 0, this, SLOT( init() ) );
 
144
        return;
 
145
    }
 
146
 
 
147
    Tomahawk::InfoSystem::InfoSystemCache* cache = m_infoSystemCacheThreadController->cache();
 
148
    Tomahawk::InfoSystem::InfoSystemWorker* worker = m_infoSystemWorkerThreadController->worker();
 
149
 
 
150
    connect( cache, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
 
151
             worker, SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
 
152
 
 
153
    connect( worker, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
 
154
             this,       SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
 
155
 
 
156
    connect( worker, SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
 
157
 
 
158
    connect( worker, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ),
 
159
             this, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ), Qt::UniqueConnection );
 
160
 
 
161
    qRegisterMetaType< Tomahawk::InfoSystem::InfoTypeSet >();
 
162
    connect( worker, SIGNAL( updatedSupportedGetTypes( Tomahawk::InfoSystem::InfoTypeSet ) ),
 
163
             this,   SLOT(   receiveUpdatedSupportedGetTypes( Tomahawk::InfoSystem::InfoTypeSet ) ) );
 
164
    connect( worker, SIGNAL( updatedSupportedPushTypes( Tomahawk::InfoSystem::InfoTypeSet ) ),
 
165
             this,   SLOT(   receiveUpdatedSupportedPushTypes( Tomahawk::InfoSystem::InfoTypeSet ) ) );
 
166
 
 
167
    QMetaObject::invokeMethod( worker, "init", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoSystemCache*, cache ) );
 
168
 
 
169
    m_inited = true;
 
170
}
 
171
 
 
172
 
 
173
bool
 
174
InfoSystem::getInfo( const InfoRequestData &requestData )
 
175
{
 
176
    //qDebug() << Q_FUNC_INFO;
 
177
    if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
 
178
    {
 
179
        init();
 
180
        return false;
 
181
    }
 
182
    QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
 
183
    return true;
 
184
}
 
185
 
 
186
 
 
187
bool
 
188
InfoSystem::getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap, bool allSources )
 
189
{
 
190
    if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
 
191
    {
 
192
        init();
 
193
        return false;
 
194
    }
 
195
    InfoRequestData requestData;
 
196
    requestData.caller = caller;
 
197
    requestData.customData = customData;
 
198
    requestData.allSources = allSources;
 
199
    Q_FOREACH( InfoType type, inputMap.keys() )
 
200
    {
 
201
        requestData.type = type;
 
202
        requestData.input = inputMap[ type ];
 
203
        requestData.timeoutMillis = timeoutMap.contains( type ) ? timeoutMap[ type ] : DEFAULT_TIMEOUT_MILLIS;
 
204
        QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
 
205
    }
 
206
    return false;
 
207
}
 
208
 
 
209
 
 
210
bool
 
211
InfoSystem::pushInfo( InfoPushData pushData )
 
212
{
 
213
    tDebug() << Q_FUNC_INFO << "type is " << pushData.type;
 
214
    if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
 
215
    {
 
216
        init();
 
217
        return false;
 
218
    }
 
219
 
 
220
    PushInfoPair pushInfoPair( QVariantMap(), pushData.input );
 
221
    pushData.infoPair = pushInfoPair;
 
222
    QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "pushInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPushData, pushData ) );
 
223
 
 
224
    return true;
 
225
}
 
226
 
 
227
 
 
228
bool
 
229
InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input, const PushInfoFlags pushFlags )
 
230
{
 
231
    if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
 
232
    {
 
233
        init();
 
234
        return false;
 
235
    }
 
236
 
 
237
    Q_FOREACH( InfoType type, input.keys() )
 
238
    {
 
239
        InfoPushData pushData( caller, type, input[ type ], pushFlags );
 
240
        pushData.infoPair = PushInfoPair( QVariantMap(), pushData.input );
 
241
        QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "pushInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPushData, pushData ) );
 
242
    }
 
243
 
 
244
    return true;
 
245
}
 
246
 
 
247
 
 
248
void
 
249
InfoSystem::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
 
250
{
 
251
    // Init is not complete (waiting for worker thread to start and create worker object) so keep trying till then
 
252
    if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
 
253
    {
 
254
        QMetaObject::invokeMethod( this, "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
 
255
        return;
 
256
    }
 
257
 
 
258
    if ( plugin.isNull() )
 
259
    {
 
260
        tDebug() << Q_FUNC_INFO << "Given plugin is null!";
 
261
        return;
 
262
    }
 
263
 
 
264
    if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() )
 
265
    {
 
266
        Q_ASSERT( false );
 
267
        tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()";
 
268
        return;
 
269
    }
 
270
 
 
271
    tDebug() << Q_FUNC_INFO << plugin.data();
 
272
    QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
 
273
}
 
274
 
 
275
 
 
276
void
 
277
InfoSystem::removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
 
278
{
 
279
    // Init is not complete (waiting for worker th read to start and create worker object) so keep trying till then
 
280
    if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
 
281
    {
 
282
        QMetaObject::invokeMethod( this, "removeInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
 
283
        return;
 
284
    }
 
285
 
 
286
    if ( plugin.isNull() )
 
287
    {
 
288
        tDebug() << Q_FUNC_INFO << "Given plugin is null!";
 
289
        return;
 
290
    }
 
291
 
 
292
    if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() )
 
293
    {
 
294
        tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()";
 
295
        return;
 
296
    }
 
297
 
 
298
    tDebug() << Q_FUNC_INFO << plugin.data();
 
299
    QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "removeInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
 
300
}
 
301
 
 
302
 
 
303
void
 
304
InfoSystem::receiveUpdatedSupportedGetTypes( InfoTypeSet supportedTypes )
 
305
{
 
306
    m_supportedGetTypes = supportedTypes;
 
307
    emit updatedSupportedGetTypes( m_supportedGetTypes );
 
308
}
 
309
 
 
310
 
 
311
void
 
312
InfoSystem::receiveUpdatedSupportedPushTypes( InfoTypeSet supportedTypes )
 
313
{
 
314
    m_supportedPushTypes = supportedTypes;
 
315
    emit updatedSupportedPushTypes( m_supportedPushTypes );
 
316
}
 
317
 
 
318
 
 
319
QWeakPointer< QThread >
 
320
InfoSystem::workerThread() const
 
321
{
 
322
    if ( m_infoSystemWorkerThreadController->isRunning() && m_infoSystemWorkerThreadController->worker() )
 
323
        return QWeakPointer< QThread >( m_infoSystemWorkerThreadController->worker()->thread() );
 
324
 
 
325
    return QWeakPointer< QThread >();
 
326
}
 
327
 
 
328
 
 
329
InfoSystemCacheThread::InfoSystemCacheThread( QObject *parent )
 
330
    : QThread( parent )
 
331
{
 
332
    tDebug() << Q_FUNC_INFO;
 
333
}
 
334
 
 
335
 
 
336
InfoSystemCacheThread::~InfoSystemCacheThread()
 
337
{
 
338
    tDebug() << Q_FUNC_INFO;
 
339
}
 
340
 
 
341
 
 
342
void
 
343
InfoSystemCacheThread::InfoSystemCacheThread::run()
 
344
{
 
345
    m_cache = QWeakPointer< InfoSystemCache >( new InfoSystemCache() );
 
346
    exec();
 
347
    if ( !m_cache.isNull() )
 
348
        delete m_cache.data();
 
349
}
 
350
 
 
351
 
 
352
InfoSystemCache*
 
353
InfoSystemCacheThread::cache() const
 
354
{
 
355
    if ( m_cache.isNull() )
 
356
        return 0;
 
357
    return m_cache.data();
 
358
}
 
359
 
 
360
 
 
361
InfoSystemWorkerThread::InfoSystemWorkerThread( QObject *parent )
 
362
    : QThread( parent )
 
363
{
 
364
    tDebug() << Q_FUNC_INFO;
 
365
}
 
366
 
 
367
InfoSystemWorkerThread::~InfoSystemWorkerThread()
 
368
{
 
369
    tDebug() << Q_FUNC_INFO;
 
370
}
 
371
 
 
372
void
 
373
InfoSystemWorkerThread::InfoSystemWorkerThread::run()
 
374
{
 
375
    m_worker = QWeakPointer< InfoSystemWorker >( new InfoSystemWorker() );
 
376
    exec();
 
377
    if( !m_worker.isNull() )
 
378
        delete m_worker.data();
 
379
}
 
380
 
 
381
InfoSystemWorker*
 
382
InfoSystemWorkerThread::worker() const
 
383
{
 
384
    if ( m_worker.isNull() )
 
385
        return 0;
 
386
    return m_worker.data();
 
387
}
 
388
 
 
389
 
 
390
} //namespace InfoSystem
 
391
 
 
392
} //namespace Tomahawk