sync up with WRS 0329 build

Change-Id: I8cb84e48333f621fedc81a855a615485febaf3a8
diff --git a/mix_audio/ChangeLog b/mix_audio/ChangeLog
index 3eb86f3..00fa650 100644
--- a/mix_audio/ChangeLog
+++ b/mix_audio/ChangeLog
@@ -1,3 +1,30 @@
+2010-01-31  Echo Choi  <echo@firefly>
+
+	* Reverted to use num_chan as output number of channel for AAC.
+
+2010-01-29  Echo Choi  <echo@firefly>
+
+	* Fixed Audio Manager setting.
+	* Updated version to 0.4.1 since API changes since 0.3.5.
+
+2010-01-25  Echo Choi  <echo@firefly>
+
+	* Updated MixCommon dependency to 0.1.8.
+	* Updated version to 0.3.6.
+
+2010-01-24  Echo Choi  <echo@firefly>
+
+	* Sync MixIOVec between capture and decode.
+
+2010-01-22  Echo Choi  <echo@firefly>
+
+	* Updated MixIOVec definition.
+	* Updated API sync with 0.79 doc.
+
+2010-01-20  Echo Choi  <echo@firefly>
+
+	* Updated API doc 0.79 sync up.
+
 2010-01-18  Echo Choi  <echo@firefly>
  
 	* Updated version to 0.3.5 and submit for build.
diff --git a/mix_audio/configure.ac b/mix_audio/configure.ac
index bcbb4ab..01c84a9 100644
--- a/mix_audio/configure.ac
+++ b/mix_audio/configure.ac
@@ -2,7 +2,7 @@
 
 AC_CONFIG_MACRO_DIR(m4)
 
-AS_MIX_VERSION(mixaudio, MIXAUDIO, 0, 3, 5)
+AS_MIX_VERSION(mixaudio, MIXAUDIO, 0, 4, 1)
 
 dnl AM_MAINTAINER_MODE provides the option to enable maintainer mode
 AM_MAINTAINER_MODE
@@ -88,7 +88,7 @@
   AC_MSG_ERROR(You need glib development packages installed !)
 fi
 
-MIXCOMMON_REQUIRED=0.1.6
+MIXCOMMON_REQUIRED=0.1.8
 PKG_CHECK_MODULES(MIXCOMMON, mixcommon >= $MIXCOMMON_REQUIRED , HAVE_MIXCOMMON=yes, HAVE_MIXCOMMON=no)
 if test "x$HAVE_MIXCOMMON" = "xno"; then
   AC_MSG_ERROR(You need mixcommon development package $MIXCOMMON_REQUIRED installed !)
diff --git a/mix_audio/mixaudio.spec b/mix_audio/mixaudio.spec
index e618d51..54e658b 100644
--- a/mix_audio/mixaudio.spec
+++ b/mix_audio/mixaudio.spec
@@ -6,7 +6,7 @@
 
 Summary: MIX Audio
 Name: mixaudio
-Version: 0.3.5
+Version: 0.4.1
 Release: 1
 Source0: %{name}-%{version}.tar.gz
 NoSource: 0
diff --git a/mix_audio/src/Android.mk b/mix_audio/src/Android.mk
index 466e3ce..08f3566 100644
--- a/mix_audio/src/Android.mk
+++ b/mix_audio/src/Android.mk
@@ -44,8 +44,8 @@
 	mixaip.h		\
 	mixaudio.h		\
 	mixaudiotypes.h		\
-	pvt.h			\
 	sst_proxy.h
+#	pvt.h			\
 
 LOCAL_MODULE := libmixaudio
 
diff --git a/mix_audio/src/Makefile.am b/mix_audio/src/Makefile.am
index b03751b..4a4cd36 100644
--- a/mix_audio/src/Makefile.am
+++ b/mix_audio/src/Makefile.am
@@ -42,7 +42,7 @@
 #libmixaudio_stub_la_LIBTOOLFLAGS = $(libmixaudio_la_LIBTOOLFLAGS)
 
 # headers we need but don't want installed
-noinst_HEADERS = intel_sst_ioctl.h sst_proxy.h pvt.h amhelper.h
+noinst_HEADERS = intel_sst_ioctl.h sst_proxy.h amhelper.h
 
 # TODO: decide whehter a /usr/include/mix is needed for mix headers
 include_HEADERS = mixaudio.h \
diff --git a/mix_audio/src/amhelper.c b/mix_audio/src/amhelper.c
index 501ece7..5124a6a 100644
--- a/mix_audio/src/amhelper.c
+++ b/mix_audio/src/amhelper.c
@@ -11,7 +11,7 @@
  * return -1 means failed
  * return 0 means succeeded
  * */
