Ticket #3405: 3405-v2.patch
File 3405-v2.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) … … 2232 2215 2233 2216 void NuppelVideoRecorder::doAudioThread(void) 2234 2217 { 2235 #if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H) 2236 VERBOSE(VB_IMPORTANT, LOC + 2237 QString("doAudioThread() This Unix doesn't support" 2238 " device files for audio access. Skipping")); 2239 return; 2240 #else 2241 int afmt = 0, trigger = 0; 2242 int afd = 0, act = 0, lastread = 0; 2243 int frag = 0, blocksize = 0; 2244 unsigned char *buffer; 2245 audio_buf_info ispace; 2246 struct timeval anow; 2247 2248 act_audio_sample = 0; 2249 2250 if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK))) 2218 if (!audio_device) 2251 2219 { 2252 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Cannot open DSP '%1', exiting"). 2253 arg(audiodevice)); 2254 perror("open"); 2220 VERBOSE(VB_GENERAL, LOC + "Audio: no audio device"); 2255 2221 return; 2256 2222 } 2257 2258 fcntl(afd, F_SETFL, fcntl(afd, F_GETFL) & ~O_NONBLOCK); 2259 //ioctl(afd, SNDCTL_DSP_RESET, 0); 2260 2261 frag = (8 << 16) | (10); //8 buffers, 1024 bytes each 2262 ioctl(afd, SNDCTL_DSP_SETFRAGMENT, &frag); 2263 2264 afmt = AFMT_S16_LE; 2265 ioctl(afd, SNDCTL_DSP_SETFMT, &afmt); 2266 if (afmt != AFMT_S16_LE) 2223 2224 int act = 0, lastread = 0; 2225 unsigned char *buffer; 2226 struct timeval anow; 2227 2228 if (!audio_device->Open(audio_bits, 2229 audio_samplerate, 2230 audio_channels)) 2267 2231 { 2268 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get 16 bit DSP, exiting"); 2269 close(afd); 2232 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audio: Unable to open device"); 2270 2233 return; 2271 2234 } 2272 2235 2273 if (ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 ||2274 ioctl(afd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 ||2275 ioctl(afd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0)2276 {2277 VERBOSE(VB_IMPORTANT, LOC_ERR + QString(" %1: error setting audio input device to "2278 "%2 kHz/%3 bits/%4 channel").2279 arg(audiodevice).arg(audio_samplerate).2280 arg(audio_bits).arg(audio_channels));2281 close(afd);2282 return;2283 }2284 2285 2236 audio_bytes_per_sample = audio_channels * audio_bits / 8; 2286 2237 2287 if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize))2288 {2289 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't get DSP blocksize, exiting");2290 close(afd);2291 return;2292 }2293 2294 blocksize *= 4; // allways read 4*blocksize2295 2296 if (blocksize != audio_buffer_size)2297 {2298 VERBOSE(VB_IMPORTANT, LOC +2299 QString("Warning, audio blocksize = '%1' while audio_buffer_size='%2'").2300 arg(blocksize).arg(audio_buffer_size));2301 }2302 2303 2238 buffer = new unsigned char[audio_buffer_size]; 2304 2239 2305 /* trigger record */2306 trigger = 0;2307 ioctl(afd,SNDCTL_DSP_SETTRIGGER,&trigger);2308 2309 trigger = PCM_ENABLE_INPUT;2310 ioctl(afd,SNDCTL_DSP_SETTRIGGER,&trigger);2311 2312 2240 audiopaused = false; 2241 2242 if (!audio_device->Start()) 2243 { 2244 VERBOSE(VB_IMPORTANT, LOC_ERR + "Audio: Unable to start capture"); 2245 return; 2246 } 2247 2313 2248 while (childrenLive) 2314 2249 { 2315 2250 if (request_pause) … … 2325 2260 } 2326 2261 audiopaused = false; 2327 2262 2328 if (audio_buffer_size != (lastread = read(afd, buffer,2329 audio_buffer_size)))2263 lastread = audio_device->GetSamples(buffer, audio_buffer_size); 2264 if (audio_buffer_size != lastread) 2330 2265 { 2331 2266 VERBOSE(VB_IMPORTANT, LOC_ERR + 2332 2267 QString("Only read %1 bytes of %2 bytes from '%3"). 2333 arg(lastread).arg(audio_buffer_size).arg(audiodevice) );2334 perror("read audio");2268 arg(lastread).arg(audio_buffer_size).arg(audiodevice) + 2269 ENO); 2335 2270 } 2336 2271 2337 2272 /* record the current time */ … … 2339 2274 (like we used to.) Measure to see how much stuff is in there, 2340 2275 and correct for it when calculating the timestamp */ 2341 2276 gettimeofday(&anow, &tzone); 2342 i octl( afd, SNDCTL_DSP_GETISPACE, &ispace);2277 int bytes_read = max(audio_device->GetNumReadyBytes(), 0); 2343 2278 2344 2279 act = act_audio_buffer; 2345 2280 … … 2360 2295 audio chunk. So, subtract off the length of the chunk 2361 2296 and the length of audio still in the capture buffer. */ 2362 2297 audiobuffer[act]->timecode -= (int)( 2363 ( ispace.fragments * ispace.fragsize+ audio_buffer_size)2298 (bytes_read + audio_buffer_size) 2364 2299 * 1000.0 / (audio_samplerate * audio_bytes_per_sample)); 2365 2300 2366 2301 memcpy(audiobuffer[act]->buffer, buffer, audio_buffer_size); … … 2375 2310 } 2376 2311 2377 2312 delete [] buffer; 2378 close(afd); 2379 #endif 2313 2314 if (audio_device->IsOpen()) 2315 audio_device->Close(); 2380 2316 } 2381 2317 2382 2318 struct VBIData -
libs/libmythtv/libmythtv.pro
87 87 cygwin:QMAKE_LFLAGS_SHLIB += -Wl,--noinhibit-exec 88 88 cygwin:DEFINES += _WIN32 89 89 90 # Enable Linux Open Sound System support 91 using_oss:DEFINES += USING_OSS 90 # Enable sound systems support 91 using_alsa:DEFINES += USING_ALSA 92 using_arts:DEFINES += USING_ARTS 93 using_jack:DEFINES += USING_JACK 94 using_oss: DEFINES += USING_OSS 95 macx: DEFINES += USING_COREAUDIO 96 92 97 # Enable Valgrind, i.e. disable some timeouts 93 98 using_valgrind:DEFINES += USING_VALGRIND 94 99 -
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
833 833 { 834 834 public: 835 835 AudioDevice(const CaptureCard &parent) : 836 PathSetting(this, true),836 PathSetting(this, false), 837 837 CaptureCardDBStorage(this, parent, "audiodevice") 838 838 { 839 839 setLabel(QObject::tr("Audio device")); 840 #ifdef USING_OSS 840 841 QDir dev("/dev", "dsp*", QDir::Name, QDir::System); 841 842 fillSelectionsFromDir(dev); 842 843 dev.setPath("/dev/sound"); 843 844 fillSelectionsFromDir(dev); 844 addSelection(QObject::tr("(None)"), "/dev/null"); 845 #endif 846 #ifdef USING_ALSA 847 addSelection("ALSA:default", "ALSA:default"); 848 #endif 849 #ifdef USING_ARTS 850 //addSelection("ARTS:", "ARTS:"); 851 #endif 852 #ifdef USING_JACK 853 //addSelection("JACK:output", "JACK:output"); 854 #endif 855 #ifdef USING_COREAUDIO 856 //addSelection("CoreAudio:", "CoreAudio:"); 857 #endif 858 addSelection(QObject::tr("(None)"), "NULL"); 845 859 }; 846 860 }; 847 861 -
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
85 85 86 86 using_oss { 87 87 DEFINES += USING_OSS 88 SOURCES += audiooutputoss.cpp89 HEADERS += audiooutputoss.h88 SOURCES *= audiooutputoss.cpp audioinputoss.cpp audioinput.cpp 89 HEADERS *= audiooutputoss.h audioinputoss.h audioinput.h 90 90 } 91 91 92 92 unix:!cygwin { … … 175 175 176 176 using_alsa { 177 177 DEFINES += USE_ALSA 178 HEADERS += audiooutputalsa.h179 SOURCES += audiooutputalsa.cpp178 HEADERS *= audiooutputalsa.h audioinputalsa.h audioinput.h 179 SOURCES *= audiooutputalsa.cpp audioinputalsa.cpp audioinput.cpp 180 180 LIBS += $$ALSA_LIBS 181 181 } 182 182 -
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