X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_filter%2Frss.c;h=a9ff0c2126879678a8e3ccaa1be977beda758760;hb=9d016759c25f227281fb0af9a4ea82bf38328b6d;hp=d77c4733b270b977f3dc861d538b399d14f61891;hpb=2838403d2843a0dcd079360bcbe4e78945dad03c;p=vlc diff --git a/modules/video_filter/rss.c b/modules/video_filter/rss.c index d77c4733b2..a9ff0c2126 100644 --- a/modules/video_filter/rss.c +++ b/modules/video_filter/rss.c @@ -5,6 +5,7 @@ * $Id$ * * Authors: Antoine Cellerier + * Rémi Duraffort * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,9 +40,7 @@ #include #include -#include -#include #include #include #include @@ -57,8 +56,8 @@ static int CreateFilter ( vlc_object_t * ); static void DestroyFilter( vlc_object_t * ); static subpicture_t *Filter( filter_t *, mtime_t ); -static int FetchRSS( filter_t * ); -static void FreeRSS( filter_t * ); +static struct rss_feed_t *FetchRSS( filter_t * ); +static void FreeRSS( struct rss_feed_t *, int ); static int ParseUrls( filter_t *, char * ); static void Fetch( void * ); @@ -119,7 +118,6 @@ struct filter_sys_t int i_feeds; rss_feed_t *p_feeds; - int i_ttl; bool b_images; int i_title; @@ -168,6 +166,8 @@ struct filter_sys_t #define TITLE_TEXT N_("Title display mode") #define TITLE_LONGTEXT N_("Title display mode. Default is 0 (hidden) if the feed has an image and feed images are enabled, 1 otherwise.") +#define RSS_HELP N_("Display a RSS or ATOM Feed on your video") + static const int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 }; static const char *const ppsz_pos_descriptions[] = { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"), @@ -190,11 +190,12 @@ static const char *const ppsz_title_modes[] = *****************************************************************************/ vlc_module_begin () set_capability( "sub filter", 1 ) - set_shortname( "RSS / Atom" ) + set_shortname( N_("RSS / Atom") ) + set_help(RSS_HELP) set_callbacks( CreateFilter, DestroyFilter ) set_category( CAT_VIDEO ) set_subcategory( SUBCAT_VIDEO_SUBPIC ) - add_string( CFG_PREFIX "urls", "rss", NULL, MSG_TEXT, MSG_LONGTEXT, false ) + add_string( CFG_PREFIX "urls", NULL, NULL, MSG_TEXT, MSG_LONGTEXT, false ) set_section( N_("Position"), NULL ) add_integer( CFG_PREFIX "x", 0, NULL, POSX_TEXT, POSX_LONGTEXT, true ) @@ -217,13 +218,12 @@ vlc_module_begin () add_integer( CFG_PREFIX "length", 60, NULL, LENGTH_TEXT, LENGTH_LONGTEXT, false ) add_integer( CFG_PREFIX "ttl", 1800, NULL, TTL_TEXT, TTL_LONGTEXT, false ) - add_bool( CFG_PREFIX "images", 1, NULL, IMAGE_TEXT, IMAGE_LONGTEXT, false ) + add_bool( CFG_PREFIX "images", true, NULL, IMAGE_TEXT, IMAGE_LONGTEXT, false ) add_integer( CFG_PREFIX "title", default_title, NULL, TITLE_TEXT, TITLE_LONGTEXT, false ) change_integer_list( pi_title_modes, ppsz_title_modes, NULL ) set_description( N_("RSS and Atom feed display") ) - add_shortcut( "rss" ) - add_shortcut( "atom" ) + add_shortcut( "rss", "atom" ) vlc_module_end () static const char *const ppsz_filter_options[] = { @@ -238,8 +238,8 @@ static int CreateFilter( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; - int i_ret = VLC_ENOMEM; char *psz_urls; + int i_ttl; /* Allocate structure */ p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) ); @@ -249,7 +249,16 @@ static int CreateFilter( vlc_object_t *p_this ) config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options, p_filter->p_cfg ); - psz_urls = var_CreateGetString( p_filter, CFG_PREFIX "urls" ); + /* Get the urls to parse: must be non empty */ + psz_urls = var_CreateGetNonEmptyString( p_filter, CFG_PREFIX "urls" ); + if( !psz_urls ) + { + msg_Err( p_filter, "The list of urls must not be empty" ); + free( p_sys ); + return VLC_EGENERIC; + } + + /* Fill the p_sys structure with the configuration */ p_sys->i_title = var_CreateGetInteger( p_filter, CFG_PREFIX "title" ); p_sys->i_cur_feed = 0; p_sys->i_cur_item = p_sys->i_title == scroll_title ? -1 : 0; @@ -258,12 +267,17 @@ static int CreateFilter( vlc_object_t *p_this ) p_sys->p_feeds = NULL; p_sys->i_speed = var_CreateGetInteger( p_filter, CFG_PREFIX "speed" ); p_sys->i_length = var_CreateGetInteger( p_filter, CFG_PREFIX "length" ); - p_sys->i_ttl = __MAX( 0, var_CreateGetInteger( p_filter, CFG_PREFIX "ttl" ) ); p_sys->b_images = var_CreateGetBool( p_filter, CFG_PREFIX "images" ); + i_ttl = __MAX( 0, var_CreateGetInteger( p_filter, CFG_PREFIX "ttl" ) ); + p_sys->psz_marquee = malloc( p_sys->i_length + 1 ); if( p_sys->psz_marquee == NULL ) - goto error; + { + free( psz_urls ); + free( p_sys ); + return VLC_ENOMEM; + } p_sys->psz_marquee[p_sys->i_length] = '\0'; p_sys->p_style = text_style_New(); @@ -277,18 +291,14 @@ static int CreateFilter( vlc_object_t *p_this ) p_sys->p_style->i_font_color = var_CreateGetInteger( p_filter, CFG_PREFIX "color" ); p_sys->p_style->i_font_size = var_CreateGetInteger( p_filter, CFG_PREFIX "size" ); - if( p_sys->b_images == true && p_sys->p_style->i_font_size == -1 ) + if( p_sys->b_images && p_sys->p_style->i_font_size == -1 ) { msg_Warn( p_filter, "rss-size wasn't specified. Feed images will thus be displayed without being resized" ); } /* Parse the urls */ if( ParseUrls( p_filter, psz_urls ) ) - { - free( psz_urls ); goto error; - } - free( psz_urls ); /* Misc init */ vlc_mutex_init( &p_sys->lock ); @@ -303,14 +313,18 @@ static int CreateFilter( vlc_object_t *p_this ) goto error; } vlc_timer_schedule( p_sys->timer, false, 1, - (mtime_t)(p_sys->i_ttl)*1000000 ); + (mtime_t)(i_ttl)*1000000 ); + free( psz_urls ); return VLC_SUCCESS; error: + if( p_sys->p_style ) + text_style_Delete( p_sys->p_style ); free( p_sys->psz_marquee ); + free( psz_urls ); free( p_sys ); - return i_ret; + return VLC_ENOMEM; } /***************************************************************************** * DestroyFilter: destroy RSS video filter @@ -325,7 +339,7 @@ static void DestroyFilter( vlc_object_t *p_this ) text_style_Delete( p_sys->p_style ); free( p_sys->psz_marquee ); - FreeRSS( p_filter ); + FreeRSS( p_sys->p_feeds, p_sys->i_feeds ); free( p_sys ); } @@ -468,7 +482,7 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) /* where to locate the string: */ if( p_sys->i_pos < 0 ) { /* set to an absolute xy */ - p_spu->p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP; + p_spu->p_region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP; p_spu->b_absolute = true; } else @@ -476,6 +490,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) p_spu->p_region->i_align = p_sys->i_pos; p_spu->b_absolute = false; } + p_spu->p_region->i_x = p_sys->i_xoff; + p_spu->p_region->i_y = p_sys->i_yoff; p_spu->p_region->p_style = text_style_Duplicate( p_sys->p_style ); @@ -488,7 +504,6 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_out.i_chroma = VLC_CODEC_YUVA; - fmt_out.i_aspect = VOUT_ASPECT_FACTOR; fmt_out.i_sar_num = fmt_out.i_sar_den = 1; fmt_out.i_width = fmt_out.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch; @@ -502,15 +517,15 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) } else { - p_region->i_x = p_sys->i_xoff; - p_region->i_y = p_sys->i_yoff; + p_region->i_x = p_spu->p_region->i_x; + p_region->i_y = p_spu->p_region->i_y; /* FIXME the copy is probably not needed anymore */ picture_Copy( p_region->p_picture, p_pic ); p_spu->p_region->p_next = p_region; - } - /* Offset text to display right next to the image */ - p_spu->p_region->i_x = p_pic->p[Y_PLANE].i_visible_pitch; + /* Offset text to display right next to the image */ + p_spu->p_region->i_x += fmt_out.i_visible_width; + } } vlc_mutex_unlock( &p_sys->lock ); @@ -693,8 +708,8 @@ static bool ParseFeed( filter_t *p_filter, xml_reader_t *p_xml_reader, { b_is_item = true; p_feed->i_items++; - p_feed->p_items = realloc( p_feed->p_items, - p_feed->i_items * sizeof( rss_item_t ) ); + p_feed->p_items = xrealloc( p_feed->p_items, + p_feed->i_items * sizeof( rss_item_t ) ); p_feed->p_items[p_feed->i_items-1].psz_title = NULL; p_feed->p_items[p_feed->i_items-1].psz_description = NULL; p_feed->p_items[p_feed->i_items-1].psz_link = NULL; @@ -879,45 +894,49 @@ end: /**************************************************************************** * FetchRSS (or Atom) feeds ***************************************************************************/ -static int FetchRSS( filter_t *p_filter ) +static rss_feed_t* FetchRSS( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; stream_t *p_stream; xml_t *p_xml; xml_reader_t *p_xml_reader; + int i_feed; + + /* These data are not modified after the creation of the module so we don't + need to hold the lock */ + int i_feeds = p_sys->i_feeds; + bool b_images = p_sys->b_images; + + /* Allocate a new structure */ + rss_feed_t *p_feeds = malloc( i_feeds * sizeof( rss_feed_t ) ); + if( !p_feeds ) + return NULL; p_xml = xml_Create( p_filter ); if( !p_xml ) { msg_Err( p_filter, "Failed to open XML parser" ); - return 1; + free( p_feeds ); + return NULL; } /* Fetch all feeds and parse them */ - for( int i_feed = 0; i_feed < p_sys->i_feeds; i_feed++ ) + for( i_feed = 0; i_feed < i_feeds; i_feed++ ) { - rss_feed_t *p_feed = p_sys->p_feeds+i_feed; - - /* Free the ressources */ - FREENULL( p_feed->psz_title ); - FREENULL( p_feed->psz_description ); - FREENULL( p_feed->psz_link ); - FREENULL( p_feed->psz_image ); - if( p_feed->p_pic ) - { - picture_Release( p_feed->p_pic ); - p_feed->p_pic = NULL; - } - for( int i = 0; i < p_feed->i_items; i++ ) - { - rss_item_t *p_item = p_feed->p_items + i; - free( p_item->psz_title ); - free( p_item->psz_link ); - free( p_item->psz_description ); - } + rss_feed_t *p_feed = p_feeds + i_feed; + rss_feed_t *p_old_feed = p_sys->p_feeds + i_feed; + + /* Initialize the structure */ + p_feed->psz_title = NULL; + p_feed->psz_description = NULL; + p_feed->psz_link = NULL; + p_feed->psz_image = NULL; + p_feed->p_pic = NULL; p_feed->i_items = 0; - FREENULL( p_feed->p_items ); + p_feed->p_items = NULL; + + p_feed->psz_url = strdup( p_old_feed->psz_url ); /* Fetch the feed */ msg_Dbg( p_filter, "opening %s RSS/Atom feed ...", p_feed->psz_url ); @@ -942,42 +961,39 @@ static int FetchRSS( filter_t *p_filter ) goto error; /* If we have a image: load it if requiere */ - if( p_sys->b_images == true - && p_feed->psz_image && !p_feed->p_pic ) + if( b_images && p_feed->psz_image && !p_feed->p_pic ) { p_feed->p_pic = LoadImage( p_filter, p_feed->psz_image ); } msg_Dbg( p_filter, "done with %s RSS/Atom feed", p_feed->psz_url ); - xml_ReaderDelete( p_xml, p_xml_reader ); + xml_ReaderDelete( p_xml_reader ); stream_Delete( p_stream ); } xml_Delete( p_xml ); - return 0; + return p_feeds; error: - + FreeRSS( p_feeds, i_feed + 1 ); if( p_xml_reader ) - xml_ReaderDelete( p_xml, p_xml_reader ); + xml_ReaderDelete( p_xml_reader ); if( p_stream ) stream_Delete( p_stream ); if( p_xml ) xml_Delete( p_xml ); - return 1; + return NULL; } /**************************************************************************** * FreeRSS ***************************************************************************/ -static void FreeRSS( filter_t *p_filter) +static void FreeRSS( rss_feed_t *p_feeds, int i_feeds ) { - filter_sys_t *p_sys = p_filter->p_sys; - - for( int i_feed = 0; i_feed < p_sys->i_feeds; i_feed++ ) + for( int i_feed = 0; i_feed < i_feeds; i_feed++ ) { - rss_feed_t *p_feed = p_sys->p_feeds+i_feed; + rss_feed_t *p_feed = p_feeds+i_feed; for( int i_item = 0; i_item < p_feed->i_items; i_item++ ) { rss_item_t *p_item = p_feed->p_items+i_item; @@ -994,8 +1010,7 @@ static void FreeRSS( filter_t *p_filter) picture_Release( p_feed->p_pic ); free( p_feed->psz_url ); } - free( p_sys->p_feeds ); - p_sys->i_feeds = 0; + free( p_feeds ); } static void Fetch( void *p_data ) @@ -1003,8 +1018,26 @@ static void Fetch( void *p_data ) filter_t *p_filter = p_data; filter_sys_t *p_sys = p_filter->p_sys; + msg_Dbg( p_filter, "Updating the rss feeds" ); + rss_feed_t *p_feeds = FetchRSS( p_filter ); + if( !p_feeds ) + { + msg_Err( p_filter, "Unable to fetch the feeds" ); + return; + } + + rss_feed_t *p_old_feeds = p_sys->p_feeds; + vlc_mutex_lock( &p_sys->lock ); - FetchRSS( p_filter ); + /* Update the feeds */ + p_sys->p_feeds = p_feeds; p_sys->b_fetched = true; + /* Set all current info to the original values */ + p_sys->i_cur_feed = 0; + p_sys->i_cur_item = p_sys->i_title == scroll_title ? -1 : 0; + p_sys->i_cur_char = 0; vlc_mutex_unlock( &p_sys->lock ); + + if( p_old_feeds ) + FreeRSS( p_old_feeds, p_sys->i_feeds ); }