-gint dbus_init() {
+gint32 dbus_init() {
     GError *error;
     const char *name = "org.moblin.audiomanager";
 
@@ -25,7 +25,7 @@
     else
 	am_enable = FALSE;
 
-    if (am_enable) {
+    if (am_enable && (proxy_lpe == NULL)) {
 	    error = NULL;
 	    connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
 
@@ -94,25 +94,25 @@
   return s_output;
 }
 
-gint32 lpe_stream_notify_pause(guint32 stream_id)
+gint32 lpe_stream_notify_pause(guint32 am_stream_id)
 {
   GError *error;
   gint32 s_output=0;
 
   if (am_enable) {
-    dbus_g_proxy_call (proxy_lpe, "LPEStreamNotifyPause", &error, G_TYPE_UINT, stream_id, G_TYPE_INVALID, G_TYPE_INT, &s_output, G_TYPE_INVALID);
+    dbus_g_proxy_call (proxy_lpe, "LPEStreamNotifyPause", &error, G_TYPE_UINT, am_stream_id, G_TYPE_INVALID, G_TYPE_INT, &s_output, G_TYPE_INVALID);
   }
 
   return s_output;
 }
 
-gint32 lpe_stream_notify_resume(guint32 stream_id)
+gint32 lpe_stream_notify_resume(guint32 am_stream_id)
 {
   GError *error;
   gint32 s_output=0;
 
   if (am_enable) {
-    dbus_g_proxy_call (proxy_lpe, "LPEStreamNotifyResume", &error, G_TYPE_UINT, stream_id, G_TYPE_INVALID, G_TYPE_INT, &s_output, G_TYPE_INVALID);
+    dbus_g_proxy_call (proxy_lpe, "LPEStreamNotifyResume", &error, G_TYPE_UINT, am_stream_id, G_TYPE_INVALID, G_TYPE_INT, &s_output, G_TYPE_INVALID);
   }
 
   return s_output;
diff --git a/mix_audio/src/amhelper.h b/mix_audio/src/amhelper.h
index 9ec115c..8a00681 100644
--- a/mix_audio/src/amhelper.h
+++ b/mix_audio/src/amhelper.h
@@ -12,14 +12,14 @@
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
 
-gint dbus_init();
+gint32 dbus_init();
 
 gint32 lpe_stream_register(guint32 lpe_stream_id, char* media_role, char* lpe_stream_name, guint32 stream_type);
 
 gint32 lpe_stream_unregister(guint32 am_stream_id);
 
-gint32 lpe_stream_notify_pause(guint32 stream_id);
+gint32 lpe_stream_notify_pause(guint32 am_stream_id);
 
-gint32 lpe_stream_notify_resume(guint32 stream_id);
+gint32 lpe_stream_notify_resume(guint32 am_stream_id);
 
 #endif
diff --git a/mix_audio/src/mixacp.c b/mix_audio/src/mixacp.c
index d66ee3c..3478bf3 100644
--- a/mix_audio/src/mixacp.c
+++ b/mix_audio/src/mixacp.c
@@ -319,3 +319,37 @@
     } 
 }
 
+
+MIX_RESULT mix_acp_set_audio_manager(MixAudioConfigParams *obj, MixAudioManager am)
+{
+    if (obj == NULL) return MIX_RESULT_NULL_PTR;
+
+    if (!G_UNLIKELY(MIX_IS_AUDIOCONFIGPARAMS(obj)))
+    {
+        return MIX_RESULT_INVALID_PARAM;
+    }
+
+    if ((am >= MIX_AUDIOMANAGER_LAST) || (am <MIX_AUDIOMANAGER_NONE))
+    {
+        return MIX_RESULT_INVALID_PARAM;
+    }
+    else
+    {
+        obj->audio_manager = am;
+    }
+
+    return MIX_RESULT_SUCCESS;
+
+}
+
+MixAudioManager mix_acp_get_audio_manager(MixAudioConfigParams *obj)
+{
+    if (G_LIKELY(MIX_IS_AUDIOCONFIGPARAMS(obj)))
+    {
+        return obj->audio_manager;
+    }
+    else
+        return MIX_AUDIOMANAGER_NONE;
+}
+
+
diff --git a/mix_audio/src/mixacpaac.c b/mix_audio/src/mixacpaac.c
index 4f83eb9..4b47c3d 100644
--- a/mix_audio/src/mixacpaac.c
+++ b/mix_audio/src/mixacpaac.c
@@ -178,6 +178,10 @@
     return FALSE;
   }
 
+  // If either one of the input is not the same class then forget it.
+  if (!MIX_IS_AUDIOCONFIGPARAMSAAC(first) || !MIX_IS_AUDIOCONFIGPARAMSAAC(second))
+    return FALSE;
+
   // members within this scope equal. chaining up.
   MixParamsClass *klass = MIX_PARAMS_CLASS(parent_class);
   if (klass->equal)
@@ -185,7 +189,7 @@
   else
     ret = TRUE;
 
-  if (ret && MIX_IS_AUDIOCONFIGPARAMSAAC(first) && MIX_IS_AUDIOCONFIGPARAMSAAC(second))
+  if (ret)
   {
 
     MixAudioConfigParamsAAC *acp1 = MIX_AUDIOCONFIGPARAMSAAC(first);
diff --git a/mix_audio/src/mixacpmp3.c b/mix_audio/src/mixacpmp3.c
index 75ab8cb..5514a24 100644
--- a/mix_audio/src/mixacpmp3.c
+++ b/mix_audio/src/mixacpmp3.c
@@ -152,6 +152,9 @@
     return FALSE;
   }
 
+  if (!MIX_IS_AUDIOCONFIGPARAMSMP3(first) || !MIX_IS_AUDIOCONFIGPARAMSMP3(second))
+    return FALSE;
+
   // members within this scope equal. chaining up.
   MixParamsClass *klass = MIX_PARAMS_CLASS(parent_class);
   if (klass->equal)
@@ -159,7 +162,7 @@
   else
     ret = TRUE;
 
-  if (ret && MIX_IS_AUDIOCONFIGPARAMSMP3(first) && MIX_IS_AUDIOCONFIGPARAMSMP3(second))
+  if (ret)
   {
     MixAudioConfigParamsMP3 *acp1 = MIX_AUDIOCONFIGPARAMSMP3(first);
     MixAudioConfigParamsMP3 *acp2 = MIX_AUDIOCONFIGPARAMSMP3(second);
diff --git a/mix_audio/src/mixacpwma.c b/mix_audio/src/mixacpwma.c
index cf2590f..9e0db82 100644
--- a/mix_audio/src/mixacpwma.c
+++ b/mix_audio/src/mixacpwma.c
@@ -159,13 +159,16 @@
     return FALSE;
   }
 
+  if (!MIX_IS_AUDIOCONFIGPARAMSWMA(first) || !MIX_IS_AUDIOCONFIGPARAMSWMA(second))
+    return FALSE;
+
   MixParamsClass *klass = MIX_PARAMS_CLASS(parent_class);
   if (klass->equal)
     ret = klass->equal(first, second);
   else
     ret = TRUE;
 
-  if (ret && MIX_IS_AUDIOCONFIGPARAMSWMA(first) && MIX_IS_AUDIOCONFIGPARAMSWMA(second))
+  if (ret)
   {
     MixAudioConfigParamsWMA *acp1 = MIX_AUDIOCONFIGPARAMSWMA(first);
     MixAudioConfigParamsWMA *acp2 = MIX_AUDIOCONFIGPARAMSWMA(second);
diff --git a/mix_audio/src/mixaudio.c b/mix_audio/src/mixaudio.c
index 196a0b0..53d61a5 100644
--- a/mix_audio/src/mixaudio.c
+++ b/mix_audio/src/mixaudio.c
@@ -59,6 +59,7 @@
 #include <glib/gprintf.h>
 #include <mixlog.h>
 #include "mixaudio.h"
+#include "mixacpaac.h"
 
 #ifdef AUDIO_MANAGER
 #include "amhelper.h"
@@ -105,7 +106,7 @@
 
 MIX_RESULT mix_audio_initialize_default(MixAudio *mix, MixCodecMode mode, MixAudioInitParams *aip, MixDrmParams *drminitparams);
 MIX_RESULT mix_audio_configure_default(MixAudio *mix, MixAudioConfigParams *audioconfigparams, MixDrmParams *drmparams);
-MIX_RESULT mix_audio_decode_default(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt, guint64 *outsize);
+MIX_RESULT mix_audio_decode_default(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt);
 MIX_RESULT mix_audio_capture_encode_default(MixAudio *mix, MixIOVec *iovout, gint iovoutcnt);
 MIX_RESULT mix_audio_start_default(MixAudio *mix);
 MIX_RESULT mix_audio_stop_drop_default(MixAudio *mix);
@@ -122,13 +123,13 @@
 MIX_RESULT mix_audio_deinitialize_default(MixAudio *mix);
 MIX_RESULT mix_audio_get_stream_state_default(MixAudio *mix, MixStreamState *streamState);
 MIX_RESULT mix_audio_get_state_default(MixAudio *mix, MixState *state);
-MIX_RESULT mix_audio_is_am_available_default(MixAudio *mix, MixAudioManager am, gboolean *avail);
-MIX_RESULT mix_audio_get_output_configuration_default(MixAudio *mix, MixAudioConfigParams **audioconfigparams);
+MIX_RESULT mix_audio_get_config_default(MixAudio *mix, MixAudioConfigParams **audioconfigparams);
 
 static gboolean g_IAM_available = FALSE;
 MIX_RESULT mix_audio_am_unregister(MixAudio *mix, MixAudioConfigParams *audioconfigparams);
 MIX_RESULT mix_audio_am_register(MixAudio *mix, MixAudioConfigParams *audioconfigparams);
 MIX_RESULT mix_audio_AM_Change(MixAudioConfigParams *oldparams, MixAudioConfigParams *newparams);
+static MIX_RESULT mix_audio_verify_params(MixAudio *mix, const MixAudioConfigParams *audioconfigparams);
 
 static void mix_audio_finalize(GObject *obj);
 G_DEFINE_TYPE (MixAudio, mix_audio, G_TYPE_OBJECT);
@@ -139,8 +140,9 @@
 static MIX_RESULT mix_audio_FW_INFO(MixAudio *mix);
 static MIX_RESULT mix_audio_SST_SET_PARAMS(MixAudio *mix, MixAudioConfigParams *params);
 static MIX_RESULT mix_audio_SST_writev(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize);
-static MIX_RESULT mix_audio_SST_STREAM_DECODE(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt, guint64 *outsize);
+static MIX_RESULT mix_audio_SST_STREAM_DECODE(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt);
 static void mix_audio_debug_dump(MixAudio *mix);
+static MIX_RESULT mix_audio_is_stream_changed(MixAudio *mix, MixAudioConfigParams *new_params, gboolean *pChanged);
 
 static guint g_log_handler=0;
 static void mix_audio_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data);
@@ -155,7 +157,6 @@
 
 static void mix_audio_init (MixAudio *self)
 {
-  self->useIAM = FALSE;
   self->streamID = 0; // TODO: Find out the invalid value for stream ID when integrates with IAM.
   self->amStreamID = 0;         // TODO: as above
   self->streamState = MIX_STREAM_NULL;
@@ -164,6 +165,7 @@
   self->state = MIX_STATE_UNINITIALIZED;
   self->codecMode = MIX_CODING_INVALID;
   self->am_registered = FALSE;
+  self->stream_muted = FALSE;
 
   /* private member initialization */
   g_static_rec_mutex_init (&self->streamlock);
@@ -216,8 +218,7 @@
   klass->deinitialize = mix_audio_deinitialize_default;
   klass->get_stream_state = mix_audio_get_stream_state_default;
   klass->get_state = mix_audio_get_state_default;
-  klass->is_am_available = mix_audio_is_am_available_default;
-  klass->get_output_configuration = mix_audio_get_output_configuration_default;
+  klass->get_config = mix_audio_get_config_default;
 
   // Set log handler...
   if (!g_log_handler)
@@ -268,7 +269,7 @@
 
   // convert bit mask back to index.
   index = ffs(mask) - 1;
-  
+
   if ((index<0) || (index >= (sizeof(lognames)/sizeof(lognames[0])))) return;
 
   g_get_current_time(&t);
@@ -323,88 +324,80 @@
 
 MIX_RESULT mix_audio_initialize_default(MixAudio *mix, MixCodecMode mode, MixAudioInitParams *aip, MixDrmParams *drminitparams)
 {
-  MIX_RESULT ret = MIX_RESULT_FAIL;
+    // API version 0.79. 1/19/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
 
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
 
-  // TODO: parse and process MixAudioInitParams. It is ignored for now.
+    if ((mode <= MIX_CODING_INVALID) || (mode >= MIX_CODING_LAST)) return MIX_RESULT_INVALID_PARAM;
 
-  // initialized must be called with both thread-lock held, so no other operation is allowed.
-  
-  // try lock stream thread. If failed, a pending _decode/_encode/_drain is ongoing.
-  if (!g_static_rec_mutex_trylock(&mix->streamlock)) return MIX_RESULT_WRONG_STATE;
+    // initialized must be called with both thread-lock held, so no other operation is allowed.
+    
+    // try lock stream thread. If failed, a pending _decode/_encode/_drain is ongoing.
+    if (!g_static_rec_mutex_trylock(&mix->streamlock)) return MIX_RESULT_WRONG_STATE;
 
-  // also lock the control thread lock.
-  _LOCK(&mix->controllock);
+    // also lock the control thread lock.
+    _LOCK(&mix->controllock);
 
-  if (mix->state == MIX_STATE_UNINITIALIZED)
-  {
-    // Only allowed in uninitialized state.
-    switch (mode)
+    if (mix->state != MIX_STATE_UNINITIALIZED)
+        ret = MIX_RESULT_ALREADY_INIT;
+
+    if (!MIX_SUCCEEDED(ret))
     {
-      case MIX_CODING_DECODE:
-      case MIX_CODING_ENCODE:
-        {
+        _UNLOCK(&mix->controllock);
+        _UNLOCK(&mix->streamlock);
+        return ret;
+    }
+
           // Open device. Same flags to open for decode and encode?
 #ifdef LPESTUB
-          //g_debug("Reading env var LPESTUB_FILE for data output file.\n");
-          //const char* filename = g_getenv("LPESTUB_FILE");
-          gchar *filename = NULL;
-          GError *err = NULL;
-          const gchar* fn = NULL;
-	  fn = g_getenv("MIX_AUDIO_OUTPUT");
-	  if (fn)
-	    mix->fileDescriptor = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
-
-          if (mix->fileDescriptor == -1)
-          {
-	    mix->fileDescriptor = g_file_open_tmp ("mixaudio.XXXXXX", &filename, &err);
-
+    {
+        gchar *filename = NULL;
+        GError *err = NULL;
+        const gchar* fn = NULL;
+        fn = g_getenv("MIX_AUDIO_OUTPUT");
+        if (fn) mix->fileDescriptor = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
+        if (mix->fileDescriptor == -1)
+        {
+            mix->fileDescriptor = g_file_open_tmp ("mixaudio.XXXXXX", &filename, &err);
             if (err)
             {
-              g_warning("Oops, cannot open temp file: Error message: %s", err->message);
+                g_warning("Oops, cannot open temp file: Error message: %s", err->message);
             }
             else
             {
-              g_debug("Opening %s as output data file.\n", filename);
+                g_debug("Opening %s instead of %s as output data file.\n", filename, LPE_DEVICE);
             }
-          }
-          else
-          {
-            g_debug("Opening %s as output data file.\n", fn);
-          }
-          if (filename) g_free(filename);
-#else
-          g_debug("Opening %s\n", LPE_DEVICE);
-          mix->fileDescriptor = open(LPE_DEVICE, O_RDWR);
-#endif
-          if (mix->fileDescriptor != -1)
-          {
-            mix->codecMode = mode;
-            mix->state = MIX_STATE_INITIALIZED;
-            ret = MIX_RESULT_SUCCESS;
-            g_debug("open() succeeded. fd=%d", mix->fileDescriptor);
-          }
-          else
-          {
-            ret = MIX_RESULT_LPE_NOTAVAIL;
-          }
         }
-        break;
-      default:
-        ret = MIX_RESULT_INVALID_PARAM;
-      break;
+        else
+        {
+            g_debug("Opening %s as output data file.\n", fn);
+        }
+        if (filename) g_free(filename);
     }
-  }
-  else
-  {
-    ret = MIX_RESULT_WRONG_STATE;
-  }
+#else
+    g_debug("Calling open(%s)\n", LPE_DEVICE);
+    mix->fileDescriptor = open(LPE_DEVICE, O_RDWR);
+    g_debug("open returned %d", mix->fileDescriptor);
+#endif
 
-  _UNLOCK(&mix->controllock);
-  _UNLOCK(&mix->streamlock);
+    if (mix->fileDescriptor != -1)
+    {
+        mix->codecMode = mode;
+        mix->state = MIX_STATE_INITIALIZED;
+        ret = MIX_RESULT_SUCCESS;
+        mix->deviceState = MIX_AUDIO_DEV_OPENED;
+    }
+    else
+    {
+        ret = MIX_RESULT_LPE_NOTAVAIL;
+        g_warning("open() failed. Error(0x%08x): %s", errno, strerror(errno));
+    }
 
-  return ret;
+    _UNLOCK(&mix->controllock);
+    _UNLOCK(&mix->streamlock);
+
+    return ret;
 }
 
 gboolean mix_audio_am_is_available(void)
@@ -538,18 +531,18 @@
 
 MIX_RESULT mix_audio_get_state_default(MixAudio *mix, MixState *state)
 {
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
-  
-  if (state)
-    *state = mix->state;
-  else
-    ret = MIX_RESULT_NULL_PTR;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
 
-  return ret;
+    if (G_UNLIKELY(mix == NULL)) return MIX_RESULT_NULL_PTR;
+    if (state == NULL) return MIX_RESULT_NULL_PTR;
+
+    *state = mix->state;
+
+    return ret;
 }
 
-MIX_RESULT mix_audio_decode_default(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt, guint64 *outsize)
+MIX_RESULT mix_audio_decode_default(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt)
 {
   MIX_RESULT ret = MIX_RESULT_FAIL;
 
@@ -562,7 +555,7 @@
   if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DIRECTRENDER)
     ret = mix_audio_SST_writev(mix, iovin, iovincnt, insize);
   else
-    ret = mix_audio_SST_STREAM_DECODE(mix, iovin, iovincnt, insize, iovout, iovoutcnt, outsize);
+    ret = mix_audio_SST_STREAM_DECODE(mix, iovin, iovincnt, insize, iovout, iovoutcnt);
 
   _UNLOCK(&mix->streamlock);
 
@@ -599,6 +592,7 @@
       mix->deviceState = MIX_AUDIO_DEV_CLOSED;
     }
     mix->state = MIX_STATE_UNINITIALIZED;
+    mix->stream_muted = FALSE;
   }
 
   mix->bytes_written = 0;
@@ -612,21 +606,29 @@
 
 MIX_RESULT mix_audio_stop_drop_default(MixAudio *mix)
 {
-  MIX_RESULT ret = MIX_RESULT_FAIL;
-
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
-
-  _LOCK(&mix->controllock);
-
-  if (mix->state != MIX_STATE_CONFIGURED)
-    _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
-
-  // Will call DROP even if we are already stopped. It is needed to unblock any pending write() call.
-//  if (mix->streamState == MIX_STREAM_DRAINING)
-//    ret = MIX_RESULT_WRONG_STATE;
-//  else
-  {
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
     int retVal = 0;
+
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+
+    _LOCK(&mix->controllock);
+
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->state != MIX_STATE_CONFIGURED) 
+    {
+        // Not allowing control operation if it is not configured.
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    }
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+    {
+        // Not allowing control operation if it is configured as DNR.
+        ret = MIX_RESULT_WRONGMODE;
+    }
+
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
+
+  // Will call DROP even if we are already stopped. It is needed to unblock any pending readv()/write() call that is made after the last STOP_x and before the next START.
 #ifdef LPESTUB
     // Not calling ioctl.
 #else
@@ -635,124 +637,146 @@
     g_debug("_DROP returned %d", retVal);
 #endif
 
-    if (!retVal)
-      {
+    if (retVal != 0)
+    {
+        ret = MIX_RESULT_SYSTEM_ERRNO; 
+        g_warning("Failed to stop stream. Error(0x%08x): %s", errno, strerror(errno));
+    }
+    else
+    {
         mix->streamState = MIX_STREAM_STOPPED;
         ret = MIX_RESULT_SUCCESS;
-      }
-    else
-      {
-        ret = MIX_RESULT_SYSTEM_ERRNO; 
-        g_debug("Failed to stop stream. Error:0x%08x. Unknown stream state.", errno);
-      }
-  }
+    }
 
-  _UNLOCK(&mix->controllock);
+    _UNLOCK(&mix->controllock);
 
-  return ret;
+    return ret;
 }
 
 MIX_RESULT mix_audio_stop_drain_default(MixAudio *mix)
 {
-  MIX_RESULT ret = MIX_RESULT_FAIL;
-  int retVal = 0;
-
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
-
-  // No need to lock to check vars that won't be changed in this function
-
-  if (g_static_rec_mutex_trylock(&mix->streamlock))
-  {
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    int retVal = 0;
     gboolean doDrain = FALSE;
+    
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
 
-    if (mix->state != MIX_STATE_CONFIGURED) 
-      _UNLOCK_RETURN(&mix->streamlock, MIX_RESULT_NOT_CONFIGURED);
+    // No need to lock to check vars that won't be changed in this function
+
+    // If cannot obtain stream lock meaning there's a pending _decode/_encode and will not proceed.
+    if (!g_static_rec_mutex_trylock(&mix->streamlock)) return MIX_RESULT_WRONG_STATE;
 
     _LOCK(&mix->controllock);
+
+    // Check unallowed condition
+
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
     {
-      if (mix->streamState == MIX_STREAM_STOPPED)
-        ret = MIX_RESULT_SUCCESS;
-      else if ((mix->streamState == MIX_STREAM_DRAINING) || mix->streamState == MIX_STREAM_PAUSED_DRAINING)
-        ret = MIX_RESULT_WRONG_STATE;
-      else
-      {
-        doDrain = TRUE;
-        g_debug("MIX stream is DRAINING");
-        mix->streamState = MIX_STREAM_DRAINING;
-      }
+        // Not allowing control operation if it is configure for decode.
+        ret = MIX_RESULT_WRONGMODE;
     }
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+    {
+        // Not allowing control operation if it is not configured.
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    }
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+    {
+        // Not allowing control operation if it is configured as DNR.
+        ret = MIX_RESULT_WRONGMODE;
+    }
+
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret))
+    {
+        _UNLOCK(&mix->controllock);
+        _UNLOCK(&mix->streamlock);
+        return ret;
+    }
+
+    if (mix->streamState == MIX_STREAM_STOPPED)
+        // no need to drain and we already stopped.
+        ret = MIX_RESULT_SUCCESS;
+    else if ((mix->streamState == MIX_STREAM_DRAINING) || mix->streamState == MIX_STREAM_PAUSED_DRAINING)
+        // Not allowed if we are already draining or PAUSED in draining state.
+        ret = MIX_RESULT_WRONG_STATE;
+    else
+    {
+        doDrain = TRUE;
+        g_debug("MIX stream needs DRAINING");
+        mix->streamState = MIX_STREAM_DRAINING;
+        // Set state to MIX_STREAM_DRAINING and other operations that may change teh streamState has to
+        // be careful when handling stream with this state.
+    }
+
+    // release the control lock. we only hold the stream lock during this blocking DRAIN call.
     _UNLOCK(&mix->controllock);
 
 
     if (doDrain)
     {
-      // Calling the blocking DRAIN without holding the controllock
-      // TODO: remove this ifdef when API becomes available.
-  #ifdef LPESTUB
+      // Calling the blocking DRAIN holding just the stream lock, without the control lock
+
+#ifdef LPESTUB
       
-  #else
-      //g_debug("Calling SNDRV_SST_STREAM_DRAIN. fd=0x%08x", mix->fileDescriptor);
-      //retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_DRAIN);
-//      g_warning("Calling SNDRV_SST_STREAM_DROP instead of SNDRV_SST_STREAM_DRAIN here since DRAIN is not yet integrated. There may be data loss. fd=%d", mix->fileDescriptor);
+#else
       g_debug("Calling SNDRV_SST_STREAM_DRAIN fd=%d", mix->fileDescriptor);
       retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_DRAIN);
       g_debug("_DRAIN returned %d", retVal);
