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/* MuteSolo implementation */
18
19#include "sles_allinclusive.h"
20
21
22static SLresult IMuteSolo_SetChannelMute(SLMuteSoloItf self, SLuint8 chan, SLboolean mute)
23{
24    SL_ENTER_INTERFACE
25
26    IMuteSolo *thiz = (IMuteSolo *) self;
27    IObject *thisObject = thiz->mThis;
28    if (SL_OBJECTID_AUDIOPLAYER != IObjectToObjectID(thisObject)) {
29        result = SL_RESULT_FEATURE_UNSUPPORTED;
30    } else {
31        CAudioPlayer *ap = (CAudioPlayer *) thisObject;
32        interface_lock_exclusive(thiz);
33        SLuint8 numChannels = ap->mNumChannels;
34        if (1 >= numChannels) {
35            interface_unlock_exclusive(thiz);
36            result = SL_RESULT_FEATURE_UNSUPPORTED;
37        } else if (numChannels <= chan) {
38            interface_unlock_exclusive(thiz);
39            result = SL_RESULT_PARAMETER_INVALID;
40        } else {
41            SLuint8 mask = 1 << chan;
42            SLuint8 oldMuteMask = ap->mMuteMask;
43            if (mute) {
44                ap->mMuteMask |= mask;
45            } else {
46                ap->mMuteMask &= ~mask;
47            }
48            interface_unlock_exclusive_attributes(thiz, oldMuteMask != ap->mMuteMask ? ATTR_GAIN :
49                ATTR_NONE);
50            result = SL_RESULT_SUCCESS;
51        }
52    }
53
54    SL_LEAVE_INTERFACE
55}
56
57
58static SLresult IMuteSolo_GetChannelMute(SLMuteSoloItf self, SLuint8 chan, SLboolean *pMute)
59{
60    SL_ENTER_INTERFACE
61
62    if (NULL == pMute) {
63        result = SL_RESULT_PARAMETER_INVALID;
64    } else {
65        IMuteSolo *thiz = (IMuteSolo *) self;
66        IObject *thisObject = thiz->mThis;
67        if (SL_OBJECTID_AUDIOPLAYER != IObjectToObjectID(thisObject)) {
68            result = SL_RESULT_FEATURE_UNSUPPORTED;
69        } else {
70            CAudioPlayer *ap = (CAudioPlayer *) thisObject;
71            SLboolean mute;
72            interface_lock_shared(thiz);
73            SLuint8 numChannels = ap->mNumChannels;
74            if (1 >= numChannels) {
75                mute = SL_BOOLEAN_FALSE;
76                result = SL_RESULT_FEATURE_UNSUPPORTED;
77            } else if (numChannels <= chan) {
78                mute = SL_BOOLEAN_FALSE;
79                result = SL_RESULT_PARAMETER_INVALID;
80            } else {
81                SLuint8 mask = ap->mMuteMask;
82                mute = (SLboolean) ((mask >> chan) & 1);
83                result = SL_RESULT_SUCCESS;
84            }
85            interface_unlock_shared(thiz);
86            *pMute = mute;
87        }
88    }
89
90    SL_LEAVE_INTERFACE
91}
92
93
94static SLresult IMuteSolo_SetChannelSolo(SLMuteSoloItf self, SLuint8 chan, SLboolean solo)
95{
96    SL_ENTER_INTERFACE
97
98    IMuteSolo *thiz = (IMuteSolo *) self;
99    IObject *thisObject = thiz->mThis;
100    if (SL_OBJECTID_AUDIOPLAYER != IObjectToObjectID(thisObject)) {
101        result = SL_RESULT_FEATURE_UNSUPPORTED;
102    } else {
103        CAudioPlayer *ap = (CAudioPlayer *) thisObject;
104        interface_lock_exclusive(thiz);
105        SLuint8 numChannels = ap->mNumChannels;
106        if (1 >= numChannels) {
107            interface_unlock_exclusive(thiz);
108            result = SL_RESULT_FEATURE_UNSUPPORTED;
109        } else if (numChannels <= chan) {
110            interface_unlock_exclusive(thiz);
111            result = SL_RESULT_PARAMETER_INVALID;
112        } else {
113            SLuint8 mask = 1 << chan;
114            SLuint8 oldSoloMask = ap->mSoloMask;
115            if (solo) {
116                ap->mSoloMask |= mask;
117            } else {
118                ap->mSoloMask &= ~mask;
119            }
120            interface_unlock_exclusive_attributes(thiz, oldSoloMask != ap->mSoloMask ? ATTR_GAIN :
121                ATTR_NONE);
122            result = SL_RESULT_SUCCESS;
123        }
124    }
125
126    SL_LEAVE_INTERFACE
127}
128
129
130static SLresult IMuteSolo_GetChannelSolo(SLMuteSoloItf self, SLuint8 chan, SLboolean *pSolo)
131{
132    SL_ENTER_INTERFACE
133
134    if (NULL == pSolo) {
135        result = SL_RESULT_PARAMETER_INVALID;
136    } else {
137        IMuteSolo *thiz = (IMuteSolo *) self;
138        IObject *thisObject = thiz->mThis;
139        if (SL_OBJECTID_AUDIOPLAYER != IObjectToObjectID(thisObject)) {
140            result = SL_RESULT_FEATURE_UNSUPPORTED;
141        } else {
142            CAudioPlayer *ap = (CAudioPlayer *) thisObject;
143            SLboolean solo;
144            interface_lock_shared(thiz);
145            SLuint8 numChannels = ap->mNumChannels;
146            if (1 >= numChannels) {
147                solo = SL_BOOLEAN_FALSE;
148                result = SL_RESULT_FEATURE_UNSUPPORTED;
149            } else if (numChannels <= chan) {
150                solo = SL_BOOLEAN_FALSE;
151                result = SL_RESULT_PARAMETER_INVALID;
152            } else {
153                SLuint8 mask = ap->mSoloMask;
154                solo = (SLboolean) ((mask >> chan) & 1);
155                result = SL_RESULT_SUCCESS;
156            }
157            interface_unlock_shared(thiz);
158            *pSolo = solo;
159        }
160    }
161
162    SL_LEAVE_INTERFACE
163}
164
165
166static SLresult IMuteSolo_GetNumChannels(SLMuteSoloItf self, SLuint8 *pNumChannels)
167{
168    SL_ENTER_INTERFACE
169
170    if (NULL == pNumChannels) {
171        result = SL_RESULT_PARAMETER_INVALID;
172    } else {
173        IMuteSolo *thiz = (IMuteSolo *) self;
174        IObject *thisObject = thiz->mThis;
175        if (SL_OBJECTID_AUDIOPLAYER != IObjectToObjectID(thisObject)) {
176            result = SL_RESULT_FEATURE_UNSUPPORTED;
177        } else {
178            CAudioPlayer *ap = (CAudioPlayer *) thisObject;
179            object_lock_shared(thisObject);
180            SLuint8 numChannels = ap->mNumChannels;
181            object_unlock_shared(thisObject);
182            *pNumChannels = numChannels;
183            // spec errata says to return 0 (== UNKNOWN_NUMCHANNELS) if channel count is unknown
184            result = SL_RESULT_SUCCESS;
185        }
186    }
187
188    SL_LEAVE_INTERFACE
189}
190
191
192static const struct SLMuteSoloItf_ IMuteSolo_Itf = {
193    IMuteSolo_SetChannelMute,
194    IMuteSolo_GetChannelMute,
195    IMuteSolo_SetChannelSolo,
196    IMuteSolo_GetChannelSolo,
197    IMuteSolo_GetNumChannels
198};
199
200void IMuteSolo_init(void *self)
201{
202    IMuteSolo *thiz = (IMuteSolo *) self;
203    thiz->mItf = &IMuteSolo_Itf;
204}
205