Ticket #3405: mythtv_alsa.patch

File mythtv_alsa.patch, 28.9 KB (added by amistry@…, 17 years ago)

Patch for alsa capture

  • 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
     27class ALSAAudioInput : public AudioInput
     28{
     29public:
     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   
     44private:
     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
     25class OSSAudioInput : public AudioInput
     26{
     27public:
     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   
     42private:
     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

     
    1717
    1818#include <qstringlist.h>
    1919
     20#include "audioinput.h"
     21
    2022#include <iostream>
    2123using namespace std;
    2224
     
    113115    audiobytes = 0;
    114116    audio_bits = 16;
    115117    audio_channels = 2;
    116     audio_samplerate = 44100;
     118    audio_samplerate = 48000;
    117119    audio_bytes_per_sample = audio_channels * audio_bits / 8;
    118120
    119121    picture_format = PIX_FMT_YUV420P;
     
    626628
    627629int NuppelVideoRecorder::AudioInit(bool skipdevice)
    628630{
    629     int afmt, afd;
    630     int frag, blocksize = 4096;
     631    AudioInput *audio_device;
     632   
     633    int blocksize = 256;
    631634    int tmp;
    632635
    633636    if (!skipdevice)
     
    642645
    643646        return 1;
    644647#else
    645         if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK)))
     648        audio_device = AudioInput::CreateDevice(audiodevice);
     649        if (NULL == audio_device)
    646650        {
    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");
    650653            return 1;
    651654        }
    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))
    663659        {
    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");
    666663            return 1;
    667664        }
    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)
    672671        {
    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;
    680676        }
    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));
    690681#endif
    691682    }
    692683
    693     audio_bytes_per_sample = audio_channels * audio_bits / 8;
    694     blocksize *= 4;
    695 
    696684    audio_buffer_size = blocksize;
    697685
    698686    if (compressaudio)
     
    21952183
    21962184void NuppelVideoRecorder::doAudioThread(void)
    21972185{
     2186    AudioInput *audio_device;
     2187    int act = 0, lastread = 0;
     2188    unsigned char *buffer;
     2189    struct timeval anow;
     2190   
    21982191#if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H)
    21992192    VERBOSE(VB_IMPORTANT, LOC +
    22002193            QString("doAudioThread() This Unix doesn't support"
    22012194                    " device files for audio access. Skipping"));
    22022195    return;
    22032196#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)
    22142200    {
    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");
    22182202        return;
    22192203    }
    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))
    22302208    {
    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");
    22332211        return;
    22342212    }
    22352213
    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 
    22482214    audio_bytes_per_sample = audio_channels * audio_bits / 8;
    22492215
    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*blocksize
    2258 
    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 
    22662216    buffer = new unsigned char[audio_buffer_size];
    22672217
    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 
    22752218    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");   
    22762228    while (childrenLive)
    22772229    {
    22782230        if (request_pause)
     
    22882240        }
    22892241        audiopaused = false;
    22902242
    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)))
    22932246        {
    22942247            VERBOSE(VB_IMPORTANT, LOC_ERR +
    22952248                    QString("Only read %1 bytes of %2 bytes from '%3").
    22962249                    arg(lastread).arg(audio_buffer_size).arg(audiodevice));
    22972250            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            }
    22982261        }
    2299 
     2262           
    23002263        /* record the current time */
    23012264        /* Don't assume that the sound device's record buffer is empty
    23022265           (like we used to.) Measure to see how much stuff is in there,
    23032266           and correct for it when calculating the timestamp */
    23042267        gettimeofday(&anow, &tzone);
    2305         ioctl( afd, SNDCTL_DSP_GETISPACE, &ispace );
    23062268
    23072269        act = act_audio_buffer;
    23082270
    23092271        if (!audiobuffer[act]->freeToBuffer)
    23102272        {
    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 :-(");
    23122275            act_audio_sample++;
    23132276            continue;
    23142277        }
     
    23232286           audio chunk. So, subtract off the length of the chunk
    23242287           and the length of audio still in the capture buffer. */
    23252288        audiobuffer[act]->timecode -= (int)(
    2326                 (ispace.fragments * ispace.fragsize + audio_buffer_size)
     2289                (audio_device->GetNumReadyBytes() + audio_buffer_size)
    23272290                 * 1000.0 / (audio_samplerate * audio_bytes_per_sample));
    23282291
    23292292        memcpy(audiobuffer[act]->buffer, buffer, audio_buffer_size);
     
    23382301    }
    23392302
    23402303    delete [] buffer;
    2341     close(afd);
     2304    delete audio_device;
    23422305#endif
    23432306}
    23442307
  • libs/libmythtv/libmythtv.pro

     
    365365
    366366    # Simple NuppelVideo Recorder
    367367    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    }
    370383
    371384    # Support for Video4Linux devices
    372385    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
     31AudioInput * 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
     39OSSAudioInput::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
     50OSSAudioInput::~OSSAudioInput()
     51{
     52    CloseDevice();
     53}
     54
     55int 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
     151int 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
     164int 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
     191int OSSAudioInput::StopCapture()
     192{
     193    return -1;
     194}
     195
     196int 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
     219int 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
     238int 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
     25class AudioInput
     26{
     27public:
     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

     
    774774{
    775775  public:
    776776    AudioDevice(const CaptureCard &parent) :
    777         PathSetting(this, true),
     777        PathSetting(this, false),
    778778        CaptureCardDBStorage(this, parent, "audiodevice")
    779779    {
    780780        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
     35ALSAAudioInput::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
     46ALSAAudioInput::~ALSAAudioInput()
     47{
     48    CloseDevice();
     49}
     50
     51int 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
     131int 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
     144int 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
     170int ALSAAudioInput::StopCapture()
     171{
     172    return -1;
     173}
     174
     175int 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
     198int 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
     228int 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