Index: pjproject/trunk/pjmedia/include/pjmedia/event.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/event.h	(revision 5919)
+++ pjproject/trunk/pjmedia/include/pjmedia/event.h	(revision 5920)
@@ -88,5 +88,10 @@
      * RTCP-FB has been received.
      */
-    PJMEDIA_EVENT_RX_RTCP_FB = PJMEDIA_FOURCC('R', 'T', 'F', 'B')
+    PJMEDIA_EVENT_RX_RTCP_FB = PJMEDIA_FOURCC('R', 'T', 'F', 'B'),
+
+    /**
+     * Audio device stopped on error.
+     */
+    PJMEDIA_EVENT_AUD_DEV_ERROR = PJMEDIA_FOURCC('A', 'E', 'R', 'R')
 
 } pjmedia_event_type;
@@ -134,4 +139,19 @@
     pj_bool_t		cancel;
 } pjmedia_event_wnd_closing_data;
+
+/**
+ * Additional data/parameters for audio device error event.
+ */
+typedef struct pjmedia_event_aud_dev_err_data
+{
+    /** The media direction that fails */
+    pjmedia_dir		     dir;
+
+    /** The audio device ID */
+    pjmedia_aud_dev_index    id;
+
+    /** The error code */
+    pj_status_t		     status;
+} pjmedia_event_aud_dev_err_data;
 
 /** Additional parameters for window changed event. */
@@ -216,4 +236,7 @@
 	/** Keyframe missing event data */
 	pjmedia_event_keyframe_missing_data	keyframe_missing;
+
+	/** Audio device error event data */
+	pjmedia_event_aud_dev_err_data		aud_dev_err;
 
 	/** Storage for user event data */
Index: pjproject/trunk/pjmedia/src/pjmedia-audiodev/wmme_dev.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-audiodev/wmme_dev.c	(revision 5919)
+++ pjproject/trunk/pjmedia/src/pjmedia-audiodev/wmme_dev.c	(revision 5920)
@@ -24,4 +24,5 @@
 #include <pj/string.h>
 #include <pj/unicode.h>
+#include <pjmedia/event.h>
 
 #if PJMEDIA_AUDIO_DEV_HAS_WMME
@@ -894,4 +895,5 @@
     static unsigned rec_cnt, play_cnt;
     enum { MAX_BURST = 1000 };
+    pjmedia_dir signalled_dir = PJMEDIA_DIR_NONE;
 
     /* Suppress compile warning for unused debugging vars */
@@ -928,5 +930,4 @@
 
 	DWORD rc;
-	pjmedia_dir signalled_dir;
 
 	/* Swap hWaveIn and hWaveOut to get equal opportunity for both */
@@ -1047,4 +1048,6 @@
 		if (mr != MMSYSERR_NOERROR) {
 		    status = PJMEDIA_AUDIODEV_ERRNO_FROM_WMME_OUT(mr);
+		    PJ_PERROR(3, (THIS_FILE, status,
+				  "Failed to write audio frame for playback"));
 		    break;
 		}
@@ -1149,4 +1152,6 @@
 		if (mr != MMSYSERR_NOERROR) {
 		    status = PJMEDIA_AUDIODEV_ERRNO_FROM_WMME_IN(mr);
+		    PJ_PERROR(3, (THIS_FILE, status,
+				  "Failed to add recording buffer"));
 		    break;
 		}
@@ -1169,4 +1174,29 @@
 
     PJ_LOG(5,(THIS_FILE, "WMME: thread stopping.."));
+    
+    if (status != PJ_SUCCESS) {
+	pjmedia_event e;
+	pj_timestamp *ts;
+	pjmedia_aud_param param;
+
+	PJ_PERROR(3, (THIS_FILE, status, "WMME thread stopped due to error"));
+
+	/* Broadcast WMME error */
+	pj_assert(signalled_dir != PJMEDIA_DIR_NONE);
+	ts = (signalled_dir==PJMEDIA_DIR_PLAYBACK)?
+	     &strm->play_strm.timestamp : &strm->rec_strm.timestamp;
+	pjmedia_event_init(&e, PJMEDIA_EVENT_AUD_DEV_ERROR, ts, &strm->base);
+	e.data.aud_dev_err.dir = signalled_dir;
+	e.data.aud_dev_err.status = status;
+	e.data.aud_dev_err.id = PJMEDIA_AUD_INVALID_DEV;
+	if (pjmedia_aud_stream_get_param(&strm->base, &param) == PJ_SUCCESS) {
+	    e.data.aud_dev_err.id = (signalled_dir==PJMEDIA_DIR_PLAYBACK)?
+				    param.play_id : param.rec_id;
+	}
+
+	pjmedia_event_publish(NULL, &strm->base, &e,
+			      PJMEDIA_EVENT_PUBLISH_DEFAULT);
+    }
+
     return 0;
 }
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_aud.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_aud.c	(revision 5919)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_aud.c	(revision 5920)
@@ -1948,4 +1948,8 @@
     pjsua_var.snd_is_on = PJ_TRUE;
 
+    /* Subscribe to audio device events */
+    pjmedia_event_subscribe(NULL, &call_media_on_event, NULL,
+		    pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port));
+
     pj_log_pop_indent();
     return PJ_SUCCESS;
@@ -1984,4 +1988,7 @@
 			     "%s sound capture device",
 			     play_info.name, cap_info.name));
+
+	/* Unsubscribe from audio device events */
+	pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, strm);
 
 	pjmedia_snd_port_disconnect(pjsua_var.snd_port);
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 5919)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 5920)
@@ -1427,5 +1427,5 @@
 {
     pjsua_call_media *call_med = (pjsua_call_media*)user_data;
-    pjsua_call *call = call_med->call;
+    pjsua_call *call = call_med? call_med->call : NULL;
     pj_status_t status = PJ_SUCCESS;
   
@@ -1471,7 +1471,13 @@
     }
 
-    if (pjsua_var.ua_cfg.cb.on_call_media_event && call) {
-	(*pjsua_var.ua_cfg.cb.on_call_media_event)(call->index,
-						   call_med->idx, event);
+    if (pjsua_var.ua_cfg.cb.on_call_media_event) {
+	if (call) {
+	    (*pjsua_var.ua_cfg.cb.on_call_media_event)(call->index,
+						       call_med->idx, event);
+	} else {
+	    /* Also deliver non call events such as audio device error */
+	    (*pjsua_var.ua_cfg.cb.on_call_media_event)(PJSUA_INVALID_ID,
+						       0, event);
+	}
     }
 
