Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/bb10_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/bb10_dev.c	(revision 4479)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/bb10_dev.c	(revision 4480)
@@ -53,7 +53,5 @@
 #define THIS_FILE 			"bb10_dev.c"
 #define BB10_DEVICE_NAME 		"plughw:%d,%d"
-/* Double these for 16khz sampling */
-#define PREFERRED_FRAME_SIZE 320
-#define VOIP_SAMPLE_RATE 8000
+
 
 /* Set to 1 to enable tracing */
@@ -434,8 +432,5 @@
 {
     struct bb10_stream* stream = (struct bb10_stream *) arg;
-    /* Handle from bb10_open_playback */
-    /* Will be 640 */
     int size                   	= stream->pb_buf_size;
-    /* 160 frames for 20ms */
     unsigned long nframes	= stream->pb_frames;
     void *user_data            	= stream->user_data;
@@ -683,4 +678,20 @@
 }
 
+static int32_t get_alsa_pcm_fmt(const pjmedia_aud_param *param)
+{
+    switch (param->bits_per_sample) {
+    case 8:
+	return SND_PCM_SFMT_S8;
+    case 16:
+	return SND_PCM_SFMT_S16_LE;
+    case 24:
+	return SND_PCM_SFMT_S24_LE;
+    case 32:
+	return SND_PCM_SFMT_S32_LE;
+    default:
+	PJ_ASSERT_RETURN(!"Unsupported bits_per_frame", SND_PCM_SFMT_S16_LE);
+    }
+}
+
 static pj_status_t bb10_open_playback (struct bb10_stream *stream,
                                        const pjmedia_aud_param *param)
@@ -697,4 +708,6 @@
         return PJMEDIA_EAUD_INVDEV;
     }
+
+    PJ_ASSERT_RETURN(param->bits_per_sample == 16, PJMEDIA_EAUD_SAMPFORMAT);
 
     /* Use the bb10 audio manager API to open as opposed to QNX core audio
@@ -727,5 +740,4 @@
     }
 
-    /* TODO PJ_ZERO */
     memset (&pi, 0, sizeof (pi));
     pi.channel = SND_PCM_CHANNEL_PLAYBACK;
@@ -742,16 +754,12 @@
     pp.start_mode = SND_PCM_START_DATA;
     pp.stop_mode = SND_PCM_STOP_ROLLOVER;
-    /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */
-    pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2;
+    pp.buf.block.frag_size = param->samples_per_frame * param->bits_per_sample / 8;
     /* RIM recommends maximum of 3 */
     pp.buf.block.frags_max = 3;
     pp.buf.block.frags_min = 1;
     pp.format.interleave = 1;
-    /* HARD CODE for the time being PJMEDIA expects 16khz */
-    PJ_TODO(REMOVE_SAMPLE_RATE_HARD_CODE);
-    pj_assert(param->clock_rate == VOIP_SAMPLE_RATE * 2);
-    pp.format.rate = VOIP_SAMPLE_RATE*2;
-    pp.format.voices = 1;
-    pp.format.format = SND_PCM_SFMT_S16_LE;
+    pp.format.rate = param->clock_rate;
+    pp.format.voices = param->channel_count;
+    pp.format.format = get_alsa_pcm_fmt(param);
 
     /* Make the calls as per the wave sample */
@@ -778,15 +786,15 @@
     /* Set the sound device buffer size and latency */
     if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) {
-        tmp_buf_size = (rate / 1000) * param->output_latency_ms;
+        tmp_buf_size = rate * param->output_latency_ms / 1000;
     } else {
-	tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
+	tmp_buf_size = rate * PJMEDIA_SND_DEFAULT_PLAY_LATENCY / 1000;
     }
     /* Set period size to samples_per_frame frames. */
-    stream->pb_frames = param->samples_per_frame;
-    stream->param.output_latency_ms = tmp_buf_size / (rate / 1000);
+    stream->pb_frames = param->samples_per_frame / param->channel_count;
+    stream->param.output_latency_ms = tmp_buf_size * 1000 / rate;
 
     /* Set our buffer */
     stream->pb_buf_size = stream->pb_frames * param->channel_count *
-                          (param->bits_per_sample/8);
+                          param->bits_per_sample / 8;
     stream->pb_buf = (char *) pj_pool_alloc(stream->pool, stream->pb_buf_size);
 
@@ -811,4 +819,6 @@
     if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt)
         return PJMEDIA_EAUD_INVDEV;
+
+    PJ_ASSERT_RETURN(param->bits_per_sample == 16, PJMEDIA_EAUD_SAMPFORMAT);
 
     if ((ret=audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT,
@@ -854,16 +864,12 @@
     /* Auto-recover from errors */
     pp.stop_mode = SND_PCM_STOP_ROLLOVER;
-    /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */
-    pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2;
+    pp.buf.block.frag_size = param->samples_per_frame * param->bits_per_sample / 8;
     /* From January 2013 gold OS release. RIM recommend these for capture */
     pp.buf.block.frags_max = 1;
     pp.buf.block.frags_min = 1;
     pp.format.interleave = 1;
-    /* HARD CODE for the time being PJMEDIA expects 16khz */
-    PJ_TODO(REMOVE_SAMPLE_RATE_HARD_CODE);
-    pj_assert(param->clock_rate == VOIP_SAMPLE_RATE * 2);
-    pp.format.rate = VOIP_SAMPLE_RATE*2;
-    pp.format.voices = 1;
-    pp.format.format = SND_PCM_SFMT_S16_LE;
+    pp.format.rate = param->clock_rate;
+    pp.format.voices = param->channel_count;
+    pp.format.format = get_alsa_pcm_fmt(param);
 
     /* make the request */
@@ -898,14 +904,14 @@
     /* Set the sound device buffer size and latency */
     if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) {
-        tmp_buf_size = (rate / 1000) * param->input_latency_ms;
+        tmp_buf_size = rate * param->input_latency_ms / 1000;
     } else {
-        tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_REC_LATENCY;
-    }
-
-    stream->param.input_latency_ms = tmp_buf_size / (rate / 1000);
+        tmp_buf_size = rate * PJMEDIA_SND_DEFAULT_REC_LATENCY / 1000;
+    }
+
+    stream->param.input_latency_ms = tmp_buf_size * 1000 / rate;
 
     /* Set our buffer */
     stream->ca_buf_size = stream->ca_frames * param->channel_count *
-			  (param->bits_per_sample/8);
+			  param->bits_per_sample / 8;
     stream->ca_buf = (char *)pj_pool_alloc (stream->pool, stream->ca_buf_size);
 
@@ -966,11 +972,19 @@
     }
 
-    /* Part of the play functionality but the RIM/Truphone loopback sample
-     * initialializes after the play and capture
-     * "false" is default/earpiece for output
-     */
-    status = bb10_initialize_playback_ctrl(stream,false);
-    if (status != PJ_SUCCESS) {
-    	return PJMEDIA_EAUD_SYSERR;
+    /* Set the audio routing ONLY if app explicitly asks one */
+    if ((param->dir & PJMEDIA_DIR_PLAYBACK) &&
+	(param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE))
+    {
+	status = bb10_stream_set_cap(&stream->base,
+				     PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
+                                     &param->output_route);
+	if (status != PJ_SUCCESS) {
+	    TRACE_((THIS_FILE, "Error setting output route"));
+	    bb10_stream_destroy(&stream->base);
+	    return status;
+	}
+    } else {
+	/* Legacy behavior: if none specified, set to speaker */
+	status = bb10_initialize_playback_ctrl(stream, false);
     }
 
