66
|
1 |
/*
|
|
2 |
* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
* All rights reserved.
|
|
4 |
* This component and the accompanying materials are made available
|
|
5 |
* under the terms of "Eclipse Public License v1.0"
|
|
6 |
* which accompanies this distribution, and is available
|
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
*
|
|
9 |
* Initial Contributors:
|
|
10 |
* Nokia Corporation - initial contribution.
|
|
11 |
*
|
|
12 |
* Contributors:
|
|
13 |
*
|
|
14 |
* Description: This class is used for volume setting
|
|
15 |
*
|
|
16 |
*/
|
|
17 |
|
|
18 |
|
|
19 |
// INCLUDE FILES
|
|
20 |
#include "cmmaplayer.h"
|
|
21 |
#include "cmmavolumecontrol.h"
|
|
22 |
#include <jdebug.h>
|
|
23 |
#include <MProfile.h>
|
|
24 |
#include <MProfileEngine.h>
|
|
25 |
#include <CProfileChangeNotifyHandler.h>
|
|
26 |
|
|
27 |
_LIT(KMMAVolumeErrorMsg, "Can't set volume level");
|
|
28 |
|
|
29 |
const TInt KMMAJavaSoundIndex = 0;
|
|
30 |
const TInt KMMAProfileSoundIndex = 1;
|
|
31 |
const TInt KMMAGlobalVolumeSoundIndex = 2;
|
|
32 |
const TInt KAudioEarpiece = 3;
|
|
33 |
|
|
34 |
void CMMAVolumeControl::StaticSetLevelL(CMMAVolumeControl* aVolumeControl,
|
|
35 |
TInt aLevel)
|
|
36 |
{
|
|
37 |
// Java level is the first
|
|
38 |
aVolumeControl->SetVolumeLevelL(KMMAJavaSoundIndex, aLevel);
|
|
39 |
}
|
|
40 |
|
|
41 |
void CMMAVolumeControl::StaticGetLevelL(CMMAVolumeControl* aVolumeControl,
|
|
42 |
TInt* aLevel)
|
|
43 |
{
|
|
44 |
// Java level is the first
|
|
45 |
aVolumeControl->GetVolumeLevelL(KMMAJavaSoundIndex, aLevel);
|
|
46 |
}
|
|
47 |
|
|
48 |
|
|
49 |
EXPORT_C CMMAVolumeControl::CMMAVolumeControl(CMMAPlayer* aPlayer)
|
|
50 |
: iPlayer(aPlayer), iLevel(KMMAVolumeMaxLevel)
|
|
51 |
{
|
|
52 |
}
|
|
53 |
|
|
54 |
|
|
55 |
EXPORT_C CMMAVolumeControl::~CMMAVolumeControl()
|
|
56 |
{
|
|
57 |
delete iProfChangeNotifier;
|
|
58 |
iLevels.Close();
|
|
59 |
}
|
|
60 |
|
|
61 |
|
|
62 |
EXPORT_C void CMMAVolumeControl::ConstructBaseL()
|
|
63 |
{
|
|
64 |
iPlayer->AddStateListenerL(this);
|
|
65 |
|
|
66 |
// Add level for javasound, will set in StaticSetLevelL method.
|
|
67 |
SetJavaSoundVolumeLevelL();
|
|
68 |
|
|
69 |
SetProfileSoundVolumeLevelL();
|
|
70 |
|
|
71 |
// Sets level to 0 if profile isn't on
|
|
72 |
iLevel = CalculateLevel();
|
|
73 |
|
|
74 |
// The default value is not yet known. Volume control may change the
|
|
75 |
// volume of the controller before it has been retrieved so when the
|
|
76 |
// state of the player is changed the Java volume is retrieved from
|
|
77 |
// the controller.
|
|
78 |
iLevels[ KMMAJavaSoundIndex ] = KErrNotFound;
|
|
79 |
}
|
|
80 |
|
|
81 |
void CMMAVolumeControl::SetJavaSoundVolumeLevelL()
|
|
82 |
{
|
|
83 |
// In constructor iLevels array is empty and Java level will be the first,
|
|
84 |
// KMMAJavaSoundIndex.
|
|
85 |
AddLevelL();
|
|
86 |
}
|
|
87 |
|
|
88 |
void CMMAVolumeControl::SetProfileSoundVolumeLevelL()
|
|
89 |
{
|
|
90 |
// Add level for profile, level's index will be 1, KMMAProfileSoundIndex
|
|
91 |
AddLevelL();
|
|
92 |
}
|
|
93 |
|
|
94 |
void CMMAVolumeControl::SetProfilesBasedSoundMutingL()
|
|
95 |
{
|
|
96 |
//Get the current active profile id.
|
|
97 |
MProfileEngine* lProfileEngine = CreateProfileEngineL();
|
|
98 |
iProfileId =lProfileEngine->ActiveProfileId();
|
|
99 |
lProfileEngine->Release();
|
|
100 |
|
|
101 |
// if profile is silent or meeting and no headset or bluetooth device
|
|
102 |
// connected,set profile volume level to 0, otherwise keep the original
|
|
103 |
// value 100
|
|
104 |
if ( (EProfileSilentId == iProfileId || EProfileMeetingId == iProfileId)&&
|
|
105 |
iAudioOutputPreference != KAudioEarpiece )
|
|
106 |
{
|
|
107 |
iLevels[ KMMAProfileSoundIndex ] = 0;
|
|
108 |
}
|
|
109 |
|
|
110 |
// Gets notfication about profile changes
|
|
111 |
// Notification is sent to MProfileChangeObserver::HandleActiveProfileEventL()
|
|
112 |
iProfChangeNotifier = CProfileChangeNotifyHandler::NewL( this );
|
|
113 |
// Sets level to 0 if profile isn't on
|
|
114 |
iLevel = CalculateLevel();
|
|
115 |
|
|
116 |
}
|
|
117 |
EXPORT_C void CMMAVolumeControl::HandleActiveProfileEventL(
|
|
118 |
TProfileEvent aProfileEvent, TInt aProfileId)
|
|
119 |
{
|
|
120 |
switch (aProfileEvent)
|
|
121 |
{
|
|
122 |
case EProfileNewActiveProfile:
|
|
123 |
{
|
|
124 |
// New profile is activated
|
|
125 |
// Update the volume level, if profile is changed to silent or meeting
|
|
126 |
// then mute it, if no headset or bluetooth device is connected
|
|
127 |
// else set it to max volume level
|
|
128 |
TInt level = 0;
|
|
129 |
iProfileId = aProfileId;
|
|
130 |
|
|
131 |
if ( EProfileSilentId != aProfileId &&
|
|
132 |
EProfileMeetingId != aProfileId)
|
|
133 |
{
|
|
134 |
|
|
135 |
level = KMMAVolumeMaxLevel;
|
|
136 |
}
|
|
137 |
else if (iAudioOutputPreference == KAudioEarpiece)
|
|
138 |
{
|
|
139 |
level = KMMAVolumeMaxLevel;
|
|
140 |
}
|
|
141 |
else
|
|
142 |
{
|
|
143 |
level = 0;
|
|
144 |
}
|
|
145 |
TRAPD( error, SetVolumeLevelL( KMMAProfileSoundIndex, level ) );
|
|
146 |
if ( error != KErrNone )
|
|
147 |
{
|
|
148 |
iPlayer->PostStringEvent( CMMAPlayerEvent::EError,
|
|
149 |
KMMAVolumeErrorMsg );
|
|
150 |
}
|
|
151 |
break;
|
|
152 |
}
|
|
153 |
default: // do nothing
|
|
154 |
break;
|
|
155 |
}
|
|
156 |
}
|
|
157 |
|
|
158 |
|
|
159 |
|
|
160 |
EXPORT_C const TDesC& CMMAVolumeControl::ClassName() const
|
|
161 |
{
|
|
162 |
return KMMAVolumeControlName;
|
|
163 |
}
|
|
164 |
|
|
165 |
void CMMAVolumeControl::SetLevelL(TInt aLevel)
|
|
166 |
{
|
|
167 |
// Level cannot be set to derived control if player is not prefetched.
|
|
168 |
if (iPlayer->State() > CMMAPlayer::ERealized)
|
|
169 |
{
|
|
170 |
DoSetLevelL(aLevel);
|
|
171 |
}
|
|
172 |
iLevel = aLevel;
|
|
173 |
}
|
|
174 |
|
|
175 |
EXPORT_C void CMMAVolumeControl::StateChanged(TInt aState)
|
|
176 |
{
|
|
177 |
DEBUG_INT("CMMAVolumeControl::StateChanged - state %d", aState);
|
|
178 |
// Set the volume if the player is prefetched
|
|
179 |
if (aState == CMMAPlayer::EPrefetched)
|
|
180 |
{
|
|
181 |
TRAPD(error,
|
|
182 |
{
|
|
183 |
// Get the default value for the Java sound level
|
|
184 |
if (iLevels[ KMMAJavaSoundIndex ] == KErrNotFound)
|
|
185 |
{
|
|
186 |
iLevels[ KMMAJavaSoundIndex ] = DoGetLevelL();
|
|
187 |
iLevel = CalculateLevel();
|
|
188 |
}
|
|
189 |
SetLevelL(iLevel);
|
|
190 |
|
|
191 |
});
|
|
192 |
if (error != KErrNone)
|
|
193 |
{
|
|
194 |
iPlayer->PostStringEvent(CMMAPlayerEvent::EError,
|
|
195 |
KMMAVolumeErrorMsg);
|
|
196 |
}
|
|
197 |
}
|
|
198 |
|
|
199 |
// Level is already set for Global Volume so no need to set it again
|
|
200 |
// Notify the initial global volume value to java
|
|
201 |
// Notify only if STATE == CMMAPlayer::ERealized
|
|
202 |
// Error ID AKUR-7G69Q5 GLOBAL VOLUME EVENT CR
|
|
203 |
if (aState == CMMAPlayer::ERealized)
|
|
204 |
{
|
|
205 |
if ((iLevels.Count() - 1) == KMMAGlobalVolumeSoundIndex)
|
|
206 |
{
|
|
207 |
if ((iLevels[ KMMAGlobalVolumeSoundIndex ] != KErrNotFound) &&
|
|
208 |
(iLevels[ KMMAGlobalVolumeSoundIndex] != iInitialGlobalVolumeLevel))
|
|
209 |
{
|
|
210 |
DEBUG("MMA::CMMAVolumeControl::StateChanged : Post GLOBAL VOL EVENT ");
|
|
211 |
DEBUG_INT("MMA::CMMAVolumeControl::StateChanged : Post complete Val = %d ",
|
|
212 |
iLevels[ KMMAGlobalVolumeSoundIndex ]);
|
|
213 |
iPlayer->PostLongEvent(CMMAPlayerEvent::ENOKIA_EXTERNAL_VOLUME_EVENT,
|
|
214 |
iLevels[ KMMAGlobalVolumeSoundIndex ]);
|
|
215 |
}
|
|
216 |
}
|
|
217 |
}
|
|
218 |
}
|
|
219 |
|
|
220 |
EXPORT_C void CMMAVolumeControl::RefreshVolume()
|
|
221 |
{
|
|
222 |
DEBUG("MMA::CMMAVolumeControl::RefreshVolume ++ ");
|
|
223 |
TRAPD(error,
|
|
224 |
{
|
|
225 |
// Get the default value for the Java sound level
|
|
226 |
if (iLevels[ KMMAJavaSoundIndex ] == KErrNotFound)
|
|
227 |
{
|
|
228 |
iLevels[ KMMAJavaSoundIndex ] = DoGetLevelL();
|
|
229 |
iLevel = CalculateLevel();
|
|
230 |
}
|
|
231 |
SetLevelL(iLevel);
|
|
232 |
|
|
233 |
});
|
|
234 |
|
|
235 |
if (error != KErrNone)
|
|
236 |
{
|
|
237 |
iPlayer->PostStringEvent(CMMAPlayerEvent::EError,
|
|
238 |
KMMAVolumeErrorMsg);
|
|
239 |
}
|
|
240 |
DEBUG("MMA::CMMAVolumeControl::RefreshVolume -- ");
|
|
241 |
}
|
|
242 |
|
|
243 |
EXPORT_C void CMMAVolumeControl::RefreshControl()
|
|
244 |
{
|
|
245 |
RefreshVolume();
|
|
246 |
}
|
|
247 |
|
|
248 |
EXPORT_C TInt CMMAVolumeControl::AddLevelL()
|
|
249 |
{
|
|
250 |
User::LeaveIfError(iLevels.Append(KMMAVolumeMaxLevel));
|
|
251 |
|
|
252 |
// New level is the last element
|
|
253 |
return iLevels.Count() - 1;
|
|
254 |
}
|
|
255 |
|
|
256 |
EXPORT_C void CMMAVolumeControl::SetVolumeLevelL(TInt aLevelIndex,
|
|
257 |
TInt aVolumeLevel)
|
|
258 |
{
|
|
259 |
DEBUG_INT2("CMMAVolumeControl::SetVolumeLevelL - setting index %d, level %d",
|
|
260 |
aLevelIndex, aVolumeLevel);
|
|
261 |
if (0 >= iLevels.Count() || iLevels.Count() > 4)
|
|
262 |
{
|
|
263 |
return ;
|
|
264 |
}
|
|
265 |
TInt oldVolumeLevel = iLevels[ aLevelIndex ];
|
|
266 |
iLevels[ aLevelIndex ] = aVolumeLevel;
|
|
267 |
SetLevelL(CalculateLevel());
|
|
268 |
|
|
269 |
// send event if level is really changed
|
|
270 |
if ((aLevelIndex == KMMAJavaSoundIndex) &&
|
|
271 |
(aVolumeLevel != oldVolumeLevel))
|
|
272 |
{
|
|
273 |
iPlayer->PostObjectEvent(CMMAPlayerEvent::EVolumeChanged,
|
|
274 |
iControlObject);
|
|
275 |
}
|
|
276 |
|
|
277 |
// send event if global volume level is really changed
|
|
278 |
// Error ID AKUR-7G69Q5 GLOBAL VOLUME EVENT CR
|
|
279 |
if ((aLevelIndex == KMMAGlobalVolumeSoundIndex) &&
|
|
280 |
(aVolumeLevel != oldVolumeLevel))
|
|
281 |
{
|
|
282 |
|
|
283 |
iPlayer->PostLongEvent(CMMAPlayerEvent::ENOKIA_EXTERNAL_VOLUME_EVENT,
|
|
284 |
iLevels[ aLevelIndex ]);
|
|
285 |
}
|
|
286 |
}
|
|
287 |
|
|
288 |
void CMMAVolumeControl::InitializeGlobalVolumeLevel(TInt aGlobalVolumeLevel)
|
|
289 |
{
|
|
290 |
iInitialGlobalVolumeLevel = aGlobalVolumeLevel;
|
|
291 |
}
|
|
292 |
void CMMAVolumeControl::GetVolumeLevelL(TInt aLevelIndex,
|
|
293 |
TInt* aVolumeLevel)
|
|
294 |
{
|
|
295 |
DEBUG_INT("CMMAVolumeControl::GetVolumeLevelL - level index %d", aLevelIndex);
|
|
296 |
|
|
297 |
// Return max volume if the default Java volume level is not yet known
|
|
298 |
if (aLevelIndex == KMMAJavaSoundIndex &&
|
|
299 |
iLevels[ KMMAJavaSoundIndex ] == KErrNotFound)
|
|
300 |
{
|
|
301 |
*aVolumeLevel = KMMAVolumeMaxLevel;
|
|
302 |
return;
|
|
303 |
}
|
|
304 |
|
|
305 |
*aVolumeLevel = iLevels[ aLevelIndex ];
|
|
306 |
|
|
307 |
DEBUG_INT("CMMAVolumeControl::GetVolumeLevelL - level %d", *aVolumeLevel);
|
|
308 |
}
|
|
309 |
|
|
310 |
EXPORT_C void CMMAVolumeControl::SetAudioOutputPreferenceL(
|
|
311 |
TInt aRoutingPreference)
|
|
312 |
{
|
|
313 |
iAudioOutputPreference = aRoutingPreference;
|
|
314 |
// If audio o/p preference is set to private then set the profile sound
|
|
315 |
// to max value else if profile is in silent or meeting set the profile
|
|
316 |
// sound to 0
|
|
317 |
if ( iAudioOutputPreference == KAudioEarpiece)
|
|
318 |
{
|
|
319 |
SetVolumeLevelL(KMMAProfileSoundIndex, KMMAVolumeMaxLevel);
|
|
320 |
}
|
|
321 |
else if (EProfileSilentId == iProfileId || EProfileMeetingId == iProfileId)
|
|
322 |
{
|
|
323 |
SetVolumeLevelL(KMMAProfileSoundIndex, 0);
|
|
324 |
}
|
|
325 |
}
|
|
326 |
|
|
327 |
TInt CMMAVolumeControl::CalculateLevel()
|
|
328 |
{
|
|
329 |
TInt levelCount = iLevels.Count();
|
|
330 |
|
|
331 |
// 64 bit integer must be used to have more than 4 levels.
|
|
332 |
TInt64 level = KMMAVolumeMaxLevel;
|
|
333 |
TInt64 sum = 1;
|
|
334 |
|
|
335 |
// All levels in the array are percentage of the max volume (0..100).
|
|
336 |
// Actual sound level will be multiplying all levels.
|
|
337 |
for (TInt i = 0; i < levelCount; i++)
|
|
338 |
{
|
|
339 |
DEBUG_INT2("CMMAVolumeControl::CalculateLevel value at iLevels[ %d ] is %d",i,iLevels[i]);
|
|
340 |
// If the level is not known it is expected to be max volume
|
|
341 |
level = (iLevels[ i ] == KErrNotFound ?
|
|
342 |
level * KMMAVolumeMaxLevel :
|
|
343 |
level * iLevels[ i ]);
|
|
344 |
sum *= KMMAVolumeMaxLevel;
|
|
345 |
}
|
|
346 |
return level / sum;
|
|
347 |
}
|
|
348 |
// END OF FILE
|