-  #endif
+#endif
 
-      if (retVal)
-      {
+        // obtain control lock and update state.
         _LOCK(&mix->controllock);
-        if (mix->streamState != MIX_STREAM_STOPPED)
+
+        if (retVal != 0)
         {
-          // DRAIN could return failed if DROP is called during DRAIN.
-          // Any state resulting as a failed DRAIN would be error, execpt STOPPED.
-          ret = MIX_RESULT_SYSTEM_ERRNO;
-          g_debug("Failed to drain stream. Error:0x%08x. Unknown stream state.", errno);
-        }
-        _UNLOCK(&mix->controllock);
-      }
-      else
-      {
-        _LOCK(&mix->controllock);
-        if ((mix->streamState != MIX_STREAM_DRAINING) &&
-          (mix->streamState != MIX_STREAM_STOPPED))
-        {
-          // State is changed while in DRAINING. This should not be allowed and is a bug.
-          g_warning("MIX Internal state error! DRAIN state(%u) changed!",mix->streamState);
-          ret = MIX_RESULT_FAIL;
+            if (mix->streamState != MIX_STREAM_STOPPED)
+            {
+                // DRAIN could return failed if DROP is called during DRAIN.
+                // Any state resulting as a failed DRAIN would be error, except STOPPED.
+                ret = MIX_RESULT_SYSTEM_ERRNO;
+                g_debug("Failed to drain stream. Error(0x%08x): %s", errno, strerror(errno));
+            }
         }
         else
         {
-          mix->streamState = MIX_STREAM_STOPPED;
-          ret = MIX_RESULT_SUCCESS;
+            if ((mix->streamState != MIX_STREAM_DRAINING) &&
+                (mix->streamState != MIX_STREAM_STOPPED))
+            {
+                // State is changed while in DRAINING. This should not be allowed and is a bug.
+                g_warning("MIX Internal state error! DRAIN state(%u) changed!",mix->streamState);
+                ret = MIX_RESULT_FAIL;
+            }
+            else
+            {
+                mix->streamState = MIX_STREAM_STOPPED;
+                ret = MIX_RESULT_SUCCESS;
+            }
         }
+    
         _UNLOCK(&mix->controllock);
-      }
     }
 
     _UNLOCK(&mix->streamlock);
-  }
-  else
-  {
-    // Cannot obtain stream lock meaning there's a pending _decode/_encode.
-    // Will not proceed.
-    ret = MIX_RESULT_WRONG_STATE;
-  }
 
   return ret;
 }
 
 MIX_RESULT mix_audio_start_default(MixAudio *mix)
 {
+  // API version 0.79. 1/22/2009
   MIX_RESULT ret = MIX_RESULT_FAIL;
 
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+  if (G_UNLIKELY(mix==NULL)) return MIX_RESULT_NULL_PTR;
 
   _LOCK(&mix->controllock);
 
   if (mix->state != MIX_STATE_CONFIGURED)
     _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
 
+  // Not allowed if in DNR mode.
   if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
     _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_WRONGMODE);
 
