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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * ram.c : RAM playlist format import
  3.  *****************************************************************************
  4.  * Copyright (C) 2009 the VideoLAN team
  5.  * $Id: bdcbb5a5f587dc153053f9b2a7b020ce80fdf26d $
  6.  *
  7.  * Authors: Srikanth Raju <srikiraju@gmail.com>
  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. An example:
  25. rtsp://helixserver.example.com/video1.rm?rpcontextheight=250
  26. &rpcontextwidth=280&rpcontexturl="http://www.example.com/relatedinfo1.html"
  27. rtsp://helixserver.example.com/video2.rm?rpurl="http://www.example.com/index.html"
  28. rtsp://helixserver.example.com/sample1.smil?screensize=full
  29. rtsp://helixserver.example.com/audio1.rm?start=55&end=1:25
  30. rtsp://helixserver.example.com/introvid.rm?title="Introduction to Streaming Media
  31. Production"&author="RealNetworks, Inc."&copyright="&#169;2001, RealNetworks, Inc."
  32. rtsp://helixserver.example.com/song1.rm?clipinfo="title=Artist of the Year|artist name=Your Name
  33. Here|album name=My Debut|genre=Rock|copyright=2001|year=2001|comments=This one really
  34. knows how to rock!"
  35. See also:
  36. http://service.real.com/help/library/guides/realone/IntroGuide/HTML/htmfiles/ramsum.htm
  37. http://service.real.com/help/library/guides/realone/IntroGuide/HTML/htmfiles/ramfile.htm
  38. */
  39. /*****************************************************************************
  40.  * Preamble
  41.  *****************************************************************************/
  42. #ifdef HAVE_CONFIG_H
  43. # include "config.h"
  44. #endif
  45. #include <vlc_common.h>
  46. #include <vlc_demux.h>
  47. #include <vlc_charset.h>
  48. #include <ctype.h>
  49. #include "playlist.h"
  50. struct demux_sys_t
  51. {
  52.     char *psz_prefix;
  53. };
  54. /*****************************************************************************
  55.  * Local prototypes
  56.  *****************************************************************************/
  57. static int Demux( demux_t *p_demux);
  58. static int Control( demux_t *p_demux, int i_query, va_list args );
  59. static void ParseClipInfo( const char * psz_clipinfo, char **ppsz_artist, char **ppsz_title,
  60.                            char **ppsz_album, char **ppsz_genre, char **ppsz_year,
  61.                            char **ppsz_cdnum, char **ppsz_comments );
  62. /**
  63.  * Import_RAM: main import function
  64.  * @param p_this: this demux object
  65.  * @return VLC_SUCCESS if everything is okay
  66.  */
  67. int Import_RAM( vlc_object_t *p_this )
  68. {
  69.     demux_t *p_demux = (demux_t *)p_this;
  70.     const uint8_t *p_peek;
  71.     CHECK_PEEK( p_peek, 8 );
  72.     if(! demux_IsPathExtension( p_demux, ".ram" ) ||
  73.          demux_IsPathExtension( p_demux, ".rm" ) )
  74.         return VLC_EGENERIC;
  75.     STANDARD_DEMUX_INIT_MSG( "found valid RAM playlist" );
  76.     p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
  77.     return VLC_SUCCESS;
  78. }
  79. /**
  80.  * Frees up memory on module close
  81.  * @param p_this: this demux object
  82.  */
  83. void Close_RAM( vlc_object_t *p_this )
  84. {
  85.     demux_t *p_demux = (demux_t *)p_this;
  86.     free( p_demux->p_sys->psz_prefix );
  87.     free( p_demux->p_sys );
  88. }
  89. /**
  90.  * Returns a UTF8 encoded version of the string
  91.  * @param str: input string
  92.  * @return pointer to UTF8 string
  93.  */
  94. static inline char *MaybeFromLocaleDup (const char *str)
  95. {
  96.     if (str == NULL)
  97.         return NULL;
  98.     return IsUTF8 (str) ? strdup (str) : FromLocaleDup (str);
  99. }
  100. /**
  101.  * Converts a string to UTF8 encoding
  102.  * @param str: input string
  103.  */
  104. static inline void MaybeFromLocaleRep (char **str)
  105. {
  106.     char *const orig_str = *str;
  107.     if ((orig_str != NULL) && !IsUTF8 (orig_str))
  108.     {
  109.         *str = FromLocaleDup (orig_str);
  110.         free (orig_str);
  111.     }
  112. }
  113. /**
  114.  * Skips blanks in a given buffer
  115.  * @param s: input string
  116.  * @param i_strlen: length of the buffer
  117.  */
  118. static const char *SkipBlanks( const char *s, size_t i_strlen )
  119. {
  120.     while( i_strlen > 0 ) {
  121.         switch( *s )
  122.         {
  123.             case ' ':
  124.             case 't':
  125.             case 'r':
  126.             case 'n':
  127.                 --i_strlen;
  128.                 ++s;
  129.                 break;
  130.             default:
  131.                 i_strlen = 0;
  132.         }
  133.     }
  134.     return s;
  135. }
  136. /**
  137.  * Converts a time of format hour:minutes:sec.fraction to seconds
  138.  * @param s: input string
  139.  * @param i_strlen: length of the buffer
  140.  * @return time in seconds
  141.  */
  142. static int ParseTime( const char *s, size_t i_strlen)
  143. {
  144.     // need to parse hour:minutes:sec.fraction string
  145.     int result = 0;
  146.     int val;
  147.     const char *end = s + i_strlen;
  148.     // skip leading spaces if any
  149.     s = SkipBlanks(s, i_strlen);
  150.     val = 0;
  151.     while( (s < end) && isdigit(*s) )
  152.     {
  153.         int newval = val*10 + (*s - '0');
  154.         if( newval < val )
  155.         {
  156.             // overflow
  157.             val = 0;
  158.             break;
  159.         }
  160.         val = newval;
  161.         ++s;
  162.     }
  163.     result = val;
  164.     s = SkipBlanks(s, end-s);
  165.     if( *s == ':' )
  166.     {
  167.         ++s;
  168.         s = SkipBlanks(s, end-s);
  169.         result = result * 60;
  170.         val = 0;
  171.         while( (s < end) && isdigit(*s) )
  172.         {
  173.             int newval = val*10 + (*s - '0');
  174.             if( newval < val )
  175.             {
  176.                 // overflow
  177.                 val = 0;
  178.                 break;
  179.             }
  180.             val = newval;
  181.             ++s;
  182.         }
  183.         result += val;
  184.         s = SkipBlanks(s, end-s);
  185.         if( *s == ':' )
  186.         {
  187.             ++s;
  188.             s = SkipBlanks(s, end-s);
  189.             result = result * 60;
  190.             val = 0;
  191.             while( (s < end) && isdigit(*s) )
  192.             {
  193.                 int newval = val*10 + (*s - '0');
  194.                 if( newval < val )
  195.                 {
  196.                     // overflow
  197.                     val = 0;
  198.                     break;
  199.                 }
  200.                 val = newval;
  201.                 ++s;
  202.             }
  203.             result += val;
  204.             // TODO: one day, we may need to parse fraction for sub-second resolution
  205.         }
  206.     }
  207.     return result;
  208. }
  209. /**
  210.  * Main demux callback function
  211.  * @param p_demux: this demux object
  212.  */
  213. static int Demux( demux_t *p_demux )
  214. {
  215.     char       *psz_line;
  216.     char       *psz_name = NULL;
  217.     char       *psz_artist = NULL, *psz_album = NULL, *psz_genre = NULL, *psz_year = NULL;
  218.     char       *psz_author = NULL, *psz_title = NULL, *psz_copyright = NULL, *psz_cdnum = NULL, *psz_comments = NULL;
  219.     int        i_parsed_duration = 0;
  220.     mtime_t    i_duration = -1;
  221.     const char **ppsz_options = NULL;
  222.     int        i_options = 0, i_start = 0, i_stop = 0;
  223.     bool b_cleanup = false;
  224.     input_item_t *p_input;
  225.     INIT_PLAYLIST_STUFF;
  226.     psz_line = stream_ReadLine( p_demux->s );
  227.     while( psz_line )
  228.     {
  229.         char *psz_parse = psz_line;
  230.         /* Skip leading tabs and spaces */
  231.         while( *psz_parse == ' ' || *psz_parse == 't' ||
  232.                *psz_parse == 'n' || *psz_parse == 'r' ) psz_parse++;
  233.         if( *psz_parse == '#' )
  234.         {
  235.             /* Ignore comments */
  236.         }
  237.         else if( *psz_parse )
  238.         {
  239.             char *psz_mrl, *psz_option_start, *psz_option_next, *psz_temp_mrl, *psz_option;
  240.             char *psz_param, *psz_value;
  241.             if( !psz_name || !*psz_name )
  242.             {
  243.                 /* Default filename as name for relative entries
  244.                    TODO: Currently not used. Either remove or use */
  245.                 psz_name = MaybeFromLocaleDup( psz_parse );
  246.             }
  247.             /* Get the MRL from the file. Note that this might contain parameters of form ?param1=value1&param2=value2 in a RAM file */
  248.             psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix );
  249.             MaybeFromLocaleRep( &psz_mrl );
  250.             b_cleanup = true;
  251.             if ( !psz_mrl ) goto error;
  252.             /* We have the MRL, now we have to check for options and parse them from MRL */
  253.             psz_temp_mrl = strdup( psz_mrl );
  254.             psz_option_start = strchr( psz_temp_mrl, '?' ); /* Look for start of options */
  255.             if( psz_option_start )
  256.             {
  257.                 psz_option_start++;
  258.                 psz_option_next = psz_option_start;
  259.                 while( 1 ) /* Process each option */
  260.                 {
  261.                     /* Look for end of first option which maybe a & or  */
  262.                     psz_option_start = psz_option_next;
  263.                     psz_option_next = strchr( psz_option_start, '&' );
  264.                     if( psz_option_next )
  265.                     {
  266.                         *psz_option_next = '';
  267.                         psz_option_next++;
  268.                     }
  269.                     else
  270.                         psz_option_next = strchr( psz_option_start, '' );
  271.                     /* Quit if options are over */
  272.                     if( psz_option_next == psz_option_start )
  273.                         break;
  274.                     psz_option = MaybeFromLocaleDup( psz_option_start );
  275.                     /* If this option is screwed up, try the next one */
  276.                     if( !psz_option )
  277.                         continue;
  278.                     /* Parse out param and value */
  279.                     psz_param = psz_option;
  280.                     if( strchr( psz_option, '=' ) )
  281.                     {
  282.                         psz_value = strchr( psz_option, '=' ) + 1;
  283.                         *(strchr( psz_option, '=' )) = '';
  284.                     }
  285.                     else
  286.                         break;
  287.                     /* Take action based on parameter value in the below if else structure */
  288.                     /* TODO: Remove any quotes surrounding values if required */
  289.                     if( !strcmp( psz_param, "clipinfo" ) )
  290.                     {
  291.                         ParseClipInfo( psz_value, &psz_artist, &psz_title,
  292.                            &psz_album, &psz_genre, &psz_year,
  293.                            &psz_cdnum, &psz_comments ); /* clipinfo has various sub parameters, which is parsed by this function */
  294.                     }
  295.                     else if( !strcmp( psz_param, "author" ) )
  296.                         psz_author = strdup(psz_value);
  297.                     else if( !strcmp( psz_param, "start" ) )
  298.                     {
  299.                         i_start = ParseTime( psz_value, strlen( psz_value ) );
  300.                         char *temp;
  301.                         if( i_start )
  302.                         {
  303.                             if( asprintf( &temp, ":start-time=%d", i_start ) != -1 )
  304.                                 INSERT_ELEM( ppsz_options, i_options, i_options, temp );
  305.                         }
  306.                     }
  307.                     else if( !strcmp( psz_param, "end" ) )
  308.                     {
  309.                         i_stop = ParseTime( psz_value, strlen( psz_value ) );
  310.                         char *temp;
  311.                         if( i_stop )
  312.                         {
  313.                             if( asprintf( &temp, ":stop-time=%d", i_stop ) != -1 )
  314.                                 INSERT_ELEM( ppsz_options, i_options, i_options, temp );
  315.                         }
  316.                     }
  317.                     else if( !strcmp( psz_param, "title" ) )
  318.                         psz_title = strdup(psz_value);
  319.                     else if( !strcmp( psz_param, "copyright" ) )
  320.                         psz_copyright = strdup(psz_value);
  321.                     else
  322.                     {   /* TODO: insert option anyway? Currently ignores*/
  323.                         /* INSERT_ELEM( ppsz_options, i_options, i_options, psz_option ); */
  324.                     }
  325.                     free( psz_option );
  326.                 }
  327.                 *(strchr( psz_mrl, '?' )) = ''; /* Remove options from MRL because VLC can't get the file otherwise */
  328.             }
  329.             free( psz_temp_mrl );
  330.             /* Create the input item and pump in all the options into playlist item */
  331.             p_input = input_item_NewExt( p_demux, psz_mrl, psz_title, i_options, ppsz_options, 0, i_duration );
  332.             if( !EMPTY_STR( psz_artist ) ) input_item_SetArtist( p_input, psz_artist );
  333.             if( !EMPTY_STR( psz_author ) ) input_item_SetPublisher( p_input, psz_author );
  334.             if( !EMPTY_STR( psz_title ) ) input_item_SetTitle( p_input, psz_title );
  335.             if( !EMPTY_STR( psz_copyright ) ) input_item_SetCopyright( p_input, psz_copyright );
  336.             if( !EMPTY_STR( psz_album ) ) input_item_SetAlbum( p_input, psz_album );
  337.             if( !EMPTY_STR( psz_genre ) ) input_item_SetGenre( p_input, psz_genre );
  338.             if( !EMPTY_STR( psz_year ) ) input_item_SetDate( p_input, psz_copyright );
  339.             if( !EMPTY_STR( psz_cdnum ) ) input_item_SetTrackNum( p_input, psz_cdnum );
  340.             if( !EMPTY_STR( psz_comments ) ) input_item_SetDescription( p_input, psz_comments );
  341.             input_item_AddSubItem( p_current_input, p_input );
  342.             vlc_gc_decref( p_input );
  343.             free( psz_mrl );
  344.         }
  345.  error:
  346.         /* Fetch another line */
  347.         free( psz_line );
  348.         psz_line = stream_ReadLine( p_demux->s );
  349.         if( !psz_line ) b_cleanup = true;
  350.         if( b_cleanup )
  351.         {
  352.             /* Cleanup state */
  353.             while( i_options-- ) free( (char*)ppsz_options[i_options] );
  354.             FREENULL( ppsz_options );
  355.             FREENULL( psz_name );
  356.             FREENULL( psz_artist );
  357.             FREENULL( psz_title );
  358.             FREENULL( psz_author );
  359.             FREENULL( psz_copyright );
  360.             FREENULL( psz_album );
  361.             FREENULL( psz_genre );
  362.             FREENULL( psz_year );
  363.             FREENULL( psz_cdnum );
  364.             FREENULL( psz_comments );
  365.             i_options = 0;
  366.             i_parsed_duration = 0;
  367.             i_duration = -1;
  368.             i_start = 0;
  369.             i_stop = 0;
  370.             b_cleanup = false;
  371.         }
  372.     }
  373.     HANDLE_PLAY_AND_RELEASE;
  374.     var_Destroy( p_demux, "m3u-extvlcopt" );
  375.     return 0; /* Needed for correct operation of go back */
  376. }
  377. /**
  378.  * @param p_demux: This object
  379.  * @param i_query:
  380.  * @param args: List of arguments
  381.  */
  382. static int Control( demux_t *p_demux, int i_query, va_list args )
  383. {
  384.     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
  385.     return VLC_EGENERIC;
  386. }
  387. /**
  388.  * Parses clipinfo parameter
  389.  * @param psz_clipinfo: string containing the clipinfo parameter along with quotes
  390.  * @param ppsz_artist: Buffer to store artist name
  391.  * @param ppsz_title: Buffer to store title
  392.  * @param ppsz_album: Buffer to store album
  393.  * @param ppsz_genre: Buffer to store genre
  394.  * @param ppsz_year: Buffer to store year
  395.  * @param ppsz_cdnum: Buffer to store cdnum
  396.  * @param ppsz_comments: Buffer to store comments
  397.  */
  398. static void ParseClipInfo( const char *psz_clipinfo, char **ppsz_artist, char **ppsz_title,
  399.                            char **ppsz_album, char **ppsz_genre, char **ppsz_year,
  400.                            char **ppsz_cdnum, char **ppsz_comments )
  401. {
  402.     char *psz_option_next, *psz_option_start, *psz_param, *psz_value, *psz_suboption;
  403.     char *psz_temp_clipinfo = strdup( psz_clipinfo );
  404.     psz_option_start = strchr( psz_temp_clipinfo, '"' );
  405.     if( !psz_option_start )
  406.     {
  407.         free( psz_temp_clipinfo );
  408.         return;
  409.     }
  410.     psz_option_start++;
  411.     psz_option_next = psz_option_start;
  412.     while( 1 ) /* Process each sub option */
  413.     {
  414.         /* Get the sub option */
  415.         psz_option_start = psz_option_next;
  416.         psz_option_next = strchr( psz_option_start, '|' );
  417.         if( psz_option_next )
  418.             *psz_option_next = '';
  419.         else
  420.             psz_option_next = strchr( psz_option_start, '"' );
  421.         if( psz_option_next )
  422.             *psz_option_next = '';
  423.         else
  424.             psz_option_next = strchr( psz_option_start, '' );
  425.         if( psz_option_next == psz_option_start )
  426.             break;
  427.         psz_suboption = MaybeFromLocaleDup( psz_option_start );
  428.         if( !psz_suboption )
  429.             break;
  430.         /* Parse out param and value */
  431.         psz_param = psz_suboption;
  432.         if( strchr( psz_suboption, '=' ) )
  433.         {
  434.             psz_value = strchr( psz_suboption, '=' ) + 1;
  435.             *( strchr( psz_suboption, '=' ) ) = '';
  436.         }
  437.         else
  438.             break;
  439.         /* Put into args */
  440.         if( !strcmp( psz_param, "artist name" ) )
  441.             *ppsz_artist = strdup( psz_value );
  442.         else if( !strcmp( psz_param, "title" ) )
  443.             *ppsz_title = strdup( psz_value );
  444.         else if( !strcmp( psz_param, "album name" ) )
  445.             *ppsz_album = strdup( psz_value );
  446.         else if( !strcmp( psz_param, "genre" ) )
  447.             *ppsz_genre = strdup( psz_value );
  448.         else if( !strcmp( psz_param, "year" ) )
  449.             *ppsz_year = strdup( psz_value );
  450.         else if( !strcmp( psz_param, "cdnum" ) )
  451.             *ppsz_cdnum = strdup( psz_value );
  452.         else if( !strcmp( psz_param, "comments" ) )
  453.             *ppsz_comments = strdup( psz_value );
  454.         free( psz_suboption );
  455.         psz_option_next++;
  456.     }
  457.     free( psz_temp_clipinfo );
  458. }