~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/phonon/mmf/mmf_videoplayer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

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 <QApplication> // for QApplication::activeWindow
 
20
#include <QUrl>
 
21
#include <QTimer>
 
22
#include <QWidget>
 
23
 
 
24
#include <coemain.h>    // for CCoeEnv
 
25
#include <coecntrl.h>
 
26
 
 
27
#include "mmf_videoplayer.h"
 
28
#include "utils.h"
 
29
 
 
30
#ifdef _DEBUG
 
31
#include "objectdump.h"
 
32
#endif
 
33
 
 
34
QT_BEGIN_NAMESPACE
 
35
 
 
36
using namespace Phonon;
 
37
using namespace Phonon::MMF;
 
38
 
 
39
/*! \class MMF::VideoPlayer
 
40
  \internal
 
41
*/
 
42
 
 
43
//-----------------------------------------------------------------------------
 
44
// Constructor / destructor
 
45
//-----------------------------------------------------------------------------
 
46
 
 
47
MMF::VideoPlayer::VideoPlayer()
 
48
        :   m_wsSession(0)
 
49
        ,   m_screenDevice(0)
 
50
        ,   m_window(0)
 
51
        ,   m_totalTime(0)
 
52
        ,   m_mmfOutputChangePending(false)
 
53
{
 
54
    construct();
 
55
}
 
56
 
 
57
MMF::VideoPlayer::VideoPlayer(const AbstractPlayer& player)
 
58
        :   AbstractMediaPlayer(player)
 
59
        ,   m_wsSession(0)
 
60
        ,   m_screenDevice(0)
 
61
        ,   m_window(0)
 
62
        ,   m_totalTime(0)
 
63
        ,   m_mmfOutputChangePending(false)
 
64
{
 
65
    construct();
 
66
}
 
67
 
 
68
void MMF::VideoPlayer::construct()
 
69
{
 
70
    TRACE_CONTEXT(VideoPlayer::VideoPlayer, EVideoApi);
 
71
    TRACE_ENTRY_0();
 
72
 
 
73
    if(m_videoOutput)
 
74
        m_videoOutput->setObserver(this);
 
75
 
 
76
    const TInt priority = 0;
 
77
    const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone;
 
78
 
 
79
    getNativeWindowSystemHandles();
 
80
 
 
81
    // TODO: is this the correct way to handle errors which occur when
 
82
    // creating a Symbian object in the constructor of a Qt object?
 
83
    
 
84
    // TODO: check whether videoOutput is visible?  If not, then the 
 
85
    // corresponding window will not be active, meaning that the 
 
86
    // clipping region will be set to empty and the video will not be
 
87
    // visible.  If this is the case, we should set m_mmfOutputChangePending
 
88
    // and respond to future showEvents from the videoOutput widget.
 
89
    
 
90
    TRAPD(err,
 
91
          m_player.reset(CVideoPlayerUtility::NewL
 
92
                     (
 
93
                         *this,
 
94
                         priority, preference,
 
95
                         *m_wsSession, *m_screenDevice,
 
96
                         *m_window,
 
97
                         m_windowRect, m_clipRect
 
98
                     ))
 
99
         );
 
100
 
 
101
    if (KErrNone != err) {
 
102
        changeState(ErrorState);
 
103
    }
 
104
 
 
105
    TRACE_EXIT_0();
 
106
}
 
107
 
 
108
MMF::VideoPlayer::~VideoPlayer()
 
109
{
 
110
    TRACE_CONTEXT(VideoPlayer::~VideoPlayer, EVideoApi);
 
111
    TRACE_ENTRY_0();
 
112
 
 
113
    TRACE_EXIT_0();
 
114
}
 
115
 
 
116
//-----------------------------------------------------------------------------
 
117
// Public API
 
118
//-----------------------------------------------------------------------------
 
119
 
 
120
void MMF::VideoPlayer::doPlay()
 
121
{
 
122
    TRACE_CONTEXT(VideoPlayer::doPlay, EVideoApi);
 
123
    
 
124
    // See comment in updateMmfOutput
 
125
    if(m_mmfOutputChangePending) {
 
126
        TRACE_0("MMF output change pending - pushing now");
 
127
        updateMmfOutput();
 
128
    }
 
129
    
 
130
    m_player->Play();
 
131
}
 
132
 
 
133
void MMF::VideoPlayer::doPause()
 
134
{
 
135
    TRACE_CONTEXT(VideoPlayer::doPause, EVideoApi);
 
136
 
 
137
    TRAPD(err, m_player->PauseL());
 
138
    if (KErrNone != err) {
 
139
        TRACE("PauseL error %d", err);
 
140
        setError(NormalError);
 
141
    }
 
142
}
 
