diff --git a/autogen.sh b/autogen.sh index 06b6a97c95e0c7f4db9c8bd21a358a14784e9187..ac85bd137c9dcf2f99eef6992751d1a92876cdcd 100755 --- a/autogen.sh +++ b/autogen.sh @@ -4,6 +4,6 @@ aclocal -I m4 libtoolize --force autoheader -autoconf -f +autoconf -v -f automake -a ./configure $@ diff --git a/build-package.sh b/build-package.sh index a2c775ac077e8d1f9aedf5cc837277e5f99aca2b..78aa9774b07f8bf2ccc14c2cdb902a8f35adf96c 100755 --- a/build-package.sh +++ b/build-package.sh @@ -2,16 +2,48 @@ # # @author: Yun Liu <yun.liu@savoirfairelinux.com> # -# Build sflphone debian packages for Ubuntu 8.04 +# Build sflphone rpm packages for Fedora 10 and openSUSE 11 # 1 - The SFLphone package must be build with a specific GnuPG key. Please contact us to have more information about that (<sflphoneteam@savoirfairelinux.com>) # 2. The source code can be teched through anonymous http access. So no need of special access. -# 3. After having all the prerequisites, you can run "build-package.sh" to build debian packages for sflphone. -# All the source packages and binary packages will be generated in the current directory. +# 3. After having all the prerequisites, you can run "build-rpm-package.sh" to build rpm packages for sflphone. +# # Refer to http://www.sflphone.org for futher information +# Analyze parameters +if [ "$1" == "--help" ] || [ "$1" == "" ];then + echo -e '\E[34mThis script is used to build sflphone rpm packages on ubuntu series(8.04,8,10,9), Fedora 10 and SUSE 11 platform.' + echo -e '\E[34mYou can add --fedora, --suse or --ubuntu to start packaging.' + echo + echo "The SFLphone package must be build with a specific GnuPG key. Please contact us to have more information about that (<sflphoneteam@savoirfairelinux.com>)" + echo + echo "For fedora and SUSE, you also need to add the following lines to $HOME/.rpmmacros:" + echo -e '\E[32m%_gpg_path /home/yun/.gnupg' + echo -e '\E[32m%_gpg_name Savoir-Faire Linux Inc. (Génération des paquets pour SFLphone) <sflphoneteam@savoirfairelinux.com>' + echo -e '\E[32m%_gpgbin /usr/bin/gpg' + echo + echo -e '\E[34mAfter all these preparations done, you can run ./build-package.sh --platform-name' + echo + echo -e '\E[36mHave fun!' + + tput sgr0 # Reset colors to "normal." + echo + exit 1 +elif [ $1 == "--fedora" ];then + BUILDDIR=$HOME/rpmbuild + platform="fedora" +elif [ $1 == "--suse" ];then + BUILDDIR=/usr/src/packages + platform="suse" +elif [ $1 == "--ubuntu" ];then + platform="ubuntu" +else + echo "This script can only be used for Ubuntu series, Fedora 10 and SUSE 11 platform. Use --help to get more information." + exit 1 +fi + if [ -d "sflphone" ]; then echo "Directory sflphone already exists. Please remove it first." - exit 1 + exit 1 fi # Anonymous git http access @@ -22,33 +54,54 @@ git checkout origin/release -b release # Get system parameters arch_flag=`getconf -a|grep LONG_BIT | sed -e 's/LONG_BIT\s*//'` os_version=`lsb_release -d -s -c | sed -e '1d'` +ver=0.9.2 + +if [ $platform == "ubuntu" ];then + # Generate the changelog, according to the distribution and the git commit messages + cp debian/changelog.$os_version debian/changelog + git-dch --debian-branch=release --release +fi -# Generate the changelog, according to the distribution and the git commit messages -cp debian/changelog.$os_version debian/changelog -git-dch --debian-branch=release --release cd .. # Remove useless git directory rm sflphone/.git/ -rf -# Copy the appropriate control file based on different archtecture -cp sflphone/debian/control.$os_version sflphone/debian/control +# Get the public gpg key to sign the packages +wget -q http://www.sflphone.org/downloads/gpg/sflphone.gpg.asc -O- | gpg --import - -echo "Building sflphone package on Ubuntu $os_version $arch_flag bit architecture...." +if [ $platform == "ubuntu" ];then + # Copy the appropriate control file based on different archtecture + cp sflphone/debian/control.$os_version sflphone/debian/control -# Provide prerequisite directories used by debuild -cp sflphone sflphone-0.9.2 -r -cp sflphone sflphone-0.9.2.orig -r + echo "Building sflphone package on Ubuntu $os_version $arch_flag bit architecture...." + # Provide prerequisite directories used by debuild + cp sflphone sflphone-$ver -r + cp sflphone sflphone-$ver.orig -r + + # Build packages + cd sflphone-$ver/debian; debuild -k'Savoir-Faire Linux Inc.' -# Get the public gpg key to sign the packages -wget -q http://www.sflphone.org/downloads/gpg/sflphone.gpg.asc -O- | gpg --import - + # Post clean + cd .. + rm sflphone-$ver sflphone -rf + echo "Done! All the source packages and binary packages are generated in the current directory" -# Build packages -cd sflphone-0.9.2/debian; debuild -k'Savoir-Faire Linux Inc.' +else + # Prepare for packaging + mv sflphone sflphone-$ver -# Clean -cd ../.. -rm sflphone-0.9.2/ -rf -rm sflphone/ -rf + cp sflphone-$ver/platform/$platform.spec $BUILDDIR/SPECS/ + cp sflphone-$ver/libs/pjproject-1.0/libpj-sfl.pc $BUILDDIR/SOURCES + tar zcvf sflphone-$ver.tar.gz sflphone-$ver -echo "Building package finished successullly!" + rm sflphone-$ver -rf + mv sflphone-$ver.tar.gz $BUILDDIR/SOURCES + echo "Building sflphone package on $platform $arch_flag bit architecture...." + + # Build packages + cd $BUILDDIR/SPECS/ + rpmbuild -ba --sign sflphone.spec + + echo "Done! All source rpms and binary rpms are stored in $BUILDDIR/SRPMS and $BUILDDIR/RPMS" +fi diff --git a/configure.ac b/configure.ac index b07bc5ccf138ce263ede685185445b28019e9d81..b79bb61592859d9ab248973e624725313167b77c 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,10 @@ AC_CONFIG_FILES([src/Makefile \ src/audio/codecs/Makefile src/audio/codecs/ilbc/Makefile \ src/config/Makefile \ - src/dbus/Makefile ]) + src/dbus/Makefile \ + src/plug-in/audiorecorder/Makefile \ + src/plug-in/Makefile \ + src/plug-in/test/Makefile]) dnl Unitary test section AC_CONFIG_FILES([test/Makefile]) diff --git a/globals.mak b/globals.mak index c03985035c4058b00b378f1b0809017241339313..7a0b085b9efbe0f7deefb226deed286cbba7982a 100644 --- a/globals.mak +++ b/globals.mak @@ -1,6 +1,7 @@ # Global variables src=$(top_srcdir) sflcodecdir=$(libdir)/sflphone/codecs +sflplugindir=$(libdir)/sflphone/plugins PJSIP_LIBS = -lpjnath-sfl -lpjsua-sfl -lpjsip-sfl -lpjmedia-sfl -lpjsip-simple-sfl -lpjsip-ua-sfl -lpjmedia-codec-sfl -lpjlib-util-sfl -lpj-sfl @@ -16,5 +17,6 @@ AM_CPPFLAGS = \ @SIP_CFLAGS@ \ @DBUSCPP_CFLAGS@ \ -DCODECS_DIR=\""$(sflcodecdir)"\" \ + -DPLUGINS_DIR=\""$(sflplugindir)"\" \ -DENABLE_TRACE diff --git a/src/Makefile.am b/src/Makefile.am index b7c1a2839d2f02c089c3c17d24aa359d7c532dfa..dc83d84f8a88dce7600a278648ba0b2d265180b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,7 @@ IAXSOURCES = IAXHEADERS = endif -SUBDIRS = audio config dbus +SUBDIRS = audio config dbus plug-in # Add here the cpp files to be build with sflphone sflphoned_SOURCES = \ @@ -75,6 +75,8 @@ libsflphone_la_LIBADD = \ ./audio/libaudio.la \ ./dbus/libdbus.la \ ./config/libconfig.la \ + ./plug-in/libplugin.la \ + ./plug-in/audiorecorder/libaudiorecorder.la \ $(IAX_LIBS) libsflphone_la_SOURCES = diff --git a/src/audio/audiorecord.cpp b/src/audio/audiorecord.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65f63803942947e3cac58e91adcab2e76e1a9cf4 --- /dev/null +++ b/src/audio/audiorecord.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * Author: Alexandre Savard <alexandre.savard@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. + */ + +#include "audiorecord.h" + +AudioRecord::AudioRecord(){ + sndSmplRate_ = 44100; + channels_ = 1; + byteCounter_ = 0; + +} + + +void AudioRecord::setSndSamplingRate(int smplRate){ + sndSmplRate_ = smplRate; +} + + +void AudioRecord::openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format) { + + channels_ =1; + fileType_ = type; + byteCounter_ = 0; + sndFormat_ = format; + + bool result = false; + + if(fileType_ == FILE_RAW){ + result = setRawFile( fileName.c_str() ); + } + else if (fileType_ == FILE_WAV){ + result = setWavFile( fileName.c_str() ); + } + +} + + +void AudioRecord::closeFile() { + + if (fp == 0) return; + + if (fileType_ == FILE_RAW) + fclose(fp); + else if (fileType_ == FILE_WAV) + this->closeWavFile(); + +} + + +bool AudioRecord::isOpenFile() { + + if(fp) + return true; + else + return false; +} + + +bool AudioRecord::setRawFile(const char *fileName) { + + char name[8192]; + strncpy(name, fileName, 8192); + if ( strstr(name, ".raw") == NULL) strcat(name, ".raw"); + fp = fopen(name, "wb"); + if ( !fp ) { + cout << "AudioRecord: could not create RAW file: " << name << '.'; + return false; + } + + if ( sndFormat_ != INT16 ) { // TODO need to change INT16 to SINT16 + sndFormat_ = INT16; + cout << "AudioRecord: using 16-bit signed integer data format for file " << name << '.'; + } + + cout << "AudioRecord: creating RAW file: " << name; + return true; +} + + +bool AudioRecord::setWavFile(const char *fileName) { + + char name[8192]; + strncpy(name, fileName, 8192); + if ( strstr(name, ".wav") == NULL) strcat(name, ".wav"); + fp = fopen(name, "wb"); + if ( !fp ) { + cout << "AudioRecord: could not create WAV file: " << name; + return false; + } + + struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1, + 44100, 0, 2, 16, "dat", 0}; + hdr.riff[3] = 'F'; + hdr.wave[3] = 'E'; + hdr.fmt[3] = ' '; + hdr.data[3] = 'a'; + hdr.num_chans = channels_; + if ( sndFormat_ == INT16 ) { // TODO need to write INT16 to SINT16 + hdr.bits_per_samp = 16; + } + hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8); + hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp); + + + if ( fwrite(&hdr, 4, 11, fp) != 11 ) { + cout << "AudioRecord: could not write WAV header for file " << name << '.'; + return false; + } + + cout << "AudioRecord: creating WAV file: " << name; + return true; +} + + +void AudioRecord::closeWavFile() +{ + int bytes_per_sample = 1; + if ( sndFormat_ == INT16 ) + bytes_per_sample = 2; + + + SINT32 bytes = byteCounter_ * channels_ * bytes_per_sample; + fseek(fp, 40, SEEK_SET); // jump to data length + fwrite(&bytes, 4, 1, fp); + + bytes = byteCounter_ * channels_ * bytes_per_sample + 44; // + 44 for the wave header + fseek(fp, 4, SEEK_SET); // jump to file size + fwrite(&bytes, 4, 1, fp); + fclose( fp ); +} + + +void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) { + + if (fp == 0){ + cout << "AudioRecord: Can't record data, a file has not yet been opened!"; + return; + } + + if ( sndFormat_ == INT16 ) { // TODO change INT16 to SINT16 + if (nSamples <= 1){ + if ( fwrite(buffer, 2, 1, fp) != 1) + cout << "AudioRecord: Could not record data!"; + } + else { + for ( int k=0; k<nSamples; k++ ) { + cout << "Buffer[" << k << "] : " << buffer[k] << "\n"; + if ( fwrite(&buffer[k], 2, 1, fp) != 1 ) + cout << "AudioRecord: Could not record data!"; + } + } + } + + + + + byteCounter_ += (unsigned long)(sizeof(buffer) / sizeof(SINT16)); + + return; +} + diff --git a/src/audio/audiorecord.h b/src/audio/audiorecord.h new file mode 100644 index 0000000000000000000000000000000000000000..b38eefb29a59be117d896e9c2c6147ff43011ef3 --- /dev/null +++ b/src/audio/audiorecord.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * Author: Alexandre Savard <alexandre.savard@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. + */ + + +#include <iostream> +#include <string.h> + +#include "global.h" + +using namespace std; + + +// structure for the wave header +struct wavhdr { + char riff[4]; // "RIFF" + SINT32 file_size; // in bytes + char wave[4]; // "WAVE" + char fmt[4]; // "fmt " + SINT32 chunk_size; // in bytes (16 for PCM) + SINT16 format_tag; // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law + SINT16 num_chans; // 1=mono, 2=stereo + SINT32 sample_rate; + SINT32 bytes_per_sec; + SINT16 bytes_per_samp; // 2=16-bit mono, 4=16-bit stereo + SINT16 bits_per_samp; + char data[4]; // "data" + SINT32 data_length; // in bytes +}; + +class AudioRecord +{ + +public: + + AudioRecord(); + + void setSndSamplingRate(int smplRate); + + /** + * Check if no otehr file is opened, then create a new one + * @param fileName A string containing teh file (with/without extension) + * @param type The sound file format (FILE_RAW, FILE_WAVE) + * @param format Internal sound format (INT16 / INT32) + */ + void openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format); + + /** + * Close the opend recording file. If wave: cout the number of byte + */ + void closeFile(); + + /** + * Check if a file is already opened + */ + bool isOpenFile(); + + /** + * Record a chunk of data in an openend file + * @param buffer The data chunk to be recorded + * @param nSamples Number of samples (number of bytes) to be recorded + */ + void recData(SFLDataFormat* buffer, int nSamples); // TODO ad the data to rec + +protected: + + /** + * Set the header for raw files + */ + bool setRawFile(const char* fileName); + + /** + * Set the header for wave files + */ + bool setWavFile(const char* fileName); + + /** + * Compute the number of byte recorded and close the file + */ + void closeWavFile(); + + /** + * Pointer to the recorded file + */ + FILE *fp; //file pointer + + /** + * File format (RAW / WAVE) + */ + FILE_TYPE fileType_; + + /** + * Sound format (SINT16/SINT32) + */ + SOUND_FORMAT sndFormat_; + + /** + * Number of channels + */ + int channels_; + + /** + * Number f byte recorded + */ + unsigned long byteCounter_; + + /** + * Sampling rate + */ + int sndSmplRate_; + +}; diff --git a/src/audio/pulselayer.h b/src/audio/pulselayer.h index bdb34085b62e9abea85f27f4517b4f76b701e780..36ca8057ce47dccc78c23455dfa9b4ae40cb6ce7 100644 --- a/src/audio/pulselayer.h +++ b/src/audio/pulselayer.h @@ -22,6 +22,7 @@ #include "audiolayer.h" #include "audiostream.h" +#include "plug-in/audiorecorder/audiorecord.h" #include <pulse/pulseaudio.h> diff --git a/src/global.h b/src/global.h index 45332563dc0bbb28a0f22a777d997deafa5c32f5..6dfe9a1e1ba3c2a34eb2231a15f4b222ca033085 100644 --- a/src/global.h +++ b/src/global.h @@ -37,6 +37,19 @@ typedef float float32; typedef short int16; +//useful typedefs. +typedef signed short SINT16; +typedef signed int SINT32; + +typedef unsigned long FILE_TYPE; +typedef unsigned long SOUND_FORMAT; + +const FILE_TYPE FILE_RAW = 1; +const FILE_TYPE FILE_WAV = 2; + +static const SOUND_FORMAT INT16 = 0x2; // TODO shold change these symbols +static const SOUND_FORMAT INT32 = 0x8; + #define SUCCESS 0 #define ASSERT( expected , value) if( value == expected ) return SUCCESS; \ diff --git a/src/plug-in/Makefile.am b/src/plug-in/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..c97ccdc21ad9d23126553e6efeda496aba88d944 --- /dev/null +++ b/src/plug-in/Makefile.am @@ -0,0 +1,12 @@ +include ../../globals.mak + +SUBDIRS=audiorecorder + +noinst_LTLIBRARIES = libplugin.la + +SUBDIRS=test + +libplugin_la_SOURCES = \ + pluginmanager.cpp \ + librarymanager.cpp + diff --git a/src/plug-in/audiorecorder/Makefile.am b/src/plug-in/audiorecorder/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..37a2ce4ed072fc300b0d85771f72e81d2fdf42e6 --- /dev/null +++ b/src/plug-in/audiorecorder/Makefile.am @@ -0,0 +1,7 @@ +include $(top_srcdir)/globals.mak + +noinst_LTLIBRARIES = libaudiorecorder.la + +libaudiorecorder_la_SOURCES = \ + audiorecord.cpp + diff --git a/src/plug-in/audiorecorder/audiorecord.cpp b/src/plug-in/audiorecorder/audiorecord.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65f63803942947e3cac58e91adcab2e76e1a9cf4 --- /dev/null +++ b/src/plug-in/audiorecorder/audiorecord.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * Author: Alexandre Savard <alexandre.savard@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. + */ + +#include "audiorecord.h" + +AudioRecord::AudioRecord(){ + sndSmplRate_ = 44100; + channels_ = 1; + byteCounter_ = 0; + +} + + +void AudioRecord::setSndSamplingRate(int smplRate){ + sndSmplRate_ = smplRate; +} + + +void AudioRecord::openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format) { + + channels_ =1; + fileType_ = type; + byteCounter_ = 0; + sndFormat_ = format; + + bool result = false; + + if(fileType_ == FILE_RAW){ + result = setRawFile( fileName.c_str() ); + } + else if (fileType_ == FILE_WAV){ + result = setWavFile( fileName.c_str() ); + } + +} + + +void AudioRecord::closeFile() { + + if (fp == 0) return; + + if (fileType_ == FILE_RAW) + fclose(fp); + else if (fileType_ == FILE_WAV) + this->closeWavFile(); + +} + + +bool AudioRecord::isOpenFile() { + + if(fp) + return true; + else + return false; +} + + +bool AudioRecord::setRawFile(const char *fileName) { + + char name[8192]; + strncpy(name, fileName, 8192); + if ( strstr(name, ".raw") == NULL) strcat(name, ".raw"); + fp = fopen(name, "wb"); + if ( !fp ) { + cout << "AudioRecord: could not create RAW file: " << name << '.'; + return false; + } + + if ( sndFormat_ != INT16 ) { // TODO need to change INT16 to SINT16 + sndFormat_ = INT16; + cout << "AudioRecord: using 16-bit signed integer data format for file " << name << '.'; + } + + cout << "AudioRecord: creating RAW file: " << name; + return true; +} + + +bool AudioRecord::setWavFile(const char *fileName) { + + char name[8192]; + strncpy(name, fileName, 8192); + if ( strstr(name, ".wav") == NULL) strcat(name, ".wav"); + fp = fopen(name, "wb"); + if ( !fp ) { + cout << "AudioRecord: could not create WAV file: " << name; + return false; + } + + struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1, + 44100, 0, 2, 16, "dat", 0}; + hdr.riff[3] = 'F'; + hdr.wave[3] = 'E'; + hdr.fmt[3] = ' '; + hdr.data[3] = 'a'; + hdr.num_chans = channels_; + if ( sndFormat_ == INT16 ) { // TODO need to write INT16 to SINT16 + hdr.bits_per_samp = 16; + } + hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8); + hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp); + + + if ( fwrite(&hdr, 4, 11, fp) != 11 ) { + cout << "AudioRecord: could not write WAV header for file " << name << '.'; + return false; + } + + cout << "AudioRecord: creating WAV file: " << name; + return true; +} + + +void AudioRecord::closeWavFile() +{ + int bytes_per_sample = 1; + if ( sndFormat_ == INT16 ) + bytes_per_sample = 2; + + + SINT32 bytes = byteCounter_ * channels_ * bytes_per_sample; + fseek(fp, 40, SEEK_SET); // jump to data length + fwrite(&bytes, 4, 1, fp); + + bytes = byteCounter_ * channels_ * bytes_per_sample + 44; // + 44 for the wave header + fseek(fp, 4, SEEK_SET); // jump to file size + fwrite(&bytes, 4, 1, fp); + fclose( fp ); +} + + +void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) { + + if (fp == 0){ + cout << "AudioRecord: Can't record data, a file has not yet been opened!"; + return; + } + + if ( sndFormat_ == INT16 ) { // TODO change INT16 to SINT16 + if (nSamples <= 1){ + if ( fwrite(buffer, 2, 1, fp) != 1) + cout << "AudioRecord: Could not record data!"; + } + else { + for ( int k=0; k<nSamples; k++ ) { + cout << "Buffer[" << k << "] : " << buffer[k] << "\n"; + if ( fwrite(&buffer[k], 2, 1, fp) != 1 ) + cout << "AudioRecord: Could not record data!"; + } + } + } + + + + + byteCounter_ += (unsigned long)(sizeof(buffer) / sizeof(SINT16)); + + return; +} + diff --git a/src/plug-in/audiorecorder/audiorecord.h b/src/plug-in/audiorecorder/audiorecord.h new file mode 100644 index 0000000000000000000000000000000000000000..b38eefb29a59be117d896e9c2c6147ff43011ef3 --- /dev/null +++ b/src/plug-in/audiorecorder/audiorecord.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * Author: Alexandre Savard <alexandre.savard@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. + */ + + +#include <iostream> +#include <string.h> + +#include "global.h" + +using namespace std; + + +// structure for the wave header +struct wavhdr { + char riff[4]; // "RIFF" + SINT32 file_size; // in bytes + char wave[4]; // "WAVE" + char fmt[4]; // "fmt " + SINT32 chunk_size; // in bytes (16 for PCM) + SINT16 format_tag; // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law + SINT16 num_chans; // 1=mono, 2=stereo + SINT32 sample_rate; + SINT32 bytes_per_sec; + SINT16 bytes_per_samp; // 2=16-bit mono, 4=16-bit stereo + SINT16 bits_per_samp; + char data[4]; // "data" + SINT32 data_length; // in bytes +}; + +class AudioRecord +{ + +public: + + AudioRecord(); + + void setSndSamplingRate(int smplRate); + + /** + * Check if no otehr file is opened, then create a new one + * @param fileName A string containing teh file (with/without extension) + * @param type The sound file format (FILE_RAW, FILE_WAVE) + * @param format Internal sound format (INT16 / INT32) + */ + void openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format); + + /** + * Close the opend recording file. If wave: cout the number of byte + */ + void closeFile(); + + /** + * Check if a file is already opened + */ + bool isOpenFile(); + + /** + * Record a chunk of data in an openend file + * @param buffer The data chunk to be recorded + * @param nSamples Number of samples (number of bytes) to be recorded + */ + void recData(SFLDataFormat* buffer, int nSamples); // TODO ad the data to rec + +protected: + + /** + * Set the header for raw files + */ + bool setRawFile(const char* fileName); + + /** + * Set the header for wave files + */ + bool setWavFile(const char* fileName); + + /** + * Compute the number of byte recorded and close the file + */ + void closeWavFile(); + + /** + * Pointer to the recorded file + */ + FILE *fp; //file pointer + + /** + * File format (RAW / WAVE) + */ + FILE_TYPE fileType_; + + /** + * Sound format (SINT16/SINT32) + */ + SOUND_FORMAT sndFormat_; + + /** + * Number of channels + */ + int channels_; + + /** + * Number f byte recorded + */ + unsigned long byteCounter_; + + /** + * Sampling rate + */ + int sndSmplRate_; + +}; diff --git a/src/plug-in/librarymanager.cpp b/src/plug-in/librarymanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..138b59f5f49b2c2ed19b170deb36dfb373b00846 --- /dev/null +++ b/src/plug-in/librarymanager.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009 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. + */ + + +#include "librarymanager.h" + + LibraryManager::LibraryManager (const std::string &filename) + : _filename(filename), _handlePtr(NULL) +{ + _handlePtr = loadLibrary (filename); +} + +LibraryManager::~LibraryManager (void) +{ + unloadLibrary (); +} + +LibraryManager::LibraryHandle LibraryManager::loadLibrary (const std::string &filename) +{ + LibraryHandle pluginHandlePtr = NULL; + const char *error; + + _debug("Loading dynamic library %s\n", filename.c_str()); + + /* Load the library */ + pluginHandlePtr = dlopen( filename.c_str(), RTLD_LAZY ); + if( !pluginHandlePtr ) { + error = dlerror(); + _debug("Error while opening plug-in: %s\n", error); + return NULL; + } + dlerror(); + return pluginHandlePtr; +} + +int LibraryManager::unloadLibrary () +{ + if (_handlePtr == NULL) + return 1; + + _debug("Unloading dynamic library ...\n"); + dlclose( _handlePtr ); + if (dlerror()) + { + _debug("Error unloading the library : %s\n...", dlerror()); + return 1; + } + return 0; +} + +int LibraryManager::resolveSymbol (const std::string &symbol, SymbolHandle *symbolPtr) +{ + SymbolHandle sy = 0; + + if (_handlePtr){ + try { + sy = dlsym(_handlePtr, symbol.c_str()); + if(sy != NULL) { + *symbolPtr = sy; + return 0; + } + } + catch (...) {} + + throw LibraryManagerException ( _filename, symbol, LibraryManagerException::symbolNotFound); + } + else + return 1; +} + + +/************************************************************************************************/ + +LibraryManagerException::LibraryManagerException (const std::string &libraryName, const std::string &details, Reason reason) : + _reason (reason), _details (""), std::runtime_error ("") + +{ + if (_reason == loadingFailed) + _details = "Error when loading " + libraryName + "\n" + details; + else + _details = "Error when resolving symbol " + details + " in " + libraryName; +} + +const char* LibraryManagerException::what () const throw() +{ + return _details.c_str(); +} diff --git a/src/plug-in/librarymanager.h b/src/plug-in/librarymanager.h new file mode 100644 index 0000000000000000000000000000000000000000..e244d448a1152a46950d4b0ec95e06847eac4ff5 --- /dev/null +++ b/src/plug-in/librarymanager.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009 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 LIBRARY_MANAGER_H +#define LIBRARY_MANAGER_H + +#include "dlfcn.h" +#include <stdexcept> + +#include "global.h" + +class LibraryManager { + + public: + typedef void* LibraryHandle; + typedef void* SymbolHandle; + + LibraryManager (const std::string &filename); + ~LibraryManager (void); + + int resolveSymbol (const std::string &symbol, SymbolHandle *ptr); + + int unloadLibrary (void); + + protected: + LibraryHandle loadLibrary (const std::string &filename); + + private: + std::string _filename; + LibraryHandle _handlePtr; +}; + +class LibraryManagerException : public std::runtime_error { + + public: + + typedef enum Reason { + loadingFailed = 0, + symbolNotFound + }Reason; + + LibraryManagerException (const std::string &libraryName, const std::string &details, Reason reason); + ~LibraryManagerException (void) throw() {} + + inline Reason getReason (void) { return _reason; } + + const char* what () const throw(); + + private: + Reason _reason; + std::string _details; +}; + +#endif // LIBRARY_MANAGER_H diff --git a/src/plug-in/plugin.h b/src/plug-in/plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..2769c56c372e22be24334107ef6efdf5bf4e8b31 --- /dev/null +++ b/src/plug-in/plugin.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009 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 PLUGIN_H +#define PLUGIN_H + +#include "global.h" + +#include "pluginmanager.h" + +/* + * @file plugin.h + * @brief Define a plugin object + */ + +class Plugin { + + public: + Plugin( const std::string &name ){ + _name = name; + } + + virtual ~Plugin() {} + + inline std::string getPluginName (void) { return _name; } + + /** + * Return the minimal core version required so that the plugin could work + * @return int The version required + */ + virtual int initFunc (PluginInfo **info) = 0; + + private: + Plugin &operator =(const Plugin &plugin); + + std::string _name; +}; + +typedef Plugin* createFunc (void); + +typedef void destroyFunc (Plugin*); + +#endif //PLUGIN_H + diff --git a/src/plug-in/pluginmanager.cpp b/src/plug-in/pluginmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d391f6ae6383c18220484b0c98d00991184ac9b --- /dev/null +++ b/src/plug-in/pluginmanager.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2009 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. + */ + +#include <dirent.h> +#include <dlfcn.h> + +#include "pluginmanager.h" + +PluginManager* PluginManager::_instance = 0; + + PluginManager* +PluginManager::instance() +{ + if(!_instance){ + return new PluginManager(); + } + return _instance; +} + + PluginManager::PluginManager() +:_loadedPlugins() +{ + _instance = this; +} + +PluginManager::~PluginManager() +{ + _instance = 0; +} + + int +PluginManager::loadPlugins (const std::string &path) +{ + std::string pluginDir, current; + DIR *dir; + dirent *dirStruct; + LibraryManager *library; + Plugin *plugin; + + const std::string pDir = ".."; + const std::string cDir = "."; + + /* The directory in which plugins are dropped. Default: /usr/lib/sflphone/plugins/ */ + ( path == "" )? pluginDir = std::string(PLUGINS_DIR).append("/"):pluginDir = path; + _debug("Loading plugins from %s...\n", pluginDir.c_str()); + + dir = opendir( pluginDir.c_str() ); + /* Test if the directory exists or is readable */ + if( dir ){ + /* Read the directory */ + while( (dirStruct=readdir(dir)) ){ + /* Get the name of the current item in the directory */ + current = dirStruct->d_name; + /* Test if the current item is not the parent or the current directory */ + if( current != pDir && current != cDir ){ + + /* Load the dynamic library */ + library = loadDynamicLibrary( pluginDir + current ); + + /* Instanciate the plugin object */ + if(instanciatePlugin (library, &plugin) != 0) + { + _debug("Error instanciating the plugin ...\n"); + return 1; + } + + /* Regitering the current plugin */ + if(registerPlugin (plugin, library) != 0) + { + _debug("Error registering the plugin ...\n"); + return 1; + } + } + } + } + else + return 1; + + /* Close the directory */ + closedir( dir ); + + return 0; +} + +int +PluginManager::unloadPlugins (void) +{ + PluginInfo *info; + + if(_loadedPlugins.empty()) return 0; + + /* Use an iterator on the loaded plugins map */ + pluginMap::iterator iter; + + iter = _loadedPlugins.begin(); + while( iter != _loadedPlugins.end() ) { + info = iter->second; + + if (deletePlugin (info) != 0) + { + _debug("Error deleting the plugin ... \n"); + return 1; + } + + unloadDynamicLibrary (info->_libraryPtr); + + if (unregisterPlugin (info) != 0) + { + _debug("Error unregistering the plugin ... \n"); + return 1; + } + + iter++; + } + return 0; +} + + bool +PluginManager::isPluginLoaded (const std::string &name) +{ + if(_loadedPlugins.empty()) return false; + + /* Use an iterator on the loaded plugins map */ + pluginMap::iterator iter; + iter = _loadedPlugins.find (name); + + /* Returns map::end if the specified key has not been found */ + if(iter==_loadedPlugins.end()) + return false; + + /* Returns the plugin pointer */ + return true; +} + + + LibraryManager* +PluginManager::loadDynamicLibrary (const std::string& filename) +{ + /* Load the library through the library manager */ + return new LibraryManager (filename); +} + + int +PluginManager::unloadDynamicLibrary (LibraryManager *libraryPtr) +{ + _debug("Unloading dynamic library ...\n"); + /* Close it */ + return libraryPtr->unloadLibrary (); +} + + int +PluginManager::instanciatePlugin (LibraryManager *libraryPtr, Plugin **plugin) +{ + createFunc *createPlugin; + LibraryManager::SymbolHandle symbol; + + if (libraryPtr->resolveSymbol ("createPlugin", &symbol) != 0) + return 1; + createPlugin = (createFunc*)symbol; + *plugin = createPlugin(); + return 0; +} + + int +PluginManager::deletePlugin (PluginInfo *plugin) +{ + destroyFunc *destroyPlugin; + LibraryManager::SymbolHandle symbol; + + if (plugin->_libraryPtr->resolveSymbol ("destroyPlugin", &symbol) != 0) + return 1; + destroyPlugin = (destroyFunc*)symbol; + /* Call it */ + destroyPlugin (plugin->_plugin); + return 0; +} + + int +PluginManager::registerPlugin (Plugin *plugin, LibraryManager *library) +{ + std::string key; + PluginInfo *p_info; + + if( plugin==0 ) + return 1; + + p_info = new PluginInfo(); + /* Retrieve information from the plugin */ + plugin->initFunc (&p_info); + key = p_info->_name; + + //p_info->_plugin = plugin; + p_info->_libraryPtr = library; + + /* Add the data in the loaded plugin map */ + _loadedPlugins[ key ] = p_info; + return 0; +} + +int +PluginManager::unregisterPlugin (PluginInfo *plugin) +{ + pluginMap::iterator iter; + std::string key; + + key = plugin->_name; + + if (!isPluginLoaded(key)) + return 1; + + iter = _loadedPlugins.find (key); + _loadedPlugins.erase (iter); + + return 0; +} diff --git a/src/plug-in/pluginmanager.h b/src/plug-in/pluginmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..4b3a1869200ce7deaac770d661d360223adbc7b0 --- /dev/null +++ b/src/plug-in/pluginmanager.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 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 PLUGIN_MANAGER_H +#define PLUGIN_MANAGER_H + +/* + * @file pluginmanager.h + * @brief Base class of the plugin manager + */ + +#include "librarymanager.h" +#include "global.h" + +#include <map> +#include <string> +#include <vector> + +class Plugin; + +typedef struct PluginInfo { + std::string _name; + LibraryManager *_libraryPtr; + Plugin *_plugin; + int _major_version; + int _minor_version; +} PluginInfo; + +#include "plugin.h" + +class PluginManager { + public: + /** + * Destructor + */ + ~PluginManager(); + + /** + * Returns the unique instance of the plugin manager + */ + static PluginManager* instance(); + + /** + * Load all the plugins found in a specific directory + * @param path The absolute path to the directory + * @return int The number of items loaded + */ + int loadPlugins (const std::string &path = ""); + + int unloadPlugins (void); + + int instanciatePlugin (LibraryManager* libraryPtr, Plugin** plugin); + + /** + * Check if a plugin has been already loaded + * @param name The name of the plugin looked for + * @return bool The pointer on the plugin or NULL if not found + */ + bool isPluginLoaded (const std::string &name); + + int registerPlugin (Plugin *plugin, LibraryManager *library); + + int unregisterPlugin (PluginInfo *plugin); + + int deletePlugin (PluginInfo *plugin); + + /** + * Load a unix dynamic/shared library + * @param filename The path to the dynamic/shared library + * @return LibraryManager* A pointer on the library + */ + LibraryManager* loadDynamicLibrary (const std::string &filename); + + /** + * Unload a unix dynamic/shared library + * @param LibraryManager* The pointer on the loaded library + */ + int unloadDynamicLibrary (LibraryManager* libraryPtr); + + private: + /** + * Default constructor + */ + PluginManager(); + + /* Map of plugins associated by their string name */ + typedef std::map<std::string, PluginInfo*> pluginMap; + pluginMap _loadedPlugins; + + /* The unique static instance */ + static PluginManager* _instance; + +}; + +#endif //PLUGIN_MANAGER_H diff --git a/src/plug-in/test/Makefile.am b/src/plug-in/test/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..6809be2c0a185e16f72edcef1b57103fbcbea8f8 --- /dev/null +++ b/src/plug-in/test/Makefile.am @@ -0,0 +1,19 @@ +include $(top_srcdir)/globals.mak + +PLUGIN_LIB = libplugintest.so +libplugintest_so_SOURCES = pluginTest.cpp +libplugintest_so_CXXFLAGS = -fPIC -g -Wall +libplugintest_so_LDFLAGS = --shared -lc +INSTALL_PLUGIN_RULE = install-libplugintest_so + +noinst_PROGRAMS = libplugintest.so + +install-exec-local: install-libplugintest_so +uninstall-local: uninstall-libplugintest_so + +install-libplugintest_so: libplugintest.so + mkdir -p $(sflplugindir) + $(INSTALL_PROGRAM) libplugintest.so $(sflplugindir) + +uninstall-libplugintest_so: + rm -f $(sflplugindir)/libplugintest.so diff --git a/src/plug-in/test/pluginTest.cpp b/src/plug-in/test/pluginTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbd1b1d760dd79797bdafead09b73fb69c1836a4 --- /dev/null +++ b/src/plug-in/test/pluginTest.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 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. + */ + +#include "../plugin.h" + +#define MAJOR_VERSION 1 +#define MINOR_VERSION 0 + +class PluginTest : public Plugin { + + public: + PluginTest( const std::string &name ) + :Plugin( name ) { + } + + virtual int initFunc (PluginInfo **info) { + + (*info)->_plugin = this; + (*info)->_major_version = MAJOR_VERSION; + (*info)->_minor_version = MINOR_VERSION; + (*info)->_name = getPluginName(); + + return 0; + } +}; + +extern "C" Plugin* createPlugin (void){ + return new PluginTest("mytest"); +} + +extern "C" void destroyPlugin (Plugin *p){ + delete p; +} diff --git a/test/Makefile.am b/test/Makefile.am index 14411aa140bbc3264308b27f0cd418287544821c..5c684888b422490c0e15316692bc4fcee3eceb78 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,6 @@ include ../globals.mak -bin_PROGRAMS = configurationTester +bin_PROGRAMS = configurationTester pluginmanagerTester audiorecorderTester OBJECT_FILES= \ ../src/sflphoned-managerimpl.o \ @@ -15,7 +15,8 @@ OBJECT_FILES= \ ../src/sflphoned-sipaccount.o \ ../src/sflphoned-iaxaccount.o \ ../src/sflphoned-eventthread.o \ - ../src/sflphoned-useragent.o \ + ../src/plug-in/pluginmanager.o \ + ../src/plug-in/audiorecorder/audiorecord.o \ ../src/sflphoned-samplerateconverter.o configurationTester_SOURCES = \ @@ -23,6 +24,17 @@ configurationTester_SOURCES = \ configurationTest.h \ TestMain.cpp +pluginmanagerTester_SOURCES = \ + pluginmanagerTest.h \ + pluginmanagerTest.cpp \ + TestMain.cpp + +audiorecorderTester_SOURCES = \ + audiorecorderTest.h \ + audiorecorderTest.cpp \ + TestMain.cpp + + configurationTester_LDADD = \ ../src/libsflphone.la \ $(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) $(IAX_LIBS) \ @@ -36,4 +48,32 @@ configurationTester_LDADD = \ @SAMPLERATE_LIBS@ \ $(PJSIP_LIBS) \ $(OBJECT_FILES) - + +pluginmanagerTester_LDADD = \ + ../src/libsflphone.la \ + $(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) $(IAX_LIBS) \ + @ALSA_LIBS@ \ + @PULSEAUDIO_LIBS@ \ + @CPPUNIT_LIBS@ \ + @CCEXT2_LIBS@ \ + @CCGNU2_LIBS@ \ + @CCRTP_LIBS@ \ + @DBUSCPP_LIBS@ \ + @SAMPLERATE_LIBS@ \ + $(PJSIP_LIBS) \ + $(OBJECT_FILES) + +audiorecorderTester_LDADD = \ + ../src/libsflphone.la \ + $(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) $(IAX_LIBS) \ + @ALSA_LIBS@ \ + @PULSEAUDIO_LIBS@ \ + @CPPUNIT_LIBS@ \ + @CCEXT2_LIBS@ \ + @CCGNU2_LIBS@ \ + @CCRTP_LIBS@ \ + @DBUSCPP_LIBS@ \ + @SAMPLERATE_LIBS@ \ + $(PJSIP_LIBS) \ + $(OBJECT_FILES) + diff --git a/test/audiorecorderTest.cpp b/test/audiorecorderTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f766d4af1d082307a256fe08c6506806810d733a --- /dev/null +++ b/test/audiorecorderTest.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 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. + */ + +#include <stdio.h> +#include <sstream> + +#include "audiorecorderTest.h" + +using std::cout; +using std::endl; + +void AudioRecorderTest::setUp(){ + // Instanciate the object + _ar = new AudioRecord(); +} + +void AudioRecorderTest::testRecordData(){ + + FILE_TYPE ft = FILE_WAV; + SOUND_FORMAT sf = INT16; + _ar->setSndSamplingRate(44100); + _ar->openFile("theWavFile.wav",ft,sf); + + cout << "file opened!\n"; + + SFLDataFormat buf [2]; + for (SFLDataFormat i = -32768; i < 32767; i++ ){ + buf[0] = i; + buf[1] = i; + _ar->recData(buf,2); + } + + _ar->closeFile(); +} + +void AudioRecorderTest::tearDown(){ + // Delete the audio recorder module + delete _ar; _ar = NULL; +} diff --git a/test/audiorecorderTest.h b/test/audiorecorderTest.h new file mode 100644 index 0000000000000000000000000000000000000000..216b657079562007a1eb04955f390e3263ef1c87 --- /dev/null +++ b/test/audiorecorderTest.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2009 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. + */ + +// Cppunit import +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCaller.h> +#include <cppunit/TestCase.h> +#include <cppunit/TestSuite.h> + +#include <assert.h> + +// Application import +#include "plug-in/pluginmanager.h" +#include "plug-in/audiorecorder/audiorecord.h" + +/* + * @file audiorecorderTest.cpp + * @brief Regroups unitary tests related to the plugin manager. + */ + +#ifndef _AUDIORECORDER_TEST_ +#define _AUDIORECORDER_TEST_ + +class AudioRecorderTest : public CppUnit::TestCase { + + /* + * Use cppunit library macros to add unit test the factory + */ + CPPUNIT_TEST_SUITE( AudioRecorderTest ); + CPPUNIT_TEST( testRecordData ); + CPPUNIT_TEST_SUITE_END(); + + public: + AudioRecorderTest() : CppUnit::TestCase("Audio Recorder Tests") {} + + /* + * Code factoring - Common resources can be initialized here. + * This method is called by unitcpp before each test + */ + void setUp(); + + /* + * Code factoring - Common resources can be released here. + * This method is called by unitcpp after each test + */ + inline void tearDown(); + + void testRecordData(); + + private: + AudioRecord *_ar; +}; + +/* Register our test module */ +CPPUNIT_TEST_SUITE_REGISTRATION( AudioRecorderTest ); + +#endif diff --git a/test/pluginmanagerTest.cpp b/test/pluginmanagerTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96994b6925219cfc565906873e8d6574fcc3c238 --- /dev/null +++ b/test/pluginmanagerTest.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2009 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. + */ + +#include <stdio.h> +#include <sstream> +#include <dlfcn.h> + +#include "pluginmanagerTest.h" + +using std::cout; +using std::endl; + +#define PLUGIN_TEST_DIR "/usr/lib/sflphone/plugins/" +#define PLUGIN_TEST_DESC "mytest" +#define PLUGIN_TEST_NAME "/usr/lib/sflphone/plugins/libplugintest.so" + + +void PluginManagerTest::setUp(){ + // Instanciate the plugin manager singleton + _pm = PluginManager::instance(); + library = 0; + plugin = 0; +} + +void PluginManagerTest::testLoadDynamicLibrary(){ + CPPUNIT_ASSERT(_pm->loadDynamicLibrary(PLUGIN_TEST_NAME) != NULL); +} + +void PluginManagerTest::testUnloadDynamicLibrary(){ + library = _pm->loadDynamicLibrary(PLUGIN_TEST_NAME); + CPPUNIT_ASSERT(library != NULL); + CPPUNIT_ASSERT(_pm->unloadDynamicLibrary(library) == 0 ); +} + +void PluginManagerTest::testInstanciatePlugin(){ + library = _pm->loadDynamicLibrary (PLUGIN_TEST_NAME); + CPPUNIT_ASSERT(library != NULL); + CPPUNIT_ASSERT (_pm->instanciatePlugin (library, &plugin) == 0); + CPPUNIT_ASSERT (plugin!=NULL); +} + +void PluginManagerTest::testInitPlugin(){ + + library = _pm->loadDynamicLibrary (PLUGIN_TEST_NAME); + CPPUNIT_ASSERT(library != NULL); + CPPUNIT_ASSERT (_pm->instanciatePlugin (library, &plugin) == 0); + CPPUNIT_ASSERT (plugin!=NULL); + CPPUNIT_ASSERT (plugin->getPluginName() == PLUGIN_TEST_DESC); +} + +void PluginManagerTest::testRegisterPlugin(){ + library = _pm->loadDynamicLibrary (PLUGIN_TEST_NAME); + CPPUNIT_ASSERT(library != NULL); + CPPUNIT_ASSERT (_pm->instanciatePlugin (library, &plugin) == 0); + CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == false); + CPPUNIT_ASSERT (_pm->registerPlugin (plugin, library) == 0); + CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == true); +} + +void PluginManagerTest::testLoadPlugins (){ + CPPUNIT_ASSERT (_pm->loadPlugins (PLUGIN_TEST_DIR) == 0); + CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == true); +} + +void PluginManagerTest::testUnloadPlugins (){ + CPPUNIT_ASSERT (_pm->loadPlugins (PLUGIN_TEST_DIR) == 0); + CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == true); + CPPUNIT_ASSERT (_pm->unloadPlugins () == 0); + CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == false); +} + +void PluginManagerTest::tearDown(){ + // Delete the plugin manager object + delete _pm; _pm=0; + if(plugin) + delete plugin; plugin = 0; + if(library) + delete library; library = 0; +} diff --git a/test/pluginmanagerTest.h b/test/pluginmanagerTest.h new file mode 100644 index 0000000000000000000000000000000000000000..2e421958460445c3339ea1c2a97cef767258fabc --- /dev/null +++ b/test/pluginmanagerTest.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009 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. + */ + +// Cppunit import +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCaller.h> +#include <cppunit/TestCase.h> +#include <cppunit/TestSuite.h> + +#include <assert.h> + +// Application import +#include "plug-in/pluginmanager.h" +#include "plug-in/librarymanager.h" +#include "plug-in/plugin.h" + +/* + * @file pluginManagerTest.cpp + * @brief Regroups unitary tests related to the plugin manager. + */ + +#ifndef _PLUGINMANAGER_TEST_ +#define _PLUGINMANAGER_TEST_ + +class PluginManagerTest : public CppUnit::TestCase { + + /* + * Use cppunit library macros to add unit test the factory + */ + CPPUNIT_TEST_SUITE( PluginManagerTest ); + CPPUNIT_TEST( testLoadDynamicLibrary ); + CPPUNIT_TEST( testUnloadDynamicLibrary ); + CPPUNIT_TEST( testInstanciatePlugin ); + CPPUNIT_TEST( testInitPlugin ); + CPPUNIT_TEST( testRegisterPlugin ); + CPPUNIT_TEST( testLoadPlugins ); + CPPUNIT_TEST( testUnloadPlugins ); + CPPUNIT_TEST_SUITE_END(); + + public: + PluginManagerTest() : CppUnit::TestCase("Plugin Manager Tests") {} + + /* + * Code factoring - Common resources can be initialized here. + * This method is called by unitcpp before each test + */ + void setUp(); + + /* + * Code factoring - Common resources can be released here. + * This method is called by unitcpp after each test + */ + inline void tearDown (); + + void testLoadDynamicLibrary (); + + void testUnloadDynamicLibrary (); + + void testInstanciatePlugin (); + + void testInitPlugin (); + + void testRegisterPlugin (); + + void testLoadPlugins (); + + void testUnloadPlugins (); + + private: + PluginManager *_pm; + LibraryManager *library; + Plugin *plugin; +}; + +/* Register our test module */ +CPPUNIT_TEST_SUITE_REGISTRATION( PluginManagerTest ); + +#endif