summaryrefslogtreecommitdiff
path: root/pjmedia/src
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-03-23 13:15:59 +0000
committerBenny Prijono <bennylp@teluu.com>2006-03-23 13:15:59 +0000
commit5b2cb511256b572db42309e52005d59a91f4768d (patch)
treebb74203a9cee94ab49583f42d0493c9c92089875 /pjmedia/src
parenta6ab2ff2d65de77f7953aaab59f9d47c3de52e7a (diff)
Changed sound device framework to allow opening bidirectional streams from one device
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@352 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia/src')
-rw-r--r--pjmedia/src/pjmedia/conference.c75
-rw-r--r--pjmedia/src/pjmedia/nullsound.c29
-rw-r--r--pjmedia/src/pjmedia/pasound.c231
-rw-r--r--pjmedia/src/pjmedia/sound_port.c103
4 files changed, 332 insertions, 106 deletions
diff --git a/pjmedia/src/pjmedia/conference.c b/pjmedia/src/pjmedia/conference.c
index c6cb1278..fad562c7 100644
--- a/pjmedia/src/pjmedia/conference.c
+++ b/pjmedia/src/pjmedia/conference.c
@@ -158,8 +158,7 @@ struct pjmedia_conf
unsigned max_ports; /**< Maximum ports. */
unsigned port_cnt; /**< Current number of ports. */
unsigned connect_cnt; /**< Total number of connections */
- pjmedia_snd_port *snd_rec; /**< Sound recorder stream. */
- pjmedia_snd_port *snd_player; /**< Sound player stream. */
+ pjmedia_snd_port *snd_dev_port; /**< Sound device port. */
pjmedia_port *master_port; /**< Port zero's port. */
pj_mutex_t *mutex; /**< Conference mutex. */
struct conf_port **ports; /**< Array of ports. */
@@ -342,40 +341,33 @@ static pj_status_t create_sound_port( pj_pool_t *pool,
conf->port_cnt++;
- /* Create sound devices: */
+ /* Create sound device port: */
- /* Create recorder only if mic is not disabled. */
- if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0 &&
- (conf->options & PJMEDIA_CONF_NO_MIC) == 0)
- {
- status = pjmedia_snd_port_create_rec( pool, -1, conf->clock_rate,
+ if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) {
+
+ /*
+ * If capture is disabled then create player only port.
+ * Otherwise create bidirectional sound device port.
+ */
+ if (conf->options & PJMEDIA_CONF_NO_MIC) {
+ status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate,
+ conf->channel_count,
+ conf->samples_per_frame,
+ conf->bits_per_sample,
+ 0, /* options */
+ &conf->snd_dev_port);
+
+ } else {
+ status = pjmedia_snd_port_create( pool, -1, -1, conf->clock_rate,
conf->channel_count,
conf->samples_per_frame,
conf->bits_per_sample,
0, /* Options */
- &conf->snd_rec);
- if (status != PJ_SUCCESS) {
- conf->snd_rec = NULL;
- return status;
+ &conf->snd_dev_port);
}
- }
- /* Create player device */
- if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) {
- status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate,
- conf->channel_count,
- conf->samples_per_frame,
- conf->bits_per_sample,
- 0, /* options */
- &conf->snd_player);
- if (status != PJ_SUCCESS) {
- if (conf->snd_rec) {
- pjmedia_snd_port_destroy(conf->snd_rec);
- conf->snd_rec = NULL;
- }
- conf->snd_player = NULL;
+ if (status != PJ_SUCCESS)
return status;
- }
}
@@ -433,7 +425,7 @@ PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
conf->master_port->info.channel_count = channel_count;
conf->master_port->info.encoding_name = pj_str("pcm");
conf->master_port->info.has_info = 1;
- conf->master_port->info.name = pj_str("master port");
+ conf->master_port->info.name = pj_str("sound-dev");
conf->master_port->info.need_info = 0;
conf->master_port->info.pt = 0xFF;
conf->master_port->info.sample_rate = clock_rate;
@@ -464,8 +456,8 @@ PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
/* If sound device was created, connect sound device to the
* master port.
*/
- if (conf->snd_player) {
- status = pjmedia_snd_port_connect( conf->snd_player,
+ if (conf->snd_dev_port) {
+ status = pjmedia_snd_port_connect( conf->snd_dev_port,
conf->master_port );
if (status != PJ_SUCCESS) {
pjmedia_conf_destroy(conf);
@@ -473,15 +465,6 @@ PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
}
}
- if (conf->snd_rec) {
- status = pjmedia_snd_port_connect( conf->snd_rec,
- conf->master_port);
- if (status != PJ_SUCCESS) {
- pjmedia_conf_destroy(conf);
- return status;
- }
- }
-
/* Done */
@@ -519,14 +502,10 @@ PJ_DEF(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf )
{
PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL);
- /* Destroy sound devices. */
- if (conf->snd_rec) {
- pjmedia_snd_port_destroy(conf->snd_rec);
- conf->snd_rec = NULL;
- }
- if (conf->snd_player) {
- pjmedia_snd_port_destroy(conf->snd_player);
- conf->snd_player = NULL;
+ /* Destroy sound device port. */
+ if (conf->snd_dev_port) {
+ pjmedia_snd_port_destroy(conf->snd_dev_port);
+ conf->snd_dev_port = NULL;
}
/* Destroy mutex */
diff --git a/pjmedia/src/pjmedia/nullsound.c b/pjmedia/src/pjmedia/nullsound.c
index 9d454c08..e60cfa31 100644
--- a/pjmedia/src/pjmedia/nullsound.c
+++ b/pjmedia/src/pjmedia/nullsound.c
@@ -47,7 +47,7 @@ PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
return &null_info;
}
-PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index,
+PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
@@ -91,6 +91,33 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
return PJ_SUCCESS;
}
+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)
+{
+ PJ_UNUSED_ARG(rec_id);
+ PJ_UNUSED_ARG(play_id);
+ PJ_UNUSED_ARG(clock_rate);
+ PJ_UNUSED_ARG(channel_count);
+ PJ_UNUSED_ARG(samples_per_frame);
+ PJ_UNUSED_ARG(bits_per_sample);
+ PJ_UNUSED_ARG(rec_cb);
+ PJ_UNUSED_ARG(play_cb);
+ PJ_UNUSED_ARG(user_data);
+
+ *p_snd_strm = (void*)1;
+
+ return PJ_SUCCESS;
+}
+
+
PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
{
PJ_UNUSED_ARG(stream);
diff --git a/pjmedia/src/pjmedia/pasound.c b/pjmedia/src/pjmedia/pasound.c
index cb36b927..44bac29b 100644
--- a/pjmedia/src/pjmedia/pasound.c
+++ b/pjmedia/src/pjmedia/pasound.c
@@ -32,26 +32,35 @@ static struct snd_mgr
pj_pool_factory *factory;
} snd_mgr;
+/*
+ * Sound stream descriptor.
+ * This struct may be used for both unidirectional or bidirectional sound
+ * streams.
+ */
struct pjmedia_snd_stream
{
- pj_pool_t *pool;
- pj_str_t name;
- PaStream *stream;
- int dev_index;
- int bytes_per_sample;
- pj_uint32_t samples_per_sec;
- int channel_count;
- pj_uint32_t timestamp;
- pj_uint32_t underflow;
- pj_uint32_t overflow;
- void *user_data;
- pjmedia_snd_rec_cb rec_cb;
- pjmedia_snd_play_cb play_cb;
- pj_bool_t quit_flag;
- pj_bool_t thread_has_exited;
- pj_bool_t thread_initialized;
- pj_thread_desc thread_desc;
- pj_thread_t *thread;
+ pj_pool_t *pool;
+ pj_str_t name;
+ pjmedia_dir dir;
+ int bytes_per_sample;
+ pj_uint32_t samples_per_sec;
+ int channel_count;
+
+ PaStream *stream;
+ void *user_data;
+ pjmedia_snd_rec_cb rec_cb;
+ pjmedia_snd_play_cb play_cb;
+
+ pj_uint32_t timestamp;
+ pj_uint32_t underflow;
+ pj_uint32_t overflow;
+
+ pj_bool_t quit_flag;
+
+ pj_bool_t thread_exited;
+ pj_bool_t thread_initialized;
+ pj_thread_desc thread_desc;
+ pj_thread_t *thread;
};
@@ -72,7 +81,8 @@ static int PaRecorderCallback(const void *input,
goto on_break;
if (stream->thread_initialized == 0) {
- status = pj_thread_register("pa_rec", stream->thread_desc, &stream->thread);
+ status = pj_thread_register("pa_rec", stream->thread_desc,
+ &stream->thread);
stream->thread_initialized = 1;
PJ_LOG(5,(THIS_FILE, "Recorder thread started"));
}
@@ -92,7 +102,7 @@ static int PaRecorderCallback(const void *input,
return paContinue;
on_break:
- stream->thread_has_exited = 1;
+ stream->thread_exited = 1;
return paAbort;
}
@@ -115,7 +125,8 @@ static int PaPlayerCallback( const void *input,
goto on_break;
if (stream->thread_initialized == 0) {
- status = pj_thread_register("pa_rec", stream->thread_desc, &stream->thread);
+ status = pj_thread_register("portaudio", stream->thread_desc,
+ &stream->thread);
stream->thread_initialized = 1;
PJ_LOG(5,(THIS_FILE, "Player thread started"));
}
@@ -134,11 +145,31 @@ static int PaPlayerCallback( const void *input,
return paContinue;
on_break:
- stream->thread_has_exited = 1;
+ stream->thread_exited = 1;
return paAbort;
}
+static int PaRecorderPlayerCallback( const void *input,
+ void *output,
+ unsigned long frameCount,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData )
+{
+ int rc;
+
+ rc = PaRecorderCallback(input, output, frameCount, timeInfo,
+ statusFlags, userData);
+ if (rc != paContinue)
+ return rc;
+
+ rc = PaPlayerCallback(input, output, frameCount, timeInfo,
+ statusFlags, userData);
+ return rc;
+}
+
+
/*
* Init sound library.
*/
@@ -194,7 +225,7 @@ PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index)
/*
* Open stream.
*/
-PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index,
+PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
@@ -215,7 +246,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index,
int count = Pa_GetDeviceCount();
for (index=0; index<count; ++index) {
paDevInfo = Pa_GetDeviceInfo(index);
- if (paDevInfo->maxInputChannels > 0)
+ if (paDevInfo->maxInputChannels >= (int)channel_count)
break;
}
if (index == count) {
@@ -245,9 +276,9 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index,
stream = pj_pool_zalloc(pool, sizeof(*stream));
stream->pool = pool;
- stream->name = pj_str("snd-rec");
+ pj_strdup2_with_null(pool, &stream->name, paDevInfo->name);
+ stream->dir = PJMEDIA_DIR_CAPTURE;
stream->user_data = user_data;
- stream->dev_index = index;
stream->samples_per_sec = samples_per_frame;
stream->bytes_per_sample = bits_per_sample / 8;
stream->channel_count = channel_count;
@@ -304,7 +335,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
int count = Pa_GetDeviceCount();
for (index=0; index<count; ++index) {
paDevInfo = Pa_GetDeviceInfo(index);
- if (paDevInfo->maxOutputChannels > 0)
+ if (paDevInfo->maxOutputChannels >= (int)channel_count)
break;
}
if (index == count) {
@@ -334,12 +365,12 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
stream = pj_pool_calloc(pool, 1, sizeof(*stream));
stream->pool = pool;
- stream->name = pj_str("player");
+ pj_strdup2_with_null(pool, &stream->name, paDevInfo->name);
+ stream->dir = stream->dir = PJMEDIA_DIR_PLAYBACK;
stream->user_data = user_data;
stream->samples_per_sec = samples_per_frame;
stream->bytes_per_sample = bits_per_sample / 8;
stream->channel_count = channel_count;
- stream->dev_index = index;
stream->play_cb = play_cb;
pj_memset(&outputParam, 0, sizeof(outputParam));
@@ -374,6 +405,131 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,
/*
+ * Open both player and recorder.
+ */
+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)
+{
+ pj_pool_t *pool;
+ pjmedia_snd_stream *stream;
+ PaStreamParameters inputParam;
+ PaStreamParameters outputParam;
+ int sampleFormat;
+ const PaDeviceInfo *paRecDevInfo = NULL;
+ const PaDeviceInfo *paPlayDevInfo = NULL;
+ unsigned paFrames;
+ PaError err;
+
+ if (rec_id == -1) {
+ int count = Pa_GetDeviceCount();
+ for (rec_id=0; rec_id<count; ++rec_id) {
+ paRecDevInfo = Pa_GetDeviceInfo(rec_id);
+ if (paRecDevInfo->maxInputChannels >= (int)channel_count)
+ break;
+ }
+ if (rec_id == count) {
+ /* No such device. */
+ return PJMEDIA_ENOSNDREC;
+ }
+ } else {
+ paRecDevInfo = Pa_GetDeviceInfo(rec_id);
+ if (!paRecDevInfo) {
+ /* Assumed it is "No such device" error. */
+ return PJMEDIA_ESNDINDEVID;
+ }
+ }
+
+ if (play_id == -1) {
+ int count = Pa_GetDeviceCount();
+ for (play_id=0; play_id<count; ++play_id) {
+ paPlayDevInfo = Pa_GetDeviceInfo(play_id);
+ if (paPlayDevInfo->maxOutputChannels >= (int)channel_count)
+ break;
+ }
+ if (play_id == count) {
+ /* No such device. */
+ return PJMEDIA_ENOSNDPLAY;
+ }
+ } else {
+ paPlayDevInfo = Pa_GetDeviceInfo(play_id);
+ if (!paPlayDevInfo) {
+ /* Assumed it is "No such device" error. */
+ return PJMEDIA_ESNDINDEVID;
+ }
+ }
+
+ if (bits_per_sample == 8)
+ sampleFormat = paUInt8;
+ else if (bits_per_sample == 16)
+ sampleFormat = paInt16;
+ else if (bits_per_sample == 32)
+ sampleFormat = paInt32;
+ else
+ return PJMEDIA_ESNDINSAMPLEFMT;
+
+ pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);
+ if (!pool)
+ return PJ_ENOMEM;
+
+ stream = pj_pool_zalloc(pool, sizeof(*stream));
+ stream->pool = pool;
+ pj_strdup2_with_null(pool, &stream->name, paRecDevInfo->name);
+ stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+ stream->user_data = user_data;
+ stream->samples_per_sec = samples_per_frame;
+ stream->bytes_per_sample = bits_per_sample / 8;
+ stream->channel_count = channel_count;
+ stream->rec_cb = rec_cb;
+ stream->play_cb = play_cb;
+
+ pj_memset(&inputParam, 0, sizeof(inputParam));
+ inputParam.device = rec_id;
+ inputParam.channelCount = channel_count;
+ inputParam.hostApiSpecificStreamInfo = NULL;
+ inputParam.sampleFormat = sampleFormat;
+ inputParam.suggestedLatency = paRecDevInfo->defaultLowInputLatency;
+
+ pj_memset(&outputParam, 0, sizeof(outputParam));
+ outputParam.device = play_id;
+ outputParam.channelCount = channel_count;
+ outputParam.hostApiSpecificStreamInfo = NULL;
+ outputParam.sampleFormat = sampleFormat;
+ outputParam.suggestedLatency = paPlayDevInfo->defaultLowInputLatency;
+
+ /* Frames in PortAudio is number of samples in a single channel */
+ paFrames = samples_per_frame / channel_count;
+
+ err = Pa_OpenStream( &stream->stream, &inputParam, &outputParam,
+ clock_rate, paFrames,
+ paClipOff, &PaRecorderPlayerCallback, stream );
+ if (err != paNoError) {
+ pj_pool_release(pool);
+ return PJMEDIA_ERRNO_FROM_PORTAUDIO(err);
+ }
+
+ PJ_LOG(5,(THIS_FILE, "%s opening device %s/%s for recording and playback, "
+ "sample rate=%d, channel count=%d, "
+ "%d bits per sample, %d samples per buffer",
+ (err==0 ? "Success" : "Error"),
+ paRecDevInfo->name, paPlayDevInfo->name,
+ clock_rate, channel_count,
+ bits_per_sample, samples_per_frame));
+
+ *p_snd_strm = stream;
+
+
+ return PJ_SUCCESS;
+}
+
+/*
* Start stream.
*/
PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream)
@@ -397,7 +553,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream)
int i, err;
stream->quit_flag = 1;
- for (i=0; !stream->thread_has_exited && i<100; ++i)
+ for (i=0; !stream->thread_exited && i<100; ++i)
pj_thread_sleep(10);
pj_thread_sleep(1);
@@ -417,18 +573,15 @@ 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)
{
int i, err;
- const PaDeviceInfo *paDevInfo;
stream->quit_flag = 1;
- for (i=0; !stream->thread_has_exited && i<100; ++i)
- pj_thread_sleep(10);
-
- pj_thread_sleep(1);
-
- paDevInfo = Pa_GetDeviceInfo(stream->dev_index);
+ for (i=0; !stream->thread_exited && i<100; ++i) {
+ pj_thread_sleep(1);
+ }
- PJ_LOG(5,(THIS_FILE, "Closing %s: %lu underflow, %lu overflow",
- paDevInfo->name,
+ PJ_LOG(5,(THIS_FILE, "Closing %.*s: %lu underflow, %lu overflow",
+ (int)stream->name.slen,
+ stream->name.ptr,
stream->underflow, stream->overflow));
err = Pa_CloseStream(stream->stream);
diff --git a/pjmedia/src/pjmedia/sound_port.c b/pjmedia/src/pjmedia/sound_port.c
index f3e285a2..aca74e16 100644
--- a/pjmedia/src/pjmedia/sound_port.c
+++ b/pjmedia/src/pjmedia/sound_port.c
@@ -23,7 +23,8 @@
struct pjmedia_snd_port
{
- int snd_index;
+ int rec_id;
+ int play_id;
pjmedia_snd_stream *snd_stream;
pjmedia_dir dir;
pjmedia_port *port;
@@ -123,17 +124,18 @@ static pj_status_t start_sound_device( pjmedia_snd_port *snd_port )
return PJ_SUCCESS;
/* Open sound stream. */
- if (snd_port->dir == PJMEDIA_DIR_ENCODING) {
- status = pjmedia_snd_open_recorder( snd_port->snd_index,
- snd_port->clock_rate,
- snd_port->channel_count,
- snd_port->samples_per_frame,
- snd_port->bits_per_sample,
- &rec_cb,
- snd_port,
- &snd_port->snd_stream);
- } else {
- status = pjmedia_snd_open_player( snd_port->snd_index,
+ if (snd_port->dir == PJMEDIA_DIR_CAPTURE) {
+ status = pjmedia_snd_open_rec( snd_port->rec_id,
+ snd_port->clock_rate,
+ snd_port->channel_count,
+ snd_port->samples_per_frame,
+ snd_port->bits_per_sample,
+ &rec_cb,
+ snd_port,
+ &snd_port->snd_stream);
+
+ } else if (snd_port->dir == PJMEDIA_DIR_PLAYBACK) {
+ status = pjmedia_snd_open_player( snd_port->play_id,
snd_port->clock_rate,
snd_port->channel_count,
snd_port->samples_per_frame,
@@ -141,6 +143,21 @@ static pj_status_t start_sound_device( pjmedia_snd_port *snd_port )
&play_cb,
snd_port,
&snd_port->snd_stream);
+
+ } else if (snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK) {
+ status = pjmedia_snd_open( snd_port->rec_id,
+ snd_port->play_id,
+ snd_port->clock_rate,
+ snd_port->channel_count,
+ snd_port->samples_per_frame,
+ snd_port->bits_per_sample,
+ &rec_cb,
+ &play_cb,
+ snd_port,
+ &snd_port->snd_stream);
+ } else {
+ pj_assert(!"Invalid dir");
+ status = PJ_EBUG;
}
if (status != PJ_SUCCESS)
@@ -176,10 +193,49 @@ static pj_status_t stop_sound_device( pjmedia_snd_port *snd_port )
/*
+ * Create bidirectional port.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_port_create( pj_pool_t *pool,
+ int rec_id,
+ int play_id,
+ unsigned clock_rate,
+ unsigned channel_count,
+ unsigned samples_per_frame,
+ unsigned bits_per_sample,
+ unsigned options,
+ pjmedia_snd_port **p_port)
+{
+ pjmedia_snd_port *snd_port;
+
+ PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
+ PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
+
+ snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port));
+ PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
+
+ snd_port->rec_id = rec_id;
+ snd_port->play_id = play_id;
+ snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+ snd_port->clock_rate = clock_rate;
+ snd_port->channel_count = channel_count;
+ snd_port->samples_per_frame = samples_per_frame;
+ snd_port->bits_per_sample = bits_per_sample;
+
+ *p_port = snd_port;
+
+ /* Start sound device immediately.
+ * If there's no port connected, the sound callback will return
+ * empty signal.
+ */
+ return start_sound_device( snd_port );
+
+}
+
+/*
* Create sound recorder port.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool,
- int index,
+ int dev_id,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
@@ -195,8 +251,8 @@ PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool,
snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port));
PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
- snd_port->snd_index = index;
- snd_port->dir = PJMEDIA_DIR_ENCODING;
+ snd_port->rec_id = dev_id;
+ snd_port->dir = PJMEDIA_DIR_CAPTURE;
snd_port->clock_rate = clock_rate;
snd_port->channel_count = channel_count;
snd_port->samples_per_frame = samples_per_frame;
@@ -216,7 +272,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool,
* Create sound player port.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_create_player( pj_pool_t *pool,
- int index,
+ int dev_id,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
@@ -232,8 +288,8 @@ PJ_DEF(pj_status_t) pjmedia_snd_port_create_player( pj_pool_t *pool,
snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port));
PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
- snd_port->snd_index = index;
- snd_port->dir = PJMEDIA_DIR_DECODING;
+ snd_port->play_id = dev_id;
+ snd_port->dir = PJMEDIA_DIR_PLAYBACK;
snd_port->clock_rate = clock_rate;
snd_port->channel_count = channel_count;
snd_port->samples_per_frame = samples_per_frame;
@@ -261,6 +317,17 @@ PJ_DEF(pj_status_t) pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port)
/*
+ * Retrieve the sound stream associated by this sound device port.
+ */
+PJ_DEF(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream(
+ pjmedia_snd_port *snd_port)
+{
+ PJ_ASSERT_RETURN(snd_port, NULL);
+ return snd_port->snd_stream;
+}
+
+
+/*
* Connect a port.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_connect( pjmedia_snd_port *snd_port,