Index: pjproject/trunk/pjmedia/include/pjmedia/errno.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 318)
+++ pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 319)
@@ -31,4 +31,15 @@
 
 
+/*
+ * Mapping from PortAudio error codes to pjmedia error space.
+ */
+#define PJMEDIA_PORTAUDIO_ERRNO_START (PJMEDIA_ERRNO_START+PJ_ERRNO_SPACE_SIZE-1000)
+
+/*
+ * Convert PortAudio error code to PJMEDIA error code.
+ */
+#define PJMEDIA_ERRNO_FROM_PORTAUDIO(err)   (err+PJMEDIA_PORTAUDIO_ERRNO_START)
+
+
 /************************************************************
  * GENERIC/GENERAL PJMEDIA ERRORS
Index: pjproject/trunk/pjmedia/include/pjmedia/sound.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/sound.h	(revision 318)
+++ pjproject/trunk/pjmedia/include/pjmedia/sound.h	(revision 319)
@@ -49,17 +49,4 @@
     unsigned	default_samples_per_sec;/**< Default sampling rate.	    */
 } pj_snd_dev_info;
-
-/**
- * Sound device parameter, to be specified when calling #pj_snd_open_recorder
- * or #pj_snd_open_player.
- */
-typedef struct pj_snd_stream_info
-{
-    unsigned samples_per_sec;		/**< Sampling rate.		*/
-    unsigned bits_per_sample;		/**< No of bits per sample.	*/
-    unsigned samples_per_frame;		/**< No of samples per frame.	*/
-    unsigned bytes_per_frame;		/**< No of bytes per frame.	*/
-    unsigned frames_per_packet;		/**< No of frames per packet.	*/
-} pj_snd_stream_info;
 
 /** 
@@ -135,8 +122,12 @@
  * @return		Audio stream, or NULL if failed.
  */
-PJ_DECL(pj_snd_stream*) pj_snd_open_recorder(int index,
-					     const pj_snd_stream_info *param,
-					     pj_snd_rec_cb rec_cb,
-					     void *user_data);
+PJ_DECL(pj_status_t) pj_snd_open_recorder( int index,
+					   unsigned clock_rate,
+					   unsigned channel_count,
+					   unsigned samples_per_frame,
+					   unsigned bits_per_sample,
+					   pj_snd_rec_cb rec_cb,
+					   void *user_data,
+					   pj_snd_stream **p_snd_strm);
 
 /**
@@ -151,8 +142,12 @@
  * @return		Audio stream, or NULL if failed.
  */
-PJ_DECL(pj_snd_stream*) pj_snd_open_player(int index,
-					   const pj_snd_stream_info *param,
-					   pj_snd_play_cb play_cb,
-					   void *user_data);
+PJ_DECL(pj_status_t) pj_snd_open_player( int index,
+					 unsigned clock_rate,
+					 unsigned channel_count,
+					 unsigned samples_per_frame,
+					 unsigned bits_per_sample,
+					 pj_snd_play_cb play_cb,
+					 void *user_data,
+					 pj_snd_stream **p_snd_strm );
 
 /**
Index: pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 318)
+++ pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 319)
@@ -140,5 +140,4 @@
     unsigned		  samples_per_frame;	/**< Samples per frame.	    */
     unsigned		  bits_per_sample;	/**< Bits per sample.	    */
-    pj_snd_stream_info	  snd_info;	/**< Sound device parameter.	    */
 };
 
@@ -287,13 +286,4 @@
 
 
-    /* Init default sound device parameters. */
-    pj_memset(&conf->snd_info, 0, sizeof(conf->snd_info));
-    conf->snd_info.samples_per_sec = conf->clock_rate;
-    conf->snd_info.bits_per_sample = conf->bits_per_sample;
-    conf->snd_info.samples_per_frame = conf->samples_per_frame;
-    conf->snd_info.bytes_per_frame = conf->samples_per_frame * 
-			       conf->bits_per_sample / 8;
-    conf->snd_info.frames_per_packet = 1;
-    
 
     /* Create port */
