~ubuntu-branches/ubuntu/oneiric/phonon/oneiric-201108111512

« back to all changes in this revision

Viewing changes to mmf/mediaobject.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2011-01-24 10:12:11 UTC
  • mfrom: (0.5.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110124101211-w9rew7q0dmwbwhqx
Tags: 4:4.7.0really4.4.4-0ubuntu1
* New upstream release
* Xine and GStreamer backends now split out source, remove build-deps and
  binary packages from debian/control
* Remove 02_no_rpath.patch, now upstream
* Disable kubuntu04_no_va_mangle.patch, no longer applies
* Remove kubuntu_05_gst_codec_installer_window_id.diff, kubuntu_06_forward_events.diff,
  kubuntu_07_include_fix.diff, gstreamer now separate

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  This file is part of the KDE project.
2
 
 
3
 
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
 
 
5
 
This library is free software: you can redistribute it and/or modify
6
 
it under the terms of the GNU Lesser General Public License as published by
7
 
the Free Software Foundation, either version 2.1 or 3 of the License.
8
 
 
9
 
This library is distributed in the hope that it will be useful,
10
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
GNU Lesser General Public License for more details.
13
 
 
14
 
You should have received a copy of the GNU Lesser General Public License
15
 
along with this library.  If not, see <http://www.gnu.org/licenses/>.
16
 
 
17
 
*/
18
 
 
19
 
#include "audiooutput.h"
20
 
#include "audioplayer.h"
21
 
#include "defs.h"
22
 
#include "dummyplayer.h"
23
 
#include "utils.h"
24
 
#include "utils.h"
25
 
 
26
 
#ifdef PHONON_MMF_VIDEO_SURFACES
27
 
#include "videoplayer_surface.h"
28
 
#else
29
 
#include "videoplayer_dsa.h"
30
 
#endif
31
 
 
32
 
#include "videowidget.h"
33
 
 
34
 
#include "mediaobject.h"
35
 
 
36
 
#include <QDir>
37
 
#include <QResource>
38
 
#include <QUrl>
39
 
 
40
 
QT_BEGIN_NAMESPACE
41
 
 
42
 
using namespace Phonon;
43
 
using namespace Phonon::MMF;
44
 
 
45
 
/*! \class MMF::MediaObject
46
 
  \internal
47
 
*/
48
 
 
49
 
//-----------------------------------------------------------------------------
50
 
// Constructor / destructor
51
 
//-----------------------------------------------------------------------------
52
 
 
53
 
MMF::MediaObject::MediaObject(QObject *parent) : MMF::MediaNode::MediaNode(parent)
54
 
                                               , m_recognizerOpened(false)
55
 
                                               , m_nextSourceSet(false)
56
 
                                               , m_file(0)
57
 
                                               , m_resource(0)
58
 
{
59
 
    m_player.reset(new DummyPlayer());
60
 
 
61
 
    TRACE_CONTEXT(MediaObject::MediaObject, EAudioApi);
62
 
    TRACE_ENTRY_0();
63
 
 
64
 
    Q_UNUSED(parent);
65
 
 
66
 
    TRACE_EXIT_0();
67
 
}
68
 
 
69
 
MMF::MediaObject::~MediaObject()
70
 
{
71
 
    TRACE_CONTEXT(MediaObject::~MediaObject, EAudioApi);
72
 
    TRACE_ENTRY_0();
73
 
 
74
 
    delete m_resource;
75
 
 
76
 
    if (m_file)
77
 
        m_file->Close();
78
 
    delete m_file;
79
 
 
80
 
    m_fileServer.Close();
81
 
    m_recognizer.Close();
82
 
 
83
 
    TRACE_EXIT_0();
84
 
}
85
 
 
86
 
 
87
 
//-----------------------------------------------------------------------------
88
 
// Recognizer
89
 
//-----------------------------------------------------------------------------
90
 
 
91
 
bool MMF::MediaObject::openRecognizer()
92
 
{
93
 
    TRACE_CONTEXT(MediaObject::openRecognizer, EAudioInternal);
94
 
 
95
 
    if (!m_recognizerOpened) {
96
 
        TInt err = m_recognizer.Connect();
97
 
        if (KErrNone != err) {
98
 
            TRACE("RApaLsSession::Connect error %d", err);
99
 
            return false;
100
 
        }
101
 
 
102
 
        err = m_fileServer.Connect();
103
 
        if (KErrNone != err) {
104
 
            TRACE("RFs::Connect error %d", err);
105
 
            return false;
106
 
        }
107
 
 
108
 
        // This must be called in order to be able to share file handles with
109
 
        // the recognizer server (see fileMediaType function).
110
 
        err = m_fileServer.ShareProtected();
111
 
        if (KErrNone != err) {
112
 
            TRACE("RFs::ShareProtected error %d", err);
113
 
            return false;
114
 
        }
115
 
 
116
 
        m_recognizerOpened = true;
117
 
    }
118
 
 
119
 
    return true;
120
 
}
121
 
 
122
 
MMF::MediaType MMF::MediaObject::fileMediaType
123
 
(const QString& fileName)
124
 
{
125
 
    TRACE_CONTEXT(MediaObject::fileMediaType, EAudioInternal);
126
 
 
127
 
    MediaType result = MediaTypeUnknown;
128
 
 
129
 
    if (openRecognizer()) {
130
 
 
131
 
        const QHBufC fileNameSymbian(QDir::toNativeSeparators(fileName));
132
 
 
133
 
        Q_ASSERT(!m_file);
134
 
        m_file = new RFile;
135
 
        TInt err = m_file->Open(m_fileServer, *fileNameSymbian, EFileRead | EFileShareReadersOnly);
136
 
 
137
 
        if (KErrNone == err) {
138
 
            TDataRecognitionResult recognizerResult;
139
 
            err = m_recognizer.RecognizeData(*m_file, recognizerResult);
140
 
            if (KErrNone == err) {
141
 
                const TPtrC mimeType = recognizerResult.iDataType.Des();
142
 
                result = Utils::mimeTypeToMediaType(mimeType);
143
 
            } else {
144
 
                TRACE("RApaLsSession::RecognizeData filename %S error %d", fileNameSymbian.data(), err);
145
 
            }
146
 
        } else {
147
 
            TRACE("RFile::Open filename %S error %d", fileNameSymbian.data(), err);
148
 
        }
149
 
    }
150
 
 
151
 
    return result;
152
 
}
153
 
 
154
 
MMF::MediaType MMF::MediaObject::bufferMediaType(const uchar *data, qint64 size)
155
 
{
156
 
    TRACE_CONTEXT(MediaObject::bufferMediaType, EAudioInternal);
157
 
    MediaType result = MediaTypeUnknown;
158
 
    if (openRecognizer()) {
159
 
        TDataRecognitionResult recognizerResult;
160
 
        const TPtrC8 des(data, size);
161
 
        const TInt err = m_recognizer.RecognizeData(des, recognizerResult);
162
 
        if (KErrNone == err) {
163
 
            const TPtrC mimeType = recognizerResult.iDataType.Des();
164
 
            result = Utils::mimeTypeToMediaType(mimeType);
165
 
        } else {
166
 
            TRACE("RApaLsSession::RecognizeData error %d", err);
167
 
        }
168
 
    }
169
 
    return result;
170
 
}
171
 
 
172
 
//-----------------------------------------------------------------------------
173
 
// MediaObjectInterface
174
 
//-----------------------------------------------------------------------------
175
 
 
176
 
void MMF::MediaObject::play()
177
 
{
178
 
    m_player->play();
179
 
}
180
 
 
181
 
void MMF::MediaObject::pause()
182
 
{
183
 
    m_player->pause();
184
 
}
185
 
 
186
 
void MMF::MediaObject::stop()
187
 
{
188
 
    m_player->stop();
189
 
}
190
 
 
191
 
void MMF::MediaObject::seek(qint64 ms)
192
 
{
193
 
    m_player->seek(ms);
194
 
 
195
 
    if (state() == PausedState or state() == PlayingState) {
196
 
        emit tick(currentTime());
197
 
    }
198
 
}
199
 
 
200
 
qint32 MMF::MediaObject::tickInterval() const
201
 
{
202
 
    return m_player->tickInterval();
203
 
}
204
 
 
205
 
void MMF::MediaObject::setTickInterval(qint32 interval)
206
 
{
207
 
    m_player->setTickInterval(interval);
208
 
}
209
 
 
210
 
bool MMF::MediaObject::hasVideo() const
211
 
{
212
 
    return m_player->hasVideo();
213
 
}
214
 
 
215
 
bool MMF::MediaObject::isSeekable() const
216
 
{
217
 
    return m_player->isSeekable();
218
 
}
219
 
 
220
 
Phonon::State MMF::MediaObject::state() const
221
 
{
222
 
    return m_player->state();
223
 
}
224
 
 
225
 
qint64 MMF::MediaObject::currentTime() const
226
 
{
227
 
    return m_player->currentTime();
228
 
}
229
 
 
230
 
QString MMF::MediaObject::errorString() const
231
 
{
232
 
    return m_player->errorString();
233
 
}
234
 
 
235
 
Phonon::ErrorType MMF::MediaObject::errorType() const
236
 
{
237
 
    return m_player->errorType();
238
 
}
239
 
 
240
 
qint64 MMF::MediaObject::totalTime() const
241
 
{
242
 
    return m_player->totalTime();
243
 
}
244
 
 
245
 
MediaSource MMF::MediaObject::source() const
246
 
{
247
 
    return m_source;
248
 
}
249
 
 
250
 
void MMF::MediaObject::setSource(const MediaSource &source)
251
 
{
252
 
    switchToSource(source);
253
 
}
254
 
 
255
 
void MMF::MediaObject::switchToSource(const MediaSource &source)
256
 
{
257
 
    if (m_file)
258
 
        m_file->Close();
259
 
    delete m_file;
260
 
    m_file = 0;
261
 
 
262
 
    delete m_resource;
263
 
    m_resource = 0;
264
 
 
265
 
    createPlayer(source);
266
 
    m_source = source;
267
 
    m_player->open();
268
 
    emit currentSourceChanged(m_source);
269
 
}
270
 
 
271
 
void MMF::MediaObject::createPlayer(const MediaSource &source)
272
 
{
273
 
    TRACE_CONTEXT(MediaObject::createPlayer, EAudioApi);
274
 
    TRACE_ENTRY("state %d source.type %d", state(), source.type());
275
 
    TRACE_ENTRY("source.type %d", source.type());
276
 
 
277
 
    MediaType mediaType = MediaTypeUnknown;
278
 
 
279
 
    AbstractPlayer* oldPlayer = m_player.data();
280
 
 
281
 
    const bool oldPlayerHasVideo = oldPlayer->hasVideo();
282
 
    const bool oldPlayerSeekable = oldPlayer->isSeekable();
283
 
 
284
 
    QString errorMessage;
285
 
 
286
 
    // Determine media type
287
 
    switch (source.type()) {
288
 
    case MediaSource::LocalFile:
289
 
        mediaType = fileMediaType(source.fileName());
290
 
        break;
291
 
 
292
 
    case MediaSource::Url:
293
 
        {
294
 
            const QUrl url(source.url());
295
 
            if (url.scheme() == QLatin1String("file")) {
296
 
                mediaType = fileMediaType(url.toLocalFile());
297
 
            }
298
 
            else {
299
 
                // Streaming playback is generally not supported by the implementation
300
 
                // of the audio player API, so we use CVideoPlayerUtility for both
301
 
                // audio and video streaming.
302
 
                mediaType = MediaTypeVideo;
303
 
            }
304
 
        }
305
 
        break;
306
 
 
307
 
    case MediaSource::Invalid:
308
 
    case MediaSource::Disc:
309
 
        errorMessage = tr("Error opening source: type not supported");
310
 
        break;
311
 
 
312
 
    case MediaSource::Stream:
313
 
        {
314
 
            const QString fileName = source.url().toLocalFile();
315
 
            if (fileName.startsWith(QLatin1String(":/")) || fileName.startsWith(QLatin1String("qrc://"))) {
316
 
                Q_ASSERT(!m_resource);
317
 
                m_resource = new QResource(fileName);
318
 
                if (m_resource->isValid()) {
319
 
                    if (m_resource->isCompressed())
320
 
                        errorMessage = tr("Error opening source: resource is compressed");
321
 
                    else
322
 
                        mediaType = bufferMediaType(m_resource->data(), m_resource->size());
323
 
                } else {
324
 
                    errorMessage = tr("Error opening source: resource not valid");
325
 
                }
326
 
            } else {
327
 
                errorMessage = tr("Error opening source: type not supported");
328
 
            }
329
 
        }
330
 
        break;
331
 
 
332
 
    case MediaSource::Empty:
333
 
        TRACE_0("Empty media source");
334
 
        break;
335
 
    }
336
 
 
337
 
    if (oldPlayer)
338
 
        oldPlayer->close();
339
 
 
340
 
    AbstractPlayer* newPlayer = 0;
341
 
 
342
 
    // Construct newPlayer using oldPlayer (if not 0) in order to copy
343
 
    // parameters (volume, prefinishMark, transitionTime) which may have
344
 
    // been set on oldPlayer.
345
 
 
346
 
    switch (mediaType) {
347
 
    case MediaTypeUnknown:
348
 
        TRACE_0("Media type could not be determined");
349
 
        newPlayer = new DummyPlayer(oldPlayer);
350
 
        errorMessage = tr("Error opening source: media type could not be determined");
351
 
        break;
352
 
 
353
 
    case MediaTypeAudio:
354
 
        newPlayer = new AudioPlayer(this, oldPlayer);
355
 
        break;
356
 
 
357
 
    case MediaTypeVideo:
358
 
#ifdef PHONON_MMF_VIDEO_SURFACES
359
 
        newPlayer = SurfaceVideoPlayer::create(this, oldPlayer);
360
 
#else
361
 
        newPlayer = DsaVideoPlayer::create(this, oldPlayer);
362
 
#endif
363
 
        break;
364
 
    }
365
 
 
366
 
    if (oldPlayer)
367
 
        emit abstractPlayerChanged(0);
368
 
    m_player.reset(newPlayer);
369
 
    emit abstractPlayerChanged(newPlayer);
370
 
 
371
 
    if (oldPlayerHasVideo != hasVideo()) {
372
 
        emit hasVideoChanged(hasVideo());
373
 
    }
374
 
 
375
 
    if (oldPlayerSeekable != isSeekable()) {
376
 
        emit seekableChanged(isSeekable());
377
 
    }
378
 
 
379
 
    connect(m_player.data(), SIGNAL(totalTimeChanged(qint64)), SIGNAL(totalTimeChanged(qint64)));
380
 
    connect(m_player.data(), SIGNAL(stateChanged(Phonon::State,Phonon::State)), SIGNAL(stateChanged(Phonon::State,Phonon::State)));
381
 
    connect(m_player.data(), SIGNAL(finished()), SIGNAL(finished()));
382
 
    connect(m_player.data(), SIGNAL(bufferStatus(int)), SIGNAL(bufferStatus(int)));
383
 
    connect(m_player.data(), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)));
