OSDN Git Service

Support no ALSA mixing.
[android-x86/hardware-alsa_sound.git] / AudioStreamInALSA.cpp
1 /* AudioStreamInALSA.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 namespace android
37 {
38
39 AudioStreamInALSA::AudioStreamInALSA(AudioHardwareALSA *parent,
40         alsa_handle_t *handle,
41         AudioSystem::audio_in_acoustics audio_acoustics) :
42     ALSAStreamOps(parent, handle),
43     mFramesLost(0),
44     mAcoustics(audio_acoustics)
45 {
46     acoustic_device_t *aDev = acoustics();
47
48     if (aDev) aDev->set_params(aDev, mAcoustics, NULL);
49 }
50
51 AudioStreamInALSA::~AudioStreamInALSA()
52 {
53     close();
54 }
55
56 status_t AudioStreamInALSA::setGain(float gain)
57 {
58     return mixer() ? mixer()->setMasterGain(gain) : (status_t)NO_INIT;
59 }
60
61 ssize_t AudioStreamInALSA::read(void *buffer, ssize_t bytes)
62 {
63     AutoMutex lock(mLock);
64
65     if (!mPowerLock) {
66         acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock");
67         mPowerLock = true;
68     }
69
70     acoustic_device_t *aDev = acoustics();
71
72     // If there is an acoustics module read method, then it overrides this
73     // implementation (unlike AudioStreamOutALSA write).
74     if (aDev && aDev->read)
75         return aDev->read(aDev, buffer, bytes);
76
77     snd_pcm_sframes_t n, frames = snd_pcm_bytes_to_frames(mHandle->handle, bytes);
78     status_t          err;
79
80     do {
81         n = snd_pcm_readi(mHandle->handle, buffer, frames);
82         if (n < frames) {
83             if (mHandle->handle) {
84                 if (n < 0) {
85                     n = snd_pcm_recover(mHandle->handle, n, 0);
86
87                     if (aDev && aDev->recover) aDev->recover(aDev, n);
88                 } else
89                     n = snd_pcm_prepare(mHandle->handle);
90             }
91             return static_cast<ssize_t>(n);
92         }
93     } while (n == -EAGAIN);
94
95     return static_cast<ssize_t>(snd_pcm_frames_to_bytes(mHandle->handle, n));
96 }
97
98 status_t AudioStreamInALSA::dump(int fd, const Vector<String16>& args)
99 {
100     return NO_ERROR;
101 }
102
103 status_t AudioStreamInALSA::open(int mode)
104 {
105     AutoMutex lock(mLock);
106
107     status_t status = ALSAStreamOps::open(mode);
108
109     acoustic_device_t *aDev = acoustics();
110
111     if (status == NO_ERROR && aDev)
112         status = aDev->use_handle(aDev, mHandle);
113
114     return status;
115 }
116
117 status_t AudioStreamInALSA::close()
118 {
119     AutoMutex lock(mLock);
120
121     acoustic_device_t *aDev = acoustics();
122
123     if (mHandle && aDev) aDev->cleanup(aDev);
124
125     ALSAStreamOps::close();
126
127     if (mPowerLock) {
128         release_wake_lock ("AudioInLock");
129         mPowerLock = false;
130     }
131
132     return NO_ERROR;
133 }
134
135 status_t AudioStreamInALSA::standby()
136 {
137     AutoMutex lock(mLock);
138
139     if (mPowerLock) {
140         release_wake_lock ("AudioInLock");
141         mPowerLock = false;
142     }
143
144     return NO_ERROR;
145 }
146
147 void AudioStreamInALSA::resetFramesLost()
148 {
149     AutoMutex lock(mLock);
150     mFramesLost = 0;
151 }
152
153 unsigned int AudioStreamInALSA::getInputFramesLost() const
154 {
155     unsigned int count = mFramesLost;
156     // Stupid interface wants us to have a side effect of clearing the count
157     // but is defined as a const to prevent such a thing.
158     ((AudioStreamInALSA *)this)->resetFramesLost();
159     return count;
160 }
161
162 status_t AudioStreamInALSA::setAcousticParams(void *params)
163 {
164     AutoMutex lock(mLock);
165
166     acoustic_device_t *aDev = acoustics();
167
168     return aDev ? aDev->set_params(aDev, mAcoustics, params) : (status_t)NO_ERROR;
169 }
170
171 }       // namespace android