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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * shoutcast.c: Winamp >=5.2 shoutcast demuxer
  3.  *****************************************************************************
  4.  * Copyright (C) 2006 the VideoLAN team
  5.  * $Id: e5257de3dd1d61b001f0f744e7b36e9367017d6e $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea -@t- videolan -Dot- org>
  8.  *          based on b4s.c by Sigmund Augdal Helberg <dnumgis@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_demux.h>
  32. #include "playlist.h"
  33. #include "vlc_xml.h"
  34. struct demux_sys_t
  35. {
  36.     input_item_t *p_current_input;
  37.     xml_t *p_xml;
  38.     xml_reader_t *p_xml_reader;
  39.     bool b_adult;
  40. };
  41. /* duplicate from modules/services_discovery/shout.c */
  42. #define SHOUTCAST_BASE_URL "http/shout-winamp://www.shoutcast.com/sbin/newxml.phtml"
  43. #define SHOUTCAST_TUNEIN_BASE_URL "http://www.shoutcast.com"
  44. #define SHOUTCAST_TV_TUNEIN_URL "http://www.shoutcast.com/sbin/tunein-tvstation.pls?id="
  45. /*****************************************************************************
  46.  * Local prototypes
  47.  *****************************************************************************/
  48. static int Demux( demux_t *p_demux);
  49. static int Control( demux_t *p_demux, int i_query, va_list args );
  50. static int DemuxGenre( demux_t *p_demux );
  51. static int DemuxStation( demux_t *p_demux );
  52. /*****************************************************************************
  53.  * Import_Shoutcast: main import function
  54.  *****************************************************************************/
  55. int Import_Shoutcast( vlc_object_t *p_this )
  56. {
  57.     demux_t *p_demux = (demux_t *)p_this;
  58.     if( !demux_IsForced( p_demux, "shout-winamp" ) )
  59.         return VLC_EGENERIC;
  60.     STANDARD_DEMUX_INIT_MSG( "using shoutcast playlist reader" );
  61.     p_demux->p_sys->p_xml = NULL;
  62.     p_demux->p_sys->p_xml_reader = NULL;
  63.     /* Do we want to list adult content ? */
  64.     var_Create( p_demux, "shoutcast-show-adult",
  65.                 VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  66.     p_demux->p_sys->b_adult = var_GetBool( p_demux, "shoutcast-show-adult" );
  67.     return VLC_SUCCESS;
  68. }
  69. /*****************************************************************************
  70.  * Deactivate: frees unused data
  71.  *****************************************************************************/
  72. void Close_Shoutcast( vlc_object_t *p_this )
  73. {
  74.     demux_t *p_demux = (demux_t *)p_this;
  75.     demux_sys_t *p_sys = p_demux->p_sys;
  76.     if( p_sys->p_xml_reader )
  77.         xml_ReaderDelete( p_sys->p_xml, p_sys->p_xml_reader );
  78.     if( p_sys->p_xml )
  79.         xml_Delete( p_sys->p_xml );
  80.     free( p_sys );
  81. }
  82. static int Demux( demux_t *p_demux )
  83. {
  84.     demux_sys_t *p_sys = p_demux->p_sys;
  85.     xml_t *p_xml;
  86.     xml_reader_t *p_xml_reader;
  87.     char *psz_eltname = NULL;
  88.     INIT_PLAYLIST_STUFF;
  89.     p_sys->p_current_input = p_current_input;
  90.     p_xml = p_sys->p_xml = xml_Create( p_demux );
  91.     if( !p_xml ) return -1;
  92.     p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s );
  93.     if( !p_xml_reader ) return -1;
  94.     p_sys->p_xml_reader = p_xml_reader;
  95.     /* check root node */
  96.     if( xml_ReaderRead( p_xml_reader ) != 1 )
  97.     {
  98.         msg_Err( p_demux, "invalid file (no root node)" );
  99.         return -1;
  100.     }
  101.     if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
  102.         ( psz_eltname = xml_ReaderName( p_xml_reader ) ) == NULL ||
  103.         ( strcmp( psz_eltname, "genrelist" )
  104.           && strcmp( psz_eltname, "stationlist" ) ) )
  105.     {
  106.         msg_Err( p_demux, "invalid root node %i, %s",
  107.                  xml_ReaderNodeType( p_xml_reader ), psz_eltname );
  108.         free( psz_eltname );
  109.         return -1;
  110.     }
  111.     if( !strcmp( psz_eltname, "genrelist" ) )
  112.     {
  113.         /* we're reading a genre list */
  114.         free( psz_eltname );
  115.         if( DemuxGenre( p_demux ) ) return -1;
  116.     }
  117.     else
  118.     {
  119.         /* we're reading a station list */
  120.         free( psz_eltname );
  121.         if( DemuxStation( p_demux ) ) return -1;
  122.     }
  123.     HANDLE_PLAY_AND_RELEASE;
  124.     return 0; /* Needed for correct operation of go back */
  125. }
  126. #define GET_VALUE( a ) 
  127.                         if( !strcmp( psz_attrname, #a ) ) 
  128.                         { 
  129.                             psz_ ## a = strdup( psz_attrvalue ); 
  130.                         }
  131. /* <genrelist>
  132.  *   <genre name="the name"></genre>
  133.  *   ...
  134.  * </genrelist>
  135.  **/
  136. static int DemuxGenre( demux_t *p_demux )
  137. {
  138.     demux_sys_t *p_sys = p_demux->p_sys;
  139.     char *psz_name = NULL; /* genre name */
  140.     char *psz_eltname = NULL; /* tag name */
  141.     input_item_t *p_input;
  142.     while( xml_ReaderRead( p_sys->p_xml_reader ) == 1 )
  143.     {
  144.         int i_type;
  145.         // Get the node type
  146.         i_type = xml_ReaderNodeType( p_sys->p_xml_reader );
  147.         switch( i_type )
  148.         {
  149.             // Error
  150.             case -1:
  151.                 return -1;
  152.                 break;
  153.             case XML_READER_STARTELEM:
  154.                 // Read the element name
  155.                 psz_eltname = xml_ReaderName( p_sys->p_xml_reader );
  156.                 if( !psz_eltname ) return -1;
  157.                 if( !strcmp( psz_eltname, "genre" ) )
  158.                 {
  159.                     // Read the attributes
  160.                     while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS )
  161.                     {
  162.                         char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader );
  163.                         char *psz_attrvalue =
  164.                             xml_ReaderValue( p_sys->p_xml_reader );
  165.                         if( !psz_attrname || !psz_attrvalue )
  166.                         {
  167.                             FREENULL(psz_attrname);
  168.                             FREENULL(psz_attrvalue);
  169.                             free(psz_eltname);
  170.                             /*FIXME: isn't return a bit too much. what about break*/
  171.                             return -1;
  172.                         }
  173.                         GET_VALUE( name )
  174.                         else
  175.                         {
  176.                             msg_Warn( p_demux,
  177.                                       "unexpected attribure %s in element %s",
  178.                                       psz_attrname,psz_eltname );
  179.                         }
  180.                         free( psz_attrname );
  181.                         free( psz_attrvalue );
  182.                     }
  183.                 }
  184.                 free( psz_eltname ); psz_eltname = NULL;
  185.                 break;
  186.             case XML_READER_TEXT:
  187.                 break;
  188.             // End element
  189.             case XML_READER_ENDELEM:
  190.                 // Read the element name
  191.                 psz_eltname = xml_ReaderName( p_sys->p_xml_reader );
  192.                 if( !psz_eltname ) return -1;
  193.                 if( !strcmp( psz_eltname, "genre" ) )
  194.                 {
  195.                     char* psz_mrl;
  196.                     if( asprintf( &psz_mrl, SHOUTCAST_BASE_URL "?genre=%s",
  197.                              psz_name ) != -1 )
  198.                     {
  199.                         p_input = input_item_New( p_demux, psz_mrl, psz_name );
  200.                         input_item_CopyOptions( p_sys->p_current_input, p_input );
  201.                         free( psz_mrl );
  202.                         input_item_AddSubItem( p_sys->p_current_input, p_input );
  203.                         vlc_gc_decref( p_input );
  204.                     }
  205.                     FREENULL( psz_name );
  206.                 }
  207.                 FREENULL( psz_eltname );
  208.                 break;
  209.         }
  210.     }
  211.     return 0;
  212. }
  213. /* radio stations:
  214.  * <stationlist>
  215.  *   <tunein base="/sbin/tunein-station.pls"></tunein>
  216.  *   <station name="the name"
  217.  *            mt="mime type"
  218.  *            id="the id"
  219.  *            br="bit rate"
  220.  *            genre="A big genre string"
  221.  *            ct="current track name/author/..."
  222.  *            lc="listener count"></station>
  223.  * </stationlist>
  224.  *
  225.  * TV stations:
  226.  * <stationlist>
  227.  *   <tunein base="/sbin/tunein-station.pls"></tunein>
  228.  *   <station name="the name"
  229.  *            id="the id"
  230.  *            br="bit rate"
  231.  *            rt="rating"
  232.  *            load="server load ?"
  233.  *            ct="current track name/author/..."
  234.  *            genre="A big genre string"
  235.  *            lc="listener count"></station>
  236.  * </stationlist>
  237.  **/
  238. static int DemuxStation( demux_t *p_demux )
  239. {
  240.     demux_sys_t *p_sys = p_demux->p_sys;
  241.     input_item_t *p_input;
  242.     char *psz_base = NULL; /* */
  243.     char *psz_name = NULL; /* genre name */
  244.     char *psz_mt = NULL; /* mime type */
  245.     char *psz_id = NULL; /* id */
  246.     char *psz_br = NULL; /* bit rate */
  247.     char *psz_genre = NULL; /* genre */
  248.     char *psz_ct = NULL; /* current track */
  249.     char *psz_lc = NULL; /* listener count */
  250.     /* If these are set then it's *not* a radio but a TV */
  251.     char *psz_rt = NULL; /* rating for shoutcast TV */
  252.     char *psz_load = NULL; /* load for shoutcast TV */
  253.     char *psz_eltname = NULL; /* tag name */
  254.     while( xml_ReaderRead( p_sys->p_xml_reader ) == 1 )
  255.     {
  256.         int i_type;
  257.         // Get the node type
  258.         i_type = xml_ReaderNodeType( p_sys->p_xml_reader );
  259.         switch( i_type )
  260.         {
  261.             // Error
  262.             case -1:
  263.                 return -1;
  264.                 break;
  265.             case XML_READER_STARTELEM:
  266.                 // Read the element name
  267.                 psz_eltname = xml_ReaderName( p_sys->p_xml_reader );
  268.                 if( !psz_eltname ) return -1;
  269.                 // Read the attributes
  270.                 if( !strcmp( psz_eltname, "tunein" ) )
  271.                 {
  272.                     while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS )
  273.                     {
  274.                         char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader );
  275.                         char *psz_attrvalue =
  276.                             xml_ReaderValue( p_sys->p_xml_reader );
  277.                         if( !psz_attrname || !psz_attrvalue )
  278.                         {
  279.                             free( psz_eltname );
  280.                             free( psz_attrname );
  281.                             free( psz_attrvalue );
  282.                             return -1;
  283.                         }
  284.                         GET_VALUE( base )
  285.                         else
  286.                         {
  287.                             msg_Warn( p_demux,
  288.                                       "unexpected attribure %s in element %s",
  289.                                       psz_attrname, psz_eltname );
  290.                         }
  291.                         free( psz_attrname );
  292.                         free( psz_attrvalue );
  293.                     }
  294.                 }
  295.                 else if( !strcmp( psz_eltname, "station" ) )
  296.                 {
  297.                     while( xml_ReaderNextAttr( p_sys->p_xml_reader ) == VLC_SUCCESS )
  298.                     {
  299.                         char *psz_attrname = xml_ReaderName( p_sys->p_xml_reader );
  300.                         char *psz_attrvalue =
  301.                             xml_ReaderValue( p_sys->p_xml_reader );
  302.                         if( !psz_attrname || !psz_attrvalue )
  303.                         {
  304.                             free( psz_eltname );
  305.                             free( psz_attrname );
  306.                             free( psz_attrvalue );
  307.                             return -1;
  308.                         }
  309.                         GET_VALUE( name )
  310.                         else GET_VALUE( mt )
  311.                         else GET_VALUE( id )
  312.                         else GET_VALUE( br )
  313.                         else GET_VALUE( genre )
  314.                         else GET_VALUE( ct )
  315.                         else GET_VALUE( lc )
  316.                         else GET_VALUE( rt )
  317.                         else GET_VALUE( load )
  318.                         else
  319.                         {
  320.                             msg_Warn( p_demux,
  321.                                       "unexpected attribute %s in element %s",
  322.                                       psz_attrname, psz_eltname );
  323.                         }
  324.                         free( psz_attrname );
  325.                         free( psz_attrvalue );
  326.                     }
  327.                 }
  328.                 free( psz_eltname );
  329.                 break;
  330.             case XML_READER_TEXT:
  331.                 break;
  332.             // End element
  333.             case XML_READER_ENDELEM:
  334.                 // Read the element name
  335.                 psz_eltname = xml_ReaderName( p_sys->p_xml_reader );
  336.                 if( !psz_eltname ) return -1;
  337.                 if( !strcmp( psz_eltname, "station" ) &&
  338.                     ( psz_base || ( psz_rt && psz_load &&
  339.                     ( p_sys->b_adult || strcmp( psz_rt, "NC17" ) ) ) ) )
  340.                 {
  341.                     char *psz_mrl = NULL;
  342.                     if( psz_rt || psz_load )
  343.                     {
  344.                         /* tv */
  345.                         if( asprintf( &psz_mrl, SHOUTCAST_TV_TUNEIN_URL "%s",
  346.                                  psz_id ) == -1)
  347.                             psz_mrl = NULL;
  348.                     }
  349.                     else
  350.                     {
  351.                         /* radio */
  352.                         if( asprintf( &psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s",
  353.                              psz_base, psz_id ) == -1 )
  354.                             psz_mrl = NULL;
  355.                     }
  356.                     p_input = input_item_New( p_demux, psz_mrl, psz_name );
  357.                     input_item_CopyOptions( p_sys->p_current_input, p_input );
  358.                     free( psz_mrl );
  359. #define SADD_INFO( type, field ) 
  360.                     if( field ) 
  361.                         input_item_AddInfo( p_input, _("Shoutcast"), 
  362.                                             vlc_gettext(type), "%s", field )
  363.                     SADD_INFO( N_("Mime"), psz_mt );
  364.                     SADD_INFO( N_("Bitrate"), psz_br );
  365.                     SADD_INFO( N_("Listeners"), psz_lc );
  366.                     SADD_INFO( N_("Load"), psz_load );
  367.                     if( psz_genre )
  368.                         input_item_SetGenre( p_input, psz_genre );
  369.                     if( psz_ct )
  370.                         input_item_SetNowPlaying( p_input, psz_ct );
  371.                     if( psz_rt )
  372.                         input_item_SetRating( p_input, psz_rt );
  373.                     input_item_AddSubItem( p_sys->p_current_input, p_input );
  374.                     vlc_gc_decref( p_input );
  375.                     FREENULL( psz_name );
  376.                     FREENULL( psz_mt );
  377.                     FREENULL( psz_id );
  378.                     FREENULL( psz_br );
  379.                     FREENULL( psz_genre );
  380.                     FREENULL( psz_ct );
  381.                     FREENULL( psz_lc );
  382.                     FREENULL( psz_rt );
  383.                 }
  384.                 free( psz_eltname );
  385.                 break;
  386.         }
  387.     }
  388.     return 0;
  389. }
  390. static int Control( demux_t *p_demux, int i_query, va_list args )
  391. {
  392.     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
  393.     return VLC_EGENERIC;
  394. }