podcast.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * podcast.c:  Podcast services discovery module
  3.  *****************************************************************************
  4.  * Copyright (C) 2005-2009 the VideoLAN team
  5.  * $Id: 83c92c12bfd7e306fba5d1e9776e7f3f680e495f $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Includes
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_playlist.h>
  32. #include <vlc_services_discovery.h>
  33. #include <vlc_network.h>
  34. #include <assert.h>
  35. #include <errno.h>                                                 /* ENOMEM */
  36. #ifdef HAVE_UNISTD_H
  37. #    include <unistd.h>
  38. #endif
  39. #ifdef HAVE_SYS_TIME_H
  40. #    include <sys/time.h>
  41. #endif
  42. /************************************************************************
  43.  * Macros and definitions
  44.  ************************************************************************/
  45. /*****************************************************************************
  46.  * Module descriptor
  47.  *****************************************************************************/
  48. /* Callbacks */
  49. static int  Open ( vlc_object_t * );
  50. static void Close( vlc_object_t * );
  51. #define URLS_TEXT N_("Podcast URLs list")
  52. #define URLS_LONGTEXT N_("Enter the list of podcasts to retrieve, " 
  53.                          "separated by '|' (pipe)." )
  54. vlc_module_begin ()
  55.     set_shortname( "Podcast")
  56.     set_description( N_("Podcasts") )
  57.     set_category( CAT_PLAYLIST )
  58.     set_subcategory( SUBCAT_PLAYLIST_SD )
  59.     add_string( "podcast-urls", NULL, NULL,
  60.                 URLS_TEXT, URLS_LONGTEXT, false )
  61.         change_autosave ()
  62.     set_capability( "services_discovery", 0 )
  63.     set_callbacks( Open, Close )
  64. vlc_module_end ()
  65. /*****************************************************************************
  66.  * Local structures
  67.  *****************************************************************************/
  68. struct services_discovery_sys_t
  69. {
  70.     /* playlist node */
  71.     input_thread_t **pp_input;
  72.     int i_input;
  73.     char **ppsz_urls;
  74.     int i_urls;
  75.     vlc_thread_t thread;
  76.     vlc_mutex_t lock;
  77.     vlc_cond_t  wait;
  78.     bool b_update;
  79. };
  80. /*****************************************************************************
  81.  * Local prototypes
  82.  *****************************************************************************/
  83. static void *Run( void * );
  84. static int UrlsChange( vlc_object_t *, char const *, vlc_value_t,
  85.                        vlc_value_t, void * );
  86. static void ParseUrls( services_discovery_t *p_sd, char *psz_urls );
  87. /*****************************************************************************
  88.  * Open: initialize and create stuff
  89.  *****************************************************************************/
  90. static int Open( vlc_object_t *p_this )
  91. {
  92.     services_discovery_t *p_sd = ( services_discovery_t* )p_this;
  93.     services_discovery_sys_t *p_sys  = malloc(
  94.                                     sizeof( services_discovery_sys_t ) );
  95.     if( !p_sys )
  96.         return VLC_ENOMEM;
  97.     p_sys->i_urls = 0;
  98.     p_sys->ppsz_urls = NULL;
  99.     p_sys->i_input = 0;
  100.     p_sys->pp_input = NULL;
  101.     vlc_mutex_init( &p_sys->lock );
  102.     vlc_cond_init( &p_sys->wait );
  103.     p_sys->b_update = true;
  104.     p_sd->p_sys  = p_sys;
  105.     /* Launch the callback associated with this variable */
  106.     var_Create( p_sd, "podcast-urls", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  107.     var_AddCallback( p_sd, "podcast-urls", UrlsChange, p_sys );
  108.     if (vlc_clone (&p_sys->thread, Run, p_sd, VLC_THREAD_PRIORITY_LOW))
  109.     {
  110.         var_DelCallback( p_sd, "podcast-urls", UrlsChange, p_sys );
  111.         vlc_cond_destroy( &p_sys->wait );
  112.         vlc_mutex_destroy( &p_sys->lock );
  113.         free (p_sys);
  114.         return VLC_EGENERIC;
  115.     }
  116.     return VLC_SUCCESS;
  117. }
  118. /*****************************************************************************
  119.  * Close:
  120.  *****************************************************************************/
  121. static void Close( vlc_object_t *p_this )
  122. {
  123.     services_discovery_t *p_sd = ( services_discovery_t* )p_this;
  124.     services_discovery_sys_t *p_sys  = p_sd->p_sys;
  125.     int i;
  126.     vlc_cancel (p_sys->thread);
  127.     vlc_join (p_sys->thread, NULL);
  128.     var_DelCallback( p_sd, "podcast-urls", UrlsChange, p_sys );
  129.     vlc_cond_destroy( &p_sys->wait );
  130.     vlc_mutex_destroy( &p_sys->lock );
  131.     for( i = 0; i < p_sys->i_input; i++ )
  132.     {
  133.         input_thread_t *p_input = p_sd->p_sys->pp_input[i];
  134.         if( !p_input )
  135.             continue;
  136.         input_Stop( p_input, true );
  137.         vlc_thread_join( p_input );
  138.         vlc_object_release( p_input );
  139.         p_sd->p_sys->pp_input[i] = NULL;
  140.     }
  141.     free( p_sd->p_sys->pp_input );
  142.     for( i = 0; i < p_sys->i_urls; i++ ) free( p_sys->ppsz_urls[i] );
  143.     free( p_sys->ppsz_urls );
  144.     free( p_sys );
  145. }
  146. /*****************************************************************************
  147.  * Run: main thread
  148.  *****************************************************************************/
  149. static void *Run( void *data )
  150. {
  151.     services_discovery_t *p_sd = data;
  152.     services_discovery_sys_t *p_sys  = p_sd->p_sys;
  153.     vlc_mutex_lock( &p_sys->lock );
  154.     mutex_cleanup_push( &p_sys->lock );
  155.     for( ;; )
  156.     {
  157.         while( !p_sys->b_update )
  158.             vlc_cond_wait( &p_sys->wait, &p_sys->lock );
  159.         int canc = vlc_savecancel ();
  160.         msg_Dbg( p_sd, "Update required" );
  161.         char* psz_urls = var_GetNonEmptyString( p_sd, "podcast-urls" );
  162.         if( psz_urls != NULL )
  163.             ParseUrls( p_sd, psz_urls );
  164.         free( psz_urls );
  165.         p_sys->b_update = false;
  166.         for( int i = 0; i < p_sd->p_sys->i_input; i++ )
  167.         {
  168.             input_thread_t *p_input = p_sd->p_sys->pp_input[i];
  169.             if( p_input->b_eof || p_input->b_error )
  170.             {
  171.                 input_Stop( p_input, false );
  172.                 vlc_thread_join( p_input );
  173.                 vlc_object_release( p_input );
  174.                 p_sd->p_sys->pp_input[i] = NULL;
  175.                 REMOVE_ELEM( p_sys->pp_input, p_sys->i_input, i );
  176.                 i--;
  177.             }
  178.         }
  179.         vlc_restorecancel (canc);
  180.     }
  181.     vlc_cleanup_pop();
  182.     assert(0); /* dead code */
  183. }
  184. static int UrlsChange( vlc_object_t *p_this, char const *psz_var,
  185.                        vlc_value_t oldval, vlc_value_t newval,
  186.                        void *p_data )
  187. {
  188.     VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(oldval);
  189.     VLC_UNUSED(newval);
  190.     services_discovery_sys_t *p_sys  = (services_discovery_sys_t *)p_data;
  191.     vlc_mutex_lock( &p_sys->lock );
  192.     p_sys->b_update = true;
  193.     vlc_cond_signal( &p_sys->wait );
  194.     vlc_mutex_unlock( &p_sys->lock );
  195.     return VLC_SUCCESS;
  196. }
  197. static void ParseUrls( services_discovery_t *p_sd, char *psz_urls )
  198. {
  199.     services_discovery_sys_t *p_sys = p_sd->p_sys;
  200.     for( ;; )
  201.     {
  202.         int i;
  203.         char *psz_tok = strchr( psz_urls, '|' );
  204.         if( psz_tok ) *psz_tok = '';
  205.         for( i = 0; i < p_sys->i_urls; i++ )
  206.             if( !strcmp( psz_urls, p_sys->ppsz_urls[i] ) )
  207.                 break;
  208.         if( i == p_sys->i_urls )
  209.         {
  210.             /* Only add new urls.
  211.              * FIXME: We don't delete urls which have been removed from
  212.              * the config since we don't have a way to know which inputs
  213.              * they spawned */
  214.             input_item_t *p_input;
  215.             INSERT_ELEM( p_sys->ppsz_urls, p_sys->i_urls, p_sys->i_urls,
  216.                          strdup( psz_urls ) );
  217.             p_input = input_item_New( p_sd, psz_urls, psz_urls );
  218.             input_item_AddOption( p_input, "demux=podcast", VLC_INPUT_OPTION_TRUSTED );
  219.             services_discovery_AddItem( p_sd, p_input, NULL /* no cat */ );
  220.             vlc_gc_decref( p_input );
  221.             INSERT_ELEM( p_sys->pp_input, p_sys->i_input, p_sys->i_input,
  222.                          input_CreateAndStart( p_sd, p_input, NULL ) );
  223.         }
  224.         if( psz_tok )  psz_urls = psz_tok+1;
  225.         else           return;
  226.     }
  227. }