143
 
 
144
void MMF::VideoPlayer::doStop()
 
145
{
 
146
    m_player->Stop();
 
147
}
 
148
 
 
149
void MMF::VideoPlayer::doSeek(qint64 ms)
 
150
{
 
151
    TRACE_CONTEXT(VideoPlayer::doSeek, EVideoApi);
 
152
    
 
153
    bool wasPlaying = false;
 
154
    if(state() == PlayingState) {
 
155
                // The call to SetPositionL does not have any effect if playback is
 
156
                // ongoing, so we pause before seeking.
 
157
                doPause();
 
158
                wasPlaying = true;
 
159
    }
 
160
 
 
161
    TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000)));
 
162
 
 
163
    if(KErrNone == err) {
 
164
                if(wasPlaying)
 
165
                        doPlay();
 
166
    }
 
167
    else {
 
168
        TRACE("SetPositionL error %d", err);
 
169
        setError(NormalError);
 
170
    }
 
171
}
 
172
 
 
173
int MMF::VideoPlayer::setDeviceVolume(int mmfVolume)
 
174
{
 
175
    TRAPD(err, m_player->SetVolumeL(mmfVolume));
 
176
    return err;
 
177
}
 
178
 
 
179
int MMF::VideoPlayer::openFile(RFile& file)
 
180
{
 
181
    TRAPD(err, m_player->OpenFileL(file));
 
182
    return err;
 
183
}
 
184
 
 
185
void MMF::VideoPlayer::close()
 
186
{
 
187
    m_player->Close();
 
188
}
 
189
 
 
190
bool MMF::VideoPlayer::hasVideo() const
 
191
{
 
192
    return true;
 
193
}
 
194
 
 
195
qint64 MMF::VideoPlayer::currentTime() const
 
196
{
 
197
    TRACE_CONTEXT(VideoPlayer::currentTime, EVideoApi);
 
198
 
 
199
    TTimeIntervalMicroSeconds us;
 
200
    TRAPD(err, us = m_player->PositionL())
 
201
 
 
202
    qint64 result = 0;
 
203
 
 
204
    if (KErrNone == err) {
 
205
        result = toMilliSeconds(us);
 
206
    } else {
 
207
        TRACE("PositionL error %d", err);
 
208
 
 
209
        // If we don't cast away constness here, we simply have to ignore
 
210
        // the error.
 
211
        const_cast<VideoPlayer*>(this)->setError(NormalError);
 
212
    }
 
213
 
 
214
    return result;
 
215
}
 
216
 
 
217
qint64 MMF::VideoPlayer::totalTime() const
 
218
{
 
219
    return m_totalTime;
 
220
}
 
221
 
 
222
 
 
223
//-----------------------------------------------------------------------------
 
224
// MVideoPlayerUtilityObserver callbacks
 
225
//-----------------------------------------------------------------------------
 
226
 
 
227
void MMF::VideoPlayer::MvpuoOpenComplete(TInt aError)
 
228
{
 
229
    TRACE_CONTEXT(VideoPlayer::MvpuoOpenComplete, EVideoApi);
 
230
    TRACE_ENTRY("state %d error %d", state(), aError);
 
231
 
 
232
    __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic));
 
233
 
 
234
    if (KErrNone == aError)
 
235
        m_player->Prepare();
 
236
    else
 
237
        setError(NormalError);
 
238
 
 
239
    TRACE_EXIT_0();
 
240
}
 
241
 
 
242
void MMF::VideoPlayer::MvpuoPrepareComplete(TInt aError)
 
243
{
 
244
    TRACE_CONTEXT(VideoPlayer::MvpuoPrepareComplete, EVideoApi);
 
245
    TRACE_ENTRY("state %d error %d", state(), aError);
 
246
 
 
247
    __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic));
 
248
 
 
249
    TRAPD(err, doPrepareCompleteL(aError));
 
250
 
 
251
    if (KErrNone == err) {
 
252
        maxVolumeChanged(m_player->MaxVolume());
 
253
 
 
254
        if(m_videoOutput)
 
255
                m_videoOutput->setFrameSize(m_frameSize);
 
256
 
 
257
        // See comment in updateMmfOutput
 
258
        if(m_mmfOutputChangePending) {
 
259
            TRACE_0("MMF output change pending - pushing now");
 
260
            updateMmfOutput();
 
261
        }       
 
262
        
 
263
        emit totalTimeChanged(totalTime());
 
264
        changeState(StoppedState);
 
265
    } else {
 
266
        setError(NormalError);
 
267
    }
 
268
 
 
269
    TRACE_EXIT_0();
 
270
}
 
