Index: pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/wmme_dev.c
===================================================================
--- pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/wmme_dev.c	(revision 2489)
+++ pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/wmme_dev.c	(revision 2492)
@@ -48,5 +48,4 @@
 #define THIS_FILE			"wmme_dev.c"
 
-
 /* WMME device info */
 struct wmme_dev_info
@@ -81,5 +80,4 @@
     DWORD         dwBufIdx;
     DWORD         dwMaxBufIdx;
-    unsigned	  latency_ms;
     pj_timestamp  timestamp;
 };
@@ -89,8 +87,6 @@
 struct wmme_stream
 {
-    pjmedia_aud_stream	 base;
-    pjmedia_dir          dir;               /**< Sound direction.      */
-    int                  play_id;           /**< Playback dev id.      */
-    int                  rec_id;            /**< Recording dev id.     */
+    pjmedia_aud_stream	 base;		    /**< Base stream	       */
+    pjmedia_aud_param	 param;		    /**< Settings	       */
     pj_pool_t           *pool;              /**< Memory pool.          */
 
@@ -105,9 +101,5 @@
     pjmedia_format_id	 fmt_id;	    /**< Frame format	       */
     pj_uint8_t		 silence_char;	    /**< Silence pattern       */
-    unsigned             clock_rate;        /**< Clock rate.           */
     unsigned		 bytes_per_frame;   /**< Bytes per frame       */
-    unsigned             samples_per_frame; /**< Samples per frame.    */
-    unsigned             bits_per_sample;   /**< Bits per sample.      */
-    unsigned             channel_count;     /**< Channel count.        */
 
     pjmedia_frame_ext	*xfrm;		    /**< Extended frame buffer */
@@ -438,5 +430,6 @@
     param->samples_per_frame = di->info.default_samples_per_sec * 20 / 1000;
     param->bits_per_sample = 16;
-    param->flags = di->info.caps;
+    param->flags = PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |
+		   PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY;
     param->input_latency_ms = PJMEDIA_SND_DEFAULT_REC_LATENCY;
     param->output_latency_ms = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
@@ -498,5 +491,5 @@
 
     if (id == PJMEDIA_FORMAT_L16)
-	return "l16";
+	return "PCM";
     pj_memcpy(name, &id, 4);
     name[4] = '\0';
@@ -686,7 +679,7 @@
     eventCount = 0;
     events[eventCount++] = strm->thread_quit_event;
-    if (strm->dir & PJMEDIA_DIR_PLAYBACK)
+    if (strm->param.dir & PJMEDIA_DIR_PLAYBACK)
 	events[eventCount++] = strm->play_strm.hEvent;
-    if (strm->dir & PJMEDIA_DIR_CAPTURE)
+    if (strm->param.dir & PJMEDIA_DIR_CAPTURE)
 	events[eventCount++] = strm->rec_strm.hEvent;
 
@@ -696,5 +689,5 @@
      */
 #if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE != 0
-    if (strm->dir & PJMEDIA_DIR_PLAYBACK)
+    if (strm->param.dir & PJMEDIA_DIR_PLAYBACK)
 	CeSetThreadPriority(GetCurrentThread(), 153);
     else
@@ -834,6 +827,6 @@
 		if (++wmme_strm->dwBufIdx >= wmme_strm->dwMaxBufIdx)
 		    wmme_strm->dwBufIdx = 0;
-		wmme_strm->timestamp.u64 += strm->samples_per_frame / 
-					    strm->channel_count;
+		wmme_strm->timestamp.u64 += strm->param.samples_per_frame /
+					    strm->param.channel_count;
 	    }
 	}
@@ -914,7 +907,9 @@
 		    strm->xfrm->samples_cnt = 0;
 		    strm->xfrm->subframe_cnt = 0;
-		    pjmedia_frame_ext_append_subframe(strm->xfrm, buffer,
-						      strm->bytes_per_frame *8,
-						      strm->samples_per_frame);
+		    pjmedia_frame_ext_append_subframe(
+			strm->xfrm, buffer,
+			strm->bytes_per_frame *8,
+			strm->param.samples_per_frame
+		    );
 		}
 
@@ -938,6 +933,6 @@
 		if (++wmme_strm->dwBufIdx >= wmme_strm->dwMaxBufIdx)
 		    wmme_strm->dwBufIdx = 0;
-		wmme_strm->timestamp.u64 += strm->samples_per_frame / 
-					    strm->channel_count;
+		wmme_strm->timestamp.u64 += strm->param.samples_per_frame /
+					    strm->param.channel_count;
 	    }
 	}
@@ -982,7 +977,5 @@
 
     strm = PJ_POOL_ZALLOC_T(pool, struct wmme_stream);
-    strm->dir = param->dir;
-    strm->play_id = param->play_id;
-    strm->rec_id = param->rec_id;
+    pj_memcpy(&strm->param, param, sizeof(*param));
     strm->pool = pool;
     strm->rec_cb = rec_cb;
@@ -991,8 +984,4 @@
     strm->fmt_id = param->ext_fmt.id;
     strm->silence_char = silence_char;
-    strm->clock_rate = param->clock_rate;
-    strm->samples_per_frame = param->samples_per_frame;
-    strm->bits_per_sample = param->bits_per_sample;
-    strm->channel_count = param->channel_count;
 
     /* Create player stream */
@@ -1000,10 +989,10 @@
 	unsigned buf_count;
 