@@ -774,7 +798,8 @@
         retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_START);
         g_debug("_START returned %d", retVal);
 #endif
-        if (retVal)
+
+        if (retVal != 0)
         {
           ret = MIX_RESULT_SYSTEM_ERRNO; 
           g_debug("Fail to START. Error:0x%08x. Stream state unchanged.", errno);
@@ -823,15 +848,31 @@
 
 MIX_RESULT mix_audio_configure_default(MixAudio *mix, MixAudioConfigParams *audioconfigparams, MixDrmParams *drmparams)
 {
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
+  // API version 0.79. 1/19/2009
+
+  MIX_RESULT ret = MIX_RESULT_FAIL;
+  gboolean changed = FALSE;
+  MixParams *new_params = NULL;
 
   if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
 
-  // param checks
+  g_message("_configure() starts.");
+
+  // input param checks
   if (!MIX_IS_AUDIOCONFIGPARAMS(audioconfigparams)) return MIX_RESULT_NOT_ACP;
   if (MIX_ACP_DECODEMODE(audioconfigparams) >= MIX_DECODE_LAST) return MIX_RESULT_INVALID_DECODE_MODE;
   if (!mix_acp_is_streamname_valid(audioconfigparams)) return MIX_RESULT_INVALID_STREAM_NAME;
 
+  // dup a copy. we will need it when configure is successful.
+  // don't want to find out we can't dup it only after everything is set.
+  new_params = mix_params_dup(MIX_PARAMS(audioconfigparams));
+  if (!MIX_IS_AUDIOCONFIGPARAMS(new_params))
+  {
+    if (MIX_IS_PARAMS(new_params)) mix_params_unref(new_params);
+    g_error("Failed to duplicate input MixAudioConfigParams!");
+    return MIX_RESULT_FAIL;
+  }
+
   // If we cannot lock stream thread, data is flowing and we can't configure.
   if (!g_static_rec_mutex_trylock(&mix->streamlock)) return MIX_RESULT_WRONG_STATE;
 
@@ -839,23 +880,20 @@
 
   // Check all unallowed conditions
   if (mix->state == MIX_STATE_UNINITIALIZED) 
-    ret = MIX_RESULT_NOT_INIT; // Will not allowed if the state is still UNINITIALIZED
-  else if ((mix->codecMode != MIX_CODING_DECODE) && (mix->codecMode != MIX_CODING_ENCODE))
-    ret = MIX_RESULT_WRONGMODE; // This configure is allowed only in DECODE mode.
-  else if ((mix->streamState != MIX_STREAM_STOPPED) && (mix->streamState != MIX_STREAM_NULL))
-    ret = MIX_RESULT_WRONG_STATE;
-
-  if (!MIX_SUCCEEDED(ret))
   {
-    // Some check failed. Unlock and return.
-    _UNLOCK(&mix->controllock);
-    _UNLOCK(&mix->streamlock);
-    return ret;
+    ret = MIX_RESULT_NOT_INIT; // Will not allowed if the state is still UNINITIALIZED
+    goto _configure_done;
   }
 
-  if (audioconfigparams->audio_manager == MIX_AUDIOMANAGER_INTELAUDIOMANAGER) {
-    mix->useIAM = TRUE;
+  if ((mix->streamState != MIX_STREAM_STOPPED) && (mix->streamState != MIX_STREAM_NULL))
+  {
+    ret = MIX_RESULT_WRONG_STATE;
+    goto _configure_done;
   }
+
+  ret = mix_audio_verify_params(mix, audioconfigparams);
+  if (!MIX_SUCCEEDED(ret)) goto _configure_done;
+
   // now configure stream.
 
 #ifdef AUDIO_MANAGER
@@ -863,102 +901,131 @@
 #else
   ret = MIX_RESULT_SUCCESS;
 #endif
+  if (!MIX_SUCCEEDED(ret)) goto _configure_failed;
 
-  if (MIX_SUCCEEDED(ret))
+  ret = mix_audio_is_stream_changed(mix, audioconfigparams, &changed);
+  if (!MIX_SUCCEEDED(ret)) goto _configure_failed;
+
+  if (changed)
   {
     ret = mix_audio_SST_SET_PARAMS(mix, audioconfigparams);
-  }
-
-  if (MIX_SUCCEEDED(ret))
-  {
-#ifdef AUDIO_MANAGER
-    ret = mix_audio_am_register(mix, audioconfigparams);
-#else
-  ret = MIX_RESULT_SUCCESS;
-#endif
-  }
-
-  if (MIX_SUCCEEDED(ret))
-  {
-    mix->state = MIX_STATE_CONFIGURED;
+    if (!MIX_SUCCEEDED(ret)) goto _configure_failed;
   }
   else
   {
-    mix->state = MIX_STATE_INITIALIZED;
+    g_message("No stream change is detected. Not calling SET_PARAMS.");
   }
 
-  _UNLOCK(&mix->controllock);
-  _UNLOCK(&mix->streamlock);
+#ifdef AUDIO_MANAGER
+  ret = mix_audio_am_register(mix, audioconfigparams);
+#else
+  ret = MIX_RESULT_SUCCESS;
+#endif
+  if (!MIX_SUCCEEDED(ret)) goto _configure_failed;
 
-  return ret;
+  ret = MIX_RESULT_SUCCESS;
+
+_configure_failed:
+
+    if (mix->audioconfigparams)
+    {
+        mix_acp_unref(mix->audioconfigparams);
+        mix->audioconfigparams=NULL;
+    }
+
+    if (MIX_SUCCEEDED(ret))
+    {
+        mix->state = MIX_STATE_CONFIGURED;
+        mix->audioconfigparams = MIX_AUDIOCONFIGPARAMS(new_params);
+        new_params = NULL;
+    }
+    else
+    {
+        // attempt to configure has failed. Revert state back to INITIALIZED only.
+        mix->state = MIX_STATE_INITIALIZED;
+        mix->streamState = MIX_STREAM_STOPPED;
+        // No need to un-set SST PARAM. not supported really.
+    }
+
+_configure_done:
+
+    _UNLOCK(&mix->controllock);
+    _UNLOCK(&mix->streamlock);
+
+    if (new_params)
+    {
+        mix_params_unref(new_params);
+    }
+
+    g_message("_configure() done returning 0x%08x.", ret);
+
+    return ret;
 }
 
 MIX_RESULT mix_audio_get_timestamp_default(MixAudio *mix, guint64 *msecs)
 {
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    unsigned long long ts = 0;
+    int retVal = 0;
+    
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;    
+    if (!msecs) return MIX_RESULT_NULL_PTR;
 
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    _LOCK(&mix->controllock);
 
-  if (!msecs) return MIX_RESULT_NULL_PTR;
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
 
-  _LOCK(&mix->controllock);
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
 
-  if (mix->state == MIX_STATE_CONFIGURED)
-  {
-    if ((mix->codecMode == MIX_CODING_DECODE) && (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN))
-    {
-      ret = MIX_RESULT_WRONGMODE;
-    }
-    else {
-
-      unsigned long long ts = 0;
-      int retVal = 0;
 
 #ifdef LPESTUB
-      // For stubbing, just get system clock.
-      if (MIX_ACP_BITRATE(mix->audioconfigparams) > 0)
-      {
+    // For stubbing, just get system clock.
+    if (MIX_ACP_BITRATE(mix->audioconfigparams) > 0)
+    {
         // use bytes_written and bitrate
         // to get times in msec.
         ts = mix->bytes_written * 8000 / MIX_ACP_BITRATE(mix->audioconfigparams);
-      }
-      else if (mix->ts_last)
-      {
+    }
+    else if (mix->ts_last)
+    {
         GTimeVal tval = {0};
         g_get_current_time(&tval);
         ts = 1000ll * tval.tv_sec + tval.tv_usec / 1000;
         ts -= mix->ts_last;
         ts += mix->ts_elapsed;
-      }
-      else
-      {
+    }
+    else
+    {
         ts = 0;
-      }
+    }
 #else
-      g_debug("Calling SNDRV_SST_STREAM_GET_TSTAMP. fd=%d", mix->fileDescriptor);
-      ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_GET_TSTAMP, &ts);
+    g_debug("Calling _GET_TSTAMP. fd=%d", mix->fileDescriptor);
+    retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_GET_TSTAMP, &ts);
+    g_debug("_GET_TSTAMP returned %d. timestamp=%" G_GUINT64_FORMAT, retVal, ts);
 #endif
 
-      if (retVal)
-      {
+    if (retVal != 0)
+    {
         ret = MIX_RESULT_SYSTEM_ERRNO; 
-        g_debug("_GET_TSTAMP failed. Error:0x%08x", errno);
-        //ret = MIX_RESULT_FAIL;
+        g_debug("_GET_TSTAMP failed. Error(0x%08x): %s", errno, strerror(errno));
         mix_audio_debug_dump(mix);
-      }
-      else
-      {
-        *msecs = ts;
-        g_debug("_GET_TSTAMP returned %" G_GUINT64_FORMAT, ts);
-      }
     }
-  }
-  else
-    ret = MIX_RESULT_NOT_CONFIGURED;
+    else
+    {
+        *msecs = ts;
+    }
 
-  _UNLOCK(&mix->controllock);
+    _UNLOCK(&mix->controllock);
 
-  return ret;
+    return ret;
 }
 
 #ifdef AUDIO_MANAGER
@@ -986,8 +1053,9 @@
       // decode mode change.
       if (mix->amStreamID > 0) {
         if (lpe_stream_unregister(mix->amStreamID) != 0) {
-	  return MIX_RESULT_FAIL;
+          return MIX_RESULT_AM_UNREGISTER_FAIL;
         }
+        mix->amStreamID = 0;
         mix->am_registered = FALSE;
       }
     }
@@ -1016,15 +1084,19 @@
     return MIX_RESULT_FAIL;
 
 // if AM is enable, and not_registered, then register
