 +  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
 +};
 +
+diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
+index 6a0688f..3d3ae0c 100644
+--- a/src/xine-engine/audio_decoder.c
++++ b/src/xine-engine/audio_decoder.c
+@@ -42,6 +42,36 @@
+ #include <xine/xine_internal.h>
+ #include <xine/xineutils.h>
+ 
++/* if updating SPU decoders for audio only streams, the decoders might crash
++   as they'll expect a valid video out - so only allow the ones we know are ok */
++static int is_suitable_audio_spu(int type)
++{
++  int streamtype = type & 0xFFFF0000;
++  switch (streamtype) {
++    case BUF_SPU_KATE:
++      return 1;
++    default:
++      return 0;
++  }
++}
++
++static void update_spu_decoder (xine_stream_t *stream, int type) {
++
++  int streamtype = (type>>16) & 0xFF;
++  
++  if( stream->spu_decoder_streamtype != streamtype ||
++      !stream->spu_decoder_plugin ) {
++    
++    if (stream->spu_decoder_plugin)
++      _x_free_spu_decoder (stream, stream->spu_decoder_plugin);
++          
++    stream->spu_decoder_streamtype = streamtype;
++    stream->spu_decoder_plugin = _x_get_spu_decoder (stream, streamtype);
++
++  }
++  return ;
++}
++
+ static void *audio_decoder_loop (void *stream_gen) {
+ 
+   buf_element_t   *buf = NULL;
+@@ -52,11 +82,14 @@ static void *audio_decoder_loop (void *stream_gen) {
+   xine_ticket_t   *running_ticket = stream->xine->port_ticket;
+   int              running = 1;
+   int              prof_audio_decode = -1;
++  int              prof_spu_decode = -1;
+   uint32_t         buftype_unknown = 0;
+   int              audio_channel_user = stream->audio_channel_user;
+ 
+   if (prof_audio_decode == -1)
+     prof_audio_decode = xine_profiler_allocate_slot ("audio decoder/output");
++  if (!stream->video_out && prof_spu_decode == -1)
++    prof_spu_decode = xine_profiler_allocate_slot ("SPU decoder/output");
+ 
+   while (running) {
+ 
+@@ -96,6 +129,12 @@ static void *audio_decoder_loop (void *stream_gen) {
+ 	stream->audio_type = 0;
+       }
+       
++      if (!stream->video_out && stream->spu_decoder_plugin) {
++        _x_free_spu_decoder (stream, stream->spu_decoder_plugin);
++        stream->spu_decoder_plugin = NULL;
++        stream->spu_track_map_entries = 0;
++      }
++
+       running_ticket->release(running_ticket, 0);
+       
+       if( !stream->gapless_switch )
+@@ -173,6 +212,11 @@ static void *audio_decoder_loop (void *stream_gen) {
+ 	stream->audio_track_map_entries = 0;
+ 	stream->audio_type = 0;
+       }
++      if (!stream->video_out && stream->spu_decoder_plugin) {
++        _x_free_spu_decoder (stream, stream->spu_decoder_plugin);
++        stream->spu_decoder_plugin = NULL;
++        stream->spu_track_map_entries = 0;
++      }
+       
+       running_ticket->release(running_ticket, 0);
+       running = 0;
+@@ -185,11 +229,14 @@ static void *audio_decoder_loop (void *stream_gen) {
+       lprintf ("reset\n");
+ 
+       _x_extra_info_reset( stream->audio_decoder_extra_info );
++      running_ticket->acquire(running_ticket, 0);
+       if (stream->audio_decoder_plugin) {
+-	running_ticket->acquire(running_ticket, 0);
+ 	stream->audio_decoder_plugin->reset (stream->audio_decoder_plugin);
+-	running_ticket->release(running_ticket, 0);
+       }
++      if (stream->spu_decoder_plugin) {
++        stream->spu_decoder_plugin->reset (stream->spu_decoder_plugin);
++      }
++      running_ticket->release(running_ticket, 0);
+       break;
+           
+     case BUF_CONTROL_DISCONTINUITY:
+@@ -240,19 +287,19 @@ static void *audio_decoder_loop (void *stream_gen) {
+ 
+     default:
+ 
+-      if (_x_stream_info_get(stream, XINE_STREAM_INFO_IGNORE_AUDIO))
+-        break;
+-
+-      xine_profiler_start_count (prof_audio_decode);
+-
+-      running_ticket->acquire(running_ticket, 0);
+-	  
+       if ( (buf->type & 0xFF000000) == BUF_AUDIO_BASE ) {
+ 	
+ 	uint32_t audio_type = 0;
+ 	int      i,j;
+ 	uint32_t chan=buf->type&0x0000FFFF;
+ 
++        if (_x_stream_info_get(stream, XINE_STREAM_INFO_IGNORE_AUDIO))
++          break;
++
++        xine_profiler_start_count (prof_audio_decode);
++
++        running_ticket->acquire(running_ticket, 0);
++	  
+ 	/*
+         printf("audio_decoder: buf_type=%08x auto=%08x user=%08x\n",
+ 	       buf->type, 
+@@ -377,17 +424,81 @@ static void *audio_decoder_loop (void *stream_gen) {
+ 	    }
+ 	  }
+ 	}
++
++        if (running_ticket->ticket_revoked)
++          running_ticket->renew(running_ticket, 0);
++        running_ticket->release(running_ticket, 0);
++      
++        xine_profiler_stop_count (prof_audio_decode);
++
++///
++      } else if ( (buf->type & 0xFF000000) == BUF_SPU_BASE ) {
++
++        int      i,j;
++
++        if (stream->video_out || !is_suitable_audio_spu(buf->type))
++          break;
++
++        if (_x_stream_info_get(stream, XINE_STREAM_INFO_IGNORE_SPU))
++          break;
++
++        xine_profiler_start_count (prof_spu_decode);
++
++        running_ticket->acquire(running_ticket, 0);
++      
++        update_spu_decoder(stream, buf->type);
++
++        /* update track map */
++
++        i = 0;
++        while ( (i<stream->spu_track_map_entries) && (stream->spu_track_map[i]<buf->type) ) 
++          i++;
++        
++        if ( (i==stream->spu_track_map_entries)
++             || (stream->spu_track_map[i] != buf->type) ) {
++          xine_event_t  ui_event;
++
++          j = stream->spu_track_map_entries;
++
++          if (j >= 50)
++            break;
++
++          while (j>i) {
++            stream->spu_track_map[j] = stream->spu_track_map[j-1];
++            j--;
++          }
++          stream->spu_track_map[i] = buf->type;
++          stream->spu_track_map_entries++;
++
++	  ui_event.type        = XINE_EVENT_UI_CHANNELS_CHANGED;
++	  ui_event.data_length = 0;
++	  xine_event_send (stream, &ui_event);
++        }
++
++        if (stream->spu_channel_user >= 0) {
++          if (stream->spu_channel_user < stream->spu_track_map_entries)
++            stream->spu_channel = (stream->spu_track_map[stream->spu_channel_user] & 0xFF);
++          else
++            stream->spu_channel = stream->spu_channel_auto;
++        }
++
++        if (stream->spu_decoder_plugin) {
++          stream->spu_decoder_plugin->decode_data (stream->spu_decoder_plugin, buf);
++        }
++
++        if (running_ticket->ticket_revoked)
++          running_ticket->renew(running_ticket, 0);
++        running_ticket->release(running_ticket, 0);
++      
++        xine_profiler_stop_count (prof_spu_decode);
++
++///
++
+       } else if( buf->type != buftype_unknown ) {
+ 	  xine_log (stream->xine, XINE_LOG_MSG, 
+ 		    _("audio_decoder: error, unknown buffer type: %08x\n"), buf->type );
+ 	  buftype_unknown = buf->type;
+       }
+-
+-      if (running_ticket->ticket_revoked)
+-        running_ticket->renew(running_ticket, 0);
+-      running_ticket->release(running_ticket, 0);
+-      
+-      xine_profiler_stop_count (prof_audio_decode);
+     }
+ 
+     /* some decoders require a full reinitialization when audio
+diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c
+index 1d3754d..ddf46a5 100644
+--- a/src/xine-engine/osd.c
++++ b/src/xine-engine/osd.c
+@@ -299,6 +299,7 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) {
+   rle_elem_t rle, *rle_p=0;
+   int x, y;
+   uint8_t *c;
++  int ret;
+ 
+   lprintf("osd=%p vpts=%"PRId64"\n", osd, vpts);
+   
+@@ -415,15 +416,18 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) {
+     this->event.event_type = OVERLAY_EVENT_SHOW;
+     this->event.vpts = vpts;
+     ovl_manager->add_event(ovl_manager, (void *)&this->event);
++
++    ret = 1;
+   } else {
+     /* osd empty - hide it */
+     _osd_hide(osd, vpts);
++    ret = 0;
+   }
+   pthread_mutex_unlock (&this->osd_mutex);  
+   
+   this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1);
+   
+-  return 1;
++  return ret;
+ }
+ 
+ /* normal OSD show
+@@ -1683,6 +1687,14 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap,
+ 
+   lprintf("osd=%p at (%d,%d) %dx%d\n",osd, x1,y1, width,height );
+ 
++  /* prevent overflowing to right and bottom */
++  if (x1+width > osd->width) {
++    width = osd->width-x1;
++  }
++  if (y1+height > osd->height) {
++    height = osd->height-y1;
++  }
++
+   /* update clipping area */
+   osd->x1 = MIN( osd->x1, x1 );
+   osd->x2 = MAX( osd->x2, x1+width );
+-- 
+1.6.0
+

         } else {
           xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
                   "demux_ogg: unknown stream type (signature >%.8s<). hex dump of bos packet follows:\n",
@@ -1918,6 +2004,8 @@
       strcpy( str, "none");
       return DEMUX_OPTIONAL_SUCCESS;
     } else if ((channel>=0) && (channel<this->num_streams)) {

 
 /* block lacing */
 #define MATROSKA_NO_LACING               0x0
diff --git a/src/spu_dec/Makefile.am b/src/spu_dec/Makefile.am
index 98048fe..df3604d 100644
--- a/src/spu_dec/Makefile.am
+++ b/src/spu_dec/Makefile.am
@@ -34,3 +34,11 @@ xineplug_decode_spudvb_la_LIBADD  = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL)
 
 xineplug_sputext_la_SOURCES = sputext_demuxer.c sputext_decoder.c
 xineplug_sputext_la_LIBADD  = $(XINE_LIB) $(LTLIBINTL)
