00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "mythconfig.h"
00024 #if HAVE_SYS_SOUNDCARD_H
00025 #include <sys/soundcard.h>
00026 #elif HAVE_SOUNDCARD_H
00027 #include <soundcard.h>
00028 #endif
00029
00030 #include "audioinputoss.h"
00031 #include "mythlogging.h"
00032 #include <fcntl.h>
00033 #include <sys/ioctl.h>
00034
00035 #define LOC QString("AudioInOSS: ")
00036 #define LOC_DEV QString("AudioInOSS(%1): ").arg(m_device_name.constData())
00037
00038 AudioInputOSS::AudioInputOSS(const QString &device) : AudioInput(device)
00039 {
00040 if (!device.isEmpty())
00041 m_device_name = QByteArray(device.toAscii());
00042 else
00043 m_device_name = QByteArray();
00044 dsp_fd = -1;
00045 }
00046
00047 bool AudioInputOSS::Open(uint sample_bits, uint sample_rate, uint channels)
00048 {
00049 m_audio_sample_bits = sample_bits;
00050 m_audio_sample_rate = sample_rate;
00051
00052 int chk;
00053
00054 if (IsOpen())
00055 Close();
00056
00057
00058 dsp_fd = open(m_device_name.constData(), O_RDONLY);
00059 if (dsp_fd < 0)
00060 {
00061 LOG(VB_GENERAL, LOG_ERR, LOC_DEV + QString("open failed: ") + ENO);
00062 Close();
00063 return false;
00064 }
00065
00066 chk = 0;
00067 ioctl(dsp_fd, SNDCTL_DSP_SETTRIGGER, &chk);
00068
00069
00070 int format, choice;
00071 QString tag = QString::null;
00072 switch (sample_bits)
00073 {
00074 case 8:
00075 choice = AFMT_U8;
00076 tag = "AFMT_U8";
00077 break;
00078 case 16:
00079 default:
00080 #if HAVE_BIGENDIAN
00081 choice = AFMT_S16_BE;
00082 tag = "AFMT_S16_BE";
00083 #else
00084 choice = AFMT_S16_LE;
00085 tag = "AFMT_S16_LE";
00086 #endif
00087 break;
00088 }
00089 format = choice;
00090 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &format)) < 0)
00091 {
00092 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00093 QString("failed to set audio format %1: ").arg(tag) + ENO);
00094 Close();
00095 return false;
00096 }
00097 if (format != choice)
00098 {
00099 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00100 QString("set audio format not %1 as requested").arg(tag));
00101 Close();
00102 return false;
00103 }
00104
00105
00106 m_audio_sample_bits = choice = sample_bits;
00107 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_SAMPLESIZE, &m_audio_sample_bits)) < 0)
00108 {
00109 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00110 QString("failed to set audio sample bits to %1: ")
00111 .arg(sample_bits) + ENO);
00112 Close();
00113 return false;
00114 }
00115 if (m_audio_sample_bits != choice)
00116 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00117 QString("requested %1 sample bits, got %2")
00118 .arg(choice).arg(m_audio_sample_bits));
00119
00120 m_audio_channels = choice = channels;
00121 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_CHANNELS, &m_audio_channels)) < 0)
00122 {
00123 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00124 QString("failed to set audio channels to %1: ").arg(channels)+ENO);
00125 Close();
00126 return false;
00127 }
00128 if (m_audio_channels != choice)
00129 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00130 QString("requested %1 channels, got %2")
00131 .arg(choice).arg(m_audio_channels));
00132
00133
00134 int choice_sample_rate;
00135 m_audio_sample_rate = choice_sample_rate = sample_rate;
00136 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_SPEED, &m_audio_sample_rate)) < 0)
00137 {
00138 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00139 QString("failed to set sample rate to %1: ").arg(sample_rate)+ENO);
00140 Close();
00141 return false;
00142 }
00143 if (m_audio_sample_rate != choice_sample_rate)
00144 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00145 QString("requested sample rate %1, got %2")
00146 .arg(choice_sample_rate).arg(m_audio_sample_rate));
00147 LOG(VB_AUDIO, LOG_INFO, LOC_DEV + "device open");
00148 return true;
00149 }
00150
00151 void AudioInputOSS::Close(void)
00152 {
00153 if (IsOpen())
00154 close(dsp_fd);
00155 dsp_fd = -1;
00156 m_audio_sample_bits = 0;
00157 m_audio_sample_rate = 0;
00158 m_audio_channels = 0;
00159 LOG(VB_AUDIO, LOG_INFO, LOC_DEV + "device closed");
00160 }
00161
00162 bool AudioInputOSS::Start(void)
00163 {
00164 bool started = false;
00165 if (IsOpen())
00166 {
00167 int chk;
00168 int trig = 0;
00169 ioctl(dsp_fd, SNDCTL_DSP_SETTRIGGER, &trig);
00170 trig = PCM_ENABLE_INPUT;
00171 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_SETTRIGGER, &trig)) < 0)
00172 {
00173 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00174 QString("Start() failed: ") + ENO);
00175 }
00176 else
00177 {
00178 LOG(VB_AUDIO, LOG_INFO, LOC_DEV + "capture started");
00179 started = true;
00180 }
00181 }
00182 return started;
00183 }
00184
00185 bool AudioInputOSS::Stop(void)
00186 {
00187 bool stopped = false;
00188 int chk;
00189 int trig = 0;
00190 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_SETTRIGGER, &trig)) < 0)
00191 {
00192 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00193 QString("stop action failed: ") + ENO);
00194 }
00195 else
00196 {
00197 stopped = true;
00198 LOG(VB_AUDIO, LOG_INFO, LOC_DEV + "capture stopped");
00199 }
00200 return stopped;
00201 }
00202
00203 int AudioInputOSS::GetBlockSize(void)
00204 {
00205 int frag = 0;
00206 if (IsOpen())
00207 {
00208 int chk;
00209 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_GETBLKSIZE, &frag)) < 0)
00210 {
00211 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00212 QString("fragment size query failed, returned %1: ").arg(frag) +
00213 ENO);
00214 frag = 0;
00215 }
00216 }
00217 LOG(VB_AUDIO, LOG_INFO, LOC_DEV + QString("block size %1").arg(frag));
00218 return frag;
00219 }
00220
00221 int AudioInputOSS::GetSamples(void *buffer, uint num_bytes)
00222 {
00223 uint bytes_read = 0;
00224 if (IsOpen())
00225 {
00226 unsigned char* bufptr = (unsigned char*)buffer;
00227 int this_read;
00228 int retries = 0;
00229 while (bytes_read < num_bytes && retries < 3)
00230 {
00231 this_read = read(dsp_fd, buffer, num_bytes - bytes_read);
00232 if (this_read < 0)
00233 {
00234 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00235 QString("GetSamples read failed: ") + ENO);
00236 }
00237 else
00238 {
00239 bytes_read += this_read;
00240 bufptr += this_read;
00241 }
00242 ++retries;
00243 }
00244 if (num_bytes > (uint)bytes_read)
00245 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00246 QString("GetSamples short read, %1 of %2 bytes")
00247 .arg(bytes_read).arg(num_bytes));
00248 }
00249 return bytes_read;
00250 }
00251
00252 int AudioInputOSS::GetNumReadyBytes(void)
00253 {
00254 int readies = 0;
00255 if (IsOpen())
00256 {
00257 audio_buf_info ispace;
00258 int chk;
00259 if ((chk = ioctl(dsp_fd, SNDCTL_DSP_GETISPACE, &ispace)) < 0)
00260 {
00261 LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
00262 QString("get ready bytes failed, returned %1: ")
00263 .arg(ispace.bytes) + ENO);
00264 }
00265 else if ((readies = ispace.bytes) > 0)
00266 LOG(VB_AUDIO, LOG_DEBUG, LOC_DEV + QString("ready bytes %1")
00267 .arg(readies));
00268 }
00269 return readies;
00270 }
00271
00272