1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* Volume implementation */
18
19#include "sles_allinclusive.h"
20
21
22static SLresult IVolume_SetVolumeLevel(SLVolumeItf self, SLmillibel level)
23{
24    SL_ENTER_INTERFACE
25
26    if (!((SL_MILLIBEL_MIN <= level) && (level <= PLATFORM_MILLIBEL_MAX_VOLUME))) {
27        result = SL_RESULT_PARAMETER_INVALID;
28    } else {
29        IVolume *thiz = (IVolume *) self;
30        interface_lock_exclusive(thiz);
31        SLmillibel oldLevel = thiz->mLevel;
32        if (oldLevel != level) {
33            thiz->mLevel = level;
34            interface_unlock_exclusive_attributes(thiz, ATTR_GAIN);
35        } else {
36            interface_unlock_exclusive(thiz);
37        }
38        result = SL_RESULT_SUCCESS;
39    }
40
41    SL_LEAVE_INTERFACE
42}
43
44
45static SLresult IVolume_GetVolumeLevel(SLVolumeItf self, SLmillibel *pLevel)
46{
47    SL_ENTER_INTERFACE
48
49    if (NULL == pLevel) {
50        result = SL_RESULT_PARAMETER_INVALID;
51    } else {
52        IVolume *thiz = (IVolume *) self;
53        interface_lock_shared(thiz);
54        SLmillibel level = thiz->mLevel;
55        interface_unlock_shared(thiz);
56        *pLevel = level;
57        result = SL_RESULT_SUCCESS;
58    }
59
60    SL_LEAVE_INTERFACE
61}
62
63
64static SLresult IVolume_GetMaxVolumeLevel(SLVolumeItf self, SLmillibel *pMaxLevel)
65{
66    SL_ENTER_INTERFACE
67
68    if (NULL == pMaxLevel) {
69        result = SL_RESULT_PARAMETER_INVALID;
70    } else {
71        *pMaxLevel = PLATFORM_MILLIBEL_MAX_VOLUME;
72        result = SL_RESULT_SUCCESS;
73    }
74
75    SL_LEAVE_INTERFACE
76}
77
78
79static SLresult IVolume_SetMute(SLVolumeItf self, SLboolean mute)
80{
81    SL_ENTER_INTERFACE
82
83    IVolume *thiz = (IVolume *) self;
84    mute = SL_BOOLEAN_FALSE != mute; // normalize
85    interface_lock_exclusive(thiz);
86    SLboolean oldMute = thiz->mMute;
87    if (oldMute != mute) {
88        thiz->mMute = (SLuint8) mute;
89        interface_unlock_exclusive_attributes(thiz, ATTR_GAIN);
90    } else {
91        interface_unlock_exclusive(thiz);
92    }
93    result = SL_RESULT_SUCCESS;
94
95    SL_LEAVE_INTERFACE
96}
97
98
99static SLresult IVolume_GetMute(SLVolumeItf self, SLboolean *pMute)
100{
101    SL_ENTER_INTERFACE
102
103    if (NULL == pMute) {
104        result = SL_RESULT_PARAMETER_INVALID;
105    } else {
106        IVolume *thiz = (IVolume *) self;
107        interface_lock_shared(thiz);
108        SLboolean mute = thiz->mMute;
109        interface_unlock_shared(thiz);
110        *pMute = mute;
111        result = SL_RESULT_SUCCESS;
112    }
113
114    SL_LEAVE_INTERFACE
115}
116
117
118static SLresult IVolume_EnableStereoPosition(SLVolumeItf self, SLboolean enable)
119{
120    SL_ENTER_INTERFACE
121
122    IVolume *thiz = (IVolume *) self;
123    enable = SL_BOOLEAN_FALSE != enable; // normalize
124    interface_lock_exclusive(thiz);
125    SLboolean oldEnable = thiz->mEnableStereoPosition;
126    if (oldEnable != enable) {
127        thiz->mEnableStereoPosition = (SLuint8) enable;
128        interface_unlock_exclusive_attributes(thiz, ATTR_GAIN);
129    } else {
130        interface_unlock_exclusive(thiz);
131    }
132    result = SL_RESULT_SUCCESS;
133
134    SL_LEAVE_INTERFACE
135}
136
137
138static SLresult IVolume_IsEnabledStereoPosition(SLVolumeItf self, SLboolean *pEnable)
139{
140    SL_ENTER_INTERFACE
141
142    if (NULL == pEnable) {
143        result = SL_RESULT_PARAMETER_INVALID;
144    } else {
145        IVolume *thiz = (IVolume *) self;
146        interface_lock_shared(thiz);
147        SLboolean enable = thiz->mEnableStereoPosition;
148        interface_unlock_shared(thiz);
149        *pEnable = enable;
150        result = SL_RESULT_SUCCESS;
151    }
152
153    SL_LEAVE_INTERFACE
154}
155
156
157static SLresult IVolume_SetStereoPosition(SLVolumeItf self, SLpermille stereoPosition)
158{
159    SL_ENTER_INTERFACE
160
161    if (!((-1000 <= stereoPosition) && (1000 >= stereoPosition))) {
162        result = SL_RESULT_PARAMETER_INVALID;
163    } else {
164        IVolume *thiz = (IVolume *) self;
165        interface_lock_exclusive(thiz);
166        SLpermille oldStereoPosition = thiz->mStereoPosition;
167        if (oldStereoPosition != stereoPosition) {
168            thiz->mStereoPosition = stereoPosition;
169            interface_unlock_exclusive_attributes(thiz, ATTR_GAIN);
170        } else {
171            interface_unlock_exclusive(thiz);
172        }
173        result = SL_RESULT_SUCCESS;
174    }
175
176    SL_LEAVE_INTERFACE
177}
178
179
180static SLresult IVolume_GetStereoPosition(SLVolumeItf self, SLpermille *pStereoPosition)
181{
182    SL_ENTER_INTERFACE
183
184    if (NULL == pStereoPosition) {
185        result = SL_RESULT_PARAMETER_INVALID;
186    } else {
187        IVolume *thiz = (IVolume *) self;
188        interface_lock_shared(thiz);
189        SLpermille stereoPosition = thiz->mStereoPosition;
190        interface_unlock_shared(thiz);
191        *pStereoPosition = stereoPosition;
192        result = SL_RESULT_SUCCESS;
193    }
194
195    SL_LEAVE_INTERFACE
196}
197
198
199static const struct SLVolumeItf_ IVolume_Itf = {
200    IVolume_SetVolumeLevel,
201    IVolume_GetVolumeLevel,
202    IVolume_GetMaxVolumeLevel,
203    IVolume_SetMute,
204    IVolume_GetMute,
205    IVolume_EnableStereoPosition,
206    IVolume_IsEnabledStereoPosition,
207    IVolume_SetStereoPosition,
208    IVolume_GetStereoPosition
209};
210
211void IVolume_init(void *self)
212{
213    IVolume *thiz = (IVolume *) self;
214    thiz->mItf = &IVolume_Itf;
215    thiz->mLevel = 0;
216    thiz->mMute = SL_BOOLEAN_FALSE;
217    thiz->mEnableStereoPosition = SL_BOOLEAN_FALSE;
218    thiz->mStereoPosition = 0;
219}
220