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#include "sles_allinclusive.h"
18
19/* AudioIODeviceCapabilities implementation */
20
21// NTH make it platform-configurable
22
23
24static SLresult IAudioIODeviceCapabilities_GetAvailableAudioInputs(
25    SLAudioIODeviceCapabilitiesItf self, SLint32 *pNumInputs, SLuint32 *pInputDeviceIDs)
26{
27    SL_ENTER_INTERFACE
28
29    if (NULL == pNumInputs) {
30        result = SL_RESULT_PARAMETER_INVALID;
31    } else {
32        result = SL_RESULT_SUCCESS;
33        if (NULL != pInputDeviceIDs) {
34            if (1 > *pNumInputs) {
35                result = SL_RESULT_BUFFER_INSUFFICIENT;
36            } else {
37                pInputDeviceIDs[0] = SL_DEFAULTDEVICEID_AUDIOINPUT;
38            }
39        }
40        *pNumInputs = 1;
41    }
42
43    SL_LEAVE_INTERFACE
44}
45
46
47static SLresult IAudioIODeviceCapabilities_QueryAudioInputCapabilities(
48    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID, SLAudioInputDescriptor *pDescriptor)
49{
50    SL_ENTER_INTERFACE
51
52    if (NULL == pDescriptor) {
53        result = SL_RESULT_PARAMETER_INVALID;
54    } else {
55        result = SL_RESULT_SUCCESS;
56        switch (deviceID) {
57        case SL_DEFAULTDEVICEID_AUDIOINPUT:
58            *pDescriptor = *AudioInput_id_descriptors[0].descriptor;
59            break;
60        default:
61            result = SL_RESULT_IO_ERROR;
62            break;
63        }
64    }
65
66    SL_LEAVE_INTERFACE
67}
68
69
70static SLresult IAudioIODeviceCapabilities_RegisterAvailableAudioInputsChangedCallback(
71    SLAudioIODeviceCapabilitiesItf self, slAvailableAudioInputsChangedCallback callback,
72    void *pContext)
73{
74    SL_ENTER_INTERFACE
75
76    IAudioIODeviceCapabilities * thiz = (IAudioIODeviceCapabilities *) self;
77    interface_lock_exclusive(thiz);
78    thiz->mAvailableAudioInputsChangedCallback = callback;
79    thiz->mAvailableAudioInputsChangedContext = pContext;
80    interface_unlock_exclusive(thiz);
81    result = SL_RESULT_SUCCESS;
82
83    SL_LEAVE_INTERFACE
84}
85
86
87static SLresult IAudioIODeviceCapabilities_GetAvailableAudioOutputs(
88    SLAudioIODeviceCapabilitiesItf self, SLint32 *pNumOutputs, SLuint32 *pOutputDeviceIDs)
89{
90    SL_ENTER_INTERFACE
91
92    if (NULL == pNumOutputs) {
93        result = SL_RESULT_PARAMETER_INVALID;
94    } else {
95        result = SL_RESULT_SUCCESS;
96        if (NULL != pOutputDeviceIDs) {
97            if (2 > *pNumOutputs) {
98                result = SL_RESULT_BUFFER_INSUFFICIENT;
99                // if 1 slot available, should still fill that
100            } else {
101                pOutputDeviceIDs[0] = DEVICE_ID_HEADSET;
102                pOutputDeviceIDs[1] = DEVICE_ID_HANDSFREE;
103                // SL_DEFAULTDEVICEID_AUDIOOUTPUT?
104            }
105        }
106        *pNumOutputs = 2;
107    }
108
109    SL_LEAVE_INTERFACE
110}
111
112
113static SLresult IAudioIODeviceCapabilities_QueryAudioOutputCapabilities(
114    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID, SLAudioOutputDescriptor *pDescriptor)
115{
116    SL_ENTER_INTERFACE
117
118    if (NULL == pDescriptor) {
119        result = SL_RESULT_PARAMETER_INVALID;
120    } else {
121        result = SL_RESULT_SUCCESS;
122        switch (deviceID) {
123        case DEVICE_ID_HEADSET:
124            *pDescriptor = *AudioOutput_id_descriptors[1].descriptor;
125            break;
126        case DEVICE_ID_HANDSFREE:
127            *pDescriptor = *AudioOutput_id_descriptors[2].descriptor;
128            break;
129        // SL_DEFAULTDEVICEID_AUDIOOUTPUT?
130        default:
131            result = SL_RESULT_IO_ERROR;
132            break;
133        }
134    }
135
136    SL_LEAVE_INTERFACE
137}
138
139
140static SLresult IAudioIODeviceCapabilities_RegisterAvailableAudioOutputsChangedCallback(
141    SLAudioIODeviceCapabilitiesItf self, slAvailableAudioOutputsChangedCallback callback,
142    void *pContext)
143{
144    SL_ENTER_INTERFACE
145
146    IAudioIODeviceCapabilities * thiz = (IAudioIODeviceCapabilities *) self;
147    interface_lock_exclusive(thiz);
148    thiz->mAvailableAudioOutputsChangedCallback = callback;
149    thiz->mAvailableAudioOutputsChangedContext = pContext;
150    interface_unlock_exclusive(thiz);
151    result = SL_RESULT_SUCCESS;
152
153    SL_LEAVE_INTERFACE
154}
155
156
157static SLresult IAudioIODeviceCapabilities_RegisterDefaultDeviceIDMapChangedCallback(
158    SLAudioIODeviceCapabilitiesItf self, slDefaultDeviceIDMapChangedCallback callback,
159    void *pContext)
160{
161    SL_ENTER_INTERFACE
162
163    IAudioIODeviceCapabilities * thiz = (IAudioIODeviceCapabilities *) self;
164    interface_lock_exclusive(thiz);
165    thiz->mDefaultDeviceIDMapChangedCallback = callback;
166    thiz->mDefaultDeviceIDMapChangedContext = pContext;
167    interface_unlock_exclusive(thiz);
168    result = SL_RESULT_SUCCESS;
169
170    SL_LEAVE_INTERFACE
171}
172
173
174static SLresult IAudioIODeviceCapabilities_GetAssociatedAudioInputs(
175    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID,
176    SLint32 *pNumAudioInputs, SLuint32 *pAudioInputDeviceIDs)
177{
178    SL_ENTER_INTERFACE
179
180    if (NULL == pNumAudioInputs) {
181        result = SL_RESULT_PARAMETER_INVALID;
182    } else {
183        // Incomplete
184        *pNumAudioInputs = 0;
185        result = SL_RESULT_SUCCESS;
186    }
187
188    SL_LEAVE_INTERFACE
189}
190
191
192static SLresult IAudioIODeviceCapabilities_GetAssociatedAudioOutputs(
193    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID,
194    SLint32 *pNumAudioOutputs, SLuint32 *pAudioOutputDeviceIDs)
195{
196    SL_ENTER_INTERFACE
197
198    if (NULL == pNumAudioOutputs) {
199        result = SL_RESULT_PARAMETER_INVALID;
200    } else {
201        // Incomplete
202        *pNumAudioOutputs = 0;
203        result = SL_RESULT_SUCCESS;
204    }
205
206    SL_LEAVE_INTERFACE
207}
208
209
210static SLresult IAudioIODeviceCapabilities_GetDefaultAudioDevices(
211    SLAudioIODeviceCapabilitiesItf self, SLuint32 defaultDeviceID,
212    SLint32 *pNumAudioDevices, SLuint32 *pAudioDeviceIDs)
213{
214    SL_ENTER_INTERFACE
215
216    if (NULL == pNumAudioDevices) {
217        result = SL_RESULT_PARAMETER_INVALID;
218    } else {
219        switch (defaultDeviceID) {
220        case SL_DEFAULTDEVICEID_AUDIOINPUT:
221        case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
222            result = SL_RESULT_SUCCESS;
223            if (NULL != pAudioDeviceIDs) {
224                switch (defaultDeviceID) {
225                case SL_DEFAULTDEVICEID_AUDIOINPUT:
226                    if (1 > *pNumAudioDevices) {
227                        result = SL_RESULT_BUFFER_INSUFFICIENT;
228                    } else {
229                        pAudioDeviceIDs[0] = SL_DEFAULTDEVICEID_AUDIOINPUT;
230                    }
231                    *pNumAudioDevices = 1;
232                    break;
233                case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
234                    if (2 > *pNumAudioDevices) {
235                        result = SL_RESULT_BUFFER_INSUFFICIENT;
236                    } else {
237                        pAudioDeviceIDs[0] = DEVICE_ID_HEADSET;
238                        pAudioDeviceIDs[1] = DEVICE_ID_HANDSFREE;
239                        // should be capable of returning first item if 1 slot
240                    }
241                    *pNumAudioDevices = 2;
242                    break;
243                default:
244                    assert(SL_BOOLEAN_FALSE);
245                    *pNumAudioDevices = 0;
246                    break;
247                }
248            }
249            break;
250        default:
251            result = SL_RESULT_IO_ERROR;
252            break;
253        }
254    }
255
256    SL_LEAVE_INTERFACE
257}
258
259
260static SLresult IAudioIODeviceCapabilities_QuerySampleFormatsSupported(
261    SLAudioIODeviceCapabilitiesItf self, SLuint32 deviceID, SLmilliHertz samplingRate,
262    SLint32 *pSampleFormats, SLint32 *pNumOfSampleFormats)
263{
264    SL_ENTER_INTERFACE
265
266    if (NULL == pNumOfSampleFormats) {
267        result = SL_RESULT_PARAMETER_INVALID;
268    } else {
269        switch (deviceID) {
270        case SL_DEFAULTDEVICEID_AUDIOINPUT:
271        case SL_DEFAULTDEVICEID_AUDIOOUTPUT:
272            result = SL_RESULT_SUCCESS;
273            // incomplete
274            switch (samplingRate) {
275            case SL_SAMPLINGRATE_44_1:
276                break;
277            default:
278                result = SL_RESULT_IO_ERROR;
279                break;
280            }
281            if (NULL != pSampleFormats) {
282                if (1 > *pNumOfSampleFormats)
283                    result = SL_RESULT_BUFFER_INSUFFICIENT;
284                // incomplete
285                pSampleFormats[0] = SL_PCMSAMPLEFORMAT_FIXED_16;
286            }
287            *pNumOfSampleFormats = 1;
288            break;
289        default:
290            result = SL_RESULT_IO_ERROR;
291            break;
292        }
293    }
294
295    SL_LEAVE_INTERFACE
296}
297
298
299static const struct SLAudioIODeviceCapabilitiesItf_ IAudioIODeviceCapabilities_Itf = {
300    IAudioIODeviceCapabilities_GetAvailableAudioInputs,
301    IAudioIODeviceCapabilities_QueryAudioInputCapabilities,
302    IAudioIODeviceCapabilities_RegisterAvailableAudioInputsChangedCallback,
303    IAudioIODeviceCapabilities_GetAvailableAudioOutputs,
304    IAudioIODeviceCapabilities_QueryAudioOutputCapabilities,
305    IAudioIODeviceCapabilities_RegisterAvailableAudioOutputsChangedCallback,
306    IAudioIODeviceCapabilities_RegisterDefaultDeviceIDMapChangedCallback,
307    IAudioIODeviceCapabilities_GetAssociatedAudioInputs,
308    IAudioIODeviceCapabilities_GetAssociatedAudioOutputs,
309    IAudioIODeviceCapabilities_GetDefaultAudioDevices,
310    IAudioIODeviceCapabilities_QuerySampleFormatsSupported
311};
312
313void IAudioIODeviceCapabilities_init(void *self)
314{
315    IAudioIODeviceCapabilities *thiz = (IAudioIODeviceCapabilities *) self;
316    thiz->mItf = &IAudioIODeviceCapabilities_Itf;
317    thiz->mAvailableAudioInputsChangedCallback = NULL;
318    thiz->mAvailableAudioInputsChangedContext = NULL;
319    thiz->mAvailableAudioOutputsChangedCallback = NULL;
320    thiz->mAvailableAudioOutputsChangedContext = NULL;
321    thiz->mDefaultDeviceIDMapChangedCallback = NULL;
322    thiz->mDefaultDeviceIDMapChangedContext = NULL;
323}
324