384
 
    connect(m_player.data(), SIGNAL(aboutToFinish()), SIGNAL(aboutToFinish()));
385
 
    connect(m_player.data(), SIGNAL(prefinishMarkReached(qint32)), SIGNAL(prefinishMarkReached(qint32)));
386
 
    connect(m_player.data(), SIGNAL(prefinishMarkReached(qint32)), SLOT(handlePrefinishMarkReached(qint32)));
387
 
    connect(m_player.data(), SIGNAL(tick(qint64)), SIGNAL(tick(qint64)));
388
 
 
389
 
    // We need to call setError() after doing the connects, otherwise the
390
 
    // error won't be received.
391
 
    if (!errorMessage.isEmpty()) {
392
 
        Q_ASSERT(m_player);
393
 
        m_player->setError(errorMessage);
394
 
    }
395
 
 
396
 
    TRACE_EXIT_0();
397
 
}
398
 
 
399
 
void MMF::MediaObject::setNextSource(const MediaSource &source)
400
 
{
401
 
    m_nextSource = source;
402
 
    m_nextSourceSet = true;
403
 
}
404
 
 
405
 
qint32 MMF::MediaObject::prefinishMark() const
406
 
{
407
 
    return m_player->prefinishMark();
408
 
}
409
 
 
410
 