-  if (mix->useIAM && !mix->am_registered) {
+  if ((audioconfigparams->audio_manager == MIX_AUDIOMANAGER_INTELAUDIOMANAGER) && !mix->am_registered) {
+//  if (!mix->am_registered) {  // TODO: remove this and uncomment line above
+    mix_log(MIX_AUDIO_COMP, MIX_LOG_LEVEL_INFO, "audio_manager=MIX_AUDIOMANAGER_INTELAUDIOMANAGER and !am_registered\n");
     gint32 amStreamID = lpe_stream_register(mix->streamID, "music", audioconfigparams->stream_name, codec_mode);
 
     if (amStreamID == -1){
       mix->amStreamID = 0;
-        return MIX_RESULT_FAIL;
+      mix_log(MIX_AUDIO_COMP, MIX_LOG_LEVEL_INFO, "AM register failed: general error\n");
+      return MIX_RESULT_AM_REGISTER_FAIL;
     }
-    else if (amStreamID == -2) {	// -2: Direct render not avail, see AM spec
+    else if (amStreamID == -2) {        // -2: Direct render not avail, see AM spec
       mix->amStreamID = 0;
+      mix_log(MIX_AUDIO_COMP, MIX_LOG_LEVEL_INFO, "AM register failed: Direct render not available\n");
       return MIX_RESULT_DIRECT_NOTAVAIL;
     }
     mix->am_registered = TRUE;
@@ -1058,33 +1130,41 @@
   for (i=0; i < iovoutcnt; i++)
   {
     vec[i].iov_base = iovout[i].data;
-    vec[i].iov_len = iovout[i].size;
+    vec[i].iov_len = iovout[i].buffer_size;
+    iovout[i].data_size = 0;
   }
 
   mix_log(MIX_AUDIO_COMP, MIX_LOG_LEVEL_INFO, "begin readv()\n");
   bytes_read = readv(mix->fileDescriptor, vec, iovoutcnt);
   mix_log(MIX_AUDIO_COMP, MIX_LOG_LEVEL_INFO, "end readv(), return: %d\n", bytes_read);
-  if (bytes_read < 0) { // TODO: should not be 0, but driver return 0 right now
+  if (bytes_read < 1) { 
     mix_log(MIX_AUDIO_COMP, MIX_LOG_LEVEL_ERROR, "return: %d\n", bytes_read);
     return MIX_RESULT_FAIL;
   }
-/* 
-  gint bytes_count=0;
-  for (i=0; i < iovoutcnt; i++)
+
+  i=0;
+  while (bytes_read > 0)
   {
-    bytes_count += iovout[i].size;
+    if (bytes_read > iovout[i].buffer_size) {
+      iovout[i].data_size = iovout[i].buffer_size;
+      bytes_read = bytes_read - iovout[i].buffer_size;
+    }
+    else {
+      iovout[i].data_size = bytes_read;
+      bytes_read = 0;
+    }
+    i++;
   }
-  iovout[i].size = bytes_read - bytes_count;
-*/
+
   return MIX_RESULT_SUCCESS;
 }
 
 MIX_RESULT mix_audio_get_max_vol_default(MixAudio *mix, gint *maxvol)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
-
+    // API version 0.79. 1/22/2009
   MIX_RESULT ret = MIX_RESULT_SUCCESS;
 
+  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
   if (!maxvol) return MIX_RESULT_NULL_PTR;
 
   _LOCK(&mix->controllock);
@@ -1107,10 +1187,10 @@
 
 MIX_RESULT mix_audio_get_min_vol_default(MixAudio *mix, gint *minvol)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
-
+    // API version 0.79. 1/22/2009
   MIX_RESULT ret = MIX_RESULT_SUCCESS;
 
+  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
   if (!minvol) return MIX_RESULT_NULL_PTR;
 
   _LOCK(&mix->controllock);
@@ -1132,57 +1212,73 @@
 
 MIX_RESULT mix_audio_get_stream_state_default(MixAudio *mix, MixStreamState *streamState)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
 
-  if (!streamState) return MIX_RESULT_NULL_PTR;
+    if (G_UNLIKELY(mix==NULL)) return MIX_RESULT_NULL_PTR;
+    if (streamState == NULL) return MIX_RESULT_NULL_PTR;
 
-  _LOCK(&mix->controllock);
+    _LOCK(&mix->controllock);
 
-  if (mix->state != MIX_STATE_CONFIGURED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
+    if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
 
-  // PAUSED_DRAINING is internal state.
-  if (mix->streamState == MIX_STREAM_PAUSED_DRAINING)
-    *streamState = MIX_STREAM_PAUSED;
-  else
-    *streamState = mix->streamState;
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
 
-  _UNLOCK(&mix->controllock);
+    // PAUSED_DRAINING is internal state.
+    if (mix->streamState == MIX_STREAM_PAUSED_DRAINING)
+        *streamState = MIX_STREAM_PAUSED;
+    else
+        *streamState = mix->streamState;
 
-  return MIX_RESULT_SUCCESS;
+    _UNLOCK(&mix->controllock);
+
+    return MIX_RESULT_SUCCESS;
 }
 
 
 MIX_RESULT mix_audio_get_volume_default(MixAudio *mix, gint *currvol, MixVolType type)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    struct snd_sst_vol vol = {0};
+    int retVal = 0;
+    
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    if (!currvol) return MIX_RESULT_NULL_PTR;
+    if ((type != MIX_VOL_PERCENT) && (type != MIX_VOL_DECIBELS)) return MIX_RESULT_INVALID_PARAM;
 
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    _LOCK(&mix->controllock);
 
-  struct snd_sst_vol vol = {0};
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
 
-  if (!currvol) return MIX_RESULT_NULL_PTR;
-  if ((type != MIX_VOL_PERCENT) && (type != MIX_VOL_DECIBELS)) return MIX_RESULT_INVALID_PARAM;
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
 
-  _LOCK(&mix->controllock);
+    vol.stream_id = mix->streamID;
 
-  if (mix->state != MIX_STATE_CONFIGURED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
-
-  vol.stream_id = mix->streamID;
-
-  int retVal = 0;
 
 #ifdef LPESTUB
   // Not calling.
 #else
-  g_debug("Calling SNDRV_SST_GET_VOL. fd=%d", mix->fileDescriptor);
-  retVal = ioctl(mix->fileDescriptor, SNDRV_SST_GET_VOL, &vol);
-  g_debug("SNDRV_SST_GET_VOL returned %d. vol=%d", retVal, vol.volume);
+    g_debug("Calling _GET_VOL. fd=%d", mix->fileDescriptor);
+    retVal = ioctl(mix->fileDescriptor, SNDRV_SST_GET_VOL, &vol);
+    g_debug("_GET_VOL returned %d. vol=%d", retVal, vol.volume);
 #endif
 
-  if (retVal)
+  if (retVal != 0)
   {
     ret = MIX_RESULT_SYSTEM_ERRNO; 
-    g_debug("_GET_VOL failed. Error:0x%08x", errno);
+    g_debug("_GET_VOL failed. Error(0x%08x): %s", errno, strerror(errno));
     mix_audio_debug_dump(mix);
   }
   else
@@ -1206,42 +1302,77 @@
 
 MIX_RESULT mix_audio_get_mute_default(MixAudio *mix, gboolean* muted)
 {
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
-  return ret;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    if (muted == NULL) return MIX_RESULT_NULL_PTR;
+
+    _LOCK(&mix->controllock);
+
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
+
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
+
+    *muted = mix->stream_muted;
+
+    _UNLOCK(&mix->controllock);
+
+    return ret;
 }
 
 MIX_RESULT mix_audio_set_mute_default(MixAudio *mix, gboolean mute)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    int retVal = 0;
 
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
 
-  struct snd_sst_mute m = { 0 };
+    struct snd_sst_mute m = { 0 };
 
-  if (mute) m.mute = 1;
-  else m.mute = 0;
+    if (mute) m.mute = 1;
+    else m.mute = 0;
 
-  _LOCK(&mix->controllock);
+    _LOCK(&mix->controllock);
 
-  if (mix->state != MIX_STATE_CONFIGURED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
 
-  m.stream_id = mix->streamID;
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
 
-  int retVal = 0;
+    m.stream_id = mix->streamID;
 
 #ifdef LPESTUB
   // Not calling.
 #else
-  retVal = ioctl(mix->fileDescriptor, SNDRV_SST_MUTE, &m);
+    g_debug("Calling _MUTE. fd=%d", mix->fileDescriptor);
+    retVal = ioctl(mix->fileDescriptor, SNDRV_SST_MUTE, &m);
+    g_debug("_MUTE returned %d", retVal);
 #endif
 
-  if (retVal)
-  {
-    //ret = MIX_RESULT_FAIL;
-    ret = MIX_RESULT_SYSTEM_ERRNO; 
-    g_debug("_MUTE failed. Error:0x%08x", errno);
-    mix_audio_debug_dump(mix);
-  }
+    if (retVal != 0)
+    {
+        ret = MIX_RESULT_SYSTEM_ERRNO; 
+        g_debug("_MUTE failed. Error(0x%08x): %s", errno, strerror(errno));
+        mix_audio_debug_dump(mix);
+    }
+    else
+    {
+        mix->stream_muted = mute;
+    }
 
   _UNLOCK(&mix->controllock);
 
@@ -1250,38 +1381,51 @@
 
 MIX_RESULT mix_audio_pause_default(MixAudio *mix)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    int retVal = 0;
 
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    if (G_UNLIKELY(mix==NULL)) return MIX_RESULT_NULL_PTR;
 
-  _LOCK(&mix->controllock);
+    _LOCK(&mix->controllock);
 
-  if (mix->state != MIX_STATE_CONFIGURED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
+    else if ((mix->streamState != MIX_STREAM_PLAYING) && (mix->streamState != MIX_STREAM_DRAINING))
+        ret = MIX_RESULT_WRONG_STATE;
 
-  if (mix->streamState == MIX_STREAM_PAUSED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_SUCCESS);
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
 
-  if ((mix->streamState != MIX_STREAM_PLAYING) && (mix->streamState != MIX_STREAM_DRAINING))
-    _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_WRONG_STATE);
-
-  int retVal = 0;
+    // If stream is paused, return success.
+    if ((mix->streamState == MIX_STREAM_PAUSED) ||
+        (mix->streamState == MIX_STREAM_PAUSED_DRAINING))
+    {
+        g_debug("Stream already paused.");
+        _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_SUCCESS);
+    }
 
 #ifdef LPESTUB
   // Not calling
 #else
-  g_debug("Calling SNDRV_SST_STREAM_PAUSE. fd=%d", mix->fileDescriptor);
-  retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_PAUSE);
-  g_debug("_PAUSE returned %d", retVal);
+    g_debug("Calling SNDRV_SST_STREAM_PAUSE. fd=%d", mix->fileDescriptor);
+    retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_PAUSE);
+    g_debug("_PAUSE returned %d", retVal);
 #endif
 
-  if (retVal)
+  if (retVal != 0)
   {
     if (mix->streamState == MIX_STREAM_DRAINING)
     {
-      // if stream state has been DRAINING, DRAIN could become successful during the PAUSE call, but not yet have chance to update streamState since we now hold the lock. 
+      // if stream state has been DRAINING, DRAIN could become successful during the PAUSE call, but not yet have chance to update streamState since we now hold the control lock. 
       // In this case, the mix_streamState becomes out-of-sync with the actual playback state. PAUSE failed due to stream already STOPPED but mix->streamState remains at "DRAINING"
       // On the other hand, we can't let DRAIN hold the lock the entire time.
       // We would not know if we fail PAUSE due to DRAINING, or a valid reason.
-      // Need a better mechanism to sync DRAINING.
       // DRAINING is not likely problem for resume, as long as the PAUSED state is set when stream is really PAUSED.
       ret = MIX_RESULT_NEED_RETRY;
       g_warning("PAUSE failed while DRAINING. Draining could be just completed. Retry needed.");
@@ -1296,13 +1440,16 @@
   else
   {
     if (mix->streamState == MIX_STREAM_DRAINING)
-    {
       mix->streamState = MIX_STREAM_PAUSED_DRAINING;
-    }
     else
-    {
       mix->streamState = MIX_STREAM_PAUSED;
+
+#ifdef AUDIO_MANAGER
+    if (lpe_stream_notify_pause(mix->amStreamID) != 0) 
+    {
+        ret = MIX_RESULT_AM_NOTIFY_PAUSE_FAIL;
     }
+#endif
   }
 
   _UNLOCK(&mix->controllock);
@@ -1322,41 +1469,61 @@
 
 MIX_RESULT mix_audio_resume_default(MixAudio *mix)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    int retVal = 0;
 
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
 
-  _LOCK(&mix->controllock);
+    _LOCK(&mix->controllock);
 
-  if (mix->state != MIX_STATE_CONFIGURED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
+    else if ((mix->streamState != MIX_STREAM_PAUSED) && (mix->streamState != MIX_STREAM_PAUSED_DRAINING))
+        ret = MIX_RESULT_WRONG_STATE;
 
-  if ((mix->streamState == MIX_STREAM_PLAYING) || (mix->streamState == MIX_STREAM_DRAINING))
-    _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_SUCCESS);
-  
-  if ((mix->streamState != MIX_STREAM_PAUSED_DRAINING) && (mix->streamState != MIX_STREAM_PAUSED))
-    _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_WRONG_STATE);
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
 
-  int retVal = 0;
+    // If stream is paused, return success.
+    if ((mix->streamState == MIX_STREAM_PLAYING) ||
+        (mix->streamState == MIX_STREAM_DRAINING))
+    {
+        g_debug("Stream already playing.");
+        _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_SUCCESS);
+    }
 
 #ifdef LPESTUB
   // Not calling
 #else
-  g_debug("Calling SNDRV_SST_STREAM_RESUME");
+  g_debug("Calling SNDRV_SST_STREAM_RESUME. fd=%d", mix->fileDescriptor);
   retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_RESUME);
   g_debug("_STREAM_RESUME returned %d", retVal);
 #endif
 
-  if (retVal)
+  if (retVal != 0)
   {
     ret = MIX_RESULT_SYSTEM_ERRNO; 
     g_debug("_PAUSE failed. Error:0x%08x", errno);
     mix_audio_debug_dump(mix);
   }
+  else 
   {
     if (mix->streamState == MIX_STREAM_PAUSED_DRAINING)
       mix->streamState = MIX_STREAM_DRAINING;
     else
       mix->streamState = MIX_STREAM_PLAYING;
+ 
+#ifdef AUDIO_MANAGER
+    if (lpe_stream_notify_resume(mix->amStreamID) != 0) {
+      ret = MIX_RESULT_AM_NOTIFY_RESUME_FAIL;
+    }
+#endif
   }
 
   _UNLOCK(&mix->controllock);
@@ -1376,57 +1543,63 @@
 
 MIX_RESULT mix_audio_set_volume_default(MixAudio *mix, gint currvol, MixVolType type, gulong msecs, MixVolRamp ramptype)
 {
-  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
-
-  MIX_RESULT ret = MIX_RESULT_SUCCESS;
-
-  struct snd_sst_vol vol = {0};
-
-  vol.ramp_duration = msecs;
-  vol.ramp_type = ramptype; // TODO: confirm the mappings between Mix and SST.
-
-  if (!mix) return MIX_RESULT_NULL_PTR;
-
-  if ((type != MIX_VOL_PERCENT) && (type != MIX_VOL_DECIBELS)) return MIX_RESULT_INVALID_PARAM;
-
-  _LOCK(&mix->controllock);
-
-  if (mix->state != MIX_STATE_CONFIGURED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
-
-  vol.stream_id = mix->streamID;
-
-  if (type == MIX_VOL_DECIBELS)
-  {
-    vol.volume = currvol;
-  }
-  else
-  {
-    gint maxvol = 0;
-    ret = mix_audio_get_max_vol(mix, &maxvol);
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    int retVal = 0;
+    struct snd_sst_vol vol = {
+        .ramp_duration = msecs,
+        .ramp_type = ramptype
+    };
     
-    if (!maxvol)
-      g_critical("Max Vol is 0!");
+    if (G_UNLIKELY(mix == NULL)) return MIX_RESULT_NULL_PTR;
+    if ((type != MIX_VOL_PERCENT) && (type != MIX_VOL_DECIBELS)) return MIX_RESULT_INVALID_PARAM;
+    
+    _LOCK(&mix->controllock);
 
-    if (MIX_SUCCEEDED(ret))
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
+
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
+
+    vol.stream_id = mix->streamID;
+
+    if (type == MIX_VOL_DECIBELS)
     {
-      vol.volume = currvol * maxvol / 100;
+        vol.volume = currvol;
     }
-  }
+    else
+    {
+        gint maxvol = 0;
+        ret = mix_audio_get_max_vol(mix, &maxvol);
+        
+        if (!maxvol)
+        g_critical("Max Vol is 0!");
+    
+        if (MIX_SUCCEEDED(ret))
+        {
+        vol.volume = currvol * maxvol / 100;
+        }
+    }
 
-  int retVal = 0;
 
 #ifdef LPESTUB
   // Not calling
 #else
-  g_debug("calling SNDRV_SST_SET_VOL vol=%d", vol.volume);
+  g_debug("calling _SET_VOL vol=%d", vol.volume);
   retVal = ioctl(mix->fileDescriptor, SNDRV_SST_SET_VOL, &vol);
-  g_debug("SNDRV_SST_SET_VOL returned %d", retVal);
+  g_debug("_SET_VOL returned %d", retVal);
 #endif
 
-  if (retVal)
+  if (retVal != 0)
   {
     ret = MIX_RESULT_SYSTEM_ERRNO; 
-    g_debug("_SET_VOL failed. Error:0x%08x", errno);
+    g_debug("_SET_VOL failed. Error(0x%08x): %s", errno, strerror(errno));
     mix_audio_debug_dump(mix);
   }
 
@@ -1496,7 +1669,7 @@
   for (i=0;i<iovincnt;i++)
   {
     in[i].iov_base = (void*)iovin[i].data;
-    in[i].iov_len = (size_t)iovin[i].size;
+    in[i].iov_len = (size_t)iovin[i].data_size;
     total_bytes += in[i].iov_len;
   }
 
@@ -1552,7 +1725,7 @@
   return ret;
 }
 
-static MIX_RESULT mix_audio_SST_STREAM_DECODE(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt, guint64 *outsize)
+static MIX_RESULT mix_audio_SST_STREAM_DECODE(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt)
 {
   MIX_RESULT ret = MIX_RESULT_SUCCESS;
   int retVal = 0;
@@ -1594,14 +1767,14 @@
   int i = 0;
   for (i=0;i<iovincnt;i++)
   {
-    ientries[i].size = (unsigned long)iovin[i].size;
+    ientries[i].size = (unsigned long)iovin[i].data_size;
     ientries[i].buffer = (void *)iovin[i].data;
     g_debug("Creating in entry#%d, size=%u", i, ientries[i].size);
   }
 
   for (i=0;i<iovoutcnt;i++)
   {
-    oentries[i].size = (unsigned long)iovout[i].size;
+    oentries[i].size = (unsigned long)iovout[i].buffer_size;
     oentries[i].buffer = (void *)iovout[i].data;
     g_debug("Creating out entry#%d, size=%u", i, oentries[i].size);
   }
@@ -1615,11 +1788,11 @@
     for (i=0;i<iovincnt-1;i++)
     {
       in[i].iov_base = (void*)iovin[i].data;
-      in[i].iov_len = (size_t)iovin[i].size;
+      in[i].iov_len = (size_t)iovin[i].data_size;
       total_bytes += in[i].iov_len;
     }
     in[i].iov_base = (void*)iovin[i].data;
-    in[i].iov_len = (size_t)iovin[i].size/2;
+    in[i].iov_len = (size_t)iovin[i].data_size/2;
     total_bytes += in[i].iov_len;
   }
   else
@@ -1627,7 +1800,7 @@
     for (i=0;i<iovincnt;i++)
     {
       in[i].iov_base = (void*)iovin[i].data;
-      in[i].iov_len = (size_t)iovin[i].size;
+      in[i].iov_len = (size_t)iovin[i].data_size;
       total_bytes += in[i].iov_len;
     }
   }
@@ -1657,8 +1830,36 @@
   else
   {
     if (insize) *insize = dbufs.input_bytes_consumed;
-    if (outsize) *outsize = dbufs.output_bytes_produced;
-    g_message("consumed=%" G_GUINT64_FORMAT " produced=%" G_GUINT64_FORMAT, dbufs.input_bytes_consumed, dbufs.output_bytes_produced);
+    //if (outsize) *outsize = dbufs.output_bytes_produced;
+    unsigned long long produced = dbufs.output_bytes_produced;
+    int i;
+    for (i=0;i<iovoutcnt;i++)
+    {
+        if (produced != 0)
+        {
+            if (produced > iovout[i].buffer_size)
+            {
+                iovout[i].data_size = iovout[i].buffer_size;
+                produced -= iovout[i].data_size;
+            }
+            else
+            {
+                iovout[i].data_size = produced;
+                produced = 0;
+            }
+        }
+        else
+        {
+            iovout[i].data_size = 0;
+        }
+    }
+    produced = 0;
+    for (i=0;i<iovoutcnt;i++)
+    {
+        produced += iovout[i].data_size;
+    }
+    g_message("consumed=%" G_GUINT64_FORMAT " produced=%" G_GUINT64_FORMAT "(%" G_GUINT64_FORMAT ")", dbufs.input_bytes_consumed, dbufs.output_bytes_produced, produced);
+
   }
 
   return ret;
@@ -1701,7 +1902,7 @@
   return klass->configure(mix, audioconfigparams, drmparams);
 }
 
-MIX_RESULT mix_audio_decode(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt, guint64 *outsize)
+MIX_RESULT mix_audio_decode(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt)
 {
   if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
 
@@ -1710,7 +1911,7 @@
   if (!klass->decode)
     return MIX_RESULT_FAIL;
 
-  return klass->decode(mix, iovin, iovincnt, insize, iovout, iovoutcnt, outsize);
+  return klass->decode(mix, iovin, iovincnt, insize, iovout, iovoutcnt);
 }
 
 MIX_RESULT mix_audio_capture_encode(MixAudio *mix, MixIOVec *iovout, gint iovoutcnt)
@@ -1905,7 +2106,7 @@
   return klass->get_state(mix, state);
 }
 
