Skip to content

Commit

Permalink
fix header with attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeferson Tenorio committed Mar 6, 2019
1 parent 37acbb0 commit 5767ca5
Show file tree
Hide file tree
Showing 80 changed files with 195 additions and 34,792 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ __pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
buildtools/**
!buildtools/packages.config

# Telerik's JustMock configuration file
*.jmconfig
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions m3uParser.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.10
VisualStudioVersion = 15.0.27130.2020
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{19BA96D9-4DB8-4361-A592-EEBD390650D6}"
EndProject
Expand All @@ -20,14 +20,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{9A4065E4-8C28-4C36-8546-C4C8460B116A}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "buildtools", "buildtools", "{9A4065E4-8C28-4C36-8546-C4C8460B116A}"
ProjectSection(SolutionItems) = preProject
tools\packages.config = tools\packages.config
buildtools\packages.config = buildtools\packages.config
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "m3uParser.Tests", "tests\m3uParser.Tests\m3uParser.Tests.csproj", "{8A14FB47-E478-4622-B2F3-325A2CB964CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "m3uParser", "src\m3uParser\m3uParser.csproj", "{7FEB1DF7-D1EC-4682-A9CC-41771D73084D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "m3uParser", "src\m3uParser\m3uParser.csproj", "{7FEB1DF7-D1EC-4682-A9CC-41771D73084D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
30 changes: 24 additions & 6 deletions src/m3uParser.tool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,39 @@ internal class Program
{
static void Main(string[] args)
{
var a1 = GenericSpecification.InfoSetCollection.Parse(simpleVod);
var a2 = GenericSpecification.InfoSetCollection.Parse(headerParameter);
var simpleVodM3u = M3U.Parse(simpleVod);
var headerParameterM3u = M3U.Parse(headerParameter);

a1.ToList().ForEach(a => Console.WriteLine(a));
var urls = new List<string>();
urls.Add("https://pastebin.com/raw/gavXcCcQ");
urls.Add("http://bit.ly/2F3aZVH");
urls.Add("http://bit.ly/despotes455");
urls.Add("http://bit.ly/pastebintvaaa");
urls.Add("http://bit.ly/googletv55");
urls.Add("http://bit.ly/graduelas55");
urls.Add("http://bit.ly/srvista");
urls.Add("http://bit.ly/tpiptv456");
urls.Add("http://bit.ly/extraiptv85");
urls.Add("http://bit.ly/gstatic85");
urls.Add("http://bit.ly/listaiptvtv58");
urls.Add("http://bit.ly/iptvstreaming56");

Extm3u m = new Extm3u();

var lists = new List<Extm3u>();
urls.ToList().ForEach(a => {
try
{
lists.Add(M3U.ParseFromUrlAsync(a).Result);
}
catch { }
});
}

static readonly string simpleVod = @"#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
##COMMENT
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
Expand Down
31 changes: 16 additions & 15 deletions src/m3uParser/M3U.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Sprache;
using m3uParser.Model;
using Sprache;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -10,41 +11,41 @@
namespace m3uParser
{
/// <summary>
/// https://en.wikipedia.org/wiki/M3U
/// https://github.com/sprache/Sprache
/// https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.2
/// http://ss-iptv.com/en/users/documents/m3u
/// https://developer.apple.com/library/content/technotes/tn2288/_index.html
/// https://developer.apple.com/documentation/http_live_streaming/example_playlists_for_http_live_streaming/event_playlist_construction
/// https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#page-12
/// </summary>
public static class M3U
{
public static Root ParseText(string text)
public static Extm3u Parse(string content)
{
// Clear comments
Regex commentRegex = new Regex("##{1,}.*");
text = commentRegex.Replace(text, string.Empty);

// Parse EXTINF
return ParseSpecification.root.Parse(text);
return new Extm3u(content);
}

public static Root ParseBytes(byte[] byteArr)
public static Extm3u ParseBytes(byte[] byteArr)
{
return ParseText(Encoding.Default.GetString(byteArr));
return Parse(Encoding.Default.GetString(byteArr));
}

public static Root ParseFromFile(string file)
public static Extm3u ParseFromFile(string file)
{
return ParseText(System.IO.File.ReadAllText(file));
return Parse(System.IO.File.ReadAllText(file));
}

public static async Task<Root> ParseFromUrlAsync(string requestUri)
public static async Task<Extm3u> ParseFromUrlAsync(string requestUri)
{
return await ParseFromUrlAsync(requestUri, new HttpClient());
}

public static async Task<Root> ParseFromUrlAsync(string requestUri, HttpClient client)
public static async Task<Extm3u> ParseFromUrlAsync(string requestUri, HttpClient client)
{
var get = await client.GetAsync(requestUri);
var content = await get.Content.ReadAsStringAsync();
return ParseText(content);
return Parse(content);
}
}
}
37 changes: 18 additions & 19 deletions src/m3uParser/Model/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,27 @@

namespace m3uParser
{
/// <summary>
/// https://en.wikipedia.org/wiki/M3U
/// https://github.com/sprache/Sprache
/// https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-4.2
/// http://ss-iptv.com/en/users/documents/m3u
/// https://developer.apple.com/library/content/technotes/tn2288/_index.html
/// </summary>
public class AttributeInfo
public class Attributes
{
public AttributeInfo() { }
public AttributeInfo(IEnumerable<KeyValuePair<string, string>> attributes)
internal Attributes(IEnumerable<KeyValuePair<string, string>> attributes)
{
this.Attributes = attributes;
this.AttributeList = attributes;
this.GroupTitle = this.AttributeList.FirstOrDefault(w => w.Key.ToLower().Replace("-", string.Empty) == "grouptitle").Value;
this.GuideTimeShiftingTV = this.AttributeList.FirstOrDefault(w => w.Key.ToLower().Replace("-", string.Empty) == "tvgshift").Value;
this.GuideIdentifierTV = this.AttributeList.FirstOrDefault(w => w.Key.ToLower().Replace("-", string.Empty) == "tvgname").Value;
this.Logo = this.AttributeList.FirstOrDefault(w => w.Key.ToLower().Replace("-", string.Empty) == "tvglogo").Value;
this.AudioTrack = this.AttributeList.FirstOrDefault(w => w.Key.ToLower().Replace("-", string.Empty) == "audiotrack").Value;
this.AspectRatio = this.AttributeList.FirstOrDefault(w => w.Key.ToLower().Replace("-", string.Empty) == "aspectratio").Value;
this.Id = this.AttributeList.FirstOrDefault(w => w.Key.ToLower().Replace("-", string.Empty) == "tvgid").Value;
}

public IEnumerable<KeyValuePair<string, string>> Attributes { get; set; }
public string GroupTitle { get { return this.Attributes?.FirstOrDefault(w => w.Key.ToLower().Trim() == "group-title").Value; } }
public string GuideTimeShiftingTV { get { return this.Attributes?.FirstOrDefault(w => w.Key.ToLower().Trim() == "tvg-shift").Value; } }
public string GuideIdentifierTV { get { return this.Attributes?.FirstOrDefault(w => w.Key.ToLower().Trim() == "tvg-name").Value; } }
public string Logo { get { return this.Attributes?.FirstOrDefault(w => w.Key.ToLower().Trim() == "tvg-logo").Value; } }
public string AudioTrack { get { return this.Attributes?.FirstOrDefault(w => w.Key.ToLower().Trim() == "audio-track").Value; } }
public string AspectRatio { get { return this.Attributes?.FirstOrDefault(w => w.Key.ToLower().Trim() == "aspect-ratio").Value; } }
public string Id { get { return this.Attributes?.FirstOrDefault(w => w.Key.ToLower().Trim() == "tvg-id").Value; } }
public IEnumerable<KeyValuePair<string, string>> AttributeList { get; private set; }
public string GroupTitle { get; private set; }
public string GuideTimeShiftingTV { get; private set; }
public string GuideIdentifierTV { get; private set; }
public string Logo { get; private set; }
public string AudioTrack { get; private set; }
public string AspectRatio { get; private set; }
public string Id { get; private set; }
}
}
12 changes: 0 additions & 12 deletions src/m3uParser/Model/Couple.cs

This file was deleted.

69 changes: 67 additions & 2 deletions src/m3uParser/Model/Extm3u.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sprache;

namespace m3uParser.Model
{
Expand All @@ -9,8 +11,71 @@ public class Extm3u
public string PlayListType { get; set; }
public int? TargetDuration { get; set; }
public int? Version { get; set; }
public int? MeidaSequence { get; set; }
public IEnumerable<KeyValuePair<string, string>> Attributes { get; set; }
public int? MediaSequence { get; set; }
public Attributes Attributes { get; set; }
public IEnumerable<Media> Medias { get; set; }
public IEnumerable<string> Warnings { get; set; }

internal Extm3u(string content)
{
var segments = SegmentSpecification.SegmentCollection.Parse(content);

if (segments == null || segments.Count() == 0)
{
throw new Exception("The content cannot be parsed");
}

if (!segments.First().StartsWith("#EXTM3U", StringComparison.CurrentCultureIgnoreCase))
{
throw new Exception("The content do not has extm3u header");
}
else
{
// parse attributes
Attributes = new Attributes(PairsSpecification.Attributes.Parse(segments.First()));
}

IList<string> warnings = new List<string>();
IList<Media> medias = new List<Media>();

foreach (var item in segments.Skip(1))
{
var tag = PairsSpecification.Tag.Parse(item);

switch (tag.Key)
{
case "EXT-X-PLAYLIST-TYPE":
this.PlayListType = tag.Value;
break;

case "EXT-X-TARGETDURATION":
this.TargetDuration = int.Parse(tag.Value);
break;

case "EXT-X-VERSION":
this.Version = int.Parse(tag.Value);
break;

case "EXT-X-MEDIA-SEQUENCE":
this.MediaSequence = int.Parse(tag.Value);
break;

case "EXTINF":
medias.Add(new Media(tag.Value));
break;

case "EXT-X-ENDLIST":
break;

default:
warnings.Add($"The content #{tag.Key}{(string.IsNullOrEmpty(tag.Value) ? string.Empty : ":")}{tag.Value} cannot be parsed");

break;
}
}

this.Warnings = warnings.AsEnumerable();
this.Medias = medias.AsEnumerable();
}
}
}
14 changes: 0 additions & 14 deletions src/m3uParser/Model/IInfo.cs

This file was deleted.

16 changes: 0 additions & 16 deletions src/m3uParser/Model/InfoSet.cs

This file was deleted.

16 changes: 13 additions & 3 deletions src/m3uParser/Model/Media.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using Sprache;

namespace m3uParser
{
Expand All @@ -14,15 +15,24 @@ public class Media

public bool IsStream { get { return this.Duration <= 0; } }

public AttributeInfo AttributeInfo { get; set; }
public Attributes Attributes { get; set; }

internal Media(string source)
{
var media = LinesSpecification.Extinf.Parse(source);

this.Duration = media.Duration;
this.Title = media.Title;
this.MediaFile = media.MediaFile;
this.Attributes = media.Attributes;
}

internal Media(decimal duration, IEnumerable<KeyValuePair<string, string>> attributes, Title title, string mediafile)
{
AttributeInfo = new AttributeInfo();
Duration = duration;
Title = title;
MediaFile = mediafile;
AttributeInfo.Attributes = attributes;
Attributes = new Attributes(attributes);
}
}
}
24 changes: 0 additions & 24 deletions src/m3uParser/Model/Root.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/m3uParser/Model/Title.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class Title
public string RawTitle { get; set; }
public string InnerTitle { get; set; }

public Title(string title, string innerTitle)
internal Title(string title, string innerTitle)
{
RawTitle = title;
InnerTitle = innerTitle;
Expand Down
Loading

0 comments on commit 5767ca5

Please sign in to comment.