void MMF::MediaObject::setPrefinishMark(qint32 mark)
411
 
{
412
 
    m_player->setPrefinishMark(mark);
413
 
}
414
 
 
415
 
qint32 MMF::MediaObject::transitionTime() const
416
 
{
417
 
    return m_player->transitionTime();
418
 
}
419
 
 
420
 
void MMF::MediaObject::setTransitionTime(qint32 time)
421
 
{
422
 
    m_player->setTransitionTime(time);
423
 
}
424
 
 
425
 
void MMF::MediaObject::volumeChanged(qreal volume)
426
 
{
427
 
    m_player->volumeChanged(volume);
428
 
}
429
 
 
430
 
RFile* MMF::MediaObject::file() const
431
 
{
432
 
    return m_file;
433
 
}
434
 
 
435
 
QResource* MMF::MediaObject::resource() const
436
 
{
437
 
    return m_resource;
438
 
}
439
 
 
440
 
//-----------------------------------------------------------------------------
441
 
// MediaNode
442
 
//-----------------------------------------------------------------------------
443
 
 
444
 
void MMF::MediaObject::connectMediaObject(MediaObject * /*mediaObject*/)
445
 
{
446
 
    // This function should never be called - see MediaNode::setMediaObject()
447
 
    Q_ASSERT_X(false, Q_FUNC_INFO,
448
 
        "Connection of MediaObject to MediaObject");
449
 
}
450
 
 
451
 
