00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <ctype.h>
00029
00030 #include <vlc/vlc.h>
00031 #include <vlc/input.h>
00032 #include <vlc/intf.h>
00033
00034 #include <errno.h>
00035 #include "playlist.h"
00036 #include "vlc_xml.h"
00037
00038 struct demux_sys_t
00039 {
00040 char *psz_prefix;
00041 playlist_t *p_playlist;
00042 xml_t *p_xml;
00043 xml_reader_t *p_xml_reader;
00044 int b_shout;
00045 };
00046
00047
00048
00049
00050 static int Demux( demux_t *p_demux);
00051 static int Control( demux_t *p_demux, int i_query, va_list args );
00052 static char *GetNextToken(char *psz_cur_string);
00053 static int IsWhitespace( char *psz_string );
00054 static void ShoutcastAdd( playlist_t *p_playlist, playlist_item_t* p_genre,
00055 playlist_item_t *p_bitrate, playlist_item_t *p_item,
00056 char *psz_genre, char *psz_bitrate );
00057
00058
00059
00060
00061 int E_(Import_B4S)( vlc_object_t *p_this )
00062 {
00063 demux_t *p_demux = (demux_t *)p_this;
00064 demux_sys_t *p_sys;
00065
00066 char *psz_ext;
00067
00068 psz_ext = strrchr ( p_demux->psz_path, '.' );
00069
00070 if( ( psz_ext && !strcasecmp( psz_ext, ".b4s") ) ||
00071 ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "b4s-open") ) ||
00072 ( p_demux->psz_demux && !strcmp(p_demux->psz_demux, "shout-b4s") ) )
00073 {
00074 ;
00075 }
00076 else
00077 {
00078 return VLC_EGENERIC;
00079 }
00080 msg_Dbg( p_demux, "using b4s playlist import");
00081
00082 p_demux->pf_control = Control;
00083 p_demux->pf_demux = Demux;
00084 p_demux->p_sys = p_sys = malloc( sizeof(demux_sys_t) );
00085 if( p_sys == NULL )
00086 {
00087 msg_Err( p_demux, "Out of memory" );
00088 return VLC_ENOMEM;
00089 }
00090 p_sys->b_shout = p_demux->psz_demux &&
00091 !strcmp(p_demux->psz_demux, "shout-b4s");
00092 p_sys->psz_prefix = E_(FindPrefix)( p_demux );
00093 p_sys->p_playlist = NULL;
00094 p_sys->p_xml = NULL;
00095 p_sys->p_xml_reader = NULL;
00096
00097 return VLC_SUCCESS;
00098 }
00099
00100
00101
00102
00103 void E_(Close_B4S)( vlc_object_t *p_this )
00104 {
00105 demux_t *p_demux = (demux_t *)p_this;
00106 demux_sys_t *p_sys = p_demux->p_sys;
00107
00108 if( p_sys->psz_prefix ) free( p_sys->psz_prefix );
00109 if( p_sys->p_playlist ) vlc_object_release( p_sys->p_playlist );
00110 if( p_sys->p_xml_reader ) xml_ReaderDelete( p_sys->p_xml, p_sys->p_xml_reader );
00111 if( p_sys->p_xml ) xml_Delete( p_sys->p_xml );
00112 free( p_sys );
00113 }
00114
00115 static int Demux( demux_t *p_demux )
00116 {
00117 demux_sys_t *p_sys = p_demux->p_sys;
00118 playlist_t *p_playlist;
00119 playlist_item_t *p_item, *p_current;
00120 playlist_item_t *p_bitrate = NULL, *p_genre = NULL;
00121
00122 vlc_bool_t b_play;
00123 int i_ret;
00124
00125 xml_t *p_xml;
00126 xml_reader_t *p_xml_reader;
00127 char *psz_elname = NULL;
00128 int i_type, b_shoutcast;
00129 char *psz_mrl = NULL, *psz_name = NULL, *psz_genre = NULL;
00130 char *psz_now = NULL, *psz_listeners = NULL, *psz_bitrate = NULL;
00131
00132
00133 b_shoutcast = p_sys->b_shout;
00134
00135 p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
00136 FIND_PARENT );
00137 if( !p_playlist )
00138 {
00139 msg_Err( p_demux, "can't find playlist" );
00140 return -1;
00141 }
00142 p_sys->p_playlist = p_playlist;
00143
00144 b_play = E_(FindItem)( p_demux, p_playlist, &p_current );
00145
00146 playlist_ItemToNode( p_playlist, p_current );
00147 p_current->input.i_type = ITEM_TYPE_PLAYLIST;
00148 if( b_shoutcast )
00149 {
00150 p_genre = playlist_NodeCreate( p_playlist, p_current->pp_parents[0]->i_view, "Genre", p_current );
00151 playlist_CopyParents( p_current, p_genre );
00152
00153 p_bitrate = playlist_NodeCreate( p_playlist, p_current->pp_parents[0]->i_view, "Bitrate", p_current );
00154 playlist_CopyParents( p_current, p_bitrate );
00155 }
00156
00157 p_xml = p_sys->p_xml = xml_Create( p_demux );
00158 if( !p_xml ) return -1;
00159
00160 psz_elname = stream_ReadLine( p_demux->s );
00161 if( psz_elname ) free( psz_elname );
00162 psz_elname = 0;
00163
00164 p_xml_reader = xml_ReaderCreate( p_xml, p_demux->s );
00165 if( !p_xml_reader ) return -1;
00166 p_sys->p_xml_reader = p_xml_reader;
00167
00168
00169
00170 if( xml_ReaderRead( p_xml_reader ) != 1 )
00171 {
00172 msg_Err( p_demux, "invalid file (no root node)" );
00173 return -1;
00174 }
00175
00176 if( xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM ||
00177 ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
00178 strcmp( psz_elname, "WinampXML" ) )
00179 {
00180 msg_Err( p_demux, "invalid root node %i, %s",
00181 xml_ReaderNodeType( p_xml_reader ), psz_elname );
00182 if( psz_elname ) free( psz_elname );
00183 return -1;
00184 }
00185 free( psz_elname );
00186
00187
00188
00189
00190
00191 while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 &&
00192 xml_ReaderNodeType( p_xml_reader ) != XML_READER_STARTELEM );
00193 if( i_ret != 1 )
00194 {
00195 msg_Err( p_demux, "invalid file (no child node)" );
00196 return -1;
00197 }
00198
00199 if( ( psz_elname = xml_ReaderName( p_xml_reader ) ) == NULL ||
00200 strcmp( psz_elname, "playlist" ) )
00201 {
00202 msg_Err( p_demux, "invalid child node %s", psz_elname );
00203 if( psz_elname ) free( psz_elname );
00204 return -1;
00205 }
00206 free( psz_elname ); psz_elname = 0;
00207
00208
00209 while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
00210 {
00211 char *psz_name = xml_ReaderName( p_xml_reader );
00212 char *psz_value = xml_ReaderValue( p_xml_reader );
00213 if( !psz_name || !psz_value ) return -1;
00214 if( !strcmp( psz_name, "num_entries" ) )
00215 {
00216 msg_Dbg( p_demux, "playlist has %d entries", atoi(psz_value) );
00217 }
00218 else if( !strcmp( psz_name, "label" ) )
00219 {
00220 playlist_ItemSetName( p_current, psz_value );
00221 }
00222 else
00223 {
00224 msg_Warn( p_demux, "stray attribute %s with value %s in element"
00225 " 'playlist'", psz_name, psz_value );
00226 }
00227 free( psz_name );
00228 free( psz_value );
00229 }
00230
00231 while( (i_ret = xml_ReaderRead( p_xml_reader )) == 1 )
00232 {
00233
00234 i_type = xml_ReaderNodeType( p_xml_reader );
00235 switch( i_type )
00236 {
00237
00238 case -1:
00239 return -1;
00240 break;
00241
00242 case XML_READER_STARTELEM:
00243 {
00244
00245 if( psz_elname ) free( psz_elname );
00246 psz_elname = xml_ReaderName( p_xml_reader );
00247 if( !psz_elname ) return -1;
00248
00249
00250
00251 while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
00252 {
00253 char *psz_name = xml_ReaderName( p_xml_reader );
00254 char *psz_value = xml_ReaderValue( p_xml_reader );
00255 if( !psz_name || !psz_value ) return -1;
00256 if( !strcmp( psz_elname, "entry" ) &&
00257 !strcmp( psz_name, "Playstring" ) )
00258 {
00259 psz_mrl = strdup( psz_value );
00260 }
00261 else
00262 {
00263 msg_Warn( p_demux, "unexpected attribure %s in element %s",
00264 psz_name, psz_elname );
00265 }
00266 free( psz_name );
00267 free( psz_value );
00268 }
00269 break;
00270 }
00271 case XML_READER_TEXT:
00272 {
00273 char *psz_text = xml_ReaderValue( p_xml_reader );
00274 if( IsWhitespace( psz_text ) )
00275 {
00276 free( psz_text );
00277 break;
00278 }
00279 if( !strcmp( psz_elname, "Name" ) )
00280 {
00281 psz_name = strdup( psz_text );
00282 }
00283 else if( !strcmp( psz_elname, "Genre" ) )
00284 {
00285 psz_genre = strdup( psz_text );
00286 }
00287 else if( !strcmp( psz_elname, "Nowplaying" ) )
00288 {
00289 psz_now = strdup( psz_text );
00290 }
00291 else if( !strcmp( psz_elname, "Listeners" ) )
00292 {
00293 psz_listeners = strdup( psz_text );
00294 }
00295 else if( !strcmp( psz_elname, "Bitrate" ) )
00296 {
00297 psz_bitrate = strdup( psz_text );
00298 }
00299 else if( !strcmp( psz_elname, "" ) )
00300 {
00301 ;
00302 }
00303 else
00304 {
00305 msg_Warn( p_demux, "unexpected text in element '%s'",
00306 psz_elname );
00307 }
00308 free( psz_text );
00309 break;
00310 }
00311
00312 case XML_READER_ENDELEM:
00313 {
00314
00315 free( psz_elname );
00316 psz_elname = xml_ReaderName( p_xml_reader );
00317 if( !psz_elname ) return -1;
00318 if( !strcmp( psz_elname, "entry" ) )
00319 {
00320 p_item = playlist_ItemNew( p_playlist, psz_mrl, psz_name );
00321 if( psz_now )
00322 {
00323 vlc_input_item_AddInfo( &(p_item->input),
00324 _("Meta-information"),
00325 _( VLC_META_NOW_PLAYING ),
00326 "%s",
00327 psz_now );
00328 }
00329 if( psz_genre )
00330 {
00331 vlc_input_item_AddInfo( &p_item->input,
00332 _("Meta-information"),
00333 _( VLC_META_GENRE ),
00334 "%s",
00335 psz_genre );
00336 }
00337 if( psz_listeners )
00338 {
00339 vlc_input_item_AddInfo( &p_item->input,
00340 _("Meta-information"),
00341 _( "Listeners" ),
00342 "%s",
00343 psz_listeners );
00344 }
00345 if( psz_bitrate )
00346 {
00347 vlc_input_item_AddInfo( &p_item->input,
00348 _("Meta-information"),
00349 _( "Bitrate" ),
00350 "%s",
00351 psz_bitrate );
00352 }
00353 playlist_NodeAddItem( p_playlist, p_item,
00354 p_current->pp_parents[0]->i_view,
00355 p_current, PLAYLIST_APPEND,
00356 PLAYLIST_END );
00357
00358
00359
00360 playlist_CopyParents( p_current, p_item );
00361
00362 vlc_input_item_CopyOptions( &p_current->input,
00363 &p_item->input );
00364 if( b_shoutcast )
00365 {
00366 char *psz_genreToken;
00367 char *psz_otherToken;
00368 int i = 0;
00369
00370 psz_genreToken = psz_genre;
00371
00372
00373
00374 while ( psz_genreToken &&
00375 ( psz_otherToken = GetNextToken(psz_genreToken )))
00376 {
00377 if( strlen(psz_genreToken)>2 )
00378
00379
00380 {
00381
00382 for( i=0; psz_genreToken[i]!=0; i++ )
00383 psz_genreToken[i] =
00384 tolower(psz_genreToken[i]);
00385
00386 psz_genreToken[0] =
00387 toupper( psz_genreToken[0] );
00388 ShoutcastAdd( p_playlist, p_genre,
00389 p_bitrate, p_item,
00390 psz_genreToken, psz_bitrate );
00391
00392 psz_genreToken = psz_otherToken;
00393 }
00394 }
00395 }
00396
00397 #define FREE(a) if( a ) free( a ); a = NULL;
00398 FREE( psz_name );
00399 FREE( psz_mrl );
00400 FREE( psz_genre );
00401 FREE( psz_bitrate );
00402 FREE( psz_listeners );
00403 FREE( psz_now );
00404 #undef FREE
00405 }
00406 free( psz_elname );
00407 psz_elname = strdup("");
00408
00409 break;
00410 }
00411 }
00412 }
00413
00414 if( i_ret != 0 )
00415 {
00416 msg_Warn( p_demux, "error while parsing data" );
00417 }
00418 if( b_shoutcast )
00419 {
00420 vlc_mutex_lock( &p_playlist->object_lock );
00421 playlist_NodeSort( p_playlist, p_bitrate, SORT_TITLE_NUMERIC, ORDER_NORMAL );
00422 vlc_mutex_unlock( &p_playlist->object_lock );
00423 }
00424
00425
00426 if( b_play && p_playlist->status.p_item &&
00427 p_playlist->status.p_item->i_children > 0 )
00428 {
00429 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
00430 p_playlist->status.i_view,
00431 p_playlist->status.p_item,
00432 p_playlist->status.p_item->pp_children[0] );
00433 }
00434
00435 vlc_object_release( p_playlist );
00436 p_sys->p_playlist = NULL;
00437 return VLC_SUCCESS;
00438 }
00439
00440 static int Control( demux_t *p_demux, int i_query, va_list args )
00441 {
00442 return VLC_EGENERIC;
00443 }
00444
00455 static char *GetNextToken(char *psz_cur_string) {
00456 while (*psz_cur_string && !isspace(*psz_cur_string))
00457 psz_cur_string++;
00458 if (!*psz_cur_string)
00459 return NULL;
00460 *psz_cur_string++ = '\0';
00461 while (*psz_cur_string && isspace(*psz_cur_string))
00462 psz_cur_string++;
00463 return psz_cur_string;
00464 }
00465
00466 static int IsWhitespace( char *psz_string )
00467 {
00468 while( *psz_string )
00469 {
00470 if( *psz_string != ' ' && *psz_string != '\t' && *psz_string != '\r' &&
00471 *psz_string != '\n' )
00472 {
00473 return VLC_FALSE;
00474 }
00475 psz_string++;
00476 }
00477 return VLC_TRUE;
00478 }
00479
00480 static void ShoutcastAdd( playlist_t *p_playlist, playlist_item_t* p_genre,
00481 playlist_item_t *p_bitrate, playlist_item_t *p_item,
00482 char *psz_genre, char *psz_bitrate )
00483 {
00484 playlist_item_t *p_parent;
00485 if( psz_bitrate )
00486 {
00487 playlist_item_t *p_copy = playlist_ItemCopy(p_playlist,p_item);
00488 p_parent = playlist_ChildSearchName( p_bitrate, psz_bitrate );
00489 if( !p_parent )
00490 {
00491 p_parent = playlist_NodeCreate( p_playlist, p_genre->pp_parents[0]->i_view, psz_bitrate,
00492 p_bitrate );
00493 playlist_CopyParents( p_bitrate, p_parent );
00494 }
00495 playlist_NodeAddItem( p_playlist, p_copy, p_parent->pp_parents[0]->i_view, p_parent, PLAYLIST_APPEND, PLAYLIST_END );
00496 playlist_CopyParents( p_parent, p_copy );
00497
00498 }
00499
00500 if( psz_genre )
00501 {
00502 playlist_item_t *p_copy = playlist_ItemCopy(p_playlist,p_item);
00503 p_parent = playlist_ChildSearchName( p_genre, psz_genre );
00504 if( !p_parent )
00505 {
00506 p_parent = playlist_NodeCreate( p_playlist, p_genre->pp_parents[0]->i_view, psz_genre,
00507 p_genre );
00508 playlist_CopyParents( p_genre, p_parent );
00509 }
00510 playlist_NodeAddItem( p_playlist, p_copy, p_parent->pp_parents[0]->i_view, p_parent, PLAYLIST_APPEND, PLAYLIST_END );
00511 playlist_CopyParents( p_parent, p_copy );
00512 }
00513 }