OSDN Git Service

change libasound to be a shared library
[android-x86/hardware-alsa_sound.git] / AudioHardwareALSA.cpp
1 /* AudioHardwareALSA.cpp
2  **
3  ** Copyright 2008-2009 Wind River Systems
4  **
5  ** Licensed under the Apache License, Version 2.0 (the "License");
6  ** you may not use this file except in compliance with the License.
7  ** You may obtain a copy of the License at
8  **
9  **     http://www.apache.org/licenses/LICENSE-2.0
10  **
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  */
17
18 #include <errno.h>
19 #include <stdarg.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <dlfcn.h>
25
26 #define LOG_TAG "AudioHardwareALSA"
27 #include <utils/Log.h>
28 #include <utils/String8.h>
29
30 #include <cutils/properties.h>
31 #include <media/AudioRecord.h>
32 #include <hardware_legacy/power.h>
33
34 #include "AudioHardwareALSA.h"
35
36 #undef DISABLE_HARWARE_RESAMPLING
37
38 #ifndef ALSA_DEFAULT_SAMPLE_RATE
39 #define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
40 #endif
41
42 #define SND_MIXER_VOL_RANGE_MIN  (0)
43 #define SND_MIXER_VOL_RANGE_MAX  (100)
44
45 #define ALSA_NAME_MAX 128
46
47 #define ALSA_STRCAT(x,y) \
48     if (strlen(x) + strlen(y) < ALSA_NAME_MAX) \
49         strcat(x, y);
50
51 extern "C"
52 {
53     //
54     // Make sure this prototype is consistent with what's in
55     // external/libasound/alsa-lib-1.0.16/src/pcm/pcm_null.c!
56     //
57     extern int snd_pcm_null_open(snd_pcm_t **pcmp,
58                                  const char *name,
59                                  snd_pcm_stream_t stream,
60                                  int mode);
61
62     //
63     // Function for dlsym() to look up for creating a new AudioHardwareInterface.
64     //
65     android::AudioHardwareInterface *createAudioHardware(void) {
66         return new android::AudioHardwareALSA();
67     }
68 }         // extern "C"
69
70 namespace android
71 {
72
73 typedef AudioSystem::audio_routes audio_routes;
74
75 #define ROUTE_ALL            AudioSystem::ROUTE_ALL
76 #define ROUTE_EARPIECE       AudioSystem::ROUTE_EARPIECE
77 #define ROUTE_SPEAKER        AudioSystem::ROUTE_SPEAKER
78 #define ROUTE_BLUETOOTH_SCO  AudioSystem::ROUTE_BLUETOOTH_SCO
79 #define ROUTE_HEADSET        AudioSystem::ROUTE_HEADSET
80 #define ROUTE_BLUETOOTH_A2DP AudioSystem::ROUTE_BLUETOOTH_A2DP
81 #ifdef FM_ROUTE_SUPPORT
82 #define ROUTE_FM             AudioSystem::ROUTE_FM
83 #endif
84
85 // ----------------------------------------------------------------------------
86
87 static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
88
89 static const char _nullALSADeviceName[] = "NULL_Device";
90
91 static void ALSAErrorHandler(const char *file,
92                              int line,
93                              const char *function,
94                              int err,
95                              const char *fmt,
96                              ...)
97 {
98     char buf[BUFSIZ];
99     va_list arg;
100     int l;
101
102     va_start(arg, fmt);
103     l = snprintf(buf, BUFSIZ, "%s:%i:(%s) ", file, line, function);
104     vsnprintf(buf + l, BUFSIZ - l, fmt, arg);
105     buf[BUFSIZ-1] = '\0';
106     LOG(LOG_ERROR, "ALSALib", buf);
107     va_end(arg);
108 }
109
110 // ----------------------------------------------------------------------------
111
112 /* The following table(s) need to match in order of the route bits
113  */
114 static const char *deviceSuffix[] = {
115     /* ROUTE_EARPIECE       */ "_Earpiece",
116     /* ROUTE_SPEAKER        */ "_Speaker",
117     /* ROUTE_BLUETOOTH_SCO  */ "_Bluetooth",
118     /* ROUTE_HEADSET        */ "_Headset",
119     /* ROUTE_BLUETOOTH_A2DP */ "_Bluetooth-A2DP",
120 #ifdef FM_ROUTE_SUPPORT
121     /* ROUTE_FM             */ "_FM",
122 #endif
123 };
124
125 static const int deviceSuffixLen = (sizeof(deviceSuffix) / sizeof(char *));
126
127 struct mixer_info_t;
128
129 struct alsa_properties_t
130 {
131     const audio_routes  routes;
132     const char         *propName;
133     const char         *propDefault;
134     mixer_info_t       *mInfo;
135 };
136
137 static alsa_properties_t
138 mixerMasterProp[SND_PCM_STREAM_LAST+1] = {
139     { ROUTE_ALL, "alsa.mixer.playback.master",  "PCM",     NULL},
140     { ROUTE_ALL, "alsa.mixer.capture.master",   "Capture", NULL}
141 };
142
143 static alsa_properties_t
144 mixerProp[][SND_PCM_STREAM_LAST+1] = {
145     {
146         {ROUTE_EARPIECE,       "alsa.mixer.playback.earpiece",       "Earpiece", NULL},
147         {ROUTE_EARPIECE,       "alsa.mixer.capture.earpiece",        "Capture",  NULL}
148     },
149     {
150         {ROUTE_SPEAKER,        "alsa.mixer.playback.speaker",        "Speaker", NULL},
151         {ROUTE_SPEAKER,        "alsa.mixer.capture.speaker",         "",        NULL}
152     },
153     {
154         {ROUTE_BLUETOOTH_SCO,  "alsa.mixer.playback.bluetooth.sco",  "Bluetooth",         NULL},
155         {ROUTE_BLUETOOTH_SCO,  "alsa.mixer.capture.bluetooth.sco",   "Bluetooth Capture", NULL}
156     },
157     {
158         {ROUTE_HEADSET,        "alsa.mixer.playback.headset",        "Headphone", NULL},
159         {ROUTE_HEADSET,        "alsa.mixer.capture.headset",         "Capture",   NULL}
160     },
161     {
162         {ROUTE_BLUETOOTH_A2DP, "alsa.mixer.playback.bluetooth.a2dp", "Bluetooth A2DP",         NULL},
163         {ROUTE_BLUETOOTH_A2DP, "alsa.mixer.capture.bluetooth.a2dp",  "Bluetooth A2DP Capture", NULL}
164     },
165 #ifdef FM_ROUTE_SUPPORT
166     {
167         {ROUTE_FM,             "alsa.mixer.playback.fm",             "FM", NULL},
168         {ROUTE_FM,             "alsa.mixer.capture.fm",              "",   NULL}
169     },
170 #endif
171     {
172         {static_cast<audio_routes>(0), NULL, NULL, NULL},
173         {static_cast<audio_routes>(0), NULL, NULL, NULL}
174     }
175 };
176
177 // ----------------------------------------------------------------------------
178
179 AudioHardwareALSA::AudioHardwareALSA() :
180     mOutput(0),
181     mInput(0),
182     mAcousticDevice(0)
183 {
184     snd_lib_error_set_handler(&ALSAErrorHandler);
185     mMixer = new ALSAMixer;
186
187     hw_module_t *module;
188     int err = hw_get_module(ACOUSTICS_HARDWARE_MODULE_ID,
189             (hw_module_t const**)&module);
190
191     if (err == 0) {
192         hw_device_t* device;
193         err = module->methods->open(module, ACOUSTICS_HARDWARE_NAME, &device);
194         if (err == 0) {
195             mAcousticDevice = (acoustic_device_t *)device;
196         }
197     }
198 }
199
200 AudioHardwareALSA::~AudioHardwareALSA()
201 {
202     if (mOutput) delete mOutput;
203     if (mInput) delete mInput;
204     if (mMixer) delete mMixer;
205     if (mAcousticDevice)
206         mAcousticDevice->common.close(&mAcousticDevice->common);
207 }
208
209 status_t AudioHardwareALSA::initCheck()
210 {
211     if (mMixer && mMixer->isValid())
212         return NO_ERROR;
213     else
214         return NO_INIT;
215 }
216
217 status_t AudioHardwareALSA::setVoiceVolume(float volume)
218 {
219     // The voice volume is used by the VOICE_CALL audio stream.
220     if (mMixer)
221         return mMixer->setVolume(ROUTE_EARPIECE, volume);
222     else
223         return INVALID_OPERATION;
224 }
225
226 status_t AudioHardwareALSA::setMasterVolume(float volume)
227 {
228     if (mMixer)
229         return mMixer->setMasterVolume(volume);
230     else
231         return INVALID_OPERATION;
232 }
233
234 AudioStreamOut *
235 AudioHardwareALSA::openOutputStream(int format,
236                                     int channelCount,
237                                     uint32_t sampleRate,
238                                     status_t *status)
239 {
240     AutoMutex lock(mLock);
241
242     // only one output stream allowed
243     if (mOutput) {
244         *status = ALREADY_EXISTS;
245         return 0;
246     }
247
248     AudioStreamOutALSA *out = new AudioStreamOutALSA(this);
249
250     *status = out->set(format, channelCount, sampleRate);
251
252     if (*status == NO_ERROR) {
253         mOutput = out;
254         // Some information is expected to be available immediately after
255         // the device is open.
256         *status = mOutput->setDevice(mMode, mRoutes[mMode]);
257     }
258     else {
259         delete out;
260     }
261
262     return mOutput;
263 }
264
265 AudioStreamIn *
266 AudioHardwareALSA::openInputStream(int      inputSource,
267                                    int      format,
268                                    int      channelCount,
269                                    uint32_t sampleRate,
270                                    status_t *status,
271                                    AudioSystem::audio_in_acoustics acoustics)
272 {
273     // check for valid input source
274     if ((inputSource < AudioRecord::DEFAULT_INPUT) ||
275         (inputSource >= AudioRecord::NUM_INPUT_SOURCES)) {
276         return 0;
277     }
278
279     AutoMutex lock(mLock);
280
281     // only one input stream allowed
282     if (mInput) {
283         *status = ALREADY_EXISTS;
284         return 0;
285     }
286
287     AudioStreamInALSA *in = new AudioStreamInALSA(this, acoustics);
288
289     *status = in->set(format, channelCount, sampleRate);
290     if (*status == NO_ERROR) {
291         mInput = in;
292         // Some information is expected to be available immediately after
293         // the device is open.
294         *status = mInput->setDevice(mMode, mRoutes[mMode]);
295     }
296     else {
297         delete in;
298     }
299
300     return mInput;
301 }
302
303 status_t AudioHardwareALSA::doRouting()
304 {
305     AutoMutex lock(mLock);
306
307     if (!mOutput)
308         return NO_INIT;
309
310     return mOutput->setDevice(mMode, mRoutes[mMode]);
311 }
312
313 status_t AudioHardwareALSA::setMicMute(bool state)
314 {
315     if (mMixer)
316         return mMixer->setCaptureMuteState(ROUTE_EARPIECE, state);
317
318     return NO_INIT;
319 }
320
321 status_t AudioHardwareALSA::getMicMute(bool *state)
322 {
323     if (mMixer)
324         return mMixer->getCaptureMuteState(ROUTE_EARPIECE, state);
325
326     return NO_ERROR;
327 }
328
329 status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
330 {
331     return NO_ERROR;
332 }
333
334 // ----------------------------------------------------------------------------
335
336 ALSAStreamOps::ALSAStreamOps(AudioHardwareALSA *parent) :
337     mParent(parent),
338     mHandle(0),
339     mHardwareParams(0),
340     mSoftwareParams(0),
341     mMode(-1),
342     mDevice(0),
343     mPowerLock(false)
344 {
345     if (snd_pcm_hw_params_malloc(&mHardwareParams) < 0) {
346         LOG_ALWAYS_FATAL("Failed to allocate ALSA hardware parameters!");
347     }
348
349     if (snd_pcm_sw_params_malloc(&mSoftwareParams) < 0) {
350         LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
351     }
352 }
353
354 ALSAStreamOps::~ALSAStreamOps()
355 {
356     AutoMutex lock(mLock);
357
358     close();
359
360     if (mHardwareParams)
361         snd_pcm_hw_params_free(mHardwareParams);
362
363     if (mSoftwareParams)
364         snd_pcm_sw_params_free(mSoftwareParams);
365 }
366
367 status_t ALSAStreamOps::set(int      format,
368                             int      channels,
369                             uint32_t rate)
370 {
371     if (channels > 0)
372         mDefaults->channels = channels;
373
374     if (rate > 0)
375         mDefaults->sampleRate = rate;
376
377     switch(format) {
378       // format == 0
379         case AudioSystem::DEFAULT:
380             break;
381
382         case AudioSystem::PCM_16_BIT:
383             mDefaults->format = SND_PCM_FORMAT_S16_LE;
384             break;
385
386         case AudioSystem::PCM_8_BIT:
387             mDefaults->format = SND_PCM_FORMAT_S8;
388             break;
389
390         default:
391             LOGE("Unknown PCM format %i. Forcing default", format);
392             break;
393     }
394
395     return NO_ERROR;
396 }
397
398 uint32_t ALSAStreamOps::sampleRate() const
399 {
400     unsigned int rate;
401     int err;
402
403     if (!mHandle)
404         return mDefaults->sampleRate;
405
406     return snd_pcm_hw_params_get_rate(mHardwareParams, &rate, 0) < 0
407         ? 0 : static_cast<uint32_t>(rate);
408 }
409
410 status_t ALSAStreamOps::sampleRate(uint32_t rate)
411 {
412     const char *stream;
413     unsigned int requestedRate;
414     int err;
415
416     if (!mHandle)
417         return NO_INIT;
418
419     stream = streamName();
420     requestedRate = rate;
421     err = snd_pcm_hw_params_set_rate_near(mHandle,
422                                           mHardwareParams,
423                                           &requestedRate,
424                                           0);
425
426     if (err < 0) {
427         LOGE("Unable to set %s sample rate to %u: %s",
428             stream, rate, snd_strerror(err));
429         return BAD_VALUE;
430     }
431     if (requestedRate != rate) {
432         // Some devices have a fixed sample rate, and can not be changed.
433         // This may cause resampling problems; i.e. PCM playback will be too
434         // slow or fast.
435         LOGW("Requested rate (%u HZ) does not match actual rate (%u HZ)",
436             rate, requestedRate);
437     }
438     else {
439         LOGV("Set %s sample rate to %u HZ", stream, requestedRate);
440     }
441     return NO_ERROR;
442 }
443
444 //
445 // Return the number of bytes (not frames)
446 //
447 size_t ALSAStreamOps::bufferSize() const
448 {
449     if (!mHandle)
450         return NO_INIT;
451
452     snd_pcm_uframes_t bufferSize = 0;
453     snd_pcm_uframes_t periodSize = 0;
454     int err;
455
456     err = snd_pcm_get_params(mHandle, &bufferSize, &periodSize);
457
458     if (err < 0)
459         return -1;
460
461     size_t bytes = static_cast<size_t>(snd_pcm_frames_to_bytes(mHandle, bufferSize));
462
463     // Not sure when this happened, but unfortunately it now
464     // appears that the bufferSize must be reported as a
465     // power of 2. This might be the fault of 3rd party
466     // users.
467     for (size_t i = 1; (bytes & ~i) != 0; i<<=1)
468         bytes &= ~i;
469
470     return bytes;
471 }
472
473 int ALSAStreamOps::format() const
474 {
475     snd_pcm_format_t ALSAFormat;
476     int pcmFormatBitWidth;
477     int audioSystemFormat;
478
479     if (!mHandle)
480         return -1;
481
482     if (snd_pcm_hw_params_get_format(mHardwareParams, &ALSAFormat) < 0) {
483         return -1;
484     }
485
486     pcmFormatBitWidth = snd_pcm_format_physical_width(ALSAFormat);
487     audioSystemFormat = AudioSystem::DEFAULT;
488     switch(pcmFormatBitWidth) {
489         case 8:
490             audioSystemFormat = AudioSystem::PCM_8_BIT;
491             break;
492
493         case 16:
494             audioSystemFormat = AudioSystem::PCM_16_BIT;
495             break;
496
497         default:
498             LOG_FATAL("Unknown AudioSystem bit width %i!", pcmFormatBitWidth);
499     }
500
501     return audioSystemFormat;
502 }
503
504 int ALSAStreamOps::channelCount() const
505 {
506     if (!mHandle)
507         return mDefaults->channels;
508
509     unsigned int val;
510     int err;
511
512     err = snd_pcm_hw_params_get_channels(mHardwareParams, &val);
513     if (err < 0) {
514         LOGE("Unable to get device channel count: %s",
515             snd_strerror(err));
516         return mDefaults->channels;
517     }
518
519     return val;
520 }
521
522 status_t ALSAStreamOps::channelCount(int channels) {
523     int err;
524
525     if (!mHandle)
526         return NO_INIT;
527
528     err = snd_pcm_hw_params_set_channels(mHandle, mHardwareParams, channels);
529     if (err < 0) {
530         LOGE("Unable to set channel count to %i: %s",
531             channels, snd_strerror(err));
532         return BAD_VALUE;
533     }
534
535     LOGV("Using %i %s for %s.",
536         channels, channels == 1 ? "channel" : "channels", streamName());
537
538     return NO_ERROR;
539 }
540
541 status_t ALSAStreamOps::open(int mode, uint32_t device)
542 {
543     const char *stream = streamName();
544     const char *devName = deviceName(mode, device);
545
546     int         err;
547
548     for(;;) {
549         // The PCM stream is opened in blocking mode, per ALSA defaults.  The
550         // AudioFlinger seems to assume blocking mode too, so asynchronous mode
551         // should not be used.
552         err = snd_pcm_open(&mHandle, devName, mDefaults->direction, 0);
553         if (err == 0) break;
554
555         // See if there is a less specific name we can try.
556         // Note: We are changing the contents of a const char * here.
557         char *tail = strrchr(devName, '_');
558         if (!tail) break;
559         *tail = 0;
560     }
561
562     if (err < 0) {
563         // None of the Android defined audio devices exist. Open a generic one.
564         devName = "default";
565         err = snd_pcm_open(&mHandle, devName, mDefaults->direction, 0);
566         if (err < 0) {
567             // Last resort is the NULL device (i.e. the bit bucket).
568             devName = _nullALSADeviceName;
569             err = snd_pcm_open(&mHandle, devName, mDefaults->direction, 0);
570         }
571     }
572
573     mMode   = mode;
574     mDevice = device;
575
576     LOGI("Initialized ALSA %s device %s", stream, devName);
577     return err;
578 }
579
580 void ALSAStreamOps::close()
581 {
582     snd_pcm_t *handle = mHandle;
583     mHandle = NULL;
584
585     if (handle)
586         snd_pcm_close(handle);
587 }
588
589 status_t ALSAStreamOps::setSoftwareParams()
590 {
591     if (!mHandle)
592         return NO_INIT;
593
594     int err;
595
596     // Get the current software parameters
597     err = snd_pcm_sw_params_current(mHandle, mSoftwareParams);
598     if (err < 0) {
599         LOGE("Unable to get software parameters: %s", snd_strerror(err));
600         return NO_INIT;
601     }
602
603     snd_pcm_uframes_t bufferSize = 0;
604     snd_pcm_uframes_t periodSize = 0;
605     snd_pcm_uframes_t startThreshold, stopThreshold;
606
607     // Configure ALSA to start the transfer when the buffer is almost full.
608     snd_pcm_get_params(mHandle, &bufferSize, &periodSize);
609
610     if (mDefaults->direction == SND_PCM_STREAM_PLAYBACK) {
611         // For playback, configure ALSA to start the transfer when the
612         // buffer is full.
613         startThreshold = bufferSize - periodSize;
614         stopThreshold = bufferSize;
615     }
616     else {
617         // For recording, configure ALSA to start the transfer on the
618         // first frame.
619         startThreshold = 1;
620         stopThreshold = bufferSize;
621 }
622
623     err = snd_pcm_sw_params_set_start_threshold(mHandle,
624                                                 mSoftwareParams,
625                                                 startThreshold);
626     if (err < 0) {
627         LOGE("Unable to set start threshold to %lu frames: %s",
628             startThreshold, snd_strerror(err));
629         return NO_INIT;
630     }
631
632     err = snd_pcm_sw_params_set_stop_threshold(mHandle,
633                                                mSoftwareParams,
634                                                stopThreshold);
635     if (err < 0) {
636         LOGE("Unable to set stop threshold to %lu frames: %s",
637             stopThreshold, snd_strerror(err));
638         return NO_INIT;
639     }
640
641     // Allow the transfer to start when at least periodSize samples can be
642     // processed.
643     err = snd_pcm_sw_params_set_avail_min(mHandle,
644                                           mSoftwareParams,
645                                           periodSize);
646     if (err < 0) {
647         LOGE("Unable to configure available minimum to %lu: %s",
648             periodSize, snd_strerror(err));
649         return NO_INIT;
650     }
651
652     // Commit the software parameters back to the device.
653     err = snd_pcm_sw_params(mHandle, mSoftwareParams);
654     if (err < 0) {
655         LOGE("Unable to configure software parameters: %s",
656             snd_strerror(err));
657         return NO_INIT;
658     }
659
660     return NO_ERROR;
661 }
662
663 status_t ALSAStreamOps::setPCMFormat(snd_pcm_format_t format)
664 {
665     const char *formatDesc;
666     const char *formatName;
667     bool validFormat;
668     int err;
669
670     // snd_pcm_format_description() and snd_pcm_format_name() do not perform
671     // proper bounds checking.
672     validFormat = (static_cast<int>(format) > SND_PCM_FORMAT_UNKNOWN) &&
673         (static_cast<int>(format) <= SND_PCM_FORMAT_LAST);
674     formatDesc = validFormat ?
675         snd_pcm_format_description(format) : "Invalid Format";
676     formatName = validFormat ?
677         snd_pcm_format_name(format) : "UNKNOWN";
678
679     err = snd_pcm_hw_params_set_format(mHandle, mHardwareParams, format);
680     if (err < 0) {
681         LOGE("Unable to configure PCM format %s (%s): %s",
682             formatName, formatDesc, snd_strerror(err));
683         return NO_INIT;
684     }
685
686     LOGV("Set %s PCM format to %s (%s)", streamName(), formatName, formatDesc);
687     return NO_ERROR;
688 }
689
690 status_t ALSAStreamOps::setHardwareResample(bool resample)
691 {
692     int err;
693
694     err = snd_pcm_hw_params_set_rate_resample(mHandle,
695                                               mHardwareParams,
696                                               static_cast<int>(resample));
697     if (err < 0) {
698         LOGE("Unable to %s hardware resampling: %s",
699             resample ? "enable" : "disable",
700             snd_strerror(err));
701         return NO_INIT;
702     }
703     return NO_ERROR;
704 }
705
706 const char *ALSAStreamOps::streamName()
707 {
708     // Don't use snd_pcm_stream(mHandle), as the PCM stream may not be
709     // opened yet.  In such case, snd_pcm_stream() will abort().
710     return snd_pcm_stream_name(mDefaults->direction);
711 }
712
713 //
714 // Set playback or capture PCM device.  It's possible to support audio output
715 // or input from multiple devices by using the ALSA plugins, but this is
716 // not supported for simplicity.
717 //
718 // The AudioHardwareALSA API does not allow one to set the input routing.
719 //
720 // If the "routes" value does not map to a valid device, the default playback
721 // device is used.
722 //
723 status_t ALSAStreamOps::setDevice(int mode, uint32_t device)
724 {
725     // Close off previously opened device.
726     // It would be nice to determine if the underlying device actually
727     // changes, but we might be manipulating mixer settings (see asound.conf).
728     //
729     close();
730
731     const char *stream = streamName();
732
733     status_t    status = open (mode, device);
734     int     err;
735
736     if (status != NO_ERROR)
737         return status;
738
739     err = snd_pcm_hw_params_any(mHandle, mHardwareParams);
740     if (err < 0) {
741         LOGE("Unable to configure hardware: %s", snd_strerror(err));
742         return NO_INIT;
743     }
744
745     // Set the interleaved read and write format.
746     err = snd_pcm_hw_params_set_access(mHandle, mHardwareParams,
747                                        SND_PCM_ACCESS_RW_INTERLEAVED);
748     if (err < 0) {
749         LOGE("Unable to configure PCM read/write format: %s",
750             snd_strerror(err));
751         return NO_INIT;
752     }
753
754     status = setPCMFormat(mDefaults->format);
755
756     //
757     // Some devices do not have the default two channels.  Force an error to
758     // prevent AudioMixer from crashing and taking the whole system down.
759     //
760     // Note that some devices will return an -EINVAL if the channel count
761     // is queried before it has been set.  i.e. calling channelCount()
762     // before channelCount(channels) may return -EINVAL.
763     //
764     status = channelCount(mDefaults->channels);
765     if (status != NO_ERROR)
766         return status;
767
768     // Don't check for failure; some devices do not support the default
769     // sample rate.
770     sampleRate(mDefaults->sampleRate);
771
772 #ifdef DISABLE_HARWARE_RESAMPLING
773     // Disable hardware resampling.
774     status = setHardwareResample(false);
775     if (status != NO_ERROR)
776         return status;
777 #endif
778
779     snd_pcm_uframes_t bufferSize = mDefaults->bufferSize;
780
781     // Make sure we have at least the size we originally wanted
782     err = snd_pcm_hw_params_set_buffer_size(mHandle, mHardwareParams, bufferSize);
783     if (err < 0) {
784         LOGE("Unable to set buffer size to %d:  %s",
785              (int)bufferSize, snd_strerror(err));
786         return NO_INIT;
787     }
788
789     unsigned int latency = mDefaults->latency;
790
791     // Setup buffers for latency
792     err = snd_pcm_hw_params_set_buffer_time_near (mHandle, mHardwareParams,
793                                                   &latency, NULL);
794     if (err < 0) {
795         /* That didn't work, set the period instead */
796         unsigned int periodTime = latency / 4;
797         err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,
798                                                       &periodTime, NULL);
799         if (err < 0) {
800             LOGE("Unable to set the period time for latency: %s", snd_strerror(err));
801             return NO_INIT;
802         }
803         snd_pcm_uframes_t periodSize;
804         err = snd_pcm_hw_params_get_period_size (mHardwareParams, &periodSize, NULL);
805         if (err < 0) {
806             LOGE("Unable to get the period size for latency: %s", snd_strerror(err));
807             return NO_INIT;
808         }
809         bufferSize = periodSize * 4;
810         if (bufferSize < mDefaults->bufferSize)
811             bufferSize = mDefaults->bufferSize;
812         err = snd_pcm_hw_params_set_buffer_size_near (mHandle, mHardwareParams, &bufferSize);
813         if (err < 0) {
814             LOGE("Unable to set the buffer size for latency: %s", snd_strerror(err));
815             return NO_INIT;
816         }
817     } else {
818         // OK, we got buffer time near what we expect. See what that did for bufferSize.
819         err = snd_pcm_hw_params_get_buffer_size (mHardwareParams, &bufferSize);
820         if (err < 0) {
821             LOGE("Unable to get the buffer size for latency: %s", snd_strerror(err));
822             return NO_INIT;
823         }
824         // Does set_buffer_time_near change the passed value? It should.
825         err = snd_pcm_hw_params_get_buffer_time (mHardwareParams, &latency, NULL);
826         if (err < 0) {
827             LOGE("Unable to get the buffer time for latency: %s", snd_strerror(err));
828             return NO_INIT;
829         }
830         unsigned int periodTime = latency / 4;
831         err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,
832                                                       &periodTime, NULL);
833         if (err < 0) {
834             LOGE("Unable to set the period time for latency: %s", snd_strerror(err));
835             return NO_INIT;
836         }
837     }
838
839     LOGV("Buffer size: %d", (int)bufferSize);
840     LOGV("Latency: %d", (int)latency);
841
842     mDefaults->bufferSize = bufferSize;
843     mDefaults->latency = latency;
844
845     // Commit the hardware parameters back to the device.
846     err = snd_pcm_hw_params(mHandle, mHardwareParams);
847     if (err < 0) {
848         LOGE("Unable to set hardware parameters: %s", snd_strerror(err));
849         return NO_INIT;
850     }
851
852     status = setSoftwareParams();
853
854     return status;
855 }
856
857 const char *ALSAStreamOps::deviceName(int mode, uint32_t device)
858 {
859     static char devString[ALSA_NAME_MAX];
860     int hasDevExt = 0;
861
862     strcpy (devString, mDefaults->devicePrefix);
863
864     for (int dev=0; device; dev++)
865         if (device & (1 << dev)) {
866             /* Don't go past the end of our list */
867             if (dev >= deviceSuffixLen)
868                 break;
869             ALSA_STRCAT (devString, deviceSuffix[dev]);
870             device &= ~(1 << dev);
871             hasDevExt = 1;
872         }
873
874     if (hasDevExt)
875         switch (mode) {
876             case AudioSystem::MODE_NORMAL:
877                 ALSA_STRCAT (devString, "_normal");
878                 break;
879             case AudioSystem::MODE_RINGTONE:
880                 ALSA_STRCAT (devString, "_ringtone");
881                 break;
882             case AudioSystem::MODE_IN_CALL:
883                 ALSA_STRCAT (devString, "_incall");
884                 break;
885         };
886
887     return devString;
888 }
889
890 // ----------------------------------------------------------------------------
891
892 AudioStreamOutALSA::AudioStreamOutALSA(AudioHardwareALSA *parent) :
893     ALSAStreamOps(parent)
894 {
895     static StreamDefaults _defaults = {
896         devicePrefix   : "AndroidPlayback",
897         direction      : SND_PCM_STREAM_PLAYBACK,
898         format         : SND_PCM_FORMAT_S16_LE,   // AudioSystem::PCM_16_BIT
899         channels       : 2,
900         sampleRate     : DEFAULT_SAMPLE_RATE,
901         latency        : 200000,                  // Desired Delay in usec
902         bufferSize     : DEFAULT_SAMPLE_RATE / 5, // Desired Number of samples
903         };
904
905     setStreamDefaults(&_defaults);
906
907     snd_pcm_uframes_t bufferSize = mDefaults->bufferSize;
908
909     // See comment in bufferSize() method.
910     for (size_t i = 1; (bufferSize & ~i) != 0; i<<=1)
911         bufferSize &= ~i;
912
913     mDefaults->bufferSize = bufferSize;
914 }
915
916 AudioStreamOutALSA::~AudioStreamOutALSA()
917 {
918     standby();
919     mParent->mOutput = NULL;
920 }
921
922 int AudioStreamOutALSA::channelCount() const
923 {
924     int c = ALSAStreamOps::channelCount();
925
926     // AudioMixer will seg fault if it doesn't have two channels.
927     LOGW_IF(c != 2,
928         "AudioMixer expects two channels, but only %i found!", c);
929     return c;
930 }
931
932 status_t AudioStreamOutALSA::setVolume(float volume)
933 {
934     if (!mParent->mMixer || !mDevice)
935         return NO_INIT;
936
937     return mParent->mMixer->setVolume (mDevice, volume);
938 }
939
940 ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
941 {
942     snd_pcm_sframes_t n;
943     size_t            sent = 0;
944     status_t          err;
945
946     AutoMutex lock(mLock);
947
948     if (!mPowerLock) {
949         acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
950         mPowerLock = true;
951     }
952
953     if (!mHandle)
954         ALSAStreamOps::setDevice(mMode, mDevice);
955
956     do {
957         n = snd_pcm_writei(mHandle,
958                            (char *)buffer + sent,
959                            snd_pcm_bytes_to_frames(mHandle, bytes));
960         if (n == -EBADFD) {
961             // Somehow the stream is in a bad state. The driver probably
962             // has a bug and snd_pcm_recover() doesn't seem to handle this.
963             ALSAStreamOps::setDevice(mMode, mDevice);
964         }
965         else if (n < 0) {
966             if (mHandle) {
967                 // snd_pcm_recover() will return 0 if successful in recovering from
968                 // an error, or -errno if the error was unrecoverable.
969                 n = snd_pcm_recover(mHandle, n, 1);
970                 if (n)
971                     return static_cast<ssize_t>(n);
972             }
973         }
974         else
975             sent += static_cast<ssize_t>(snd_pcm_frames_to_bytes(mHandle, n));
976
977     } while (mHandle && sent < bytes);
978
979     return sent;
980 }
981
982 status_t AudioStreamOutALSA::dump(int fd, const Vector<String16>& args)
983 {
984     return NO_ERROR;
985 }
986
987 status_t AudioStreamOutALSA::setDevice(int mode, uint32_t newDevice)
988 {
989     AutoMutex lock(mLock);
990
991     return ALSAStreamOps::setDevice(mode, newDevice);
992 }
993
994 status_t AudioStreamOutALSA::standby()
995 {
996     AutoMutex lock(mLock);
997
998     if (mHandle) {
999         snd_pcm_drain (mHandle);
1000         close();
1001     }
1002
1003     if (mPowerLock) {
1004         release_wake_lock ("AudioOutLock");
1005         mPowerLock = false;
1006     }
1007
1008     return NO_ERROR;
1009 }
1010
1011 #define USEC_TO_MSEC(x) ((x + 999) / 1000)
1012
1013 uint32_t AudioStreamOutALSA::latency() const
1014 {
1015     // Android wants latency in milliseconds.
1016     return USEC_TO_MSEC (mDefaults->latency);
1017 }
1018
1019 // ----------------------------------------------------------------------------
1020
1021 AudioStreamInALSA::AudioStreamInALSA(AudioHardwareALSA *parent,
1022                                      AudioSystem::audio_in_acoustics acoustics) :
1023     ALSAStreamOps(parent),
1024     mAcoustics(acoustics)
1025 {
1026     static StreamDefaults _defaults = {
1027         devicePrefix   : "AndroidRecord",
1028         direction      : SND_PCM_STREAM_CAPTURE,
1029         format         : SND_PCM_FORMAT_S16_LE,   // AudioSystem::PCM_16_BIT
1030         channels       : 1,
1031         sampleRate     : AudioRecord::DEFAULT_SAMPLE_RATE,
1032         latency        : 250000,                  // Desired Delay in usec
1033         bufferSize     : 2048,                    // Desired Number of samples
1034         };
1035
1036     setStreamDefaults(&_defaults);
1037 }
1038
1039 AudioStreamInALSA::~AudioStreamInALSA()
1040 {
1041     standby();
1042     mParent->mInput = NULL;
1043 }
1044
1045 status_t AudioStreamInALSA::setGain(float gain)
1046 {
1047     if (mParent->mMixer)
1048         return mParent->mMixer->setMasterGain (gain);
1049     else
1050         return NO_INIT;
1051 }
1052
1053 ssize_t AudioStreamInALSA::read(void *buffer, ssize_t bytes)
1054 {
1055     snd_pcm_sframes_t n, frames = snd_pcm_bytes_to_frames(mHandle, bytes);
1056     status_t          err;
1057
1058     AutoMutex lock(mLock);
1059
1060     if (!mPowerLock) {
1061         acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock");
1062         mPowerLock = true;
1063     }
1064
1065     if (!mHandle)
1066         ALSAStreamOps::setDevice(mMode, mDevice);
1067
1068     n = snd_pcm_readi(mHandle, buffer, frames);
1069     if (n < frames) {
1070         if (mHandle) {
1071             if (n < 0)
1072                 n = snd_pcm_recover(mHandle, n, 0);
1073             else
1074                 n = snd_pcm_prepare(mHandle);
1075         }
1076         return static_cast<ssize_t>(n);
1077     }
1078
1079     if (mParent->mAcousticDevice &&
1080         mParent->mAcousticDevice->filter) {
1081         n = mParent->mAcousticDevice->filter(mHandle, buffer, frames);
1082         if (n < 0)
1083             return static_cast<ssize_t>(n);
1084     }
1085
1086     return static_cast<ssize_t>(snd_pcm_frames_to_bytes(mHandle, n));
1087 }
1088
1089 status_t AudioStreamInALSA::dump(int fd, const Vector<String16>& args)
1090 {
1091     return NO_ERROR;
1092 }
1093
1094 status_t AudioStreamInALSA::setDevice(int mode, uint32_t newDevice)
1095 {
1096     AutoMutex lock(mLock);
1097
1098     status_t status = ALSAStreamOps::setDevice(mode, newDevice);
1099
1100     if (status == NO_ERROR && mParent->mAcousticDevice)
1101         status = mParent->mAcousticDevice->set_acoustics(mHandle, mAcoustics);
1102
1103     return status;
1104 }
1105
1106 status_t AudioStreamInALSA::standby()
1107 {
1108     AutoMutex lock(mLock);
1109
1110     close();
1111
1112     if (mPowerLock) {
1113         release_wake_lock ("AudioInLock");
1114         mPowerLock = false;
1115     }
1116
1117     return NO_ERROR;
1118 }
1119
1120 // ----------------------------------------------------------------------------
1121
1122 struct mixer_info_t
1123 {
1124     mixer_info_t() :
1125         elem(0),
1126         min(SND_MIXER_VOL_RANGE_MIN),
1127         max(SND_MIXER_VOL_RANGE_MAX),
1128         mute(false)
1129     {
1130     }
1131
1132     snd_mixer_elem_t *elem;
1133     long              min;
1134     long              max;
1135     long              volume;
1136     bool              mute;
1137     char              name[ALSA_NAME_MAX];
1138 };
1139
1140 static int initMixer (snd_mixer_t **mixer, const char *name)
1141 {
1142     int err;
1143
1144     if ((err = snd_mixer_open(mixer, 0)) < 0) {
1145         LOGE("Unable to open mixer: %s", snd_strerror(err));
1146         return err;
1147     }
1148
1149     if ((err = snd_mixer_attach(*mixer, name)) < 0) {
1150         LOGE("Unable to attach mixer to device %s: %s",
1151             name, snd_strerror(err));
1152
1153         if ((err = snd_mixer_attach(*mixer, "hw:00")) < 0) {
1154             LOGE("Unable to attach mixer to device default: %s",
1155                 snd_strerror(err));
1156
1157             snd_mixer_close (*mixer);
1158             *mixer = NULL;
1159             return err;
1160         }
1161     }
1162
1163     if ((err = snd_mixer_selem_register(*mixer, NULL, NULL)) < 0) {
1164         LOGE("Unable to register mixer elements: %s", snd_strerror(err));
1165         snd_mixer_close (*mixer);
1166         *mixer = NULL;
1167         return err;
1168     }
1169
1170     // Get the mixer controls from the kernel
1171     if ((err = snd_mixer_load(*mixer)) < 0) {
1172         LOGE("Unable to load mixer elements: %s", snd_strerror(err));
1173         snd_mixer_close (*mixer);
1174         *mixer = NULL;
1175         return err;
1176     }
1177
1178     return 0;
1179 }
1180
1181 typedef int (*hasVolume_t)(snd_mixer_elem_t*);
1182
1183 static const hasVolume_t hasVolume[] = {
1184     snd_mixer_selem_has_playback_volume,
1185     snd_mixer_selem_has_capture_volume
1186 };
1187
1188 typedef int (*getVolumeRange_t)(snd_mixer_elem_t*, long int*, long int*);
1189
1190 static const getVolumeRange_t getVolumeRange[] = {
1191     snd_mixer_selem_get_playback_volume_range,
1192     snd_mixer_selem_get_capture_volume_range
1193 };
1194
1195 typedef int (*setVolume_t)(snd_mixer_elem_t*, long int);
1196
1197 static const setVolume_t setVol[] = {
1198     snd_mixer_selem_set_playback_volume_all,
1199     snd_mixer_selem_set_capture_volume_all
1200 };
1201
1202 ALSAMixer::ALSAMixer()
1203 {
1204     int err;
1205
1206     initMixer (&mMixer[SND_PCM_STREAM_PLAYBACK], "AndroidPlayback");
1207     initMixer (&mMixer[SND_PCM_STREAM_CAPTURE], "AndroidRecord");
1208
1209     snd_mixer_selem_id_t *sid;
1210     snd_mixer_selem_id_alloca(&sid);
1211
1212     for (int i = 0; i <= SND_PCM_STREAM_LAST; i++) {
1213
1214         mixer_info_t *info = mixerMasterProp[i].mInfo = new mixer_info_t;
1215
1216         property_get (mixerMasterProp[i].propName,
1217                       info->name,
1218                       mixerMasterProp[i].propDefault);
1219
1220         for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]);
1221              elem;
1222              elem = snd_mixer_elem_next(elem)) {
1223
1224             if (!snd_mixer_selem_is_active(elem))
1225                 continue;
1226
1227             snd_mixer_selem_get_id(elem, sid);
1228
1229             // Find PCM playback volume control element.
1230             const char *elementName = snd_mixer_selem_id_get_name(sid);
1231
1232             if (info->elem == NULL &&
1233                 strcmp(elementName, info->name) == 0 &&
1234                 hasVolume[i] (elem)) {
1235
1236                 info->elem = elem;
1237                 getVolumeRange[i] (elem, &info->min, &info->max);
1238                 info->volume = info->max;
1239                 setVol[i] (elem, info->volume);
1240                 if (i == SND_PCM_STREAM_PLAYBACK &&
1241                     snd_mixer_selem_has_playback_switch (elem))
1242                     snd_mixer_selem_set_playback_switch_all (elem, 1);
1243                 break;
1244             }
1245         }
1246
1247         LOGV("Mixer: master '%s' %s.", info->name, info->elem ? "found" : "not found");
1248
1249         for (int j = 0; mixerProp[j][i].routes; j++) {
1250
1251             mixer_info_t *info = mixerProp[j][i].mInfo = new mixer_info_t;
1252
1253             property_get (mixerProp[j][i].propName,
1254                           info->name,
1255                           mixerProp[j][i].propDefault);
1256
1257             for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]);
1258                  elem;
1259                  elem = snd_mixer_elem_next(elem)) {
1260
1261                 if (!snd_mixer_selem_is_active(elem))
1262                     continue;
1263
1264                 snd_mixer_selem_get_id(elem, sid);
1265
1266                 // Find PCM playback volume control element.
1267                 const char *elementName = snd_mixer_selem_id_get_name(sid);
1268
1269                if (info->elem == NULL &&
1270                     strcmp(elementName, info->name) == 0 &&
1271                     hasVolume[i] (elem)) {
1272
1273                     info->elem = elem;
1274                     getVolumeRange[i] (elem, &info->min, &info->max);
1275                     info->volume = info->max;
1276                     setVol[i] (elem, info->volume);
1277                     if (i == SND_PCM_STREAM_PLAYBACK &&
1278                         snd_mixer_selem_has_playback_switch (elem))
1279                         snd_mixer_selem_set_playback_switch_all (elem, 1);
1280                     break;
1281                 }
1282             }
1283             LOGV("Mixer: route '%s' %s.", info->name, info->elem ? "found" : "not found");
1284         }
1285     }
1286     LOGV("mixer initialized.");
1287 }
1288
1289 ALSAMixer::~ALSAMixer()
1290 {
1291     for (int i = 0; i <= SND_PCM_STREAM_LAST; i++) {
1292         if (mMixer[i]) snd_mixer_close (mMixer[i]);
1293         if (mixerMasterProp[i].mInfo) {
1294             delete mixerMasterProp[i].mInfo;
1295             mixerMasterProp[i].mInfo = NULL;
1296         }
1297         for (int j = 0; mixerProp[j][i].routes; j++) {
1298             if (mixerProp[j][i].mInfo) {
1299                 delete mixerProp[j][i].mInfo;
1300                 mixerProp[j][i].mInfo = NULL;
1301             }
1302         }
1303     }
1304     LOGV("mixer destroyed.");
1305 }
1306
1307 status_t ALSAMixer::setMasterVolume(float volume)
1308 {
1309     mixer_info_t *info = mixerMasterProp[SND_PCM_STREAM_PLAYBACK].mInfo;
1310     if (!info || !info->elem) return INVALID_OPERATION;
1311
1312     long minVol = info->min;
1313     long maxVol = info->max;
1314
1315     // Make sure volume is between bounds.
1316     long vol = minVol + volume * (maxVol - minVol);
1317     if (vol > maxVol) vol = maxVol;
1318     if (vol < minVol) vol = minVol;
1319
1320     info->volume = vol;
1321     snd_mixer_selem_set_playback_volume_all (info->elem, vol);
1322
1323     return NO_ERROR;
1324 }
1325
1326 status_t ALSAMixer::setMasterGain(float gain)
1327 {
1328     mixer_info_t *info = mixerMasterProp[SND_PCM_STREAM_CAPTURE].mInfo;
1329     if (!info || !info->elem) return INVALID_OPERATION;
1330
1331     long minVol = info->min;
1332     long maxVol = info->max;
1333
1334     // Make sure volume is between bounds.
1335     long vol = minVol + gain * (maxVol - minVol);
1336     if (vol > maxVol) vol = maxVol;
1337     if (vol < minVol) vol = minVol;
1338
1339     info->volume = vol;
1340     snd_mixer_selem_set_capture_volume_all (info->elem, vol);
1341
1342     return NO_ERROR;
1343 }
1344
1345 status_t ALSAMixer::setVolume(uint32_t device, float volume)
1346 {
1347     for (int j = 0; mixerProp[j][SND_PCM_STREAM_PLAYBACK].routes; j++)
1348         if (mixerProp[j][SND_PCM_STREAM_PLAYBACK].routes & device) {
1349
1350             mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_PLAYBACK].mInfo;
1351             if (!info || !info->elem) return INVALID_OPERATION;
1352
1353             long minVol = info->min;
1354             long maxVol = info->max;
1355
1356             // Make sure volume is between bounds.
1357             long vol = minVol + volume * (maxVol - minVol);
1358             if (vol > maxVol) vol = maxVol;
1359             if (vol < minVol) vol = minVol;
1360
1361             info->volume = vol;
1362             snd_mixer_selem_set_playback_volume_all (info->elem, vol);
1363         }
1364
1365     return NO_ERROR;
1366 }
1367
1368 status_t ALSAMixer::setGain(uint32_t device, float gain)
1369 {
1370     for (int j = 0; mixerProp[j][SND_PCM_STREAM_CAPTURE].routes; j++)
1371         if (mixerProp[j][SND_PCM_STREAM_CAPTURE].routes & device) {
1372
1373             mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_CAPTURE].mInfo;
1374             if (!info || !info->elem) return INVALID_OPERATION;
1375
1376             long minVol = info->min;
1377             long maxVol = info->max;
1378
1379             // Make sure volume is between bounds.
1380             long vol = minVol + gain * (maxVol - minVol);
1381             if (vol > maxVol) vol = maxVol;
1382             if (vol < minVol) vol = minVol;
1383
1384             info->volume = vol;
1385             snd_mixer_selem_set_capture_volume_all (info->elem, vol);
1386         }
1387
1388     return NO_ERROR;
1389 }
1390
1391 status_t ALSAMixer::setCaptureMuteState(uint32_t device, bool state)
1392 {
1393     for (int j = 0; mixerProp[j][SND_PCM_STREAM_CAPTURE].routes; j++)
1394         if (mixerProp[j][SND_PCM_STREAM_CAPTURE].routes & device) {
1395
1396             mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_CAPTURE].mInfo;
1397             if (!info || !info->elem) return INVALID_OPERATION;
1398
1399             if (snd_mixer_selem_has_capture_switch (info->elem)) {
1400
1401                 int err = snd_mixer_selem_set_capture_switch_all (info->elem, static_cast<int>(!state));
1402                 if (err < 0) {
1403                     LOGE("Unable to %s capture mixer switch %s",
1404                         state ? "enable" : "disable", info->name);
1405                     return INVALID_OPERATION;
1406                 }
1407             }
1408
1409             info->mute = state;
1410         }
1411
1412     return NO_ERROR;
1413 }
1414
1415 status_t ALSAMixer::getCaptureMuteState(uint32_t device, bool *state)
1416 {
1417     if (!state) return BAD_VALUE;
1418
1419     for (int j = 0; mixerProp[j][SND_PCM_STREAM_CAPTURE].routes; j++)
1420         if (mixerProp[j][SND_PCM_STREAM_CAPTURE].routes & device) {
1421
1422             mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_CAPTURE].mInfo;
1423             if (!info || !info->elem) return INVALID_OPERATION;
1424
1425             *state = info->mute;
1426             return NO_ERROR;
1427         }
1428
1429     return BAD_VALUE;
1430 }
1431
1432 status_t ALSAMixer::setPlaybackMuteState(uint32_t device, bool state)
1433 {
1434     for (int j = 0; mixerProp[j][SND_PCM_STREAM_PLAYBACK].routes; j++)
1435         if (mixerProp[j][SND_PCM_STREAM_PLAYBACK].routes & device) {
1436
1437             mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_PLAYBACK].mInfo;
1438             if (!info || !info->elem) return INVALID_OPERATION;
1439
1440             if (snd_mixer_selem_has_playback_switch (info->elem)) {
1441
1442                 int err = snd_mixer_selem_set_playback_switch_all (info->elem, static_cast<int>(!state));
1443                 if (err < 0) {
1444                     LOGE("Unable to %s playback mixer switch %s",
1445                         state ? "enable" : "disable", info->name);
1446                     return INVALID_OPERATION;
1447                 }
1448             }
1449
1450             info->mute = state;
1451         }
1452
1453     return NO_ERROR;
1454 }
1455
1456 status_t ALSAMixer::getPlaybackMuteState(uint32_t device, bool *state)
1457 {
1458     if (!state) return BAD_VALUE;
1459
1460     for (int j = 0; mixerProp[j][SND_PCM_STREAM_PLAYBACK].routes; j++)
1461         if (mixerProp[j][SND_PCM_STREAM_PLAYBACK].routes & device) {
1462
1463             mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_PLAYBACK].mInfo;
1464             if (!info || !info->elem) return INVALID_OPERATION;
1465
1466             *state = info->mute;
1467             return NO_ERROR;
1468         }
1469
1470     return BAD_VALUE;
1471 }
1472
1473 // ----------------------------------------------------------------------------
1474
1475 ALSAControl::ALSAControl(const char *device)
1476 {
1477     snd_ctl_open(&mHandle, device, 0);
1478 }
1479
1480 ALSAControl::~ALSAControl()
1481 {
1482     if (mHandle) snd_ctl_close(mHandle);
1483 }
1484
1485 status_t ALSAControl::get(const char *name, unsigned int &value, int index)
1486 {
1487     if (!mHandle) return NO_INIT;
1488
1489     snd_ctl_elem_id_t *id;
1490     snd_ctl_elem_info_t *info;
1491     snd_ctl_elem_value_t *control;
1492
1493     snd_ctl_elem_id_alloca(&id);
1494     snd_ctl_elem_info_alloca(&info);
1495     snd_ctl_elem_value_alloca(&control);
1496
1497     snd_ctl_elem_id_set_name(id, name);
1498     snd_ctl_elem_info_set_id(info, id);
1499
1500     int ret = snd_ctl_elem_info(mHandle, info);
1501     if (ret < 0) return BAD_VALUE;
1502
1503     snd_ctl_elem_info_get_id(info, id);
1504     snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info);
1505     unsigned int count = snd_ctl_elem_info_get_count(info);
1506     if ((unsigned int)index >= count) return BAD_VALUE;
1507
1508     snd_ctl_elem_value_set_id(control, id);
1509
1510     ret = snd_ctl_elem_read(mHandle, control);
1511     if (ret < 0) return BAD_VALUE;
1512
1513     switch (type) {
1514         case SND_CTL_ELEM_TYPE_BOOLEAN:
1515             value = snd_ctl_elem_value_get_boolean(control, index);
1516             break;
1517         case SND_CTL_ELEM_TYPE_INTEGER:
1518             value = snd_ctl_elem_value_get_integer(control, index);
1519             break;
1520         case SND_CTL_ELEM_TYPE_INTEGER64:
1521             value = snd_ctl_elem_value_get_integer64(control, index);
1522             break;
1523         case SND_CTL_ELEM_TYPE_ENUMERATED:
1524             value = snd_ctl_elem_value_get_enumerated(control, index);
1525             break;
1526         case SND_CTL_ELEM_TYPE_BYTES:
1527             value = snd_ctl_elem_value_get_byte(control, index);
1528             break;
1529         default:
1530             return BAD_VALUE;
1531     }
1532
1533     return NO_ERROR;
1534 }
1535
1536 status_t ALSAControl::set(const char *name, unsigned int value, int index)
1537 {
1538     if (!mHandle) return NO_INIT;
1539
1540     snd_ctl_elem_id_t *id;
1541     snd_ctl_elem_info_t *info;
1542     snd_ctl_elem_value_t *control;
1543
1544     snd_ctl_elem_id_alloca(&id);
1545     snd_ctl_elem_info_alloca(&info);
1546     snd_ctl_elem_value_alloca(&control);
1547
1548     snd_ctl_elem_id_set_name(id, name);
1549     snd_ctl_elem_info_set_id(info, id);
1550
1551     int ret = snd_ctl_elem_info(mHandle, info);
1552     if (ret < 0) return BAD_VALUE;
1553
1554     snd_ctl_elem_info_get_id(info, id);
1555     snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info);
1556     unsigned int count = snd_ctl_elem_info_get_count(info);
1557     if ((unsigned int)index >= count) return BAD_VALUE;
1558
1559     if (index == -1)
1560         index = 0; // Range over all of them
1561     else
1562         count = index + 1; // Just do the one specified
1563
1564     snd_ctl_elem_value_set_id(control, id);
1565
1566     for (unsigned int i = index; i < count; i++)
1567         switch (type) {
1568             case SND_CTL_ELEM_TYPE_BOOLEAN:
1569                 snd_ctl_elem_value_set_boolean(control, i, value);
1570                 break;
1571             case SND_CTL_ELEM_TYPE_INTEGER:
1572                 snd_ctl_elem_value_set_integer(control, i, value);
1573                 break;
1574             case SND_CTL_ELEM_TYPE_INTEGER64:
1575                 snd_ctl_elem_value_set_integer64(control, i, value);
1576                 break;
1577             case SND_CTL_ELEM_TYPE_ENUMERATED:
1578                 snd_ctl_elem_value_set_enumerated(control, i, value);
1579                 break;
1580             case SND_CTL_ELEM_TYPE_BYTES:
1581                 snd_ctl_elem_value_set_byte(control, i, value);
1582                 break;
1583             default:
1584                 break;
1585         }
1586
1587     ret = snd_ctl_elem_write(mHandle, control);
1588     return (ret < 0) ? BAD_VALUE : NO_ERROR;
1589 }
1590
1591 // ----------------------------------------------------------------------------
1592
1593 };        // namespace android