Initial sources of APS-direct.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/aps-direct@2434 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
27c98df853
commit
4e50262076
|
@ -1,6 +1,3 @@
|
|||
#define SND_USE_NULL 0
|
||||
#define SND_USE_APS 0
|
||||
|
||||
prj_platforms
|
||||
winscw
|
||||
//armv5
|
||||
|
@ -25,13 +22,7 @@ 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
|
||||
symbian_audio.mmp
|
||||
|
||||
/* Applications */
|
||||
//pjlib_test.mmp
|
||||
|
|
|
@ -40,6 +40,7 @@ SOURCE bidirectional.c
|
|||
SOURCE clock_thread.c
|
||||
SOURCE codec.c
|
||||
SOURCE conference.c
|
||||
SOURCE conf_switch.c
|
||||
SOURCE echo_common.c
|
||||
SOURCE echo_port.c
|
||||
SOURCE echo_suppress.c
|
||||
|
|
|
@ -24,22 +24,23 @@ TARGETTYPE lib
|
|||
SOURCEPATH ..\pjmedia\src\pjmedia
|
||||
|
||||
OPTION CW -lang c++
|
||||
|
||||
//
|
||||
// GCCE optimization setting
|
||||
//
|
||||
OPTION GCCE -O2 -fno-unit-at-a-time
|
||||
|
||||
MACRO PJ_M_I386=1
|
||||
MACRO PJ_SYMBIAN=1
|
||||
|
||||
SOURCE nullsound.c
|
||||
SOURCE symbian_sound.cpp
|
||||
SOURCE symbian_sound_aps.cpp
|
||||
|
||||
SYSTEMINCLUDE ..\pjlib\include
|
||||
SYSTEMINCLUDE ..\pjmedia\include
|
||||
|
||||
SYSTEMINCLUDE \epoc32\include
|
||||
SYSTEMINCLUDE \epoc32\include\libc
|
||||
SYSTEMINCLUDE \epoc32\include\mmf\server
|
||||
SYSTEMINCLUDE \epoc32\include\mmf\common
|
||||
SYSTEMINCLUDE \epoc32\include\mda\common
|
||||
|
||||
SYSTEMINCLUDE \epoc32\include\mmf\plugin
|
||||
|
||||
|
|
|
@ -1,63 +1,61 @@
|
|||
#define SND_USE_NULL 0
|
||||
#define SND_USE_APS 0
|
||||
|
||||
TARGET symbian_ua.exe
|
||||
TARGETTYPE exe
|
||||
UID 0x0 0xA000000D
|
||||
|
||||
SOURCEPATH ..\pjsip-apps\src\symbian_ua
|
||||
|
||||
MACRO PJ_M_I386=1
|
||||
MACRO PJ_SYMBIAN=1
|
||||
|
||||
// Source files
|
||||
|
||||
SOURCE ua.cpp
|
||||
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
|
||||
SYSTEMINCLUDE ..\pjmedia\include
|
||||
SYSTEMINCLUDE ..\pjsip\include
|
||||
|
||||
SYSTEMINCLUDE \epoc32\include
|
||||
SYSTEMINCLUDE \epoc32\include\libc
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
#ifdef WINSCW
|
||||
STATICLIBRARY eexe.lib ecrt0.lib
|
||||
#endif
|
||||
|
||||
LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib commdb.lib apengine.lib
|
||||
|
||||
// The default 8KB seems to be insufficient with all bells and
|
||||
// whistles turned on
|
||||
EPOCSTACKSIZE 12288
|
||||
|
||||
#define SND_USE_APS 1
|
||||
#define SND_USE_VAS 0
|
||||
|
||||
TARGET symbian_ua.exe
|
||||
TARGETTYPE exe
|
||||
UID 0x0 0xA000000D
|
||||
|
||||
SOURCEPATH ..\pjsip-apps\src\symbian_ua
|
||||
|
||||
MACRO PJ_M_I386=1
|
||||
MACRO PJ_SYMBIAN=1
|
||||
|
||||
// Source files
|
||||
|
||||
SOURCE ua.cpp
|
||||
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
|
||||
SYSTEMINCLUDE ..\pjmedia\include
|
||||
SYSTEMINCLUDE ..\pjsip\include
|
||||
|
||||
SYSTEMINCLUDE \epoc32\include
|
||||
SYSTEMINCLUDE \epoc32\include\libc
|
||||
|
||||
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
|
||||
STATICLIBRARY symbian_audio.lib
|
||||
|
||||
#if SND_USE_APS
|
||||
LIBRARY APSSession2.lib
|
||||
CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
|
||||
#elif SND_USE_VAS
|
||||
// LIBRARY
|
||||
CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
|
||||
#else
|
||||
LIBRARY mediaclientaudiostream.lib
|
||||
LIBRARY mediaclientaudioinputstream.lib
|
||||
CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
|
||||
#endif
|
||||
|
||||
#ifdef WINSCW
|
||||
STATICLIBRARY eexe.lib ecrt0.lib
|
||||
#endif
|
||||
|
||||
LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib commdb.lib apengine.lib
|
||||
|
||||
// The default 8KB seems to be insufficient with all bells and
|
||||
// whistles turned on
|
||||
EPOCSTACKSIZE 12288
|
||||
|
||||
|
|
|
@ -1,53 +1,45 @@
|
|||
#define SND_USE_NULL 0
|
||||
#define SND_USE_APS 0
|
||||
#define SND_USE_APS 1
|
||||
#define SND_USE_VAS 0
|
||||
|
||||
TARGET symsndtest.exe
|
||||
TARGETTYPE exe
|
||||
UID 0x0 0xA000000E
|
||||
TARGET symsndtest.exe
|
||||
TARGETTYPE exe
|
||||
UID 0x0 0xA000000E
|
||||
|
||||
SOURCEPATH ..\pjsip-apps\src\symsndtest
|
||||
SOURCEPATH ..\pjsip-apps\src\symsndtest
|
||||
|
||||
MACRO PJ_M_I386=1
|
||||
MACRO PJ_SYMBIAN=1
|
||||
MACRO PJ_M_I386=1
|
||||
MACRO PJ_SYMBIAN=1
|
||||
|
||||
// Test files
|
||||
|
||||
SOURCE app_main.cpp
|
||||
SOURCE main_symbian.cpp
|
||||
SOURCE app_main.cpp
|
||||
SOURCE main_symbian.cpp
|
||||
|
||||
START RESOURCE symsndtest_reg.rss
|
||||
START RESOURCE symsndtest_reg.rss
|
||||
TARGETPATH \private\10003a3f\apps
|
||||
END
|
||||
|
||||
SYSTEMINCLUDE ..\pjlib\include
|
||||
SYSTEMINCLUDE ..\pjmedia\include
|
||||
SYSTEMINCLUDE ..\pjlib\include
|
||||
SYSTEMINCLUDE ..\pjmedia\include
|
||||
|
||||
SYSTEMINCLUDE \epoc32\include
|
||||
SYSTEMINCLUDE \epoc32\include\libc
|
||||
SYSTEMINCLUDE \epoc32\include
|
||||
SYSTEMINCLUDE \epoc32\include\libc
|
||||
|
||||
LIBRARY charconv.lib euser.lib estlib.lib
|
||||
LIBRARY esock.lib insock.lib
|
||||
STATICLIBRARY pjlib.lib pjmedia.lib
|
||||
LIBRARY charconv.lib euser.lib estlib.lib
|
||||
LIBRARY esock.lib insock.lib
|
||||
STATICLIBRARY pjlib.lib pjmedia.lib
|
||||
STATICLIBRARY symbian_audio.lib
|
||||
|
||||
#if SND_USE_NULL
|
||||
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
|
||||
#if SND_USE_APS
|
||||
LIBRARY APSSession2.lib
|
||||
CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
|
||||
#elif SND_USE_VAS
|
||||
// LIBRARY
|
||||
CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment MultimediaDD
|
||||
#else
|
||||
STATICLIBRARY symbian_audio.lib
|
||||
LIBRARY mediaclientaudiostream.lib
|
||||
LIBRARY mediaclientaudioinputstream.lib
|
||||
CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
|
||||
LIBRARY mediaclientaudiostream.lib
|
||||
LIBRARY mediaclientaudioinputstream.lib
|
||||
CAPABILITY NetworkServices LocalServices ReadUserData WriteUserData UserEnvironment
|
||||
#endif
|
||||
|
||||
#ifdef WINSCW
|
||||
|
|
|
@ -94,78 +94,6 @@
|
|||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
|
||||
OutputDirectory="output\$(ProjectName)-$(PlatformName)-$(ConfigurationName)"
|
||||
IntermediateDirectory="$(OutDir)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ExecutionBucket="7"
|
||||
Optimization="2"
|
||||
FavorSizeOrSpeed="2"
|
||||
AdditionalIncludeDirectories="../include,../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../third_party/portaudio/include,../../third_party/speex/include,../../third_party/build/srtp,../../third_party/srtp/include,../../third_party/srtp/crypto/include;../.."
|
||||
PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;$(ARCHFAM);$(_ARCHFAM_);SMARTPHONE2003_UI_MODEL;SMARTPHONE2003_UI_MODEL"
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalOptions=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCodeSignTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
<DeploymentTool
|
||||
ForceDirty="-1"
|
||||
RemoteDirectory=""
|
||||
RegisterOutput="0"
|
||||
AdditionalFiles=""
|
||||
/>
|
||||
<DebuggerTool
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\output\pjmedia-i386-win32-vc8-debug"
|
||||
|
@ -242,6 +170,78 @@
|
|||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Windows Mobile 6 Standard SDK (ARMV4I)"
|
||||
OutputDirectory="output\$(ProjectName)-$(PlatformName)-$(ConfigurationName)"
|
||||
IntermediateDirectory="$(OutDir)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ExecutionBucket="7"
|
||||
Optimization="2"
|
||||
FavorSizeOrSpeed="2"
|
||||
AdditionalIncludeDirectories="../include,../../pjlib/include,../../pjlib-util/include,../../pjnath/include,../../third_party/portaudio/include,../../third_party/speex/include,../../third_party/build/srtp,../../third_party/srtp/include,../../third_party/srtp/crypto/include;../.."
|
||||
PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;$(ARCHFAM);$(_ARCHFAM_);SMARTPHONE2003_UI_MODEL;SMARTPHONE2003_UI_MODEL"
|
||||
ExceptionHandling="0"
|
||||
RuntimeLibrary="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalOptions=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCodeSignTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
<DeploymentTool
|
||||
ForceDirty="-1"
|
||||
RemoteDirectory=""
|
||||
RegisterOutput="0"
|
||||
AdditionalFiles=""
|
||||
/>
|
||||
<DebuggerTool
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Windows Mobile 6 Standard SDK (ARMV4I)"
|
||||
OutputDirectory="output\$(ProjectName)-$(PlatformName)-$(ConfigurationName)"
|
||||
|
@ -433,6 +433,10 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\pjmedia\conf_switch.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\pjmedia\conference.c"
|
||||
>
|
||||
|
|
|
@ -194,5 +194,13 @@
|
|||
# define PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Enable Passthrough codecs.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
#ifndef PJMEDIA_HAS_PASSTHROUGH_CODECS
|
||||
# define PJMEDIA_HAS_PASSTHROUGH_CODECS 0
|
||||
#endif
|
||||
|
||||
#endif /* __PJMEDIA_CODEC_CONFIG_H__ */
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef struct pjmedia_conf_port_info
|
|||
{
|
||||
unsigned slot; /**< Slot number. */
|
||||
pj_str_t name; /**< Port name. */
|
||||
pjmedia_fourcc format; /**< Format (FourCC identifier) */
|
||||
pjmedia_port_op tx_setting; /**< Transmit settings. */
|
||||
pjmedia_port_op rx_setting; /**< Receive settings. */
|
||||
unsigned listener_cnt; /**< Number of listeners. */
|
||||
|
|
|
@ -44,6 +44,22 @@
|
|||
# include <pjmedia/config_auto.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Specify whether we prefer to use audio switch board rather than
|
||||
* conference bridge.
|
||||
*
|
||||
* Audio switch board is a kind of simplified version of conference
|
||||
* bridge, but not really the subset of conference bridge. It has
|
||||
* stricter rules on audio routing among the pjmedia ports and has
|
||||
* no audio mixing capability. The power of it is it could work with
|
||||
* encoded audio frames where conference brigde couldn't.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
#ifndef PJMEDIA_CONF_USE_SWITCH_BOARD
|
||||
# define PJMEDIA_CONF_USE_SWITCH_BOARD 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Types of sound stream backends.
|
||||
*/
|
||||
|
@ -60,6 +76,16 @@
|
|||
/** Constant for Win32 MME sound backend. */
|
||||
#define PJMEDIA_SOUND_WIN32_MME_SOUND 3
|
||||
|
||||
/** Constant for Symbian Multimedia Audio Stream backend. */
|
||||
#define PJMEDIA_SOUND_SYMB_MDA_SOUND 4
|
||||
|
||||
/** Constant for Symbian APS backend. */
|
||||
#define PJMEDIA_SOUND_SYMB_APS_SOUND 5
|
||||
|
||||
/** Constant for Symbian VAS backend. */
|
||||
#define PJMEDIA_SOUND_SYMB_VAS_SOUND 6
|
||||
|
||||
|
||||
/** When this is set, pjmedia will not provide any sound device backend.
|
||||
* Application will have to provide its own sound device backend
|
||||
* and link the application with it.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* @brief Port interface declaration
|
||||
*/
|
||||
#include <pjmedia/types.h>
|
||||
#include <pj/assert.h>
|
||||
#include <pj/os.h>
|
||||
|
||||
|
||||
|
@ -211,6 +212,7 @@ typedef struct pjmedia_port_info
|
|||
pj_bool_t has_info; /**< Has info? */
|
||||
pj_bool_t need_info; /**< Need info on connect? */
|
||||
unsigned pt; /**< Payload type (can be dynamic). */
|
||||
pjmedia_fourcc format; /**< Format (FourCC identifier) */
|
||||
pj_str_t encoding_name; /**< Encoding name. */
|
||||
unsigned clock_rate; /**< Sampling rate. */
|
||||
unsigned channel_count; /**< Number of channels. */
|
||||
|
@ -226,7 +228,8 @@ typedef struct pjmedia_port_info
|
|||
typedef enum pjmedia_frame_type
|
||||
{
|
||||
PJMEDIA_FRAME_TYPE_NONE, /**< No frame. */
|
||||
PJMEDIA_FRAME_TYPE_AUDIO /**< Normal audio frame. */
|
||||
PJMEDIA_FRAME_TYPE_AUDIO, /**< Normal audio frame. */
|
||||
PJMEDIA_FRAME_TYPE_EXTENDED /**< Extended audio frame. */
|
||||
|
||||
} pjmedia_frame_type;
|
||||
|
||||
|
@ -248,6 +251,88 @@ typedef struct pjmedia_frame
|
|||
} pjmedia_frame;
|
||||
|
||||
|
||||
/**
|
||||
* The pjmedia_frame_ext is used to carry a more complex audio frames than
|
||||
* the typical PCM audio frames, and it is signaled by setting the "type"
|
||||
* field of a pjmedia_frame to PJMEDIA_FRAME_TYPE_EXTENDED. With this set,
|
||||
* application may typecast pjmedia_frame to pjmedia_frame_ext.
|
||||
*
|
||||
* This structure may contain more than one audio frames, which subsequently
|
||||
* will be called subframes in this structure. The subframes section
|
||||
* immediately follows the end of this structure, and each subframe is
|
||||
* represented by pjmedia_frame_ext_subframe structure. Every next
|
||||
* subframe immediately follows the previous subframe, and all subframes
|
||||
* are byte-aligned although its payload may not be byte-aligned.
|
||||
*/
|
||||
typedef struct pjmedia_frame_ext {
|
||||
pjmedia_frame base; /**< Base frame info */
|
||||
pj_uint16_t samples_cnt; /**< Number of samples in this frame */
|
||||
pj_uint16_t subframe_cnt; /**< Number of (sub)frames in this frame */
|
||||
|
||||
/* Zero or more (sub)frames follows immediately after this,
|
||||
* each will be represented by pjmedia_frame_ext_subframe
|
||||
*/
|
||||
} pjmedia_frame_ext;
|
||||
|
||||
/**
|
||||
* This structure represents the individual subframes in the
|
||||
* pjmedia_frame_ext structure.
|
||||
*/
|
||||
typedef struct pjmedia_frame_ext_subframe {
|
||||
pj_uint16_t bitlen; /**< Number of bits in the data */
|
||||
pj_uint8_t data[1]; /**< Start of encoded data */
|
||||
} pjmedia_frame_ext_subframe;
|
||||
|
||||
|
||||
/* Append one subframe to the frame_ext */
|
||||
PJ_INLINE(void) pjmedia_frame_ext_append_subframe(pjmedia_frame_ext *frm,
|
||||
const void *src,
|
||||
pj_uint16_t bitlen,
|
||||
pj_uint16_t samples_cnt)
|
||||
{
|
||||
pj_uint8_t *p;
|
||||
unsigned i, tmp;
|
||||
|
||||
p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext);
|
||||
for (i = 0; i < frm->subframe_cnt; ++i) {
|
||||
pjmedia_frame_ext_subframe *fsub;
|
||||
fsub = (pjmedia_frame_ext_subframe*) p;
|
||||
p += fsub->bitlen / 8;
|
||||
if (fsub->bitlen % 8)
|
||||
++p;
|
||||
}
|
||||
|
||||
tmp = bitlen / 8;
|
||||
if (bitlen % 8) ++tmp;
|
||||
pj_memcpy(p, &bitlen, sizeof(bitlen));
|
||||
pj_memcpy(p + sizeof(bitlen), src, tmp);
|
||||
frm->subframe_cnt++;
|
||||
frm->samples_cnt = frm->samples_cnt + samples_cnt;
|
||||
}
|
||||
|
||||
/* Get the pointer and length of the n-th subframe */
|
||||
PJ_INLINE(pjmedia_frame_ext_subframe*)
|
||||
pjmedia_frame_ext_get_subframe(const pjmedia_frame_ext *frm,
|
||||
unsigned n)
|
||||
{
|
||||
pj_uint8_t *p;
|
||||
unsigned i;
|
||||
pjmedia_frame_ext_subframe *tmp;
|
||||
|
||||
pj_assert(n < frm->subframe_cnt);
|
||||
|
||||
p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext);
|
||||
for (i = 0; i < n; ++i) {
|
||||
tmp = (pjmedia_frame_ext_subframe*) p;
|
||||
p += tmp->bitlen / 8;
|
||||
if (tmp->bitlen % 8)
|
||||
++p;
|
||||
}
|
||||
|
||||
tmp = (pjmedia_frame_ext_subframe*) p;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Port interface.
|
||||
*/
|
||||
|
|
|
@ -30,6 +30,24 @@
|
|||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Declaration of APS sound setting.
|
||||
*/
|
||||
typedef struct pjmedia_snd_aps_setting
|
||||
{
|
||||
pjmedia_fourcc format; /**< Format (FourCC ID). */
|
||||
pj_uint32_t bitrate; /**< Bitrate (bps). */
|
||||
pj_uint32_t mode; /**< Mode, currently only used
|
||||
for specifying iLBC mode,
|
||||
20ms or 30ms frame size. */
|
||||
pj_bool_t plc; /**< PLC enabled/disabled. */
|
||||
pj_bool_t vad; /**< VAD enabled/disabled. */
|
||||
pj_bool_t cng; /**< CNG enabled/disabled. */
|
||||
pj_bool_t loudspk; /**< Audio routed to loudspeaker.*/
|
||||
|
||||
} pjmedia_snd_aps_setting;
|
||||
|
||||
|
||||
/**
|
||||
* Activate/deactivate loudspeaker, when loudspeaker is inactive, audio
|
||||
* will be routed to earpiece.
|
||||
|
@ -47,6 +65,17 @@ PJ_DECL(pj_status_t) pjmedia_snd_aps_activate_loudspeaker(
|
|||
pj_bool_t active);
|
||||
|
||||
|
||||
/**
|
||||
* Set a codec and its settings to be used on the next sound device session.
|
||||
*
|
||||
* @param setting APS sound device setting, see @pjmedia_snd_aps_setting.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_snd_aps_modify_setting(
|
||||
const pjmedia_snd_aps_setting *setting);
|
||||
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Top most media type.
|
||||
/**
|
||||
* Top most media type.
|
||||
*/
|
||||
typedef enum pjmedia_type
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ typedef enum pjmedia_type
|
|||
/** The media is video. */
|
||||
PJMEDIA_TYPE_VIDEO = 2,
|
||||
|
||||
/** Unknown media type, in this case the name will be specified in
|
||||
/** Unknown media type, in this case the name will be specified in
|
||||
* encoding_name.
|
||||
*/
|
||||
PJMEDIA_TYPE_UNKNOWN = 3,
|
||||
|
@ -72,8 +72,8 @@ typedef enum pjmedia_type
|
|||
} pjmedia_type;
|
||||
|
||||
|
||||
/**
|
||||
* Media transport protocol.
|
||||
/**
|
||||
* Media transport protocol.
|
||||
*/
|
||||
typedef enum pjmedia_tp_proto
|
||||
{
|
||||
|
@ -92,8 +92,8 @@ typedef enum pjmedia_tp_proto
|
|||
} pjmedia_tp_proto;
|
||||
|
||||
|
||||
/**
|
||||
* Media direction.
|
||||
/**
|
||||
* Media direction.
|
||||
*/
|
||||
typedef enum pjmedia_dir
|
||||
{
|
||||
|
@ -138,8 +138,8 @@ typedef enum pjmedia_dir
|
|||
(a<<24 | b<<16 | c<<8 | d)
|
||||
|
||||
|
||||
/**
|
||||
* Opague declaration of media endpoint.
|
||||
/**
|
||||
* Opaque declaration of media endpoint.
|
||||
*/
|
||||
typedef struct pjmedia_endpt pjmedia_endpt;
|
||||
|
||||
|
@ -150,7 +150,7 @@ typedef struct pjmedia_endpt pjmedia_endpt;
|
|||
typedef struct pjmedia_stream pjmedia_stream;
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Media socket info is used to describe the underlying sockets
|
||||
* to be used as media transport.
|
||||
*/
|
||||
|
@ -178,10 +178,34 @@ typedef struct pjmedia_sock_info
|
|||
|
||||
} pjmedia_sock_info;
|
||||
|
||||
/**
|
||||
* Declaration of FourCC type.
|
||||
*/
|
||||
typedef union pjmedia_fourcc {
|
||||
pj_uint32_t u32;
|
||||
char c[4];
|
||||
} pjmedia_fourcc;
|
||||
|
||||
|
||||
/**
|
||||
* FourCC packing macro.
|
||||
*/
|
||||
#define PJMEDIA_FOURCC_PACK(C1, C2, C3, C4) ( C1<<24 | C2<<16 | C3<<8 | C4 )
|
||||
|
||||
/**
|
||||
* FourCC identifier definitions.
|
||||
*/
|
||||
#define PJMEDIA_FOURCC_L16 PJMEDIA_FOURCC_PACK(' ', 'L', '1', '6')
|
||||
#define PJMEDIA_FOURCC_G711A PJMEDIA_FOURCC_PACK('G', '7', '1', '1')
|
||||
#define PJMEDIA_FOURCC_G711U PJMEDIA_FOURCC_PACK('U', 'L', 'A', 'W')
|
||||
#define PJMEDIA_FOURCC_AMR PJMEDIA_FOURCC_PACK(' ', 'A', 'M', 'R')
|
||||
#define PJMEDIA_FOURCC_G729 PJMEDIA_FOURCC_PACK('G', '7', '2', '9')
|
||||
#define PJMEDIA_FOURCC_ILBC PJMEDIA_FOURCC_PACK('i', 'L', 'B', 'C')
|
||||
|
||||
|
||||
/**
|
||||
* This is a general purpose function set PCM samples to zero.
|
||||
* Since this function is needed by many parts of the library,
|
||||
* Since this function is needed by many parts of the library,
|
||||
* by putting this functionality in one place, it enables some.
|
||||
* clever people to optimize this function.
|
||||
*
|
||||
|
@ -205,7 +229,7 @@ PJ_INLINE(void) pjmedia_zero_samples(pj_int16_t *samples, unsigned count)
|
|||
|
||||
/**
|
||||
* This is a general purpose function to copy samples from/to buffers with
|
||||
* equal size. Since this function is needed by many parts of the library,
|
||||
* equal size. Since this function is needed by many parts of the library,
|
||||
* by putting this functionality in one place, it enables some.
|
||||
* clever people to optimize this function.
|
||||
*/
|
||||
|
@ -220,7 +244,7 @@ PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src,
|
|||
#else
|
||||
unsigned i;
|
||||
count >>= 1;
|
||||
for (i=0; i<count; ++i)
|
||||
for (i=0; i<count; ++i)
|
||||
((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i];
|
||||
#endif
|
||||
}
|
||||
|
@ -228,7 +252,7 @@ PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src,
|
|||
|
||||
/**
|
||||
* This is a general purpose function to copy samples from/to buffers with
|
||||
* equal size. Since this function is needed by many parts of the library,
|
||||
* equal size. Since this function is needed by many parts of the library,
|
||||
* by putting this functionality in one place, it enables some.
|
||||
* clever people to optimize this function.
|
||||
*/
|
||||
|
@ -243,7 +267,7 @@ PJ_INLINE(void) pjmedia_move_samples(pj_int16_t *dst, const pj_int16_t *src,
|
|||
#else
|
||||
unsigned i;
|
||||
count >>= 1;
|
||||
for (i=0; i<count; ++i)
|
||||
for (i=0; i<count; ++i)
|
||||
((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i];
|
||||
#endif
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,6 +33,7 @@
|
|||
#include <pj/pool.h>
|
||||
#include <pj/string.h>
|
||||
|
||||
#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
|
||||
|
||||
/* CONF_DEBUG enables detailed operation of the conference bridge.
|
||||
* Beware that it prints large amounts of logs (several lines per frame).
|
||||
|
@ -1987,3 +1988,4 @@ static pj_status_t put_frame(pjmedia_port *this_port,
|
|||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <pj/log.h>
|
||||
#include <pj/os.h>
|
||||
|
||||
#if PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_SYMB_MDA_SOUND
|
||||
|
||||
/*
|
||||
* This file provides sound implementation for Symbian Audio Streaming
|
||||
|
@ -942,3 +943,5 @@ PJ_DEF(pj_status_t) pjmedia_snd_set_latency(unsigned input_latency,
|
|||
PJ_UNUSED_ARG(output_latency);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,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/symbian_sound_aps.h>
|
||||
#include <pjmedia/sound.h>
|
||||
#include <pjmedia/alaw_ulaw.h>
|
||||
#include <pjmedia/errno.h>
|
||||
|
@ -25,6 +26,8 @@
|
|||
#include <pj/math.h>
|
||||
#include <pj/os.h>
|
||||
|
||||
#if PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_SYMB_APS_SOUND
|
||||
|
||||
#include <e32msgqueue.h>
|
||||
#include <sounddevice.h>
|
||||
#include <APSClientSession.h>
|
||||
|
@ -45,7 +48,7 @@
|
|||
# define TRACE_(st)
|
||||
#endif
|
||||
|
||||
static pjmedia_snd_dev_info symbian_snd_dev_info =
|
||||
static pjmedia_snd_dev_info symbian_snd_dev_info =
|
||||
{
|
||||
"Symbian Sound Device (APS)",
|
||||
1,
|
||||
|
@ -56,56 +59,81 @@ static pjmedia_snd_dev_info symbian_snd_dev_info =
|
|||
/* 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;
|
||||
/* Default setting */
|
||||
static pjmedia_snd_aps_setting def_setting;
|
||||
|
||||
/* APS G.711 frame length */
|
||||
static pj_uint8_t aps_g711_frame_len;
|
||||
|
||||
/* Pool factory */
|
||||
static pj_pool_factory *snd_pool_factory;
|
||||
|
||||
/* Forward declaration of CPjAudioEngine */
|
||||
class CPjAudioEngine;
|
||||
|
||||
/*
|
||||
* PJMEDIA Sound Stream instance
|
||||
/*
|
||||
* PJMEDIA Sound Stream instance
|
||||
*/
|
||||
struct pjmedia_snd_stream
|
||||
{
|
||||
// Pool
|
||||
pj_pool_t *pool;
|
||||
pj_pool_t *pool;
|
||||
|
||||
// Common settings.
|
||||
pjmedia_dir dir;
|
||||
unsigned clock_rate;
|
||||
unsigned channel_count;
|
||||
unsigned samples_per_frame;
|
||||
pjmedia_dir dir;
|
||||
unsigned clock_rate;
|
||||
unsigned channel_count;
|
||||
unsigned samples_per_frame;
|
||||
pjmedia_snd_rec_cb rec_cb;
|
||||
pjmedia_snd_play_cb play_cb;
|
||||
void *user_data;
|
||||
|
||||
// Audio engine
|
||||
CPjAudioEngine *engine;
|
||||
};
|
||||
CPjAudioEngine *engine;
|
||||
|
||||
static pj_pool_factory *snd_pool_factory;
|
||||
pj_timestamp ts_play;
|
||||
pj_timestamp ts_rec;
|
||||
|
||||
pj_int16_t *play_buf;
|
||||
pj_uint16_t play_buf_len;
|
||||
pj_uint16_t play_buf_start;
|
||||
pj_int16_t *rec_buf;
|
||||
pj_uint16_t rec_buf_len;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Utility: print sound device error
|
||||
*/
|
||||
static void snd_perror(const char *title, TInt rc)
|
||||
static void snd_perror(const char *title, TInt rc)
|
||||
{
|
||||
PJ_LOG(1,(THIS_FILE, "%s (error code=%d)", title, rc));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
typedef void(*PjAudioCallback)(TAPSCommBuffer &buf, void *user_data);
|
||||
|
||||
/**
|
||||
* Abstract class for handler of callbacks from APS client.
|
||||
*/
|
||||
class MQueueHandlerObserver
|
||||
{
|
||||
public:
|
||||
MQueueHandlerObserver(PjAudioCallback RecCb_, PjAudioCallback PlayCb_,
|
||||
void *UserData_)
|
||||
: RecCb(RecCb_), PlayCb(PlayCb_), UserData(UserData_)
|
||||
{}
|
||||
|
||||
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;
|
||||
public:
|
||||
PjAudioCallback RecCb;
|
||||
PjAudioCallback PlayCb;
|
||||
void *UserData;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -132,11 +160,13 @@ public:
|
|||
EAPSRecorderInitComplete = 6
|
||||
};
|
||||
|
||||
static CQueueHandler* NewL(MQueueHandlerObserver* aObserver,
|
||||
RMsgQueue<TAPSCommBuffer>* aQ,
|
||||
static CQueueHandler* NewL(MQueueHandlerObserver* aObserver,
|
||||
RMsgQueue<TAPSCommBuffer>* aQ,
|
||||
RMsgQueue<TAPSCommBuffer>* aWriteQ,
|
||||
TQueueHandlerType aType)
|
||||
{
|
||||
CQueueHandler* self = new (ELeave) CQueueHandler(aObserver, aQ, aType);
|
||||
CQueueHandler* self = new (ELeave) CQueueHandler(aObserver, aQ, aWriteQ,
|
||||
aType);
|
||||
CleanupStack::PushL(self);
|
||||
self->ConstructL();
|
||||
CleanupStack::Pop(self);
|
||||
|
@ -154,11 +184,12 @@ public:
|
|||
|
||||
private:
|
||||
// Constructor
|
||||
CQueueHandler(MQueueHandlerObserver* aObserver,
|
||||
RMsgQueue<TAPSCommBuffer>* aQ,
|
||||
TQueueHandlerType aType)
|
||||
CQueueHandler(MQueueHandlerObserver* aObserver,
|
||||
RMsgQueue<TAPSCommBuffer>* aQ,
|
||||
RMsgQueue<TAPSCommBuffer>* aWriteQ,
|
||||
TQueueHandlerType aType)
|
||||
: CActive(CActive::EPriorityHigh),
|
||||
iQ(aQ), iObserver(aObserver), iType(aType)
|
||||
iQ(aQ), iWriteQ(aWriteQ), iObserver(aObserver), iType(aType)
|
||||
{
|
||||
CActiveScheduler::Add(this);
|
||||
|
||||
|
@ -177,7 +208,7 @@ private:
|
|||
if (iStatus != KErrNone) {
|
||||
iObserver->NotifyError(iStatus.Int());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TAPSCommBuffer buffer;
|
||||
TInt ret = iQ->Receive(buffer);
|
||||
|
@ -190,7 +221,9 @@ private:
|
|||
switch (iType) {
|
||||
case ERecordQueue:
|
||||
if (buffer.iCommand == EAPSRecordData) {
|
||||
iObserver->RecCb(buffer);
|
||||
iObserver->RecCb(buffer, iObserver->UserData);
|
||||
} else {
|
||||
iObserver->NotifyError(buffer.iStatus);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -199,7 +232,8 @@ private:
|
|||
switch (buffer.iCommand) {
|
||||
case EAPSPlayData:
|
||||
if (buffer.iStatus == KErrUnderflow) {
|
||||
iObserver->PlayCb(buffer);
|
||||
iObserver->PlayCb(buffer, iObserver->UserData);
|
||||
iWriteQ->Send(buffer);
|
||||
}
|
||||
break;
|
||||
case EAPSPlayerInitialize:
|
||||
|
@ -224,14 +258,9 @@ private:
|
|||
// 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:
|
||||
iObserver->NotifyError(buffer.iStatus);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -245,12 +274,30 @@ private:
|
|||
SetActive();
|
||||
}
|
||||
|
||||
TInt RunError(TInt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Data
|
||||
RMsgQueue<TAPSCommBuffer> *iQ; // (not owned)
|
||||
RMsgQueue<TAPSCommBuffer> *iWriteQ; // (not owned)
|
||||
MQueueHandlerObserver *iObserver; // (not owned)
|
||||
TQueueHandlerType iType;
|
||||
};
|
||||
|
||||
/*
|
||||
* Audio setting for CPjAudioEngine.
|
||||
*/
|
||||
class CPjAudioSetting
|
||||
{
|
||||
public:
|
||||
TFourCC fourcc;
|
||||
TAPSCodecMode mode;
|
||||
TBool plc;
|
||||
TBool vad;
|
||||
TBool cng;
|
||||
TBool loudspk;
|
||||
};
|
||||
|
||||
/*
|
||||
* Implementation: Symbian Input & Output Stream.
|
||||
|
@ -268,9 +315,10 @@ public:
|
|||
~CPjAudioEngine();
|
||||
|
||||
static CPjAudioEngine *NewL(pjmedia_snd_stream *parent_strm,
|
||||
pjmedia_snd_rec_cb rec_cb,
|
||||
pjmedia_snd_play_cb play_cb,
|
||||
void *user_data);
|
||||
PjAudioCallback rec_cb,
|
||||
PjAudioCallback play_cb,
|
||||
void *user_data,
|
||||
const CPjAudioSetting &setting);
|
||||
|
||||
TInt StartL();
|
||||
void Stop();
|
||||
|
@ -279,33 +327,29 @@ public:
|
|||
|
||||
private:
|
||||
CPjAudioEngine(pjmedia_snd_stream *parent_strm,
|
||||
pjmedia_snd_rec_cb rec_cb,
|
||||
pjmedia_snd_play_cb play_cb,
|
||||
void *user_data);
|
||||
PjAudioCallback rec_cb,
|
||||
PjAudioCallback play_cb,
|
||||
void *user_data,
|
||||
const CPjAudioSetting &setting);
|
||||
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_snd_rec_cb recCb_;
|
||||
pjmedia_snd_play_cb playCb_;
|
||||
void *userData_;
|
||||
pj_uint32_t TsPlay_;
|
||||
pj_uint32_t TsRec_;
|
||||
CPjAudioSetting setting_;
|
||||
|
||||
RAPSSession iSession;
|
||||
TAPSInitSettings iSettings;
|
||||
TAPSInitSettings iPlaySettings;
|
||||
TAPSInitSettings iRecSettings;
|
||||
|
||||
RMsgQueue<TAPSCommBuffer> iReadQ;
|
||||
RMsgQueue<TAPSCommBuffer> iReadCommQ;
|
||||
RMsgQueue<TAPSCommBuffer> iWriteQ;
|
||||
|
@ -314,28 +358,19 @@ private:
|
|||
CQueueHandler *iPlayCommHandler;
|
||||
CQueueHandler *iRecCommHandler;
|
||||
CQueueHandler *iRecHandler;
|
||||
|
||||
static pj_uint8_t aps_samples_per_frame;
|
||||
|
||||
pj_int16_t *play_buf;
|
||||
pj_uint16_t play_buf_len;
|
||||
pj_uint16_t play_buf_start;
|
||||
pj_int16_t *rec_buf;
|
||||
pj_uint16_t rec_buf_len;
|
||||
};
|
||||
|
||||
|
||||
pj_uint8_t CPjAudioEngine::aps_samples_per_frame = 0;
|
||||
|
||||
|
||||
CPjAudioEngine* CPjAudioEngine::NewL(pjmedia_snd_stream *parent_strm,
|
||||
pjmedia_snd_rec_cb rec_cb,
|
||||
pjmedia_snd_play_cb play_cb,
|
||||
void *user_data)
|
||||
PjAudioCallback rec_cb,
|
||||
PjAudioCallback play_cb,
|
||||
void *user_data,
|
||||
const CPjAudioSetting &setting)
|
||||
{
|
||||
CPjAudioEngine* self = new (ELeave) CPjAudioEngine(parent_strm,
|
||||
rec_cb, play_cb,
|
||||
user_data);
|
||||
user_data,
|
||||
setting);
|
||||
CleanupStack::PushL(self);
|
||||
self->ConstructL();
|
||||
CleanupStack::Pop(self);
|
||||
|
@ -343,14 +378,14 @@ CPjAudioEngine* CPjAudioEngine::NewL(pjmedia_snd_stream *parent_strm,
|
|||
}
|
||||
|
||||
CPjAudioEngine::CPjAudioEngine(pjmedia_snd_stream *parent_strm,
|
||||
pjmedia_snd_rec_cb rec_cb,
|
||||
pjmedia_snd_play_cb play_cb,
|
||||
void *user_data)
|
||||
: state_(STATE_NULL),
|
||||
PjAudioCallback rec_cb,
|
||||
PjAudioCallback play_cb,
|
||||
void *user_data,
|
||||
const CPjAudioSetting &setting)
|
||||
: MQueueHandlerObserver(rec_cb, play_cb, user_data),
|
||||
state_(STATE_NULL),
|
||||
parentStrm_(parent_strm),
|
||||
recCb_(rec_cb),
|
||||
playCb_(play_cb),
|
||||
userData_(user_data),
|
||||
setting_(setting),
|
||||
iPlayCommHandler(0),
|
||||
iRecCommHandler(0),
|
||||
iRecHandler(0)
|
||||
|
@ -361,10 +396,21 @@ CPjAudioEngine::~CPjAudioEngine()
|
|||
{
|
||||
Stop();
|
||||
|
||||
delete iRecHandler;
|
||||
delete iPlayCommHandler;
|
||||
iPlayCommHandler = NULL;
|
||||
delete iRecCommHandler;
|
||||
iRecCommHandler = NULL;
|
||||
|
||||
// On some devices, immediate closing after stopping may cause APS server
|
||||
// panic KERN-EXEC 0, so let's wait for sometime before really closing
|
||||
// the client session.
|
||||
TTime start, now;
|
||||
enum { APS_CLOSE_WAIT_TIME = 200 };
|
||||
start.UniversalTime();
|
||||
now.UniversalTime();
|
||||
while (now.MicroSecondsFrom(start) < APS_CLOSE_WAIT_TIME * 1000) {
|
||||
pj_symbianos_poll(-1, APS_CLOSE_WAIT_TIME);
|
||||
now.UniversalTime();
|
||||
}
|
||||
|
||||
iSession.Close();
|
||||
|
||||
|
@ -383,16 +429,16 @@ TInt CPjAudioEngine::InitPlayL()
|
|||
if (state_ == STATE_STREAMING || state_ == STATE_READY)
|
||||
return 0;
|
||||
|
||||
TInt err = iSession.InitializePlayer(iSettings);
|
||||
TInt err = iSession.InitializePlayer(iPlaySettings);
|
||||
if (err != KErrNone) {
|
||||
snd_perror("Failed to initialize player", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// Open message queues for the output stream
|
||||
TBuf<128> buf2 = iSettings.iGlobal;
|
||||
TBuf<128> buf2 = iPlaySettings.iGlobal;
|
||||
buf2.Append(_L("PlayQueue"));
|
||||
TBuf<128> buf3 = iSettings.iGlobal;
|
||||
TBuf<128> buf3 = iPlaySettings.iGlobal;
|
||||
buf3.Append(_L("PlayCommQueue"));
|
||||
|
||||
while (iWriteQ.OpenGlobal(buf2))
|
||||
|
@ -401,8 +447,7 @@ TInt CPjAudioEngine::InitPlayL()
|
|||
User::After(10);
|
||||
|
||||
// Construct message queue handler
|
||||
iPlayCommHandler = CQueueHandler::NewL(this,
|
||||
&iWriteCommQ,
|
||||
iPlayCommHandler = CQueueHandler::NewL(this, &iWriteCommQ, &iWriteQ,
|
||||
CQueueHandler::EPlayCommQueue);
|
||||
|
||||
// Start observing APS callbacks on output stream message queue
|
||||
|
@ -417,15 +462,15 @@ TInt CPjAudioEngine::InitRecL()
|
|||
return 0;
|
||||
|
||||
// Initialize input stream device
|
||||
TInt err = iSession.InitializeRecorder(iSettings);
|
||||
if (err != KErrNone) {
|
||||
TInt err = iSession.InitializeRecorder(iRecSettings);
|
||||
if (err != KErrNone && err != KErrAlreadyExists) {
|
||||
snd_perror("Failed to initialize recorder", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
TBuf<128> buf1 = iSettings.iGlobal;
|
||||
TBuf<128> buf1 = iRecSettings.iGlobal;
|
||||
buf1.Append(_L("RecordQueue"));
|
||||
TBuf<128> buf4 = iSettings.iGlobal;
|
||||
TBuf<128> buf4 = iRecSettings.iGlobal;
|
||||
buf4.Append(_L("RecordCommQueue"));
|
||||
|
||||
// Must wait for APS thread to finish creating message queues
|
||||
|
@ -436,60 +481,57 @@ TInt CPjAudioEngine::InitRecL()
|
|||
User::After(10);
|
||||
|
||||
// Construct message queue handlers
|
||||
iRecCommHandler = CQueueHandler::NewL(this,
|
||||
&iReadCommQ,
|
||||
iRecHandler = CQueueHandler::NewL(this, &iReadQ, NULL,
|
||||
CQueueHandler::ERecordQueue);
|
||||
iRecCommHandler = CQueueHandler::NewL(this, &iReadCommQ, NULL,
|
||||
CQueueHandler::ERecordCommQueue);
|
||||
|
||||
// Start observing APS callbacks from on input stream message queue
|
||||
iRecHandler->Start();
|
||||
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
|
||||
// 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;
|
||||
if (state_ == STATE_STREAMING) {
|
||||
iSession.Stop();
|
||||
state_ = STATE_READY;
|
||||
TRACE_((THIS_FILE, "Streaming stopped"));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* play_buf size is samples per frame of parent stream. */
|
||||
play_buf = (pj_int16_t*)pj_pool_alloc(parentStrm_->pool,
|
||||
parentStrm_->samples_per_frame << 1);
|
||||
play_buf_len = 0;
|
||||
play_buf_start = 0;
|
||||
|
||||
/* rec_buf size is samples per frame of parent stream. */
|
||||
rec_buf = (pj_int16_t*)pj_pool_alloc(parentStrm_->pool,
|
||||
parentStrm_->samples_per_frame << 1);
|
||||
rec_buf_len = 0;
|
||||
// Recorder settings
|
||||
iRecSettings.iFourCC = setting_.fourcc;
|
||||
iRecSettings.iGlobal = APP_UID;
|
||||
iRecSettings.iPriority = TMdaPriority(100);
|
||||
iRecSettings.iPreference = TMdaPriorityPreference(0x05210001);
|
||||
iRecSettings.iSettings.iChannels = EMMFMono;
|
||||
iRecSettings.iSettings.iSampleRate = EMMFSampleRate8000Hz;
|
||||
|
||||
// Player settings
|
||||
iPlaySettings.iFourCC = setting_.fourcc;
|
||||
iPlaySettings.iGlobal = APP_UID;
|
||||
iPlaySettings.iPriority = TMdaPriority(100);
|
||||
iPlaySettings.iPreference = TMdaPriorityPreference(0x05220001);
|
||||
iPlaySettings.iSettings.iChannels = EMMFMono;
|
||||
iPlaySettings.iSettings.iSampleRate = EMMFSampleRate8000Hz;
|
||||
iPlaySettings.iSettings.iVolume = 0;
|
||||
|
||||
User::LeaveIfError(iSession.Connect());
|
||||
}
|
||||
|
||||
TInt CPjAudioEngine::StartStreamL()
|
||||
|
@ -497,26 +539,23 @@ TInt CPjAudioEngine::StartStreamL()
|
|||
if (state_ == STATE_STREAMING)
|
||||
return 0;
|
||||
|
||||
iSession.SetCng(EFalse);
|
||||
iSession.SetVadMode(EFalse);
|
||||
iSession.SetPlc(EFalse);
|
||||
iSession.SetEncoderMode(EULawOr30ms);
|
||||
iSession.SetDecoderMode(EULawOr30ms);
|
||||
iSession.ActivateLoudspeaker(act_loudspeaker);
|
||||
|
||||
// Not only playback
|
||||
if (parentStrm_->dir != PJMEDIA_DIR_PLAYBACK) {
|
||||
iRecHandler = CQueueHandler::NewL(this, &iReadQ,
|
||||
CQueueHandler::ERecordQueue);
|
||||
iRecHandler->Start();
|
||||
iSession.Read();
|
||||
TRACE_((THIS_FILE, "APS recorder started"));
|
||||
}
|
||||
iSession.SetCng(setting_.cng);
|
||||
iSession.SetVadMode(setting_.vad);
|
||||
iSession.SetPlc(setting_.plc);
|
||||
iSession.SetEncoderMode(setting_.mode);
|
||||
iSession.SetDecoderMode(setting_.mode);
|
||||
iSession.ActivateLoudspeaker(setting_.loudspk);
|
||||
|
||||
// Not only capture
|
||||
if (parentStrm_->dir != PJMEDIA_DIR_CAPTURE) {
|
||||
iSession.Write();
|
||||
TRACE_((THIS_FILE, "APS player started"));
|
||||
TRACE_((THIS_FILE, "Player streaming started"));
|
||||
}
|
||||
|
||||
// Not only playback
|
||||
if (parentStrm_->dir != PJMEDIA_DIR_PLAYBACK) {
|
||||
iSession.Read();
|
||||
TRACE_((THIS_FILE, "Recorder streaming started"));
|
||||
}
|
||||
|
||||
state_ = STATE_STREAMING;
|
||||
|
@ -556,90 +595,6 @@ void CPjAudioEngine::NotifyError(const TInt aError)
|
|||
snd_perror("Error from CQueueHandler", aError);
|
||||
}
|
||||
|
||||
void CPjAudioEngine::RecCb(TAPSCommBuffer &buffer)
|
||||
{
|
||||
pj_assert(buffer.iBuffer[0] == 1 && buffer.iBuffer[1] == 0);
|
||||
|
||||
/* Detect the recorder G.711 frame size, player frame size will follow
|
||||
* this recorder frame size.
|
||||
*/
|
||||
if (CPjAudioEngine::aps_samples_per_frame == 0) {
|
||||
CPjAudioEngine::aps_samples_per_frame = buffer.iBuffer.Length() < 160?
|
||||
80 : 160;
|
||||
TRACE_((THIS_FILE, "Detected APS G.711 frame size = %u samples",
|
||||
CPjAudioEngine::aps_samples_per_frame));
|
||||
}
|
||||
|
||||
/* Decode APS buffer (coded in G.711) and put the PCM result into rec_buf.
|
||||
* Whenever rec_buf is full, call parent stream callback.
|
||||
*/
|
||||
unsigned dec_len = 0;
|
||||
|
||||
while (dec_len < CPjAudioEngine::aps_samples_per_frame) {
|
||||
unsigned tmp;
|
||||
|
||||
tmp = PJ_MIN(parentStrm_->samples_per_frame - rec_buf_len,
|
||||
CPjAudioEngine::aps_samples_per_frame - dec_len);
|
||||
pjmedia_ulaw_decode(&rec_buf[rec_buf_len],
|
||||
buffer.iBuffer.Ptr() + 2 + dec_len,
|
||||
tmp);
|
||||
rec_buf_len += tmp;
|
||||
dec_len += tmp;
|
||||
|
||||
pj_assert(rec_buf_len <= parentStrm_->samples_per_frame);
|
||||
|
||||
if (rec_buf_len == parentStrm_->samples_per_frame) {
|
||||
recCb_(userData_, 0, rec_buf, rec_buf_len << 1);
|
||||
rec_buf_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPjAudioEngine::PlayCb(TAPSCommBuffer &buffer)
|
||||
{
|
||||
buffer.iCommand = CQueueHandler::EAPSPlayData;
|
||||
buffer.iStatus = 0;
|
||||
buffer.iBuffer.Zero();
|
||||
buffer.iBuffer.Append(1);
|
||||
buffer.iBuffer.Append(0);
|
||||
|
||||
/* Send 10ms silence frame if frame size hasn't been known. */
|
||||
if (CPjAudioEngine::aps_samples_per_frame == 0) {
|
||||
pjmedia_zero_samples(play_buf, 80);
|
||||
pjmedia_ulaw_encode((pj_uint8_t*)play_buf, play_buf, 80);
|
||||
buffer.iBuffer.Append((TUint8*)play_buf, 80);
|
||||
iWriteQ.Send(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned enc_len = 0;
|
||||
|
||||
/* Call parent stream callback to get PCM samples to play,
|
||||
* encode the PCM samples into G.711 and put it into APS buffer.
|
||||
*/
|
||||
while (enc_len < CPjAudioEngine::aps_samples_per_frame) {
|
||||
if (play_buf_len == 0) {
|
||||
playCb_(userData_, 0, play_buf, parentStrm_->samples_per_frame<<1);
|
||||
play_buf_len = parentStrm_->samples_per_frame;
|
||||
play_buf_start = 0;
|
||||
}
|
||||
|
||||
unsigned tmp;
|
||||
|
||||
tmp = PJ_MIN(play_buf_len,
|
||||
CPjAudioEngine::aps_samples_per_frame - enc_len);
|
||||
pjmedia_ulaw_encode((pj_uint8_t*)&play_buf[play_buf_start],
|
||||
&play_buf[play_buf_start],
|
||||
tmp);
|
||||
buffer.iBuffer.Append((TUint8*)&play_buf[play_buf_start], tmp);
|
||||
enc_len += tmp;
|
||||
play_buf_len -= tmp;
|
||||
play_buf_start += tmp;
|
||||
}
|
||||
|
||||
iWriteQ.Send(buffer);
|
||||
}
|
||||
|
||||
//
|
||||
// End of inherited from MQueueHandlerObserver
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
@ -649,6 +604,7 @@ TInt CPjAudioEngine::ActivateSpeaker(TBool active)
|
|||
{
|
||||
if (state_ == STATE_READY || state_ == STATE_STREAMING) {
|
||||
iSession.ActivateLoudspeaker(active);
|
||||
TRACE_((THIS_FILE, "Loudspeaker on/off: %d", active));
|
||||
return KErrNone;
|
||||
}
|
||||
return KErrNotReady;
|
||||
|
@ -657,12 +613,110 @@ TInt CPjAudioEngine::ActivateSpeaker(TBool active)
|
|||
//
|
||||
|
||||
|
||||
static void RecCbPcm(TAPSCommBuffer &buf, void *user_data)
|
||||
{
|
||||
pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data;
|
||||
|
||||
pj_assert(buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0);
|
||||
|
||||
/* Detect the recorder G.711 frame size, player frame size will follow
|
||||
* this recorder frame size.
|
||||
*/
|
||||
if (aps_g711_frame_len == 0) {
|
||||
aps_g711_frame_len = buf.iBuffer.Length() < 160? 80 : 160;
|
||||
TRACE_((THIS_FILE, "Detected APS G.711 frame size = %u samples",
|
||||
aps_g711_frame_len));
|
||||
}
|
||||
|
||||
/* Decode APS buffer (coded in G.711) and put the PCM result into rec_buf.
|
||||
* Whenever rec_buf is full, call parent stream callback.
|
||||
*/
|
||||
unsigned dec_len = 0;
|
||||
|
||||
while (dec_len < aps_g711_frame_len) {
|
||||
unsigned tmp;
|
||||
|
||||
tmp = PJ_MIN(strm->samples_per_frame - strm->rec_buf_len,
|
||||
aps_g711_frame_len - dec_len);
|
||||
pjmedia_ulaw_decode(&strm->rec_buf[strm->rec_buf_len],
|
||||
buf.iBuffer.Ptr() + 2 + dec_len,
|
||||
tmp);
|
||||
strm->rec_buf_len += tmp;
|
||||
dec_len += tmp;
|
||||
|
||||
pj_assert(strm->rec_buf_len <= strm->samples_per_frame);
|
||||
|
||||
if (strm->rec_buf_len == strm->samples_per_frame) {
|
||||
strm->rec_cb(strm->user_data, 0, strm->rec_buf,
|
||||
strm->rec_buf_len << 1);
|
||||
strm->rec_buf_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PlayCbPcm(TAPSCommBuffer &buf, void *user_data)
|
||||
{
|
||||
pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data;
|
||||
unsigned g711_frame_len = aps_g711_frame_len;
|
||||
|
||||
buf.iCommand = CQueueHandler::EAPSPlayData;
|
||||
buf.iStatus = 0;
|
||||
buf.iBuffer.Zero();
|
||||
buf.iBuffer.Append(1);
|
||||
buf.iBuffer.Append(0);
|
||||
|
||||
/* Assume frame size is 10ms if frame size hasn't been known. */
|
||||
if (g711_frame_len == 0)
|
||||
g711_frame_len = 80;
|
||||
|
||||
/* Call parent stream callback to get PCM samples to play,
|
||||
* encode the PCM samples into G.711 and put it into APS buffer.
|
||||
*/
|
||||
unsigned enc_len = 0;
|
||||
while (enc_len < g711_frame_len) {
|
||||
if (strm->play_buf_len == 0) {
|
||||
strm->play_cb(strm->user_data, 0, strm->play_buf,
|
||||
strm->samples_per_frame<<1);
|
||||
strm->play_buf_len = strm->samples_per_frame;
|
||||
strm->play_buf_start = 0;
|
||||
}
|
||||
|
||||
unsigned tmp;
|
||||
|
||||
tmp = PJ_MIN(strm->play_buf_len, g711_frame_len - enc_len);
|
||||
pjmedia_ulaw_encode((pj_uint8_t*)&strm->play_buf[strm->play_buf_start],
|
||||
&strm->play_buf[strm->play_buf_start],
|
||||
tmp);
|
||||
buf.iBuffer.Append((TUint8*)&strm->play_buf[strm->play_buf_start], tmp);
|
||||
enc_len += tmp;
|
||||
strm->play_buf_len -= tmp;
|
||||
strm->play_buf_start += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static void RecCb(TAPSCommBuffer &buf, void *user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static void PlayCb(TAPSCommBuffer &buf, void *user_data)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize sound subsystem.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory)
|
||||
{
|
||||
snd_pool_factory = factory;
|
||||
|
||||
def_setting.format.u32 = PJMEDIA_FOURCC_L16;
|
||||
def_setting.mode = 0;
|
||||
def_setting.bitrate = 128000;
|
||||
def_setting.plc = PJ_FALSE;
|
||||
def_setting.vad = PJ_FALSE;
|
||||
def_setting.cng = PJ_FALSE;
|
||||
def_setting.loudspk = PJ_FALSE;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -700,21 +754,24 @@ static pj_status_t sound_open(pjmedia_dir dir,
|
|||
{
|
||||
pj_pool_t *pool;
|
||||
pjmedia_snd_stream *strm;
|
||||
CPjAudioSetting setting;
|
||||
PjAudioCallback aps_rec_cb;
|
||||
PjAudioCallback aps_play_cb;
|
||||
|
||||
PJ_ASSERT_RETURN(p_snd_strm, PJ_EINVAL);
|
||||
PJ_ASSERT_RETURN(clock_rate == 8000 && channel_count == 1 &&
|
||||
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,
|
||||
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,
|
||||
strm = (pjmedia_snd_stream*) pj_pool_zalloc(pool,
|
||||
sizeof(pjmedia_snd_stream));
|
||||
strm->dir = dir;
|
||||
strm->pool = pool;
|
||||
|
@ -722,14 +779,68 @@ static pj_status_t sound_open(pjmedia_dir dir,
|
|||
strm->channel_count = channel_count;
|
||||
strm->samples_per_frame = samples_per_frame;
|
||||
|
||||
/* Set audio engine settings. */
|
||||
if (def_setting.format.u32 == PJMEDIA_FOURCC_G711U ||
|
||||
def_setting.format.u32 == PJMEDIA_FOURCC_L16)
|
||||
{
|
||||
setting.fourcc = TFourCC(KMCPFourCCIdG711);
|
||||
} else {
|
||||
setting.fourcc = TFourCC(def_setting.format.u32);
|
||||
}
|
||||
|
||||
if (def_setting.format.u32 == PJMEDIA_FOURCC_AMR)
|
||||
{
|
||||
setting.mode = (TAPSCodecMode)def_setting.bitrate;
|
||||
} else if (def_setting.format.u32 == PJMEDIA_FOURCC_G711U ||
|
||||
def_setting.format.u32 == PJMEDIA_FOURCC_L16 ||
|
||||
(def_setting.format.u32 == PJMEDIA_FOURCC_ILBC &&
|
||||
def_setting.mode == 30))
|
||||
{
|
||||
setting.mode = EULawOr30ms;
|
||||
} else {
|
||||
setting.mode = EALawOr20ms;
|
||||
}
|
||||
|
||||
setting.vad = def_setting.vad;
|
||||
setting.plc = def_setting.plc;
|
||||
setting.cng = def_setting.cng;
|
||||
setting.loudspk = def_setting.loudspk;
|
||||
|
||||
if (def_setting.format.u32 == PJMEDIA_FOURCC_AMR ||
|
||||
def_setting.format.u32 == PJMEDIA_FOURCC_G711A ||
|
||||
def_setting.format.u32 == PJMEDIA_FOURCC_G711U ||
|
||||
def_setting.format.u32 == PJMEDIA_FOURCC_G729 ||
|
||||
def_setting.format.u32 == PJMEDIA_FOURCC_ILBC)
|
||||
{
|
||||
aps_play_cb = &PlayCb;
|
||||
aps_rec_cb = &RecCb;
|
||||
} else {
|
||||
aps_play_cb = &PlayCbPcm;
|
||||
aps_rec_cb = &RecCbPcm;
|
||||
}
|
||||
|
||||
// Create the audio engine.
|
||||
TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm, rec_cb, play_cb,
|
||||
user_data));
|
||||
TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm,
|
||||
aps_rec_cb, aps_play_cb,
|
||||
strm, setting));
|
||||
if (err != KErrNone) {
|
||||
pj_pool_release(pool);
|
||||
pj_pool_release(pool);
|
||||
return PJ_RETURN_OS_ERROR(err);
|
||||
}
|
||||
|
||||
strm->rec_cb = rec_cb;
|
||||
strm->play_cb = play_cb;
|
||||
strm->user_data = user_data;
|
||||
|
||||
/* play_buf size is samples per frame. */
|
||||
strm->play_buf = (pj_int16_t*)pj_pool_alloc(pool, samples_per_frame << 1);
|
||||
strm->play_buf_len = 0;
|
||||
strm->play_buf_start = 0;
|
||||
|
||||
/* rec_buf size is samples per frame. */
|
||||
strm->rec_buf = (pj_int16_t*)pj_pool_alloc(pool, samples_per_frame << 1);
|
||||
strm->rec_buf_len = 0;
|
||||
|
||||
// Done.
|
||||
*p_snd_strm = strm;
|
||||
return PJ_SUCCESS;
|
||||
|
@ -752,7 +863,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,
|
|||
if (index < 0) index = 0;
|
||||
PJ_ASSERT_RETURN(index == 0, PJ_EINVAL);
|
||||
|
||||
return sound_open(PJMEDIA_DIR_CAPTURE, clock_rate, channel_count,
|
||||
return sound_open(PJMEDIA_DIR_CAPTURE, clock_rate, channel_count,
|
||||
samples_per_frame, bits_per_sample, rec_cb, NULL,
|
||||
user_data, p_snd_strm);
|
||||
}
|
||||
|
@ -769,7 +880,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
|
|||
if (index < 0) index = 0;
|
||||
PJ_ASSERT_RETURN(index == 0, PJ_EINVAL);
|
||||
|
||||
return sound_open(PJMEDIA_DIR_PLAYBACK, clock_rate, channel_count,
|
||||
return sound_open(PJMEDIA_DIR_PLAYBACK, clock_rate, channel_count,
|
||||
samples_per_frame, bits_per_sample, NULL, play_cb,
|
||||
user_data, p_snd_strm);
|
||||
}
|
||||
|
@ -789,7 +900,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id,
|
|||
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,
|
||||
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);
|
||||
}
|
||||
|
@ -821,13 +932,13 @@ PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -835,11 +946,11 @@ PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -847,20 +958,18 @@ PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream)
|
|||
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;
|
||||
}
|
||||
|
||||
delete stream->engine;
|
||||
stream->engine = NULL;
|
||||
|
||||
pool = stream->pool;
|
||||
if (pool) {
|
||||
if (pool) {
|
||||
stream->pool = NULL;
|
||||
pj_pool_release(pool);
|
||||
}
|
||||
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -875,7 +984,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_deinit(void)
|
|||
/*
|
||||
* Set sound latency.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pjmedia_snd_set_latency(unsigned input_latency,
|
||||
PJ_DEF(pj_status_t) pjmedia_snd_set_latency(unsigned input_latency,
|
||||
unsigned output_latency)
|
||||
{
|
||||
/* Nothing to do */
|
||||
|
@ -889,11 +998,11 @@ PJ_DEF(pj_status_t) pjmedia_snd_set_latency(unsigned input_latency,
|
|||
* Activate/deactivate loudspeaker.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pjmedia_snd_aps_activate_loudspeaker(
|
||||
pjmedia_snd_stream *stream,
|
||||
pjmedia_snd_stream *stream,
|
||||
pj_bool_t active)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
act_loudspeaker = active;
|
||||
def_setting.loudspk = active;
|
||||
} else {
|
||||
if (stream->engine == NULL)
|
||||
return PJ_EINVAL;
|
||||
|
@ -905,3 +1014,18 @@ PJ_DEF(pj_status_t) pjmedia_snd_aps_activate_loudspeaker(
|
|||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a codec and its settings to be used on the next sound device session.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pjmedia_snd_aps_modify_setting(
|
||||
const pjmedia_snd_aps_setting *setting)
|
||||
{
|
||||
PJ_ASSERT_RETURN(setting, PJ_EINVAL);
|
||||
|
||||
def_setting = *setting;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_SYMB_APS_SOUND
|
||||
|
|
|
@ -49,7 +49,7 @@ static void log_writer(int level, const char *buf, unsigned len)
|
|||
static wchar_t buf16[PJ_LOG_MAX_SIZE];
|
||||
|
||||
PJ_UNUSED_ARG(level);
|
||||
|
||||
|
||||
pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
|
||||
|
||||
TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
|
||||
|
@ -57,24 +57,24 @@ static void log_writer(int level, const char *buf, unsigned len)
|
|||
}
|
||||
|
||||
/* perror util */
|
||||
static void app_perror(const char *title, pj_status_t status)
|
||||
static void app_perror(const char *title, pj_status_t status)
|
||||
{
|
||||
char errmsg[PJ_ERR_MSG_SIZE];
|
||||
char errmsg[PJ_ERR_MSG_SIZE];
|
||||
pj_strerror(status, errmsg, sizeof(errmsg));
|
||||
PJ_LOG(1,(THIS_FILE, "Error: %s: %s", title, errmsg));
|
||||
}
|
||||
|
||||
/* Application init */
|
||||
static pj_status_t app_init()
|
||||
static pj_status_t app_init()
|
||||
{
|
||||
unsigned i, count;
|
||||
pj_status_t status;
|
||||
|
||||
|
||||
/* 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(3);
|
||||
|
||||
|
||||
/* Init pjlib */
|
||||
status = pj_init();
|
||||
if (status != PJ_SUCCESS) {
|
||||
|
@ -83,7 +83,7 @@ static pj_status_t app_init()
|
|||
}
|
||||
|
||||
pj_caching_pool_init(&cp, NULL, 0);
|
||||
|
||||
|
||||
/* Init sound subsystem */
|
||||
status = pjmedia_snd_init(&cp.factory);
|
||||
if (status != PJ_SUCCESS) {
|
||||
|
@ -92,16 +92,16 @@ static pj_status_t app_init()
|
|||
pj_shutdown();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
count = pjmedia_snd_get_dev_count();
|
||||
PJ_LOG(3,(THIS_FILE, "Device count: %d", count));
|
||||
for (i=0; i<count; ++i) {
|
||||
const pjmedia_snd_dev_info *info;
|
||||
|
||||
|
||||
info = pjmedia_snd_get_dev_info(i);
|
||||
PJ_LOG(3, (THIS_FILE, "%d: %s %d/%d %dHz",
|
||||
i, info->name, info->input_count, info->output_count,
|
||||
info->default_samples_per_sec));
|
||||
info->default_samples_per_sec));
|
||||
}
|
||||
|
||||
/* Create pool */
|
||||
|
@ -114,8 +114,8 @@ static pj_status_t app_init()
|
|||
}
|
||||
|
||||
/* Init delay buffer */
|
||||
status = pjmedia_delay_buf_create(pool, THIS_FILE, CLOCK_RATE,
|
||||
SAMPLES_PER_FRAME, CHANNEL_COUNT,
|
||||
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);
|
||||
|
@ -123,16 +123,16 @@ static pj_status_t app_init()
|
|||
//pj_shutdown();
|
||||
//return status;
|
||||
}
|
||||
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Sound capture callback */
|
||||
static pj_status_t rec_cb(void *user_data,
|
||||
static pj_status_t rec_cb(void *user_data,
|
||||
pj_uint32_t timestamp,
|
||||
void *input,
|
||||
unsigned size)
|
||||
unsigned size)
|
||||
{
|
||||
PJ_UNUSED_ARG(user_data);
|
||||
PJ_UNUSED_ARG(timestamp);
|
||||
|
@ -153,28 +153,28 @@ static pj_status_t rec_cb(void *user_data,
|
|||
static pj_status_t play_cb(void *user_data,
|
||||
pj_uint32_t timestamp,
|
||||
void *output,
|
||||
unsigned size)
|
||||
unsigned size)
|
||||
{
|
||||
PJ_UNUSED_ARG(user_data);
|
||||
PJ_UNUSED_ARG(timestamp);
|
||||
PJ_UNUSED_ARG(size);
|
||||
|
||||
|
||||
pjmedia_delay_buf_get(delaybuf, (pj_int16_t*)output);
|
||||
|
||||
|
||||
++play_cnt;
|
||||
return PJ_SUCCESS;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/* Start sound */
|
||||
static pj_status_t snd_start(unsigned flag)
|
||||
static pj_status_t snd_start(unsigned flag)
|
||||
{
|
||||
pj_status_t status;
|
||||
|
||||
|
||||
if (strm != NULL) {
|
||||
app_perror("snd already open", PJ_EINVALIDOP);
|
||||
return PJ_EINVALIDOP;
|
||||
}
|
||||
|
||||
|
||||
if (flag==PJMEDIA_DIR_CAPTURE_PLAYBACK)
|
||||
status = pjmedia_snd_open(-1, -1, CLOCK_RATE, CHANNEL_COUNT,
|
||||
SAMPLES_PER_FRAME, BITS_PER_SAMPLE,
|
||||
|
@ -187,7 +187,7 @@ static pj_status_t snd_start(unsigned flag)
|
|||
status = pjmedia_snd_open_player(-1, CLOCK_RATE, CHANNEL_COUNT,
|
||||
SAMPLES_PER_FRAME, BITS_PER_SAMPLE,
|
||||
&play_cb, NULL, &strm);
|
||||
|
||||
|
||||
if (status != PJ_SUCCESS) {
|
||||
app_perror("snd open", status);
|
||||
return status;
|
||||
|
@ -210,19 +210,23 @@ static pj_status_t snd_start(unsigned flag)
|
|||
}
|
||||
|
||||
/* Stop sound */
|
||||
static pj_status_t snd_stop()
|
||||
static pj_status_t snd_stop()
|
||||
{
|
||||
pj_time_val now;
|
||||
pj_status_t status;
|
||||
|
||||
|
||||
if (strm == NULL) {
|
||||
app_perror("snd not open", PJ_EINVALIDOP);
|
||||
return PJ_EINVALIDOP;
|
||||
}
|
||||
|
||||
|
||||
status = pjmedia_snd_stream_stop(strm);
|
||||
if (status != PJ_SUCCESS) {
|
||||
app_perror("snd failed to stop", status);
|
||||
}
|
||||
status = pjmedia_snd_stream_close(strm);
|
||||
strm = NULL;
|
||||
|
||||
|
||||
pj_gettimeofday(&now);
|
||||
PJ_TIME_VAL_SUB(now, t_start);
|
||||
|
||||
|
@ -234,11 +238,11 @@ static pj_status_t snd_stop()
|
|||
}
|
||||
|
||||
/* Shutdown application */
|
||||
static void app_fini()
|
||||
static void app_fini()
|
||||
{
|
||||
if (strm)
|
||||
snd_stop();
|
||||
|
||||
|
||||
pjmedia_snd_deinit();
|
||||
pjmedia_delay_buf_destroy(delaybuf);
|
||||
pj_pool_release(pool);
|
||||
|
@ -253,56 +257,55 @@ static void app_fini()
|
|||
*/
|
||||
#include <e32base.h>
|
||||
|
||||
class ConsoleUI : public CActive
|
||||
class ConsoleUI : public CActive
|
||||
{
|
||||
public:
|
||||
ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con);
|
||||
ConsoleUI(CConsoleBase *con);
|
||||
|
||||
// Run console UI
|
||||
void Run();
|
||||
|
||||
// Stop
|
||||
void Stop();
|
||||
|
||||
|
||||
protected:
|
||||
// Cancel asynchronous read.
|
||||
void DoCancel();
|
||||
|
||||
// Implementation: called when read has completed.
|
||||
void RunL();
|
||||
|
||||
|
||||
private:
|
||||
CActiveSchedulerWait *asw_;
|
||||
CConsoleBase *con_;
|
||||
};
|
||||
|
||||
|
||||
ConsoleUI::ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con)
|
||||
: CActive(EPriorityHigh), asw_(asw), con_(con)
|
||||
ConsoleUI::ConsoleUI(CConsoleBase *con)
|
||||
: CActive(EPriorityUserInput), con_(con)
|
||||
{
|
||||
CActiveScheduler::Add(this);
|
||||
}
|
||||
|
||||
// Run console UI
|
||||
void ConsoleUI::Run()
|
||||
void ConsoleUI::Run()
|
||||
{
|
||||
con_->Read(iStatus);
|
||||
SetActive();
|
||||
}
|
||||
|
||||
// Stop console UI
|
||||
void ConsoleUI::Stop()
|
||||
void ConsoleUI::Stop()
|
||||
{
|
||||
DoCancel();
|
||||
}
|
||||
|
||||
// Cancel asynchronous read.
|
||||
void ConsoleUI::DoCancel()
|
||||
void ConsoleUI::DoCancel()
|
||||
{
|
||||
con_->ReadCancel();
|
||||
}
|
||||
|
||||
static void PrintMenu()
|
||||
static void PrintMenu()
|
||||
{
|
||||
PJ_LOG(3, (THIS_FILE, "\n\n"
|
||||
"Menu:\n"
|
||||
|
@ -314,14 +317,15 @@ static void PrintMenu()
|
|||
}
|
||||
|
||||
// Implementation: called when read has completed.
|
||||
void ConsoleUI::RunL()
|
||||
void ConsoleUI::RunL()
|
||||
{
|
||||
TKeyCode kc = con_->KeyCode();
|
||||
pj_bool_t reschedule = PJ_TRUE;
|
||||
|
||||
|
||||
switch (kc) {
|
||||
case 'w':
|
||||
asw_->AsyncStop();
|
||||
snd_stop();
|
||||
CActiveScheduler::Stop();
|
||||
reschedule = PJ_FALSE;
|
||||
break;
|
||||
case 'a':
|
||||
|
@ -343,30 +347,28 @@ void ConsoleUI::RunL()
|
|||
}
|
||||
|
||||
PrintMenu();
|
||||
|
||||
|
||||
if (reschedule)
|
||||
Run();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int app_main()
|
||||
int app_main()
|
||||
{
|
||||
if (app_init() != PJ_SUCCESS)
|
||||
return -1;
|
||||
|
||||
|
||||
// Run the UI
|
||||
CActiveSchedulerWait *asw = new CActiveSchedulerWait;
|
||||
ConsoleUI *con = new ConsoleUI(asw, console);
|
||||
|
||||
ConsoleUI *con = new ConsoleUI(console);
|
||||
|
||||
con->Run();
|
||||
|
||||
|
||||
PrintMenu();
|
||||
asw->Start();
|
||||
|
||||
CActiveScheduler::Start();
|
||||
|
||||
delete con;
|
||||
delete asw;
|
||||
|
||||
|
||||
app_fini();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,74 +29,11 @@
|
|||
CConsoleBase* console;
|
||||
|
||||
// Needed by APS
|
||||
TPtrC APP_UID = _L("A000000D");
|
||||
TPtrC APP_UID = _L("A000000E");
|
||||
|
||||
int app_main();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class MyTask : public CActive
|
||||
{
|
||||
public:
|
||||
static MyTask *NewL(CActiveSchedulerWait *asw);
|
||||
~MyTask();
|
||||
void Start();
|
||||
|
||||
protected:
|
||||
MyTask(CActiveSchedulerWait *asw);
|
||||
void ConstructL();
|
||||
virtual void RunL();
|
||||
virtual void DoCancel();
|
||||
|
||||
private:
|
||||
RTimer timer_;
|
||||
CActiveSchedulerWait *asw_;
|
||||
};
|
||||
|
||||
MyTask::MyTask(CActiveSchedulerWait *asw)
|
||||
: CActive(EPriorityNormal), asw_(asw)
|
||||
{
|
||||
}
|
||||
|
||||
MyTask::~MyTask()
|
||||
{
|
||||
timer_.Close();
|
||||
}
|
||||
|
||||
void MyTask::ConstructL()
|
||||
{
|
||||
timer_.CreateLocal();
|
||||
CActiveScheduler::Add(this);
|
||||
}
|
||||
|
||||
MyTask *MyTask::NewL(CActiveSchedulerWait *asw)
|
||||
{
|
||||
MyTask *self = new (ELeave) MyTask(asw);
|
||||
CleanupStack::PushL(self);
|
||||
|
||||
self->ConstructL();
|
||||
|
||||
CleanupStack::Pop(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
void MyTask::Start()
|
||||
{
|
||||
timer_.After(iStatus, 0);
|
||||
SetActive();
|
||||
}
|
||||
|
||||
void MyTask::RunL()
|
||||
{
|
||||
int rc = app_main();
|
||||
asw_->AsyncStop();
|
||||
}
|
||||
|
||||
void MyTask::DoCancel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LOCAL_C void DoStartL()
|
||||
|
@ -105,19 +42,8 @@ LOCAL_C void DoStartL()
|
|||
CleanupStack::PushL(scheduler);
|
||||
CActiveScheduler::Install(scheduler);
|
||||
|
||||
CActiveSchedulerWait *asw = new CActiveSchedulerWait;
|
||||
CleanupStack::PushL(asw);
|
||||
|
||||
MyTask *task = MyTask::NewL(asw);
|
||||
task->Start();
|
||||
app_main();
|
||||
|
||||
asw->Start();
|
||||
|
||||
delete task;
|
||||
|
||||
CleanupStack::Pop(asw);
|
||||
delete asw;
|
||||
|
||||
CActiveScheduler::Install(NULL);
|
||||
CleanupStack::Pop(scheduler);
|
||||
delete scheduler;
|
||||
|
@ -142,13 +68,13 @@ GLDEF_C TInt E32Main()
|
|||
|
||||
TRAPD(startError, DoStartL());
|
||||
|
||||
console->Printf(_L("[press any key to close]\n"));
|
||||
console->Getch();
|
||||
|
||||
//console->Printf(_L("[press any key to close]\n"));
|
||||
//console->Getch();
|
||||
|
||||
delete console;
|
||||
delete cleanup;
|
||||
|
||||
CloseSTDLIB();
|
||||
CloseSTDLIB();
|
||||
|
||||
// Mark end of heap usage, detect memory leaks
|
||||
__UHEAP_MARKEND;
|
||||
|
|
Loading…
Reference in New Issue