Skip to content
Snippets Groups Projects
Commit 80bd7a99 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Implements inheritance model for the audio layers

parent d7f5e874
Branches
Tags
No related merge requests found
...@@ -23,7 +23,7 @@ endif ...@@ -23,7 +23,7 @@ endif
SUBDIRS = codecs SUBDIRS = codecs
libaudio_la_SOURCES = audiofile.cpp tonelist.cpp \ libaudio_la_SOURCES = audiofile.cpp tonelist.cpp \
audiortp.cpp dtmf.cpp tone.cpp audiolayer.cpp audiolayer-pulse.cpp audiodevice.cpp dtmfgenerator.cpp \ audiortp.cpp dtmf.cpp tone.cpp alsalayer.cpp pulselayer.cpp audiodevice.cpp dtmfgenerator.cpp \
tonegenerator.cpp codecDescriptor.cpp \ tonegenerator.cpp codecDescriptor.cpp \
audioloop.cpp ringbuffer.cpp $(SPEEX_SOURCES_CPP) audioloop.cpp ringbuffer.cpp $(SPEEX_SOURCES_CPP)
...@@ -31,7 +31,7 @@ AM_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libs $(libccext2_CFLAGS) $ ...@@ -31,7 +31,7 @@ AM_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libs $(libccext2_CFLAGS) $
-DCODECS_DIR=\""$(sflcodecdir)"\" $(SPEEX_FLAG) $(GSM_FLAG) $(ILBC_FLAG) -DCODECS_DIR=\""$(sflcodecdir)"\" $(SPEEX_FLAG) $(GSM_FLAG) $(ILBC_FLAG)
noinst_HEADERS = audioloop.h common.h ringbuffer.h audiofile.h \ noinst_HEADERS = audioloop.h common.h ringbuffer.h audiofile.h \
tonelist.h audiortp.h audiolayer.h audiolayer.h audiodevice.h \ tonelist.h audiortp.h audiolayer.h alsalayer.h pulselayer.h audiodevice.h \
dtmfgenerator.h tonegenerator.h \ dtmfgenerator.h tonegenerator.h \
codecDescriptor.h dtmf.h tone.h codecDescriptor.h dtmf.h tone.h
This diff is collapsed.
/*
* Copyright (C) 2007 - 2008 Savoir-Faire Linux inc.
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ALSA_LAYER_H
#define _ALSA_LAYER_H
#include "audiolayer.h"
class RingBuffer;
class ManagerImpl;
/** Associate a sound card index to its string description */
typedef std::pair<int , std::string> HwIDPair;
/**
* @file AlsaLayer.h
* @brief Main sound class. Manages the data transfers between the application and the hardware.
*/
class AlsaLayer : public AudioLayer {
public:
/**
* Constructor
* @param manager An instance of managerimpl
*/
AlsaLayer( ManagerImpl* manager );
/**
* Destructor
*/
~AlsaLayer(void);
/**
* Check if no devices are opened, otherwise close them.
* Then open the specified devices by calling the private functions open_device
* @param indexIn The number of the card choosen for capture
* @param indexOut The number of the card choosen for playback
* @param sampleRate The sample rate
* @param frameSize The frame size
* @param stream To indicate which kind of stream you want to open
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @param plugin The alsa plugin ( dmix , default , front , surround , ...)
*/
bool openDevice(int indexIn, int indexOut, int sampleRate, int frameSize, int stream, std::string plugin);
/**
* Start the capture stream and prepare the playback stream.
* The playback starts accordingly to its threshold
* ALSA Library API
*/
void startStream(void);
/**
* Stop the playback and capture streams.
* Drops the pending frames and put the capture and playback handles to PREPARED state
* ALSA Library API
*/
void stopStream(void);
/**
* Check if the playback is running
* @return true if the state of the playback handle equals SND_PCM_STATE_RUNNING
* false otherwise
*/
bool isPlaybackActive( void );
/**
* Check if the capture is running
* @return true if the state of the capture handle equals SND_PCM_STATE_RUNNING
* false otherwise
*/
bool isCaptureActive( void );
/**
* Check if both capture and playback are running
* @return true if capture and playback are running
* false otherwise
*/
bool isStreamActive(void);
/**
* Check if both capture and playback are stopped
* @return true if capture and playback are stopped
* false otherwise
*/
bool isStreamStopped(void);
/**
* Send samples to the audio device.
* @param buffer The buffer containing the data to be played ( voice and DTMF )
* @param toCopy The number of samples, in bytes
* @param isTalking If whether or not the conversation is running
* @return int The number of bytes played
*/
int playSamples(void* buffer, int toCopy, bool isTalking);
/**
* Send a chunk of data to the hardware buffer to start the playback
* Copy data in the urgent buffer.
* @param buffer The buffer containing the data to be played ( ringtones )
* @param toCopy The size of the buffer
* @return int The number of bytes copied in the urgent buffer
*/
int putUrgent(void* buffer, int toCopy);
/**
* Query the capture device for number of bytes available in the hardware ring buffer
* @return int The number of bytes available
*/
int canGetMic();
/**
* Get data from the capture device
* @param buffer The buffer for data
* @param toCopy The number of bytes to get
* @return int The number of bytes acquired ( 0 if an error occured)
*/
int getMic(void * buffer, int toCopy);
/**
* Concatenate two strings. Used to build a valid pcm device name.
* @param plugin the alsa PCM name
* @param card the sound card number
* @param subdevice the subdevice number
* @return std::string the concatenated string
*/
std::string buildDeviceTopo( std::string plugin, int card, int subdevice );
/**
* Scan the sound card available on the system
* @param stream To indicate whether we are looking for capture devices or playback devices
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @return std::vector<std::string> The vector containing the string description of the card
*/
std::vector<std::string> getSoundCardsInfo( int stream );
/**
* Check if the given index corresponds to an existing sound card and supports the specified streaming mode
* @param card An index
* @param stream The stream mode
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @return bool True if it exists and supports the mode
* false otherwise
*/
bool soundCardIndexExist( int card , int stream );
/**
* An index is associated with its string description
* @param description The string description
* @return int Its index
*/
int soundCardGetIndex( std::string description );
/**
* Get the current audio plugin.
* @return std::string The name of the audio plugin
*/
std::string getAudioPlugin( void ) { return _audioPlugin; }
private:
/**
* Drop the pending frames and close the capture device
* ALSA Library API
*/
void closeCaptureStream( void );
/**
* Drop the pending frames and close the playback device
* ALSA Library API
*/
void closePlaybackStream( void );
/**
* Fill the alsa internal ring buffer with chunks of data
*/
void fillHWBuffer( void) ;
/**
* Callback used for asynchronous playback.
* Called when a certain amount of data is written ot the device
* @param pcm_callback The callback pointer
*/
static void AlsaCallBack( snd_async_handler_t* pcm_callback);
/**
* Callback used for asynchronous playback.
* Write tones buffer to the alsa internal ring buffer.
*/
void playTones( void );
/**
* Open the specified device.
* ALSA Library API
* @param pcm_p The string name for the playback device
* @param pcm_c The string name for the capture device
* @param flag To indicate which kind of stream you want to open
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @return true if successful
* false otherwise
*/
bool open_device( std::string pcm_p, std::string pcm_c, int flag);
/**
* Copy a data buffer in the internal ring buffer
* ALSA Library API
* @param buffer The data to be copied
* @param length The size of the buffer
* @return int The number of frames actually copied
*/
int write( void* buffer, int length);
/**
* Read data from the internal ring buffer
* ALSA Library API
* @param buffer The buffer to stock the read data
* @param toCopy The number of bytes to get
* @return int The number of frames actually read
*/
int read( void* buffer, int toCopy);
/**
* Recover from XRUN state for capture
* ALSA Library API
*/
void handle_xrun_capture( void );
/**
* Recover from XRUN state for playback
* ALSA Library API
*/
void handle_xrun_playback( void );
/**
* Handles to manipulate playback stream
* ALSA Library API
*/
snd_pcm_t* _PlaybackHandle;
/**
* Handles to manipulate capture stream
* ALSA Library API
*/
snd_pcm_t* _CaptureHandle;
/**
* Alsa parameter - Size of a period in the hardware ring buffer
*/
snd_pcm_uframes_t _periodSize;
/**
* Handle on asynchronous event
*/
snd_async_handler_t *_AsyncHandler;
/**
* Volume is controlled by the application. Data buffer are modified here to adjust to the right volume selected by the user on the main interface
* @param buffer The buffer to adjust
* @param len The number of bytes
* @param stream The stream mode ( PLAYBACK - CAPTURE )
*/
void * adjustVolume( void * , int , int);
/**
* name of the alsa audio plugin used
*/
std::string _audioPlugin;
/**
* Input channel (mic) should be 1 mono
*/
unsigned int _inChannel;
/**
* Output channel (stereo) should be 1 mono
*/
unsigned int _outChannel;
/**
* Default volume for incoming RTP and Urgent sounds.
*/
unsigned short _defaultVolume; // 100
/** Vector to manage all soundcard index - description association of the system */
std::vector<HwIDPair> IDSoundCards;
};
#endif // _ALSA_LAYER_H_
...@@ -23,22 +23,22 @@ ...@@ -23,22 +23,22 @@
#define _AUDIO_LAYER_H #define _AUDIO_LAYER_H
#include "../global.h" #include "../global.h"
#include "../manager.h"
#include "audiodevice.h" #include "audiodevice.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include <cc++/thread.h> // for ost::Mutex #include <cc++/thread.h> // for ost::Mutex
#include <vector> #include <vector>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include <pulse/pulseaudio.h>
#include <iostream> #include <iostream>
#include <istream> #include <istream>
#include <sstream> #include <sstream>
#define FRAME_PER_BUFFER 160
class RingBuffer; #define FRAME_PER_BUFFER 160
class ManagerImpl;
/** Associate a sound card index to its string description */
typedef std::pair<int , std::string> HwIDPair;
/** /**
* @file audiolayer.h * @file audiolayer.h
...@@ -51,12 +51,21 @@ class AudioLayer { ...@@ -51,12 +51,21 @@ class AudioLayer {
* Constructor * Constructor
* @param manager An instance of managerimpl * @param manager An instance of managerimpl
*/ */
AudioLayer(ManagerImpl* manager); AudioLayer( ManagerImpl* manager )
: _manager(manager)
, _urgentBuffer( SIZEBUF )
{
_inChannel = 1; // don't put in stereo
_outChannel = 1; // don't put in stereo
deviceClosed = true;
}
/** /**
* Destructor * Destructor
*/ */
~AudioLayer(void); ~AudioLayer(void){}
/** /**
* Check if no devices are opened, otherwise close them. * Check if no devices are opened, otherwise close them.
...@@ -71,49 +80,35 @@ class AudioLayer { ...@@ -71,49 +80,35 @@ class AudioLayer {
* SFL_PCM_BOTH * SFL_PCM_BOTH
* @param plugin The alsa plugin ( dmix , default , front , surround , ...) * @param plugin The alsa plugin ( dmix , default , front , surround , ...)
*/ */
bool openDevice(int indexIn, int indexOut, int sampleRate, int frameSize, int stream, std::string plugin); virtual bool openDevice(int indexIn, int indexOut, int sampleRate, int frameSize, int stream, std::string plugin) = 0;
/** /**
* Start the capture stream and prepare the playback stream. * Start the capture stream and prepare the playback stream.
* The playback starts accordingly to its threshold * The playback starts accordingly to its threshold
* ALSA Library API * ALSA Library API
*/ */
void startStream(void); virtual void startStream(void) = 0;
/** /**
* Stop the playback and capture streams. * Stop the playback and capture streams.
* Drops the pending frames and put the capture and playback handles to PREPARED state * Drops the pending frames and put the capture and playback handles to PREPARED state
* ALSA Library API * ALSA Library API
*/ */
void stopStream(void); virtual void stopStream(void) = 0;
/**
* Check if the playback is running
* @return true if the state of the playback handle equals SND_PCM_STATE_RUNNING
* false otherwise
*/
bool isPlaybackActive( void );
/**
* Check if the capture is running
* @return true if the state of the capture handle equals SND_PCM_STATE_RUNNING
* false otherwise
*/
bool isCaptureActive( void );
/** /**
* Check if both capture and playback are running * Check if both capture and playback are running
* @return true if capture and playback are running * @return true if capture and playback are running
* false otherwise * false otherwise
*/ */
bool isStreamActive(void); virtual bool isStreamActive(void) = 0;
/** /**
* Check if both capture and playback are stopped * Check if the capture is running
* @return true if capture and playback are stopped * @return true if the state of the capture handle equals SND_PCM_STATE_RUNNING
* false otherwise * false otherwise
*/ */
bool isStreamStopped(void); virtual bool isCaptureActive( void ) = 0;
/** /**
* Send samples to the audio device. * Send samples to the audio device.
...@@ -122,7 +117,7 @@ class AudioLayer { ...@@ -122,7 +117,7 @@ class AudioLayer {
* @param isTalking If whether or not the conversation is running * @param isTalking If whether or not the conversation is running
* @return int The number of bytes played * @return int The number of bytes played
*/ */
int playSamples(void* buffer, int toCopy, bool isTalking); virtual int playSamples(void* buffer, int toCopy, bool isTalking) = 0;
/** /**
* Send a chunk of data to the hardware buffer to start the playback * Send a chunk of data to the hardware buffer to start the playback
...@@ -131,13 +126,13 @@ class AudioLayer { ...@@ -131,13 +126,13 @@ class AudioLayer {
* @param toCopy The size of the buffer * @param toCopy The size of the buffer
* @return int The number of bytes copied in the urgent buffer * @return int The number of bytes copied in the urgent buffer
*/ */
int putUrgent(void* buffer, int toCopy); virtual int putUrgent(void* buffer, int toCopy) = 0;
/** /**
* Query the capture device for number of bytes available in the hardware ring buffer * Query the capture device for number of bytes available in the hardware ring buffer
* @return int The number of bytes available * @return int The number of bytes available
*/ */
int canGetMic(); virtual int canGetMic() = 0;
/** /**
* Get data from the capture device * Get data from the capture device
...@@ -145,16 +140,7 @@ class AudioLayer { ...@@ -145,16 +140,7 @@ class AudioLayer {
* @param toCopy The number of bytes to get * @param toCopy The number of bytes to get
* @return int The number of bytes acquired ( 0 if an error occured) * @return int The number of bytes acquired ( 0 if an error occured)
*/ */
int getMic(void * buffer, int toCopy); virtual int getMic(void * buffer, int toCopy) = 0;
/**
* Concatenate two strings. Used to build a valid pcm device name.
* @param plugin the alsa PCM name
* @param card the sound card number
* @param subdevice the subdevice number
* @return std::string the concatenated string
*/
std::string buildDeviceTopo( std::string plugin, int card, int subdevice );
/** /**
* Scan the sound card available on the system * Scan the sound card available on the system
...@@ -164,7 +150,7 @@ class AudioLayer { ...@@ -164,7 +150,7 @@ class AudioLayer {
* SFL_PCM_BOTH * SFL_PCM_BOTH
* @return std::vector<std::string> The vector containing the string description of the card * @return std::vector<std::string> The vector containing the string description of the card
*/ */
std::vector<std::string> getSoundCardsInfo( int stream ); virtual std::vector<std::string> getSoundCardsInfo( int stream ) = 0;
/** /**
* Check if the given index corresponds to an existing sound card and supports the specified streaming mode * Check if the given index corresponds to an existing sound card and supports the specified streaming mode
...@@ -176,14 +162,20 @@ class AudioLayer { ...@@ -176,14 +162,20 @@ class AudioLayer {
* @return bool True if it exists and supports the mode * @return bool True if it exists and supports the mode
* false otherwise * false otherwise
*/ */
bool soundCardIndexExist( int card , int stream ); virtual bool soundCardIndexExist( int card , int stream ) = 0;
/** /**
* An index is associated with its string description * An index is associated with its string description
* @param description The string description * @param description The string description
* @return int Its index * @return int Its index
*/ */
int soundCardGetIndex( std::string description ); virtual int soundCardGetIndex( std::string description ) = 0;
/**
* Get the current audio plugin.
* @return std::string The name of the audio plugin
*/
virtual std::string getAudioPlugin( void ) = 0;
/** /**
* Write accessor to the error state * Write accessor to the error state
...@@ -227,11 +219,6 @@ class AudioLayer { ...@@ -227,11 +219,6 @@ class AudioLayer {
*/ */
unsigned int getFrameSize() { return _frameSize; } unsigned int getFrameSize() { return _frameSize; }
/**
* Get the current audio plugin.
* @return std::string The name of the audio plugin
*/
std::string getAudioPlugin( void ) { return _audioPlugin; }
/** /**
* Get the current state. Conversation or not * Get the current state. Conversation or not
* @return bool true if playSamples has been called * @return bool true if playSamples has been called
...@@ -239,125 +226,26 @@ class AudioLayer { ...@@ -239,125 +226,26 @@ class AudioLayer {
*/ */
bool getCurrentState( void ) { return _talk; } bool getCurrentState( void ) { return _talk; }
/** protected:
* Toggle echo testing on/off
*/
void toggleEchoTesting();
private:
/** /**
* Drop the pending frames and close the capture device * Drop the pending frames and close the capture device
* ALSA Library API
*/ */
void closeCaptureStream( void ); virtual void closeCaptureStream( void ) = 0;
/** /**
* Drop the pending frames and close the playback device * Drop the pending frames and close the playback device
* ALSA Library API
*/
void closePlaybackStream( void );
/**
* Fill the alsa internal ring buffer with chunks of data
*/
void fillHWBuffer( void) ;
/**
* Callback used for asynchronous playback.
* Called when a certain amount of data is written ot the device
* @param pcm_callback The callback pointer
*/
static void AlsaCallBack( snd_async_handler_t* pcm_callback);
/**
* Callback used for asynchronous playback.
* Write tones buffer to the alsa internal ring buffer.
*/
void playTones( void );
/**
* Open the specified device.
* ALSA Library API
* @param pcm_p The string name for the playback device
* @param pcm_c The string name for the capture device
* @param flag To indicate which kind of stream you want to open
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @return true if successful
* false otherwise
*/
bool open_device( std::string pcm_p, std::string pcm_c, int flag);
/**
* Copy a data buffer in the internal ring buffer
* ALSA Library API
* @param buffer The data to be copied
* @param length The size of the buffer
* @return int The number of frames actually copied
*/
int write( void* buffer, int length);
/**
* Read data from the internal ring buffer
* ALSA Library API
* @param buffer The buffer to stock the read data
* @param toCopy The number of bytes to get
* @return int The number of frames actually read
*/
int read( void* buffer, int toCopy);
/**
* Recover from XRUN state for capture
* ALSA Library API
*/
void handle_xrun_capture( void );
/**
* Recover from XRUN state for playback
* ALSA Library API
*/ */
void handle_xrun_playback( void ); virtual void closePlaybackStream( void ) = 0;
/** Augment coupling, reduce indirect access */ /** Augment coupling, reduce indirect access */
ManagerImpl* _manager; ManagerImpl* _manager;
/**
* Handles to manipulate playback stream
* ALSA Library API
*/
snd_pcm_t* _PlaybackHandle;
/**
* Handles to manipulate capture stream
* ALSA Library API
*/
snd_pcm_t* _CaptureHandle;
/**
* Alsa parameter - Size of a period in the hardware ring buffer
*/
snd_pcm_uframes_t _periodSize;
/**
* Handle on asynchronous event
*/
snd_async_handler_t *_AsyncHandler;
/** /**
* Urgent ring buffer used for ringtones * Urgent ring buffer used for ringtones
*/ */
RingBuffer _urgentBuffer; RingBuffer _urgentBuffer;
/**
* Volume is controlled by the application. Data buffer are modified here to adjust to the right volume selected by the user on the main interface
* @param buffer The buffer to adjust
* @param len The number of bytes
* @param stream The stream mode ( PLAYBACK - CAPTURE )
*/
void * adjustVolume( void * , int , int);
/** /**
* Determine if both endpoints hang up. * Determine if both endpoints hang up.
* true if conversation is running * true if conversation is running
...@@ -394,11 +282,6 @@ class AudioLayer { ...@@ -394,11 +282,6 @@ class AudioLayer {
*/ */
unsigned int _frameSize; unsigned int _frameSize;
/**
* name of the alsa audio plugin used
*/
std::string _audioPlugin;
/** /**
* Input channel (mic) should be 1 mono * Input channel (mic) should be 1 mono
*/ */
...@@ -409,19 +292,6 @@ class AudioLayer { ...@@ -409,19 +292,6 @@ class AudioLayer {
*/ */
unsigned int _outChannel; unsigned int _outChannel;
/**
* Default volume for incoming RTP and Urgent sounds.
*/
unsigned short _defaultVolume; // 100
/**
* Echo testing or not
*/
bool _echoTesting;
/** Vector to manage all soundcard index - description association of the system */
std::vector<HwIDPair> IDSoundCards;
/** Contains the current error code */ /** Contains the current error code */
int _errorMessage; int _errorMessage;
......
/* /*
* Copyright (C) 2005 Savoir-Faire Linux inc. * Copyright (C) 2008 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author: Jerome Oufella <jerome.oufella@savoirfairelinux.com>
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -19,14 +17,8 @@ ...@@ -19,14 +17,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <pulse/pulseaudio.h> #include "pulselayer.h"
#include "audiolayer-pulse.h"
#include "../global.h"
#include "../manager.h"
static pa_context *context = NULL; static pa_context *context = NULL;
static pa_mainloop_api *mainloop_api = NULL; static pa_mainloop_api *mainloop_api = NULL;
...@@ -38,20 +30,10 @@ static std::string stream_r = NULL; ...@@ -38,20 +30,10 @@ static std::string stream_r = NULL;
PulseLayer::PulseLayer(ManagerImpl* manager) PulseLayer::PulseLayer(ManagerImpl* manager)
: _urgentRingBuffer(SIZEBUF) : AudioLayer( manager )
, _mainSndRingBuffer(SIZEBUF)
, _micRingBuffer(SIZEBUF)
, _defaultVolume(PA_VOLUME_NORM)
, playback(NULL)
, record(NULL)
, _errorMessage("")
, _manager(manager)
{ {
_sampleRate = 8000; playback = NULL;
record = NULL;
_inChannel = 1; // don't put in stereo
_outChannel = 1; // don't put in stereo
_echoTesting = false;
} }
// Destructor // Destructor
...@@ -63,6 +45,12 @@ PulseLayer::~PulseLayer (void) ...@@ -63,6 +45,12 @@ PulseLayer::~PulseLayer (void)
// pa_stream_disconnect(); // pa_stream_disconnect();
} }
void
PulseLayer::stream_state_callback( pa_stream* s, void* user_data )
{
_debug("The state of the stream changed\n");
}
void void
PulseLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize) PulseLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize)
...@@ -74,7 +62,7 @@ PulseLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize ...@@ -74,7 +62,7 @@ PulseLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize
sample_spec.format = PA_SAMPLE_S16LE; sample_spec.format = PA_SAMPLE_S16LE;
sample_spec.channels = 1; sample_spec.channels = 1;
channel_map.channels = 1; channel_map.channels = 1;
pa_stream_flags_t flag = PA_STREAM_START_CORKED ;
_debug(" Setting PulseLayer: device in=%2d, out=%2d\n", indexIn, indexOut); _debug(" Setting PulseLayer: device in=%2d, out=%2d\n", indexIn, indexOut);
_debug(" : nb channel in=%2d, out=%2d\n", _inChannel, _outChannel); _debug(" : nb channel in=%2d, out=%2d\n", _inChannel, _outChannel);
...@@ -101,24 +89,19 @@ PulseLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize ...@@ -101,24 +89,19 @@ PulseLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize
pa_stream_set_state_callback(playback, stream_state_callback, NULL); pa_stream_set_state_callback(playback, stream_state_callback, NULL);
// Transferring Data - Asynchronous Mode // Transferring Data - Asynchronous Mode
pa_stream_set_write_callback(playback, audioCallback, NULL); pa_stream_set_write_callback(playback, audioCallback, NULL);
pa_stream_connect_playback( playback, NULL , NULL , 0 , NULL, NULL ); pa_stream_connect_playback( playback, NULL , NULL , flag , NULL, NULL );
break; break;
case PA_CONTEXT_TERMINATED: case PA_CONTEXT_TERMINATED:
quit(0); _debug("Context terminated\n");
break; break;
case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
default: default:
_debug(" Error : %s" , pa_strerror(pa_context_errno(c))); _debug(" Error : %s" , pa_strerror(pa_context_errno(context)));
quit(1); exit(1);
} }
} }
PulseLayer::stream_state_callback( void )
{
_debug("The state of the stream changed\n");
}
int int
PulseLayer::putMain(void* buffer, int toCopy) PulseLayer::putMain(void* buffer, int toCopy)
{ {
...@@ -154,12 +137,9 @@ PulseLayer::isStreamStopped (void) ...@@ -154,12 +137,9 @@ PulseLayer::isStreamStopped (void)
{ {
} }
void
PulseLayer::toggleEchoTesting() {
}
int void
PulseLayer::audioCallback () PulseLayer::audioCallback ( pa_stream* s, size_t bytes, void* user_data )
{ {
_debug("Audio callback: New data may be written to the stream\n"); _debug("Audio callback: New data may be written to the stream\n");
// pa_stream_write // pa_stream_write
......
...@@ -17,22 +17,15 @@ ...@@ -17,22 +17,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#ifndef _AUDIO_LAYER_PULSE_H #ifndef _PULSE_LAYER_H
#define _AUDIO_LAYER_PULSE_H #define _PULSE_LAYER_H
#include <cc++/thread.h> // for ost::Mutex #include "audiolayer.h"
#include "../global.h"
#include "ringbuffer.h"
#include "audiodevice.h"
#define FRAME_PER_BUFFER 160
class RingBuffer; class RingBuffer;
class ManagerImpl; class ManagerImpl;
class PulseLayer { class PulseLayer : public AudioLayer {
public: public:
PulseLayer(ManagerImpl* manager); PulseLayer(ManagerImpl* manager);
~PulseLayer(void); ~PulseLayer(void);
...@@ -46,11 +39,16 @@ class PulseLayer { ...@@ -46,11 +39,16 @@ class PulseLayer {
void openDevice(int, int, int, int); void openDevice(int, int, int, int);
void startStream(void); void startStream(void);
void stopStream(void); void stopStream(void);
void sleep(int);
bool hasStream(void);
bool isStreamActive(void); bool isStreamActive(void);
bool isStreamStopped(void); bool isStreamStopped(void);
/**
* Check if the capture is running
* @return true if the state of the capture handle equals SND_PCM_STATE_RUNNING
* false otherwise
*/
bool isCaptureActive( void ) { return true; }
void flushMain(); void flushMain();
int putMain(void* buffer, int toCopy); int putMain(void* buffer, int toCopy);
int putUrgent(void* buffer, int toCopy); int putUrgent(void* buffer, int toCopy);
...@@ -58,76 +56,55 @@ class PulseLayer { ...@@ -58,76 +56,55 @@ class PulseLayer {
int getMic(void *, int); int getMic(void *, int);
void flushMic(); void flushMic();
int audioCallback (); static void audioCallback ( pa_stream* s, size_t bytes, void* user_data );
void setErrorMessage(const std::string& error) { _errorMessage = error; } static void stream_state_callback( pa_stream* s, void* user_data );
std::string getErrorMessage() { return _errorMessage; }
/** /**
* Get the sample rate of PulseLayer * Scan the sound card available on the system
* accessor only * @param stream To indicate whether we are looking for capture devices or playback devices
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @return std::vector<std::string> The vector containing the string description of the card
*/ */
unsigned int getSampleRate() { return _sampleRate; } std::vector<std::string> getSoundCardsInfo( int stream ) {
unsigned int getFrameSize() { return _frameSize; } std::vector<std::string> tmp;
return tmp;
}
/** /**
* Toggle echo testing on/off * Check if the given index corresponds to an existing sound card and supports the specified streaming mode
* @param card An index
* @param stream The stream mode
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @return bool True if it exists and supports the mode
* false otherwise
*/ */
void toggleEchoTesting(); bool soundCardIndexExist( int card , int stream ) { return true; }
private:
void closeStream (void);
RingBuffer _urgentRingBuffer;
RingBuffer _mainSndRingBuffer;
RingBuffer _micRingBuffer;
ManagerImpl* _manager; // augment coupling, reduce indirect access
// a PulseLayer can't live without manager
pa_stream* playback;
pa_stream* record;
/** /**
* Sample Rate SFLphone should send sound data to the sound card * An index is associated with its string description
* The value can be set in the user config file- now: 44100HZ * @param description The string description
* @return int Its index
*/ */
unsigned int _sampleRate; int soundCardGetIndex( std::string description ) { return 0;}
/** /**
* Length of the sound frame we capture or read in ms * Get the current audio plugin.
* The value can be set in the user config file - now: 20ms * @return std::string The name of the audio plugin
*/ */
unsigned int _frameSize; std::string getAudioPlugin( void ) { return ""; }
/** private:
* Input channel (mic) should be 1 mono void closeStream (void);
*/
unsigned int _inChannel; // mic
/**
* Output channel (stereo) should be 1 mono
*/
unsigned int _outChannel; // speaker
/**
* Default volume for incoming RTP and Urgent sounds.
*/
//unsigned short _defaultVolume; // 100
pa_volume_t _defaultVolume;
/**
* Echo testing or not
*/
bool _echoTesting;
std::string _errorMessage; pa_stream* playback;
ost::Mutex _mutex; pa_stream* record;
float *table_;
int tableSize_;
int leftPhase_;
}; };
#endif // _AUDIO_LAYER_PULSE_H_ #endif // _PULSE_LAYER_H_
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include "manager.h" #include "manager.h"
#include "account.h" #include "account.h"
#include "audio/audiolayer.h" #include "audio/audiolayer.h"
#include "audio/alsalayer.h"
#include "audio/pulselayer.h"
#include "audio/tonelist.h" #include "audio/tonelist.h"
#include "accountcreator.h" // create new account #include "accountcreator.h" // create new account
...@@ -1431,7 +1433,8 @@ ManagerImpl::getCurrentAudioOutputPlugin( void ) ...@@ -1431,7 +1433,8 @@ ManagerImpl::getCurrentAudioOutputPlugin( void )
ManagerImpl::initAudioDriver(void) ManagerImpl::initAudioDriver(void)
{ {
_debugInit("AudioLayer Creation"); _debugInit("AudioLayer Creation");
_audiodriver = new AudioLayer(this); //_audiodriver = new AudioLayer(this);
_audiodriver = new AlsaLayer( this );
if (_audiodriver == 0) { if (_audiodriver == 0) {
_debug("Init audio driver error\n"); _debug("Init audio driver error\n");
} else { } else {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment