OSDN Git Service

b295676e7d487c35f57943d271aa3d87b7e2db47
[android-x86/hardware-alsa_sound.git] / AudioStreamOutALSA.cpp
1 /* AudioStreamOutALSA.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 #ifndef ALSA_DEFAULT_SAMPLE_RATE
37 #define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
38 #endif
39
40 namespace android
41 {
42
43 // ----------------------------------------------------------------------------
44
45 static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
46
47 // ----------------------------------------------------------------------------
48
49 AudioStreamOutALSA::AudioStreamOutALSA(AudioHardwareALSA *parent, alsa_handle_t *handle) :
50     ALSAStreamOps(parent, handle),
51     mFrameCount(0)
52 {
53 }
54
55 AudioStreamOutALSA::~AudioStreamOutALSA()
56 {
57     close();
58 }
59
60 uint32_t AudioStreamOutALSA::channels() const
61 {
62     int c = ALSAStreamOps::channels();
63     return c;
64 }
65
66 status_t AudioStreamOutALSA::setVolume(float left, float right)
67 {
68     return mixer()->setVolume (mHandle->curDev, left, right);
69 }
70
71 ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
72 {
73     AutoMutex lock(mLock);
74
75     if (!mPowerLock) {
76         acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
77         mPowerLock = true;
78     }
79
80     acoustic_device_t *aDev = acoustics();
81
82     // For output, we will pass the data on to the acoustics module, but the actual
83     // data is expected to be sent to the audio device directly as well.
84     if (aDev && aDev->write)
85         aDev->write(aDev, buffer, bytes);
86
87     snd_pcm_sframes_t n;
88     size_t            sent = 0;
89     status_t          err;
90
91     do {
92         n = snd_pcm_writei(mHandle->handle,
93                            (char *)buffer + sent,
94                            snd_pcm_bytes_to_frames(mHandle->handle, bytes - sent));
95         if (n == -EBADFD) {
96             // Somehow the stream is in a bad state. The driver probably
97             // has a bug and snd_pcm_recover() doesn't seem to handle this.
98             mHandle->module->open(mHandle, mHandle->curDev, mHandle->curMode);
99
100             if (aDev && aDev->recover) aDev->recover(aDev, n);
101         }
102         else if (n < 0) {
103             if (mHandle->handle) {
104                 // snd_pcm_recover() will return 0 if successful in recovering from
105                 // an error, or -errno if the error was unrecoverable.
106                 n = snd_pcm_recover(mHandle->handle, n, 1);
107
108                 if (aDev && aDev->recover) aDev->recover(aDev, n);
109
110                 if (n) return static_cast<ssize_t>(n);
111             }
112         }
113         else {
114             mFrameCount += n;
115             sent += static_cast<ssize_t>(snd_pcm_frames_to_bytes(mHandle->handle, n));
116         }
117
118     } while (mHandle->handle && sent < bytes);
119
120     return sent;
121 }
122
123 status_t AudioStreamOutALSA::dump(int fd, const Vector<String16>& args)
124 {
125     return NO_ERROR;
126 }
127
128 status_t AudioStreamOutALSA::open(int mode)
129 {
130     AutoMutex lock(mLock);
131
132     return ALSAStreamOps::open(mode);
133 }
134
135 status_t AudioStreamOutALSA::close()
136 {
137     AutoMutex lock(mLock);
138
139     snd_pcm_drain (mHandle->handle);
140     ALSAStreamOps::close();
141
142     if (mPowerLock) {
143         release_wake_lock ("AudioOutLock");
144         mPowerLock = false;
145     }
146
147     return NO_ERROR;
148 }
149
150 status_t AudioStreamOutALSA::standby()
151 {
152     AutoMutex lock(mLock);
153
154     snd_pcm_drain (mHandle->handle);
155
156     if (mPowerLock) {
157         release_wake_lock ("AudioOutLock");
158         mPowerLock = false;
159     }
160
161     mFrameCount = 0;
162
163     return NO_ERROR;
164 }
165
166 #define USEC_TO_MSEC(x) ((x + 999) / 1000)
167
168 uint32_t AudioStreamOutALSA::latency() const
169 {
170     // Android wants latency in milliseconds.
171     return USEC_TO_MSEC (mHandle->latency);
172 }
173
174 // return the number of audio frames written by the audio dsp to DAC since
175 // the output has exited standby
176 status_t AudioStreamOutALSA::getRenderPosition(uint32_t *dspFrames)
177 {
178     *dspFrames = mFrameCount;
179     return NO_ERROR;
180 }
181
182 }       // namespace android