-MIX_RESULT mix_audio_is_am_available_default(MixAudio *mix, MixAudioManager am, gboolean *avail)
+MIX_RESULT mix_audio_is_am_available(MixAudioManager am, gboolean *avail)
 {
   MIX_RESULT ret = MIX_RESULT_SUCCESS;
 
@@ -1917,16 +2118,6 @@
   return ret;
 }
 
-MIX_RESULT mix_audio_is_am_available(MixAudio *mix, MixAudioManager am, gboolean *avail)
-{
-  MixAudioClass *klass = MIX_AUDIO_GET_CLASS(mix);
-
-  if (!klass->is_am_available)
-    return MIX_RESULT_FAIL;
-
-  return klass->is_am_available(mix, am, avail);
-}
-
 const gchar* dbgstr_UNKNOWN="UNKNOWN";
 
 static const gchar* _mix_stream_state_get_name (MixStreamState s)
@@ -2046,20 +2237,21 @@
   return;
 }
 
-MIX_RESULT mix_audio_get_output_configuration(MixAudio *mix, MixAudioConfigParams **audioconfigparams)
+MIX_RESULT mix_audio_get_config(MixAudio *mix, MixAudioConfigParams **audioconfigparams)
 {
   if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
 
   MixAudioClass *klass = MIX_AUDIO_GET_CLASS(mix);
 
-  if (!klass->get_output_configuration)
+  if (!klass->get_config)
     return MIX_RESULT_FAIL;
 
-  return klass->get_output_configuration(mix, audioconfigparams);
+  return klass->get_config(mix, audioconfigparams);
 }
 