-	if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY)
-	    strm->play_strm.latency_ms = param->output_latency_ms;
-	else
-	    strm->play_strm.latency_ms = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
-
-	buf_count = strm->play_strm.latency_ms * param->clock_rate * 
+	if ((param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY)==0) {
+	    strm->param.flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY;
+	    strm->param.output_latency_ms = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
+	}
+
+	buf_count = strm->param.output_latency_ms * param->clock_rate * 
 		    param->channel_count / param->samples_per_frame / 1000;
 
@@ -1024,10 +1013,10 @@
 	unsigned buf_count;
 
-	if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY)
-	    strm->rec_strm.latency_ms = param->input_latency_ms;
-	else
-	    strm->rec_strm.latency_ms = PJMEDIA_SND_DEFAULT_REC_LATENCY;
-
-	buf_count = strm->rec_strm.latency_ms * param->clock_rate * 
+	if ((param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY)==0) {
+	    strm->param.flags |= PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY;
+	    strm->param.input_latency_ms = PJMEDIA_SND_DEFAULT_REC_LATENCY;
+	}
+
+	buf_count = strm->param.input_latency_ms * param->clock_rate * 
 		    param->channel_count / param->samples_per_frame / 1000;
 
@@ -1075,4 +1064,11 @@
     }
 
+    /* Apply the remaining settings */
+    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) {
+	stream_set_cap(&strm->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
+		       &param->output_vol);
+    }
+
+
     /* Done */
     strm->base.op = &stream_op;
@@ -1090,24 +1086,6 @@
     PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
 
-    pj_bzero(pi, sizeof(*pi));
-    pi->dir = strm->dir;
-    pi->play_id = strm->play_id;
-    pi->rec_id = strm->rec_id;
-    pi->clock_rate = strm->clock_rate;
-    pi->channel_count = strm->channel_count;
-    pi->samples_per_frame = strm->samples_per_frame;
-    pi->bits_per_sample = strm->bits_per_sample;
+    pj_memcpy(pi, &strm->param, sizeof(*pi));
     
-    if (pi->dir & PJMEDIA_DIR_CAPTURE) {
-	pi->flags |= PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY;
-	pi->input_latency_ms = strm->rec_strm.latency_ms;
-    }
-
-    if (pi->dir & PJMEDIA_DIR_PLAYBACK) {
-	/* TODO: report the actual latency? */
-	pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY;
-	pi->output_latency_ms = strm->play_strm.latency_ms;
-    }
-
     return PJ_SUCCESS;
 }
@@ -1123,14 +1101,14 @@
 
     if (cap==PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY && 
-	(strm->dir & PJMEDIA_DIR_CAPTURE)) 
+	(strm->param.dir & PJMEDIA_DIR_CAPTURE)) 
     {
 	/* Recording latency */
-	*(unsigned*)pval = strm->rec_strm.latency_ms;
+	*(unsigned*)pval = strm->param.input_latency_ms;
 	return PJ_SUCCESS;
     } else if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY  && 
-	       (strm->dir & PJMEDIA_DIR_PLAYBACK))
+	       (strm->param.dir & PJMEDIA_DIR_PLAYBACK))
     {
 	/* Playback latency */
-	*(unsigned*)pval = strm->play_strm.latency_ms;
+	*(unsigned*)pval = strm->param.output_latency_ms;
 	return PJ_SUCCESS;
     } else if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING &&
@@ -1138,14 +1116,14 @@
     {
 	/* Output volume setting */
-	DWORD dwVol;
+	DWORD waveVol;
 	MMRESULT mr;
 
-	mr = waveOutGetVolume(strm->play_strm.hWave.Out, &dwVol);
+	mr = waveOutGetVolume(strm->play_strm.hWave.Out, &waveVol);
 	if (mr != MMSYSERR_NOERROR) {
 	    return PJMEDIA_AUDIODEV_ERRNO_FROM_WMME_OUT(mr);
 	}
 
-	dwVol &= 0xFFFF;
-	*(unsigned*)pval = (dwVol * 100) / 0xFFFF;
+	waveVol &= 0xFFFF;
+	*(unsigned*)pval = (waveVol * 100) / 0xFFFF;
 	return PJ_SUCCESS;
     } else {
@@ -1167,13 +1145,22 @@
     {
 	/* Output volume setting */
-	DWORD dwVol;
+	unsigned vol = *(unsigned*)pval;
+	DWORD waveVol;
 	MMRESULT mr;
-
-	dwVol = ((*(unsigned*)pval) * 0xFFFF) / 100;
-	dwVol |= (dwVol << 16);
-
-	mr = waveOutSetVolume(strm->play_strm.hWave.Out, dwVol);
-	return (mr==MMSYSERR_NOERROR)? PJ_SUCCESS : 
+	pj_status_t status;
+
+	if (vol > 100)
+	    vol = 100;
+
+	waveVol = (vol * 0xFFFF) / 100;
+	waveVol |= (waveVol << 16);
+
+	mr = waveOutSetVolume(strm->play_strm.hWave.Out, waveVol);
+	status = (mr==MMSYSERR_NOERROR)? PJ_SUCCESS : 
 				PJMEDIA_AUDIODEV_ERRNO_FROM_WMME_OUT(mr);
+	if (status == PJ_SUCCESS) {
+	    strm->param.output_vol = *(unsigned*)pval;
+	}
+	return status;
     }
 
