summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.symbian/bld.inf14
-rw-r--r--build.symbian/symbian_audio_aps.mmp20
-rw-r--r--build.symbian/symbian_ua.mmp48
-rw-r--r--build.symbian/symsndtest.mmp47
-rw-r--r--pjmedia/include/pjmedia/symbian_sound_aps.h52
-rw-r--r--pjmedia/src/pjmedia/symbian_sound_aps.cpp824
-rw-r--r--pjsip-apps/src/symbian_ua/main_symbian.cpp3
-rw-r--r--pjsip-apps/src/symbian_ua/ua.cpp5
-rw-r--r--pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp26
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp4
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp4
-rw-r--r--pjsip-apps/src/symsndtest/app_main.cpp72
-rw-r--r--pjsip-apps/src/symsndtest/main_symbian.cpp3
13 files changed, 1041 insertions, 81 deletions
diff --git a/build.symbian/bld.inf b/build.symbian/bld.inf
index 80645f64..b624905e 100644
--- a/build.symbian/bld.inf
+++ b/build.symbian/bld.inf
@@ -1,3 +1,6 @@
+#define SND_USE_NULL 0
+#define SND_USE_APS 0
+
prj_platforms
winscw
//armv5
@@ -10,8 +13,6 @@ pjlib.mmp
pjlib_util.mmp
pjnath.mmp
pjsdp.mmp
-//null_audio.mmp
-symbian_audio.mmp
pjmedia.mmp
pjsip.mmp
pjsip_simple.mmp
@@ -23,6 +24,15 @@ libsrtp.mmp
libgsmcodec.mmp
libspeexcodec.mmp
+/* Sound device impl */
+#if SND_USE_NULL
+ null_audio.mmp
+#elif SND_USE_APS
+ symbian_audio_aps.mmp
+#else
+ symbian_audio.mmp
+#endif
+
/* Applications */
//pjlib_test.mmp
//symsndtest.mmp
diff --git a/build.symbian/symbian_audio_aps.mmp b/build.symbian/symbian_audio_aps.mmp
new file mode 100644
index 00000000..85cb1e84
--- /dev/null
+++ b/build.symbian/symbian_audio_aps.mmp
@@ -0,0 +1,20 @@
+TARGET symbian_audio_aps.lib
+TARGETTYPE lib
+
+OPTION CW -lang c++
+OPTION GCCE -O2 -fno-unit-at-a-time
+
+MACRO PJ_M_I386=1
+MACRO PJ_SYMBIAN=1
+
+SYSTEMINCLUDE ..\pjmedia\include
+SYSTEMINCLUDE ..\pjlib\include
+
+SOURCEPATH ..\pjmedia\src\pjmedia
+SOURCE symbian_sound_aps.cpp
+
+SYSTEMINCLUDE \epoc32\include\mmf\server
+SYSTEMINCLUDE \epoc32\include\mmf\common
+SYSTEMINCLUDE \epoc32\include\mda\common
+SYSTEMINCLUDE \epoc32\include\libc
+SYSTEMINCLUDE \epoc32\include
diff --git a/build.symbian/symbian_ua.mmp b/build.symbian/symbian_ua.mmp
index e23d0d86..5bdfebad 100644
--- a/build.symbian/symbian_ua.mmp
+++ b/build.symbian/symbian_ua.mmp
@@ -1,3 +1,6 @@
+#define SND_USE_NULL 0
+#define SND_USE_APS 0
+
TARGET symbian_ua.exe
TARGETTYPE exe
UID 0x0 0xA000000D
@@ -7,10 +10,6 @@ SOURCEPATH ..\pjsip-apps\src\symbian_ua
MACRO PJ_M_I386=1
MACRO PJ_SYMBIAN=1
-#if defined(PJ_BUILD_DLL)
- MACRO PJ_DLL=1
-#endif
-
// Source files
SOURCE ua.cpp
@@ -18,6 +17,10 @@ SOURCE main_symbian.cpp
DOCUMENT ua.h
+START RESOURCE symbian_ua_reg.rss
+ TARGETPATH \private\10003a3f\apps
+END
+
SYSTEMINCLUDE ..\pjlib\include
SYSTEMINCLUDE ..\pjlib-util\include
SYSTEMINCLUDE ..\pjnath\include
@@ -27,18 +30,25 @@ SYSTEMINCLUDE ..\pjsip\include
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
-#if defined(PJ_BUILD_DLL)
- LIBRARY pjsua_lib.lib pjsip_ua.lib
- LIBRARY pjsip_simple.lib pjsip.lib pjsdp.lib pjmedia.lib
- LIBRARY pjnath.lib pjlib_util.lib pjlib.lib
- LIBRARY symbian_audio.lib libsrtp.lib
- LIBRARY libgsmcodec.lib libspeexcodec.lib
+STATICLIBRARY pjsua_lib.lib pjsip_ua.lib
+STATICLIBRARY pjsip_simple.lib pjsip.lib pjsdp.lib pjmedia.lib
+STATICLIBRARY pjnath.lib pjlib_util.lib pjlib.lib
+STATICLIBRARY libsrtp.lib
+STATICLIBRARY libgsmcodec.lib libspeexcodec.lib
+
+#if SND_USE_NULL || defined(WINSCW)
+ STATICLIBRARY null_audio.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
+#elif SND_USE_APS
+ STATICLIBRARY symbian_audio_aps.lib
+ LIBRARY APSSession2.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
+ MACRO PJMEDIA_SYM_SND_USE_APS=1
#else
- STATICLIBRARY pjsua_lib.lib pjsip_ua.lib
- STATICLIBRARY pjsip_simple.lib pjsip.lib pjsdp.lib pjmedia.lib
- STATICLIBRARY pjnath.lib pjlib_util.lib pjlib.lib
- STATICLIBRARY symbian_audio.lib libsrtp.lib
- STATICLIBRARY libgsmcodec.lib libspeexcodec.lib
+ STATICLIBRARY symbian_audio.lib
+ LIBRARY mediaclientaudiostream.lib
+ LIBRARY mediaclientaudioinputstream.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
#endif
#ifdef WINSCW
@@ -46,14 +56,6 @@ SYSTEMINCLUDE \epoc32\include\libc
#endif
LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib
-LIBRARY mediaclientaudiostream.lib
-LIBRARY mediaclientaudioinputstream.lib
-
-CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
-
-START RESOURCE symbian_ua_reg.rss
- TARGETPATH \private\10003a3f\apps
-END
// The default 8KB seems to be insufficient with all bells and
// whistles turned on
diff --git a/build.symbian/symsndtest.mmp b/build.symbian/symsndtest.mmp
index daea7005..ed42770e 100644
--- a/build.symbian/symsndtest.mmp
+++ b/build.symbian/symsndtest.mmp
@@ -1,3 +1,6 @@
+#define SND_USE_NULL 0
+#define SND_USE_APS 0
+
TARGET symsndtest.exe
TARGETTYPE exe
UID 0x0 0xA000000E
@@ -7,15 +10,15 @@ SOURCEPATH ..\pjsip-apps\src\symsndtest
MACRO PJ_M_I386=1
MACRO PJ_SYMBIAN=1
-#if defined(PJ_BUILD_DLL)
- MACRO PJ_DLL=1
-#endif
-
// Test files
SOURCE app_main.cpp
SOURCE main_symbian.cpp
+START RESOURCE symsndtest_reg.rss
+ TARGETPATH \private\10003a3f\apps
+END
+
SYSTEMINCLUDE ..\pjlib\include
SYSTEMINCLUDE ..\pjmedia\include
@@ -23,24 +26,30 @@ SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
LIBRARY charconv.lib euser.lib estlib.lib
-
-#if defined(PJ_BUILD_DLL)
- LIBRARY symbian_audio.lib pjlib.lib
+LIBRARY esock.lib insock.lib
+STATICLIBRARY pjlib.lib pjmedia.lib
+
+#if SND_USE_NULL || defined(WINSCW)
+ STATICLIBRARY null_audio.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
+#elif SND_USE_APS
+ SOURCEPATH ..\pjmedia\src\pjmedia
+ SOURCE symbian_sound_aps.cpp
+
+ SYSTEMINCLUDE \epoc32\include\mmf\server
+ SYSTEMINCLUDE \epoc32\include\mmf\common
+ SYSTEMINCLUDE \epoc32\include\mda\common
+
+ //STATICLIBRARY symbian_audio_aps.lib
+ LIBRARY APSSession2.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
#else
- STATICLIBRARY symbian_audio.lib pjlib.lib
+ STATICLIBRARY symbian_audio.lib
+ LIBRARY mediaclientaudiostream.lib
+ LIBRARY mediaclientaudioinputstream.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
#endif
-LIBRARY esock.lib insock.lib
-LIBRARY mediaclientaudiostream.lib
-LIBRARY mediaclientaudioinputstream.lib
-
#ifdef WINSCW
STATICLIBRARY eexe.lib ecrt0.lib
#endif
-
-CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
-
-START RESOURCE symsndtest_reg.rss
- TARGETPATH \private\10003a3f\apps
-END
-
diff --git a/pjmedia/include/pjmedia/symbian_sound_aps.h b/pjmedia/include/pjmedia/symbian_sound_aps.h
new file mode 100644
index 00000000..c42c9580
--- /dev/null
+++ b/pjmedia/include/pjmedia/symbian_sound_aps.h
@@ -0,0 +1,52 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJMEDIA_SYMBIAN_SOUND_APS_H__
+#define __PJMEDIA_SYMBIAN_SOUND_APS_H__
+
+
+/**
+ * @file symbian_sound_aps.h
+ * @brief Sound device wrapper using Audio Proxy Server on
+ * Symbian S60 3rd edition.
+ */
+#include <pjmedia/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * Activate/deactivate loudspeaker, when loudspeaker is inactive, audio
+ * will be routed to earpiece.
+ *
+ * @param stream The sound device stream, the stream should be started
+ * before calling this function. This param can be NULL
+ * to set the behaviour of next opened stream.
+ * @param active Specify PJ_TRUE to activate loudspeaker, and PJ_FALSE
+ * otherwise.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_aps_activate_loudspeaker(
+ pjmedia_snd_stream *stream,
+ pj_bool_t active);
+
+
+PJ_END_DECL
+
+
+#endif /* __PJMEDIA_SYMBIAN_SOUND_APS_H__ */
diff --git a/pjmedia/src/pjmedia/symbian_sound_aps.cpp b/pjmedia/src/pjmedia/symbian_sound_aps.cpp
new file mode 100644
index 00000000..9b54c3d3
--- /dev/null
+++ b/pjmedia/src/pjmedia/symbian_sound_aps.cpp
@@ -0,0 +1,824 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjmedia/sound.h>
+#include <pjmedia/alaw_ulaw.h>
+#include <pjmedia/errno.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/os.h>
+
+#include <e32msgqueue.h>
+#include <sounddevice.h>
+#include <APSClientSession.h>
+
+//////////////////////////////////////////////////////////////////////////////
+//
+
+#define THIS_FILE "symbian_sound_aps.cpp"
+
+#define BYTES_PER_SAMPLE 2
+#define POOL_NAME "SymbianSoundAps"
+#define POOL_SIZE 512
+#define POOL_INC 512
+
+#if 1
+# define TRACE_(st) PJ_LOG(3, st)
+#else
+# define TRACE_(st)
+#endif
+
+static pjmedia_snd_dev_info symbian_snd_dev_info =
+{
+ "Symbian Sound Device (APS)",
+ 1,
+ 1,
+ 8000
+};
+
+/* App UID to open global APS queues to communicate with the APS server. */
+extern TPtrC APP_UID;
+
+/* Default setting for loudspeaker */
+static pj_bool_t act_loudspeaker = PJ_FALSE;
+
+/* Forward declaration of CPjAudioEngine */
+class CPjAudioEngine;
+
+/*
+ * PJMEDIA Sound Stream instance
+ */
+struct pjmedia_snd_stream
+{
+ // Pool
+ pj_pool_t *pool;
+
+ // Common settings.
+ pjmedia_dir dir;
+ unsigned clock_rate;
+ unsigned channel_count;
+ unsigned samples_per_frame;
+
+ // Audio engine
+ CPjAudioEngine *engine;
+};
+
+static pj_pool_factory *snd_pool_factory;
+
+
+/*
+ * Utility: print sound device error
+ */
+static void snd_perror(const char *title, TInt rc)
+{
+ PJ_LOG(1,(THIS_FILE, "%s (error code=%d)", title, rc));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+
+/**
+ * Abstract class for handler of callbacks from APS client.
+ */
+class MQueueHandlerObserver
+{
+public:
+ virtual void InputStreamInitialized(const TInt aStatus) = 0;
+ virtual void OutputStreamInitialized(const TInt aStatus) = 0;
+ virtual void NotifyError(const TInt aError) = 0;
+
+ virtual void RecCb(TAPSCommBuffer &buffer) = 0;
+ virtual void PlayCb(TAPSCommBuffer &buffer) = 0;
+};
+
+/**
+ * Handler for communication and data queue.
+ */
+class CQueueHandler : public CActive
+{
+public:
+ // Types of queue handler
+ enum TQueueHandlerType {
+ ERecordCommQueue,
+ EPlayCommQueue,
+ ERecordQueue,
+ EPlayQueue
+ };
+
+ // The order corresponds to the APS Server state, do not change!
+ enum TState {
+ EAPSPlayerInitialize = 1,
+ EAPSRecorderInitialize = 2,
+ EAPSPlayData = 3,
+ EAPSRecordData = 4,
+ EAPSPlayerInitComplete = 5,
+ EAPSRecorderInitComplete = 6
+ };
+
+ static CQueueHandler* NewL(MQueueHandlerObserver* aObserver,
+ RMsgQueue<TAPSCommBuffer>* aQ,
+ TQueueHandlerType aType)
+ {
+ CQueueHandler* self = new (ELeave) CQueueHandler(aObserver, aQ, aType);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+ // Destructor
+ ~CQueueHandler() { Cancel(); }
+
+ // Start listening queue event
+ void Start() {
+ iQ->NotifyDataAvailable(iStatus);
+ SetActive();
+ }
+
+private:
+ // Constructor
+ CQueueHandler(MQueueHandlerObserver* aObserver,
+ RMsgQueue<TAPSCommBuffer>* aQ,
+ TQueueHandlerType aType)
+ : CActive(CActive::EPriorityHigh),
+ iQ(aQ), iObserver(aObserver), iType(aType)
+ {
+ CActiveScheduler::Add(this);
+
+ // use lower priority for comm queues
+ if ((iType == ERecordCommQueue) || (iType == EPlayCommQueue))
+ SetPriority(CActive::EPriorityStandard);
+ }
+
+ // Second phase constructor
+ void ConstructL() {}
+
+ // Inherited from CActive
+ void DoCancel() { iQ->CancelDataAvailable(); }
+
+ void RunL() {
+ if (iStatus != KErrNone) {
+ iObserver->NotifyError(iStatus.Int());
+ return;
+ }
+
+ TAPSCommBuffer buffer;
+ TInt ret = iQ->Receive(buffer);
+
+ if (ret != KErrNone) {
+ iObserver->NotifyError(ret);
+ return;
+ }
+
+ switch (iType) {
+ case ERecordQueue:
+ if (buffer.iCommand == EAPSRecordData) {
+ iObserver->RecCb(buffer);
+ }
+ break;
+
+ // Callbacks from the APS main thread
+ case EPlayCommQueue:
+ switch (buffer.iCommand) {
+ case EAPSPlayData:
+ if (buffer.iStatus == KErrUnderflow) {
+ iObserver->PlayCb(buffer);
+ }
+ break;
+ case EAPSPlayerInitialize:
+ iObserver->NotifyError(buffer.iStatus);
+ break;
+ case EAPSPlayerInitComplete:
+ iObserver->OutputStreamInitialized(buffer.iStatus);
+ break;
+ case EAPSRecorderInitComplete:
+ iObserver->InputStreamInitialized(buffer.iStatus);
+ break;
+ default:
+ iObserver->NotifyError(buffer.iStatus);
+ break;
+ }
+ break;
+
+ // Callbacks from the APS recorder thread
+ case ERecordCommQueue:
+ switch (buffer.iCommand) {
+ // The APS recorder thread will only report errors
+ // through this handler. All other callbacks will be
+ // sent from the APS main thread through EPlayCommQueue
+ case EAPSRecorderInitialize:
+ if (buffer.iStatus == KErrNone) {
+ iObserver->InputStreamInitialized(buffer.iStatus);
+ break;
+ }
+ case EAPSRecordData:
+ iObserver->NotifyError(buffer.iStatus);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // issue next request
+ iQ->NotifyDataAvailable(iStatus);
+ SetActive();
+ }
+
+ // Data
+ RMsgQueue<TAPSCommBuffer> *iQ; // (not owned)
+ MQueueHandlerObserver *iObserver; // (not owned)
+ TQueueHandlerType iType;
+};
+
+
+/*
+ * Implementation: Symbian Input & Output Stream.
+ */
+class CPjAudioEngine : public CBase, MQueueHandlerObserver
+{
+public:
+ enum State
+ {
+ STATE_NULL,
+ STATE_READY,
+ STATE_STREAMING
+ };
+
+ ~CPjAudioEngine();
+
+ static CPjAudioEngine *NewL(pjmedia_snd_stream *parent_strm,
+ pjmedia_dir dir,
+ pjmedia_snd_rec_cb rec_cb,
+ pjmedia_snd_play_cb play_cb,
+ void *user_data);
+
+ TInt StartL();
+ void Stop();
+
+ TInt ActivateSpeaker(TBool active);
+
+private:
+ CPjAudioEngine(pjmedia_snd_stream *parent_strm,
+ pjmedia_dir dir,
+ pjmedia_snd_rec_cb rec_cb,
+ pjmedia_snd_play_cb play_cb,
+ void *user_data);
+ void ConstructL();
+
+ TInt InitPlayL();
+ TInt InitRecL();
+ TInt StartStreamL();
+
+ // Inherited from MQueueHandlerObserver
+ virtual void InputStreamInitialized(const TInt aStatus);
+ virtual void OutputStreamInitialized(const TInt aStatus);
+ virtual void NotifyError(const TInt aError);
+
+ virtual void RecCb(TAPSCommBuffer &buffer);
+ virtual void PlayCb(TAPSCommBuffer &buffer);
+
+ State state_;
+ pjmedia_snd_stream *parentStrm_;
+ pjmedia_dir dir_;
+ pjmedia_snd_rec_cb recCb_;
+ pjmedia_snd_play_cb playCb_;
+ void *userData_;
+ pj_uint32_t TsPlay_;
+ pj_uint32_t TsRec_;
+
+ RAPSSession iSession;
+ TAPSInitSettings iSettings;
+ RMsgQueue<TAPSCommBuffer> iReadQ;
+ RMsgQueue<TAPSCommBuffer> iReadCommQ;
+ RMsgQueue<TAPSCommBuffer> iWriteQ;
+ RMsgQueue<TAPSCommBuffer> iWriteCommQ;
+
+ CQueueHandler *iPlayCommHandler;
+ CQueueHandler *iRecCommHandler;
+ CQueueHandler *iRecHandler;
+};
+
+
+CPjAudioEngine* CPjAudioEngine::NewL(pjmedia_snd_stream *parent_strm,
+ pjmedia_dir dir,
+ pjmedia_snd_rec_cb rec_cb,
+ pjmedia_snd_play_cb play_cb,
+ void *user_data)
+{
+ CPjAudioEngine* self = new (ELeave) CPjAudioEngine(parent_strm, dir,
+ rec_cb, play_cb,
+ user_data);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CPjAudioEngine::CPjAudioEngine(pjmedia_snd_stream *parent_strm,
+ pjmedia_dir dir,
+ pjmedia_snd_rec_cb rec_cb,
+ pjmedia_snd_play_cb play_cb,
+ void *user_data)
+ : state_(STATE_NULL),
+ parentStrm_(parent_strm),
+ dir_(dir),
+ recCb_(rec_cb),
+ playCb_(play_cb),
+ userData_(user_data),
+ iPlayCommHandler(0),
+ iRecCommHandler(0),
+ iRecHandler(0)
+{
+}
+
+CPjAudioEngine::~CPjAudioEngine()
+{
+ Stop();
+
+ delete iPlayCommHandler;
+ iPlayCommHandler = NULL;
+ delete iRecCommHandler;
+ iRecCommHandler = NULL;
+
+ iSession.Close();
+
+ if (state_ == STATE_READY) {
+ if (dir_ != PJMEDIA_DIR_PLAYBACK) {
+ iReadQ.Close();
+ iReadCommQ.Close();
+ }
+ iWriteQ.Close();
+ iWriteCommQ.Close();
+ }
+}
+
+TInt CPjAudioEngine::InitPlayL()
+{
+ if (state_ == STATE_STREAMING || state_ == STATE_READY)
+ return 0;
+
+ TInt err = iSession.InitializePlayer(iSettings);
+ if (err != KErrNone) {
+ snd_perror("Failed to initialize player", err);
+ return err;
+ }
+
+ // Open message queues for the output stream
+ TBuf<128> buf2 = iSettings.iGlobal;
+ buf2.Append(_L("PlayQueue"));
+ TBuf<128> buf3 = iSettings.iGlobal;
+ buf3.Append(_L("PlayCommQueue"));
+
+ while (iWriteQ.OpenGlobal(buf2))
+ User::After(10);
+ while (iWriteCommQ.OpenGlobal(buf3))
+ User::After(10);
+
+ // Construct message queue handler
+ iPlayCommHandler = CQueueHandler::NewL(this,
+ &iWriteCommQ,
+ CQueueHandler::EPlayCommQueue);
+
+ // Start observing APS callbacks on output stream message queue
+ iPlayCommHandler->Start();
+
+ return 0;
+}
+
+TInt CPjAudioEngine::InitRecL()
+{
+ if (state_ == STATE_STREAMING || state_ == STATE_READY)
+ return 0;
+
+ // Initialize input stream device
+ TInt err = iSession.InitializeRecorder(iSettings);
+ if (err != KErrNone) {
+ snd_perror("Failed to initialize recorder", err);
+ return err;
+ }
+
+ TBuf<128> buf1 = iSettings.iGlobal;
+ buf1.Append(_L("RecordQueue"));
+ TBuf<128> buf4 = iSettings.iGlobal;
+ buf4.Append(_L("RecordCommQueue"));
+
+ // Must wait for APS thread to finish creating message queues
+ // before we can open and use them.
+ while (iReadQ.OpenGlobal(buf1))
+ User::After(10);
+ while (iReadCommQ.OpenGlobal(buf4))
+ User::After(10);
+
+ // Construct message queue handlers
+ iRecCommHandler = CQueueHandler::NewL(this,
+ &iReadCommQ,
+ CQueueHandler::ERecordCommQueue);
+
+ // Start observing APS callbacks from on input stream message queue
+ iRecCommHandler->Start();
+
+ return 0;
+}
+
+TInt CPjAudioEngine::StartL()
+{
+ TInt err = iSession.Connect();
+ if (err != KErrNone && err != KErrAlreadyExists)
+ return err;
+
+ if (state_ == STATE_READY)
+ return StartStreamL();
+
+ // Even if only capturer are opened, playback thread of APS Server need
+ // to be run(?). Since some messages will be delivered via play comm queue.
+ return InitPlayL();
+}
+
+void CPjAudioEngine::Stop()
+{
+ iSession.Stop();
+
+ delete iRecHandler;
+ iRecHandler = NULL;
+
+ state_ = STATE_READY;
+}
+
+void CPjAudioEngine::ConstructL()
+{
+ iSettings.iFourCC = TFourCC(KMCPFourCCIdG711);
+ iSettings.iGlobal = APP_UID;
+ iSettings.iPriority = TMdaPriority(100);
+ iSettings.iPreference = TMdaPriorityPreference(0x05210001);
+ iSettings.iSettings.iChannels = EMMFMono;
+ iSettings.iSettings.iSampleRate = EMMFSampleRate8000Hz;
+ iSettings.iSettings.iVolume = 0;
+}
+
+TInt CPjAudioEngine::StartStreamL()
+{
+ if (state_ == STATE_STREAMING)
+ return 0;
+
+ iSession.SetCng(EFalse);
+ iSession.SetVadMode(EFalse);
+ iSession.SetPlc(EFalse);
+ iSession.SetEncoderMode(EALawOr20ms);
+ iSession.SetDecoderMode(EALawOr20ms);
+ iSession.ActivateLoudspeaker(act_loudspeaker);
+
+ // Not only playback
+ if (dir_ != PJMEDIA_DIR_PLAYBACK) {
+ iRecHandler = CQueueHandler::NewL(this, &iReadQ,
+ CQueueHandler::ERecordQueue);
+ iRecHandler->Start();
+ iSession.Read();
+ }
+
+ // Not only capture
+ if (dir_ != PJMEDIA_DIR_CAPTURE) {
+ iSession.Write();
+ }
+
+ state_ = STATE_STREAMING;
+ return 0;
+}
+
+// Inherited from MQueueHandlerObserver
+void CPjAudioEngine::InputStreamInitialized(const TInt aStatus)
+{
+ TRACE_((THIS_FILE, "InputStreamInitialized %d", aStatus));
+
+ state_ = STATE_READY;
+ if (aStatus == KErrNone) {
+ StartStreamL();
+ }
+}
+
+void CPjAudioEngine::OutputStreamInitialized(const TInt aStatus)
+{
+ TRACE_((THIS_FILE, "OutputStreamInitialized %d", aStatus));
+
+ if (aStatus == KErrNone) {
+ if (dir_ == PJMEDIA_DIR_PLAYBACK) {
+ state_ = STATE_READY;
+ // Only playback, start directly
+ StartStreamL();
+ } else
+ InitRecL();
+ }
+}
+
+void CPjAudioEngine::NotifyError(const TInt aError)
+{
+ snd_perror("Error from CQueueHandler", aError);
+}
+
+void CPjAudioEngine::RecCb(TAPSCommBuffer &buffer)
+{
+ pj_int16_t buf[160];
+ pj_assert(buffer.iBuffer[0] == 1 && buffer.iBuffer[1] == 0);
+
+ for (int i=0; i<160; ++i)
+ buf[i] = pjmedia_alaw2linear(buffer.iBuffer[i+2]);
+
+ recCb_(userData_, 0, buf, sizeof(buf));
+}
+
+void CPjAudioEngine::PlayCb(TAPSCommBuffer &buffer)
+{
+ pj_int16_t buf[160];
+
+ playCb_(userData_, 0, buf, sizeof(buf));
+
+ buffer.iCommand = CQueueHandler::EAPSPlayData;
+ buffer.iStatus = 0;
+ buffer.iBuffer.Zero();
+ buffer.iBuffer.Append(1);
+ buffer.iBuffer.Append(0);
+ for (int i=0; i<160; ++i)
+ buffer.iBuffer.Append(pjmedia_linear2alaw(buf[i]));
+
+ iWriteQ.Send(buffer);
+}
+
+
+TInt CPjAudioEngine::ActivateSpeaker(TBool active)
+{
+ if (state_ == STATE_READY || state_ == STATE_STREAMING) {
+ iSession.ActivateLoudspeaker(active);
+ return KErrNone;
+ }
+ return KErrNotReady;
+}
+//////////////////////////////////////////////////////////////////////////////
+//
+
+
+/*
+ * Initialize sound subsystem.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)
+{
+ snd_pool_factory = factory;
+ return PJ_SUCCESS;
+}
+
+/*
+ * Get device count.
+ */
+PJ_DEF(int) pjmedia_snd_get_dev_count(void)
+{
+ /* Always return 1 */
+ return 1;
+}
+
+/*
+ * Get device info.
+ */
+PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
+{
+ /* Always return the default sound device */
+ if (index == (unsigned)-1)
+ index = 0;
+
+ PJ_ASSERT_RETURN(index==0, NULL);
+ return &symbian_snd_dev_info;
+}
+
+static pj_status_t sound_open(pjmedia_dir dir,
+ unsigned clock_rate,
+ unsigned channel_count,
+ unsigned samples_per_frame,
+ unsigned bits_per_sample,
+ pjmedia_snd_rec_cb rec_cb,
+ pjmedia_snd_play_cb play_cb,
+ void *user_data,
+ pjmedia_snd_stream **p_snd_strm)
+{
+ pj_pool_t *pool;
+ pjmedia_snd_stream *strm;
+
+ PJ_ASSERT_RETURN(p_snd_strm, PJ_EINVAL);
+ PJ_ASSERT_RETURN(clock_rate == 8000 && channel_count == 1 &&
+ bits_per_sample == 16, PJ_ENOTSUP);
+ PJ_ASSERT_RETURN((dir == PJMEDIA_DIR_CAPTURE_PLAYBACK && rec_cb && play_cb)
+ || (dir == PJMEDIA_DIR_CAPTURE && rec_cb && !play_cb)
+ || (dir == PJMEDIA_DIR_PLAYBACK && !rec_cb && play_cb),
+ PJ_EINVAL);
+
+ pool = pj_pool_create(snd_pool_factory, POOL_NAME, POOL_SIZE, POOL_INC,
+ NULL);
+ if (!pool)
+ return PJ_ENOMEM;
+
+ strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
+ sizeof(pjmedia_snd_stream));
+ strm->dir = dir;
+ strm->pool = pool;
+ strm->clock_rate = clock_rate;
+ strm->channel_count = channel_count;
+ strm->samples_per_frame = samples_per_frame;
+
+ // Create the audio engine.
+ TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm, strm->dir,
+ rec_cb, play_cb,
+ user_data));
+ if (err != KErrNone) {
+ pj_pool_release(pool);
+ return PJ_RETURN_OS_ERROR(err);
+ }
+
+ // Done.
+ *p_snd_strm = strm;
+ return PJ_SUCCESS;
+}
+
+
+
+/*
+ * Open sound recorder stream.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,
+ unsigned clock_rate,
+ unsigned channel_count,
+ unsigned samples_per_frame,
+ unsigned bits_per_sample,
+ pjmedia_snd_rec_cb rec_cb,
+ void *user_data,
+ pjmedia_snd_stream **p_snd_strm)
+{
+ if (index < 0) index = 0;
+ PJ_ASSERT_RETURN(index == 0, PJ_EINVAL);
+
+ return sound_open(PJMEDIA_DIR_CAPTURE, clock_rate, channel_count,
+ samples_per_frame, bits_per_sample, rec_cb, NULL,
+ user_data, p_snd_strm);
+}
+
+PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
+ unsigned clock_rate,
+ unsigned channel_count,
+ unsigned samples_per_frame,
+ unsigned bits_per_sample,
+ pjmedia_snd_play_cb play_cb,
+ void *user_data,
+ pjmedia_snd_stream **p_snd_strm )
+{
+ if (index < 0) index = 0;
+ PJ_ASSERT_RETURN(index == 0, PJ_EINVAL);
+
+ return sound_open(PJMEDIA_DIR_PLAYBACK, clock_rate, channel_count,
+ samples_per_frame, bits_per_sample, NULL, play_cb,
+ user_data, p_snd_strm);
+}
+
+PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id,
+ int play_id,
+ unsigned clock_rate,
+ unsigned channel_count,
+ unsigned samples_per_frame,
+ unsigned bits_per_sample,
+ pjmedia_snd_rec_cb rec_cb,
+ pjmedia_snd_play_cb play_cb,
+ void *user_data,
+ pjmedia_snd_stream **p_snd_strm)
+{
+ if (rec_id < 0) rec_id = 0;
+ if (play_id < 0) play_id = 0;
+ PJ_ASSERT_RETURN(play_id == 0 && rec_id == 0, PJ_EINVAL);
+
+ return sound_open(PJMEDIA_DIR_CAPTURE_PLAYBACK, clock_rate, channel_count,
+ samples_per_frame, bits_per_sample, rec_cb, play_cb,
+ user_data, p_snd_strm);
+}
+
+/*
+ * Get stream info.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,
+ pjmedia_snd_stream_info *pi)
+{
+ PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
+
+ pj_bzero(pi, sizeof(*pi));
+ pi->dir = strm->dir;
+ pi->play_id = 0;
+ pi->rec_id = 0;
+ pi->clock_rate = strm->clock_rate;
+ pi->channel_count = strm->channel_count;
+ pi->samples_per_frame = strm->samples_per_frame;
+ pi->bits_per_sample = BYTES_PER_SAMPLE * 8;
+ pi->rec_latency = 0;
+ pi->play_latency = 0;
+
+ return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
+{
+ PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
+
+ if (stream->engine) {
+ TInt err = stream->engine->StartL();
+ if (err != KErrNone)
+ return PJ_RETURN_OS_ERROR(err);
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream)
+{
+ PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
+
+ if (stream->engine) {
+ stream->engine->Stop();
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream)
+{
+ pj_pool_t *pool;
+
+ PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
+
+ if (stream->engine) {
+ delete stream->engine;
+ stream->engine = NULL;
+ }
+
+ pool = stream->pool;
+ if (pool) {
+ stream->pool = NULL;
+ pj_pool_release(pool);
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)
+{
+ /* Nothing to do */
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Set sound latency.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_set_latency(unsigned input_latency,
+ unsigned output_latency)
+{
+ /* Nothing to do */
+ PJ_UNUSED_ARG(input_latency);
+ PJ_UNUSED_ARG(output_latency);
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Activate/deactivate loudspeaker.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_aps_activate_loudspeaker(
+ pjmedia_snd_stream *stream,
+ pj_bool_t active)
+{
+ if (stream == NULL) {
+ act_loudspeaker = active;
+ } else {
+ if (stream->engine == NULL)
+ return PJ_EINVAL;
+
+ TInt err = stream->engine->ActivateSpeaker(active);
+ if (err != KErrNone)
+ return PJ_RETURN_OS_ERROR(err);
+ }
+
+ return PJ_SUCCESS;
+}
diff --git a/pjsip-apps/src/symbian_ua/main_symbian.cpp b/pjsip-apps/src/symbian_ua/main_symbian.cpp
index 62de1581..1786148f 100644
--- a/pjsip-apps/src/symbian_ua/main_symbian.cpp
+++ b/pjsip-apps/src/symbian_ua/main_symbian.cpp
@@ -27,6 +27,9 @@
// Global Variables
CConsoleBase* console;
+// Needed by APS
+TPtrC APP_UID = _L("A000000E");
+
////////////////////////////////////////////////////////////////////////////
class MyTask : public CActive
diff --git a/pjsip-apps/src/symbian_ua/ua.cpp b/pjsip-apps/src/symbian_ua/ua.cpp
index 5396bc72..7e4c9c3a 100644
--- a/pjsip-apps/src/symbian_ua/ua.cpp
+++ b/pjsip-apps/src/symbian_ua/ua.cpp
@@ -326,12 +326,17 @@ static pj_status_t app_startup()
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4;
log_cfg.cb = &log_writer;
+ //log_cfg.log_filename = pj_str("C:\\data\\symbian_ua.log");
pjsua_media_config_default(&med_cfg);
med_cfg.thread_cnt = 0; // Disable threading on Symbian
med_cfg.has_ioqueue = PJ_FALSE;
med_cfg.clock_rate = 8000;
+#if defined(PJMEDIA_SYM_SND_USE_APS) && (PJMEDIA_SYM_SND_USE_APS==1)
+ med_cfg.audio_frame_ptime = 20;
+#else
med_cfg.audio_frame_ptime = 40;
+#endif
med_cfg.ec_tail_len = 0;
med_cfg.enable_ice = USE_ICE;
med_cfg.snd_auto_close_time = 5; // wait for 5 seconds idle before sound dev get auto-closed
diff --git a/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp b/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp
index c00e1e28..7077b6ca 100644
--- a/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp
+++ b/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp
@@ -1,3 +1,6 @@
+#define SND_USE_NULL 0
+#define SND_USE_APS 0
+
TARGET symbian_ua_gui.exe
UID 0x100039CE 0xEBD12EE4
VENDORID 0
@@ -32,17 +35,30 @@ LIBRARY commonengine.lib efsrv.lib estor.lib eikcoctl.lib eikdlg.lib
LIBRARY eikctl.lib bafl.lib fbscli.lib aknnotify.lib aknicon.lib
LIBRARY etext.lib gdi.lib egul.lib insock.lib
LIBRARY ecom.lib inetprotutil.lib http.lib esock.lib
+LIBRARY charconv.lib estlib.lib
STATICLIBRARY pjsua_lib.lib pjsip_ua.lib
STATICLIBRARY pjsip_simple.lib pjsip.lib pjsdp.lib pjmedia.lib
STATICLIBRARY pjnath.lib pjlib_util.lib pjlib.lib
-STATICLIBRARY symbian_audio.lib libsrtp.lib
+STATICLIBRARY libsrtp.lib
STATICLIBRARY libgsmcodec.lib
STATICLIBRARY libspeexcodec.lib
-LIBRARY charconv.lib estlib.lib
-LIBRARY mediaclientaudiostream.lib
-LIBRARY mediaclientaudioinputstream.lib
+
+#if SND_USE_NULL || defined(WINSCW)
+ STATICLIBRARY null_audio.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
+#elif SND_USE_APS
+ STATICLIBRARY symbian_audio_aps.lib
+ LIBRARY APSSession2.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
+ MACRO PJMEDIA_SYM_SND_USE_APS=1
+#else
+ STATICLIBRARY symbian_audio.lib
+ LIBRARY mediaclientaudiostream.lib
+ LIBRARY mediaclientaudioinputstream.lib
+ CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
+#endif
LANG 01
@@ -56,5 +72,3 @@ END
SOURCEPATH ..\src
SOURCE symbian_ua_guiContainerView.cpp symbian_ua_guiContainer.cpp symbian_ua_guiAppUi.cpp symbian_ua_guiDocument.cpp symbian_ua_guiApplication.cpp symbian_ua_guiSettingItemList.cpp Symbian_ua_guiSettingItemListSets.cpp symbian_ua_guiSettingItemListView.cpp
SOURCE symbian_ua.cpp
-
-CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
index 7d693b41..7bb75177 100644
--- a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
@@ -323,7 +323,11 @@ int symbian_ua_init()
med_cfg.thread_cnt = 0; // Disable threading on Symbian
med_cfg.has_ioqueue = PJ_FALSE;
med_cfg.clock_rate = 8000;
+#if defined(PJMEDIA_SYM_SND_USE_APS) && (PJMEDIA_SYM_SND_USE_APS==1)
+ med_cfg.audio_frame_ptime = 20;
+#else
med_cfg.audio_frame_ptime = 40;
+#endif
med_cfg.ec_tail_len = 0;
med_cfg.enable_ice = USE_ICE;
med_cfg.snd_auto_close_time = 5; // wait for 5 seconds idle before sound dev get auto-closed
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp
index e1b5e2bf..a234b036 100644
--- a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua_guiApplication.cpp
@@ -17,6 +17,10 @@
#endif
// ]]] end generated region [Generated Includes]
+
+// Needed by APS
+TPtrC APP_UID = _L("EBD12EE4");
+
/**
* @brief Returns the application's UID (override from CApaApplication::AppDllUid())
* @return UID for this application (KUidsymbian_ua_guiApplication)
diff --git a/pjsip-apps/src/symsndtest/app_main.cpp b/pjsip-apps/src/symsndtest/app_main.cpp
index 981e5308..3ee50731 100644
--- a/pjsip-apps/src/symsndtest/app_main.cpp
+++ b/pjsip-apps/src/symsndtest/app_main.cpp
@@ -16,6 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <pjmedia/delaybuf.h>
#include <pjmedia/sound.h>
#include <pj/errno.h>
#include <pj/os.h>
@@ -27,10 +28,9 @@
#define THIS_FILE "app_main.cpp"
#define CLOCK_RATE 8000
#define CHANNEL_COUNT 1
-#define PTIME 100
-#define SAMPLES_PER_FRAME (80)
+#define PTIME 20
+#define SAMPLES_PER_FRAME (CLOCK_RATE*PTIME/1000)
#define BITS_PER_SAMPLE 16
-#define LOOPBACK_BUFF_COUNT 100
extern CConsoleBase* console;
@@ -39,9 +39,8 @@ static pjmedia_snd_stream *strm;
static unsigned rec_cnt, play_cnt;
static pj_time_val t_start;
-
-static pj_int16_t buff_loopback[SAMPLES_PER_FRAME*LOOPBACK_BUFF_COUNT];
-static pj_uint32_t pointer_w, pointer_r;
+pj_pool_t *pool;
+pjmedia_delay_buf *delaybuf;
/* Logging callback */
static void log_writer(int level, const char *buf, unsigned len)
@@ -73,7 +72,7 @@ static pj_status_t app_init()
/* Redirect log */
pj_log_set_log_func((void (*)(int,const char*,int)) &log_writer);
pj_log_set_decor(PJ_LOG_HAS_NEWLINE);
- pj_log_set_level(5);
+ pj_log_set_level(3);
/* Init pjlib */
status = pj_init();
@@ -103,6 +102,26 @@ static pj_status_t app_init()
i, info->name, info->input_count, info->output_count,
info->default_samples_per_sec));
}
+
+ /* Create pool */
+ pool = pj_pool_create(&cp.factory, THIS_FILE, 512, 512, NULL);
+ if (pool == NULL) {
+ app_perror("pj_pool_create()", status);
+ pj_caching_pool_destroy(&cp);
+ pj_shutdown();
+ return status;
+ }
+
+ /* Init delay buffer */
+ status = pjmedia_delay_buf_create(pool, THIS_FILE, CLOCK_RATE,
+ SAMPLES_PER_FRAME, CHANNEL_COUNT,
+ 0, 0, &delaybuf);
+ if (status != PJ_SUCCESS) {
+ app_perror("pjmedia_delay_buf_create()", status);
+ //pj_caching_pool_destroy(&cp);
+ //pj_shutdown();
+ //return status;
+ }
return PJ_SUCCESS;
}
@@ -116,21 +135,15 @@ static pj_status_t rec_cb(void *user_data,
{
PJ_UNUSED_ARG(user_data);
PJ_UNUSED_ARG(timestamp);
- PJ_UNUSED_ARG(input);
PJ_UNUSED_ARG(size);
- pj_memcpy(&buff_loopback[pointer_w*SAMPLES_PER_FRAME], input, size);
+ pjmedia_delay_buf_put(delaybuf, (pj_int16_t*)input);
if (size != SAMPLES_PER_FRAME*2) {
PJ_LOG(3, (THIS_FILE, "Size captured = %u",
size));
- pj_bzero(&buff_loopback[pointer_w*SAMPLES_PER_FRAME]+size/2, SAMPLES_PER_FRAME*2 - size);
}
- if (++pointer_w >= LOOPBACK_BUFF_COUNT) {
- pointer_w = 0;
- }
-
++rec_cnt;
return PJ_SUCCESS;
}
@@ -143,13 +156,9 @@ static pj_status_t play_cb(void *user_data,
{
PJ_UNUSED_ARG(user_data);
PJ_UNUSED_ARG(timestamp);
+ PJ_UNUSED_ARG(size);
- //pj_bzero(output, size);
- pj_memcpy(output, &buff_loopback[pointer_r*SAMPLES_PER_FRAME], SAMPLES_PER_FRAME*2);
-
- if (++pointer_r >= LOOPBACK_BUFF_COUNT) {
- pointer_r = 0;
- }
+ pjmedia_delay_buf_get(delaybuf, (pj_int16_t*)output);
++play_cnt;
return PJ_SUCCESS;
@@ -186,6 +195,8 @@ static pj_status_t snd_start(unsigned flag)
rec_cnt = play_cnt = 0;
pj_gettimeofday(&t_start);
+ pjmedia_delay_buf_reset(delaybuf);
+
status = pjmedia_snd_stream_start(strm);
if (status != PJ_SUCCESS) {
app_perror("snd start", status);
@@ -194,9 +205,6 @@ static pj_status_t snd_start(unsigned flag)
return status;
}
- pointer_w = LOOPBACK_BUFF_COUNT/2;
- pointer_r = 0;
-
return PJ_SUCCESS;
}
@@ -231,6 +239,8 @@ static void app_fini()
snd_stop();
pjmedia_snd_deinit();
+ pjmedia_delay_buf_destroy(delaybuf);
+ pj_pool_release(pool);
pj_caching_pool_destroy(&cp);
pj_shutdown();
}
@@ -295,11 +305,11 @@ static void PrintMenu()
{
PJ_LOG(3, (THIS_FILE, "\n\n"
"Menu:\n"
- " b Start bidir sound\n"
- " r Start recorder\n"
+ " a Start bidir sound\n"
+ " t Start recorder\n"
" p Start player\n"
- " c Stop & close sound\n"
- " q Quit\n"));
+ " d Stop & close sound\n"
+ " w Quit\n"));
}
// Implementation: called when read has completed.
@@ -309,20 +319,20 @@ void ConsoleUI::RunL()
pj_bool_t reschedule = PJ_TRUE;
switch (kc) {
- case 'q':
+ case 'w':
asw_->AsyncStop();
reschedule = PJ_FALSE;
break;
- case 'b':
+ case 'a':
snd_start(PJMEDIA_DIR_CAPTURE_PLAYBACK);
break;
- case 'r':
+ case 't':
snd_start(PJMEDIA_DIR_CAPTURE);
break;
case 'p':
snd_start(PJMEDIA_DIR_PLAYBACK);
break;
- case 'c':
+ case 'd':
snd_stop();
break;
default:
diff --git a/pjsip-apps/src/symsndtest/main_symbian.cpp b/pjsip-apps/src/symsndtest/main_symbian.cpp
index 8c4d8026..3db9a19c 100644
--- a/pjsip-apps/src/symsndtest/main_symbian.cpp
+++ b/pjsip-apps/src/symsndtest/main_symbian.cpp
@@ -27,6 +27,9 @@
// Global Variables
CConsoleBase* console;
+// Needed by APS
+TPtrC APP_UID = _L("A000000D");
+
int app_main();