-MIX_RESULT mix_audio_get_output_configuration_default(MixAudio *mix, MixAudioConfigParams **audioconfigparams)
+MIX_RESULT mix_audio_get_config_default(MixAudio *mix, MixAudioConfigParams **audioconfigparams)
 {
+  // API version 0.79. 1/22/2009
   MIX_RESULT ret = MIX_RESULT_SUCCESS;
   struct snd_sst_get_stream_params stream_params = {{0}};
   MixAudioConfigParams *p = NULL;
@@ -2069,7 +2261,8 @@
 
   _LOCK(&mix->controllock);
 
-  if (mix->state <= MIX_STATE_UNINITIALIZED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_INIT);
+  // _get_config is called only it is configured.
+  if (mix->state != MIX_STATE_CONFIGURED) _UNLOCK_RETURN(&mix->controllock, MIX_RESULT_NOT_CONFIGURED);
 
 #ifdef LPESTUB
 #else
@@ -2079,9 +2272,7 @@
     g_debug("_GET_PARAMS returned %d", retVal);
 #endif
 
-  _UNLOCK(&mix->controllock);
-
-  if (retVal)
+  if (retVal != 0)
   {
       ret = MIX_RESULT_SYSTEM_ERRNO; 
       g_debug("Failed to GET_PARAMS. errno:0x%08x. %s\n", errno, strerror(errno));
@@ -2089,14 +2280,232 @@
   else
   {
       p = mix_sst_params_to_acp(&stream_params);
+      if (p != NULL)
+      {
+         if (mix->audioconfigparams != NULL)
+         {
+            // Complete the return structure with fields that are not returned from the SST.
+            MIX_ACP_DECODEMODE(p) = MIX_ACP_DECODEMODE(mix->audioconfigparams);
+
+            gchar *sn = mix_acp_get_streamname(mix->audioconfigparams);
+            if (sn != NULL)
+            {
+                if (!MIX_SUCCEEDED(mix_acp_set_streamname(MIX_AUDIOCONFIGPARAMS(p), sn)))
+                {
+                    g_error("Failed to set stream name!");
+                }
+                g_free(sn);
+            }
+
+            if (!MIX_SUCCEEDED(mix_acp_set_audio_manager(MIX_AUDIOCONFIGPARAMS(p), mix_acp_get_audio_manager(mix->audioconfigparams))))
+            {
+                g_error("Failed to set audio manager!");
+            }
+
+            // remove existingi copy of audioconfigparams and copy this return struct.
+            mix_acp_unref(mix->audioconfigparams);
+            mix->audioconfigparams = NULL;
+         }
+
+         mix->audioconfigparams = MIX_AUDIOCONFIGPARAMS(mix_params_dup(MIX_PARAMS(p)));
+      }
       *audioconfigparams = p;
   }
 
+  _UNLOCK(&mix->controllock);
+
   return ret;
 }
 
-MIX_RESULT mix_audio_get_stream_byte_decoded(MixAudio *mix, guint64 *byte)
+MIX_RESULT mix_audio_get_bytes_decoded(MixAudio *mix, guint64 *byte)
 {
-    return MIX_RESULT_NOT_SUPPORTED;
+  if (G_UNLIKELY(!mix)) return MIX_RESULT_NULL_PTR;
+
+  MixAudioClass *klass = MIX_AUDIO_GET_CLASS(mix);
+
+  if (!klass->get_bytes_decoded)
+    return MIX_RESULT_FAIL;
+
+  return klass->get_bytes_decoded(mix, byte);
 }
 
+MIX_RESULT mix_audio_get_bytes_decoded_default(MixAudio *mix, guint64 *bytecount)
+{
+    // API version 0.79. 1/22/2009
+    MIX_RESULT ret = MIX_RESULT_SUCCESS;
+    unsigned long long bytes_decoded = 0;
+    int retVal = 0;
+
+    if ((G_UNLIKELY(!mix)) || (bytecount == NULL)) return MIX_RESULT_NULL_PTR;
+
+    _LOCK(&mix->controllock);
+
+    // ret should be SUCCESS when this sequence starts...
+    if (mix->codecMode != MIX_CODING_DECODE) 
+        ret = MIX_RESULT_WRONGMODE;
+    else if (mix->state != MIX_STATE_CONFIGURED) 
+        ret = MIX_RESULT_NOT_CONFIGURED;
+    else if (MIX_ACP_DECODEMODE(mix->audioconfigparams) == MIX_DECODE_DECODERETURN)
+        ret = MIX_RESULT_WRONGMODE;
+
+    // Now check if we need to exit.
+    if (!MIX_SUCCEEDED(ret)) _UNLOCK_RETURN(&mix->controllock, ret);
+
+
+#ifdef LPESTUB
+#else
+      g_debug("Calling _STREAM_BYTES_DECODED. fd=%d", mix->fileDescriptor);
+      retVal = ioctl(mix->fileDescriptor, SNDRV_SST_STREAM_BYTES_DECODED, &bytes_decoded);
+      g_debug("_STREAM_BYTES_DECODED returned %d. Bytes decoded=%" G_GUINT64_FORMAT, retVal, bytes_decoded);
+#endif
+
+      if (retVal != 0)
+      {
+        ret = MIX_RESULT_SYSTEM_ERRNO; 
+        g_debug("_STREAM_BYTES_DECODED failed. Error(0x%08x): %s", errno, strerror(errno));
+        mix_audio_debug_dump(mix);
+      }
+      else
+      {
+        *bytecount = bytes_decoded;
+      }
+
+  _UNLOCK(&mix->controllock);
+
+  return ret;
+}
+
+static MIX_RESULT mix_audio_verify_params(MixAudio *mix, const MixAudioConfigParams *audioconfigparams)
+{
+    MIX_RESULT ret = MIX_RESULT_FAIL;
+
+    if (G_UNLIKELY(!mix))
+    {
+        g_error("Null pointer passed to internal function!");
+        return MIX_RESULT_NULL_PTR;
+    }
+
+    g_message("_verify_params() starts.");
+
+    switch (mix->codecMode)
+    {
+        case MIX_CODING_DECODE:
+        {
+            if ((MIX_ACP_DECODEMODE(audioconfigparams) != MIX_DECODE_DIRECTRENDER) &&
+            (MIX_ACP_DECODEMODE(audioconfigparams) != MIX_DECODE_DECODERETURN))
+            {
+                ret = MIX_RESULT_CONF_MISMATCH;
+                goto verify_params_done;
+            }
+            break;
+        }
+        case MIX_CODING_ENCODE: 
+        {
+            if (!MIX_IS_AUDIOCONFIGPARAMSAAC(audioconfigparams))
+            {
+                ret = MIX_RESULT_CODEC_NOTSUPPORTED;
+                goto verify_params_done;
+            }
+        }
+        default:
+        break;
+    }
+
+    ret = MIX_RESULT_SUCCESS;
+
+verify_params_done:
+
+    g_message("_verify_params() done. Returning 0x%08x.", ret);
+
+    return ret;
+}
+
+static MIX_RESULT mix_audio_is_stream_changed(MixAudio *mix, MixAudioConfigParams *new_params, gboolean *pChanged)
+{
+    MIX_RESULT ret = MIX_RESULT_FAIL;
+
+    gboolean changed = FALSE;
+    MixParams *old_mask = NULL;
+    MixParams *new_mask = NULL;
+
+    g_message("is_stream_changed() starts");
+
+    if ((mix == NULL) || (new_params == NULL) || (pChanged == NULL))
+    {
+        g_error("Null pointer passed to internal function!");
+        return MIX_RESULT_NULL_PTR;
+    }
+
+    changed = (mix->audioconfigparams == NULL);
+    if (changed) 
+    {
+        ret = MIX_RESULT_SUCCESS;
+        goto stream_changed_done;
+    }
+
+    old_mask = mix_params_dup(MIX_PARAMS(mix->audioconfigparams));
+    if (MIX_IS_AUDIOCONFIGPARAMS(old_mask))
+    {
+         MIX_ACP_DECODEMODE(old_mask) = MIX_DECODE_NULL;
+         if (!MIX_SUCCEEDED(mix_acp_set_streamname(MIX_AUDIOCONFIGPARAMS(old_mask), NULL)))
+         {
+            g_error("Failed to set stream name!");
+            goto stream_changed_done;
+         }
+         if (!MIX_SUCCEEDED(mix_acp_set_audio_manager(MIX_AUDIOCONFIGPARAMS(old_mask), MIX_AUDIOMANAGER_NONE)))
+         {
+            g_error("Failed to set audio manager!");
+            goto stream_changed_done;
+         }
+    }
+    else
+    {
+        g_error("Failed to duplicate param!");
+        goto stream_changed_done;
+    }
+
+    new_mask = mix_params_dup(MIX_PARAMS(new_params));
+    if (MIX_IS_AUDIOCONFIGPARAMS(new_mask))
+    {
+         MIX_ACP_DECODEMODE(new_mask) = MIX_DECODE_NULL;
+         if (!MIX_SUCCEEDED(mix_acp_set_streamname(MIX_AUDIOCONFIGPARAMS(new_mask), NULL)))
+         {
+            g_error("Failed to set stream name!");
+            goto stream_changed_done;
+         }
+         if (!MIX_SUCCEEDED(mix_acp_set_audio_manager(MIX_AUDIOCONFIGPARAMS(new_mask), MIX_AUDIOMANAGER_NONE)))
+         {
+            g_error("Failed to set audio manager!");
+            goto stream_changed_done;
+         }
+    }
+    else
+    {
+        g_error("Failed to duplicate param!");
+        goto stream_changed_done;
+    }
+
+
+    changed = !mix_params_equal(old_mask, new_mask);
+
+    ret = MIX_RESULT_SUCCESS;
+
+stream_changed_done:
+
+    if (old_mask)
+    {
+        mix_params_unref(old_mask);
+        old_mask=NULL;
+    }
+    if (new_mask)
+    {
+        mix_params_unref(new_mask);
+        new_mask=NULL;
+    }
+
+    *pChanged = changed;
+
+    g_message("is_stream_changed() done returning 0x%08x, changed=%d", ret, changed);
+
+    return ret;
+}
diff --git a/mix_audio/src/mixaudio.h b/mix_audio/src/mixaudio.h
index a3cef5a..ca7e353 100644
--- a/mix_audio/src/mixaudio.h
+++ b/mix_audio/src/mixaudio.h
@@ -120,7 +120,8 @@
  */
 typedef struct {
   guchar *data;
-  gint size;
+  gint32 buffer_size;
+  gint32 data_size;
 } MixIOVec;
 
 /**
@@ -151,7 +152,7 @@
   /*< virtual public >*/
   MIX_RESULT (*initialize) (MixAudio *mix, MixCodecMode mode, MixAudioInitParams *aip, MixDrmParams *drminitparams);
   MIX_RESULT (*configure) (MixAudio *mix, MixAudioConfigParams *audioconfigparams, MixDrmParams *drmparams);
-  MIX_RESULT (*decode) (MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt, guint64 *outsize);
+  MIX_RESULT (*decode) (MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt);
   MIX_RESULT (*capture_encode) (MixAudio *mix, MixIOVec *iovout, gint iovoutcnt);
   MIX_RESULT (*start) (MixAudio *mix);
   MIX_RESULT (*stop_drop) (MixAudio *mix);
@@ -168,8 +169,8 @@
   MIX_RESULT (*deinitialize) (MixAudio *mix);
   MIX_RESULT (*get_stream_state) (MixAudio *mix, MixStreamState *streamState);
   MIX_RESULT (*get_state) (MixAudio *mix, MixState *state);
-  MIX_RESULT (*is_am_available) (MixAudio *mix, MixAudioManager am, gboolean *avail);
-  MIX_RESULT (*get_output_configuration) (MixAudio *mix, MixAudioConfigParams **audioconfigparams);
+  MIX_RESULT (*get_config) (MixAudio *mix, MixAudioConfigParams **audioconfigparams);
+  MIX_RESULT (*get_bytes_decoded) (MixAudio *mix, guint64 *byte);
 };
 
 /**
@@ -197,7 +198,6 @@
   gchar *encoding;
   MixState state;
   MixCodecMode codecMode;
-  gboolean useIAM;
   int fileDescriptor;
   gint streamID;
   guint32 amStreamID;
@@ -206,6 +206,7 @@
   MixAudioConfigParams *audioconfigparams;
   gboolean am_registered;
   MixDeviceState deviceState;
+  gboolean stream_muted;
 
   guint64 ts_last;
   guint64 ts_elapsed;
@@ -330,7 +331,7 @@
  * Note: If the stream is configured as #MIX_DECODE_DIRECTRENDER, and whenever the stream in #MIX_STREAM_STOPPED state, the call to mix_audio_decode() will not start the playback until mix_audio_start() is called. This behavior would allow application to queue up data but delay the playback until appropriate time.
  * 
  */