271
 
 
272
void MMF::VideoPlayer::doPrepareCompleteL(TInt aError)
 
273
{
 
274
    User::LeaveIfError(aError);
 
275
 
 
276
    // Get frame size
 
277
    TSize size;
 
278
    m_player->VideoFrameSizeL(size);
 
279
    m_frameSize = QSize(size.iWidth, size.iHeight);
 
280
 
 
281
    // Get duration
 
282
    m_totalTime = toMilliSeconds(m_player->DurationL());
 
283
}
 
284
 
 
285
 
 
286
void MMF::VideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
 
287
{
 
288
    TRACE_CONTEXT(VideoPlayer::MvpuoFrameReady, EVideoApi);
 
289
    TRACE_ENTRY("state %d error %d", state(), aError);
 
290
 
 
291
    // TODO
 
292
    Q_UNUSED(aFrame);
 
293
    Q_UNUSED(aError);   // suppress warnings in release builds
 
294
 
 
295
    TRACE_EXIT_0();
 
296
}
 
297
 
 
298
void MMF::VideoPlayer::MvpuoPlayComplete(TInt aError)
 
299
{
 
300
    TRACE_CONTEXT(VideoPlayer::MvpuoPlayComplete, EVideoApi)
 
301
    TRACE_ENTRY("state %d error %d", state(), aError);
 
302
 
 
303
    // TODO
 
304
    Q_UNUSED(aError);   // suppress warnings in release builds
 
305
 
 
306
    TRACE_EXIT_0();
 
307
}
 
308
 
 
309
void MMF::VideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
 
310
{
 
311
    TRACE_CONTEXT(VideoPlayer::MvpuoEvent, EVideoApi);
 
312
    TRACE_ENTRY("state %d", state());
 
313
 
 
314
    // TODO
 
315
    Q_UNUSED(aEvent);
 
316
 
 
317
    TRACE_EXIT_0();
 
318
}
 
319
 
 
320
 
 
321
//-----------------------------------------------------------------------------
 
322
// VideoOutputObserver
 
323
//-----------------------------------------------------------------------------
 
324
 
 
325
void MMF::VideoPlayer::videoOutputRegionChanged()
 
326
{
 
327
    TRACE_CONTEXT(VideoPlayer::videoOutputRegionChanged, EVideoInternal);
 
328
    TRACE_ENTRY("state %d", state());
 
329
 
 
330
    getNativeWindowSystemHandles();
 
331
 
 
332
    // See comment in updateMmfOutput
 
333
    if(state() == LoadingState)
 
334
        m_mmfOutputChangePending = true;
 
335
    else
 
336
        updateMmfOutput();
 
337
        
 
338
    TRACE_EXIT_0();
 
339
}
 
340
 
 
341
// DEBUGGING *** DO NOT INTEGRATE ***
 
342
class CDummyAO : public CActive
 
343
{
 
344
public:
 
345
        CDummyAO() : CActive(CActive::EPriorityStandard) { CActiveScheduler::Add(this); }
 
346
        void RunL() { }
 
347
        void DoCancel() { }
 
348
        TRequestStatus& Status() { return iStatus; }
 
349
        void SetActive() { CActive::SetActive(); }
 
350
};
 
351
 
 
352
// DEBUGGING *** DO NOT INTEGRATE ***
 
353
void getDsaRegion(RWsSession &session, const RWindowBase &window)
 
354
{
 
355
        RDirectScreenAccess dsa(session);
 
356
        TInt err = dsa.Construct();
 
357
        CDummyAO ao;
 
358
        RRegion* region;
 
359
        err = dsa.Request(region, ao.Status(), window);
 
360
        ao.SetActive();
 
361
        dsa.Close();
 
362
        ao.Cancel(); 
 
363
        if(region) {
 
364
                qDebug() << "Phonon::MMF::getDsaRegion count" << region->Count();
 
365
                for(int i=0; i<region->Count(); ++i) {
 
366
                        const TRect& rect = region->RectangleList()[i];
 
367
                        qDebug() << "Phonon::MMF::getDsaRegion rect" << rect.iTl.iX << rect.iTl.iY << rect.iBr.iX << rect.iBr.iY;
 
368
                }
 
369
                region->Close();
 
370
        }
 
371
}
 
372
 
 
373
void MMF::VideoPlayer::updateMmfOutput()
 
