OSDN Git Service

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