-MIX_RESULT mix_audio_decode(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt, guint64 *outsize);
+MIX_RESULT mix_audio_decode(MixAudio *mix, const MixIOVec *iovin, gint iovincnt, guint64 *insize, MixIOVec *iovout, gint iovoutcnt);
 
 /**
  * mix_audio_capture_encode:
@@ -547,20 +548,20 @@
  * 
  * Check if AM is available.
  */
-MIX_RESULT mix_audio_is_am_available(MixAudio *mix, MixAudioManager am, gboolean *avail);
+MIX_RESULT mix_audio_is_am_available(MixAudioManager am, gboolean *avail);
 
 /**
- * mix_audio_get_output_configuration:
+ * mix_audio_get_config:
  * @mix: #MixAudio object.
  * @audioconfigparams: double pointer to hold output configuration.
  * @returns: #MIX_RESULT_SUCCESS on success or other fail code.
  * 
  * This method retrieve the current configuration. This can be called after initialization. If a stream has been configured, it returns the corresponding derive object of MixAudioConfigParams.
  */
-MIX_RESULT mix_audio_get_output_configuration(MixAudio *mix, MixAudioConfigParams **audioconfigparams);
+MIX_RESULT mix_audio_get_config(MixAudio *mix, MixAudioConfigParams **audioconfigparams);
 
 /**
- * mix_audio_get_stream_byte_decoded:
+ * mix_audio_get_bytes_decoded:
  * @mix: #MixAudio object.
  * @msecs: stream byte decoded..
  * @returns: #MIX_RESULT_SUCCESS if the value is available. #MIX_RESULT_WRONG_MODE if operation is not allowed with the current mode.
@@ -569,6 +570,6 @@
  * 
  * <remark>Not Implemented.</remark>
  */
-MIX_RESULT mix_audio_get_stream_byte_decoded(MixAudio *mix, guint64 *byte);
+MIX_RESULT mix_audio_get_bytes_decoded(MixAudio *mix, guint64 *byte);
 
 #endif /* __MIX_AUDIO_H__ */
diff --git a/mix_audio/src/sst_proxy.c b/mix_audio/src/sst_proxy.c
index 438e06e..de7f7a4 100644
--- a/mix_audio/src/sst_proxy.c
+++ b/mix_audio/src/sst_proxy.c
@@ -147,8 +147,10 @@
         s->codec = p->codec = SST_CODEC_TYPE_AAC;
     }
 
-    p->num_chan = MIX_ACP_AAC_CHANNELS(acp); // core/internal channels
-    p->ext_chl = MIX_ACP_NUM_CHANNELS(acp);  // external channels
+    p->num_chan = MIX_ACP_NUM_CHANNELS(acp);  // external channels
+    p->ext_chl = MIX_ACP_AAC_CHANNELS(acp); // extension channel configuration.
+    //p->ext_chl = MIX_ACP_AAC_CHANNELS(acp); // core/internal channels
+    if (p->num_chan <= 0) p->num_chan = p->ext_chl;
     p->aac_srate = MIX_ACP_AAC_SAMPLE_RATE(acp);  // aac decoder internal frequency
     p->sfreq = MIX_ACP_SAMPLE_FREQ(acp);  // output/external frequency
     
diff --git a/mix_common/ChangeLog b/mix_common/ChangeLog
index b3469f8..d5dceab 100644
--- a/mix_common/ChangeLog
+++ b/mix_common/ChangeLog
@@ -1,3 +1,7 @@
+2010-01-25  Echo Choi  <echo@firefly>
+
+	* Updated version to 0.1.8
+
 2010-01-11  Echo Choi  <echo@firefly>
 
 	* Updated version to 0.1.6
diff --git a/mix_common/configure.ac b/mix_common/configure.ac
index 2165138..2dfa6aa 100644
--- a/mix_common/configure.ac
+++ b/mix_common/configure.ac
@@ -2,7 +2,7 @@
 
 AC_CONFIG_MACRO_DIR(m4)
 
-AS_MIX_VERSION(mixcommon, MIXCOMMON, 0, 1, 7)
+AS_MIX_VERSION(mixcommon, MIXCOMMON, 0, 1, 8)
 
 AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
 #AM_INIT_AUTOMAKE([-Wall -Werror foreign])
diff --git a/mix_common/mixcommon.spec b/mix_common/mixcommon.spec
index 46f900a..be17602 100644
--- a/mix_common/mixcommon.spec
+++ b/mix_common/mixcommon.spec
@@ -1,6 +1,6 @@
 Summary: MIX Common
 Name: mixcommon
-Version: 0.1.7
+Version: 0.1.8
 Release: 1
 Source0: %{name}-%{version}.tar.gz
 NoSource: 0
diff --git a/mix_common/src/mixlog.c b/mix_common/src/mixlog.c
index 0d306e4..239920e 100644
--- a/mix_common/src/mixlog.c
+++ b/mix_common/src/mixlog.c
@@ -257,3 +257,4 @@
 #endif /* MIX_LOG_USE_HT */
 
 #endif /* !ANDROID */
+
diff --git a/mix_common/src/mixlog.h b/mix_common/src/mixlog.h
index 906e6c9..99ab4e2 100644
--- a/mix_common/src/mixlog.h
+++ b/mix_common/src/mixlog.h
@@ -31,6 +31,7 @@
 #define MIX_LOG_LEVEL_INFO	3
 #define MIX_LOG_LEVEL_VERBOSE	4
 
+
 /* MACROS for mixlog */
 #ifdef MIX_LOG_ENABLE
 
diff --git a/mix_common/src/mixresult.h b/mix_common/src/mixresult.h
index 9472a7e..0559bc2 100644
--- a/mix_common/src/mixresult.h
+++ b/mix_common/src/mixresult.h
@@ -69,6 +69,10 @@
         MIX_RESULT_NO_MEMORY = (MIX_RESULT)0x80000016,
         MIX_RESULT_NEED_RETRY = (MIX_RESULT)0x80000017,
         MIX_RESULT_SYSTEM_ERRNO = (MIX_RESULT)0x80000018,
+        MIX_RESULT_AM_REGISTER_FAIL = (MIX_RESULT)0x80000019,
+	MIX_RESULT_AM_UNREGISTER_FAIL = (MIX_RESULT)0x80000020,
+	MIX_RESULT_AM_NOTIFY_PAUSE_FAIL = (MIX_RESULT)0x80000021,
+	MIX_RESULT_AM_NOTIFY_RESUME_FAIL = (MIX_RESULT)0x80000022,
 
 	/** Module specific errors starting number */