@ -39,68 +39,45 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
var url = info . Url ;
var urlHash = url . GetMD5 ( ) . ToString ( "N" ) ;
int position = 0 ;
string line ;
// Read the file and display it line by line.
var file = new StreamReader ( url ) ;
var channels = new List < M3UChannel > ( ) ;
string channnelName = null ;
string channelNumber = null ;
while ( ( line = file . ReadLine ( ) ) ! = null )
{
line = line . Trim ( ) ;
if ( ! String . IsNullOrWhiteSpace ( line ) )
if ( s tring. IsNullOrWhiteSpace ( line ) )
{
if ( position = = 0 & & ! line . StartsWith ( "#EXTM3U" ) )
{
throw new ApplicationException ( "wrong file" ) ;
}
if ( position % 2 = = 0 )
{
if ( position ! = 0 )
{
channels . Last ( ) . Path = line ;
}
else
{
line = line . Replace ( "#EXTM3U" , "" ) ;
line = line . Trim ( ) ;
var vars = line . Split ( ' ' ) . ToList ( ) ;
foreach ( var variable in vars )
{
var list = variable . Replace ( '"' , ' ' ) . Split ( '=' ) ;
switch ( list [ 0 ] )
{
case ( "id" ) :
//_id = list[1];
break ;
}
}
}
}
else
continue ;
}
if ( line . StartsWith ( "#EXTM3U" , StringComparison . OrdinalIgnoreCase ) )
{
continue ;
}
if ( line . StartsWith ( "#EXTINF:" , StringComparison . OrdinalIgnoreCase ) )
{
var parts = line . Split ( new [ ] { ':' } , 2 ) . Last ( ) . Split ( new [ ] { ',' } , 2 ) ;
channelNumber = parts [ 0 ] ;
channnelName = parts [ 1 ] ;
}
else if ( ! string . IsNullOrWhiteSpace ( channelNumber ) )
{
channels . Add ( new M3UChannel
{
if ( ! line . StartsWith ( "#EXTINF:" ) ) { throw new ApplicationException ( "Bad file" ) ; }
line = line . Replace ( "#EXTINF:" , "" ) ;
var nameStart = line . LastIndexOf ( ',' ) ;
line = line . Substring ( 0 , nameStart ) ;
var vars = line . Split ( ' ' ) . ToList ( ) ;
vars . RemoveAt ( 0 ) ;
channels . Add ( new M3UChannel ( ) ) ;
foreach ( var variable in vars )
{
var list = variable . Replace ( '"' , ' ' ) . Split ( '=' ) ;
switch ( list [ 0 ] )
{
case "tvg-id" :
channels . Last ( ) . Id = ChannelIdPrefix + urlHash + list [ 1 ] ;
channels . Last ( ) . Number = list [ 1 ] ;
break ;
case "tvg-name" :
channels . Last ( ) . Name = list [ 1 ] ;
break ;
}
}
}
position + + ;
Name = channnelName ,
Number = channelNumber ,
Id = ChannelIdPrefix + urlHash + channelNumber ,
Path = line
} ) ;
channelNumber = null ;
channnelName = null ;
}
}
file . Close ( ) ;
@ -125,6 +102,35 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
}
protected override async Task < MediaSourceInfo > GetChannelStream ( TunerHostInfo info , string channelId , string streamId , CancellationToken cancellationToken )
{
var sources = await GetChannelStreamMediaSources ( info , channelId , cancellationToken ) . ConfigureAwait ( false ) ;
return sources . First ( ) ;
}
class M3UChannel : ChannelInfo
{
public string Path { get ; set ; }
public M3UChannel ( )
{
}
}
public async Task Validate ( TunerHostInfo info )
{
if ( ! File . Exists ( info . Url ) )
{
throw new FileNotFoundException ( ) ;
}
}
protected override bool IsValidChannelId ( string channelId )
{
return channelId . StartsWith ( ChannelIdPrefix , StringComparison . OrdinalIgnoreCase ) ;
}
protected override async Task < List < MediaSourceInfo > > GetChannelStreamMediaSources ( TunerHostInfo info , string channelId , CancellationToken cancellationToken )
{
var urlHash = info . Url . GetMD5 ( ) . ToString ( "N" ) ;
var prefix = ChannelIdPrefix + urlHash ;
@ -133,29 +139,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
return null ;
}
channelId = channelId . Substring ( prefix . Length ) ;
//channelId = channelId.Substring(prefix.Length) ;
var channels = await GetChannels ( info , true , cancellationToken ) . ConfigureAwait ( false ) ;
var m3uchannels = channels . Cast < M3UChannel > ( ) ;
var channel = m3uchannels . FirstOrDefault ( c = > c . Id = = channelId ) ;
var channel = m3uchannels . FirstOrDefault ( c = > string . Equals ( c . Id , channelId , StringComparison . OrdinalIgnoreCase ) ) ;
if ( channel ! = null )
{
var path = channel . Path ;
MediaProtocol protocol = MediaProtocol . File ;
if ( path . StartsWith ( "http" ))
if ( path . StartsWith ( "http" , StringComparison . OrdinalIgnoreCase ))
{
protocol = MediaProtocol . Http ;
}
else if ( path . StartsWith ( "rtmp" ))
else if ( path . StartsWith ( "rtmp" , StringComparison . OrdinalIgnoreCase ))
{
protocol = MediaProtocol . Rtmp ;
}
else if ( path . StartsWith ( "rtsp" ))
else if ( path . StartsWith ( "rtsp" , StringComparison . OrdinalIgnoreCase ))
{
protocol = MediaProtocol . Rtsp ;
}
return new MediaSourceInfo
var mediaSource = new MediaSourceInfo
{
Path = channel . Path ,
Protocol = protocol ,
@ -179,35 +185,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
RequiresOpening = false ,
RequiresClosing = false
} ;
}
throw new ApplicationException ( "Host doesnt provide this channel" ) ;
}
class M3UChannel : ChannelInfo
{
public string Path { get ; set ; }
public M3UChannel ( )
{
}
}
public async Task Validate ( TunerHostInfo info )
{
if ( ! File . Exists ( info . Url ) )
{
throw new FileNotFoundException ( ) ;
return new List < MediaSourceInfo > { mediaSource } ;
}
}
protected override bool IsValidChannelId ( string channelId )
{
return channelId . StartsWith ( ChannelIdPrefix , StringComparison . OrdinalIgnoreCase ) ;
}
protected override Task < List < MediaSourceInfo > > GetChannelStreamMediaSources ( TunerHostInfo info , string channelId , CancellationToken cancellationToken )
{
throw new NotImplementedException ( ) ;
return new List < MediaSourceInfo > { } ;
}
protected override Task < bool > IsAvailableInternal ( TunerHostInfo tuner , string channelId , CancellationToken cancellationToken )