Ticket #3405: mythtv_alsa.patch
File mythtv_alsa.patch, 28.9 KB (added by , 17 years ago) |
---|
-
libs/libmythtv/alsaaudioinput.h
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301, USA. 18 */ 19 20 #ifndef _ALSAAUDIOINPUT_H_ 21 #define _ALSAAUDIOINPUT_H_ 22 23 #include <alsa/asoundlib.h> 24 25 #include "audioinput.h" 26 27 class ALSAAudioInput : public AudioInput 28 { 29 public: 30 ALSAAudioInput( QString &device ); 31 virtual ~ALSAAudioInput(); 32 33 int OpenDevice( int depth, int sample_rate, int channels ); 34 int CloseDevice(); 35 36 int StartCapture(); 37 int StopCapture(); 38 39 int GetBlockSize(); 40 41 int GetSamples(void *buffer, int num_samples); 42 int GetNumReadyBytes(); 43 44 private: 45 snd_pcm_t *audio_handle; 46 int audio_channels, audio_sample_size, audio_sample_rate; 47 48 QString device_name; 49 }; 50 51 #endif /* _ALSAAUDIOINPUT_H_ */ -
libs/libmythtv/ossaudioinput.h
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301, USA. 18 */ 19 20 #ifndef _OSSAUDIOINPUT_H_ 21 #define _OSSAUDIOINPUT_H_ 22 23 #include "audioinput.h" 24 25 class OSSAudioInput : public AudioInput 26 { 27 public: 28 OSSAudioInput( QString &device ); 29 virtual ~OSSAudioInput(); 30 31 int OpenDevice( int depth, int sample_rate, int channels ); 32 int CloseDevice(); 33 34 int StartCapture(); 35 int StopCapture(); 36 37 int GetBlockSize(); 38 39 int GetSamples(void *buffer, int num_samples); 40 int GetNumReadyBytes(); 41 42 private: 43 int audio_fd; 44 int audio_channels, audio_sample_size, audio_sample_rate; 45 46 QString device_name; 47 }; 48 49 #endif /* _OSSAUDIOINPUT_H_ */ -
libs/libmythtv/NuppelVideoRecorder.cpp
17 17 18 18 #include <qstringlist.h> 19 19 20 #include "audioinput.h" 21 20 22 #include <iostream> 21 23 using namespace std; 22 24 … … 113 115 audiobytes = 0; 114 116 audio_bits = 16; 115 117 audio_channels = 2; 116 audio_samplerate = 4 4100;118 audio_samplerate = 48000; 117 119 audio_bytes_per_sample = audio_channels * audio_bits / 8; 118 120 119 121 picture_format = PIX_FMT_YUV420P; … … 626 628 627 629 int NuppelVideoRecorder::AudioInit(bool skipdevice) 628 630 { 629 int afmt, afd; 630 int frag, blocksize = 4096; 631 AudioInput *audio_device; 632 633 int blocksize = 256; 631 634 int tmp; 632 635 633 636 if (!skipdevice) … … 642 645 643 646 return 1; 644 647 #else 645 if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK))) 648 audio_device = AudioInput::CreateDevice(audiodevice); 649 if (NULL == audio_device) 646 650 { 647 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Cannot open DSP '%1'") 648 .arg(audiodevice)); 649 perror("open"); 651 VERBOSE(VB_IMPORTANT, 652 LOC_ERR + "AudioInit: Unable to create device"); 650 653 return 1; 651 654 } 652 653 fcntl(afd, F_SETFL, fcntl(afd, F_GETFL) & ~O_NONBLOCK); 654 655 //ioctl(afd, SNDCTL_DSP_RESET, 0); 656 657 frag = (8 << 16) | (10); //8 buffers, 1024 bytes each 658 ioctl(afd, SNDCTL_DSP_SETFRAGMENT, &frag); 659 660 afmt = AFMT_S16_LE; 661 ioctl(afd, SNDCTL_DSP_SETFMT, &afmt); 662 if (afmt != AFMT_S16_LE) 655 656 if (-1 == audio_device->OpenDevice(audio_bits, 657 audio_samplerate, 658 audio_channels)) 663 659 { 664 close(afd); 665 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get 16 bit DSP"); 660 delete audio_device; 661 VERBOSE(VB_IMPORTANT, 662 LOC_ERR + "AudioInit: Unable to open device"); 666 663 return 1; 667 664 } 668 669 if (ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 || 670 ioctl(afd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 || 671 ioctl(afd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0) 665 666 blocksize = audio_device->GetBlockSize(); 667 668 delete audio_device; 669 670 if (-1 == blocksize) 672 671 { 673 close(afd); 674 QString msg = LOC_ERR + 675 QString("AudioInit(): %1 : error setting audio input device" 676 " to %2kHz/%3bits/%4channel").arg(audiodevice). 677 arg(audio_samplerate).arg(audio_bits).arg(audio_channels); 678 VERBOSE(VB_IMPORTANT, msg); 679 return 1; 672 VERBOSE(VB_IMPORTANT, 673 LOC_ERR + "AudioInit: Unable to determine block size," 674 "using default 1024 bytes"); 675 blocksize = 1024; 680 676 } 681 682 if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize)) 683 { 684 close(afd); 685 VERBOSE(VB_IMPORTANT, LOC_ERR + "AudioInit(): Can't get DSP blocksize"); 686 return(1); 687 } 688 689 close(afd); 677 678 VERBOSE(VB_IMPORTANT, 679 LOC + QString("AudioInit: Using buffer size of %1 bytes") 680 .arg(blocksize)); 690 681 #endif 691 682 } 692 683 693 audio_bytes_per_sample = audio_channels * audio_bits / 8;694 blocksize *= 4;695 696 684 audio_buffer_size = blocksize; 697 685 698 686 if (compressaudio) … … 2195 2183 2196 2184 void NuppelVideoRecorder::doAudioThread(void) 2197 2185 { 2186 AudioInput *audio_device; 2187 int act = 0, lastread = 0; 2188 unsigned char *buffer; 2189 struct timeval anow; 2190 2198 2191 #if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H) 2199 2192 VERBOSE(VB_IMPORTANT, LOC + 2200 2193 QString("doAudioThread() This Unix doesn't support" 2201 2194 " device files for audio access. Skipping")); 2202 2195 return; 2203 2196 #else 2204 int afmt = 0, trigger = 0; 2205 int afd = 0, act = 0, lastread = 0; 2206 int frag = 0, blocksize = 0; 2207 unsigned char *buffer; 2208 audio_buf_info ispace; 2209 struct timeval anow; 2210 2211 act_audio_sample = 0; 2212 2213 if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK))) 2197 2198 audio_device = AudioInput::CreateDevice(audiodevice); 2199 if (NULL == audio_device) 2214 2200 { 2215 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Cannot open DSP '%1', exiting"). 2216 arg(audiodevice)); 2217 perror("open"); 2201 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audio: Unable to create device"); 2218 2202 return; 2219 2203 } 2220 2221 fcntl(afd, F_SETFL, fcntl(afd, F_GETFL) & ~O_NONBLOCK); 2222 //ioctl(afd, SNDCTL_DSP_RESET, 0); 2223 2224 frag = (8 << 16) | (10); //8 buffers, 1024 bytes each 2225 ioctl(afd, SNDCTL_DSP_SETFRAGMENT, &frag); 2226 2227 afmt = AFMT_S16_LE; 2228 ioctl(afd, SNDCTL_DSP_SETFMT, &afmt); 2229 if (afmt != AFMT_S16_LE) 2204 2205 if (-1 == audio_device->OpenDevice(audio_bits, 2206 audio_samplerate, 2207 audio_channels)) 2230 2208 { 2231 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get 16 bit DSP, exiting");2232 close(afd);2209 delete audio_device; 2210 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audio: Unable to open device"); 2233 2211 return; 2234 2212 } 2235 2213 2236 if (ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 ||2237 ioctl(afd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 ||2238 ioctl(afd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0)2239 {2240 VERBOSE(VB_IMPORTANT, LOC_ERR + QString(" %1: error setting audio input device to "2241 "%2 kHz/%3 bits/%4 channel").2242 arg(audiodevice).arg(audio_samplerate).2243 arg(audio_bits).arg(audio_channels));2244 close(afd);2245 return;2246 }2247 2248 2214 audio_bytes_per_sample = audio_channels * audio_bits / 8; 2249 2215 2250 if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize))2251 {2252 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get DSP blocksize, exiting");2253 close(afd);2254 return;2255 }2256 2257 blocksize *= 4; // allways read 4*blocksize2258 2259 if (blocksize != audio_buffer_size)2260 {2261 VERBOSE(VB_IMPORTANT, LOC +2262 QString("Warning, audio blocksize = '%1' while audio_buffer_size='%2'").2263 arg(blocksize).arg(audio_buffer_size));2264 }2265 2266 2216 buffer = new unsigned char[audio_buffer_size]; 2267 2217 2268 /* trigger record */2269 trigger = 0;2270 ioctl(afd,SNDCTL_DSP_SETTRIGGER,&trigger);2271 2272 trigger = PCM_ENABLE_INPUT;2273 ioctl(afd,SNDCTL_DSP_SETTRIGGER,&trigger);2274 2275 2218 audiopaused = false; 2219 2220 if (-1 == audio_device->StartCapture()) 2221 { 2222 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audio: Unable to start capture"); 2223 delete audio_device; 2224 return; 2225 } 2226 2227 VERBOSE(VB_IMPORTANT, LOC + "Audio: Successfully opened & started device"); 2276 2228 while (childrenLive) 2277 2229 { 2278 2230 if (request_pause) … … 2288 2240 } 2289 2241 audiopaused = false; 2290 2242 2291 if (audio_buffer_size != (lastread = read(afd, buffer, 2292 audio_buffer_size))) 2243 if (audio_buffer_size != 2244 (lastread = audio_device->GetSamples(buffer, 2245 audio_buffer_size))) 2293 2246 { 2294 2247 VERBOSE(VB_IMPORTANT, LOC_ERR + 2295 2248 QString("Only read %1 bytes of %2 bytes from '%3"). 2296 2249 arg(lastread).arg(audio_buffer_size).arg(audiodevice)); 2297 2250 perror("read audio"); 2251 2252 // TODO: Potentially evil!!! 2253 if (0 > lastread) 2254 { 2255 continue; 2256 } 2257 else if (0 == lastread) 2258 { 2259 continue; 2260 } 2298 2261 } 2299 2262 2300 2263 /* record the current time */ 2301 2264 /* Don't assume that the sound device's record buffer is empty 2302 2265 (like we used to.) Measure to see how much stuff is in there, 2303 2266 and correct for it when calculating the timestamp */ 2304 2267 gettimeofday(&anow, &tzone); 2305 ioctl( afd, SNDCTL_DSP_GETISPACE, &ispace );2306 2268 2307 2269 act = act_audio_buffer; 2308 2270 2309 2271 if (!audiobuffer[act]->freeToBuffer) 2310 2272 { 2311 VERBOSE(VB_IMPORTANT, LOC_ERR + "Ran out of free AUDIO buffers :-("); 2273 VERBOSE(VB_IMPORTANT, 2274 LOC_ERR + "Audio: Ran out of free AUDIO buffers :-("); 2312 2275 act_audio_sample++; 2313 2276 continue; 2314 2277 } … … 2323 2286 audio chunk. So, subtract off the length of the chunk 2324 2287 and the length of audio still in the capture buffer. */ 2325 2288 audiobuffer[act]->timecode -= (int)( 2326 ( ispace.fragments * ispace.fragsize+ audio_buffer_size)2289 (audio_device->GetNumReadyBytes() + audio_buffer_size) 2327 2290 * 1000.0 / (audio_samplerate * audio_bytes_per_sample)); 2328 2291 2329 2292 memcpy(audiobuffer[act]->buffer, buffer, audio_buffer_size); … … 2338 2301 } 2339 2302 2340 2303 delete [] buffer; 2341 close(afd);2304 delete audio_device; 2342 2305 #endif 2343 2306 } 2344 2307 -
libs/libmythtv/libmythtv.pro
365 365 366 366 # Simple NuppelVideo Recorder 367 367 using_ffmpeg_threads:DEFINES += USING_FFMPEG_THREADS 368 HEADERS += NuppelVideoRecorder.h fifowriter.h 369 SOURCES += NuppelVideoRecorder.cpp fifowriter.cpp 368 HEADERS += NuppelVideoRecorder.h fifowriter.h audioinput.h 369 SOURCES += NuppelVideoRecorder.cpp fifowriter.cpp audioinput.cpp 370 371 using_oss { 372 DEFINES += USING_OSS 373 HEADERS += ossaudioinput.h 374 SOURCES += ossaudioinput.cpp 375 } 376 377 using_alsa { 378 DEFINES += USE_ALSA 379 HEADERS += alsaaudioinput.h 380 SOURCES += alsaaudioinput.cpp 381 LIBS += $$ALSA_LIBS 382 } 370 383 371 384 # Support for Video4Linux devices 372 385 using_v4l { -
libs/libmythtv/audioinput.cpp
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301, USA. 18 */ 19 20 #include "audioinput.h" 21 #include "mythcontext.h" 22 23 #ifdef USE_ALSA 24 #include "alsaaudioinput.h" 25 #endif 26 27 #ifdef USING_OSS 28 #include "ossaudioinput.h" 29 #endif 30 31 AudioInput * AudioInput::CreateDevice(QString device) 32 { 33 AudioInput *dev = NULL; 34 35 if (device.startsWith("ALSA:")) 36 { 37 #ifdef USE_ALSA 38 dev = new ALSAAudioInput(device.remove(0,5)); 39 #else 40 VERBOSE(VB_AUDIO, "ALSA input support not available"); 41 #endif 42 } 43 else 44 { 45 #ifdef USING_OSS 46 dev = new OSSAudioInput(device); 47 #else 48 VERBOSE(VB_AUDIO, "OSS input support not available"); 49 #endif 50 } 51 52 return dev; 53 } 54 -
libs/libmythtv/ossaudioinput.cpp
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * Based upon OSS code from NuppelVideoRecorder.cpp 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 * 02110-1301, USA. 19 */ 20 21 #include <fcntl.h> 22 #include <unistd.h> 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 #include <sys/ioctl.h> 26 27 #include "mythconfig.h" 28 #ifdef HAVE_SYS_SOUNDCARD_H 29 #include <sys/soundcard.h> 30 #elif HAVE_SOUNDCARD_H 31 #include <soundcard.h> 32 #endif 33 34 #include "ossaudioinput.h" 35 #include "mythcontext.h" 36 37 #define LOC QString("OSSAudioInput: ") 38 39 OSSAudioInput::OSSAudioInput( QString &device ) 40 { 41 audio_fd = 0; 42 43 audio_channels = 0; 44 audio_sample_size = 0; 45 audio_sample_rate = 0; 46 47 device_name = device; 48 } 49 50 OSSAudioInput::~OSSAudioInput() 51 { 52 CloseDevice(); 53 } 54 55 int OSSAudioInput::OpenDevice( int sample_size, int sample_rate, int channels ) 56 { 57 int retval = 0; 58 int format; 59 int trigger; 60 61 // Open the device 62 retval = open(device_name.ascii(), O_RDONLY | O_NONBLOCK); 63 if (0 <= retval) 64 { 65 audio_fd = 0; 66 VERBOSE(VB_AUDIO, QString(LOC + "Cannot open DSP '%1', exiting") 67 .arg(device_name)); 68 } 69 70 if (0 <= retval) 71 { 72 audio_fd = retval; 73 74 // Disable trigger 75 trigger = 0; 76 retval = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &trigger); 77 if (0 > retval) 78 { 79 VERBOSE(VB_AUDIO, LOC + "Can't stop trigger, exiting"); 80 } 81 82 } 83 84 if (0 <= retval) 85 { 86 // Set blocking IO 87 retval = fcntl(audio_fd, F_SETFL, 88 fcntl(audio_fd, F_GETFL) & ~O_NONBLOCK); 89 if (0 > retval) 90 { 91 VERBOSE(VB_AUDIO, LOC + "Unable to set blocking, exiting"); 92 } 93 } 94 95 if (0 <= retval) 96 { 97 // Set format 98 format = AFMT_S16_LE; 99 retval = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format); 100 if (0 > retval) 101 { 102 VERBOSE(VB_AUDIO, LOC + "Can't get 16 bit DSP, exiting"); 103 } 104 } 105 106 if (0 <= retval) 107 { 108 // Set sample size 109 audio_sample_size = sample_size; 110 retval = ioctl(audio_fd, SNDCTL_DSP_SAMPLESIZE, &audio_sample_size); 111 if (0 > retval) 112 { 113 VERBOSE(VB_AUDIO, LOC + "Unable to set sample size"); 114 } 115 } 116 117 if (0 <= retval) 118 { 119 // Set channels 120 audio_channels = channels; 121 retval = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &audio_channels); 122 if (0 > retval) 123 { 124 VERBOSE(VB_AUDIO, LOC + "Unable to set number of channels"); 125 } 126 } 127 128 if (0 <= retval) 129 { 130 // Set sample rate 131 audio_sample_rate = sample_rate; 132 retval = ioctl(audio_fd, SNDCTL_DSP_SPEED, &audio_sample_rate); 133 if (0 > retval) 134 { 135 VERBOSE(VB_AUDIO, LOC + "Unable to set sample rate"); 136 } 137 } 138 139 if (0 > retval) 140 { 141 CloseDevice(); 142 } 143 else 144 { 145 VERBOSE(VB_AUDIO, LOC + "Opened device" + device_name); 146 } 147 148 return retval; 149 } 150 151 int OSSAudioInput::CloseDevice() 152 { 153 if (0 < audio_fd) 154 { 155 close(audio_fd); 156 audio_fd = 0; 157 158 VERBOSE(VB_AUDIO, LOC + "Closed device" + device_name); 159 } 160 161 return 0; 162 } 163 164 int OSSAudioInput::StartCapture() 165 { 166 int retval = 0; 167 int trigger; 168 169 if (0 == audio_fd) 170 { 171 retval = -1; 172 } 173 174 if (0 <= retval) 175 { 176 trigger = PCM_ENABLE_INPUT; 177 retval = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &trigger); 178 if (0 > retval) 179 { 180 VERBOSE(VB_AUDIO, LOC + "Unable to start capture"); 181 } 182 else 183 { 184 VERBOSE(VB_AUDIO, LOC + "Started capture on " + device_name); 185 } 186 } 187 188 return retval; 189 } 190 191 int OSSAudioInput::StopCapture() 192 { 193 return -1; 194 } 195 196 int OSSAudioInput::GetBlockSize() 197 { 198 int retval = 0; 199 int fragment_size; 200 201 if (0 == audio_fd) 202 { 203 retval = -1; 204 } 205 206 if (0 <= retval) 207 { 208 retval = ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size); 209 } 210 211 if (0 <= retval) 212 { 213 retval = fragment_size; 214 } 215 216 return retval; 217 } 218 219 int OSSAudioInput::GetSamples(void *buffer, int num_bytes) 220 { 221 int retval = 0; 222 223 224 if (0 != (num_bytes % ((audio_sample_size * audio_channels) / 8))) 225 { 226 VERBOSE(VB_AUDIO, LOC + "Invalid num_bytes"); 227 retval = -1; 228 } 229 230 if (0 <= retval) 231 { 232 retval = read(audio_fd, buffer, num_bytes); 233 } 234 235 return retval; 236 } 237 238 int OSSAudioInput::GetNumReadyBytes() 239 { 240 int retval = 0; 241 audio_buf_info ispace; 242 243 if (0 == audio_fd) 244 { 245 retval = -1; 246 } 247 248 if (0 <= retval) 249 { 250 retval = ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &ispace); 251 if (0 > retval) 252 { 253 VERBOSE(VB_AUDIO, LOC + "Unable to get ready bytes"); 254 } 255 } 256 257 if (0 <= retval) 258 { 259 retval = ispace.bytes; 260 } 261 262 return retval; 263 } -
libs/libmythtv/audioinput.h
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301, USA. 18 */ 19 20 #ifndef _AUDIOINPUT_H_ 21 #define _AUDIOINPUT_H_ 22 23 #include <qstring.h> 24 25 class AudioInput 26 { 27 public: 28 29 // Factory function 30 static AudioInput * CreateDevice( QString device ); 31 32 virtual ~AudioInput() {}; 33 34 virtual int OpenDevice( int depth, int sample_rate, int channels ) =0; 35 virtual int CloseDevice() =0; 36 37 virtual int StartCapture() =0; 38 virtual int StopCapture() =0; 39 40 virtual int GetBlockSize() =0; 41 42 virtual int GetSamples(void *buffer, int num_samples) =0; 43 virtual int GetNumReadyBytes() =0; 44 }; 45 46 47 #endif /* _AUDIOINPUT_H_ */ 48 -
libs/libmythtv/videosource.cpp
774 774 { 775 775 public: 776 776 AudioDevice(const CaptureCard &parent) : 777 PathSetting(this, true),777 PathSetting(this, false), 778 778 CaptureCardDBStorage(this, parent, "audiodevice") 779 779 { 780 780 setLabel(QObject::tr("Audio device")); -
libs/libmythtv/alsaaudioinput.cpp
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301, USA. 18 */ 19 20 #include <fcntl.h> 21 #include <unistd.h> 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 #include <sys/ioctl.h> 25 26 #include <iostream> 27 28 #include "mythconfig.h" 29 30 #include "alsaaudioinput.h" 31 #include "mythcontext.h" 32 33 #define LOC QString("ALSAAudioInput: ") 34 35 ALSAAudioInput::ALSAAudioInput( QString &device ) 36 { 37 audio_handle = NULL; 38 39 audio_channels = 0; 40 audio_sample_size = 0; 41 audio_sample_rate = 0; 42 43 device_name = device; 44 } 45 46 ALSAAudioInput::~ALSAAudioInput() 47 { 48 CloseDevice(); 49 } 50 51 int ALSAAudioInput::OpenDevice( int sample_size, int sample_rate, int channels ) 52 { 53 int retval = 0; 54 snd_pcm_hw_params_t * hw_params; 55 56 // Open the device 57 retval = snd_pcm_open(&audio_handle, 58 device_name.ascii(), SND_PCM_STREAM_CAPTURE, 0); 59 if (0 > retval) { 60 audio_handle = NULL; 61 VERBOSE(VB_AUDIO, 62 QString(LOC + "Cannot open ALSA '%1', exiting") 63 .arg(device_name)); 64 } 65 66 if (0 <= retval) 67 { 68 // Allocate hw params structure 69 retval = snd_pcm_hw_params_malloc(&hw_params); 70 } 71 72 if (0 <= retval) 73 { 74 // Initialize hw params 75 retval = snd_pcm_hw_params_any(audio_handle, hw_params); 76 } 77 78 if (0 <= retval) 79 { 80 // Set interleaved access 81 retval = snd_pcm_hw_params_set_access(audio_handle, 82 hw_params, 83 SND_PCM_ACCESS_RW_INTERLEAVED); 84 } 85 86 if (0 <= retval) 87 { 88 // Set format 89 retval = snd_pcm_hw_params_set_format(audio_handle, 90 hw_params, 91 SND_PCM_FORMAT_S16_LE); 92 } 93 94 if (0 <= retval) 95 { 96 // Set sampling rate 97 audio_sample_rate = sample_rate; 98 retval = snd_pcm_hw_params_set_rate(audio_handle, 99 hw_params, 100 audio_sample_rate, 0); 101 } 102 103 if (0 <= retval) 104 { 105 // Set channels 106 audio_channels = channels; 107 retval = snd_pcm_hw_params_set_channels(audio_handle, 108 hw_params, 109 audio_channels); 110 } 111 112 if (0 <= retval) 113 { 114 // Set sample size 115 audio_sample_size = sample_size; 116 117 // Apply settings 118 retval = snd_pcm_hw_params(audio_handle, hw_params); 119 } 120 121 snd_pcm_hw_params_free(hw_params); 122 123 if (0 <= retval) 124 { 125 VERBOSE(VB_AUDIO, LOC + "Opened device " + device_name); 126 } 127 128 return retval; 129 } 130 131 int ALSAAudioInput::CloseDevice() 132 { 133 if (0 < audio_handle) 134 { 135 snd_pcm_close(audio_handle); 136 audio_handle = 0; 137 138 VERBOSE(VB_AUDIO, LOC + "Closed device" + device_name); 139 } 140 141 return 0; 142 } 143 144 int ALSAAudioInput::StartCapture() 145 { 146 int retval = 0; 147 148 if (0 == audio_handle) 149 { 150 retval = -1; 151 } 152 153 if (0 <= retval) 154 { 155 retval = snd_pcm_prepare(audio_handle); 156 } 157 158 if (0 <= retval) 159 { 160 VERBOSE(VB_AUDIO, LOC + "Started capture on " + device_name); 161 } 162 else 163 { 164 VERBOSE(VB_AUDIO, LOC + "Unable to start capture"); 165 } 166 167 return retval; 168 } 169 170 int ALSAAudioInput::StopCapture() 171 { 172 return -1; 173 } 174 175 int ALSAAudioInput::GetBlockSize() 176 { 177 int retval = 0; 178 snd_pcm_uframes_t buffer_size, period_size; 179 180 if (NULL == audio_handle) 181 { 182 retval = -1; 183 } 184 185 if (0 <= retval) 186 { 187 retval = snd_pcm_get_params(audio_handle, &buffer_size, &period_size); 188 } 189 190 if (0 <= retval) 191 { 192 retval = (period_size * audio_channels * audio_sample_size) / 8; 193 } 194 195 return retval; 196 } 197 198 int ALSAAudioInput::GetSamples(void *buffer, int num_bytes) 199 { 200 int retval = 0; 201 int frame_size; 202 203 frame_size = (audio_sample_size * audio_channels) / 8; 204 205 if (0 != (num_bytes % frame_size)) 206 { 207 VERBOSE(VB_AUDIO, LOC + "Invalid num_bytes"); 208 retval = -1; 209 } 210 211 if (0 <= retval) 212 { 213 retval = snd_pcm_readi(audio_handle, buffer, num_bytes/frame_size); 214 if (0 > retval) 215 { 216 retval = snd_pcm_recover(audio_handle, retval, 1); 217 } 218 } 219 220 if (0 <= retval) 221 { 222 retval *= frame_size; 223 } 224 225 return retval; 226 } 227 228 int ALSAAudioInput::GetNumReadyBytes() 229 { 230 int retval = 0; 231 snd_pcm_sframes_t delay; 232 233 if (NULL == audio_handle) 234 { 235 retval = -1; 236 } 237 238 if (0 <= retval) 239 { 240 retval = snd_pcm_delay(audio_handle, &delay); 241 } 242 243 if (0 <= retval) 244 { 245 retval = (delay * audio_channels * audio_sample_size) / 8; 246 } 247 248 return retval; 249 } 250