@@ -389,20 +379,30 @@
 static pj_status_t create_sound( pjmedia_conf *conf )
 {
+    pj_status_t status;
+
     /* Open recorder only if mic is not disabled. */
     if ((conf->options & PJMEDIA_CONF_NO_MIC) == 0) {
-	conf->snd_rec = pj_snd_open_recorder(-1 ,&conf->snd_info, 
-					     &rec_cb, conf);
-	if (conf->snd_rec == NULL) {
-	    return -1;
+	status = pj_snd_open_recorder(-1, conf->clock_rate, 1, 
+				      conf->samples_per_frame,
+				      conf->bits_per_sample,
+				      &rec_cb, conf, &conf->snd_rec);
+	if (status != PJ_SUCCESS) {
+	    conf->snd_rec = NULL;
+	    return status;
 	}
     }
 
     /* Open player */
-    conf->snd_player = pj_snd_open_player(-1, &conf->snd_info, &play_cb, conf);
-    if (conf->snd_player == NULL) {
+    status = pj_snd_open_player(-1, conf->clock_rate, 1,
+			        conf->samples_per_frame,
+				conf->bits_per_sample, 
+				&play_cb, conf, &conf->snd_player);
+    if (status != PJ_SUCCESS) {
 	if (conf->snd_rec) {
 	    pj_snd_stream_close(conf->snd_rec);
+	    conf->snd_rec = NULL;
 	}
-	return -1;
+	conf->snd_player = NULL;
+	return status;
     }
 
Index: pjproject/trunk/pjmedia/src/pjmedia/errno.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 318)
+++ pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 319)
@@ -19,4 +19,5 @@
 #include <pjmedia/errno.h>
 #include <pj/string.h>
+#include <portaudio.h>
 
 
@@ -130,6 +131,21 @@
     pj_str_t errstr;
 
-    if (statcode >= PJMEDIA_ERRNO_START && 
-	statcode < PJMEDIA_ERRNO_START + PJ_ERRNO_SPACE_SIZE)
+    /* See if the error comes from PortAudio. */
+    if (statcode >= PJMEDIA_ERRNO_FROM_PORTAUDIO(paNotInitialized) &&
+	statcode <  PJMEDIA_ERRNO_FROM_PORTAUDIO(paNotInitialized + 10000))
+    {
+
+	int pa_err = statcode - PJMEDIA_ERRNO_FROM_PORTAUDIO(0);
+	pj_str_t msg;
+	
+	msg.ptr = (char*)Pa_GetErrorText(pa_err);
+	msg.slen = pj_ansi_strlen(msg.ptr);
+
+	errstr.ptr = buf;
+	pj_strncpy_with_null(&errstr, &msg, bufsize);
+	return errstr;
+
+    } else if (statcode >= PJMEDIA_ERRNO_START && 
+	       statcode < PJMEDIA_ERRNO_START + PJ_ERRNO_SPACE_SIZE)
     {
 	/* Find the error in the table.
Index: pjproject/trunk/pjmedia/src/pjmedia/pasound.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 318)
+++ pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 319)
@@ -18,7 +18,8 @@
  */
 #include <pjmedia/sound.h>
+#include <pjmedia/errno.h>
+#include <pj/log.h>
+#include <pj/os.h>
 #include <pj/string.h>
-#include <pj/os.h>
-#include <pj/log.h>
 #include <portaudio.h>
 
@@ -38,4 +39,5 @@
     int		     bytes_per_sample;
     pj_uint32_t	     samples_per_sec;
+    int		     channel_count;
     pj_uint32_t	     timestamp;
     pj_uint32_t	     underflow;
@@ -189,8 +191,12 @@
  * Open stream.
  */
-PJ_DEF(pj_snd_stream*) pj_snd_open_recorder( int index,
-					     const pj_snd_stream_info *param,
-					     pj_snd_rec_cb rec_cb,
-					     void *user_data)
+PJ_DEF(pj_status_t) pj_snd_open_recorder( int index,
+					  unsigned clock_rate,
+					  unsigned channel_count,
+					  unsigned samples_per_frame,
+					  unsigned bits_per_sample,
+					  pj_snd_rec_cb rec_cb,
+					  void *user_data,
+					  pj_snd_stream **p_snd_strm)
 {
     pj_pool_t *pool;
@@ -209,38 +215,41 @@
 	}
 	if (index == count) {
-	    PJ_LOG(2,(THIS_FILE, "Error: unable to find recorder device"));
-	    return NULL;
+	    /* No such device. */
+	    return PJ_ENOTFOUND;
 	}
     } else {
 	paDevInfo = Pa_GetDeviceInfo(index);
-	if (!paDevInfo)
-	    return NULL;
-    }
-
-    if (param->bits_per_sample == 8)
+	if (!paDevInfo) {
+	    /* Assumed it is "No such device" error. */
+	    return PJ_ENOTFOUND;
+	}
+    }
+
+    if (bits_per_sample == 8)
 	sampleFormat = paUInt8;