void MMF::MediaObject::disconnectMediaObject(MediaObject * /*mediaObject*/)
452
 
{
453
 
    // This function should never be called - see MediaNode::setMediaObject()
454
 
    Q_ASSERT_X(false, Q_FUNC_INFO,
455
 
        "Disconnection of MediaObject from MediaObject");
456
 
}
457
 
 
458
 
 
459
 
//-----------------------------------------------------------------------------
460
 
// Video output
461
 
//-----------------------------------------------------------------------------
462
 
 
463
 
void MMF::MediaObject::setVideoOutput(AbstractVideoOutput* videoOutput)
464
 
{
465
 
    m_player->setVideoOutput(videoOutput);
466
 
}
467
 
 
468
 
 
469
 
AbstractPlayer *MMF::MediaObject::abstractPlayer() const
470
 
{
471
 
    return m_player.data();
472
 
}
473
 
 
474
 
//-----------------------------------------------------------------------------
475
 
// Playlist support
476
 
//-----------------------------------------------------------------------------
477
 
 
478
 
void MMF::MediaObject::switchToNextSource()
479
 
{
480
 
    if (m_nextSourceSet) {
481
 
        m_nextSourceSet = false;
482
 
        switchToSource(m_nextSource);
483
 
        play();
484
 
    } else {
485
 
        emit finished();
486
 
    }
487
 
}
488
 
 
489
 
//-----------------------------------------------------------------------------
490
 
// Other private functions
491
 
//-----------------------------------------------------------------------------
492
 
 
493
 
void MMF::MediaObject::handlePrefinishMarkReached(qint32 time)
494
 
{
495
 
    emit tick(time);
496
 
}
497
 
 
498
 
 
499
 
QT_END_NAMESPACE
500