Commit 379990ae authored by llea's avatar llea

Add alsa support but not yet operational.

Change setup directory name to ".sflphone".
Fix volume control.
parent 91c51f29
......@@ -23,7 +23,7 @@ INCPATH = -I. -I$(QTDIR)/include -I$(CCPPDIR)/include/cc++2 -I$(CCRTPDIR)/inclu
CXXFLAGS = -pipe -Wall -W -g -pipe -march=i386 -mcpu=i686 -DQT_NO_DEBUG -DQT_SHARED -DQT_THREAD_SUPPORT -fpermissive -Wno-deprecated $(INCPATH)
LIBS = -L$(QTDIR)/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm -L/opt/lib -losip2 -leXosip -lccrtp1 `ccgnu2-config --flags --stdlibs`
LIBS = -L$(QTDIR)/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm -L/opt/lib -losip2 -leXosip -lccrtp1 -lasound `ccgnu2-config --flags --stdlibs`
CONFIGURE_CONF=$(shell ls ../configure.conf)
......@@ -32,6 +32,7 @@ OBJS = \
audiocodec.o \
audiodrivers.o \
audiodriversoss.o \
audiodriversalsa.o \
audiortp.o \
configuration.o \
configitem.o \
......
......@@ -41,8 +41,6 @@ public:
virtual int initDevice (DeviceMode) = 0;
virtual int resetDevice (void) = 0;
virtual int closeDevice (void) = 0;
virtual int writeBuffer (void *, int) = 0;
virtual int writeBuffer (void) = 0;
virtual int readBuffer (void *, int) = 0;
virtual int readBuffer (int) = 0;
......
/**
* Copyright (C) 2004 Savoir-Faire Linux inc.
* Author: Jerome Oufella <jerome.oufella@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 2 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.
*/
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/soundcard.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "audiodriversalsa.h"
#include "global.h"
#define ALSA_DEVICE "plughw:0,0"
AudioDriversALSA::AudioDriversALSA(DeviceMode mode) : AudioDrivers () {
audio_hdl = (snd_pcm_t *) NULL;
initDevice(mode);
}
AudioDriversALSA::~AudioDriversALSA (void) {
/* Close the audio handle */
snd_pcm_close (audio_hdl);
}
int
AudioDriversALSA::initDevice (DeviceMode mode) {
int err;
if (devstate == DeviceOpened) {
printf ("ERROR: ALSA Device Already Open !\n");
return -1;
}
// Open the audio device
// Flags : blocking (else have to OR omode with SND_PCM_OPEN_NONBLOCK).
switch (mode) {
case ReadOnly:
/* Only read sound from the device */
err = snd_pcm_open (&audio_hdl, ALSA_DEVICE,SND_PCM_STREAM_CAPTURE, 0);
break;
case WriteOnly:
/* Only write sound to the device */
err = snd_pcm_open (&audio_hdl, ALSA_DEVICE,SND_PCM_STREAM_PLAYBACK,0);
break;
default:
break;
}
if (err < 0) {
printf ("ERROR: ALSA/snd_pcm_open: Cannot open audio device (%s)\n",
snd_strerror (err));
return -1;
}
////////////////////////////////////////////////////////////////////////////
// BEGIN DEVICE SETUP
////////////////////////////////////////////////////////////////////////////
// Allocate space for device configuration
snd_pcm_hw_params_t *hw_params;
err = snd_pcm_hw_params_malloc (&hw_params);
if (err < 0) {
printf ("Cannot allocate hardware parameter structure (%s)\n",
snd_strerror (err));
return -1;
}
if ((err = snd_pcm_hw_params_any (audio_hdl, hw_params)) < 0) {
printf ("Cannot initialize hardware parameter structure (%s)\n",
snd_strerror (err));
return -1;
}
err = snd_pcm_hw_params_set_access (audio_hdl, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0) {
printf ("Cannot set access type (%s)\n", snd_strerror (err));
}
// Set sample formats (Signed, 16Bits, little endian)
err = snd_pcm_hw_params_set_format (audio_hdl, hw_params,
SND_PCM_FORMAT_S16_LE);
if (err < 0) {
printf ("Cannot set sample format (%s)\n", snd_strerror (err));
return -1;
}
unsigned int rate = SAMPLING_RATE;
// Set sampling rate (8kHz)
err = snd_pcm_hw_params_set_rate_near (audio_hdl, hw_params,
&rate, 0);
if (err < 0) {
printf ("Cannot set sample rate (%s)\n", snd_strerror (err));
return -1;
}
// Set number of channels - Mono(1) or Stereo(2)
err = snd_pcm_hw_params_set_channels (audio_hdl, hw_params, MONO);
if (err < 0) {
printf ("Cannot set channel count (%s)\n", snd_strerror (err));
return -1;
}
// Apply previously setup parameters
err = snd_pcm_hw_params (audio_hdl, hw_params);
if (err < 0) {
printf ("Cannot set parameters (%s)\n", snd_strerror (err));
return -1;
}
// Free temp variable used for configuration.
snd_pcm_hw_params_free (hw_params);
////////////////////////////////////////////////////////////////////////////
// END DEVICE SETUP
////////////////////////////////////////////////////////////////////////////
#if 0
// keep fragsize less than 20ms !!
int frag = ( ( 32767 << 16 ) | 7 );
if( ioctl( audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag ) ) {
lasterror = QString( "SETFRAG" ) + QString( strerror( errno ) );
printf( "ERROR: %s\n", lasterror.ascii() );
return -1;
}
audio_buf_info info;
if( mode == WriteOnly ) {
if( ioctl( audio_fd, SNDCTL_DSP_GETOSPACE, &info ) == -1 ) {
lasterror = QString( "GETISPACE" ) + QString( strerror( errno ) );
printf( "ERROR: %s\n", lasterror.ascii() );
return -1;
}
} else {
if( ioctl( audio_fd, SNDCTL_DSP_GETISPACE, &info ) == -1 ) {
lasterror = QString( "GETOSPACE" ) + QString( strerror( errno ) );
printf( "ERROR: %s\n", lasterror.ascii() );
return -1;
}
}
audio_buf.resize( info.fragsize * sizeof( short ) );
#endif
// Success
devstate = DeviceOpened;
return 0;
}
int
AudioDriversALSA::writeBuffer (void) {
if (devstate != DeviceOpened) {
printf ("ALSA: writeBuffer(): Device Not Open\n");
return -1;
}
int rc;
size_t count = audio_buf.getSize();
short *buf = (short*)audio_buf.getData();
while (count > 0) {
rc = snd_pcm_writei(audio_hdl, buf, count);
if (rc == -EPIPE) {
snd_pcm_prepare(audio_hdl);
} else if (rc == -EAGAIN) {
continue;
} else if (rc < 0) {
printf ("ALSA: write(): %s\n", strerror(errno));
break;
}
buf += rc;
count -= rc;
}
return rc;
}
unsigned int
AudioDriversALSA::readableBytes (void) {
audio_buf_info info;
#if 0
struct timeval timeout;
fd_set read_fds;
if (devstate != DeviceOpened) {
return 0;
}
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO (&read_fds);
FD_SET (audio_fd, &read_fds);
if (select (audio_fd + 1, &read_fds, NULL, NULL, &timeout) == -1) {
return 0;
}
if (!FD_ISSET ( audio_fd, &read_fds)) {
return 0;
}
if (ioctl (audio_fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
printf ("ERROR: readableBytes %s\n", strerror(errno));
return 0;
}
#endif
return info.bytes;
}
int
AudioDriversALSA::readBuffer (int bytes) {
if (devstate != DeviceOpened) {
printf ("Device Not Open\n");
return false;
}
audio_buf.resize (bytes);
size_t count = bytes;
void *buf;
buf = audio_buf.getData ();
size_t rc = read (audio_fd, buf, count);
if (rc != count) {
printf ("warning: asked microphone for %d got %d\n", count, rc);
}
return true;
}
int
AudioDriversALSA::readBuffer (void *ptr, int bytes) {
if( devstate != DeviceOpened ) {
printf ("ALSA: readBuffer(): Device Not Open\n");
return -1;
}
ssize_t count = bytes;
ssize_t rc;
rc = snd_pcm_readi(audio_hdl, ptr, count);
if (rc < 0) {
return -1;
} else if (rc != count) {
printf("warning: asked microphone for %d frames but got %d\n",
count, rc);
return -1;
}
return rc;
}
int
AudioDriversALSA::resetDevice (void) {
printf ("ALSA: Resetting device.\n");
return 0;
}
// EOF
/**
* Copyright (C) 2004 Savoir-Faire Linux inc.
* Author: Jerome Oufella <jerome.oufella@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 2 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 _AUDIO_DRIVERS_ALSA_H_
#define _AUDIO_DRIVERS_ALSA_H_
#include <alsa/asoundlib.h>
#include "audiodrivers.h"
/**
* This is the ALSA implementation of DspOut.
* Note that you cannot change how many fragments
* this class requests, yet.
*/
class AudioDriversALSA : public AudioDrivers {
public:
/**
* Constructs a AudioDriversALSA object representing the given
* filename. Default is /dev/dsp.
*/
AudioDriversALSA(DeviceMode);
/**
* Destructor. Will close the device if it is open.
*/
virtual ~AudioDriversALSA( void );
int initDevice (DeviceMode);
int resetDevice (void);
int writeBuffer (void);
int readBuffer (int);
int readBuffer (void *, int);
unsigned int readableBytes(void);
int audio_fd;
snd_pcm_t *audio_hdl;
private:
};
#endif // _AUDIO_DRIVERS_ALSA_H_
......@@ -34,11 +34,10 @@
#include "audiodriversoss.h"
#include "global.h"
#define MONO 1
AudioDriversOSS::AudioDriversOSS (void) : AudioDrivers () {
AudioDriversOSS::AudioDriversOSS (DeviceMode mode) : AudioDrivers () {
audio_fd = -1;
initDevice(AudioDrivers::ReadWrite);
initDevice(mode);
}
AudioDriversOSS::~AudioDriversOSS (void) {
......@@ -61,7 +60,6 @@ AudioDriversOSS::resetDevice (void) {
int
AudioDriversOSS::initDevice (DeviceMode mode) {
int oflag;
switch (mode) {
case ReadOnly:
oflag = O_RDONLY;
......@@ -113,18 +111,18 @@ AudioDriversOSS::initDevice (DeviceMode mode) {
int channels = MONO;
if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
printf ("ERROR: DSP_STEREO %s\n", strerror(errno));
return false;
return -1;
}
if (channels != MONO) {
printf ("ERROR: Unsupported Number of Channels\n");
return false;
return -1;
}
// Setup sampling rate
// Setup sampling rate 8KHz
int rate = SAMPLING_RATE;
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate ) == -1 ) {
printf ("ERROR: DSP_SPEED %s\n", strerror(errno));
return false;
return -1;
}
if (rate != SAMPLING_RATE) {
......@@ -137,12 +135,12 @@ AudioDriversOSS::initDevice (DeviceMode mode) {
if (mode == WriteOnly) {
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
printf ("ERROR: GETISPACE %s\n", strerror(errno));
return false;
return -1;
}
} else {
if (ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &info ) == -1) {
printf ("ERROR: GETOSPACE %s\n", strerror(errno));
return false;
return -1;
}
}
// audio_buf.resize (info.fragsize * sizeof(short));
......@@ -178,31 +176,6 @@ AudioDriversOSS::openDevice (int exist_fd) {
return true;
}
#if 0
#ifndef min
#define min(a,b) (a<b?a:b)
#endif
int
AudioDriversOSS::readBuffer (void *buf, int read_bytes) {
int read_len,
available;
audio_buf_info info;
/* Figure out how many bytes we can read before blocking... */
ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &info);
available = min(info.bytes, read_bytes);
printf("info=%d, read_bytes=%d, available=%d\n", info.bytes, read_bytes,
available);
read_len = read (audio_fd, (char *)buf, available);
if (read_len < 0) {
perror("audio_read");
return 0;
}
return read_len;
}
#endif
int
AudioDriversOSS::readBuffer (void *ptr, int bytes) {
......@@ -210,12 +183,7 @@ AudioDriversOSS::readBuffer (void *ptr, int bytes) {
printf ("Device Not Open\n");
return false;
}
//audio_buf.resize(bytes);
ssize_t count = bytes;
// unsigned char *buf;
// buf = audio_buf.getData();
ssize_t rc;
rc = read (audio_fd, ptr, count);
......@@ -234,7 +202,7 @@ int
AudioDriversOSS::readBuffer (int bytes) {
if( devstate != DeviceOpened ) {
printf ("Device Not Open\n");
return false;
return -1;
}
audio_buf.resize(bytes);
......
......@@ -31,12 +31,11 @@
class AudioDriversOSS : public AudioDrivers {
public:
AudioDriversOSS (void);
AudioDriversOSS (DeviceMode);
~AudioDriversOSS (void);
int initDevice (DeviceMode);
int resetDevice (void);
int closeDevice (void);
bool openDevice (int);
int writeBuffer (void *, int);
int writeBuffer (void);
......@@ -45,8 +44,8 @@ public:
unsigned int readableBytes (void);
int audio_fd;
private:
int closeDevice (void);
};
......
......@@ -67,8 +67,15 @@ AudioRtp::createNewSession (SipCall *ca) {
} else {
symetric = true;
}
RTXThread = new AudioRtpRTX (ca, manager->audiodriver, manager, symetric);
if (manager->useAlsa) {
RTXThread = new AudioRtpRTX (ca, manager->audiodriver,
manager->audiodriverReadAlsa, manager, symetric);
} else {
RTXThread = new AudioRtpRTX (ca, manager->audiodriver, NULL, manager,
symetric);
}
if (RTXThread->start() != 0) {
return -1;
}
......@@ -98,11 +105,13 @@ AudioRtp::closeRtpSession (SipCall *ca) {
// AudioRtpRTX Class //
////////////////////////////////////////////////////////////////////////////////
AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioDrivers *driver,
Manager *mngr, bool sym) {
this->ca = sipcall;
this->audioDevice = driver;
AudioDrivers *read_driver, Manager *mngr, bool sym) {
this->manager = mngr;
this->ca = sipcall;
this->sym =sym;
this->audioDevice = driver;
if (manager->useAlsa)
this->audioDeviceRead = read_driver;
// TODO: Change bind address according to user settings.
InetHostAddress local_ip("0.0.0.0");
......@@ -245,13 +254,24 @@ AudioRtpRTX::run (void) {
// Send session
////////////////////////////
if (!manager->mute) {
i = audioDevice->readBuffer (data_from_mic, 320);
if (manager->useAlsa) {
i = audioDeviceRead->readBuffer (data_from_mic, 320);
} else {
i = audioDevice->readBuffer (data_from_mic, 320);
}
} else {
// When IP-phone user click on mute button, we read buffer of a
// temp buffer to avoid delay in sound.
i = audioDevice->readBuffer (data_mute, 320);
if (manager->useAlsa)
i = audioDeviceRead->readBuffer (data_mute, 320);
else
i = audioDevice->readBuffer (data_mute, 320);
}
// TODO : return an error because no sound
if (i < 0) {
break;
}
for (int j = 0; j < i; j++)
data_from_mic_tmp[j] = data_from_mic[j]*manager->getMicVolume()/100;
......@@ -294,7 +314,6 @@ AudioRtpRTX::run (void) {
audioDevice->audio_buf.resize(expandedSize);
audioDevice->audio_buf.setData (data_for_speakers,
manager->getSpkrVolume());
// i = audioDevice->writeBuffer (data_for_speakers, expandedSize);
i = audioDevice->writeBuffer ();
delete adu;
......
......@@ -38,13 +38,16 @@ class Manager;
///////////////////////////////////////////////////////////////////////////////
class AudioRtpRTX : public Thread, public TimerPort {
public:
AudioRtpRTX (SipCall *, AudioDrivers *, Manager *, bool);
AudioRtpRTX (SipCall *, AudioDrivers *, AudioDrivers *, Manager *, bool);
~AudioRtpRTX();
virtual void run ();
private:
SipCall *ca;
AudioDrivers *audioDevice;
#ifdef ALSA
AudioDrivers *audioDeviceRead;
#endif
RTPSession *sessionSend;
RTPSession *sessionRecv;
SymmetricRTPSession *session;
......
......@@ -9,7 +9,7 @@
<x>0</x>
<y>0</y>
<width>560</width>
<height>515</height>
<height>536</height>
</rect>
</property>
<property name="caption">
......@@ -148,7 +148,7 @@
</widget>
<widget class="QLayoutWidget" row="0" column="1">
<property name="name">
<cstring>layout18</cstring>
<cstring>layout17</cstring>
</property>
<vbox>
<property name="name">
......@@ -192,107 +192,190 @@
<attribute name="title">
<string>SIP Authentication</string>
</attribute>
<widget class="QGroupBox">
<widget class="QLayoutWidget">
<property name="name">
<cstring>groupBox1</cstring>
<cstring>layout24</cstring>
</property>
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>380</width>
<height>322</height>
<x>16</x>
<y>12</y>
<width>401</width>
<height>393</height>
</rect>
</property>
<property name="title">
<string></string>
</property>
<grid>
<vbox>