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 <QDir>
20
#include <QUrl>
21
22
#include "audioplayer.h"
23
#include "utils.h"
24
25
QT_BEGIN_NAMESPACE
26
27
using namespace Phonon;
28
using namespace Phonon::MMF;
29
30
/*! \class MMF::AudioPlayer
31
  \internal
32
*/
33
34
//-----------------------------------------------------------------------------
35
// Constructor / destructor
36
//-----------------------------------------------------------------------------
37
38
MMF::AudioPlayer::AudioPlayer(MediaObject *parent, const AbstractPlayer *player)
39
        :   AbstractMediaPlayer(parent, player)
40
        ,   m_totalTime(0)
41
{
42
    construct();
43
}
44
45
void MMF::AudioPlayer::construct()
46
{
47
    TRACE_CONTEXT(AudioPlayer::AudioPlayer, EAudioApi);
48
    TRACE_ENTRY_0();
49
50
    NativePlayer *player = 0;
51
    QT_TRAP_THROWING(player = NativePlayer::NewL(*this, 0, EMdaPriorityPreferenceNone));
52
    m_player.reset(player);
53
    m_player->RegisterForAudioLoadingNotification(*this);
54
55
    TRACE_EXIT_0();
56
}
57
58
MMF::AudioPlayer::~AudioPlayer()
59
{
60
    TRACE_CONTEXT(AudioPlayer::~AudioPlayer, EAudioApi);
61
    TRACE_ENTRY_0();
62
63
    TRACE_EXIT_0();
64
}
65
66
MMF::AudioPlayer::NativePlayer *MMF::AudioPlayer::nativePlayer() const
67
{
68
    return m_player.data();
69
}
70
71
//-----------------------------------------------------------------------------
72
// Public API
73
//-----------------------------------------------------------------------------
74
75
void MMF::AudioPlayer::doPlay()
76
{
77
    m_player->Play();
78
}
79
80
void MMF::AudioPlayer::doPause()
81
{
82
    m_player->Pause();
83
}
84
85
void MMF::AudioPlayer::doStop()
86
{
87
    m_player->Stop();
88
}
89
90
void MMF::AudioPlayer::doSeek(qint64 ms)
91
{
92
    m_player->SetPosition(TTimeIntervalMicroSeconds(ms * 1000));
93
}
94
95
int MMF::AudioPlayer::setDeviceVolume(int mmfVolume)
96
{
97
    /* In SDK 3.1, SetVolume() returns void. If we're compiling against
98
     * 3.1, we handle it with ifdefs. However, if we compile against a later
99
     * SDK but are _running_ against 3.1, we avoid returning from an undefined
100
     * stack by doing a runtime check of the SDK version. */
101
#if !defined(__SERIES60_31__)
102
    const int err = m_player->SetVolume(mmfVolume);
103
    if (QSysInfo::s60Version() >= QSysInfo::SV_S60_3_2)
104
        return err;
105
    else
106
        return KErrNone;
107
 #else
108
     m_player->SetVolume(mmfVolume);
109
     return KErrNone;
110
#endif
111
}
112
113
int MMF::AudioPlayer::openFile(const QString &fileName)
114
{
115
    const QHBufC nativeFileName(QDir::toNativeSeparators(fileName));
116
    TRAPD(err, m_player->OpenFileL(*nativeFileName));
117
    return err;
118
}
119
120
int MMF::AudioPlayer::openFile(RFile& file)
121
{
122
    TRAPD(err, m_player->OpenFileL(file));
123
124
#ifdef QT_PHONON_MMF_AUDIO_DRM
125
    if (KErrNone == err) {
126
        // There appears to be a bug in the CDrmPlayerUtility implementation (at least
127
        // in S60 5.x) whereby the player does not check whether the loading observer
128
        // pointer is null before dereferencing it.  Therefore we must register for
129
        // loading notification, even though we do nothing in the callback functions.
130
        m_player->RegisterForAudioLoadingNotification(*this);
131
    }
132
#endif
133
134
    return err;
135
}
136
137
int MMF::AudioPlayer::openUrl(const QString& /*url*/, int /*iap*/)
138
{
139
    // Streaming playback is generally not supported by the implementation
140
    // of the audio player API, so we use CVideoPlayerUtility for both
141
    // audio and video streaming.
142
    Utils::panic(AudioUtilityUrlNotSupported);
143
144
    // Silence warning
145
    return 0;
146
}
147
148
int MMF::AudioPlayer::openDescriptor(const TDesC8 &des)
149
{
150
    TRAPD(err, m_player->OpenDesL(des));
151
    return err;
152
}
153
154
int MMF::AudioPlayer::bufferStatus() const
155
{
156
    int result = 0;
157
    TRAP_IGNORE(m_player->GetAudioLoadingProgressL(result));
158
    return result;
159
}
160
161
void MMF::AudioPlayer::doClose()
162
{
163
    m_player->Close();
164
}
165
166
bool MMF::AudioPlayer::hasVideo() const
167
{
168
    return false;
169
}
170
171
qint64 MMF::AudioPlayer::getCurrentTime() const
172
{
173
    TRACE_CONTEXT(AudioPlayer::getCurrentTime, EAudioApi);
174
175
    TTimeIntervalMicroSeconds us;
176
    const TInt err = m_player->GetPosition(us);
177
178
    qint64 result = 0;
179
180
    if (KErrNone == err) {
181
        result = toMilliSeconds(us);
182
    } else {
183
        TRACE("GetPosition err %d", err);
184
185
        // If we don't cast away constness here, we simply have to ignore
186
        // the error.
187
        const_cast<AudioPlayer*>(this)->setError(tr("Getting position failed"), err);
188
    }
189
190
    return result;
191
}
192
193
qint64 MMF::AudioPlayer::totalTime() const
194
{
195
    return m_totalTime;
196
}
197
198
199
//-----------------------------------------------------------------------------
200
// Symbian multimedia client observer callbacks
201
//-----------------------------------------------------------------------------
202
203
#ifdef QT_PHONON_MMF_AUDIO_DRM
204
void MMF::AudioPlayer::MdapcInitComplete(TInt aError,
205
        const TTimeIntervalMicroSeconds &)
