Ticket #3405: 3405-v1.patch
File 3405-v1.patch, 33.0 KB (added by , 16 years ago) |
---|
-
libs/libmythtv/NuppelVideoRecorder.cpp
5 5 #include <sys/types.h> 6 6 #include <sys/stat.h> 7 7 #include "mythconfig.h" 8 #ifdef HAVE_SYS_SOUNDCARD_H9 #include <sys/soundcard.h>10 #elif HAVE_SOUNDCARD_H11 #include <soundcard.h>12 #endif13 8 #include <sys/ioctl.h> 14 9 #include <sys/mman.h> 15 10 #include <cerrno> … … 17 12 18 13 #include <qstringlist.h> 19 14 15 #include <algorithm> 20 16 #include <iostream> 21 17 using namespace std; 22 18 23 19 #include "mythcontext.h" 24 20 #include "NuppelVideoRecorder.h" 21 #include "audioinput.h" 25 22 #include "vbitext/cc.h" 26 23 #include "channelbase.h" 27 24 #include "filtermanager.h" … … 57 54 #define LOC_ERR QString("NVR(%1) Error: ").arg(videodevice) 58 55 59 56 NuppelVideoRecorder::NuppelVideoRecorder(TVRec *rec, ChannelBase *channel) 60 : RecorderBase(rec) 57 : RecorderBase(rec), audio_device(NULL) 61 58 { 62 59 channelObj = channel; 63 60 … … 189 186 lame_close(gf); 190 187 if (strm) 191 188 delete [] strm; 189 if (audio_device) 190 { 191 delete audio_device; 192 audio_device = NULL; 193 } 192 194 if (fd >= 0) 193 195 close(fd); 194 196 if (seektable) … … 663 665 664 666 int NuppelVideoRecorder::AudioInit(bool skipdevice) 665 667 { 666 int afmt, afd; 667 int frag, blocksize = 4096; 668 int blocksize = 4096; 668 669 int tmp; 669 670 670 671 if (!skipdevice) … … 679 680 680 681 return 1; 681 682 #else 682 if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK))) 683 audio_device = AudioInput::CreateDevice(audiodevice); 684 if (!audio_device) 683 685 { 684 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Cannot open DSP '%1'") 685 .arg(audiodevice)); 686 perror("open"); 686 VERBOSE(VB_IMPORTANT, 687 LOC_ERR + "AudioInit: Unable to create device"); 687 688 return 1; 688 689 } 689 690 fcntl(afd, F_SETFL, fcntl(afd, F_GETFL) & ~O_NONBLOCK);691 692 //ioctl(afd, SNDCTL_DSP_RESET, 0);693 694 frag = (8 << 16) | (10); //8 buffers, 1024 bytes each695 ioctl(afd, SNDCTL_DSP_SETFRAGMENT, &frag);696 697 afmt = AFMT_S16_LE;698 ioctl(afd, SNDCTL_DSP_SETFMT, &afmt);699 if (afmt != AFMT_S16_LE)700 {701 close(afd);702 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get 16 bit DSP");703 return 1;704 }705 690 706 if (ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 || 707 ioctl(afd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 || 708 ioctl(afd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0) 691 if (!audio_device->Open(audio_bits, audio_samplerate, audio_channels)) 709 692 { 710 close(afd); 711 QString msg = LOC_ERR + 712 QString("AudioInit(): %1 : error setting audio input device" 713 " to %2kHz/%3bits/%4channel").arg(audiodevice). 714 arg(audio_samplerate).arg(audio_bits).arg(audio_channels); 715 VERBOSE(VB_IMPORTANT, msg); 693 VERBOSE(VB_IMPORTANT, 694 LOC_ERR + "AudioInit: Unable to open device"); 716 695 return 1; 717 696 } 718 697 719 if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize)) 698 blocksize = audio_device->GetBlockSize(); 699 700 if (-1 == blocksize) 720 701 { 721 close(afd); 722 VERBOSE(VB_IMPORTANT, LOC_ERR + "AudioInit(): Can't get DSP blocksize"); 723 return(1); 702 VERBOSE(VB_GENERAL, 703 LOC_ERR + "AudioInit: Unable to determine block size," 704 "using default of 1024 bytes"); 705 blocksize = 1024; 724 706 } 725 707 726 close(afd); 708 VERBOSE(VB_AUDIO, 709 LOC + QString("AudioInit: Using buffer size of %1 bytes") 710 .arg(blocksize)); 711 712 audio_device->Close(); 727 713 #endif 728 714 } 729 715 730 audio_bytes_per_sample = audio_channels * audio_bits / 8;731 blocksize *= 4;732 733 716 audio_buffer_size = blocksize; 734 717 735 718 if (compressaudio) … … 2233 2216 2234 2217 void NuppelVideoRecorder::doAudioThread(void) 2235 2218 { 2236 #if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H) 2237 VERBOSE(VB_IMPORTANT, LOC + 2238 QString("doAudioThread() This Unix doesn't support" 2239 " device files for audio access. Skipping")); 2240 return; 2241 #else 2242 int afmt = 0, trigger = 0; 2243 int afd = 0, act = 0, lastread = 0; 2244 int frag = 0, blocksize = 0; 2245 unsigned char *buffer; 2246 audio_buf_info ispace; 2247 struct timeval anow; 2248 2249 act_audio_sample = 0; 2250 2251 if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK))) 2219 if (!audio_device) 2252 2220 { 2253 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Cannot open DSP '%1', exiting"). 2254 arg(audiodevice)); 2255 perror("open"); 2221 VERBOSE(VB_GENERAL, LOC + "Audio: no audio device"); 2256 2222 return; 2257 2223 } 2258 2259 fcntl(afd, F_SETFL, fcntl(afd, F_GETFL) & ~O_NONBLOCK); 2260 //ioctl(afd, SNDCTL_DSP_RESET, 0); 2261 2262 frag = (8 << 16) | (10); //8 buffers, 1024 bytes each 2263 ioctl(afd, SNDCTL_DSP_SETFRAGMENT, &frag); 2264 2265 afmt = AFMT_S16_LE; 2266 ioctl(afd, SNDCTL_DSP_SETFMT, &afmt); 2267 if (afmt != AFMT_S16_LE) 2224 2225 int act = 0, lastread = 0; 2226 unsigned char *buffer; 2227 struct timeval anow; 2228 2229 if (!audio_device->Open(audio_bits, 2230 audio_samplerate, 2231 audio_channels)) 2268 2232 { 2269 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get 16 bit DSP, exiting"); 2270 close(afd); 2233 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audio: Unable to open device"); 2271 2234 return; 2272 2235 } 2273 2236 2274 if (ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 ||2275 ioctl(afd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 ||2276 ioctl(afd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0)2277 {2278 VERBOSE(VB_IMPORTANT, LOC_ERR + QString(" %1: error setting audio input device to "2279 "%2 kHz/%3 bits/%4 channel").2280 arg(audiodevice).arg(audio_samplerate).2281 arg(audio_bits).arg(audio_channels));2282 close(afd);2283 return;2284 }2285 2286 2237 audio_bytes_per_sample = audio_channels * audio_bits / 8; 2287 2238 2288 if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize))2289 {2290 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get DSP blocksize, exiting");2291 close(afd);2292 return;2293 }2294 2295 blocksize *= 4; // allways read 4*blocksize2296 2297 if (blocksize != audio_buffer_size)2298 {2299 VERBOSE(VB_IMPORTANT, LOC +2300 QString("Warning, audio blocksize = '%1' while audio_buffer_size='%2'").2301 arg(blocksize).arg(audio_buffer_size));2302 }2303 2304 2239 buffer = new unsigned char[audio_buffer_size]; 2305 2240 2306 /* trigger record */2307 trigger = 0;2308 ioctl(afd,SNDCTL_DSP_SETTRIGGER,&trigger);2309 2310 trigger = PCM_ENABLE_INPUT;2311 ioctl(afd,SNDCTL_DSP_SETTRIGGER,&trigger);2312 2313 2241 audiopaused = false; 2242 2243 if (!audio_device->Start()) 2244 { 2245 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audio: Unable to start capture"); 2246 return; 2247 } 2248 2314 2249 while (childrenLive) 2315 2250 { 2316 2251 if (request_pause) … … 2326 2261 } 2327 2262 audiopaused = false; 2328 2263 2329 if (audio_buffer_size != (lastread = read(afd, buffer,2330 audio_buffer_size)))2264 lastread = audio_device->GetSamples(buffer, audio_buffer_size); 2265 if (audio_buffer_size != lastread) 2331 2266 { 2332 2267 VERBOSE(VB_IMPORTANT, LOC_ERR + 2333 2268 QString("Only read %1 bytes of %2 bytes from '%3"). 2334 arg(lastread).arg(audio_buffer_size).arg(audiodevice) );2335 perror("read audio");2269 arg(lastread).arg(audio_buffer_size).arg(audiodevice) + 2270 ENO); 2336 2271 } 2337 2272 2338 2273 /* record the current time */ … … 2340 2275 (like we used to.) Measure to see how much stuff is in there, 2341 2276 and correct for it when calculating the timestamp */ 2342 2277 gettimeofday(&anow, &tzone); 2343 i octl( afd, SNDCTL_DSP_GETISPACE, &ispace);2278 int bytes_read = max(audio_device->GetNumReadyBytes(), 0); 2344 2279 2345 2280 act = act_audio_buffer; 2346 2281 … … 2361 2296 audio chunk. So, subtract off the length of the chunk 2362 2297 and the length of audio still in the capture buffer. */ 2363 2298 audiobuffer[act]->timecode -= (int)( 2364 ( ispace.fragments * ispace.fragsize+ audio_buffer_size)2299 (bytes_read + audio_buffer_size) 2365 2300 * 1000.0 / (audio_samplerate * audio_bytes_per_sample)); 2366 2301 2367 2302 memcpy(audiobuffer[act]->buffer, buffer, audio_buffer_size); … … 2376 2311 } 2377 2312 2378 2313 delete [] buffer; 2379 close(afd); 2380 #endif 2314 2315 if (audio_device->IsOpen()) 2316 audio_device->Close(); 2381 2317 } 2382 2318 2383 2319 struct VBIData -
libs/libmythtv/libmythtv.pro
97 97 cygwin:QMAKE_LFLAGS_SHLIB += -Wl,--noinhibit-exec 98 98 cygwin:DEFINES += _WIN32 99 99 100 # Enable Linux Open Sound System support 101 using_oss:DEFINES += USING_OSS 100 # Enable sound systems support 101 using_alsa:DEFINES += USING_ALSA 102 using_arts:DEFINES += USING_ARTS 103 using_jack:DEFINES += USING_JACK 104 using_oss: DEFINES += USING_OSS 105 macx: DEFINES += USING_COREAUDIO 106 102 107 # Enable Valgrind, i.e. disable some timeouts 103 108 using_valgrind:DEFINES += USING_VALGRIND 104 109 -
libs/libmythtv/NuppelVideoRecorder.h
44 44 class ChannelBase; 45 45 class FilterManager; 46 46 class FilterChain; 47 class AudioInput; 47 48 48 49 class MPUBLIC NuppelVideoRecorder : public RecorderBase, public CC608Reader 49 50 { … … 152 153 int inputchannel; 153 154 int compression; 154 155 int compressaudio; 156 AudioInput *audio_device; 155 157 unsigned long long audiobytes; 156 158 int audio_channels; 157 159 int audio_bits; -
libs/libmythtv/videosource.cpp
809 809 { 810 810 public: 811 811 AudioDevice(const CaptureCard &parent) : 812 PathSetting(this, true),812 PathSetting(this, false), 813 813 CaptureCardDBStorage(this, parent, "audiodevice") 814 814 { 815 815 setLabel(QObject::tr("Audio device")); 816 #ifdef USING_OSS 816 817 QDir dev("/dev", "dsp*", QDir::Name, QDir::System); 817 818 fillSelectionsFromDir(dev); 818 819 dev.setPath("/dev/sound"); 819 820 fillSelectionsFromDir(dev); 820 addSelection(QObject::tr("(None)"), "/dev/null"); 821 #endif 822 #ifdef USING_ALSA 823 addSelection("ALSA:default", "ALSA:default"); 824 #endif 825 #ifdef USING_ARTS 826 //addSelection("ARTS:", "ARTS:"); 827 #endif 828 #ifdef USING_JACK 829 //addSelection("JACK:output", "JACK:output"); 830 #endif 831 #ifdef USING_COREAUDIO 832 //addSelection("CoreAudio:", "CoreAudio:"); 833 #endif 834 addSelection(QObject::tr("(None)"), "NULL"); 821 835 }; 822 836 }; 823 837 -
libs/libmyth/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 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 20 21 #ifndef _AUDIOINPUT_H_ 22 #define _AUDIOINPUT_H_ 23 24 #include <qstring.h> 25 26 class AudioInput 27 { 28 public: 29 virtual ~AudioInput() {} 30 31 virtual bool Open(uint depth, uint sample_rate, uint channels) = 0; 32 virtual bool IsOpen(void) const = 0; 33 virtual void Close(void) = 0; 34 35 virtual bool Start(void) = 0; 36 virtual bool Stop(void) = 0; 37 38 virtual int GetBlockSize(void) = 0; 39 virtual int GetSamples(void *buffer, uint num_samples) = 0; 40 virtual int GetNumReadyBytes(void) = 0; 41 42 // Factory function 43 static AudioInput *CreateDevice(const QString &device); 44 45 protected: 46 AudioInput(const QString &device); 47 QString m_device_name; 48 int m_audio_channels; 49 int m_audio_sample_size; 50 int m_audio_sample_rate; 51 }; 52 53 54 #endif /* _AUDIOINPUT_H_ */ 55 -
libs/libmyth/audioinputoss.cpp
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * Copyright (C) 2007 Daniel Kristjansson 4 * Copyright (C) 2003-2007 Others who contributed to NuppelVideoRecorder.cpp 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 * 02110-1301, USA. 20 */ 21 22 #include <fcntl.h> 23 #include <unistd.h> 24 #include <sys/types.h> 25 #include <sys/stat.h> 26 #include <sys/ioctl.h> 27 28 #include "mythconfig.h" 29 #ifdef HAVE_SYS_SOUNDCARD_H 30 #include <sys/soundcard.h> 31 #elif HAVE_SOUNDCARD_H 32 #include <soundcard.h> 33 #endif 34 35 #include "audioinputoss.h" 36 #include "mythcontext.h" 37 38 #define LOC QString("AudInOSS(%1): ").arg(m_device_name) 39 #define LOC_WARN QString("AudInOSS(%1) Warning: ").arg(m_device_name) 40 #define LOC_ERR QString("AudInOSS(%1) Error: ").arg(m_device_name) 41 42 AudioInputOSS::AudioInputOSS(const QString &device) : 43 AudioInput(device), m_audio_fd(-1) 44 { 45 } 46 47 AudioInputOSS::~AudioInputOSS() 48 { 49 Close(); 50 } 51 52 bool AudioInputOSS::Open(uint sample_size, uint sample_rate, uint channels) 53 { 54 int desired_format = AFMT_S16_LE, format; 55 56 if (IsOpen()) 57 Close(); 58 59 // Open the device 60 const QString tmp = QDeepCopy<QString>(m_device_name); 61 m_audio_fd = open(tmp.ascii(), O_RDONLY | O_NONBLOCK); 62 if (m_audio_fd < 0) 63 { 64 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Cannot open '%1'") 65 .arg(m_device_name) + ENO); 66 67 return false; 68 } 69 70 // Disable trigger 71 int trigger = 0; 72 int ret = ioctl(m_audio_fd, SNDCTL_DSP_SETTRIGGER, &trigger); 73 if (0 != ret) 74 { 75 VERBOSE(VB_AUDIO, LOC_WARN + "Can't stop capture" + ENO); 76 } 77 78 // Get file descriptor flags 79 int flags = fcntl(m_audio_fd, F_GETFL); 80 if (-1 == flags) 81 { 82 VERBOSE(VB_AUDIO, LOC_WARN + "Unable to get blocking status" + ENO); 83 } 84 else 85 { 86 // Set blocking IO 87 ret = fcntl(m_audio_fd, F_SETFL, flags & ~O_NONBLOCK); 88 if (-1 == ret) 89 VERBOSE(VB_AUDIO, LOC_WARN + "Unable to set blocking" + ENO); 90 } 91 92 // Set buffering hints 93 { 94 int bufcnt = 8; // 8 buffers 95 int bufbits = 10; // 1<<10 = 1024 bytes each 96 int frag = (bufcnt << 16) | (bufbits); 97 ret = ioctl(m_audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag); 98 } 99 100 // Set format 101 format = desired_format; 102 ret = ioctl(m_audio_fd, SNDCTL_DSP_SETFMT, &format); 103 if ((-1 == ret) || (desired_format != format)) 104 { 105 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to set desired format"); 106 goto err_exit; 107 } 108 109 // Set sample size 110 m_audio_sample_size = sample_size; 111 ret = ioctl(m_audio_fd, SNDCTL_DSP_SAMPLESIZE, &m_audio_sample_size); 112 if (ret < 0) 113 { 114 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to set sample size" + ENO); 115 goto err_exit; 116 } 117 118 // Set channels 119 m_audio_channels = channels; 120 ret = ioctl(m_audio_fd, SNDCTL_DSP_CHANNELS, &m_audio_channels); 121 if (ret < 0) 122 { 123 VERBOSE(VB_IMPORTANT, LOC_ERR + 124 "Unable to set number of channels" + ENO); 125 goto err_exit; 126 } 127 128 // Set sample rate 129 m_audio_sample_rate = sample_rate; 130 ret = ioctl(m_audio_fd, SNDCTL_DSP_SPEED, &m_audio_sample_rate); 131 if (ret < 0) 132 { 133 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to set sample rate" + ENO); 134 goto err_exit; 135 } 136 137 return true; 138 139 err_exit: 140 close(m_audio_fd); 141 m_audio_fd = -1; 142 m_audio_sample_size = 0; 143 m_audio_sample_rate = 0; 144 m_audio_channels = 0; 145 return false; 146 } 147 148 void AudioInputOSS::Close(void) 149 { 150 VERBOSE(VB_AUDIO, LOC + QString("Closing device '%1' %2") 151 .arg(m_device_name).arg(IsOpen())); 152 153 if (IsOpen()) 154 { 155 close(m_audio_fd); 156 m_audio_fd = -1; 157 m_audio_sample_size = 0; 158 m_audio_sample_rate = 0; 159 m_audio_channels = 0; 160 } 161 } 162 163 bool AudioInputOSS::Start(void) 164 { 165 if (!IsOpen()) 166 return false; 167 168 int trigger = PCM_ENABLE_INPUT; 169 int ret = ioctl(m_audio_fd, SNDCTL_DSP_SETTRIGGER, &trigger); 170 if (-1 == ret) 171 { 172 VERBOSE(VB_AUDIO, LOC + "Unable to start capture" + ENO); 173 return false; 174 } 175 176 VERBOSE(VB_AUDIO, LOC + "Started capture"); 177 178 return true; 179 } 180 181 bool AudioInputOSS::Stop(void) 182 { 183 VERBOSE(VB_IMPORTANT, LOC_ERR + "Not implemented"); 184 return false; 185 } 186 187 int AudioInputOSS::GetBlockSize(void) 188 { 189 if (!IsOpen()) 190 return -1; 191 192 int fragment_size; 193 int ret = ioctl(m_audio_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size); 194 195 if (-1 == ret) 196 { 197 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to query fragment size" + ENO); 198 return -1; 199 } 200 201 return fragment_size; 202 } 203 204 int AudioInputOSS::GetSamples(void *buffer, uint num_bytes) 205 { 206 if (!IsOpen()) 207 return -1; 208 209 if (0 != (num_bytes % ((m_audio_sample_size * m_audio_channels) / 8))) 210 { 211 VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid num_bytes"); 212 return -1; 213 } 214 215 // TODO FIXME This will fail if the read is interrupted by a signal... 216 int bytes_read = read(m_audio_fd, buffer, num_bytes); 217 218 return bytes_read; 219 } 220 221 int AudioInputOSS::GetNumReadyBytes(void) 222 { 223 if (!IsOpen()) 224 return -1; 225 226 audio_buf_info ispace; 227 int ret = ioctl(m_audio_fd, SNDCTL_DSP_GETISPACE, &ispace); 228 if (-1 == ret) 229 { 230 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get ready bytes" + ENO); 231 } 232 233 return ispace.bytes; 234 } 235 236 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmyth/audioinputoss.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 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 20 21 #ifndef _AUDIOINPUTOSS_H_ 22 #define _AUDIOINPUTOSS_H_ 23 24 #include "audioinput.h" 25 26 class AudioInputOSS : public AudioInput 27 { 28 public: 29 AudioInputOSS(const QString &device); 30 virtual ~AudioInputOSS(); 31 32 virtual bool Open(uint depth, uint sample_rate, uint channels); 33 virtual bool IsOpen(void) const { return m_audio_fd >= 0; } 34 virtual void Close(void); 35 36 virtual bool Start(void); 37 virtual bool Stop(void); 38 39 virtual int GetBlockSize(void); 40 virtual int GetSamples(void *buffer, uint num_samples); 41 virtual int GetNumReadyBytes(void); 42 43 private: 44 int m_audio_fd; 45 }; 46 47 #endif /* _AUDIOINPUTOSS_H_ */ 48 -
libs/libmyth/audioinputalsa.cpp
1 /* 2 * Copyright (C) 2007 Anand K. Mistry 3 * Copyright (C) 2007 Daniel Kristjansson 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 <alsa/asoundlib.h> 28 29 #include "audioinputalsa.h" 30 #include "mythcontext.h" 31 32 #define LOC QString("AudInALSA(%1): ").arg(m_device_name) 33 #define LOC_WARN QString("AudInALSA(%1) Warning: ").arg(m_device_name) 34 #define LOC_ERR QString("AudInALSA(%1) Error: ").arg(m_device_name) 35 36 AudioInputALSA::AudioInputALSA(const QString &device) : 37 AudioInput(device), m_audio_handle(NULL) 38 { 39 } 40 41 AudioInputALSA::~AudioInputALSA() 42 { 43 Close(); 44 } 45 46 bool AudioInputALSA::Open(uint sample_size, uint sample_rate, uint channels) 47 { 48 if (IsOpen()) 49 Close(); 50 51 // Open the device 52 const QString tmp = QDeepCopy<QString>(m_device_name); 53 int ret = snd_pcm_open((snd_pcm_t**)(&m_audio_handle), 54 tmp.ascii(), SND_PCM_STREAM_CAPTURE, 0); 55 56 if (ret) 57 { 58 m_audio_handle = NULL; 59 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Cannot open '%1'") 60 .arg(m_device_name)); 61 62 return false; 63 } 64 65 // Allocate hw params structure 66 snd_pcm_hw_params_t *hw_params = NULL; 67 ret = snd_pcm_hw_params_malloc(&hw_params); 68 if (ret) 69 { 70 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate hw params"); 71 goto err_exit; 72 } 73 74 // Initialize hw params 75 ret = snd_pcm_hw_params_any(((snd_pcm_t*) m_audio_handle), hw_params); 76 if (ret) 77 { 78 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to init hw params"); 79 goto err_exit; 80 } 81 82 // Set interleaved access 83 ret = snd_pcm_hw_params_set_access(((snd_pcm_t*) m_audio_handle), 84 hw_params, 85 SND_PCM_ACCESS_RW_INTERLEAVED); 86 if (ret) 87 { 88 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set interleaved"); 89 goto err_exit; 90 } 91 92 // Set format 93 ret = snd_pcm_hw_params_set_format(((snd_pcm_t*) m_audio_handle), 94 hw_params, 95 SND_PCM_FORMAT_S16_LE); 96 if (ret) 97 { 98 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to set desired format"); 99 goto err_exit; 100 } 101 102 // Set sampling rate 103 m_audio_sample_rate = sample_rate; 104 ret = snd_pcm_hw_params_set_rate(((snd_pcm_t*) m_audio_handle), 105 hw_params, m_audio_sample_rate, 0); 106 if (ret) 107 { 108 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to set sample rate" + ENO); 109 goto err_exit; 110 } 111 112 // Set channels 113 m_audio_channels = channels; 114 ret = snd_pcm_hw_params_set_channels(((snd_pcm_t*) m_audio_handle), 115 hw_params, m_audio_channels); 116 if (ret) 117 { 118 VERBOSE(VB_IMPORTANT, LOC_ERR + 119 "Unable to set number of channels" + ENO); 120 goto err_exit; 121 } 122 123 // Apply settings 124 ret = snd_pcm_hw_params(((snd_pcm_t*) m_audio_handle), hw_params); 125 if (ret) 126 { 127 VERBOSE(VB_IMPORTANT, LOC_ERR + 128 "Unable to apply settings to device" + ENO); 129 goto err_exit; 130 } 131 132 snd_pcm_hw_params_free(hw_params); 133 134 // Set sample size 135 m_audio_sample_size = sample_size; 136 137 return true; 138 139 err_exit: 140 snd_pcm_close(((snd_pcm_t*) m_audio_handle)); 141 m_audio_handle = NULL; 142 m_audio_sample_size = 0; 143 m_audio_sample_rate = 0; 144 m_audio_channels = 0; 145 return false; 146 } 147 148 void AudioInputALSA::Close(void) 149 { 150 VERBOSE(VB_AUDIO, LOC + QString("Closing device '%1' %2") 151 .arg(m_device_name).arg(IsOpen())); 152 153 if (IsOpen()) 154 { 155 snd_pcm_close(((snd_pcm_t*) m_audio_handle)); 156 m_audio_handle = NULL; 157 m_audio_sample_size = 0; 158 m_audio_sample_rate = 0; 159 m_audio_channels = 0; 160 } 161 } 162 163 bool AudioInputALSA::Start(void) 164 { 165 if (!IsOpen()) 166 return false; 167 168 int ret = snd_pcm_prepare(((snd_pcm_t*) m_audio_handle)); 169 if (0 != ret) 170 { 171 VERBOSE(VB_AUDIO, LOC + "Unable to start capture"); 172 return false; 173 } 174 175 VERBOSE(VB_AUDIO, LOC + "Started capture on " + m_device_name); 176 177 return true; 178 } 179 180 bool AudioInputALSA::Stop(void) 181 { 182 VERBOSE(VB_IMPORTANT, LOC_ERR + "Not implemented"); 183 return false; 184 } 185 186 int AudioInputALSA::GetBlockSize(void) 187 { 188 if (!IsOpen()) 189 return -1; 190 191 snd_pcm_uframes_t buffer_size, period_size; 192 193 int ret = snd_pcm_get_params(((snd_pcm_t*) m_audio_handle), 194 &buffer_size, &period_size); 195 196 if (0 != ret) 197 { 198 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to query fragment size" + ENO); 199 return -1; 200 } 201 202 return (period_size * m_audio_channels * m_audio_sample_size) / 8; 203 } 204 205 int AudioInputALSA::GetSamples(void *buffer, uint num_bytes) 206 { 207 if (!IsOpen()) 208 return -1; 209 210 uint frame_size = (m_audio_sample_size * m_audio_channels) / 8; 211 212 if (0 != (num_bytes % frame_size)) 213 { 214 VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid num_bytes"); 215 return -1; 216 } 217 218 int ret = snd_pcm_readi(((snd_pcm_t*) m_audio_handle), 219 buffer, num_bytes / frame_size); 220 221 if ((-EINTR == ret) || (-EPIPE == ret) || (-ESTRPIPE == ret)) 222 { 223 ret = snd_pcm_recover(((snd_pcm_t*) m_audio_handle), ret, 1); 224 if ((ret < 0) && (-EAGAIN != ret)) 225 { 226 VERBOSE(VB_IMPORTANT, LOC_ERR + 227 "Failed to recover from error" + ENO); 228 return -1; 229 } 230 ret = 0; 231 } 232 233 return (ret>=0) ? ret * frame_size : -1; 234 } 235 236 int AudioInputALSA::GetNumReadyBytes(void) 237 { 238 if (!IsOpen()) 239 return -1; 240 241 snd_pcm_sframes_t delay; 242 int ret = snd_pcm_delay(((snd_pcm_t*) m_audio_handle), &delay); 243 244 if (0 != ret) 245 { 246 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get ready bytes" + ENO); 247 return -1; 248 } 249 250 return (delay * m_audio_channels * m_audio_sample_size) / 8; 251 } 252 253 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmyth/libmyth.pro
63 63 64 64 using_oss { 65 65 DEFINES += USING_OSS 66 SOURCES += audiooutputoss.cpp67 HEADERS += audiooutputoss.h66 SOURCES *= audiooutputoss.cpp audioinputoss.cpp audioinput.cpp 67 HEADERS *= audiooutputoss.h audioinputoss.h audioinput.h 68 68 } 69 69 70 70 unix:!cygwin { … … 129 129 130 130 using_alsa { 131 131 DEFINES += USE_ALSA 132 HEADERS += audiooutputalsa.h133 SOURCES += audiooutputalsa.cpp132 HEADERS *= audiooutputalsa.h audioinputalsa.h audioinput.h 133 SOURCES *= audiooutputalsa.cpp audioinputalsa.cpp audioinput.cpp 134 134 LIBS += $$ALSA_LIBS 135 135 } 136 136 -
libs/libmyth/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 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 20 21 #include "audioinput.h" 22 #include "mythcontext.h" 23 #include "audioinputalsa.h" 24 #include "audioinputoss.h" 25 26 #define LOC QString("AudIn(%1): ").arg(device) 27 #define LOC_WARN QString("AudIn(%1) Warning: ").arg(device) 28 #define LOC_ERR QString("AudIn(%1) Error: ").arg(device) 29 30 AudioInput::AudioInput(const QString &device) : 31 m_device_name(QString::null), m_audio_channels(0), 32 m_audio_sample_size(0), m_audio_sample_rate(0) 33 { 34 if (!device.isEmpty()) 35 m_device_name = QDeepCopy<QString>(device); 36 } 37 38 AudioInput *AudioInput::CreateDevice(const QString &device) 39 { 40 AudioInput *dev = NULL; 41 42 if (device.isEmpty()) 43 { 44 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device string is empty"); 45 return NULL; 46 } 47 48 if ((device == "NULL") || (device == "/dev/null")) 49 { 50 VERBOSE(VB_AUDIO, LOC + "Using NULL audio in"); 51 } 52 else if (device.startsWith("ALSA:")) 53 { 54 #ifdef USE_ALSA 55 QString tmp = QDeepCopy<QString>(device); 56 dev = new AudioInputALSA(tmp.remove(0,5)); 57 #else 58 VERBOSE(VB_IMPORTANT, LOC_ERR + "ALSA input support not available"); 59 #endif 60 } 61 else if (device.startsWith("/")) 62 { 63 #ifdef USING_OSS 64 dev = new AudioInputOSS(device); 65 #else 66 VERBOSE(VB_IMPORTANT, LOC_ERR + "OSS input support not available"); 67 #endif 68 } 69 else 70 { 71 VERBOSE(VB_IMPORTANT, LOC_ERR + 72 QString("Unrecognized audio in '%1' device").arg(device)); 73 } 74 75 return dev; 76 } -
libs/libmyth/audioinputalsa.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 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 20 21 #ifndef _AUDIOINPUTALSA_H_ 22 #define _AUDIOINPUTALSA_H_ 23 24 #include "audioinput.h" 25 26 class AudioInputALSA : public AudioInput 27 { 28 public: 29 AudioInputALSA(const QString &device); 30 virtual ~AudioInputALSA(); 31 32 virtual bool Open(uint depth, uint sample_rate, uint channels); 33 virtual bool IsOpen(void) const { return m_audio_handle; } 34 virtual void Close(void); 35 36 virtual bool Start(void); 37 virtual bool Stop(void); 38 39 virtual int GetBlockSize(void); 40 virtual int GetSamples(void *buffer, uint num_samples); 41 virtual int GetNumReadyBytes(void); 42 43 private: 44 void *m_audio_handle; 45 }; 46 47 #endif /* _AUDIOINPUTALSA_H_ */ 48