-    else if (param->bits_per_sample == 16)
+    else if (bits_per_sample == 16)
 	sampleFormat = paInt16;
-    else if (param->bits_per_sample == 32)
+    else if (bits_per_sample == 32)
 	sampleFormat = paInt32;
     else
-	return NULL;
+	return PJ_ENOTSUP;
     
     pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);
     if (!pool)
-	return NULL;
-
-    stream = pj_pool_calloc(pool, 1, sizeof(*stream));
+	return PJ_ENOMEM;
+
+    stream = pj_pool_zalloc(pool, sizeof(*stream));
     stream->pool = pool;
-    stream->name = pj_str("recorder");
+    stream->name = pj_str("snd-rec");
     stream->user_data = user_data;
     stream->dev_index = index;
-    stream->samples_per_sec = param->samples_per_frame;
-    stream->bytes_per_sample = param->bits_per_sample / 8;
+    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;
 
     pj_memset(&inputParam, 0, sizeof(inputParam));
     inputParam.device = index;
-    inputParam.channelCount = 1;
+    inputParam.channelCount = channel_count;
     inputParam.hostApiSpecificStreamInfo = NULL;
     inputParam.sampleFormat = sampleFormat;
@@ -248,29 +257,31 @@
 
     err = Pa_OpenStream( &stream->stream, &inputParam, NULL,
-			 param->samples_per_sec, 
-			 param->samples_per_frame * param->frames_per_packet, 
-			 0,
-			 &PaRecorderCallback, stream );
+			 clock_rate, samples_per_frame, 
+			 0, &PaRecorderCallback, stream );
     if (err != paNoError) {
 	pj_pool_release(pool);
-	PJ_LOG(2,(THIS_FILE, "Error opening player: %s", Pa_GetErrorText(err)));
-	return NULL;
+	return PJMEDIA_ERRNO_FROM_PORTAUDIO(err);
     }
 
     PJ_LOG(5,(THIS_FILE, "%s opening device %s for recording, sample rate=%d, "
+			 "channel count=%d, "
 			 "%d bits per sample, %d samples per buffer",
 			 (err==0 ? "Success" : "Error"),
-			 paDevInfo->name, param->samples_per_sec, 
-			 param->bits_per_sample,
-			 param->samples_per_frame * param->frames_per_packet));
-
-    return stream;
-}
-
-
-PJ_DEF(pj_snd_stream*) pj_snd_open_player(int index,
-					   const pj_snd_stream_info *param,
-					   pj_snd_play_cb play_cb,
-					   void *user_data)
+			 paDevInfo->name, clock_rate, channel_count,
+			 bits_per_sample, samples_per_frame));
+
+    *p_snd_strm = stream;
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_snd_open_player( int index,
+					unsigned clock_rate,
+					unsigned channel_count,
+					unsigned samples_per_frame,
+					unsigned bits_per_sample,
+					pj_snd_play_cb play_cb,
+					void *user_data,
+					pj_snd_stream **p_snd_strm)
 {
     pj_pool_t *pool;
@@ -289,25 +300,27 @@
 	}
 	if (index == count) {
-	    PJ_LOG(2,(THIS_FILE, "Error: unable to find player device"));
-	    return NULL;
+	    /* No such device. */
+	    return PJ_ENOTFOUND;
 	}
     } else {
 	paDevInfo = Pa_GetDeviceInfo(index);
-	if (!paDevInfo)
-	    return NULL;
-    }
-
-    if (param->bits_per_sample == 8)
+	if (!paDevInfo) {
+	    /* Assumed it is "No such device" error. */
+	    return PJ_ENOTFOUND;
+	}
+    }
+
+    if (bits_per_sample == 8)
 	sampleFormat = paUInt8;
-    else if (param->bits_per_sample == 16)
+    else if (bits_per_sample == 16)
 	sampleFormat = paInt16;
-    else if (param->bits_per_sample == 32)
+    else if (bits_per_sample == 32)
 	sampleFormat = paInt32;
     else
-	return NULL;
+	return PJ_ENOTSUP;
     
     pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);
     if (!pool)
-	return NULL;
+	return PJ_ENOMEM;
 
     stream = pj_pool_calloc(pool, 1, sizeof(*stream));
@@ -315,6 +328,7 @@
     stream->name = pj_str("player");
     stream->user_data = user_data;
