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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * b4s.c : B4S playlist format import
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  * $Id: be33b7826fb3b151669bb09d1fed8b6cdae19dc8 $
  6.  *
  7.  * Authors: Sigmund Augdal Helberg <dnumgis@videolan.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.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_demux.h>
  31. #include <vlc_interface.h>
  32. #include "playlist.h"
  33. #include "vlc_xml.h"
  34. struct demux_sys_t
  35. {
  36.     char *psz_prefix;
  37.     xml_t *p_xml;
  38.     xml_reader_t *p_xml_reader;
  39. };
  40. /*****************************************************************************
  41.  * Local prototypes
  42.  *****************************************************************************/
  43. static int Demux( demux_t *p_demux);
  44. static int Control( demux_t *p_demux, int i_query, va_list args );
  45. //static char *GetNextToken(char *psz_cur_string);
  46. static int IsWhitespace( char *psz_string );
  47. /*****************************************************************************
  48.  * Import_B4S: main import function
  49.  *****************************************************************************/
  50. int Import_B4S( vlc_object_t *p_this )
  51. {
  52.     DEMUX_BY_EXTENSION_OR_FORCED_MSG( ".b4s", "b4s-open",
  53.                                       "using B4S playlist reader" );
  54.     p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
  55.     p_demux->p_sys->p_xml = NULL;
  56.     p_demux->p_sys->p_xml_reader = NULL;
  57.     return VLC_SUCCESS;
  58. }
  59. /*****************************************************************************
  60.  * Deactivate: frees unused data
  61.  *****************************************************************************/
  62. void Close_B4S( vlc_object_t *p_this )
  63. {
  64.     demux_t *p_demux = (demux_t *)p_this;
  65.     demux_sys_t *p_sys = p_demux->p_sys;
  66.     free( p_sys->psz_prefix );
  67.     if( p_sys->p_xml_reader ) xml_ReaderDelete( p_sys->p_xml, p_sys->p_xml_reader );
  68.     if( p_sys->p_xml ) xml_Delete( p_sys->p_xml );
  69.     free( p_sys );
  70. }
  71. static int Demux( demux_t *p_demux )
  72. {
  73.     demux_sys_t *p_sys = p_demux->p_sys;
  74.     int i_ret;
  75.     xml_t *p_xml;
  76.     xml_reader_t *p_xml_reader;
  77.     char *psz_elname = NULL;
  78.     int i_type;
  79.     input_item_t *p_input;
  80.     char *psz_mrl = NULL, *psz_name = NULL, *psz_genre = NULL;
  81.     char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL;
  82.     INIT_PLAYLIST_STUFF;
  83.     p_xml = p_sys->p_xml = xml_Create( p_demux );
  84.     if( !p_xml ) return -1;
  85.     psz_elname = stream_ReadLine( p_demux->s );
  86.     free( psz_elname );
  87.     psz_elname = NULL;
  88.     p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s );
  89.     if( !p_xml_reader ) return -1;
  90.     p_sys->p_xml_reader = p_xml_reader;
  91.     /* xml */
  92.     /* check root node */
  93.     if( xml_ReaderRead( p_xml_reader ) != 1 )
  94.     {
  95.         msg_Err( p_demux, "invalid file (no root node)" );
  96.         return -1;
  97.     }
  98.     if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
  99.         ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
  100.         strcmp( psz_elname, "WinampXML" ) )
  101.     {
  102.         msg_Err( p_demux, "invalid root node %i, %s",
  103.                  xml_ReaderNodeType( p_xml_reader ), psz_elname );
  104.         free( psz_elname );
  105.         return -1;
  106.     }
  107.     free( psz_elname );
  108.     /* root node should not have any attributes, and should only
  109.      * contain the "playlist node */
  110.     /* Skip until 1st child node */
  111.     while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 &&
  112.            xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM );
  113.     if( i_ret != 1 )
  114.     {
  115.         msg_Err( p_demux, "invalid file (no child node)" );
  116.         return -1;
  117.     }
  118.     if( ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
  119.         strcmp( psz_elname, "playlist" ) )
  120.     {
  121.         msg_Err( p_demux, "invalid child node %s", psz_elname );
  122.         free( psz_elname );
  123.         return -1;
  124.     }
  125.     free( psz_elname ); psz_elname = NULL;
  126.     // Read the attributes
  127.     while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
  128.     {
  129.         char *psz_name = xml_ReaderName( p_xml_reader );
  130.         char *psz_value = xml_ReaderValue( p_xml_reader );
  131.         if( !psz_name || !psz_value )
  132.         {
  133.             free( psz_name );
  134.             free( psz_value );
  135.             return -1;
  136.         }
  137.         if( !strcmp( psz_name, "num_entries" ) )
  138.         {
  139.             msg_Dbg( p_demux, "playlist has %d entries", atoi(psz_value) );
  140.         }
  141.         else if( !strcmp( psz_name, "label" ) )
  142.         {
  143.             input_item_SetName( p_current_input, psz_value );
  144.         }
  145.         else
  146.         {
  147.             msg_Warn( p_demux, "stray attribute %s with value %s in element"
  148.                       " 'playlist'", psz_name, psz_value );
  149.         }
  150.         free( psz_name );
  151.         free( psz_value );
  152.     }
  153.     while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 )
  154.     {
  155.         // Get the node type
  156.         i_type = xml_ReaderNodeType( p_xml_reader );
  157.         switch( i_type )
  158.         {
  159.             // Error
  160.             case -1:
  161.                 return -1;
  162.                 break;
  163.             case XML_READER_STARTELEM:
  164.             {
  165.                 // Read the element name
  166.                 free( psz_elname );
  167.                 psz_elname = xml_ReaderName( p_xml_reader );
  168.                 if( !psz_elname ) return -1;
  169.                 // Read the attributes
  170.                 while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
  171.                 {
  172.                     char *psz_name = xml_ReaderName( p_xml_reader );
  173.                     char *psz_value = xml_ReaderValue( p_xml_reader );
  174.                     if( !psz_name || !psz_value ) return -1;
  175.                     if( !strcmp( psz_elname, "entry" ) &&
  176.                         !strcmp( psz_name, "Playstring" ) )
  177.                     {
  178.                         psz_mrl = strdup( psz_value );
  179.                     }
  180.                     else
  181.                     {
  182.                         msg_Warn( p_demux, "unexpected attribure %s in element %s",
  183.                                   psz_name, psz_elname );
  184.                     }
  185.                     free( psz_name );
  186.                     free( psz_value );
  187.                 }
  188.                 break;
  189.             }
  190.             case XML_READER_TEXT:
  191.             {
  192.                 char *psz_text = xml_ReaderValue( p_xml_reader );
  193.                 if( IsWhitespace( psz_text ) )
  194.                 {
  195.                     free( psz_text );
  196.                     break;
  197.                 }
  198.                 if( !strcmp( psz_elname, "Name" ) )
  199.                 {
  200.                     psz_name = strdup( psz_text );
  201.                 }
  202.                 else if( !strcmp( psz_elname, "Genre" ) )
  203.                 {
  204.                     psz_genre = strdup( psz_text );
  205.                 }
  206.                 else if( !strcmp( psz_elname, "Nowplaying" ) )
  207.                 {
  208.                     psz_now = strdup( psz_text );
  209.                 }
  210.                 else if( !strcmp( psz_elname, "Listeners" ) )
  211.                 {
  212.                     psz_listeners = strdup( psz_text );
  213.                 }
  214.                 else if( !strcmp( psz_elname, "Bitrate" ) )
  215.                 {
  216.                     psz_bitrate = strdup( psz_text );
  217.                 }
  218.                 else if( !strcmp( psz_elname, "" ) )
  219.                 {
  220.                     ;
  221.                 }
  222.                 else
  223.                 {
  224.                     msg_Warn( p_demux, "unexpected text in element '%s'",
  225.                               psz_elname );
  226.                 }
  227.                 free( psz_text );
  228.                 break;
  229.             }
  230.             // End element
  231.             case XML_READER_ENDELEM:
  232.             {
  233.                 // Read the element name
  234.                 free( psz_elname );
  235.                 psz_elname = xml_ReaderName( p_xml_reader );
  236.                 if( !psz_elname ) return -1;
  237.                 if( !strcmp( psz_elname, "entry" ) )
  238.                 {
  239.                     p_input = input_item_New( p_demux, psz_mrl, psz_name );
  240.                     if( psz_now )
  241.                         input_item_SetNowPlaying( p_input, psz_now );
  242.                     if( psz_genre )
  243.                         input_item_SetGenre( p_input, psz_genre );
  244.                     if( psz_listeners )
  245.                         msg_Err( p_demux, "Unsupported meta listeners" );
  246.                     if( psz_bitrate )
  247.                         msg_Err( p_demux, "Unsupported meta bitrate" );
  248.                     input_item_AddSubItem( p_current_input, p_input );
  249.                     vlc_gc_decref( p_input );
  250.                     FREENULL( psz_name );
  251.                     FREENULL( psz_mrl );
  252.                     FREENULL( psz_genre );
  253.                     FREENULL( psz_bitrate );
  254.                     FREENULL( psz_listeners );
  255.                     FREENULL( psz_now );
  256.                 }
  257.                 free( psz_elname );
  258.                 psz_elname = strdup("");
  259.                 break;
  260.             }
  261.         }
  262.     }
  263.     if( i_ret != 0 )
  264.     {
  265.         msg_Warn( p_demux, "error while parsing data" );
  266.     }
  267.    free( psz_elname );
  268.     HANDLE_PLAY_AND_RELEASE;
  269.     return 0; /* Needed for correct operation of go back */
  270. }
  271. static int Control( demux_t *p_demux, int i_query, va_list args )
  272. {
  273.     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
  274.     return VLC_EGENERIC;
  275. }
  276. #if 0
  277. /**
  278.  * Get a in-string pointer to the start of the next token from a
  279.  * string terminating the pointer returned by a previous call.
  280.  *
  281.  * param psz_cur_string The string to search for the token from
  282.  * return a pointer to withing psz_cur_string, or NULL if no token
  283.  * was found
  284.  * note The returned pointer may contain more than one
  285.  * token, Run GetNextToken once more to terminate the token properly
  286.  */
  287. static char *GetNextToken(char *psz_cur_string) {
  288.     while (*psz_cur_string && !isspace(*psz_cur_string))
  289.         psz_cur_string++;
  290.     if (!*psz_cur_string)
  291.         return NULL;
  292.     *psz_cur_string++ = '';
  293.     while (*psz_cur_string && isspace(*psz_cur_string))
  294.         psz_cur_string++;
  295.     return psz_cur_string;
  296. }
  297. #endif
  298. static int IsWhitespace( char *psz_string )
  299. {
  300.     while( *psz_string )
  301.     {
  302.         if( *psz_string != ' ' && *psz_string != 't' && *psz_string != 'r' &&
  303.             *psz_string != 'n' )
  304.         {
  305.             return false;
  306.         }
  307.         psz_string++;
  308.     }
  309.     return true;
  310. }