+ else
+ {
+ msg_Dbg( p_spu, "no sub filter found" );
+ vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] );
+ vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] );
+ }
+
+ if( p_spu->i_filter >= 10 )
+ {
+ msg_Dbg( p_spu, "can't add anymore filters" );
+ }
+
+ psz_filter = psz_parser;
+ }
+ if( psz_filter_orig ) free( psz_filter_orig );
+
+ return VLC_EGENERIC;
+}
+
+/**
+ * Destroy the subpicture unit
+ *
+ * \param p_this the parent object which destroys the subpicture unit
+ */
+void spu_Destroy( spu_t *p_spu )
+{
+ int i_index;
+
+ vlc_object_detach( p_spu );
+
+ /* Destroy all remaining subpictures */
+ for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
+ {
+ if( p_spu->p_subpicture[i_index].i_status != FREE_SUBPICTURE )
+ {
+ spu_DestroySubpicture( p_spu, &p_spu->p_subpicture[i_index] );
+ }
+ }
+
+ if( p_spu->p_blend )
+ {
+ if( p_spu->p_blend->p_module )
+ module_Unneed( p_spu->p_blend, p_spu->p_blend->p_module );
+
+ vlc_object_detach( p_spu->p_blend );
+ vlc_object_destroy( p_spu->p_blend );
+ }
+
+ if( p_spu->p_text )
+ {
+ if( p_spu->p_text->p_module )
+ module_Unneed( p_spu->p_text, p_spu->p_text->p_module );
+
+ vlc_object_detach( p_spu->p_text );
+ vlc_object_destroy( p_spu->p_text );
+ }
+
+ if( p_spu->p_scale )
+ {
+ if( p_spu->p_scale->p_module )
+ module_Unneed( p_spu->p_scale, p_spu->p_scale->p_module );
+
+ vlc_object_detach( p_spu->p_scale );
+ vlc_object_destroy( p_spu->p_scale );
+ }
+
+ while( p_spu->i_filter-- )
+ {
+ module_Unneed( p_spu->pp_filter[p_spu->i_filter],
+ p_spu->pp_filter[p_spu->i_filter]->p_module );
+ free( p_spu->pp_filter[p_spu->i_filter]->p_owner );
+ vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] );
+ vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] );
+ }
+
+ vlc_mutex_destroy( &p_spu->subpicture_lock );
+ vlc_object_destroy( p_spu );
+}
+
+/**
+ * Attach/Detach the SPU from any input
+ *
+ * \param p_this the object in which to destroy the subpicture unit
+ * \param b_attach to select attach or detach
+ */
+void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, vlc_bool_t b_attach )
+{
+ vlc_object_t *p_input;
+
+ p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
+ if( !p_input ) return;
+
+ if( b_attach )
+ {
+ UpdateSPU( p_spu, VLC_OBJECT(p_input) );
+ var_AddCallback( p_input, "highlight", CropCallback, p_spu );
+ vlc_object_release( p_input );
+ }
+ else
+ {
+ /* Delete callback */
+ var_DelCallback( p_input, "highlight", CropCallback, p_spu );
+ vlc_object_release( p_input );
+ }
+}
+
+/**
+ * Create a subpicture region
+ *
+ * \param p_this vlc_object_t
+ * \param p_fmt the format that this subpicture region should have
+ */
+static void RegionPictureRelease( picture_t *p_pic )
+{
+ if( p_pic->p_data_orig ) free( p_pic->p_data_orig );
+}
+subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this,
+ video_format_t *p_fmt )
+{
+ subpicture_region_t *p_region = malloc( sizeof(subpicture_region_t) );
+ memset( p_region, 0, sizeof(subpicture_region_t) );
+ p_region->p_next = 0;
+ p_region->p_cache = 0;
+ p_region->fmt = *p_fmt;
+ p_region->psz_text = 0;
+ p_region->i_text_color = 0xFFFFFF;
+
+ if( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') )
+ p_fmt->p_palette = p_region->fmt.p_palette =
+ malloc( sizeof(video_palette_t) );
+ else p_fmt->p_palette = p_region->fmt.p_palette = NULL;
+
+ p_region->picture.p_data_orig = 0;
+
+ if( p_fmt->i_chroma == VLC_FOURCC('T','E','X','T') ) return p_region;
+
+ vout_AllocatePicture( p_this, &p_region->picture, p_fmt->i_chroma,
+ p_fmt->i_width, p_fmt->i_height, p_fmt->i_aspect );
+
+ if( !p_region->picture.i_planes )
+ {
+ free( p_region );
+ free( p_fmt->p_palette );
+ return NULL;
+ }
+
+ p_region->picture.pf_release = RegionPictureRelease;
+
+ return p_region;
+}
+
+/**
+ * Make a subpicture region from an existing picture_t
+ *
+ * \param p_this vlc_object_t
+ * \param p_fmt the format that this subpicture region should have
+ * \param p_pic a pointer to the picture creating the region (not freed)
+ */
+subpicture_region_t *__spu_MakeRegion( vlc_object_t *p_this,
+ video_format_t *p_fmt,
+ picture_t *p_pic )
+{
+ subpicture_region_t *p_region = malloc( sizeof(subpicture_region_t) );
+ memset( p_region, 0, sizeof(subpicture_region_t) );
+ p_region->p_next = 0;
+ p_region->p_cache = 0;
+ p_region->fmt = *p_fmt;
+ p_region->psz_text = 0;
+ p_region->i_text_color = 0xFFFFFF;
+
+ if( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') )
+ p_fmt->p_palette = p_region->fmt.p_palette =
+ malloc( sizeof(video_palette_t) );
+ else p_fmt->p_palette = p_region->fmt.p_palette = NULL;
+
+ memcpy( &p_region->picture, p_pic, sizeof(picture_t) );
+ p_region->picture.pf_release = RegionPictureRelease;
+
+ return p_region;
+}
+
+/**
+ * Destroy a subpicture region
+ *
+ * \param p_this vlc_object_t
+ * \param p_region the subpicture region to destroy
+ */
+void __spu_DestroyRegion( vlc_object_t *p_this, subpicture_region_t *p_region )
+{
+ if( !p_region ) return;
+ if( p_region->picture.pf_release )
+ p_region->picture.pf_release( &p_region->picture );
+ if( p_region->fmt.p_palette ) free( p_region->fmt.p_palette );
+ if( p_region->psz_text ) free( p_region->psz_text );
+ if( p_region->p_cache ) __spu_DestroyRegion( p_this, p_region->p_cache );
+ free( p_region );
+}
+
+/**
+ * Display a subpicture
+ *
+ * Remove the reservation flag of a subpicture, which will cause it to be
+ * ready for display.
+ * \param p_spu the subpicture unit object
+ * \param p_subpic the subpicture to display
+ */
+void spu_DisplaySubpicture( spu_t *p_spu, subpicture_t *p_subpic )
+{
+ /* Check if status is valid */
+ if( p_subpic->i_status != RESERVED_SUBPICTURE )
+ {
+ msg_Err( p_spu, "subpicture %p has invalid status #%d",
+ p_subpic, p_subpic->i_status );