-    stream->samples_per_sec = param->samples_per_frame;
-    stream->bytes_per_sample = param->bits_per_sample / 8;
+    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;
@@ -322,5 +336,5 @@
     pj_memset(&outputParam, 0, sizeof(outputParam));
     outputParam.device = index;
-    outputParam.channelCount = 1;
+    outputParam.channelCount = channel_count;
     outputParam.hostApiSpecificStreamInfo = NULL;
     outputParam.sampleFormat = sampleFormat;
@@ -328,22 +342,21 @@
 
     err = Pa_OpenStream( &stream->stream, NULL, &outputParam,
-			 param->samples_per_sec, 
-			 param->samples_per_frame * param->frames_per_packet, 
-			 0,
-			 &PaPlayerCallback, stream );
+			 clock_rate,  samples_per_frame, 
+			 0, &PaPlayerCallback, stream );
     if (err != paNoError) {
 	pj_pool_release(pool);
-	PJ_LOG(2,(THIS_FILE, "Error opening player: %s", Pa_GetErrorText(err)));
-	return NULL;
+	return PJMEDIA_ERRNO_FROM_PORTAUDIO(err);
     }
 
     PJ_LOG(5,(THIS_FILE, "%s opening device %s for playing, sample rate=%d, "
+			 "channel count=%d, "
 			 "%d bits per sample, %d samples per buffer",
 			 (err==0 ? "Success" : "Error"),
-			 paDevInfo->name, param->samples_per_sec, 
-		 	 param->bits_per_sample,
-			 param->samples_per_frame * param->frames_per_packet));
-
-    return stream;
+			 paDevInfo->name, clock_rate, channel_count,
+		 	 bits_per_sample, samples_per_frame));
+
+    *p_snd_strm = stream;
+
+    return PJ_SUCCESS;
 }
 
Index: pjproject/trunk/pjmedia/src/pjmedia/portaudio/portaudio.h
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/portaudio/portaudio.h	(revision 318)
+++ pjproject/trunk/pjmedia/src/pjmedia/portaudio/portaudio.h	(revision 319)
@@ -65,5 +65,5 @@
     paNoError = 0,
 
-    paNotInitialized = -10000,
+    paNotInitialized = 1,   /* blp: changed from -10000 */
     paUnanticipatedHostError,
     paInvalidChannelCount,
Index: pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 318)
+++ pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 319)
@@ -54,6 +54,4 @@
     unsigned		    pt;		    /**< Payload type.		    */
     pj_bool_t		    paused;	    /**< Paused?.		    */
-    pj_snd_stream_info	    snd_info;	    /**< Sound stream param.	    */
-    //pj_snd_stream	   *snd_stream;	    /**< Sound stream.		    */
     unsigned		    in_pkt_size;    /**< Size of input buffer.	    */
     void		   *in_pkt;	    /**< Input buffer.		    */
@@ -279,5 +277,5 @@
 
     /* Number of samples in the frame */
-    ts_len = frame->size / (channel->snd_info.bits_per_sample / 8);
+    ts_len = frame->size / 2;
 
     /* Init frame_out buffer. */
@@ -565,22 +563,4 @@
 
 /*
- * Create sound stream parameter from codec attributes.
- */
-static void init_snd_param( pj_snd_stream_info *snd_param,
-			    const pjmedia_codec_param *codec_param)
-{
-    pj_memset(snd_param, 0, sizeof(*snd_param));
-
-    snd_param->bits_per_sample	 = codec_param->pcm_bits_per_sample;
-    snd_param->bytes_per_frame   = 2;
-    snd_param->frames_per_packet = codec_param->sample_rate * 
-				   codec_param->ptime / 
-				   1000;
-    snd_param->samples_per_frame = 1;
-    snd_param->samples_per_sec   = codec_param->sample_rate;
-}
-
-
-/*
  * Create media channel.
  */
@@ -643,20 +623,4 @@
     if (status != PJ_SUCCESS)
 	return status;
-
-    /* Create and initialize sound device */
-
-    init_snd_param(&channel->snd_info, codec_param);
-
-    /*
-    if (dir == PJMEDIA_DIR_ENCODING)
-	channel->snd_stream = pj_snd_open_recorder(-1, &channel->snd_info, 
-						   &rec_callback, channel);
-    else
-	channel->snd_stream = pj_snd_open_player(-1, &channel->snd_info, 
-						 &play_callback, channel);
-
-    if (!channel->snd_stream)
-	return -1;
-    */
 
     /* Done. */
