--- a/src/libxineadec/nosefart/nes_apu.c
+++ b/src/libxineadec/nosefart/nes_apu.c
@@ -57,6 +57,11 @@
 static int8 noise_short_lut[APU_NOISE_93];
 #endif /* !REALTIME_NOISE */
 
+/* $$$ ben : last error */
+#define SET_APU_ERROR(APU,X) \
+if (APU) (APU)->errstr = "apu: " X; else
+
+#define APU_MIX_ENABLE(BIT) (apu->mix_enable&(1<<(BIT)))
 
 /* vblank length table used for rectangles, triangle, noise */
 static const uint8 vbl_length[32] =
@@ -102,27 +107,32 @@
 /* ratios of pos/neg pulse for rectangle waves */
 static const int duty_lut[4] = { 2, 4, 8, 12 };
 
-#if 0 /* unused */
-static void apu_setcontext(apu_t *src_apu)
+
+void apu_setcontext(apu_t *src_apu)
 {
    apu = src_apu;
-}
-#endif
+   /* $$$ ben reset eoor string here. */
+   SET_APU_ERROR(apu,"no error");
+}
 
 /*
 ** Simple queue routines
 */
 #define  APU_QEMPTY()   (apu->q_head == apu->q_tail)
 
-static void apu_enqueue(apudata_t *d)
+static int apu_enqueue(apudata_t *d)
 {
    ASSERT(apu);
    apu->queue[apu->q_head] = *d;
 
    apu->q_head = (apu->q_head + 1) & APUQUEUE_MASK;
 
-   if (APU_QEMPTY())
+   if (APU_QEMPTY()) {
       log_printf("apu: queue overflow\n");      
+      SET_APU_ERROR(apu,"queue overflow");
+      return -1;
+   }
+   return 0;
 }
 
 static apudata_t *apu_dequeue(void)
@@ -131,19 +141,32 @@
 
    ASSERT(apu);
 
-   if (APU_QEMPTY())
-      log_printf("apu: queue empty\n");
-
+   if (APU_QEMPTY()) {
+     log_printf("apu: queue empty\n");
+     SET_APU_ERROR(apu,"queue empty");
+     /* $$$ ben : should return 0 ??? */
+   }
    loc = apu->q_tail;
    apu->q_tail = (apu->q_tail + 1) & APUQUEUE_MASK;
 
    return &apu->queue[loc];
 }
 
-void apu_setchan(int chan, boolean enabled)
-{
-   ASSERT(apu);
-   apu->mix_enable[chan] = enabled;
+int apu_setchan(int chan, boolean enabled)
+{
+  const unsigned int max = 6;
+  int old;
+
+  ASSERT(apu);
+  if ((unsigned int)chan >= max) {
+    SET_APU_ERROR(apu,"channel out of range");
+    return -1;
+  }
+  old = (apu->mix_enable>>chan) & 1;
+  if (enabled != (boolean)-1) {
+    apu->mix_enable = (apu->mix_enable & ~(1<<chan)) | ((!!enabled)<<chan);
+  }
+  return old;
 }
 
 /* emulation of the 15-bit shift register the
@@ -977,13 +1000,13 @@
       elapsed_cycles += APU_FROM_FIXED(apu->cycle_rate);
 
       accum = 0;
-      if (apu->mix_enable[0]) accum += apu_rectangle(&apu->rectangle[0]);
-      if (apu->mix_enable[1]) accum += apu_rectangle(&apu->rectangle[1]);
-      if (apu->mix_enable[2]) accum += apu_triangle(&apu->triangle);
-      if (apu->mix_enable[3]) accum += apu_noise(&apu->noise);
-      if (apu->mix_enable[4]) accum += apu_dmc(&apu->dmc);
-
-      if (apu->ext && apu->mix_enable[5]) accum += apu->ext->process();
+      if (APU_MIX_ENABLE(0)) accum += apu_rectangle(&apu->rectangle[0]);
+      if (APU_MIX_ENABLE(1)) accum += apu_rectangle(&apu->rectangle[1]);
+      if (APU_MIX_ENABLE(2)) accum += apu_triangle(&apu->triangle);
+      if (APU_MIX_ENABLE(3)) accum += apu_noise(&apu->noise);
+      if (APU_MIX_ENABLE(4)) accum += apu_dmc(&apu->dmc);
+
+      if (apu->ext && APU_MIX_ENABLE(5)) accum += apu->ext->process();
 
       /* do any filtering */
       if (APU_FILTER_NONE != apu->filter_type)
@@ -1012,11 +1035,12 @@
 
       /* signed 16-bit output, unsigned 8-bit */
       if (16 == apu->sample_bits) {
-         *((int16 *) buffer) = (int16) accum; 
-         buffer = (int16 *) buffer + 1;
-      } else {
-         *((uint8 *) buffer) = (accum >> 8) ^ 0x80; 
-         buffer = (int8 *) buffer + 1;
+         *(int16 *)(buffer) = (int16) accum;
+         buffer += sizeof(int16);
+      }
+      else {
+         *(uint8 *)(buffer) = (accum >> 8) ^ 0x80;
+         buffer += sizeof(uint8);
       }
    }
 
@@ -1025,10 +1049,18 @@
 }
 
 /* set the filter type */
-void apu_setfilter(int filter_type)
-{
+/* $$$ ben :
+ * Add a get feature (filter_type == -1) and returns old filter type
+ */
+int apu_setfilter(int filter_type)
+{
+  int old; 
    ASSERT(apu);
-   apu->filter_type = filter_type;
+   old = apu->filter_type;
+   if (filter_type != -1) {
+     apu->filter_type = filter_type;
+   }
+   return old;
 }
 
 void apu_reset(void)
@@ -1057,7 +1089,7 @@
       apu->ext->reset();
 }
 
-static void apu_build_luts(int num_samples)
+void apu_build_luts(int num_samples)
 {
    int i;
 
@@ -1090,12 +1122,15 @@
 apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo)
 {
    apu_t *temp_apu;
-   int channel;
+/*    int channel; */
 
    temp_apu = malloc(sizeof(apu_t));
    if (NULL == temp_apu)
       return NULL;
-
+   /* $$$ ben : safety net, in case we forgot to init something */
+   memset(temp_apu,0,sizeof(apu_t));
+
+   SET_APU_ERROR(temp_apu,"no error");
    temp_apu->sample_rate = sample_rate;
    temp_apu->refresh_rate = refresh_rate;
    temp_apu->sample_bits = sample_bits;
@@ -1114,8 +1149,9 @@
    apu_setactive(temp_apu);
    apu_reset();
 
-   for (channel = 0; channel < 6; channel++)
-      apu_setchan(channel, TRUE);
+   temp_apu->mix_enable = 0x3F;
+/*    for (channel = 0; channel < 6; channel++) */
+/*       apu_setchan(channel, TRUE); */
 
    apu_setfilter(APU_FILTER_LOWPASS);
 
@@ -1137,15 +1173,23 @@
    }
 }
 
-void apu_setext(apu_t *src_apu, apuext_t *ext)
+int apu_setext(apu_t *src_apu, apuext_t *ext)
 {
    ASSERT(src_apu);
+
+   /* $$$ ben : seem cleaner like this */
+   if (src_apu->ext) {
+     src_apu->ext->shutdown();
+   }
 
    src_apu->ext = ext;
 
    /* initialize it */
    if (src_apu->ext)
       src_apu->ext->init();
+
+   /* $$$ ben : May be one day extension int () will return error code */
+   return 0;
 }
 
 /* this exists for external mixing routines */