206
#else
207
void MMF::AudioPlayer::MapcInitComplete(TInt aError,
208
                                        const TTimeIntervalMicroSeconds &)
209
#endif
210
{
211
    TRACE_CONTEXT(AudioPlayer::MapcInitComplete, EAudioInternal);
212
    TRACE_ENTRY("state %d error %d", state(), aError);
213
214
    __ASSERT_ALWAYS(LoadingState == state() ||
215
                    progressiveDownloadStalled() && BufferingState == state(),
216
                    Utils::panic(InvalidStatePanic));
217
218
    if (KErrNone == aError) {
219
        maxVolumeChanged(m_player->MaxVolume());
220
        m_totalTime = toMilliSeconds(m_player->Duration());
221
        emit totalTimeChanged(m_totalTime);
222
    }
223
224
    loadingComplete(aError);
225
226
    TRACE_EXIT_0();
227
}
228
229
#ifdef QT_PHONON_MMF_AUDIO_DRM
230
void MMF::AudioPlayer::MdapcPlayComplete(TInt aError)
231
#else
232
void MMF::AudioPlayer::MapcPlayComplete(TInt aError)
233
#endif
234
{
235
    TRACE_CONTEXT(AudioPlayer::MapcPlayComplete, EAudioInternal);
236
    TRACE_ENTRY("state %d error %d", state(), aError);
237
238
    // Call base class function which handles end of playback for both
239
    // audio and video clips.
240
    playbackComplete(aError);
241
242
    TRACE_EXIT_0();
243
}
244
245
#ifdef QT_PHONON_MMF_AUDIO_DRM
246
void MMF::AudioPlayer::MaloLoadingStarted()
247
{
248
249
}
250
251
void MMF::AudioPlayer::MaloLoadingComplete()
252
{
253
254
}
255
#endif // QT_PHONON_MMF_AUDIO_DRM
256
257
258
//-----------------------------------------------------------------------------
259
// MAudioLoadingObserver callbacks
260
//-----------------------------------------------------------------------------
261
262
void MMF::AudioPlayer::MaloLoadingStarted()
263
{
264
    bufferingStarted();
265
}
266
267
void MMF::AudioPlayer::MaloLoadingComplete()
268
{
269
    bufferingComplete();
270
}
271
272
273
//-----------------------------------------------------------------------------
274
// Private functions
275
//-----------------------------------------------------------------------------
276
277
int MMF::AudioPlayer::numberOfMetaDataEntries() const
278
{
279
    int numberOfEntries = 0;
280
    m_player->GetNumberOfMetaDataEntries(numberOfEntries); // ignoring return code
281
    return numberOfEntries;
282
}
283
284
QPair<QString, QString> MMF::AudioPlayer::metaDataEntry(int index) const
285
{
286
    CMMFMetaDataEntry *entry = 0;
287
    QT_TRAP_THROWING(entry = m_player->GetMetaDataEntryL(index));
288
    return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value()));
289
}
290
291
292
QT_END_NAMESPACE