+
+static msg_context_t* GetContext(void)
+{
+ msg_context_t *p_ctx = vlc_threadvar_get( &msg_context );
+ if( p_ctx == NULL )
+ {
+ MALLOC_NULL( p_ctx, msg_context_t );
+ p_ctx->psz_message = NULL;
+ vlc_threadvar_set( &msg_context, p_ctx );
+ }
+ return p_ctx;
+}
+
+void msg_StackDestroy (void *data)
+{
+ msg_context_t *p_ctx = data;
+
+ free (p_ctx->psz_message);
+ free (p_ctx);
+}
+
+void msg_StackSet( int i_code, const char *psz_message, ... )
+{
+ va_list ap;
+ msg_context_t *p_ctx = GetContext();
+
+ if( p_ctx == NULL )
+ return;
+ free( p_ctx->psz_message );
+
+ va_start( ap, psz_message );
+ if( vasprintf( &p_ctx->psz_message, psz_message, ap ) == -1 )
+ p_ctx->psz_message = NULL;
+ va_end( ap );
+
+ p_ctx->i_code = i_code;
+}
+
+void msg_StackAdd( const char *psz_message, ... )
+{
+ char *psz_tmp;
+ va_list ap;
+ msg_context_t *p_ctx = GetContext();
+
+ if( p_ctx == NULL )
+ return;
+
+ va_start( ap, psz_message );
+ if( vasprintf( &psz_tmp, psz_message, ap ) == -1 )
+ psz_tmp = NULL;
+ va_end( ap );
+
+ if( !p_ctx->psz_message )
+ p_ctx->psz_message = psz_tmp;
+ else
+ {
+ char *psz_new;
+ if( asprintf( &psz_new, "%s: %s", psz_tmp, p_ctx->psz_message ) == -1 )
+ psz_new = NULL;
+
+ free( p_ctx->psz_message );
+ p_ctx->psz_message = psz_new;
+ free( psz_tmp );
+ }
+}
+
+const char* msg_StackMsg( void )
+{
+ msg_context_t *p_ctx = GetContext();
+ assert( p_ctx );
+ return p_ctx->psz_message;
+}