374
{
 
375
    TRACE_CONTEXT(VideoPlayer::updateMmfOutput, EVideoInternal);
 
376
    TRACE_ENTRY_0();
 
377
    
 
378
    // Calling SetDisplayWindowL is a no-op unless the MMF controller has 
 
379
    // been loaded, so we shouldn't do it.  Instead, the
 
380
    // m_mmfOutputChangePending flag is used to record the fact that we
 
381
    // need to call SetDisplayWindowL, and this is checked in 
 
382
    // MvpuoPrepareComplete, at which point the MMF controller has been
 
383
    // loaded.
 
384
    
 
385
    getNativeWindowSystemHandles();
 
386
    
 
387
// DEBUGGING *** DO NOT INTEGRATE ***
 
388
getDsaRegion(*m_wsSession, *m_window);
 
389
 
 
390
    TRAPD(err,
 
391
          m_player->SetDisplayWindowL
 
392
          (
 
393
              *m_wsSession, *m_screenDevice,
 
394
              *m_window,
 
395
              m_windowRect, m_clipRect
 
396
          )
 
397
         );
 
398
 
 
399
    if (KErrNone != err) {
 
400
        TRACE("SetDisplayWindowL error %d", err);
 
401
        setError(NormalError);
 
402
    }
 
403
    
 
404
    m_mmfOutputChangePending = false;
 
405
    
 
406
    TRACE_EXIT_0();
 
407
}
 
408
 
 
409
 
 
410
//-----------------------------------------------------------------------------
 
411
// Private functions
 
412
//-----------------------------------------------------------------------------
 
413
 
 
414
void MMF::VideoPlayer::videoOutputChanged()
 
415
{
 
416
    TRACE_CONTEXT(VideoPlayer::videoOutputChanged, EVideoInternal);
 
417
    TRACE_ENTRY_0();
 
418
 
 
419
    if(m_videoOutput) {
 
420
                m_videoOutput->setObserver(this);
 
421
                m_videoOutput->setFrameSize(m_frameSize);
 
422
    }
 
423
 
 
424
    videoOutputRegionChanged();
 
425
 
 
426
    TRACE_EXIT_0();
 
427
}
 
428
 
 
429
void MMF::VideoPlayer::getNativeWindowSystemHandles()
 
430
{
 
431
    TRACE_CONTEXT(VideoPlayer::getNativeWindowSystemHandles, EVideoInternal);
 
432
    TRACE_ENTRY_0();
 
433
    
 
434
    CCoeControl *control = 0;
 
435
    
 
436
    if(m_videoOutput)
 
437
        // Create native window
 
438
        control = m_videoOutput->winId();
 
439
    else
 
440
        // Get top-level window
 
441
        control = QApplication::activeWindow()->effectiveWinId();
 
442
 
 
443
    CCoeEnv* const coeEnv = control->ControlEnv();
 
444
    m_wsSession = &(coeEnv->WsSession());
 
445
    m_screenDevice = coeEnv->ScreenDevice();
 
446
    m_window = control->DrawableWindow();
 
447
 
 
448
#ifdef _DEBUG
 
449
    if(m_videoOutput) {
 
450
                QScopedPointer<ObjectDump::QDumper> dumper(new ObjectDump::QDumper);
 
451
                dumper->setPrefix("Phonon::MMF"); // to aid searchability of logs
 
452
                ObjectDump::addDefaultAnnotators(*dumper);
 
453
                TRACE_0("Dumping VideoOutput:");
 
454
                dumper->dumpObject(*m_videoOutput);
 
455
    }
 
456
    else {
 
457
        TRACE_0("m_videoOutput is null - dumping top-level control info:");
 
458
                TRACE("control %08x", control);
 
459
                TRACE("control.parent %08x", control->Parent());
 
460
                TRACE("control.isVisible %d", control->IsVisible());
 
461
                TRACE("control.rect %d,%d %dx%d",
 
462
                        control->Position().iX, control->Position().iY,
 
463
                        control->Size().iWidth, control->Size().iHeight);
 
464
                TRACE("control.ownsWindow %d", control->OwnsWindow());
 
465
    }
 
466
#endif
 
467
 
 
468
    m_windowRect = TRect(
 
469
        control->DrawableWindow()->AbsPosition(),
 
470
        control->DrawableWindow()->Size());
 
471
        m_clipRect = m_windowRect;
 
472
 
 
473
    TRACE("windowRect            %d %d - %d %d",
 
474
        m_windowRect.iTl.iX, m_windowRect.iTl.iY,
 
475
        m_windowRect.iBr.iX, m_windowRect.iBr.iY);
 
476
    TRACE("clipRect              %d %d - %d %d",
 
477
        m_clipRect.iTl.iX, m_clipRect.iTl.iY,
 
478
        m_clipRect.iBr.iX, m_clipRect.iBr.iY);
 
479
    
 
480
    TRACE_EXIT_0();
 
481
}
 
482
 
 
483
 
 
484
QT_END_NAMESPACE
 
485